comparison mercurial/merge.py @ 39463:7fea205fd5dc

merge: move purge logic from extension Working directory purging feels like functionality that should be in core rather than in an extension. This commit effectively moves the core purging logic from the purge extension to merge.py. Code was refactored slightly. Rather than deal with printing in this function, the function is a generator of paths and the caller can worry about printing. Differential Revision: https://phab.mercurial-scm.org/D4477
author Gregory Szorc <gregory.szorc@gmail.com>
date Thu, 06 Sep 2018 18:30:12 -0700
parents d49e490a9e85
children 3dd34b401bc2
comparison
equal deleted inserted replaced
39462:e5449ff273d6 39463:7fea205fd5dc
7 7
8 from __future__ import absolute_import 8 from __future__ import absolute_import
9 9
10 import errno 10 import errno
11 import hashlib 11 import hashlib
12 import os
12 import shutil 13 import shutil
13 import struct 14 import struct
14 15
15 from .i18n import _ 16 from .i18n import _
16 from .node import ( 17 from .node import (
2238 repo.setparents(repo['.'].node(), pother) 2239 repo.setparents(repo['.'].node(), pother)
2239 repo.dirstate.write(repo.currenttransaction()) 2240 repo.dirstate.write(repo.currenttransaction())
2240 # fix up dirstate for copies and renames 2241 # fix up dirstate for copies and renames
2241 copies.duplicatecopies(repo, repo[None], ctx.rev(), pctx.rev()) 2242 copies.duplicatecopies(repo, repo[None], ctx.rev(), pctx.rev())
2242 return stats 2243 return stats
2244
2245 def purge(repo, matcher, ignored=False, removeemptydirs=True,
2246 removefiles=True, abortonerror=False, noop=False):
2247 """Purge the working directory of untracked files.
2248
2249 ``matcher`` is a matcher configured to scan the working directory -
2250 potentially a subset.
2251
2252 ``ignored`` controls whether ignored files should also be purged.
2253
2254 ``removeemptydirs`` controls whether empty directories should be removed.
2255
2256 ``removefiles`` controls whether files are removed.
2257
2258 ``abortonerror`` causes an exception to be raised if an error occurs
2259 deleting a file or directory.
2260
2261 ``noop`` controls whether to actually remove files. If not defined, actions
2262 will be taken.
2263
2264 Returns an iterable of relative paths in the working directory that were
2265 or would be removed.
2266 """
2267
2268 def remove(removefn, path):
2269 try:
2270 removefn(repo.wvfs.join(path))
2271 except OSError:
2272 m = _('%s cannot be removed') % path
2273 if abortonerror:
2274 raise error.Abort(m)
2275 else:
2276 repo.ui.warn(_('warning: %s\n') % m)
2277
2278 # There's no API to copy a matcher. So mutate the passed matcher and
2279 # restore it when we're done.
2280 oldexplicitdir = matcher.explicitdir
2281 oldtraversedir = matcher.traversedir
2282
2283 res = []
2284
2285 try:
2286 if removeemptydirs:
2287 directories = []
2288 matcher.explicitdir = matcher.traversedir = directories.append
2289
2290 status = repo.status(match=matcher, ignored=ignored, unknown=True)
2291
2292 if removefiles:
2293 for f in sorted(status.unknown + status.ignored):
2294 if not noop:
2295 repo.ui.note(_('removing file %s\n') % f)
2296 remove(util.unlink, f)
2297 res.append(f)
2298
2299 if removeemptydirs:
2300 for f in sorted(directories, reverse=True):
2301 if matcher(f) and not os.listdir(repo.wvfs.join(f)):
2302 if not noop:
2303 repo.ui.note(_('removing directory %s\n') % f)
2304 remove(os.rmdir, f)
2305 res.append(f)
2306
2307 return res
2308
2309 finally:
2310 matcher.explicitdir = oldexplicitdir
2311 matcher.traversedir = oldtraversedir