From: Charles McGarvey Date: Wed, 13 Nov 2019 04:46:47 +0000 (-0700) Subject: add projects command and filtering to show command X-Git-Tag: v0.42~1 X-Git-Url: https://git.dogcows.com/gitweb?a=commitdiff_plain;h=3c7ed3d762399efb2d01121392f7115104095788;p=chaz%2Fgit-codeowners add projects command and filtering to show command --- diff --git a/bin/git-codeowners b/bin/git-codeowners index 8da6976..be0025b 100755 --- a/bin/git-codeowners +++ b/bin/git-codeowners @@ -6,7 +6,9 @@ git-codeowners [--version|--help|--manual] - git-codeowners [show] [--format FORMAT] [--[no-]project] [PATH...] + git-codeowners [show] [--format FORMAT] [--owner OWNER]... + [--pattern PATTERN]... [--[no-]patterns] + [--project PROJECT]... [--[no-]projects] [PATH...] git-codeowners owners [--format FORMAT] [--pattern PATTERN] @@ -94,18 +96,33 @@ Does not yet support Zsh... =head2 show - git-codeowners [show] [--format FORMAT] [--[no-]project] [PATH...] + git-codeowners [show] [--format FORMAT] [--owner OWNER]... + [--pattern PATTERN]... [--[no-]patterns] + [--project PROJECT]... [--[no-]projects] [PATH...] Show owners of one or more files in a repo. +If C<--owner>, C<--project>, C<--pattern> are set, only show files with matching +criteria. These can be repeated. + +Use C<--patterns> to also show the matching pattern associated with each file. + +By default the output might show associated projects if the C file +defines them. You can control this by explicitly using C<--projects> or +C<--no-projects> to always show or always hide defined projects, respectively. + =head2 owners git-codeowners owners [--format FORMAT] [--pattern PATTERN] +List all owners defined in the F file. + =head2 patterns git-codeowners patterns [--format FORMAT] [--owner OWNER] +List all patterns defined in the F file. + =head2 create git-codeowners create [REPO_DIRPATH|CODEOWNERS_FILEPATH] diff --git a/lib/App/Codeowners.pm b/lib/App/Codeowners.pm index 20be985..1dc97cc 100644 --- a/lib/App/Codeowners.pm +++ b/lib/App/Codeowners.pm @@ -54,19 +54,46 @@ sub _command_show { my ($proc, $cdup) = run_git(qw{rev-parse --show-cdup}); $proc->wait and exit 1; + my $show_projects = $opts->{projects} // scalar @{$codeowners->projects}; + my $formatter = App::Codeowners::Formatter->new( format => $opts->{format} || ' * %-50F %O', handle => *STDOUT, - columns => [qw(File Owner), $opts->{project} ? 'Project' : ()], + columns => [ + 'File', + $opts->{patterns} ? 'Pattern' : (), + 'Owner', + $show_projects ? 'Project' : (), + ], ); + my %filter_owners = map { $_ => 1 } @{$opts->{owner}}; + my %filter_projects = map { $_ => 1 } @{$opts->{project}}; + my %filter_patterns = map { $_ => 1 } @{$opts->{pattern}}; + $proc = git_ls_files('.', $opts->args); while (my $filepath = $proc->next) { my $match = $codeowners->match(path($filepath)->relative($cdup)); + if (%filter_owners) { + for my $owner (@{$match->{owners}}) { + goto ADD_RESULT if $filter_owners{$owner}; + } + next; + } + if (%filter_patterns) { + goto ADD_RESULT if $filter_patterns{$match->{pattern} || ''}; + next; + } + if (%filter_projects) { + goto ADD_RESULT if $filter_projects{$match->{project} || ''}; + next; + } + ADD_RESULT: $formatter->add_result([ $filepath, + $opts->{patterns} ? $match->{pattern} : (), $match->{owners}, - $opts->{project} ? $match->{project} : (), + $show_projects ? $match->{project} : (), ]); } $proc->wait and exit 1; @@ -112,6 +139,26 @@ sub _command_patterns { $formatter->add_result(map { [$_] } @$results); } +sub _command_projects { + my $self = shift; + my $opts = shift; + + my $toplevel = git_toplevel('.') or die "Not a git repo\n"; + + my $codeowners_path = find_codeowners_in_directory($toplevel) + or die "No CODEOWNERS file in $toplevel\n"; + my $codeowners = File::Codeowners->parse_from_filepath($codeowners_path); + + my $results = $codeowners->projects; + + my $formatter = App::Codeowners::Formatter->new( + format => $opts->{format} || '%P', + handle => *STDOUT, + columns => [qw(Project)], + ); + $formatter->add_result(map { [$_] } @$results); +} + sub _command_create { goto &_command_update } sub _command_update { my $self = shift; diff --git a/lib/App/Codeowners/Options.pm b/lib/App/Codeowners/Options.pm index 67dc324..7b43b75 100644 --- a/lib/App/Codeowners/Options.pm +++ b/lib/App/Codeowners/Options.pm @@ -30,8 +30,13 @@ sub command_options { 'patterns' => { 'owner=s' => '', }, + 'projects' => {}, 'show' => { - 'project!' => 1, + 'owner=s@' => [], + 'pattern=s@' => [], + 'project=s@' => [], + 'patterns!' => 0, + 'projects!' => undef, }, 'update' => {}, }; diff --git a/lib/File/Codeowners.pm b/lib/File/Codeowners.pm index fb3ec55..648390e 100644 --- a/lib/File/Codeowners.pm +++ b/lib/File/Codeowners.pm @@ -355,6 +355,31 @@ sub patterns { return $patterns; } +=method projects + + $projects = $codeowners->projects; + +Get an arrayref of all projects defined. + +=cut + +sub projects { + my $self = shift; + + return $self->{projects} if $self->{projects}; + + my %projects; + for my $line (@{$self->_lines}) { + my $project = $line->{project}; + $projects{$project}++ if $project; + } + + my $projects = [sort keys %projects]; + $self->{projects} = $projects; + + return $projects; +} + =method update_owners $codeowners->update_owners($pattern => \@new_owners); @@ -497,6 +522,7 @@ sub _clear { delete $self->{match_lines}; delete $self->{owners}; delete $self->{patterns}; + delete $self->{projects}; } 1; diff --git a/t/app-codeowners.t b/t/app-codeowners.t index 6441539..28309d3 100644 --- a/t/app-codeowners.t +++ b/t/app-codeowners.t @@ -65,7 +65,7 @@ END subtest 'format json' => sub { plan skip_all => 'No JSON::MaybeXS' if !eval { require JSON::MaybeXS }; - ($stdout, $stderr, $exit) = run { App::Codeowners->main(qw{-f json show --no-project}) }; + ($stdout, $stderr, $exit) = run { App::Codeowners->main(qw{-f json show --no-projects}) }; is($exit, 0, 'exited without error'); my $expect = '[{"File":"CODEOWNERS","Owner":null},{"File":"a/b/c/bar.txt","Owner":["@snickers"]},{"File":"foo.txt","Owner":["@twix"]}]'; is($stdout, $expect, 'correct output with json format');