# HG changeset patch # User Benoit Boissinot # Date 1225109846 -3600 # Node ID 723d7a2e6ec0864dd183fcb94554925131ca516e # Parent c4461ea8b4c8022568080ecc847ba4ed3e17906c# Parent 421f4cbddd6858dc8734560c4f53e5ca7ceade50 merge with crew diff -r c4461ea8b4c8 -r 723d7a2e6ec0 doc/hgrc.5.txt --- 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: diff -r c4461ea8b4c8 -r 723d7a2e6ec0 hgext/bookmarks.py --- /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 +# +# 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]')), +} diff -r c4461ea8b4c8 -r 723d7a2e6ec0 hgext/zeroconf/__init__.py --- 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 diff -r c4461ea8b4c8 -r 723d7a2e6ec0 tests/test-grep --- 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 + diff -r c4461ea8b4c8 -r 723d7a2e6ec0 tests/test-grep.out --- 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