comparison hg_delta_editor.py @ 59:430af23bef4a

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.
author Augie Fackler <durin42@gmail.com>
date Tue, 04 Nov 2008 16:38:16 -0600
parents 987e44afa71e
children e319c9168910
comparison
equal deleted inserted replaced
58:a8b9c7e7c2ac 59:430af23bef4a
244 def update_branch_tag_map_for_rev(self, revision): 244 def update_branch_tag_map_for_rev(self, revision):
245 paths = revision.paths 245 paths = revision.paths
246 added_branches = {} 246 added_branches = {}
247 added_tags = {} 247 added_tags = {}
248 tags_to_delete = set() 248 tags_to_delete = set()
249 branches_to_delete = set()
249 for p in paths: 250 for p in paths:
250 if self._is_path_valid(p): 251 if self._is_path_valid(p):
251 fi, br = self._path_and_branch_for_path(p) 252 fi, br = self._path_and_branch_for_path(p)
252 if fi == '' and br not in self.branches: 253 if fi == '' and br not in self.branches:
253 # TODO handle creating a branch from a tag
254 src_p = paths[p].copyfrom_path 254 src_p = paths[p].copyfrom_path
255 src_rev = paths[p].copyfrom_rev 255 src_rev = paths[p].copyfrom_rev
256 src_tag = self._is_path_tag(src_p) 256 src_tag = self._is_path_tag(src_p)
257 257
258 if not src_p or not (self._is_path_valid(src_p) or src_tag): 258 if not ((src_p and self._is_path_valid(src_p)) or
259 (src_tag and src_tag in self.tags)):
259 # we'll imply you're a branch off of trunk 260 # we'll imply you're a branch off of trunk
260 # if you have no path, but if you do, it must be valid 261 # if you have no path, but if you do, it must be valid
261 # or else we assume trunk as well 262 # or else we assume trunk as well
262 src_branch = None 263 src_branch = None
263 src_rev = revision.revnum 264 src_rev = revision.revnum
270 else: 271 else:
271 # Not from a tag, and from a valid repo path 272 # Not from a tag, and from a valid repo path
272 (src_p, 273 (src_p,
273 src_branch) = self._path_and_branch_for_path(src_p) 274 src_branch) = self._path_and_branch_for_path(src_p)
274 added_branches[br] = src_branch, src_rev, revision.revnum 275 added_branches[br] = src_branch, src_rev, revision.revnum
276 elif fi == '' and br in self.branches:
277 br2 = br or 'default'
278 if br2 not in self.repo.branchtags() and paths[p].action == 'D':
279 branches_to_delete.add(br)
275 elif br in added_branches: 280 elif br in added_branches:
276 if paths[p].copyfrom_rev > added_branches[br][1]: 281 if paths[p].copyfrom_rev > added_branches[br][1]:
277 x,y,z = added_branches[br] 282 x,y,z = added_branches[br]
278 added_branches[br] = x, paths[p].copyfrom_rev, z 283 added_branches[br] = x, paths[p].copyfrom_rev, z
279 else: 284 else:
300 elif (paths[p].action == 'D' and p.endswith(t_name) 305 elif (paths[p].action == 'D' and p.endswith(t_name)
301 and t_name in self.tags): 306 and t_name in self.tags):
302 tags_to_delete.add(t_name) 307 tags_to_delete.add(t_name)
303 for t in tags_to_delete: 308 for t in tags_to_delete:
304 del self.tags[t] 309 del self.tags[t]
310 for br in branches_to_delete:
311 del self.branches[br]
305 self.tags.update(added_tags) 312 self.tags.update(added_tags)
306 self.branches.update(added_branches) 313 self.branches.update(added_branches)
307 self._save_metadata() 314 self._save_metadata()
308 315
309 def commit_current_delta(self): 316 def commit_current_delta(self):
337 files = dict(files) 344 files = dict(files)
338 345
339 parents = (self.get_parent_revision(rev.revnum, branch), 346 parents = (self.get_parent_revision(rev.revnum, branch),
340 revlog.nullid) 347 revlog.nullid)
341 if branch is not None: 348 if branch is not None:
342 if branch not in self.branches: 349 if branch not in self.branches and branch not in self.repo.branchtags():
343 continue 350 continue
344 if parents == (revlog.nullid, revlog.nullid):
345 assert False, ('a non-trunk branch should probably have'
346 ' parents figured out by this point')
347 extra['branch'] = branch 351 extra['branch'] = branch
348 parent_ctx = self.repo.changectx(parents[0]) 352 parent_ctx = self.repo.changectx(parents[0])
349 def filectxfn(repo, memctx, path): 353 def filectxfn(repo, memctx, path):
350 copied = None 354 copied = None
351 current_file = files[path] 355 current_file = files[path]
352 if current_file in self.deleted_files: 356 if current_file in self.deleted_files:
353 raise IOError() 357 raise IOError()
354 # TODO(augie) tag copies from files 358 # TODO(augie) tag copies from files
355 flags = parent_ctx.flags(path) 359 flags = parent_ctx.flags(path)
356 is_exec = self.current_files_exec.get(current_file, 360 is_exec = self.current_files_exec.get(current_file,
357 'x' in flags) 361 'x' in flags)
358 is_link = self.current_files_symlink.get(current_file, 362 is_link = self.current_files_symlink.get(current_file,
359 'l' in flags) 363 'l' in flags)
360 if current_file in self.current_files: 364 if current_file in self.current_files:
361 data = self.current_files[current_file] 365 data = self.current_files[current_file]
362 if is_link: 366 if is_link:
363 assert data.startswith('link ') 367 assert data.startswith('link ')
495 copyfrom_revision, file_pool=None): 499 copyfrom_revision, file_pool=None):
496 self.current_file = 'foobaz' 500 self.current_file = 'foobaz'
497 self.base_revision = None 501 self.base_revision = None
498 if path in self.deleted_files: 502 if path in self.deleted_files:
499 del self.deleted_files[path] 503 del self.deleted_files[path]
500 if (self._is_path_valid(path) and 504 if (self._is_path_valid(path) and
501 self._path_and_branch_for_path(path)[0]): 505 self._path_and_branch_for_path(path)[0]):
502 self.current_file = path 506 self.current_file = path
503 self.should_edit_most_recent_plaintext = False 507 self.should_edit_most_recent_plaintext = False
504 if copyfrom_path: 508 if copyfrom_path:
505 self.ui.status('A+ %s\n' % path) 509 self.ui.status('A+ %s\n' % path)
531 self.commit_branches_empty[branch] = True 535 self.commit_branches_empty[branch] = True
532 else: 536 else:
533 self.commit_branches_empty[branch] = False 537 self.commit_branches_empty[branch] = False
534 if not self._is_path_valid(path) or not copyfrom_path: 538 if not self._is_path_valid(path) or not copyfrom_path:
535 return 539 return
536 if copyfrom_path and not self._is_path_valid(copyfrom_path): 540 if copyfrom_path:
537 self.missing_plaintexts.add('%s/' % path) 541 tag = self._is_path_tag(copyfrom_path)
538 return 542 if tag not in self.tags:
539 543 tag = None
540 cp_f, br_from = self._path_and_branch_for_path(copyfrom_path) 544 if not self._is_path_valid(copyfrom_path) and not tag:
541 new_hash = self.get_parent_revision(copyfrom_revision + 1, br_from) 545 self.missing_plaintexts.add('%s/' % path)
546 return
547
548 if tag:
549 source_branch, source_rev = self.tags[tag]
550 cp_f = ''
551 else:
552 source_rev = copyfrom_revision
553 cp_f, source_branch = self._path_and_branch_for_path(copyfrom_path)
554 new_hash = self.get_parent_revision(source_rev + 1,
555 source_branch)
542 if new_hash == node.nullid: 556 if new_hash == node.nullid:
543 self.missing_plaintexts.add('%s/' % path) 557 self.missing_plaintexts.add('%s/' % path)
544 return 558 return
545 cp_f_ctx = self.repo.changectx(new_hash) 559 cp_f_ctx = self.repo.changectx(new_hash)
546 if cp_f != '/' and cp_f != '': 560 if cp_f != '/' and cp_f != '':