App-Gitc
view release on metacpan or search on metacpan
bin/gitc-submit view on Meta::CPAN
. "reviewer with any instructions he might need to correctly\n"
. "resolve the conflicts.\n"
. "Press ENTER to continue.\n";
;
my $junk = <STDIN>;
}
# export the patch emails and let the user edit the cover
my ( $tmpdir, $cover_letter ) = export_patches($changeset);
let_user_edit($cover_letter) unless ($skip_email || $skip_edit);
# die if the user deleted the entire cover letter
die "Aborting submit at the user's request\n" if -s $cover_letter <= 10;
update_email_headers( $tmpdir, $cover_letter );
# record the submit action in meta data
my $id = meta_data_add({
action => 'submit',
changeset => $changeset,
reviewer => $reviewer,
});
to_undo { meta_data_rm(id => $id, changeset => $changeset) };
# record the review action for self-review
if ( $self_review ) {
my $id = meta_data_add({
action => 'review',
changeset => $changeset,
});
to_undo { meta_data_rm(id => $id, changeset => $changeset) };
}
# put the changeset branch where others can see it
if ( not $self_review ) {
git "push --force origin $changeset:pu/$changeset";
to_undo { git "push origin :pu/$changeset" };
}
# delete the local branch
if ( not $keep ) {
git "checkout master";
to_undo { git "checkout -f $changeset" };
local $@;
eval { # failing in here is ok
my $sha1 = is_valid_ref($changeset);
git "branch -D $changeset";
to_undo { git "branch $changeset $sha1" };
};
warn "Unable to delete branch $changeset: $@\n" if $@;
}
# blast out the emails
git "send-email --to " . get_user_email($reviewer)
. ' --from "' . author_email() . '"'
. ' --no-chain-reply-to'
. ' --signed-off-by-cc'
. ' --suppress-cc author'
. ' --suppress-from'
. ' --quiet'
. ' --no-validate'
. " $tmpdir/*.patch"
if not $skip_email
;
if ($its) {
# update the Issue status
my $issue = $its->get_issue($changeset, reload => 1);
my $project = project_name();
my $what_happened = $its->transition_state({
command => 'submit',
issue => $issue,
reviewer => $reviewer,
message => "Submitted $project#$changeset to $reviewer for code review",
changeset => $changeset,
});
}
return;
};
# reinstate any changes present when we started
git "stash apply $stash" if $stash;
exec "gitc pass --from-self-review" if $self_review;
exit;
################################ helper subs ########################
# decide who should review this changeset
sub find_reviewer {
my $reviewer = shift or die "You must specify a reviewer\n";
# handle self-review for dataload projects
my $current_user = get_user_name();
if ( $reviewer eq $current_user ) {
if ( project_config()->{'self submit'} ) {
$self_review = 1;
$skip_email = 1;
$keep = 1;
return $reviewer;
}
}
validate_reviewer($reviewer);
return $reviewer;
}
# determine whether the given reviewer is valid. if not, suggest
# an alternative based on possible mis-spellings
sub validate_reviewer {
my ($reviewer) = @_;
fetch_tags();
my @users = user_lookup_class()->users();
return if any { $_ eq $reviewer } @users;
# an invalid reviewer. make some suggestions
require Text::Levenshtein;
require List::Util;
my @suggestions =
map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
grep { $_->[1] < 4 } # only "close" matches
map { [ $_, scalar Text::Levenshtein::distance( $reviewer, $_ ) ] }
@users;
my @short_list = @suggestions[ 0 .. List::Util::min($#suggestions, 2) ];
my $msg = "The user name '$reviewer' is invalid. ";
if (@suggestions) {
$msg .= "Perhaps you meant one of:\n";
$msg .= " - $_\n" for @short_list;
}
else {
$msg .= "\n";
}
die $msg;
}
# Execute a rebase (and never return) if this changeset hasn't accounted
# for the most recent commits on its 'onto' branch.
sub launch_auto_rebase {
my ($branch_point) = @_;
# are there new commits since the changeset branch?
my $basis = branch_basis($branch_point);
return if $basis !~ /^(master|test|stage|prod)$/;
my @upstream = git "rev-list --first-parent origin/$basis ^HEAD";
return if not @upstream;
# yup, so start a rebase
my $count = @upstream;
my $s = $count == 1 ? '' : 's';
warn "Uh oh, $basis has $count commit$s since you started.\n"
. "I'm rebasing for you. When it's done, resubmit.\n"
. "\n"
;
exec "git rebase --onto origin/$basis $branch_point";
}
sub export_patches {
my ($changeset) = @_;
# generate the patches
require File::Temp;
my $tmpdir = File::Temp::tempdir(
'gitc-submit-XXXXX',
TMPDIR => 1,
CLEANUP => 1,
);
( run in 1.015 second using v1.01-cache-2.11-cpan-39bf76dae61 )