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

Re: [PATCH] Allow multiple tag and branch directories in git-svnimport

From
Stefan Sperling <stsp@elego.de>
Date
Aug 21, 2007, 17:38 UTC
Message-ID
<20070821173838.GC1721@jack.stsp.lan>
In-Reply-To
<20070821170858.GA1721@jack.stsp.lan>
On Tue, Aug 21, 2007 at 07:08:58PM +0200, Stefan Sperling wrote:
> +my @tag_dirs = defined $opt_t ? split /:/,$opt_t : "tags";
      ^                                                ^^^^^
> +my @branch_dirs = defined $opt_b ? split /:/,$opt_b : "branches";
      ^                                                  ^^^^^^^^^^

Ouch, just noticed it's a bad idea to try to initialise an array with a scalar. Sorry :-/

Updated diff:
diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt
index e97d15e..2cfc407 100644
--- a/Documentation/git-svnimport.txt
+++ b/Documentation/git-svnimport.txt
@@ -12,11 +12,11 @@ SYNOPSIS
 [verse]
 'git-svnimport' [ -o <branch-for-HEAD> ] [ -h ] [ -v ] [ -d | -D ]
 		[ -C <GIT_repository> ] [ -i ] [ -u ] [-l limit_rev]
-		[ -b branch_subdir ] [ -T trunk_subdir ] [ -t tag_subdir ]
-		[ -s start_chg ] [ -m ] [ -r ] [ -M regex ]
-		[ -I <ignorefile_name> ] [ -A <author_file> ]
-		[ -R <repack_each_revs>] [ -P <path_from_trunk> ]
-		<SVN_repository_URL> [ <path> ]
+		[ -b branch_subdir[:branch_subdir:...] ] [ -T trunk_subdir ]
+		[ -t tag_subdir[:tag_subdir:...] ] [ -s start_chg ] [ -m ]
+		[ -r ] [ -M regex ] [ -I <ignorefile_name> ]
+		[ -A <author_file> ] [ -R <repack_each_revs>]
+		[ -P <path_from_trunk> ] <SVN_repository_URL> [ <path> ]
 
 
 DESCRIPTION
@@ -26,11 +26,6 @@ repository, or incrementally import into an existing one.
 
 SVN access is done by the SVN::Perl module.
 
-git-svnimport assumes that SVN repositories are organized into one
-"trunk" directory where the main development happens, "branches/FOO"
-directories for branches, and "/tags/FOO" directories for tags.
-Other subdirectories are ignored.
-
 git-svnimport creates a file ".git/svn2git", which is required for
 incremental SVN imports.
 
@@ -53,11 +48,13 @@ When importing incrementally, you might need to edit the .git/svn2git file.
 -T <trunk_subdir>::
 	Name the SVN trunk. Default "trunk".
 
--t <tag_subdir>::
-	Name the SVN subdirectory for tags. Default "tags".
+-t <tag_subdir[:tag_subdir:..]>::
+	Colon-seperated list of names of subdirectories containing tags.
+	Default "tags".
 
--b <branch_subdir>::
-	Name the SVN subdirectory for branches. Default "branches".
+-b <branch_subdir[:branch_subdir:...]>::
+	Colon-seperated list of names of subdirectories containing branches.
+	Default "branches".
 
 -o <branch-for-HEAD>::
 	The 'trunk' branch from SVN is imported to the 'origin' branch within
diff --git a/git-svnimport.perl b/git-svnimport.perl
index fc9ea71..96f0926 100755
--- a/git-svnimport.perl
+++ b/git-svnimport.perl
@@ -38,9 +38,10 @@ sub usage() {
 	print STDERR <<END;
 Usage: ${\basename $0}     # fetch/update GIT from SVN
        [-o branch-for-HEAD] [-h] [-v] [-l max_rev] [-R repack_each_revs]
-       [-C GIT_repository] [-t tagname] [-T trunkname] [-b branchname]
-       [-d|-D] [-i] [-u] [-r] [-I ignorefilename] [-s start_chg]
-       [-m] [-M regex] [-A author_file] [-S] [-F] [-P project_name] [SVN_URL]
+       [-C GIT_repository] [-t tag_subdir[:tag_subdir:...]] [-T trunk_subdir]
+       [-b branch_subdir[:branch_subdir:...]] [-d|-D] [-i] [-u] [-r]
+       [-I ignorefilename] [-s start_chg] [-m] [-M regex]
+       [-A author_file] [-S] [-F] [-P project_name] [SVN_URL]
 END
 	exit(1);
 }
@@ -48,9 +49,9 @@ END
 getopts("A:b:C:dDFhiI:l:mM:o:rs:t:T:SP:R:uv") or usage();
 usage if $opt_h;
 
-my $tag_name = $opt_t || "tags";
-my $trunk_name = defined $opt_T ? $opt_T : "trunk";
-my $branch_name = $opt_b || "branches";
+my @tag_dirs = defined $opt_t ? split /:/,$opt_t : ("tags");
+my $trunk_dir = defined $opt_T ? $opt_T : "trunk";
+my @branch_dirs = defined $opt_b ? split /:/,$opt_b : ("branches");
 my $project_name = $opt_P || "";
 $project_name = "/" . $project_name if ($project_name);
 my $repack_after = $opt_R || 1000;
@@ -68,14 +69,18 @@ my $svn_dir = $ARGV[1];
 
 our @mergerx = ();
 if ($opt_m) {
-	my $branch_esc = quotemeta ($branch_name);
-	my $trunk_esc  = quotemeta ($trunk_name);
-	@mergerx =
-	(
-		qr!\b(?:merg(?:ed?|ing))\b.*?\b((?:(?<=$branch_esc/)[\w\.\-]+)|(?:$trunk_esc))\b!i,
-		qr!\b(?:from|of)\W+((?:(?<=$branch_esc/)[\w\.\-]+)|(?:$trunk_esc))\b!i,
-		qr!\b(?:from|of)\W+(?:the )?([\w\.\-]+)[-\s]branch\b!i
-	);
+	my @branch_escs;
+	foreach (@branch_dirs) { push @branch_escs, quotemeta ($_); }
+	my $trunk_esc  = quotemeta ($trunk_dir);
+
+	foreach my $branch_esc (@branch_escs) {
+		push (@mergerx,
+		(
+			qr!\b(?:merg(?:ed?|ing))\b.*?\b((?:(?<=$branch_esc/)[\w\.\-]+)|(?:$trunk_esc))\b!i,
+			qr!\b(?:from|of)\W+((?:(?<=$branch_esc/)[\w\.\-]+)|(?:$trunk_esc))\b!i,
+			qr!\b(?:from|of)\W+(?:the )?([\w\.\-]+)[-\s]branch\b!i
+		));
+	}
 }
 if ($opt_M) {
 	unshift (@mergerx, qr/$opt_M/);
@@ -452,29 +457,39 @@ sub project_path($$)
 
 sub split_path($$) {
 	my($rev,$path) = @_;
-	my $branch;
+	my $dir; # tag or branch dir
+
+	OUTER: foreach my $tag_dir (@tag_dirs) {
+		foreach my $branch_dir (@branch_dirs) {
+			if ($path =~ s#^/\Q$tag_dir\E/([^/]+)/?##) {
+				$dir = "/$1";
+			} elsif ($path =~ s#^/\Q$trunk_dir\E/?##) {
+				$dir = "/";
+			} elsif ($path =~ s#^/\Q$branch_dir\E/([^/]+)/?##) {
+				$dir = $1;
+			}
+			last OUTER if $dir;
+		}
+	}
 
-	if($path =~ s#^/\Q$tag_name\E/([^/]+)/?##) {
-		$branch = "/$1";
-	} elsif($path =~ s#^/\Q$trunk_name\E/?##) {
-		$branch = "/";
-	} elsif($path =~ s#^/\Q$branch_name\E/([^/]+)/?##) {
-		$branch = $1;
-	} else {
-		my %no_error = (
-			"/" => 1,
-			"/$tag_name" => 1,
-			"/$branch_name" => 1
-		);
-		print STDERR "$rev: Unrecognized path: $path\n" unless (defined $no_error{$path});
-		return ()
+	if (! $dir) {
+		my %no_error = ( "/" => 1, "/tags" => 1, "/branches" => 1 );
+		foreach (@tag_dirs) {
+			$no_error{"/$_"} = 1;
+		}
+		foreach (@branch_dirs) {
+			$no_error{"/$_"} = 1;
+		}
+		print STDERR "$rev: Could not determine tag or branch ",
+			"directory for path '$path'\n",
+			unless (defined $no_error{$path});
 	}
 	if ($path eq "") {
 		$path = "/";
 	} elsif ($project_name) {
 		$path = project_path($path, $project_name);
 	}
-	return ($branch,$path);
+	return ($dir,$path);
 }
 
 sub branch_rev($$) {
@@ -874,9 +889,32 @@ sub commit {
 
 		$dest =~ tr/_/\./ if $opt_u;
 
-		system('git-tag', $dest, $cid) == 0
-			or die "Cannot create tag $dest: $!\n";
-
+		# Since we support multiple directories that host tags we
+		# must support repositories that contain the same tag name
+		# in different tag directories for whatever reason,
+		# e.g. tags/jim/1.0-rc3 and tags/huck/1.0-rc3
+		#
+		# Also, because in Subversion a given tag directory could
+		# exist in revision A, be deleted in revision B and later
+		# recreated under the same name in revision C, we
+		# cannot guarantee that a tag is unique simply by
+		# looking at the tag's path.
+		#
+		# So if we fail to create the tag the first time, we try
+		# to create the tag with the same name except with the
+		# revision number of the current commit appended.
+		# Users can rename tags again later after the repository
+		# has been converted if they don't like this.
+		# It's still much better than failing to convert the
+		# repository alltogether.
+		if (system('git-tag', $dest, $cid) != 0) {
+			print STDERR "Could not create tag $dest, ",
+				"trying to create tag $dest-r$revision ",
+				"instead\n";
+			$dest = "$dest-r$revision";
+			system('git-tag', $dest, $cid) == 0
+				or die "Cannot create tag $dest: $? $!\n";
+		}
 		print "Created tag '$dest' on '$branch'\n" if $opt_v;
 	}
 	$branches{$branch}{"LAST"} = $cid;
-- 
Stefan Sperling <stsp@elego.de>                 Software Developer
elego Software Solutions GmbH                            HRB 77719
Gustav-Meyer-Allee 25, Gebaeude 12        Tel:  +49 30 23 45 86 96 
13355 Berlin                              Fax:  +49 30 23 45 86 95
http://www.elego.de                 Geschaeftsfuehrer: Olaf Wagner
Previous: Stefan SperlingNext: Randal L. Schwartz
Message 2 of 4 in “Allow multiple tag and branch directories in git-svnimport”
  1. Allow multiple tag and branch directories in git-svnimportStefan Sperling, Aug 21, 2007
  2. Stefan SperlingAug 21, 2007
  3. Randal L. SchwartzAug 21, 2007
  4. Stefan SperlingAug 22, 2007

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.