Mercurial > hg
changeset 18742:a07be8953733
merge with crew
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Thu, 28 Feb 2013 21:58:37 -0600 |
parents | af9ddea2cb99 (diff) b376e8f91c16 (current diff) |
children | 70e2a22fd66e |
files | mercurial/httppeer.py |
diffstat | 43 files changed, 724 insertions(+), 303 deletions(-) [+] |
line wrap: on
line diff
--- a/contrib/check-code.py Sun Feb 17 14:41:31 2013 -0600 +++ b/contrib/check-code.py Thu Feb 28 21:58:37 2013 -0600 @@ -105,7 +105,10 @@ "use (glob) to match Windows paths too"), ], # warnings - [] + [ + (r'^ [^*?/\n]* \(glob\)$', + "warning: glob match with no glob character (?*/)"), + ] ] for i in [0, 1]:
--- a/contrib/mergetools.hgrc Sun Feb 17 14:41:31 2013 -0600 +++ b/contrib/mergetools.hgrc Thu Feb 28 21:58:37 2013 -0600 @@ -15,7 +15,7 @@ gvimdiff.regname=path gvimdiff.priority=-9 -vimdiff.args=$local $other $base +vimdiff.args=$local $other $base -c 'redraw | echomsg "hg merge conflict, type \":cq\" to abort vimdiff"' vimdiff.check=changed vimdiff.priority=-10
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgext/blackbox.py Thu Feb 28 21:58:37 2013 -0600 @@ -0,0 +1,106 @@ +# blackbox.py - log repository events to a file for post-mortem debugging +# +# Copyright 2010 Nicolas Dumazet +# Copyright 2013 Facebook, Inc. +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +"""log repository events to a blackbox for debugging + +Logs event information to .hg/blackbox.log to help debug and diagnose problems. +The events that get logged can be configured via the blackbox.track config key. +Examples: + + [blackbox] + track = * + + [blackbox] + track = command, commandfinish, commandexception, exthook, pythonhook + + [blackbox] + track = incoming + +""" + +from mercurial import util, cmdutil +from mercurial.i18n import _ +import os, getpass, re + +cmdtable = {} +command = cmdutil.command(cmdtable) +testedwith = 'internal' +lastblackbox = None + +def wrapui(ui): + class blackboxui(ui.__class__): + @util.propertycache + def track(self): + return ui.configlist('blackbox', 'track', ['*']) + + def log(self, event, *msg, **opts): + global lastblackbox + super(blackboxui, self).log(event, *msg, **opts) + + if not '*' in self.track and not event in self.track: + return + + if util.safehasattr(self, '_blackbox'): + blackbox = self._blackbox + else: + # certain ui instances exist outside the context of + # a repo, so just default to the last blackbox that + # was seen. + blackbox = lastblackbox + + if blackbox: + date = util.datestr(None, '%Y/%m/%d %H:%M:%S') + user = getpass.getuser() + formattedmsg = msg[0] % msg[1:] + blackbox.write('%s %s> %s' % (date, user, formattedmsg)) + lastblackbox = blackbox + + def setrepo(self, repo): + self._blackbox = repo.opener('blackbox.log', 'a') + + ui.__class__ = blackboxui + +def uisetup(ui): + wrapui(ui) + +def reposetup(ui, repo): + # During 'hg pull' a httppeer repo is created to represent the remote repo. + # It doesn't have a .hg directory to put a blackbox in, so we don't do + # the blackbox setup for it. + if not repo.local(): + return + + ui.setrepo(repo) + +@command('^blackbox', + [('l', 'limit', 10, _('the number of events to show')), + ], + _('hg blackbox [OPTION]...')) +def blackbox(ui, repo, *revs, **opts): + '''view the recent repository events + ''' + + if not os.path.exists(repo.join('blackbox.log')): + return + + limit = opts.get('limit') + blackbox = repo.opener('blackbox.log', 'r') + lines = blackbox.read().split('\n') + + count = 0 + output = [] + for line in reversed(lines): + if count >= limit: + break + + # count the commands by matching lines like: 2013/01/23 19:13:36 root> + if re.match('^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} .*> .*', line): + count += 1 + output.append(line) + + ui.status('\n'.join(reversed(output)))
--- a/hgext/convert/cvsps.py Sun Feb 17 14:41:31 2013 -0600 +++ b/hgext/convert/cvsps.py Thu Feb 28 21:58:37 2013 -0600 @@ -508,9 +508,15 @@ ui.status(_('creating changesets\n')) + # try to order commitids by date + mindate = {} + for e in log: + if e.commitid: + mindate[e.commitid] = min(e.date, mindate.get(e.commitid)) + # Merge changesets - log.sort(key=lambda x: (x.commitid, x.comment, x.author, x.branch, x.date, - x.branchpoints)) + log.sort(key=lambda x: (mindate.get(x.commitid), x.commitid, x.comment, + x.author, x.branch, x.date, x.branchpoints)) changesets = [] files = set()
--- a/hgext/largefiles/__init__.py Sun Feb 17 14:41:31 2013 -0600 +++ b/hgext/largefiles/__init__.py Thu Feb 28 21:58:37 2013 -0600 @@ -41,13 +41,17 @@ enabled for this to work. When you pull a changeset that affects largefiles from a remote -repository, the largefiles for the changeset usually won't be -pulled down until you update to the revision (there is one exception -to this case). However, when you update to such a revision, any -largefiles needed by that revision are downloaded and cached (if -they have never been downloaded before). This means that network -access may be required to update to changesets you have no -previously updated to. +repository, the largefiles for the changeset won't be pulled down. +Instead, when you later update to such a revision, any largefiles +needed by that revision are downloaded and cached (if they have +never been downloaded before). This means that network access may +be required to update to changesets you have previously updated to. + +If you know you are pulling from a non-default location and want to +ensure that you will have the largefiles needed to merge or rebase +with new heads that you are pulling, then you can pull with the +--cache-largefiles flag to pre-emptively download any largefiles +that are new in the heads you are pulling. The one exception to the "largefiles won't be pulled until you update to a revision that changes them" rule is when you pull new heads.
--- a/hgext/largefiles/basestore.py Sun Feb 17 14:41:31 2013 -0600 +++ b/hgext/largefiles/basestore.py Thu Feb 28 21:58:37 2013 -0600 @@ -60,6 +60,8 @@ missing = [] ui = self.ui + util.makedirs(lfutil.storepath(self.repo, '')) + at = 0 for filename, hash in files: ui.progress(_('getting largefiles'), at, unit='lfile',
--- a/hgext/largefiles/lfcommands.py Sun Feb 17 14:41:31 2013 -0600 +++ b/hgext/largefiles/lfcommands.py Thu Feb 28 21:58:37 2013 -0600 @@ -8,7 +8,7 @@ '''High-level command function for lfconvert, plus the cmdtable.''' -import os +import os, errno import shutil from mercurial import util, match as match_, hg, node, context, error, \ @@ -403,22 +403,13 @@ toget = [] for lfile in lfiles: - # If we are mid-merge, then we have to trust the standin that is in the - # working copy to have the correct hashvalue. This is because the - # original hg.merge() already updated the standin as part of the normal - # merge process -- we just have to update the largefile to match. - if (getattr(repo, "_ismerging", False) and - os.path.exists(repo.wjoin(lfutil.standin(lfile)))): - expectedhash = lfutil.readstandin(repo, lfile) - else: + try: expectedhash = repo[node][lfutil.standin(lfile)].data().strip() - - # if it exists and its hash matches, it might have been locally - # modified before updating and the user chose 'local'. in this case, - # it will not be in any store, so don't look for it. - if ((not os.path.exists(repo.wjoin(lfile)) or - expectedhash != lfutil.hashfile(repo.wjoin(lfile))) and - not lfutil.findfile(repo, expectedhash)): + except IOError, err: + if err.errno == errno.ENOENT: + continue # node must be None and standin wasn't found in wctx + raise + if not lfutil.findfile(repo, expectedhash): toget.append((lfile, expectedhash)) if toget: @@ -435,11 +426,12 @@ pass totalsuccess = 0 totalmissing = 0 - for ctx in cmdutil.walkchangerevs(repo, matchfn, {'rev' : rev}, - prepare): - success, missing = cachelfiles(ui, repo, ctx.node()) - totalsuccess += len(success) - totalmissing += len(missing) + if rev != []: # walkchangerevs on empty list would return all revs + for ctx in cmdutil.walkchangerevs(repo, matchfn, {'rev' : rev}, + prepare): + success, missing = cachelfiles(ui, repo, ctx.node()) + totalsuccess += len(success) + totalmissing += len(missing) ui.status(_("%d additional largefiles cached\n") % totalsuccess) if totalmissing > 0: ui.status(_("%d largefiles failed to download\n") % totalmissing) @@ -458,7 +450,7 @@ if printmessage and lfiles: ui.status(_('getting changed largefiles\n')) printed = True - cachelfiles(ui, repo, '.', lfiles) + cachelfiles(ui, repo, None, lfiles) updated, removed = 0, 0 for f in lfiles: @@ -500,6 +492,8 @@ # use normallookup() to allocate entry in largefiles dirstate, # because lack of it misleads lfilesrepo.status() into # recognition that such cache missing files are REMOVED. + if lfile not in repo[None]: # not switched to normal file + util.unlinkpath(abslfile, ignoremissing=True) lfdirstate.normallookup(lfile) return None # don't try to set the mode else:
--- a/hgext/largefiles/lfutil.py Sun Feb 17 14:41:31 2013 -0600 +++ b/hgext/largefiles/lfutil.py Thu Feb 28 21:58:37 2013 -0600 @@ -225,13 +225,9 @@ standindir = repo.wjoin(shortname) if pats: pats = [os.path.join(standindir, pat) for pat in pats] - elif os.path.isdir(standindir): + else: # no patterns: relative to repo root pats = [standindir] - else: - # no patterns and no standin dir: return matcher that matches nothing - return match_.match(repo.root, None, [], exact=True) - # no warnings about missing files or directories match = scmutil.match(repo[None], pats, opts) match.bad = lambda f, msg: None
--- a/hgext/largefiles/overrides.py Sun Feb 17 14:41:31 2013 -0600 +++ b/hgext/largefiles/overrides.py Thu Feb 28 21:58:37 2013 -0600 @@ -686,15 +686,8 @@ return result def hgmerge(orig, repo, node, force=None, remind=True): - # Mark the repo as being in the middle of a merge, so that - # updatelfiles() will know that it needs to trust the standins in - # the working copy, not in the standins in the current node - repo._ismerging = True - try: - result = orig(repo, node, force, remind) - lfcommands.updatelfiles(repo.ui, repo) - finally: - repo._ismerging = False + result = orig(repo, node, force, remind) + lfcommands.updatelfiles(repo.ui, repo) return result # When we rebase a repository with remotely changed largefiles, we need to @@ -733,23 +726,25 @@ repo.lfpullsource = source oldheads = lfutil.getcurrentheads(repo) result = orig(ui, repo, source, **opts) - # If we do not have the new largefiles for any new heads we pulled, we - # will run into a problem later if we try to merge or rebase with one of - # these heads, so cache the largefiles now directly into the system - # cache. - numcached = 0 - heads = lfutil.getcurrentheads(repo) - newheads = set(heads).difference(set(oldheads)) - if len(newheads) > 0: - ui.status(_("caching largefiles for %s heads\n") % len(newheads)) - for head in newheads: - (cached, missing) = lfcommands.cachelfiles(ui, repo, head) - numcached += len(cached) - ui.status(_("%d largefiles cached\n") % numcached) + if opts.get('cache_largefiles'): + # If you are pulling from a remote location that is not your + # default location, you may want to cache largefiles for new heads + # that have been pulled, so you can easily merge or rebase with + # them later + numcached = 0 + heads = lfutil.getcurrentheads(repo) + newheads = set(heads).difference(set(oldheads)) + if len(newheads) > 0: + ui.status(_("caching largefiles for %s heads\n") % + len(newheads)) + for head in newheads: + (cached, missing) = lfcommands.cachelfiles(ui, repo, head) + numcached += len(cached) + ui.status(_("%d largefiles cached\n") % numcached) if opts.get('all_largefiles'): revspostpull = len(repo) revs = [] - for rev in xrange(revsprepull + 1, revspostpull): + for rev in xrange(revsprepull, revspostpull): revs.append(repo[rev].rev()) lfcommands.downloadlfiles(ui, repo, revs) return result @@ -772,17 +767,6 @@ sourcerepo, destrepo = result repo = destrepo.local() - # The .hglf directory must exist for the standin matcher to match - # anything (which listlfiles uses for each rev), and .hg/largefiles is - # assumed to exist by the code that caches the downloaded file. These - # directories exist if clone updated to any rev. (If the repo does not - # have largefiles, download never gets to the point of needing - # .hg/largefiles, and the standin matcher won't match anything anyway.) - if 'largefiles' in repo.requirements: - if opts.get('noupdate'): - util.makedirs(repo.wjoin(lfutil.shortname)) - util.makedirs(repo.join(lfutil.longname)) - # Caching is implicitly limited to 'rev' option, since the dest repo was # truncated at that point. The user may expect a download count with # this option, so attempt whether or not this is a largefile repo.
--- a/hgext/largefiles/reposetup.py Sun Feb 17 14:41:31 2013 -0600 +++ b/hgext/largefiles/reposetup.py Thu Feb 28 21:58:37 2013 -0600 @@ -299,9 +299,9 @@ lfdirstate = lfutil.openlfdirstate(ui, self) dirtymatch = match_.always(self.root, self.getcwd()) s = lfdirstate.status(dirtymatch, [], False, False, False) - modifiedfiles = [] - for i in s: - modifiedfiles.extend(i) + (unsure, modified, added, removed, _missing, _unknown, + _ignored, _clean) = s + modifiedfiles = unsure + modified + added + removed lfiles = lfutil.listlfiles(self) # this only loops through largefiles that exist (not # removed/renamed)
--- a/hgext/largefiles/uisetup.py Sun Feb 17 14:41:31 2013 -0600 +++ b/hgext/largefiles/uisetup.py Thu Feb 28 21:58:37 2013 -0600 @@ -79,7 +79,9 @@ entry = extensions.wrapcommand(commands.table, 'pull', overrides.overridepull) pullopt = [('', 'all-largefiles', None, - _('download all pulled versions of largefiles'))] + _('download all pulled versions of largefiles')), + ('', 'cache-largefiles', None, + _('caches new largefiles in all pulled heads'))] entry[1].extend(pullopt) entry = extensions.wrapcommand(commands.table, 'clone', overrides.overrideclone)
--- a/hgext/pager.py Sun Feb 17 14:41:31 2013 -0600 +++ b/hgext/pager.py Thu Feb 28 21:58:37 2013 -0600 @@ -94,6 +94,8 @@ @atexit.register def killpager(): + if util.safehasattr(signal, "SIGINT"): + signal.signal(signal.SIGINT, signal.SIG_IGN) pager.stdin.close() os.dup2(stdout, sys.stdout.fileno()) os.dup2(stderr, sys.stderr.fileno())
--- a/mercurial/cmdutil.py Sun Feb 17 14:41:31 2013 -0600 +++ b/mercurial/cmdutil.py Thu Feb 28 21:58:37 2013 -0600 @@ -1210,6 +1210,13 @@ if ff.match(x): wanted.discard(x) + # Choose a small initial window if we will probably only visit a + # few commits. + limit = loglimit(opts) + windowsize = 8 + if limit: + windowsize = min(limit, windowsize) + # Now that wanted is correctly initialized, we can iterate over the # revision range, yielding only revisions in wanted. def iterate(): @@ -1221,7 +1228,7 @@ def want(rev): return rev in wanted - for i, window in increasingwindows(0, len(revs)): + for i, window in increasingwindows(0, len(revs), windowsize): nrevs = [rev for rev in revs[i:i + window] if want(rev)] for rev in sorted(nrevs): fns = fncache.get(rev) @@ -1821,6 +1828,52 @@ return text +def commitstatus(repo, node, branch, bheads=None, opts={}): + ctx = repo[node] + parents = ctx.parents() + + if (not opts.get('amend') and bheads and node not in bheads and not + [x for x in parents if x.node() in bheads and x.branch() == branch]): + repo.ui.status(_('created new head\n')) + # The message is not printed for initial roots. For the other + # changesets, it is printed in the following situations: + # + # Par column: for the 2 parents with ... + # N: null or no parent + # B: parent is on another named branch + # C: parent is a regular non head changeset + # H: parent was a branch head of the current branch + # Msg column: whether we print "created new head" message + # In the following, it is assumed that there already exists some + # initial branch heads of the current branch, otherwise nothing is + # printed anyway. + # + # Par Msg Comment + # N N y additional topo root + # + # B N y additional branch root + # C N y additional topo head + # H N n usual case + # + # B B y weird additional branch root + # C B y branch merge + # H B n merge with named branch + # + # C C y additional head from merge + # C H n merge with a head + # + # H H n head merge: head count decreases + + if not opts.get('close_branch'): + for r in parents: + if r.closesbranch() and r.branch() == branch: + repo.ui.status(_('reopening closed branch head %d\n') % r) + + if repo.ui.debugflag: + repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex())) + elif repo.ui.verbose: + repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx)) + def revert(ui, repo, ctx, parents, *pats, **opts): parent, p2 = parents node = ctx.node()
--- a/mercurial/commands.py Sun Feb 17 14:41:31 2013 -0600 +++ b/mercurial/commands.py Thu Feb 28 21:58:37 2013 -0600 @@ -456,14 +456,11 @@ wlock = repo.wlock() try: branch = repo.dirstate.branch() + bheads = repo.branchheads(branch) hg.clean(repo, node, show_stats=False) repo.dirstate.setbranch(branch) - revert_opts = opts.copy() - revert_opts['date'] = None - revert_opts['all'] = True - revert_opts['rev'] = hex(parent) - revert_opts['no_backup'] = None - revert(ui, repo, **revert_opts) + rctx = scmutil.revsingle(repo, hex(parent)) + cmdutil.revert(ui, repo, rctx, repo.dirstate.parents()) if not opts.get('merge') and op1 != node: try: ui.setconfig('ui', 'forcemerge', opts.get('tool', '')) @@ -471,13 +468,18 @@ finally: ui.setconfig('ui', 'forcemerge', '') - commit_opts = opts.copy() - commit_opts['addremove'] = False - if not commit_opts['message'] and not commit_opts['logfile']: + e = cmdutil.commiteditor + if not opts['message'] and not opts['logfile']: # we don't translate commit messages - commit_opts['message'] = "Backed out changeset %s" % short(node) - commit_opts['force_editor'] = True - commit(ui, repo, **commit_opts) + opts['message'] = "Backed out changeset %s" % short(node) + e = cmdutil.commitforceeditor + + def commitfunc(ui, repo, message, match, opts): + return repo.commit(message, opts.get('user'), opts.get('date'), + match, editor=e) + newnode = cmdutil.commit(ui, repo, commitfunc, [], opts) + cmdutil.commitstatus(repo, newnode, branch, bheads) + def nice(node): return '%d:%s' % (repo.changelog.rev(node), short(node)) ui.status(_('changeset %s backs out changeset %s\n') % @@ -1066,7 +1068,7 @@ dest = ui.expandpath(dest or 'default-push', dest or 'default') dest, branches = hg.parseurl(dest, opts.get('branch')) other = hg.peer(repo, opts, dest) - revs, checkout = hg.addbranchrevs(repo, other, branches, revs) + revs, checkout = hg.addbranchrevs(repo, repo, branches, revs) heads = revs and map(repo.lookup, revs) or revs outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=heads, @@ -1361,50 +1363,7 @@ ui.status(_("nothing changed\n")) return 1 - ctx = repo[node] - parents = ctx.parents() - - if (not opts.get('amend') and bheads and node not in bheads and not - [x for x in parents if x.node() in bheads and x.branch() == branch]): - ui.status(_('created new head\n')) - # The message is not printed for initial roots. For the other - # changesets, it is printed in the following situations: - # - # Par column: for the 2 parents with ... - # N: null or no parent - # B: parent is on another named branch - # C: parent is a regular non head changeset - # H: parent was a branch head of the current branch - # Msg column: whether we print "created new head" message - # In the following, it is assumed that there already exists some - # initial branch heads of the current branch, otherwise nothing is - # printed anyway. - # - # Par Msg Comment - # N N y additional topo root - # - # B N y additional branch root - # C N y additional topo head - # H N n usual case - # - # B B y weird additional branch root - # C B y branch merge - # H B n merge with named branch - # - # C C y additional head from merge - # C H n merge with a head - # - # H H n head merge: head count decreases - - if not opts.get('close_branch'): - for r in parents: - if r.closesbranch() and r.branch() == branch: - ui.status(_('reopening closed branch head %d\n') % r) - - if ui.debugflag: - ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex())) - elif ui.verbose: - ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx)) + cmdutil.commitstatus(repo, node, branch, bheads, opts) @command('copy|cp', [('A', 'after', None, _('record a copy that has already occurred')), @@ -4256,10 +4215,10 @@ displayer.show(ctx, copies=copies, matchfn=revmatchfn) for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep): + if displayer.flush(ctx.rev()): + count += 1 if count == limit: break - if displayer.flush(ctx.rev()): - count += 1 displayer.close() @command('manifest',
--- a/mercurial/dispatch.py Sun Feb 17 14:41:31 2013 -0600 +++ b/mercurial/dispatch.py Thu Feb 28 21:58:37 2013 -0600 @@ -247,6 +247,7 @@ (_("** Mercurial Distributed SCM (version %s)\n") % myver) + (_("** Extensions loaded: %s\n") % ", ".join([x[0] for x in extensions.extensions()]))) + ui.log("commandexception", "%s\n%s\n", warning, traceback.format_exc()) ui.warn(warning) raise @@ -333,7 +334,7 @@ self.cmdname = cmd = args.pop(0) args = map(util.expandpath, args) - for invalidarg in ("--cwd", "-R", "--repository", "--repo"): + for invalidarg in ("--cwd", "-R", "--repository", "--repo", "--config"): if _earlygetopt([invalidarg], args): def fn(ui, *args): ui.warn(_("error in definition for alias '%s': %s may only " @@ -738,10 +739,16 @@ msg = ' '.join(' ' in a and repr(a) or a for a in fullargs) ui.log("command", msg + "\n") d = lambda: util.checksignature(func)(ui, *args, **cmdoptions) + starttime = time.time() + ret = None try: - return runcommand(lui, repo, cmd, fullargs, ui, options, d, - cmdpats, cmdoptions) + ret = runcommand(lui, repo, cmd, fullargs, ui, options, d, + cmdpats, cmdoptions) + return ret finally: + duration = time.time() - starttime + ui.log("commandfinish", "%s exited %s after %0.2f seconds\n", + cmd, ret, duration) if repo and repo != req.repo: repo.close()
--- a/mercurial/extensions.py Sun Feb 17 14:41:31 2013 -0600 +++ b/mercurial/extensions.py Thu Feb 28 21:58:37 2013 -0600 @@ -50,7 +50,6 @@ raise def load(ui, name, path): - # unused ui argument kept for backwards compatibility if name.startswith('hgext.') or name.startswith('hgext/'): shortname = name[6:] else:
--- a/mercurial/help/config.txt Sun Feb 17 14:41:31 2013 -0600 +++ b/mercurial/help/config.txt Thu Feb 28 21:58:37 2013 -0600 @@ -745,7 +745,7 @@ For example:: [hostfingerprints] - hg.intevation.org = 38:76:52:7c:87:26:9a:8f:4a:f8:d3:de:08:45:3b:ea:d6:4b:ee:cc + hg.intevation.org = 44:ed:af:1f:97:11:b6:01:7a:48:45:fc:10:3c:b7:f9:d4:89:2a:9d This feature is only supported when using Python 2.6 or later.
--- a/mercurial/hook.py Sun Feb 17 14:41:31 2013 -0600 +++ b/mercurial/hook.py Thu Feb 28 21:58:37 2013 -0600 @@ -6,7 +6,7 @@ # GNU General Public License version 2 or any later version. from i18n import _ -import os, sys +import os, sys, time, types import extensions, util, demandimport def _pythonhook(ui, repo, name, hname, funcname, args, throw): @@ -20,6 +20,8 @@ be run as hooks without wrappers to convert return values.''' ui.note(_("calling hook %s: %s\n") % (hname, funcname)) + starttime = time.time() + obj = funcname if not util.safehasattr(obj, '__call__'): d = funcname.rfind('.') @@ -92,6 +94,12 @@ return True finally: sys.stdout, sys.stderr, sys.stdin = old + duration = time.time() - starttime + readablefunc = funcname + if isinstance(funcname, types.FunctionType): + readablefunc = funcname.__module__ + "." + funcname.__name__ + ui.log('pythonhook', 'pythonhook-%s: %s finished in %0.2f seconds\n', + name, readablefunc, duration) if r: if throw: raise util.Abort(_('%s hook failed') % hname) @@ -101,6 +109,7 @@ def _exthook(ui, repo, name, cmd, args, throw): ui.note(_("running hook %s: %s\n") % (name, cmd)) + starttime = time.time() env = {} for k, v in args.iteritems(): if util.safehasattr(v, '__call__'): @@ -121,6 +130,10 @@ r = util.system(cmd, environ=env, cwd=cwd, out=ui) else: r = util.system(cmd, environ=env, cwd=cwd, out=ui.fout) + + duration = time.time() - starttime + ui.log('exthook', 'exthook-%s: %s finished in %0.2f seconds\n', + name, cmd, duration) if r: desc, r = util.explainexit(r) if throw:
--- a/mercurial/localrepo.py Sun Feb 17 14:41:31 2013 -0600 +++ b/mercurial/localrepo.py Thu Feb 28 21:58:37 2013 -0600 @@ -1532,12 +1532,12 @@ modified, added, clean = [], [], [] withflags = mf1.withflags() | mf2.withflags() - for fn in mf2: + for fn, mf2node in mf2.iteritems(): if fn in mf1: if (fn not in deleted and ((fn in withflags and mf1.flags(fn) != mf2.flags(fn)) or - (mf1[fn] != mf2[fn] and - (mf2[fn] or ctx1[fn].cmp(ctx2[fn]))))): + (mf1[fn] != mf2node and + (mf2node or ctx1[fn].cmp(ctx2[fn]))))): modified.append(fn) elif listclean: clean.append(fn) @@ -2399,6 +2399,12 @@ for n in added: self.hook("incoming", node=hex(n), source=srctype, url=url) + + newheads = [h for h in self.heads() if h not in oldheads] + self.ui.log("incoming", + "%s incoming changes - new heads: %s\n", + len(added), + ', '.join([hex(c[:6]) for c in newheads])) self._afterlock(runhooks) finally:
--- a/mercurial/match.py Sun Feb 17 14:41:31 2013 -0600 +++ b/mercurial/match.py Thu Feb 28 21:58:37 2013 -0600 @@ -62,6 +62,7 @@ self._files = [] self._anypats = bool(include or exclude) self._ctx = ctx + self._always = False if include: pats = _normalize(include, 'glob', root, cwd, auditor) @@ -103,6 +104,7 @@ m = lambda f: not em(f) else: m = lambda f: True + self._always = True self.matchfn = m self._fmap = set(self._files) @@ -130,7 +132,7 @@ def anypats(self): return self._anypats def always(self): - return False + return self._always class exact(match): def __init__(self, root, cwd, files): @@ -139,8 +141,7 @@ class always(match): def __init__(self, root, cwd): match.__init__(self, root, cwd, []) - def always(self): - return True + self._always = True class narrowmatcher(match): """Adapt a matcher to work on a subdirectory only. @@ -175,6 +176,7 @@ self._cwd = matcher._cwd self._path = path self._matcher = matcher + self._always = matcher._always self._files = [f[len(path) + 1:] for f in matcher._files if f.startswith(path + "/")]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/scmposix.py Thu Feb 28 21:58:37 2013 -0600 @@ -0,0 +1,32 @@ +import sys, os +import osutil + +def _rcfiles(path): + rcs = [os.path.join(path, 'hgrc')] + rcdir = os.path.join(path, 'hgrc.d') + try: + rcs.extend([os.path.join(rcdir, f) + for f, kind in osutil.listdir(rcdir) + if f.endswith(".rc")]) + except OSError: + pass + return rcs + +def systemrcpath(): + path = [] + if sys.platform == 'plan9': + root = 'lib/mercurial' + else: + root = 'etc/mercurial' + # old mod_python does not set sys.argv + if len(getattr(sys, 'argv', [])) > 0: + p = os.path.dirname(os.path.dirname(sys.argv[0])) + path.extend(_rcfiles(os.path.join(p, root))) + path.extend(_rcfiles('/' + root)) + return path + +def userrcpath(): + if sys.platform == 'plan9': + return [os.environ['home'] + '/lib/hgrc'] + else: + return [os.path.expanduser('~/.hgrc')]
--- a/mercurial/scmutil.py Sun Feb 17 14:41:31 2013 -0600 +++ b/mercurial/scmutil.py Thu Feb 28 21:58:37 2013 -0600 @@ -9,7 +9,15 @@ from mercurial.node import nullrev import util, error, osutil, revset, similar, encoding, phases import match as matchmod -import os, errno, re, stat, sys, glob +import os, errno, re, stat, glob + +if os.name == 'nt': + import scmwindows as scmplatform +else: + import scmposix as scmplatform + +systemrcpath = scmplatform.systemrcpath +userrcpath = scmplatform.userrcpath def nochangesfound(ui, repo, excluded=None): '''Report no changes for push/pull, excluded is None or a list of @@ -306,8 +314,7 @@ # to a directory. Let the posixfile() call below raise IOError. if basename: if atomictemp: - if not os.path.isdir(dirname): - util.makedirs(dirname, self.createmode) + util.ensuredirs(dirname, self.createmode) return util.atomictempfile(f, mode, self.createmode) try: if 'w' in mode: @@ -325,8 +332,7 @@ if e.errno != errno.ENOENT: raise nlink = 0 - if not os.path.isdir(dirname): - util.makedirs(dirname, self.createmode) + util.ensuredirs(dirname, self.createmode) if nlink > 0: if self._trustnlink is None: self._trustnlink = nlink > 1 or util.checknlink(f) @@ -345,9 +351,7 @@ except OSError: pass - dirname = os.path.dirname(linkname) - if not os.path.exists(dirname): - util.makedirs(dirname, self.createmode) + util.ensuredirs(os.path.dirname(linkname), self.createmode) if self._cansymlink: try: @@ -535,84 +539,6 @@ _rcpath = osrcpath() return _rcpath -if os.name != 'nt': - - def rcfiles(path): - rcs = [os.path.join(path, 'hgrc')] - rcdir = os.path.join(path, 'hgrc.d') - try: - rcs.extend([os.path.join(rcdir, f) - for f, kind in osutil.listdir(rcdir) - if f.endswith(".rc")]) - except OSError: - pass - return rcs - - def systemrcpath(): - path = [] - if sys.platform == 'plan9': - root = 'lib/mercurial' - else: - root = 'etc/mercurial' - # old mod_python does not set sys.argv - if len(getattr(sys, 'argv', [])) > 0: - p = os.path.dirname(os.path.dirname(sys.argv[0])) - path.extend(rcfiles(os.path.join(p, root))) - path.extend(rcfiles('/' + root)) - return path - - def userrcpath(): - if sys.platform == 'plan9': - return [os.environ['home'] + '/lib/hgrc'] - else: - return [os.path.expanduser('~/.hgrc')] - -else: - - import _winreg - - def systemrcpath(): - '''return default os-specific hgrc search path''' - rcpath = [] - filename = util.executablepath() - # Use mercurial.ini found in directory with hg.exe - progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini') - if os.path.isfile(progrc): - rcpath.append(progrc) - return rcpath - # Use hgrc.d found in directory with hg.exe - progrcd = os.path.join(os.path.dirname(filename), 'hgrc.d') - if os.path.isdir(progrcd): - for f, kind in osutil.listdir(progrcd): - if f.endswith('.rc'): - rcpath.append(os.path.join(progrcd, f)) - return rcpath - # else look for a system rcpath in the registry - value = util.lookupreg('SOFTWARE\\Mercurial', None, - _winreg.HKEY_LOCAL_MACHINE) - if not isinstance(value, str) or not value: - return rcpath - value = util.localpath(value) - for p in value.split(os.pathsep): - if p.lower().endswith('mercurial.ini'): - rcpath.append(p) - elif os.path.isdir(p): - for f, kind in osutil.listdir(p): - if f.endswith('.rc'): - rcpath.append(os.path.join(p, f)) - return rcpath - - def userrcpath(): - '''return os-specific hgrc search path to the user dir''' - home = os.path.expanduser('~') - path = [os.path.join(home, 'mercurial.ini'), - os.path.join(home, '.hgrc')] - userprofile = os.environ.get('USERPROFILE') - if userprofile: - path.append(os.path.join(userprofile, 'mercurial.ini')) - path.append(os.path.join(userprofile, '.hgrc')) - return path - def revsingle(repo, revspec, default='.'): if not revspec: return repo[default]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/scmwindows.py Thu Feb 28 21:58:37 2013 -0600 @@ -0,0 +1,46 @@ +import os +import osutil +import util +import _winreg + +def systemrcpath(): + '''return default os-specific hgrc search path''' + rcpath = [] + filename = util.executablepath() + # Use mercurial.ini found in directory with hg.exe + progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini') + if os.path.isfile(progrc): + rcpath.append(progrc) + return rcpath + # Use hgrc.d found in directory with hg.exe + progrcd = os.path.join(os.path.dirname(filename), 'hgrc.d') + if os.path.isdir(progrcd): + for f, kind in osutil.listdir(progrcd): + if f.endswith('.rc'): + rcpath.append(os.path.join(progrcd, f)) + return rcpath + # else look for a system rcpath in the registry + value = util.lookupreg('SOFTWARE\\Mercurial', None, + _winreg.HKEY_LOCAL_MACHINE) + if not isinstance(value, str) or not value: + return rcpath + value = util.localpath(value) + for p in value.split(os.pathsep): + if p.lower().endswith('mercurial.ini'): + rcpath.append(p) + elif os.path.isdir(p): + for f, kind in osutil.listdir(p): + if f.endswith('.rc'): + rcpath.append(os.path.join(p, f)) + return rcpath + +def userrcpath(): + '''return os-specific hgrc search path to the user dir''' + home = os.path.expanduser('~') + path = [os.path.join(home, 'mercurial.ini'), + os.path.join(home, '.hgrc')] + userprofile = os.environ.get('USERPROFILE') + if userprofile: + path.append(os.path.join(userprofile, 'mercurial.ini')) + path.append(os.path.join(userprofile, '.hgrc')) + return path
--- a/mercurial/templatefilters.py Sun Feb 17 14:41:31 2013 -0600 +++ b/mercurial/templatefilters.py Thu Feb 28 21:58:37 2013 -0600 @@ -5,6 +5,7 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. +from i18n import _ import cgi, re, os, time, urllib import encoding, node, util, error import hbisect
--- a/mercurial/templatekw.py Sun Feb 17 14:41:31 2013 -0600 +++ b/mercurial/templatekw.py Thu Feb 28 21:58:37 2013 -0600 @@ -244,8 +244,8 @@ copies.append((fn, rename[0])) c = [{'name': x[0], 'source': x[1]} for x in copies] - return showlist('file_copy', c, plural='file_copies', - element='file', **args) + f = _showlist('file_copy', c, plural='file_copies', **args) + return _hybrid(f, c) # showfilecopiesswitch() displays file copies only if copy records are # provided before calling the templater, usually with a --copies @@ -256,8 +256,8 @@ """ copies = args['revcache'].get('copies') or [] c = [{'name': x[0], 'source': x[1]} for x in copies] - return showlist('file_copy', c, plural='file_copies', - element='file', **args) + f = _showlist('file_copy', c, plural='file_copies', **args) + return _hybrid(f, c) def showfiledels(**args): """:file_dels: List of strings. Files removed by this changeset."""
--- a/mercurial/ui.py Sun Feb 17 14:41:31 2013 -0600 +++ b/mercurial/ui.py Thu Feb 28 21:58:37 2013 -0600 @@ -739,7 +739,7 @@ else: self.debug('%s:%s %s%s\n' % (topic, item, pos, unit)) - def log(self, service, message): + def log(self, service, *msg, **opts): '''hook for logging facility extensions service should be a readily-identifiable subsystem, which will
--- a/mercurial/util.py Sun Feb 17 14:41:31 2013 -0600 +++ b/mercurial/util.py Thu Feb 28 21:58:37 2013 -0600 @@ -880,6 +880,23 @@ if mode is not None: os.chmod(name, mode) +def ensuredirs(name, mode=None): + """race-safe recursive directory creation""" + if os.path.isdir(name): + return + parent = os.path.dirname(os.path.abspath(name)) + if parent != name: + ensuredirs(parent, mode) + try: + os.mkdir(name) + except OSError, err: + if err.errno == errno.EEXIST and os.path.isdir(name): + # someone else seems to have won a directory creation race + return + raise + if mode is not None: + os.chmod(name, mode) + def readfile(path): fp = open(path, 'rb') try: @@ -1251,7 +1268,18 @@ except (UnicodeDecodeError, UnicodeEncodeError): return _ellipsis(text, maxlength)[0] -_byteunits = ( +def unitcountfn(*unittable): + '''return a function that renders a readable count of some quantity''' + + def go(count): + for multiplier, divisor, format in unittable: + if count >= divisor * multiplier: + return format % (count / float(divisor)) + return unittable[-1][2] % count + + return go + +bytecount = unitcountfn( (100, 1 << 30, _('%.0f GB')), (10, 1 << 30, _('%.1f GB')), (1, 1 << 30, _('%.2f GB')), @@ -1264,14 +1292,6 @@ (1, 1, _('%.0f bytes')), ) -def bytecount(nbytes): - '''return byte count formatted as readable string, with units''' - - for multiplier, divisor, format in _byteunits: - if nbytes >= divisor * multiplier: - return format % (nbytes / float(divisor)) - return _byteunits[-1][2] % nbytes - def uirepr(s): # Avoid double backslash in Windows path repr() return repr(s).replace('\\\\', '\\') @@ -1852,3 +1872,46 @@ return fd.isatty() except AttributeError: return False + +timecount = unitcountfn( + (1, 1e3, _('%.0f s')), + (100, 1, _('%.1f s')), + (10, 1, _('%.2f s')), + (1, 1, _('%.3f s')), + (100, 0.001, _('%.1f ms')), + (10, 0.001, _('%.2f ms')), + (1, 0.001, _('%.3f ms')), + (100, 0.000001, _('%.1f us')), + (10, 0.000001, _('%.2f us')), + (1, 0.000001, _('%.3f us')), + (100, 0.000000001, _('%.1f ns')), + (10, 0.000000001, _('%.2f ns')), + (1, 0.000000001, _('%.3f ns')), + ) + +_timenesting = [0] + +def timed(func): + '''Report the execution time of a function call to stderr. + + During development, use as a decorator when you need to measure + the cost of a function, e.g. as follows: + + @util.timed + def foo(a, b, c): + pass + ''' + + def wrapper(*args, **kwargs): + start = time.time() + indent = 2 + _timenesting[0] += indent + try: + return func(*args, **kwargs) + finally: + elapsed = time.time() - start + _timenesting[0] -= indent + sys.stderr.write('%s%s: %s\n' % + (' ' * _timenesting[0], func.__name__, + timecount(elapsed))) + return wrapper
--- a/mercurial/worker.py Sun Feb 17 14:41:31 2013 -0600 +++ b/mercurial/worker.py Thu Feb 28 21:58:37 2013 -0600 @@ -6,7 +6,7 @@ # GNU General Public License version 2 or any later version. from i18n import _ -import os, signal, sys, util +import os, signal, sys, threading, util def countcpus(): '''try to count the number of CPUs on the system''' @@ -75,9 +75,13 @@ def _posixworker(ui, func, staticargs, args): rfd, wfd = os.pipe() workers = _numworkers(ui) + oldhandler = signal.getsignal(signal.SIGINT) + signal.signal(signal.SIGINT, signal.SIG_IGN) + pids, problem = [], [0] for pargs in partition(args, workers): pid = os.fork() if pid == 0: + signal.signal(signal.SIGINT, oldhandler) try: os.close(rfd) for i, item in func(*(staticargs + (pargs,))): @@ -85,29 +89,57 @@ os._exit(0) except KeyboardInterrupt: os._exit(255) + pids.append(pid) + pids.reverse() os.close(wfd) fp = os.fdopen(rfd, 'rb', 0) - oldhandler = signal.getsignal(signal.SIGINT) - signal.signal(signal.SIGINT, signal.SIG_IGN) + def killworkers(): + # if one worker bails, there's no good reason to wait for the rest + for p in pids: + try: + os.kill(p, signal.SIGTERM) + except OSError, err: + if err.errno != errno.ESRCH: + raise + def waitforworkers(): + for _ in pids: + st = _exitstatus(os.wait()[1]) + if st and not problem: + problem[0] = st + killworkers() + t = threading.Thread(target=waitforworkers) + t.start() def cleanup(): - # python 2.4 is too dumb for try/yield/finally signal.signal(signal.SIGINT, oldhandler) - problems = 0 - for i in xrange(workers): - problems |= os.wait()[1] - if problems: - sys.exit(1) + t.join() + status = problem[0] + if status: + if status < 0: + os.kill(os.getpid(), -status) + sys.exit(status) try: for line in fp: l = line.split(' ', 1) yield int(l[0]), l[1][:-1] except: # re-raises + killworkers() cleanup() raise cleanup() +def _posixexitstatus(code): + '''convert a posix exit status into the same form returned by + os.spawnv + + returns None if the process was stopped instead of exiting''' + if os.WIFEXITED(code): + return os.WEXITSTATUS(code) + elif os.WIFSIGNALED(code): + return -os.WTERMSIG(code) + if os.name != 'nt': _platformworker = _posixworker + _exitstatus = _posixexitstatus def partition(lst, nslices): '''partition a list into N slices of equal size'''
--- a/tests/run-tests.py Sun Feb 17 14:41:31 2013 -0600 +++ b/tests/run-tests.py Thu Feb 28 21:58:37 2013 -0600 @@ -541,6 +541,13 @@ def globmatch(el, l): # The only supported special characters are * and ? plus / which also # matches \ on windows. Escaping of these caracters is supported. + if el + '\n' == l: + if os.name == 'nt': + # matching on "/" is not needed for this line + iolock.acquire() + print "\nInfo, unnecessary glob: %s (glob)" % el + iolock.release() + return True i, n = 0, len(el) res = '' while i < n:
--- a/tests/test-alias.t Sun Feb 17 14:41:31 2013 -0600 +++ b/tests/test-alias.t Thu Feb 28 21:58:37 2013 -0600 @@ -17,6 +17,7 @@ > no-R = status -R elsewhere > no--repo = status --repo elsewhere > no--repository = status --repository elsewhere + > no--config = status --config a.config=1 > mylog = log > lognull = log -r null > shortlog = log --template '{rev} {node|short} | {date|isodate}\n' @@ -106,6 +107,8 @@ error in definition for alias 'no--repository': --repository may only be given on the command line $ hg help no--repository error in definition for alias 'no--repository': --repository may only be given on the command line + $ hg no--config + error in definition for alias 'no--config': --config may only be given on the command line optional repository
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-blackbox.t Thu Feb 28 21:58:37 2013 -0600 @@ -0,0 +1,79 @@ +setup + $ cat > mock.py <<EOF + > from mercurial import util + > import getpass + > + > def makedate(): + > return 0, 0 + > def getuser(): + > return 'bob' + > # mock the date and user apis so the output is always the same + > def uisetup(ui): + > util.makedate = makedate + > getpass.getuser = getuser + > EOF + $ cat >> $HGRCPATH <<EOF + > [extensions] + > blackbox= + > mock=`pwd`/mock.py + > EOF + $ hg init blackboxtest + $ cd blackboxtest + +command, exit codes, and duration + + $ echo a > a + $ hg add a + $ hg blackbox + 1970/01/01 00:00:00 bob> add a + 1970/01/01 00:00:00 bob> add exited 0 after * seconds (glob) + +incoming change tracking + +create two heads to verify that we only see one change in the log later + $ hg commit -ma + $ hg up null + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ echo b > b + $ hg commit -Amb + adding b + created new head + +clone, commit, pull + $ hg clone . ../blackboxtest2 + updating to branch default + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo c > c + $ hg commit -Amc + adding c + $ cd ../blackboxtest2 + $ hg pull + pulling from $TESTTMP/blackboxtest (glob) + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + (run 'hg update' to get a working copy) + $ hg blackbox -l 3 + 1970/01/01 00:00:00 bob> pull + 1970/01/01 00:00:00 bob> 1 incoming changes - new heads: d02f48003e62 + 1970/01/01 00:00:00 bob> pull exited None after * seconds (glob) + +extension and python hooks - use the eol extension for a pythonhook + + $ echo '[extensions]' >> .hg/hgrc + $ echo 'eol=' >> .hg/hgrc + $ echo '[hooks]' >> .hg/hgrc + $ echo 'update = echo hooked' >> .hg/hgrc + $ hg update + hooked + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg blackbox -l 4 + 1970/01/01 00:00:00 bob> update + 1970/01/01 00:00:00 bob> pythonhook-preupdate: hgext.eol.preupdate finished in * seconds (glob) + 1970/01/01 00:00:00 bob> exthook-update: echo hooked finished in * seconds (glob) + 1970/01/01 00:00:00 bob> update exited False after * seconds (glob) + +cleanup + $ cd ..
--- a/tests/test-bundle.t Sun Feb 17 14:41:31 2013 -0600 +++ b/tests/test-bundle.t Thu Feb 28 21:58:37 2013 -0600 @@ -522,6 +522,21 @@ [255] $ cd .. +test to bundle revisions on the newly created branch (issue3828): + + $ hg -q clone -U test test-clone + $ cd test + + $ hg -q branch foo + $ hg commit -m "create foo branch" + $ hg -q outgoing ../test-clone + 9:b4f5acb1ee27 + $ hg -q bundle --branch foo foo.hg ../test-clone + $ hg -R foo.hg -q log -r "bundle()" + 9:b4f5acb1ee27 + + $ cd .. + test for http://mercurial.selenic.com/bts/issue1144 test that verify bundle does not traceback
--- a/tests/test-command-template.t Sun Feb 17 14:41:31 2013 -0600 +++ b/tests/test-command-template.t Thu Feb 28 21:58:37 2013 -0600 @@ -43,6 +43,9 @@ $ hg mv second fourth $ hg commit -m third -d "2020-01-01 10:01" + $ hg log --template '{file_copies % "{source} -> {name}\n"}' -r . + second -> fourth + Quoting for ui.logtemplate $ hg tip --config "ui.logtemplate={rev}\n"
--- a/tests/test-diff-color.t Sun Feb 17 14:41:31 2013 -0600 +++ b/tests/test-diff-color.t Thu Feb 28 21:58:37 2013 -0600 @@ -152,7 +152,7 @@ c c \x1b[0;32m+aa\x1b[0m (esc) - \x1b[0;1mdiff --git a/sub/b b/sub/b\x1b[0m (glob) (esc) + \x1b[0;1mdiff --git a/sub/b b/sub/b\x1b[0m (esc) \x1b[0;31;1m--- a/sub/b\x1b[0m (esc) \x1b[0;32;1m+++ b/sub/b\x1b[0m (esc) \x1b[0;35m@@ -1,1 +1,2 @@\x1b[0m (esc)
--- a/tests/test-https.t Sun Feb 17 14:41:31 2013 -0600 +++ b/tests/test-https.t Thu Feb 28 21:58:37 2013 -0600 @@ -106,7 +106,7 @@ #if windows $ hg serve -p $HGPORT --certificate=$PRIV 2>&1 - abort: cannot start server at ':$HGPORT': (glob) + abort: cannot start server at ':$HGPORT': [255] #else $ hg serve -p $HGPORT --certificate=$PRIV 2>&1
--- a/tests/test-issue3084.t Sun Feb 17 14:41:31 2013 -0600 +++ b/tests/test-issue3084.t Thu Feb 28 21:58:37 2013 -0600 @@ -31,6 +31,8 @@ foo has been turned into a largefile use (l)argefile or keep as (n)ormal file? 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) + getting changed largefiles + 0 largefiles updated, 0 removed $ hg status $ cat foo
--- a/tests/test-largefiles-cache.t Sun Feb 17 14:41:31 2013 -0600 +++ b/tests/test-largefiles-cache.t Thu Feb 28 21:58:37 2013 -0600 @@ -16,6 +16,9 @@ $ echo large > large $ hg add --large large $ hg commit -m 'add largefile' + $ hg rm large + $ hg commit -m 'branchhead without largefile' + $ hg up -qr 0 $ cd .. Discard all cached largefiles in USERCACHE @@ -35,16 +38,14 @@ adding changesets adding manifests adding file changes - added 1 changesets with 1 changes to 1 files + added 2 changesets with 1 changes to 1 files (run 'hg update' to get a working copy) - caching largefiles for 1 heads - 0 largefiles cached Update working directory to "tip", which requires largefile("large"), but there is no cache file for it. So, hg must treat it as "missing"(!) file. - $ hg update + $ hg update -r0 getting changed largefiles error getting id 7f7097b041ccf68cc5561e9600da4655d21c6d18 from url file:$TESTTMP/mirror for file large: can't get file locally (glob) 0 largefiles updated, 0 removed @@ -61,7 +62,7 @@ Update working directory to tip, again. - $ hg update + $ hg update -r0 getting changed largefiles error getting id 7f7097b041ccf68cc5561e9600da4655d21c6d18 from url file:$TESTTMP/mirror for file large: can't get file locally (glob) 0 largefiles updated, 0 removed @@ -70,6 +71,17 @@ ! large $ cd .. +Verify that largefiles from pulled branchheads are fetched, also to an empty repo + + $ hg init mirror2 + $ hg -R mirror2 pull src -r0 + pulling from src + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + (run 'hg update' to get a working copy) + #if unix-permissions Portable way to print file permissions: @@ -90,6 +102,7 @@ $ chmod 660 large $ echo change >> large $ hg commit -m change + created new head $ ../ls-l.py .hg/largefiles/e151b474069de4ca6898f67ce2f2a7263adf8fea 640
--- a/tests/test-largefiles.t Sun Feb 17 14:41:31 2013 -0600 +++ b/tests/test-largefiles.t Thu Feb 28 21:58:37 2013 -0600 @@ -883,9 +883,7 @@ adding file changes added 6 changesets with 16 changes to 8 files (run 'hg update' to get a working copy) - caching largefiles for 1 heads - 3 largefiles cached - 3 additional largefiles cached + 6 additional largefiles cached $ cd .. Rebasing between two repositories does not revert largefiles to old @@ -919,8 +917,12 @@ $ cd d More rebase testing, but also test that the largefiles are downloaded from -'default' instead of 'default-push' when no source is specified (issue3584). -The error messages go away if repo 'b' is created with --all-largefiles. +'default-push' when no source is specified (issue3584). (The largefile from the +pulled revision is however not downloaded but found in the local cache.) +Largefiles are fetched for the new pulled revision, not for existing revisions, +rebased or not. + + $ [ ! -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ] $ hg pull --rebase --all-largefiles --config paths.default-push=bogus/path --config paths.default=../b pulling from $TESTTMP/b (glob) searching for changes @@ -932,18 +934,9 @@ M sub/normal4 M sub2/large6 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob) - error getting id eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 from url file:$TESTTMP/b for file large3: can't get file locally (glob) - error getting id eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 from url file:$TESTTMP/b for file sub/large4: can't get file locally (glob) - error getting id eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 from url file:$TESTTMP/b for file large1: can't get file locally (glob) - error getting id eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 from url file:$TESTTMP/b for file sub/large2: can't get file locally (glob) - error getting id eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 from url file:$TESTTMP/b for file sub/large2: can't get file locally (glob) - error getting id 5f78770c0e77ba4287ad6ef3071c9bf9c379742f from url file:$TESTTMP/b for file large1: can't get file locally (glob) - error getting id eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 from url file:$TESTTMP/b for file sub/large2: can't get file locally (glob) - error getting id 4669e532d5b2c093a78eca010077e708a071bb64 from url file:$TESTTMP/b for file large1: can't get file locally (glob) - error getting id 1deebade43c8c498a3c8daddac0244dc55d1331d from url file:$TESTTMP/b for file sub/large2: can't get file locally (glob) 0 additional largefiles cached - 9 largefiles failed to download nothing to rebase + $ [ -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ] $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 9:598410d3eb9a modify normal file largefile in repo d 8:a381d2c8c80e modify normal file and largefile in repo b @@ -974,8 +967,6 @@ adding file changes added 1 changesets with 2 changes to 2 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge) - caching largefiles for 1 heads - 0 largefiles cached $ hg rebase Invoking status precommit hook M sub/normal4 @@ -1233,10 +1224,76 @@ changeset 3:9e8fbc4bce62: large1 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob) changeset 4:74c02385b94c: large3 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob) changeset 4:74c02385b94c: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob) + changeset 5:9d5af5072dbd: large3 references missing $TESTTMP/d/.hg/largefiles/baaf12afde9d8d67f25dab6dced0d2bf77dba47c + changeset 5:9d5af5072dbd: sub/large4 references missing $TESTTMP/d/.hg/largefiles/aeb2210d19f02886dde00dac279729a48471e2f9 + changeset 6:4355d653f84f: large3 references missing $TESTTMP/d/.hg/largefiles/7838695e10da2bb75ac1156565f40a2595fa2fa0 [1] - cleanup $ rm $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 + $ rm -f .hglf/sub/*.orig + +Update to revision with missing largefile - and make sure it really is missing + + $ rm ${USERCACHE}/7838695e10da2bb75ac1156565f40a2595fa2fa0 + $ hg up -r 6 + getting changed largefiles + error getting id 7838695e10da2bb75ac1156565f40a2595fa2fa0 from url file:$TESTTMP/d for file large3: can't get file locally (glob) + 1 largefiles updated, 2 removed + 4 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ rm normal3 + $ echo >> sub/normal4 + $ hg ci -m 'commit with missing files' + Invoking status precommit hook + M sub/normal4 + ! large3 + ! normal3 + created new head + $ hg st + ! large3 + ! normal3 + $ hg up -r. + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg st + ! large3 + ! normal3 + $ hg up -Cr. + getting changed largefiles + error getting id 7838695e10da2bb75ac1156565f40a2595fa2fa0 from url file:$TESTTMP/d for file large3: can't get file locally (glob) + 0 largefiles updated, 0 removed + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg st + ! large3 + $ hg rollback + repository tip rolled back to revision 9 (undo commit) + working directory now based on revision 6 + +Merge with revision with missing largefile - and make sure it tries to fetch it. + + $ hg up -Cqr null + $ echo f > f + $ hg ci -Am branch + adding f + Invoking status precommit hook + A f + created new head + $ hg merge -r 6 + 4 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + getting changed largefiles + error getting id 7838695e10da2bb75ac1156565f40a2595fa2fa0 from url file:$TESTTMP/d for file large3: can't get file locally (glob) + 1 largefiles updated, 0 removed + + $ hg rollback -q + $ hg up -Cq + +Pulling 0 revisions with --all-largefiles should not fetch for all revisions + + $ hg pull --all-largefiles + pulling from $TESTTMP/d (glob) + searching for changes + no changes found + 0 additional largefiles cached Merging does not revert to old versions of largefiles and also check that merging after having pulled from a non-default remote works @@ -1265,7 +1322,8 @@ $ hg commit -m "Modify large4 to test merge" Invoking status precommit hook M sub/large4 - $ hg pull ../e +# Test --cache-largefiles flag + $ hg pull --cache-largefiles ../e pulling from ../e searching for changes adding changesets
--- a/tests/test-mq.t Sun Feb 17 14:41:31 2013 -0600 +++ b/tests/test-mq.t Thu Feb 28 21:58:37 2013 -0600 @@ -1567,12 +1567,13 @@ > wsgicgi.launch(app) > HGWEB $ . "$TESTDIR/cgienv" +#if msys + $ PATH_INFO=//tags; export PATH_INFO +#else $ PATH_INFO=/tags; export PATH_INFO +#endif $ QUERY_STRING='style=raw' - $ python hgweb.cgi | grep -v ETag: - Status: 200 Script output follows\r (esc) - Content-Type: text/plain; charset=ascii\r (esc) - \r (esc) + $ python hgweb.cgi | grep '^tip' tip [0-9a-f]{40} (re) $ cd ..
--- a/tests/test-obsolete.t Sun Feb 17 14:41:31 2013 -0600 +++ b/tests/test-obsolete.t Thu Feb 28 21:58:37 2013 -0600 @@ -816,7 +816,7 @@ summary: A $ hg incoming - comparing with $TESTTMP/tmpe/repo-issue3805 + comparing with $TESTTMP/tmpe/repo-issue3805 (glob) searching for changes changeset: 2:3816541e5485 tag: tip @@ -826,7 +826,7 @@ summary: A $ hg incoming --bundle ../issue3805.hg - comparing with $TESTTMP/tmpe/repo-issue3805 + comparing with $TESTTMP/tmpe/repo-issue3805 (glob) searching for changes changeset: 2:3816541e5485 tag: tip @@ -836,7 +836,7 @@ summary: A $ hg outgoing - comparing with $TESTTMP/tmpe/repo-issue3805 + comparing with $TESTTMP/tmpe/repo-issue3805 (glob) searching for changes no changes found [1]
--- a/tests/test-progress.t Sun Feb 17 14:41:31 2013 -0600 +++ b/tests/test-progress.t Thu Feb 28 21:58:37 2013 -0600 @@ -167,6 +167,7 @@ $ hg -y loop 8 \r (no-eol) (esc) + loop [====> ] 1/8 1m18s\r (no-eol) (esc) loop [=========> ] 2/8 1m07s\r (no-eol) (esc) loop [===============> ] 3/8 56s\r (no-eol) (esc) loop [=====================> ] 4/8 45s\r (no-eol) (esc) @@ -203,6 +204,7 @@ Time estimates should not fail when there's no end point: $ hg -y loop -- -4 \r (no-eol) (esc) - loop [ <=> ] 2\r (no-eol) (esc) - loop [ <=> ] 3\r (no-eol) (esc) + loop [ <=> ] 1\r (no-eol) (esc) + loop [ <=> ] 2\r (no-eol) (esc) + loop [ <=> ] 3\r (no-eol) (esc) \r (no-eol) (esc)
--- a/tests/test-subrepo.t Sun Feb 17 14:41:31 2013 -0600 +++ b/tests/test-subrepo.t Thu Feb 28 21:58:37 2013 -0600 @@ -269,9 +269,9 @@ $ cd .. $ hg clone t tc updating to branch default - cloning subrepo s from $TESTTMP/t/s (glob) + cloning subrepo s from $TESTTMP/t/s cloning subrepo s/ss from $TESTTMP/t/s/ss (glob) - cloning subrepo t from $TESTTMP/t/t (glob) + cloning subrepo t from $TESTTMP/t/t 3 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd tc $ hg debugsub @@ -292,10 +292,10 @@ pushing subrepo s/ss to $TESTTMP/t/s/ss (glob) searching for changes no changes found - pushing subrepo s to $TESTTMP/t/s (glob) + pushing subrepo s to $TESTTMP/t/s searching for changes no changes found - pushing subrepo t to $TESTTMP/t/t (glob) + pushing subrepo t to $TESTTMP/t/t searching for changes adding changesets adding manifests @@ -317,7 +317,7 @@ pushing subrepo s/ss to $TESTTMP/t/s/ss (glob) searching for changes no changes found - pushing subrepo s to $TESTTMP/t/s (glob) + pushing subrepo s to $TESTTMP/t/s searching for changes abort: push creates new remote head 12a213df6fa9! (in subrepo s) (did you forget to merge? use push -f to force) @@ -327,13 +327,13 @@ pushing subrepo s/ss to $TESTTMP/t/s/ss (glob) searching for changes no changes found - pushing subrepo s to $TESTTMP/t/s (glob) + pushing subrepo s to $TESTTMP/t/s searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) - pushing subrepo t to $TESTTMP/t/t (glob) + pushing subrepo t to $TESTTMP/t/t searching for changes no changes found searching for changes @@ -366,7 +366,7 @@ should pull t $ hg up - pulling subrepo t from $TESTTMP/t/t (glob) + pulling subrepo t from $TESTTMP/t/t searching for changes adding changesets adding manifests @@ -572,7 +572,7 @@ adding .hgsub $ hg clone repo repo2 updating to branch default - cloning subrepo s from $TESTTMP/repo/s (glob) + cloning subrepo s from $TESTTMP/repo/s 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg -q -R repo2 pull -u $ echo 1 > repo2/s/a
--- a/tests/test-walk.t Sun Feb 17 14:41:31 2013 -0600 +++ b/tests/test-walk.t Thu Feb 28 21:58:37 2013 -0600 @@ -155,7 +155,7 @@ abort: path 'mammals/.hg' is inside nested repo 'mammals' (glob) [255] $ hg debugwalk ../.hg - abort: path contains illegal component: .hg (glob) + abort: path contains illegal component: .hg [255] $ cd .. @@ -187,10 +187,10 @@ abort: beans/../.. not under root '$TESTTMP/t' (glob) [255] $ hg debugwalk .hg - abort: path contains illegal component: .hg (glob) + abort: path contains illegal component: .hg [255] $ hg debugwalk beans/../.hg - abort: path contains illegal component: .hg (glob) + abort: path contains illegal component: .hg [255] $ hg debugwalk beans/../.hg/data abort: path contains illegal component: .hg/data (glob)