From 755cdca249b7cc19f6c06cf95adcbaae8d9cfcde Mon Sep 17 00:00:00 2001 From: Turiiya <34311583+ttytm@users.noreply.github.com> Date: Sat, 18 May 2024 13:30:50 +0200 Subject: [PATCH] vdoc: improve vdocignore file handling by walking all .vdocignore sub-paths in IgnoreRules.get, add test (#21521) --- cmd/tools/vdoc/files.v | 66 ++++++++++++++++++++++---------------- cmd/tools/vdoc/vdoc_test.v | 32 ++++++++++++------ 2 files changed, 62 insertions(+), 36 deletions(-) diff --git a/cmd/tools/vdoc/files.v b/cmd/tools/vdoc/files.v index db8553c7ed..13d050b796 100644 --- a/cmd/tools/vdoc/files.v +++ b/cmd/tools/vdoc/files.v @@ -14,9 +14,8 @@ mut: } fn get_modules(path string) []string { - mut ignore_rules := IgnoreRules{} mut modules := map[string]bool{} - for p in get_paths(path, mut ignore_rules) { + for p in get_paths(path, IgnoreRules.get(path)) { modules[os.dir(p)] = true } mut res := modules.keys() @@ -24,10 +23,9 @@ fn get_modules(path string) []string { return res } -fn get_paths(path string, mut ignore_rules IgnoreRules) []string { +fn get_paths(path string, ignore_rules IgnoreRules) []string { mut res := []string{} outer: for p in os.ls(path) or { return [] } { - ignore_rules.get(path) fp := os.join_path(path, p) if fp in ignore_rules.paths { continue @@ -45,7 +43,7 @@ fn get_paths(path string, mut ignore_rules IgnoreRules) []string { } } if is_dir { - res << get_paths(fp, mut ignore_rules) + res << get_paths(fp, ignore_rules) continue } if p.ends_with('.v') { @@ -55,30 +53,44 @@ fn get_paths(path string, mut ignore_rules IgnoreRules) []string { return res } -fn (mut ignore_rules IgnoreRules) get(path string) { - ignore_content := os.read_file(os.join_path(path, '.vdocignore')) or { return } - if ignore_content.trim_space() == '' { - return - } - rules := ignore_content.split_into_lines().map(it.trim_space()) - for rule in rules { - if rule.starts_with('#') { +fn IgnoreRules.get(path string) IgnoreRules { + mut res := IgnoreRules{} + mut vdocignore_paths := []string{} + mut vdocignore_paths_ref := &vdocignore_paths + os.walk(path, fn [vdocignore_paths_ref] (p string) { + if os.file_name(p) == '.vdocignore' { + unsafe { + vdocignore_paths_ref << p + } + } + }) + for ignore_path in vdocignore_paths { + ignore_content := os.read_file(ignore_path) or { continue } + if ignore_content.trim_space() == '' { continue } - if rule.contains('*.') || rule.contains('**') { - // Skip wildcards that are defined in an ignore file. - // For now, only add a basic implementation in `get_paths` - // that can handle the default `*_test.v` pattern. - eprintln('vdoc: Wildcards in ignore rules are not yet supported.') - continue - } - if rule.starts_with('/') { - // Similar to `.gitignore`, a pattern starting with `/` should only ignore - // the pattern relative to the directory of the `.vdocignore` file. - // `/a` should ignore `/a` but not `/b/a`. While `a` should ignore `/a` and `/b/a`. - ignore_rules.paths[os.join_path(path, rule.trim_left('/'))] = true - } else { - ignore_rules.patterns[path] << rule + rules := ignore_content.split_into_lines().map(it.trim_space()) + for rule in rules { + if rule.starts_with('#') { + continue + } + if rule.contains('*.') || rule.contains('**') { + // Skip wildcards that are defined in an ignore file. + // For now, only add a basic implementation in `get_paths` + // that can handle the default `*_test.v` pattern. + eprintln('vdoc: Wildcards in ignore rules are not yet supported.') + continue + } + p := os.dir(ignore_path) + if rule.starts_with('/') { + // Similar to `.gitignore`, a pattern starting with `/` should only ignore + // the pattern relative to the directory of the `.vdocignore` file. + // `/a` should ignore `/a` but not `/b/a`. While `a` should ignore `/a` and `/b/a`. + res.paths[os.join_path(p, rule.trim_left('/'))] = true + } else { + res.patterns[p] << rule + } } } + return res } diff --git a/cmd/tools/vdoc/vdoc_test.v b/cmd/tools/vdoc/vdoc_test.v index 2e30be2be6..199bb80945 100644 --- a/cmd/tools/vdoc/vdoc_test.v +++ b/cmd/tools/vdoc/vdoc_test.v @@ -3,6 +3,19 @@ module main import os import arrays +const tpath = os.join_path(os.vtmp_dir(), 'vod_test_module') + +fn testsuite_begin() { + os.rmdir_all(tpath) or {} + os.mkdir_all(tpath)! + os.chdir(tpath)! +} + + +fn testsuite_end() { + os.rmdir_all(tpath) or {} +} + fn test_trim_doc_node_description() { mod := 'foo' mut readme := '## Description @@ -20,16 +33,17 @@ It also assists with composing and testing baz.' assert res2 == res } +fn test_ignore_rules() { + os.write_file('.vdocignore', ['pattern1', 'pattern2', '/path1'].join_lines())! + os.mkdir('subdir')! + os.write_file(os.join_path('subdir', '.vdocignore'), ['pattern3', '/path2'].join_lines())! + rules := IgnoreRules.get('.') + assert rules.patterns['.'] == ['pattern1', 'pattern2'] + assert rules.patterns['./subdir'] == ['pattern3'] + assert rules.paths == {'./path1': true, './subdir/path2': true} +} + fn test_get_module_list() { - tpath := os.join_path(os.vtmp_dir(), 'vod_test_module') - os.rmdir_all(tpath) or {} - os.mkdir_all(tpath)! - defer { - os.rmdir_all(tpath) or {} - } - - os.chdir(tpath)! - // For information on leading slash rules, refer to the comments in `IgnoreRules.get`. ignore_rules := ['bravo', '/echo', '/foxtrot/golf', 'hotel.v/', 'india/juliett'] os.write_file('.vdocignore', ignore_rules.join_lines())!