]> git.ipfire.org Git - thirdparty/git.git/blame - git-cvsimport.perl
Update mailmap for a handful of folks
[thirdparty/git.git] / git-cvsimport.perl
CommitLineData
3328aced 1#!/usr/bin/perl
9718a00b 2
a57a9493
MU
3# This tool is copyright (c) 2005, Matthias Urlichs.
4# It is released under the Gnu Public License, version 2.
5#
6# The basic idea is to aggregate CVS check-ins into related changes.
7# Fortunately, "cvsps" does that for us; all we have to do is to parse
8# its output.
9#
10# Checking out the files is done by a single long-running CVS connection
11# / server process.
12#
13# The head revision is on branch "origin" by default.
14# You can change that with the '-o' option.
15
d48b2841 16use 5.008;
a57a9493
MU
17use strict;
18use warnings;
bc434e82 19use Getopt::Long;
79ee456c 20use File::Spec;
7ccd9009 21use File::Temp qw(tempfile tmpnam);
a57a9493
MU
22use File::Path qw(mkpath);
23use File::Basename qw(basename dirname);
24use Time::Local;
2a3e1a85
MU
25use IO::Socket;
26use IO::Pipe;
e49289df 27use POSIX qw(strftime dup2 ENOENT);
0d821d4d 28use IPC::Open2;
a57a9493
MU
29
30$SIG{'PIPE'}="IGNORE";
31$ENV{'TZ'}="UTC";
32
0455ec03 33our ($opt_h,$opt_o,$opt_v,$opt_k,$opt_u,$opt_d,$opt_p,$opt_C,$opt_z,$opt_i,$opt_P, $opt_s,$opt_m,@opt_M,$opt_A,$opt_S,$opt_L, $opt_a, $opt_r, $opt_R);
ffd97f3a 34my (%conv_author_name, %conv_author_email);
a57a9493 35
7bf77644
FL
36sub usage(;$) {
37 my $msg = shift;
38 print(STDERR "Error: $msg\n") if $msg;
a57a9493 39 print STDERR <<END;
1b1dd23f 40Usage: git cvsimport # fetch/update GIT from CVS
ffd97f3a 41 [-o branch-for-HEAD] [-h] [-v] [-d CVSROOT] [-A author-conv-file]
edbe4466
FL
42 [-p opts-for-cvsps] [-P file] [-C GIT_repository] [-z fuzz] [-i] [-k]
43 [-u] [-s subst] [-a] [-m] [-M regex] [-S regex] [-L commitlimit]
0455ec03 44 [-r remote] [-R] [CVS_module]
a57a9493
MU
45END
46 exit(1);
47}
48
ffd97f3a
AE
49sub read_author_info($) {
50 my ($file) = @_;
51 my $user;
52 open my $f, '<', "$file" or die("Failed to open $file: $!\n");
53
54 while (<$f>) {
8cd16211 55 # Expected format is this:
ffd97f3a 56 # exon=Andreas Ericsson <ae@op5.se>
8cd16211 57 if (m/^(\S+?)\s*=\s*(.+?)\s*<(.+)>\s*$/) {
ffd97f3a 58 $user = $1;
8cd16211
JH
59 $conv_author_name{$user} = $2;
60 $conv_author_email{$user} = $3;
ffd97f3a 61 }
8cd16211
JH
62 # However, we also read from CVSROOT/users format
63 # to ease migration.
64 elsif (/^(\w+):(['"]?)(.+?)\2\s*$/) {
65 my $mapped;
66 ($user, $mapped) = ($1, $3);
67 if ($mapped =~ /^\s*(.*?)\s*<(.*)>\s*$/) {
68 $conv_author_name{$user} = $1;
69 $conv_author_email{$user} = $2;
70 }
71 elsif ($mapped =~ /^<?(.*)>?$/) {
72 $conv_author_name{$user} = $user;
73 $conv_author_email{$user} = $1;
74 }
75 }
76 # NEEDSWORK: Maybe warn on unrecognized lines?
ffd97f3a
AE
77 }
78 close ($f);
79}
80
81sub write_author_info($) {
82 my ($file) = @_;
83 open my $f, '>', $file or
84 die("Failed to open $file for writing: $!");
85
86 foreach (keys %conv_author_name) {
8cd16211 87 print $f "$_=$conv_author_name{$_} <$conv_author_email{$_}>\n";
ffd97f3a
AE
88 }
89 close ($f);
90}
91
cfc44a12 92# convert getopts specs for use by git config
60d5985d
MG
93my %longmap = (
94 'A:' => 'authors-file',
95 'M:' => 'merge-regex',
96 'P:' => undef,
97 'R' => 'track-revisions',
98 'S:' => 'ignore-paths',
99);
100
ed35dece 101sub read_repo_config {
549ad6d2
MG
102 # Split the string between characters, unless there is a ':'
103 # So "abc:de" becomes ["a", "b", "c:", "d", "e"]
ed35dece
JB
104 my @opts = split(/ *(?!:)/, shift);
105 foreach my $o (@opts) {
106 my $key = $o;
107 $key =~ s/://g;
cfc44a12 108 my $arg = 'git config';
ed35dece 109 $arg .= ' --bool' if ($o !~ /:$/);
60d5985d 110 my $ckey = $key;
ed35dece 111
60d5985d
MG
112 if (exists $longmap{$o}) {
113 # An uppercase option like -R cannot be
114 # expressed in the configuration, as the
115 # variable names are downcased.
116 $ckey = $longmap{$o};
117 next if (! defined $ckey);
118 $ckey =~ s/-//g;
119 }
120 chomp(my $tmp = `$arg --get cvsimport.$ckey`);
ed35dece 121 if ($tmp && !($arg =~ /--bool/ && $tmp eq 'false')) {
549ad6d2
MG
122 no strict 'refs';
123 my $opt_name = "opt_" . $key;
124 if (!$$opt_name) {
125 $$opt_name = $tmp;
126 }
ed35dece
JB
127 }
128 }
ed35dece
JB
129}
130
0455ec03 131my $opts = "haivmkuo:d:p:r:C:z:s:M:P:A:S:L:R";
ed35dece 132read_repo_config($opts);
bc434e82
PB
133Getopt::Long::Configure( 'no_ignore_case', 'bundling' );
134
135# turn the Getopt::Std specification in a Getopt::Long one,
136# with support for multiple -M options
137GetOptions( map { s/:/=s/; /M/ ? "$_\@" : $_ } split( /(?!:)/, $opts ) )
138 or usage();
a57a9493
MU
139usage if $opt_h;
140
67d23242 141if (@ARGV == 0) {
cfc44a12 142 chomp(my $module = `git config --get cvsimport.module`);
67d23242
JK
143 push(@ARGV, $module) if $? == 0;
144}
7bf77644 145@ARGV <= 1 or usage("You can't specify more than one CVS module");
a57a9493 146
86d11cf2 147if ($opt_d) {
2a3e1a85 148 $ENV{"CVSROOT"} = $opt_d;
86d11cf2 149} elsif (-f 'CVS/Root') {
f9714a4a
SV
150 open my $f, '<', 'CVS/Root' or die 'Failed to open CVS/Root';
151 $opt_d = <$f>;
152 chomp $opt_d;
153 close $f;
154 $ENV{"CVSROOT"} = $opt_d;
86d11cf2 155} elsif ($ENV{"CVSROOT"}) {
2a3e1a85
MU
156 $opt_d = $ENV{"CVSROOT"};
157} else {
7bf77644 158 usage("CVSROOT needs to be set");
2a3e1a85 159}
fbfd60d6 160$opt_s ||= "-";
ded9f400
ML
161$opt_a ||= 0;
162
f9714a4a 163my $git_tree = $opt_C;
2a3e1a85
MU
164$git_tree ||= ".";
165
8b7f5fc1
AW
166my $remote;
167if (defined $opt_r) {
168 $remote = 'refs/remotes/' . $opt_r;
169 $opt_o ||= "master";
170} else {
171 $opt_o ||= "origin";
172 $remote = 'refs/heads';
173}
174
f9714a4a
SV
175my $cvs_tree;
176if ($#ARGV == 0) {
177 $cvs_tree = $ARGV[0];
178} elsif (-f 'CVS/Repository') {
a6080a0a 179 open my $f, '<', 'CVS/Repository' or
f9714a4a
SV
180 die 'Failed to open CVS/Repository';
181 $cvs_tree = <$f>;
182 chomp $cvs_tree;
db4b6582 183 close $f;
f9714a4a 184} else {
7bf77644 185 usage("CVS module has to be specified");
f9714a4a
SV
186}
187
db4b6582
ML
188our @mergerx = ();
189if ($opt_m) {
fbbbc362 190 @mergerx = ( qr/\b(?:from|of|merge|merging|merged) ([-\w]+)/i );
db4b6582 191}
bc434e82
PB
192if (@opt_M) {
193 push (@mergerx, map { qr/$_/ } @opt_M);
db4b6582
ML
194}
195
6211988f
ML
196# Remember UTC of our starting time
197# we'll want to avoid importing commits
198# that are too recent
199our $starttime = time();
200
a57a9493
MU
201select(STDERR); $|=1; select(STDOUT);
202
203
204package CVSconn;
205# Basic CVS dialog.
2a3e1a85 206# We're only interested in connecting and downloading, so ...
a57a9493 207
2eb6d82e
SV
208use File::Spec;
209use File::Temp qw(tempfile);
f65ae603
MU
210use POSIX qw(strftime dup2);
211
a57a9493 212sub new {
86d11cf2 213 my ($what,$repo,$subdir) = @_;
a57a9493
MU
214 $what=ref($what) if ref($what);
215
216 my $self = {};
217 $self->{'buffer'} = "";
218 bless($self,$what);
219
220 $repo =~ s#/+$##;
221 $self->{'fullrep'} = $repo;
222 $self->conn();
223
224 $self->{'subdir'} = $subdir;
225 $self->{'lines'} = undef;
226
227 return $self;
228}
229
58fdef0c
GR
230sub find_password_entry {
231 my ($cvspass, @cvsroot) = @_;
232 my ($file, $delim) = @$cvspass;
233 my $pass;
234 local ($_);
235
236 if (open(my $fh, $file)) {
237 # :pserver:cvs@mea.tmt.tele.fi:/cvsroot/zmailer Ah<Z
238 CVSPASSFILE:
239 while (<$fh>) {
240 chomp;
241 s/^\/\d+\s+//;
242 my ($w, $p) = split($delim,$_,2);
243 for my $cvsroot (@cvsroot) {
244 if ($w eq $cvsroot) {
245 $pass = $p;
246 last CVSPASSFILE;
247 }
248 }
249 }
250 close($fh);
251 }
252 return $pass;
253}
254
a57a9493
MU
255sub conn {
256 my $self = shift;
257 my $repo = $self->{'fullrep'};
86d11cf2
JH
258 if ($repo =~ s/^:pserver(?:([^:]*)):(?:(.*?)(?::(.*?))?@)?([^:\/]*)(?::(\d*))?//) {
259 my ($param,$user,$pass,$serv,$port) = ($1,$2,$3,$4,$5);
73bcf533 260
86d11cf2
JH
261 my ($proxyhost,$proxyport);
262 if ($param && ($param =~ m/proxy=([^;]+)/)) {
73bcf533
IA
263 $proxyhost = $1;
264 # Default proxyport, if not specified, is 8080.
265 $proxyport = 8080;
86d11cf2 266 if ($ENV{"CVS_PROXY_PORT"}) {
73bcf533
IA
267 $proxyport = $ENV{"CVS_PROXY_PORT"};
268 }
86d11cf2 269 if ($param =~ m/proxyport=([^;]+)/) {
73bcf533
IA
270 $proxyport = $1;
271 }
272 }
8c372fb0 273 $repo ||= '/';
73bcf533 274
2e458e05
GH
275 # if username is not explicit in CVSROOT, then use current user, as cvs would
276 $user=(getlogin() || $ENV{'LOGNAME'} || $ENV{'USER'} || "anonymous") unless $user;
2a3e1a85 277 my $rr2 = "-";
86d11cf2 278 unless ($port) {
a57a9493
MU
279 $rr2 = ":pserver:$user\@$serv:$repo";
280 $port=2401;
281 }
282 my $rr = ":pserver:$user\@$serv:$port$repo";
283
3fb9d582
PO
284 if ($pass) {
285 $pass = $self->_scramble($pass);
286 } else {
58fdef0c
GR
287 my @cvspass = ([$ENV{'HOME'}."/.cvspass", qr/\s/],
288 [$ENV{'HOME'}."/.cvs/cvspass", qr/=/]);
289 my @loc = ();
290 foreach my $cvspass (@cvspass) {
291 my $p = find_password_entry($cvspass, $rr, $rr2);
292 if ($p) {
293 push @loc, $cvspass->[0];
294 $pass = $p;
a57a9493 295 }
58fdef0c
GR
296 }
297
298 if (1 < @loc) {
299 die("Multiple cvs password files have ".
300 "entries for CVSROOT $opt_d: @loc");
301 } elsif (!$pass) {
302 $pass = "A";
303 }
a57a9493 304 }
b2139dbd 305
73bcf533 306 my ($s, $rep);
86d11cf2 307 if ($proxyhost) {
73bcf533
IA
308
309 # Use a HTTP Proxy. Only works for HTTP proxies that
310 # don't require user authentication
311 #
312 # See: http://www.ietf.org/rfc/rfc2817.txt
313
314 $s = IO::Socket::INET->new(PeerHost => $proxyhost, PeerPort => $proxyport);
315 die "Socket to $proxyhost: $!\n" unless defined $s;
316 $s->write("CONNECT $serv:$port HTTP/1.1\r\nHost: $serv:$port\r\n\r\n")
317 or die "Write to $proxyhost: $!\n";
318 $s->flush();
319
320 $rep = <$s>;
321
322 # The answer should look like 'HTTP/1.x 2yy ....'
86d11cf2 323 if (!($rep =~ m#^HTTP/1\.. 2[0-9][0-9]#)) {
73bcf533
IA
324 die "Proxy connect: $rep\n";
325 }
326 # Skip up to the empty line of the proxy server output
327 # including the response headers.
328 while ($rep = <$s>) {
329 last if (!defined $rep ||
330 $rep eq "\n" ||
331 $rep eq "\r\n");
332 }
333 } else {
334 $s = IO::Socket::INET->new(PeerHost => $serv, PeerPort => $port);
335 die "Socket to $serv: $!\n" unless defined $s;
336 }
337
a57a9493
MU
338 $s->write("BEGIN AUTH REQUEST\n$repo\n$user\n$pass\nEND AUTH REQUEST\n")
339 or die "Write to $serv: $!\n";
340 $s->flush();
341
73bcf533 342 $rep = <$s>;
a57a9493 343
86d11cf2 344 if ($rep ne "I LOVE YOU\n") {
a57a9493
MU
345 $rep="<unknown>" unless $rep;
346 die "AuthReply: $rep\n";
347 }
348 $self->{'socketo'} = $s;
349 $self->{'socketi'} = $s;
34155390 350 } else { # local or ext: Fork off our own cvs server.
a57a9493
MU
351 my $pr = IO::Pipe->new();
352 my $pw = IO::Pipe->new();
353 my $pid = fork();
354 die "Fork: $!\n" unless defined $pid;
8d0ea311
SV
355 my $cvs = 'cvs';
356 $cvs = $ENV{CVS_SERVER} if exists $ENV{CVS_SERVER};
34155390
SV
357 my $rsh = 'rsh';
358 $rsh = $ENV{CVS_RSH} if exists $ENV{CVS_RSH};
359
360 my @cvs = ($cvs, 'server');
361 my ($local, $user, $host);
362 $local = $repo =~ s/:local://;
363 if (!$local) {
364 $repo =~ s/:ext://;
365 $local = !($repo =~ s/^(?:([^\@:]+)\@)?([^:]+)://);
366 ($user, $host) = ($1, $2);
367 }
368 if (!$local) {
369 if ($user) {
370 unshift @cvs, $rsh, '-l', $user, $host;
371 } else {
372 unshift @cvs, $rsh, $host;
373 }
374 }
375
86d11cf2 376 unless ($pid) {
a57a9493
MU
377 $pr->writer();
378 $pw->reader();
a57a9493
MU
379 dup2($pw->fileno(),0);
380 dup2($pr->fileno(),1);
381 $pr->close();
382 $pw->close();
34155390 383 exec(@cvs);
a57a9493
MU
384 }
385 $pw->writer();
386 $pr->reader();
387 $self->{'socketo'} = $pw;
388 $self->{'socketi'} = $pr;
389 }
390 $self->{'socketo'}->write("Root $repo\n");
391
392 # Trial and error says that this probably is the minimum set
b0921331 393 $self->{'socketo'}->write("Valid-responses ok error Valid-requests Mode M Mbinary E Checked-in Created Updated Merged Removed\n");
a57a9493
MU
394
395 $self->{'socketo'}->write("valid-requests\n");
396 $self->{'socketo'}->flush();
397
e7cad3cc
FK
398 my $rep=$self->readline();
399 die "Failed to read from server" unless defined $rep;
400 chomp($rep);
86d11cf2 401 if ($rep !~ s/^Valid-requests\s*//) {
a57a9493
MU
402 $rep="<unknown>" unless $rep;
403 die "Expected Valid-requests from server, but got: $rep\n";
404 }
405 chomp(my $res=$self->readline());
406 die "validReply: $res\n" if $res ne "ok";
407
408 $self->{'socketo'}->write("UseUnchanged\n") if $rep =~ /\bUseUnchanged\b/;
409 $self->{'repo'} = $repo;
410}
411
412sub readline {
86d11cf2 413 my ($self) = @_;
a57a9493
MU
414 return $self->{'socketi'}->getline();
415}
416
417sub _file {
418 # Request a file with a given revision.
419 # Trial and error says this is a good way to do it. :-/
86d11cf2 420 my ($self,$fn,$rev) = @_;
a57a9493
MU
421 $self->{'socketo'}->write("Argument -N\n") or return undef;
422 $self->{'socketo'}->write("Argument -P\n") or return undef;
abe05822
ML
423 # -kk: Linus' version doesn't use it - defaults to off
424 if ($opt_k) {
425 $self->{'socketo'}->write("Argument -kk\n") or return undef;
426 }
a57a9493
MU
427 $self->{'socketo'}->write("Argument -r\n") or return undef;
428 $self->{'socketo'}->write("Argument $rev\n") or return undef;
429 $self->{'socketo'}->write("Argument --\n") or return undef;
430 $self->{'socketo'}->write("Argument $self->{'subdir'}/$fn\n") or return undef;
431 $self->{'socketo'}->write("Directory .\n") or return undef;
432 $self->{'socketo'}->write("$self->{'repo'}\n") or return undef;
4f7c0caa 433 # $self->{'socketo'}->write("Sticky T1.0\n") or return undef;
a57a9493
MU
434 $self->{'socketo'}->write("co\n") or return undef;
435 $self->{'socketo'}->flush() or return undef;
436 $self->{'lines'} = 0;
437 return 1;
438}
439sub _line {
440 # Read a line from the server.
441 # ... except that 'line' may be an entire file. ;-)
86d11cf2 442 my ($self, $fh) = @_;
a57a9493
MU
443 die "Not in lines" unless defined $self->{'lines'};
444
445 my $line;
2eb6d82e 446 my $res=0;
86d11cf2 447 while (defined($line = $self->readline())) {
a57a9493
MU
448 # M U gnupg-cvs-rep/AUTHORS
449 # Updated gnupg-cvs-rep/
450 # /daten/src/rsync/gnupg-cvs-rep/AUTHORS
451 # /AUTHORS/1.1///T1.1
452 # u=rw,g=rw,o=rw
453 # 0
454 # ok
455
86d11cf2 456 if ($line =~ s/^(?:Created|Updated) //) {
a57a9493
MU
457 $line = $self->readline(); # path
458 $line = $self->readline(); # Entries line
459 my $mode = $self->readline(); chomp $mode;
460 $self->{'mode'} = $mode;
461 defined (my $cnt = $self->readline())
462 or die "EOF from server after 'Changed'\n";
463 chomp $cnt;
464 die "Duh: Filesize $cnt" if $cnt !~ /^\d+$/;
465 $line="";
55cad842 466 $res = $self->_fetchfile($fh, $cnt);
86d11cf2 467 } elsif ($line =~ s/^ //) {
2eb6d82e
SV
468 print $fh $line;
469 $res += length($line);
86d11cf2 470 } elsif ($line =~ /^M\b/) {
a57a9493 471 # output, do nothing
86d11cf2 472 } elsif ($line =~ /^Mbinary\b/) {
a57a9493
MU
473 my $cnt;
474 die "EOF from server after 'Mbinary'" unless defined ($cnt = $self->readline());
475 chomp $cnt;
476 die "Duh: Mbinary $cnt" if $cnt !~ /^\d+$/ or $cnt<1;
477 $line="";
55cad842 478 $res += $self->_fetchfile($fh, $cnt);
a57a9493
MU
479 } else {
480 chomp $line;
86d11cf2 481 if ($line eq "ok") {
a57a9493
MU
482 # print STDERR "S: ok (".length($res).")\n";
483 return $res;
86d11cf2 484 } elsif ($line =~ s/^E //) {
a57a9493 485 # print STDERR "S: $line\n";
86d11cf2 486 } elsif ($line =~ /^(Remove-entry|Removed) /i) {
8b8840e0
MU
487 $line = $self->readline(); # filename
488 $line = $self->readline(); # OK
489 chomp $line;
490 die "Unknown: $line" if $line ne "ok";
491 return -1;
a57a9493
MU
492 } else {
493 die "Unknown: $line\n";
494 }
495 }
496 }
39ba7d54 497 return undef;
a57a9493
MU
498}
499sub file {
86d11cf2 500 my ($self,$fn,$rev) = @_;
a57a9493
MU
501 my $res;
502
a6080a0a 503 my ($fh, $name) = tempfile('gitcvs.XXXXXX',
2eb6d82e
SV
504 DIR => File::Spec->tmpdir(), UNLINK => 1);
505
506 $self->_file($fn,$rev) and $res = $self->_line($fh);
507
508 if (!defined $res) {
39ba7d54
MM
509 print STDERR "Server has gone away while fetching $fn $rev, retrying...\n";
510 truncate $fh, 0;
2eb6d82e 511 $self->conn();
39ba7d54 512 $self->_file($fn,$rev) or die "No file command send";
2eb6d82e 513 $res = $self->_line($fh);
39ba7d54 514 die "Retry failed" unless defined $res;
a57a9493 515 }
c619ad51 516 close ($fh);
a57a9493 517
2eb6d82e 518 return ($name, $res);
a57a9493 519}
55cad842
ML
520sub _fetchfile {
521 my ($self, $fh, $cnt) = @_;
61efa5e3 522 my $res = 0;
55cad842 523 my $bufsize = 1024 * 1024;
86d11cf2 524 while ($cnt) {
55cad842
ML
525 if ($bufsize > $cnt) {
526 $bufsize = $cnt;
527 }
528 my $buf;
529 my $num = $self->{'socketi'}->read($buf,$bufsize);
530 die "Server: Filesize $cnt: $num: $!\n" if not defined $num or $num<=0;
531 print $fh $buf;
532 $res += $num;
533 $cnt -= $num;
534 }
535 return $res;
536}
a57a9493 537
b2139dbd
DH
538sub _scramble {
539 my ($self, $pass) = @_;
540 my $scrambled = "A";
541
542 return $scrambled unless $pass;
543
544 my $pass_len = length($pass);
545 my @pass_arr = split("", $pass);
546 my $i;
547
548 # from cvs/src/scramble.c
549 my @shifts = (
550 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
551 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
552 114,120, 53, 79, 96,109, 72,108, 70, 64, 76, 67,116, 74, 68, 87,
553 111, 52, 75,119, 49, 34, 82, 81, 95, 65,112, 86,118,110,122,105,
554 41, 57, 83, 43, 46,102, 40, 89, 38,103, 45, 50, 42,123, 91, 35,
555 125, 55, 54, 66,124,126, 59, 47, 92, 71,115, 78, 88,107,106, 56,
556 36,121,117,104,101,100, 69, 73, 99, 63, 94, 93, 39, 37, 61, 48,
557 58,113, 32, 90, 44, 98, 60, 51, 33, 97, 62, 77, 84, 80, 85,223,
558 225,216,187,166,229,189,222,188,141,249,148,200,184,136,248,190,
559 199,170,181,204,138,232,218,183,255,234,220,247,213,203,226,193,
560 174,172,228,252,217,201,131,230,197,211,145,238,161,179,160,212,
561 207,221,254,173,202,146,224,151,140,196,205,130,135,133,143,246,
562 192,159,244,239,185,168,215,144,139,165,180,157,147,186,214,176,
563 227,231,219,169,175,156,206,198,129,164,150,210,154,177,134,127,
564 182,128,158,208,162,132,167,209,149,241,153,251,237,236,171,195,
565 243,233,253,240,194,250,191,155,142,137,245,235,163,242,178,152
566 );
567
568 for ($i = 0; $i < $pass_len; $i++) {
569 $scrambled .= pack("C", $shifts[ord($pass_arr[$i])]);
570 }
571
572 return $scrambled;
573}
a57a9493
MU
574
575package main;
576
2a3e1a85 577my $cvs = CVSconn->new($opt_d, $cvs_tree);
a57a9493
MU
578
579
580sub pdate($) {
86d11cf2 581 my ($d) = @_;
a57a9493
MU
582 m#(\d{2,4})/(\d\d)/(\d\d)\s(\d\d):(\d\d)(?::(\d\d))?#
583 or die "Unparseable date: $d\n";
584 my $y=$1; $y-=1900 if $y>1900;
585 return timegm($6||0,$5,$4,$3,$2-1,$y);
9718a00b
TM
586}
587
a57a9493 588sub pmode($) {
86d11cf2 589 my ($mode) = @_;
a57a9493
MU
590 my $m = 0;
591 my $mm = 0;
592 my $um = 0;
593 for my $x(split(//,$mode)) {
86d11cf2 594 if ($x eq ",") {
a57a9493
MU
595 $m |= $mm&$um;
596 $mm = 0;
597 $um = 0;
86d11cf2
JH
598 } elsif ($x eq "u") { $um |= 0700;
599 } elsif ($x eq "g") { $um |= 0070;
600 } elsif ($x eq "o") { $um |= 0007;
601 } elsif ($x eq "r") { $mm |= 0444;
602 } elsif ($x eq "w") { $mm |= 0222;
603 } elsif ($x eq "x") { $mm |= 0111;
604 } elsif ($x eq "=") { # do nothing
a57a9493
MU
605 } else { die "Unknown mode: $mode\n";
606 }
607 }
608 $m |= $mm&$um;
609 return $m;
610}
d4f8b390 611
a57a9493
MU
612sub getwd() {
613 my $pwd = `pwd`;
614 chomp $pwd;
615 return $pwd;
d4f8b390
LT
616}
617
e73aefe4
JK
618sub is_sha1 {
619 my $s = shift;
620 return $s =~ /^[a-f0-9]{40}$/;
621}
db4b6582 622
9da0dabc
JK
623sub get_headref ($) {
624 my $name = shift;
625 my $r = `git rev-parse --verify '$name' 2>/dev/null`;
626 return undef unless $? == 0;
627 chomp $r;
628 return $r;
db4b6582
ML
629}
630
f6fdbb68
JK
631my $user_filename_prepend = '';
632sub munge_user_filename {
633 my $name = shift;
634 return File::Spec->file_name_is_absolute($name) ?
635 $name :
636 $user_filename_prepend . $name;
637}
638
a57a9493
MU
639-d $git_tree
640 or mkdir($git_tree,0777)
641 or die "Could not create $git_tree: $!";
f6fdbb68
JK
642if ($git_tree ne '.') {
643 $user_filename_prepend = getwd() . '/';
644 chdir($git_tree);
645}
d4f8b390 646
a57a9493 647my $last_branch = "";
46541669 648my $orig_branch = "";
a57a9493 649my %branch_date;
8a5f2eac 650my $tip_at_start = undef;
a57a9493
MU
651
652my $git_dir = $ENV{"GIT_DIR"} || ".git";
653$git_dir = getwd()."/".$git_dir unless $git_dir =~ m#^/#;
654$ENV{"GIT_DIR"} = $git_dir;
79ee456c
SV
655my $orig_git_index;
656$orig_git_index = $ENV{GIT_INDEX_FILE} if exists $ENV{GIT_INDEX_FILE};
8f732649
ML
657
658my %index; # holds filenames of one index per branch
061303f0 659
86d11cf2 660unless (-d $git_dir) {
91fe7324 661 system(qw(git init));
a57a9493 662 die "Cannot init the GIT db at $git_tree: $?\n" if $?;
1bb28d87 663 system(qw(git read-tree --empty));
a57a9493
MU
664 die "Cannot init an empty tree: $?\n" if $?;
665
666 $last_branch = $opt_o;
46541669 667 $orig_branch = "";
a57a9493 668} else {
a12477db 669 open(F, "-|", qw(git symbolic-ref HEAD)) or
640d9d08 670 die "Cannot run git symbolic-ref: $!\n";
8366a10a
PR
671 chomp ($last_branch = <F>);
672 $last_branch = basename($last_branch);
673 close(F);
86d11cf2 674 unless ($last_branch) {
46541669
MU
675 warn "Cannot read the last branch name: $! -- assuming 'master'\n";
676 $last_branch = "master";
677 }
678 $orig_branch = $last_branch;
640d9d08 679 $tip_at_start = `git rev-parse --verify HEAD`;
a57a9493
MU
680
681 # Get the last import timestamps
1f24c587 682 my $fmt = '($ref, $author) = (%(refname), %(author));';
a12477db
BW
683 my @cmd = ('git', 'for-each-ref', '--perl', "--format=$fmt", $remote);
684 open(H, "-|", @cmd) or die "Cannot run git for-each-ref: $!\n";
86d11cf2 685 while (defined(my $entry = <H>)) {
1f24c587
AW
686 my ($ref, $author);
687 eval($entry) || die "cannot eval refs list: $@";
8b7f5fc1 688 my ($head) = ($ref =~ m|^$remote/(.*)|);
1f24c587
AW
689 $author =~ /^.*\s(\d+)\s[-+]\d{4}$/;
690 $branch_date{$head} = $1;
a57a9493 691 }
1f24c587 692 close(H);
7ca055f7
SS
693 if (!exists $branch_date{$opt_o}) {
694 die "Branch '$opt_o' does not exist.\n".
695 "Either use the correct '-o branch' option,\n".
696 "or import to a new repository.\n";
697 }
a57a9493
MU
698}
699
700-d $git_dir
701 or die "Could not create git subdir ($git_dir).\n";
702
ffd97f3a
AE
703# now we read (and possibly save) author-info as well
704-f "$git_dir/cvs-authors" and
705 read_author_info("$git_dir/cvs-authors");
706if ($opt_A) {
f6fdbb68 707 read_author_info(munge_user_filename($opt_A));
ffd97f3a
AE
708 write_author_info("$git_dir/cvs-authors");
709}
710
0455ec03
AC
711# open .git/cvs-revisions, if requested
712open my $revision_map, '>>', "$git_dir/cvs-revisions"
713 or die "Can't open $git_dir/cvs-revisions for appending: $!\n"
714 if defined $opt_R;
715
2f57c697
ML
716
717#
718# run cvsps into a file unless we are getting
719# it passed as a file via $opt_P
720#
4083c2fc 721my $cvspsfile;
2f57c697
ML
722unless ($opt_P) {
723 print "Running cvsps...\n" if $opt_v;
724 my $pid = open(CVSPS,"-|");
4083c2fc 725 my $cvspsfh;
2f57c697 726 die "Cannot fork: $!\n" unless defined $pid;
86d11cf2 727 unless ($pid) {
2f57c697
ML
728 my @opt;
729 @opt = split(/,/,$opt_p) if defined $opt_p;
730 unshift @opt, '-z', $opt_z if defined $opt_z;
731 unshift @opt, '-q' unless defined $opt_v;
732 unless (defined($opt_p) && $opt_p =~ m/--no-cvs-direct/) {
733 push @opt, '--cvs-direct';
734 }
735 exec("cvsps","--norc",@opt,"-u","-A",'--root',$opt_d,$cvs_tree);
736 die "Could not start cvsps: $!\n";
df73e9c6 737 }
4083c2fc
ML
738 ($cvspsfh, $cvspsfile) = tempfile('gitXXXXXX', SUFFIX => '.cvsps',
739 DIR => File::Spec->tmpdir());
2f57c697
ML
740 while (<CVSPS>) {
741 print $cvspsfh $_;
211dcac6 742 }
2f57c697 743 close CVSPS;
640d9d08 744 $? == 0 or die "git cvsimport: fatal: cvsps reported error\n";
2f57c697 745 close $cvspsfh;
4083c2fc 746} else {
f6fdbb68 747 $cvspsfile = munge_user_filename($opt_P);
a57a9493
MU
748}
749
4083c2fc 750open(CVS, "<$cvspsfile") or die $!;
2f57c697 751
a57a9493
MU
752## cvsps output:
753#---------------------
754#PatchSet 314
755#Date: 1999/09/18 13:03:59
756#Author: wkoch
757#Branch: STABLE-BRANCH-1-0
758#Ancestor branch: HEAD
759#Tag: (none)
760#Log:
761# See ChangeLog: Sat Sep 18 13:03:28 CEST 1999 Werner Koch
762#Members:
763# README:1.57->1.57.2.1
764# VERSION:1.96->1.96.2.1
765#
766#---------------------
767
768my $state = 0;
769
e73aefe4
JK
770sub update_index (\@\@) {
771 my $old = shift;
772 my $new = shift;
640d9d08
BW
773 open(my $fh, '|-', qw(git update-index -z --index-info))
774 or die "unable to open git update-index: $!";
6a1871e1
JK
775 print $fh
776 (map { "0 0000000000000000000000000000000000000000\t$_\0" }
e73aefe4 777 @$old),
6a1871e1 778 (map { '100' . sprintf('%o', $_->[0]) . " $_->[1]\t$_->[2]\0" }
e73aefe4 779 @$new)
640d9d08 780 or die "unable to write to git update-index: $!";
6a1871e1 781 close $fh
640d9d08
BW
782 or die "unable to write to git update-index: $!";
783 $? and die "git update-index reported error: $?";
e73aefe4 784}
a57a9493 785
e73aefe4 786sub write_tree () {
a12477db 787 open(my $fh, '-|', qw(git write-tree))
640d9d08 788 or die "unable to open git write-tree: $!";
e73aefe4
JK
789 chomp(my $tree = <$fh>);
790 is_sha1($tree)
791 or die "Cannot get tree id ($tree): $!";
792 close($fh)
640d9d08 793 or die "Error running git write-tree: $?\n";
a57a9493 794 print "Tree ID $tree\n" if $opt_v;
e73aefe4
JK
795 return $tree;
796}
a57a9493 797
86d11cf2 798my ($patchset,$date,$author_name,$author_email,$branch,$ancestor,$tag,$logmsg);
0455ec03 799my (@old,@new,@skipped,%ignorebranch,@commit_revisions);
71b08148
ML
800
801# commits that cvsps cannot place anywhere...
802$ignorebranch{'#CVSPS_NO_BRANCH'} = 1;
803
e73aefe4 804sub commit {
9da0dabc
JK
805 if ($branch eq $opt_o && !$index{branch} &&
806 !get_headref("$remote/$branch")) {
c5f448b0 807 # looks like an initial commit
640d9d08 808 # use the index primed by git init
23fcdc79
MM
809 $ENV{GIT_INDEX_FILE} = "$git_dir/index";
810 $index{$branch} = "$git_dir/index";
c5f448b0
ML
811 } else {
812 # use an index per branch to speed up
813 # imports of projects with many branches
814 unless ($index{$branch}) {
815 $index{$branch} = tmpnam();
816 $ENV{GIT_INDEX_FILE} = $index{$branch};
817 if ($ancestor) {
640d9d08 818 system("git", "read-tree", "$remote/$ancestor");
c5f448b0 819 } else {
640d9d08 820 system("git", "read-tree", "$remote/$branch");
c5f448b0
ML
821 }
822 die "read-tree failed: $?\n" if $?;
823 }
824 }
825 $ENV{GIT_INDEX_FILE} = $index{$branch};
826
e73aefe4
JK
827 update_index(@old, @new);
828 @old = @new = ();
829 my $tree = write_tree();
9da0dabc 830 my $parent = get_headref("$remote/$last_branch");
e73aefe4
JK
831 print "Parent ID " . ($parent ? $parent : "(empty)") . "\n" if $opt_v;
832
833 my @commit_args;
834 push @commit_args, ("-p", $parent) if $parent;
835
836 # loose detection of merges
837 # based on the commit msg
838 foreach my $rx (@mergerx) {
839 next unless $logmsg =~ $rx && $1;
840 my $mparent = $1 eq 'HEAD' ? $opt_o : $1;
9da0dabc 841 if (my $sha1 = get_headref("$remote/$mparent")) {
c36c5b84 842 push @commit_args, '-p', "$remote/$mparent";
e73aefe4 843 print "Merge parent branch: $mparent\n" if $opt_v;
db4b6582 844 }
a57a9493 845 }
e73aefe4
JK
846
847 my $commit_date = strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date));
62bf0d96
JK
848 $ENV{GIT_AUTHOR_NAME} = $author_name;
849 $ENV{GIT_AUTHOR_EMAIL} = $author_email;
850 $ENV{GIT_AUTHOR_DATE} = $commit_date;
851 $ENV{GIT_COMMITTER_NAME} = $author_name;
852 $ENV{GIT_COMMITTER_EMAIL} = $author_email;
853 $ENV{GIT_COMMITTER_DATE} = $commit_date;
e73aefe4 854 my $pid = open2(my $commit_read, my $commit_write,
640d9d08 855 'git', 'commit-tree', $tree, @commit_args);
e371046b
MU
856
857 # compatibility with git2cvs
858 substr($logmsg,32767) = "" if length($logmsg) > 32767;
859 $logmsg =~ s/[\s\n]+\z//;
860
5179c8a5
ML
861 if (@skipped) {
862 $logmsg .= "\n\n\nSKIPPED:\n\t";
863 $logmsg .= join("\n\t", @skipped) . "\n";
f396f01f 864 @skipped = ();
5179c8a5
ML
865 }
866
e73aefe4 867 print($commit_write "$logmsg\n") && close($commit_write)
640d9d08 868 or die "Error writing to git commit-tree: $!\n";
2a3e1a85 869
e73aefe4
JK
870 print "Committed patch $patchset ($branch $commit_date)\n" if $opt_v;
871 chomp(my $cid = <$commit_read>);
872 is_sha1($cid) or die "Cannot get commit id ($cid): $!\n";
a57a9493 873 print "Commit ID $cid\n" if $opt_v;
e73aefe4 874 close($commit_read);
2a3e1a85
MU
875
876 waitpid($pid,0);
640d9d08 877 die "Error running git commit-tree: $?\n" if $?;
a57a9493 878
640d9d08 879 system('git' , 'update-ref', "$remote/$branch", $cid) == 0
a57a9493
MU
880 or die "Cannot write branch $branch for update: $!\n";
881
0455ec03
AC
882 if ($revision_map) {
883 print $revision_map "@$_ $cid\n" for @commit_revisions;
884 }
885 @commit_revisions = ();
886
86d11cf2 887 if ($tag) {
86d11cf2 888 my ($xtag) = $tag;
0d821d4d
PA
889 $xtag =~ s/\s+\*\*.*$//; # Remove stuff like ** INVALID ** and ** FUNKY **
890 $xtag =~ tr/_/\./ if ( $opt_u );
34c99da2 891 $xtag =~ s/[\/]/$opt_s/g;
509792b9 892 $xtag =~ s/\[//g;
a6080a0a 893
640d9d08 894 system('git' , 'tag', '-f', $xtag, $cid) == 0
0d821d4d 895 or die "Cannot create tag $xtag: $!\n";
0d821d4d
PA
896
897 print "Created tag '$xtag' on '$branch'\n" if $opt_v;
a57a9493 898 }
a57a9493
MU
899};
900
06918348 901my $commitcount = 1;
86d11cf2 902while (<CVS>) {
a57a9493 903 chomp;
86d11cf2 904 if ($state == 0 and /^-+$/) {
a57a9493 905 $state = 1;
86d11cf2 906 } elsif ($state == 0) {
a57a9493
MU
907 $state = 1;
908 redo;
86d11cf2 909 } elsif (($state==0 or $state==1) and s/^PatchSet\s+//) {
a57a9493
MU
910 $patchset = 0+$_;
911 $state=2;
86d11cf2 912 } elsif ($state == 2 and s/^Date:\s+//) {
a57a9493 913 $date = pdate($_);
86d11cf2 914 unless ($date) {
a57a9493
MU
915 print STDERR "Could not parse date: $_\n";
916 $state=0;
917 next;
918 }
919 $state=3;
86d11cf2 920 } elsif ($state == 3 and s/^Author:\s+//) {
a57a9493 921 s/\s+$//;
94c23343
JH
922 if (/^(.*?)\s+<(.*)>/) {
923 ($author_name, $author_email) = ($1, $2);
ffd97f3a
AE
924 } elsif ($conv_author_name{$_}) {
925 $author_name = $conv_author_name{$_};
926 $author_email = $conv_author_email{$_};
94c23343
JH
927 } else {
928 $author_name = $author_email = $_;
929 }
a57a9493 930 $state = 4;
86d11cf2 931 } elsif ($state == 4 and s/^Branch:\s+//) {
a57a9493 932 s/\s+$//;
a0554224 933 tr/_/\./ if ( $opt_u );
fbfd60d6 934 s/[\/]/$opt_s/g;
a57a9493
MU
935 $branch = $_;
936 $state = 5;
86d11cf2 937 } elsif ($state == 5 and s/^Ancestor branch:\s+//) {
a57a9493
MU
938 s/\s+$//;
939 $ancestor = $_;
0fa2824f 940 $ancestor = $opt_o if $ancestor eq "HEAD";
a57a9493 941 $state = 6;
86d11cf2 942 } elsif ($state == 5) {
a57a9493
MU
943 $ancestor = undef;
944 $state = 6;
945 redo;
86d11cf2 946 } elsif ($state == 6 and s/^Tag:\s+//) {
a57a9493 947 s/\s+$//;
86d11cf2 948 if ($_ eq "(none)") {
a57a9493
MU
949 $tag = undef;
950 } else {
951 $tag = $_;
952 }
953 $state = 7;
86d11cf2 954 } elsif ($state == 7 and /^Log:/) {
a57a9493
MU
955 $logmsg = "";
956 $state = 8;
86d11cf2 957 } elsif ($state == 8 and /^Members:/) {
a57a9493 958 $branch = $opt_o if $branch eq "HEAD";
86d11cf2 959 if (defined $branch_date{$branch} and $branch_date{$branch} >= $date) {
a57a9493 960 # skip
9da07f34 961 print "skip patchset $patchset: $date before $branch_date{$branch}\n" if $opt_v;
a57a9493
MU
962 $state = 11;
963 next;
964 }
ded9f400 965 if (!$opt_a && $starttime - 300 - (defined $opt_z ? $opt_z : 300) <= $date) {
6211988f 966 # skip if the commit is too recent
77190eb9 967 # given that the cvsps default fuzz is 300s, we give ourselves another
6211988f
ML
968 # 300s just in case -- this also prevents skipping commits
969 # due to server clock drift
970 print "skip patchset $patchset: $date too recent\n" if $opt_v;
971 $state = 11;
972 next;
973 }
71b08148
ML
974 if (exists $ignorebranch{$branch}) {
975 print STDERR "Skipping $branch\n";
976 $state = 11;
977 next;
978 }
86d11cf2
JH
979 if ($ancestor) {
980 if ($ancestor eq $branch) {
71b08148
ML
981 print STDERR "Branch $branch erroneously stems from itself -- changed ancestor to $opt_o\n";
982 $ancestor = $opt_o;
983 }
0750d751 984 if (defined get_headref("$remote/$branch")) {
a57a9493
MU
985 print STDERR "Branch $branch already exists!\n";
986 $state=11;
987 next;
988 }
0750d751
JK
989 my $id = get_headref("$remote/$ancestor");
990 if (!$id) {
a57a9493 991 print STDERR "Branch $ancestor does not exist!\n";
71b08148 992 $ignorebranch{$branch} = 1;
a57a9493
MU
993 $state=11;
994 next;
995 }
0750d751
JK
996
997 system(qw(git update-ref -m cvsimport),
998 "$remote/$branch", $id);
999 if($? != 0) {
1000 print STDERR "Could not create branch $branch\n";
71b08148 1001 $ignorebranch{$branch} = 1;
a57a9493
MU
1002 $state=11;
1003 next;
1004 }
a57a9493 1005 }
46e63efc 1006 $last_branch = $branch if $branch ne $last_branch;
a57a9493 1007 $state = 9;
86d11cf2 1008 } elsif ($state == 8) {
a57a9493 1009 $logmsg .= "$_\n";
86d11cf2 1010 } elsif ($state == 9 and /^\s+(.+?):(INITIAL|\d+(?:\.\d+)+)->(\d+(?:\.\d+)+)\s*$/) {
a57a9493 1011# VERSION:1.96->1.96.2.1
2a3e1a85 1012 my $init = ($2 eq "INITIAL");
a57a9493 1013 my $fn = $1;
f65ae603
MU
1014 my $rev = $3;
1015 $fn =~ s#^/+##;
5179c8a5
ML
1016 if ($opt_S && $fn =~ m/$opt_S/) {
1017 print "SKIPPING $fn v $rev\n";
1018 push(@skipped, $fn);
1019 next;
1020 }
0455ec03 1021 push @commit_revisions, [$fn, $rev];
5179c8a5 1022 print "Fetching $fn v $rev\n" if $opt_v;
2eb6d82e 1023 my ($tmpname, $size) = $cvs->file($fn,$rev);
86d11cf2 1024 if ($size == -1) {
8b8840e0
MU
1025 push(@old,$fn);
1026 print "Drop $fn\n" if $opt_v;
1027 } else {
1028 print "".($init ? "New" : "Update")." $fn: $size bytes\n" if $opt_v;
dd27478f
JH
1029 my $pid = open(my $F, '-|');
1030 die $! unless defined $pid;
1031 if (!$pid) {
640d9d08 1032 exec("git", "hash-object", "-w", $tmpname)
8b8840e0 1033 or die "Cannot create object: $!\n";
dd27478f 1034 }
8b8840e0
MU
1035 my $sha = <$F>;
1036 chomp $sha;
1037 close $F;
1038 my $mode = pmode($cvs->{'mode'});
1039 push(@new,[$mode, $sha, $fn]); # may be resurrected!
1040 }
2eb6d82e 1041 unlink($tmpname);
86d11cf2 1042 } elsif ($state == 9 and /^\s+(.+?):\d+(?:\.\d+)+->(\d+(?:\.\d+)+)\(DEAD\)\s*$/) {
f65ae603 1043 my $fn = $1;
0455ec03 1044 my $rev = $2;
f65ae603 1045 $fn =~ s#^/+##;
0455ec03 1046 push @commit_revisions, [$fn, $rev];
f65ae603 1047 push(@old,$fn);
8b8840e0 1048 print "Delete $fn\n" if $opt_v;
86d11cf2 1049 } elsif ($state == 9 and /^\s*$/) {
a57a9493 1050 $state = 10;
86d11cf2 1051 } elsif (($state == 9 or $state == 10) and /^-+$/) {
4adcea99
LT
1052 $commitcount++;
1053 if ($opt_L && $commitcount > $opt_L) {
06918348
ML
1054 last;
1055 }
c4b16f8d 1056 commit();
4adcea99 1057 if (($commitcount & 1023) == 0) {
91fe7324 1058 system(qw(git repack -a -d));
4adcea99 1059 }
a57a9493 1060 $state = 1;
86d11cf2 1061 } elsif ($state == 11 and /^-+$/) {
a57a9493 1062 $state = 1;
86d11cf2 1063 } elsif (/^-+$/) { # end of unknown-line processing
a57a9493 1064 $state = 1;
86d11cf2 1065 } elsif ($state != 11) { # ignore stuff when skipping
3be39998 1066 print STDERR "* UNKNOWN LINE * $_\n";
a57a9493
MU
1067 }
1068}
c4b16f8d 1069commit() if $branch and $state != 11;
d4f8b390 1070
4083c2fc
ML
1071unless ($opt_P) {
1072 unlink($cvspsfile);
1073}
1074
efe4abd1
JM
1075# The heuristic of repacking every 1024 commits can leave a
1076# lot of unpacked data. If there is more than 1MB worth of
1077# not-packed objects, repack once more.
640d9d08 1078my $line = `git count-objects`;
efe4abd1
JM
1079if ($line =~ /^(\d+) objects, (\d+) kilobytes$/) {
1080 my ($n_objects, $kb) = ($1, $2);
1081 1024 < $kb
91fe7324 1082 and system(qw(git repack -a -d));
efe4abd1
JM
1083}
1084
8f732649 1085foreach my $git_index (values %index) {
23fcdc79 1086 if ($git_index ne "$git_dir/index") {
c5f448b0
ML
1087 unlink($git_index);
1088 }
8f732649 1089}
79ee456c 1090
210569f9
SV
1091if (defined $orig_git_index) {
1092 $ENV{GIT_INDEX_FILE} = $orig_git_index;
1093} else {
1094 delete $ENV{GIT_INDEX_FILE};
1095}
1096
46541669 1097# Now switch back to the branch we were in before all of this happened
86d11cf2 1098if ($orig_branch) {
8a5f2eac
JH
1099 print "DONE.\n" if $opt_v;
1100 if ($opt_i) {
1101 exit 0;
1102 }
640d9d08 1103 my $tip_at_end = `git rev-parse --verify HEAD`;
8a5f2eac 1104 if ($tip_at_start ne $tip_at_end) {
cb9594e2 1105 for ($tip_at_start, $tip_at_end) { chomp; }
8a5f2eac 1106 print "Fetched into the current branch.\n" if $opt_v;
640d9d08 1107 system(qw(git read-tree -u -m),
8a5f2eac
JH
1108 $tip_at_start, $tip_at_end);
1109 die "Fast-forward update failed: $?\n" if $?;
1110 }
1111 else {
640d9d08 1112 system(qw(git merge cvsimport HEAD), "$remote/$opt_o");
8a5f2eac
JH
1113 die "Could not merge $opt_o into the current branch.\n" if $?;
1114 }
46541669
MU
1115} else {
1116 $orig_branch = "master";
1117 print "DONE; creating $orig_branch branch\n" if $opt_v;
640d9d08 1118 system("git", "update-ref", "refs/heads/master", "$remote/$opt_o")
0750d751 1119 unless defined get_headref('refs/heads/master');
640d9d08 1120 system("git", "symbolic-ref", "$remote/HEAD", "$remote/$opt_o")
06baffd3 1121 if ($opt_r && $opt_o ne 'HEAD');
640d9d08 1122 system('git', 'update-ref', 'HEAD', "$orig_branch");
c1c774e7 1123 unless ($opt_i) {
91fe7324 1124 system(qw(git checkout -f));
c1c774e7
SV
1125 die "checkout failed: $?\n" if $?;
1126 }
46541669 1127}