App-Sqitch

 view release on metacpan or  search on metacpan

lib/App/Sqitch/Command/checkout.pm  view on Meta::CPAN

    my $git    = $self->client;
    my $engine = $target->engine;
    $engine->with_verify( $self->verify );
    $engine->log_only( $self->log_only );
    $engine->lock_timeout( $self->lock_timeout );

    # What branch are we on?
    my $current_branch = $sqitch->probe($git, qw(rev-parse --abbrev-ref HEAD));
    hurl {
        ident   => 'checkout',
        message => __x('Already on branch {branch}', branch => $branch),
        exitval => 1,
    } if $current_branch eq $branch;

    # Instantitate a plan without calling $target->plan.
    my $from_plan = App::Sqitch::Plan->new(
        sqitch => $sqitch,
        target => $target,
    );

    # Load the branch plan from Git, assuming the same path.
    my $to_plan = App::Sqitch::Plan->new(
        sqitch => $sqitch,
        target => $target,
      )->parse(
        # Git assumes a relative file name is relative to the repo root, even
        # when you're in a subdirectory. So we have to prepend the currrent
        # directory path ./ to convince it to read the file relative to the
        # current directory. See #560 and
        # https://git-scm.com/docs/gitrevisions#Documentation/gitrevisions.txt-emltrevgtltpathgtemegemHEADREADMEememmasterREADMEem
        # for details.
        # XXX Handle missing file/no contents.
        scalar $sqitch->capture(
            $git, 'show', "$branch:"
            . File::Spec->catfile(File::Spec->curdir, $target->plan_file)
        )
    );

    # Find the last change the plans have in common.
    my $last_common_change;
    for my $change ($to_plan->changes){
        last unless $from_plan->get( $change->id );
        $last_common_change = $change;
    }

    hurl checkout => __x(
        'Branch {branch} has no changes in common with current branch {current}',
        branch  => $branch,
        current => $current_branch,
    ) unless $last_common_change;

    $sqitch->info(__x(
        'Last change before the branches diverged: {last_change}',
        last_change => $last_common_change->format_name_with_tags,
    ));

    # Revert to the last common change.
    $engine->set_variables( $self->_collect_revert_vars($target) );
    $engine->plan( $from_plan );
    try {
        $engine->revert( $last_common_change->id, ! $self->no_prompt, $self->prompt_accept );
    } catch {
        # Rethrow unknown errors or errors with exitval > 1.
        die $_ if ! eval { $_->isa('App::Sqitch::X') }
            || $_->exitval > 1
            || $_->ident eq 'revert:confirm';
        # Emite notice of non-fatal errors (e.g., nothing to revert).
        $self->info($_->message)
    };


    # Check out the new branch.
    $sqitch->run($git, 'checkout', $branch);

    # Deploy!
    $engine->set_variables( $self->_collect_deploy_vars($target) );
    $engine->plan( $to_plan );
    $engine->deploy( undef, $self->mode);
    return $self;
}

1;

__END__

=head1 Name

App::Sqitch::Command::checkout - Revert, change checkout a VCS branch, and redeploy

=head1 Synopsis

  my $cmd = App::Sqitch::Command::checkout->new(%params);
  $cmd->execute;

=head1 Description

If you want to know how to use the C<checkout> command, you probably want to
be reading C<sqitch-checkout>. But if you really want to know how the
C<checkout> command works, read on.

=head1 Interface

=head2 Class Methods

=head3 C<options>

  my @opts = App::Sqitch::Command::checkout->options;

Returns a list of L<Getopt::Long> option specifications for the command-line
options for the C<checkout> command.

=head2 Instance Methods

=head3 C<execute>

  $checkout->execute;

Executes the checkout command.

=head1 See Also



( run in 0.591 second using v1.01-cache-2.11-cpan-0b5f733616e )