App-Gitc
view release on metacpan or search on metacpan
bin/gitc-promote view on Meta::CPAN
git
git_tag
guarantee_a_clean_working_directory
is_suspendable
is_valid_ref
is_merge_commit
its_for_changeset
meta_data_add
meta_data_rm
new_version_tag
project_config
project_name
restore_meta_data
short_ref_name
sort_changesets_by_name
unpromoted
);
use App::Gitc::Reversible;
use POSIX qw( strftime );
use Getopt::Long qw( :config pass_through );
# git 1.7.10 added interactive logging of merges. Since promotions can
# involve hundreds of merges, we really don't want interactive logging.
$ENV{GIT_MERGE_AUTOEDIT} = 'no';
our $dry_run;
our $ignore_dependencies;
our $force;
our $verify_promotion = 1;
our $except;
our $without_theirs;
our $new_major_version;
GetOptions(
'except|X=s' => \$except,
'force|f' => \$force,
'no-verify' => sub { $verify_promotion = 0 },
'dry-run|n' => \$dry_run,
'I|ignore-changeset-dependencies' => \$ignore_dependencies,
'without-theirs' => \$without_theirs,
'new-major-version' => \$new_major_version,
);
is_suspendable();
my $refs;
my $changesets_list;
our $target;
git "remote update -p origin";
( $target, $refs, $changesets_list ) = parse_command_line(@ARGV);
my @refs = @$refs;
# calculate the changeset list based on --except
my $source = environment_preceding($target);
my @available = unpromoted( "origin/$source", "origin/$target" );
if ($except) {
die "You gave --except and a list of changesets. You may only specify "
. "one or the other\n"
if @refs;
my %except = map { $_ => 1 } split /,/, $except;
@refs = map { $except{$_} ? () : full_changeset_name($_) } @available;
die "It looks like you excluded all the changesets\n" if not @refs;
}
my $cherry_pick = @refs ? 1 : 0;
# handle dependencies for cherry pick promotions
if ($cherry_pick) {
if ( not $ignore_dependencies ) {
while ( my @missing = find_missing_dependencies( $target, @refs ) ) {
@refs = handle_missing_dependencies( \@refs, \@missing );
}
}
# prevent out of order promotions (it must go master->test->stage->prod)
my %available = map { ( $_ => 1 ) } @available;
my @out_of_order =
grep { not $available{$_} }
map { short_ref_name($_) }
@refs;
if (@out_of_order) {
warn "These changesets have not yet been promoted to $source:\n";
sort_changesets_by_name(\@out_of_order);
warn " - $_\n" for @out_of_order;
exit 1;
}
}
# don't do any real work if this is just a dry run
if ($dry_run) {
if ($cherry_pick) {
warn "Would promote the following changesets:\n";
my @changesets = map { short_ref_name($_) } @refs;
sort_changesets_by_name(\@changesets);
warn sprintf(" - %s\n", short_ref_name($_) ) for @changesets;
}
else {
warn "Promoting all of $source to $target would promote:\n";
sort_changesets_by_name(\@available);
warn " - $_\n" for @available;
}
exit;
}
my $original_branch = current_branch();
my $stash;
my @new_tags;
reversibly {
failure_warning "\nCanceling promotion to $target\n";
$stash = guarantee_a_clean_working_directory();
to_undo { git "stash apply $stash" if $stash; $stash = undef };
# create an integration branch for merging all the changesets
my $integration_branch_existed = is_valid_ref($target);
if ( $integration_branch_existed ) {
git "checkout $target";
git "reset --hard origin/$target";
to_undo { git "checkout -f $original_branch" };
}
else {
git "checkout --no-track -b $target origin/$target";
to_undo {
( run in 1.970 second using v1.01-cache-2.11-cpan-5837b0d9d2c )