From 1142038098810a69e57d88554559e4e6116df177 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 1 Mar 2006 23:10:00 -0800 Subject: [PATCH 1/2] read-tree --aggressive: remove deleted entry from the working tree. When both heads deleted, or our side deleted while the other side did not touch, we did not have to update the working tree. However, we forgot to remove existing working tree file when we did not touch and the other side did. Signed-off-by: Junio C Hamano --- read-tree.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/read-tree.c b/read-tree.c index bb50a800d7..da0fcf035e 100644 --- a/read-tree.c +++ b/read-tree.c @@ -560,9 +560,11 @@ static int threeway_merge(struct cache_entry **stages) */ if ((head_deleted && remote_deleted) || (head_deleted && remote && remote_match) || - (remote_deleted && head && head_match)) + (remote_deleted && head && head_match)) { + if (index) + return deleted_entry(index, index); return 0; - + } /* * Added in both, identically. */ From 2beb3cdd18225be657849790ed845c4d367b760a Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 1 Mar 2006 21:58:31 -0800 Subject: [PATCH 2/2] contrib/git-svn: use refs/remotes/git-svn instead of git-svn-HEAD After reading a lengthy discussion on the list, I've come to the conclusion that creating a 'remotes' directory in refs isn't such a bad idea. You can still branch from it by specifying remotes/git-svn (not needing the leading 'refs/'), and the documentation has been updated to reflect that. The 'git-svn' part of the ref can of course be set to whatever you want by using the GIT_SVN_ID environment variable, as before. I'm using refs/remotes/git-svn, and not going with something like refs/remotes/git-svn/HEAD as it's redundant for Subversion where there's zero distinction between branches and directories. Run git-svn rebuild --upgrade to upgrade your repository to use the new head. git-svn-HEAD must be manually deleted for safety reasons. Side note: if you ever (and I hope you never) want to run git-update-refs on a 'remotes/' ref, make sure you have the 'refs/' prefix as you don't want to be clobbering your 'remotes/' in $GIT_DIR (where remote URLs are stored). Signed-off-by: Eric Wong Signed-off-by: Junio C Hamano --- contrib/git-svn/git-svn.perl | 63 +++++++++++++++++----- contrib/git-svn/git-svn.txt | 18 +++---- contrib/git-svn/t/t0000-contrib-git-svn.sh | 36 ++++++------- 3 files changed, 78 insertions(+), 39 deletions(-) diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl index 0b7416526d..0e092c5d3f 100755 --- a/contrib/git-svn/git-svn.perl +++ b/contrib/git-svn/git-svn.perl @@ -34,13 +34,14 @@ use POSIX qw/strftime/; 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); + $_find_copies_harder, $_l, $_version, $_upgrade); GetOptions( 'revision|r=s' => \$_revision, 'no-ignore-externals' => \$_no_ignore_ext, 'stdin|' => \$_stdin, 'edit|e' => \$_edit, 'rmdir' => \$_rmdir, + 'upgrade' => \$_upgrade, 'help|H|h' => \$_help, 'find-copies-harder' => \$_find_copies_harder, 'l=i' => \$_l, @@ -106,13 +107,18 @@ sub rebuild { $SVN_URL = shift or undef; my $repo_uuid; my $newest_rev = 0; + if ($_upgrade) { + sys('git-update-ref',"refs/remotes/$GIT_SVN","$GIT_SVN-HEAD"); + } else { + check_upgrade_needed(); + } my $pid = open(my $rev_list,'-|'); defined $pid or croak $!; if ($pid == 0) { - exec("git-rev-list","$GIT_SVN-HEAD") or croak $!; + exec("git-rev-list","refs/remotes/$GIT_SVN") or croak $!; } - my $first; + my $latest; while (<$rev_list>) { chomp; my $c = $_; @@ -132,18 +138,20 @@ sub rebuild { "$c, $id\n"; } } + + # if we merged or otherwise started elsewhere, this is + # how we break out of it + next if (defined $repo_uuid && ($uuid ne $repo_uuid)); + next if (defined $SVN_URL && ($url ne $SVN_URL)); + print "r$rev = $c\n"; - unless (defined $first) { + unless (defined $latest) { if (!$SVN_URL && !$url) { croak "SVN repository location required: $url\n"; } $SVN_URL ||= $url; - $repo_uuid = setup_git_svn(); - $first = $rev; - } - if ($uuid ne $repo_uuid) { - croak "Repository UUIDs do not match!\ngot: $uuid\n", - "expected: $repo_uuid\n"; + $repo_uuid ||= setup_git_svn(); + $latest = $rev; } assert_revision_eq_or_unknown($rev, $c); sys('git-update-ref',"$GIT_SVN/revs/$rev",$c); @@ -151,7 +159,7 @@ sub rebuild { } close $rev_list or croak $?; if (!chdir $SVN_WC) { - my @svn_co = ('svn','co',"-r$first"); + my @svn_co = ('svn','co',"-r$latest"); push @svn_co, '--ignore-externals' unless $_no_ignore_ext; sys(@svn_co, $SVN_URL, $SVN_WC); chdir $SVN_WC or croak $!; @@ -168,6 +176,13 @@ sub rebuild { exec('git-write-tree'); } waitpid $pid, 0; + + if ($_upgrade) { + print STDERR <<""; +Keeping deprecated refs/head/$GIT_SVN-HEAD for now. Please remove it +when you have upgraded your tools and habits to use refs/remotes/$GIT_SVN + + } } sub init { @@ -180,6 +195,7 @@ sub init { sub fetch { my (@parents) = @_; + check_upgrade_needed(); $SVN_URL ||= file_to_s("$GIT_DIR/$GIT_SVN/info/url"); my @log_args = -d $SVN_WC ? ($SVN_WC) : ($SVN_URL); unless ($_revision) { @@ -222,6 +238,7 @@ sub fetch { sub commit { my (@commits) = @_; + check_upgrade_needed(); if ($_stdin || !@commits) { print "Reading from stdin...\n"; @commits = (); @@ -863,7 +880,7 @@ sub git_commit { if ($commit !~ /^$sha1$/o) { croak "Failed to commit, invalid sha1: $commit\n"; } - my @update_ref = ('git-update-ref',"refs/heads/$GIT_SVN-HEAD",$commit); + my @update_ref = ('git-update-ref',"refs/remotes/$GIT_SVN",$commit); if (my $primary_parent = shift @exec_parents) { push @update_ref, $primary_parent; } @@ -936,6 +953,28 @@ sub svn_check_ignore_externals { $_no_ignore_ext = 1; } } + +sub check_upgrade_needed { + my $old = eval { + my $pid = open my $child, '-|'; + defined $pid or croak $!; + if ($pid == 0) { + close STDERR; + exec('git-rev-parse',"$GIT_SVN-HEAD") or croak $?; + } + my @ret = (<$child>); + close $child or croak $?; + die $? if $?; # just in case close didn't error out + return wantarray ? @ret : join('',@ret); + }; + return unless $old; + my $head = eval { safe_qx('git-rev-parse',"refs/remotes/$GIT_SVN") }; + if ($@ || !$head) { + print STDERR "Please run: $0 rebuild --upgrade\n"; + exit 1; + } +} + __END__ Data structures: diff --git a/contrib/git-svn/git-svn.txt b/contrib/git-svn/git-svn.txt index b29073997c..4102deb381 100644 --- a/contrib/git-svn/git-svn.txt +++ b/contrib/git-svn/git-svn.txt @@ -41,12 +41,12 @@ init:: fetch:: Fetch unfetched revisions from the SVN_URL we are tracking. - refs/heads/git-svn-HEAD will be updated to the latest revision. + refs/heads/remotes/git-svn will be updated to the latest revision. - Note: You should never attempt to modify the git-svn-HEAD branch - outside of git-svn. Instead, create a branch from git-svn-HEAD + Note: You should never attempt to modify the remotes/git-svn branch + outside of git-svn. Instead, create a branch from remotes/git-svn and work on that branch. Use the 'commit' command (see below) - to write git commits back to git-svn-HEAD. + to write git commits back to remotes/git-svn. commit:: Commit specified commit or tree objects to SVN. This relies on @@ -155,13 +155,13 @@ Tracking and contributing to an Subversion managed-project: # Fetch remote revisions:: git-svn fetch # Create your own branch to hack on:: - git checkout -b my-branch git-svn-HEAD + git checkout -b my-branch remotes/git-svn # Commit only the git commits you want to SVN:: git-svn commit [ ...] # Commit all the git commits from my-branch that don't exist in SVN:: - git-svn commit git-svn-HEAD..my-branch + git-svn commit remotes/git-svn..my-branch # Something is committed to SVN, pull the latest into your branch:: - git-svn fetch && git pull . git-svn-HEAD + git-svn fetch && git pull . remotes/git-svn # Append svn:ignore settings to the default git exclude file: git-svn show-ignore >> .git/info/exclude @@ -184,8 +184,8 @@ SVN repositories via one git repository. Simply set the GIT_SVN_ID environment variable to a name other other than "git-svn" (the default) and git-svn will ignore the contents of the $GIT_DIR/git-svn directory and instead do all of its work in $GIT_DIR/$GIT_SVN_ID for that -invocation. The interface branch will be $GIT_SVN_ID-HEAD, instead of -git-svn-HEAD. Any $GIT_SVN_ID-HEAD branch should never be modified +invocation. The interface branch will be remotes/$GIT_SVN_ID, instead of +remotes/git-svn. Any remotes/$GIT_SVN_ID branch should never be modified by the user outside of git-svn commands. ADDITIONAL FETCH ARGUMENTS diff --git a/contrib/git-svn/t/t0000-contrib-git-svn.sh b/contrib/git-svn/t/t0000-contrib-git-svn.sh index 181dfe008b..80ad3573db 100644 --- a/contrib/git-svn/t/t0000-contrib-git-svn.sh +++ b/contrib/git-svn/t/t0000-contrib-git-svn.sh @@ -71,14 +71,14 @@ test_expect_success \ name='try a deep --rmdir with a commit' -git checkout -b mybranch git-svn-HEAD +git checkout -b mybranch remotes/git-svn mv dir/a/b/c/d/e/file dir/file cp dir/file file git update-index --add --remove dir/a/b/c/d/e/file dir/file file git commit -m "$name" test_expect_success "$name" \ - "git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch && + "git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch && test -d $SVN_TREE/dir && test ! -d $SVN_TREE/dir/a" @@ -91,13 +91,13 @@ git update-index --add dir/file/file git commit -m "$name" test_expect_code 1 "$name" \ - 'git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch' \ + 'git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch' \ || true name='detect node change from directory to file #1' rm -rf dir $GIT_DIR/index -git checkout -b mybranch2 git-svn-HEAD +git checkout -b mybranch2 remotes/git-svn mv bar/zzz zzz rm -rf bar mv zzz bar @@ -106,13 +106,13 @@ git update-index --add -- bar git commit -m "$name" test_expect_code 1 "$name" \ - 'git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch2' \ + 'git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch2' \ || true name='detect node change from file to directory #2' rm -f $GIT_DIR/index -git checkout -b mybranch3 git-svn-HEAD +git checkout -b mybranch3 remotes/git-svn rm bar/zzz git-update-index --remove bar/zzz mkdir bar/zzz @@ -121,13 +121,13 @@ git-update-index --add bar/zzz/yyy git commit -m "$name" test_expect_code 1 "$name" \ - 'git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch3' \ + 'git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch3' \ || true name='detect node change from directory to file #2' rm -f $GIT_DIR/index -git checkout -b mybranch4 git-svn-HEAD +git checkout -b mybranch4 remotes/git-svn rm -rf dir git update-index --remove -- dir/file touch dir @@ -136,19 +136,19 @@ git update-index --add -- dir git commit -m "$name" test_expect_code 1 "$name" \ - 'git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch4' \ + 'git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch4' \ || true name='remove executable bit from a file' rm -f $GIT_DIR/index -git checkout -b mybranch5 git-svn-HEAD +git checkout -b mybranch5 remotes/git-svn chmod -x exec.sh git update-index exec.sh git commit -m "$name" test_expect_success "$name" \ - "git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch5 && + "git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch5 && test ! -x $SVN_TREE/exec.sh" @@ -158,7 +158,7 @@ git update-index exec.sh git commit -m "$name" test_expect_success "$name" \ - "git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch5 && + "git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch5 && test -x $SVN_TREE/exec.sh" @@ -170,7 +170,7 @@ git update-index exec.sh git commit -m "$name" test_expect_success "$name" \ - "git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch5 && + "git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch5 && test -L $SVN_TREE/exec.sh" @@ -182,7 +182,7 @@ git update-index --add bar/zzz exec-2.sh git commit -m "$name" test_expect_success "$name" \ - "git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch5 && + "git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch5 && test -x $SVN_TREE/bar/zzz && test -L $SVN_TREE/exec-2.sh" @@ -196,7 +196,7 @@ git update-index exec-2.sh git commit -m "$name" test_expect_success "$name" \ - "git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch5 && + "git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch5 && test -f $SVN_TREE/exec-2.sh && test ! -L $SVN_TREE/exec-2.sh && diff -u help $SVN_TREE/exec-2.sh" @@ -207,9 +207,9 @@ name='test fetch functionality (svn => git) with alternate GIT_SVN_ID' GIT_SVN_ID=alt export GIT_SVN_ID test_expect_success "$name" \ - "git-svn init $svnrepo && git-svn fetch -v && - git-rev-list --pretty=raw git-svn-HEAD | grep ^tree | uniq > a && - git-rev-list --pretty=raw alt-HEAD | grep ^tree | uniq > b && + "git-svn init $svnrepo && git-svn fetch && + git-rev-list --pretty=raw remotes/git-svn | grep ^tree | uniq > a && + git-rev-list --pretty=raw remotes/alt | grep ^tree | uniq > b && diff -u a b" test_done