Beispiel #1
0
def underwayrevset(repo, subset, x):
    args = revset.getargsdict(x, 'underway', 'commitage headage')
    if 'commitage' not in args:
        args['commitage'] = None
    if 'headage' not in args:
        args['headage'] = None

    # We assume callers of this revset add a topographical sort on the
    # result. This means there is no benefit to making the revset lazy
    # since the topographical sort needs to consume all revs.
    #
    # With this in mind, we build up the set manually instead of constructing
    # a complex revset. This enables faster execution.

    # Mutable changesets (non-public) are the most important changesets
    # to return. ``not public()`` will also pull in obsolete changesets if
    # there is a non-obsolete changeset with obsolete ancestors. This is
    # why we exclude obsolete changesets from this query.
    rs = 'not public() and not obsolete()'
    rsargs = []
    if args['commitage']:
        rs += ' and date(%s)'
        rsargs.append(
            revsetlang.getstring(args['commitage'],
                                 _('commitage requires a string')))

    mutable = repo.revs(rs, *rsargs)
    relevant = revset.baseset(mutable)

    # Add parents of mutable changesets to provide context.
    relevant += repo.revs('parents(%ld)', mutable)

    # We also pull in (public) heads if they a) aren't closing a branch
    # b) are recent.
    rs = 'head() and not closed()'
    rsargs = []
    if args['headage']:
        rs += ' and date(%s)'
        rsargs.append(
            revsetlang.getstring(args['headage'],
                                 _('headage requires a string')))

    relevant += repo.revs(rs, *rsargs)

    # Add working directory parent.
    wdirrev = repo['.'].rev()
    if wdirrev != nullrev:
        relevant += revset.baseset(set([wdirrev]))

    return subset & relevant
def _revsetutil(repo, subset, x, rtypes):
    """utility function to return a set of revs based on the rtypes"""
    args = revsetlang.getargs(x, 0, 1, _(b'only one argument accepted'))
    if args:
        kind, pattern, matcher = stringutil.stringmatcher(
            revsetlang.getstring(args[0], _(b'argument must be a string')))
    else:
        kind = pattern = None
        matcher = util.always

    nodes = set()
    cl = repo.changelog
    for rtype in rtypes:
        if rtype in repo.names:
            ns = repo.names[rtype]
            for name in ns.listnames(repo):
                if not matcher(name):
                    continue
                nodes.update(ns.nodes(repo, name))
    if kind == b'literal' and not nodes:
        raise error.RepoLookupError(
            _(b"remote name '%s' does not exist") % pattern)

    revs = (cl.rev(n) for n in nodes if cl.hasnode(n))
    return subset & smartset.baseset(revs)
Beispiel #3
0
def _localbranch(repo, subset, x):
    """``_localbranch(changectx)``
    localbranch changesets

    Returns all commits within the same localbranch as the changeset(s). A local
    branch is all draft changesets that are connected, uninterupted by public
    changesets.  Any draft commit within a branch, or a public commit at the
    base of the branch, can be passed used to identify localbranches.
    """
    # executed on an filtered repo
    args = revset.getargsdict(x, 'branchrevset', 'changectx')
    revstring = revsetlang.getstring(args.get('changectx'),
                               _('localbranch argument must be a changectx'))
    revs = repo.revs(revstring)
    # we assume that there is only a single rev
    if repo[revs.first()].phase() == phases.public:
        querystring = revsetlang.formatspec('(children(%d) & draft())::',
                                            revs.first())
    else:
        querystring = revsetlang.formatspec('((::%ld) & draft())::', revs)
    return subset & smartset.baseset(repo.revs(querystring))
Beispiel #4
0
def smartlogrevset(repo, subset, x):
    """``smartlog([master], [recentdays=N])``
    Changesets relevent to you.

    'master' is the head of the public branch.
    Unnamed heads will be hidden unless it's within 'recentdays'.
    """

    args = revset.getargsdict(x, 'smartlogrevset', 'master recentdays')
    if 'master' in args:
        masterstring = revsetlang.getstring(args['master'],
                                            _('master must be a string'))
    else:
        masterstring = ''

    recentdays = revsetlang.getinteger(args.get('recentdays'),
                                       _("recentdays should be int"), -1)

    revs = set()
    heads = set()

    rev = repo.changelog.rev
    ancestor = repo.changelog.ancestor
    node = repo.changelog.node
    parentrevs = repo.changelog.parentrevs

    books = bookmarks.bmstore(repo)
    ignore = re.compile(repo.ui.config('smartlog',
                                       'ignorebookmarks',
                                       '!'))
    for b in books:
        if not ignore.match(b):
            heads.add(rev(books[b]))

    # add 'interesting' remote bookmarks as well
    remotebooks = set()
    if util.safehasattr(repo, 'names') and 'remotebookmarks' in repo.names:
        ns = repo.names['remotebookmarks']
        remotebooks = set(ns.listnames(repo))
        for name in _reposnames(repo.ui):
            if name in remotebooks:
                heads.add(rev(ns.namemap(repo, name)[0]))

    heads.update(repo.revs('.'))

    global hiddenchanges
    headquery = 'head()'
    if remotebooks:
        # When we have remote bookmarks, only show draft heads, since public
        # heads should have a remote bookmark indicating them. This allows us
        # to force push server bookmarks to new locations, and not have the
        # commits clutter the user's smartlog.
        headquery = 'heads(draft())'

    allheads = set(repo.revs(headquery))
    if recentdays >= 0:
        recentquery = revsetlang.formatspec('%r & date(-%d)', headquery,
                                            recentdays)
        recentrevs = set(repo.revs(recentquery))
        hiddenchanges += len(allheads - heads) - len(recentrevs - heads)
        heads.update(recentrevs)
    else:
        heads.update(allheads)

    masterrevset = _masterrevset(repo.ui, repo, masterstring)
    masterrev = _masterrev(repo, masterrevset)

    if masterrev is None:
        masterrev = repo['tip'].rev()

    masternode = node(masterrev)

    # Find all draft ancestors and latest public ancestor of heads
    # that are not in master.
    # We don't want to draw all public commits because there can be too
    # many of them.
    # Don't use revsets, they are too slow
    for head in heads:
        anc = rev(ancestor(node(head), masternode))
        queue = [head]
        while queue:
            current = queue.pop(0)
            if current not in revs:
                revs.add(current)
                # stop as soon as we find public commit
                ispublic = repo[current].phase() == phases.public
                if current != anc and not ispublic:
                    parents = parentrevs(current)
                    for p in parents:
                        if p > anc:
                            queue.append(p)

    # add context: master, current commit, and the common ancestor
    revs.add(masterrev)

    return subset & revs
Beispiel #5
0
def smartlogrevset(repo, subset, x):
    """``smartlog([master], [recentdays=N])``
    Changesets relevent to you.

    'master' is the head of the public branch.
    Unnamed heads will be hidden unless it's within 'recentdays'.
    """

    args = revset.getargsdict(x, 'smartlogrevset', 'master recentdays')
    if 'master' in args:
        masterstring = revsetlang.getstring(args['master'],
                                            _('master must be a string'))
    else:
        masterstring = ''

    recentdays = revsetlang.getinteger(args.get('recentdays'),
                                       _("recentdays should be int"), -1)

    revs = set()
    heads = set()

    rev = repo.changelog.rev
    branchinfo = repo.changelog.branchinfo
    ancestor = repo.changelog.ancestor
    node = repo.changelog.node
    parentrevs = repo.changelog.parentrevs

    books = bookmarks.bmstore(repo)
    ignore = re.compile(repo.ui.config('smartlog',
                                       'ignorebookmarks',
                                       '!'))
    for b in books:
        if not ignore.match(b):
            heads.add(rev(books[b]))

    # add 'interesting' remote bookmarks as well
    remotebooks = set()
    if util.safehasattr(repo, 'names') and 'remotebookmarks' in repo.names:
        ns = repo.names['remotebookmarks']
        remotebooks = set(ns.listnames(repo))
        for name in _reposnames(repo.ui):
            if name in remotebooks:
                heads.add(rev(ns.namemap(repo, name)[0]))

    heads.update(repo.revs('.'))

    global hiddenchanges
    headquery = 'head() & branch(.)'
    if remotebooks:
        # When we have remote bookmarks, only show draft heads, since public
        # heads should have a remote bookmark indicating them. This allows us
        # to force push server bookmarks to new locations, and not have the
        # commits clutter the user's smartlog.
        headquery = 'draft() &' + headquery

    allheads = set(repo.revs(headquery))
    if recentdays >= 0:
        recentquery = revsetlang.formatspec('%r & date(-%d)', headquery,
                                            recentdays)
        recentrevs = set(repo.revs(recentquery))
        hiddenchanges += len(allheads - heads) - len(recentrevs - heads)
        heads.update(recentrevs)
    else:
        heads.update(allheads)

    branches = set()
    for head in heads:
        branches.add(branchinfo(head)[0])

    masterrevset = _masterrevset(repo.ui, repo, masterstring)
    masterrev = _masterrev(repo, masterrevset)

    if masterrev is None:
        masterbranch = None
    else:
        masterbranch = branchinfo(masterrev)[0]

    for branch in branches:
        if branch != masterbranch:
            try:
                rs = 'first(reverse(branch("%s")) & public())' % branch
                branchmaster = repo.revs(rs).first()
                if branchmaster is None:
                    # local-only (draft) branch
                    rs = 'branch("%s")' % branch
                    branchmaster = repo.revs(rs).first()
            except Exception:
                branchmaster = repo.revs('tip').first()
        else:
            branchmaster = masterrev

        # Find all draft ancestors and latest public ancestor of heads
        # that are not in master.
        # We don't want to draw all public commits because there can be too
        # many of them.
        # Don't use revsets, they are too slow
        for head in heads:
            if branchinfo(head)[0] != branch:
                continue
            anc = rev(ancestor(node(head), node(branchmaster)))
            queue = [head]
            while queue:
                current = queue.pop(0)
                if current not in revs:
                    revs.add(current)
                    # stop as soon as we find public commit
                    ispublic = repo[current].phase() == phases.public
                    if current != anc and not ispublic:
                        parents = parentrevs(current)
                        for p in parents:
                            if p > anc:
                                queue.append(p)

        # add context: master, current commit, and the common ancestor
        revs.add(branchmaster)

        # get common branch ancestor
        if branch != masterbranch:
            anc = None
            for r in revs:
                if branchinfo(r)[0] != branch:
                    continue
                if anc is None:
                    anc = r
                else:
                    anc = rev(ancestor(node(anc), node(r)))
            if anc:
                revs.add(anc)

    return subset & revs