use warnings;
use strict;
use vars qw/ $AUTHOR $VERSION
- $sha1 $sha1_short $_revision
+ $sha1 $sha1_short $_revision $_repository
$_q $_authors %users/;
$AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
$VERSION = '@@GIT_VERSION@@';
}
$ENV{GIT_DIR} = $git_dir;
}
+ $_repository = Git->repository(Repository => $ENV{GIT_DIR});
}
my %opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
}
}
command_noisy(@init_db);
+ $_repository = Git->repository(Repository => ".git");
}
my $set;
my $pfx = "svn-remote.$Git::SVN::default_repo_id";
mkpath([$repo_path]) unless -d $repo_path;
chdir $repo_path or die "Couldn't chdir to $repo_path: $!\n";
$ENV{GIT_DIR} = '.git';
+ $_repository = Git->repository(Repository => $ENV{GIT_DIR});
}
sub cmd_clone {
$head ||= 'HEAD';
my @refs;
my ($url, $rev, $uuid, $gs) = working_head_info($head, \@refs);
- print "Committing to $url ...\n";
+ if ($url) {
+ print "Committing to $url ...\n";
+ }
unless ($gs) {
die "Unable to determine upstream SVN information from ",
- "$head history\n";
+ "$head history.\nPerhaps the repository is empty.";
}
my $last_rev;
my ($linear_refs, $parents) = linearize_history($gs, \@refs);
}
sub cmd_find_rev {
- my $revision_or_hash = shift;
+ my $revision_or_hash = shift or die "SVN or git revision required ",
+ "as a command-line argument\n";
my $result;
if ($revision_or_hash =~ /^r\d+$/) {
my $head = shift;
"wanted to set to: $gs->{url}\n";
}
command_oneline('config', $k, $gs->{url}) unless $orig_url;
- my $remote_path = "$ra->{svn_path}/$repo_path/*";
+ my $remote_path = "$ra->{svn_path}/$repo_path";
$remote_path =~ s#/+#/#g;
$remote_path =~ s#^/##g;
+ $remote_path .= "/*" if $remote_path !~ /\*/;
my ($n) = ($switch =~ /^--(\w+)/);
if (length $pfx && $pfx !~ m#/$#) {
die "--prefix='$pfx' must have a trailing slash '/'\n";
sub working_head_info {
my ($head, $refs) = @_;
- my @args = ('log', '--no-color', '--first-parent');
+ my @args = ('log', '--no-color', '--first-parent', '--pretty=medium');
my ($fh, $ctx) = command_output_pipe(@args, $head);
my $hash;
my %max;
$remotes->{$repo_id}->{$_});
}
my $p = $path;
+ my $rwr = rewrite_root({repo_id => $repo_id});
unless (defined $p) {
$p = $full_url;
- $p =~ s#^\Q$u\E(?:/|$)## or next;
+ my $z = $u;
+ if ($rwr) {
+ $z = $rwr;
+ }
+ $p =~ s#^\Q$z\E(?:/|$)## or next;
}
foreach my $f (keys %$fetch) {
next if $f ne $p;
foreach (sort keys %$dirent) {
next if $dirent->{$_}->{kind} != $SVN::Node::dir;
- $self->prop_walk($path . '/' . $_, $rev, $sub);
+ $self->prop_walk($p . $_, $rev, $sub);
}
}
# just grow a tail if we're not unique enough :x
$ref_id .= '-' while find_ref($ref_id);
print STDERR "Initializing parent: $ref_id\n";
- my ($u, $p) = ($new_url, '');
+ my ($u, $p, $repo_id) = ($new_url, '', $ref_id);
if ($u =~ s#^\Q$url\E(/|$)##) {
$p = $u;
$u = $url;
+ $repo_id = $self->{repo_id};
}
- $gs = Git::SVN->init($u, $p, $self->{repo_id}, $ref_id, 1);
+ $gs = Git::SVN->init($u, $p, $repo_id, $ref_id, 1);
}
my ($r0, $parent) = $gs->find_rev_before($r, 1);
if (!defined $r0 || !defined $parent) {
my ($author) = @_;
if (!defined $author || length $author == 0) {
$author = '(no author)';
- }
- if (defined $::_authors && ! defined $::users{$author}) {
+ } elsif (defined $::_authors && ! defined $::users{$author}) {
die "Author: $author not defined in $::_authors file\n";
}
$author;
$name_field = $1;
}
if (!defined $name_field) {
- #
+ if (!defined $email) {
+ $email = $name;
+ }
} elsif ($name_field =~ /(.*?)\s+<(.*)>/) {
($name, $email) = ($1, $2);
} elsif ($name_field =~ /(.*)@/) {
($name, $email) = ($1, $name_field);
} else {
- ($name, $email) = ($name_field, 'unknown');
+ ($name, $email) = ($name_field, $name_field);
}
}
if (defined $headrev && $self->use_svm_props) {
my ($self, $path) = @_;
my $r = -1;
open my $fh, '<', $path or croak "open: $!";
+ binmode $fh or croak "binmode: $!";
while (<$fh>) {
length($_) == 41 or croak "inconsistent size in ($_) != 41";
chomp($_);
sub _rev_map_set {
my ($fh, $rev, $commit) = @_;
+ binmode $fh or croak "binmode: $!";
my $size = (stat($fh))[7];
($size % 24) == 0 or croak "inconsistent size: $size";
my $map_path = $self->map_path;
stat $map_path or return $want_commit ? (0, undef) : 0;
sysopen(my $fh, $map_path, O_RDONLY) or croak "open: $!";
+ binmode $fh or croak "binmode: $!";
my $size = (stat($fh))[7];
($size % 24) == 0 or croak "inconsistent size: $size";
return undef unless -e $map_path;
sysopen(my $fh, $map_path, O_RDONLY) or croak "open: $!";
+ binmode $fh or croak "binmode: $!";
my $size = (stat($fh))[7];
($size % 24) == 0 or croak "inconsistent size: $size";
use strict;
use warnings;
use Carp qw/croak/;
+use File::Temp qw/tempfile/;
use IO::File qw//;
# file baton members: path, mode_a, mode_b, pool, fh, blob, base
my $base = IO::File->new_tmpfile;
$base->autoflush(1);
if ($fb->{blob}) {
- defined (my $pid = fork) or croak $!;
- if (!$pid) {
- open STDOUT, '>&', $base or croak $!;
- print STDOUT 'link ' if ($fb->{mode_a} == 120000);
- exec qw/git-cat-file blob/, $fb->{blob} or croak $!;
- }
- waitpid $pid, 0;
- croak $? if $?;
+ print $base 'link ' if ($fb->{mode_a} == 120000);
+ my $size = $::_repository->cat_blob($fb->{blob}, $base);
+ die "Failed to read object $fb->{blob}" unless $size;
if (defined $exp) {
seek $base, 0, 0 or croak $!;
sysseek($fh, 0, 0) or croak $!;
}
}
- defined(my $pid = open my $out,'-|') or die "Can't fork: $!\n";
- if (!$pid) {
- open STDIN, '<&', $fh or croak $!;
- exec qw/git-hash-object -w --stdin/ or croak $!;
+
+ my ($tmp_fh, $tmp_filename) = File::Temp::tempfile(UNLINK => 1);
+ my $result;
+ while ($result = sysread($fh, my $string, 1024)) {
+ syswrite($tmp_fh, $string, $result);
}
- chomp($hash = do { local $/; <$out> });
- close $out or croak $!;
+ defined $result or croak $!;
+ close $tmp_fh or croak $!;
+
close $fh or croak $!;
+
+ $hash = $::_repository->hash_and_insert_object($tmp_filename);
$hash =~ /^[a-f\d]{40}$/ or die "not a sha1: $hash\n";
close $fb->{base} or croak $!;
} else {
} elsif ($m->{mode_a} =~ /^120/ && $m->{mode_b} !~ /^120/) {
$self->change_file_prop($fbat,'svn:special',undef);
}
- defined(my $pid = fork) or croak $!;
- if (!$pid) {
- open STDOUT, '>&', $fh or croak $!;
- exec qw/git-cat-file blob/, $m->{sha1_b} or croak $!;
- }
- waitpid $pid, 0;
- croak $? if $?;
+ my $size = $::_repository->cat_blob($m->{sha1_b}, $fh);
+ croak "Failed to read object $m->{sha1_b}" unless $size;
$fh->flush == 0 or croak $!;
seek $fh, 0, 0 or croak $!;
my ($uri) = @_;
my @tmp;
foreach (split m{/}, $uri) {
- s/([^\w.-])/sprintf("%%%02X",ord($1))/eg;
+ s/([^\w.%-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
push @tmp, $_;
}
join('/', @tmp);