Mercurial > hg
changeset 11493:cc4e2a7ca23f
Merge with stable
author | Martin Geisler <mg@aragost.com> |
---|---|
date | Fri, 02 Jul 2010 11:30:57 +0200 |
parents | 8b452fe4bf50 (current diff) c37f35d7f2f5 (diff) |
children | 2347513f562a |
files | |
diffstat | 40 files changed, 373 insertions(+), 116 deletions(-) [+] |
line wrap: on
line diff
--- a/contrib/mercurial.spec Mon Jun 21 17:02:48 2010 -0300 +++ b/contrib/mercurial.spec Fri Jul 02 11:30:57 2010 +0200 @@ -41,7 +41,6 @@ make install DESTDIR=$RPM_BUILD_ROOT PREFIX=%{_prefix} MANDIR=%{_mandir} install contrib/hgk $RPM_BUILD_ROOT%{_bindir} -install contrib/convert-repo $RPM_BUILD_ROOT%{_bindir}/mercurial-convert-repo install contrib/hg-ssh $RPM_BUILD_ROOT%{_bindir} bash_completion_dir=$RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d @@ -74,7 +73,6 @@ %{_bindir}/hg %{_bindir}/hgk %{_bindir}/hg-ssh -%{_bindir}/mercurial-convert-repo %dir %{_sysconfdir}/bash_completion.d/ %dir %{_datadir}/zsh/site-functions/ %dir %{_sysconfdir}/mercurial
--- a/contrib/tcsh_completion Mon Jun 21 17:02:48 2010 -0300 +++ b/contrib/tcsh_completion Fri Jul 02 11:30:57 2010 +0200 @@ -2,7 +2,7 @@ # tcsh completion for Mercurial # # This file has been auto-generated by tcsh_completion_build.sh for -# Mercurial Distributed SCM (version 1.3.1+269-5d8125bbbbf4) +# Mercurial Distributed SCM (version 1.5.4+154-8b452fe4bf50) # # Copyright (C) 2005 TK Soh. # @@ -32,18 +32,19 @@ 'p/1/(add addremove annotate blame archive \ backout bisect branch branches bundle \ cat clone commit ci copy \ - cp debugancestor debugcheckstate debugcommands debugcomplete \ - debugdata debugdate debugfsinfo debugindex debugindexdot \ - debuginstall debugrebuildstate debugrename debugsetparents debugstate \ - debugsub debugwalk diff export forget \ - grep heads help identify id \ - import patch incoming in init \ - locate log history manifest merge \ - outgoing out parents paths pull \ - push recover remove rm rename \ - mv resolve revert rollback root \ - serve showconfig debugconfig status st \ - summary sum tag tags tip \ - unbundle update up checkout co \ - verify version)/' + cp debugancestor debugbuilddag debugcheckstate debugcommands \ + debugcomplete debugdag debugdata debugdate debugfsinfo \ + debugindex debugindexdot debuginstall debugpushkey debugrebuildstate \ + debugrename debugrevspec debugsetparents debugstate debugsub \ + debugwalk diff export forget grep \ + heads help identify id import \ + patch incoming in init locate \ + log history manifest merge outgoing \ + out parents paths pull push \ + recover remove rm rename mv \ + resolve revert rollback root serve \ + showconfig debugconfig status st summary \ + sum tag tags tip unbundle \ + update up checkout co verify \ + version)/'
--- a/hgext/bookmarks.py Mon Jun 21 17:02:48 2010 -0300 +++ b/hgext/bookmarks.py Fri Jul 02 11:30:57 2010 +0200 @@ -30,7 +30,7 @@ from mercurial.i18n import _ from mercurial.node import nullid, nullrev, hex, short -from mercurial import util, commands, repair, extensions, pushkey, hg +from mercurial import util, commands, repair, extensions, pushkey, hg, url import os def write(repo): @@ -53,6 +53,13 @@ for refspec, node in refs.iteritems(): file.write("%s %s\n" % (hex(node), refspec)) file.rename() + + # touch 00changelog.i so hgweb reloads bookmarks (no lock needed) + try: + os.utime(repo.sjoin('00changelog.i'), None) + except OSError: + pass + finally: wlock.release() @@ -327,16 +334,15 @@ if r: self.ui.status(_("updating bookmark %s\n") % k) else: - self.ui.warn(_("failed to update bookmark" - " %s!\n") % k) + self.ui.warn(_('updating bookmark %s' + ' failed!\n') % k) return result - def addchangegroup(self, source, srctype, url, emptyok=False): + def addchangegroup(self, *args, **kwargs): parents = self.dirstate.parents() - result = super(bookmark_repo, self).addchangegroup( - source, srctype, url, emptyok) + result = super(bookmark_repo, self).addchangegroup(*args, **kwargs) if result > 1: # We have more heads than before return result @@ -445,6 +451,40 @@ return result +def diffbookmarks(ui, repo, remote): + ui.status(_("searching for changes\n")) + + lmarks = repo.listkeys('bookmarks') + rmarks = remote.listkeys('bookmarks') + + diff = set(rmarks) - set(lmarks) + for k in diff: + ui.write(" %-25s %s\n" % (k, rmarks[k][:12])) + + if len(diff) <= 0: + ui.status(_("no changes found\n")) + return 1 + return 0 + +def incoming(oldincoming, ui, repo, source="default", **opts): + if opts.get('bookmarks'): + source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch')) + other = hg.repository(hg.remoteui(repo, opts), source) + ui.status(_('comparing with %s\n') % url.hidepassword(source)) + return diffbookmarks(ui, repo, other) + else: + return oldincoming(ui, repo, source, **opts) + +def outgoing(oldoutgoing, ui, repo, dest=None, **opts): + if opts.get('bookmarks'): + dest = ui.expandpath(dest or 'default-push', dest or 'default') + dest, branches = hg.parseurl(dest, opts.get('branch')) + other = hg.repository(hg.remoteui(repo, opts), dest) + ui.status(_('comparing with %s\n') % url.hidepassword(dest)) + return diffbookmarks(ui, other, repo) + else: + return oldoutgoing(ui, repo, dest, **opts) + def uisetup(ui): extensions.wrapfunction(repair, "strip", strip) if ui.configbool('bookmarks', 'track.current'): @@ -456,6 +496,12 @@ entry = extensions.wrapcommand(commands.table, 'push', push) entry[1].append(('B', 'bookmark', [], _("bookmark to export"))) + entry = extensions.wrapcommand(commands.table, 'incoming', incoming) + entry[1].append(('B', 'bookmarks', False, + _("compare bookmark"))) + entry = extensions.wrapcommand(commands.table, 'outgoing', outgoing) + entry[1].append(('B', 'bookmarks', False, + _("compare bookmark"))) pushkey.register('bookmarks', pushbookmark, listbookmarks)
--- a/hgext/graphlog.py Mon Jun 21 17:02:48 2010 -0300 +++ b/hgext/graphlog.py Fri Jul 02 11:30:57 2010 +0200 @@ -209,6 +209,8 @@ def get_revs(repo, rev_opt): if rev_opt: revs = revrange(repo, rev_opt) + if len(revs) == 0: + return (nullrev, nullrev) return (max(revs), min(revs)) else: return (len(repo) - 1, 0)
--- a/hgext/mq.py Mon Jun 21 17:02:48 2010 -0300 +++ b/hgext/mq.py Fri Jul 02 11:30:57 2010 +0200 @@ -250,6 +250,7 @@ self.ui = ui self.applied_dirty = 0 self.series_dirty = 0 + self.added = [] self.series_path = "series" self.status_path = "status" self.guards_path = "guards" @@ -1017,7 +1018,7 @@ _("cannot push to a previous patch: %s") % patch) self.ui.warn( _('qpush: %s is already at the top\n') % patch) - return + return 0 pushable, reason = self.pushable(patch) if not pushable: if reason: @@ -1046,10 +1047,12 @@ if move: try: - del self.full_series[self.full_series.index(patch, start)] + index = self.series.index(patch, start) + fullpatch = self.full_series[index] + del self.full_series[index] except ValueError: raise util.Abort(_("patch '%s' not found") % patch) - self.full_series.insert(start, patch) + self.full_series.insert(start, fullpatch) self.parse_series() self.series_dirty = 1 @@ -1620,7 +1623,7 @@ if (len(files) > 1 or len(rev) > 1) and patchname: raise util.Abort(_('option "-n" not valid when importing multiple ' 'patches')) - added = [] + self.added = [] if rev: # If mq patches are applied, we can only import revisions # that form a linear path to qbase. @@ -1670,10 +1673,11 @@ se = statusentry(n, patchname) self.applied.insert(0, se) - added.append(patchname) + self.added.append(patchname) patchname = None self.parse_series() self.applied_dirty = 1 + self.series_dirty = True for i, filename in enumerate(files): if existing: @@ -1707,13 +1711,10 @@ index = self.full_series_end() + i self.full_series[index:index] = [patchname] self.parse_series() + self.series_dirty = True self.ui.warn(_("adding %s to series file\n") % patchname) - added.append(patchname) + self.added.append(patchname) patchname = None - self.series_dirty = 1 - qrepo = self.qrepo() - if qrepo: - qrepo[None].add(added) def delete(ui, repo, *patches, **opts): """remove patches from queue @@ -1803,10 +1804,15 @@ using the --name flag. """ q = repo.mq - q.qimport(repo, filename, patchname=opts['name'], + try: + q.qimport(repo, filename, patchname=opts['name'], existing=opts['existing'], force=opts['force'], rev=opts['rev'], git=opts['git']) - q.save_dirty() + finally: + q.save_dirty() + qrepo = q.qrepo() + if qrepo: + qrepo[None].add(q.added) if opts.get('push') and not opts.get('rev'): return q.push(repo, None)
--- a/hgext/progress.py Mon Jun 21 17:02:48 2010 -0300 +++ b/hgext/progress.py Fri Jul 02 11:30:57 2010 +0200 @@ -51,6 +51,9 @@ def spacejoin(*args): return ' '.join(s for s in args if s) +def shouldprint(ui): + return sys.stderr.isatty() or ui.configbool('progress', 'assume-tty') + class progbar(object): def __init__(self, ui): self.ui = ui @@ -69,6 +72,8 @@ default=['topic', 'bar', 'number']) def show(self, topic, pos, item, unit, total): + if not shouldprint(self.ui): + return termwidth = self.width() self.printed = True head = '' @@ -137,9 +142,13 @@ sys.stderr.flush() def clear(self): + if not shouldprint(self.ui): + return sys.stderr.write('\r%s\r' % (' ' * self.width())) def complete(self): + if not shouldprint(self.ui): + return if self.ui.configbool('progress', 'clear-complete', default=True): self.clear() else: @@ -177,8 +186,7 @@ # setconfig('progress', 'disable', 'True') to disable this extension if ui.configbool('progress', 'disable'): return - if ((sys.stderr.isatty() or ui.configbool('progress', 'assume-tty')) - and not ui.debugflag and not ui.quiet): + if shouldprint(ui) and not ui.debugflag and not ui.quiet: # we instantiate one globally shared progress bar to avoid # competing progress bars when multiple UI objects get created global sharedprog
--- a/hgext/zeroconf/Zeroconf.py Mon Jun 21 17:02:48 2010 -0300 +++ b/hgext/zeroconf/Zeroconf.py Fri Jul 02 11:30:57 2010 +0200 @@ -204,6 +204,13 @@ class BadTypeInNameException(Exception): pass +class BadDomainName(Exception): + def __init__(self, pos): + Exception.__init__(self, "at position %s" % pos) + +class BadDomainNameCircular(BadDomainName): + pass + # implementation classes class DNSEntry(object): @@ -598,10 +605,10 @@ next = off + 1 off = ((len & 0x3F) << 8) | ord(self.data[off]) if off >= first: - raise "Bad domain name (circular) at " + str(off) + raise BadDomainNameCircular(off) first = off else: - raise "Bad domain name at " + str(off) + raise BadDomainName(off) if next >= 0: self.offset = next
--- a/i18n/polib.py Mon Jun 21 17:02:48 2010 -0300 +++ b/i18n/polib.py Fri Jul 02 11:30:57 2010 +0200 @@ -1,5 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +# no-check-code # # License: MIT (see LICENSE file provided) # vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4:
--- a/mercurial/cmdutil.py Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/cmdutil.py Fri Jul 02 11:30:57 2010 +0200 @@ -905,7 +905,9 @@ if self.buffered: self.header[ctx.rev()] = h else: - self.ui.write(h) + if self.lastheader != h: + self.lastheader = h + self.ui.write(h) # write changeset metadata, then patch if requested key = types['changeset']
--- a/mercurial/commands.py Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/commands.py Fri Jul 02 11:30:57 2010 +0200 @@ -2570,6 +2570,10 @@ head, the other head is merged with by default. Otherwise, an explicit revision with which to merge with must be provided. + To undo an uncommitted merge, use :hg:`update --clean .` which + will check out a clean copy of the original merge parent, losing + all changes. + Returns 0 on success, 1 if there are unresolved files. """ @@ -3015,8 +3019,11 @@ def revert(ui, repo, *pats, **opts): """restore individual files or directories to an earlier state - (Use update -r to check out earlier revisions, revert does not - change the working directory parents.) + NOTE: This command is most likely not what you are looking for. revert + will partially overwrite content in the working directory without changing + the working directory parents. Use :hg:`update -r rev` to check out earlier + revisions, or :hg:`update --clean .` to undo a merge which has added + another parent. With no revision specified, revert the named files or directories to the contents they had in the parent of the working directory. @@ -3745,7 +3752,8 @@ for fname in fnames: f = url.open(ui, fname) gen = changegroup.readbundle(f, fname) - modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname) + modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname, + lock=lock) finally: lock.release()
--- a/mercurial/context.py Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/context.py Fri Jul 02 11:30:57 2010 +0200 @@ -490,12 +490,16 @@ return zip(hist[f][0], hist[f][1].splitlines(True)) - def ancestor(self, fc2): + def ancestor(self, fc2, actx=None): """ find the common ancestor file context, if any, of self, and fc2 + + If actx is given, it must be the changectx of the common ancestor + of self's and fc2's respective changesets. """ - actx = self.changectx().ancestor(fc2.changectx()) + if actx is None: + actx = self.changectx().ancestor(fc2.changectx()) # the trivial case: changesets are unrelated, files must be too if not actx:
--- a/mercurial/discovery.py Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/discovery.py Fri Jul 02 11:30:57 2010 +0200 @@ -280,7 +280,7 @@ remotemap = remote.branchmap() newbranches = branches - set(remotemap) if newbranches and not newbranch: # new branch requires --new-branch - branchnames = ', '.join("%s" % b for b in newbranches) + branchnames = ', '.join(sorted(newbranches)) repo.ui.warn(_("abort: push creates " "new remote branches: %s!\n") % branchnames)
--- a/mercurial/help/glossary.txt Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/help/glossary.txt Fri Jul 02 11:30:57 2010 +0200 @@ -8,7 +8,7 @@ Branch (Noun) A child changeset that has been created from a parent that is not a head. These are known as topological branches, see - 'Branch, topological'.If a topological branch is named, it becomes + 'Branch, topological'. If a topological branch is named, it becomes a named branch. If a topological branch is not named, it becomes an anonymous branch. See 'Branch, anonymous' and 'Branch, named'. @@ -55,8 +55,8 @@ collection of disjoint subsets. A named branch is not necessarily a topological branch. If a new named branch is created from the head of another named branch, or the default branch, but no - further changesets are added to that previous branch, then the new - named branch will be a branch in name only. + further changesets are added to that previous branch, then that + previous branch will be a branch in name only. Branch tip See 'Tip, branch'. @@ -151,7 +151,7 @@ consisting of nodes and edges, where nodes correspond to changesets and edges imply a parent -> child relation. This graph can be visualized by graphical tools such as :hg:`glog` - (graphlog). In mercurial, the DAG is limited by the requirement + (graphlog). In Mercurial, the DAG is limited by the requirement for children to have at most two parents. Default branch @@ -322,7 +322,7 @@ pointing to the data. Rewriting history - See 'History, rewriting'. + See 'History, rewriting'. Root A changeset that has only the null changeset as its parent. Most @@ -342,7 +342,7 @@ Update (Noun) Another synonym of changeset. - Example: "I've pushed an update". + Example: "I've pushed an update". (Verb) This term is usually used to describe updating the state of the working directory to that of a specific changeset. See @@ -354,4 +354,4 @@ See 'Directory, working'. Working directory parent - See 'Parent, working directory'. + See 'Parent, working directory'.
--- a/mercurial/help/revsets.txt Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/help/revsets.txt Fri Jul 02 11:30:57 2010 +0200 @@ -21,7 +21,7 @@ A DAG range, meaning all changesets that are descendants of x and ancestors of y, including x and y themselves. If the first endpoint is left out, this is equivalent to ``ancestors(y)``, if the second - is left out it is equivalent to ``descendents(x)``. + is left out it is equivalent to ``descendants(x)``. An alternative syntax is ``x..y``.
--- a/mercurial/hgweb/protocol.py Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/hgweb/protocol.py Fri Jul 02 11:30:57 2010 +0200 @@ -164,7 +164,7 @@ urllib.quote(req.env.get('REMOTE_HOST', '')), urllib.quote(req.env.get('REMOTE_USER', ''))) try: - ret = repo.addchangegroup(gen, 'serve', url) + ret = repo.addchangegroup(gen, 'serve', url, lock=lock) except util.Abort, inst: sys.stdout.write("abort: %s\n" % inst) ret = 0
--- a/mercurial/hook.py Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/hook.py Fri Jul 02 11:30:57 2010 +0200 @@ -98,7 +98,10 @@ cwd = repo.root else: cwd = os.getcwd() - r = util.system(cmd, environ=env, cwd=cwd) + if 'HG_URL' in env and env['HG_URL'].startswith('remote:http'): + r = util.system(cmd, environ=env, cwd=cwd, out=ui) + else: + r = util.system(cmd, environ=env, cwd=cwd) if r: desc, r = util.explain_exit(r) if throw:
--- a/mercurial/localrepo.py Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/localrepo.py Fri Jul 02 11:30:57 2010 +0200 @@ -1199,7 +1199,7 @@ "other repository doesn't support " "changegroupsubset.")) cg = remote.changegroupsubset(fetch, heads, 'pull') - return self.addchangegroup(cg, 'pull', remote.url()) + return self.addchangegroup(cg, 'pull', remote.url(), lock=lock) finally: lock.release() @@ -1233,8 +1233,8 @@ ret = discovery.prepush(self, remote, force, revs, newbranch) if ret[0] is not None: cg, remote_heads = ret - # here, we return an integer indicating remote head count change - return remote.addchangegroup(cg, 'push', self.url()) + # we return an integer indicating remote head count change + return remote.addchangegroup(cg, 'push', self.url(), lock=lock) # and here we return 0 for "nothing to push" or 1 for # "something to push but I refuse" return ret[1] @@ -1620,7 +1620,7 @@ return util.chunkbuffer(gengroup()) - def addchangegroup(self, source, srctype, url, emptyok=False): + def addchangegroup(self, source, srctype, url, emptyok=False, lock=None): """Add the changegroup returned by source.read() to this repo. srctype is a string like 'push', 'pull', or 'unbundle'. url is the URL of the repo where this changegroup is coming from. @@ -1760,6 +1760,8 @@ tr.close() finally: tr.release() + if lock: + lock.release() if changesets > 0: # forcefully update the on-disk branch cache
--- a/mercurial/merge.py Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/merge.py Fri Jul 02 11:30:57 2010 +0200 @@ -23,15 +23,13 @@ def _read(self): self._state = {} try: - localnode = None f = self._repo.opener("merge/state") for i, l in enumerate(f): if i == 0: - localnode = l[:-1] + self._local = bin(l[:-1]) else: bits = l[:-1].split("\0") self._state[bits[0]] = bits[1:] - self._local = bin(localnode) except IOError, err: if err.errno != errno.ENOENT: raise @@ -184,7 +182,9 @@ rflags = fmerge(f, f, f) a = ma.get(f, nullid) if n == m2[f] or m2[f] == a: # same or local newer - if m1.flags(f) != rflags: + # is file locally modified or flags need changing? + # dirstate flags may need to be made current + if m1.flags(f) != rflags or n[20:]: act("update permissions", "e", f, rflags) elif n == a: # remote newer act("remote is newer", "g", f, rflags) @@ -244,8 +244,13 @@ def actionkey(a): return a[1] == 'r' and -1 or 0, a -def applyupdates(repo, action, wctx, mctx): - "apply the merge action list to the working directory" +def applyupdates(repo, action, wctx, mctx, actx): + """apply the merge action list to the working directory + + wctx is the working copy context + mctx is the context to be merged into the working copy + actx is the context of the common ancestor + """ updated, merged, removed, unresolved = 0, 0, 0, 0 ms = mergestate(repo) @@ -265,7 +270,7 @@ repo.ui.debug("preserving %s for resolve of %s\n" % (f, fd)) fcl = wctx[f] fco = mctx[f2] - fca = fcl.ancestor(fco) or repo.filectx(f, fileid=nullrev) + fca = fcl.ancestor(fco, actx) or repo.filectx(f, fileid=nullrev) ms.add(fcl, fco, fca, fd, flags) if f != fd and move: moves.append(f) @@ -507,7 +512,7 @@ if not partial: repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2) - stats = applyupdates(repo, action, wc, p2) + stats = applyupdates(repo, action, wc, p2, pa) if not partial: repo.dirstate.setparents(fp1, fp2)
--- a/mercurial/minirst.py Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/minirst.py Fri Jul 02 11:30:57 2010 +0200 @@ -36,7 +36,13 @@ """ import re, sys -import util +import util, encoding + +def replace(text, substs): + utext = text.decode(encoding.encoding) + for f, t in substs: + utext = utext.replace(f, t) + return utext.encode(encoding.encoding) def findblocks(text): """Find continuous blocks of lines in text. @@ -251,21 +257,22 @@ def inlineliterals(blocks): + substs = [('``', '"')] for b in blocks: if b['type'] in ('paragraph', 'section'): - b['lines'] = [l.replace('``', '"') for l in b['lines']] + b['lines'] = [replace(l, substs) for l in b['lines']] return blocks def hgrole(blocks): + substs = [(':hg:`', '"hg '), ('`', '"')] for b in blocks: if b['type'] in ('paragraph', 'section'): # Turn :hg:`command` into "hg command". This also works # when there is a line break in the command and relies on # the fact that we have no stray back-quotes in the input # (run the blocks through inlineliterals first). - b['lines'] = [l.replace(':hg:`', '"hg ').replace('`', '"') - for l in b['lines']] + b['lines'] = [replace(l, substs) for l in b['lines']] return blocks
--- a/mercurial/parser.py Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/parser.py Fri Jul 02 11:30:57 2010 +0200 @@ -5,7 +5,7 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -# see http://effbot.org/zone/simple-top-down-parsing.txt and +# see http://effbot.org/zone/simple-top-down-parsing.htm and # http://eli.thegreenplace.net/2010/01/02/top-down-operator-precedence-parsing/ # for background
--- a/mercurial/revset.py Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/revset.py Fri Jul 02 11:30:57 2010 +0200 @@ -111,10 +111,6 @@ # operator methods -def negate(repo, subset, x): - return getset(repo, subset, - ('string', '-' + getstring(x, _("can't negate that")))) - def stringset(repo, subset, x): x = repo[x].rev() if x == -1 and len(subset) == len(repo): @@ -129,11 +125,24 @@ return stringset(repo, subset, x) def rangeset(repo, subset, x, y): - m = getset(repo, subset, x)[0] - n = getset(repo, subset, y)[-1] + m = getset(repo, subset, x) + if not m: + m = getset(repo, range(len(repo)), x) + + n = getset(repo, subset, y) + if not n: + n = getset(repo, range(len(repo)), y) + + if not m or not n: + return [] + m, n = m[0], n[-1] + if m < n: - return range(m, n + 1) - return range(m, n - 1, -1) + r = range(m, n + 1) + else: + r = range(m, n - 1, -1) + s = set(subset) + return [x for x in r if x in s] def andset(repo, subset, x, y): return getset(repo, getset(repo, subset, x), y) @@ -222,11 +231,15 @@ def ancestors(repo, subset, x): args = getset(repo, range(len(repo)), x) + if not args: + return [] s = set(repo.changelog.ancestors(*args)) | set(args) return [r for r in subset if r in s] def descendants(repo, subset, x): args = getset(repo, range(len(repo)), x) + if not args: + return [] s = set(repo.changelog.descendants(*args)) | set(args) return [r for r in subset if r in s] @@ -422,7 +435,6 @@ repo.ui.popbuffer() cl = repo.changelog o = set([cl.rev(r) for r in repo.changelog.nodesbetween(o, None)[0]]) - print 'out', dest, o return [r for r in subset if r in o] def tagged(repo, subset, x): @@ -466,7 +478,6 @@ } methods = { - "negate": negate, "range": rangeset, "string": stringset, "symbol": symbolset, @@ -499,6 +510,9 @@ return optimize(('range', ('string', '0'), x[1]), small) elif op == 'rangepost': return optimize(('range', x[1], ('string', 'tip')), small) + elif op == 'negate': + return optimize(('string', + '-' + getstring(x[1], _("can't negate that"))), small) elif op in 'string symbol negate': return smallbonus, x # single revisions are small elif op == 'and' or op == 'dagrange':
--- a/mercurial/sshserver.py Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/sshserver.py Fri Jul 02 11:30:57 2010 +0200 @@ -161,7 +161,8 @@ return self.respond("") - r = self.repo.addchangegroup(self.fin, 'serve', self.client_url()) + r = self.repo.addchangegroup(self.fin, 'serve', self.client_url(), + lock=self.lock) self.respond(str(r)) def client_url(self): @@ -205,7 +206,8 @@ # push can proceed fp.seek(0) - r = self.repo.addchangegroup(fp, 'serve', self.client_url()) + r = self.repo.addchangegroup(fp, 'serve', self.client_url(), + lock=self.lock) self.respond(str(r)) finally: if not was_locked:
--- a/mercurial/subrepo.py Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/subrepo.py Fri Jul 02 11:30:57 2010 +0200 @@ -67,19 +67,21 @@ repo.ui.debug(" subrepo %s: %s %s\n" % (s, msg, r)) for s, l in s1.items(): + ld = l # local state with possible dirty flag for compares if wctx != actx and wctx.sub(s).dirty(): - l = (l[0], l[1] + "+") + ld = (l[0], l[1] + "+") + a = sa.get(s, nullstate) if s in s2: r = s2[s] - if l == r or r == a: # no change or local is newer + if ld == r or r == a: # no change or local is newer sm[s] = l continue - elif l == a: # other side changed + elif ld == a: # other side changed debug(s, "other changed, get", r) wctx.sub(s).get(r) sm[s] = r - elif l[0] != r[0]: # sources differ + elif ld[0] != r[0]: # sources differ if repo.ui.promptchoice( _(' subrepository sources for %s differ\n' 'use (l)ocal source (%s) or (r)emote source (%s)?') @@ -88,7 +90,7 @@ debug(s, "prompt changed, get", r) wctx.sub(s).get(r) sm[s] = r - elif l[1] == a[1]: # local side is unchanged + elif ld[1] == a[1]: # local side is unchanged debug(s, "other side changed, get", r) wctx.sub(s).get(r) sm[s] = r @@ -96,7 +98,7 @@ debug(s, "both sides changed, merge with", r) wctx.sub(s).merge(r) sm[s] = l - elif l == a: # remote removed, local unchanged + elif ld == a: # remote removed, local unchanged debug(s, "remote removed, remove") wctx.sub(s).remove() else: @@ -379,8 +381,8 @@ self.get(state) def push(self, force): - # nothing for svn - pass + # push is a no-op for SVN + return True types = { 'hg': hgsubrepo,
--- a/mercurial/url.py Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/url.py Fri Jul 02 11:30:57 2010 +0200 @@ -542,11 +542,25 @@ conn.ui = self.ui return conn -# In python < 2.5 AbstractDigestAuthHandler raises a ValueError if -# it doesn't know about the auth type requested. This can happen if -# somebody is using BasicAuth and types a bad password. class httpdigestauthhandler(urllib2.HTTPDigestAuthHandler): + def __init__(self, *args, **kwargs): + urllib2.HTTPDigestAuthHandler.__init__(self, *args, **kwargs) + self.retried_req = None + + def reset_retry_count(self): + # Python 2.6.5 will call this on 401 or 407 errors and thus loop + # forever. We disable reset_retry_count completely and reset in + # http_error_auth_reqed instead. + pass + def http_error_auth_reqed(self, auth_header, host, req, headers): + # Reset the retry counter once for each request. + if req is not self.retried_req: + self.retried_req = req + self.retried = 0 + # In python < 2.5 AbstractDigestAuthHandler raises a ValueError if + # it doesn't know about the auth type requested. This can happen if + # somebody is using BasicAuth and types a bad password. try: return urllib2.HTTPDigestAuthHandler.http_error_auth_reqed( self, auth_header, host, req, headers) @@ -556,13 +570,6 @@ return raise - # Python 2.6.5 will keep resetting the retry count on redirects, for - # example when the server returns 401 on failing auth (like google code - # currently does). We stop the endless recursion by not resetting the - # count. - def reset_retry_count(self): - pass - def getauthinfo(path): scheme, netloc, urlpath, query, frag = urlparse.urlsplit(path) if not urlpath:
--- a/mercurial/util.py Mon Jun 21 17:02:48 2010 -0300 +++ b/mercurial/util.py Fri Jul 02 11:30:57 2010 +0200 @@ -366,13 +366,16 @@ global _hgexecutable _hgexecutable = path -def system(cmd, environ={}, cwd=None, onerr=None, errprefix=None): +def system(cmd, environ={}, cwd=None, onerr=None, errprefix=None, out=None): '''enhanced shell command execution. run with environment maybe modified, maybe in different dir. if command fails and onerr is None, return status. if ui object, print error message and return status, else raise onerr object as - exception.''' + exception. + + if out is specified, it is assumed to be a file-like object that has a + write() method. stdout and stderr will be redirected to out.''' def py2shell(val): 'convert python object into string that is useful to shell' if val is None or val is False: @@ -386,8 +389,17 @@ env = dict(os.environ) env.update((k, py2shell(v)) for k, v in environ.iteritems()) env['HG'] = hgexecutable() - rc = subprocess.call(cmd, shell=True, close_fds=closefds, - env=env, cwd=cwd) + if out is None: + rc = subprocess.call(cmd, shell=True, close_fds=closefds, + env=env, cwd=cwd) + else: + proc = subprocess.Popen(cmd, shell=True, close_fds=closefds, + env=env, cwd=cwd, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + for line in proc.stdout: + out.write(line) + proc.wait() + rc = proc.returncode if sys.platform == 'OpenVMS' and rc & 1: rc = 0 if rc and onerr:
--- a/setup.py Mon Jun 21 17:02:48 2010 -0300 +++ b/setup.py Fri Jul 02 11:30:57 2010 +0200 @@ -35,12 +35,15 @@ import os, subprocess, time import shutil import tempfile +from distutils import log from distutils.core import setup, Extension from distutils.dist import Distribution from distutils.command.build import build +from distutils.command.build_ext import build_ext from distutils.command.build_py import build_py from distutils.spawn import spawn, find_executable from distutils.ccompiler import new_compiler +from distutils.errors import CCompilerError scripts = ['hg'] if os.name == 'nt': @@ -209,6 +212,17 @@ Distribution.global_options.append(('pure', None, "use pure (slow) Python " "code instead of C extensions")) +class hgbuildext(build_ext): + + def build_extension(self, ext): + try: + build_ext.build_extension(self, ext) + except CCompilerError: + if not hasattr(ext, 'optional') or not ext.optional: + raise + log.warn("Failed to build optional extension '%s' (skipping)", + ext.name) + class hgbuildpy(build_py): def finalize_options(self): @@ -232,6 +246,7 @@ yield module cmdclass = {'build_mo': hgbuildmo, + 'build_ext': hgbuildext, 'build_py': hgbuildpy} packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert', @@ -256,10 +271,13 @@ if sys.platform == 'linux2' and os.uname()[2] > '2.6': # The inotify extension is only usable with Linux 2.6 kernels. # You also need a reasonably recent C library. + # In any case, if it fails to build the error will be skipped ('optional'). cc = new_compiler() if hasfunction(cc, 'inotify_add_watch'): - extmodules.append(Extension('hgext.inotify.linux._inotify', - ['hgext/inotify/linux/_inotify.c'])) + inotify = Extension('hgext.inotify.linux._inotify', + ['hgext/inotify/linux/_inotify.c']) + inotify.optional = True + extmodules.append(inotify) packages.extend(['hgext.inotify', 'hgext.inotify.linux']) packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
--- a/tests/test-acl Mon Jun 21 17:02:48 2010 -0300 +++ b/tests/test-acl Fri Jul 02 11:30:57 2010 +0200 @@ -44,7 +44,7 @@ [acl] sources = push [extensions] -f=$PWD/fakegroups.py +f=`pwd`/fakegroups.py EOF }
--- a/tests/test-alias Mon Jun 21 17:02:48 2010 -0300 +++ b/tests/test-alias Fri Jul 02 11:30:57 2010 +0200 @@ -13,7 +13,7 @@ shortlog = log --template '{rev} {node|short} | {date|isodate}\n' dln = lognull --debug nousage = rollback -put = export -r 0 -o "\$PWD/%R.diff" +put = export -r 0 -o "\$FOO/%R.diff" [defaults] mylog = -q @@ -62,5 +62,5 @@ hg dln echo '% path expanding' -hg put +FOO=`pwd` hg put cat 0.diff
--- a/tests/test-command-template Mon Jun 21 17:02:48 2010 -0300 +++ b/tests/test-command-template Fri Jul 02 11:30:57 2010 +0200 @@ -100,6 +100,9 @@ hg log --style=changelog > changelog cat changelog +echo '# issue 2130' +hg heads --style changelog + echo "# keys work" for key in author branches date desc file_adds file_dels file_mods \ file_copies file_copies_switch files \
--- a/tests/test-command-template.out Mon Jun 21 17:02:48 2010 -0300 +++ b/tests/test-command-template.out Fri Jul 02 11:30:57 2010 +0200 @@ -437,6 +437,23 @@ line 1 line 2 [1e4e1b8f71e0] +# issue 2130 +2020-01-01 test <test> + + * fourth, second, third: + third + [95c24699272e] [tip] + +1970-01-18 person <person> + + * merge + [c7b487c6c50e] + +1970-01-17 person <person> + + * new branch + [32a18f097fcc] <foo> + # keys work author: test author: User Name <user@hostname>
--- a/tests/test-glog Mon Jun 21 17:02:48 2010 -0300 +++ b/tests/test-glog Fri Jul 02 11:30:57 2010 +0200 @@ -146,6 +146,9 @@ echo % unused arguments hg glog -q foo bar || echo failed +echo % empty revision range - display nothing +hg glog -r 1..0 + echo % from outer space cd .. hg glog -l1 repo
--- a/tests/test-glog.out Mon Jun 21 17:02:48 2010 -0300 +++ b/tests/test-glog.out Fri Jul 02 11:30:57 2010 +0200 @@ -548,6 +548,7 @@ show revision history alongside an ASCII revision graph failed +% empty revision range - display nothing % from outer space @ changeset: 34:fea3ac5810e0 | tag: tip
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-mq-qimport-fail-cleanup Fri Jul 02 11:30:57 2010 +0200 @@ -0,0 +1,33 @@ +#!/bin/sh +#failed qimport of patches from files should cleanup by recording successfully +#imported patches in series file. + +echo "[extensions]" >> $HGRCPATH +echo "mq=" >> $HGRCPATH + +hg init repo +cd repo + +echo a > a +hg ci -Am'add a' + +cat >b.patch<<EOF +diff --git a/a b/a +--- a/a ++++ b/a +@@ -1,1 +1,2 @@ + a ++b +EOF + +echo +echo '#empty series' +hg qseries + +echo +echo '#qimport valid patch followed by invalid patch' +hg qimport b.patch fakepatch + +echo +echo '#valid patches before fail added to series' +hg qseries
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-mq-qimport-fail-cleanup.out Fri Jul 02 11:30:57 2010 +0200 @@ -0,0 +1,10 @@ +adding a + +#empty series + +#qimport valid patch followed by invalid patch +adding b.patch to series file +abort: unable to read fakepatch + +#valid patches before fail added to series +b.patch
--- a/tests/test-push-http Mon Jun 21 17:02:48 2010 -0300 +++ b/tests/test-push-http Fri Jul 02 11:30:57 2010 +0200 @@ -39,11 +39,9 @@ echo % expect success echo 'allow_push = *' >> .hg/hgrc echo '[hooks]' >> .hg/hgrc -echo 'changegroup = python ../printenv.py changegroup 0 ../urls' >> .hg/hgrc +echo 'changegroup = python ../printenv.py changegroup 0' >> .hg/hgrc req -cat ../urls - hg rollback echo % expect authorization error: all users denied echo '[web]' > .hg/hgrc
--- a/tests/test-push-http.out Mon Jun 21 17:02:48 2010 -0300 +++ b/tests/test-push-http.out Fri Jul 02 11:30:57 2010 +0200 @@ -23,8 +23,8 @@ remote: adding manifests remote: adding file changes remote: added 1 changesets with 1 changes to 1 files +remote: changegroup hook: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_URL=remote:http % serve errors -changegroup hook: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_URL=remote:http rolling back to revision 0 (undo serve) % expect authorization error: all users denied abort: authorization failed
--- a/tests/test-resolve Mon Jun 21 17:02:48 2010 -0300 +++ b/tests/test-resolve Fri Jul 02 11:30:57 2010 +0200 @@ -25,3 +25,9 @@ echo % resolve -l, should be empty hg resolve -l + +# test crashed merge with empty mergestate +mkdir .hg/merge +touch .hg/merge/state +echo % resolve -l, should be empty +hg resolve -l
--- a/tests/test-resolve.out Mon Jun 21 17:02:48 2010 -0300 +++ b/tests/test-resolve.out Fri Jul 02 11:30:57 2010 +0200 @@ -6,3 +6,4 @@ 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C' to abandon % resolve -l, should be empty +% resolve -l, should be empty
--- a/tests/test-revset Mon Jun 21 17:02:48 2010 -0300 +++ b/tests/test-revset Fri Jul 02 11:30:57 2010 +0200 @@ -126,3 +126,11 @@ log '4:8' log 'sort(!merge() & (modifies(b) | user(bob) | keyword(bug) | keyword(issue) & 1::9), "-date")' + +log 'not 0 and 0:2' +log 'not 1 and 0:2' +log 'not 2 and 0:2' +log '(1 and 2)::' +log '(1 and 2):' +log '(1 and 2):3' +log 'sort(head(), -rev)'
--- a/tests/test-revset.out Mon Jun 21 17:02:48 2010 -0300 +++ b/tests/test-revset.out Fri Jul 02 11:30:57 2010 +0200 @@ -198,3 +198,25 @@ 4 2 5 +% log 'not 0 and 0:2' +1 +2 +% log 'not 1 and 0:2' +0 +2 +% log 'not 2 and 0:2' +0 +1 +% log '(1 and 2)::' +% log '(1 and 2):' +% log '(1 and 2):3' +% log 'sort(head(), -rev)' +9 +7 +6 +5 +4 +3 +2 +1 +0