Extract some utilities from git-svn to allow extracting Git::SVN.

Put them in a new module called Git::SVN::Utils.  Yeah, not terribly
original and it will be a dumping ground.  But its better than having
them in the main git-svn program.  At least they can be documented
and tested.

* fatal() is used by many classes.
* Change the $can_compress lexical into a function.

This should be enough to extract Git::SVN.

Signed-off-by: Michael G. Schwern <schwern@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Eric Wong <normalperson@yhbt.net>
This commit is contained in:
Michael G. Schwern 2012-07-26 16:22:22 -07:00 committed by Eric Wong
parent ee9be06770
commit c2768fa152
6 changed files with 132 additions and 15 deletions

View File

@ -10,6 +10,8 @@ use vars qw/ $AUTHOR $VERSION
$AUTHOR = 'Eric Wong <normalperson@yhbt.net>'; $AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
$VERSION = '@@GIT_VERSION@@'; $VERSION = '@@GIT_VERSION@@';
use Git::SVN::Utils qw(fatal can_compress);
# From which subdir have we been invoked? # From which subdir have we been invoked?
my $cmd_dir_prefix = eval { my $cmd_dir_prefix = eval {
command_oneline([qw/rev-parse --show-prefix/], STDERR => 0) command_oneline([qw/rev-parse --show-prefix/], STDERR => 0)
@ -35,8 +37,6 @@ $Git::SVN::Log::TZ = $ENV{TZ};
$ENV{TZ} = 'UTC'; $ENV{TZ} = 'UTC';
$| = 1; # unbuffer STDOUT $| = 1; # unbuffer STDOUT
sub fatal (@) { print STDERR "@_\n"; exit 1 }
# All SVN commands do it. Otherwise we may die on SIGPIPE when the remote # All SVN commands do it. Otherwise we may die on SIGPIPE when the remote
# repository decides to close the connection which we expect to be kept alive. # repository decides to close the connection which we expect to be kept alive.
$SIG{PIPE} = 'IGNORE'; $SIG{PIPE} = 'IGNORE';
@ -66,7 +66,7 @@ sub _req_svn {
fatal "Need SVN::Core 1.1.0 or better (got $SVN::Core::VERSION)"; fatal "Need SVN::Core 1.1.0 or better (got $SVN::Core::VERSION)";
} }
} }
my $can_compress = eval { require Compress::Zlib; 1};
use Carp qw/croak/; use Carp qw/croak/;
use Digest::MD5; use Digest::MD5;
use IO::File qw//; use IO::File qw//;
@ -1578,7 +1578,7 @@ sub cmd_reset {
} }
sub cmd_gc { sub cmd_gc {
if (!$can_compress) { if (!can_compress()) {
warn "Compress::Zlib could not be found; unhandled.log " . warn "Compress::Zlib could not be found; unhandled.log " .
"files will not be compressed.\n"; "files will not be compressed.\n";
} }
@ -2013,13 +2013,13 @@ sub md5sum {
} elsif (!$ref) { } elsif (!$ref) {
$md5->add($arg) or croak $!; $md5->add($arg) or croak $!;
} else { } else {
::fatal "Can't provide MD5 hash for unknown ref type: '", $ref, "'"; fatal "Can't provide MD5 hash for unknown ref type: '", $ref, "'";
} }
return $md5->hexdigest(); return $md5->hexdigest();
} }
sub gc_directory { sub gc_directory {
if ($can_compress && -f $_ && basename($_) eq "unhandled.log") { if (can_compress() && -f $_ && basename($_) eq "unhandled.log") {
my $out_filename = $_ . ".gz"; my $out_filename = $_ . ".gz";
open my $in_fh, "<", $_ or die "Unable to open $_: $!\n"; open my $in_fh, "<", $_ or die "Unable to open $_: $!\n";
binmode $in_fh; binmode $in_fh;
@ -2054,6 +2054,9 @@ use Time::Local;
use Memoize; # core since 5.8.0, Jul 2002 use Memoize; # core since 5.8.0, Jul 2002
use Memoize::Storable; use Memoize::Storable;
use POSIX qw(:signal_h); use POSIX qw(:signal_h);
use Git::SVN::Utils qw(fatal can_compress);
my $can_use_yaml; my $can_use_yaml;
BEGIN { BEGIN {
$can_use_yaml = eval { require Git::SVN::Memoize::YAML; 1}; $can_use_yaml = eval { require Git::SVN::Memoize::YAML; 1};
@ -2879,8 +2882,8 @@ sub assert_index_clean {
command_noisy('read-tree', $treeish); command_noisy('read-tree', $treeish);
$x = command_oneline('write-tree'); $x = command_oneline('write-tree');
if ($y ne $x) { if ($y ne $x) {
::fatal "trees ($treeish) $y != $x\n", fatal "trees ($treeish) $y != $x\n",
"Something is seriously wrong..."; "Something is seriously wrong...";
} }
}); });
} }
@ -3235,7 +3238,7 @@ sub mkemptydirs {
my %empty_dirs = (); my %empty_dirs = ();
my $gz_file = "$self->{dir}/unhandled.log.gz"; my $gz_file = "$self->{dir}/unhandled.log.gz";
if (-f $gz_file) { if (-f $gz_file) {
if (!$can_compress) { if (!can_compress()) {
warn "Compress::Zlib could not be found; ", warn "Compress::Zlib could not be found; ",
"empty directories in $gz_file will not be read\n"; "empty directories in $gz_file will not be read\n";
} else { } else {
@ -3918,7 +3921,7 @@ sub set_tree {
my ($self, $tree) = (shift, shift); my ($self, $tree) = (shift, shift);
my $log_entry = ::get_commit_entry($tree); my $log_entry = ::get_commit_entry($tree);
unless ($self->{last_rev}) { unless ($self->{last_rev}) {
::fatal("Must have an existing revision to commit"); fatal("Must have an existing revision to commit");
} }
my %ed_opts = ( r => $self->{last_rev}, my %ed_opts = ( r => $self->{last_rev},
log => $log_entry->{log}, log => $log_entry->{log},
@ -4347,6 +4350,7 @@ sub remove_username {
package Git::SVN::Log; package Git::SVN::Log;
use strict; use strict;
use warnings; use warnings;
use Git::SVN::Utils qw(fatal);
use POSIX qw/strftime/; use POSIX qw/strftime/;
use constant commit_log_separator => ('-' x 72) . "\n"; use constant commit_log_separator => ('-' x 72) . "\n";
use vars qw/$TZ $limit $color $pager $non_recursive $verbose $oneline use vars qw/$TZ $limit $color $pager $non_recursive $verbose $oneline
@ -4445,15 +4449,15 @@ sub config_pager {
sub run_pager { sub run_pager {
return unless defined $pager; return unless defined $pager;
pipe my ($rfd, $wfd) or return; pipe my ($rfd, $wfd) or return;
defined(my $pid = fork) or ::fatal "Can't fork: $!"; defined(my $pid = fork) or fatal "Can't fork: $!";
if (!$pid) { if (!$pid) {
open STDOUT, '>&', $wfd or open STDOUT, '>&', $wfd or
::fatal "Can't redirect to stdout: $!"; fatal "Can't redirect to stdout: $!";
return; return;
} }
open STDIN, '<&', $rfd or ::fatal "Can't redirect stdin: $!"; open STDIN, '<&', $rfd or fatal "Can't redirect stdin: $!";
$ENV{LESS} ||= 'FRSX'; $ENV{LESS} ||= 'FRSX';
exec $pager or ::fatal "Can't run pager: $! ($pager)"; exec $pager or fatal "Can't run pager: $! ($pager)";
} }
sub format_svn_date { sub format_svn_date {
@ -4602,7 +4606,7 @@ sub cmd_show_log {
} elsif ($::_revision =~ /^\d+$/) { } elsif ($::_revision =~ /^\d+$/) {
$r_min = $r_max = $::_revision; $r_min = $r_max = $::_revision;
} else { } else {
::fatal "-r$::_revision is not supported, use ", fatal "-r$::_revision is not supported, use ",
"standard 'git log' arguments instead"; "standard 'git log' arguments instead";
} }
} }

59
perl/Git/SVN/Utils.pm Normal file
View File

@ -0,0 +1,59 @@
package Git::SVN::Utils;
use strict;
use warnings;
use base qw(Exporter);
our @EXPORT_OK = qw(fatal can_compress);
=head1 NAME
Git::SVN::Utils - utility functions used across Git::SVN
=head1 SYNOPSIS
use Git::SVN::Utils qw(functions to import);
=head1 DESCRIPTION
This module contains functions which are useful across many different
parts of Git::SVN. Mostly it's a place to put utility functions
rather than duplicate the code or have classes grabbing at other
classes.
=head1 FUNCTIONS
All functions can be imported only on request.
=head3 fatal
fatal(@message);
Display a message and exit with a fatal error code.
=cut
# Note: not certain why this is in use instead of die. Probably because
# the exit code of die is 255? Doesn't appear to be used consistently.
sub fatal (@) { print STDERR "@_\n"; exit 1 }
=head3 can_compress
my $can_compress = can_compress;
Returns true if Compress::Zlib is available, false otherwise.
=cut
my $can_compress;
sub can_compress {
return $can_compress if defined $can_compress;
return $can_compress = eval { require Compress::Zlib; };
}
1;

View File

@ -34,6 +34,7 @@ modules += Git/SVN/Fetcher
modules += Git/SVN/Editor modules += Git/SVN/Editor
modules += Git/SVN/Prompt modules += Git/SVN/Prompt
modules += Git/SVN/Ra modules += Git/SVN/Ra
modules += Git/SVN/Utils
$(makfile): ../GIT-CFLAGS Makefile $(makfile): ../GIT-CFLAGS Makefile
echo all: private-Error.pm Git.pm Git/I18N.pm > $@ echo all: private-Error.pm Git.pm Git/I18N.pm > $@

8
t/Git-SVN/00compile.t Normal file
View File

@ -0,0 +1,8 @@
#!/usr/bin/env perl
use strict;
use warnings;
use Test::More tests => 1;
require_ok 'Git::SVN::Utils';

View File

@ -0,0 +1,11 @@
#!/usr/bin/perl
use strict;
use warnings;
use Test::More 'no_plan';
use Git::SVN::Utils qw(can_compress);
# !! is the "convert this to boolean" operator.
is !!can_compress(), !!eval { require Compress::Zlib };

34
t/Git-SVN/Utils/fatal.t Normal file
View File

@ -0,0 +1,34 @@
#!/usr/bin/perl
use strict;
use warnings;
use Test::More 'no_plan';
BEGIN {
# Override exit at BEGIN time before Git::SVN::Utils is loaded
# so it will see our local exit later.
*CORE::GLOBAL::exit = sub(;$) {
return @_ ? CORE::exit($_[0]) : CORE::exit();
};
}
use Git::SVN::Utils qw(fatal);
# fatal()
{
# Capture the exit code and prevent exit.
my $exit_status;
no warnings 'redefine';
local *CORE::GLOBAL::exit = sub { $exit_status = $_[0] || 0 };
# Trap fatal's message to STDERR
my $stderr;
close STDERR;
ok open STDERR, ">", \$stderr;
fatal "Some", "Stuff", "Happened";
is $stderr, "Some Stuff Happened\n";
is $exit_status, 1;
}