diff --git a/Documentation/git-cvsexportcommit.txt b/Documentation/git-cvsexportcommit.txt index 363c36d694..f75afaaadc 100644 --- a/Documentation/git-cvsexportcommit.txt +++ b/Documentation/git-cvsexportcommit.txt @@ -8,7 +8,7 @@ git-cvsexportcommit - Export a single commit to a CVS checkout SYNOPSIS -------- -'git-cvsexportcommit' [-h] [-u] [-v] [-c] [-P] [-p] [-a] [-d cvsroot] [-w cvsworkdir] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID +'git-cvsexportcommit' [-h] [-u] [-v] [-c] [-P] [-p] [-a] [-d cvsroot] [-w cvsworkdir] [-W] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID DESCRIPTION @@ -68,6 +68,11 @@ OPTIONS current directory is within a git repository. The default is the value of 'cvsexportcommit.cvsdir'. +-W:: + Tell cvsexportcommit that the current working directory is not only + a Git checkout, but also the CVS checkout. Therefore, Git will + reset the working directory to the parent commit before proceeding. + -v:: Verbose. diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl index c93bd9c9b5..c6c70e9eba 100755 --- a/git-cvsexportcommit.perl +++ b/git-cvsexportcommit.perl @@ -8,9 +8,9 @@ use File::Spec; use Git; -our ($opt_h, $opt_P, $opt_p, $opt_v, $opt_c, $opt_f, $opt_a, $opt_m, $opt_d, $opt_u, $opt_w); +our ($opt_h, $opt_P, $opt_p, $opt_v, $opt_c, $opt_f, $opt_a, $opt_m, $opt_d, $opt_u, $opt_w, $opt_W); -getopts('uhPpvcfam:d:w:'); +getopts('uhPpvcfam:d:w:W'); $opt_h && usage(); @@ -20,7 +20,7 @@ my $repo = Git->repository(); $opt_w = $repo->config('cvsexportcommit.cvsdir') unless defined $opt_w; -if ($opt_w) { +if ($opt_w || $opt_W) { # Remember where GIT_DIR is before changing to CVS checkout unless ($ENV{GIT_DIR}) { # No GIT_DIR set. Figure it out for ourselves @@ -30,7 +30,9 @@ } # Make sure GIT_DIR is absolute $ENV{GIT_DIR} = File::Spec->rel2abs($ENV{GIT_DIR}); +} +if ($opt_w) { if (! -d $opt_w."/CVS" ) { die "$opt_w is not a CVS checkout"; } @@ -121,6 +123,15 @@ } } +my $go_back_to = 0; + +if ($opt_W) { + $opt_v && print "Resetting to $parent\n"; + $go_back_to = `git symbolic-ref HEAD 2> /dev/null || + git rev-parse HEAD` || die "Could not determine current branch"; + system("git checkout -q $parent^0") && die "Could not check out $parent^0"; +} + $opt_v && print "Applying to CVS commit $commit from parent $parent\n"; # grab the commit message @@ -215,7 +226,8 @@ my $basename = basename($name); $basename = "no file " . $basename if (exists($added{$basename})); - chomp($basename); + $basename =~ s/^\s+//; + $basename =~ s/\s+$//; if (!exists($fullname{$basename})) { $fullname{$basename} = $name; @@ -264,7 +276,11 @@ } print "Applying\n"; -`GIT_DIR= git-apply $context --summary --numstat --apply <.cvsexportcommit.diff` || die "cannot patch"; +if ($opt_W) { + system("git checkout -q $commit^0") && die "cannot patch"; +} else { + `GIT_DIR= git-apply $context --summary --numstat --apply <.cvsexportcommit.diff` || die "cannot patch"; +} print "Patch applied successfully. Adding new files and directories to CVS\n"; my $dirtypatch = 0; @@ -317,7 +333,9 @@ print "using a patch program. After applying the patch and resolving the\n"; print "problems you may commit using:"; print "\n cd \"$opt_w\"" if $opt_w; - print "\n $cmd\n\n"; + print "\n $cmd\n"; + print "\n git checkout $go_back_to\n" if $go_back_to; + print "\n"; exit(1); } @@ -337,6 +355,14 @@ # clean up unlink(".cvsexportcommit.diff"); +if ($opt_W) { + system("git checkout $go_back_to") && die "cannot move back to $go_back_to"; + if (!($go_back_to =~ /^[0-9a-fA-F]{40}$/)) { + system("git symbolic-ref HEAD $go_back_to") && + die "cannot move back to $go_back_to"; + } +} + # CVS version 1.11.x and 1.12.x sleeps the wrong way to ensure the timestamp # used by CVS and the one set by subsequence file modifications are different. # If they are not different CVS will not detect changes. diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh index 42b144b1b3..b1dc32d056 100755 --- a/t/t9200-git-cvsexportcommit.sh +++ b/t/t9200-git-cvsexportcommit.sh @@ -297,4 +297,21 @@ test_expect_success 'commit a file with leading spaces in the name' ' ' +test_expect_success 'use the same checkout for Git and CVS' ' + + (mkdir shared && + cd shared && + unset GIT_DIR && + cvs co . && + git init && + git add " space" && + git commit -m "fake initial commit" && + echo Hello >> " space" && + git commit -m "Another change" " space" && + git cvsexportcommit -W -p -u -c HEAD && + grep Hello " space" && + git diff-files) + +' + test_done