Mercurial > hg
changeset 14628:33f620027b58
merge with i18n
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Tue, 14 Jun 2011 20:43:04 -0500 |
parents | f03c82d1f50a (diff) 166776f97c9c (current diff) |
children | c3f2152e423d 71b9c29eb44a |
files | |
diffstat | 74 files changed, 2287 insertions(+), 1068 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Tue Jun 14 00:31:56 2011 +0400 +++ b/.hgignore Tue Jun 14 20:43:04 2011 -0500 @@ -26,6 +26,7 @@ doc/*.[0-9].gendoc.txt doc/*.[0-9].{x,ht}ml MANIFEST +MANIFEST.in patches mercurial/__version__.py mercurial.egg-info @@ -35,6 +36,7 @@ cscope.* i18n/hg.pot locale/*/LC_MESSAGES/hg.mo +hgext/__index__.py # files installed with a local --pure build mercurial/base85.py
--- a/Makefile Tue Jun 14 00:31:56 2011 +0400 +++ b/Makefile Tue Jun 14 20:43:04 2011 -0500 @@ -46,7 +46,7 @@ -$(PYTHON) setup.py clean --all # ignore errors from this command find . \( -name '*.py[cdo]' -o -name '*.so' \) -exec rm -f '{}' ';' rm -f $(addprefix mercurial/,$(notdir $(wildcard mercurial/pure/*.py))) - rm -f MANIFEST tests/*.err + rm -f MANIFEST MANIFEST.in tests/*.err rm -rf build mercurial/locale $(MAKE) -C doc clean @@ -69,14 +69,14 @@ MANIFEST-doc: $(MAKE) -C doc MANIFEST -MANIFEST: MANIFEST-doc - hg manifest > MANIFEST - echo mercurial/__version__.py >> MANIFEST - cat doc/MANIFEST >> MANIFEST +MANIFEST.in: MANIFEST-doc + hg manifest | sed -e 's/^/include /' > MANIFEST.in + echo include mercurial/__version__.py >> MANIFEST.in + sed -e 's/^/include /' < doc/MANIFEST >> MANIFEST.in dist: tests dist-notests -dist-notests: doc MANIFEST +dist-notests: doc MANIFEST.in TAR_OPTIONS="--owner=root --group=root --mode=u+w,go-w,a+rX-s" $(PYTHON) setup.py -q sdist check: tests
--- a/contrib/check-code.py Tue Jun 14 00:31:56 2011 +0400 +++ b/contrib/check-code.py Tue Jun 14 20:43:04 2011 -0500 @@ -177,6 +177,7 @@ "always assign an opened file to a variable, and close it afterwards"), (r'[\s\(](open|file)\([^)]*\)\.', "always assign an opened file to a variable, and close it afterwards"), + (r'(?i)descendent', "the proper spelling is descendAnt"), ], # warnings [
--- a/hgext/bugzilla.py Tue Jun 14 00:31:56 2011 +0400 +++ b/hgext/bugzilla.py Tue Jun 14 20:43:04 2011 -0500 @@ -197,7 +197,7 @@ XMLRPC+email example configuration. This uses the Bugzilla at ``http://my-project.org/bugzilla``, logging in as user -``bugmail@my-project.org`` wityh password ``plugh``. It is used with a +``bugmail@my-project.org`` with password ``plugh``. It is used with a collection of Mercurial repositories in ``/var/local/hg/repos/``, with a web interface at ``http://my-project.org/hg``. Bug comments are sent to the Bugzilla email address
--- a/hgext/convert/hg.py Tue Jun 14 00:31:56 2011 +0400 +++ b/hgext/convert/hg.py Tue Jun 14 20:43:04 2011 -0500 @@ -112,7 +112,7 @@ self.after() for pbranch, heads in missings.iteritems(): pbranchpath = os.path.join(self.path, pbranch) - prepo = hg.repository(self.ui, pbranchpath) + prepo = hg.peer(self.ui, {}, pbranchpath) self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch)) self.repo.pull(prepo, [prepo.lookup(h) for h in heads]) self.before()
--- a/hgext/fetch.py Tue Jun 14 00:31:56 2011 +0400 +++ b/hgext/fetch.py Tue Jun 14 20:43:04 2011 -0500 @@ -63,8 +63,7 @@ raise util.Abort(_('multiple heads in this branch ' '(use "hg heads ." and "hg merge" to merge)')) - other = hg.repository(hg.remoteui(repo, opts), - ui.expandpath(source)) + other = hg.peer(repo, opts, ui.expandpath(source)) ui.status(_('pulling from %s\n') % util.hidepassword(ui.expandpath(source))) revs = None
--- a/hgext/keyword.py Tue Jun 14 00:31:56 2011 +0400 +++ b/hgext/keyword.py Tue Jun 14 20:43:04 2011 -0500 @@ -595,12 +595,10 @@ wlock.release() # monkeypatches - def kwpatchfile_init(orig, self, ui, fname, backend, store, mode, create, - remove, eolmode=None, copysource=None): + def kwpatchfile_init(orig, self, ui, gp, backend, store, eolmode=None): '''Monkeypatch/wrap patch.patchfile.__init__ to avoid rejects or conflicts due to expanded keywords in working dir.''' - orig(self, ui, fname, backend, store, mode, create, remove, - eolmode, copysource) + orig(self, ui, gp, backend, store, eolmode) # shrink keywords read from working dir self.lines = kwt.shrinklines(self.fname, self.lines)
--- a/hgext/mq.py Tue Jun 14 00:31:56 2011 +0400 +++ b/hgext/mq.py Tue Jun 14 20:43:04 2011 -0500 @@ -267,14 +267,14 @@ self.path = patchdir or curpath self.opener = scmutil.opener(self.path) self.ui = ui - self.applied_dirty = 0 - self.series_dirty = 0 + self.applieddirty = 0 + self.seriesdirty = 0 self.added = [] - self.series_path = "series" - self.status_path = "status" - self.guards_path = "guards" - self.active_guards = None - self.guards_dirty = False + self.seriespath = "series" + self.statuspath = "status" + self.guardspath = "guards" + self.activeguards = None + self.guardsdirty = False # Handle mq.git as a bool with extended values try: gitmode = ui.configbool('mq', 'git', None) @@ -287,7 +287,7 @@ @util.propertycache def applied(self): - if os.path.exists(self.join(self.status_path)): + if os.path.exists(self.join(self.statuspath)): def parselines(lines): for l in lines: entry = l.split(':', 1) @@ -297,34 +297,34 @@ elif l.strip(): self.ui.warn(_('malformated mq status line: %s\n') % entry) # else we ignore empty lines - lines = self.opener.read(self.status_path).splitlines() + lines = self.opener.read(self.statuspath).splitlines() return list(parselines(lines)) return [] @util.propertycache - def full_series(self): - if os.path.exists(self.join(self.series_path)): - return self.opener.read(self.series_path).splitlines() + def fullseries(self): + if os.path.exists(self.join(self.seriespath)): + return self.opener.read(self.seriespath).splitlines() return [] @util.propertycache def series(self): - self.parse_series() + self.parseseries() return self.series @util.propertycache - def series_guards(self): - self.parse_series() - return self.series_guards + def seriesguards(self): + self.parseseries() + return self.seriesguards def invalidate(self): - for a in 'applied full_series series series_guards'.split(): + for a in 'applied fullseries series seriesguards'.split(): if a in self.__dict__: delattr(self, a) - self.applied_dirty = 0 - self.series_dirty = 0 - self.guards_dirty = False - self.active_guards = None + self.applieddirty = 0 + self.seriesdirty = 0 + self.guardsdirty = False + self.activeguards = None def diffopts(self, opts={}, patchfn=None): diffopts = patchmod.diffopts(self.ui, opts) @@ -360,21 +360,21 @@ def join(self, *p): return os.path.join(self.path, *p) - def find_series(self, patch): + def findseries(self, patch): def matchpatch(l): l = l.split('#', 1)[0] return l.strip() == patch - for index, l in enumerate(self.full_series): + for index, l in enumerate(self.fullseries): if matchpatch(l): return index return None guard_re = re.compile(r'\s?#([-+][^-+# \t\r\n\f][^# \t\r\n\f]*)') - def parse_series(self): + def parseseries(self): self.series = [] - self.series_guards = [] - for l in self.full_series: + self.seriesguards = [] + for l in self.fullseries: h = l.find('#') if h == -1: patch = l @@ -388,11 +388,11 @@ if patch: if patch in self.series: raise util.Abort(_('%s appears more than once in %s') % - (patch, self.join(self.series_path))) + (patch, self.join(self.seriespath))) self.series.append(patch) - self.series_guards.append(self.guard_re.findall(comment)) - - def check_guard(self, guard): + self.seriesguards.append(self.guard_re.findall(comment)) + + def checkguard(self, guard): if not guard: return _('guard cannot be an empty string') bad_chars = '# \t\r\n\f' @@ -404,52 +404,52 @@ if c in guard: return _('invalid character in guard %r: %r') % (guard, c) - def set_active(self, guards): + def setactive(self, guards): for guard in guards: - bad = self.check_guard(guard) + bad = self.checkguard(guard) if bad: raise util.Abort(bad) guards = sorted(set(guards)) self.ui.debug('active guards: %s\n' % ' '.join(guards)) - self.active_guards = guards - self.guards_dirty = True + self.activeguards = guards + self.guardsdirty = True def active(self): - if self.active_guards is None: - self.active_guards = [] + if self.activeguards is None: + self.activeguards = [] try: - guards = self.opener.read(self.guards_path).split() + guards = self.opener.read(self.guardspath).split() except IOError, err: if err.errno != errno.ENOENT: raise guards = [] for i, guard in enumerate(guards): - bad = self.check_guard(guard) + bad = self.checkguard(guard) if bad: self.ui.warn('%s:%d: %s\n' % - (self.join(self.guards_path), i + 1, bad)) + (self.join(self.guardspath), i + 1, bad)) else: - self.active_guards.append(guard) - return self.active_guards - - def set_guards(self, idx, guards): + self.activeguards.append(guard) + return self.activeguards + + def setguards(self, idx, guards): for g in guards: if len(g) < 2: raise util.Abort(_('guard %r too short') % g) if g[0] not in '-+': raise util.Abort(_('guard %r starts with invalid char') % g) - bad = self.check_guard(g[1:]) + bad = self.checkguard(g[1:]) if bad: raise util.Abort(bad) - drop = self.guard_re.sub('', self.full_series[idx]) - self.full_series[idx] = drop + ''.join([' #' + g for g in guards]) - self.parse_series() - self.series_dirty = True + drop = self.guard_re.sub('', self.fullseries[idx]) + self.fullseries[idx] = drop + ''.join([' #' + g for g in guards]) + self.parseseries() + self.seriesdirty = True def pushable(self, idx): if isinstance(idx, str): idx = self.series.index(idx) - patchguards = self.series_guards[idx] + patchguards = self.seriesguards[idx] if not patchguards: return True, None guards = self.active() @@ -464,7 +464,7 @@ return False, ' '.join(map(repr, pos)) return True, '' - def explain_pushable(self, idx, all_patches=False): + def explainpushable(self, idx, all_patches=False): write = all_patches and self.ui.write or self.ui.warn if all_patches or self.ui.verbose: if isinstance(idx, str): @@ -489,18 +489,18 @@ write(_('skipping %s - no matching guards\n') % self.series[idx]) - def save_dirty(self): - def write_list(items, path): + def savedirty(self): + def writelist(items, path): fp = self.opener(path, 'w') for i in items: fp.write("%s\n" % i) fp.close() - if self.applied_dirty: - write_list(map(str, self.applied), self.status_path) - if self.series_dirty: - write_list(self.full_series, self.series_path) - if self.guards_dirty: - write_list(self.active_guards, self.guards_path) + if self.applieddirty: + writelist(map(str, self.applied), self.statuspath) + if self.seriesdirty: + writelist(self.fullseries, self.seriespath) + if self.guardsdirty: + writelist(self.activeguards, self.guardspath) if self.added: qrepo = self.qrepo() if qrepo: @@ -587,7 +587,7 @@ n = repo.commit('[mq]: merge marker', force=True) self.removeundo(repo) self.applied.append(statusentry(n, pname)) - self.applied_dirty = 1 + self.applieddirty = 1 head = self.qparents(repo) @@ -598,7 +598,7 @@ return (1, None) pushable, reason = self.pushable(patch) if not pushable: - self.explain_pushable(patch, all_patches=True) + self.explainpushable(patch, all_patches=True) continue info = mergeq.isapplied(patch) if not info: @@ -608,16 +608,16 @@ err, head = self.mergeone(repo, mergeq, head, patch, rev, diffopts) if head: self.applied.append(statusentry(head, patch)) - self.applied_dirty = 1 + self.applieddirty = 1 if err: return (err, head) - self.save_dirty() + self.savedirty() return (0, head) def patch(self, repo, patchfile): '''Apply patchfile to the working directory. patchfile: name of patch file''' - files = {} + files = set() try: fuzz = patchmod.patch(self.ui, repo, patchfile, strip=1, files=files, eolmode=None) @@ -639,7 +639,7 @@ ret = self._apply(repo, series, list, update_status, strict, patchdir, merge, all_files=all_files) tr.close() - self.save_dirty() + self.savedirty() return ret except: try: @@ -664,7 +664,7 @@ for patchname in series: pushable, reason = self.pushable(patchname) if not pushable: - self.explain_pushable(patchname, all_patches=True) + self.explainpushable(patchname, all_patches=True) continue self.ui.status(_("applying %s\n") % patchname) pf = os.path.join(patchdir, patchname) @@ -742,14 +742,14 @@ if numrevs: qfinished = self.applied[:numrevs] del self.applied[:numrevs] - self.applied_dirty = 1 + self.applieddirty = 1 unknown = [] - for (i, p) in sorted([(self.find_series(p), p) for p in patches], + for (i, p) in sorted([(self.findseries(p), p) for p in patches], reverse=True): if i is not None: - del self.full_series[i] + del self.fullseries[i] else: unknown.append(p) @@ -763,8 +763,8 @@ msg = _('unknown patches: %s\n') raise util.Abort(''.join(msg % p for p in unknown)) - self.parse_series() - self.series_dirty = 1 + self.parseseries() + self.seriesdirty = 1 def _revpatches(self, repo, revs): firstrev = repo[self.applied[0].node].rev() @@ -823,7 +823,7 @@ self._cleanup(realpatches, numrevs, opts.get('keep')) - def check_toppatch(self, repo): + def checktoppatch(self, repo): if self.applied: top = self.applied[-1].node patch = self.applied[-1].name @@ -833,7 +833,7 @@ return top, patch return None, None - def check_substate(self, repo): + def checksubstate(self, repo): '''return list of subrepos at a different revision than substate. Abort if any subrepos have uncommitted changes.''' inclsubs = [] @@ -852,14 +852,14 @@ else: raise util.Abort(_("local changes found")) - def check_localchanges(self, repo, force=False, refresh=True): + def checklocalchanges(self, repo, force=False, refresh=True): m, a, r, d = repo.status()[:4] if (m or a or r or d) and not force: self.localchangesfound(refresh) return m, a, r, d _reserved = ('series', 'status', 'guards', '.', '..') - def check_reserved_name(self, name): + def checkreservedname(self, name): if name in self._reserved: raise util.Abort(_('"%s" cannot be used as the name of a patch') % name) @@ -873,7 +873,7 @@ % c) def checkpatchname(self, name, force=False): - self.check_reserved_name(name) + self.checkreservedname(name) if not force and os.path.exists(self.join(name)): if os.path.isdir(self.join(name)): raise util.Abort(_('"%s" already exists as a directory') @@ -893,7 +893,7 @@ diffopts = self.diffopts({'git': opts.get('git')}) if opts.get('checkname', True): self.checkpatchname(patchfn) - inclsubs = self.check_substate(repo) + inclsubs = self.checksubstate(repo) if inclsubs: inclsubs.append('.hgsubstate') if opts.get('include') or opts.get('exclude') or pats: @@ -907,13 +907,13 @@ match.bad = badfn m, a, r, d = repo.status(match=match)[:4] else: - m, a, r, d = self.check_localchanges(repo, force=True) + m, a, r, d = self.checklocalchanges(repo, force=True) match = scmutil.matchfiles(repo, m + a + r + inclsubs) if len(repo[None].parents()) > 1: raise util.Abort(_('cannot manage merge changesets')) commitfiles = m + a + r - self.check_toppatch(repo) - insert = self.full_series_end() + self.checktoppatch(repo) + insert = self.fullseriesend() wlock = repo.wlock() try: try: @@ -945,11 +945,11 @@ if n is None: raise util.Abort(_("repo commit failed")) try: - self.full_series[insert:insert] = [patchfn] + self.fullseries[insert:insert] = [patchfn] self.applied.append(statusentry(n, patchfn)) - self.parse_series() - self.series_dirty = 1 - self.applied_dirty = 1 + self.parseseries() + self.seriesdirty = 1 + self.applieddirty = 1 if msg: msg = msg + "\n\n" p.write(msg) @@ -986,7 +986,7 @@ lock = repo.lock() if update: - self.check_localchanges(repo, force=force, refresh=False) + self.checklocalchanges(repo, force=force, refresh=False) urev = self.qparents(repo, revs[0]) hg.clean(repo, urev) repo.dirstate.write() @@ -1016,7 +1016,7 @@ def lookup(self, patch, strict=False): patch = patch and str(patch) - def partial_name(s): + def partialname(s): if s in self.series: return s matches = [x for x in self.series if s in x] @@ -1029,7 +1029,7 @@ return matches[0] if self.series and self.applied: if s == 'qtip': - return self.series[self.series_end(True)-1] + return self.series[self.seriesend(True)-1] if s == 'qbase': return self.series[0] return None @@ -1049,12 +1049,12 @@ return self.series[sno] if not strict: - res = partial_name(patch) + res = partialname(patch) if res: return res minus = patch.rfind('-') if minus >= 0: - res = partial_name(patch[:minus]) + res = partialname(patch[:minus]) if res: i = self.series.index(res) try: @@ -1066,7 +1066,7 @@ return self.series[i - off] plus = patch.rfind('+') if plus >= 0: - res = partial_name(patch[:plus]) + res = partialname(patch[:plus]) if res: i = self.series.index(res) try: @@ -1109,7 +1109,7 @@ pushable, reason = self.pushable(patch) if pushable: - if self.series.index(patch) < self.series_end(): + if self.series.index(patch) < self.seriesend(): raise util.Abort( _("cannot push to a previous patch: %s") % patch) else: @@ -1130,7 +1130,7 @@ # qpush without an argument is an error (nothing to # apply). This allows a loop of "...while hg qpush..." to # work as it detects an error when done - start = self.series_end() + start = self.seriesend() if start == len(self.series): self.ui.warn(_('patch series already fully applied\n')) return 1 @@ -1150,21 +1150,21 @@ if move: if not patch: raise util.Abort(_("please specify the patch to move")) - for i, rpn in enumerate(self.full_series[start:]): + for i, rpn in enumerate(self.fullseries[start:]): # strip markers for patch guards if self.guard_re.split(rpn, 1)[0] == patch: break index = start + i - assert index < len(self.full_series) - fullpatch = self.full_series[index] - del self.full_series[index] - self.full_series.insert(start, fullpatch) - self.parse_series() - self.series_dirty = 1 - - self.applied_dirty = 1 + assert index < len(self.fullseries) + fullpatch = self.fullseries[index] + del self.fullseries[index] + self.fullseries.insert(start, fullpatch) + self.parseseries() + self.seriesdirty = 1 + + self.applieddirty = 1 if start > 0: - self.check_toppatch(repo) + self.checktoppatch(repo) if not patch: patch = self.series[start] end = start + 1 @@ -1183,7 +1183,7 @@ if wcfiles.intersection(patchfiles): self.localchangesfound(self.applied) elif mergeq: - self.check_localchanges(refresh=self.applied) + self.checklocalchanges(refresh=self.applied) all_files = set() try: @@ -1265,11 +1265,11 @@ break update = needupdate - self.applied_dirty = 1 + self.applieddirty = 1 end = len(self.applied) rev = self.applied[start].node if update: - top = self.check_toppatch(repo)[0] + top = self.checktoppatch(repo)[0] try: heads = repo.changelog.heads(rev) @@ -1319,7 +1319,7 @@ wlock.release() def diff(self, repo, pats, opts): - top, patch = self.check_toppatch(repo) + top, patch = self.checktoppatch(repo) if not top: self.ui.write(_("no patches applied\n")) return @@ -1343,12 +1343,12 @@ wlock = repo.wlock() try: - self.check_toppatch(repo) + self.checktoppatch(repo) (top, patchfn) = (self.applied[-1].node, self.applied[-1].name) if repo.changelog.heads(top) != [top]: raise util.Abort(_("cannot refresh a revision with children")) - inclsubs = self.check_substate(repo) + inclsubs = self.checksubstate(repo) cparents = repo.changelog.parents(top) patchparent = self.qparents(repo, top) @@ -1494,7 +1494,7 @@ # assumes strip can roll itself back if interrupted repo.dirstate.setparents(*cparents) self.applied.pop() - self.applied_dirty = 1 + self.applieddirty = 1 self.strip(repo, [top], update=False, backup='strip') except: @@ -1511,7 +1511,7 @@ except: ctx = repo[cparents[0]] repo.dirstate.rebuild(ctx.node(), ctx.manifest()) - self.save_dirty() + self.savedirty() self.ui.warn(_('refresh interrupted while patch was popped! ' '(revert --all, qpush to recover)\n')) raise @@ -1534,7 +1534,7 @@ if patch and patch not in self.series: raise util.Abort(_("patch %s is not in series file") % patch) if not patch: - start = self.series_end() + start = self.seriesend() else: start = self.series.index(patch) + 1 unapplied = [] @@ -1542,7 +1542,7 @@ pushable, reason = self.pushable(i) if pushable: unapplied.append((i, self.series[i])) - self.explain_pushable(i) + self.explainpushable(i) return unapplied def qseries(self, repo, missing=None, start=0, length=None, status=None, @@ -1593,8 +1593,8 @@ for f in files: fl = os.path.join(d, f) if (fl not in self.series and - fl not in (self.status_path, self.series_path, - self.guards_path) + fl not in (self.statuspath, self.seriespath, + self.guardspath) and not fl.startswith('.')): msng_list.append(fl) for x in sorted(msng_list): @@ -1638,11 +1638,11 @@ self.ui.warn(_("No saved patch data found\n")) return 1 self.ui.warn(_("restoring status: %s\n") % lines[0]) - self.full_series = series + self.fullseries = series self.applied = applied - self.parse_series() - self.series_dirty = 1 - self.applied_dirty = 1 + self.parseseries() + self.seriesdirty = 1 + self.applieddirty = 1 heads = repo.changelog.heads() if delete: if rev not in heads: @@ -1684,25 +1684,25 @@ msg += "\nDirstate: %s %s" % (hex(pp[0]), hex(pp[1])) msg += "\n\nPatch Data:\n" msg += ''.join('%s\n' % x for x in self.applied) - msg += ''.join(':%s\n' % x for x in self.full_series) + msg += ''.join(':%s\n' % x for x in self.fullseries) n = repo.commit(msg, force=True) if not n: self.ui.warn(_("repo commit failed\n")) return 1 self.applied.append(statusentry(n, '.hg.patches.save.line')) - self.applied_dirty = 1 + self.applieddirty = 1 self.removeundo(repo) - def full_series_end(self): + def fullseriesend(self): if self.applied: p = self.applied[-1].name - end = self.find_series(p) + end = self.findseries(p) if end is None: - return len(self.full_series) + return len(self.fullseries) return end + 1 return 0 - def series_end(self, all_patches=False): + def seriesend(self, all_patches=False): """If all_patches is False, return the index of the next pushable patch in the series, or the series length. If all_patches is True, return the index of the first patch past the last applied one. @@ -1715,7 +1715,7 @@ p, reason = self.pushable(i) if p: break - self.explain_pushable(i) + self.explainpushable(i) return i if self.applied: p = self.applied[-1].name @@ -1789,7 +1789,7 @@ patchname = normname('%d.diff' % r) checkseries(patchname) self.checkpatchname(patchname, force) - self.full_series.insert(0, patchname) + self.fullseries.insert(0, patchname) patchf = self.opener(patchname, "w") cmdutil.export(repo, [n], fp=patchf, opts=diffopts) @@ -1800,16 +1800,16 @@ self.added.append(patchname) patchname = None - self.parse_series() - self.applied_dirty = 1 - self.series_dirty = True + self.parseseries() + self.applieddirty = 1 + self.seriesdirty = True for i, filename in enumerate(files): if existing: if filename == '-': raise util.Abort(_('-e is incompatible with import from -')) filename = normname(filename) - self.check_reserved_name(filename) + self.checkreservedname(filename) originpath = self.join(filename) if not os.path.isfile(originpath): raise util.Abort(_("patch %s does not exist") % filename) @@ -1844,10 +1844,10 @@ if not force: checkseries(patchname) if patchname not in self.series: - index = self.full_series_end() + i - self.full_series[index:index] = [patchname] - self.parse_series() - self.series_dirty = True + index = self.fullseriesend() + i + self.fullseries[index:index] = [patchname] + self.parseseries() + self.seriesdirty = True self.ui.warn(_("adding %s to series file\n") % patchname) self.added.append(patchname) patchname = None @@ -1869,7 +1869,7 @@ use the :hg:`qfinish` command.""" q = repo.mq q.delete(repo, patches, opts) - q.save_dirty() + q.savedirty() return 0 @command("qapplied", @@ -1888,7 +1888,7 @@ raise util.Abort(_("patch %s is not in series file") % patch) end = q.series.index(patch) + 1 else: - end = q.series_end(True) + end = q.seriesend(True) if opts.get('last') and not end: ui.write(_("no patches applied\n")) @@ -1920,7 +1920,7 @@ raise util.Abort(_("patch %s is not in series file") % patch) start = q.series.index(patch) + 1 else: - start = q.series_end(True) + start = q.seriesend(True) if start == len(q.series) and opts.get('first'): ui.write(_("all patches applied\n")) @@ -1979,7 +1979,7 @@ existing=opts.get('existing'), force=opts.get('force'), rev=opts.get('rev'), git=opts.get('git')) finally: - q.save_dirty() + q.savedirty() if opts.get('push') and not opts.get('rev'): return q.push(repo, None) @@ -1995,7 +1995,7 @@ Returns 0 if initialization succeeded.""" q = repo.mq r = q.init(repo, create) - q.save_dirty() + q.savedirty() if r: if not os.path.exists(r.wjoin('.hgignore')): fp = r.wopener('.hgignore', 'w') @@ -2084,13 +2084,13 @@ except error.RepoError: pass ui.note(_('cloning main repository\n')) - sr, dr = hg.clone(ui, sr.url(), dest, + sr, dr = hg.clone(ui, opts, sr.url(), dest, pull=opts.get('pull'), rev=destrev, update=False, stream=opts.get('uncompressed')) ui.note(_('cloning patch repository\n')) - hg.clone(ui, opts.get('patches') or patchdir(sr), patchdir(dr), + hg.clone(ui, opts, opts.get('patches') or patchdir(sr), patchdir(dr), pull=opts.get('pull'), update=not opts.get('noupdate'), stream=opts.get('uncompressed')) if dr.local(): @@ -2132,7 +2132,7 @@ Returns 0 on success.""" q = repo.mq - t = q.applied and q.series_end(True) or 0 + t = q.applied and q.seriesend(True) or 0 if t: q.qseries(repo, start=t - 1, length=1, status='A', summary=opts.get('summary')) @@ -2146,7 +2146,7 @@ Returns 0 on success.""" q = repo.mq - end = q.series_end() + end = q.seriesend() if end == len(q.series): ui.write(_("all patches applied\n")) return 1 @@ -2222,7 +2222,7 @@ opts['msg'] = msg setupheaderopts(ui, opts) q.new(repo, patch, *args, **opts) - q.save_dirty() + q.savedirty() return 0 @command("^qrefresh", @@ -2275,9 +2275,13 @@ # We don't want to lose the patch message if qrefresh fails (issue2062) repo.savecommitmessage(message) setupheaderopts(ui, opts) - ret = q.refresh(repo, pats, msg=message, **opts) - q.save_dirty() - return ret + wlock = repo.wlock() + try: + ret = q.refresh(repo, pats, msg=message, **opts) + q.savedirty() + return ret + finally: + wlock.release() @command("^qdiff", commands.diffopts + commands.diffopts2 + commands.walkopts, @@ -2324,9 +2328,9 @@ if not files: raise util.Abort(_('qfold requires at least one patch name')) - if not q.check_toppatch(repo)[0]: + if not q.checktoppatch(repo)[0]: raise util.Abort(_('no patches applied')) - q.check_localchanges(repo) + q.checklocalchanges(repo) message = cmdutil.logmessage(opts) if opts.get('edit'): @@ -2366,9 +2370,13 @@ message = ui.edit(message, user or ui.username()) diffopts = q.patchopts(q.diffopts(), *patches) - q.refresh(repo, msg=message, git=diffopts.git) - q.delete(repo, patches, opts) - q.save_dirty() + wlock = repo.wlock() + try: + q.refresh(repo, msg=message, git=diffopts.git) + q.delete(repo, patches, opts) + q.savedirty() + finally: + wlock.release() @command("qgoto", [('f', 'force', None, _('overwrite any local changes'))], @@ -2383,7 +2391,7 @@ ret = q.pop(repo, patch, force=opts.get('force')) else: ret = q.push(repo, patch, force=opts.get('force')) - q.save_dirty() + q.savedirty() return ret @command("qguard", @@ -2412,7 +2420,7 @@ Returns 0 on success. ''' def status(idx): - guards = q.series_guards[idx] or ['unguarded'] + guards = q.seriesguards[idx] or ['unguarded'] if q.series[idx] in applied: state = 'applied' elif q.pushable(idx)[0]: @@ -2451,11 +2459,11 @@ if patch is None: raise util.Abort(_('no patch to work with')) if args or opts.get('none'): - idx = q.find_series(patch) + idx = q.findseries(patch) if idx is None: raise util.Abort(_('no patch named %s') % patch) - q.set_guards(idx, args) - q.save_dirty() + q.setguards(idx, args) + q.savedirty() else: status(q.series.index(q.lookup(patch))) @@ -2561,7 +2569,7 @@ q = repo.mq ret = q.pop(repo, patch, force=opts.get('force'), update=localupdate, all=opts.get('all')) - q.save_dirty() + q.savedirty() return ret @command("qrename|qmv", [], _('hg qrename PATCH1 [PATCH2]')) @@ -2593,16 +2601,16 @@ q.checkpatchname(name) ui.note(_('renaming %s to %s\n') % (patch, name)) - i = q.find_series(patch) - guards = q.guard_re.findall(q.full_series[i]) - q.full_series[i] = name + ''.join([' #' + g for g in guards]) - q.parse_series() - q.series_dirty = 1 + i = q.findseries(patch) + guards = q.guard_re.findall(q.fullseries[i]) + q.fullseries[i] = name + ''.join([' #' + g for g in guards]) + q.parseseries() + q.seriesdirty = 1 info = q.isapplied(patch) if info: q.applied[info[0]] = statusentry(info[1], name) - q.applied_dirty = 1 + q.applieddirty = 1 destdir = os.path.dirname(absdest) if not os.path.isdir(destdir): @@ -2624,7 +2632,7 @@ finally: wlock.release() - q.save_dirty() + q.savedirty() @command("qrestore", [('d', 'delete', None, _('delete save entry')), @@ -2638,7 +2646,7 @@ q = repo.mq q.restore(repo, rev, delete=opts.get('delete'), qupdate=opts.get('update')) - q.save_dirty() + q.savedirty() return 0 @command("qsave", @@ -2657,7 +2665,7 @@ ret = q.save(repo, msg=message) if ret: return ret - q.save_dirty() + q.savedirty() if opts.get('copy'): path = q.path if opts.get('name'): @@ -2675,7 +2683,7 @@ util.copyfiles(path, newpath) if opts.get('empty'): try: - os.unlink(q.join(q.status_path)) + os.unlink(q.join(q.statuspath)) except: pass return 0 @@ -2745,7 +2753,7 @@ # refresh queue state if we're about to strip # applied patches if cl.rev(repo.lookup('qtip')) in strippedrevs: - q.applied_dirty = True + q.applieddirty = True start = 0 end = len(q.applied) for i, statusentry in enumerate(q.applied): @@ -2755,7 +2763,7 @@ start = i break del q.applied[start:end] - q.save_dirty() + q.savedirty() revs = list(rootnodes) if update and opts.get('keep'): @@ -2819,8 +2827,8 @@ old_unapplied = q.unapplied(repo) old_guarded = [i for i in xrange(len(q.applied)) if not q.pushable(i)[0]] - q.set_active(args) - q.save_dirty() + q.setactive(args) + q.savedirty() if not args: ui.status(_('guards deactivated\n')) if not opts.get('pop') and not opts.get('reapply'): @@ -2838,7 +2846,7 @@ elif opts.get('series'): guards = {} noguards = 0 - for gs in q.series_guards: + for gs in q.seriesguards: if not gs: noguards += 1 for g in gs: @@ -2881,7 +2889,7 @@ ui.status(_('reapplying unguarded patches\n')) q.push(repo, reapply) finally: - q.save_dirty() + q.savedirty() @command("qfinish", [('a', 'applied', None, _('finish all applied changesets'))], @@ -2916,7 +2924,7 @@ revs = scmutil.revrange(repo, revrange) q.finish(repo, revs) - q.save_dirty() + q.savedirty() return 0 @command("qqueue", @@ -3095,7 +3103,7 @@ def mq(self): return queue(self.ui, self.join("")) - def abort_if_wdir_patched(self, errmsg, force=False): + def abortifwdirpatched(self, errmsg, force=False): if self.mq.applied and not force: parents = self.dirstate.parents() patches = [s.node for s in self.mq.applied] @@ -3104,7 +3112,7 @@ def commit(self, text="", user=None, date=None, match=None, force=False, editor=False, extra={}): - self.abort_if_wdir_patched( + self.abortifwdirpatched( _('cannot commit over an applied mq patch'), force) @@ -3136,7 +3144,7 @@ try: self.changelog.rev(mqtags[-1][0]) - except error.RepoLookupError: + except error.LookupError: self.ui.warn(_('mq status file refers to unknown node %s\n') % short(mqtags[-1][0])) return result @@ -3189,9 +3197,9 @@ repo.__class__ = mqrepo def mqimport(orig, ui, repo, *args, **kwargs): - if (hasattr(repo, 'abort_if_wdir_patched') + if (hasattr(repo, 'abortifwdirpatched') and not kwargs.get('no_commit', False)): - repo.abort_if_wdir_patched(_('cannot import over an applied patch'), + repo.abortifwdirpatched(_('cannot import over an applied patch'), kwargs.get('force')) return orig(ui, repo, *args, **kwargs)
--- a/hgext/notify.py Tue Jun 14 00:31:56 2011 +0400 +++ b/hgext/notify.py Tue Jun 14 20:43:04 2011 -0500 @@ -21,6 +21,8 @@ incoming.notify = python:hgext.notify.hook # batch emails when many changesets incoming at one time changegroup.notify = python:hgext.notify.hook + # batch emails when many changesets outgoing at one time (client side) + outgoing.notify = python:hgext.notify.hook [notify] # config items go here @@ -37,7 +39,8 @@ style = ... # style file to use when formatting email template = ... # template to use when formatting email incoming = ... # template to use when run as incoming hook - changegroup = ... # template when run as changegroup hook + outgoing = ... # template to use when run as outgoing hook + changegroup = ... # template to use when run as changegroup hook maxdiff = 300 # max lines of diffs to include (0=none, -1=all) maxsubject = 67 # truncate subject line longer than this diffstat = True # add a diffstat before the diff content @@ -290,7 +293,7 @@ ui.pushbuffer() data = '' count = 0 - if hooktype == 'changegroup': + if hooktype == 'changegroup' or hooktype == 'outgoing': start, end = ctx.rev(), len(repo) for rev in xrange(start, end): if n.node(repo[rev]):
--- a/hgext/patchbomb.py Tue Jun 14 00:31:56 2011 +0400 +++ b/hgext/patchbomb.py Tue Jun 14 20:43:04 2011 -0500 @@ -276,7 +276,7 @@ dest = ui.expandpath(dest or 'default-push', dest or 'default') dest, branches = hg.parseurl(dest) revs, checkout = hg.addbranchrevs(repo, repo, branches, revs) - other = hg.repository(hg.remoteui(repo, opts), dest) + other = hg.peer(repo, opts, dest) ui.status(_('comparing with %s\n') % util.hidepassword(dest)) common, _anyinc, _heads = discovery.findcommonincoming(repo, other) nodes = revs and map(repo.lookup, revs) or revs
--- a/hgext/rebase.py Tue Jun 14 00:31:56 2011 +0400 +++ b/hgext/rebase.py Tue Jun 14 20:43:04 2011 -0500 @@ -376,7 +376,7 @@ 'Update rebased mq patches - finalize and then import them' mqrebase = {} mq = repo.mq - original_series = mq.full_series[:] + original_series = mq.fullseries[:] for p in mq.applied: rev = repo[p.node].rev() @@ -396,15 +396,10 @@ mq.qimport(repo, (), patchname=name, git=isgit, rev=[str(state[rev])]) - # Restore missing guards - for s in original_series: - pname = mq.guard_re.split(s, 1)[0] - if pname in mq.full_series: - repo.ui.debug('restoring guard for patch %s' % (pname)) - mq.full_series.remove(pname) - mq.full_series.append(s) - mq.series_dirty = True - mq.save_dirty() + # restore old series to preserve guards + mq.fullseries = original_series + mq.series_dirty = True + mq.savedirty() def storestatus(repo, originalwd, target, state, collapse, keep, keepbranches, external):
--- a/hgext/record.py Tue Jun 14 00:31:56 2011 +0400 +++ b/hgext/record.py Tue Jun 14 20:43:04 2011 -0500 @@ -17,6 +17,15 @@ lines_re = re.compile(r'@@ -(\d+),(\d+) \+(\d+),(\d+) @@\s*(.*)') +diffopts = [ + ('w', 'ignore-all-space', False, + _('ignore white space when comparing lines')), + ('b', 'ignore-space-change', None, + _('ignore changes in the amount of white space')), + ('B', 'ignore-blank-lines', None, + _('ignore changes whose lines are all blank')), +] + def scanpatch(fp): """like patch.iterhunks, but yield different events @@ -345,7 +354,8 @@ if h[0].special() or len(h) > 1], []) @command("record", - commands.table['^commit|ci'][1], # same options as commit + # same options as commit + white space diff options + commands.table['^commit|ci'][1][:] + diffopts, _('hg record [OPTION]... [FILE]...')) def record(ui, repo, *pats, **opts): '''interactively select changes to commit @@ -435,7 +445,10 @@ '(use "hg commit" instead)')) changes = repo.status(match=match)[:3] - diffopts = mdiff.diffopts(git=True, nodates=True) + diffopts = mdiff.diffopts(git=True, nodates=True, + ignorews=opts.get('ignore_all_space'), + ignorewsamount=opts.get('ignore_space_change'), + ignoreblanklines=opts.get('ignore_blank_lines')) chunks = patch.diff(repo, changes=changes, opts=diffopts) fp = cStringIO.StringIO() fp.write(''.join(chunks)) @@ -567,8 +580,8 @@ cmdtable["qrecord"] = \ (qrecord, # same options as qnew, but copy them so we don't get - # -i/--interactive for qrecord - mq.cmdtable['^qnew'][1][:], + # -i/--interactive for qrecord and add white space diff options + mq.cmdtable['^qnew'][1][:] + diffopts, _('hg qrecord [OPTION]... PATCH [FILE]...')) _wrapcmd('qnew', mq.cmdtable, qrecord, _("interactively record a new patch"))
--- a/hgext/relink.py Tue Jun 14 00:31:56 2011 +0400 +++ b/hgext/relink.py Tue Jun 14 20:43:04 2011 -0500 @@ -38,9 +38,8 @@ """ if not hasattr(util, 'samefile') or not hasattr(util, 'samedevice'): raise util.Abort(_('hardlinks are not supported on this system')) - src = hg.repository(hg.remoteui(repo, opts), - ui.expandpath(origin or 'default-relink', - origin or 'default')) + src = hg.repository(ui, ui.expandpath(origin or 'default-relink', + origin or 'default')) if not src.local(): raise util.Abort(_('must specify local origin repository')) ui.status(_('relinking %s to %s\n') % (src.store.path, repo.store.path))
--- a/hgext/schemes.py Tue Jun 14 00:31:56 2011 +0400 +++ b/hgext/schemes.py Tue Jun 14 20:43:04 2011 -0500 @@ -69,7 +69,7 @@ tail = '' context = dict((str(i + 1), v) for i, v in enumerate(parts)) url = ''.join(self.templater.process(self.url, context)) + tail - return hg._lookup(url).instance(ui, url, create) + return hg._peerlookup(url).instance(ui, url, create) def hasdriveletter(orig, path): for scheme in schemes:
--- a/hgext/transplant.py Tue Jun 14 00:31:56 2011 +0400 +++ b/hgext/transplant.py Tue Jun 14 20:43:04 2011 -0500 @@ -227,7 +227,7 @@ raise util.Abort(_('can only omit patchfile if merging')) if patchfile: try: - files = {} + files = set() patch.patch(self.ui, repo, patchfile, files=files, eolmode=None) files = list(files) if not files: @@ -561,7 +561,7 @@ sourcerepo = opts.get('source') if sourcerepo: - source = hg.repository(ui, ui.expandpath(sourcerepo)) + source = hg.peer(ui, opts, ui.expandpath(sourcerepo)) branches = map(source.lookup, opts.get('branch', ())) source, csets, cleanupfn = bundlerepo.getremotechanges(ui, repo, source, onlyheads=branches, force=True)
--- a/mercurial/bookmarks.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/bookmarks.py Tue Jun 14 20:43:04 2011 -0500 @@ -114,7 +114,7 @@ wlock = repo.wlock() try: file = repo.opener('bookmarks.current', 'w', atomictemp=True) - file.write(mark) + file.write(encoding.fromlocal(mark)) file.rename() finally: wlock.release()
--- a/mercurial/commands.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/commands.py Tue Jun 14 20:43:04 2011 -0500 @@ -891,7 +891,7 @@ else: 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) + other = hg.peer(repo, opts, dest) revs, checkout = hg.addbranchrevs(repo, other, branches, revs) heads = revs and map(repo.lookup, revs) or revs common, outheads = discovery.findcommonoutgoing(repo, other, @@ -1026,7 +1026,7 @@ if opts.get('noupdate') and opts.get('updaterev'): raise util.Abort(_("cannot specify both --noupdate and --updaterev")) - r = hg.clone(hg.remoteui(ui, opts), source, dest, + r = hg.clone(ui, opts, source, dest, pull=opts.get('pull'), stream=opts.get('uncompressed'), rev=opts.get('rev'), @@ -1542,7 +1542,7 @@ def debugdiscovery(ui, repo, remoteurl="default", **opts): """runs the changeset discovery protocol in isolation""" remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch')) - remote = hg.repository(hg.remoteui(repo, opts), remoteurl) + remote = hg.peer(repo, opts, remoteurl) ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl)) # make sure tests are repeatable @@ -1603,6 +1603,10 @@ if ui.verbose: tree = fileset.parse(expr)[0] ui.note(tree, "\n") + matcher = lambda x: scmutil.match(repo, x, default='glob') + + for f in fileset.getfileset(repo[None], matcher, expr): + ui.write("%s\n" % f) @command('debugfsinfo', [], _('[PATH]')) def debugfsinfo(ui, path = "."): @@ -1625,7 +1629,7 @@ Every ID must be a full-length hex node id string. Saves the bundle to the given file. """ - repo = hg.repository(ui, repopath) + repo = hg.peer(ui, opts, repopath) if not repo.capable('getbundle'): raise util.Abort("getbundle() not supported by target repository") args = {} @@ -1800,14 +1804,14 @@ Every ID must be a full-length hex node id string. Returns a list of 0s and 1s indicating unknown/known. """ - repo = hg.repository(ui, repopath) + repo = hg.peer(ui, opts, repopath) if not repo.capable('known'): raise util.Abort("known() not supported by target repository") flags = repo.known([bin(s) for s in ids]) ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags]))) @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]')) -def debugpushkey(ui, repopath, namespace, *keyinfo): +def debugpushkey(ui, repopath, namespace, *keyinfo, **opts): '''access the pushkey key/value protocol With two args, list the keys in the given namespace. @@ -1816,7 +1820,7 @@ Reports success or failure. ''' - target = hg.repository(ui, repopath) + target = hg.peer(ui, {}, repopath) if keyinfo: key, old, new = keyinfo r = target.pushkey(namespace, key, old, new) @@ -2113,7 +2117,7 @@ ] + remoteopts, _('REPO [OPTIONS]... [ONE [TWO]]')) def debugwireargs(ui, repopath, *vals, **opts): - repo = hg.repository(hg.remoteui(ui, opts), repopath) + repo = hg.peer(ui, opts, repopath) for opt in remoteopts: del opts[opt[1]] args = {} @@ -2268,8 +2272,9 @@ for f in m.files(): if f not in repo.dirstate and not os.path.isdir(m.rel(f)): - ui.warn(_('not removing %s: file is already untracked\n') - % m.rel(f)) + if os.path.exists(m.rel(f)): + ui.warn(_('not removing %s: file is already untracked\n') + % m.rel(f)) errs = 1 for f in forget: @@ -2910,7 +2915,7 @@ if source: source, branches = hg.parseurl(ui.expandpath(source)) - repo = hg.repository(ui, source) + repo = hg.peer(ui, {}, source) revs, checkout = hg.addbranchrevs(repo, repo, branches, None) if not repo.local(): @@ -2997,6 +3002,8 @@ ('f', 'force', None, _('skip check for outstanding uncommitted changes')), ('', 'no-commit', None, _("don't commit, just update the working directory")), + ('', 'bypass', None, + _("apply patch without touching the working directory")), ('', 'exact', None, _('apply patch to the nodes from which it was generated')), ('', 'import-branch', None, @@ -3030,6 +3037,11 @@ the patch. This may happen due to character set problems or other deficiencies in the text patch format. + Use --bypass to apply and commit patches directly to the + repository, not touching the working directory. Without --exact, + patches will be applied on top of the working directory parent + revision. + With -s/--similarity, hg will attempt to discover renames and copies in the patch in the same way as 'addremove'. @@ -3045,14 +3057,19 @@ if date: opts['date'] = util.parsedate(date) + update = not opts.get('bypass') + if not update and opts.get('no_commit'): + raise util.Abort(_('cannot use --no-commit with --bypass')) try: sim = float(opts.get('similarity') or 0) except ValueError: raise util.Abort(_('similarity must be a number')) if sim < 0 or sim > 100: raise util.Abort(_('similarity must be between 0 and 100')) - - if opts.get('exact') or not opts.get('force'): + if sim and not update: + raise util.Abort(_('cannot use --similarity with --bypass')) + + if (opts.get('exact') or not opts.get('force')) and update: cmdutil.bailifchanged(repo) d = opts["base"] @@ -3060,7 +3077,12 @@ wlock = lock = None msgs = [] - def tryone(ui, hunk): + def checkexact(repo, n, nodeid): + if opts.get('exact') and hex(n) != nodeid: + repo.rollback() + raise util.Abort(_('patch is damaged or loses information')) + + def tryone(ui, hunk, parents): tmpname, message, user, date, branch, nodeid, p1, p2 = \ patch.extract(ui, hunk) @@ -3081,53 +3103,77 @@ message = None ui.debug('message:\n%s\n' % message) - wp = repo.parents() + if len(parents) == 1: + parents.append(repo[nullid]) if opts.get('exact'): if not nodeid or not p1: raise util.Abort(_('not a Mercurial patch')) - p1 = repo.lookup(p1) - p2 = repo.lookup(p2 or hex(nullid)) - - if p1 != wp[0].node(): - hg.clean(repo, p1) - repo.dirstate.setparents(p1, p2) + p1 = repo[p1] + p2 = repo[p2 or nullid] elif p2: try: - p1 = repo.lookup(p1) - p2 = repo.lookup(p2) - if p1 == wp[0].node(): - repo.dirstate.setparents(p1, p2) + p1 = repo[p1] + p2 = repo[p2] except error.RepoError: - pass - if opts.get('exact') or opts.get('import_branch'): - repo.dirstate.setbranch(branch or 'default') - - files = {} - patch.patch(ui, repo, tmpname, strip=strip, files=files, - eolmode=None, similarity=sim / 100.0) - files = list(files) - if opts.get('no_commit'): - if message: - msgs.append(message) + p1, p2 = parents else: - if opts.get('exact'): - m = None + p1, p2 = parents + + n = None + if update: + if opts.get('exact') and p1 != parents[0]: + hg.clean(repo, p1.node()) + if p1 != parents[0] and p2 != parents[1]: + repo.dirstate.setparents(p1.node(), p2.node()) + + if opts.get('exact') or opts.get('import_branch'): + repo.dirstate.setbranch(branch or 'default') + + files = set() + patch.patch(ui, repo, tmpname, strip=strip, files=files, + eolmode=None, similarity=sim / 100.0) + files = list(files) + if opts.get('no_commit'): + if message: + msgs.append(message) else: - m = scmutil.matchfiles(repo, files or []) - n = repo.commit(message, opts.get('user') or user, - opts.get('date') or date, match=m, - editor=cmdutil.commiteditor) - if opts.get('exact'): - if hex(n) != nodeid: - repo.rollback() - raise util.Abort(_('patch is damaged' - ' or loses information')) - # Force a dirstate write so that the next transaction - # backups an up-do-date file. - repo.dirstate.write() - if n: - commitid = short(n) - + if opts.get('exact'): + m = None + else: + m = scmutil.matchfiles(repo, files or []) + n = repo.commit(message, opts.get('user') or user, + opts.get('date') or date, match=m, + editor=cmdutil.commiteditor) + checkexact(repo, n, nodeid) + # Force a dirstate write so that the next transaction + # backups an up-to-date file. + repo.dirstate.write() + else: + if opts.get('exact') or opts.get('import_branch'): + branch = branch or 'default' + else: + branch = p1.branch() + store = patch.filestore() + try: + files = set() + try: + patch.patchrepo(ui, repo, p1, store, tmpname, strip, + files, eolmode=None) + except patch.PatchError, e: + raise util.Abort(str(e)) + memctx = patch.makememctx(repo, (p1.node(), p2.node()), + message, + opts.get('user') or user, + opts.get('date') or date, + branch, files, store, + editor=cmdutil.commiteditor) + repo.savecommitmessage(memctx.description()) + n = memctx.commit() + checkexact(repo, n, nodeid) + finally: + store.close() + if n: + commitid = short(n) return commitid finally: os.unlink(tmpname) @@ -3135,6 +3181,7 @@ try: wlock = repo.wlock() lock = repo.lock() + parents = repo.parents() lastcommit = None for p in patches: pf = os.path.join(d, p) @@ -3148,12 +3195,16 @@ haspatch = False for hunk in patch.split(pf): - commitid = tryone(ui, hunk) + commitid = tryone(ui, hunk, parents) if commitid: haspatch = True if lastcommit: ui.status(_('applied %s\n') % lastcommit) lastcommit = commitid + if update or opts.get('exact'): + parents = repo.parents() + else: + parents = [repo[commitid]] if not haspatch: raise util.Abort(_('no diffs found')) @@ -3195,7 +3246,7 @@ if opts.get('bookmarks'): source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch')) - other = hg.repository(hg.remoteui(repo, opts), source) + other = hg.peer(repo, opts, source) if 'bookmarks' not in other.listkeys('namespaces'): ui.warn(_("remote doesn't support bookmarks\n")) return 0 @@ -3223,7 +3274,7 @@ Returns 0 on success. """ - hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=True) + hg.peer(ui, opts, ui.expandpath(dest), create=True) @command('locate', [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')), @@ -3557,7 +3608,7 @@ 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) + other = hg.peer(repo, opts, dest) if 'bookmarks' not in other.listkeys('namespaces'): ui.warn(_("remote doesn't support bookmarks\n")) return 0 @@ -3709,7 +3760,7 @@ Returns 0 on success, 1 if an update had unresolved files. """ source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch')) - other = hg.repository(hg.remoteui(repo, opts), source) + other = hg.peer(repo, opts, source) ui.status(_('pulling from %s\n') % util.hidepassword(source)) revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev')) @@ -3806,7 +3857,7 @@ dest, branches = hg.parseurl(dest, opts.get('branch')) ui.status(_('pushing to %s\n') % util.hidepassword(dest)) revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev')) - other = hg.repository(hg.remoteui(repo, opts), dest) + other = hg.peer(repo, opts, dest) if revs: revs = [repo.lookup(rev) for rev in revs] @@ -3913,7 +3964,8 @@ for f in m.files(): if f not in repo.dirstate and not os.path.isdir(m.rel(f)): - ui.warn(_('not removing %s: file is untracked\n') % m.rel(f)) + if os.path.exists(m.rel(f)): + ui.warn(_('not removing %s: file is untracked\n') % m.rel(f)) ret = 1 if force: @@ -4086,44 +4138,29 @@ ] + walkopts + dryrunopts, _('[OPTION]... [-r REV] [NAME]...')) def revert(ui, repo, *pats, **opts): - """restore individual files or directories to an earlier state + """restore files to their checkout state .. 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. - This restores the contents of the affected files to an unmodified - state and unschedules adds, removes, copies, and renames. If the - working directory has two parents, you must explicitly specify a - revision. - - Using the -r/--rev option, revert the given files or directories - to their contents as of a specific revision. This can be helpful - to "roll back" some or all of an earlier change. See :hg:`help - dates` for a list of formats valid for -d/--date. - - Revert modifies the working directory. It does not commit any - changes, or change the parent of the working directory. If you - revert to a revision other than the parent of the working - directory, the reverted files will thus appear modified - afterwards. - - If a file has been deleted, it is restored. Files scheduled for - addition are just unscheduled and left as they are. If the - executable mode of a file was changed, it is reset. - - If names are given, all files matching the names are reverted. - If no arguments are given, no files are reverted. + To check out earlier revisions, you should use :hg:`update REV`. + To cancel a merge (and lose your changes), use :hg:`update --clean .`. + + With no revision specified, revert the specified files or directories + to the state they had in the first parent of the working directory. + This restores the contents of files to an unmodified + state and unschedules adds, removes, copies, and renames. + + Using the -r/--rev or -d/--date options, revert the given files or + directories to their states as of a specific revision. Because + revert does not change the working directory parents, this will + cause these files to appear modified. This can be helpful to "back + out" some or all of an earlier change. See :hg:`backout` for a + related method. Modified files are saved with a .orig suffix before reverting. To disable these backups, use --no-backup. + See :hg:`help dates` for a list of formats valid for -d/--date. + Returns 0 on success. """ @@ -4133,13 +4170,10 @@ opts["rev"] = cmdutil.finddate(ui, repo, opts["date"]) parent, p2 = repo.dirstate.parents() - if not opts.get('rev') and p2 != nullid: - raise util.Abort(_('uncommitted merge - ' - 'use "hg update", see "hg help revert"')) if not pats and not opts.get('all'): - raise util.Abort(_('no files or directories specified; ' - 'use --all to revert the whole repo')) + raise util.Abort(_('no files or directories specified'), + hint=_('use --all to revert all files')) ctx = scmutil.revsingle(repo, opts.get('rev')) node = ctx.node() @@ -4756,7 +4790,7 @@ if opts.get('remote'): t = [] source, branches = hg.parseurl(ui.expandpath('default')) - other = hg.repository(hg.remoteui(repo, {}), source) + other = hg.peer(repo, {}, source) revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev')) ui.debug('comparing with %s\n' % util.hidepassword(source)) repo.ui.pushbuffer() @@ -4769,7 +4803,7 @@ dest, branches = hg.parseurl(ui.expandpath('default-push', 'default')) revs, checkout = hg.addbranchrevs(repo, repo, branches, None) if source != dest: - other = hg.repository(hg.remoteui(repo, {}), dest) + other = hg.peer(repo, {}, dest) commoninc = None ui.debug('comparing with %s\n' % util.hidepassword(dest)) repo.ui.pushbuffer()
--- a/mercurial/dispatch.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/dispatch.py Tue Jun 14 20:43:04 2011 -0500 @@ -12,34 +12,55 @@ import ui as uimod class request(object): - def __init__(self, args, ui=None, repo=None): + def __init__(self, args, ui=None, repo=None, fin=None, fout=None, ferr=None): self.args = args self.ui = ui self.repo = repo + # input/output/error streams + self.fin = fin + self.fout = fout + self.ferr = ferr + def run(): "run the command in sys.argv" sys.exit(dispatch(request(sys.argv[1:]))) def dispatch(req): "run the command specified in req.args" + if req.ferr: + ferr = req.ferr + elif req.ui: + ferr = req.ui.ferr + else: + ferr = sys.stderr + try: if not req.ui: req.ui = uimod.ui() if '--traceback' in req.args: req.ui.setconfig('ui', 'traceback', 'on') + + # set ui streams from the request + if req.fin: + req.ui.fin = req.fin + if req.fout: + req.ui.fout = req.fout + if req.ferr: + req.ui.ferr = req.ferr except util.Abort, inst: - sys.stderr.write(_("abort: %s\n") % inst) + ferr.write(_("abort: %s\n") % inst) if inst.hint: - sys.stderr.write(_("(%s)\n") % inst.hint) + ferr.write(_("(%s)\n") % inst.hint) return -1 except error.ParseError, inst: if len(inst.args) > 1: - sys.stderr.write(_("hg: parse error at %s: %s\n") % + ferr.write(_("hg: parse error at %s: %s\n") % (inst.args[1], inst.args[0])) else: - sys.stderr.write(_("hg: parse error: %s\n") % inst.args[0]) + ferr.write(_("hg: parse error: %s\n") % inst.args[0]) return -1 + return _runcatch(req) def _runcatch(req): @@ -572,16 +593,20 @@ atexit.register(print_time) if options['verbose'] or options['debug'] or options['quiet']: - ui.setconfig('ui', 'verbose', str(bool(options['verbose']))) - ui.setconfig('ui', 'debug', str(bool(options['debug']))) - ui.setconfig('ui', 'quiet', str(bool(options['quiet']))) + for ui_ in (ui, lui): + ui_.setconfig('ui', 'verbose', str(bool(options['verbose']))) + ui_.setconfig('ui', 'debug', str(bool(options['debug']))) + ui_.setconfig('ui', 'quiet', str(bool(options['quiet']))) if options['traceback']: - ui.setconfig('ui', 'traceback', 'on') + for ui_ in (ui, lui): + ui_.setconfig('ui', 'traceback', 'on') if options['noninteractive']: - ui.setconfig('ui', 'interactive', 'off') + for ui_ in (ui, lui): + ui_.setconfig('ui', 'interactive', 'off') if cmdoptions.get('insecure', False): - ui.setconfig('web', 'cacerts', '') + for ui_ in (ui, lui): + ui_.setconfig('web', 'cacerts', '') if options['help']: return commands.help_(ui, cmd, options['version'])
--- a/mercurial/extensions.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/extensions.py Tue Jun 14 20:43:04 2011 -0500 @@ -262,6 +262,14 @@ def disabled(): '''find disabled extensions from hgext. returns a dict of {name: desc}''' + try: + from hgext import __index__ + return dict((name, gettext(desc)) + for name, desc in __index__.docs.iteritems() + if name not in _order) + except ImportError: + pass + paths = _disabledpaths() if not paths: return None @@ -276,6 +284,15 @@ def disabledext(name): '''find a specific disabled extension from hgext. returns desc''' + try: + from hgext import __index__ + if name in _order: # enabled + return + else: + return gettext(__index__.docs.get(name)) + except ImportError: + pass + paths = _disabledpaths() if name in paths: return _disabledhelp(paths[name])
--- a/mercurial/fileset.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/fileset.py Tue Jun 14 20:43:04 2011 -0500 @@ -27,6 +27,8 @@ keywords = set(['and', 'or', 'not']) +globchars = ".*{}[]?/\\" + def tokenize(program): pos, l = 0, len(program) while pos < l: @@ -56,13 +58,13 @@ pos += 1 else: raise error.ParseError(_("unterminated string"), s) - elif c.isalnum() or c in '.*{}[]?' or ord(c) > 127: + elif c.isalnum() or c in globchars or ord(c) > 127: # gather up a symbol/keyword s = pos pos += 1 while pos < l: # find end of symbol d = program[pos] - if not (d.isalnum() or d in ".*{}[]?," or ord(d) > 127): + if not (d.isalnum() or d in globchars or ord(d) > 127): break pos += 1 sym = program[s:pos] @@ -78,3 +80,63 @@ parse = parser.parser(tokenize, elements).parse +def getstring(x, err): + if x and (x[0] == 'string' or x[0] == 'symbol'): + return x[1] + raise error.ParseError(err) + +def getset(mctx, x): + if not x: + raise error.ParseError(_("missing argument")) + return methods[x[0]](mctx, *x[1:]) + +def stringset(mctx, x): + m = mctx.matcher([x]) + return [f for f in mctx.subset if m(f)] + +def andset(mctx, x, y): + return getset(mctx.narrow(getset(mctx, x)), y) + +def orset(mctx, x, y): + # needs optimizing + xl = getset(mctx, x) + yl = getset(mctx, y) + return xl + [f for f in yl if f not in xl] + +def notset(mctx, x): + s = set(getset(mctx, x)) + return [r for r in mctx.subset if r not in s] + +def listset(mctx, a, b): + raise error.ParseError(_("can't use a list in this context")) + +methods = { + 'string': stringset, + 'symbol': stringset, + 'and': andset, + 'or': orset, + 'list': listset, + 'group': getset, + 'not': notset +} + +class matchctx(object): + def __init__(self, ctx, matchfn, subset=None): + self.ctx = ctx + self.matchfn = matchfn + self.subset = subset + if subset is None: + self.subset = ctx.walk(matchfn([])) # optimize this later + def matcher(self, pattern): + return self.matchfn(pattern) + def filter(self, files): + return [f for f in files if f in self.subset] + def narrow(self, files): + return matchctx(self.ctx, self.matchfn, + self.filter(files)) + +def getfileset(ctx, matchfn, expr): + tree, pos = parse(expr) + if (pos != len(expr)): + raise error.ParseError("invalid token", pos) + return getset(matchctx(ctx, matchfn), tree)
--- a/mercurial/hg.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/hg.py Tue Jun 14 20:43:04 2011 -0500 @@ -70,7 +70,7 @@ 'static-http': statichttprepo, } -def _lookup(path): +def _peerlookup(path): u = util.url(path) scheme = u.scheme or 'file' thing = schemes.get(scheme) or schemes['file'] @@ -83,14 +83,14 @@ '''return true if repo or path is local''' if isinstance(repo, str): try: - return _lookup(repo).islocal(repo) + return _peerlookup(repo).islocal(repo) except AttributeError: return False return repo.local() def repository(ui, path='', create=False): """return a repository object for the specified path""" - repo = _lookup(path).instance(ui, path, create) + repo = _peerlookup(path).instance(ui, path, create) ui = getattr(repo, "ui", ui) for name, module in extensions.extensions(): hook = getattr(module, 'reposetup', None) @@ -98,6 +98,11 @@ hook(ui, repo) return repo +def peer(ui, opts, path, create=False): + '''return a repository peer for the specified path''' + rui = remoteui(ui, opts) + return _peerlookup(path).instance(rui, path, create) + def defaultdest(source): '''return default destination of clone if none is given''' return os.path.basename(os.path.normpath(source)) @@ -169,8 +174,8 @@ continue _update(r, uprev) -def clone(ui, source, dest=None, pull=False, rev=None, update=True, - stream=False, branch=None): +def clone(ui, peeropts, source, dest=None, pull=False, rev=None, + update=True, stream=False, branch=None): """Make a copy of an existing repository. Create a copy of an existing repository in a new directory. The @@ -209,7 +214,7 @@ if isinstance(source, str): origsource = ui.expandpath(source) source, branch = parseurl(origsource, branch) - srcrepo = repository(ui, source) + srcrepo = repository(remoteui(ui, peeropts), source) else: srcrepo = source branch = (None, branch or []) @@ -303,12 +308,13 @@ # we need to re-init the repo after manually copying the data # into it - destrepo = repository(ui, dest) + destrepo = repository(remoteui(ui, peeropts), dest) srcrepo.hook('outgoing', source='clone', node=node.hex(node.nullid)) else: try: - destrepo = repository(ui, dest, create=True) + destrepo = repository(remoteui(ui, peeropts), dest, + create=True) except OSError, inst: if inst.errno == errno.EEXIST: dircleanup.close() @@ -318,7 +324,7 @@ revs = None if rev: - if 'lookup' not in srcrepo.capabilities: + if not srcrepo.capable('lookup'): raise util.Abort(_("src repository does not support " "revision lookup and so doesn't " "support clone by revision")) @@ -423,7 +429,7 @@ and is supposed to contain only code that can't be unified. """ source, branches = parseurl(ui.expandpath(source), opts.get('branch')) - other = repository(remoteui(repo, opts), source) + other = peer(repo, opts, source) ui.status(_('comparing with %s\n') % util.hidepassword(source)) revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev')) @@ -481,7 +487,7 @@ if revs: revs = [repo.lookup(rev) for rev in revs] - other = repository(remoteui(repo, opts), dest) + other = peer(repo, opts, dest) common, outheads = discovery.findcommonoutgoing(repo, other, revs, force=opts.get('force')) o = repo.changelog.findmissing(common, outheads)
--- a/mercurial/hgweb/protocol.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/hgweb/protocol.py Tue Jun 14 20:43:04 2011 -0500 @@ -5,16 +5,17 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -import cgi, cStringIO, zlib, sys, urllib +import cgi, cStringIO, zlib, urllib from mercurial import util, wireproto from common import HTTP_OK HGTYPE = 'application/mercurial-0.1' class webproto(object): - def __init__(self, req): + def __init__(self, req, ui): self.req = req self.response = '' + self.ui = ui def getargs(self, args): knownargs = self._args() data = {} @@ -46,8 +47,12 @@ for s in util.filechunkiter(self.req, limit=length): fp.write(s) def redirect(self): - self.oldio = sys.stdout, sys.stderr - sys.stderr = sys.stdout = cStringIO.StringIO() + self.oldio = self.ui.fout, self.ui.ferr + self.ui.ferr = self.ui.fout = cStringIO.StringIO() + def restore(self): + val = self.ui.fout.getvalue() + self.ui.ferr, self.ui.fout = self.oldio + return val def groupchunks(self, cg): z = zlib.compressobj() while True: @@ -66,7 +71,7 @@ return cmd in wireproto.commands def call(repo, req, cmd): - p = webproto(req) + p = webproto(req, repo.ui) rsp = wireproto.dispatch(repo, p, cmd) if isinstance(rsp, str): req.respond(HTTP_OK, HGTYPE, length=len(rsp)) @@ -75,14 +80,13 @@ req.respond(HTTP_OK, HGTYPE) return rsp.gen elif isinstance(rsp, wireproto.pushres): - val = sys.stdout.getvalue() - sys.stdout, sys.stderr = p.oldio + val = p.restore() req.respond(HTTP_OK, HGTYPE) return ['%d\n%s' % (rsp.res, val)] elif isinstance(rsp, wireproto.pusherr): # drain the incoming bundle req.drain() - sys.stdout, sys.stderr = p.oldio + p.restore() rsp = '0\n%s\n' % rsp.res req.respond(HTTP_OK, HGTYPE, length=len(rsp)) return [rsp]
--- a/mercurial/hgweb/webcommands.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/hgweb/webcommands.py Tue Jun 14 20:43:04 2011 -0500 @@ -271,7 +271,8 @@ diffs = webutil.diffs(web.repo, tmpl, ctx, None, parity, style) parity = paritygen(web.stripecount) - diffstat = webutil.diffstat(tmpl, ctx, parity) + diffstatgen = webutil.diffstatgen(ctx) + diffstat = webutil.diffstat(tmpl, ctx, diffstatgen, parity) return tmpl('changeset', diff=diffs, @@ -286,6 +287,7 @@ desc=ctx.description(), date=ctx.date(), files=files, + diffsummary=lambda **x: webutil.diffsummary(diffstatgen), diffstat=diffstat, archives=web.archivelist(ctx.hex()), tags=webutil.nodetagsdict(web.repo, ctx.node()),
--- a/mercurial/hgweb/webutil.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/hgweb/webutil.py Tue Jun 14 20:43:04 2011 -0500 @@ -8,6 +8,7 @@ import os, copy from mercurial import match, patch, scmutil, error, ui, util +from mercurial.i18n import _ from mercurial.node import hex, nullid def up(p): @@ -211,25 +212,40 @@ yield tmpl('diffblock', parity=parity.next(), lines=prettyprintlines(''.join(block))) -def diffstat(tmpl, ctx, parity): - '''Return a diffstat template for each file in the cset.''' +def diffstatgen(ctx): + '''Generator function that provides the diffstat data.''' stats = patch.diffstatdata(util.iterlines(ctx.diff())) maxname, maxtotal, addtotal, removetotal, binary = patch.diffstatsum(stats) + while True: + yield stats, maxname, maxtotal, addtotal, removetotal, binary - statsdict = {} - if maxtotal > 0: - for filename, adds, removes, isbinary in stats: - total = adds + removes - addpct = (float(adds) / maxtotal) * 100 - removepct = (float(removes) / maxtotal) * 100 - statsdict[filename] = (total, addpct, removepct) +def diffsummary(statgen): + '''Return a short summary of the diff.''' + + stats, maxname, maxtotal, addtotal, removetotal, binary = statgen.next() + return _(' %d files changed, %d insertions(+), %d deletions(-)\n') % ( + len(stats), addtotal, removetotal) + +def diffstat(tmpl, ctx, statgen, parity): + '''Return a diffstat template for each file in the diff.''' + + stats, maxname, maxtotal, addtotal, removetotal, binary = statgen.next() + files = ctx.files() - for f in ctx.files(): - template = f in ctx and 'diffstatlink' or 'diffstatnolink' - total, addpct, removepct = statsdict.get(f, ('', 0, 0)) - yield tmpl(template, node=ctx.hex(), file=f, total=total, - addpct=addpct, removepct=removepct, parity=parity.next()) + def pct(i): + if maxtotal == 0: + return 0 + return (float(i) / maxtotal) * 100 + + fileno = 0 + for filename, adds, removes, isbinary in stats: + template = filename in files and 'diffstatlink' or 'diffstatnolink' + total = adds + removes + fileno += 1 + yield tmpl(template, node=ctx.hex(), file=filename, fileno=fileno, + total=total, addpct=pct(adds), removepct=pct(removes), + parity=parity.next()) class sessionvars(object): def __init__(self, vars, start='?'):
--- a/mercurial/localrepo.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/localrepo.py Tue Jun 14 20:43:04 2011 -0500 @@ -563,7 +563,7 @@ return [(n in nm) for n in nodes] def local(self): - return True + return self def join(self, f): return os.path.join(self.path, f) @@ -1456,7 +1456,7 @@ def changegroupsubset(self, bases, heads, source): """Compute a changegroup consisting of all the nodes that are - descendents of any of the bases and ancestors of any of the heads. + descendants of any of the bases and ancestors of any of the heads. Return a chunkbuffer object whose read() method will return successive changegroup chunks.
--- a/mercurial/patch.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/patch.py Tue Jun 14 20:43:04 2011 -0500 @@ -11,7 +11,8 @@ from i18n import _ from node import hex, nullid, short -import base85, mdiff, scmutil, util, diffhelpers, copies, encoding +import base85, mdiff, scmutil, util, diffhelpers, copies, encoding, error +import context gitre = re.compile('diff --git a/(.*) b/(.*)') @@ -281,6 +282,14 @@ isexec = mode & 0100 self.mode = (islink, isexec) + def copy(self): + other = patchmeta(self.path) + other.oldpath = self.oldpath + other.mode = self.mode + other.op = self.op + other.binary = self.binary + return other + def __repr__(self): return "<patchmeta %s %r>" % (self.op, self.path) @@ -483,7 +492,7 @@ self.files = {} self.created = 0 - def setfile(self, fname, data, mode): + def setfile(self, fname, data, mode, copied=None): if self.opener is None: root = tempfile.mkdtemp(prefix='hg-patch-') self.opener = scmutil.opener(root) @@ -491,27 +500,68 @@ fn = str(self.created) self.opener.write(fn, data) self.created += 1 - self.files[fname] = (fn, mode) + self.files[fname] = (fn, mode, copied) def getfile(self, fname): if fname not in self.files: raise IOError() - fn, mode = self.files[fname] - return self.opener.read(fn), mode + fn, mode, copied = self.files[fname] + return self.opener.read(fn), mode, copied def close(self): if self.opener: shutil.rmtree(self.opener.base) +class repobackend(abstractbackend): + def __init__(self, ui, repo, ctx, store): + super(repobackend, self).__init__(ui) + self.repo = repo + self.ctx = ctx + self.store = store + self.changed = set() + self.removed = set() + self.copied = {} + + def _checkknown(self, fname): + if fname not in self.ctx: + raise PatchError(_('cannot patch %s: file is not tracked') % fname) + + def getfile(self, fname): + try: + fctx = self.ctx[fname] + except error.LookupError: + raise IOError() + flags = fctx.flags() + return fctx.data(), ('l' in flags, 'x' in flags) + + def setfile(self, fname, data, mode, copysource): + if copysource: + self._checkknown(copysource) + if data is None: + data = self.ctx[fname].data() + self.store.setfile(fname, data, mode, copysource) + self.changed.add(fname) + if copysource: + self.copied[fname] = copysource + + def unlink(self, fname): + self._checkknown(fname) + self.removed.add(fname) + + def exists(self, fname): + return fname in self.ctx + + def close(self): + return self.changed | self.removed + # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@') contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)') eolmodes = ['strict', 'crlf', 'lf', 'auto'] class patchfile(object): - def __init__(self, ui, fname, backend, store, mode, create, remove, - eolmode='strict', copysource=None): - self.fname = fname + def __init__(self, ui, gp, backend, store, eolmode='strict'): + self.fname = gp.path self.eolmode = eolmode self.eol = None self.backend = backend @@ -519,17 +569,17 @@ self.lines = [] self.exists = False self.missing = True - self.mode = mode - self.copysource = copysource - self.create = create - self.remove = remove + self.mode = gp.mode + self.copysource = gp.oldpath + self.create = gp.op in ('ADD', 'COPY', 'RENAME') + self.remove = gp.op == 'DELETE' try: - if copysource is None: - data, mode = backend.getfile(fname) + if self.copysource is None: + data, mode = backend.getfile(self.fname) self.exists = True else: - data, mode = store.getfile(copysource) - self.exists = backend.exists(fname) + data, mode = store.getfile(self.copysource)[:2] + self.exists = backend.exists(self.fname) self.missing = False if data: self.lines = data.splitlines(True) @@ -549,7 +599,7 @@ nlines.append(l) self.lines = nlines except IOError: - if create: + if self.create: self.missing = False if self.mode is None: self.mode = (False, False) @@ -1016,14 +1066,7 @@ count -= 1 return path[:i].lstrip(), path[i:].rstrip() -def selectfile(backend, afile_orig, bfile_orig, hunk, strip, gp): - if gp: - # Git patches do not play games. Excluding copies from the - # following heuristic avoids a lot of confusion - fname = pathstrip(gp.path, strip - 1)[1] - create = gp.op in ('ADD', 'COPY', 'RENAME') - remove = gp.op == 'DELETE' - return fname, create, remove +def makepatchmeta(backend, afile_orig, bfile_orig, hunk, strip): nulla = afile_orig == "/dev/null" nullb = bfile_orig == "/dev/null" create = nulla and hunk.starta == 0 and hunk.lena == 0 @@ -1065,7 +1108,12 @@ else: raise PatchError(_("undefined source and destination files")) - return fname, create, remove + gp = patchmeta(fname) + if create: + gp.op = 'ADD' + elif remove: + gp.op = 'DELETE' + return gp def scangitpatch(lr, firstline): """ @@ -1134,7 +1182,7 @@ hunknum += 1 if emitfile: emitfile = False - yield 'file', (afile, bfile, h, gp) + yield 'file', (afile, bfile, h, gp and gp.copy() or None) yield 'hunk', h elif x.startswith('diff --git'): m = gitre.match(x) @@ -1144,14 +1192,14 @@ # scan whole input for git metadata gitpatches = [('a/' + gp.path, 'b/' + gp.path, gp) for gp in scangitpatch(lr, x)] - yield 'git', [g[2] for g in gitpatches + yield 'git', [g[2].copy() for g in gitpatches if g[2].op in ('COPY', 'RENAME')] gitpatches.reverse() afile = 'a/' + m.group(1) bfile = 'b/' + m.group(2) while afile != gitpatches[-1][0] and bfile != gitpatches[-1][1]: gp = gitpatches.pop()[2] - yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp) + yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp.copy()) gp = gitpatches[-1][2] # copy/rename + modify should modify target, not source if gp.op in ('COPY', 'DELETE', 'RENAME', 'ADD') or gp.mode: @@ -1191,23 +1239,22 @@ while gitpatches: gp = gitpatches.pop()[2] - yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp) + yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp.copy()) -def applydiff(ui, fp, changed, backend, store, strip=1, eolmode='strict'): +def applydiff(ui, fp, backend, store, strip=1, eolmode='strict'): """Reads a patch from fp and tries to apply it. - The dict 'changed' is filled in with all of the filenames changed - by the patch. Returns 0 for a clean patch, -1 if any rejects were - found and 1 if there was any fuzz. + Returns 0 for a clean patch, -1 if any rejects were found and 1 if + there was any fuzz. If 'eolmode' is 'strict', the patch content and patched file are read in binary mode. Otherwise, line endings are ignored when patching then normalized according to 'eolmode'. """ - return _applydiff(ui, fp, patchfile, backend, store, changed, strip=strip, + return _applydiff(ui, fp, patchfile, backend, store, strip=strip, eolmode=eolmode) -def _applydiff(ui, fp, patcher, backend, store, changed, strip=1, +def _applydiff(ui, fp, patcher, backend, store, strip=1, eolmode='strict'): def pstrip(p): @@ -1222,51 +1269,45 @@ if not current_file: continue ret = current_file.apply(values) - if ret >= 0: - changed.setdefault(current_file.fname, None) - if ret > 0: - err = 1 + if ret > 0: + err = 1 elif state == 'file': if current_file: rejects += current_file.close() current_file = None afile, bfile, first_hunk, gp = values - copysource = None if gp: path = pstrip(gp.path) + gp.path = pstrip(gp.path) if gp.oldpath: - copysource = pstrip(gp.oldpath) - changed[path] = gp - if gp.op == 'RENAME': - backend.unlink(copysource) - if not first_hunk: - if gp.op == 'DELETE': - backend.unlink(path) - continue - data, mode = None, None - if gp.op in ('RENAME', 'COPY'): - data, mode = store.getfile(copysource) - if gp.mode: - mode = gp.mode - if gp.op == 'ADD': - # Added files without content have no hunk and - # must be created - data = '' - if data or mode: - if (gp.op in ('ADD', 'RENAME', 'COPY') - and backend.exists(path)): - raise PatchError(_("cannot create %s: destination " - "already exists") % path) - backend.setfile(path, data, mode, copysource) + gp.oldpath = pstrip(gp.oldpath) + else: + gp = makepatchmeta(backend, afile, bfile, first_hunk, strip) + if gp.op == 'RENAME': + backend.unlink(gp.oldpath) if not first_hunk: + if gp.op == 'DELETE': + backend.unlink(gp.path) + continue + data, mode = None, None + if gp.op in ('RENAME', 'COPY'): + data, mode = store.getfile(gp.oldpath)[:2] + if gp.mode: + mode = gp.mode + if gp.op == 'ADD': + # Added files without content have no hunk and + # must be created + data = '' + if data or mode: + if (gp.op in ('ADD', 'RENAME', 'COPY') + and backend.exists(gp.path)): + raise PatchError(_("cannot create %s: destination " + "already exists") % gp.path) + backend.setfile(gp.path, data, mode, gp.oldpath) continue try: - mode = gp and gp.mode or None - current_file, create, remove = selectfile( - backend, afile, bfile, first_hunk, strip, gp) - current_file = patcher(ui, current_file, backend, store, mode, - create, remove, eolmode=eolmode, - copysource=copysource) + current_file = patcher(ui, gp, backend, store, + eolmode=eolmode) except PatchError, inst: ui.warn(str(inst) + '\n') current_file = None @@ -1306,7 +1347,7 @@ if line.startswith('patching file '): pf = util.parsepatchoutput(line) printed_file = False - files.setdefault(pf, None) + files.add(pf) elif line.find('with fuzz') >= 0: fuzz = True if not printed_file: @@ -1334,13 +1375,9 @@ util.explainexit(code)[0]) return fuzz -def internalpatch(ui, repo, patchobj, strip, files=None, eolmode='strict', - similarity=0): - """use builtin patch to apply <patchobj> to the working directory. - returns whether patch was applied with fuzz factor.""" - +def patchbackend(ui, backend, patchobj, strip, files=None, eolmode='strict'): if files is None: - files = {} + files = set() if eolmode is None: eolmode = ui.config('patch', 'eol', 'strict') if eolmode.lower() not in eolmodes: @@ -1348,23 +1385,49 @@ eolmode = eolmode.lower() store = filestore() - backend = workingbackend(ui, repo, similarity) try: fp = open(patchobj, 'rb') except TypeError: fp = patchobj try: - ret = applydiff(ui, fp, files, backend, store, strip=strip, + ret = applydiff(ui, fp, backend, store, strip=strip, eolmode=eolmode) finally: if fp != patchobj: fp.close() - files.update(dict.fromkeys(backend.close())) + files.update(backend.close()) store.close() if ret < 0: raise PatchError(_('patch failed to apply')) return ret > 0 +def internalpatch(ui, repo, patchobj, strip, files=None, eolmode='strict', + similarity=0): + """use builtin patch to apply <patchobj> to the working directory. + returns whether patch was applied with fuzz factor.""" + backend = workingbackend(ui, repo, similarity) + return patchbackend(ui, backend, patchobj, strip, files, eolmode) + +def patchrepo(ui, repo, ctx, store, patchobj, strip, files=None, + eolmode='strict'): + backend = repobackend(ui, repo, ctx, store) + return patchbackend(ui, backend, patchobj, strip, files, eolmode) + +def makememctx(repo, parents, text, user, date, branch, files, store, + editor=None): + def getfilectx(repo, memctx, path): + data, (islink, isexec), copied = store.getfile(path) + return context.memfilectx(path, data, islink=islink, isexec=isexec, + copied=copied) + extra = {} + if branch: + extra['branch'] = encoding.fromlocal(branch) + ctx = context.memctx(repo, parents, text, files, getfilectx, user, + date, extra) + if editor: + ctx._text = editor(repo, ctx, []) + return ctx + def patch(ui, repo, patchname, strip=1, files=None, eolmode='strict', similarity=0): """Apply <patchname> to the working directory. @@ -1380,7 +1443,7 @@ """ patcher = ui.config('ui', 'patch') if files is None: - files = {} + files = set() try: if patcher: return _externalpatch(ui, repo, patcher, patchname, strip, @@ -1399,14 +1462,14 @@ if state == 'file': afile, bfile, first_hunk, gp = values if gp: - changed.add(pathstrip(gp.path, strip - 1)[1]) - if gp.op == 'RENAME': - changed.add(pathstrip(gp.oldpath, strip - 1)[1]) - if not first_hunk: - continue - current_file, create, remove = selectfile( - backend, afile, bfile, first_hunk, strip, gp) - changed.add(current_file) + gp.path = pathstrip(gp.path, strip - 1)[1] + if gp.oldpath: + gp.oldpath = pathstrip(gp.oldpath, strip - 1)[1] + else: + gp = makepatchmeta(backend, afile, bfile, first_hunk, strip) + changed.add(gp.path) + if gp.op == 'RENAME': + changed.add(gp.oldpath) elif state not in ('hunk', 'git'): raise util.Abort(_('unsupported parser state: %s') % state) return changed
--- a/mercurial/revlog.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/revlog.py Tue Jun 14 20:43:04 2011 -0500 @@ -491,7 +491,7 @@ return nonodes lowestrev = min([self.rev(n) for n in roots]) else: - roots = [nullid] # Everybody's a descendent of nullid + roots = [nullid] # Everybody's a descendant of nullid lowestrev = nullrev if (lowestrev == nullrev) and (heads is None): # We want _all_ the nodes! @@ -528,7 +528,7 @@ r = self.rev(n) if r >= lowestrev: if n not in ancestors: - # If we are possibly a descendent of one of the roots + # If we are possibly a descendant of one of the roots # and we haven't already been marked as an ancestor ancestors.add(n) # Mark as ancestor # Add non-nullid parents to list of nodes to tag. @@ -562,41 +562,41 @@ lowestrev = nullrev roots = [nullid] # Transform our roots list into a set. - descendents = set(roots) + descendants = set(roots) # Also, keep the original roots so we can filter out roots that aren't # 'real' roots (i.e. are descended from other roots). - roots = descendents.copy() + roots = descendants.copy() # Our topologically sorted list of output nodes. orderedout = [] # Don't start at nullid since we don't want nullid in our output list, # and if nullid shows up in descedents, empty parents will look like - # they're descendents. + # they're descendants. for r in xrange(max(lowestrev, 0), highestrev + 1): n = self.node(r) - isdescendent = False - if lowestrev == nullrev: # Everybody is a descendent of nullid - isdescendent = True - elif n in descendents: - # n is already a descendent - isdescendent = True + isdescendant = False + if lowestrev == nullrev: # Everybody is a descendant of nullid + isdescendant = True + elif n in descendants: + # n is already a descendant + isdescendant = True # This check only needs to be done here because all the roots - # will start being marked is descendents before the loop. + # will start being marked is descendants before the loop. if n in roots: # If n was a root, check if it's a 'real' root. p = tuple(self.parents(n)) - # If any of its parents are descendents, it's not a root. - if (p[0] in descendents) or (p[1] in descendents): + # If any of its parents are descendants, it's not a root. + if (p[0] in descendants) or (p[1] in descendants): roots.remove(n) else: p = tuple(self.parents(n)) - # A node is a descendent if either of its parents are - # descendents. (We seeded the dependents list with the roots + # A node is a descendant if either of its parents are + # descendants. (We seeded the dependents list with the roots # up there, remember?) - if (p[0] in descendents) or (p[1] in descendents): - descendents.add(n) - isdescendent = True - if isdescendent and ((ancestors is None) or (n in ancestors)): - # Only include nodes that are both descendents and ancestors. + if (p[0] in descendants) or (p[1] in descendants): + descendants.add(n) + isdescendant = True + if isdescendant and ((ancestors is None) or (n in ancestors)): + # Only include nodes that are both descendants and ancestors. orderedout.append(n) if (ancestors is not None) and (n in heads): # We're trying to figure out which heads are reachable
--- a/mercurial/revset.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/revset.py Tue Jun 14 20:43:04 2011 -0500 @@ -599,7 +599,7 @@ revs, checkout = hg.addbranchrevs(repo, repo, branches, []) if revs: revs = [repo.lookup(rev) for rev in revs] - other = hg.repository(hg.remoteui(repo, {}), dest) + other = hg.peer(repo, {}, dest) repo.ui.pushbuffer() common, outheads = discovery.findcommonoutgoing(repo, other, onlyheads=revs) repo.ui.popbuffer()
--- a/mercurial/setdiscovery.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/setdiscovery.py Tue Jun 14 20:43:04 2011 -0500 @@ -91,15 +91,27 @@ roundtrips = 0 cl = local.changelog dag = dagutil.revlogdag(cl) - nodes = dag.nodeset() - # early exit if we know all the specified server heads already + # early exit if we know all the specified remote heads already ui.debug("query 1; heads\n") roundtrips += 1 - srvheadhashes = remote.heads() - - ## TODO We might want to request an additional random sample of the server's - ## nodes batched with the heads query here. + ownheads = dag.heads() + sample = ownheads + if remote.local(): + # stopgap until we have a proper localpeer that supports batch() + srvheadhashes = remote.heads() + yesno = remote.known(dag.externalizeall(sample)) + elif remote.capable('batch'): + batch = remote.batch() + srvheadhashesref = batch.heads() + yesnoref = batch.known(dag.externalizeall(sample)) + batch.submit() + srvheadhashes = srvheadhashesref.value + yesno = yesnoref.value + else: + # compatibitity with pre-batch, but post-known remotes during 1.9 devel + srvheadhashes = remote.heads() + sample = [] if cl.tip() == nullid: if srvheadhashes != [nullid]: @@ -115,46 +127,48 @@ ui.note("all remote heads known locally\n") return (srvheadhashes, False, srvheadhashes,) + if sample and util.all(yesno): + ui.note("all local heads known remotely\n") + ownheadhashes = dag.externalizeall(ownheads) + return (ownheadhashes, True, srvheadhashes,) + # full blown discovery - undecided = nodes # own nodes where I don't know if the server knows them + undecided = dag.nodeset() # own nodes where I don't know if remote knows them common = set() # own nodes I know we both know - missing = set() # own nodes I know the server lacks + missing = set() # own nodes I know remote lacks - # treat remote heads as a first implicit sample response + # treat remote heads (and maybe own heads) as a first implicit sample response common.update(dag.ancestorset(srvheads)) undecided.difference_update(common) - # use cheapish initial sample - if common: - ui.debug("taking initial sample\n") - sample = _takefullsample(dag, undecided, size=fullsamplesize) - else: - ui.debug("taking quick initial sample\n") - sample = _takequicksample(dag, nodes, size=initialsamplesize, - initial=True) + + full = False + while undecided: - roundtrips += 1 - ui.progress(_('searching'), roundtrips, unit=_('queries')) - ui.debug("query %i; still undecided: %i, sample size is: %i\n" - % (roundtrips, len(undecided), len(sample))) - # indices between sample and externalized version must match - sample = list(sample) - yesno = remote.known(dag.externalizeall(sample)) + if sample: + commoninsample = set(n for i, n in enumerate(sample) if yesno[i]) + common.update(dag.ancestorset(commoninsample, common)) - while undecided: - commoninsample = set(n for i, n in enumerate(sample) if yesno[i]) - common.update(dag.ancestorset(commoninsample, common)) + missinginsample = [n for i, n in enumerate(sample) if not yesno[i]] + missing.update(dag.descendantset(missinginsample, missing)) - missinginsample = [n for i, n in enumerate(sample) if not yesno[i]] - missing.update(dag.descendantset(missinginsample, missing)) - - undecided.difference_update(missing) - undecided.difference_update(common) + undecided.difference_update(missing) + undecided.difference_update(common) if not undecided: break - ui.note("sampling from both directions\n") - sample = _takefullsample(dag, undecided, size=fullsamplesize) + if full: + ui.note("sampling from both directions\n") + sample = _takefullsample(dag, undecided, size=fullsamplesize) + elif common: + # use cheapish initial sample + ui.debug("taking initial sample\n") + sample = _takefullsample(dag, undecided, size=fullsamplesize) + else: + # use even cheaper initial sample + ui.debug("taking quick initial sample\n") + sample = _takequicksample(dag, undecided, size=initialsamplesize, + initial=True) roundtrips += 1 ui.progress(_('searching'), roundtrips, unit=_('queries')) @@ -163,6 +177,7 @@ # indices between sample and externalized version must match sample = list(sample) yesno = remote.known(dag.externalizeall(sample)) + full = True result = dag.headsetofconnecteds(common) ui.progress(_('searching'), None)
--- a/mercurial/simplemerge.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/simplemerge.py Tue Jun 14 20:43:04 2011 -0500 @@ -211,7 +211,7 @@ Method is as follows: The two sequences align only on regions which match the base - and both descendents. These are found by doing a two-way diff + and both descendants. These are found by doing a two-way diff of each one against the base, and then finding the intersections between those regions. These "sync regions" are by definition unchanged in both and easily dealt with. @@ -315,7 +315,7 @@ mismatch_region = staticmethod(mismatch_region) def find_sync_regions(self): - """Return a list of sync regions, where both descendents match the base. + """Return a list of sync regions, where both descendants match the base. Generates a list of (base1, base2, a1, a2, b1, b2). There is always a zero-length sync region at the end of all the files.
--- a/mercurial/sshserver.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/sshserver.py Tue Jun 14 20:43:04 2011 -0500 @@ -14,11 +14,11 @@ self.ui = ui self.repo = repo self.lock = None - self.fin = sys.stdin - self.fout = sys.stdout + self.fin = ui.fin + self.fout = ui.fout hook.redirect(True) - sys.stdout = sys.stderr + ui.fout = repo.ui.fout = ui.ferr # Prevent insertion/deletion of CRs util.setbinary(self.fin)
--- a/mercurial/sslutil.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/sslutil.py Tue Jun 14 20:43:04 2011 -0500 @@ -18,6 +18,8 @@ except ImportError: CERT_REQUIRED = 2 + import socket, httplib + def ssl_wrap_socket(sock, key_file, cert_file, cert_reqs=CERT_REQUIRED, ca_certs=None): if ca_certs:
--- a/mercurial/subrepo.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/subrepo.py Tue Jun 14 20:43:04 2011 -0500 @@ -437,14 +437,14 @@ if revision not in self._repo: self._repo._subsource = source srcurl = _abssource(self._repo) - other = hg.repository(self._repo.ui, srcurl) + other = hg.peer(self._repo.ui, {}, srcurl) if len(self._repo) == 0: self._repo.ui.status(_('cloning subrepo %s from %s\n') % (subrelpath(self), srcurl)) parentrepo = self._repo._subparent shutil.rmtree(self._repo.root) - other, self._repo = hg.clone(self._repo._subparent.ui, other, - self._repo.root, update=False) + other, self._repo = hg.clone(self._repo._subparent.ui, {}, other, + self._repo.root, update=False) self._initrepo(parentrepo, source, create=True) else: self._repo.ui.status(_('pulling subrepo %s from %s\n') @@ -495,7 +495,7 @@ dsturl = _abssource(self._repo, True) self._repo.ui.status(_('pushing subrepo %s to %s\n') % (subrelpath(self), dsturl)) - other = hg.repository(self._repo.ui, dsturl) + other = hg.peer(self._repo.ui, {}, dsturl) return self._repo.push(other, force) def outgoing(self, ui, dest, opts):
--- a/mercurial/templates/coal/map Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/templates/coal/map Tue Jun 14 20:43:04 2011 -0500 @@ -23,6 +23,8 @@ filenodelink = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> ' filenolink = '{file|escape} ' fileellipses = '...' +diffstatlink = ../paper/diffstat.tmpl +diffstatnolink = ../paper/diffstat.tmpl changelogentry = ../paper/shortlogentry.tmpl searchentry = ../paper/shortlogentry.tmpl changeset = ../paper/changeset.tmpl
--- a/mercurial/templates/paper/changeset.tmpl Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/templates/paper/changeset.tmpl Tue Jun 14 20:43:04 2011 -0500 @@ -62,6 +62,18 @@ <th class="files">files</th> <td class="files">{files}</td> </tr> +<tr> + <th class="diffstat">diffstat</th> + <td class="diffstat"> + {diffsummary} + <a id="diffstatexpand" href="javascript:showDiffstat()"/>[<tt>+</tt>]</a> + <div id="diffstatdetails" style="display:none;"> + <a href="javascript:hideDiffstat()"/>[<tt>-</tt>]</a> + <p> + <table>{diffstat}</table> + </div> + </td> +</tr> </table> <div class="overflow">
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/templates/paper/diffstat.tmpl Tue Jun 14 20:43:04 2011 -0500 @@ -0,0 +1,8 @@ + <tr class="parity{parity}"> + <td class="diffstat-file"><a href="#l{fileno}.1">{file|escape}</a></td> + <td class="diffstat-total" align="right">{total}</td> + <td class="diffstat-graph"> + <span class="diffstat-add" style="width:{addpct}%;"> </span> + <span class="diffstat-remove" style="width:{removepct}%;"> </span> + </td> + </tr>
--- a/mercurial/templates/paper/map Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/templates/paper/map Tue Jun 14 20:43:04 2011 -0500 @@ -22,6 +22,8 @@ filenodelink = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> ' filenolink = '{file|escape} ' fileellipses = '...' +diffstatlink = diffstat.tmpl +diffstatnolink = diffstat.tmpl changelogentry = shortlogentry.tmpl searchentry = shortlogentry.tmpl changeset = changeset.tmpl
--- a/mercurial/templates/static/mercurial.js Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/templates/static/mercurial.js Tue Jun 14 20:43:04 2011 -0500 @@ -2,6 +2,7 @@ // // Rendering of branch DAGs on the client side // Display of elapsed time +// Show or hide diffstat // // Copyright 2008 Dirkjan Ochtman <dirkjan AT ochtman DOT nl> // Copyright 2006 Alexander Schremmer <alex AT alexanderweb DOT de> @@ -218,3 +219,13 @@ } } })(document, RegExp, Math, isNaN, Date, false, true) + +function showDiffstat() { + document.getElementById('diffstatdetails').style.display = 'inline'; + document.getElementById('diffstatexpand').style.display = 'none'; +} + +function hideDiffstat() { + document.getElementById('diffstatdetails').style.display = 'none'; + document.getElementById('diffstatexpand').style.display = 'inline'; +}
--- a/mercurial/templates/static/style-coal.css Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/templates/static/style-coal.css Tue Jun 14 20:43:04 2011 -0500 @@ -103,6 +103,26 @@ .minusline { color: #dc143c; } /* crimson */ .atline { color: purple; } +.diffstat-file { + white-space: nowrap; + font-size: 90%; +} +.diffstat-total { + white-space: nowrap; + font-size: 90%; +} +.diffstat-graph { + width: 100%; +} +.diffstat-add { + background-color: green; + float: left; +} +.diffstat-remove { + background-color: red; + float: left; +} + .navigate { text-align: right; font-size: 60%;
--- a/mercurial/templates/static/style-paper.css Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/templates/static/style-paper.css Tue Jun 14 20:43:04 2011 -0500 @@ -94,6 +94,26 @@ .minusline { color: #dc143c; } /* crimson */ .atline { color: purple; } +.diffstat-file { + white-space: nowrap; + font-size: 90%; +} +.diffstat-total { + white-space: nowrap; + font-size: 90%; +} +.diffstat-graph { + width: 100%; +} +.diffstat-add { + background-color: green; + float: left; +} +.diffstat-remove { + background-color: red; + float: left; +} + .navigate { text-align: right; font-size: 60%;
--- a/mercurial/ui.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/ui.py Tue Jun 14 20:43:04 2011 -0500 @@ -21,6 +21,10 @@ self._trustgroups = set() if src: + self.fout = src.fout + self.ferr = src.ferr + self.fin = src.fin + self._tcfg = src._tcfg.copy() self._ucfg = src._ucfg.copy() self._ocfg = src._ocfg.copy() @@ -29,6 +33,10 @@ self.environ = src.environ self.fixconfig() else: + self.fout = sys.stdout + self.ferr = sys.stderr + self.fin = sys.stdin + # shared read-only environment self.environ = os.environ # we always trust global config files @@ -435,26 +443,26 @@ self._buffers[-1].extend([str(a) for a in args]) else: for a in args: - sys.stdout.write(str(a)) + self.fout.write(str(a)) def write_err(self, *args, **opts): try: - if not getattr(sys.stdout, 'closed', False): - sys.stdout.flush() + if not getattr(self.fout, 'closed', False): + self.fout.flush() for a in args: - sys.stderr.write(str(a)) + self.ferr.write(str(a)) # stderr may be buffered under win32 when redirected to files, # including stdout. - if not getattr(sys.stderr, 'closed', False): - sys.stderr.flush() + if not getattr(self.ferr, 'closed', False): + self.ferr.flush() except IOError, inst: if inst.errno not in (errno.EPIPE, errno.EIO): raise def flush(self): - try: sys.stdout.flush() + try: self.fout.flush() except: pass - try: sys.stderr.flush() + try: self.ferr.flush() except: pass def interactive(self): @@ -475,7 +483,7 @@ if i is None: # some environments replace stdin without implementing isatty # usually those are non-interactive - return util.isatty(sys.stdin) + return util.isatty(self.fin) return i @@ -513,12 +521,12 @@ if i is None: # some environments replace stdout without implementing isatty # usually those are non-interactive - return util.isatty(sys.stdout) + return util.isatty(self.fout) return i def _readline(self, prompt=''): - if util.isatty(sys.stdin): + if util.isatty(self.fin): try: # magically add command line editing support, where # available @@ -528,7 +536,14 @@ # windows sometimes raises something other than ImportError except Exception: pass + + # instead of trying to emulate raw_input, swap our in/out + # with sys.stdin/out + old = sys.stdout, sys.stdin + sys.stdout, sys.stdin = self.fout, self.fin line = raw_input(prompt) + sys.stdout, sys.stdin = old + # When stdin is in binary mode on Windows, it can cause # raw_input() to emit an extra trailing carriage return if os.linesep == '\r\n' and line and line[-1] == '\r':
--- a/mercurial/wireproto.py Tue Jun 14 00:31:56 2011 +0400 +++ b/mercurial/wireproto.py Tue Jun 14 20:43:04 2011 -0500 @@ -12,6 +12,110 @@ import repo, error, encoding, util, store import pushkey as pushkeymod +# abstract batching support + +class future(object): + '''placeholder for a value to be set later''' + def set(self, value): + if hasattr(self, 'value'): + raise error.RepoError("future is already set") + self.value = value + +class batcher(object): + '''base class for batches of commands submittable in a single request + + All methods invoked on instances of this class are simply queued and return a + a future for the result. Once you call submit(), all the queued calls are + performed and the results set in their respective futures. + ''' + def __init__(self): + self.calls = [] + def __getattr__(self, name): + def call(*args, **opts): + resref = future() + self.calls.append((name, args, opts, resref,)) + return resref + return call + def submit(self): + pass + +class localbatch(batcher): + '''performs the queued calls directly''' + def __init__(self, local): + batcher.__init__(self) + self.local = local + def submit(self): + for name, args, opts, resref in self.calls: + resref.set(getattr(self.local, name)(*args, **opts)) + +class remotebatch(batcher): + '''batches the queued calls; uses as few roundtrips as possible''' + def __init__(self, remote): + '''remote must support _submitbatch(encbatch) and _submitone(op, encargs)''' + batcher.__init__(self) + self.remote = remote + def submit(self): + req, rsp = [], [] + for name, args, opts, resref in self.calls: + mtd = getattr(self.remote, name) + if hasattr(mtd, 'batchable'): + batchable = getattr(mtd, 'batchable')(mtd.im_self, *args, **opts) + encargsorres, encresref = batchable.next() + if encresref: + req.append((name, encargsorres,)) + rsp.append((batchable, encresref, resref,)) + else: + resref.set(encargsorres) + else: + if req: + self._submitreq(req, rsp) + req, rsp = [], [] + resref.set(mtd(*args, **opts)) + if req: + self._submitreq(req, rsp) + def _submitreq(self, req, rsp): + encresults = self.remote._submitbatch(req) + for encres, r in zip(encresults, rsp): + batchable, encresref, resref = r + encresref.set(encres) + resref.set(batchable.next()) + +def batchable(f): + '''annotation for batchable methods + + Such methods must implement a coroutine as follows: + + @batchable + def sample(self, one, two=None): + # Handle locally computable results first: + if not one: + yield "a local result", None + # Build list of encoded arguments suitable for your wire protocol: + encargs = [('one', encode(one),), ('two', encode(two),)] + # Create future for injection of encoded result: + encresref = future() + # Return encoded arguments and future: + yield encargs, encresref + # Assuming the future to be filled with the result from the batched request + # now. Decode it: + yield decode(encresref.value) + + The decorator returns a function which wraps this coroutine as a plain method, + but adds the original method as an attribute called "batchable", which is + used by remotebatch to split the call into separate encoding and decoding + phases. + ''' + def plain(*args, **opts): + batchable = f(*args, **opts) + encargsorres, encresref = batchable.next() + if not encresref: + return encargsorres # a local result in this case + self = args[0] + encresref.set(self._submitone(f.func_name, encargsorres)) + return batchable.next() + setattr(plain, 'batchable', f) + return plain + # list of nodes encoding / decoding def decodelist(l, sep=' '): @@ -22,34 +126,77 @@ def encodelist(l, sep=' '): return sep.join(map(hex, l)) +# batched call argument encoding + +def escapearg(plain): + return (plain + .replace(':', '::') + .replace(',', ':,') + .replace(';', ':;') + .replace('=', ':=')) + +def unescapearg(escaped): + return (escaped + .replace(':=', '=') + .replace(':;', ';') + .replace(':,', ',') + .replace('::', ':')) + # client side +def todict(**args): + return args + class wirerepository(repo.repository): + + def batch(self): + return remotebatch(self) + def _submitbatch(self, req): + cmds = [] + for op, argsdict in req: + args = ','.join('%s=%s' % p for p in argsdict.iteritems()) + cmds.append('%s %s' % (op, args)) + rsp = self._call("batch", cmds=';'.join(cmds)) + return rsp.split(';') + def _submitone(self, op, args): + return self._call(op, **args) + + @batchable def lookup(self, key): self.requirecap('lookup', _('look up remote revision')) - d = self._call("lookup", key=encoding.fromlocal(key)) + f = future() + yield todict(key=encoding.fromlocal(key)), f + d = f.value success, data = d[:-1].split(" ", 1) if int(success): - return bin(data) + yield bin(data) self._abort(error.RepoError(data)) + @batchable def heads(self): - d = self._call("heads") + f = future() + yield {}, f + d = f.value try: - return decodelist(d[:-1]) + yield decodelist(d[:-1]) except ValueError: self._abort(error.ResponseError(_("unexpected response:"), d)) + @batchable def known(self, nodes): - n = encodelist(nodes) - d = self._call("known", nodes=n) + f = future() + yield todict(nodes=encodelist(nodes)), f + d = f.value try: - return [bool(int(f)) for f in d] + yield [bool(int(f)) for f in d] except ValueError: self._abort(error.ResponseError(_("unexpected response:"), d)) + @batchable def branchmap(self): - d = self._call("branchmap") + f = future() + yield {}, f + d = f.value try: branchmap = {} for branchpart in d.splitlines(): @@ -57,7 +204,7 @@ branchname = encoding.tolocal(urllib.unquote(branchname)) branchheads = decodelist(branchheads) branchmap[branchname] = branchheads - return branchmap + yield branchmap except TypeError: self._abort(error.ResponseError(_("unexpected response:"), d)) @@ -82,30 +229,35 @@ self._abort(error.ResponseError(_("unexpected response:"), d)) return r + @batchable def pushkey(self, namespace, key, old, new): if not self.capable('pushkey'): - return False - d = self._call("pushkey", - namespace=encoding.fromlocal(namespace), - key=encoding.fromlocal(key), - old=encoding.fromlocal(old), - new=encoding.fromlocal(new)) + yield False, None + f = future() + yield todict(namespace=encoding.fromlocal(namespace), + key=encoding.fromlocal(key), + old=encoding.fromlocal(old), + new=encoding.fromlocal(new)), f + d = f.value try: d = bool(int(d)) except ValueError: raise error.ResponseError( _('push failed (unexpected response):'), d) - return d + yield d + @batchable def listkeys(self, namespace): if not self.capable('pushkey'): - return {} - d = self._call("listkeys", namespace=encoding.fromlocal(namespace)) + yield {}, None + f = future() + yield todict(namespace=encoding.fromlocal(namespace)), f + d = f.value r = {} for l in d.splitlines(): k, v = l.split('\t') r[encoding.tolocal(k)] = encoding.tolocal(v) - return r + yield r def stream_out(self): return self._callstream('stream_out') @@ -198,6 +350,34 @@ % (cmd, ",".join(others))) return opts +def batch(repo, proto, cmds, others): + res = [] + for pair in cmds.split(';'): + op, args = pair.split(' ', 1) + vals = {} + for a in args.split(','): + if a: + n, v = a.split('=') + vals[n] = unescapearg(v) + func, spec = commands[op] + if spec: + keys = spec.split() + data = {} + for k in keys: + if k == '*': + star = {} + for key in vals.keys(): + if key not in keys: + star[key] = vals[key] + data['*'] = star + else: + data[k] = vals[k] + result = func(repo, proto, *[data[k] for k in keys]) + else: + result = func(repo, proto) + res.append(escapearg(result)) + return ';'.join(res) + def between(repo, proto, pairs): pairs = [decodelist(p, '-') for p in pairs.split(" ")] r = [] @@ -223,7 +403,7 @@ def capabilities(repo, proto): caps = ('lookup changegroupsubset branchmap pushkey known getbundle ' - 'unbundlehash').split() + 'unbundlehash batch').split() if _allowstream(repo.ui): requiredformats = repo.requirements & repo.supportedformats # if our local revlogs are just revlogv1, add 'stream' cap @@ -402,6 +582,7 @@ os.unlink(tempname) commands = { + 'batch': (batch, 'cmds *'), 'between': (between, 'pairs'), 'branchmap': (branchmap, ''), 'branches': (branches, 'nodes'),
--- a/setup.py Tue Jun 14 00:31:56 2011 +0400 +++ b/setup.py Tue Jun 14 20:43:04 2011 -0500 @@ -56,7 +56,7 @@ import shutil import tempfile from distutils import log -from distutils.core import setup, Extension +from distutils.core import setup, Command, Extension from distutils.dist import Distribution from distutils.command.build import build from distutils.command.build_ext import build_ext @@ -64,7 +64,7 @@ from distutils.command.install_scripts import install_scripts from distutils.spawn import spawn, find_executable from distutils.ccompiler import new_compiler -from distutils.errors import CCompilerError +from distutils.errors import CCompilerError, DistutilsExecError from distutils.sysconfig import get_python_inc from distutils.version import StrictVersion @@ -260,6 +260,34 @@ else: yield module +class buildhgextindex(Command): + description = 'generate prebuilt index of hgext (for frozen package)' + user_options = [] + _indexfilename = 'hgext/__index__.py' + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + if os.path.exists(self._indexfilename): + os.unlink(self._indexfilename) + + # here no extension enabled, disabled() lists up everything + code = ('import pprint; from mercurial import extensions; ' + 'pprint.pprint(extensions.disabled())') + out, err = runcmd([sys.executable, '-c', code], env) + if err: + raise DistutilsExecError(err) + + f = open(self._indexfilename, 'w') + f.write('# this file is autogenerated by setup.py\n') + f.write('docs = ') + f.write(out) + f.close() + class hginstallscripts(install_scripts): ''' This is a specialization of install_scripts that replaces the @LIBDIR@ with @@ -309,6 +337,7 @@ cmdclass = {'build_mo': hgbuildmo, 'build_ext': hgbuildext, 'build_py': hgbuildpy, + 'build_hgextindex': buildhgextindex, 'install_scripts': hginstallscripts} packages = ['mercurial', 'mercurial.hgweb', @@ -373,6 +402,8 @@ {'script':'hg', 'copyright':'Copyright (C) 2005-2010 Matt Mackall and others', 'product_version':version}] + # sub command of 'build' because 'py2exe' does not handle sub_commands + build.sub_commands.insert(0, ('build_hgextindex', None)) if os.name == 'nt': # Windows binary file versions for exe/dll files must have the
--- a/tests/hghave Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/hghave Tue Jun 14 20:43:04 2011 -0500 @@ -52,7 +52,7 @@ def has_mtn(): return matchoutput('mtn --version', r'monotone', True) and not matchoutput( - 'mtn --version', r'monotone 0\.(\d|[12]\d|3[01])[^\d]', True) + 'mtn --version', r'monotone 0\.', True) def has_eol_in_paths(): try:
--- a/tests/run-tests.py Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/run-tests.py Tue Jun 14 20:43:04 2011 -0500 @@ -741,6 +741,7 @@ skip("doesn't exist") return None else: + vlog('# Test file', test, 'not supported, ignoring') return None # not a supported test, don't record if not (options.whitelisted and test in options.whitelisted):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-batching.py Tue Jun 14 20:43:04 2011 -0500 @@ -0,0 +1,175 @@ +# test-batching.py - tests for transparent command batching +# +# Copyright 2011 Peter Arrenbrecht <peter@arrenbrecht.ch> +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +from mercurial.wireproto import localbatch, remotebatch, batchable, future + +# equivalent of repo.repository +class thing(object): + def hello(self): + return "Ready." + +# equivalent of localrepo.localrepository +class localthing(thing): + def foo(self, one, two=None): + if one: + return "%s and %s" % (one, two,) + return "Nope" + def bar(self, b, a): + return "%s und %s" % (b, a,) + def greet(self, name=None): + return "Hello, %s" % name + def batch(self): + '''Support for local batching.''' + return localbatch(self) + +# usage of "thing" interface +def use(it): + + # Direct call to base method shared between client and server. + print it.hello() + + # Direct calls to proxied methods. They cause individual roundtrips. + print it.foo("Un", two="Deux") + print it.bar("Eins", "Zwei") + + # Batched call to a couple of (possibly proxied) methods. + batch = it.batch() + # The calls return futures to eventually hold results. + foo = batch.foo(one="One", two="Two") + foo2 = batch.foo(None) + bar = batch.bar("Eins", "Zwei") + # We can call non-batchable proxy methods, but the break the current batch + # request and cause additional roundtrips. + greet = batch.greet(name="John Smith") + # We can also add local methods into the mix, but they break the batch too. + hello = batch.hello() + bar2 = batch.bar(b="Uno", a="Due") + # Only now are all the calls executed in sequence, with as few roundtrips + # as possible. + batch.submit() + # After the call to submit, the futures actually contain values. + print foo.value + print foo2.value + print bar.value + print greet.value + print hello.value + print bar2.value + +# local usage +mylocal = localthing() +print +print "== Local" +use(mylocal) + +# demo remoting; mimicks what wireproto and HTTP/SSH do + +# shared + +def escapearg(plain): + return (plain + .replace(':', '::') + .replace(',', ':,') + .replace(';', ':;') + .replace('=', ':=')) +def unescapearg(escaped): + return (escaped + .replace(':=', '=') + .replace(':;', ';') + .replace(':,', ',') + .replace('::', ':')) + +# server side + +# equivalent of wireproto's global functions +class server: + def __init__(self, local): + self.local = local + def _call(self, name, args): + args = dict(arg.split('=', 1) for arg in args) + return getattr(self, name)(**args) + def perform(self, req): + print "REQ:", req + name, args = req.split('?', 1) + args = args.split('&') + vals = dict(arg.split('=', 1) for arg in args) + res = getattr(self, name)(**vals) + print " ->", res + return res + def batch(self, cmds): + res = [] + for pair in cmds.split(';'): + name, args = pair.split(':', 1) + vals = {} + for a in args.split(','): + if a: + n, v = a.split('=') + vals[n] = unescapearg(v) + res.append(escapearg(getattr(self, name)(**vals))) + return ';'.join(res) + def foo(self, one, two): + return mangle(self.local.foo(unmangle(one), unmangle(two))) + def bar(self, b, a): + return mangle(self.local.bar(unmangle(b), unmangle(a))) + def greet(self, name): + return mangle(self.local.greet(unmangle(name))) +myserver = server(mylocal) + +# local side + +# equivalent of wireproto.encode/decodelist, that is, type-specific marshalling +# here we just transform the strings a bit to check we're properly en-/decoding +def mangle(s): + return ''.join(chr(ord(c) + 1) for c in s) +def unmangle(s): + return ''.join(chr(ord(c) - 1) for c in s) + +# equivalent of wireproto.wirerepository and something like http's wire format +class remotething(thing): + def __init__(self, server): + self.server = server + def _submitone(self, name, args): + req = name + '?' + '&'.join(['%s=%s' % (n, v) for n, v in args]) + return self.server.perform(req) + def _submitbatch(self, cmds): + req = [] + for name, args in cmds: + args = ','.join(n + '=' + escapearg(v) for n, v in args) + req.append(name + ':' + args) + req = ';'.join(req) + res = self._submitone('batch', [('cmds', req,)]) + return res.split(';') + + def batch(self): + return remotebatch(self) + + @batchable + def foo(self, one, two=None): + if not one: + yield "Nope", None + encargs = [('one', mangle(one),), ('two', mangle(two),)] + encresref = future() + yield encargs, encresref + yield unmangle(encresref.value) + + @batchable + def bar(self, b, a): + encresref = future() + yield [('b', mangle(b),), ('a', mangle(a),)], encresref + yield unmangle(encresref.value) + + # greet is coded directly. It therefore does not support batching. If it + # does appear in a batch, the batch is split around greet, and the call to + # greet is done in its own roundtrip. + def greet(self, name=None): + return unmangle(self._submitone('greet', [('name', mangle(name),)])) + +# demo remote usage + +myproxy = remotething(myserver) +print +print "== Remote" +use(myproxy)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-batching.py.out Tue Jun 14 20:43:04 2011 -0500 @@ -0,0 +1,32 @@ + +== Local +Ready. +Un and Deux +Eins und Zwei +One and Two +Nope +Eins und Zwei +Hello, John Smith +Ready. +Uno und Due + +== Remote +Ready. +REQ: foo?one=Vo&two=Efvy + -> Vo!boe!Efvy +Un and Deux +REQ: bar?b=Fjot&a=[xfj + -> Fjot!voe![xfj +Eins und Zwei +REQ: batch?cmds=foo:one=Pof,two=Uxp;bar:b=Fjot,a=[xfj + -> Pof!boe!Uxp;Fjot!voe![xfj +REQ: greet?name=Kpio!Tnjui + -> Ifmmp-!Kpio!Tnjui +REQ: batch?cmds=bar:b=Vop,a=Evf + -> Vop!voe!Evf +One and Two +Nope +Eins und Zwei +Hello, John Smith +Ready. +Uno und Due
--- a/tests/test-clone.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-clone.t Tue Jun 14 20:43:04 2011 -0500 @@ -433,7 +433,7 @@ > from mercurial import ui, hg > myui = ui.ui() > repo = hg.repository(myui, 'a') - > hg.clone(myui, repo, dest="ua") + > hg.clone(myui, {}, repo, dest="ua") > EOF $ python simpleclone.py @@ -446,7 +446,7 @@ > from mercurial import ui, hg > myui = ui.ui() > repo = hg.repository(myui, 'a') - > hg.clone(myui, repo, dest="ua", branch=["stable",]) + > hg.clone(myui, {}, repo, dest="ua", branch=["stable",]) > EOF $ python branchclone.py
--- a/tests/test-confused-revert.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-confused-revert.t Tue Jun 14 20:43:04 2011 -0500 @@ -59,7 +59,8 @@ Revert should fail: $ hg revert - abort: uncommitted merge - use "hg update", see "hg help revert" + abort: no files or directories specified + (use --all to revert all files) [255] Revert should be ok now:
--- a/tests/test-convert-cvs-detectmerge.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-convert-cvs-detectmerge.t Tue Jun 14 20:43:04 2011 -0500 @@ -16,6 +16,7 @@ $ cvsci() > { + > sleep 1 > cvs -f ci "$@" > /dev/null > } @@ -53,7 +54,6 @@ modify file1 on branch v1_0 $ cvscall -Q update -rv1_0 - $ sleep 1 $ echo "change" >> file1 $ cvsci -m"add text" cvs commit: Examining . @@ -96,7 +96,6 @@ this will create rev 1.3 change on trunk to backport - $ sleep 1 $ echo "backport me" >> file1 $ cvsci -m"add other text" file1 $ cvscall log file1 @@ -150,7 +149,6 @@ fix bug on v1_1, merge to trunk with error $ cvscall -Q update -rv1_1 - $ sleep 1 $ echo "merge forward" >> file1 $ cvscall -Q tag unmerged $ cvsci -m"fix file1"
--- a/tests/test-convert-cvs-synthetic.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-convert-cvs-synthetic.t Tue Jun 14 20:43:04 2011 -0500 @@ -23,6 +23,7 @@ $ cvsci() > { + > sleep 1 > cvs -f ci "$@" >/dev/null > } $ cvscall -d "$CVSROOT" init
--- a/tests/test-debugcomplete.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-debugcomplete.t Tue Jun 14 20:43:04 2011 -0500 @@ -245,7 +245,7 @@ heads: rev, topo, active, closed, style, template help: extension, command identify: rev, num, id, branch, tags, bookmarks - import: strip, base, force, no-commit, exact, import-branch, message, logfile, date, user, similarity + import: strip, base, force, no-commit, bypass, exact, import-branch, message, logfile, date, user, similarity incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos locate: rev, print0, fullpath, include, exclude manifest: rev, all
--- a/tests/test-git-import.t Tue Jun 14 00:31:56 2011 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,468 +0,0 @@ - - $ hg init - -New file: - - $ hg import -d "1000000 0" -mnew - <<EOF - > diff --git a/new b/new - > new file mode 100644 - > index 0000000..7898192 - > --- /dev/null - > +++ b/new - > @@ -0,0 +1 @@ - > +a - > EOF - applying patch from stdin - - $ hg tip -q - 0:ae3ee40d2079 - -New empty file: - - $ hg import -d "1000000 0" -mempty - <<EOF - > diff --git a/empty b/empty - > new file mode 100644 - > EOF - applying patch from stdin - - $ hg tip -q - 1:ab199dc869b5 - - $ hg locate empty - empty - -chmod +x: - - $ hg import -d "1000000 0" -msetx - <<EOF - > diff --git a/new b/new - > old mode 100644 - > new mode 100755 - > EOF - applying patch from stdin - - $ hg tip -q - 2:3a34410f282e - - $ test -x new - -Copy: - - $ hg import -d "1000000 0" -mcopy - <<EOF - > diff --git a/new b/copy - > old mode 100755 - > new mode 100644 - > similarity index 100% - > copy from new - > copy to copy - > diff --git a/new b/copyx - > similarity index 100% - > copy from new - > copy to copyx - > EOF - applying patch from stdin - - $ hg tip -q - 3:37bacb7ca14d - - $ if "$TESTDIR/hghave" -q execbit; then - > test -f copy -a ! -x copy || echo bad - > test -x copyx || echo bad - > else - > test -f copy || echo bad - > fi - - $ cat copy - a - - $ hg cat copy - a - -Rename: - - $ hg import -d "1000000 0" -mrename - <<EOF - > diff --git a/copy b/rename - > similarity index 100% - > rename from copy - > rename to rename - > EOF - applying patch from stdin - - $ hg tip -q - 4:47b81a94361d - - $ hg locate - copyx - empty - new - rename - -Delete: - - $ hg import -d "1000000 0" -mdelete - <<EOF - > diff --git a/copyx b/copyx - > deleted file mode 100755 - > index 7898192..0000000 - > --- a/copyx - > +++ /dev/null - > @@ -1 +0,0 @@ - > -a - > EOF - applying patch from stdin - - $ hg tip -q - 5:d9b001d98336 - - $ hg locate - empty - new - rename - - $ test -f copyx - [1] - -Regular diff: - - $ hg import -d "1000000 0" -mregular - <<EOF - > diff --git a/rename b/rename - > index 7898192..72e1fe3 100644 - > --- a/rename - > +++ b/rename - > @@ -1 +1,5 @@ - > a - > +a - > +a - > +a - > +a - > EOF - applying patch from stdin - - $ hg tip -q - 6:ebe901e7576b - -Copy and modify: - - $ hg import -d "1000000 0" -mcopymod - <<EOF - > diff --git a/rename b/copy2 - > similarity index 80% - > copy from rename - > copy to copy2 - > index 72e1fe3..b53c148 100644 - > --- a/rename - > +++ b/copy2 - > @@ -1,5 +1,5 @@ - > a - > a - > -a - > +b - > a - > a - > EOF - applying patch from stdin - - $ hg tip -q - 7:18f368958ecd - - $ hg cat copy2 - a - a - b - a - a - -Rename and modify: - - $ hg import -d "1000000 0" -mrenamemod - <<EOF - > diff --git a/copy2 b/rename2 - > similarity index 80% - > rename from copy2 - > rename to rename2 - > index b53c148..8f81e29 100644 - > --- a/copy2 - > +++ b/rename2 - > @@ -1,5 +1,5 @@ - > a - > a - > b - > -a - > +c - > a - > EOF - applying patch from stdin - - $ hg tip -q - 8:c32b0d7e6f44 - - $ hg locate copy2 - [1] - $ hg cat rename2 - a - a - b - c - a - -One file renamed multiple times: - - $ hg import -d "1000000 0" -mmultirenames - <<EOF - > diff --git a/rename2 b/rename3 - > rename from rename2 - > rename to rename3 - > diff --git a/rename2 b/rename3-2 - > rename from rename2 - > rename to rename3-2 - > EOF - applying patch from stdin - - $ hg tip -q - 9:034a6bf95330 - - $ hg log -vr. --template '{rev} {files} / {file_copies}\n' - 9 rename2 rename3 rename3-2 / rename3 (rename2)rename3-2 (rename2) - - $ hg locate rename2 rename3 rename3-2 - rename3 - rename3-2 - - $ hg cat rename3 - a - a - b - c - a - - $ hg cat rename3-2 - a - a - b - c - a - - $ echo foo > foo - $ hg add foo - $ hg ci -m 'add foo' - -Binary files and regular patch hunks: - - $ hg import -d "1000000 0" -m binaryregular - <<EOF - > diff --git a/binary b/binary - > new file mode 100644 - > index 0000000000000000000000000000000000000000..593f4708db84ac8fd0f5cc47c634f38c013fe9e4 - > GIT binary patch - > literal 4 - > Lc\${NkU|;|M00aO5 - > - > diff --git a/foo b/foo2 - > rename from foo - > rename to foo2 - > EOF - applying patch from stdin - - $ hg tip -q - 11:c39bce63e786 - - $ cat foo2 - foo - - $ hg manifest --debug | grep binary - 045c85ba38952325e126c70962cc0f9d9077bc67 644 binary - -Multiple binary files: - - $ hg import -d "1000000 0" -m multibinary - <<EOF - > diff --git a/mbinary1 b/mbinary1 - > new file mode 100644 - > index 0000000000000000000000000000000000000000..593f4708db84ac8fd0f5cc47c634f38c013fe9e4 - > GIT binary patch - > literal 4 - > Lc\${NkU|;|M00aO5 - > - > diff --git a/mbinary2 b/mbinary2 - > new file mode 100644 - > index 0000000000000000000000000000000000000000..112363ac1917b417ffbd7f376ca786a1e5fa7490 - > GIT binary patch - > literal 5 - > Mc\${NkU|\`?^000jF3jhEB - > - > EOF - applying patch from stdin - - $ hg tip -q - 12:30b530085242 - - $ hg manifest --debug | grep mbinary - 045c85ba38952325e126c70962cc0f9d9077bc67 644 mbinary1 - a874b471193996e7cb034bb301cac7bdaf3e3f46 644 mbinary2 - -Filenames with spaces: - - $ hg import -d "1000000 0" -m spaces - <<EOF - > diff --git a/foo bar b/foo bar - > new file mode 100644 - > index 0000000..257cc56 - > --- /dev/null - > +++ b/foo bar - > @@ -0,0 +1 @@ - > +foo - > EOF - applying patch from stdin - - $ hg tip -q - 13:04750ef42fb3 - - $ cat "foo bar" - foo - -Copy then modify the original file: - - $ hg import -d "1000000 0" -m copy-mod-orig - <<EOF - > diff --git a/foo2 b/foo2 - > index 257cc56..fe08ec6 100644 - > --- a/foo2 - > +++ b/foo2 - > @@ -1 +1,2 @@ - > foo - > +new line - > diff --git a/foo2 b/foo3 - > similarity index 100% - > copy from foo2 - > copy to foo3 - > EOF - applying patch from stdin - - $ hg tip -q - 14:c4cd9cdeaa74 - - $ cat foo3 - foo - -Move text file and patch as binary - - $ echo a > text2 - $ hg ci -Am0 - adding text2 - $ hg import -d "1000000 0" -m rename-as-binary - <<"EOF" - > diff --git a/text2 b/binary2 - > rename from text2 - > rename to binary2 - > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757 - > GIT binary patch - > literal 5 - > Mc$`b*O5$Pw00T?_*Z=?k - > - > EOF - applying patch from stdin - - $ cat binary2 - a - b - \x00 (no-eol) (esc) - - $ hg st --copies --change . - A binary2 - text2 - R text2 - $ cd .. - -Consecutive import with renames (issue2459) - - $ hg init issue2459 - $ cd issue2459 - $ hg import --no-commit --force - <<EOF - > diff --git a/a b/a - > new file mode 100644 - > EOF - applying patch from stdin - $ hg import --no-commit --force - <<EOF - > diff --git a/a b/b - > rename from a - > rename to b - > EOF - applying patch from stdin - a has not been committed yet, so no copy data will be stored for b. - $ hg debugstate - a 0 -1 unset b - $ hg ci -m done - $ cd .. - -Renames and strip - - $ hg init renameandstrip - $ cd renameandstrip - $ echo a > a - $ hg ci -Am adda - adding a - $ hg import --no-commit -p2 - <<EOF - > diff --git a/foo/a b/foo/b - > rename from foo/a - > rename to foo/b - > EOF - applying patch from stdin - $ hg st --copies - A b - a - R a - $ cd .. - -Pure copy with existing destination - - $ hg init copytoexisting - $ cd copytoexisting - $ echo a > a - $ echo b > b - $ hg ci -Am add - adding a - adding b - $ hg import --no-commit - <<EOF - > diff --git a/a b/b - > copy from a - > copy to b - > EOF - applying patch from stdin - abort: cannot create b: destination already exists - [255] - $ cat b - b - -Copy and changes with existing destination - - $ hg import --no-commit - <<EOF - > diff --git a/a b/b - > copy from a - > copy to b - > --- a/a - > +++ b/b - > @@ -1,1 +1,2 @@ - > a - > +b - > EOF - applying patch from stdin - cannot create b: destination already exists - 1 out of 1 hunks FAILED -- saving rejects to file b.rej - abort: patch failed to apply - [255] - $ cat b - b - - $ ln -s b linkb - $ hg add linkb - $ hg ci -m addlinkb - $ hg import --no-commit - <<EOF - > diff --git a/linkb b/linkb - > deleted file mode 120000 - > --- a/linkb - > +++ /dev/null - > @@ -1,1 +0,0 @@ - > -badhunk - > \ No newline at end of file - > EOF - applying patch from stdin - patching file linkb - Hunk #1 FAILED at 0 - 1 out of 1 hunks FAILED -- saving rejects to file linkb.rej - abort: patch failed to apply - [255] - $ hg st - ? b.rej - ? linkb.rej - - $ cd ..
--- a/tests/test-globalopts.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-globalopts.t Tue Jun 14 20:43:04 2011 -0500 @@ -316,7 +316,7 @@ remove remove the specified files on the next commit rename rename files; equivalent of copy + remove resolve redo merges or set/view the merge status of files - revert restore individual files or directories to an earlier state + revert restore files to their checkout state rollback roll back the last transaction (dangerous) root print the root (top) of the current working directory serve start stand-alone webserver @@ -396,7 +396,7 @@ remove remove the specified files on the next commit rename rename files; equivalent of copy + remove resolve redo merges or set/view the merge status of files - revert restore individual files or directories to an earlier state + revert restore files to their checkout state rollback roll back the last transaction (dangerous) root print the root (top) of the current working directory serve start stand-alone webserver
--- a/tests/test-help.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-help.t Tue Jun 14 20:43:04 2011 -0500 @@ -86,7 +86,7 @@ remove remove the specified files on the next commit rename rename files; equivalent of copy + remove resolve redo merges or set/view the merge status of files - revert restore individual files or directories to an earlier state + revert restore files to their checkout state rollback roll back the last transaction (dangerous) root print the root (top) of the current working directory serve start stand-alone webserver @@ -160,7 +160,7 @@ remove remove the specified files on the next commit rename rename files; equivalent of copy + remove resolve redo merges or set/view the merge status of files - revert restore individual files or directories to an earlier state + revert restore files to their checkout state rollback roll back the last transaction (dangerous) root print the root (top) of the current working directory serve start stand-alone webserver @@ -673,7 +673,7 @@ remove remove the specified files on the next commit rename rename files; equivalent of copy + remove resolve redo merges or set/view the merge status of files - revert restore individual files or directories to an earlier state + revert restore files to their checkout state rollback roll back the last transaction (dangerous) root print the root (top) of the current working directory serve start stand-alone webserver
--- a/tests/test-hgweb-commands.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-hgweb-commands.t Tue Jun 14 20:43:04 2011 -0500 @@ -352,6 +352,35 @@ <th class="files">files</th> <td class="files"><a href="/file/2ef0ac749a14/da/foo">da/foo</a> <a href="/file/2ef0ac749a14/foo">foo</a> </td> </tr> + <tr> + <th class="diffstat">diffstat</th> + <td class="diffstat"> + 2 files changed, 2 insertions(+), 0 deletions(-) + + <a id="diffstatexpand" href="javascript:showDiffstat()"/>[<tt>+</tt>]</a> + <div id="diffstatdetails" style="display:none;"> + <a href="javascript:hideDiffstat()"/>[<tt>-</tt>]</a> + <p> + <table> <tr class="parity0"> + <td class="diffstat-file"><a href="#l1.1">da/foo</a></td> + <td class="diffstat-total" align="right">1</td> + <td class="diffstat-graph"> + <span class="diffstat-add" style="width:100.0%;"> </span> + <span class="diffstat-remove" style="width:0.0%;"> </span> + </td> + </tr> + <tr class="parity1"> + <td class="diffstat-file"><a href="#l2.1">foo</a></td> + <td class="diffstat-total" align="right">1</td> + <td class="diffstat-graph"> + <span class="diffstat-add" style="width:100.0%;"> </span> + <span class="diffstat-remove" style="width:0.0%;"> </span> + </td> + </tr> + </table> + </div> + </td> + </tr> </table> <div class="overflow"> @@ -952,7 +981,7 @@ $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=capabilities'; echo 200 Script output follows - lookup changegroupsubset branchmap pushkey known getbundle unbundlehash unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024 + lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024 heads
--- a/tests/test-hgweb-diffs.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-hgweb-diffs.t Tue Jun 14 20:43:04 2011 -0500 @@ -94,6 +94,35 @@ <th class="files">files</th> <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td> </tr> + <tr> + <th class="diffstat">diffstat</th> + <td class="diffstat"> + 2 files changed, 2 insertions(+), 0 deletions(-) + + <a id="diffstatexpand" href="javascript:showDiffstat()"/>[<tt>+</tt>]</a> + <div id="diffstatdetails" style="display:none;"> + <a href="javascript:hideDiffstat()"/>[<tt>-</tt>]</a> + <p> + <table> <tr class="parity0"> + <td class="diffstat-file"><a href="#l1.1">a</a></td> + <td class="diffstat-total" align="right">1</td> + <td class="diffstat-graph"> + <span class="diffstat-add" style="width:100.0%;"> </span> + <span class="diffstat-remove" style="width:0.0%;"> </span> + </td> + </tr> + <tr class="parity1"> + <td class="diffstat-file"><a href="#l2.1">b</a></td> + <td class="diffstat-total" align="right">1</td> + <td class="diffstat-graph"> + <span class="diffstat-add" style="width:100.0%;"> </span> + <span class="diffstat-remove" style="width:0.0%;"> </span> + </td> + </tr> + </table> + </div> + </td> + </tr> </table> <div class="overflow"> @@ -325,6 +354,35 @@ <th class="files">files</th> <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td> </tr> + <tr> + <th class="diffstat">diffstat</th> + <td class="diffstat"> + 2 files changed, 2 insertions(+), 0 deletions(-) + + <a id="diffstatexpand" href="javascript:showDiffstat()"/>[<tt>+</tt>]</a> + <div id="diffstatdetails" style="display:none;"> + <a href="javascript:hideDiffstat()"/>[<tt>-</tt>]</a> + <p> + <table> <tr class="parity0"> + <td class="diffstat-file"><a href="#l1.1">a</a></td> + <td class="diffstat-total" align="right">1</td> + <td class="diffstat-graph"> + <span class="diffstat-add" style="width:100.0%;"> </span> + <span class="diffstat-remove" style="width:0.0%;"> </span> + </td> + </tr> + <tr class="parity1"> + <td class="diffstat-file"><a href="#l2.1">b</a></td> + <td class="diffstat-total" align="right">1</td> + <td class="diffstat-graph"> + <span class="diffstat-add" style="width:100.0%;"> </span> + <span class="diffstat-remove" style="width:0.0%;"> </span> + </td> + </tr> + </table> + </div> + </td> + </tr> </table> <div class="overflow">
--- a/tests/test-hgweb-removed.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-hgweb-removed.t Tue Jun 14 20:43:04 2011 -0500 @@ -89,6 +89,27 @@ <th class="files">files</th> <td class="files">a </td> </tr> + <tr> + <th class="diffstat">diffstat</th> + <td class="diffstat"> + 1 files changed, 0 insertions(+), 1 deletions(-) + + <a id="diffstatexpand" href="javascript:showDiffstat()"/>[<tt>+</tt>]</a> + <div id="diffstatdetails" style="display:none;"> + <a href="javascript:hideDiffstat()"/>[<tt>-</tt>]</a> + <p> + <table> <tr class="parity0"> + <td class="diffstat-file"><a href="#l1.1">a</a></td> + <td class="diffstat-total" align="right">1</td> + <td class="diffstat-graph"> + <span class="diffstat-add" style="width:0.0%;"> </span> + <span class="diffstat-remove" style="width:100.0%;"> </span> + </td> + </tr> + </table> + </div> + </td> + </tr> </table> <div class="overflow">
--- a/tests/test-hook.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-hook.t Tue Jun 14 20:43:04 2011 -0500 @@ -346,6 +346,9 @@ > def brokenhook(**args): > return 1 + {} > + > def verbosehook(ui, **args): + > ui.note('verbose output from hook\n') + > > class container: > unreachable = 1 > EOF @@ -535,3 +538,14 @@ cb9a9f314b8b 1 files updated, 0 files merged, 0 files removed, 0 files unresolved +make sure --verbose (and --quiet/--debug etc.) are propogated to the local ui +that is passed to pre/post hooks + + $ echo '[hooks]' > .hg/hgrc + $ echo 'pre-identify = python:hooktests.verbosehook' >> .hg/hgrc + $ hg id + cb9a9f314b8b + $ hg id --verbose + calling hook pre-identify: hooktests.verbosehook + verbose output from hook + cb9a9f314b8b
--- a/tests/test-http-proxy.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-http-proxy.t Tue Jun 14 20:43:04 2011 -0500 @@ -102,19 +102,19 @@ * - - [*] "GET http://localhost:$HGPORT/?cmd=stream_out HTTP/1.1" - - (glob) * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys HTTP/1.1" - - x-hgarg-1:namespace=bookmarks (glob) * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob) - * - - [*] "GET http://localhost:$HGPORT/?cmd=heads HTTP/1.1" - - (glob) + * - - [*] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob) * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629 (glob) * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys HTTP/1.1" - - x-hgarg-1:namespace=bookmarks (glob) * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob) - * - - [*] "GET http://localhost:$HGPORT/?cmd=heads HTTP/1.1" - - (glob) + * - - [*] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob) * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629 (glob) * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys HTTP/1.1" - - x-hgarg-1:namespace=bookmarks (glob) * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob) - * - - [*] "GET http://localhost:$HGPORT/?cmd=heads HTTP/1.1" - - (glob) + * - - [*] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob) * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629 (glob) * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys HTTP/1.1" - - x-hgarg-1:namespace=bookmarks (glob) * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob) - * - - [*] "GET http://localhost:$HGPORT/?cmd=heads HTTP/1.1" - - (glob) + * - - [*] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob) * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629 (glob) * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys HTTP/1.1" - - x-hgarg-1:namespace=bookmarks (glob)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-import-bypass.t Tue Jun 14 20:43:04 2011 -0500 @@ -0,0 +1,261 @@ + $ echo "[extensions]" >> $HGRCPATH + $ echo "purge=" >> $HGRCPATH + $ echo "graphlog=" >> $HGRCPATH + + $ shortlog() { + > hg glog --template '{rev}:{node|short} {author} {date|hgdate} - {branch} - {desc|firstline}\n' + > } + +Test --bypass with other options + + $ hg init repo-options + $ cd repo-options + $ echo a > a + $ hg ci -Am adda + adding a + $ echo a >> a + $ hg branch foo + marked working directory as branch foo + $ hg ci -Am changea + $ hg export . > ../test.diff + $ hg up null + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + +Test importing an existing revision + + $ hg import --bypass --exact ../test.diff + applying ../test.diff + $ shortlog + o 1:4e322f7ce8e3 test 0 0 - foo - changea + | + o 0:07f494440405 test 0 0 - default - adda + + +Test failure without --exact + + $ hg import --bypass ../test.diff + applying ../test.diff + unable to find 'a' for patching + abort: patch failed to apply + [255] + $ hg st + $ shortlog + o 1:4e322f7ce8e3 test 0 0 - foo - changea + | + o 0:07f494440405 test 0 0 - default - adda + + +Test --user, --date and --message + + $ hg up 0 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg import --bypass --u test2 -d '1 0' -m patch2 ../test.diff + applying ../test.diff + $ cat .hg/last-message.txt + patch2 (no-eol) + $ shortlog + o 2:2e127d1da504 test2 1 0 - default - patch2 + | + | o 1:4e322f7ce8e3 test 0 0 - foo - changea + |/ + @ 0:07f494440405 test 0 0 - default - adda + + $ hg rollback + repository tip rolled back to revision 1 (undo commit) + working directory now based on revision 0 + +Test --import-branch + + $ hg import --bypass --import-branch ../test.diff + applying ../test.diff + $ shortlog + o 1:4e322f7ce8e3 test 0 0 - foo - changea + | + @ 0:07f494440405 test 0 0 - default - adda + + $ hg rollback + repository tip rolled back to revision 1 (undo commit) + working directory now based on revision 0 + +Test --strip + + $ hg import --bypass --strip 0 - <<EOF + > # HG changeset patch + > # User test + > # Date 0 0 + > # Branch foo + > # Node ID 4e322f7ce8e3e4203950eac9ece27bf7e45ffa6c + > # Parent 07f4944404050f47db2e5c5071e0e84e7a27bba9 + > changea + > + > diff -r 07f494440405 -r 4e322f7ce8e3 a + > --- a Thu Jan 01 00:00:00 1970 +0000 + > +++ a Thu Jan 01 00:00:00 1970 +0000 + > @@ -1,1 +1,2 @@ + > a + > +a + > EOF + applying patch from stdin + $ hg rollback + repository tip rolled back to revision 1 (undo commit) + working directory now based on revision 0 + +Test unsupported combinations + + $ hg import --bypass --no-commit ../test.diff + abort: cannot use --no-commit with --bypass + [255] + $ hg import --bypass --similarity 50 ../test.diff + abort: cannot use --similarity with --bypass + [255] + +Test commit editor + + $ hg diff -c 1 > ../test.diff + $ HGEDITOR=cat hg import --bypass ../test.diff + applying ../test.diff + + + HG: Enter commit message. Lines beginning with 'HG:' are removed. + HG: Leave message empty to abort commit. + HG: -- + HG: user: test + HG: branch 'default' + HG: changed a + abort: empty commit message + [255] + +Test patch.eol is handled + + $ python -c 'file("a", "wb").write("a\r\n")' + $ hg ci -m makeacrlf + $ hg import -m 'should fail because of eol' --bypass ../test.diff + applying ../test.diff + patching file a + Hunk #1 FAILED at 0 + abort: patch failed to apply + [255] + $ hg --config patch.eol=auto import -d '0 0' -m 'test patch.eol' --bypass ../test.diff + applying ../test.diff + $ shortlog + o 3:d7805b4d2cb3 test 0 0 - default - test patch.eol + | + @ 2:872023de769d test 0 0 - default - makeacrlf + | + | o 1:4e322f7ce8e3 test 0 0 - foo - changea + |/ + o 0:07f494440405 test 0 0 - default - adda + + +Test applying multiple patches + + $ hg up -qC 0 + $ echo e > e + $ hg ci -Am adde + adding e + created new head + $ hg export . > ../patch1.diff + $ hg up -qC 1 + $ echo f > f + $ hg ci -Am addf + adding f + $ hg export . > ../patch2.diff + $ cd .. + $ hg clone -r1 repo-options repo-multi1 + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 1 files + updating to branch foo + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd repo-multi1 + $ hg up 0 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg import --bypass ../patch1.diff ../patch2.diff + applying ../patch1.diff + applying ../patch2.diff + applied 16581080145e + $ shortlog + o 3:bc8ca3f8a7c4 test 0 0 - default - addf + | + o 2:16581080145e test 0 0 - default - adde + | + | o 1:4e322f7ce8e3 test 0 0 - foo - changea + |/ + @ 0:07f494440405 test 0 0 - default - adda + + +Test applying multiple patches with --exact + + $ cd .. + $ hg clone -r1 repo-options repo-multi2 + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 1 files + updating to branch foo + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd repo-multi2 + $ hg import --bypass --exact ../patch1.diff ../patch2.diff + applying ../patch1.diff + applying ../patch2.diff + applied 16581080145e + $ shortlog + o 3:d60cb8989666 test 0 0 - foo - addf + | + | o 2:16581080145e test 0 0 - default - adde + | | + @ | 1:4e322f7ce8e3 test 0 0 - foo - changea + |/ + o 0:07f494440405 test 0 0 - default - adda + + + $ cd .. + +Test complicated patch with --exact + + $ hg init repo-exact + $ cd repo-exact + $ echo a > a + $ echo c > c + $ echo d > d + $ echo e > e + $ echo f > f + $ chmod +x f + $ ln -s c linkc + $ hg ci -Am t + adding a + adding c + adding d + adding e + adding f + adding linkc + $ hg cp a aa1 + $ echo b >> a + $ echo b > b + $ hg add b + $ hg cp a aa2 + $ echo aa >> aa2 + $ chmod +x e + $ chmod -x f + $ ln -s a linka + $ hg rm d + $ hg rm linkc + $ hg mv c cc + $ hg ci -m patch + $ hg export --git . > ../test.diff + $ hg up -C null + 0 files updated, 0 files merged, 7 files removed, 0 files unresolved + $ hg purge + $ hg st + $ hg import --bypass --exact ../test.diff + applying ../test.diff + +The patch should have matched the exported revision and generated no additional +data. If not, diff both heads to debug it. + + $ shortlog + o 1:2978fd5c8aa4 test 0 0 - default - patch + | + o 0:a0e19e636a43 test 0 0 - default - t +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-import-git.t Tue Jun 14 20:43:04 2011 -0500 @@ -0,0 +1,468 @@ + + $ hg init + +New file: + + $ hg import -d "1000000 0" -mnew - <<EOF + > diff --git a/new b/new + > new file mode 100644 + > index 0000000..7898192 + > --- /dev/null + > +++ b/new + > @@ -0,0 +1 @@ + > +a + > EOF + applying patch from stdin + + $ hg tip -q + 0:ae3ee40d2079 + +New empty file: + + $ hg import -d "1000000 0" -mempty - <<EOF + > diff --git a/empty b/empty + > new file mode 100644 + > EOF + applying patch from stdin + + $ hg tip -q + 1:ab199dc869b5 + + $ hg locate empty + empty + +chmod +x: + + $ hg import -d "1000000 0" -msetx - <<EOF + > diff --git a/new b/new + > old mode 100644 + > new mode 100755 + > EOF + applying patch from stdin + + $ hg tip -q + 2:3a34410f282e + + $ test -x new + +Copy: + + $ hg import -d "1000000 0" -mcopy - <<EOF + > diff --git a/new b/copy + > old mode 100755 + > new mode 100644 + > similarity index 100% + > copy from new + > copy to copy + > diff --git a/new b/copyx + > similarity index 100% + > copy from new + > copy to copyx + > EOF + applying patch from stdin + + $ hg tip -q + 3:37bacb7ca14d + + $ if "$TESTDIR/hghave" -q execbit; then + > test -f copy -a ! -x copy || echo bad + > test -x copyx || echo bad + > else + > test -f copy || echo bad + > fi + + $ cat copy + a + + $ hg cat copy + a + +Rename: + + $ hg import -d "1000000 0" -mrename - <<EOF + > diff --git a/copy b/rename + > similarity index 100% + > rename from copy + > rename to rename + > EOF + applying patch from stdin + + $ hg tip -q + 4:47b81a94361d + + $ hg locate + copyx + empty + new + rename + +Delete: + + $ hg import -d "1000000 0" -mdelete - <<EOF + > diff --git a/copyx b/copyx + > deleted file mode 100755 + > index 7898192..0000000 + > --- a/copyx + > +++ /dev/null + > @@ -1 +0,0 @@ + > -a + > EOF + applying patch from stdin + + $ hg tip -q + 5:d9b001d98336 + + $ hg locate + empty + new + rename + + $ test -f copyx + [1] + +Regular diff: + + $ hg import -d "1000000 0" -mregular - <<EOF + > diff --git a/rename b/rename + > index 7898192..72e1fe3 100644 + > --- a/rename + > +++ b/rename + > @@ -1 +1,5 @@ + > a + > +a + > +a + > +a + > +a + > EOF + applying patch from stdin + + $ hg tip -q + 6:ebe901e7576b + +Copy and modify: + + $ hg import -d "1000000 0" -mcopymod - <<EOF + > diff --git a/rename b/copy2 + > similarity index 80% + > copy from rename + > copy to copy2 + > index 72e1fe3..b53c148 100644 + > --- a/rename + > +++ b/copy2 + > @@ -1,5 +1,5 @@ + > a + > a + > -a + > +b + > a + > a + > EOF + applying patch from stdin + + $ hg tip -q + 7:18f368958ecd + + $ hg cat copy2 + a + a + b + a + a + +Rename and modify: + + $ hg import -d "1000000 0" -mrenamemod - <<EOF + > diff --git a/copy2 b/rename2 + > similarity index 80% + > rename from copy2 + > rename to rename2 + > index b53c148..8f81e29 100644 + > --- a/copy2 + > +++ b/rename2 + > @@ -1,5 +1,5 @@ + > a + > a + > b + > -a + > +c + > a + > EOF + applying patch from stdin + + $ hg tip -q + 8:c32b0d7e6f44 + + $ hg locate copy2 + [1] + $ hg cat rename2 + a + a + b + c + a + +One file renamed multiple times: + + $ hg import -d "1000000 0" -mmultirenames - <<EOF + > diff --git a/rename2 b/rename3 + > rename from rename2 + > rename to rename3 + > diff --git a/rename2 b/rename3-2 + > rename from rename2 + > rename to rename3-2 + > EOF + applying patch from stdin + + $ hg tip -q + 9:034a6bf95330 + + $ hg log -vr. --template '{rev} {files} / {file_copies}\n' + 9 rename2 rename3 rename3-2 / rename3 (rename2)rename3-2 (rename2) + + $ hg locate rename2 rename3 rename3-2 + rename3 + rename3-2 + + $ hg cat rename3 + a + a + b + c + a + + $ hg cat rename3-2 + a + a + b + c + a + + $ echo foo > foo + $ hg add foo + $ hg ci -m 'add foo' + +Binary files and regular patch hunks: + + $ hg import -d "1000000 0" -m binaryregular - <<EOF + > diff --git a/binary b/binary + > new file mode 100644 + > index 0000000000000000000000000000000000000000..593f4708db84ac8fd0f5cc47c634f38c013fe9e4 + > GIT binary patch + > literal 4 + > Lc\${NkU|;|M00aO5 + > + > diff --git a/foo b/foo2 + > rename from foo + > rename to foo2 + > EOF + applying patch from stdin + + $ hg tip -q + 11:c39bce63e786 + + $ cat foo2 + foo + + $ hg manifest --debug | grep binary + 045c85ba38952325e126c70962cc0f9d9077bc67 644 binary + +Multiple binary files: + + $ hg import -d "1000000 0" -m multibinary - <<EOF + > diff --git a/mbinary1 b/mbinary1 + > new file mode 100644 + > index 0000000000000000000000000000000000000000..593f4708db84ac8fd0f5cc47c634f38c013fe9e4 + > GIT binary patch + > literal 4 + > Lc\${NkU|;|M00aO5 + > + > diff --git a/mbinary2 b/mbinary2 + > new file mode 100644 + > index 0000000000000000000000000000000000000000..112363ac1917b417ffbd7f376ca786a1e5fa7490 + > GIT binary patch + > literal 5 + > Mc\${NkU|\`?^000jF3jhEB + > + > EOF + applying patch from stdin + + $ hg tip -q + 12:30b530085242 + + $ hg manifest --debug | grep mbinary + 045c85ba38952325e126c70962cc0f9d9077bc67 644 mbinary1 + a874b471193996e7cb034bb301cac7bdaf3e3f46 644 mbinary2 + +Filenames with spaces: + + $ hg import -d "1000000 0" -m spaces - <<EOF + > diff --git a/foo bar b/foo bar + > new file mode 100644 + > index 0000000..257cc56 + > --- /dev/null + > +++ b/foo bar + > @@ -0,0 +1 @@ + > +foo + > EOF + applying patch from stdin + + $ hg tip -q + 13:04750ef42fb3 + + $ cat "foo bar" + foo + +Copy then modify the original file: + + $ hg import -d "1000000 0" -m copy-mod-orig - <<EOF + > diff --git a/foo2 b/foo2 + > index 257cc56..fe08ec6 100644 + > --- a/foo2 + > +++ b/foo2 + > @@ -1 +1,2 @@ + > foo + > +new line + > diff --git a/foo2 b/foo3 + > similarity index 100% + > copy from foo2 + > copy to foo3 + > EOF + applying patch from stdin + + $ hg tip -q + 14:c4cd9cdeaa74 + + $ cat foo3 + foo + +Move text file and patch as binary + + $ echo a > text2 + $ hg ci -Am0 + adding text2 + $ hg import -d "1000000 0" -m rename-as-binary - <<"EOF" + > diff --git a/text2 b/binary2 + > rename from text2 + > rename to binary2 + > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757 + > GIT binary patch + > literal 5 + > Mc$`b*O5$Pw00T?_*Z=?k + > + > EOF + applying patch from stdin + + $ cat binary2 + a + b + \x00 (no-eol) (esc) + + $ hg st --copies --change . + A binary2 + text2 + R text2 + $ cd .. + +Consecutive import with renames (issue2459) + + $ hg init issue2459 + $ cd issue2459 + $ hg import --no-commit --force - <<EOF + > diff --git a/a b/a + > new file mode 100644 + > EOF + applying patch from stdin + $ hg import --no-commit --force - <<EOF + > diff --git a/a b/b + > rename from a + > rename to b + > EOF + applying patch from stdin + a has not been committed yet, so no copy data will be stored for b. + $ hg debugstate + a 0 -1 unset b + $ hg ci -m done + $ cd .. + +Renames and strip + + $ hg init renameandstrip + $ cd renameandstrip + $ echo a > a + $ hg ci -Am adda + adding a + $ hg import --no-commit -p2 - <<EOF + > diff --git a/foo/a b/foo/b + > rename from foo/a + > rename to foo/b + > EOF + applying patch from stdin + $ hg st --copies + A b + a + R a + $ cd .. + +Pure copy with existing destination + + $ hg init copytoexisting + $ cd copytoexisting + $ echo a > a + $ echo b > b + $ hg ci -Am add + adding a + adding b + $ hg import --no-commit - <<EOF + > diff --git a/a b/b + > copy from a + > copy to b + > EOF + applying patch from stdin + abort: cannot create b: destination already exists + [255] + $ cat b + b + +Copy and changes with existing destination + + $ hg import --no-commit - <<EOF + > diff --git a/a b/b + > copy from a + > copy to b + > --- a/a + > +++ b/b + > @@ -1,1 +1,2 @@ + > a + > +b + > EOF + applying patch from stdin + cannot create b: destination already exists + 1 out of 1 hunks FAILED -- saving rejects to file b.rej + abort: patch failed to apply + [255] + $ cat b + b + + $ ln -s b linkb + $ hg add linkb + $ hg ci -m addlinkb + $ hg import --no-commit - <<EOF + > diff --git a/linkb b/linkb + > deleted file mode 120000 + > --- a/linkb + > +++ /dev/null + > @@ -1,1 +0,0 @@ + > -badhunk + > \ No newline at end of file + > EOF + applying patch from stdin + patching file linkb + Hunk #1 FAILED at 0 + 1 out of 1 hunks FAILED -- saving rejects to file linkb.rej + abort: patch failed to apply + [255] + $ hg st + ? b.rej + ? linkb.rej + + $ cd ..
--- a/tests/test-mq-merge.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-mq-merge.t Tue Jun 14 20:43:04 2011 -0500 @@ -130,7 +130,7 @@ patch failed, unable to continue (try -v) patch failed, rejects left in working dir patch didn't work out, merging patcha - 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved 0 files updated, 2 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) applying patcha2
--- a/tests/test-notify.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-notify.t Tue Jun 14 20:43:04 2011 -0500 @@ -32,6 +32,8 @@ incoming.notify = python:hgext.notify.hook # batch emails when many changesets incoming at one time changegroup.notify = python:hgext.notify.hook + # batch emails when many changesets outgoing at one time (client side) + outgoing.notify = python:hgext.notify.hook [notify] # config items go here @@ -48,7 +50,8 @@ style = ... # style file to use when formatting email template = ... # template to use when formatting email incoming = ... # template to use when run as incoming hook - changegroup = ... # template when run as changegroup hook + outgoing = ... # template to use when run as outgoing hook + changegroup = ... # template to use when run as changegroup hook maxdiff = 300 # max lines of diffs to include (0=none, -1=all) maxsubject = 67 # truncate subject line longer than this diffstat = True # add a diffstat before the diff content
--- a/tests/test-push-warn.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-push-warn.t Tue Jun 14 20:43:04 2011 -0500 @@ -35,7 +35,7 @@ searching for changes taking quick initial sample searching: 2 queries - query 2; still undecided: 2, sample size is: 2 + query 2; still undecided: 1, sample size is: 1 2 total queries new remote heads on branch 'default' new remote head 1e108cc5548c
--- a/tests/test-qrecord.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-qrecord.t Tue Jun 14 20:43:04 2011 -0500 @@ -64,6 +64,9 @@ -l --logfile FILE read commit message from file -d --date DATE record the specified date as commit date -u --user USER record the specified user as committer + -w --ignore-all-space ignore white space when comparing lines + -b --ignore-space-change ignore changes in the amount of white space + -B --ignore-blank-lines ignore changes whose lines are all blank [+] marked option can be specified multiple times @@ -136,6 +139,9 @@ -X --exclude PATTERN [+] exclude names matching the given patterns -m --message TEXT use text as commit message -l --logfile FILE read commit message from file + -w --ignore-all-space ignore white space when comparing lines + -b --ignore-space-change ignore changes in the amount of white space + -B --ignore-blank-lines ignore changes whose lines are all blank --mq operate on patch repository [+] marked option can be specified multiple times
--- a/tests/test-rebase-mq.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-rebase-mq.t Tue Jun 14 20:43:04 2011 -0500 @@ -250,6 +250,7 @@ $ hg qnew foo $ hg qguard foo +baz $ echo foo > foo + $ hg add foo $ hg qref $ hg qpop popping foo @@ -258,6 +259,7 @@ $ hg qnew bar $ hg qguard bar +baz $ echo bar > bar + $ hg add bar $ hg qref $ hg qguard -l @@ -272,13 +274,13 @@ Create new head to rebase bar onto: $ hg up -C 0 - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ echo b > b $ hg add b $ hg ci -m b created new head $ hg up -C 1 - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved $ echo a >> a $ hg qref @@ -290,13 +292,19 @@ o 0:* 'a' tags: qparent (glob) -Rebase bar: +Rebase bar (make sure series order is preserved): + $ hg qseries + bar + foo $ hg -q rebase -d 1 + $ hg qseries + bar + foo $ hg qguard -l + bar: +baz foo: +baz - bar: +baz $ hg tglog @ 2:* '[mq]: bar' tags: bar qbase qtip tip (glob)
--- a/tests/test-revert.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-revert.t Tue Jun 14 20:43:04 2011 -0500 @@ -185,7 +185,8 @@ should fail - no arguments $ hg revert -rtip - abort: no files or directories specified; use --all to revert the whole repo + abort: no files or directories specified + (use --all to revert all files) [255] should succeed
--- a/tests/test-schemes.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-schemes.t Tue Jun 14 20:43:04 2011 -0500 @@ -28,7 +28,7 @@ sending capabilities command comparing with parts://localhost/ query 1; heads - sending heads command + sending batch command searching for changes all remote heads known locally no changes found
--- a/tests/test-setdiscovery.t Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-setdiscovery.t Tue Jun 14 20:43:04 2011 -0500 @@ -44,10 +44,7 @@ comparing with b query 1; heads searching for changes - taking initial sample - searching: 2 queries - query 2; still undecided: 4, sample size is: 4 - 2 total queries + all local heads known remotely common heads: b5714e113bc0 01241442b3c2 local is subset @@ -83,9 +80,9 @@ comparing with b query 1; heads searching for changes - taking quick initial sample + taking initial sample searching: 2 queries - query 2; still undecided: 35, sample size is: 35 + query 2; still undecided: 29, sample size is: 29 2 total queries common heads: bebd167eb94d @@ -101,7 +98,7 @@ searching for changes taking initial sample searching: 2 queries - query 2; still undecided: 3, sample size is: 3 + query 2; still undecided: 2, sample size is: 2 2 total queries common heads: bebd167eb94d @@ -122,9 +119,9 @@ comparing with b query 1; heads searching for changes - taking quick initial sample + taking initial sample searching: 2 queries - query 2; still undecided: 34, sample size is: 34 + query 2; still undecided: 29, sample size is: 29 2 total queries common heads: 2dc09a01254d @@ -140,7 +137,7 @@ searching for changes taking initial sample searching: 2 queries - query 2; still undecided: 30, sample size is: 30 + query 2; still undecided: 29, sample size is: 29 2 total queries common heads: 2dc09a01254d @@ -163,7 +160,7 @@ searching for changes taking quick initial sample searching: 2 queries - query 2; still undecided: 32, sample size is: 32 + query 2; still undecided: 31, sample size is: 31 2 total queries common heads: 66f7d451a68b @@ -179,7 +176,7 @@ searching for changes taking quick initial sample searching: 2 queries - query 2; still undecided: 32, sample size is: 32 + query 2; still undecided: 31, sample size is: 31 2 total queries common heads: 66f7d451a68b @@ -202,7 +199,7 @@ searching for changes taking quick initial sample searching: 2 queries - query 2; still undecided: 52, sample size is: 52 + query 2; still undecided: 51, sample size is: 51 2 total queries common heads: 66f7d451a68b @@ -218,7 +215,7 @@ searching for changes taking quick initial sample searching: 2 queries - query 2; still undecided: 32, sample size is: 32 + query 2; still undecided: 31, sample size is: 31 2 total queries common heads: 66f7d451a68b @@ -241,7 +238,7 @@ searching for changes taking quick initial sample searching: 2 queries - query 2; still undecided: 1050, sample size is: 11 + query 2; still undecided: 1049, sample size is: 11 sampling from both directions searching: 3 queries query 3; still undecided: 31, sample size is: 31 @@ -260,7 +257,7 @@ searching for changes taking quick initial sample searching: 2 queries - query 2; still undecided: 1030, sample size is: 11 + query 2; still undecided: 1029, sample size is: 11 sampling from both directions searching: 3 queries query 3; still undecided: 16, sample size is: 16
--- a/tests/test-symlink-os-yes-fs-no.py Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-symlink-os-yes-fs-no.py Tue Jun 14 20:43:04 2011 -0500 @@ -10,7 +10,7 @@ # clone with symlink support u = ui.ui() -hg.clone(u, BUNDLEPATH, 'test0') +hg.clone(u, {}, BUNDLEPATH, 'test0') repo = hg.repository(u, 'test0') @@ -39,4 +39,4 @@ # try cloning a repo which contains symlinks u = ui.ui() -hg.clone(u, BUNDLEPATH, 'test1') +hg.clone(u, {}, BUNDLEPATH, 'test1')
--- a/tests/test-ui-color.py Tue Jun 14 00:31:56 2011 +0400 +++ b/tests/test-ui-color.py Tue Jun 14 20:43:04 2011 -0500 @@ -19,13 +19,13 @@ ui_ = ui.ui() ui_.setconfig('ui', 'formatted', 'True') +# we're not interested in the output, so write that to devnull +ui_.fout = open(os.devnull, 'w') + # call some arbitrary command just so we go through # color's wrapped _runcommand twice. -# we're not interested in the output, so write that to devnull def runcmd(): - sys.stdout = open(os.devnull, 'w') dispatch.dispatch(dispatch.request(['version', '-q'], ui_)) - sys.stdout = sys.__stdout__ runcmd() print "colored? " + str(issubclass(ui_.__class__, color.colorui))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-wireprotocol.py Tue Jun 14 20:43:04 2011 -0500 @@ -0,0 +1,45 @@ +from mercurial import wireproto + +class proto(): + def __init__(self, args): + self.args = args + def getargs(self, spec): + args = self.args + args.setdefault('*', {}) + names = spec.split() + return [args[n] for n in names] + +class clientrepo(wireproto.wirerepository): + def __init__(self, serverrepo): + self.serverrepo = serverrepo + def _call(self, cmd, **args): + return wireproto.dispatch(self.serverrepo, proto(args), cmd) + + @wireproto.batchable + def greet(self, name): + f = wireproto.future() + yield wireproto.todict(name=mangle(name)), f + yield unmangle(f.value) + +class serverrepo(): + def greet(self, name): + return "Hello, " + name + +def mangle(s): + return ''.join(chr(ord(c) + 1) for c in s) +def unmangle(s): + return ''.join(chr(ord(c) - 1) for c in s) + +def greet(repo, proto, name): + return mangle(repo.greet(unmangle(name))) + +wireproto.commands['greet'] = (greet, 'name',) + +srv = serverrepo() +clt = clientrepo(srv) + +print clt.greet("Foobar") +b = clt.batch() +fs = [b.greet(s) for s in ["Fo, =;o", "Bar"]] +b.submit() +print [f.value for f in fs]