def perfwalk(ui, repo, *pats): try: m = scmutil.match(repo[None], pats, {}) timer(lambda: len(list(repo.dirstate.walk(m, [], True, False)))) except Exception: try: m = scmutil.match(repo[None], pats, {}) timer(lambda: len([b for a, b, c in repo.dirstate.statwalk([], m)])) except Exception: timer(lambda: len(list(cmdutil.walk(repo, pats, {}))))
def perfwalk(ui, repo, *pats): try: m = scmutil.match(repo[None], pats, {}) timer(lambda: len(list(repo.dirstate.walk(m, [], True, False)))) except Exception: try: m = scmutil.match(repo[None], pats, {}) timer( lambda: len([b for a, b, c in repo.dirstate.statwalk([], m)])) except Exception: timer(lambda: len(list(cmdutil.walk(repo, pats, {}))))
def casecheck(ui, repo, *pats, **opts): if not repo.local(): ui.note(_('Only local repositories can be checked')) return '''check an existing local repository for filename issues (caseguard)''' try: # Mercurial >= 1.9 m = scmutil.match(repo[0], pats, opts) except ImportError: # Mercurial <= 1.8 m = cmdutil.match(repo, pats, opts) seen = dict() def dostatus(msg): ui.status('%s\n' % msg) for f in repo.walk(m): if f in repo.dirstate: badname = _wincheck(ui, f, dostatus) or \ _charcheck(ui, f, dostatus) if f.lower() in seen: dostatus(_('%s collides with %s') % (f, seen[f.lower()])) else: seen[f.lower()] = f if not badname: ui.note(_('\t[OK] %s\n') % f)
def getworkqueue(ui, repo, pats, opts, revstofix, basectxs): """"Constructs the list of files to be fixed at specific revisions It is up to the caller how to consume the work items, and the only dependence between them is that replacement revisions must be committed in topological order. Each work item represents a file in the working copy or in some revision that should be fixed and written back to the working copy or into a replacement revision. """ workqueue = [] numitems = collections.defaultdict(int) maxfilesize = ui.configbytes('fix', 'maxfilesize') for rev in revstofix: fixctx = repo[rev] match = scmutil.match(fixctx, pats, opts) for path in pathstofix(ui, repo, pats, opts, match, basectxs[rev], fixctx): if path not in fixctx: continue fctx = fixctx[path] if fctx.islink(): continue if fctx.size() > maxfilesize: ui.warn( _('ignoring file larger than %s: %s\n') % (util.bytecount(maxfilesize), path)) continue workqueue.append((rev, path)) numitems[rev] += 1 return workqueue, numitems
def getstandinmatcher(repo, rmatcher=None): '''Return a match object that applies rmatcher to the standin directory''' standindir = repo.wjoin(shortname) # no warnings about missing files or directories badfn = lambda f, msg: None if rmatcher and not rmatcher.always(): pats = [os.path.join(standindir, pat) for pat in rmatcher.files()] match = scmutil.match(repo[None], pats, badfn=badfn) # if pats is empty, it would incorrectly always match, so clear _always match._always = False else: # no patterns: relative to repo root match = scmutil.match(repo[None], [standindir], badfn=badfn) return match
def log(orig, ui, repo, *pats, **opts): if not isenabled(repo): return orig(ui, repo, *pats, **opts) follow = opts.get('follow') revs = opts.get('rev') if pats: # Force slowpath for non-follow patterns and follows that start from # non-working-copy-parent revs. if not follow or revs: # This forces the slowpath opts['removed'] = True # If this is a non-follow log without any revs specified, recommend that # the user add -f to speed it up. if not follow and not revs: match = scmutil.match(repo[b'.'], pats, pycompat.byteskwargs(opts)) isfile = not match.anypats() if isfile: for file in match.files(): if not os.path.isfile(repo.wjoin(file)): isfile = False break if isfile: ui.warn( _(b"warning: file log can be slow on large repos - " + b"use -f to speed it up\n")) return orig(ui, repo, *pats, **opts)
def override_remove(orig, ui, repo, *pats, **opts): manifest = repo[None].manifest() installnormalfilesmatchfn(manifest) orig(ui, repo, *pats, **opts) restorematchfn() after, force = opts.get('after'), opts.get('force') if not pats and not after: raise util.Abort(_('no files specified')) m = scmutil.match(repo[None], pats, opts) try: repo.lfstatus = True s = repo.status(match=m, clean=True) finally: repo.lfstatus = False modified, added, deleted, clean = [[ f for f in list if lfutil.standin(f) in manifest ] for list in [s[0], s[1], s[3], s[6]]] def warn(files, reason): for f in files: ui.warn( _('not removing %s: %s (use -f to force removal)\n') % (m.rel(f), reason)) if force: remove, forget = modified + deleted + clean, added elif after: remove, forget = deleted, [] warn(modified + added + clean, _('file still exists')) else: remove, forget = deleted + clean, [] warn(modified, _('file is modified')) warn(added, _('file has been marked for add')) for f in sorted(remove + forget): if ui.verbose or not m.exact(f): ui.status(_('removing %s\n') % m.rel(f)) # Need to lock because standin files are deleted then removed from the # repository and we could race inbetween. wlock = repo.wlock() try: lfdirstate = lfutil.openlfdirstate(ui, repo) for f in remove: if not after: os.unlink(repo.wjoin(f)) currentdir = os.path.split(f)[0] while currentdir and not os.listdir(repo.wjoin(currentdir)): os.rmdir(repo.wjoin(currentdir)) currentdir = os.path.split(currentdir)[0] lfdirstate.remove(f) lfdirstate.write() forget = [lfutil.standin(f) for f in forget] remove = [lfutil.standin(f) for f in remove] lfutil.repo_forget(repo, forget) lfutil.repo_remove(repo, remove, unlink=True) finally: wlock.release()
def _nothingtoshelvemessaging(ui, repo, pats, opts): stat = repo.status(match=scmutil.match(repo[None], pats, opts)) if stat.deleted: ui.status(_("nothing changed (%d missing files, see " "'hg status')\n") % len(stat.deleted)) else: ui.status(_("nothing changed\n"))
def badd(ui, repo, *pats, **opts): """add the specified files to big files repo If no names are given, add all files to the repository. """ setignores(ui) ds = read_bigfiledirstate(ui, repo) bigfiles = parse_bigfiles(repo) bad = [] exacts = {} names = [] m = scmutil.match(repo[None], pats, opts) oldbad = m.bad m.bad = lambda x,y: bad.append(x) or oldbad(x,y) for f in repo.walk(m): exact = m.exact(f) if exact or f not in repo.dirstate: names.append(f) if ui.verbose or not exact: ui.status(_('adding %s\n') % m.rel(f)) if not opts.get('dry_run'): brepo = bigfiles_repo(ui) _updatebigrepo(ui, repo, names, brepo, bigfiles, ds) write_dotbigfilesfile(repo, bigfiles) write_bigfiledirstate(ui, repo, ds) return bad and 1 or 0
def _modified_regions(repo, patterns, **kwargs): opt_all = kwargs.get('all', False) opt_no_ignore = kwargs.get('no_ignore', False) # Import the match (repository file name matching helper) # function. Different versions of Mercurial keep it in different # modules and implement them differently. try: from mercurial import scmutil m = scmutil.match(repo[None], patterns, kwargs) except ImportError: from mercurial import cmdutil m = cmdutil.match(repo, patterns, kwargs) modified, added, removed, deleted, unknown, ignore, clean = \ repo.status(match=m, clean=opt_all) if not opt_all: try: wctx = repo.workingctx() except: from mercurial import context wctx = context.workingctx(repo) files = [ (fn, all_regions) for fn in added ] + \ [ (fn, modregions(wctx, fn)) for fn in modified ] else: files = [(fn, all_regions) for fn in added + modified + clean] for fname, mod_regions in files: if opt_no_ignore or not check_ignores(fname): yield fname, mod_regions
def _amend(orig, ui, repo, old, extra, pats, opts): # Only wrap if not disabled and repo is instance of # localrepo.localrepository if _disabled[0] or not isinstance(repo, localrepo.localrepository): return orig(ui, repo, old, extra, pats, opts) with repo.wlock(), repo.lock(), repo.transaction('dirsyncamend'): wctx = repo[None] matcher = scmutil.match(wctx, pats, opts) if (opts.get('addremove') and scmutil.addremove(repo, matcher, "", opts)): raise error.Abort( _("failed to mark all new/missing files as added/removed")) mirroredfiles = _updateworkingcopy(repo, matcher) if mirroredfiles and not matcher.always(): # Ensure that all the files to be amended (original + synced) are # under consideration during the amend operation. We do so by # setting the value against 'include' key in opts as the only source # of truth. pats = () opts['include'] = [ f for f in wctx.files() if matcher(f)] + list(mirroredfiles) return orig(ui, repo, old, extra, pats, opts)
def _get_files(repo, patterns, options): """Return all files in the working directory that match the patterns and are tracked (clean, modified or added). Ignored or unknown files are only matched when given literally. If patterns is empty, match all tracked files. Supports options['include'] and options['exclude'] which work like the --include and --exclude options of hg status. """ ctx = repo[None] match = match_func(repo, ctx, patterns, options) try: ctx.status(listclean=True, listignored=True, listunknown=True) except TypeError: # Compatibility with older Mercurial versions. ctx.status(clean=True, ignored=True, unknown=True) files = [] for file_list in [ctx.clean(), ctx.modified(), ctx.added()]: for filename in file_list: if match(filename): files.append(filename) for file_list in [ctx.ignored(), ctx.unknown()]: for filename in file_list: if match.exact(filename): files.append(filename) return files
def autodiff(ui, repo, *pats, **opts): diffopts = patch.diffopts(ui, opts) git = opts.get('git', 'no') brokenfiles = set() losedatafn = None if git in ('yes', 'no'): diffopts.git = git == 'yes' diffopts.upgrade = False elif git == 'auto': diffopts.git = False diffopts.upgrade = True elif git == 'warn': diffopts.git = False diffopts.upgrade = True def losedatafn(fn=None, **kwargs): brokenfiles.add(fn) return True elif git == 'abort': diffopts.git = False diffopts.upgrade = True def losedatafn(fn=None, **kwargs): raise util.Abort('losing data for %s' % fn) else: raise util.Abort('--git must be yes, no or auto') node1, node2 = scmutil.revpair(repo, []) m = scmutil.match(repo[node2], pats, opts) it = patch.diff(repo, node1, node2, match=m, opts=diffopts, losedatafn=losedatafn) for chunk in it: ui.write(chunk) for fn in sorted(brokenfiles): ui.write(('data lost for: %s\n' % fn))
def _modified_regions(repo, patterns, **kwargs): opt_all = kwargs.get('all', False) opt_no_ignore = kwargs.get('no_ignore', False) # Import the match (repository file name matching helper) # function. Different versions of Mercurial keep it in different # modules and implement them differently. try: from mercurial import scmutil m = scmutil.match(repo[None], patterns, kwargs) except ImportError: from mercurial import cmdutil m = cmdutil.match(repo, patterns, kwargs) modified, added, removed, deleted, unknown, ignore, clean = \ repo.status(match=m, clean=opt_all) if not opt_all: try: wctx = repo.workingctx() except: from mercurial import context wctx = context.workingctx(repo) files = [ (fn, all_regions) for fn in added ] + \ [ (fn, modregions(wctx, fn)) for fn in modified ] else: files = [ (fn, all_regions) for fn in added + modified + clean ] for fname, mod_regions in files: if opt_no_ignore or not check_ignores(fname): yield fname, mod_regions
def purge(ui, repo, *dirs, **opts): '''removes files not tracked by Mercurial Delete files not known to Mercurial. This is useful to test local and uncommitted changes in an otherwise-clean source tree. This means that purge will delete the following by default: - Unknown files: files marked with "?" by :hg:`status` - Empty directories: in fact Mercurial ignores directories unless they contain files under source control management But it will leave untouched: - Modified and unmodified tracked files - Ignored files (unless --all is specified) - New files added to the repository (with :hg:`add`) The --files and --dirs options can be used to direct purge to delete only files, only directories, or both. If neither option is given, both will be deleted. If directories are given on the command line, only files in these directories are considered. Be careful with purge, as you could irreversibly delete some files you forgot to add to the repository. If you only want to print the list of files that this program would delete, use the --print option. ''' opts = pycompat.byteskwargs(opts) act = not opts.get(b'print') eol = b'\n' if opts.get(b'print0'): eol = b'\0' act = False # --print0 implies --print removefiles = opts.get(b'files') removedirs = opts.get(b'dirs') if not removefiles and not removedirs: removefiles = True removedirs = True match = scmutil.match(repo[None], dirs, opts) paths = mergemod.purge( repo, match, ignored=opts.get(b'all', False), removeemptydirs=removedirs, removefiles=removefiles, abortonerror=opts.get(b'abort_on_err'), noop=not act, ) for path in paths: if not act: ui.write(b'%s%s' % (path, eol))
def archive(web, req, tmpl): type_ = req.form.get('type', [None])[0] allowed = web.configlist("web", "allow_archive") key = req.form['node'][0] if type_ not in web.archives: msg = 'Unsupported archive type: %s' % type_ raise ErrorResponse(HTTP_NOT_FOUND, msg) if not ((type_ in allowed or web.configbool("web", "allow" + type_, False))): msg = 'Archive type not allowed: %s' % type_ raise ErrorResponse(HTTP_FORBIDDEN, msg) reponame = re.sub(r"\W+", "-", os.path.basename(web.reponame)) cnode = web.repo.lookup(key) arch_version = key if cnode == key or key == 'tip': arch_version = short(cnode) name = "%s-%s" % (reponame, arch_version) ctx = webutil.changectx(web.repo, req) pats = [] matchfn = scmutil.match(ctx, []) file = req.form.get('file', None) if file: pats = ['path:' + file[0]] matchfn = scmutil.match(ctx, pats, default='path') if pats: files = [f for f in ctx.manifest().keys() if matchfn(f)] if not files: raise ErrorResponse(HTTP_NOT_FOUND, 'file(s) not found: %s' % file[0]) mimetype, artype, extension, encoding = web.archive_specs[type_] headers = [ ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension)) ] if encoding: headers.append(('Content-Encoding', encoding)) req.headers.extend(headers) req.respond(HTTP_OK, mimetype) archival.archive(web.repo, req, cnode, artype, prefix=name, matchfn=matchfn, subrepos=web.configbool("web", "archivesubrepos")) return []
def override_remove(orig, ui, repo, *pats, **opts): manifest = repo[None].manifest() installnormalfilesmatchfn(manifest) orig(ui, repo, *pats, **opts) restorematchfn() after, force = opts.get('after'), opts.get('force') if not pats and not after: raise util.Abort(_('no files specified')) m = scmutil.match(repo[None], pats, opts) try: repo.lfstatus = True s = repo.status(match=m, clean=True) finally: repo.lfstatus = False modified, added, deleted, clean = [[f for f in list if lfutil.standin(f) in manifest] for list in [s[0], s[1], s[3], s[6]]] def warn(files, reason): for f in files: ui.warn(_('not removing %s: %s (use -f to force removal)\n') % (m.rel(f), reason)) if force: remove, forget = modified + deleted + clean, added elif after: remove, forget = deleted, [] warn(modified + added + clean, _('file still exists')) else: remove, forget = deleted + clean, [] warn(modified, _('file is modified')) warn(added, _('file has been marked for add')) for f in sorted(remove + forget): if ui.verbose or not m.exact(f): ui.status(_('removing %s\n') % m.rel(f)) # Need to lock because standin files are deleted then removed from the # repository and we could race inbetween. wlock = repo.wlock() try: lfdirstate = lfutil.openlfdirstate(ui, repo) for f in remove: if not after: os.unlink(repo.wjoin(f)) currentdir = os.path.split(f)[0] while currentdir and not os.listdir(repo.wjoin(currentdir)): os.rmdir(repo.wjoin(currentdir)) currentdir = os.path.split(currentdir)[0] lfdirstate.remove(f) lfdirstate.write() forget = [lfutil.standin(f) for f in forget] remove = [lfutil.standin(f) for f in remove] lfutil.repo_forget(repo, forget) lfutil.repo_remove(repo, remove, unlink=True) finally: wlock.release()
def getstandinmatcher(repo, rmatcher=None): '''Return a match object that applies rmatcher to the standin directory''' wvfs = repo.wvfs standindir = shortname # no warnings about missing files or directories badfn = lambda f, msg: None if rmatcher and not rmatcher.always(): pats = [wvfs.join(standindir, pat) for pat in rmatcher.files()] if not pats: pats = [wvfs.join(standindir)] match = scmutil.match(repo[None], pats, badfn=badfn) else: # no patterns: relative to repo root match = scmutil.match(repo[None], [wvfs.join(standindir)], badfn=badfn) return match
def countrate(ui, repo, amap, *pats, **opts): """Calculate stats""" opts = pycompat.byteskwargs(opts) if opts.get(b'dateformat'): def getkey(ctx): t, tz = ctx.date() date = datetime.datetime(*time.gmtime(float(t) - tz)[:6]) return encoding.strtolocal( date.strftime(encoding.strfromlocal(opts[b'dateformat'])) ) else: tmpl = opts.get(b'oldtemplate') or opts.get(b'template') tmpl = logcmdutil.maketemplater(ui, repo, tmpl) def getkey(ctx): ui.pushbuffer() tmpl.show(ctx) return ui.popbuffer() progress = ui.makeprogress( _(b'analyzing'), unit=_(b'revisions'), total=len(repo) ) rate = {} df = False if opts.get(b'date'): df = dateutil.matchdate(opts[b'date']) m = scmutil.match(repo[None], pats, opts) def prep(ctx, fns): rev = ctx.rev() if df and not df(ctx.date()[0]): # doesn't match date format return key = getkey(ctx).strip() key = amap.get(key, key) # alias remap if opts.get(b'changesets'): rate[key] = (rate.get(key, (0,))[0] + 1, 0) else: parents = ctx.parents() if len(parents) > 1: ui.note(_(b'revision %d is a merge, ignoring...\n') % (rev,)) return ctx1 = parents[0] lines = changedlines(ui, repo, ctx1, ctx, fns) rate[key] = [r + l for r, l in zip(rate.get(key, (0, 0)), lines)] progress.increment() for ctx in cmdutil.walkchangerevs(repo, m, opts, prep): continue progress.complete() return rate
def foamdiff(ui, repo, *files, **opts): ''' Compare two OpenFOAM-dictionaries for semantic differences Very simple. Uses pyFoamCompareDictionary.py and does not pass options along to it ''' revs = opts.get('rev') change = opts.get('change') if len(files) == 0: raise util.Abort("No files specified") if revs and change: msg = _('cannot specify --rev and --change at the same time') raise util.Abort(msg) elif change: node2 = repo.lookup(change) node1a, node1b = repo.changelog.parents(node2) else: node1a, node2 = scmutil.revpair(repo, revs) if not revs: node1b = repo.dirstate.parents()[1] else: node1b = nullid if node1b != nullid: raise util.Abort("Can't do 3-way comparisons") matcher = scmutil.match(repo[node2], files, opts) mod_a, add_a, rem_a = map(set, repo.status(node1a, node2, matcher)[:3]) modadd = mod_a | add_a common = modadd | rem_a if not common: return 0 tmproot = tempfile.mkdtemp(prefix='foamdiff.') ui.debug("Writing temporary files to %s\n" % tmproot) try: dir1a_files = mod_a | rem_a dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot)[0] dir2root = tmproot if node2: dir2 = snapshot(ui, repo, modadd, node2, tmproot)[0] else: dir2 = '' dir2root = repo.root for f in common: ui.write("\n Comparing: %s\n" % f) f1 = path.join(tmproot, dir1a, f) f2 = path.join(dir2root, dir2, f) CompareDictionary(args=[f1, f2]) finally: ui.note(_('cleaning up temp directory\n')) shutil.rmtree(tmproot)
def foamdiff(ui, repo, *files, **opts): ''' Compare two OpenFOAM-dictionaries for semantic differences Very simple. Uses pyFoamCompareDictionary.py and does not pass options along to it ''' revs = opts.get('rev') change = opts.get('change') if len(files)==0: raise util.Abort("No files specified") if revs and change: msg = _('cannot specify --rev and --change at the same time') raise util.Abort(msg) elif change: node2 = repo.lookup(change) node1a, node1b = repo.changelog.parents(node2) else: node1a, node2 = scmutil.revpair(repo, revs) if not revs: node1b = repo.dirstate.parents()[1] else: node1b = nullid if node1b!=nullid: raise util.Abort("Can't do 3-way comparisons") matcher = scmutil.match(repo[node2], files, opts) mod_a, add_a, rem_a = map(set, repo.status(node1a, node2, matcher)[:3]) modadd = mod_a | add_a common = modadd | rem_a if not common: return 0 tmproot = tempfile.mkdtemp(prefix='foamdiff.') ui.debug("Writing temporary files to %s\n" %tmproot) try: dir1a_files = mod_a | rem_a dir1a=snapshot(ui, repo, dir1a_files, node1a, tmproot)[0] dir2root = tmproot if node2: dir2=snapshot(ui, repo, modadd, node2, tmproot)[0] else: dir2='' dir2root=repo.root for f in common: ui.write("\n Comparing: %s\n" %f) f1=path.join(tmproot,dir1a,f) f2=path.join(dir2root,dir2,f) CompareDictionary(args=[f1,f2]) finally: ui.note(_('cleaning up temp directory\n')) shutil.rmtree(tmproot)
def getmatcher(repo, pats=[], opts={}, showbad=True): '''Wrapper around scmutil.match() that adds showbad: if false, neuter the match object's bad() method so it does not print any warnings about missing files or directories.''' match = scmutil.match(repo[None], pats, opts) if not showbad: match.bad = lambda f, msg: None return match
def _status(ui, repo, wctx, kwt, *pats, **opts): '''Bails out if [keyword] configuration is not active. Returns status of working directory.''' if kwt: return repo.status(match=scmutil.match(wctx, pats, opts), clean=True, unknown=opts.get('unknown') or opts.get('all')) if ui.configitems('keyword'): raise util.Abort(_('[keyword] patterns cannot match')) raise util.Abort(_('no [keyword] patterns configured'))
def _status(ui, repo, wctx, kwt, *pats, **opts): '''Bails out if [keyword] configuration is not active. Returns status of working directory.''' if kwt: return repo.status(match=scmutil.match(wctx, pats, opts), clean=True, unknown=opts.get('unknown') or opts.get('all')) if ui.configitems('keyword'): raise error.Abort(_('[keyword] patterns cannot match')) raise error.Abort(_('no [keyword] patterns configured'))
def remove_largefiles(ui, repo, *pats, **opts): after = opts.get('after') if not pats and not after: raise util.Abort(_('no files specified')) m = scmutil.match(repo[None], pats, opts) try: repo.lfstatus = True s = repo.status(match=m, clean=True) finally: repo.lfstatus = False manifest = repo[None].manifest() modified, added, deleted, clean = [[ f for f in list if lfutil.standin(f) in manifest ] for list in [s[0], s[1], s[3], s[6]]] def warn(files, reason): for f in files: ui.warn( _('not removing %s: %s (use forget to undo)\n') % (m.rel(f), reason)) if after: remove, forget = deleted, [] warn(modified + added + clean, _('file still exists')) else: remove, forget = deleted + clean, [] warn(modified, _('file is modified')) warn(added, _('file has been marked for add')) for f in sorted(remove + forget): if ui.verbose or not m.exact(f): ui.status(_('removing %s\n') % m.rel(f)) # Need to lock because standin files are deleted then removed from the # repository and we could race inbetween. wlock = repo.wlock() try: lfdirstate = lfutil.openlfdirstate(ui, repo) for f in remove: if not after: # If this is being called by addremove, notify the user that we # are removing the file. if getattr(repo, "_isaddremove", False): ui.status(_('removing %s\n') % f) if os.path.exists(repo.wjoin(f)): util.unlinkpath(repo.wjoin(f)) lfdirstate.remove(f) lfdirstate.write() forget = [lfutil.standin(f) for f in forget] remove = [lfutil.standin(f) for f in remove] lfutil.repo_forget(repo, forget) # If this is being called by addremove, let the original addremove # function handle this. if not getattr(repo, "_isaddremove", False): lfutil.repo_remove(repo, remove, unlink=True) finally: wlock.release()
def countrate(ui, repo, amap, *pats, **opts): """Calculate stats""" if opts.get('dateformat'): def getkey(ctx): t, tz = ctx.date() date = datetime.datetime(*time.gmtime(float(t) - tz)[:6]) return date.strftime(opts['dateformat']) else: tmpl = opts.get('oldtemplate') or opts.get('template') tmpl = maketemplater(ui, repo, tmpl) def getkey(ctx): ui.pushbuffer() tmpl.show(ctx) return ui.popbuffer() state = {'count': 0} rate = {} df = False if opts.get('date'): df = util.matchdate(opts['date']) m = scmutil.match(repo[None], pats, opts) def prep(ctx, fns): rev = ctx.rev() if df and not df(ctx.date()[0]): # doesn't match date format return key = getkey(ctx).strip() key = amap.get(key, key) # alias remap if opts.get('changesets'): rate[key] = (rate.get(key, (0, ))[0] + 1, 0) else: parents = ctx.parents() if len(parents) > 1: ui.note(_('revision %d is a merge, ignoring...\n') % (rev, )) return ctx1 = parents[0] lines = changedlines(ui, repo, ctx1, ctx, fns) rate[key] = [r + l for r, l in zip(rate.get(key, (0, 0)), lines)] state['count'] += 1 ui.progress(_('analyzing'), state['count'], total=len(repo), unit=_('revisions')) for ctx in cmdutil.walkchangerevs(repo, m, opts, prep): continue ui.progress(_('analyzing'), None) return rate
def remove_largefiles(ui, repo, *pats, **opts): after = opts.get('after') if not pats and not after: raise util.Abort(_('no files specified')) m = scmutil.match(repo[None], pats, opts) try: repo.lfstatus = True s = repo.status(match=m, clean=True) finally: repo.lfstatus = False manifest = repo[None].manifest() modified, added, deleted, clean = [[f for f in list if lfutil.standin(f) in manifest] for list in [s[0], s[1], s[3], s[6]]] def warn(files, reason): for f in files: ui.warn(_('not removing %s: %s (use forget to undo)\n') % (m.rel(f), reason)) if after: remove, forget = deleted, [] warn(modified + added + clean, _('file still exists')) else: remove, forget = deleted + clean, [] warn(modified, _('file is modified')) warn(added, _('file has been marked for add')) for f in sorted(remove + forget): if ui.verbose or not m.exact(f): ui.status(_('removing %s\n') % m.rel(f)) # Need to lock because standin files are deleted then removed from the # repository and we could race inbetween. wlock = repo.wlock() try: lfdirstate = lfutil.openlfdirstate(ui, repo) for f in remove: if not after: # If this is being called by addremove, notify the user that we # are removing the file. if getattr(repo, "_isaddremove", False): ui.status(_('removing %s\n' % f)) if os.path.exists(repo.wjoin(f)): util.unlinkpath(repo.wjoin(f)) lfdirstate.remove(f) lfdirstate.write() forget = [lfutil.standin(f) for f in forget] remove = [lfutil.standin(f) for f in remove] lfutil.repo_forget(repo, forget) # If this is being called by addremove, let the original addremove # function handle this. if not getattr(repo, "_isaddremove", False): lfutil.repo_remove(repo, remove, unlink=True) finally: wlock.release()
def difftree(ui, repo, node1=None, node2=None, *files, **opts): """diff trees from two commits""" def __difftree(repo, node1, node2, files=None): assert node2 is not None if files is None: files = [] mmap = repo[node1].manifest() mmap2 = repo[node2].manifest() m = scmutil.match(repo[node1], files) modified, added, removed = repo.status(node1, node2, m)[:3] empty = short(nullid) for f in modified: # TODO get file permissions ui.write((":100664 100664 %s %s M\t%s\t%s\n") % (short(mmap[f]), short(mmap2[f]), f, f)) for f in added: ui.write((":000000 100664 %s %s N\t%s\t%s\n") % (empty, short(mmap2[f]), f, f)) for f in removed: ui.write((":100664 000000 %s %s D\t%s\t%s\n") % (short(mmap[f]), empty, f, f)) ## while True: if opts[r'stdin']: line = ui.fin.readline() if not line: break line = line.rstrip(pycompat.oslinesep).split(b' ') node1 = line[0] if len(line) > 1: node2 = line[1] else: node2 = None node1 = repo.lookup(node1) if node2: node2 = repo.lookup(node2) else: node2 = node1 node1 = repo.changelog.parents(node1)[0] if opts[r'patch']: if opts[r'pretty']: catcommit(ui, repo, node2, "") m = scmutil.match(repo[node1], files) diffopts = patch.difffeatureopts(ui) diffopts.git = True chunks = patch.diff(repo, node1, node2, match=m, opts=diffopts) for chunk in chunks: ui.write(chunk) else: __difftree(repo, node1, node2, files=files) if not opts[r'stdin']: break
def add_largefiles(ui, repo, *pats, **opts): large = opts.pop("large", None) lfsize = lfutil.getminsize(ui, lfutil.islfilesrepo(repo), opts.pop("lfsize", None)) lfmatcher = None if lfutil.islfilesrepo(repo): lfpats = ui.configlist(lfutil.longname, "patterns", default=[]) if lfpats: lfmatcher = match_.match(repo.root, "", list(lfpats)) lfnames = [] m = scmutil.match(repo[None], pats, opts) m.bad = lambda x, y: None wctx = repo[None] for f in repo.walk(m): exact = m.exact(f) lfile = lfutil.standin(f) in wctx nfile = f in wctx exists = lfile or nfile # Don't warn the user when they attempt to add a normal tracked file. # The normal add code will do that for us. if exact and exists: if lfile: ui.warn(_("%s already a largefile\n") % f) continue if exact or not exists: abovemin = lfsize and os.lstat(repo.wjoin(f)).st_size >= lfsize * 1024 * 1024 if large or abovemin or (lfmatcher and lfmatcher(f)): lfnames.append(f) if ui.verbose or not exact: ui.status(_("adding %s as a largefile\n") % m.rel(f)) bad = [] standins = [] # Need to lock, otherwise there could be a race condition between # when standins are created and added to the repo. wlock = repo.wlock() try: if not opts.get("dry_run"): lfdirstate = lfutil.openlfdirstate(ui, repo) for f in lfnames: standinname = lfutil.standin(f) lfutil.writestandin(repo, standinname, hash="", executable=lfutil.getexecutable(repo.wjoin(f))) standins.append(standinname) if lfdirstate[f] == "r": lfdirstate.normallookup(f) else: lfdirstate.add(f) lfdirstate.write() bad += [lfutil.splitstandin(f) for f in lfutil.repo_add(repo, standins) if f in m.files()] finally: wlock.release() return bad
def _status(ui, repo, wctx, kwt, *pats, **opts): """Bails out if [keyword] configuration is not active. Returns status of working directory.""" if kwt: return repo.status( match=scmutil.match(wctx, pats, opts), clean=True, unknown=opts.get("unknown") or opts.get("all") ) if ui.configitems("keyword"): raise util.Abort(_("[keyword] patterns cannot match")) raise util.Abort(_("no [keyword] patterns configured"))
def perfaddremove(ui, repo, **opts): timer, fm = gettimer(ui, opts) try: oldquiet = repo.ui.quiet repo.ui.quiet = True matcher = scmutil.match(repo[None]) timer(lambda: scmutil.addremove(repo, matcher, "", dry_run=True)) finally: repo.ui.quiet = oldquiet fm.end()
def difftree(ui, repo, node1=None, node2=None, *files, **opts): """diff trees from two commits""" def __difftree(repo, node1, node2, files=[]): assert node2 is not None mmap = repo[node1].manifest() mmap2 = repo[node2].manifest() m = scmutil.match(repo[node1], files) modified, added, removed = repo.status(node1, node2, m)[:3] empty = short(nullid) for f in modified: # TODO get file permissions ui.write(":100664 100664 %s %s M\t%s\t%s\n" % (short(mmap[f]), short(mmap2[f]), f, f)) for f in added: ui.write(":000000 100664 %s %s N\t%s\t%s\n" % (empty, short(mmap2[f]), f, f)) for f in removed: ui.write(":100664 000000 %s %s D\t%s\t%s\n" % (short(mmap[f]), empty, f, f)) ## while True: if opts['stdin']: try: line = raw_input().split(' ') node1 = line[0] if len(line) > 1: node2 = line[1] else: node2 = None except EOFError: break node1 = repo.lookup(node1) if node2: node2 = repo.lookup(node2) else: node2 = node1 node1 = repo.changelog.parents(node1)[0] if opts['patch']: if opts['pretty']: catcommit(ui, repo, node2, "") m = scmutil.match(repo[node1], files) chunks = patch.diff(repo, node1, node2, match=m, opts=patch.diffopts(ui, {'git': True})) for chunk in chunks: ui.write(chunk) else: __difftree(repo, node1, node2, files=files) if not opts['stdin']: break
def gather_metrics(ui, repo, *pats, **opts): # This is my code to gather what we need for metrics state = {'count': 0} metrics = {} df = False if opts.get('date'): df = util.matchdate(opts['date']) m = scmutil.match(repo[None], pats, opts) def walker(ctx, fns): #import pdb #pdb.set_trace() # Verify that this change is inside our date # These are passed into the match and walker functions via the opts param # Not sure this is needed, but churn had it, so keeping for now # TODO: Experiment with whether this extra check is necessary if df and not df(ctx.date()[0]): return # Create the chgset's object in our tracker chgsetID = ctx.hex() metrics[chgsetID] = {} metrics[chgsetID]['is_merge'] = len(ctx.parents()) > 1 ctx1 = ctx.parents()[0] metrics[chgsetID]['parents'] = ctx.parents()[0].hex() user = ctx.user() metrics[chgsetID]['committer'] = user metrics[chgsetID]['committer_email'] = user[user.find('<') + 1:user.find('>')] metrics[chgsetID]['committer_name'] = user.split('<')[0].strip() t, tz = ctx.date() d = datetime.datetime(*time.gmtime(float(t) - tz)[:6]) metrics[chgsetID]['datestamp'] = d.strftime('%Y-%m-%dT%H:%M:%SZ') # If we have a robot committer, don't bother parsing the commit message metrics[chgsetID]['msg'] = ctx.description() if '*****@*****.**' not in user: metrics[chgsetID]['bug'], metrics[chgsetID]['is_backout'], \ metrics[chgsetID]['backout_rev'], metrics[chgsetID]['reviewer'], \ metrics[chgsetID]['approver'] = parse_commit_msg(ctx.description()) metrics[chgsetID]['files'] = get_lines_and_files( ui, repo, ctx1, ctx, fns) state['count'] += 1 ui.progress(_('analyzing'), state['count'], total=len(repo)) for ctx in cmdutil.walkchangerevs(repo, m, opts, walker): continue ui.progress(_('analyzing'), None) return metrics
def commitextra(ui, repo, *pats, **opts): '''make a commit with extra fields''' fields = opts.get('field') extras = {} for field in fields: k, v = field.split('=', 1) extras[k] = v message = cmdutil.logmessage(ui, opts) repo.commit(message, opts.get('user'), opts.get('date'), match=scmutil.match(repo[None], pats, opts), extra=extras) return 0
def countrate(ui, repo, amap, *pats, **opts): """Calculate stats""" if opts.get("dateformat"): def getkey(ctx): t, tz = ctx.date() date = datetime.datetime(*time.gmtime(float(t) - tz)[:6]) return date.strftime(opts["dateformat"]) else: tmpl = opts.get("template", "{author|email}") tmpl = maketemplater(ui, repo, tmpl) def getkey(ctx): ui.pushbuffer() tmpl.show(ctx) return ui.popbuffer() state = {"count": 0} rate = {} df = False if opts.get("date"): df = util.matchdate(opts["date"]) m = scmutil.match(repo[None], pats, opts) def prep(ctx, fns): rev = ctx.rev() if df and not df(ctx.date()[0]): # doesn't match date format return key = getkey(ctx).strip() key = amap.get(key, key) # alias remap if opts.get("changesets"): rate[key] = (rate.get(key, (0,))[0] + 1, 0) else: parents = ctx.parents() if len(parents) > 1: ui.note(_("Revision %d is a merge, ignoring...\n") % (rev,)) return ctx1 = parents[0] lines = changedlines(ui, repo, ctx1, ctx, fns) rate[key] = [r + l for r, l in zip(rate.get(key, (0, 0)), lines)] state["count"] += 1 ui.progress(_("analyzing"), state["count"], total=len(repo)) for ctx in cmdutil.walkchangerevs(repo, m, opts, prep): continue ui.progress(_("analyzing"), None) return rate
def gather_metrics(ui, repo, *pats, **opts): # This is my code to gather what we need for metrics state = {'count': 0} metrics = {} df = False if opts.get('date'): df = util.matchdate(opts['date']) m = scmutil.match(repo[None], pats, opts) def walker(ctx, fns): #import pdb #pdb.set_trace() # Verify that this change is inside our date # These are passed into the match and walker functions via the opts param # Not sure this is needed, but churn had it, so keeping for now # TODO: Experiment with whether this extra check is necessary if df and not df(ctx.date()[0]): return # Create the chgset's object in our tracker chgsetID = ctx.hex() metrics[chgsetID] = {} metrics[chgsetID]['is_merge'] = len(ctx.parents()) > 1 ctx1 = ctx.parents()[0] metrics[chgsetID]['parents'] = ctx.parents()[0].hex() user = ctx.user() metrics[chgsetID]['committer'] = user metrics[chgsetID]['committer_email'] = user[user.find('<')+1:user.find('>')] metrics[chgsetID]['committer_name'] = user.split('<')[0].strip() t, tz = ctx.date() d = datetime.datetime(*time.gmtime(float(t) - tz)[:6]) metrics[chgsetID]['datestamp'] = d.strftime('%Y-%m-%dT%H:%M:%SZ') # If we have a robot committer, don't bother parsing the commit message metrics[chgsetID]['msg'] = ctx.description() if '*****@*****.**' not in user: metrics[chgsetID]['bug'], metrics[chgsetID]['is_backout'], \ metrics[chgsetID]['backout_rev'], metrics[chgsetID]['reviewer'], \ metrics[chgsetID]['approver'] = parse_commit_msg(ctx.description()) metrics[chgsetID]['files'] = get_lines_and_files(ui, repo, ctx1, ctx, fns) state['count'] += 1 ui.progress(_('analyzing'), state['count'], total=len(repo)) for ctx in cmdutil.walkchangerevs(repo, m, opts, walker): continue ui.progress(_('analyzing'), None) return metrics
def getstandinmatcher(repo, pats=[], opts={}): '''Return a match object that applies pats to the standin directory''' standindir = repo.wjoin(shortname) if pats: pats = [os.path.join(standindir, pat) for pat in pats] else: # no patterns: relative to repo root pats = [standindir] # no warnings about missing files or directories match = scmutil.match(repo[None], pats, opts) match.bad = lambda f, msg: None return match
def difftree(ui, repo, node1=None, node2=None, *files, **opts): """diff trees from two commits""" def __difftree(repo, node1, node2, files=[]): assert node2 is not None mmap = repo[node1].manifest() mmap2 = repo[node2].manifest() m = scmutil.match(repo[node1], files) modified, added, removed = repo.status(node1, node2, m)[:3] empty = short(nullid) for f in modified: # TODO get file permissions ui.write(":100664 100664 %s %s M\t%s\t%s\n" % (short(mmap[f]), short(mmap2[f]), f, f)) for f in added: ui.write(":000000 100664 %s %s N\t%s\t%s\n" % (empty, short(mmap2[f]), f, f)) for f in removed: ui.write(":100664 000000 %s %s D\t%s\t%s\n" % (short(mmap[f]), empty, f, f)) ## while True: if opts['stdin']: try: line = raw_input().split(' ') node1 = line[0] if len(line) > 1: node2 = line[1] else: node2 = None except EOFError: break node1 = repo.lookup(node1) if node2: node2 = repo.lookup(node2) else: node2 = node1 node1 = repo.changelog.parents(node1)[0] if opts['patch']: if opts['pretty']: catcommit(ui, repo, node2, "") m = scmutil.match(repo[node1], files) diffopts = patch.difffeatureopts(ui) diffopts.git = True chunks = patch.diff(repo, node1, node2, match=m, opts=diffopts) for chunk in chunks: ui.write(chunk) else: __difftree(repo, node1, node2, files=files) if not opts['stdin']: break
def debugbuildannotatecache(ui, repo, *pats, **opts): """incrementally build fastannotate cache up to REV for specified files If REV is not specified, use the config 'fastannotate.mainbranch'. If fastannotate.client is True, download the annotate cache from the server. Otherwise, build the annotate cache locally. The annotate cache will be built using the default diff and follow options and lives in '.hg/fastannotate/default'. """ opts = pycompat.byteskwargs(opts) rev = opts.get(b'REV') or ui.config(b'fastannotate', b'mainbranch') if not rev: raise error.Abort( _(b'you need to provide a revision'), hint=_(b'set fastannotate.mainbranch or use --rev'), ) if ui.configbool(b'fastannotate', b'unfilteredrepo'): repo = repo.unfiltered() ctx = scmutil.revsingle(repo, rev) m = scmutil.match(ctx, pats, opts) paths = list(ctx.walk(m)) if util.safehasattr(repo, 'prefetchfastannotate'): # client if opts.get(b'REV'): raise error.Abort(_(b'--rev cannot be used for client')) repo.prefetchfastannotate(paths) else: # server, or full repo progress = ui.makeprogress(_(b'building'), total=len(paths)) for i, path in enumerate(paths): progress.update(i) with facontext.annotatecontext(repo, path) as actx: try: if actx.isuptodate(rev): continue actx.annotate(rev, rev) except (faerror.CannotReuseError, faerror.CorruptedFileError): # the cache is broken (could happen with renaming so the # file history gets invalidated). rebuild and try again. ui.debug(b'fastannotate: %s: rebuilding broken cache\n' % path) actx.rebuild() try: actx.annotate(rev, rev) except Exception as ex: # possibly a bug, but should not stop us from building # cache for other files. ui.warn( _(b'fastannotate: %s: failed to ' b'build cache: %r\n') % (path, ex)) progress.complete()
def overridecat(orig, ui, repo, file1, *pats, **opts): ctx = scmutil.revsingle(repo, opts.get('rev')) err = 1 notbad = set() m = scmutil.match(ctx, (file1, ) + pats, opts) origmatchfn = m.matchfn def lfmatchfn(f): if origmatchfn(f): return True lf = lfutil.splitstandin(f) if lf is None: return False notbad.add(lf) return origmatchfn(lf) m.matchfn = lfmatchfn origbadfn = m.bad def lfbadfn(f, msg): if not f in notbad: origbadfn(f, msg) m.bad = lfbadfn for f in ctx.walk(m): fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(), pathname=f) lf = lfutil.splitstandin(f) if lf is None or origmatchfn(f): # duplicating unreachable code from commands.cat data = ctx[f].data() if opts.get('decode'): data = repo.wwritedata(f, data) fp.write(data) else: hash = lfutil.readstandin(repo, lf, ctx.rev()) if not lfutil.inusercache(repo.ui, hash): store = basestore._openstore(repo) success, missing = store.get([(lf, hash)]) if len(success) != 1: raise util.Abort( _('largefile %s is not in cache and could not be ' 'downloaded') % lf) path = lfutil.usercachepath(repo.ui, hash) fpin = open(path, "rb") for chunk in util.filechunkiter(fpin, 128 * 1024): fp.write(chunk) fpin.close() fp.close() err = 0 return err
def run(self): self.repo.dirstate.invalidate() extract = lambda x, y: dict(zip(x, map(y.get, x))) stopts = extract(('unknown', 'ignored', 'clean'), self.opts) patchecked = {} try: if self.pats: if self.opts.get('checkall'): # quickop sets this flag to pre-check even !?IC files precheckfn = lambda x: True else: # status and commit only pre-check MAR files precheckfn = lambda x: x < 4 m = scmutil.match(self.repo[None], self.pats) self.repo.bfstatus = True self.repo.lfstatus = True status = self.repo.status(match=m, **stopts) self.repo.bfstatus = False self.repo.lfstatus = False # Record all matched files as initially checked for i, stat in enumerate(StatusType.preferredOrder): if stat == 'S': continue val = statusTypes[stat] if self.opts[val.name]: d = dict([(fn, precheckfn(i)) for fn in status[i]]) patchecked.update(d) wctx = context.workingctx(self.repo, changes=status) self.patchecked = patchecked elif self.pctx: self.repo.bfstatus = True self.repo.lfstatus = True status = self.repo.status(node1=self.pctx.p1().node(), **stopts) self.repo.bfstatus = False self.repo.lfstatus = False wctx = context.workingctx(self.repo, changes=status) else: wctx = self.repo[None] self.repo.bfstatus = True self.repo.lfstatus = True wctx.status(**stopts) self.repo.bfstatus = False self.repo.lfstatus = False self.wctx = wctx wctx.dirtySubrepos = [] for s in wctx.substate: if wctx.sub(s).dirty(): wctx.dirtySubrepos.append(s) except EnvironmentError, e: self.showMessage.emit(hglib.tounicode(str(e)))
def revert(orig, ui, repo, ctx, parents, *pats, **opts): # prefetch prior to reverting # used for old mercurial version if shallowrepo.requirement in repo.requirements: files = [] m = scmutil.match(ctx, pats, opts) mf = ctx.manifest() m.bad = lambda x, y: False for path in ctx.walk(m): files.append((path, hex(mf[path]))) repo.fileservice.prefetch(files) return orig(ui, repo, ctx, parents, *pats, **opts)
def _status(ui, repo, wctx, kwt, *pats, **opts): """Bails out if [keyword] configuration is not active. Returns status of working directory.""" if kwt: opts = pycompat.byteskwargs(opts) return repo.status( match=scmutil.match(wctx, pats, opts), clean=True, unknown=opts.get(b'unknown') or opts.get(b'all'), ) if ui.configitems(b'keyword'): raise error.Abort(_(b'[keyword] patterns cannot match')) raise error.Abort(_(b'no [keyword] patterns configured'))
def find_files_with_lib(dirname): """ Use the Mercurial library to recursively find versioned files in dirname. """ try: try: repo = hg.repository(ui.ui(), path=dirname) except RepoError: return # tuple of (modified, added, removed, deleted, unknown, ignored, clean) modified, added, removed, deleted, unknown = repo.status()[:5] # exclude all files that hg knows about, but haven't been added, # or have been deleted, removed, or have an unknown status excluded = removed + deleted + unknown if version in OLD_VERSIONS: from mercurial import util node = None for src, abs, rel, exact in cmdutil.walk(repo, [], {}, node=node, badmatch=util.always, default='relglob'): if src == 'b': continue if not node and abs not in repo.dirstate: continue if abs in excluded: continue yield abs else: rev = None try: match = cmdutil.match(repo, [], {}, default='relglob') except: # Probably mercurial 1.8+ from mercurial import scmutil match = scmutil.match(repo[None], [], {}, default='relglob') match.bad = lambda x, y: False for abs in repo[rev].walk(match): if not rev and abs not in repo.dirstate: continue if abs in excluded: continue yield abs except Exception: if log: log.warn("Error in setuptools_hg: %s" % sys.exc_info()[1]) # try calling hg command as a last resort find_files_with_cmd(dirname)
def getmatcher(repo, pats=[], opts={}, showbad=True): """Wrapper around scmutil.match() that adds showbad: if false, neuter the match object\'s bad() method so it does not print any warnings about missing files or directories.""" try: # Mercurial >= 1.9 match = scmutil.match(repo[None], pats, opts) except ImportError: # Mercurial <= 1.8 match = cmdutil.match(repo, pats, opts) if not showbad: match.bad = lambda f, msg: None return match
def prep(ctx, fns): rev = ctx.rev() parents = [p for p in repo.changelog.parentrevs(rev) if p != nullrev] if opts.get('no_merges') and len(parents) == 2: return if opts.get('only_merges') and len(parents) != 2: return if opts.get('branch') and ctx.branch() not in opts['branch']: return if not opts.get('hidden') and ctx.hidden(): return if df and not df(ctx.date()[0]): return lower = encoding.lower if opts.get('user'): luser = lower(ctx.user()) for k in [lower(x) for x in opts['user']]: if (k in luser): break else: return if opts.get('keyword'): luser = lower(ctx.user()) ldesc = lower(ctx.description()) lfiles = lower(" ".join(ctx.files())) for k in [lower(x) for x in opts['keyword']]: if (k in luser or k in ldesc or k in lfiles): break else: return copies = None if getrenamed is not None and rev: copies = [] for fn in ctx.files(): rename = getrenamed(fn, rev) if rename: copies.append((fn, rename[0])) revmatchfn = None if opts.get('patch') or opts.get('stat'): if opts.get('follow') or opts.get('follow_first'): # note: this might be wrong when following through merges revmatchfn = scmutil.match(repo[None], fns, default='path') else: revmatchfn = matchfn displayer.show(ctx, copies=copies, matchfn=revmatchfn)
def find_files_with_lib(dirname): """ Use the Mercurial library to recursively find versioned files in dirname. """ try: try: repo = hg.repository(ui.ui(), path=dirname) except RepoError: return # tuple of (modified, added, removed, deleted, unknown, ignored, clean) modified, added, removed, deleted, unknown = repo.status()[:5] # exclude all files that hg knows about, but haven't been added, # or have been deleted, removed, or have an unknown status excluded = removed + deleted + unknown if version in OLD_VERSIONS: from mercurial import util node = None for src, abs, rel, exact in cmdutil.walk(repo, [], {}, node=node, badmatch=util.always, default="relglob"): if src == "b": continue if not node and abs not in repo.dirstate: continue if abs in excluded: continue yield abs else: rev = None try: match = cmdutil.match(repo, [], {}, default="relglob") except: # Probably mercurial 1.8+ from mercurial import scmutil match = scmutil.match(repo[None], [], {}, default="relglob") match.bad = lambda x, y: False for abs in repo[rev].walk(match): if not rev and abs not in repo.dirstate: continue if abs in excluded: continue yield abs except Exception, e: if log: log.warn("Error in setuptools_hg: %s" % e) # try calling hg command as a last resort find_files_with_cmd(dirname)
def _resolve(orig, ui, repo, *pats, **opts): # This block is duplicated from commands.py to maintain behavior. flaglist = 'all mark unmark list no_status'.split() all, mark, unmark, show, nostatus = \ [opts.get(o) for o in flaglist] if (show and (mark or unmark)) or (mark and unmark): raise error.Abort(_("too many options specified")) if pats and all: raise error.Abort(_("can't specify --all and patterns")) if not (all or pats or show or mark or unmark): raise error.Abort(_('no files or directories specified'), hint=('use --all to re-merge all unresolved files')) # </duplication> if not show and opts.get('tool', '') == "internal:dumpjson": formatter = ui.formatter('resolve', {'template': 'json'}) mergestate = mergemod.mergestate.read(repo) matcher = scmutil.match(repo[None], pats, opts) workingctx = repo[None] fileconflicts = [] pathconflicts = [] for path in mergestate: if not matcher(path): continue info = _summarizefileconflicts(mergestate, path, workingctx) if info is not None: fileconflicts.append(info) info = _summarizepathconflicts(mergestate, path) if info is not None: pathconflicts.append(info) cmd = _findconflictcommand(repo) formatter.startitem() formatter.write('conflicts', '%s\n', fileconflicts) formatter.write('pathconflicts', '%s\n', pathconflicts) formatter.write('command', '%s\n', _findconflictcommand(repo)) if cmd: formatter.write('command', '%s\n', cmd['cmd']) # Deprecated formatter.write('command_details', '%s\n', cmd) else: formatter.write('command', '%s\n', None) # For BC formatter.end() return 0 return orig(ui, repo, *pats, **opts)
def debugbuildannotatecache(ui, repo, *pats, **opts): """incrementally build fastannotate cache up to REV for specified files If REV is not specified, use the config 'fastannotate.mainbranch'. If fastannotate.client is True, download the annotate cache from the server. Otherwise, build the annotate cache locally. The annotate cache will be built using the default diff and follow options and lives in '.hg/fastannotate/default'. """ rev = opts.get('REV') or ui.config('fastannotate', 'mainbranch') if not rev: raise error.Abort(_('you need to provide a revision'), hint=_('set fastannotate.mainbranch or use --rev')) if ui.configbool('fastannotate', 'unfilteredrepo', True): repo = repo.unfiltered() ctx = scmutil.revsingle(repo, rev) m = scmutil.match(ctx, pats, opts) paths = list(ctx.walk(m)) if util.safehasattr(repo, 'prefetchfastannotate'): # client if opts.get('REV'): raise error.Abort(_('--rev cannot be used for client')) repo.prefetchfastannotate(paths) else: # server, or full repo for i, path in enumerate(paths): ui.progress(_('building'), i, total=len(paths)) with facontext.annotatecontext(repo, path) as actx: try: if actx.isuptodate(rev): continue actx.annotate(rev, rev) except (faerror.CannotReuseError, faerror.CorruptedFileError): # the cache is broken (could happen with renaming so the # file history gets invalidated). rebuild and try again. ui.debug('fastannotate: %s: rebuilding broken cache\n' % path) actx.rebuild() try: actx.annotate(rev, rev) except Exception as ex: # possibly a bug, but should not stop us from building # cache for other files. ui.warn(_('fastannotate: %s: failed to ' 'build cache: %r\n') % (path, ex)) # clear the progress bar ui.write()