code_ownership 2.1.1 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.cargo/config +2 -2
- data/Cargo.lock +2 -2
- data/README.md +8 -8
- data/ext/cargo-vendor/codeowners-0.3.2/.cargo-checksum.json +1 -0
- data/ext/cargo-vendor/codeowners-0.3.2/.github/CODEOWNERS +1 -0
- data/ext/cargo-vendor/codeowners-0.3.2/AGENTS.md +38 -0
- data/ext/cargo-vendor/codeowners-0.3.2/CLAUDE.md +1 -0
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/Cargo.lock +1 -1
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/Cargo.toml +17 -1
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/README.md +11 -1
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/cli.rs +9 -5
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/config.rs +81 -1
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/crosscheck.rs +5 -8
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/ownership/codeowners_file_parser.rs +3 -3
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/ownership/file_owner_resolver.rs +3 -1
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/ownership/mapper/package_mapper.rs +2 -2
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/ownership/mapper.rs +2 -2
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/ownership/validator.rs +15 -10
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/ownership.rs +1 -0
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/project.rs +3 -0
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/project_builder.rs +111 -44
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/runner/api.rs +7 -6
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/runner/types.rs +2 -1
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/runner.rs +67 -16
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/tracked_files.rs +29 -1
- data/ext/cargo-vendor/codeowners-0.3.2/tests/codeowners_path_test.rs +92 -0
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/common/mod.rs +2 -1
- data/ext/cargo-vendor/codeowners-0.3.2/tests/executable_name_config_test.rs +67 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/custom_codeowners_path/config/code_ownership.yml +11 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/custom_codeowners_path/config/teams/test_team.yml +6 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/custom_codeowners_path/docs/CODEOWNERS +14 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/custom_codeowners_path/expected/CODEOWNERS +14 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/custom_codeowners_path/ruby/app/models/test.rb +3 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/custom_executable_name/.github/CODEOWNERS +10 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/custom_executable_name/app/foo.rb +3 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/custom_executable_name/config/code_ownership.yml +4 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/custom_executable_name/config/teams/foo.yml +5 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/custom_executable_name/config/teams/payments.yml +6 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/custom_executable_name/ruby/app/payments/foo.rb +4 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/default_executable_name/.github/CODEOWNERS +11 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/default_executable_name/app/bar.rb +3 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/default_executable_name/config/code_ownership.yml +5 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/default_executable_name/config/teams/bar.yml +5 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/missing_github_team/.github/CODEOWNERS +10 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/missing_github_team/config/code_ownership.yml +10 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/missing_github_team/config/teams/bad_team.yml +1 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/missing_github_team/config/teams/good.yml +3 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/fixtures/valid_project/gems/pets/dog.rb +5 -0
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/git_stage_test.rs +4 -1
- data/ext/cargo-vendor/codeowners-0.3.2/tests/missing_github_team_test.rs +23 -0
- data/ext/cargo-vendor/codeowners-0.3.2/tests/run_config_executable_override_test.rs +98 -0
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/runner_api.rs +8 -4
- data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/valid_project_test.rs +3 -3
- data/ext/cargo-vendor/codeowners-0.3.2/tests/validate_files_test.rs +378 -0
- data/ext/cargo-vendor/unicode-ident-1.0.19/.cargo-checksum.json +1 -1
- data/ext/code_ownership/Cargo.toml +1 -1
- data/ext/code_ownership/src/lib.rs +2 -2
- data/lib/code_ownership/private/file_path_finder.rb +19 -3
- data/lib/code_ownership/private/team_finder.rb +1 -2
- data/lib/code_ownership/version.rb +1 -1
- data/lib/code_ownership.rb +2 -0
- metadata +178 -152
- data/ext/cargo-vendor/codeowners-0.3.0/.cargo-checksum.json +0 -1
- data/ext/cargo-vendor/codeowners-0.3.0/tests/validate_files_test.rs +0 -144
- data/ext/cargo-vendor/unicode-ident-1.0.19/tests/fst/.gitignore +0 -1
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/.github/workflows/audit.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/.github/workflows/ci.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/.github/workflows/dotslash-config.json +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/.rustfmt.toml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/.rusty-hook.toml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/dev/run_benchmarks_for_file.sh +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/dev/run_benchmarks_for_gv.sh +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/rust-toolchain.toml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/cache/file.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/cache/mod.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/cache/noop.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/common_test.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/lib.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/main.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/ownership/codeowners_query.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/ownership/file_generator.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/ownership/file_owner_finder.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/ownership/mapper/annotated_file_mapper.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/ownership/mapper/directory_mapper.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/ownership/mapper/escaper.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/ownership/mapper/team_gem_mapper.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/ownership/mapper/team_glob_mapper.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/ownership/mapper/team_yml_mapper.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/path_utils.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/src/project_file_builder.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/cache_test.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/crosscheck_owners_test.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/invalid_project/.github/CODEOWNERS +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/invalid_project/config/code_ownership.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/invalid_project/config/teams/payments.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/invalid_project/config/teams/payroll.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/invalid_project/gems/payroll_calculator/calculator.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/invalid_project/ruby/app/models/bank_account.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/invalid_project/ruby/app/models/blockchain.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/invalid_project/ruby/app/models/payroll.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/invalid_project/ruby/app/payments/nacha.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/invalid_project/ruby/app/services/.codeowner +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/invalid_project/ruby/app/services/multi_owned.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/invalid_project/ruby/app/unowned.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/invalid_project/ruby/packages/payroll_flow/package.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/javascript_only_project/.github/CODEOWNERS +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/javascript_only_project/.keep +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/javascript_only_project/config/code_ownership.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/javascript_only_project/config/teams/design.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/javascript_only_project/config/teams/frontend.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/javascript_only_project/frontend/apps/public/index.tsx +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/javascript_only_project/frontend/packages/dashboard/package.json +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/javascript_only_project/frontend/packages/dashboard/src/index.tsx +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/javascript_only_project/frontend/packages/ui-kit/.codeowner +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/javascript_only_project/frontend/packages/ui-kit/src/button.tsx +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0/tests/fixtures/valid_project → codeowners-0.3.2/tests/fixtures/missing_github_team}/gems/pets/dog.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/multiple-directory-owners/.github/CODEOWNERS +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/multiple-directory-owners/app/consumers/.codeowner +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/multiple-directory-owners/app/consumers/deep/nesting/nestdir/deep_file.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/multiple-directory-owners/app/consumers/one_owner.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/multiple-directory-owners/app/services/.codeowner +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/multiple-directory-owners/app/services/exciting/.codeowner +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/multiple-directory-owners/app/services/exciting/some_other_file.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/multiple-directory-owners/config/code_ownership.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/multiple-directory-owners/config/teams/bar.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/multiple-directory-owners/config/teams/foo.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/.github/CODEOWNERS +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/.ignore +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/config/code_ownership.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/config/teams/payments.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/config/teams/payroll.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/config/teams/ux.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/gems/payroll_calculator/calculator.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/javascript/packages/PayrollFlow/index.tsx +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/javascript/packages/PayrollFlow/package.json +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/javascript/packages/items/(special)/.codeowner +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/javascript/packages/items/(special)/pay.ts +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/javascript/packages/items/.codeowner +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/javascript/packages/items/item.ts +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/javascript/packages/list/page-admin.tsx +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/ruby/app/models/bank_account.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/ruby/app/models/payroll.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/ruby/app/payments/foo/.codeowner +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/ruby/app/payments/foo/ownedby_payroll.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/ruby/app/payments/nacha.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/ruby/app/payroll/.codeowner +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/ruby/app/payroll/payroll.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/ruby/app/views/foos/edit.erb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/ruby/app/views/foos/index.html.erb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/ruby/app/views/foos/new.html.erb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/ruby/ignored_files/git_ignored.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/ruby/packages/payroll_flow/package.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project/should_be_ignored/an_ignored_file.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/.github/CODEOWNERS +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/config/code_ownership.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/config/teams/brewers.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/config/teams/cubs.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/config/teams/giants.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/config/teams/rockies.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/frontend/packages/components/datepicker/package.json +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/frontend/packages/components/datepicker/src/picks/dp.tsx +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/frontend/packages/components/list/package.json +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/frontend/packages/components/list/src/item.tsx +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/frontend/packages/components/textfield/package.json +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/frontend/packages/components/textfield/src/field.tsx +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/frontend/packages/components/textfield/src/fields/small.tsx +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/gems/apollo/lib/apollo.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/gems/ivy/lib/ivy.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/gems/lager/lib/lager.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/gems/summit/lib/summit.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/packs/games/app/services/stats.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/packs/games/package.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/packs/locations/app/services/capacity.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/packs/locations/package.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/packs/schedule/app/services/date.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/packs/schedule/package.yml +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/ruby/app/brewers/lib/util.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/ruby/app/brewers/services/play.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/ruby/app/cubs/.codeowner +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/ruby/app/cubs/services/models/.codeowner +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/ruby/app/cubs/services/models/db/price.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/ruby/app/cubs/services/models/entertainment.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/ruby/app/cubs/services/play.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/ruby/app/giants/services/play.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/fixtures/valid_project_with_overrides/ruby/app/rockies/services/play.rb +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/invalid_project_structure_test.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/invalid_project_test.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/multiple_directory_owners_test.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/untracked_files_test.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tests/valid_project_with_overrides_test.rs +0 -0
- /data/ext/cargo-vendor/{codeowners-0.3.0 → codeowners-0.3.2}/tmp/.gitkeep +0 -0
|
@@ -17,6 +17,7 @@ pub struct Project {
|
|
|
17
17
|
pub codeowners_file_path: PathBuf,
|
|
18
18
|
pub directory_codeowner_files: Vec<DirectoryCodeownersFile>,
|
|
19
19
|
pub teams_by_name: HashMap<String, Team>,
|
|
20
|
+
pub executable_name: String,
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
#[derive(Clone, Debug)]
|
|
@@ -111,6 +112,7 @@ pub mod deserializers {
|
|
|
111
112
|
#[derive(Deserialize)]
|
|
112
113
|
pub struct RubyPackage {
|
|
113
114
|
pub owner: Option<String>,
|
|
115
|
+
pub metadata: Option<Metadata>,
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
#[derive(Deserialize)]
|
|
@@ -219,6 +221,7 @@ mod tests {
|
|
|
219
221
|
codeowners_file_path: PathBuf::from(".github/CODEOWNERS"),
|
|
220
222
|
directory_codeowner_files: vec![],
|
|
221
223
|
teams_by_name: HashMap::new(),
|
|
224
|
+
executable_name: "codeowners generate".to_string(),
|
|
222
225
|
};
|
|
223
226
|
|
|
224
227
|
let map = project.vendored_gem_by_name();
|
|
@@ -8,7 +8,7 @@ use error_stack::{Report, Result, ResultExt};
|
|
|
8
8
|
use fast_glob::glob_match;
|
|
9
9
|
use ignore::{DirEntry, WalkBuilder, WalkParallel, WalkState};
|
|
10
10
|
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
|
11
|
-
use tracing::
|
|
11
|
+
use tracing::instrument;
|
|
12
12
|
|
|
13
13
|
use crate::{
|
|
14
14
|
cache::Cache,
|
|
@@ -178,9 +178,17 @@ impl<'a> ProjectBuilder<'a> {
|
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
fn build_project_from_entry_types(&mut self, entry_types: Vec<EntryType>) -> Result<Project, Error> {
|
|
181
|
-
|
|
181
|
+
type Accumulator = (
|
|
182
|
+
Vec<ProjectFile>,
|
|
183
|
+
Vec<Package>,
|
|
184
|
+
Vec<VendoredGem>,
|
|
185
|
+
Vec<DirectoryCodeownersFile>,
|
|
186
|
+
Vec<Team>,
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
let (project_files, packages, vendored_gems, directory_codeowners, teams): Accumulator = entry_types
|
|
182
190
|
.into_par_iter()
|
|
183
|
-
.
|
|
191
|
+
.try_fold(
|
|
184
192
|
|| {
|
|
185
193
|
(
|
|
186
194
|
Vec::<ProjectFile>::with_capacity(INITIAL_VECTOR_CAPACITY),
|
|
@@ -197,18 +205,20 @@ impl<'a> ProjectBuilder<'a> {
|
|
|
197
205
|
}
|
|
198
206
|
EntryType::Directory(absolute_path, relative_path) => {
|
|
199
207
|
if relative_path.parent() == Some(Path::new(&self.config.vendored_gems_path)) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
path:
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
+
let file_name = relative_path.file_name().ok_or_else(|| {
|
|
209
|
+
error_stack::report!(Error::Io)
|
|
210
|
+
.attach_printable(format!("Vendored gem path has no file name: {}", relative_path.display()))
|
|
211
|
+
})?;
|
|
212
|
+
gems.push(VendoredGem {
|
|
213
|
+
path: absolute_path,
|
|
214
|
+
name: file_name.to_string_lossy().to_string(),
|
|
215
|
+
});
|
|
208
216
|
}
|
|
209
217
|
}
|
|
210
218
|
EntryType::RubyPackage(absolute_path, relative_path) => {
|
|
211
|
-
match ruby_package_owner(&absolute_path)
|
|
219
|
+
match ruby_package_owner(&absolute_path)
|
|
220
|
+
.attach_printable_lazy(|| format!("Failed to read ruby package: {}", absolute_path.display()))
|
|
221
|
+
{
|
|
212
222
|
Ok(Some(owner)) => {
|
|
213
223
|
pkgs.push(Package {
|
|
214
224
|
path: relative_path.clone(),
|
|
@@ -217,13 +227,13 @@ impl<'a> ProjectBuilder<'a> {
|
|
|
217
227
|
});
|
|
218
228
|
}
|
|
219
229
|
Ok(None) => { /* No owner, do nothing */ }
|
|
220
|
-
Err(e) =>
|
|
221
|
-
warn!("Error reading ruby package owner for {:?}: {:?}", absolute_path, e);
|
|
222
|
-
}
|
|
230
|
+
Err(e) => return Err(e),
|
|
223
231
|
}
|
|
224
232
|
}
|
|
225
233
|
EntryType::JavascriptPackage(absolute_path, relative_path) => {
|
|
226
|
-
match javascript_package_owner(&absolute_path)
|
|
234
|
+
match javascript_package_owner(&absolute_path)
|
|
235
|
+
.attach_printable_lazy(|| format!("Failed to read javascript package: {}", absolute_path.display()))
|
|
236
|
+
{
|
|
227
237
|
Ok(Some(owner)) => {
|
|
228
238
|
pkgs.push(Package {
|
|
229
239
|
path: relative_path.clone(),
|
|
@@ -232,37 +242,31 @@ impl<'a> ProjectBuilder<'a> {
|
|
|
232
242
|
});
|
|
233
243
|
}
|
|
234
244
|
Ok(None) => { /* No owner, do nothing */ }
|
|
235
|
-
Err(e) =>
|
|
236
|
-
warn!("Error reading javascript package owner for {:?}: {:?}", absolute_path, e);
|
|
237
|
-
}
|
|
245
|
+
Err(e) => return Err(e),
|
|
238
246
|
}
|
|
239
247
|
}
|
|
240
|
-
EntryType::CodeownerFile(absolute_path, relative_path) =>
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
Err(e) => {
|
|
257
|
-
warn!("Error building team from team file path: {}", e);
|
|
258
|
-
}
|
|
259
|
-
},
|
|
248
|
+
EntryType::CodeownerFile(absolute_path, relative_path) => {
|
|
249
|
+
let owner = std::fs::read_to_string(&absolute_path)
|
|
250
|
+
.change_context(Error::Io)
|
|
251
|
+
.attach_printable_lazy(|| format!("Failed to read codeowner file: {}", absolute_path.display()))?;
|
|
252
|
+
let owner = owner.trim().to_owned();
|
|
253
|
+
codeowners.push(DirectoryCodeownersFile {
|
|
254
|
+
path: relative_path.clone(),
|
|
255
|
+
owner,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
EntryType::TeamFile(absolute_path, _relative_path) => {
|
|
259
|
+
let team = Team::from_team_file_path(absolute_path.clone())
|
|
260
|
+
.change_context(Error::Io)
|
|
261
|
+
.attach_printable_lazy(|| format!("Failed to read team file: {}", absolute_path.display()))?;
|
|
262
|
+
team_files.push(team);
|
|
263
|
+
}
|
|
260
264
|
EntryType::NullEntry() => {}
|
|
261
265
|
}
|
|
262
|
-
(project_files, pkgs, gems, codeowners, team_files)
|
|
266
|
+
Ok((project_files, pkgs, gems, codeowners, team_files))
|
|
263
267
|
},
|
|
264
268
|
)
|
|
265
|
-
.
|
|
269
|
+
.try_reduce(
|
|
266
270
|
|| (Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new()),
|
|
267
271
|
|mut acc, item| {
|
|
268
272
|
acc.0.extend(item.0);
|
|
@@ -270,9 +274,9 @@ impl<'a> ProjectBuilder<'a> {
|
|
|
270
274
|
acc.2.extend(item.2);
|
|
271
275
|
acc.3.extend(item.3);
|
|
272
276
|
acc.4.extend(item.4);
|
|
273
|
-
acc
|
|
277
|
+
Ok(acc)
|
|
274
278
|
},
|
|
275
|
-
)
|
|
279
|
+
)?;
|
|
276
280
|
let teams_by_name = teams
|
|
277
281
|
.iter()
|
|
278
282
|
.flat_map(|team| vec![(team.name.clone(), team.clone()), (team.github_team.clone(), team.clone())])
|
|
@@ -294,6 +298,7 @@ impl<'a> ProjectBuilder<'a> {
|
|
|
294
298
|
codeowners_file_path: self.codeowners_file_path.to_path_buf(),
|
|
295
299
|
directory_codeowner_files: directory_codeowners,
|
|
296
300
|
teams_by_name,
|
|
301
|
+
executable_name: self.config.executable_name.clone(),
|
|
297
302
|
})
|
|
298
303
|
}
|
|
299
304
|
}
|
|
@@ -309,7 +314,19 @@ fn ruby_package_owner(path: &Path) -> Result<Option<String>, Error> {
|
|
|
309
314
|
let file = File::open(path).change_context(Error::Io)?;
|
|
310
315
|
let deserializer: deserializers::RubyPackage = serde_yaml::from_reader(file).change_context(Error::SerdeYaml)?;
|
|
311
316
|
|
|
312
|
-
|
|
317
|
+
let top_level_owner = deserializer.owner;
|
|
318
|
+
let metadata_owner = deserializer.metadata.and_then(|metadata| metadata.owner);
|
|
319
|
+
|
|
320
|
+
// Error if both are present with different values
|
|
321
|
+
match (top_level_owner.as_ref(), metadata_owner.as_ref()) {
|
|
322
|
+
(Some(top), Some(meta)) if top != meta => Err(error_stack::report!(Error::Io).attach_printable(format!(
|
|
323
|
+
"Package at {} has conflicting owners: 'owner: {}' vs 'metadata.owner: {}'. Please use only one.",
|
|
324
|
+
path.display(),
|
|
325
|
+
top,
|
|
326
|
+
meta
|
|
327
|
+
))),
|
|
328
|
+
_ => Ok(top_level_owner.or(metadata_owner)),
|
|
329
|
+
}
|
|
313
330
|
}
|
|
314
331
|
|
|
315
332
|
fn javascript_package_owner(path: &Path) -> Result<Option<String>, Error> {
|
|
@@ -334,4 +351,54 @@ mod tests {
|
|
|
334
351
|
fn test_glob_match() {
|
|
335
352
|
assert!(glob_match(OWNED_GLOB, "script/.eslintrc.js"));
|
|
336
353
|
}
|
|
354
|
+
|
|
355
|
+
#[test]
|
|
356
|
+
fn test_ruby_package_owner_top_level() {
|
|
357
|
+
let yaml = "owner: TeamA\n";
|
|
358
|
+
let temp_file = tempfile::NamedTempFile::new().unwrap();
|
|
359
|
+
std::fs::write(temp_file.path(), yaml).unwrap();
|
|
360
|
+
|
|
361
|
+
let owner = ruby_package_owner(temp_file.path()).unwrap();
|
|
362
|
+
assert_eq!(owner, Some("TeamA".to_string()));
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
#[test]
|
|
366
|
+
fn test_ruby_package_owner_metadata() {
|
|
367
|
+
let yaml = "metadata:\n owner: TeamB\n";
|
|
368
|
+
let temp_file = tempfile::NamedTempFile::new().unwrap();
|
|
369
|
+
std::fs::write(temp_file.path(), yaml).unwrap();
|
|
370
|
+
|
|
371
|
+
let owner = ruby_package_owner(temp_file.path()).unwrap();
|
|
372
|
+
assert_eq!(owner, Some("TeamB".to_string()));
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
#[test]
|
|
376
|
+
fn test_ruby_package_owner_errors_when_both_present_and_different() {
|
|
377
|
+
let yaml = "owner: TeamA\nmetadata:\n owner: TeamB\n";
|
|
378
|
+
let temp_file = tempfile::NamedTempFile::new().unwrap();
|
|
379
|
+
std::fs::write(temp_file.path(), yaml).unwrap();
|
|
380
|
+
|
|
381
|
+
let result = ruby_package_owner(temp_file.path());
|
|
382
|
+
assert!(result.is_err());
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
#[test]
|
|
386
|
+
fn test_ruby_package_owner_allows_both_when_same() {
|
|
387
|
+
let yaml = "owner: TeamA\nmetadata:\n owner: TeamA\n";
|
|
388
|
+
let temp_file = tempfile::NamedTempFile::new().unwrap();
|
|
389
|
+
std::fs::write(temp_file.path(), yaml).unwrap();
|
|
390
|
+
|
|
391
|
+
let owner = ruby_package_owner(temp_file.path()).unwrap();
|
|
392
|
+
assert_eq!(owner, Some("TeamA".to_string()));
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
#[test]
|
|
396
|
+
fn test_ruby_package_owner_no_owner() {
|
|
397
|
+
let yaml = "name: my_package\n";
|
|
398
|
+
let temp_file = tempfile::NamedTempFile::new().unwrap();
|
|
399
|
+
std::fs::write(temp_file.path(), yaml).unwrap();
|
|
400
|
+
|
|
401
|
+
let owner = ruby_package_owner(temp_file.path()).unwrap();
|
|
402
|
+
assert_eq!(owner, None);
|
|
403
|
+
}
|
|
337
404
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
use std::collections::HashMap;
|
|
2
2
|
|
|
3
|
-
use crate::ownership::FileOwner;
|
|
4
3
|
use crate::project::Team;
|
|
4
|
+
use crate::{ownership::FileOwner, runner::config_from_run_config};
|
|
5
5
|
|
|
6
|
-
use super::{Error, ForFileResult, RunConfig, RunResult,
|
|
6
|
+
use super::{Error, ForFileResult, RunConfig, RunResult, run};
|
|
7
7
|
|
|
8
8
|
pub fn for_file(run_config: &RunConfig, file_path: &str, from_codeowners: bool, json: bool) -> RunResult {
|
|
9
9
|
if from_codeowners {
|
|
@@ -38,7 +38,7 @@ pub fn crosscheck_owners(run_config: &RunConfig) -> RunResult {
|
|
|
38
38
|
|
|
39
39
|
// Returns all owners for a file without creating a Runner (performance optimized)
|
|
40
40
|
pub fn owners_for_file(run_config: &RunConfig, file_path: &str) -> error_stack::Result<Vec<FileOwner>, Error> {
|
|
41
|
-
let config =
|
|
41
|
+
let config = config_from_run_config(run_config)?;
|
|
42
42
|
use crate::ownership::file_owner_resolver::find_file_owners;
|
|
43
43
|
let owners = find_file_owners(&run_config.project_root, &config, std::path::Path::new(file_path)).map_err(Error::Io)?;
|
|
44
44
|
Ok(owners)
|
|
@@ -60,10 +60,11 @@ pub fn teams_for_files_from_codeowners(
|
|
|
60
60
|
run_config: &RunConfig,
|
|
61
61
|
file_paths: &[String],
|
|
62
62
|
) -> error_stack::Result<HashMap<String, Option<Team>>, Error> {
|
|
63
|
-
let config =
|
|
63
|
+
let config = config_from_run_config(run_config)?;
|
|
64
|
+
let codeowners_file_path = super::resolve_codeowners_file_path(run_config, &config);
|
|
64
65
|
let res = crate::ownership::codeowners_query::teams_for_files_from_codeowners(
|
|
65
66
|
&run_config.project_root,
|
|
66
|
-
&
|
|
67
|
+
&codeowners_file_path,
|
|
67
68
|
&config.team_file_glob,
|
|
68
69
|
file_paths,
|
|
69
70
|
)
|
|
@@ -80,7 +81,7 @@ pub fn team_for_file_from_codeowners(run_config: &RunConfig, file_path: &str) ->
|
|
|
80
81
|
|
|
81
82
|
// Fast path that avoids creating a full Runner for single file queries
|
|
82
83
|
fn for_file_optimized(run_config: &RunConfig, file_path: &str, json: bool) -> RunResult {
|
|
83
|
-
let config = match
|
|
84
|
+
let config = match config_from_run_config(run_config) {
|
|
84
85
|
Ok(c) => c,
|
|
85
86
|
Err(err) => {
|
|
86
87
|
return RunResult::from_io_error(Error::Io(err.to_string()), json);
|
|
@@ -14,9 +14,10 @@ pub struct RunResult {
|
|
|
14
14
|
#[derive(Debug, Clone)]
|
|
15
15
|
pub struct RunConfig {
|
|
16
16
|
pub project_root: PathBuf,
|
|
17
|
-
pub codeowners_file_path: PathBuf
|
|
17
|
+
pub codeowners_file_path: Option<PathBuf>,
|
|
18
18
|
pub config_path: PathBuf,
|
|
19
19
|
pub no_cache: bool,
|
|
20
|
+
pub executable_name: Option<String>,
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
#[derive(Debug, Serialize)]
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
use std::
|
|
1
|
+
use std::path::{Path, PathBuf};
|
|
2
|
+
use std::process::Command;
|
|
2
3
|
|
|
3
4
|
use error_stack::{Result, ResultExt};
|
|
5
|
+
use fast_glob::glob_match;
|
|
4
6
|
use serde::Serialize;
|
|
5
7
|
|
|
6
8
|
use crate::{
|
|
@@ -20,6 +22,7 @@ pub struct Runner {
|
|
|
20
22
|
ownership: Ownership,
|
|
21
23
|
cache: Cache,
|
|
22
24
|
config: Config,
|
|
25
|
+
codeowners_file_path: PathBuf,
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
pub fn version() -> String {
|
|
@@ -36,7 +39,7 @@ where
|
|
|
36
39
|
Ok(runner) => runner,
|
|
37
40
|
Err(err) => {
|
|
38
41
|
return RunResult {
|
|
39
|
-
io_errors: vec![err
|
|
42
|
+
io_errors: vec![format!("{:?}", err)],
|
|
40
43
|
..Default::default()
|
|
41
44
|
};
|
|
42
45
|
}
|
|
@@ -44,15 +47,41 @@ where
|
|
|
44
47
|
runnable(runner)
|
|
45
48
|
}
|
|
46
49
|
|
|
47
|
-
pub(crate) fn
|
|
48
|
-
match crate::config::Config::load_from_path(
|
|
49
|
-
Ok(c) =>
|
|
50
|
+
pub(crate) fn config_from_run_config(run_config: &RunConfig) -> Result<Config, Error> {
|
|
51
|
+
match crate::config::Config::load_from_path(&run_config.config_path) {
|
|
52
|
+
Ok(mut c) => {
|
|
53
|
+
if let Some(executable_name) = &run_config.executable_name {
|
|
54
|
+
c.executable_name = executable_name.clone();
|
|
55
|
+
}
|
|
56
|
+
Ok(c)
|
|
57
|
+
}
|
|
50
58
|
Err(msg) => Err(error_stack::Report::new(Error::Io(msg))),
|
|
51
59
|
}
|
|
52
60
|
}
|
|
61
|
+
|
|
62
|
+
/// Resolves the CODEOWNERS file path with the following priority:
|
|
63
|
+
/// 1. Explicit `codeowners_file_path` in `RunConfig` (if provided from e.g. CLI flag)
|
|
64
|
+
/// 2. `CODEOWNERS_PATH` environment variable (if set and not empty)
|
|
65
|
+
/// 3. Computed from `codeowners_path` directory path in config + "CODEOWNERS" filename
|
|
66
|
+
/// 4. Default fallback to `.github/CODEOWNERS` (using default codeowners_path from config)
|
|
67
|
+
pub(crate) fn resolve_codeowners_file_path(run_config: &RunConfig, config: &Config) -> PathBuf {
|
|
68
|
+
if let Some(ref path) = run_config.codeowners_file_path {
|
|
69
|
+
return path.clone();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if let Ok(env_path) = std::env::var("CODEOWNERS_PATH")
|
|
73
|
+
&& !env_path.is_empty()
|
|
74
|
+
{
|
|
75
|
+
return run_config.project_root.join(env_path);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
run_config.project_root.join(&config.codeowners_path).join("CODEOWNERS")
|
|
79
|
+
}
|
|
80
|
+
|
|
53
81
|
impl Runner {
|
|
54
82
|
pub fn new(run_config: &RunConfig) -> Result<Self, Error> {
|
|
55
|
-
let config =
|
|
83
|
+
let config = config_from_run_config(run_config)?;
|
|
84
|
+
let codeowners_file_path = resolve_codeowners_file_path(run_config, &config);
|
|
56
85
|
|
|
57
86
|
let cache: Cache = if run_config.no_cache {
|
|
58
87
|
NoopCache::default().into()
|
|
@@ -66,12 +95,7 @@ impl Runner {
|
|
|
66
95
|
.into()
|
|
67
96
|
};
|
|
68
97
|
|
|
69
|
-
let mut project_builder = ProjectBuilder::new(
|
|
70
|
-
&config,
|
|
71
|
-
run_config.project_root.clone(),
|
|
72
|
-
run_config.codeowners_file_path.clone(),
|
|
73
|
-
&cache,
|
|
74
|
-
);
|
|
98
|
+
let mut project_builder = ProjectBuilder::new(&config, run_config.project_root.clone(), codeowners_file_path.clone(), &cache);
|
|
75
99
|
let project = project_builder.build().change_context(Error::Io(format!(
|
|
76
100
|
"Can't build project: {}",
|
|
77
101
|
&run_config.config_path.to_string_lossy()
|
|
@@ -88,6 +112,7 @@ impl Runner {
|
|
|
88
112
|
ownership,
|
|
89
113
|
cache,
|
|
90
114
|
config,
|
|
115
|
+
codeowners_file_path,
|
|
91
116
|
})
|
|
92
117
|
}
|
|
93
118
|
|
|
@@ -113,7 +138,25 @@ impl Runner {
|
|
|
113
138
|
let mut unowned_files = Vec::new();
|
|
114
139
|
let mut io_errors = Vec::new();
|
|
115
140
|
|
|
116
|
-
|
|
141
|
+
// Filter files based on owned_globs and unowned_globs configuration
|
|
142
|
+
// Only validate files that match owned_globs and don't match unowned_globs
|
|
143
|
+
let filtered_paths: Vec<String> = file_paths
|
|
144
|
+
.into_iter()
|
|
145
|
+
.filter(|file_path| {
|
|
146
|
+
// Convert to relative path for glob matching
|
|
147
|
+
let path = Path::new(file_path);
|
|
148
|
+
let relative_path = if path.is_absolute() {
|
|
149
|
+
path.strip_prefix(&self.run_config.project_root).unwrap_or(path)
|
|
150
|
+
} else {
|
|
151
|
+
path
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// Mirror the filtering applied by ProjectBuilder when walking the project
|
|
155
|
+
matches_globs(relative_path, &self.config.owned_globs) && !matches_globs(relative_path, &self.config.unowned_globs)
|
|
156
|
+
})
|
|
157
|
+
.collect();
|
|
158
|
+
|
|
159
|
+
for file_path in filtered_paths {
|
|
117
160
|
match team_for_file_from_codeowners(&self.run_config, &file_path) {
|
|
118
161
|
Ok(Some(_)) => {}
|
|
119
162
|
Ok(None) => unowned_files.push(file_path),
|
|
@@ -145,10 +188,10 @@ impl Runner {
|
|
|
145
188
|
|
|
146
189
|
pub fn generate(&self, git_stage: bool) -> RunResult {
|
|
147
190
|
let content = self.ownership.generate_file();
|
|
148
|
-
if let Some(parent) = &self.
|
|
191
|
+
if let Some(parent) = &self.codeowners_file_path.parent() {
|
|
149
192
|
let _ = std::fs::create_dir_all(parent);
|
|
150
193
|
}
|
|
151
|
-
match std::fs::write(&self.
|
|
194
|
+
match std::fs::write(&self.codeowners_file_path, content) {
|
|
152
195
|
Ok(_) => {
|
|
153
196
|
if git_stage {
|
|
154
197
|
self.git_stage();
|
|
@@ -173,7 +216,7 @@ impl Runner {
|
|
|
173
216
|
fn git_stage(&self) {
|
|
174
217
|
let _ = Command::new("git")
|
|
175
218
|
.arg("add")
|
|
176
|
-
.arg(&self.
|
|
219
|
+
.arg(&self.codeowners_file_path)
|
|
177
220
|
.current_dir(&self.run_config.project_root)
|
|
178
221
|
.output();
|
|
179
222
|
}
|
|
@@ -389,6 +432,14 @@ impl RunResult {
|
|
|
389
432
|
}
|
|
390
433
|
}
|
|
391
434
|
|
|
435
|
+
/// Returns true if `path` matches any of the provided glob patterns.
|
|
436
|
+
fn matches_globs(path: &Path, globs: &[String]) -> bool {
|
|
437
|
+
match path.to_str() {
|
|
438
|
+
Some(s) => globs.iter().any(|glob| glob_match(glob, s)),
|
|
439
|
+
None => false,
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
392
443
|
#[cfg(test)]
|
|
393
444
|
mod tests {
|
|
394
445
|
use super::*;
|
|
@@ -6,7 +6,7 @@ use std::{
|
|
|
6
6
|
|
|
7
7
|
pub(crate) fn find_tracked_files(base_path: &Path) -> Option<HashMap<PathBuf, bool>> {
|
|
8
8
|
let output = Command::new("git")
|
|
9
|
-
.args(["ls-files", "
|
|
9
|
+
.args(["ls-files", "-z", "--", "."])
|
|
10
10
|
.current_dir(base_path)
|
|
11
11
|
.output()
|
|
12
12
|
.ok()?;
|
|
@@ -55,4 +55,32 @@ mod tests {
|
|
|
55
55
|
assert!(tracked.len() == 1);
|
|
56
56
|
assert!(tracked.get(&tmp_dir.path().join("test.txt")).unwrap());
|
|
57
57
|
}
|
|
58
|
+
|
|
59
|
+
#[test]
|
|
60
|
+
fn test_tracked_files_from_subdirectory() {
|
|
61
|
+
let tmp_dir = tempfile::tempdir().unwrap();
|
|
62
|
+
let backend_dir = tmp_dir.path().join("backend");
|
|
63
|
+
let tracked_file = backend_dir.join("app/models/foo.rb");
|
|
64
|
+
|
|
65
|
+
std::process::Command::new("git")
|
|
66
|
+
.arg("init")
|
|
67
|
+
.current_dir(tmp_dir.path())
|
|
68
|
+
.output()
|
|
69
|
+
.expect("failed to run git init");
|
|
70
|
+
|
|
71
|
+
std::fs::create_dir_all(tracked_file.parent().unwrap()).unwrap();
|
|
72
|
+
std::fs::write(&tracked_file, "class Foo; end").unwrap();
|
|
73
|
+
std::fs::write(tmp_dir.path().join("README.md"), "readme").unwrap();
|
|
74
|
+
|
|
75
|
+
std::process::Command::new("git")
|
|
76
|
+
.args(["add", "--all"])
|
|
77
|
+
.current_dir(tmp_dir.path())
|
|
78
|
+
.output()
|
|
79
|
+
.expect("failed to add tracked files");
|
|
80
|
+
|
|
81
|
+
let tracked = find_tracked_files(&backend_dir).unwrap();
|
|
82
|
+
assert_eq!(tracked.len(), 1);
|
|
83
|
+
assert!(tracked.get(&tracked_file).unwrap());
|
|
84
|
+
assert!(!tracked.contains_key(&backend_dir.join("backend/app/models/foo.rb")));
|
|
85
|
+
}
|
|
58
86
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
use predicates::prelude::predicate;
|
|
2
|
+
use std::{error::Error, fs, path::Path};
|
|
3
|
+
|
|
4
|
+
mod common;
|
|
5
|
+
|
|
6
|
+
use common::OutputStream;
|
|
7
|
+
use common::git_add_all_files;
|
|
8
|
+
use common::run_codeowners;
|
|
9
|
+
use common::setup_fixture_repo;
|
|
10
|
+
|
|
11
|
+
#[test]
|
|
12
|
+
fn test_generate_uses_codeowners_path_from_config() -> Result<(), Box<dyn Error>> {
|
|
13
|
+
let fixture_root = Path::new("tests/fixtures/custom_codeowners_path");
|
|
14
|
+
let temp_dir = setup_fixture_repo(fixture_root);
|
|
15
|
+
let project_root = temp_dir.path();
|
|
16
|
+
git_add_all_files(project_root);
|
|
17
|
+
|
|
18
|
+
let mut cmd = assert_cmd::Command::cargo_bin("codeowners")?;
|
|
19
|
+
cmd.arg("--project-root")
|
|
20
|
+
.arg(project_root)
|
|
21
|
+
.arg("--no-cache")
|
|
22
|
+
.arg("generate")
|
|
23
|
+
.assert()
|
|
24
|
+
.success();
|
|
25
|
+
|
|
26
|
+
let expected_codeowners: String = std::fs::read_to_string(Path::new("tests/fixtures/custom_codeowners_path/expected/CODEOWNERS"))?;
|
|
27
|
+
let actual_codeowners: String = std::fs::read_to_string(project_root.join("docs/CODEOWNERS"))?;
|
|
28
|
+
|
|
29
|
+
assert_eq!(expected_codeowners, actual_codeowners);
|
|
30
|
+
|
|
31
|
+
Ok(())
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
#[test]
|
|
35
|
+
fn test_cli_overrides_codeowners_path_from_config() -> Result<(), Box<dyn Error>> {
|
|
36
|
+
fs::create_dir_all("tmp")?;
|
|
37
|
+
let codeowners_abs = std::env::current_dir()?.join("tmp/CODEOWNERS");
|
|
38
|
+
let codeowners_str = codeowners_abs.to_str().unwrap();
|
|
39
|
+
|
|
40
|
+
run_codeowners(
|
|
41
|
+
"custom_codeowners_path",
|
|
42
|
+
&["--codeowners-file-path", codeowners_str, "generate"],
|
|
43
|
+
true,
|
|
44
|
+
OutputStream::Stdout,
|
|
45
|
+
predicate::eq(""),
|
|
46
|
+
)?;
|
|
47
|
+
|
|
48
|
+
let expected_codeowners: String = std::fs::read_to_string(Path::new("tests/fixtures/custom_codeowners_path/expected/CODEOWNERS"))?;
|
|
49
|
+
let actual_codeowners: String = std::fs::read_to_string(Path::new("tmp/CODEOWNERS"))?;
|
|
50
|
+
|
|
51
|
+
assert_eq!(expected_codeowners, actual_codeowners);
|
|
52
|
+
|
|
53
|
+
Ok(())
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
#[test]
|
|
57
|
+
fn test_validate_uses_codeowners_path_from_config() -> Result<(), Box<dyn Error>> {
|
|
58
|
+
run_codeowners(
|
|
59
|
+
"custom_codeowners_path",
|
|
60
|
+
&["validate"],
|
|
61
|
+
true,
|
|
62
|
+
OutputStream::Stdout,
|
|
63
|
+
predicate::eq(""),
|
|
64
|
+
)?;
|
|
65
|
+
|
|
66
|
+
Ok(())
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
#[test]
|
|
70
|
+
fn test_validate_uses_cli_override() -> Result<(), Box<dyn Error>> {
|
|
71
|
+
fs::create_dir_all("tmp")?;
|
|
72
|
+
let codeowners_abs = std::env::current_dir()?.join("tmp/CODEOWNERS");
|
|
73
|
+
let codeowners_str = codeowners_abs.to_str().unwrap();
|
|
74
|
+
|
|
75
|
+
run_codeowners(
|
|
76
|
+
"custom_codeowners_path",
|
|
77
|
+
&["--codeowners-file-path", codeowners_str, "generate"],
|
|
78
|
+
true,
|
|
79
|
+
OutputStream::Stdout,
|
|
80
|
+
predicate::eq(""),
|
|
81
|
+
)?;
|
|
82
|
+
|
|
83
|
+
run_codeowners(
|
|
84
|
+
"custom_codeowners_path",
|
|
85
|
+
&["--codeowners-file-path", codeowners_str, "validate"],
|
|
86
|
+
true,
|
|
87
|
+
OutputStream::Stdout,
|
|
88
|
+
predicate::eq(""),
|
|
89
|
+
)?;
|
|
90
|
+
|
|
91
|
+
Ok(())
|
|
92
|
+
}
|
|
@@ -154,9 +154,10 @@ pub fn build_run_config(project_root: &Path, codeowners_rel_path: &str) -> RunCo
|
|
|
154
154
|
let config_path = project_root.join("config/code_ownership.yml");
|
|
155
155
|
RunConfig {
|
|
156
156
|
project_root,
|
|
157
|
-
codeowners_file_path,
|
|
157
|
+
codeowners_file_path: Some(codeowners_file_path),
|
|
158
158
|
config_path,
|
|
159
159
|
no_cache: true,
|
|
160
|
+
executable_name: None,
|
|
160
161
|
}
|
|
161
162
|
}
|
|
162
163
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
use indoc::indoc;
|
|
2
|
+
use predicates::prelude::*;
|
|
3
|
+
use std::error::Error;
|
|
4
|
+
|
|
5
|
+
mod common;
|
|
6
|
+
use common::OutputStream;
|
|
7
|
+
use common::run_codeowners;
|
|
8
|
+
|
|
9
|
+
#[test]
|
|
10
|
+
fn test_validate_with_custom_executable_name() -> Result<(), Box<dyn Error>> {
|
|
11
|
+
// When executable_name is configured, error should show that command
|
|
12
|
+
run_codeowners(
|
|
13
|
+
"custom_executable_name",
|
|
14
|
+
&["validate"],
|
|
15
|
+
false,
|
|
16
|
+
OutputStream::Stdout,
|
|
17
|
+
predicate::str::contains("Run `bin/codeownership validate`"),
|
|
18
|
+
)?;
|
|
19
|
+
Ok(())
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
#[test]
|
|
23
|
+
fn test_validate_with_default_executable_name() -> Result<(), Box<dyn Error>> {
|
|
24
|
+
// When executable_name is not configured, error should show default "codeowners"
|
|
25
|
+
run_codeowners(
|
|
26
|
+
"default_executable_name",
|
|
27
|
+
&["validate"],
|
|
28
|
+
false,
|
|
29
|
+
OutputStream::Stdout,
|
|
30
|
+
predicate::str::contains("Run `codeowners generate`"),
|
|
31
|
+
)?;
|
|
32
|
+
Ok(())
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
#[test]
|
|
36
|
+
fn test_custom_executable_name_full_error_message() -> Result<(), Box<dyn Error>> {
|
|
37
|
+
// Verify the complete error message format with custom executable
|
|
38
|
+
run_codeowners(
|
|
39
|
+
"custom_executable_name",
|
|
40
|
+
&["validate"],
|
|
41
|
+
false,
|
|
42
|
+
OutputStream::Stdout,
|
|
43
|
+
predicate::eq(indoc! {"
|
|
44
|
+
|
|
45
|
+
CODEOWNERS out of date. Run `bin/codeownership validate` to update the CODEOWNERS file
|
|
46
|
+
|
|
47
|
+
"}),
|
|
48
|
+
)?;
|
|
49
|
+
Ok(())
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
#[test]
|
|
53
|
+
fn test_default_executable_name_full_error_message() -> Result<(), Box<dyn Error>> {
|
|
54
|
+
// Verify the complete error message format with default executable
|
|
55
|
+
run_codeowners(
|
|
56
|
+
"default_executable_name",
|
|
57
|
+
&["validate"],
|
|
58
|
+
false,
|
|
59
|
+
OutputStream::Stdout,
|
|
60
|
+
predicate::eq(indoc! {"
|
|
61
|
+
|
|
62
|
+
CODEOWNERS out of date. Run `codeowners generate` to update the CODEOWNERS file
|
|
63
|
+
|
|
64
|
+
"}),
|
|
65
|
+
)?;
|
|
66
|
+
Ok(())
|
|
67
|
+
}
|