svnimport: Convert the svn:ignore property
authorKarl Hasselström <kha@treskal.com>
Sun, 26 Feb 2006 05:11:29 +0000 (06:11 +0100)
committerJunio C Hamano <junkio@cox.net>
Mon, 27 Feb 2006 05:34:42 +0000 (21:34 -0800)
Put the value of the svn:ignore property in a regular file when
converting a Subversion repository to GIT. The Subversion and GIT
ignore syntaxes are similar enough that it often just works to set the
filename to .gitignore and do nothing else.

Signed-off-by: Karl Hasselström <kha@treskal.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
Documentation/git-svnimport.txt
git-svnimport.perl

index b5c7721..c95ff84 100644 (file)
@@ -13,7 +13,7 @@ SYNOPSIS
                [ -C <GIT_repository> ] [ -i ] [ -u ] [-l limit_rev]
                [ -b branch_subdir ] [ -T trunk_subdir ] [ -t tag_subdir ]
                [ -s start_chg ] [ -m ] [ -r ] [ -M regex ]
-               <SVN_repository_URL> [ <path> ]
+               [ -I <ignorefile_name> ] <SVN_repository_URL> [ <path> ]
 
 
 DESCRIPTION
@@ -65,6 +65,12 @@ When importing incrementally, you might need to edit the .git/svn2git file.
        Prepend 'rX: ' to commit messages, where X is the imported
        subversion revision.
 
+-I <ignorefile_name>::
+       Import the svn:ignore directory property to files with this
+       name in each directory. (The Subversion and GIT ignore
+       syntaxes are similar enough that using the Subversion patterns
+       directly with "-I .gitignore" will almost always just work.)
+
 -m::
        Attempt to detect merges based on the commit message. This option
        will enable default regexes that try to capture the name source
index 6603b96..0dd9fab 100755 (executable)
@@ -29,19 +29,21 @@ die "Need SVN: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_r,$opt_s,$opt_l,$opt_d,$opt_D);
+our($opt_h,$opt_o,$opt_v,$opt_u,$opt_C,$opt_i,$opt_m,$opt_M,$opt_t,$opt_T,
+    $opt_b,$opt_r,$opt_I,$opt_s,$opt_l,$opt_d,$opt_D);
 
 sub usage() {
        print STDERR <<END;
 Usage: ${\basename $0}     # fetch/update GIT from SVN
        [-o branch-for-HEAD] [-h] [-v] [-l max_rev]
        [-C GIT_repository] [-t tagname] [-T trunkname] [-b branchname]
-       [-d|-D] [-i] [-u] [-r] [-s start_chg] [-m] [-M regex] [SVN_URL]
+       [-d|-D] [-i] [-u] [-r] [-I ignorefilename] [-s start_chg]
+       [-m] [-M regex] [SVN_URL]
 END
        exit(1);
 }
 
-getopts("b:C:dDhil:mM:o:rs:t:T:uv") or usage();
+getopts("b:C:dDhiI:l:mM:o:rs:t:T:uv") or usage();
 usage if $opt_h;
 
 my $tag_name = $opt_t || "tags";
@@ -130,6 +132,24 @@ sub file {
        return ($name, $mode);
 }
 
+sub ignore {
+       my($self,$path,$rev) = @_;
+
+       print "... $rev $path ...\n" if $opt_v;
+       my (undef,undef,$properties)
+           = $self->{'svn'}->get_dir($path,$rev,undef);
+       if (exists $properties->{'svn:ignore'}) {
+               my ($fh, $name) = tempfile('gitsvn.XXXXXX',
+                                          DIR => File::Spec->tmpdir(),
+                                          UNLINK => 1);
+               print $fh $properties->{'svn:ignore'};
+               close($fh);
+               return $name;
+       } else {
+               return undef;
+       }
+}
+
 package main;
 use URI;
 
@@ -341,6 +361,34 @@ sub get_file($$$) {
        return [$mode, $sha, $path];
 }
 
+sub get_ignore($$$$$) {
+       my($new,$old,$rev,$branch,$path) = @_;
+
+       return unless $opt_I;
+       my $svnpath = revert_split_path($branch,$path);
+       my $name = $svn->ignore("$svnpath",$rev);
+       if ($path eq '/') {
+               $path = $opt_I;
+       } else {
+               $path = File::Spec->catfile($path,$opt_I);
+       }
+       if (defined $name) {
+               my $pid = open(my $F, '-|');
+               die $! unless defined $pid;
+               if (!$pid) {
+                       exec("git-hash-object", "-w", $name)
+                           or die "Cannot create object: $!\n";
+               }
+               my $sha = <$F>;
+               chomp $sha;
+               close $F;
+               unlink $name;
+               push(@$new,['0644',$sha,$path]);
+       } else {
+               push(@$old,$path);
+       }
+}
+
 sub split_path($$) {
        my($rev,$path) = @_;
        my $branch;
@@ -546,6 +594,9 @@ sub commit {
                                                my $opath = $action->[3];
                                                print STDERR "$revision: $branch: could not fetch '$opath'\n";
                                        }
+                               } elsif ($node_kind eq $SVN::Node::dir) {
+                                       get_ignore(\@new, \@old, $revision,
+                                                  $branch,$path);
                                }
                        } elsif ($action->[0] eq "D") {
                                push(@old,$path);
@@ -554,6 +605,9 @@ sub commit {
                                if ($node_kind eq $SVN::Node::file) {
                                        my $f = get_file($revision,$branch,$path);
                                        push(@new,$f) if $f;
+                               } elsif ($node_kind eq $SVN::Node::dir) {
+                                       get_ignore(\@new, \@old, $revision,
+                                                  $branch,$path);
                                }
                        } else {
                                die "$revision: unknown action '".$action->[0]."' for $path\n";