From 6568d5ded4f54ec5ff663b0196f10488910145b4 Mon Sep 17 00:00:00 2001 From: Charles McGarvey Date: Fri, 17 Jan 2020 13:50:25 -0700 Subject: [PATCH] add rename_project function to File::Codeowners Also add update_owners_by_project function. --- lib/File/Codeowners.pm | 71 +++++++++++++++++++++++++++++++++++++++++- t/file-codeowners.t | 24 ++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/lib/File/Codeowners.pm b/lib/File/Codeowners.pm index 8ca8393..7212c23 100644 --- a/lib/File/Codeowners.pm +++ b/lib/File/Codeowners.pm @@ -98,11 +98,13 @@ sub parse_from_fh { } elsif ($line =~ /^\h*#(.*)/) { my $comment = $1; + my $project; if ($comment =~ /^\h*Project:\h*(.+?)\h*$/i) { - $current_project = $1 || undef; + $project = $current_project = $1 || undef; } $lines[$lineno] = { comment => $comment, + $project ? (project => $project) : (), }; } elsif ($line =~ /^\h*$/) { @@ -401,11 +403,78 @@ sub update_owners { $self->_clear; + my $count = 0; + for my $line (@{$self->_lines}) { next if !$line->{pattern}; next if $pattern ne $line->{pattern}; $line->{owners} = [@$owners]; + ++$count; } + + return $count; +} + +=method update_owners_by_project + + $codeowners->update_owners_by_project($project => \@new_owners); + +Set a new set of owners for all patterns under the given project. + +Nothing happens if the file does not have a project with the given name. + +=cut + +sub update_owners_by_project { + my $self = shift; + my $project = shift; + my $owners = shift; + $project && $owners or _usage(q{$codeowners->update_owners_by_project($project => \@owners)}); + + $owners = [$owners] if ref($owners) ne 'ARRAY'; + + $self->_clear; + + my $count = 0; + + for my $line (@{$self->_lines}) { + next if !$line->{project} || !$line->{owners}; + next if $project ne $line->{project}; + $line->{owners} = [@$owners]; + ++$count; + } + + return $count; +} + +=method rename_project + + $codeowners->rename_project($old_name => $new_name); + +Rename a project. + +Nothing happens if the file does not have a project with the old name. + +=cut + +sub rename_project { + my $self = shift; + my $old_project = shift; + my $new_project = shift; + $old_project && $new_project or _usage(q{$codeowners->rename_project($project => $new_project)}); + + $self->_clear; + + my $count = 0; + + for my $line (@{$self->_lines}) { + next if !exists $line->{project} || $old_project ne $line->{project}; + $line->{project} = $new_project; + $line->{comment} = " Project: $new_project" if exists $line->{comment}; + ++$count; + } + + return $count; } =method append diff --git a/t/file-codeowners.t b/t/file-codeowners.t index a50a050..7bfb53c 100644 --- a/t/file-codeowners.t +++ b/t/file-codeowners.t @@ -94,6 +94,30 @@ subtest 'parse errors', sub { like($@, qr/^Parse error on line 1/, 'parse error'); }; +subtest 'handling projects', sub { + my $file = File::Codeowners->parse("$Bin/samples/kitchensink.CODEOWNERS"); + my $r; + + is_deeply($r = $file->projects, [ + 'Transportation', + ], 'projects listed') or diag explain $r; + + $file->rename_project('Transportation', 'Getting Around'); + is_deeply($r = $file->projects, [ + 'Getting Around', + ], 'project renamed') or diag explain $r; + + is_deeply($r = [@{$file->_lines}[-3 .. -1]], [ + {comment => ' Project: Getting Around', project => 'Getting Around'}, + {}, + {pattern => '/vehicles/**/batmobile.cad', 'owners' => ['@"Lucius Fox"'], project => 'Getting Around'}, + ], 'renaming project properly modifies lines') or diag explain $r; + + $file->update_owners_by_project('Getting Around', '@twoface'); + ok( scalar grep { $_ eq '@twoface' } @{$file->owners}, 'updating owner adds new owner'); + ok(!scalar grep { $_ eq '@"Lucius Fox"' } @{$file->owners}, 'updating owner removes old owner'); +}; + subtest 'editing and writing files', sub { my $file = File::Codeowners->parse("$Bin/samples/basic.CODEOWNERS"); my $r; -- 2.43.0