@matheusbsbs / matheus-bagliano / commits / 553589f782
Fork 0

git-svn: Make following parents atomic

find_parent_branch generates branch@rev type branches when one has to look back through SVN history to properly get the history for a branch copied from somewhere not already being tracked by git-svn. If in the process of fetching this history, git-svn is interrupted, then when one fetches again, it will use whatever was last fetched as the parent commit and fail to fetch any more history which it didn't get to before being terminated. This is especially troubling in that different git-svn copies of the same SVN repository can end up with different commit sha1s, incorrectly showing the history as divergent and precluding easy collaboration using git push and fetch. To fix this, when we initialise the Git::SVN object $gs to search for and perhaps fetch history, we check if there are any commits in SVN in the range between the current revision $gs is at, and the top revision for which we were asked to fill history. If there are commits we're missing in that range, we continue the fetch from the current revision to the top, properly getting all history before using it as the parent for the branch we're trying to create. Signed-off-by: Deskin Miller <deskinm@umich.edu> Acked-by: Eric Wong <normalperson@yhbt.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Deskin Miller committed Dec 8, 2008 at 08:31 UTC 553589f7823db530d03b49db42251fbea624041f
2 files changed +54 -4
git-svn.perl
+12 -4
@@ -2318,12 +2318,20 @@ sub find_parent_branch {
2318 $gs = Git::SVN->init($u, $p, $repo_id, $ref_id, 1);
2319 }
2320 my ($r0, $parent) = $gs->find_rev_before($r, 1);
2321 - if (!defined $r0 || !defined $parent) {
2322 - my ($base, $head) = parse_revision_argument(0, $r);
2323 - if ($base <= $r) {
2321 + {
2322 + my ($base, $head);
2323 + if (!defined $r0 || !defined $parent) {
2324 + ($base, $head) = parse_revision_argument(0, $r);
2325 + } else {
2326 + if ($r0 < $r) {
2327 + $gs->ra->get_log([$gs->{path}], $r0 + 1, $r, 1,
2328 + 0, 1, sub { $base = $_[1] - 1 });
2329 + }
2330 + }
2331 + if (defined $base && $base <= $r) {
2332 $gs->fetch($base, $r);
2333 }
2326 - ($r0, $parent) = $gs->last_rev_commit;
2334 + ($r0, $parent) = $gs->find_rev_before($r, 1);
2335 }
2336 if (defined $r0 && defined $parent) {
2337 print STDERR "Found branch parent: ($self->{ref_id}) $parent\n";
t/t9104-git-svn-follow-parent.sh
+42
@@ -149,6 +149,48 @@ test_expect_success "track initial change if it was only made to parent" '
149 "`git rev-parse r9270-d~1`"
150 '
151
152 +test_expect_success "follow-parent is atomic" '
153 + (
154 + cd wc &&
155 + svn up &&
156 + svn mkdir stunk &&
157 + echo "trunk stunk" > stunk/readme &&
158 + svn add stunk/readme &&
159 + svn ci -m "trunk stunk" &&
160 + echo "stunk like junk" >> stunk/readme &&
161 + svn ci -m "really stunk" &&
162 + echo "stink stank stunk" >> stunk/readme &&
163 + svn ci -m "even the grinch agrees"
164 + ) &&
165 + svn copy -m "stunk flunked" "$svnrepo"/stunk "$svnrepo"/flunk &&
166 + { svn cp -m "early stunk flunked too" \
167 + "$svnrepo"/stunk@17 "$svnrepo"/flunked ||
168 + svn cp -m "early stunk flunked too" \
169 + -r17 "$svnrepo"/stunk "$svnrepo"/flunked; } &&
170 + git svn init --minimize-url -i stunk "$svnrepo"/stunk &&
171 + git svn fetch -i stunk &&
172 + git update-ref refs/remotes/flunk@18 refs/remotes/stunk~2 &&
173 + git update-ref -d refs/remotes/stunk &&
174 + git config --unset svn-remote.svn.fetch stunk &&
175 + mkdir -p "$GIT_DIR"/svn/flunk@18 &&
176 + rev_map=$(cd "$GIT_DIR"/svn/stunk && ls .rev_map*) &&
177 + dd if="$GIT_DIR"/svn/stunk/$rev_map \
178 + of="$GIT_DIR"/svn/flunk@18/$rev_map bs=24 count=1 &&
179 + rm -rf "$GIT_DIR"/svn/stunk &&
180 + git svn init --minimize-url -i flunk "$svnrepo"/flunk &&
181 + git svn fetch -i flunk &&
182 + git svn init --minimize-url -i stunk "$svnrepo"/stunk &&
183 + git svn fetch -i stunk &&
184 + git svn init --minimize-url -i flunked "$svnrepo"/flunked &&
185 + git svn fetch -i flunked
186 + test "`git rev-parse --verify refs/remotes/flunk@18`" \
187 + = "`git rev-parse --verify refs/remotes/stunk`" &&
188 + test "`git rev-parse --verify refs/remotes/flunk~1`" \
189 + = "`git rev-parse --verify refs/remotes/stunk`" &&
190 + test "`git rev-parse --verify refs/remotes/flunked~1`" \
191 + = "`git rev-parse --verify refs/remotes/stunk~1`"
192 + '
193 +
194 test_expect_success "track multi-parent paths" '
195 svn cp -m "resurrect /glob" "$svnrepo"/r9270 "$svnrepo"/glob &&
196 git-svn multi-fetch &&