diff --git a/git-hooks/gerrit-bot b/git-hooks/gerrit-bot index 915b3ec018d1bf62a2788ad37ac9323365459fe8..c95af579da93f83d10010534b5bce32e4bc00194 100755 --- a/git-hooks/gerrit-bot +++ b/git-hooks/gerrit-bot @@ -45,6 +45,17 @@ use File::Path; # <project>:<branch>. # maintainers (optional) # Space-separated list of reviewers to add on "special occasions". +# watches (optional) +# Space-separated list of path watches. Each watch requires an own +# section named watches.<name> with the following keys: +# projects (default ".*") +# Regular expression specifying the projects to watch. +# files +# Regular expression specifying the filepaths to watch. +# message (optional) +# The message to post when this watch triggers. +# invite (optional) +# Space-separated list of reviewers to add when this watch triggers. # verbose (default 0) # Print progress/result messages. @@ -87,8 +98,22 @@ my $GIT_DO_FETCH = getcfg 'gitdofetch'; my $WORKER = getcfg 'worker'; my %EXCLUDED_PROJECTS = map { $_ => 1 } split(/\s+/, getcfg('excluded', "")); my @MAINTAINERS = split(/\s+/, getcfg('maintainers', "")); +my @WATCHES = split(/\s+/, getcfg('watches', "")); my $verbose = getcfg 'verbose', 0; +my (%watch_projects, %watch_files, %watch_messages, %watch_invites); +for my $w (@WATCHES) { + my $p = $config{'watches.'.$w.'.projects'}; + $watch_projects{$w} = defined($p) ? qr/^$p$/ : undef; + my $f = $config{'watches.'.$w.'.files'}; + die "watches.$w.files not set.\n" if (!defined($f)); + $watch_files{$w} = qr/^$f$/; + my $m = $config{'watches.'.$w.'.message'}; + $watch_messages{$w} = defined($m) ? $m."\n\n" : ""; + my $i = $config{'watches.'.$w.'.invite'}; + $watch_invites{$w} = defined($i) ? [ split(/\s+/, $i) ] : []; +} + my $gerrit_rest; if ($REST_HOST) { use Gerrit::REST; @@ -119,6 +144,7 @@ sub process_commit($$$$$) my $orig_project = $project; $project =~ s,/$,,; # XXX Workaround QTQAINFRA-381 my ($score, $verdict); + my $message = ""; my @invite; my $use_rest = 0; if (defined($EXCLUDED_PROJECTS{$project}) || defined($EXCLUDED_PROJECTS{$project.":".$branch})) { @@ -157,6 +183,26 @@ sub process_commit($$$$$) } $verbose and print "===== ".strftime("%c", localtime(time()))." ===== fetched change\n"; } + + my @watches; + for my $w (@WATCHES) { + my $wp = $watch_projects{$w}; + push @watches, $w if (!defined($wp) || $project =~ $wp); + } + if (@watches) { + my @touched = `git diff-tree --name-only --no-commit-id --ignore-submodules -r -C --root $rev`; + chop(@touched); + for my $w (@watches) { + for my $file (@touched) { + if ($file =~ $watch_files{$w}) { + $message .= $watch_messages{$w}; + push @invite, @{$watch_invites{$w}}; + last; + } + } + } + } + my $worker = $WORKER; $worker =~ s/\@SHA1\@/$rev/g; open VERDICT, $worker." 2>&1 |" or die "cannot run worker: ".$!; @@ -186,6 +232,9 @@ sub process_commit($$$$$) } } if ($use_rest) { + if (defined($$verdict{message}) || length($message)) { + $$verdict{message} = $message.($$verdict{message} || ""); + } eval { $gerrit_rest->POST("/changes/$number/revisions/$rev/review", $verdict); }; @@ -195,6 +244,7 @@ sub process_commit($$$$$) return; } } else { + $verdict = $message.$verdict; my @args = (); # push @args, ("--project", $project); push @args, ("--project", $orig_project); # XXX Workaround QTQAINFRA-381 diff --git a/git-hooks/sanitize-commit b/git-hooks/sanitize-commit index c38763dc016d7f6a4c4442f5a15e1a3500ed6790..909e98faf0ae725109d3d8729656239ebf205854 100755 --- a/git-hooks/sanitize-commit +++ b/git-hooks/sanitize-commit @@ -45,11 +45,6 @@ if (defined $config{flags}) { $cfg{$c} = 1; } } -my (%watch_files, %watch_messages); -for my $key (keys %config) { - $watch_files{$1} = $config{$key} if ($key =~ /^watches\.([^.]+)\.files/); - $watch_messages{$1} = $config{$key} if ($key =~ /^watches\.([^.]+)\.message/); -} # The whitelist is space-separated, supporting double-quoted strings with spaces. # Remember to backslash-escape the quotes if you edit .gitconfig manually. my %good_names; @@ -623,11 +618,6 @@ while (<DIFF>) { #print "*** got file ".$file.".\n"; $clike = ($file =~ /\.(c|cc|cpp|c\+\+|cxx|qdoc|m|mm|h|hpp|hxx|cs|java|js|qs|qml|g|y|ypp|pl|glsl)$/i); $qmake = ($file =~ /\.pr[filo]$/i); - for my $key (keys %watch_files) { - if ($file =~ /^$watch_files{$key}$/) { - complain($watch_messages{$key}, "", -1); - } - } $is_bin = ($file =~ /\.(ps|pdf)$/); my $foreign = $is_bin || ($file =~ /(^|\/)3rdparty\//); $new_file = 0;