Mercurial > public > mercurial-scm > hg
diff mercurial/cmdutil.py @ 14259:df9ccd39828c
patch: move updatedir() from cmdutil into patch
Also, create an artificial wdutil.py to avoid import cycles between patch.py
and cmdutil.py.
author | Patrick Mezard <pmezard@gmail.com> |
---|---|
date | Sun, 08 May 2011 17:48:30 +0200 |
parents | d035ede73434 |
children | 66257848c154 |
line wrap: on
line diff
--- 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 #