changeset 5161:24d306834de5

merge with -stable
author Benoit Boissinot <benoit.boissinot@ens-lyon.org>
date Tue, 14 Aug 2007 17:20:51 +0200
parents c13610d5642c (current diff) 105d4cf7ec24 (diff)
children 9b0efeb725f4
files tests/test-issue672 tests/test-no-symlinks.bundle tests/test-profile
diffstat 15 files changed, 237 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/demandimport.py
+++ b/mercurial/demandimport.py
@@ -108,7 +108,18 @@ def _demandimport(name, globals=None, lo
                 setattr(mod, x, _demandmod(x, mod.__dict__, locals))
         return mod
 
-ignore = ['_hashlib', '_xmlplus', 'fcntl', 'win32com.gen_py']
+ignore = [
+    '_hashlib',
+    '_xmlplus',
+    'fcntl',
+    'win32com.gen_py',
+    # imported by tarfile, not available under Windows
+    'pwd',
+    'grp',
+    # imported by profile, itself imported by hotshot.stats,
+    # not available under Windows
+    'resource',
+    ]
 
 def enable():
     "enable global demand-loading of modules"
--- a/mercurial/extensions.py
+++ b/mercurial/extensions.py
@@ -24,6 +24,7 @@ def find(name):
 def load(ui, name, path):
     if name in _extensions:
         return
+    _extensions[name] = None
     if path:
         # the module will be loaded in sys.modules
         # choose an unique name so that it doesn't
--- a/mercurial/fancyopts.py
+++ b/mercurial/fancyopts.py
@@ -9,7 +9,10 @@ def fancyopts(args, options, state):
     for s, l, d, c in options:
         pl = l.replace('-', '_')
         map['-'+s] = map['--'+l] = pl
-        state[pl] = d
+        if isinstance(d, list):
+            state[pl] = d[:]
+        else:
+            state[pl] = d
         dt[pl] = type(d)
         if (d is not None and d is not True and d is not False and
             not callable(d)):
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -7,7 +7,7 @@
 
 from node import *
 from i18n import _
-import errno, util, os, tempfile, context
+import errno, util, os, tempfile, context, heapq
 
 def filemerge(repo, fw, fd, fo, wctx, mctx):
     """perform a 3-way merge in the working directory
@@ -252,6 +252,58 @@ def findcopies(repo, m1, m2, ma, limit):
 
     return copy, diverge
 
+def symmetricdifference(repo, rev1, rev2):
+    """symmetric difference of the sets of ancestors of rev1 and rev2
+    
+    I.e. revisions that are ancestors of rev1 or rev2, but not both.
+    """
+    # basic idea:
+    # - mark rev1 and rev2 with different colors
+    # - walk the graph in topological order with the help of a heap;
+    #   for each revision r:
+    #     - if r has only one color, we want to return it
+    #     - add colors[r] to its parents
+    #
+    # We keep track of the number of revisions in the heap that
+    # we may be interested in.  We stop walking the graph as soon
+    # as this number reaches 0.
+    WHITE = 1
+    BLACK = 2
+    ALLCOLORS = WHITE | BLACK
+    colors = {rev1: WHITE, rev2: BLACK}
+
+    cl = repo.changelog
+
+    visit = [-rev1, -rev2]
+    heapq.heapify(visit)
+    n_wanted = len(visit)
+    ret = []
+
+    while n_wanted:
+        r = -heapq.heappop(visit)
+        wanted = colors[r] != ALLCOLORS
+        n_wanted -= wanted
+        if wanted:
+            ret.append(r)
+
+        for p in cl.parentrevs(r):
+            if p == nullrev:
+                continue
+            if p not in colors:
+                # first time we see p; add it to visit
+                n_wanted += wanted
+                colors[p] = colors[r]
+                heapq.heappush(visit, -p)
+            elif colors[p] != ALLCOLORS and colors[p] != colors[r]:
+                # at first we thought we wanted p, but now
+                # we know we don't really want it
+                n_wanted -= 1
+                colors[p] |= colors[r]
+
+        del colors[r]
+
+    return ret
+
 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
     """
     Merge p1 and p2 with ancestor ma and generate merge action list
@@ -290,7 +342,12 @@ def manifestmerge(repo, p1, p2, pa, over
         action.append((f, m) + args)
 
     if not (backwards or overwrite):
-        copy, diverge = findcopies(repo, m1, m2, ma, pa.rev())
+        rev1 = p1.rev()
+        if rev1 is None:
+            # p1 is a workingctx
+            rev1 = p1.parents()[0].rev()
+        limit = min(symmetricdifference(repo, rev1, p2.rev()))
+        copy, diverge = findcopies(repo, m1, m2, ma, limit)
 
     for of, fl in diverge.items():
         act("divergent renames", "dr", of, fl)
--- a/tests/hghave
+++ b/tests/hghave
@@ -8,6 +8,8 @@ import os
 import sys
 import tempfile
 
+tempprefix = 'hg-hghave-'
+
 def has_symlink():
     return hasattr(os, "symlink")
 
@@ -15,7 +17,7 @@ def has_fifo():
     return hasattr(os, "mkfifo")
 
 def has_executablebit():
-    fd, path = tempfile.mkstemp()
+    fd, path = tempfile.mkstemp(prefix=tempprefix)
     os.close(fd)
     try:
         s = os.lstat(path).st_mode
@@ -26,18 +28,26 @@ def has_executablebit():
 
 def has_eol_in_paths():
     try:
-        fd, path = tempfile.mkstemp(suffix='\n\r')
+        fd, path = tempfile.mkstemp(prefix=tempprefix, suffix='\n\r')
         os.close(fd)
         os.remove(path)
         return True
     except:
         return False
 
+def has_lsprof():
+    try:
+        import _lsprof
+        return True
+    except ImportError:
+        return False
+
 checks = {
-    "symlink": (has_symlink, "symbolic links"),
+    "eol-in-paths": (has_eol_in_paths, "end-of-lines in paths"),
+    "execbit": (has_executablebit, "executable bit"),
     "fifo": (has_fifo, "named pipes"),
-    "execbit": (has_executablebit, "executable bit"),
-    "eol-in-paths": (has_eol_in_paths, "end-of-lines in paths"),
+    "lsprof": (has_lsprof, "python lsprof module"),
+    "symlink": (has_symlink, "symbolic links"),
 }
 
 def list_features():
@@ -71,7 +81,7 @@ if __name__ == '__main__':
         negate = feature.startswith('no-')
         if negate:
             feature = feature[3:]
-        
+
         if feature not in checks:
             error('hghave: unknown feature: ' + feature)
             continue
@@ -80,7 +90,7 @@ if __name__ == '__main__':
         if not negate and not check():
             error('hghave: missing feature: ' + desc)
         elif negate and check():
-            error('hghave: unexpected feature: ' + desc)
+            error('hghave: system supports %s' % desc)
 
     if failures != 0:
         sys.exit(1)
--- a/tests/test-context.py
+++ b/tests/test-context.py
@@ -5,7 +5,6 @@ u = ui.ui()
 
 repo = hg.repository(u, 'test1', create=1)
 os.chdir('test1')
-repo = hg.repository(u, '.') # FIXME: can't lock repo without doing this
 
 # create 'foo' with fixed time stamp
 f = file('foo', 'w')
new file mode 100644
--- /dev/null
+++ b/tests/test-dispatch.py
@@ -0,0 +1,32 @@
+import os
+from mercurial import commands
+
+def dispatch(cmd):
+    """Simple wrapper around commands.dispatch()
+
+    Prints command and result value, but does not handle quoting.
+    """
+    print "running: %s" % (cmd,)
+    result = commands.dispatch(cmd.split())
+    print "result: %r" % (result,)
+
+
+dispatch("init test1")
+os.chdir('test1')
+
+# create file 'foo', add and commit
+f = file('foo', 'wb')
+f.write('foo\n')
+f.close()
+dispatch("add foo")
+dispatch("commit -m commit1 -d 2000-01-01 foo")
+
+# append to file 'foo' and commit
+f = file('foo', 'ab')
+f.write('bar\n')
+f.close()
+dispatch("commit -m commit2 -d 2000-01-02 foo")
+
+# check 88803a69b24 (fancyopts modified command table)
+dispatch("log -r 0")
+dispatch("log -r tip")
new file mode 100644
--- /dev/null
+++ b/tests/test-dispatch.py.out
@@ -0,0 +1,23 @@
+running: init test1
+result: None
+running: add foo
+result: None
+running: commit -m commit1 -d 2000-01-01 foo
+result: None
+running: commit -m commit2 -d 2000-01-02 foo
+result: None
+running: log -r 0
+changeset:   0:0e4634943879
+user:        test
+date:        Sat Jan 01 00:00:00 2000 +0000
+summary:     commit1
+
+result: None
+running: log -r tip
+changeset:   1:45589e459b2e
+tag:         tip
+user:        test
+date:        Sun Jan 02 00:00:00 2000 +0000
+summary:     commit2
+
+result: None
new file mode 100755
--- /dev/null
+++ b/tests/test-issue672
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# 0-2-4
+#  \ \ \
+#   1-3-5
+#
+# rename in #1, content change in #4.
+
+hg init t
+cd t
+
+touch 1
+touch 2
+hg commit -Am init -d "0 0"  # 0
+
+hg rename 1 1a
+hg commit -m rename -d "0 0" # 1
+
+hg co -C 0
+echo unrelated >> 2
+hg ci -m unrelated1 -d "0 0"  # 2
+
+hg merge --debug 1
+hg ci -m merge1 -d "0 0" # 3
+
+hg co -C 2
+echo hello >> 1
+hg ci -m unrelated2 -d "0 0" # 4
+
+hg co -C 3
+hg merge -y --debug 4
+
+hg co -C 4
+hg merge -y --debug 3
+
new file mode 100644
--- /dev/null
+++ b/tests/test-issue672.out
@@ -0,0 +1,33 @@
+adding 1
+adding 2
+1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+resolving manifests
+ overwrite None partial False
+ ancestor 81f4b099af3d local c64f439569a9+ remote 2f8037f47a5c
+ 1: other deleted -> r
+ 1a: remote created -> g
+removing 1
+getting 1a
+1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+resolving manifests
+ overwrite None partial False
+ ancestor c64f439569a9 local ac7575e3c052+ remote 746e9549ea96
+ 1a: local moved to 1 -> m
+merging 1a and 1
+my 1a@ac7575e3c052+ other 1@746e9549ea96 ancestor 1@81f4b099af3d
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+resolving manifests
+ overwrite None partial False
+ ancestor c64f439569a9 local 746e9549ea96+ remote ac7575e3c052
+ 1: remote moved to 1a -> m
+copying 1 to 1a
+merging 1 and 1a
+my 1@746e9549ea96+ other 1a@2f8037f47a5c ancestor 1@81f4b099af3d
+removing 1
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
--- a/tests/test-no-symlinks
+++ b/tests/test-no-symlinks
@@ -12,13 +12,13 @@
 # ln -s a a.lnk
 # ln -s d/b d/b.lnk
 # hg ci -Am t
-# hg bundle --base null ../test-no-symlinks.bundle
+# hg bundle --base null ../test-no-symlinks.hg
 
 # Extract a symlink on a platform not supporting them
 echo % unbundle
 hg init t
 cd t
-hg pull "$TESTDIR/test-no-symlinks.bundle"
+hg pull -q "$TESTDIR/test-no-symlinks.hg"
 hg update
 
 cat a.lnk && echo
@@ -34,14 +34,14 @@ cat b2.lnk && echo
 
 # Bundle and extract again
 echo % bundle
-hg bundle --base null ../symlinks.bundle
+hg bundle --base null ../symlinks.hg
 cd ..
 
 hg init t2
 cd t2
-hg pull ../symlinks.bundle
+hg pull ../symlinks.hg
 hg update
 
 cat a.lnk && echo
 cat d/a2.lnk && echo
-cat b2.lnk && echo
\ No newline at end of file
+cat b2.lnk && echo
rename from tests/test-no-symlinks.bundle
rename to tests/test-no-symlinks.hg
--- a/tests/test-no-symlinks.out
+++ b/tests/test-no-symlinks.out
@@ -1,11 +1,4 @@
 % unbundle
-pulling from C:\dev\mercurial\hg\hg-local-stable\tests/test-no-symlinks.bundle
-requesting all changes
-adding changesets
-adding manifests
-adding file changes
-added 1 changesets with 4 changes to 4 files
-(run 'hg update' to get a working copy)
 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
 a
 d/b
@@ -13,7 +6,7 @@ d/b
 a
 d/b
 % bundle
-pulling from ../symlinks.bundle
+pulling from ../symlinks.hg
 requesting all changes
 adding changesets
 adding manifests
new file mode 100755
--- /dev/null
+++ b/tests/test-profile
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+echo % test --time
+hg --time help 2>&1 | grep -q Time || echo --time failed
+
+echo % test --profile
+hg --profile help 2>&1 | grep -q ncalls || echo --profile failed
+
+echo % test --lsprof
+if "$TESTDIR/hghave" -q lsprof; then
+    hg --lsprof help 2>&1 | grep -q CallCount || echo --lsprof failed
+fi
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tests/test-profile.out
@@ -0,0 +1,3 @@
+% test --time
+% test --profile
+% test --lsprof