37
37
from bzrlib.plugins.svn.logwalker import lazy_dict
38
38
from bzrlib.plugins.svn.mapping import parse_revision_id
39
39
from bzrlib.plugins.svn.repository import SvnRepositoryFormat, SvnRepository
40
from bzrlib.plugins.svn.transport import _url_escape_uri
41
from bzrlib.plugins.svn.versionedfiles import SvnTexts
42
44
def _revision_id_to_svk_feature(revid):
130
132
def __init__(self, repository, branch, parents, config, timestamp,
131
133
timezone, committer, revprops, revision_id, old_inv=None,
132
134
push_metadata=True,
135
graph=None, texts=None):
134
136
"""Instantiate a new SvnCommitBuilder.
136
138
:param repository: SvnRepository to commit to.
151
153
config, timestamp, timezone, committer, revprops, revision_id)
152
154
self.branch = branch
153
155
self.push_metadata = push_metadata
156
self._text_parents = {}
155
159
# Gather information about revision on top of which the commit is
226
230
txdelta = file_editor.apply_textdelta()
227
231
digest = send_stream(StringIO(contents), txdelta)
228
232
if 'validate' in debug.debug_flags:
229
from fetch import md5_strings
233
from bzrlib.plugins.svn.fetch import md5_strings
230
234
assert digest == md5_strings(contents)
232
236
def _dir_process(self, path, file_id, dir_editor):
240
244
# Loop over entries of file_id in self.old_inv
241
245
# remove if they no longer exist with the same name
243
if file_id in self.old_inv:
247
if (file_id in self.old_inv and
248
self.old_inv[file_id].kind == 'directory'):
244
249
for child_name in self.old_inv[file_id].children:
245
250
child_ie = self.old_inv.get_child(file_id, child_name)
281
286
child_editor = dir_editor.add_file(
282
287
full_new_child_path,
283
urlutils.join(self.repository.transport.svn_url, self.base_path, self.old_inv.id2path(child_ie.file_id)),
288
_url_escape_uri(urlutils.join(self.repository.transport.svn_url, self.base_path, self.old_inv.id2path(child_ie.file_id))),
284
289
self.base_revnum)
286
291
# open if they existed at the same location
347
352
self.mutter('copy dir %r -> %r', old_child_path, new_child_path)
348
353
child_editor = dir_editor.add_directory(
349
354
urlutils.join(self.branch.get_branch_path(), new_child_path),
350
urlutils.join(self.repository.transport.svn_url, self.base_path, old_child_path), self.base_revnum)
355
_url_escape_uri(urlutils.join(self.repository.transport.svn_url, self.base_path, old_child_path)), self.base_revnum)
352
357
# open if they existed at the same location and
353
358
# the directory was touched
409
414
self.mutter("removing branch dir %r", name)
410
415
ret[-1].delete_entry(name, -1)
411
416
if base_path is not None:
412
base_url = urlutils.join(self.repository.transport.svn_url, base_path)
417
base_url = _url_escape_uri(urlutils.join(self.repository.transport.svn_url, base_path))
415
420
self.mutter("adding branch dir %r", name)
431
436
old_inv.id2path(child_ie.file_id) != new_child_path or
432
437
old_inv[child_ie.file_id].revision != child_ie.revision or
433
438
old_inv[child_ie.file_id].parent_id != child_ie.parent_id):
434
ret.append((child_ie.file_id, new_child_path, child_ie.revision))
439
ret.append((child_ie.file_id, new_child_path, child_ie.revision, self._text_parents[child_ie.file_id]))
436
441
if (child_ie.kind == 'directory' and
437
442
child_ie.file_id in self.visit_dirs):
438
443
ret += _dir_process_file_id(old_inv, new_inv, new_child_path, child_ie.file_id)
443
447
text_parents = {}
447
451
if (self.old_inv.root is None or
448
452
self.new_inventory.root.file_id != self.old_inv.root.file_id):
449
changes.append((self.new_inventory.root.file_id, "", self.new_inventory.root.revision))
453
changes.append((self.new_inventory.root.file_id, "", self.new_inventory.root.revision, self._text_parents[self.new_inventory.root.file_id]))
451
455
changes += _dir_process_file_id(self.old_inv, self.new_inventory, "", self.new_inventory.root.file_id)
453
for id, path, revid in changes:
457
for id, path, revid, parents in changes:
454
458
fileids[path] = id
455
459
if revid is not None and revid != self.base_revid and revid != self._new_revision_id:
456
text_parents[path] = revid
457
return (fileids, text_parents)
460
text_revisions[path] = revid
461
if ((id not in self.old_inv and parents != []) or
462
(id in self.old_inv and parents != [self.base_revid])):
463
text_parents[path] = parents
464
return (fileids, text_revisions, text_parents)
459
466
def commit(self, message):
460
467
"""Finish the commit.
474
481
repository_latest_revnum = self.repository.get_latest_revnum()
475
482
lock = self.repository.transport.lock_write(".")
477
(fileids, text_parents) = self._determine_texts_identity()
484
(fileids, text_revisions, text_parents) = self._determine_texts_identity()
486
self.base_mapping.export_text_revisions(self.supports_custom_revprops, text_revisions, self._svn_revprops, self._svnprops)
479
487
self.base_mapping.export_text_parents(self.supports_custom_revprops, text_parents,
480
488
self._svn_revprops, self._svnprops)
481
489
self.base_mapping.export_fileid_map(self.supports_custom_revprops, fileids,
587
595
accessed when the entry has a revision of None - that is when
588
596
it is a candidate to commit.
598
if self._texts is None:
599
self._text_parents[ie.file_id] = [parent_inv[ie.file_id].revision for parent_inv in parent_invs if ie.file_id in parent_inv]
600
elif isinstance(self._texts, SvnTexts):
601
overridden_parents = self._texts._get_parent(ie.file_id, ie.revision)
602
if overridden_parents is None:
603
if ie.file_id in self.old_inv:
604
self._text_parents[ie.file_id] = [self.old_inv[ie.file_id].revision]
606
self._text_parents[ie.file_id] = []
608
self._text_parents[ie.file_id] = overridden_parents
610
key = (ie.file_id, ie.revision)
611
parent_map = self._texts.get_parent_map([key])
612
if ie.parent_id is None and (not key in parent_map or parent_map[key] is None):
613
# non-rich-root repositories don't have a text for the root
614
self._text_parents[ie.file_id] = self.parents
616
assert parent_map[key] is not None, "No parents found for %r" % (key,)
617
self._text_parents[ie.file_id] = [r[1] for r in parent_map[key]]
590
619
self.new_inventory.add(ie)
591
620
assert (ie.file_id not in self.old_inv or
592
621
self.old_inv[ie.file_id].revision is not None)
605
634
while fid is not None and fid not in self.visit_dirs:
606
635
self.visit_dirs.add(fid)
607
636
fid = self.new_inventory[fid].parent_id
608
return self._get_delta(ie, self.old_inv, self.new_inventory.id2path(ie.file_id)), version_recorded
637
return self._get_delta(ie, self.old_inv, self.new_inventory.id2path(ie.file_id)), version_recorded, None
611
640
def replay_delta(builder, old_tree, new_tree):
743
772
rev.timezone, rev.committer, rev.properties,
744
773
revision_id, base_tree.inventory,
745
774
push_metadata=push_metadata,
776
texts=source_repo.texts)
748
778
replay_delta(builder, base_tree, old_tree)