--- a/mercurial/cmdutil.py Sun May 08 17:48:29 2011 +0200
+++ b/mercurial/cmdutil.py Sun May 08 17:48:30 2011 +0200
@@ -8,10 +8,17 @@
from node import hex, nullid, nullrev, short
from i18n import _
import os, sys, errno, re, glob, tempfile
-import util, scmutil, templater, patch, error, templatekw
+import util, scmutil, templater, patch, error, templatekw, wdutil
import match as matchmod
import similar, revset, subrepo
+expandpats = wdutil.expandpats
+match = wdutil.match
+matchall = wdutil.matchall
+matchfiles = wdutil.matchfiles
+addremove = wdutil.addremove
+dirstatecopy = wdutil.dirstatecopy
+
revrangesep = ':'
def parsealiases(cmd):
@@ -243,157 +250,6 @@
pathname),
mode)
-def expandpats(pats):
- if not util.expandglobs:
- return list(pats)
- ret = []
- for p in pats:
- kind, name = matchmod._patsplit(p, None)
- if kind is None:
- try:
- globbed = glob.glob(name)
- except re.error:
- globbed = [name]
- if globbed:
- ret.extend(globbed)
- continue
- ret.append(p)
- return ret
-
-def match(repo, pats=[], opts={}, globbed=False, default='relpath'):
- if pats == ("",):
- pats = []
- if not globbed and default == 'relpath':
- pats = expandpats(pats or [])
- m = matchmod.match(repo.root, repo.getcwd(), pats,
- opts.get('include'), opts.get('exclude'), default,
- auditor=repo.auditor)
- def badfn(f, msg):
- repo.ui.warn("%s: %s\n" % (m.rel(f), msg))
- m.bad = badfn
- return m
-
-def matchall(repo):
- return matchmod.always(repo.root, repo.getcwd())
-
-def matchfiles(repo, files):
- return matchmod.exact(repo.root, repo.getcwd(), files)
-
-def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None):
- if dry_run is None:
- dry_run = opts.get('dry_run')
- if similarity is None:
- similarity = float(opts.get('similarity') or 0)
- # we'd use status here, except handling of symlinks and ignore is tricky
- added, unknown, deleted, removed = [], [], [], []
- audit_path = scmutil.pathauditor(repo.root)
- m = match(repo, pats, opts)
- for abs in repo.walk(m):
- target = repo.wjoin(abs)
- good = True
- try:
- audit_path(abs)
- except (OSError, util.Abort):
- good = False
- rel = m.rel(abs)
- exact = m.exact(abs)
- if good and abs not in repo.dirstate:
- unknown.append(abs)
- if repo.ui.verbose or not exact:
- repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
- elif repo.dirstate[abs] != 'r' and (not good or not os.path.lexists(target)
- or (os.path.isdir(target) and not os.path.islink(target))):
- deleted.append(abs)
- if repo.ui.verbose or not exact:
- repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
- # for finding renames
- elif repo.dirstate[abs] == 'r':
- removed.append(abs)
- elif repo.dirstate[abs] == 'a':
- added.append(abs)
- copies = {}
- if similarity > 0:
- for old, new, score in similar.findrenames(repo,
- added + unknown, removed + deleted, similarity):
- if repo.ui.verbose or not m.exact(old) or not m.exact(new):
- repo.ui.status(_('recording removal of %s as rename to %s '
- '(%d%% similar)\n') %
- (m.rel(old), m.rel(new), score * 100))
- copies[new] = old
-
- if not dry_run:
- wctx = repo[None]
- wlock = repo.wlock()
- try:
- wctx.remove(deleted)
- wctx.add(unknown)
- for new, old in copies.iteritems():
- wctx.copy(old, new)
- finally:
- wlock.release()
-
-def updatedir(ui, repo, patches, similarity=0):
- '''Update dirstate after patch application according to metadata'''
- if not patches:
- return []
- copies = []
- removes = set()
- cfiles = patches.keys()
- cwd = repo.getcwd()
- if cwd:
- cfiles = [util.pathto(repo.root, cwd, f) for f in patches.keys()]
- for f in patches:
- gp = patches[f]
- if not gp:
- continue
- if gp.op == 'RENAME':
- copies.append((gp.oldpath, gp.path))
- removes.add(gp.oldpath)
- elif gp.op == 'COPY':
- copies.append((gp.oldpath, gp.path))
- elif gp.op == 'DELETE':
- removes.add(gp.path)
-
- wctx = repo[None]
- for src, dst in copies:
- dirstatecopy(ui, repo, wctx, src, dst, cwd=cwd)
- if (not similarity) and removes:
- wctx.remove(sorted(removes), True)
-
- for f in patches:
- gp = patches[f]
- if gp and gp.mode:
- islink, isexec = gp.mode
- dst = repo.wjoin(gp.path)
- # patch won't create empty files
- if gp.op == 'ADD' and not os.path.lexists(dst):
- flags = (isexec and 'x' or '') + (islink and 'l' or '')
- repo.wwrite(gp.path, '', flags)
- util.setflags(dst, islink, isexec)
- addremove(repo, cfiles, similarity=similarity)
- files = patches.keys()
- files.extend([r for r in removes if r not in files])
- return sorted(files)
-
-def dirstatecopy(ui, repo, wctx, src, dst, dryrun=False, cwd=None):
- """Update the dirstate to reflect the intent of copying src to dst. For
- different reasons it might not end with dst being marked as copied from src.
- """
- origsrc = repo.dirstate.copied(src) or src
- if dst == origsrc: # copying back a copy?
- if repo.dirstate[dst] not in 'mn' and not dryrun:
- repo.dirstate.normallookup(dst)
- else:
- if repo.dirstate[origsrc] == 'a' and origsrc == src:
- if not ui.quiet:
- ui.warn(_("%s has not been committed yet, so no copy "
- "data will be stored for %s.\n")
- % (repo.pathto(origsrc, cwd), repo.pathto(dst, cwd)))
- if repo.dirstate[dst] in '?r' and not dryrun:
- wctx.add([dst])
- elif not dryrun:
- wctx.copy(origsrc, dst)
-
def copy(ui, repo, pats, opts, rename=False):
# called with the repo lock held
#