git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/4] Convert the svn:ignore property

From
Karl Hasselström <kha@treskal.com>
Date
Feb 26, 2006, 05:11 UTC
Message-ID
<20060226051129.24860.25274.stgit@backpacker.hemma.treskal.com>
In-Reply-To
<20060226050335.24860.95155.stgit@backpacker.hemma.treskal.com>

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>
---
 Documentation/git-svnimport.txt |    8 +++++
 git-svnimport.perl              |   60 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 64 insertions(+), 4 deletions(-)
diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt
index b5c7721..c95ff84 100644
--- a/Documentation/git-svnimport.txt
+++ b/Documentation/git-svnimport.txt
@@ -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 
 	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
diff --git a/git-svnimport.perl b/git-svnimport.perl
index 6603b96..0dd9fab 100755
--- a/git-svnimport.perl
+++ b/git-svnimport.perl
@@ -29,19 +29,21 @@ die "Need SVN:Core 1.2.1 or better" if $
 $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";
Previous: Karl HasselströmNext: Karl Hasselström
Message 4 of 12 in “some git-svnimport improvements”
  1. 0/4 some git-svnimport improvementsKarl Hasselström, Feb 26, 2006
  2. 1/4 Mention -r in usage summaryKarl Hasselström, Feb 26, 2006
  3. 2/4 Convert executable flagKarl Hasselström, Feb 26, 2006
  4. 3/4 Convert the svn:ignore propertyKarl Hasselström, Feb 26, 2006
  5. 4/4 Read author names and emails from a fileKarl Hasselström, Feb 26, 2006
  6. Andreas EricssonFeb 26, 2006
  7. Junio C HamanoFeb 27, 2006
  8. Karl HasselströmFeb 27, 2006
  9. 1/2 Let git-svnimport's author file use same syntax as git-cvsimport'sKarl Hasselström, Feb 27, 2006
  10. Jon LoeligerMar 1, 2006
  11. Karl HasselströmMar 2, 2006
  12. 2/2 Save username -> Full Name <email@addr.es> map fileKarl Hasselström, Feb 27, 2006

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.