git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Eric Wong <normalperson@yhbt.net>
To: junkio@cox.net
Cc: git@vger.kernel.org
Subject: [PATCH 1/9] contrib/git-svn: add -b/--branch switch for branch detection
Date: Fri, 3 Mar 2006 01:20:07 -0800	[thread overview]
Message-ID: <11413776074148-git-send-email-normalperson@yhbt.net> (raw)
In-Reply-To: <11413776074123-git-send-email-normalperson@yhbt.net>

I've said I don't like branches in Subversion, and I still don't.
This is a bit more flexible, though, as the argument for -b is any
arbitrary git head/tag reference.

This makes some things easier:
 * Importing git history into a brand new SVN branch.
 * Tracking multiple SVN branches via GIT_SVN_ID, even from multiple
   repositories.
 * Adding tags from SVN (still need to use GIT_SVN_ID, though).
 * Even merge tracking is supported, if and only the heads end up with
   100% equivalent tree objects.  This is more stricter but more robust
   and foolproof than parsing commit messages, imho.

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

 contrib/git-svn/git-svn.perl |   38 ++++++++++++++++++++++++++++++++++++++
 contrib/git-svn/git-svn.txt  |   17 ++++++++++++++++-
 2 files changed, 54 insertions(+), 1 deletions(-)

536109ffa6682954d3b2bb6a184978fd185ecaa4
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index 0e092c5..1f9a470 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -35,6 +35,7 @@ my $sha1 = qr/[a-f\d]{40}/;
 my $sha1_short = qr/[a-f\d]{6,40}/;
 my ($_revision,$_stdin,$_no_ignore_ext,$_no_stop_copy,$_help,$_rmdir,$_edit,
 	$_find_copies_harder, $_l, $_version, $_upgrade);
+my (@_branch_from, %tree_map);
 
 GetOptions(	'revision|r=s' => \$_revision,
 		'no-ignore-externals' => \$_no_ignore_ext,
@@ -43,6 +44,7 @@ GetOptions(	'revision|r=s' => \$_revisio
 		'rmdir' => \$_rmdir,
 		'upgrade' => \$_upgrade,
 		'help|H|h' => \$_help,
+		'branch|b=s' => \@_branch_from,
 		'find-copies-harder' => \$_find_copies_harder,
 		'l=i' => \$_l,
 		'version|V' => \$_version,
@@ -831,6 +833,8 @@ sub git_commit {
 	my $uuid = $info->{'Repository UUID'};
 	defined $uuid or croak "Unable to get Repository UUID\n";
 
+	map_tree_joins() if (@_branch_from && !%tree_map);
+
 	# commit parents can be conditionally bound to a particular
 	# svn revision via: "svn_revno=commit_sha1", filter them out here:
 	my @exec_parents;
@@ -852,6 +856,17 @@ sub git_commit {
 		git_addremove();
 		chomp(my $tree = `git-write-tree`);
 		croak if $?;
+		if (exists $tree_map{$tree}) {
+			my %seen_parent = map { $_ => 1 } @exec_parents;
+			foreach (@{$tree_map{$tree}}) {
+				# MAXPARENT is defined to 16 in commit-tree.c:
+				if ($seen_parent{$_} || @exec_parents > 16) {
+					next;
+				}
+				push @exec_parents, $_;
+				$seen_parent{$_} = 1;
+			}
+		}
 		my $msg_fh = IO::File->new_tmpfile or croak $!;
 		print $msg_fh $log_msg->{msg}, "\ngit-svn-id: ",
 					"$SVN_URL\@$log_msg->{revision}",
@@ -975,6 +990,29 @@ sub check_upgrade_needed {
 	}
 }
 
+# fills %tree_map with a reverse mapping of trees to commits.  Useful
+# for finding parents to commit on.
+sub map_tree_joins {
+	foreach my $br (@_branch_from) {
+		my $pid = open my $pipe, '-|';
+		defined $pid or croak $!;
+		if ($pid == 0) {
+			exec(qw(git-rev-list --pretty=raw), $br) or croak $?;
+		}
+		while (<$pipe>) {
+			if (/^commit ($sha1)$/o) {
+				my $commit = $1;
+				my ($tree) = (<$pipe> =~ /^tree ($sha1)$/o);
+				unless (defined $tree) {
+					die "Failed to parse commit $commit\n";
+				}
+				push @{$tree_map{$tree}}, $commit;
+			}
+		}
+		close $pipe or croak $?;
+	}
+}
+
 __END__
 
 Data structures:
diff --git a/contrib/git-svn/git-svn.txt b/contrib/git-svn/git-svn.txt
index 4102deb..7306048 100644
--- a/contrib/git-svn/git-svn.txt
+++ b/contrib/git-svn/git-svn.txt
@@ -27,7 +27,7 @@ For importing svn, git-svnimport is pote
 operating on repositories organized under the recommended
 trunk/branch/tags structure, and should be faster, too.
 
-git-svn completely ignores the very limited view of branching that
+git-svn mostly ignores the very limited view of branching that
 Subversion has.  This allows git-svn to be much easier to use,
 especially on repositories that are not organized in a manner that
 git-svnimport is designed for.
@@ -116,6 +116,21 @@ OPTIONS
 	They are both passed directly to git-diff-tree see
 	git-diff-tree(1) for more information.
 
+-b<refname>::
+--branch <refname>::
+	Used with 'fetch' or 'commit'.
+
+	This can be used to join arbitrary git branches to remotes/git-svn
+	on new commits where the tree object is equivalent.
+
+	When used with different GIT_SVN_ID values, tags and branches in
+	SVN can be tracked this way, as can some merges where the heads
+	end up having completely equivalent content.  This can even be
+	used to track branches across multiple SVN _repositories_.
+
+	This option may be specified multiple times, once for each
+	branch.
+
 COMPATIBILITY OPTIONS
 ---------------------
 --no-ignore-externals::
-- 
1.2.3.g4676

  reply	other threads:[~2006-03-03  9:20 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-03-03  9:20 contrib/git-svn: polishing up Eric Wong
2006-03-03  9:20 ` Eric Wong [this message]
2006-03-03  9:20   ` [PATCH 2/9] contrib/git-svn: several small bug fixes and changes Eric Wong
2006-03-03  9:20     ` [PATCH 3/9] contrib/git-svn: strip 'git-svn-id:' when commiting to SVN Eric Wong
2006-03-03  9:20       ` [PATCH 4/9] contrib/git-svn: allow --authors-file to be specified Eric Wong
2006-03-03  9:20         ` [PATCH 5/9] contrib/git-svn: cleanup option parsing Eric Wong
2006-03-03  9:20           ` [PATCH 6/9] contrib/git-svn: create a more recent master if one does not exist Eric Wong
2006-03-03  9:20             ` [PATCH 7/9] contrib/git-svn: avoid re-reading the repository uuid, it never changes Eric Wong
2006-03-03  9:20               ` [PATCH 8/9] contrib/git-svn: add --id/-i=$GIT_SVN_ID command-line switch Eric Wong
2006-03-03  9:20                 ` [PATCH 9/9] contrib/git-svn: better documenting of CLI switches Eric Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=11413776074148-git-send-email-normalperson@yhbt.net \
    --to=normalperson@yhbt.net \
    --cc=git@vger.kernel.org \
    --cc=junkio@cox.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).