Performance fix for branches-from-tags in real replay, which is tied up with

changes that fix problems when trunk is not the oldest branch. Also includes
fixes for copying from a tag that we chose not to create (eg tagging a vendor
branch) and includes tests for all of those things.
This commit is contained in:
Augie Fackler 2008-11-04 16:38:16 -06:00
parent 189fd9396a
commit 8c7063dc0f
5 changed files with 387 additions and 17 deletions

View File

@ -435,7 +435,8 @@ def stupid_svn_server_pull_rev(ui, svn, hg_editor, r):
files_touched.add(d)
if delete_all_files:
for p in hg_editor.repo[parent_ha].manifest().iterkeys():
files_touched.add(p)
if p:
files_touched.add(p)
if not used_diff:
for p in reduce(operator.add, [[os.path.join(x[0], y) for y in x[2]]
for x in
@ -447,7 +448,8 @@ def stupid_svn_server_pull_rev(ui, svn, hg_editor, r):
files_touched.add(p_real)
for p in hg_editor.repo[parent_ha].manifest().iterkeys():
# TODO this might not be a required step.
files_touched.add(p)
if p:
files_touched.add(p)
date = r.date.replace('T', ' ').replace('Z', '').split('.')[0]
date += ' -0000'
def filectxfn(repo, memctx, path):
@ -465,6 +467,8 @@ def stupid_svn_server_pull_rev(ui, svn, hg_editor, r):
extra = {}
if b:
extra['branch'] = b
if '' in files_touched:
files_touched.remove('')
if parent_ha != node.nullid or files_touched:
# TODO(augie) remove this debug code? Or maybe it's sane to have it.
for f in files_touched:

View File

@ -246,16 +246,17 @@ class HgChangeReceiver(delta.Editor):
added_branches = {}
added_tags = {}
tags_to_delete = set()
branches_to_delete = set()
for p in paths:
if self._is_path_valid(p):
fi, br = self._path_and_branch_for_path(p)
if fi == '' and br not in self.branches:
# TODO handle creating a branch from a tag
src_p = paths[p].copyfrom_path
src_rev = paths[p].copyfrom_rev
src_tag = self._is_path_tag(src_p)
if not src_p or not (self._is_path_valid(src_p) or src_tag):
if not ((src_p and self._is_path_valid(src_p)) or
(src_tag and src_tag in self.tags)):
# we'll imply you're a branch off of trunk
# if you have no path, but if you do, it must be valid
# or else we assume trunk as well
@ -272,6 +273,10 @@ class HgChangeReceiver(delta.Editor):
(src_p,
src_branch) = self._path_and_branch_for_path(src_p)
added_branches[br] = src_branch, src_rev, revision.revnum
elif fi == '' and br in self.branches:
br2 = br or 'default'
if br2 not in self.repo.branchtags() and paths[p].action == 'D':
branches_to_delete.add(br)
elif br in added_branches:
if paths[p].copyfrom_rev > added_branches[br][1]:
x,y,z = added_branches[br]
@ -302,6 +307,8 @@ class HgChangeReceiver(delta.Editor):
tags_to_delete.add(t_name)
for t in tags_to_delete:
del self.tags[t]
for br in branches_to_delete:
del self.branches[br]
self.tags.update(added_tags)
self.branches.update(added_branches)
self._save_metadata()
@ -339,11 +346,8 @@ class HgChangeReceiver(delta.Editor):
parents = (self.get_parent_revision(rev.revnum, branch),
revlog.nullid)
if branch is not None:
if branch not in self.branches:
if branch not in self.branches and branch not in self.repo.branchtags():
continue
if parents == (revlog.nullid, revlog.nullid):
assert False, ('a non-trunk branch should probably have'
' parents figured out by this point')
extra['branch'] = branch
parent_ctx = self.repo.changectx(parents[0])
def filectxfn(repo, memctx, path):
@ -353,9 +357,9 @@ class HgChangeReceiver(delta.Editor):
raise IOError()
# TODO(augie) tag copies from files
flags = parent_ctx.flags(path)
is_exec = self.current_files_exec.get(current_file,
is_exec = self.current_files_exec.get(current_file,
'x' in flags)
is_link = self.current_files_symlink.get(current_file,
is_link = self.current_files_symlink.get(current_file,
'l' in flags)
if current_file in self.current_files:
data = self.current_files[current_file]
@ -497,7 +501,7 @@ class HgChangeReceiver(delta.Editor):
self.base_revision = None
if path in self.deleted_files:
del self.deleted_files[path]
if (self._is_path_valid(path) and
if (self._is_path_valid(path) and
self._path_and_branch_for_path(path)[0]):
self.current_file = path
self.should_edit_most_recent_plaintext = False
@ -533,12 +537,22 @@ class HgChangeReceiver(delta.Editor):
self.commit_branches_empty[branch] = False
if not self._is_path_valid(path) or not copyfrom_path:
return
if copyfrom_path and not self._is_path_valid(copyfrom_path):
self.missing_plaintexts.add('%s/' % path)
return
if copyfrom_path:
tag = self._is_path_tag(copyfrom_path)
if tag not in self.tags:
tag = None
if not self._is_path_valid(copyfrom_path) and not tag:
self.missing_plaintexts.add('%s/' % path)
return
cp_f, br_from = self._path_and_branch_for_path(copyfrom_path)
new_hash = self.get_parent_revision(copyfrom_revision + 1, br_from)
if tag:
source_branch, source_rev = self.tags[tag]
cp_f = ''
else:
source_rev = copyfrom_revision
cp_f, source_branch = self._path_and_branch_for_path(copyfrom_path)
new_hash = self.get_parent_revision(source_rev + 1,
source_branch)
if new_hash == node.nullid:
self.missing_plaintexts.add('%s/' % path)
return

View File

@ -337,7 +337,7 @@ class SubversionRepo(object):
except core.SubversionException, e:
# can I depend on this number being constant?
if (e.message == "Server doesn't support the replay command"
or e.apr_err == 170003
or e.apr_err == 170003
or e.message == 'The requested report is unknown.'
or e.apr_err == 200007):
raise SubversionRepoCanNotReplay, ('This Subversion server '

View File

@ -0,0 +1,325 @@
SVN-fs-dump-format-version: 2
UUID: 0e935f28-8caa-dd11-b3dc-00105ae0362c
Revision-number: 0
Prop-content-length: 56
Content-length: 56
K 8
svn:date
V 27
2008-11-04T16:18:04.048615Z
PROPS-END
Revision-number: 1
Prop-content-length: 102
Content-length: 102
K 7
svn:log
V 3
btt
K 10
svn:author
V 5
durin
K 8
svn:date
V 27
2008-11-04T16:18:29.661251Z
PROPS-END
Node-path: branches
Node-kind: dir
Node-action: add
Prop-content-length: 10
Content-length: 10
PROPS-END
Node-path: tags
Node-kind: dir
Node-action: add
Prop-content-length: 10
Content-length: 10
PROPS-END
Node-path: trunk
Node-kind: dir
Node-action: add
Prop-content-length: 10
Content-length: 10
PROPS-END
Revision-number: 2
Prop-content-length: 119
Content-length: 119
K 7
svn:log
V 19
Add the vendor dir.
K 10
svn:author
V 5
durin
K 8
svn:date
V 27
2008-11-04T16:19:16.816658Z
PROPS-END
Node-path: vendor
Node-kind: dir
Node-action: add
Prop-content-length: 10
Content-length: 10
PROPS-END
Node-path: vendor/foobaz
Node-kind: dir
Node-action: add
Prop-content-length: 10
Content-length: 10
PROPS-END
Node-path: vendor/foobaz/alpha
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 6
Text-content-md5: 9f9f90dbe3e5ee1218c86b8839db1995
Content-length: 16
PROPS-END
alpha
Node-path: vendor/foobaz/beta
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 5
Text-content-md5: f0cf2a92516045024a0c99147b28f05b
Content-length: 15
PROPS-END
beta
Node-path: vendor/foobaz/delta
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 6
Text-content-md5: d2840cc81bc032bd1141b56687d0f93c
Content-length: 16
PROPS-END
delta
Node-path: vendor/foobaz/gamma
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 6
Text-content-md5: 303febb9068384eca46b5b6516843b35
Content-length: 16
PROPS-END
gamma
Revision-number: 3
Prop-content-length: 139
Content-length: 139
K 7
svn:log
V 39
Adding oldest data, which is not trunk.
K 10
svn:author
V 5
durin
K 8
svn:date
V 27
2008-11-04T16:22:06.704260Z
PROPS-END
Node-path: branches/oldest
Node-kind: dir
Node-action: add
Prop-content-length: 10
Content-length: 10
PROPS-END
Node-path: branches/oldest/five
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 5
Text-content-md5: 014835e36358e38c7f7897d6571e4529
Content-length: 15
PROPS-END
five
Node-path: branches/oldest/four
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 5
Text-content-md5: 75ffdb827341e578959bfcabde3789d8
Content-length: 15
PROPS-END
four
Node-path: branches/oldest/one
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 4
Text-content-md5: 5bbf5a52328e7439ae6e719dfe712200
Content-length: 14
PROPS-END
one
Node-path: branches/oldest/three
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 6
Text-content-md5: febe6995bad457991331348f7b9c85fa
Content-length: 16
PROPS-END
three
Node-path: branches/oldest/two
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 4
Text-content-md5: c193497a1a06b2c72230e6146ff47080
Content-length: 14
PROPS-END
two
Revision-number: 4
Prop-content-length: 105
Content-length: 105
K 7
svn:log
V 6
delete
K 10
svn:author
V 5
durin
K 8
svn:date
V 27
2008-11-04T16:22:49.936769Z
PROPS-END
Node-path: trunk
Node-action: delete
Revision-number: 5
Prop-content-length: 124
Content-length: 124
K 7
svn:log
V 24
create trunk from branch
K 10
svn:author
V 5
durin
K 8
svn:date
V 27
2008-11-04T16:23:00.562964Z
PROPS-END
Node-path: tags/foobaz_1
Node-kind: dir
Node-action: add
Node-copyfrom-rev: 2
Node-copyfrom-path: vendor/foobaz
Prop-content-length: 34
Content-length: 34
K 13
svn:mergeinfo
V 0
PROPS-END
Node-path: trunk
Node-kind: dir
Node-action: add
Node-copyfrom-rev: 3
Node-copyfrom-path: branches/oldest
Prop-content-length: 34
Content-length: 34
K 13
svn:mergeinfo
V 0
PROPS-END
Revision-number: 6
Prop-content-length: 146
Content-length: 146
K 7
svn:log
V 46
copy data from a vendor branch tag into trunk.
K 10
svn:author
V 5
durin
K 8
svn:date
V 27
2008-11-04T16:23:32.980956Z
PROPS-END
Node-path: trunk/foobaz
Node-kind: dir
Node-action: add
Node-copyfrom-rev: 5
Node-copyfrom-path: tags/foobaz_1

View File

@ -109,6 +109,18 @@ class TestBasicRepoLayout(unittest.TestCase):
'file_renamed_in_from_outside_btt.svndump')
self.assert_('LICENSE.file' in repo['tip'])
def test_oldest_not_trunk_and_tag_vendor_branch(self):
repo = self._load_fixture_and_fetch(
'tagged_vendor_and_oldest_not_trunk.svndump')
self.assertEqual(node.hex(repo['oldest'].node()),
'd73002bcdeffe389a8df81ee43303d36e79e8ca4')
self.assertEqual(repo['tip'].parents()[0].parents()[0],
repo['oldest'])
self.assertEqual(node.hex(repo['tip'].node()),
'9cf09e6ff7fa938188c3bcc9dd87abd7842c080c')
#'1316ef606dda89354ee8c4df725e6264177b5129')
class TestStupidPull(unittest.TestCase):
def setUp(self):
self.oldwd = os.getcwd()
@ -140,6 +152,21 @@ class TestStupidPull(unittest.TestCase):
self.assertEqual(repo['tip'], repo['default'])
self.assertEqual(len(repo.heads()), 2)
def test_oldest_not_trunk_and_tag_vendor_branch(self):
test_util.load_svndump_fixture(self.repo_path,
'tagged_vendor_and_oldest_not_trunk.svndump')
fetch_command.fetch_revisions(ui.ui(),
svn_url='file://%s' % self.repo_path,
hg_repo_path=self.wc_path,
stupid=True)
repo = hg.repository(ui.ui(), self.wc_path)
self.assertEqual(node.hex(repo['oldest'].node()),
'd73002bcdeffe389a8df81ee43303d36e79e8ca4')
self.assertEqual(repo['tip'].parents()[0].parents()[0],
repo['oldest'])
self.assertEqual(node.hex(repo['tip'].node()),
'9cf09e6ff7fa938188c3bcc9dd87abd7842c080c')
def suite():
all = [unittest.TestLoader().loadTestsFromTestCase(TestBasicRepoLayout),
unittest.TestLoader().loadTestsFromTestCase(TestStupidPull),