filemap.py
498 lines
| 17.7 KiB
| text/x-python
|
PythonLexer
Alexis S. L. Carvalho
|
r5376 | # Copyright 2007 Bryan O'Sullivan <bos@serpentine.com> | ||
Alexis S. L. Carvalho
|
r5377 | # Copyright 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br> | ||
Alexis S. L. Carvalho
|
r5376 | # | ||
Martin Geisler
|
r8225 | # This software may be used and distributed according to the terms of the | ||
Matt Mackall
|
r10263 | # GNU General Public License version 2 or any later version. | ||
Yuya Nishihara
|
r34139 | |||
from __future__ import absolute_import, print_function | ||||
Alexis S. L. Carvalho
|
r5376 | |||
Huayang
|
r17797 | import posixpath | ||
Yuya Nishihara
|
r29205 | |||
from mercurial.i18n import _ | ||||
timeless
|
r28367 | from mercurial import ( | ||
error, | ||||
Augie Fackler
|
r36578 | pycompat, | ||
timeless
|
r28367 | ) | ||
from . import common | ||||
Augie Fackler
|
r43346 | |||
timeless
|
r28367 | SKIPREV = common.SKIPREV | ||
Alexis S. L. Carvalho
|
r5376 | |||
Augie Fackler
|
r43346 | |||
Mads Kiilerich
|
r20048 | def rpairs(path): | ||
'''Yield tuples with path split at '/', starting with the full path. | ||||
No leading, trailing or double '/', please. | ||||
Yuya Nishihara
|
r34139 | >>> for x in rpairs(b'foo/bar/baz'): print(x) | ||
Mads Kiilerich
|
r20048 | ('foo/bar/baz', '') | ||
('foo/bar', 'baz') | ||||
('foo', 'bar/baz') | ||||
('.', 'foo/bar/baz') | ||||
''' | ||||
i = len(path) | ||||
while i != -1: | ||||
Augie Fackler
|
r43346 | yield path[:i], path[i + 1 :] | ||
Augie Fackler
|
r43347 | i = path.rfind(b'/', 0, i) | ||
yield b'.', path | ||||
Alexis S. L. Carvalho
|
r5376 | |||
Augie Fackler
|
r43346 | |||
Huayang
|
r17797 | def normalize(path): | ||
''' We use posixpath.normpath to support cross-platform path format. | ||||
However, it doesn't handle None input. So we wrap it up. ''' | ||||
if path is None: | ||||
return None | ||||
return posixpath.normpath(path) | ||||
Augie Fackler
|
r43346 | |||
Alexis S. L. Carvalho
|
r5376 | class filemapper(object): | ||
'''Map and filter filenames when importing. | ||||
A name can be mapped to itself, a new name, or None (omit from new | ||||
repository).''' | ||||
def __init__(self, ui, path=None): | ||||
self.ui = ui | ||||
self.include = {} | ||||
self.exclude = {} | ||||
self.rename = {} | ||||
Durham Goode
|
r26036 | self.targetprefixes = None | ||
Alexis S. L. Carvalho
|
r5376 | if path: | ||
if self.parse(path): | ||||
Augie Fackler
|
r43347 | raise error.Abort(_(b'errors in filemap')) | ||
Alexis S. L. Carvalho
|
r5376 | |||
def parse(self, path): | ||||
errs = 0 | ||||
Augie Fackler
|
r43346 | |||
Alexis S. L. Carvalho
|
r5376 | def check(name, mapping, listname): | ||
Mads Kiilerich
|
r11680 | if not name: | ||
Augie Fackler
|
r43346 | self.ui.warn( | ||
Augie Fackler
|
r43347 | _(b'%s:%d: path to %s is missing\n') | ||
Augie Fackler
|
r43346 | % (lex.infile, lex.lineno, listname) | ||
) | ||||
Mads Kiilerich
|
r11680 | return 1 | ||
Alexis S. L. Carvalho
|
r5376 | if name in mapping: | ||
Augie Fackler
|
r43346 | self.ui.warn( | ||
Augie Fackler
|
r43347 | _(b'%s:%d: %r already in %s list\n') | ||
Augie Fackler
|
r43346 | % (lex.infile, lex.lineno, name, listname) | ||
) | ||||
Alexis S. L. Carvalho
|
r5376 | return 1 | ||
Augie Fackler
|
r43347 | if name.startswith(b'/') or name.endswith(b'/') or b'//' in name: | ||
Augie Fackler
|
r43346 | self.ui.warn( | ||
Augie Fackler
|
r43347 | _(b'%s:%d: superfluous / in %s %r\n') | ||
Augie Fackler
|
r43346 | % (lex.infile, lex.lineno, listname, pycompat.bytestr(name)) | ||
) | ||||
Mads Kiilerich
|
r11680 | return 1 | ||
Alexis S. L. Carvalho
|
r5376 | return 0 | ||
Augie Fackler
|
r43346 | |||
Augie Fackler
|
r36577 | lex = common.shlexer( | ||
Augie Fackler
|
r43347 | filepath=path, wordchars=b'!@#$%^&*()-=+[]{}|;:,./<>?' | ||
Augie Fackler
|
r43346 | ) | ||
Alexis S. L. Carvalho
|
r5376 | cmd = lex.get_token() | ||
while cmd: | ||||
Augie Fackler
|
r43347 | if cmd == b'include': | ||
Huayang
|
r17797 | name = normalize(lex.get_token()) | ||
Augie Fackler
|
r43347 | errs += check(name, self.exclude, b'exclude') | ||
Alexis S. L. Carvalho
|
r5376 | self.include[name] = name | ||
Augie Fackler
|
r43347 | elif cmd == b'exclude': | ||
Huayang
|
r17797 | name = normalize(lex.get_token()) | ||
Augie Fackler
|
r43347 | errs += check(name, self.include, b'include') | ||
errs += check(name, self.rename, b'rename') | ||||
Alexis S. L. Carvalho
|
r5376 | self.exclude[name] = name | ||
Augie Fackler
|
r43347 | elif cmd == b'rename': | ||
Huayang
|
r17797 | src = normalize(lex.get_token()) | ||
dest = normalize(lex.get_token()) | ||||
Augie Fackler
|
r43347 | errs += check(src, self.exclude, b'exclude') | ||
Alexis S. L. Carvalho
|
r5376 | self.rename[src] = dest | ||
Augie Fackler
|
r43347 | elif cmd == b'source': | ||
Huayang
|
r17797 | errs += self.parse(normalize(lex.get_token())) | ||
Alexis S. L. Carvalho
|
r5376 | else: | ||
Augie Fackler
|
r43346 | self.ui.warn( | ||
Augie Fackler
|
r43347 | _(b'%s:%d: unknown directive %r\n') | ||
Augie Fackler
|
r43346 | % (lex.infile, lex.lineno, pycompat.bytestr(cmd)) | ||
) | ||||
Alexis S. L. Carvalho
|
r5376 | errs += 1 | ||
cmd = lex.get_token() | ||||
return errs | ||||
def lookup(self, name, mapping): | ||||
Huayang
|
r17797 | name = normalize(name) | ||
Alexis S. L. Carvalho
|
r5376 | for pre, suf in rpairs(name): | ||
try: | ||||
return mapping[pre], pre, suf | ||||
Peter Arrenbrecht
|
r7875 | except KeyError: | ||
Alexis S. L. Carvalho
|
r5376 | pass | ||
Augie Fackler
|
r43347 | return b'', name, b'' | ||
Alexis S. L. Carvalho
|
r5376 | |||
Durham Goode
|
r26036 | def istargetfile(self, filename): | ||
"""Return true if the given target filename is covered as a destination | ||||
of the filemap. This is useful for identifying what parts of the target | ||||
repo belong to the source repo and what parts don't.""" | ||||
if self.targetprefixes is None: | ||||
self.targetprefixes = set() | ||||
for before, after in self.rename.iteritems(): | ||||
self.targetprefixes.add(after) | ||||
# If "." is a target, then all target files are considered from the | ||||
# source. | ||||
Augie Fackler
|
r43347 | if not self.targetprefixes or b'.' in self.targetprefixes: | ||
Durham Goode
|
r26036 | return True | ||
filename = normalize(filename) | ||||
for pre, suf in rpairs(filename): | ||||
# This check is imperfect since it doesn't account for the | ||||
# include/exclude list, but it should work in filemaps that don't | ||||
# apply include/exclude to the same source directories they are | ||||
# renaming. | ||||
if pre in self.targetprefixes: | ||||
return True | ||||
return False | ||||
Alexis S. L. Carvalho
|
r5376 | def __call__(self, name): | ||
if self.include: | ||||
inc = self.lookup(name, self.include)[0] | ||||
else: | ||||
inc = name | ||||
if self.exclude: | ||||
exc = self.lookup(name, self.exclude)[0] | ||||
else: | ||||
Augie Fackler
|
r43347 | exc = b'' | ||
Stefan Simek
|
r9884 | if (not self.include and exc) or (len(inc) <= len(exc)): | ||
Alexis S. L. Carvalho
|
r5376 | return None | ||
newpre, pre, suf = self.lookup(name, self.rename) | ||||
if newpre: | ||||
Augie Fackler
|
r43347 | if newpre == b'.': | ||
Alexis S. L. Carvalho
|
r5376 | return suf | ||
if suf: | ||||
Augie Fackler
|
r43347 | if newpre.endswith(b'/'): | ||
Matt Mackall
|
r15565 | return newpre + suf | ||
Augie Fackler
|
r43347 | return newpre + b'/' + suf | ||
Alexis S. L. Carvalho
|
r5376 | return newpre | ||
return name | ||||
def active(self): | ||||
return bool(self.include or self.exclude or self.rename) | ||||
Alexis S. L. Carvalho
|
r5377 | |||
Augie Fackler
|
r43346 | |||
Alexis S. L. Carvalho
|
r5377 | # This class does two additional things compared to a regular source: | ||
# | ||||
# - Filter and rename files. This is mostly wrapped by the filemapper | ||||
# class above. We hide the original filename in the revision that is | ||||
Patrick Mezard
|
r11134 | # returned by getchanges to be able to find things later in getfile. | ||
Alexis S. L. Carvalho
|
r5377 | # | ||
# - Return only revisions that matter for the files we're interested in. | ||||
# This involves rewriting the parents of the original revision to | ||||
# create a graph that is restricted to those revisions. | ||||
# | ||||
# This set of revisions includes not only revisions that directly | ||||
# touch files we're interested in, but also merges that merge two | ||||
# or more interesting revisions. | ||||
Augie Fackler
|
r43346 | |||
timeless
|
r28367 | class filemap_source(common.converter_source): | ||
Alexis S. L. Carvalho
|
r5377 | def __init__(self, ui, baseconverter, filemap): | ||
Matt Harbison
|
r35168 | super(filemap_source, self).__init__(ui, baseconverter.repotype) | ||
Alexis S. L. Carvalho
|
r5377 | self.base = baseconverter | ||
self.filemapper = filemapper(ui, filemap) | ||||
self.commits = {} | ||||
# if a revision rev has parent p in the original revision graph, then | ||||
# rev will have parent self.parentmap[p] in the restricted graph. | ||||
self.parentmap = {} | ||||
# self.wantedancestors[rev] is the set of all ancestors of rev that | ||||
# are in the restricted graph. | ||||
self.wantedancestors = {} | ||||
self.convertedorder = None | ||||
self._rebuilt = False | ||||
self.origparents = {} | ||||
Alexis S. L. Carvalho
|
r5401 | self.children = {} | ||
self.seenchildren = {} | ||||
Durham Goode
|
r25742 | # experimental config: convert.ignoreancestorcheck | ||
Augie Fackler
|
r43346 | self.ignoreancestorcheck = self.ui.configbool( | ||
Augie Fackler
|
r43347 | b'convert', b'ignoreancestorcheck' | ||
Augie Fackler
|
r43346 | ) | ||
Alexis S. L. Carvalho
|
r5377 | |||
Patrick Mezard
|
r5799 | def before(self): | ||
self.base.before() | ||||
def after(self): | ||||
self.base.after() | ||||
Bryan O'Sullivan
|
r5510 | def setrevmap(self, revmap): | ||
Alexis S. L. Carvalho
|
r5377 | # rebuild our state to make things restartable | ||
# | ||||
# To avoid calling getcommit for every revision that has already | ||||
# been converted, we rebuild only the parentmap, delaying the | ||||
# rebuild of wantedancestors until we need it (i.e. until a | ||||
# merge). | ||||
# | ||||
# We assume the order argument lists the revisions in | ||||
# topological order, so that we can infer which revisions were | ||||
# wanted by previous runs. | ||||
self._rebuilt = not revmap | ||||
seen = {SKIPREV: SKIPREV} | ||||
Martin Geisler
|
r8150 | dummyset = set() | ||
Alexis S. L. Carvalho
|
r5377 | converted = [] | ||
Bryan O'Sullivan
|
r5510 | for rev in revmap.order: | ||
Alexis S. L. Carvalho
|
r5377 | mapped = revmap[rev] | ||
wanted = mapped not in seen | ||||
if wanted: | ||||
seen[mapped] = rev | ||||
self.parentmap[rev] = rev | ||||
else: | ||||
self.parentmap[rev] = seen[mapped] | ||||
self.wantedancestors[rev] = dummyset | ||||
arg = seen[mapped] | ||||
if arg == SKIPREV: | ||||
arg = None | ||||
converted.append((rev, wanted, arg)) | ||||
self.convertedorder = converted | ||||
Bryan O'Sullivan
|
r5510 | return self.base.setrevmap(revmap) | ||
Alexis S. L. Carvalho
|
r5377 | |||
def rebuild(self): | ||||
if self._rebuilt: | ||||
return True | ||||
self._rebuilt = True | ||||
self.parentmap.clear() | ||||
self.wantedancestors.clear() | ||||
Alexis S. L. Carvalho
|
r5401 | self.seenchildren.clear() | ||
Alexis S. L. Carvalho
|
r5377 | for rev, wanted, arg in self.convertedorder: | ||
Alexis S. L. Carvalho
|
r5401 | if rev not in self.origparents: | ||
Mads Kiilerich
|
r19863 | try: | ||
self.origparents[rev] = self.getcommit(rev).parents | ||||
except error.RepoLookupError: | ||||
Augie Fackler
|
r43347 | self.ui.debug(b"unknown revmap source: %s\n" % rev) | ||
Mads Kiilerich
|
r19863 | continue | ||
Alexis S. L. Carvalho
|
r5401 | if arg is not None: | ||
self.children[arg] = self.children.get(arg, 0) + 1 | ||||
for rev, wanted, arg in self.convertedorder: | ||||
Mads Kiilerich
|
r19863 | try: | ||
parents = self.origparents[rev] | ||||
except KeyError: | ||||
Augie Fackler
|
r43346 | continue # unknown revmap source | ||
Alexis S. L. Carvalho
|
r5377 | if wanted: | ||
self.mark_wanted(rev, parents) | ||||
else: | ||||
self.mark_not_wanted(rev, arg) | ||||
Alexis S. L. Carvalho
|
r5401 | self._discard(arg, *parents) | ||
Alexis S. L. Carvalho
|
r5377 | |||
return True | ||||
def getheads(self): | ||||
return self.base.getheads() | ||||
def getcommit(self, rev): | ||||
# We want to save a reference to the commit objects to be able | ||||
# to rewrite their parents later on. | ||||
Alexis S. L. Carvalho
|
r5401 | c = self.commits[rev] = self.base.getcommit(rev) | ||
for p in c.parents: | ||||
self.children[p] = self.children.get(p, 0) + 1 | ||||
return c | ||||
Matt Harbison
|
r41215 | def numcommits(self): | ||
return self.base.numcommits() | ||||
Patrick Mezard
|
r13968 | def _cachedcommit(self, rev): | ||
if rev in self.commits: | ||||
return self.commits[rev] | ||||
return self.base.getcommit(rev) | ||||
Alexis S. L. Carvalho
|
r5401 | def _discard(self, *revs): | ||
for r in revs: | ||||
if r is None: | ||||
continue | ||||
self.seenchildren[r] = self.seenchildren.get(r, 0) + 1 | ||||
if self.seenchildren[r] == self.children[r]: | ||||
Mads Kiilerich
|
r19862 | self.wantedancestors.pop(r, None) | ||
self.parentmap.pop(r, None) | ||||
Alexis S. L. Carvalho
|
r5401 | del self.seenchildren[r] | ||
if self._rebuilt: | ||||
del self.children[r] | ||||
Alexis S. L. Carvalho
|
r5377 | |||
def wanted(self, rev, i): | ||||
# Return True if we're directly interested in rev. | ||||
# | ||||
# i is an index selecting one of the parents of rev (if rev | ||||
# has no parents, i is None). getchangedfiles will give us | ||||
# the list of files that are different in rev and in the parent | ||||
# indicated by i. If we're interested in any of these files, | ||||
# we're interested in rev. | ||||
try: | ||||
files = self.base.getchangedfiles(rev, i) | ||||
except NotImplementedError: | ||||
Augie Fackler
|
r43347 | raise error.Abort(_(b"source repository doesn't support --filemap")) | ||
Alexis S. L. Carvalho
|
r5377 | for f in files: | ||
if self.filemapper(f): | ||||
return True | ||||
Matt Harbison
|
r41216 | |||
# The include directive is documented to include nothing else (though | ||||
# valid branch closes are included). | ||||
if self.filemapper.include: | ||||
return False | ||||
# Allow empty commits in the source revision through. The getchanges() | ||||
# method doesn't even bother calling this if it determines that the | ||||
# close marker is significant (i.e. all of the branch ancestors weren't | ||||
# eliminated). Therefore if there *is* a close marker, getchanges() | ||||
# doesn't consider it significant, and this revision should be dropped. | ||||
Augie Fackler
|
r43347 | return not files and b'close' not in self.commits[rev].extra | ||
Alexis S. L. Carvalho
|
r5377 | |||
def mark_not_wanted(self, rev, p): | ||||
# Mark rev as not interesting and update data structures. | ||||
if p is None: | ||||
# A root revision. Use SKIPREV to indicate that it doesn't | ||||
# map to any revision in the restricted graph. Put SKIPREV | ||||
# in the set of wanted ancestors to simplify code elsewhere | ||||
self.parentmap[rev] = SKIPREV | ||||
Martin von Zweigbergk
|
r32291 | self.wantedancestors[rev] = {SKIPREV} | ||
Alexis S. L. Carvalho
|
r5377 | return | ||
# Reuse the data from our parent. | ||||
self.parentmap[rev] = self.parentmap[p] | ||||
self.wantedancestors[rev] = self.wantedancestors[p] | ||||
def mark_wanted(self, rev, parents): | ||||
# Mark rev ss wanted and update data structures. | ||||
# rev will be in the restricted graph, so children of rev in | ||||
# the original graph should still have rev as a parent in the | ||||
# restricted graph. | ||||
self.parentmap[rev] = rev | ||||
# The set of wanted ancestors of rev is the union of the sets | ||||
# of wanted ancestors of its parents. Plus rev itself. | ||||
Martin Geisler
|
r8150 | wrev = set() | ||
Alexis S. L. Carvalho
|
r5377 | for p in parents: | ||
Mads Kiilerich
|
r19862 | if p in self.wantedancestors: | ||
wrev.update(self.wantedancestors[p]) | ||||
else: | ||||
Augie Fackler
|
r43347 | self.ui.warn( | ||
_(b'warning: %s parent %s is missing\n') % (rev, p) | ||||
) | ||||
Alexis S. L. Carvalho
|
r5377 | wrev.add(rev) | ||
self.wantedancestors[rev] = wrev | ||||
Mads Kiilerich
|
r22300 | def getchanges(self, rev, full): | ||
Alexis S. L. Carvalho
|
r5377 | parents = self.commits[rev].parents | ||
Durham Goode
|
r25742 | if len(parents) > 1 and not self.ignoreancestorcheck: | ||
Alexis S. L. Carvalho
|
r5377 | self.rebuild() | ||
# To decide whether we're interested in rev we: | ||||
# | ||||
# - calculate what parents rev will have if it turns out we're | ||||
# interested in it. If it's going to have more than 1 parent, | ||||
# we're interested in it. | ||||
# | ||||
# - otherwise, we'll compare it with the single parent we found. | ||||
# If any of the files we're interested in is different in the | ||||
# the two revisions, we're interested in rev. | ||||
# A parent p is interesting if its mapped version (self.parentmap[p]): | ||||
# - is not SKIPREV | ||||
# - is still not in the list of parents (we don't want duplicates) | ||||
Patrick Mezard
|
r17103 | # - is not an ancestor of the mapped versions of the other parents or | ||
# there is no parent in the same branch than the current revision. | ||||
Alexis S. L. Carvalho
|
r5377 | mparents = [] | ||
Patrick Mezard
|
r17103 | knownparents = set() | ||
branch = self.commits[rev].branch | ||||
hasbranchparent = False | ||||
Alexis S. L. Carvalho
|
r5377 | for i, p1 in enumerate(parents): | ||
mp1 = self.parentmap[p1] | ||||
Patrick Mezard
|
r17103 | if mp1 == SKIPREV or mp1 in knownparents: | ||
Alexis S. L. Carvalho
|
r5377 | continue | ||
Durham Goode
|
r25742 | |||
Augie Fackler
|
r43346 | isancestor = not self.ignoreancestorcheck and any( | ||
p2 | ||||
for p2 in parents | ||||
if p1 != p2 | ||||
and mp1 != self.parentmap[p2] | ||||
and mp1 in self.wantedancestors[p2] | ||||
) | ||||
Patrick Mezard
|
r17103 | if not isancestor and not hasbranchparent and len(parents) > 1: | ||
# This could be expensive, avoid unnecessary calls. | ||||
if self._cachedcommit(p1).branch == branch: | ||||
hasbranchparent = True | ||||
mparents.append((p1, mp1, i, isancestor)) | ||||
knownparents.add(mp1) | ||||
# Discard parents ancestors of other parents if there is a | ||||
# non-ancestor one on the same branch than current revision. | ||||
if hasbranchparent: | ||||
mparents = [p for p in mparents if not p[3]] | ||||
wp = None | ||||
if mparents: | ||||
wp = max(p[2] for p in mparents) | ||||
mparents = [p[1] for p in mparents] | ||||
elif parents: | ||||
Alexis S. L. Carvalho
|
r5377 | wp = 0 | ||
self.origparents[rev] = parents | ||||
Patrick Mezard
|
r13968 | closed = False | ||
Augie Fackler
|
r43347 | if b'close' in self.commits[rev].extra: | ||
Patrick Mezard
|
r13968 | # A branch closing revision is only useful if one of its | ||
# parents belong to the branch being closed | ||||
pbranches = [self._cachedcommit(p).branch for p in mparents] | ||||
if branch in pbranches: | ||||
closed = True | ||||
Matt Mackall
|
r11673 | |||
if len(mparents) < 2 and not closed and not self.wanted(rev, wp): | ||||
Alexis S. L. Carvalho
|
r5377 | # We don't want this revision. | ||
# Update our state and tell the convert process to map this | ||||
# revision to the same revision its parent as mapped to. | ||||
p = None | ||||
if parents: | ||||
p = parents[wp] | ||||
self.mark_not_wanted(rev, p) | ||||
self.convertedorder.append((rev, False, p)) | ||||
Alexis S. L. Carvalho
|
r5401 | self._discard(*parents) | ||
Alexis S. L. Carvalho
|
r5377 | return self.parentmap[rev] | ||
# We want this revision. | ||||
# Rewrite the parents of the commit object | ||||
self.commits[rev].parents = mparents | ||||
self.mark_wanted(rev, parents) | ||||
self.convertedorder.append((rev, True, None)) | ||||
Alexis S. L. Carvalho
|
r5401 | self._discard(*parents) | ||
Alexis S. L. Carvalho
|
r5377 | |||
Patrick Mezard
|
r11134 | # Get the real changes and do the filtering/mapping. To be | ||
# able to get the files later on in getfile, we hide the | ||||
# original filename in the rev part of the return value. | ||||
Mads Kiilerich
|
r24395 | changes, copies, cleanp2 = self.base.getchanges(rev, full) | ||
Wagner Bruna
|
r17174 | files = {} | ||
Mads Kiilerich
|
r24395 | ncleanp2 = set(cleanp2) | ||
Alexis S. L. Carvalho
|
r5377 | for f, r in changes: | ||
newf = self.filemapper(f) | ||||
Wagner Bruna
|
r17174 | if newf and (newf != f or newf not in files): | ||
files[newf] = (f, r) | ||||
Mads Kiilerich
|
r24395 | if newf != f: | ||
ncleanp2.discard(f) | ||||
Wagner Bruna
|
r17174 | files = sorted(files.items()) | ||
Alexis S. L. Carvalho
|
r5377 | |||
ncopies = {} | ||||
for c in copies: | ||||
newc = self.filemapper(c) | ||||
if newc: | ||||
newsource = self.filemapper(copies[c]) | ||||
if newsource: | ||||
ncopies[newc] = newsource | ||||
Mads Kiilerich
|
r24395 | return files, ncopies, ncleanp2 | ||
Alexis S. L. Carvalho
|
r5377 | |||
Durham Goode
|
r26036 | def targetfilebelongstosource(self, targetfilename): | ||
return self.filemapper.istargetfile(targetfilename) | ||||
Alexis S. L. Carvalho
|
r5377 | def getfile(self, name, rev): | ||
realname, realrev = rev | ||||
return self.base.getfile(realname, realrev) | ||||
def gettags(self): | ||||
return self.base.gettags() | ||||
Patrick Mezard
|
r8691 | |||
def hasnativeorder(self): | ||||
return self.base.hasnativeorder() | ||||
Patrick Mezard
|
r8693 | |||
def lookuprev(self, rev): | ||||
return self.base.lookuprev(rev) | ||||
etienne
|
r15107 | |||
def getbookmarks(self): | ||||
return self.base.getbookmarks() | ||||
Mads Kiilerich
|
r19892 | |||
def converted(self, rev, sinkrev): | ||||
self.base.converted(rev, sinkrev) | ||||