Merge with crew-stable
authorAlexis S. L. Carvalho <alexis@cecm.usp.br>
Tue, 30 Jan 2007 19:36:56 -0200
changeset 4059 431f3c1d3a37
parent 4051 022056263354 (current diff)
parent 4058 e7282dede8cd (diff)
child 4060 82eb0fafb56d
Merge with crew-stable
mercurial/cmdutil.py
mercurial/commands.py
mercurial/localrepo.py
mercurial/util.py
--- a/doc/hgrc.5.txt	Tue Jan 30 22:07:22 2007 +0100
+++ b/doc/hgrc.5.txt	Tue Jan 30 19:36:56 2007 -0200
@@ -439,6 +439,9 @@
     The committer of a changeset created when running "commit".
     Typically a person's name and email address, e.g. "Fred Widget
     <fred@example.com>".  Default is $EMAIL or username@hostname.
+    If the username in hgrc is empty, it has to be specified manually or
+    in a different hgrc file (e.g. $HOME/.hgrc, if the admin set "username ="
+    in the system hgrc).
   verbose;;
     Increase the amount of output printed.  True or False.  Default is False.
 
--- a/mercurial/cmdutil.py	Tue Jan 30 22:07:22 2007 +0100
+++ b/mercurial/cmdutil.py	Tue Jan 30 19:36:56 2007 -0200
@@ -125,7 +125,7 @@
                               pathname),
                 mode)
 
-def matchpats(repo, pats=[], opts={}, head=''):
+def matchpats(repo, pats=[], opts={}, head='', globbed=False):
     cwd = repo.getcwd()
     if not pats and cwd:
         opts['include'] = [os.path.join(cwd, i)
@@ -134,10 +134,12 @@
                            for x in opts.get('exclude', [])]
         cwd = ''
     return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'),
-                           opts.get('exclude'), head)
+                           opts.get('exclude'), head, globbed=globbed)
 
-def walk(repo, pats=[], opts={}, node=None, head='', badmatch=None):
-    files, matchfn, anypats = matchpats(repo, pats, opts, head)
+def walk(repo, pats=[], opts={}, node=None, head='', badmatch=None,
+         globbed=False):
+    files, matchfn, anypats = matchpats(repo, pats, opts, head,
+                                        globbed=globbed)
     exact = dict.fromkeys(files)
     for src, fn in repo.walk(node=node, files=files, match=matchfn,
                              badmatch=badmatch):
--- a/mercurial/commands.py	Tue Jan 30 22:07:22 2007 +0100
+++ b/mercurial/commands.py	Tue Jan 30 19:36:56 2007 -0200
@@ -604,7 +604,7 @@
         return res
 
 
-    pats = list(pats)
+    pats = util.expand_glob(pats)
     if not pats:
         raise util.Abort(_('no source or destination specified'))
     if len(pats) == 1:
@@ -621,7 +621,8 @@
     copylist = []
     for pat in pats:
         srcs = []
-        for tag, abssrc, relsrc, exact in cmdutil.walk(repo, [pat], opts):
+        for tag, abssrc, relsrc, exact in cmdutil.walk(repo, [pat], opts,
+                                                       globbed=True):
             origsrc = okaytocopy(abssrc, relsrc, exact)
             if origsrc:
                 srcs.append((origsrc, abssrc, relsrc, exact))
@@ -769,10 +770,16 @@
     keys = dc.keys()
     keys.sort()
     for file_ in keys:
+        if dc[file_][3] == -1:
+            # Pad or slice to locale representation
+            locale_len = len(time.strftime("%x %X", time.localtime(0)))
+            timestr = 'unset'
+            timestr = timestr[:locale_len] + ' '*(locale_len - len(timestr))
+        else:
+            timestr = time.strftime("%x %X", time.localtime(dc[file_][3]))
         ui.write("%c %3o %10d %s %s\n"
                  % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2],
-                    time.strftime("%x %X",
-                                  time.localtime(dc[file_][3])), file_))
+                    timestr, file_))
     for f in repo.dirstate.copies():
         ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
 
@@ -2478,7 +2485,11 @@
     Apply a compressed changegroup file generated by the bundle
     command.
     """
-    gen = changegroup.readbundle(urllib.urlopen(fname), fname)
+    if os.path.exists(fname):
+        f = open(fname)
+    else:
+        f = urllib.urlopen(fname)
+    gen = changegroup.readbundle(f, fname)
     modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
     return postincoming(ui, repo, modheads, opts['update'])
 
--- a/mercurial/localrepo.py	Tue Jan 30 22:07:22 2007 +0100
+++ b/mercurial/localrepo.py	Tue Jan 30 19:36:56 2007 -0200
@@ -616,6 +616,24 @@
         meta = {}
         cp = self.dirstate.copied(fn)
         if cp:
+            # Mark the new revision of this file as a copy of another
+            # file.  This copy data will effectively act as a parent 
+            # of this new revision.  If this is a merge, the first 
+            # parent will be the nullid (meaning "look up the copy data")
+            # and the second one will be the other parent.  For example:
+            #
+            # 0 --- 1 --- 3   rev1 changes file foo
+            #   \       /     rev2 renames foo to bar and changes it
+            #    \- 2 -/      rev3 should have bar with all changes and
+            #                      should record that bar descends from
+            #                      bar in rev2 and foo in rev1
+            #
+            # this allows this merge to succeed:
+            #
+            # 0 --- 1 --- 3   rev4 reverts the content change from rev2
+            #   \       /     merging rev3 and rev4 should use bar@rev2
+            #    \- 2 --- 4        as the merge base
+            #
             meta["copy"] = cp
             if not manifest2: # not a branch merge
                 meta["copyrev"] = hex(manifest1.get(cp, nullid))
@@ -624,7 +642,7 @@
                 meta["copyrev"] = hex(manifest1.get(cp, nullid))
             elif fp1 != nullid: # copied on local side, reversed
                 meta["copyrev"] = hex(manifest2.get(cp))
-                fp2 = nullid
+                fp2 = fp1
             else: # directory rename
                 meta["copyrev"] = hex(manifest1.get(cp, nullid))
             self.ui.debug(_(" %s: copy %s:%s\n") %
--- a/mercurial/util.py	Tue Jan 30 22:07:22 2007 +0100
+++ b/mercurial/util.py	Tue Jan 30 19:36:56 2007 -0200
@@ -14,10 +14,13 @@
 
 from i18n import _
 import cStringIO, errno, getpass, popen2, re, shutil, sys, tempfile
-import os, threading, time, calendar, ConfigParser, locale
+import os, threading, time, calendar, ConfigParser, locale, glob
 
-_encoding = os.environ.get("HGENCODING") or locale.getpreferredencoding() \
-            or "ascii"
+try:
+    _encoding = os.environ.get("HGENCODING") or locale.getpreferredencoding() \
+                or "ascii"
+except locale.Error:
+    _encoding = 'ascii'
 _encodingmode = os.environ.get("HGENCODINGMODE", "strict")
 _fallbackencoding = 'ISO-8859-1'
 
@@ -233,6 +236,22 @@
 def always(fn): return True
 def never(fn): return False
 
+def expand_glob(pats):
+    '''On Windows, expand the implicit globs in a list of patterns'''
+    if os.name != 'nt':
+        return list(pats)
+    ret = []
+    for p in pats:
+        kind, name = patkind(p, None)
+        if kind is None:
+            globbed = glob.glob(name)
+            if globbed:
+                ret.extend(globbed)
+                continue
+            # if we couldn't expand the glob, just keep it around
+        ret.append(p)
+    return ret
+
 def patkind(name, dflt_pat='glob'):
     """Split a string into an optional pattern kind prefix and the
     actual pattern."""
@@ -358,12 +377,11 @@
 def matcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head='', src=None):
     return _matcher(canonroot, cwd, names, inc, exc, head, 'glob', src)
 
-def cmdmatcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head='', src=None):
-    if os.name == 'nt':
-        dflt_pat = 'glob'
-    else:
-        dflt_pat = 'relpath'
-    return _matcher(canonroot, cwd, names, inc, exc, head, dflt_pat, src)
+def cmdmatcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head='',
+               src=None, globbed=False):
+    if not globbed:
+        names = expand_glob(names)
+    return _matcher(canonroot, cwd, names, inc, exc, head, 'relpath', src)
 
 def _matcher(canonroot, cwd, names, inc, exc, head, dflt_pat, src):
     """build a function to match a set of file patterns
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-merge-commit	Tue Jan 30 19:36:56 2007 -0200
@@ -0,0 +1,77 @@
+#!/bin/sh
+# check that renames are correctly saved by a commit after a merge
+
+HGMERGE=merge
+export HGMERGE
+
+# test with the merge on 3 having the rename on the local parent
+hg init a
+cd a
+
+echo line1 > foo
+hg add foo
+hg ci -m '0: add foo' -d '0 0'
+
+echo line2 >> foo
+hg ci -m '1: change foo' -d '0 0'
+
+hg up -C 0
+hg mv foo bar
+rm bar
+echo line0 > bar
+echo line1 >> bar
+hg ci -m '2: mv foo bar; change bar' -d '0 0'
+
+hg merge 1
+echo '% contents of bar should be line0 line1 line2'
+cat bar
+hg ci -m '3: merge with local rename' -d '0 0'
+hg debugindex .hg/store/data/bar.i
+hg debugrename bar
+hg debugindex .hg/store/data/foo.i
+
+# revert the content change from rev 2
+hg up -C 2
+rm bar
+echo line1 > bar
+hg ci -m '4: revert content change from rev 2' -d '0 0'
+
+hg log --template '#rev#:#node|short# #parents#\n'
+echo '% this should use bar@rev2 as the ancestor'
+hg --debug merge 3
+echo '% contents of bar should be line1 line2'
+cat bar
+hg ci -m '5: merge' -d '0 0'
+hg debugindex .hg/store/data/bar.i
+
+
+# same thing, but with the merge on 3 having the rename on the remote parent
+echo
+echo
+cd ..
+hg clone -U -r 1 -r 2 a b
+cd b
+
+hg up -C 1
+hg merge 2
+echo '% contents of bar should be line0 line1 line2'
+cat bar
+hg ci -m '3: merge with remote rename' -d '0 0'
+hg debugindex .hg/store/data/bar.i
+hg debugrename bar
+hg debugindex .hg/store/data/foo.i
+
+# revert the content change from rev 2
+hg up -C 2
+rm bar
+echo line1 > bar
+hg ci -m '4: revert content change from rev 2' -d '0 0'
+
+hg log --template '#rev#:#node|short# #parents#\n'
+echo '% this should use bar@rev2 as the ancestor'
+hg --debug merge 3
+echo '% contents of bar should be line1 line2'
+cat bar
+hg ci -m '5: merge' -d '0 0'
+hg debugindex .hg/store/data/bar.i
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-merge-commit.out	Tue Jan 30 19:36:56 2007 -0200
@@ -0,0 +1,83 @@
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+merging bar and foo
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+% contents of bar should be line0 line1 line2
+line0
+line1
+line2
+   rev    offset  length   base linkrev nodeid       p1           p2
+     0         0      77      0       2 da78c0659611 000000000000 000000000000
+     1        77      76      0       3 4b358025380b 000000000000 da78c0659611
+bar renamed from foo:9e25c27b87571a1edee5ae4dddee5687746cc8e2
+   rev    offset  length   base linkrev nodeid       p1           p2
+     0         0       7      0       0 690b295714ae 000000000000 000000000000
+     1         7      13      1       1 9e25c27b8757 690b295714ae 000000000000
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+4:2d2f9a22c82b 2:0a3ab4856510 
+3:7d3b554bfdf1 2:0a3ab4856510 1:5cd961e4045d 
+2:0a3ab4856510 0:2665aaee66e9 
+1:5cd961e4045d 
+0:2665aaee66e9 
+% this should use bar@rev2 as the ancestor
+resolving manifests
+ overwrite None partial False
+ ancestor 0a3ab4856510 local 2d2f9a22c82b+ remote 7d3b554bfdf1
+ bar: versions differ -> m
+merging bar
+my bar@2d2f9a22c82b+ other bar@7d3b554bfdf1 ancestor bar@0a3ab4856510
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+% contents of bar should be line1 line2
+line1
+line2
+   rev    offset  length   base linkrev nodeid       p1           p2
+     0         0      77      0       2 da78c0659611 000000000000 000000000000
+     1        77      76      0       3 4b358025380b 000000000000 da78c0659611
+     2       153       7      2       4 4defe5eec418 da78c0659611 000000000000
+     3       160      13      3       5 4663501da27b 4defe5eec418 4b358025380b
+
+
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 3 changesets with 3 changes to 2 files (+1 heads)
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+merging foo and bar
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+% contents of bar should be line0 line1 line2
+line0
+line1
+line2
+   rev    offset  length   base linkrev nodeid       p1           p2
+     0         0      77      0       2 da78c0659611 000000000000 000000000000
+     1        77      76      0       3 4b358025380b 000000000000 da78c0659611
+bar renamed from foo:9e25c27b87571a1edee5ae4dddee5687746cc8e2
+   rev    offset  length   base linkrev nodeid       p1           p2
+     0         0       7      0       0 690b295714ae 000000000000 000000000000
+     1         7      13      1       1 9e25c27b8757 690b295714ae 000000000000
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+4:2d2f9a22c82b 2:0a3ab4856510 
+3:96ab80c60897 1:5cd961e4045d 2:0a3ab4856510 
+2:0a3ab4856510 0:2665aaee66e9 
+1:5cd961e4045d 
+0:2665aaee66e9 
+% this should use bar@rev2 as the ancestor
+resolving manifests
+ overwrite None partial False
+ ancestor 0a3ab4856510 local 2d2f9a22c82b+ remote 96ab80c60897
+ bar: versions differ -> m
+merging bar
+my bar@2d2f9a22c82b+ other bar@96ab80c60897 ancestor bar@0a3ab4856510
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+% contents of bar should be line1 line2
+line1
+line2
+   rev    offset  length   base linkrev nodeid       p1           p2
+     0         0      77      0       2 da78c0659611 000000000000 000000000000
+     1        77      76      0       3 4b358025380b 000000000000 da78c0659611
+     2       153       7      2       4 4defe5eec418 da78c0659611 000000000000
+     3       160      13      3       5 4663501da27b 4defe5eec418 4b358025380b