view tests/test-ancestor.py @ 23183:51c9196a6bd0

largefiles: remove meaningless code path for "hg pull --rebase" This patch removes "--rebase" specific code path for "hg pull" in "overridepull", because previous patch makes it meaningless: now, "rebase.rebase" ("orig" invocation in this patch) can update/commit largefiles safely without "repo._isrebasing = True". As a side effect of removing "rebase.rebase" invocation in "overridepull", this patch removes "nothing to rebase ..." message in "test-largefiles.t", which is shown only when rebase extension is enabled AFTER largefiles: before this patch: 1. "dispatch" invokes "pullrebase" of rebase as "hg pull" at first, because rebase wraps "hg pull" later 2. "pullrebase" invokes "overridepull" of largefiles as "orig", even though rebase assumes that "orig" is "pull" of commands 3. "overridepull" executes "pull" and "rebase" directly 3.1 "pull" pulls changesets and creates new head "X" 3.2 "rebase" rebases current working parent "Y" on "X" 4. "overridepull" returns to "pullrebase" 5. "pullrebase" tries to rebase, but there is nothing to be done, because "Y" is already rebased on "X". then, it shows "nothing to rebase ..." after this patch: 1. "dispatch" invokes "pullrebase" of rebase as "hg pull" 2. "pullrebase" invokes "overridepull" of largefiles as "orig" 3. "overridepull" executes "pull" as "orig" 4. "overridepull" returns to "pullrebase" 5. revision "Y" is not yet rebased, so "pullrebase" doesn't shows "nothing to rebase ..." As another side effect of removing "rebase.rebase" invocation, this patch fixes issue3861, which occurs only when rebase extension is enabled BEFORE largefiles: before this patch: 1. "dispatch" invokes "overridepull" of largefiles at first, because largefiles wrap "hg pull" later 2. "overridepull" executes "pull" and "rebase" explicitly 2.1 "pull" pulls changesets and creates new head "X" 2.2 "rebase" rebases current working parent, but fails because no revision is checked out in issue3861 case 3. "overridepull" returns to "dispatch" with exit code 1 returned from "rebase" at (2.2) 4. "hg pull" terminates with exit code 1 unexpectedly after this patch: 1. "dispatch" invokes "overridepull" of largefiles at first 2. "overridepull" invokes "pullrebase" of rebase as "orig" 3. "pullrebase" invokes "pull" as "orig" 4. "pullrebase" invokes "rebase", and it fails 5. "pullrebase" returns to "overridepull" with exit code 0 (because "pullrebase" ignores result of "pull" and "rebase") 6. "overridepull" returns to "dispatch" with exit code 0 returned from "rebase" at (5) 7. "hg pull" terminates with exit code 0
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Wed, 05 Nov 2014 23:24:47 +0900
parents 731b2a90983b
children 3a7d9c0c57a5
line wrap: on
line source

from mercurial import ancestor, commands, hg, ui, util

# graph is a dict of child->parent adjacency lists for this graph:
# o  13
# |
# | o  12
# | |
# | | o    11
# | | |\
# | | | | o  10
# | | | | |
# | o---+ |  9
# | | | | |
# o | | | |  8
#  / / / /
# | | o |  7
# | | | |
# o---+ |  6
#  / / /
# | | o  5
# | |/
# | o  4
# | |
# o |  3
# | |
# | o  2
# |/
# o  1
# |
# o  0

graph = {0: [-1], 1: [0], 2: [1], 3: [1], 4: [2], 5: [4], 6: [4],
         7: [4], 8: [-1], 9: [6, 7], 10: [5], 11: [3, 7], 12: [9],
         13: [8]}
pfunc = graph.get

class mockchangelog(object):
    parentrevs = graph.get

def runmissingancestors(revs, bases):
    print "%% ancestors of %s and not of %s" % (revs, bases)
    print ancestor.missingancestors(revs, bases, pfunc)

def test_missingancestors():
    # Empty revs
    runmissingancestors([], [1])
    runmissingancestors([], [])

    # If bases is empty, it's the same as if it were [nullrev]
    runmissingancestors([12], [])

    # Trivial case: revs == bases
    runmissingancestors([0], [0])
    runmissingancestors([4, 5, 6], [6, 5, 4])

    # With nullrev
    runmissingancestors([-1], [12])
    runmissingancestors([12], [-1])

    # 9 is a parent of 12. 7 is a parent of 9, so an ancestor of 12. 6 is an
    # ancestor of 12 but not of 7.
    runmissingancestors([12], [9])
    runmissingancestors([9], [12])
    runmissingancestors([12, 9], [7])
    runmissingancestors([7, 6], [12])

    # More complex cases
    runmissingancestors([10], [11, 12])
    runmissingancestors([11], [10])
    runmissingancestors([11], [10, 12])
    runmissingancestors([12], [10])
    runmissingancestors([12], [11])
    runmissingancestors([10, 11, 12], [13])
    runmissingancestors([13], [10, 11, 12])

def genlazyancestors(revs, stoprev=0, inclusive=False):
    print ("%% lazy ancestor set for %s, stoprev = %s, inclusive = %s" %
           (revs, stoprev, inclusive))
    return ancestor.lazyancestors(mockchangelog, revs, stoprev=stoprev,
                                  inclusive=inclusive)

def printlazyancestors(s, l):
    print [n for n in l if n in s]

def test_lazyancestors():
    # Empty revs
    s = genlazyancestors([])
    printlazyancestors(s, [3, 0, -1])

    # Standard example
    s = genlazyancestors([11, 13])
    printlazyancestors(s, [11, 13, 7, 9, 8, 3, 6, 4, 1, -1, 0])

    # Standard with ancestry in the initial set (1 is ancestor of 3)
    s = genlazyancestors([1, 3])
    printlazyancestors(s, [1, -1, 0])

    # Including revs
    s = genlazyancestors([11, 13], inclusive=True)
    printlazyancestors(s, [11, 13, 7, 9, 8, 3, 6, 4, 1, -1, 0])

    # Test with stoprev
    s = genlazyancestors([11, 13], stoprev=6)
    printlazyancestors(s, [11, 13, 7, 9, 8, 3, 6, 4, 1, -1, 0])
    s = genlazyancestors([11, 13], stoprev=6, inclusive=True)
    printlazyancestors(s, [11, 13, 7, 9, 8, 3, 6, 4, 1, -1, 0])


# The C gca algorithm requires a real repo. These are textual descriptions of
# DAGs that have been known to be problematic.
dagtests = [
    '+2*2*2/*3/2',
    '+3*3/*2*2/*4*4/*4/2*4/2*2',
]
def test_gca():
    u = ui.ui()
    for i, dag in enumerate(dagtests):
        repo = hg.repository(u, 'gca%d' % i, create=1)
        cl = repo.changelog
        if not util.safehasattr(cl.index, 'ancestors'):
            # C version not available
            return

        commands.debugbuilddag(u, repo, dag)
        # Compare the results of the Python and C versions. This does not
        # include choosing a winner when more than one gca exists -- we make
        # sure both return exactly the same set of gcas.
        for a in cl:
            for b in cl:
                cgcas = sorted(cl.index.ancestors(a, b))
                pygcas = sorted(ancestor.ancestors(cl.parentrevs, a, b))
                if cgcas != pygcas:
                    print "test_gca: for dag %s, gcas for %d, %d:" % (dag, a, b)
                    print "  C returned:      %s" % cgcas
                    print "  Python returned: %s" % pygcas

if __name__ == '__main__':
    test_missingancestors()
    test_lazyancestors()
    test_gca()