X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=lib%2FApp%2FCodeowners.pm;h=ac88f6184c91440656f7f9f83f4662953b01372b;hb=1c893b7e095fdaffdf47ffee426407a1f7e305fb;hp=20be9855fa51d7917a683fb6ce8c0321f7c6ff87;hpb=26eed33eb4aa577d9347e5ebaf577b3e3a2c0396;p=chaz%2Fgit-codeowners diff --git a/lib/App/Codeowners.pm b/lib/App/Codeowners.pm index 20be985..ac88f61 100644 --- a/lib/App/Codeowners.pm +++ b/lib/App/Codeowners.pm @@ -10,7 +10,6 @@ use App::Codeowners::Formatter; use App::Codeowners::Options; use App::Codeowners::Util qw(find_codeowners_in_directory run_git git_ls_files git_toplevel); use Color::ANSI::Util 0.03 qw(ansifg); -use Encode qw(encode); use File::Codeowners; use Path::Tiny; @@ -36,6 +35,8 @@ sub main { my $command = $opts->command; my $handler = $self->can("_command_$command") or die "Unknown command: $command\n"; + + binmode(STDOUT, ':encoding(UTF-8)'); $self->$handler($opts); exit 0; @@ -54,19 +55,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 +140,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; @@ -137,7 +185,7 @@ sub _command_update { my $template = <<'END'; This file shows mappings between subdirs/files and the individuals and teams who own them. You can read this file yourself or use tools to query it, - so you can quickly determine who to speak with or send pull requests to. ❤️ + so you can quickly determine who to speak with or send pull requests to. Simply write a gitignore pattern followed by one or more names/emails/groups. Examples: @@ -154,11 +202,10 @@ END if ($repopath) { # if there is a repo we can try to update the list of unowned files - my $git_files = git_ls_files($repopath); - if (@$git_files) { - $codeowners->clear_unowned; - $codeowners->add_unowned(grep { !$codeowners->match($_) } @$git_files); - } + my ($proc, @filepaths) = git_ls_files($repopath); + $proc->wait and exit 1; + $codeowners->clear_unowned; + $codeowners->add_unowned(grep { !$codeowners->match($_) } @filepaths); } $codeowners->write_to_filepath($path); @@ -166,3 +213,12 @@ END } 1; +__END__ + +=head1 DESCRIPTION + +This is the implementation of the F command. + +See L for documentation. + +=cut