Mercurial > hg
changeset 19707:591cbff13a7f
merge with stable
author | Kevin Bullock <kbullock@ringworld.org> |
---|---|
date | Sat, 07 Sep 2013 00:08:36 -0500 |
parents | 79792c8ea6da (diff) 26ddce1a2a55 (current diff) |
children | 600ea1a6884c |
files | |
diffstat | 42 files changed, 710 insertions(+), 439 deletions(-) [+] |
line wrap: on
line diff
--- a/contrib/check-code.py Tue Aug 06 00:52:06 2013 +0400 +++ b/contrib/check-code.py Sat Sep 07 00:08:36 2013 -0500 @@ -61,11 +61,13 @@ (r'pushd|popd', "don't use 'pushd' or 'popd', use 'cd'"), (r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"), (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"), + (r'(?<!hg )grep.*-a', "don't use 'grep -a', use in-line python"), (r'sed.*-i', "don't use 'sed -i', use a temporary file"), (r'\becho\b.*\\n', "don't use 'echo \\n', use printf"), (r'echo -n', "don't use 'echo -n', use printf"), (r'(^| )wc[^|]*$\n(?!.*\(re\))', "filter wc output"), (r'head -c', "don't use 'head -c', use 'dd'"), + (r'tail -n', "don't use the '-n' option to tail, just use '-<num>'"), (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"), (r'ls.*-\w*R', "don't use 'ls -R', use 'find'"), (r'printf.*[^\\]\\([1-9]|0\d)', "don't use 'printf \NNN', use Python"),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/plan9/9mail Sat Sep 07 00:08:36 2013 -0500 @@ -0,0 +1,26 @@ +#!/bin/rc +# 9mail - Mercurial email wrapper for upas/marshal + +fn usage { + echo >[1=2] usage: mercurial/9mail -f from to [cc] + exit usage +} + +from=() +cc=() +to=() + +switch($1){ +case -f + from=$2 +case * + usage +} + +to=($3) +if(~ $#* 4) + cc=(-C $4) + +upasname=$from +upas/marshal $cc $to +
--- a/contrib/plan9/hgrc.d/9diff.rc Tue Aug 06 00:52:06 2013 +0400 +++ b/contrib/plan9/hgrc.d/9diff.rc Sat Sep 07 00:08:36 2013 -0500 @@ -4,4 +4,4 @@ extdiff = [extdiff] -9diff = 9diff -cm $parent $child $root +9diff = /bin/mercurial/9diff -cm $parent $child $root
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/plan9/hgrc.d/9mail.rc Sat Sep 07 00:08:36 2013 -0500 @@ -0,0 +1,4 @@ +# The 9mail to support patchbomb and other email wrappers +[email] +method = /bin/mercurial/9mail +
--- a/hgext/factotum.py Tue Aug 06 00:52:06 2013 +0400 +++ b/hgext/factotum.py Sat Sep 07 00:08:36 2013 -0500 @@ -101,7 +101,7 @@ user, passwd = auth.get('username'), auth.get('password') if not user or not passwd: if not prefix: - prefix = '*' + prefix = realm.split(' ')[0].lower() params = 'service=%s prefix=%s' % (_service, prefix) if user: params = '%s user=%s' % (params, user)
--- a/hgext/histedit.py Tue Aug 06 00:52:06 2013 +0400 +++ b/hgext/histedit.py Sat Sep 07 00:08:36 2013 -0500 @@ -419,10 +419,6 @@ if revs: revs = [repo.lookup(rev) for rev in revs] - # hexlify nodes from outgoing, because we're going to parse - # parent[0] using revsingle below, and if the binary hash - # contains special revset characters like ":" the revset - # parser can choke. outgoing = discovery.findcommonoutgoing(repo, other, revs, force=force) if not outgoing.missing: raise util.Abort(_('no outgoing ancestors'))
--- a/hgext/largefiles/reposetup.py Tue Aug 06 00:52:06 2013 +0400 +++ b/hgext/largefiles/reposetup.py Sat Sep 07 00:08:36 2013 -0500 @@ -10,8 +10,7 @@ import copy import os -from mercurial import context, error, manifest, match as match_, util, \ - discovery +from mercurial import error, manifest, match as match_, util, discovery from mercurial import node as node_ from mercurial.i18n import _ from mercurial import localrepo @@ -92,14 +91,8 @@ else: # some calls in this function rely on the old version of status self.lfstatus = False - if isinstance(node1, context.changectx): - ctx1 = node1 - else: - ctx1 = self[node1] - if isinstance(node2, context.changectx): - ctx2 = node2 - else: - ctx2 = self[node2] + ctx1 = self[node1] + ctx2 = self[node2] working = ctx2.rev() is None parentworking = working and ctx1 == self['.']
--- a/hgext/mq.py Tue Aug 06 00:52:06 2013 +0400 +++ b/hgext/mq.py Sat Sep 07 00:08:36 2013 -0500 @@ -66,6 +66,7 @@ from mercurial import repair, extensions, error, phases from mercurial import patch as patchmod from mercurial import localrepo +from mercurial import subrepo import os, re, errno, shutil commands.norepo += " qclone" @@ -800,6 +801,14 @@ p1, p2 = repo.dirstate.parents() repo.setparents(p1, merge) + if all_files and '.hgsubstate' in all_files: + wctx = repo['.'] + mctx = actx = repo[None] + overwrite = False + mergedsubstate = subrepo.submerge(repo, wctx, mctx, actx, + overwrite) + files += mergedsubstate.keys() + match = scmutil.matchfiles(repo, files or []) oldtip = repo['tip'] n = newcommit(repo, None, message, ph.user, ph.date, match=match, @@ -975,11 +984,20 @@ else: raise util.Abort(_("local changes found")) + def localchangedsubreposfound(self, refresh=True): + if refresh: + raise util.Abort(_("local changed subrepos found, refresh first")) + else: + raise util.Abort(_("local changed subrepos found")) + def checklocalchanges(self, repo, force=False, refresh=True): cmdutil.checkunfinished(repo) m, a, r, d = repo.status()[:4] - if (m or a or r or d) and not force: - self.localchangesfound(refresh) + if not force: + if (m or a or r or d): + self.localchangesfound(refresh) + if self.checksubstate(repo): + self.localchangedsubreposfound(refresh) return m, a, r, d _reserved = ('series', 'status', 'guards', '.', '..') @@ -1450,6 +1468,8 @@ self.ui.status(_("popping %s\n") % patch.name) del self.applied[start:end] self.strip(repo, [rev], update=False, backup='strip') + for s, state in repo['.'].substate.items(): + repo['.'].sub(s).get(state) if self.applied: self.ui.write(_("now at: %s\n") % self.applied[-1].name) else:
--- a/hgext/progress.py Tue Aug 06 00:52:06 2013 +0400 +++ b/hgext/progress.py Sat Sep 07 00:08:36 2013 -0500 @@ -239,6 +239,13 @@ # this one are also closed if topic in self.topics: self.topics = self.topics[:self.topics.index(topic)] + # reset the last topic to the one we just unwound to, + # so that higher-level topics will be stickier than + # lower-level topics + if self.topics: + self.lasttopic = self.topics[-1] + else: + self.lasttopic = None else: if topic not in self.topics: self.starttimes[topic] = now
--- a/mercurial/bundlerepo.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/bundlerepo.py Sat Sep 07 00:08:36 2013 -0500 @@ -120,7 +120,7 @@ chain.append(iterrev) iterrev = self.index[iterrev][3] if text is None: - text = revlog.revlog.revision(self, iterrev) + text = self.baserevision(iterrev) while chain: delta = self._chunk(chain.pop()) @@ -130,6 +130,12 @@ self._cache = (node, rev, text) return text + def baserevision(self, nodeorrev): + # Revlog subclasses may override 'revision' method to modify format of + # content retrieved from revlog. To use bundlerevlog with such class one + # needs to override 'baserevision' and make more specific call here. + return revlog.revlog.revision(self, nodeorrev) + def addrevision(self, text, transaction, link, p1=None, p2=None, d=None): raise NotImplementedError def addgroup(self, revs, linkmapper, transaction): @@ -146,12 +152,21 @@ bundlerevlog.__init__(self, opener, self.indexfile, bundle, linkmapper) + def baserevision(self, nodeorrev): + # Although changelog doesn't override 'revision' method, some extensions + # may replace this class with another that does. Same story with + # manifest and filelog classes. + return changelog.changelog.revision(self, nodeorrev) + class bundlemanifest(bundlerevlog, manifest.manifest): def __init__(self, opener, bundle, linkmapper): manifest.manifest.__init__(self, opener) bundlerevlog.__init__(self, opener, self.indexfile, bundle, linkmapper) + def baserevision(self, nodeorrev): + return manifest.manifest.revision(self, nodeorrev) + class bundlefilelog(bundlerevlog, filelog.filelog): def __init__(self, opener, path, bundle, linkmapper, repo): filelog.filelog.__init__(self, opener, path) @@ -159,6 +174,9 @@ linkmapper) self._repo = repo + def baserevision(self, nodeorrev): + return filelog.filelog.revision(self, nodeorrev) + def _file(self, f): self._repo.file(f)
--- a/mercurial/commands.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/commands.py Sat Sep 07 00:08:36 2013 -0500 @@ -1923,6 +1923,7 @@ util.writefile('.debugfsinfo', '') ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no')) ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no')) + ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no')) ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo') and 'yes' or 'no')) os.unlink('.debugfsinfo')
--- a/mercurial/context.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/context.py Sat Sep 07 00:08:36 2013 -0500 @@ -16,11 +16,150 @@ propertycache = util.propertycache -class changectx(object): +class basectx(object): + """A basectx object represents the common logic for its children: + changectx: read-only context that is already present in the repo, + workingctx: a context that represents the working directory and can + be committed, + memctx: a context that represents changes in-memory and can also + be committed.""" + def __new__(cls, repo, changeid='', *args, **kwargs): + if isinstance(changeid, basectx): + return changeid + + o = super(basectx, cls).__new__(cls) + + o._repo = repo + o._rev = nullrev + o._node = nullid + + return o + + def __str__(self): + return short(self.node()) + + def __int__(self): + return self.rev() + + def __repr__(self): + return "<%s %s>" % (type(self).__name__, str(self)) + + def __eq__(self, other): + try: + return type(self) == type(other) and self._rev == other._rev + except AttributeError: + return False + + def __ne__(self, other): + return not (self == other) + + def __contains__(self, key): + return key in self._manifest + + def __getitem__(self, key): + return self.filectx(key) + + def __iter__(self): + for f in sorted(self._manifest): + yield f + + @propertycache + def substate(self): + return subrepo.state(self, self._repo.ui) + + def rev(self): + return self._rev + def node(self): + return self._node + def hex(self): + return hex(self.node()) + def manifest(self): + return self._manifest + def phasestr(self): + return phases.phasenames[self.phase()] + def mutable(self): + return self.phase() > phases.public + + def parents(self): + """return contexts for each parent changeset""" + return self._parents + + def p1(self): + return self._parents[0] + + def p2(self): + if len(self._parents) == 2: + return self._parents[1] + return changectx(self._repo, -1) + + def _fileinfo(self, path): + if '_manifest' in self.__dict__: + try: + return self._manifest[path], self._manifest.flags(path) + except KeyError: + raise error.ManifestLookupError(self._node, path, + _('not found in manifest')) + if '_manifestdelta' in self.__dict__ or path in self.files(): + if path in self._manifestdelta: + return (self._manifestdelta[path], + self._manifestdelta.flags(path)) + node, flag = self._repo.manifest.find(self._changeset[0], path) + if not node: + raise error.ManifestLookupError(self._node, path, + _('not found in manifest')) + + return node, flag + + def filenode(self, path): + return self._fileinfo(path)[0] + + def flags(self, path): + try: + return self._fileinfo(path)[1] + except error.LookupError: + return '' + + def sub(self, path): + return subrepo.subrepo(self, path) + + def match(self, pats=[], include=None, exclude=None, default='glob'): + r = self._repo + return matchmod.match(r.root, r.getcwd(), pats, + include, exclude, default, + auditor=r.auditor, ctx=self) + + def diff(self, ctx2=None, match=None, **opts): + """Returns a diff generator for the given contexts and matcher""" + if ctx2 is None: + ctx2 = self.p1() + if ctx2 is not None: + ctx2 = self._repo[ctx2] + diffopts = patch.diffopts(self._repo.ui, opts) + return patch.diff(self._repo, ctx2.node(), self.node(), + match=match, opts=diffopts) + + @propertycache + def _dirs(self): + return scmutil.dirs(self._manifest) + + def dirs(self): + return self._dirs + + def dirty(self): + return False + +class changectx(basectx): """A changecontext object makes access to data related to a particular - changeset convenient.""" + changeset convenient. It represents a read-only context already presnt in + the repo.""" def __init__(self, repo, changeid=''): """changeid is a revision number, node, or tag""" + + # since basectx.__new__ already took care of copying the object, we + # don't need to do anything in __init__, so we just exit here + if isinstance(changeid, basectx): + return + if changeid == '': changeid = '.' self._repo = repo @@ -114,30 +253,12 @@ raise error.RepoLookupError( _("unknown revision '%s'") % changeid) - def __str__(self): - return short(self.node()) - - def __int__(self): - return self.rev() - - def __repr__(self): - return "<changectx %s>" % str(self) - def __hash__(self): try: return hash(self._rev) except AttributeError: return id(self) - def __eq__(self, other): - try: - return self._rev == other._rev - except AttributeError: - return False - - def __ne__(self, other): - return not (self == other) - def __nonzero__(self): return self._rev != nullrev @@ -160,33 +281,11 @@ p = p[:-1] return [changectx(self._repo, x) for x in p] - @propertycache - def substate(self): - return subrepo.state(self, self._repo.ui) - - def __contains__(self, key): - return key in self._manifest - - def __getitem__(self, key): - return self.filectx(key) - - def __iter__(self): - for f in sorted(self._manifest): - yield f - def changeset(self): return self._changeset - def manifest(self): - return self._manifest def manifestnode(self): return self._changeset[0] - def rev(self): - return self._rev - def node(self): - return self._node - def hex(self): - return hex(self._node) def user(self): return self._changeset[1] def date(self): @@ -207,25 +306,9 @@ return self._repo.nodebookmarks(self._node) def phase(self): return self._repo._phasecache.phase(self._repo, self._rev) - def phasestr(self): - return phases.phasenames[self.phase()] - def mutable(self): - return self.phase() > phases.public def hidden(self): return self._rev in repoview.filterrevs(self._repo, 'visible') - def parents(self): - """return contexts for each parent changeset""" - return self._parents - - def p1(self): - return self._parents[0] - - def p2(self): - if len(self._parents) == 2: - return self._parents[1] - return changectx(self._repo, -1) - def children(self): """return contexts for each child changeset""" c = self._repo.changelog.children(self._node) @@ -286,33 +369,6 @@ troubles.append('divergent') return troubles - def _fileinfo(self, path): - if '_manifest' in self.__dict__: - try: - return self._manifest[path], self._manifest.flags(path) - except KeyError: - raise error.ManifestLookupError(self._node, path, - _('not found in manifest')) - if '_manifestdelta' in self.__dict__ or path in self.files(): - if path in self._manifestdelta: - return (self._manifestdelta[path], - self._manifestdelta.flags(path)) - node, flag = self._repo.manifest.find(self._changeset[0], path) - if not node: - raise error.ManifestLookupError(self._node, path, - _('not found in manifest')) - - return node, flag - - def filenode(self, path): - return self._fileinfo(path)[0] - - def flags(self, path): - try: - return self._fileinfo(path)[1] - except error.LookupError: - return '' - def filectx(self, path, fileid=None, filelog=None): """get a file context from this changeset""" if fileid is None: @@ -353,83 +409,15 @@ if match.bad(fn, _('no such file in rev %s') % self) and match(fn): yield fn - def sub(self, path): - return subrepo.subrepo(self, path) - - def match(self, pats=[], include=None, exclude=None, default='glob'): - r = self._repo - return matchmod.match(r.root, r.getcwd(), pats, - include, exclude, default, - auditor=r.auditor, ctx=self) - - def diff(self, ctx2=None, match=None, **opts): - """Returns a diff generator for the given contexts and matcher""" - if ctx2 is None: - ctx2 = self.p1() - if ctx2 is not None and not isinstance(ctx2, changectx): - ctx2 = self._repo[ctx2] - diffopts = patch.diffopts(self._repo.ui, opts) - return patch.diff(self._repo, ctx2.node(), self.node(), - match=match, opts=diffopts) - - @propertycache - def _dirs(self): - return scmutil.dirs(self._manifest) - - def dirs(self): - return self._dirs - - def dirty(self): - return False - -class filectx(object): - """A filecontext object makes access to data related to a particular - filerevision convenient.""" - def __init__(self, repo, path, changeid=None, fileid=None, - filelog=None, changectx=None): - """changeid can be a changeset revision, node, or tag. - fileid can be a file revision or node.""" - self._repo = repo - self._path = path - - assert (changeid is not None - or fileid is not None - or changectx is not None), \ - ("bad args: changeid=%r, fileid=%r, changectx=%r" - % (changeid, fileid, changectx)) - - if filelog is not None: - self._filelog = filelog - - if changeid is not None: - self._changeid = changeid - if changectx is not None: - self._changectx = changectx - if fileid is not None: - self._fileid = fileid - - @propertycache - def _changectx(self): - try: - return changectx(self._repo, self._changeid) - except error.RepoLookupError: - # Linkrev may point to any revision in the repository. When the - # repository is filtered this may lead to `filectx` trying to build - # `changectx` for filtered revision. In such case we fallback to - # creating `changectx` on the unfiltered version of the reposition. - # This fallback should not be an issue because `changectx` from - # `filectx` are not used in complex operations that care about - # filtering. - # - # This fallback is a cheap and dirty fix that prevent several - # crashes. It does not ensure the behavior is correct. However the - # behavior was not correct before filtering either and "incorrect - # behavior" is seen as better as "crash" - # - # Linkrevs have several serious troubles with filtering that are - # complicated to solve. Proper handling of the issue here should be - # considered when solving linkrev issue are on the table. - return changectx(self._repo.unfiltered(), self._changeid) +class basefilectx(object): + """A filecontext object represents the common logic for its children: + filectx: read-only access to a filerevision that is already present + in the repo, + workingfilectx: a filecontext that represents files from the working + directory, + memfilectx: a filecontext that represents files in-memory.""" + def __new__(cls, repo, path, *args, **kwargs): + return super(basefilectx, cls).__new__(cls) @propertycache def _filelog(self): @@ -468,10 +456,10 @@ return False def __str__(self): - return "%s@%s" % (self.path(), short(self.node())) + return "%s@%s" % (self.path(), self._changectx) def __repr__(self): - return "<filectx %s>" % str(self) + return "<%s %s>" % (type(self).__name__, str(self)) def __hash__(self): try: @@ -481,7 +469,7 @@ def __eq__(self, other): try: - return (self._path == other._path + return (type(self) == type(other) and self._path == other._path and self._filenode == other._filenode) except AttributeError: return False @@ -489,12 +477,6 @@ def __ne__(self, other): return not (self == other) - def filectx(self, fileid): - '''opens an arbitrary revision of the file without - opening a new filelog''' - return filectx(self._repo, self._path, fileid=fileid, - filelog=self._filelog) - def filerev(self): return self._filerev def filenode(self): @@ -510,7 +492,7 @@ def node(self): return self._changectx.node() def hex(self): - return hex(self.node()) + return self._changectx.hex() def user(self): return self._changectx.user() def date(self): @@ -532,12 +514,8 @@ def changectx(self): return self._changectx - def data(self): - return self._filelog.read(self._filenode) def path(self): return self._path - def size(self): - return self._filelog.size(self._filerev) def isbinary(self): try: @@ -560,31 +538,6 @@ return True - def renamed(self): - """check if file was actually renamed in this changeset revision - - If rename logged in file revision, we report copy for changeset only - if file revisions linkrev points back to the changeset in question - or both changeset parents contain different file revisions. - """ - - renamed = self._filelog.renamed(self._filenode) - if not renamed: - return renamed - - if self.rev() == self.linkrev(): - return renamed - - name = self.path() - fnode = self._filenode - for p in self._changectx.parents(): - try: - if fnode == p.filenode(name): - return None - except error.LookupError: - pass - return renamed - def parents(self): p = self._path fl = self._filelog @@ -606,12 +559,6 @@ return p[1] return filectx(self._repo, self._path, fileid=-1, filelog=self._filelog) - def children(self): - # hard for renames - c = self._filelog.children(self._filenode) - return [filectx(self._repo, self._path, fileid=x, - filelog=self._filelog) for x in c] - def annotate(self, follow=False, linenumber=None, diffopts=None): '''returns a list of tuples of (ctx, line) for each line in the file, where ctx is the filectx of the node where @@ -783,15 +730,100 @@ self._copycache[sc2] = copies.pathcopies(c2) return self._copycache[sc2] -class workingctx(changectx): - """A workingctx object makes access to data related to - the current working directory convenient. - date - any valid date string or (unixtime, offset), or None. - user - username string, or None. - extra - a dictionary of extra values, or None. - changes - a list of file lists as returned by localrepo.status() - or None to use the repository status. - """ +class filectx(basefilectx): + """A filecontext object makes access to data related to a particular + filerevision convenient.""" + def __init__(self, repo, path, changeid=None, fileid=None, + filelog=None, changectx=None): + """changeid can be a changeset revision, node, or tag. + fileid can be a file revision or node.""" + self._repo = repo + self._path = path + + assert (changeid is not None + or fileid is not None + or changectx is not None), \ + ("bad args: changeid=%r, fileid=%r, changectx=%r" + % (changeid, fileid, changectx)) + + if filelog is not None: + self._filelog = filelog + + if changeid is not None: + self._changeid = changeid + if changectx is not None: + self._changectx = changectx + if fileid is not None: + self._fileid = fileid + + @propertycache + def _changectx(self): + try: + return changectx(self._repo, self._changeid) + except error.RepoLookupError: + # Linkrev may point to any revision in the repository. When the + # repository is filtered this may lead to `filectx` trying to build + # `changectx` for filtered revision. In such case we fallback to + # creating `changectx` on the unfiltered version of the reposition. + # This fallback should not be an issue because `changectx` from + # `filectx` are not used in complex operations that care about + # filtering. + # + # This fallback is a cheap and dirty fix that prevent several + # crashes. It does not ensure the behavior is correct. However the + # behavior was not correct before filtering either and "incorrect + # behavior" is seen as better as "crash" + # + # Linkrevs have several serious troubles with filtering that are + # complicated to solve. Proper handling of the issue here should be + # considered when solving linkrev issue are on the table. + return changectx(self._repo.unfiltered(), self._changeid) + + def filectx(self, fileid): + '''opens an arbitrary revision of the file without + opening a new filelog''' + return filectx(self._repo, self._path, fileid=fileid, + filelog=self._filelog) + + def data(self): + return self._filelog.read(self._filenode) + def size(self): + return self._filelog.size(self._filerev) + + def renamed(self): + """check if file was actually renamed in this changeset revision + + If rename logged in file revision, we report copy for changeset only + if file revisions linkrev points back to the changeset in question + or both changeset parents contain different file revisions. + """ + + renamed = self._filelog.renamed(self._filenode) + if not renamed: + return renamed + + if self.rev() == self.linkrev(): + return renamed + + name = self.path() + fnode = self._filenode + for p in self._changectx.parents(): + try: + if fnode == p.filenode(name): + return None + except error.LookupError: + pass + return renamed + + def children(self): + # hard for renames + c = self._filelog.children(self._filenode) + return [filectx(self._repo, self._path, fileid=x, + filelog=self._filelog) for x in c] + +class commitablectx(basectx): + """A commitablectx object provides common functionality for a context that + wants the ability to commit, e.g. workingctx or memctx.""" def __init__(self, repo, text="", user=None, date=None, extra=None, changes=None): self._repo = repo @@ -827,9 +859,6 @@ def __str__(self): return str(self._parents[0]) + "+" - def __repr__(self): - return "<workingctx %s>" % str(self) - def __nonzero__(self): return True @@ -904,12 +933,6 @@ return man - def __iter__(self): - d = self._repo.dirstate - for f in d: - if d[f] != 'r': - yield f - @propertycache def _status(self): return self._repo.status()[:4] @@ -922,13 +945,6 @@ def _date(self): return util.makedate() - @propertycache - def _parents(self): - p = self._repo.dirstate.parents() - if p[1] == nullid: - p = p[:-1] - return [changectx(self._repo, x) for x in p] - def status(self, ignored=False, clean=False, unknown=False): """Explicit status query Unless this method is used to query the working copy status, the @@ -945,8 +961,6 @@ self._status = stat[:4] return stat - def manifest(self): - return self._manifest def user(self): return self._user or self._repo.ui.username() def date(self): @@ -1016,11 +1030,6 @@ except OSError: return '' - def filectx(self, path, filelog=None): - """get a file context from the working directory""" - return workingfilectx(self._repo, path, workingctx=self, - filelog=filelog) - def ancestor(self, c2): """return the ancestor context of self and c2""" return self._parents[0].ancestor(c2) # punt on two parents for now @@ -1029,6 +1038,61 @@ return sorted(self._repo.dirstate.walk(match, sorted(self.substate), True, False)) + def ancestors(self): + for a in self._repo.changelog.ancestors( + [p.rev() for p in self._parents]): + yield changectx(self._repo, a) + + def markcommitted(self, node): + """Perform post-commit cleanup necessary after committing this ctx + + Specifically, this updates backing stores this working context + wraps to reflect the fact that the changes reflected by this + workingctx have been committed. For example, it marks + modified and added files as normal in the dirstate. + + """ + + for f in self.modified() + self.added(): + self._repo.dirstate.normal(f) + for f in self.removed(): + self._repo.dirstate.drop(f) + self._repo.dirstate.setparents(node) + + def dirs(self): + return self._repo.dirstate.dirs() + +class workingctx(commitablectx): + """A workingctx object makes access to data related to + the current working directory convenient. + date - any valid date string or (unixtime, offset), or None. + user - username string, or None. + extra - a dictionary of extra values, or None. + changes - a list of file lists as returned by localrepo.status() + or None to use the repository status. + """ + def __init__(self, repo, text="", user=None, date=None, extra=None, + changes=None): + super(workingctx, self).__init__(repo, text, user, date, extra, changes) + + def __iter__(self): + d = self._repo.dirstate + for f in d: + if d[f] != 'r': + yield f + + @propertycache + def _parents(self): + p = self._repo.dirstate.parents() + if p[1] == nullid: + p = p[:-1] + return [changectx(self._repo, x) for x in p] + + def filectx(self, path, filelog=None): + """get a file context from the working directory""" + return workingfilectx(self._repo, path, workingctx=self, + filelog=filelog) + def dirty(self, missing=False, merge=True, branch=True): "check whether a working directory is modified" # check subrepos first @@ -1093,11 +1157,6 @@ finally: wlock.release() - def ancestors(self): - for a in self._repo.changelog.ancestors( - [p.rev() for p in self._parents]): - yield changectx(self._repo, a) - def undelete(self, list): pctxs = self.parents() wlock = self._repo.wlock() @@ -1129,31 +1188,10 @@ finally: wlock.release() - def markcommitted(self, node): - """Perform post-commit cleanup necessary after committing this ctx - - Specifically, this updates backing stores this working context - wraps to reflect the fact that the changes reflected by this - workingctx have been committed. For example, it marks - modified and added files as normal in the dirstate. - - """ - - for f in self.modified() + self.added(): - self._repo.dirstate.normal(f) - for f in self.removed(): - self._repo.dirstate.drop(f) - self._repo.dirstate.setparents(node) - - def dirs(self): - return self._repo.dirstate.dirs() - -class workingfilectx(filectx): - """A workingfilectx object makes access to data related to a particular - file in the working directory convenient.""" - def __init__(self, repo, path, filelog=None, workingctx=None): - """changeid can be a changeset revision, node, or tag. - fileid can be a file revision or node.""" +class commitablefilectx(basefilectx): + """A commitablefilectx provides common functionality for a file context that + wants the ability to commit, e.g. workingfilectx or memfilectx.""" + def __init__(self, repo, path, filelog=None, ctx=None): self._repo = repo self._path = path self._changeid = None @@ -1161,30 +1199,12 @@ if filelog is not None: self._filelog = filelog - if workingctx: - self._changectx = workingctx - - @propertycache - def _changectx(self): - return workingctx(self._repo) + if ctx: + self._changectx = ctx def __nonzero__(self): return True - def __str__(self): - return "%s@%s" % (self.path(), self._changectx) - - def __repr__(self): - return "<workingfilectx %s>" % str(self) - - def data(self): - return self._repo.wread(self._path) - def renamed(self): - rp = self._repo.dirstate.copied(self._path) - if not rp: - return None - return rp, self._changectx._parents[0]._manifest.get(rp, nullid) - def parents(self): '''return parent filectxs, following copies if necessary''' def filenode(ctx, path): @@ -1209,6 +1229,24 @@ def children(self): return [] +class workingfilectx(commitablefilectx): + """A workingfilectx object makes access to data related to a particular + file in the working directory convenient.""" + def __init__(self, repo, path, filelog=None, workingctx=None): + super(workingfilectx, self).__init__(repo, path, filelog, workingctx) + + @propertycache + def _changectx(self): + return workingctx(self._repo) + + def data(self): + return self._repo.wread(self._path) + def renamed(self): + rp = self._repo.dirstate.copied(self._path) + if not rp: + return None + return rp, self._changectx._parents[0]._manifest.get(rp, nullid) + def size(self): return os.lstat(self._repo.wjoin(self._path)).st_size def date(self):
--- a/mercurial/dirstate.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/dirstate.py Sat Sep 07 00:08:36 2013 -0500 @@ -801,12 +801,9 @@ mexact = match.exact dirignore = self._dirignore checkexec = self._checkexec - checklink = self._checklink copymap = self._copymap lastnormaltime = self._lastnormaltime - lnkkind = stat.S_IFLNK - # We need to do full walks when either # - we're listing all clean files, or # - match.traversedir does something, because match.traversedir should @@ -827,20 +824,14 @@ if not st and state in "nma": dadd(fn) elif state == 'n': - # The "mode & lnkkind != lnkkind or self._checklink" - # lines are an expansion of "islink => checklink" - # where islink means "is this a link?" and checklink - # means "can we check links?". mtime = int(st.st_mtime) if (size >= 0 and ((size != st.st_size and size != st.st_size & _rangemask) or ((mode ^ st.st_mode) & 0100 and checkexec)) - and (mode & lnkkind != lnkkind or checklink) or size == -2 # other parent or fn in copymap): madd(fn) - elif ((time != mtime and time != mtime & _rangemask) - and (mode & lnkkind != lnkkind or checklink)): + elif time != mtime and time != mtime & _rangemask: ladd(fn) elif mtime == lastnormaltime: # fn may have been changed in the same timeslot without
--- a/mercurial/dispatch.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/dispatch.py Sat Sep 07 00:08:36 2013 -0500 @@ -88,11 +88,47 @@ try: try: + debugger = 'pdb' + debugtrace = { + 'pdb' : pdb.set_trace + } + debugmortem = { + 'pdb' : pdb.post_mortem + } + + # read --config before doing anything else + # (e.g. to change trust settings for reading .hg/hgrc) + cfgs = _parseconfig(req.ui, _earlygetopt(['--config'], req.args)) + + if req.repo: + # copy configs that were passed on the cmdline (--config) to + # the repo ui + for cfg in cfgs: + req.repo.ui.setconfig(*cfg) + + debugger = ui.config("ui", "debugger") + if not debugger: + debugger = 'pdb' + + try: + debugmod = __import__(debugger) + except ImportError: + debugmod = pdb + + debugtrace[debugger] = debugmod.set_trace + debugmortem[debugger] = debugmod.post_mortem + # enter the debugger before command execution if '--debugger' in req.args: ui.warn(_("entering debugger - " "type c to continue starting hg or h for help\n")) - pdb.set_trace() + + if (debugger != 'pdb' and + debugtrace[debugger] == debugtrace['pdb']): + ui.warn(_("%s debugger specified " + "but its module was not found\n") % debugger) + + debugtrace[debugger]() try: return _dispatch(req) finally: @@ -101,7 +137,7 @@ # enter the debugger when we hit an exception if '--debugger' in req.args: traceback.print_exc() - pdb.post_mortem(sys.exc_info()[2]) + debugmortem[debugger](sys.exc_info()[2]) ui.traceback() raise @@ -619,10 +655,6 @@ args = req.args ui = req.ui - # read --config before doing anything else - # (e.g. to change trust settings for reading .hg/hgrc) - cfgs = _parseconfig(ui, _earlygetopt(['--config'], args)) - # check for cwd cwd = _earlygetopt(['--cwd'], args) if cwd: @@ -699,10 +731,6 @@ if req.repo: uis.add(req.repo.ui) - # copy configs that were passed on the cmdline (--config) to the repo ui - for cfg in cfgs: - req.repo.ui.setconfig(*cfg) - if options['verbose'] or options['debug'] or options['quiet']: for opt in ('verbose', 'debug', 'quiet'): val = str(bool(options[opt]))
--- a/mercurial/hgweb/webcommands.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/hgweb/webcommands.py Sat Sep 07 00:08:36 2013 -0500 @@ -9,7 +9,7 @@ import webutil from mercurial import error, encoding, archival, templater, templatefilters from mercurial.node import short, hex, nullid -from mercurial.util import binary +from mercurial import util from common import paritygen, staticfile, get_contact, ErrorResponse from common import HTTP_OK, HTTP_FORBIDDEN, HTTP_NOT_FOUND from mercurial import graphmod, patch @@ -57,7 +57,7 @@ if guessmime: mt = mimetypes.guess_type(path)[0] if mt is None: - mt = binary(text) and 'application/binary' or 'text/plain' + mt = util.binary(text) and 'application/binary' or 'text/plain' if mt.startswith('text/'): mt += '; charset="%s"' % encoding.encoding @@ -69,7 +69,7 @@ text = fctx.data() parity = paritygen(web.stripecount) - if binary(text): + if util.binary(text): mt = mimetypes.guess_type(f)[0] or 'application/octet-stream' text = '(binary:%s)' % mt @@ -109,9 +109,13 @@ raise inst def _search(web, req, tmpl): + MODE_REVISION = 'rev' + MODE_KEYWORD = 'keyword' - def changelist(**map): - count = 0 + def revsearch(ctx): + yield ctx + + def keywordsearch(query): lower = encoding.lower qw = lower(query).split() @@ -137,6 +141,25 @@ if miss: continue + yield ctx + + searchfuncs = { + MODE_REVISION: revsearch, + MODE_KEYWORD: keywordsearch, + } + + def getsearchmode(query): + try: + ctx = web.repo[query] + except (error.RepoError, error.LookupError): + return MODE_KEYWORD, query + else: + return MODE_REVISION, ctx + + def changelist(**map): + count = 0 + + for ctx in searchfunc(funcarg): count += 1 n = ctx.node() showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n) @@ -176,6 +199,9 @@ morevars['revcount'] = revcount * 2 morevars['rev'] = query + mode, funcarg = getsearchmode(query) + searchfunc = searchfuncs[mode] + tip = web.repo['tip'] parity = paritygen(web.stripecount) @@ -188,16 +214,10 @@ query = '' if 'node' in req.form: ctx = webutil.changectx(web.repo, req) + elif 'rev' in req.form: + return _search(web, req, tmpl) else: - if 'rev' in req.form: - query = req.form['rev'][0] - hi = query - else: - hi = 'tip' - try: - ctx = web.repo[hi] - except (error.RepoError, error.LookupError): - return _search(web, req, tmpl) # XXX redirect to 404 page? + ctx = web.repo['tip'] def changelist(latestonly, **map): revs = [] @@ -617,7 +637,7 @@ context = parsecontext(web.config('web', 'comparisoncontext', '5')) def filelines(f): - if binary(f.data()): + if util.binary(f.data()): mt = mimetypes.guess_type(f.path())[0] if not mt: mt = 'application/octet-stream' @@ -675,7 +695,7 @@ def annotate(**map): last = None - if binary(fctx.data()): + if util.binary(fctx.data()): mt = (mimetypes.guess_type(fctx.path())[0] or 'application/octet-stream') lines = enumerate([((fctx.filectx(fctx.filerev()), 1),
--- a/mercurial/httpclient/__init__.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/httpclient/__init__.py Sat Sep 07 00:08:36 2013 -0500 @@ -495,6 +495,10 @@ else: raise BadRequestData('body has no __len__() nor read()') + # If we're reusing the underlying socket, there are some + # conditions where we'll want to retry, so make a note of the + # state of self.sock + fresh_socket = self.sock is None self._connect() outgoing_headers = self._buildheaders( method, path, hdrs, self.http_version) @@ -640,6 +644,26 @@ # the whole request if response is None: response = self.response_class(self.sock, self.timeout, method) + if not fresh_socket: + if not response._select(): + # This means the response failed to get any response + # data at all, and in all probability the socket was + # closed before the server even saw our request. Try + # the request again on a fresh socket. + logging.debug('response._select() failed during request().' + ' Assuming request needs to be retried.') + self.sock = None + # Call this method explicitly to re-try the + # request. We don't use self.request() because + # some tools (notably Mercurial) expect to be able + # to subclass and redefine request(), and they + # don't have the same argspec as we do. + # + # TODO restructure sending of requests to avoid + # this recursion + return HTTPConnection.request( + self, method, path, body=body, headers=headers, + expect_continue=expect_continue) data_left = bool(outgoing_headers or body) if data_left: logger.info('stopped sending request early, '
--- a/mercurial/localrepo.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/localrepo.py Sat Sep 07 00:08:36 2013 -0500 @@ -39,6 +39,8 @@ """propertycache that apply to unfiltered repo only""" def __get__(self, repo, type=None): + if hasunfilteredcache(repo, self.name): + return getattr(repo.unfiltered(), self.name) return super(unfilteredpropertycache, self).__get__(repo.unfiltered()) class filteredpropertycache(propertycache): @@ -1457,14 +1459,8 @@ del mf[fn] return mf - if isinstance(node1, context.changectx): - ctx1 = node1 - else: - ctx1 = self[node1] - if isinstance(node2, context.changectx): - ctx2 = node2 - else: - ctx2 = self[node2] + ctx1 = self[node1] + ctx2 = self[node2] working = ctx2.rev() is None parentworking = working and ctx1 == self['.'] @@ -1561,7 +1557,7 @@ for f in modified: if ctx2.flags(f) == 'l': d = ctx2[f].data() - if len(d) >= 1024 or '\n' in d or util.binary(d): + if d == '' or len(d) >= 1024 or '\n' in d or util.binary(d): self.ui.debug('ignoring suspect symlink placeholder' ' "%s"\n' % f) continue
--- a/mercurial/obsolete.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/obsolete.py Sat Sep 07 00:08:36 2013 -0500 @@ -371,7 +371,7 @@ lock.release() def syncpush(repo, remote): - """utility function to push bookmark to a remote + """utility function to push obsolete markers to a remote Exist mostly to allow overridding for experimentation purpose""" if (_enabled and repo.obsstore and @@ -387,7 +387,7 @@ repo.ui.warn(msg) def syncpull(repo, remote, gettransaction): - """utility function to pull bookmark to a remote + """utility function to pull obsolete markers from a remote The `gettransaction` is function that return the pull transaction, creating one if necessary. We return the transaction to inform the calling code that
--- a/mercurial/parsers.c Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/parsers.c Sat Sep 07 00:08:36 2013 -0500 @@ -330,7 +330,7 @@ * this. */ if (PyDict_SetItem(map, k, dirstate_unset) == -1) goto bail; - mode = 0, size = -1, mtime = -1; + mtime = -1; } putbe32(mode, p); putbe32(size, p + 4);
--- a/mercurial/pure/parsers.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/pure/parsers.py Sat Sep 07 00:08:36 2013 -0500 @@ -100,11 +100,11 @@ # systems with a granularity of 1 sec). This commonly happens # for at least a couple of files on 'update'. # The user could change the file without changing its size - # within the same second. Invalidate the file's stat data in + # within the same second. Invalidate the file's mtime in # dirstate, forcing future 'status' calls to compare the - # contents of the file. This prevents mistakenly treating such - # files as clean. - e = (e[0], 0, -1, -1) # mark entry as 'unset' + # contents of the file if the size is the same. This prevents + # mistakenly treating such files as clean. + e = (e[0], e[1], e[2], -1) dmap[f] = e if f in copymap:
--- a/mercurial/revlog.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/revlog.py Sat Sep 07 00:08:36 2013 -0500 @@ -14,7 +14,7 @@ # import stuff from node for others to import from revlog from node import bin, hex, nullid, nullrev from i18n import _ -import ancestor, mdiff, parsers, error, util +import ancestor, mdiff, parsers, error, util, templatefilters import struct, zlib, errno _pack = struct.pack @@ -943,10 +943,16 @@ def _checkhash(self, text, node, rev): p1, p2 = self.parents(node) + self.checkhash(text, p1, p2, node, rev) + return text + + def checkhash(self, text, p1, p2, node, rev=None): if node != hash(text, p1, p2): - raise RevlogError(_("integrity check failed on %s:%d") - % (self.indexfile, rev)) - return text + revornode = rev + if revornode is None: + revornode = templatefilters.short(hex(node)) + raise RevlogError(_("integrity check failed on %s:%s") + % (self.indexfile, revornode)) def checkinlinesize(self, tr, fp=None): if not self._inline or (self.start(-2) + self.length(-2)) < _maxinline: @@ -987,7 +993,8 @@ tr.replace(self.indexfile, trindex * self._io.size) self._chunkclear() - def addrevision(self, text, transaction, link, p1, p2, cachedelta=None): + def addrevision(self, text, transaction, link, p1, p2, cachedelta=None, + node=None): """add a revision to the log text - the revision data to add @@ -995,11 +1002,14 @@ link - the linkrev data to add p1, p2 - the parent nodeids of the revision cachedelta - an optional precomputed delta + node - nodeid of revision; typically node is not specified, and it is + computed by default as hash(text, p1, p2), however subclasses might + use different hashing method (and override checkhash() in such case) """ if link == nullrev: raise RevlogError(_("attempted to add linkrev -1 to %s") % self.indexfile) - node = hash(text, p1, p2) + node = node or hash(text, p1, p2) if node in self.nodemap: return node @@ -1063,9 +1073,7 @@ ifh.flush() basetext = self.revision(self.node(cachedelta[0])) btext[0] = mdiff.patch(basetext, cachedelta[1]) - chk = hash(btext[0], p1, p2) - if chk != node: - raise RevlogError(_("consistency error in delta")) + self.checkhash(btext[0], p1, p2, node) return btext[0] def builddelta(rev):
--- a/mercurial/scmutil.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/scmutil.py Sat Sep 07 00:08:36 2013 -0500 @@ -755,7 +755,8 @@ ctx = repo[None] dirstate = repo.dirstate - walkresults = dirstate.walk(matcher, sorted(ctx.substate), True, False) + walkresults = dirstate.walk(matcher, sorted(ctx.substate), True, False, + full=False) for abs, st in walkresults.iteritems(): dstate = dirstate[abs] if dstate == '?' and audit_path.check(abs):
--- a/mercurial/subrepo.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/subrepo.py Sat Sep 07 00:08:36 2013 -0500 @@ -237,6 +237,7 @@ # record merged .hgsubstate writestate(repo, sm) + return sm def _updateprompt(ui, sub, dirty, local, remote): if dirty:
--- a/mercurial/templates/paper/fileannotate.tmpl Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/templates/paper/fileannotate.tmpl Sat Sep 07 00:08:36 2013 -0500 @@ -65,7 +65,6 @@ <th class="author">children</th> <td class="author">{child%filerevchild}</td> </tr> -{changesettag} </table> <div class="overflow">
--- a/mercurial/templates/paper/filecomparison.tmpl Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/templates/paper/filecomparison.tmpl Sat Sep 07 00:08:36 2013 -0500 @@ -64,7 +64,6 @@ <th>children</th> <td>{child%filerevchild}</td> </tr> -{changesettag} </table> <div class="overflow">
--- a/mercurial/templates/paper/filediff.tmpl Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/templates/paper/filediff.tmpl Sat Sep 07 00:08:36 2013 -0500 @@ -64,7 +64,6 @@ <th>children</th> <td>{child%filerevchild}</td> </tr> -{changesettag} </table> <div class="overflow">
--- a/mercurial/templates/paper/filerevision.tmpl Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/templates/paper/filerevision.tmpl Sat Sep 07 00:08:36 2013 -0500 @@ -63,7 +63,6 @@ <th class="author">children</th> <td class="author">{child%filerevchild}</td> </tr> -{changesettag} </table> <div class="overflow">
--- a/mercurial/templates/paper/shortlogentry.tmpl Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/templates/paper/shortlogentry.tmpl Sat Sep 07 00:08:36 2013 -0500 @@ -1,5 +1,5 @@ <tr> <td class="age">{date|rfc822date}</td> <td class="author">{author|person}</td> - <td class="description"><a href="{url|urlescape}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}</a>{inbranch%changelogbranchname}{branches%changelogbranchhead}{tags % '<span class="tag">{name|escape}</span> '}{bookmarks % '<span class="tag">{name|escape}</span> '}</td> + <td class="description"><a href="{url|urlescape}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}</a>{inbranch%changelogbranchname}{branches%changelogbranchhead}{tags%changelogtag}{bookmarks%changelogtag}</td> </tr>
--- a/mercurial/templates/static/mercurial.js Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/templates/static/mercurial.js Sat Sep 07 00:08:36 2013 -0500 @@ -23,7 +23,7 @@ ]; function Graph() { - + this.canvas = document.getElementById('graph'); if (window.G_vmlCanvasManager) this.canvas = window.G_vmlCanvasManager.initElement(this.canvas); this.ctx = this.canvas.getContext('2d'); @@ -35,13 +35,13 @@ this.cell = [2, 0]; this.columns = 0; this.revlink = ''; - + this.scale = function(height) { this.bg_height = height; this.box_size = Math.floor(this.bg_height / 1.2); this.cell_height = this.box_size; } - + function colorPart(num) { num *= 255 num = num < 0 ? 0 : num; @@ -55,7 +55,7 @@ } this.setColor = function(color, bg, fg) { - + // Set the colour. // // If color is a string, expect an hexadecimal RGB @@ -81,11 +81,11 @@ this.ctx.strokeStyle = s; this.ctx.fillStyle = s; return s; - + } this.edge = function(x0, y0, x1, y1, color, width) { - + this.setColor(color, 0.0, 0.65); if(width >= 0) this.ctx.lineWidth = width; @@ -93,28 +93,28 @@ this.ctx.moveTo(x0, y0); this.ctx.lineTo(x1, y1); this.ctx.stroke(); - + } this.render = function(data) { - + var backgrounds = ''; var nodedata = ''; - + for (var i in data) { - + var parity = i % 2; this.cell[1] += this.bg_height; this.bg[1] += this.bg_height; - + var cur = data[i]; var node = cur[1]; var edges = cur[2]; var fold = false; - + var prevWidth = this.ctx.lineWidth; for (var j in edges) { - + line = edges[j]; start = line[0]; end = line[1]; @@ -125,44 +125,44 @@ var branchcolor = line[4]; if(branchcolor) color = branchcolor; - + if (end > this.columns || start > this.columns) { this.columns += 1; } - + if (start == this.columns && start > end) { var fold = true; } - + x0 = this.cell[0] + this.box_size * start + this.box_size / 2; y0 = this.bg[1] - this.bg_height / 2; x1 = this.cell[0] + this.box_size * end + this.box_size / 2; y1 = this.bg[1] + this.bg_height / 2; - + this.edge(x0, y0, x1, y1, color, width); - + } this.ctx.lineWidth = prevWidth; - + // Draw the revision node in the right column - + column = node[0] color = node[1] - + radius = this.box_size / 8; x = this.cell[0] + this.box_size * column + this.box_size / 2; y = this.bg[1] - this.bg_height / 2; var add = this.vertex(x, y, color, parity, cur); backgrounds += add[0]; nodedata += add[1]; - + if (fold) this.columns -= 1; - + } - + document.getElementById('nodebgs').innerHTML += backgrounds; document.getElementById('graphnodes').innerHTML += nodedata; - + } } @@ -258,6 +258,7 @@ // We want both: date + (age) node.textContent += ' ('+agevalue+')'; } else { + node.title = node.textContent; node.textContent = agevalue; } }
--- a/mercurial/ui.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/ui.py Sat Sep 07 00:08:36 2013 -0500 @@ -176,7 +176,7 @@ alternates = [name] for n in alternates: - value = self._data(untrusted).get(section, name, None) + value = self._data(untrusted).get(section, n, None) if value is not None: name = n break @@ -184,10 +184,11 @@ value = default if self.debugflag and not untrusted and self._reportuntrusted: - uvalue = self._ucfg.get(section, name) - if uvalue is not None and uvalue != value: - self.debug("ignoring untrusted configuration option " - "%s.%s = %s\n" % (section, name, uvalue)) + for n in alternates: + uvalue = self._ucfg.get(section, n) + if uvalue is not None and uvalue != value: + self.debug("ignoring untrusted configuration option " + "%s.%s = %s\n" % (section, n, uvalue)) return value def configpath(self, section, name, default=None, untrusted=False):
--- a/mercurial/unionrepo.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/unionrepo.py Sat Sep 07 00:08:36 2013 -0500 @@ -70,7 +70,7 @@ self.revlog2.rev(self.node(rev1)), self.revlog2.rev(self.node(rev2))) elif rev1 <= self.repotiprev and rev2 <= self.repotiprev: - return revlog.revlog.revdiff(self, rev1, rev2) + return self.baserevdiff(rev1, rev2) return mdiff.textdiff(self.revision(self.node(rev1)), self.revision(self.node(rev2))) @@ -93,10 +93,20 @@ text = self.revlog2.revision(node) self._cache = (node, rev, text) else: - text = revlog.revlog.revision(self, rev) + text = self.baserevision(rev) # already cached return text + def baserevision(self, nodeorrev): + # Revlog subclasses may override 'revision' method to modify format of + # content retrieved from revlog. To use unionrevlog with such class one + # needs to override 'baserevision' and make more specific call here. + return revlog.revlog.revision(self, nodeorrev) + + def baserevdiff(self, rev1, rev2): + # Exists for the same purpose as baserevision. + return revlog.revlog.revdiff(self, rev1, rev2) + def addrevision(self, text, transaction, link, p1=None, p2=None, d=None): raise NotImplementedError def addgroup(self, revs, linkmapper, transaction): @@ -114,6 +124,15 @@ unionrevlog.__init__(self, opener, self.indexfile, changelog2, linkmapper) + def baserevision(self, nodeorrev): + # Although changelog doesn't override 'revision' method, some extensions + # may replace this class with another that does. Same story with + # manifest and filelog classes. + return changelog.changelog.revision(self, nodeorrev) + + def baserevdiff(self, rev1, rev2): + return changelog.changelog.revdiff(self, rev1, rev2) + class unionmanifest(unionrevlog, manifest.manifest): def __init__(self, opener, opener2, linkmapper): manifest.manifest.__init__(self, opener) @@ -121,6 +140,12 @@ unionrevlog.__init__(self, opener, self.indexfile, manifest2, linkmapper) + def baserevision(self, nodeorrev): + return manifest.manifest.revision(self, nodeorrev) + + def baserevdiff(self, rev1, rev2): + return manifest.manifest.revdiff(self, rev1, rev2) + class unionfilelog(unionrevlog, filelog.filelog): def __init__(self, opener, path, opener2, linkmapper, repo): filelog.filelog.__init__(self, opener, path) @@ -129,6 +154,12 @@ linkmapper) self._repo = repo + def baserevision(self, nodeorrev): + return filelog.filelog.revision(self, nodeorrev) + + def baserevdiff(self, rev1, rev2): + return filelog.filelog.revdiff(self, rev1, rev2) + def _file(self, f): self._repo.file(f)
--- a/mercurial/url.py Tue Aug 06 00:52:06 2013 +0400 +++ b/mercurial/url.py Sat Sep 07 00:08:36 2013 -0500 @@ -108,8 +108,13 @@ def proxy_open(self, req, proxy, type_): host = req.get_host().split(':')[0] - if host in self.no_list: - return None + for e in self.no_list: + if host == e: + return None + if e.startswith('*.') and host.endswith(e[2:]): + return None + if e.startswith('.') and host.endswith(e[1:]): + return None # work around a bug in Python < 2.4.2 # (it leaves a "\n" at the end of Proxy-authorization headers)
--- a/tests/run-tests.py Tue Aug 06 00:52:06 2013 +0400 +++ b/tests/run-tests.py Sat Sep 07 00:08:36 2013 -0500 @@ -921,8 +921,10 @@ else: return ignore("doesn't match keyword") + if not lctest.startswith("test-"): + return skip("not a test file") for ext, func, out in testtypes: - if lctest.startswith("test-") and lctest.endswith(ext): + if lctest.endswith(ext): runner = func ref = os.path.join(TESTDIR, test + out) break
--- a/tests/test-hgweb-commands.t Tue Aug 06 00:52:06 2013 +0400 +++ b/tests/test-hgweb-commands.t Sat Sep 07 00:08:36 2013 -0500 @@ -537,6 +537,8 @@ </body> </html> + $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=stable&style=raw' | grep 'revision:' + revision: 2 File-related @@ -637,7 +639,6 @@ <th class="author">children</th> <td class="author"><a href="/file/1d22e65f027e/foo">1d22e65f027e</a> </td> </tr> - </table> <div class="overflow"> @@ -1256,8 +1257,10 @@ Graph json escape of multibyte character - $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'graph/' \ - > | grep -a '^var data =' + $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'graph/' > out + >>> for line in open("out"): + ... if line.startswith("var data ="): + ... print line, var data = [["061dd13ba3c3", [0, 1], [[0, 0, 1, -1, ""]], "\\u80fd", "test", "1970-01-01", ["unstable", true], ["tip"], ["something"]], ["cad8025a2e87", [0, 1], [[0, 0, 1, 3, "FF0000"]], "branch commit with null character: \x00", "test", "1970-01-01", ["unstable", false], [], []], ["1d22e65f027e", [0, 1], [[0, 0, 1, 3, ""]], "branch", "test", "1970-01-01", ["stable", true], [], []], ["a4f92ed23982", [0, 1], [[0, 0, 1, 3, ""]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], ["anotherthing"]]]; (esc) capabilities
--- a/tests/test-hgweb-diffs.t Tue Aug 06 00:52:06 2013 +0400 +++ b/tests/test-hgweb-diffs.t Sat Sep 07 00:08:36 2013 -0500 @@ -269,7 +269,6 @@ <th>children</th> <td></td> </tr> - </table> <div class="overflow"> @@ -538,7 +537,6 @@ <th>children</th> <td></td> </tr> - </table> <div class="overflow"> @@ -638,7 +636,6 @@ <th>children</th> <td></td> </tr> - </table> <div class="overflow"> @@ -760,7 +757,6 @@ <th>children</th> <td></td> </tr> - </table> <div class="overflow"> @@ -884,7 +880,6 @@ <th>children</th> <td></td> </tr> - </table> <div class="overflow">
--- a/tests/test-hgweb-removed.t Tue Aug 06 00:52:06 2013 +0400 +++ b/tests/test-hgweb-removed.t Sat Sep 07 00:08:36 2013 -0500 @@ -213,7 +213,6 @@ <th>children</th> <td></td> </tr> - </table> <div class="overflow">
--- a/tests/test-highlight.t Tue Aug 06 00:52:06 2013 +0400 +++ b/tests/test-highlight.t Sat Sep 07 00:08:36 2013 -0500 @@ -132,7 +132,6 @@ <th class="author">children</th> <td class="author"></td> </tr> - </table> <div class="overflow"> @@ -264,7 +263,6 @@ <th class="author">children</th> <td class="author"></td> </tr> - </table> <div class="overflow">
--- a/tests/test-import-merge.t Tue Aug 06 00:52:06 2013 +0400 +++ b/tests/test-import-merge.t Sat Sep 07 00:08:36 2013 -0500 @@ -129,7 +129,9 @@ $ echo a>>a $ hg ci -m3 $ hg export 2 | head -7 > ../a.patch - $ hg export tip | tail -n +8 >> ../a.patch + $ hg export tip > out + >>> apatch = open("../a.patch", "a") + >>> apatch.write("".join(open("out").readlines()[7:])) $ cd .. $ hg clone -qr0 repo3 repo3-clone
--- a/tests/test-mq-subrepo.t Tue Aug 06 00:52:06 2013 +0400 +++ b/tests/test-mq-subrepo.t Sat Sep 07 00:08:36 2013 -0500 @@ -213,6 +213,7 @@ handle subrepos safely on qpush/qpop +(and we cannot qpop / qpush with a modified subrepo) $ mkrepo repo-2499-qpush $ mksubrepo sub @@ -220,31 +221,56 @@ $ hg -R sub ci -m0sub $ echo sub = sub > .hgsub $ hg add .hgsub - $ hg qnew -m0 0.diff + $ hg commit -m0 $ hg debugsub path sub source sub revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31 + $ echo foo > ./sub/a + $ hg -R sub commit -m foo + $ hg commit -m1 + $ hg qimport -r "0:tip" + $ hg -R sub id --id + aa037b301eba qpop + $ hg -R sub update 0000 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg qpop - popping 0.diff - patch queue now empty - $ hg status -AS - $ hg debugsub - -qpush - $ hg qpush - applying 0.diff + abort: local changed subrepos found, refresh first + [255] + $ hg revert sub + reverting subrepo sub + adding sub/a + $ hg qpop + popping 1.diff now at: 0.diff $ hg status -AS C .hgsub C .hgsubstate C sub/a - $ hg debugsub - path sub - source sub - revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31 + $ hg -R sub id --id + b2fdb12cd82b + +qpush + $ hg -R sub update 0000 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg qpush + abort: local changed subrepos found, refresh first + [255] + $ hg revert sub + reverting subrepo sub + adding sub/a + $ hg qpush + applying 1.diff + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + now at: 1.diff + $ hg status -AS + C .hgsub + C .hgsubstate + C sub/a + $ hg -R sub id --id + aa037b301eba $ cd ..
--- a/tests/test-parse-date.t Tue Aug 06 00:52:06 2013 +0400 +++ b/tests/test-parse-date.t Sat Sep 07 00:08:36 2013 -0500 @@ -242,7 +242,7 @@ >>> yesterday = (datetime.date.today() - datetime.timedelta(days=1)).strftime("%b %d") >>> dates = open('dates', 'w') >>> dates.write(today + '\n') - >>> dates.write(yesterday) + >>> dates.write(yesterday + '\n') >>> dates.close() $ hg ci -d "`sed -n '1p' dates`" -m "today is a good day to code" $ hg log -d today --template '{desc}\n'
--- a/tests/test-progress.t Tue Aug 06 00:52:06 2013 +0400 +++ b/tests/test-progress.t Sat Sep 07 00:08:36 2013 -0500 @@ -1,6 +1,14 @@ $ cat > loop.py <<EOF > from mercurial import commands + > import time + > class incrementingtime(object): + > def __init__(self): + > self._time = 0.0 + > def __call__(self): + > self._time += 0.25 + > return self._time + > time.time = incrementingtime() > > def loop(ui, loops, **opts): > loops = int(loops) @@ -19,9 +27,14 @@ > if opts.get('parallel'): > ui.progress('other', i, 'other.%d' % i, 'othernum', total) > if nested: - > for j in range(2): - > ui.progress('nested', j, 'nested.%d' % j, 'nestnum', 2) - > ui.progress('nested', None, 'nested.done', 'nestnum', 2) + > nested_steps = 2 + > if i and i % 4 == 0: + > nested_steps = 5 + > for j in range(nested_steps): + > ui.progress( + > 'nested', j, 'nested.%d' % j, 'nestnum', nested_steps) + > ui.progress( + > 'nested', None, 'nested.done', 'nestnum', nested_steps) > ui.progress('loop', None, 'loop.done', 'loopnum', total) > > commands.norepo += " loop" @@ -69,6 +82,24 @@ loop [===============================> ] 2/3\r (no-eol) (esc) \r (no-eol) (esc) +Test nested long-lived topic which has the same name as a short-lived +peer. We shouldn't get stuck showing the short-lived inner steps, and +should go back to skipping the inner steps when the slow nested step +finishes. + + $ hg -y loop 7 --nested + \r (no-eol) (esc) + loop [ ] 0/7\r (no-eol) (esc) + loop [=====> ] 1/7\r (no-eol) (esc) + loop [============> ] 2/7\r (no-eol) (esc) + loop [===================> ] 3/7\r (no-eol) (esc) + loop [==========================> ] 4/7\r (no-eol) (esc) + nested [==========================> ] 3/5\r (no-eol) (esc) + nested [===================================> ] 4/5\r (no-eol) (esc) + loop [=================================> ] 5/7\r (no-eol) (esc) + loop [========================================> ] 6/7\r (no-eol) (esc) + \r (no-eol) (esc) + $ hg --config progress.changedelay=0 -y loop 3 --nested \r (no-eol) (esc)
--- a/tests/test-symlink-placeholder.t Tue Aug 06 00:52:06 2013 +0400 +++ b/tests/test-symlink-placeholder.t Sat Sep 07 00:08:36 2013 -0500 @@ -41,6 +41,13 @@ a (no-eol) $ hg --config extensions.n=$TESTTMP/nolink.py st --debug +Empty placeholder: + + $ rm b + $ touch b + $ hg --config extensions.n=$TESTTMP/nolink.py st --debug + ignoring suspect symlink placeholder "b" + Write binary data to the placeholder: >>> open('b', 'w').write('this is a binary\0')