ShipIt::VC::Git - ShipIt's git support


ShipIt documentation Contained in the ShipIt distribution.

Index


Code Index:

NAME

Top

ShipIt::VC::Git -- ShipIt's git support

CONFIGURATION

Top

In your .shipit configuration file, the following options are recognized:

git.tagpattern

Defines how the tag are defined in your git repo.

git.sign_tag

This should be set to a truthy value, if you wish the tags to be GPG signed. (git tag -s ...)

git.push_to

If you want the newly created to be pushed elsewhere (for instance in your public git repository), then you can specify the destination in this variable


ShipIt documentation Contained in the ShipIt distribution.

package ShipIt::VC::Git;
use strict;
use base 'ShipIt::VC';
use File::Temp ();

sub command { 'git' }

sub new {
    my ($class, $conf) = @_;
    my $self = bless {}, $class;
    $self->{tagpattern} = $conf->value( $self->command . ".tagpattern" );
    $self->{sign_tag} = $conf->value( $self->command . ".sign_tag" );
    $self->{push_to} = $conf->value( $self->command . ".push_to" );
    return $self;
}

sub exists_tagged_version {
    my ($self, $ver) = @_;

    my $command = $self->command;
    my $x = `git tag -l $ver`;
    chomp $x;
    return $x;
}

sub commit {
    my ($self, $msg) = @_;

    my $command = $self->command;

    if ( my $unk = `git ls-files -z --others --exclude-per-directory=.gitignore --exclude-from=.git/info/exclude` ) {
        $unk =~ s/\0/\n/;
        die "Unknown local files:\n$unk\n\nUpdate .gitignore, or $command add them";
        exit(1);
    }

    # commit
    my $tmp_fh = File::Temp->new(UNLINK => 1, SUFFIX => '.msg');
    print $tmp_fh $msg;
    my $tmp_fn = "$tmp_fh";
    system($command, "commit", "-a", "-F", $tmp_fn);

    if (my $where = $self->{push_to}) {
        my $branch = $self->_get_branch;
        if ($branch) {
            warn "pushing to $where";
            system($self->command, "push", $where, $branch);
        }
    }
}

sub _get_branch {
    my $self = shift;

    open my $fh, '<', '.git/HEAD';
    chomp(my $head = do { local $/; <$fh> });
    close $fh;

    my ($branch) = $head =~ m!ref: refs/heads/(\S+)!;
    return $branch;
}

sub local_diff {
    my ($self, $file) = @_;
    my $command = $self->command;
    return `$command diff --no-color HEAD $file`;
}

sub _tag_of_version {
    my ($self, $ver) = @_;
    my $tag = $self->{tagpattern} || '';
    $tag .= "%v" unless $tag =~ /\%v/i;
    $tag =~ s/\%v/$ver/ig;
    return $tag;
}

sub tag_version {
    my ($self, $ver, $msg) = @_;
    $msg ||= "Tagging version $ver.\n";
    my $tmp_fh = File::Temp->new(UNLINK => 1, SUFFIX => '.msg');
    print $tmp_fh $msg;
    my $tmp_fn = "$tmp_fh";
    my $tag = $self->_tag_of_version($ver); 
    system($self->command, "tag", "-a", ($self->{sign_tag} ? "-s" : ()), "-F", $tmp_fn, $tag)
        and die "Tagging of version '$ver' failed.\n";

    if (my $where = $self->{push_to}) {
        warn "pushing to $where";
        system($self->command, "push", $where, tag => $tag);
    }
}

sub are_local_diffs {
    my ($self, $ver) = @_;
    my $command = $self->command;
    my $diff = `$command diff --no-color $ver`;
    return $diff =~ /\S/ ? 1 : 0;
}

1;