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 )