From: Junio C Hamano Date: Sun, 16 Oct 2005 18:55:35 +0000 (-0700) Subject: Merge branch 'svn' of http://netz.smurf.noris.de/git/git X-Git-Tag: v0.99.9~112 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=29504118f8528f658fd0bfc02d8d78d4c01dc2cc;p=git.git Merge branch 'svn' of netz.smurf.noris.de/git/git [jc: I have my pre-commit hook enabled to catch trailing whitespaces, and fixed them up while merging.] Signed-off-by: Junio C Hamano --- 29504118f8528f658fd0bfc02d8d78d4c01dc2cc diff --cc Documentation/git-svnimport.txt index 000000000,a27a83596..88bdc08eb mode 000000,100644..100644 --- a/Documentation/git-svnimport.txt +++ b/Documentation/git-svnimport.txt @@@ -1,0 -1,137 +1,137 @@@ + git-svnimport(1) + ================ + v0.1, July 2005 + + NAME + ---- + git-svnimport - Import a SVN repository into git + + + SYNOPSIS + -------- + 'git-svnimport' [ -o ] [ -h ] [ -v ] [ -d | -D ] + [ -C ] [ -i ] [ -u ] [-l limit_nr_changes] + [ -b branch_subdir ] [ -t trunk_subdir ] [ -T tag_subdir ] + [ -s start_chg ] [ -m ] [ -M regex ] + [ ] + + + DESCRIPTION + ----------- + Imports a SVN repository into git. It will either create a new + repository, or incrementally import into an existing one. + + SVN access is done by the SVN:: Perl module. + + git-svnimport assumes that SVN repositories are organized into one + "trunk" directory where the main development happens, "branch/FOO" + directories for branches, and "/tags/FOO" directories for tags. + Other subdirectories are ignored. + + git-svnimport creates a file ".git/svn2git", which is required for -incremental SVN imports. ++incremental SVN imports. + + OPTIONS + ------- + -C :: + The GIT repository to import to. If the directory doesn't + exist, it will be created. Default is the current directory. + + -s :: + Start importing at this SVN change number. The default is 1. + + + When importing incementally, you might need to edit the .git/svn2git file. + + -i:: + Import-only: don't perform a checkout after importing. This option + ensures the working directory and cache remain untouched and will + not create them if they do not exist. + + -t :: + Name the SVN trunk. Default "trunk". - ++ + -T :: + Name the SVN subdirectory for tags. Default "tags". - ++ + -b :: + Name the SVN subdirectory for branches. Default "branches". - ++ + -o :: + The 'trunk' branch from SVN is imported to the 'origin' branch within + the git repository. Use this option if you want to import into a + different branch. + --m:: ++-m:: + Attempt to detect merges based on the commit message. This option - will enable default regexes that try to capture the name source - branch name from the commit message. ++ will enable default regexes that try to capture the name source ++ branch name from the commit message. + + -M :: + Attempt to detect merges based on the commit message with a custom - regex. It can be used with -m to also see the default regexes. - You must escape forward slashes. ++ regex. It can be used with -m to also see the default regexes. ++ You must escape forward slashes. + + -l :: + Limit the number of SVN changesets we pull before quitting. + This option is necessary because the SVN library has serious memory + leaks; the recommended value for nontrivial imports is 100. + + git-svnimport will still exit with a zero exit code. You can check + the size of the file ".git/svn2git" to determine whether to call + the importer again. + + -v:: + Verbosity: let 'svnimport' report what it is doing. + + -d:: + Use direct HTTP requests if possible. The "" argument is used + only for retrieving the SVN logs; the path to the contents is + included in the SVN log. + + -D:: + Use direct HTTP requests if possible. The "" argument is used + for retrieving the logs, as well as for the contents. + + + There's no safe way to automatically find out which of these options to + use, so you need to try both. Usually, the one that's wrong will die + with a 40x error pretty quickly. + + :: + The URL of the SVN module you want to import. For local + repositories, use "file:///absolute/path". + + + If you're using the "-d" or "-D" option, this is the URL of the SVN + repository itself; it usually ends in "/svn". + + :: + The URL of the SVN module you want to import. For local + repositories, use "file:///absolute/path". + + + The path to the module you want to check out. + + -h:: + Print a short usage message and exit. + + OUTPUT + ------ + If '-v' is specified, the script reports what it is doing. + + Otherwise, success is indicated the Unix way, i.e. by simply exiting with + a zero exit status. + + Author + ------ + Written by Matthias Urlichs , with help from + various participants of the git-list . + + Based on a cvs2git script by the same author. + + Documentation + -------------- + Documentation by Matthias Urlichs . + + GIT + --- + Part of the gitlink:git[7] suite + diff --cc Makefile index 523985566,13b949b09..5ee72bc92 --- a/Makefile +++ b/Makefile @@@ -94,7 -92,7 +94,7 @@@ SCRIPT_SH = SCRIPT_PERL = \ git-archimport.perl git-cvsimport.perl git-relink.perl \ git-rename.perl git-shortlog.perl git-fmt-merge-msg.perl \ - git-findtags.perl - git-svnimport.perl ++ git-findtags.perl git-svnimport.perl SCRIPT_PYTHON = \ git-merge-recursive.py diff --cc git-cvsimport.perl index f7c3a5159,cc0eed294..0621dc3e2 --- a/git-cvsimport.perl +++ b/git-cvsimport.perl @@@ -587,10 -585,9 +588,9 @@@ my $commit = sub if ( -e "$git_dir/refs/heads/$mparent") { $mparent = get_headref($mparent, $git_dir); push @par, '-p', $mparent; - # printing here breaks import # - # # print "Merge parent branch: $mparent\n" if $opt_v; + print OUT "Merge parent branch: $mparent\n" if $opt_v; } - } - } ++ } } exec("env", diff --cc git-svnimport.perl index 000000000,45486a852..20a85724c mode 000000,100755..100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@@ -1,0 -1,717 +1,717 @@@ + #!/usr/bin/perl -w + + # This tool is copyright (c) 2005, Matthias Urlichs. + # It is released under the Gnu Public License, version 2. + # + # The basic idea is to pull and analyze SVN changes. + # + # Checking out the files is done by a single long-running SVN connection. + # + # The head revision is on branch "origin" by default. + # You can change that with the '-o' option. + + require v5.8.0; # for shell-safe open("-|",LIST) + use strict; + use warnings; + use Getopt::Std; + use File::Spec; + use File::Temp qw(tempfile); + use File::Path qw(mkpath); + use File::Basename qw(basename dirname); + use Time::Local; + use IO::Pipe; + use POSIX qw(strftime dup2); + use IPC::Open2; + use SVN::Core; + use SVN::Ra; + + die "Need CVN:Core 1.2.1 or better" if $SVN::Core::VERSION lt "1.2.1"; + + $SIG{'PIPE'}="IGNORE"; + $ENV{'TZ'}="UTC"; + + our($opt_h,$opt_o,$opt_v,$opt_u,$opt_C,$opt_i,$opt_m,$opt_M,$opt_t,$opt_T,$opt_b,$opt_s,$opt_l,$opt_d,$opt_D); + + sub usage() { + print STDERR <{'buffer'} = ""; + bless($self,$what); + + $repo =~ s#/+$##; + $self->{'fullrep'} = $repo; + $self->conn(); + + return $self; + } + + sub conn { + my $self = shift; + my $repo = $self->{'fullrep'}; + my $s = SVN::Ra->new($repo); + + die "SVN connection to $repo: $!\n" unless defined $s; + $self->{'svn'} = $s; + $self->{'repo'} = $repo; + $self->{'maxrev'} = $s->get_latest_revnum(); + } + + sub file { + my($self,$path,$rev) = @_; + - my ($fh, $name) = tempfile('gitsvn.XXXXXX', ++ my ($fh, $name) = tempfile('gitsvn.XXXXXX', + DIR => File::Spec->tmpdir(), UNLINK => 1); + + print "... $rev $path ...\n" if $opt_v; + eval { $self->{'svn'}->get_file($path,$rev,$fh); }; + if($@) { + return undef if $@ =~ /Attempted to get checksum/; + die $@; + } + close ($fh); + + return $name; + } + + package main; + use URI; + + my $svn = $svn_url; + $svn .= "/$svn_dir" if defined $svn_dir; + $svn = SVNconn->new($svn); + + my $lwp_ua; + if($opt_d or $opt_D) { + $svn_url = URI->new($svn_url)->canonical; + if($opt_D) { + $svn_dir =~ s#/*$#/#; + } else { + $svn_dir = ""; + } + if ($svn_url->scheme eq "http") { + use LWP::UserAgent; + $lwp_ua = LWP::UserAgent->new(keep_alive => 1, requests_redirectable => []); + } else { + print STDERR "Warning: not HTTP; turning off direct file access\n"; + $opt_d=0; + } + } + + sub pdate($) { + my($d) = @_; + $d =~ m#(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)# + or die "Unparseable date: $d\n"; + my $y=$1; $y-=1900 if $y>1900; + return timegm($6||0,$5,$4,$3,$2-1,$y); + } + + sub getwd() { + my $pwd = `pwd`; + chomp $pwd; + return $pwd; + } + + + sub get_headref($$) { + my $name = shift; - my $git_dir = shift; ++ my $git_dir = shift; + my $sha; - ++ + if (open(C,"$git_dir/refs/heads/$name")) { + chomp($sha = ); + close(C); + length($sha) == 40 + or die "Cannot get head id for $name ($sha): $!\n"; + } + return $sha; + } + + + -d $git_tree + or mkdir($git_tree,0777) + or die "Could not create $git_tree: $!"; + chdir($git_tree); + + my $orig_branch = ""; + my $forward_master = 0; + my %branches; + + my $git_dir = $ENV{"GIT_DIR"} || ".git"; + $git_dir = getwd()."/".$git_dir unless $git_dir =~ m#^/#; + $ENV{"GIT_DIR"} = $git_dir; + my $orig_git_index; + $orig_git_index = $ENV{GIT_INDEX_FILE} if exists $ENV{GIT_INDEX_FILE}; + my ($git_ih, $git_index) = tempfile('gitXXXXXX', SUFFIX => '.idx', + DIR => File::Spec->tmpdir()); + close ($git_ih); + $ENV{GIT_INDEX_FILE} = $git_index; + my $maxnum = 0; + my $last_rev = ""; + my $last_branch; + my $current_rev = $opt_s-1; + unless(-d $git_dir) { + system("git-init-db"); + die "Cannot init the GIT db at $git_tree: $?\n" if $?; + system("git-read-tree"); + die "Cannot init an empty tree: $?\n" if $?; + + $last_branch = $opt_o; + $orig_branch = ""; + } else { + -f "$git_dir/refs/heads/$opt_o" + or die "Branch '$opt_o' does not exist.\n". + "Either use the correct '-o branch' option,\n". + "or import to a new repository.\n"; + + -f "$git_dir/svn2git" + or die "'$git_dir/svn2git' does not exist.\n". + "You need that file for incremental imports.\n"; + $last_branch = basename(readlink("$git_dir/HEAD")); + unless($last_branch) { + warn "Cannot read the last branch name: $! -- assuming 'master'\n"; + $last_branch = "master"; + } + $orig_branch = $last_branch; + $last_rev = get_headref($orig_branch, $git_dir); + if (-f "$git_dir/SVN2GIT_HEAD") { + die <) { + chomp; + my($num,$branch,$ref) = split; + $branches{$branch}{$num} = $ref; + $branches{$branch}{"LAST"} = $ref; + $current_rev = $num if $current_rev < $num; + } + close($B); + } + -d $git_dir + or die "Could not create git subdir ($git_dir).\n"; + + open BRANCHES,">>", "$git_dir/svn2git"; + + sub get_file($$$) { + my($rev,$branch,$path) = @_; + + # revert split_path(), below + my $svnpath; + $path = "" if $path eq "/"; # this should not happen, but ... + if($branch eq "/") { + $svnpath = "$trunk_name/$path"; + } elsif($branch =~ m#^/#) { + $svnpath = "$tag_name$branch/$path"; + } else { + $svnpath = "$branch_name/$branch/$path"; + } + + # now get it + my $name; + if($opt_d) { + my($req,$res); + + # /svn/!svn/bc/2/django/trunk/django-docs/build.py + my $url=$svn_url->clone(); + $url->path($url->path."/!svn/bc/$rev/$svn_dir$svnpath"); + print "... $path...\n" if $opt_v; + $req = HTTP::Request->new(GET => $url); + $res = $lwp_ua->request($req); + if ($res->is_success) { + my $fh; - ($fh, $name) = tempfile('gitsvn.XXXXXX', - DIR => File::Spec->tmpdir(), UNLINK => 1); ++ ($fh, $name) = tempfile('gitsvn.XXXXXX', ++ DIR => File::Spec->tmpdir(), UNLINK => 1); + print $fh $res->content; + close($fh) or die "Could not write $name: $!\n"; + } else { + return undef if $res->code == 301; # directory? + die $res->status_line." at $url\n"; + } + } else { + $name = $svn->file("/$svnpath",$rev); + return undef unless defined $name; + } + + open my $F, '-|', "git-hash-object", "-w", $name + or die "Cannot create object: $!\n"; + my $sha = <$F>; + chomp $sha; + close $F; + unlink $name; + my $mode = "0644"; # SV does not seem to store any file modes + return [$mode, $sha, $path]; + } + + sub split_path($$) { + my($rev,$path) = @_; + my $branch; + + if($path =~ s#^/\Q$tag_name\E/([^/]+)/?##) { + $branch = "/$1"; + } elsif($path =~ s#^/\Q$trunk_name\E/?##) { + $branch = "/"; + } elsif($path =~ s#^/\Q$branch_name\E/([^/]+)/?##) { + $branch = $1; + } else { + print STDERR "$rev: Unrecognized path: $path\n"; + return () + } + $path = "/" if $path eq ""; + return ($branch,$path); + } + + sub copy_subdir($$$$$$) { + # Somebody copied a whole subdirectory. + # We need to find the index entries from the old version which the + # SVN log entry points to, and add them to the new place. + + my($newrev,$newbranch,$path,$oldpath,$rev,$new) = @_; + my($branch,$srcpath) = split_path($rev,$oldpath); + + my $gitrev = $branches{$branch}{$rev}; + unless($gitrev) { + print STDERR "$newrev:$newbranch: could not find $oldpath \@ $rev\n"; + return; + } + print "$newrev:$newbranch:$path: copying from $branch:$srcpath @ $rev\n" if $opt_v; + $srcpath =~ s#/*$#/#; + open my $f,"-|","git-ls-tree","-r","-z",$gitrev,$srcpath; + local $/ = "\0"; + while(<$f>) { + chomp; + my($m,$p) = split(/\t/,$_,2); + my($mode,$type,$sha1) = split(/ /,$m); + next if $type ne "blob"; + $p = substr($p,length($srcpath)-1); + print "... found $path$p ...\n" if $opt_v; + push(@$new,[$mode,$sha1,$path.$p]); + } - close($f) or ++ close($f) or + print STDERR "$newrev:$newbranch: could not list files in $oldpath \@ $rev\n"; + } + + sub commit { + my($branch, $changed_paths, $revision, $author, $date, $message) = @_; + my($author_name,$author_email,$dest); + my(@old,@new); + + if (not defined $author) { + $author_name = $author_email = "unknown"; + } elsif ($author =~ /^(.*?)\s+<(.*)>$/) { + ($author_name, $author_email) = ($1, $2); + } else { + $author =~ s/^<(.*)>$/$1/; + $author_name = $author_email = $author; + } + $date = pdate($date); + + my $tag; + my $parent; + if($branch eq "/") { # trunk + $parent = $opt_o; + } elsif($branch =~ m#^/(.+)#) { # tag + $tag = 1; + $parent = $1; + } else { # "normal" branch + # nothing to do + $parent = $branch; + } + $dest = $parent; + + my $prev = $changed_paths->{"/"}; + if($prev and $prev->[0] eq "A") { + delete $changed_paths->{"/"}; + my $oldpath = $prev->[1]; + my $rev; + if(defined $oldpath) { + my $p; + ($parent,$p) = split_path($revision,$oldpath); + if($parent eq "/") { + $parent = $opt_o; + } else { + $parent =~ s#^/##; # if it's a tag + } + } else { + $parent = undef; + } + } + + my $rev; + if($revision > $opt_s and defined $parent) { + open(H,"git-rev-parse --verify $parent |"); + $rev = ; + close(H) or do { + print STDERR "$revision: cannot find commit '$parent'!\n"; + return; + }; + chop $rev; + if(length($rev) != 40) { + print STDERR "$revision: cannot find commit '$parent'!\n"; + return; + } + $rev = $branches{($parent eq $opt_o) ? "/" : $parent}{"LAST"}; + if($revision != $opt_s and not $rev) { + print STDERR "$revision: do not know ancestor for '$parent'!\n"; + return; + } + } else { + $rev = undef; + } + + # if($prev and $prev->[0] eq "A") { + # if(not $tag) { + # unless(open(H,"> $git_dir/refs/heads/$branch")) { + # print STDERR "$revision: Could not create branch $branch: $!\n"; + # $state=11; + # next; + # } + # print H "$rev\n" + # or die "Could not write branch $branch: $!"; + # close(H) + # or die "Could not write branch $branch: $!"; + # } + # } + if(not defined $rev) { + unlink($git_index); + } elsif ($rev ne $last_rev) { + print "Switching from $last_rev to $rev ($branch)\n" if $opt_v; + system("git-read-tree", $rev); + die "read-tree failed for $rev: $?\n" if $?; + $last_rev = $rev; + } + + my $cid; + if($tag and not %$changed_paths) { + $cid = $rev; + } else { + my @paths = sort keys %$changed_paths; + foreach my $path(@paths) { + my $action = $changed_paths->{$path}; + + if ($action->[0] eq "A") { + my $f = get_file($revision,$branch,$path); + if($f) { + push(@new,$f) if $f; + } elsif($action->[1]) { + copy_subdir($revision,$branch,$path,$action->[1],$action->[2],\@new); + } else { + my $opath = $action->[3]; + print STDERR "$revision: $branch: could not fetch '$opath'\n"; + } + } elsif ($action->[0] eq "D") { + push(@old,$path); + } elsif ($action->[0] eq "M") { + my $f = get_file($revision,$branch,$path); + push(@new,$f) if $f; + } elsif ($action->[0] eq "R") { + # refer to a file/tree in an earlier commit + push(@old,$path); # remove any old stuff + + # ... and add any new stuff + my($b,$srcpath) = split_path($revision,$action->[1]); + $srcpath =~ s#/*$#/#; + open my $F,"-|","git-ls-tree","-r","-z", $branches{$b}{$action->[2]}, $srcpath; + local $/ = "\0"; + while(<$F>) { + chomp; + my($m,$p) = split(/\t/,$_,2); + my($mode,$type,$sha1) = split(/ /,$m); + next if $type ne "blob"; + $p = substr($p,length($srcpath)-1); + push(@new,[$mode,$sha1,$path.$p]); + } + close($F); + } else { + die "$revision: unknown action '".$action->[0]."' for $path\n"; + } + } + + if(@old) { + open my $F, "-|", "git-ls-files", "-z", @old or die $!; + @old = (); + local $/ = "\0"; + while(<$F>) { + chomp; + push(@old,$_); + } + close($F); + + while(@old) { + my @o2; + if(@old > 55) { + @o2 = splice(@old,0,50); + } else { + @o2 = @old; + @old = (); + } + system("git-update-index","--force-remove","--",@o2); + die "Cannot remove files: $?\n" if $?; + } + } + while(@new) { + my @n2; + if(@new > 12) { + @n2 = splice(@new,0,10); + } else { + @n2 = @new; + @new = (); + } + system("git-update-index","--add", + (map { ('--cacheinfo', @$_) } @n2)); + die "Cannot add files: $?\n" if $?; + } + + my $pid = open(C,"-|"); + die "Cannot fork: $!" unless defined $pid; + unless($pid) { + exec("git-write-tree"); + die "Cannot exec git-write-tree: $!\n"; + } + chomp(my $tree = ); + length($tree) == 40 + or die "Cannot get tree id ($tree): $!\n"; + close(C) + or die "Error running git-write-tree: $?\n"; + print "Tree ID $tree\n" if $opt_v; + + my $pr = IO::Pipe->new() or die "Cannot open pipe: $!\n"; + my $pw = IO::Pipe->new() or die "Cannot open pipe: $!\n"; + $pid = fork(); + die "Fork: $!\n" unless defined $pid; + unless($pid) { + $pr->writer(); + $pw->reader(); + open(OUT,">&STDOUT"); + dup2($pw->fileno(),0); + dup2($pr->fileno(),1); + $pr->close(); + $pw->close(); + + my @par = (); + @par = ("-p",$rev) if defined $rev; + + # loose detection of merges + # based on the commit msg + foreach my $rx (@mergerx) { + if ($message =~ $rx) { + my $mparent = $1; + if ($mparent eq 'HEAD') { $mparent = $opt_o }; + if ( -e "$git_dir/refs/heads/$mparent") { + $mparent = get_headref($mparent, $git_dir); + push @par, '-p', $mparent; + print OUT "Merge parent branch: $mparent\n" if $opt_v; + } - } ++ } + } + + exec("env", + "GIT_AUTHOR_NAME=$author_name", + "GIT_AUTHOR_EMAIL=$author_email", + "GIT_AUTHOR_DATE=".strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date)), + "GIT_COMMITTER_NAME=$author_name", + "GIT_COMMITTER_EMAIL=$author_email", + "GIT_COMMITTER_DATE=".strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date)), + "git-commit-tree", $tree,@par); + die "Cannot exec git-commit-tree: $!\n"; + } + $pw->writer(); + $pr->reader(); + + $message =~ s/[\s\n]+\z//; + + print $pw "$message\n" + or die "Error writing to git-commit-tree: $!\n"; + $pw->close(); + + print "Committed change $revision:$branch ".strftime("%Y-%m-%d %H:%M:%S",gmtime($date)).")\n" if $opt_v; + chomp($cid = <$pr>); + length($cid) == 40 + or die "Cannot get commit id ($cid): $!\n"; + print "Commit ID $cid\n" if $opt_v; + $pr->close(); + + waitpid($pid,0); + die "Error running git-commit-tree: $?\n" if $?; + } + + if(not defined $dest) { + print "... no known parent\n" if $opt_v; + } elsif(not $tag) { + print "Writing to refs/heads/$dest\n" if $opt_v; - open(C,">$git_dir/refs/heads/$dest") and ++ open(C,">$git_dir/refs/heads/$dest") and + print C ("$cid\n") and + close(C) + or die "Cannot write branch $dest for update: $!\n"; + } + + if($tag) { + my($in, $out) = ('',''); + $last_rev = "-" if %$changed_paths; + # the tag was 'complex', i.e. did not refer to a "real" revision - ++ + $dest =~ tr/_/\./ if $opt_u; + + my $pid = open2($in, $out, 'git-mktag'); + print $out ("object $cid\n". + "type commit\n". + "tag $dest\n". + "tagger $author_name <$author_email>\n") and + close($out) + or die "Cannot create tag object $dest: $!\n"; + + my $tagobj = <$in>; + chomp $tagobj; + + if ( !close($in) or waitpid($pid, 0) != $pid or + $? != 0 or $tagobj !~ /^[0123456789abcdef]{40}$/ ) { + die "Cannot create tag object $dest: $!\n"; + } + + open(C,">$git_dir/refs/tags/$dest") and + print C ("$tagobj\n") and + close(C) + or die "Cannot create tag $branch: $!\n"; + + print "Created tag '$dest' on '$branch'\n" if $opt_v; + } + $branches{$branch}{"LAST"} = $cid; + $branches{$branch}{$revision} = $cid; + $last_rev = $cid; + print BRANCHES "$revision $branch $cid\n"; + print "DONE: $revision $dest $cid\n" if $opt_v; + } + + my ($changed_paths, $revision, $author, $date, $message, $pool) = @_; + sub _commit_all { + ($changed_paths, $revision, $author, $date, $message, $pool) = @_; + my %p; + while(my($path,$action) = each %$changed_paths) { + $p{$path} = [ $action->action,$action->copyfrom_path, $action->copyfrom_rev, $path ]; + } + $changed_paths = \%p; + } + + sub commit_all { + my %done; + my @col; + my $pref; + my $branch; + + while(my($path,$action) = each %$changed_paths) { + ($branch,$path) = split_path($revision,$path); + next if not defined $branch; + $done{$branch}{$path} = $action; + } + while(($branch,$changed_paths) = each %done) { + commit($branch, $changed_paths, $revision, $author, $date, $message); + } + } + + while(++$current_rev <= $svn->{'maxrev'}) { + $svn->{'svn'}->get_log("/",$current_rev,$current_rev,$current_rev,1,1,\&_commit_all,""); + commit_all(); + if($opt_l and not --$opt_l) { + print STDERR "Stopping, because there is a memory leak (in the SVN library).\n"; + print STDERR "Please repeat this command; it will continue safely\n"; + last; + } + } + + + unlink($git_index); + + if (defined $orig_git_index) { + $ENV{GIT_INDEX_FILE} = $orig_git_index; + } else { + delete $ENV{GIT_INDEX_FILE}; + } + + # Now switch back to the branch we were in before all of this happened + if($orig_branch) { + print "DONE\n" if $opt_v and (not defined $opt_l or $opt_l > 0); + system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master") + if $forward_master; + unless ($opt_i) { + system('git-read-tree', '-m', '-u', 'SVN2GIT_HEAD', 'HEAD'); + die "read-tree failed: $?\n" if $?; + } + } else { + $orig_branch = "master"; + print "DONE; creating $orig_branch branch\n" if $opt_v and (not defined $opt_l or $opt_l > 0); + system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master") + unless -f "$git_dir/refs/heads/master"; + unlink("$git_dir/HEAD"); + symlink("refs/heads/$orig_branch","$git_dir/HEAD"); + unless ($opt_i) { + system('git checkout'); + die "checkout failed: $?\n" if $?; + } + } + unlink("$git_dir/SVN2GIT_HEAD"); + close(BRANCHES);