App-Gitc
view release on metacpan or search on metacpan
lib/App/Gitc/Util.pm view on Meta::CPAN
$msg = "failed to execute: $!";
}
elsif ( $? & 127 ) {
$msg = sprintf "died with signal %d", ( $? & 127 );
}
else {
$msg = sprintf "exited with value %d", ( $? >> 8 );
}
require Carp;
Carp::croak("git $command_line failed: $msg");
}
elsif ( wantarray ) { # list context
warn "> git $command_line\n" if $ENV{DEBUG};
my @output = qx{git $command_line};
# there's no reliable way to check if this failed
chomp @output;
return @output;
}
# scalar context
warn "> git $command_line\n" if $ENV{DEBUG};
my $output = qx{git $command_line};
if ( not defined $output ) {
require Carp;
Carp::croak("git $command_line failed: $!");
}
chdir $start unless $start eq $base;
chomp $output;
return $output;
}
sub git_config {
our %config;
if ( not keys %config ) {
for my $line ( git "config -l" ) {
my ($name, $value) = split /=/, $line;
my @parts = split /[.]/, $name;
my $here = \%config;
for my $part ( @parts[ 0 .. $#parts-1 ] ) {
$here->{$part} = {} if not $here->{$part};
$here = $here->{$part};
}
$here->{ $parts[-1] } = $value;
}
}
return \%config;
}
sub guarantee_a_clean_working_directory {
my $arguments = "diff -C -M --name-status";
my $staged = git "$arguments --cached";
my $changed = git $arguments;
return if not $staged and not $changed;
# the tree is dirty, verify whether to continue
warn "It looks like you have uncommitted changes. If this is expected,\n"
. "type 'y' to continue. If it's not expected, type 'n'.\n"
. ( $staged ? "staged:\n$staged\n" : '' )
. ( $changed ? "changed:\n$changed\n" : '' )
;
die "Aborting at the user's request.\n" if not confirm('Continue?');
# stash the changes to let them be restored later
my $stash = git "stash create";
git "reset --hard";
return $stash;
}
sub let_user_edit {
my ($filename) = @_;
my $editor = $ENV{EDITOR} || $ENV{VISUAL} || '/usr/bin/vim';
system "$editor $filename";
}
sub create_blob {
my ($data_ref) = @_;
my $tmp_file = "meta-$$.tmp";
open my $tmp, ">", $tmp_file;
print {$tmp} Dump($data_ref);
print {$tmp} "\n";
my $blob = git "hash-object -w $tmp_file";
close $tmp;
unlink $tmp_file;
return $blob;
}
sub view_blob {
my ($ref) = @_;
my $output = git "show $ref";
return ($output and $output !~ /^fatal:/) ? Load($output) : undef;
}
sub get_user_name {
my $git_user = git 'config --get user.name';
my $git_config = git_config();
return $git_user || $git_config->{user}{name} || getpwuid $>;
}
sub get_user_email {
my ($user) = @_;
return git 'config --get user.email' unless $user;
fetch_tags();
my $git_config = git_config();
my $user_info = view_blob("user/$user") || {};
lib/App/Gitc/Util.pm view on Meta::CPAN
sub history_status {
my $history = shift;
my $last
= first { $_->{action} !~ m/^(touch|promote|demote)$/ } reverse @$history;
my $action = $last->{action};
return {
open => 'open',
submit => 'submitted',
review => 'reviewing',
fail => 'failed',
pass => 'merged',
edit => 'open',
}->{$action};
}
sub history_submitter {
my ($history) = @_;
my $last = first { $_->{action} eq 'submit' } reverse @$history;
return if not $last;
return $last->{user};
}
sub is_auto_fetch {
my $config = git_config();
my $value = $config->{gitc}{fetch} || 'auto';
return $value eq 'auto';
}
sub is_merge_commit {
my ($ref) = @_;
my ($parents) = git "log -1 --no-color --pretty=format:%P $ref";
return if not $parents; # the root commit is not a merge
my @parents = split / /, $parents;
return @parents > 1;
}
sub is_suspendable {
our $suspend_file = '.git/gitc-suspended-process';
open my $fh, '>', $suspend_file
or die "Unable to create $suspend_file: $!\n";
print $fh "$$\n";
my $command = command_name();
print $fh "gitc $command is suspended. Resume it with 'fg'\n";
our $is_suspendable = 1;
close $fh;
}
END {
our $is_suspendable;
our $suspend_file;
unlink $suspend_file if $is_suspendable and -e $suspend_file;
}
sub is_valid_ref {
my ($name) = @_;
return if not defined $name;
my $sha1 = eval { git "rev-parse --verify --quiet $name" };
return $sha1 if $sha1;
return;
}
sub open_packed_refs {
my ($prefix) = @_;
require File::Temp;
if ( not defined $prefix ) {
require Carp;
Carp::croak("open_packed_refs requires a prefix argument");
}
my $git_dir = git_dir();
my $packed_refs = "$git_dir/packed-refs";
return if not -e $packed_refs;
open my $old_fh, '<', $packed_refs or die "Can't open $packed_refs: $!";
# verify that refs were packed with 'peeled'
my $header = <$old_fh>;
my ($technique) = $header =~ /^# pack-refs with: (\S+)/;
$technique ||= '';
die "Unknown ref packing technique: $technique\n"
if $technique ne 'peeled';
# open a temporary file to store the new tags
my ( $new_fh, $new_filename )
= File::Temp::tempfile( "$prefix-XXXX", DIR => $git_dir );
print $new_fh $header;
return ( $old_fh, $new_fh, $new_filename );
}
sub parse_changeset_spec {
my ($spec) = @_;
# no $spec means to infer everything from pwd
if ( not defined $spec ) {
my $changeset = current_branch();
my $project = project_name();
return ( $project, $changeset );
}
# handle the traditional, full changeset name
return ( $1, $2 ) if $spec =~ m/^(.*)#(.*)$/;
my $project = project_name();
die "Unable to determine the project for changeset spec '$spec'.\n"
. "You either need to be inside a gitc repository or specify\n"
. "the full changeset name like project#changeset\n"
if not $project;
return ( $project, $spec );
}
sub project_name {
our $project_name;
return $project_name if defined $project_name;
my ($line) = git "show HEAD:.gitc";
die "You need to specify a project name in a .gitc file. See the HOWTO for more details." unless $line;
my ($name) = $line =~ m/^\s*name\s*:\s*(.*)$/;
return $project_name = $name;
}
sub project_root {
my $git_dir = git_dir();
if ( not $git_dir =~ s{/.git$}{} ) {
require Carp;
Carp::croak("Bare repositories don't have a meaningful project root");
}
return $git_dir;
}
sub remote_branch_exists {
my ($branch) = @_;
my @remote_branches = git "branch --no-color -r";
( run in 3.422 seconds using v1.01-cache-2.11-cpan-437f7b0c052 )