def getcopies(svn, meta, branch, branchpath, r, files, parentctx): """Return a mapping {dest: source} for every file copied into r. """ if parentctx.node() == revlog.nullid: return {} # Extract svn copy information, group them by copy source. # The idea is to duplicate the replay behaviour where copies are # evaluated per copy event (one event for all files in a directory copy, # one event for single file copy). We assume that copy events match # copy sources in revision info. svncopies = {} finder = makecopyfinder(meta, r, branchpath) for f in files: copy = finder(f) if copy: svncopies.setdefault(copy[0], []).append((f, copy[1])) if not svncopies: return {} # check svn copies really make sense in mercurial hgcopies = {} for (sourcepath, sourcectx), copies in svncopies.iteritems(): for k, v in copies: if not util.issamefile(sourcectx, parentctx, v): continue hgcopies.update({k: v}) return hgcopies
def add_file(self, path, parent_baton=None, copyfrom_path=None, copyfrom_revision=None, file_pool=None): self._checkparentdir(parent_baton) # Use existing=False because we use the fact a file is being # added here to populate the branchmap which is used with # existing=True. fpath, branch = self.meta.split_branch_path(path, existing=False)[:2] if not fpath or fpath not in self.meta.filemap: return None if path in self._svncopies: raise EditingError('trying to replace copied file %s' % path) if path in self._deleted: self._deleted.remove(path) if (branch not in self.meta.branches and not self.meta.get_path_tag(self.meta.remotename(branch))): # we know this branch will exist now, because it has at # least one file. Rock. self.meta.branches[branch] = None, 0, self.current.rev.revnum if not copyfrom_path: self.ui.note('A %s\n' % path) self.current.added.add(path) return self._openfile(path, '', False, False, None, create=True) self.ui.note('A+ %s\n' % path) (from_file, from_branch) = self.meta.split_branch_path(copyfrom_path)[:2] if not from_file: self.addmissing(path) return None # Use exact=True because during replacements ('R' action) we select # replacing branch as parent, but svn delta editor provides delta # agains replaced branch. ha = self.meta.get_parent_revision(copyfrom_revision + 1, from_branch, True) ctx = self._getctx(ha) if from_file not in ctx: self.addmissing(path) return None fctx = ctx.filectx(from_file) flags = fctx.flags() base = fctx.data() if 'l' in flags: base = 'link ' + base self.current.set(path, base, 'x' in flags, 'l' in flags) copypath = None if from_branch == branch: parentid = self.meta.get_parent_revision( self.current.rev.revnum, branch) if parentid != revlog.nullid: parentctx = self._getctx(parentid) if util.issamefile(parentctx, ctx, from_file): copypath = from_file return self._openfile(path, base, 'x' in flags, 'l' in flags, copypath, create=True)
def add_file(self, path, parent_baton=None, copyfrom_path=None, copyfrom_revision=None, file_pool=None): self.current.file = None self.current.base = None if path in self.current.deleted: del self.current.deleted[path] fpath, branch = self.meta.split_branch_path(path, existing=False)[:2] if not fpath: return if (branch not in self.meta.branches and not self.meta.get_path_tag(self.meta.remotename(branch))): # we know this branch will exist now, because it has at least one file. Rock. self.meta.branches[branch] = None, 0, self.current.rev.revnum self.current.file = path if not copyfrom_path: self.ui.note('A %s\n' % path) self.current.set(path, '', False, False) return self.ui.note('A+ %s\n' % path) (from_file, from_branch) = self.meta.split_branch_path(copyfrom_path)[:2] if not from_file: self.current.missing.add(path) return # Use exact=True because during replacements ('R' action) we select # replacing branch as parent, but svn delta editor provides delta # agains replaced branch. ha = self.meta.get_parent_revision(copyfrom_revision + 1, from_branch, True) ctx = self.repo.changectx(ha) if from_file in ctx: fctx = ctx.filectx(from_file) flags = fctx.flags() self.current.set(path, fctx.data(), 'x' in flags, 'l' in flags) if from_branch == branch: parentid = self.meta.get_parent_revision( self.current.rev.revnum, branch) if parentid != revlog.nullid: parentctx = self.repo.changectx(parentid) if util.issamefile(parentctx, ctx, from_file): self.current.copies[path] = from_file
def add_directory(self, path, parent_baton, copyfrom_path, copyfrom_revision, dir_pool=None): self._checkparentdir(parent_baton) baton = self._opendir(path) br_path, branch = self.meta.split_branch_path(path)[:2] if br_path is not None: if not copyfrom_path and not br_path: # This handles the case where a branch root is # replaced without copy info. It will show up as a # deletion and then an add. self.meta.closebranches.discard(branch) self.current.emptybranches[branch] = True else: self.current.emptybranches[branch] = False if br_path is None or not copyfrom_path: return baton if self.meta.get_path_tag(path): del self.current.emptybranches[branch] return baton tag = self.meta.get_path_tag(copyfrom_path) if tag not in self.meta.tags: tag = None if not self.meta.is_path_valid(copyfrom_path, existing=False): # The source path only exists at copyfrom_revision, use # existing=False to guess a possible branch location and # test it against the filemap. The actual path and # revision will be resolved below if necessary. self.addmissing(path, isdir=True) return baton if tag: changeid = self.meta.tags[tag] source_rev, source_branch = self.meta.get_source_rev(changeid)[:2] frompath = '' else: source_rev = copyfrom_revision frompath, source_branch = self.meta.split_branch_path(copyfrom_path)[:2] new_hash = self.meta.get_parent_revision(source_rev + 1, source_branch, True) if frompath is None or new_hash == node.nullid: self.addmissing(path, isdir=True) return baton fromctx = self._getctx(new_hash) if frompath != '/' and frompath != '': frompath = '%s/' % frompath else: frompath = '' copyfromparent = False if frompath == '' and br_path == '': pnode = self.meta.get_parent_revision( self.current.rev.revnum, branch) if pnode == new_hash: # Data parent is topological parent and relative paths # are the same, not need to do anything but restore # files marked as deleted. copyfromparent = True # Get the parent which would have been used for this branch # without the replace action. oldpnode = self.meta.get_parent_revision( self.current.rev.revnum, branch, exact=True) if (oldpnode != revlog.nullid and util.isancestor(self._getctx(oldpnode), fromctx)): # Branch-wide replacement, unmark the branch as deleted self.meta.closebranches.discard(branch) svncopies = {} copies = {} for f in fromctx: if not f.startswith(frompath): continue dest = path + '/' + f[len(frompath):] if not self.meta.is_path_valid(dest): continue if dest in self._deleted: self._deleted.remove(dest) if copyfromparent: continue svncopies[dest] = CopiedFile(new_hash, f, None) if branch == source_branch: copies[dest] = f if copies: # Preserve the directory copy records if no file was changed between # the source and destination revisions, or discard it completely. parentid = self.meta.get_parent_revision( self.current.rev.revnum, branch) if parentid != revlog.nullid: parentctx = self._getctx(parentid) for k, v in copies.iteritems(): if util.issamefile(parentctx, fromctx, v): svncopies[k].copypath = v self._svncopies.update(svncopies) # Copy the externals definitions of copied directories fromext = svnexternals.parse(self.ui, fromctx) for p, v in fromext.iteritems(): pp = p and (p + '/') or '' if pp.startswith(frompath): dest = (path + '/' + pp[len(frompath):]).rstrip('/') self.current.externals[dest] = v return baton
def add_directory(self, path, parent_baton, copyfrom_path, copyfrom_revision, dir_pool=None): self.current.batons[path] = path br_path, branch = self.meta.split_branch_path(path)[:2] if br_path is not None: if not copyfrom_path and not br_path: self.current.emptybranches[branch] = True else: self.current.emptybranches[branch] = False if br_path is None or not copyfrom_path: return path if self.meta.get_path_tag(path): del self.current.emptybranches[branch] return path tag = self.meta.get_path_tag(copyfrom_path) if tag not in self.meta.tags: tag = None if not self.meta.is_path_valid(copyfrom_path): self.current.missing.add('%s/' % path) return path if tag: changeid = self.meta.tags[tag] source_rev, source_branch = self.meta.get_source_rev(changeid)[:2] cp_f = '' else: source_rev = copyfrom_revision cp_f, source_branch = self.meta.split_branch_path(copyfrom_path)[:2] if cp_f == '' and br_path == '': assert br_path is not None tmp = source_branch, source_rev, self.current.rev.revnum self.meta.branches[branch] = tmp new_hash = self.meta.get_parent_revision(source_rev + 1, source_branch, True) if new_hash == node.nullid: self.current.missing.add('%s/' % path) return path cp_f_ctx = self.repo.changectx(new_hash) if cp_f != '/' and cp_f != '': cp_f = '%s/' % cp_f else: cp_f = '' copies = {} for f in cp_f_ctx: if not f.startswith(cp_f): continue f2 = f[len(cp_f):] fctx = cp_f_ctx.filectx(f) fp_c = path + '/' + f2 self.current.set(fp_c, fctx.data(), 'x' in fctx.flags(), 'l' in fctx.flags()) if fp_c in self.current.deleted: del self.current.deleted[fp_c] if branch == source_branch: copies[fp_c] = f if copies: # Preserve the directory copy records if no file was changed between # the source and destination revisions, or discard it completely. parentid = self.meta.get_parent_revision(self.current.rev.revnum, branch) if parentid != revlog.nullid: parentctx = self.repo.changectx(parentid) for k, v in copies.iteritems(): if util.issamefile(parentctx, cp_f_ctx, v): self.current.copies[k] = v return path
def add_directory(self, path, parent_baton, copyfrom_path, copyfrom_revision, dir_pool=None): self.current.batons[path] = path br_path, branch = self.meta.split_branch_path(path)[:2] if br_path is not None: if not copyfrom_path and not br_path: self.current.emptybranches[branch] = True else: self.current.emptybranches[branch] = False if br_path is None or not copyfrom_path: return path if self.meta.get_path_tag(path): del self.current.emptybranches[branch] return path tag = self.meta.get_path_tag(copyfrom_path) if tag not in self.meta.tags: tag = None if not self.meta.is_path_valid(copyfrom_path): self.current.missing.add('%s/' % path) return path if tag: changeid = self.meta.tags[tag] source_rev, source_branch = self.meta.get_source_rev(changeid)[:2] cp_f = '' else: source_rev = copyfrom_revision cp_f, source_branch = self.meta.split_branch_path( copyfrom_path)[:2] if cp_f == '' and br_path == '': assert br_path is not None tmp = source_branch, source_rev, self.current.rev.revnum self.meta.branches[branch] = tmp new_hash = self.meta.get_parent_revision(source_rev + 1, source_branch, True) if new_hash == node.nullid: self.current.missing.add('%s/' % path) return path cp_f_ctx = self.repo.changectx(new_hash) if cp_f != '/' and cp_f != '': cp_f = '%s/' % cp_f else: cp_f = '' copies = {} for f in cp_f_ctx: if not f.startswith(cp_f): continue f2 = f[len(cp_f):] fctx = cp_f_ctx.filectx(f) fp_c = path + '/' + f2 self.current.set(fp_c, fctx.data(), 'x' in fctx.flags(), 'l' in fctx.flags()) if fp_c in self.current.deleted: del self.current.deleted[fp_c] if branch == source_branch: copies[fp_c] = f if copies: # Preserve the directory copy records if no file was changed between # the source and destination revisions, or discard it completely. parentid = self.meta.get_parent_revision(self.current.rev.revnum, branch) if parentid != revlog.nullid: parentctx = self.repo.changectx(parentid) for k, v in copies.iteritems(): if util.issamefile(parentctx, cp_f_ctx, v): self.current.copies[k] = v return path
def add_directory(self, path, parent_baton, copyfrom_path, copyfrom_revision, dir_pool=None): self.current.batons[path] = path br_path, branch = self.meta.split_branch_path(path)[:2] if br_path is not None: if not copyfrom_path and not br_path: self.current.emptybranches[branch] = True else: self.current.emptybranches[branch] = False if br_path is None or not copyfrom_path: return path if self.meta.get_path_tag(path): del self.current.emptybranches[branch] return path tag = self.meta.get_path_tag(copyfrom_path) if tag not in self.meta.tags: tag = None if not self.meta.is_path_valid(copyfrom_path): self.current.missing.add('%s/' % path) return path if tag: changeid = self.meta.tags[tag] source_rev, source_branch = self.meta.get_source_rev(changeid)[:2] frompath = '' else: source_rev = copyfrom_revision frompath, source_branch = self.meta.split_branch_path(copyfrom_path)[:2] if frompath == '' and br_path == '': assert br_path is not None tmp = source_branch, source_rev, self.current.rev.revnum self.meta.branches[branch] = tmp new_hash = self.meta.get_parent_revision(source_rev + 1, source_branch, True) if new_hash == node.nullid: self.current.missing.add('%s/' % path) return path fromctx = self.repo.changectx(new_hash) if frompath != '/' and frompath != '': frompath = '%s/' % frompath else: frompath = '' copies = {} for f in fromctx: if not f.startswith(frompath): continue fctx = fromctx.filectx(f) dest = path + '/' + f[len(frompath):] self.current.set(dest, fctx.data(), 'x' in fctx.flags(), 'l' in fctx.flags()) if dest in self.current.deleted: del self.current.deleted[dest] if branch == source_branch: copies[dest] = f if copies: # Preserve the directory copy records if no file was changed between # the source and destination revisions, or discard it completely. parentid = self.meta.get_parent_revision(self.current.rev.revnum, branch) if parentid != revlog.nullid: parentctx = self.repo.changectx(parentid) for k, v in copies.iteritems(): if util.issamefile(parentctx, fromctx, v): self.current.copies[k] = v # Copy the externals definitions of copied directories fromext = svnexternals.parse(self.ui, fromctx) for p, v in fromext.iteritems(): pp = p and (p + '/') or '' if pp.startswith(frompath): dest = (path + '/' + pp[len(frompath):]).rstrip('/') self.current.externals[dest] = v return path