def revset_fromgit(repo, subset, x): '''``fromgit()`` Select changesets that originate from Git. ''' revset.getargs(x, 0, 0, "fromgit takes no arguments") git = repo.githandler node = repo.changelog.node return [r for r in subset if git.map_git_get(hex(node(r))) is not None]
def fxheadsrevset(repo, subset, x): """``fxheads()`` Last known head commits of pulled Firefox trees. """ revset.getargs(x, 0, 0, _("fxheads takes no arguments")) r = revset.baseset(repo[node].rev() for t, node, tr, u in get_firefoxtrees(repo)) return r & subset
def _revsetdestrebase(repo, subset, x): # ``_rebasedefaultdest()`` # default destination for rebase. # # XXX: Currently private because I expect the signature to change. # # XXX: - taking rev as arguments, # # XXX: - bailing out in case of ambiguity vs returning all data. # # XXX: - probably merging with the merge destination. # i18n: "_rebasedefaultdest" is a keyword revset.getargs(x, 0, 0, _("_rebasedefaultdest takes no arguments")) return subset & revset.baseset([_destrebase(repo)])
def revset_fromsvn(repo, subset, x): '''``fromsvn()`` Select changesets that originate from Subversion. ''' revset.getargs(x, 0, 0, "fromsvn takes no arguments") meta = repo.svnmeta(skiperrorcheck=True) if not meta.revmapexists: raise error.Abort("svn metadata is missing - " "run 'hg svn rebuildmeta' to reconstruct it") tonode = repo.changelog.node hashes = meta.revmap.hashes() return subset.filter(lambda r: tonode(r) in hashes)
def revset_svnrev(repo, subset, x): '''``svnrev(number)`` Select changesets that originate in the given Subversion revision. ''' args = revset.getargs(x, 1, 1, "svnrev takes one argument") rev = revset.getstring(args[0], "the argument to svnrev() must be a number") try: revnum = int(rev) except ValueError: raise error.ParseError("the argument to svnrev() must be a number") rev = rev + ' ' revs = [] meta = repo.svnmeta(skiperrorcheck=True) try: for l in maps.RevMap.readmapfile(meta.revmap_file, missingok=False): if l.startswith(rev): n = l.split(' ', 2)[1] r = repo[node.bin(n)].rev() if r in subset: revs.append(r) return revs except IOError, err: if err.errno != errno.ENOENT: raise raise hgutil.Abort("svn metadata is missing - " "run 'hg svn rebuildmeta' to reconstruct it")
def revset_gitnode(repo, subset, x): '''``gitnode(hash)`` Select the changeset that originates in the given Git revision. The hash may be abbreviated: `gitnode(a5b)` selects the revision whose Git hash starts with `a5b`. Aborts if multiple changesets match the abbreviation. ''' args = revset.getargs(x, 1, 1, b"gitnode takes one argument") rev = revset.getstring(args[0], b"the argument to gitnode() must be a hash") git = repo.githandler node = repo.changelog.node def matches(r): gitnode = git.map_git_get(hex(node(r))) if gitnode is None: return False return gitnode.startswith(rev) result = revset.baseset(r for r in subset if matches(r)) if 0 <= len(result) < 2: return result raise error.AmbiguousPrefixLookupError( rev, git.map_file, _(b'ambiguous identifier'), )
def grepdiffpredicate(repo, subset, x): """grepdiff: a revset for code archeology Sample usages are: $ hg log --rev "grepdiff('add:command')" mercurial/commands.py will only match changesets that add 'command' somewhere in the diff $ hg log --rev "grepdiff('remove:command')" mercurial/commands.py will match changesets which remove 'command' somewhere in the diff $ hg log --rev "grepdiff('delta:command') mercurial/commands.py" will mathc changesets where the number of 'command' adds is different from the number of 'command' removes in the diff $ hg log --rev "grepdiff('touch:command')" will only match changesets which either add or remove 'command' at least once in the diff $ hg log --rev "grepdiff('inc:command')" folder/file1.py folder/file2.py will match changesets which increase the number of occurrences of 'command' in the specified files $ hg log --rev "grepdiff('dec:command')" will match changesets which decrease the number of occurrences of 'command' """ err = _("wrong set of arguments passed to grepdiff revset") args = revset.getargs(x, 1, -1, err) files = None if len(args) > 1: files = set(pathutil.canonpath(repo.root, repo.getcwd(), arg[1]) for arg in args[1:]) pattern, processor = getpatternandprocessor(repo, args) def matcher(rev): res = processor(*ctxaddsremoves(repo[rev], files, pattern)) return res resset = subset.filter(matcher) return resset
def remotebranchesrevset(repo, subset, x): """``remotebranches()`` All remote branches heads. """ args = revset.getargs(x, 0, 0, "remotebranches takes no arguments") remoterevs = set(repo[n].rev() for n in repo._remotebranches.itervalues()) return baseset([r for r in subset if r in remoterevs])
def revset_pushid(repo, subset, x): """``pushid(int)`` Changesets that were part of the specified numeric push id. """ l = revset.getargs(x, 1, 1, 'pushid requires one argument') try: pushid = int(revset.getstring(l[0], 'pushid requires a number')) except (TypeError, ValueError): raise error.ParseError('pushid expects a number') with repo.pushlog.conn(readonly=True) as conn: push = repo.pushlog.pushfromid(conn, pushid) if conn else None if not push: return revset.baseset() to_rev = repo.changelog.rev pushrevs = set() for node in push.nodes: try: pushrevs.add(to_rev(bin(node))) except RepoLookupError: pass return subset & pushrevs
def revset_fromgit(repo, subset, x): '''``fromgit()`` Select changesets that originate from Git. ''' args = revset.getargs(x, 0, 0, "fromgit takes no arguments") git = GitHandler(repo, repo.ui) return [r for r in subset if git.map_git_get(repo[r].hex()) is not None]
def revset_pushhead(repo, subset, x): """Changesets that were heads when they were pushed. A push head is a changeset that was a head at the time it was pushed. """ revset.getargs(x, 0, 0, 'pushhead takes no arguments') # Iterating over all pushlog data is unfortunate, as there is overhead # involved. However, this is less overhead than issuing a SQL query for # every changeset, especially on large repositories. There is room to make # this optimal by batching SQL, but that adds complexity. For now, # simplicity wins. def getrevs(): for push in repo.pushlog.pushes(): yield repo[push.nodes[-1]].rev() return subset & revset.generatorset(getrevs())
def revset_pushhead(repo, subset, x): """``pushhead()`` Changesets that were heads when they were pushed. A push head is a changeset that was a head at the time it was pushed. """ revset.getargs(x, 0, 0, 'pushhead takes no arguments') # Iterating over all pushlog data is unfortunate, as there is overhead # involved. However, this is less overhead than issuing a SQL query for # every changeset, especially on large repositories. There is room to make # this optimal by batching SQL, but that adds complexity. For now, # simplicity wins. def getrevs(): for pushid, who, when, nodes in repo.pushlog.pushes(): yield repo[nodes[-1]].rev() return subset & revset.generatorset(getrevs())
def revset_fromsvn(repo, subset, x): '''``fromsvn()`` Select changesets that originate from Subversion. ''' args = revset.getargs(x, 0, 0, "fromsvn takes no arguments") def matches(r): convertinfo = repo[r].extra().get('convert_revision', '') return convertinfo[:4] == 'svn:' return [r for r in subset if matches(r)]
def upstream(repo, subset, x): """``upstream()`` Select changesets in an upstream repository according to remotebranches. """ args = revset.getargs(x, 0, 0, "upstream takes no arguments") upstream_names = [s + "/" for s in repo.ui.configlist("remotebranches", "upstream")] if not upstream_names: filt = lambda x: True else: filt = lambda name: any(map(name.startswith, upstream_names)) return upstream_revs(filt, repo, subset, x)
def gitnode(repo, subset, x): """``gitnode(id)`` Return the hg revision corresponding to a given git rev.""" l = revset.getargs(x, 1, 1, _("id requires one argument")) n = revset.getstring(l[0], _("id requires a string")) hexhgnode = _lookup_node(repo, n, from_scm_type='git') if not hexhgnode: raise error.RepoLookupError(_("unknown revision '%s'") % n) rev = repo[hexhgnode].rev() return subset.filter(lambda r: r == rev)
def upstream(repo, subset, x): '''``upstream()`` Select changesets in an upstream repository according to remotebranches. ''' args = revset.getargs(x, 0, 0, "upstream takes no arguments") upstream_names = [s + '/' for s in repo.ui.configlist('remotebranches', 'upstream')] if not upstream_names: filt = lambda x: True else: filt = lambda name: any(map(name.startswith, upstream_names)) return upstream_revs(filt, repo, subset, x)
def revset_pushdate(repo, subset, x): """Changesets that were pushed within the interval, see :hg:`help dates`.""" l = revset.getargs(x, 1, 1, 'pushdate requires one argument') ds = revset.getstring(l[0], 'pushdate requires a string argument') dm = util.matchdate(ds) def getrevs(): for push in repo.pushlog.pushes(): if dm(push.when): for node in push.nodes: yield repo[node].rev() return subset & revset.generatorset(getrevs())
def revset_gitnode(repo, subset, x): '''``gitnode(hash)`` Select changesets that originate in the given Git revision. ''' args = revset.getargs(x, 1, 1, "gitnode takes one argument") rev = revset.getstring(args[0], "the argument to gitnode() must be a hash") git = GitHandler(repo, repo.ui) def matches(r): gitnode = git.map_git_get(repo[r].hex()) if gitnode is None: return False return rev in [gitnode, gitnode[:12]] return [r for r in subset if matches(r)]
def revset_pushdate(repo, subset, x): """``pushdate(interval)`` Changesets that were pushed within the interval, see :hg:`help dates`. """ l = revset.getargs(x, 1, 1, 'pushdate requires one argument') ds = revset.getstring(l[0], 'pushdate requires a string argument') dm = util.matchdate(ds) def getrevs(): for pushid, who, when, nodes in repo.pushlog.pushes(): if dm(when): for node in nodes: yield repo[node].rev() return subset & revset.generatorset(getrevs())
def bmrevset(repo, subset, x): """``bookmark([name])`` The named bookmark or all bookmarks. """ # i18n: "bookmark" is a keyword args = revset.getargs(x, 0, 1, _('bookmark takes one or no arguments')) if args: bm = revset.getstring(args[0], # i18n: "bookmark" is a keyword _('the argument to bookmark must be a string')) bmrev = listbookmarks(repo).get(bm, None) if bmrev: bmrev = repo.changelog.rev(bin(bmrev)) return [r for r in subset if r == bmrev] bms = set([repo.changelog.rev(bin(r)) for r in listbookmarks(repo).values()]) return [r for r in subset if r in bms]
def revset_reviewer(repo, subset, x): """``reviewer(REVIEWER)`` Changesets reviewed by a specific person. """ l = revset.getargs(x, 1, 1, 'reviewer requires one argument') n = encoding.lower(revset.getstring(l[0], 'reviewer requires a string')) # Do not use a matcher here because regular expressions are not safe # for remote execution and may DoS the server. def hasreviewer(r): for reviewer in commitparser.parse_reviewers(repo[r].description()): if encoding.lower(reviewer) == n: return True return False return subset.filter(hasreviewer)
def revset_reviewer(repo, subset, x): """``reviewer(REVIEWER)`` Changesets reviewed by a specific person. """ l = revset.getargs(x, 1, 1, b'reviewer requires one argument') n = encoding.lower(revset.getstring(l[0], b'reviewer requires a string')) # Do not use a matcher here because regular expressions are not safe # for remote execution and may DoS the server. def hasreviewer(r): for reviewer in commitparser.parse_reviewers(repo[r].description()): if encoding.lower(reviewer) == n: return True return False return subset.filter(hasreviewer)
def revset_pushdate(repo, subset, x): """``pushdate(interval)`` Changesets that were pushed within the interval. See :hg:`help dates`. """ l = revset.getargs(x, 1, 1, 'pushdate requires one argument') ds = revset.getstring(l[0], 'pushdate requires a string argument') dm = dateutil.matchdate(ds) def getrevs(): to_rev = repo.changelog.rev for push in repo.pushlog.pushes(): if dm(push.when): for node in push.nodes: yield to_rev(bin(node)) return subset & revset.generatorset(getrevs())
def revset_fromsvn(repo, subset, x): '''``fromsvn()`` Select changesets that originate from Subversion. ''' args = revset.getargs(x, 0, 0, "fromsvn takes no arguments") rev = repo.changelog.rev bin = node.bin meta = repo.svnmeta(skiperrorcheck=True) try: svnrevs = set(rev(bin(l.split(' ', 2)[1])) for l in maps.RevMap.readmapfile(meta.revmap_file, missingok=False)) return filter(svnrevs.__contains__, subset) except IOError, err: if err.errno != errno.ENOENT: raise raise hgutil.Abort("svn metadata is missing - " "run 'hg svn rebuildmeta' to reconstruct it")
def revset_fromsvn(repo, subset, x): '''``fromsvn()`` Select changesets that originate from Subversion. ''' args = revset.getargs(x, 0, 0, "fromsvn takes no arguments") rev = repo.changelog.rev bin = node.bin meta = repo.svnmeta(skiperrorcheck=True) try: svnrevs = set( rev(bin(l.split(' ', 2)[1])) for l in maps.RevMap.readmapfile( meta.revmap_file, missingok=False)) return filter(svnrevs.__contains__, subset) except IOError, err: if err.errno != errno.ENOENT: raise raise hgutil.Abort("svn metadata is missing - " "run 'hg svn rebuildmeta' to reconstruct it")
def revset_svnrev(repo, subset, x): '''``svnrev(number)`` Select changesets that originate in the given Subversion revision. ''' args = revset.getargs(x, 1, 1, "svnrev takes one argument") rev = revset.getstring(args[0], "the argument to svnrev() must be a number") try: rev = int(rev) except ValueError: raise error.ParseError("the argument to svnrev() must be a number") def matches(r): convertinfo = repo[r].extra().get('convert_revision', '') if convertinfo[:4] != 'svn:': return False return int(convertinfo[40:].rsplit('@', 1)[-1]) == rev return [r for r in subset if matches(r)]
def revset_svnrev(repo, subset, x): '''``svnrev(number)`` Select changesets that originate in the given Subversion revision. ''' args = revset.getargs(x, 1, 1, "svnrev takes one argument") rev = revset.getstring(args[0], "the argument to svnrev() must be a number") try: revnum = int(rev) except ValueError: raise error.ParseError("the argument to svnrev() must be a number") meta = repo.svnmeta(skiperrorcheck=True) if not meta.revmapexists: raise error.Abort("svn metadata is missing - " "run 'hg svn rebuildmeta' to reconstruct it") torev = repo.changelog.rev revs = revset.baseset(torev(r) for r in meta.revmap.revhashes(revnum)) return subset & revs
def revset_pushuser(repo, subset, x): """User name that pushed the changeset contains string. The match is case-insensitive. If `string` starts with `re:`, the remainder of the string is treated as a regular expression. To match a user that actually contains `re:`, use the prefix `literal:`. """ l = revset.getargs(x, 1, 1, 'pushuser requires one argument') n = encoding.lower(revset.getstring(l[0], 'pushuser requires a string')) kind, pattern, matcher = revset._substringmatcher(n) def getrevs(): for push in repo.pushlog.pushes(): if matcher(encoding.lower(push.user)): for node in push.nodes: yield repo[node].rev() return subset & revset.generatorset(getrevs())
def revset_pushuser(repo, subset, x): """``pushuser(string)`` User name that pushed the changeset contains string. The match is case-insensitive. If `string` starts with `re:`, the remainder of the string is treated as a regular expression. To match a user that actually contains `re:`, use the prefix `literal:`. """ l = revset.getargs(x, 1, 1, 'pushuser requires one argument') n = encoding.lower(revset.getstring(l[0], 'pushuser requires a string')) kind, pattern, matcher = revset._substringmatcher(n) def getrevs(): for pushid, who, when, nodes in repo.pushlog.pushes(): if matcher(encoding.lower(who)): for node in nodes: yield repo[node].rev() return subset & revset.generatorset(getrevs())
def gitnode(repo, subset, x): """``gitnode(id)`` Return the hg revision corresponding to a given git rev.""" l = revset.getargs(x, 1, 1, _("id requires one argument")) n = revset.getstring(l[0], _("id requires a string")) reponame = repo.ui.config('fbconduit', 'reponame') if not reponame: # We don't know who we are, so we can't ask for a translation return subset.filter(lambda r: False) backingrepos = repo.ui.configlist('fbconduit', 'backingrepos', default=[reponame]) lasterror = None hghash = None for backingrepo in backingrepos: try: result = call_conduit('scmquery.get.mirrored.revs', from_repo=backingrepo, from_scm='git', to_repo=reponame, to_scm='hg', revs=[n] ) hghash = result[n] if hghash != '': break except Exception as ex: lasterror = ex if not hghash: if lasterror: repo.ui.warn(("Could not translate revision {0}: {1}\n".format( n, lasterror))) else: repo.ui.warn(("Could not translate revision {0}\n".format(n))) return subset.filter(lambda r: False) rn = repo[node.bin(hghash)].rev() return subset.filter(lambda r: r == rn)
def revset_gittag(repo, subset, x): """``gittag([name])`` The specified Git tag by name, or all revisions tagged with Git if no name is given. Pattern matching is supported for `name`. See :hg:`help revisions.patterns`. """ # mostly copied from tag() mercurial/revset.py # i18n: "tag" is a keyword args = revset.getargs(x, 0, 1, _(b"tag takes one or no arguments")) cl = repo.changelog git = repo.githandler if args: pattern = revset.getstring( args[0], # i18n: "tag" is a keyword _(b'the argument to tag must be a string'), ) kind, pattern, matcher = stringutil.stringmatcher(pattern) if kind == b'literal': # avoid resolving all tags tn = git.tags.get(pattern, None) if tn is None: raise error.RepoLookupError( _(b"git tag '%s' does not exist") % pattern) s = {repo[bin(tn)].rev()} else: s = {cl.rev(bin(n)) for t, n in git.tags.items() if matcher(t)} else: s = {cl.rev(bin(n)) for t, n in git.tags.items()} return subset & s
def pushed(repo, subset, x): '''``pushed()`` Select changesets in any remote repository according to remotebranches. ''' args = revset.getargs(x, 0, 0, "pushed takes no arguments") return upstream_revs(lambda x: True, repo, subset, x)