| 1 | import os |
| 2 | import term |
| 3 | import time |
| 4 | |
| 5 | struct Context { |
| 6 | mut: |
| 7 | cut_time time.Time |
| 8 | deprecations int |
| 9 | } |
| 10 | |
| 11 | fn (mut ctx Context) analyze_line(line string, position_file string, position_line int) { |
| 12 | blame_for_time := os.execute('git blame -L${position_line} --porcelain -- ${position_file}') |
| 13 | if blame_for_time.exit_code != 0 { |
| 14 | return |
| 15 | } |
| 16 | ts := blame_for_time.output.all_after('committer-time').all_before('\n').trim_space().int() |
| 17 | t := time.unix(ts) |
| 18 | if ctx.cut_time < t { |
| 19 | println(term.colorize(term.gray, |
| 20 | '>>> SKIPPING since t: ${t} > ${ctx.cut_time}, ${position_file}:${position_line}: ${line}')) |
| 21 | return |
| 22 | } |
| 23 | ctx.deprecations++ |
| 24 | blame_for_context := os.execute('git blame -L${position_line},+5 -- ${position_file}') |
| 25 | context := blame_for_context.output.trim_space().split_into_lines() |
| 26 | println(term.colorize(term.red, |
| 27 | '${position_file}:${position_line}: deprecation: ${ctx.deprecations}, timestamp: ${ts} - ${t}')) |
| 28 | for cline in context { |
| 29 | println(' ${cline}') |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | fn main() { |
| 34 | if os.args.len < 2 { |
| 35 | eprintln('Usage: v run cmd/tools/show_ancient_deprecations.v [DAYS]') |
| 36 | exit(1) |
| 37 | } |
| 38 | cut_months := os.args[1].int() |
| 39 | cut_time := time.now().add(-cut_months * 24 * time.hour) |
| 40 | mut ctx := Context{ |
| 41 | cut_time: cut_time |
| 42 | } |
| 43 | println('> Deprecations that happened before ${cut_time}') |
| 44 | all_v_files := os.walk_ext('.', '.v') |
| 45 | for v_file in all_v_files { |
| 46 | if v_file == './vlib/v/fmt/tests/attrs_keep.vv' { |
| 47 | println(term.colorize(term.gray, |
| 48 | '>>> SKIPPING deprecations attrs formatting test file ${v_file}')) |
| 49 | continue |
| 50 | } |
| 51 | if v_file.starts_with('./vlib/v/checker/tests') && v_file.contains('deprec') { |
| 52 | println(term.colorize(term.gray, '>>> SKIPPING deprecations test file ${v_file}')) |
| 53 | continue |
| 54 | } |
| 55 | file_content := os.read_file(v_file)! |
| 56 | if !file_content.contains('[deprecated') { |
| 57 | continue |
| 58 | } |
| 59 | lines := file_content.split_into_lines() |
| 60 | for line_num := lines.len - 1; line_num > 0; line_num-- { |
| 61 | line := lines[line_num].all_before('//') |
| 62 | mut is_deprecation_line := false |
| 63 | if line.contains('\tif ') { |
| 64 | continue |
| 65 | } |
| 66 | if line.contains('[deprecated:') { |
| 67 | is_deprecation_line = true |
| 68 | } |
| 69 | if line.contains('[deprecated]') { |
| 70 | is_deprecation_line = true |
| 71 | } |
| 72 | if !is_deprecation_line { |
| 73 | continue |
| 74 | } |
| 75 | ctx.analyze_line(line, v_file, line_num + 1) |
| 76 | } |
| 77 | } |
| 78 | println('> Summary: there were ${term.colorize(term.bright_yellow, ctx.deprecations.str())} deprecations found, done before ${term.colorize(term.magenta, |
| 79 | cut_time.str())}.') |
| 80 | if ctx.deprecations > 0 { |
| 81 | exit(1) |
| 82 | } |
| 83 | } |
| 84 | |