Merge branch 'aw/cvs'
authorJunio C Hamano <gitster@pobox.com>
Wed, 13 Jun 2007 04:04:52 +0000 (21:04 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 13 Jun 2007 04:04:52 +0000 (21:04 -0700)
* aw/cvs:
cvsimport: add <remote>/HEAD reference in separate remotes more
cvsimport: update documentation to include separate remotes option
cvsimport: add support for new style remote layout

1  2 
Documentation/git-cvsimport.txt
git-cvsimport.perl
index 3985e0164b3f320258a5f6b2699a9145a30e5e43,4e5f1c6ba3986adf2e15b7c528cec2622c4c42f4..fdd7ec7edd8d655a1f660db7eca90ee8cfa9ffc2
@@@ -13,7 -13,7 +13,7 @@@ SYNOPSI
              [-A <author-conv-file>] [-p <options-for-cvsps>] [-P <file>]
              [-C <git_repository>] [-z <fuzz>] [-i] [-k] [-u] [-s <subst>]
              [-a] [-m] [-M <regex>] [-S <regex>] [-L <commitlimit>]
-             [<CVS_module>]
+             [-r <remote>] [<CVS_module>]
  
  
  DESCRIPTION
@@@ -25,10 -25,12 +25,12 @@@ Splitting the CVS log into patch sets i
  At least version 2.1 is required.
  
  You should *never* do any work of your own on the branches that are
- created by git-cvsimport. The initial import will create and populate a
+ created by git-cvsimport.  By default initial import will create and populate a
  "master" branch from the CVS repository's main branch which you're free
  to work with; after that, you need to 'git merge' incremental imports, or
- any CVS branches, yourself.
+ any CVS branches, yourself.  It is advisable to specify a named remote via
+ -r to separate and protect the incoming branches.
  
  OPTIONS
  -------
@@@ -37,7 -39,7 +39,7 @@@
  
  -d <CVSROOT>::
        The root of the CVS archive. May be local (a simple path) or remote;
 -      currently, only the :local:, :ext: and :pserver: access methods 
 +      currently, only the :local:, :ext: and :pserver: access methods
        are supported. If not given, git-cvsimport will try to read it
        from `CVS/Root`. If no such file exists, it checks for the
        `CVSROOT` environment variable.
          The git repository to import to.  If the directory doesn't
          exist, it will be created.  Default is the current directory.
  
+ -r <remote>::
+       The git remote to import this CVS repository into.
+       Moves all CVS branches into remotes/<remote>/<branch>
+       akin to the git-clone --use-separate-remote option.
  -o <branch-for-HEAD>::
-       The 'HEAD' branch from CVS is imported to the 'origin' branch within
-       the git repository, as 'HEAD' already has a special meaning for git.
-       Use this option if you want to import into a different branch.
+       When no remote is specified (via -r) the 'HEAD' branch
+       from CVS is imported to the 'origin' branch within the git
+       repository, as 'HEAD' already has a special meaning for git.
+       When a remote is specified the 'HEAD' branch is named
+       remotes/<remote>/master mirroring git-clone behaviour.
+       Use this option if you want to import into a different
+       branch.
  +
  Use '-o master' for continuing an import that was initially done by
  the old cvs2git tool.
@@@ -67,7 -78,7 +78,7 @@@
  -k::
        Kill keywords: will extract files with '-kk' from the CVS archive
        to avoid noisy changesets. Highly recommended, but off by default
 -      to preserve compatibility with early imported trees. 
 +      to preserve compatibility with early imported trees.
  
  -u::
        Convert underscores in tag and branch names to dots.
@@@ -89,15 -100,15 +100,15 @@@ If you need to pass multiple options, s
        Instead of calling cvsps, read the provided cvsps output file. Useful
        for debugging or when cvsps is being handled outside cvsimport.
  
 --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 <regex>::
        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. 
 +      You must escape forward slashes.
  
  -S <regex>::
        Skip paths matching the regex.
@@@ -156,3 -167,4 +167,3 @@@ Documentation by Matthias Urlichs <smur
  GIT
  ---
  Part of the gitlink:git[7] suite
 -
diff --combined git-cvsimport.perl
index 75d65d414eca55970cb6ad3d3fe89c3a73f3c741,598b9c8da9f0e8eecac3d9ec13a1431b0466854e..433b7fd3246cf1ab29f3d74befbf6db5adfc8d2c
@@@ -29,7 -29,7 +29,7 @@@ use IPC::Open2
  $SIG{'PIPE'}="IGNORE";
  $ENV{'TZ'}="UTC";
  
- our ($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);
+ our ($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);
  my (%conv_author_name, %conv_author_email);
  
  sub usage(;$) {
@@@ -40,7 -40,7 +40,7 @@@ Usage: ${\basename $0}     # fetch/upda
         [-o branch-for-HEAD] [-h] [-v] [-d CVSROOT] [-A author-conv-file]
         [-p opts-for-cvsps] [-P file] [-C GIT_repository] [-z fuzz] [-i] [-k]
         [-u] [-s subst] [-a] [-m] [-M regex] [-S regex] [-L commitlimit]
-        [CVS_module]
+        [-r remote] [CVS_module]
  END
        exit(1);
  }
@@@ -114,7 -114,7 +114,7 @@@ sub read_repo_config 
      }
  }
  
- my $opts = "haivmkuo:d:p:C:z:s:M:P:A:S:L:";
+ my $opts = "haivmkuo:d:p:r:C:z:s:M:P:A:S:L:";
  read_repo_config($opts);
  getopts($opts) or usage();
  usage if $opt_h;
@@@ -134,18 -134,26 +134,26 @@@ if ($opt_d) 
  } else {
        usage("CVSROOT needs to be set");
  }
- $opt_o ||= "origin";
  $opt_s ||= "-";
  $opt_a ||= 0;
  
  my $git_tree = $opt_C;
  $git_tree ||= ".";
  
+ my $remote;
+ if (defined $opt_r) {
+       $remote = 'refs/remotes/' . $opt_r;
+       $opt_o ||= "master";
+ } else {
+       $opt_o ||= "origin";
+       $remote = 'refs/heads';
+ }
  my $cvs_tree;
  if ($#ARGV == 0) {
        $cvs_tree = $ARGV[0];
  } elsif (-f 'CVS/Repository') {
 -      open my $f, '<', 'CVS/Repository' or 
 +      open my $f, '<', 'CVS/Repository' or
            die 'Failed to open CVS/Repository';
        $cvs_tree = <$f>;
        chomp $cvs_tree;
@@@ -434,7 -442,7 +442,7 @@@ sub file 
        my ($self,$fn,$rev) = @_;
        my $res;
  
 -      my ($fh, $name) = tempfile('gitcvs.XXXXXX', 
 +      my ($fh, $name) = tempfile('gitcvs.XXXXXX',
                    DIR => File::Spec->tmpdir(), UNLINK => 1);
  
        $self->_file($fn,$rev) and $res = $self->_line($fh);
@@@ -520,9 -528,9 +528,9 @@@ sub is_sha1 
  
  sub get_headref ($$) {
      my $name    = shift;
 -    my $git_dir = shift; 
 -    
 +    my $git_dir = shift;
 +
-     my $f = "$git_dir/refs/heads/$name";
+     my $f = "$git_dir/$remote/$name";
      if (open(my $fh, $f)) {
            chomp(my $r = <$fh>);
            is_sha1($r) or die "Cannot get head id for $name ($r): $!";
@@@ -573,12 -581,12 +581,12 @@@ unless (-d $git_dir) 
  
        # Get the last import timestamps
        my $fmt = '($ref, $author) = (%(refname), %(author));';
-       open(H, "git-for-each-ref --perl --format='$fmt' refs/heads |") or
+       open(H, "git-for-each-ref --perl --format='$fmt' $remote |") or
                die "Cannot run git-for-each-ref: $!\n";
        while (defined(my $entry = <H>)) {
                my ($ref, $author);
                eval($entry) || die "cannot eval refs list: $@";
-               my ($head) = ($ref =~ m|^refs/heads/(.*)|);
+               my ($head) = ($ref =~ m|^$remote/(.*)|);
                $author =~ /^.*\s(\d+)\s[-+]\d{4}$/;
                $branch_date{$head} = $1;
        }
@@@ -692,8 -700,8 +700,8 @@@ sub commit 
        if ($branch eq $opt_o && !$index{branch} && !get_headref($branch, $git_dir)) {
            # looks like an initial commit
            # use the index primed by git-init
 -          $ENV{GIT_INDEX_FILE} = '.git/index';
 -          $index{$branch} = '.git/index';
 +          $ENV{GIT_INDEX_FILE} = "$git_dir/index";
 +          $index{$branch} = "$git_dir/index";
        } else {
            # use an index per branch to speed up
            # imports of projects with many branches
                $index{$branch} = tmpnam();
                $ENV{GIT_INDEX_FILE} = $index{$branch};
                if ($ancestor) {
-                   system("git-read-tree", $ancestor);
+                   system("git-read-tree", "$remote/$ancestor");
                } else {
-                   system("git-read-tree", $branch);
+                   system("git-read-tree", "$remote/$branch");
                }
                die "read-tree failed: $?\n" if $?;
            }
        waitpid($pid,0);
        die "Error running git-commit-tree: $?\n" if $?;
  
-       system("git-update-ref refs/heads/$branch $cid") == 0
+       system("git-update-ref $remote/$branch $cid") == 0
                or die "Cannot write branch $branch for update: $!\n";
  
        if ($tag) {
                $xtag =~ s/\s+\*\*.*$//; # Remove stuff like ** INVALID ** and ** FUNKY **
                $xtag =~ tr/_/\./ if ( $opt_u );
                $xtag =~ s/[\/]/$opt_s/g;
 -              
 -              my $pid = open2($in, $out, 'git-mktag');
 -              print $out "object $cid\n".
 -                  "type commit\n".
 -                  "tag $xtag\n".
 -                  "tagger $author_name <$author_email>\n"
 -                  or die "Cannot create tag object $xtag: $!\n";
 -              close($out)
 -                  or die "Cannot create tag object $xtag: $!\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 $xtag: $!\n";
 -              }
 -              
 -
 -              open(C,">$git_dir/refs/tags/$xtag")
 +
 +              system('git-tag', $xtag, $cid) == 0
                        or die "Cannot create tag $xtag: $!\n";
 -              print C "$tagobj\n"
 -                      or die "Cannot write tag $xtag: $!\n";
 -              close(C)
 -                      or die "Cannot write tag $xtag: $!\n";
  
                print "Created tag '$xtag' on '$branch'\n" if $opt_v;
        }
@@@ -861,12 -891,12 +869,12 @@@ while (<CVS>) 
                                print STDERR "Branch $branch erroneously stems from itself -- changed ancestor to $opt_o\n";
                                $ancestor = $opt_o;
                        }
-                       if (-f "$git_dir/refs/heads/$branch") {
+                       if (-f "$git_dir/$remote/$branch") {
                                print STDERR "Branch $branch already exists!\n";
                                $state=11;
                                next;
                        }
-                       unless (open(H,"$git_dir/refs/heads/$ancestor")) {
+                       unless (open(H,"$git_dir/$remote/$ancestor")) {
                                print STDERR "Branch $ancestor does not exist!\n";
                                $ignorebranch{$branch} = 1;
                                $state=11;
                        }
                        chomp(my $id = <H>);
                        close(H);
-                       unless (open(H,"> $git_dir/refs/heads/$branch")) {
+                       unless (open(H,"> $git_dir/$remote/$branch")) {
                                print STDERR "Could not create branch $branch: $!\n";
                                $ignorebranch{$branch} = 1;
                                $state=11;
@@@ -962,7 -992,7 +970,7 @@@ if ($line =~ /^(\d+) objects, (\d+) kil
  }
  
  foreach my $git_index (values %index) {
 -    if ($git_index ne '.git/index') {
 +    if ($git_index ne "$git_dir/index") {
        unlink($git_index);
      }
  }
@@@ -988,14 -1018,16 +996,16 @@@ if ($orig_branch) 
                die "Fast-forward update failed: $?\n" if $?;
        }
        else {
-               system(qw(git-merge cvsimport HEAD), "refs/heads/$opt_o");
+               system(qw(git-merge cvsimport HEAD), "$remote/$opt_o");
                die "Could not merge $opt_o into the current branch.\n" if $?;
        }
  } else {
        $orig_branch = "master";
        print "DONE; creating $orig_branch branch\n" if $opt_v;
-       system("git-update-ref", "refs/heads/master", "refs/heads/$opt_o")
+       system("git-update-ref", "refs/heads/master", "$remote/$opt_o")
                unless -f "$git_dir/refs/heads/master";
+       system("git-symbolic-ref", "$remote/HEAD", "$remote/$opt_o")
+               if ($opt_r && $opt_o ne 'HEAD');
        system('git-update-ref', 'HEAD', "$orig_branch");
        unless ($opt_i) {
                system('git checkout');