changeset 7248:723d7a2e6ec0

merge with crew
author Benoit Boissinot <benoit.boissinot@ens-lyon.org>
date Mon, 27 Oct 2008 13:17:26 +0100
parents c4461ea8b4c8 (current diff) 421f4cbddd68 (diff)
children 671b3e1eac2e
files
diffstat 5 files changed, 243 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/doc/hgrc.5.txt	Sun Oct 26 17:26:28 2008 +0100
+++ b/doc/hgrc.5.txt	Mon Oct 27 13:17:26 2008 +0100
@@ -220,8 +220,16 @@
     containing patches of outgoing messages will be encoded in
     the first charset to which conversion from local encoding
     (ui.encoding, ui.fallbackencoding) succeeds. If correct
-    conversion, including to ui.encoding, fails, the text in
-    question is sent as is in fake ascii. Defaults to empty list.
+    conversion fails, the text in question is sent as is.
+    Defaults to empty (explicit) list.
+
+  Order of outgoing email charsets:
+ 
+    us-ascii             always first, regardless of settings
+    email.charsets       in order given by user
+    ui.fallbackencoding  if not in email.charsets
+    ui.encoding          if not in email.charsets
+    utf-8                always last, regardless of settings
 
   Email example:
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext/bookmarks.py	Mon Oct 27 13:17:26 2008 +0100
@@ -0,0 +1,220 @@
+# Mercurial extension to provide the 'hg bookmark' command
+#
+# Copyright 2008 David Soria Parra <dsp@php.net>
+#
+# This software may be used and distributed according to the terms
+# of the GNU General Public License, incorporated herein by reference.
+'''mercurial bookmarks
+
+Mercurial bookmarks are local moveable pointers to changesets. Every bookmark
+points to a changesets identified by it's hash. If you commit a changeset
+that is based on a changeset that has a bookmark on it, the bookmark is forwarded
+to the new changeset.
+
+It is possible to use bookmark names in every revision lookup (e.g. hg merge, hg update)
+'''
+from mercurial.commands import templateopts, hex, short
+from mercurial.i18n import _
+from mercurial import cmdutil, util, commands, changelog
+from mercurial.node import nullrev
+from mercurial.repo import RepoError
+import mercurial, mercurial.localrepo, mercurial.repair, os
+
+
+def parse(repo):
+    '''Parse .hg/bookmarks file and return a dictionary
+    
+    Bookmarks are stored as {HASH}\s{NAME}\n (localtags format) 
+    values in the .hg/bookmarks file.
+    They are read by the parse() method and returned as a dictionary with
+    name => hash values.
+    
+    The parsed dictionary is cached until a write() operation is done.
+    '''
+    try:
+        if repo._bookmarks:
+            return repo._bookmarks
+        repo._bookmarks = {}
+        for line in repo.opener('bookmarks'):
+            sha, refspec = line.strip().split(' ', 1)
+            repo._bookmarks[refspec] = repo.lookup(sha)
+    except:
+        pass
+    return repo._bookmarks
+
+def write(repo, refs):
+    '''Write bookmarks
+    
+    Write the given bookmark => hash dictionary to the .hg/bookmarks file
+    in a format equal to those of localtags.
+
+    We also store a backup of the previous state in undo.bookmarks that
+    can be copied back on rollback.
+    '''
+    util.copyfile(repo.join('bookmarks'), repo.join('undo.bookmarks'))
+    file = repo.opener('bookmarks', 'w+')
+    for refspec, node in refs.items():
+        file.write("%s %s\n" % (hex(node), refspec))
+    file.close()
+
+def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False, move=None):
+    '''mercurial bookmarks
+    
+    Bookmarks are pointer to certain commits that move when commiting.
+    Bookmarks are local. They can be renamed, copied and deleted.
+    It is possible to use bookmark names in 'hg merge' and 'hg update' to 
+    update to a given bookmark.
+    
+    You can use 'hg bookmark [NAME]' to set a bookmark on the current tip
+    with the given name. If you specify a second [NAME] the bookmark is
+    set to the bookmark that has that name. You can also pass revision
+    identifiers to set bookmarks too.
+    '''
+    hexfn = ui.debugflag and hex or short
+    marks = parse(repo)
+    cur   = repo.changectx('.').node()
+
+    if move:
+        if move not in marks:
+            raise util.Abort(_("a bookmark of this name doesnot exists"))
+        if mark in marks and not force:
+            raise util.Abort(_("a bookmark of the same name already exists"))
+        marks[mark] = marks[move]
+        del marks[move]
+        write(repo, marks)
+        return
+    
+    if delete:
+        if mark == None:
+            raise util.Abort(_("bookmark name required"))
+        if mark not in marks:
+            raise util.Abort(_("a bookmark of this name does not exists"))
+        del marks[mark]
+        write(repo, marks)
+        return
+
+    if mark != None:
+        if mark.strip().count("\n") > 0:
+            raise Exception("bookmark cannot contain newlines")
+        if mark in marks and not force:
+            raise util.Abort(_("a bookmark of the same name already exists"))
+        if ((mark in repo.branchtags() or mark == repo.dirstate.branch()) 
+            and not force):
+            raise util.Abort(_("a bookmark cannot have the name of an existing branch"))
+        if rev:
+            marks[mark] = repo.lookup(rev)
+        else:
+            marks[mark] = repo.changectx('.').node()
+        write(repo, marks)
+        return
+
+    if mark == None:
+        if len(marks) == 0:
+            ui.status("no bookmarks set\n")
+        else:
+            for bmark, n in marks.iteritems():
+                prefix = (n == cur) and '*' or ' '
+                ui.write(" %s %-25s %d:%s\n" % (prefix, bmark, repo.changelog.rev(n), hexfn(n)))
+        return
+
+def _revstostrip(changelog, node):
+    srev = changelog.rev(node)
+    tostrip = [srev]
+    saveheads = []
+    for r in xrange(srev, changelog.rev(changelog.tip()) + 1):
+        parents = changelog.parentrevs(r)
+        if parents[0] in tostrip or parents[1] in tostrip:
+            tostrip.append(r)
+            if parents[1] != nullrev:
+                for p in parents:
+                    if p not in tostrip and p > striprev:
+                        saveheads.append(p)
+    return [r for r in tostrip if r not in saveheads]
+
+def strip(ui, repo, node, backup="all"):
+    """Strip bookmarks if revisions are stripped using
+    the mercurial.strip method. This usually happens during
+    qpush and qpop"""
+    revisions = _revstostrip(repo.changelog, node)
+    marks = parse(repo)
+    update = []
+    for mark, n in marks.items():
+        if repo.changelog.rev(n) in revisions:
+            update.append(mark)
+    result = oldstrip(ui, repo, node, backup)
+    if len(update) > 0:
+        for m in update:
+            marks[m] = repo.changectx('.').node()
+        write(repo, marks)
+
+oldstrip = mercurial.repair.strip
+mercurial.repair.strip = strip
+
+def reposetup(ui, repo):
+    if not isinstance(repo, mercurial.localrepo.localrepository):
+        return
+
+    # init a bookmark cache as otherwise we would get a infinite reading
+    # in lookup()
+    repo._bookmarks = None
+
+    class bookmark_repo(repo.__class__):
+        def rollback(self):
+            if os.path.exists(self.join('undo.bookmarks')):
+                util.rename(self.join('undo.bookmarks'), self.join('bookmarks'))
+            return super(bookmark_repo, self).rollback() 
+
+        def lookup(self, key):
+            if self._bookmarks is None:
+                self._bookmarks = parse(self)
+            if key in self._bookmarks:
+                key = self._bookmarks[key]
+            return super(bookmark_repo, self).lookup(key)
+
+        def commit(self, *k, **kw):
+            """Add a revision to the repository and
+            move the bookmark"""
+            node  = super(bookmark_repo, self).commit(*k, **kw)
+            parents = repo.changelog.parents(node)
+            marks = parse(repo)
+            update = False
+            for mark, n in marks.items():
+                if n in parents:
+                    marks[mark] = node
+                    update = True
+            if update:
+                write(repo, marks)
+            return node
+
+        def addchangegroup(self, source, srctype, url, emptyok=False):
+            try:
+                onode = repo.changectx('.').node()
+            except RepoError, inst:
+                pass
+
+            result = super(bookmark_repo, self).addchangegroup(source, srctype, url, emptyok)
+            if result > 1:
+                # We have more heads than before
+                return result
+            node = repo.changelog.tip()
+            marks = parse(repo)
+            update = False
+            for mark, n in marks.items():
+                if n == onode:
+                    marks[mark] = node
+                    update = True
+            if update:
+                write(repo, marks)
+            return result
+
+    repo.__class__ = bookmark_repo
+
+cmdtable = {
+    "bookmarks":
+        (bookmark,
+         [('f', 'force', False, _('force')),
+          ('r', 'rev', '', _('revision')),
+          ('d', 'delete', False, _('delete a given bookmark')),
+          ('m', 'move', '', _('move a given bookmark'))],
+         _('hg bookmarks [-d] [-m NAME] [-r NAME] [NAME]')),
+}
--- a/hgext/zeroconf/__init__.py	Sun Oct 26 17:26:28 2008 +0100
+++ b/hgext/zeroconf/__init__.py	Mon Oct 27 13:17:26 2008 +0100
@@ -122,8 +122,8 @@
                 return p
     return orig(self, section, key, default, untrusted)
 
-def configitems(orig, self, section):
-    r = orig(self, section, untrusted=False)
+def configitems(orig, self, section, untrusted=False):
+    r = orig(self, section, untrusted)
     if section == "paths":
         r += getzcpaths()
     return r
--- a/tests/test-grep	Sun Oct 26 17:26:28 2008 +0100
+++ b/tests/test-grep	Mon Oct 27 13:17:26 2008 +0100
@@ -53,6 +53,12 @@
 hg grep orange
 hg grep --all orange
 
+echo % match in last "line" without newline
+python -c 'fp = open("noeol", "wb"); fp.write("no infinite loop"); fp.close();'
+hg ci -Amnoeol
+echo % last character omitted in output to avoid infinite loop
+hg grep loop
+
 # Got a traceback when using grep on a single
 # revision with renamed files.
 cd ..
@@ -66,3 +72,4 @@
 hg grep octarine
 # Used to crash here
 hg grep -r 1 octarine
+
--- a/tests/test-grep.out	Sun Oct 26 17:26:28 2008 +0100
+++ b/tests/test-grep.out	Mon Oct 27 13:17:26 2008 +0100
@@ -32,6 +32,10 @@
 color:3:+:orange
 color:2:-:orange
 color:1:+:orange
+% match in last line without newline
+adding noeol
+% last character omitted in output to avoid infinite loop
+noeol:4:no infinite loo
 % issue 685
 adding color
 color:0:octarine