Page MenuHomeFreeBSD

ports-hook

Authored By
mat
Apr 16 2021, 2:23 PM
Size
7 KB
Referenced Files
None
Subscribers
None

ports-hook

#!/usr/local/bin/perl
# vim:sts=4 sw=4 et
# perltidy -bext=/ -se -i=4 -it=2 -ci=2 -xci -l=132 -pt=2 -ce -cti=1 -cab=4 -cb -cbo=0 -wbb="% + - * / x != == >= <= =~ !~ < > | &" -enc=utf8 -wn -sot -sct -asc -tqw -sbq=0 -csc -csct=30
use strict;
use warnings;
use 5.024;
use Git;
################################################################
# Helper functions
################################################################
my $git = Git->repository;
my $branch_main = 'refs/heads/main';
my $re_quarterlies = qr{^refs/heads/20\d\dQ\d\z}oms;
{ # sub context to avoid leaking @push_options
my @push_options;
for (my $i = 0 ; $i < $ENV{GIT_PUSH_OPTION_COUNT} ; ++$i) {
push @push_options, $ENV{"GIT_PUSH_OPTION_${i}"};
}
sub has_option {
my ($opt) = @_;
for (@push_options) {
return 1 if $opt eq $_;
}
return 0;
} ## end sub has_option
}
my @quarterlies;
for ($git->command('show-ref', '--heads')) {
my ($hash, $ref) = split / /;
next if $ref !~ m{refs/heads/\d\d\d\dQ\d\z}oms;
push @quarterlies, $ref;
}
@quarterlies = sort @quarterlies;
my $latest_quarterly = $quarterlies[-1];
sub do_die {
die "\n================================================================\n"
. join("\n", @_)
. "\n================================================================\n\n";
}
sub short_ref {
my ($ref) = @_;
$ref =~ s{refs/heads/}{}oms;
return $ref;
}
################################################################
# Here starts actual hooks
################################################################
# Some filenames are forbidden in the repo.
sub deny_filenames {
my ($rev, @changed) = @_;
for my $line (@changed) {
if (
$line =~ m{\A(?:CVS|[.](?:svn|git))\z}oms # cvs/svn/git
|| $line =~ m{[.](?:rej|orig)\z}oms # patch
|| $line =~ m{[.]core\z}oms # core file
)
{
do_die
'This file in your commit look suspiciously like core file,',
'patch leftover, CVS, Subversion or git directory:',
$line,
'Please double-check your commit and try committing again.';
} ## end if ($line =~ m{\A(?:CVS|[.](?:svn|git))\z}oms...)
if ($line =~ m{(?:\A|/)Makefile.local\z}oms) {
do_die
'Makefile.local is a user file and MUST NOT be committed:',
$line;
}
} ## end for my $line (@changed)
} ## end sub deny_filenames
################################################################
# Empty files forbidden
sub empty {
my ($rev, @changed) = @_;
for my $file (@changed) {
my $content = $git->command('show', "$rev:$file");
next if length($content) > 0;
do_die
"Some files in your commit are empty: $file",
"Please fix this and try committing again.";
} ## end for my $file (@changed)
} ## end sub empty
################################################################
# vulm.xml has to be committed alone, as it is never merged back to the
# quarterly branches.
sub vuxml_unique {
my ($ref, $rev, @changed) = @_;
my ($seen, $other) = (0, 0);
for my $line (@changed) {
if ($line =~ m{\Asecurity/vuxml/vuln(?:-\d{4})?.xml\z}oms) {
$seen = 1;
} else {
$other = 1;
}
} ## end for my $line (@changed)
if ($seen && $branch_main ne $ref) {
do_die "Commits to security/vuxml/vuln.xml are only allowed on main";
}
if ($seen && $other) {
do_die "Commit to security/vuxml/vuln.xml first, and then other files";
}
} ## end sub vuxml_unique
################################################################
# Check git cherry-pick ran with `-x`
sub cherry_pick {
my ($ref, $log) = @_;
# Only do this on quarterlies
return if $ref !~ $re_quarterlies;
# Gave the magic push option
return if has_option('direct-quarterly-commit');
# Found the actual magic words
return if $log =~ m{
^ # Start of line
[(] # A litteral opening parenthesis
cherry[ ]picked[ ]from[ ]commit # The magic words
[0-9a-fA-F]{30,} # A commit hash
[)] # A litteral closing parenthesis
$ # End of line
}omsx;
do_die # Comments
"$ENV{GL_USER}, you are pushing a commit to ${\(short_ref($ref))} which does", # to get this
'not seems to be a cherry-pick.', # indented
'', # properly
'If you did a cherry-pick, you probably forgot to add `-x`,', # by
'make sure you do run `git cherry-pick -x <hash>`.', # perltidy
'', #
'If you did a direct commit, make sure it was approved first, and then run:', #
"\tgit push --push-option=direct-quarterly-commit";
} ## end sub cherry_pick
################################################################
# Check that commits only go to the latest quarterly branch
sub unsupported_quarterly {
my ($ref) = @_;
# Only applies to quarterlies
return if $ref !~ $re_quarterlies;
# Gave the magic push option
return if has_option('direct-quarterly-commit');
do_die # Comments
"$ENV{GL_USER}, you are pushing a commit to ${\(short_ref($ref))} which is not", # for
"the latest quarterly branch. The latest is ${\(short_ref($latest_quarterly))}.", # indentation
'', #
'Please check that you really mean to do this, and got approval, use:', #
"\tgit push --push-option=unsupported-quarterly";
} ## end sub unsupported_quarterly
################################################################
# Check log does not contains stuff generated by phabricator
sub stomp_bad_formatting {
my ($log) = @_;
if ($log =~ m|\n\nReviewers:[\t ]+|oms) {
do_die "Non-standard/badly formatted template - found 'Reviewers:' instead of 'Reviewed by:'.";
}
if ($log =~ m|\n\nSubscribers:[\t ]+|oms) {
do_die "Non-standard/badly formatted template - found 'Subscribers:'.";
}
} ## end sub stomp_bad_formatting
################################################################
# Main loop, everything called in here.
for (<STDIN>) {
chomp;
my ($old, $new, $ref) = split / /;
unsupported_quarterly($ref);
for my $rev ($git->command('log', '--format=%H', $new, '--not', '--all')) {
my @changed = $git->command('diff', '--name-only', "$rev~1..$rev");
my $log = $git->command('show', '-s', '--format=%B', $rev);
deny_filenames($rev, @changed);
vuxml_unique($ref, $rev, @changed);
cherry_pick($ref, $log);
stomp_bad_formatting($log);
empty($rev, @changed);
} ## end for my $rev ($git->command('log',...))
} ## end for (<STDIN>)
exit 1;

File Metadata

Mime Type
text/plain; charset=utf-8
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3601241
Default Alt Text
ports-hook (7 KB)

Event Timeline