Mercurial > hg
changeset 23272:394c79df66c3
merge with stable
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Wed, 12 Nov 2014 15:18:30 -0600 |
parents | 76302f5ceba4 (diff) 3246801ff313 (current diff) |
children | 236c978bceca |
files | |
diffstat | 108 files changed, 2144 insertions(+), 1724 deletions(-) [+] |
line wrap: on
line diff
--- a/contrib/Makefile.python Tue Nov 11 17:25:09 2014 -0600 +++ b/contrib/Makefile.python Wed Nov 12 15:18:30 2014 -0600 @@ -1,4 +1,4 @@ -PYTHONVER=2.7.6 +PYTHONVER=2.7.8 PYTHONNAME=python- PREFIX=$(HOME)/bin/prefix-$(PYTHONNAME)$(PYTHONVER) SYMLINKDIR=$(HOME)/bin @@ -27,7 +27,7 @@ # debian: apt-get install zlib1g-dev libbz2-dev libssl-dev @echo @echo 'To build a nice collection of interesting Python versions:' - @echo ' $$ for v in 2.{4{,.2,.3},5{,.6},6{,.1,.2,.9},7{,.6}}; do' + @echo ' $$ for v in 2.{4{,.2,.3},5{,.6},6{,.1,.2,.9},7{,.8}}; do' @echo ' make -f Makefile.python symlink PYTHONVER=$$v || break; done' @echo 'To run a Mercurial test on all these Python versions:' @echo ' $$ for py in `cd ~/bin && ls $(PYTHONNAME)2.*`; do' @@ -60,7 +60,7 @@ printf 'import sys, zlib, bz2\nif sys.version_info >= (2,6):\n import ssl' | $(PREFIX)/bin/python rm -rf $(PYTHON_SRCDIR) -DOCUTILSVER=0.11 +DOCUTILSVER=0.12 DOCUTILS_SRCDIR=docutils-$(DOCUTILSVER) DOCUTILS_SRCFILE=$(DOCUTILS_SRCDIR).tar.gz
--- a/contrib/buildrpm Tue Nov 11 17:25:09 2014 -0600 +++ b/contrib/buildrpm Wed Nov 12 15:18:30 2014 -0600 @@ -18,6 +18,7 @@ --withpython | --with-python) shift PYTHONVER=2.7.8 + PYTHONMD5=d4bca0159acb0b44a781292b5231936f ;; --rpmbuilddir ) shift @@ -76,11 +77,18 @@ cd build PYTHON_SRCFILE=Python-$PYTHONVER.tgz [ -f $PYTHON_SRCFILE ] || curl -Lo $PYTHON_SRCFILE http://www.python.org/ftp/python/$PYTHONVER/$PYTHON_SRCFILE + if [ "$PYTHONMD5" ]; then + echo "$PYTHONMD5 $PYTHON_SRCFILE" | md5sum -w -c + fi ln -f $PYTHON_SRCFILE $RPMBUILDDIR/SOURCES/$PYTHON_SRCFILE DOCUTILSVER=`sed -ne "s/^%global docutilsname docutils-//p" $specfile` DOCUTILS_SRCFILE=docutils-$DOCUTILSVER.tar.gz [ -f $DOCUTILS_SRCFILE ] || curl -Lo $DOCUTILS_SRCFILE http://downloads.sourceforge.net/project/docutils/docutils/$DOCUTILSVER/$DOCUTILS_SRCFILE + DOCUTILSMD5=`sed -ne "s/^%global docutilsmd5 //p" $specfile` + if [ "$DOCUTILSMD5" ]; then + echo "$DOCUTILSMD5 $DOCUTILS_SRCFILE" | md5sum -w -c + fi ln -f $DOCUTILS_SRCFILE $RPMBUILDDIR/SOURCES/$DOCUTILS_SRCFILE ) fi
--- a/contrib/check-code.py Tue Nov 11 17:25:09 2014 -0600 +++ b/contrib/check-code.py Wed Nov 12 15:18:30 2014 -0600 @@ -94,7 +94,7 @@ (r'sed.*-i', "don't use 'sed -i', use a temporary file"), (r'\becho\b.*\\n', "don't use 'echo \\n', use printf"), (r'echo -n', "don't use 'echo -n', use printf"), - (r'(^| )\bwc\b[^|]*$\n(?!.*\(re\))', "filter wc output"), + (r'(^|\|\s*)\bwc\b[^|]*$\n(?!.*\(re\))', "filter wc output"), (r'head -c', "don't use 'head -c', use 'dd'"), (r'tail -n', "don't use the '-n' option to tail, just use '-<num>'"), (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"), @@ -291,7 +291,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"), + (r'(?i)descend[e]nt', "the proper spelling is descendAnt"), (r'\.debug\(\_', "don't mark debug messages for translation"), (r'\.strip\(\)\.split\(\)', "no need to strip before splitting"), (r'^\s*except\s*:', "naked except clause", r'#.*re-raises'),
--- a/contrib/mercurial.spec Tue Nov 11 17:25:09 2014 -0600 +++ b/contrib/mercurial.spec Wed Nov 12 15:18:30 2014 -0600 @@ -6,7 +6,8 @@ %global pythonver %{withpython} %global pythonname Python-%{withpython} -%global docutilsname docutils-0.11 +%global docutilsname docutils-0.12 +%global docutilsmd5 4622263b62c5c771c03502afa3157768 %global pythonhg python-hg %global hgpyprefix /usr/%{pythonhg} # byte compilation will fail on some some Python /test/ files @@ -126,7 +127,6 @@ install -m 644 contrib/mq.el $RPM_BUILD_ROOT%{emacs_lispdir}/ mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/mercurial/hgrc.d -install -m 644 contrib/mergetools.hgrc $RPM_BUILD_ROOT%{_sysconfdir}/mercurial/hgrc.d/mergetools.rc %clean rm -rf $RPM_BUILD_ROOT @@ -149,7 +149,6 @@ %config(noreplace) %{_sysconfdir}/bash_completion.d/mercurial.sh %dir %{_sysconfdir}/mercurial %dir %{_sysconfdir}/mercurial/hgrc.d -%config(noreplace) %{_sysconfdir}/mercurial/hgrc.d/mergetools.rc %if "%{?withpython}" %{_bindir}/%{pythonhg} %{hgpyprefix}
--- a/contrib/mergetools.hgrc Tue Nov 11 17:25:09 2014 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -# Some default global settings for common merge tools - -[merge-tools] -kdiff3.args=--auto --L1 base --L2 local --L3 other $base $local $other -o $output -kdiff3.regkey=Software\KDiff3 -kdiff3.regkeyalt=Software\Wow6432Node\KDiff3 -kdiff3.regappend=\kdiff3.exe -kdiff3.fixeol=True -kdiff3.gui=True -kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child - -gvimdiff.args=--nofork -d -g -O $local $other $base -gvimdiff.regkey=Software\Vim\GVim -gvimdiff.regkeyalt=Software\Wow6432Node\Vim\GVim -gvimdiff.regname=path -gvimdiff.priority=-9 -gvimdiff.diffargs=--nofork -d -g -O $parent $child - -vimdiff.args=$local $other $base -c 'redraw | echomsg "hg merge conflict, type \":cq\" to abort vimdiff"' -vimdiff.check=changed -vimdiff.priority=-10 - -merge.check=conflicts -merge.priority=-100 - -gpyfm.gui=True - -meld.gui=True -meld.args=--label='local' $local --label='merged' $base --label='other' $other -o $output -meld.check=changed -meld.diffargs=-a --label='$plabel1' $parent --label='$clabel' $child - -tkdiff.args=$local $other -a $base -o $output -tkdiff.gui=True -tkdiff.priority=-8 -tkdiff.diffargs=-L '$plabel1' $parent -L '$clabel' $child - -xxdiff.args=--show-merged-pane --exit-with-merge-status --title1 local --title2 base --title3 other --merged-filename $output --merge $local $base $other -xxdiff.gui=True -xxdiff.priority=-8 -xxdiff.diffargs=--title1 '$plabel1' $parent --title2 '$clabel' $child - -diffmerge.regkey=Software\SourceGear\SourceGear DiffMerge\ -diffmerge.regkeyalt=Software\Wow6432Node\SourceGear\SourceGear DiffMerge\ -diffmerge.regname=Location -diffmerge.priority=-7 -diffmerge.args=-nosplash -merge -title1=local -title2=merged -title3=other $local $base $other -result=$output -diffmerge.check=changed -diffmerge.gui=True -diffmerge.diffargs=--nosplash --title1='$plabel1' --title2='$clabel' $parent $child - -p4merge.args=$base $local $other $output -p4merge.regkey=Software\Perforce\Environment -p4merge.regkeyalt=Software\Wow6432Node\Perforce\Environment -p4merge.regname=P4INSTROOT -p4merge.regappend=\p4merge.exe -p4merge.gui=True -p4merge.priority=-8 -p4merge.diffargs=$parent $child - -p4mergeosx.executable = /Applications/p4merge.app/Contents/MacOS/p4merge -p4mergeosx.args = $base $local $other $output -p4mergeosx.gui = True -p4mergeosx.priority=-8 -p4mergeosx.diffargs=$parent $child - -tortoisemerge.args=/base:$base /mine:$local /theirs:$other /merged:$output -tortoisemerge.regkey=Software\TortoiseSVN -tortoisemerge.regkeyalt=Software\Wow6432Node\TortoiseSVN -tortoisemerge.check=changed -tortoisemerge.gui=True -tortoisemerge.priority=-8 -tortoisemerge.diffargs=/base:$parent /mine:$child /basename:'$plabel1' /minename:'$clabel' - -ecmerge.args=$base $local $other --mode=merge3 --title0=base --title1=local --title2=other --to=$output -ecmerge.regkey=Software\Elli\xc3\xa9 Computing\Merge -ecmerge.regkeyalt=Software\Wow6432Node\Elli\xc3\xa9 Computing\Merge -ecmerge.gui=True -ecmerge.diffargs=$parent $child --mode=diff2 --title1='$plabel1' --title2='$clabel' - -# editmerge is a small script shipped in contrib. -# It needs this config otherwise it behaves the same as internal:local -editmerge.args=$output -editmerge.check=changed -editmerge.premerge=keep - -filemerge.executable=/Developer/Applications/Utilities/FileMerge.app/Contents/MacOS/FileMerge -filemerge.args=-left $other -right $local -ancestor $base -merge $output -filemerge.gui=True - -; Windows version of Beyond Compare -beyondcompare3.args=$local $other $base $output /ro /lefttitle=local /centertitle=base /righttitle=other /automerge /reviewconflicts /solo -beyondcompare3.regkey=Software\Scooter Software\Beyond Compare 3 -beyondcompare3.regname=ExePath -beyondcompare3.gui=True -beyondcompare3.priority=-2 -beyondcompare3.diffargs=/lro /lefttitle='$plabel1' /righttitle='$clabel' /solo /expandall $parent $child - -; Linux version of Beyond Compare -bcompare.args=$local $other $base -mergeoutput=$output -ro -lefttitle=parent1 -centertitle=base -righttitle=parent2 -outputtitle=merged -automerge -reviewconflicts -solo -bcompare.gui=True -bcompare.priority=-1 -bcompare.diffargs=-lro -lefttitle='$plabel1' -righttitle='$clabel' -solo -expandall $parent $child - -winmerge.args=/e /x /wl /ub /dl other /dr local $other $local $output -winmerge.regkey=Software\Thingamahoochie\WinMerge -winmerge.regkeyalt=Software\Wow6432Node\Thingamahoochie\WinMerge\ -winmerge.regname=Executable -winmerge.check=changed -winmerge.gui=True -winmerge.priority=-10 -winmerge.diffargs=/r /e /x /ub /wl /dl '$plabel1' /dr '$clabel' $parent $child - -araxis.regkey=SOFTWARE\Classes\TypeLib\{46799e0a-7bd1-4330-911c-9660bb964ea2}\7.0\HELPDIR -araxis.regappend=\ConsoleCompare.exe -araxis.priority=-2 -araxis.args=/3 /a2 /wait /merge /title1:"Other" /title2:"Base" /title3:"Local :"$local $other $base $local $output -araxis.checkconflict=True -araxis.binary=True -araxis.gui=True -araxis.diffargs=/2 /wait /title1:"$plabel1" /title2:"$clabel" $parent $child - -diffuse.priority=-3 -diffuse.args=$local $base $other -diffuse.gui=True -diffuse.diffargs=$parent $child - -UltraCompare.regkey=Software\Microsoft\Windows\CurrentVersion\App Paths\UC.exe -UltraCompare.regkeyalt=Software\Wow6432Node\Microsoft\Windows\CurrentVersion\App Paths\UC.exe -UltraCompare.args = $base $local $other -title1 base -title3 other -UltraCompare.priority = -2 -UltraCompare.gui = True -UltraCompare.binary = True -UltraCompare.check = conflicts,changed -UltraCompare.diffargs=$child $parent -title1 $clabel -title2 $plabel1
--- a/contrib/perf.py Tue Nov 11 17:25:09 2014 -0600 +++ b/contrib/perf.py Wed Nov 12 15:18:30 2014 -0600 @@ -4,11 +4,26 @@ from mercurial import cmdutil, scmutil, util, commands, obsolete from mercurial import repoview, branchmap, merge, copies import time, os, sys +import functools cmdtable = {} command = cmdutil.command(cmdtable) -def timer(func, title=None): +def gettimer(ui, opts=None): + """return a timer function and formatter: (timer, formatter) + + This functions exist to gather the creation of formatter in a single + place instead of duplicating it in all performance command.""" + if opts is None: + opts = {} + # redirect all to stderr + ui = ui.copy() + ui.fout = ui.ferr + # get a formatter + fm = ui.formatter('perf', opts) + return functools.partial(_timer, fm), fm + +def _timer(fm, func, title=None): results = [] begin = time.time() count = 0 @@ -25,16 +40,25 @@ break if cstop - begin > 10 and count >= 3: break + + fm.startitem() + if title: - sys.stderr.write("! %s\n" % title) + fm.write('title', '! %s\n', title) if r: - sys.stderr.write("! result: %s\n" % r) + fm.write('result', '! result: %s\n', r) m = min(results) - sys.stderr.write("! wall %f comb %f user %f sys %f (best of %d)\n" - % (m[0], m[1] + m[2], m[1], m[2], count)) + fm.plain('!') + fm.write('wall', ' wall %f', m[0]) + fm.write('comb', ' comb %f', m[1] + m[2]) + fm.write('user', ' user %f', m[1]) + fm.write('sys', ' sys %f', m[2]) + fm.write('count', ' (best of %d)', count) + fm.plain('\n') @command('perfwalk') def perfwalk(ui, repo, *pats): + timer, fm = gettimer(ui) try: m = scmutil.match(repo[None], pats, {}) timer(lambda: len(list(repo.dirstate.walk(m, [], True, False)))) @@ -44,11 +68,14 @@ timer(lambda: len([b for a, b, c in repo.dirstate.statwalk([], m)])) except Exception: timer(lambda: len(list(cmdutil.walk(repo, pats, {})))) + fm.end() @command('perfannotate') def perfannotate(ui, repo, f): + timer, fm = gettimer(ui) fc = repo['.'][f] timer(lambda: len(fc.annotate(True))) + fm.end() @command('perfstatus', [('u', 'unknown', False, @@ -57,16 +84,20 @@ #m = match.always(repo.root, repo.getcwd()) #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False, # False)))) + timer, fm = gettimer(ui) timer(lambda: sum(map(len, repo.status(**opts)))) + fm.end() @command('perfaddremove') def perfaddremove(ui, repo): + timer, fm = gettimer(ui) try: oldquiet = repo.ui.quiet repo.ui.quiet = True timer(lambda: scmutil.addremove(repo, dry_run=True)) finally: repo.ui.quiet = oldquiet + fm.end() def clearcaches(cl): # behave somewhat consistently across internal API changes @@ -79,33 +110,40 @@ @command('perfheads') def perfheads(ui, repo): + timer, fm = gettimer(ui) cl = repo.changelog def d(): len(cl.headrevs()) clearcaches(cl) timer(d) + fm.end() @command('perftags') def perftags(ui, repo): import mercurial.changelog import mercurial.manifest + timer, fm = gettimer(ui) def t(): repo.changelog = mercurial.changelog.changelog(repo.sopener) repo.manifest = mercurial.manifest.manifest(repo.sopener) repo._tags = None return len(repo.tags()) timer(t) + fm.end() @command('perfancestors') def perfancestors(ui, repo): + timer, fm = gettimer(ui) heads = repo.changelog.headrevs() def d(): for a in repo.changelog.ancestors(heads): pass timer(d) + fm.end() @command('perfancestorset') def perfancestorset(ui, repo, revset): + timer, fm = gettimer(ui) revs = repo.revs(revset) heads = repo.changelog.headrevs() def d(): @@ -113,34 +151,42 @@ for rev in revs: rev in s timer(d) + fm.end() @command('perfdirs') def perfdirs(ui, repo): + timer, fm = gettimer(ui) dirstate = repo.dirstate 'a' in dirstate def d(): dirstate.dirs() del dirstate._dirs timer(d) + fm.end() @command('perfdirstate') def perfdirstate(ui, repo): + timer, fm = gettimer(ui) "a" in repo.dirstate def d(): repo.dirstate.invalidate() "a" in repo.dirstate timer(d) + fm.end() @command('perfdirstatedirs') def perfdirstatedirs(ui, repo): + timer, fm = gettimer(ui) "a" in repo.dirstate def d(): "a" in repo.dirstate._dirs del repo.dirstate._dirs timer(d) + fm.end() @command('perfdirstatefoldmap') def perffoldmap(ui, repo): + timer, fm = gettimer(ui) dirstate = repo.dirstate 'a' in dirstate def d(): @@ -148,19 +194,23 @@ del dirstate._foldmap del dirstate._dirs timer(d) + fm.end() @command('perfdirstatewrite') def perfdirstatewrite(ui, repo): + timer, fm = gettimer(ui) ds = repo.dirstate "a" in ds def d(): ds._dirty = True ds.write() timer(d) + fm.end() @command('perfmergecalculate', [('r', 'rev', '.', 'rev to merge against')]) def perfmergecalculate(ui, repo, rev): + timer, fm = gettimer(ui) wctx = repo[None] rctx = scmutil.revsingle(repo, rev, rev) ancestor = wctx.ancestor(rctx) @@ -173,17 +223,21 @@ merge.calculateupdates(repo, wctx, rctx, ancestor, False, False, False, acceptremote=True) timer(d) + fm.end() @command('perfpathcopies', [], "REV REV") def perfpathcopies(ui, repo, rev1, rev2): + timer, fm = gettimer(ui) ctx1 = scmutil.revsingle(repo, rev1, rev1) ctx2 = scmutil.revsingle(repo, rev2, rev2) def d(): copies.pathcopies(ctx1, ctx2) timer(d) + fm.end() @command('perfmanifest', [], 'REV') def perfmanifest(ui, repo, rev): + timer, fm = gettimer(ui) ctx = scmutil.revsingle(repo, rev, rev) t = ctx.manifestnode() def d(): @@ -191,51 +245,65 @@ repo.manifest._cache = None repo.manifest.read(t) timer(d) + fm.end() @command('perfchangeset') def perfchangeset(ui, repo, rev): + timer, fm = gettimer(ui) n = repo[rev].node() def d(): repo.changelog.read(n) #repo.changelog._cache = None timer(d) + fm.end() @command('perfindex') def perfindex(ui, repo): import mercurial.revlog + timer, fm = gettimer(ui) mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg n = repo["tip"].node() def d(): cl = mercurial.revlog.revlog(repo.sopener, "00changelog.i") cl.rev(n) timer(d) + fm.end() @command('perfstartup') def perfstartup(ui, repo): + timer, fm = gettimer(ui) cmd = sys.argv[0] def d(): os.system("HGRCPATH= %s version -q > /dev/null" % cmd) timer(d) + fm.end() @command('perfparents') def perfparents(ui, repo): + timer, fm = gettimer(ui) nl = [repo.changelog.node(i) for i in xrange(1000)] def d(): for n in nl: repo.changelog.parents(n) timer(d) + fm.end() @command('perflookup') def perflookup(ui, repo, rev): + timer, fm = gettimer(ui) timer(lambda: len(repo.lookup(rev))) + fm.end() @command('perfrevrange') def perfrevrange(ui, repo, *specs): + timer, fm = gettimer(ui) revrange = scmutil.revrange timer(lambda: len(revrange(repo, specs))) + fm.end() @command('perfnodelookup') def perfnodelookup(ui, repo, rev): + timer, fm = gettimer(ui) import mercurial.revlog mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg n = repo[rev].node() @@ -244,14 +312,17 @@ cl.rev(n) clearcaches(cl) timer(d) + fm.end() @command('perflog', [('', 'rename', False, 'ask log to follow renames')]) def perflog(ui, repo, **opts): + timer, fm = gettimer(ui) ui.pushbuffer() timer(lambda: commands.log(ui, repo, rev=[], date='', user='', copies=opts.get('rename'))) ui.popbuffer() + fm.end() @command('perfmoonwalk') def perfmoonwalk(ui, repo): @@ -259,52 +330,65 @@ This also loads the changelog data for each revision in the changelog. """ + timer, fm = gettimer(ui) def moonwalk(): for i in xrange(len(repo), -1, -1): ctx = repo[i] ctx.branch() # read changelog data (in addition to the index) timer(moonwalk) + fm.end() @command('perftemplating') def perftemplating(ui, repo): + timer, fm = gettimer(ui) ui.pushbuffer() timer(lambda: commands.log(ui, repo, rev=[], date='', user='', template='{date|shortdate} [{rev}:{node|short}]' ' {author|person}: {desc|firstline}\n')) ui.popbuffer() + fm.end() @command('perfcca') def perfcca(ui, repo): + timer, fm = gettimer(ui) timer(lambda: scmutil.casecollisionauditor(ui, False, repo.dirstate)) + fm.end() @command('perffncacheload') def perffncacheload(ui, repo): + timer, fm = gettimer(ui) s = repo.store def d(): s.fncache._load() timer(d) + fm.end() @command('perffncachewrite') def perffncachewrite(ui, repo): + timer, fm = gettimer(ui) s = repo.store s.fncache._load() def d(): s.fncache._dirty = True s.fncache.write() timer(d) + fm.end() @command('perffncacheencode') def perffncacheencode(ui, repo): + timer, fm = gettimer(ui) s = repo.store s.fncache._load() def d(): for p in s.fncache.entries: s.encode(p) timer(d) + fm.end() @command('perfdiffwd') def perfdiffwd(ui, repo): """Profile diff of working directory changes""" + timer, fm = gettimer(ui) options = { 'w': 'ignore_all_space', 'b': 'ignore_space_change', @@ -319,11 +403,13 @@ ui.popbuffer() title = 'diffopts: %s' % (diffopt and ('-' + diffopt) or 'none') timer(d, title) + fm.end() @command('perfrevlog', [('d', 'dist', 100, 'distance between the revisions')], "[INDEXFILE]") def perfrevlog(ui, repo, file_, **opts): + timer, fm = gettimer(ui) from mercurial import revlog dist = opts['dist'] def d(): @@ -332,6 +418,7 @@ r.revision(r.node(x)) timer(d) + fm.end() @command('perfrevset', [('C', 'clear', False, 'clear volatile cache between each call.')], @@ -342,17 +429,20 @@ Use the --clean option if need to evaluate the impact of build volatile revisions set cache on the revset execution. Volatile cache hold filtered and obsolete related cache.""" + timer, fm = gettimer(ui) def d(): if clear: repo.invalidatevolatilesets() for r in repo.revs(expr): pass timer(d) + fm.end() @command('perfvolatilesets') def perfvolatilesets(ui, repo, *names): """benchmark the computation of various volatile set Volatile set computes element related to filtering and obsolescence.""" + timer, fm = gettimer(ui) repo = repo.unfiltered() def getobs(name): @@ -380,6 +470,7 @@ for name in allfilter: timer(getfiltered(name), title=name) + fm.end() @command('perfbranchmap', [('f', 'full', False, @@ -390,6 +481,7 @@ This benchmarks the full repo.branchmap() call with read and write disabled """ + timer, fm = gettimer(ui) def getbranchmap(filtername): """generate a benchmark function for the filtername""" if filtername is None: @@ -432,3 +524,4 @@ finally: branchmap.read = oldread branchmap.branchcache.write = oldwrite + fm.end()
--- a/contrib/revsetbenchmarks.py Tue Nov 11 17:25:09 2014 -0600 +++ b/contrib/revsetbenchmarks.py Wed Nov 12 15:18:30 2014 -0600 @@ -74,7 +74,7 @@ parser = OptionParser(usage="usage: %prog [options] <revs>") parser.add_option("-f", "--file", - help="read revset from FILE (stdin if omited)", + help="read revset from FILE (stdin if omitted)", metavar="FILE") parser.add_option("-R", "--repo", help="run benchmark on REPO", metavar="REPO")
--- a/contrib/synthrepo.py Tue Nov 11 17:25:09 2014 -0600 +++ b/contrib/synthrepo.py Wed Nov 12 15:18:30 2014 -0600 @@ -410,16 +410,18 @@ break if filesadded: dirs = list(pctx.dirs()) - dirs.append('') + dirs.insert(0, '') for __ in xrange(pick(filesadded)): - path = [random.choice(dirs)] - if pick(dirsadded): + pathstr = '' + while pathstr in dirs: + path = [random.choice(dirs)] + if pick(dirsadded): + path.append(random.choice(words)) path.append(random.choice(words)) - path.append(random.choice(words)) - path = '/'.join(filter(None, path)) + pathstr = '/'.join(filter(None, path)) data = '\n'.join(makeline() for __ in xrange(pick(linesinfilesadded))) + '\n' - changes[path] = context.memfilectx(repo, path, data) + changes[pathstr] = context.memfilectx(repo, pathstr, data) def filectxfn(repo, memctx, path): return changes[path] if not changes: @@ -428,6 +430,8 @@ date = repo['tip'].date()[0] + pick(interarrival) else: date = time.time() - (86400 * count) + # dates in mercurial must be positive, fit in 32-bit signed integers. + date = min(0x7fffffff, max(0, date)) user = random.choice(words) + '@' + random.choice(words) mc = context.memctx(repo, pl, makeline(minimum=2), sorted(changes.iterkeys()),
--- a/contrib/win32/mercurial.iss Tue Nov 11 17:25:09 2014 -0600 +++ b/contrib/win32/mercurial.iss Wed Nov 12 15:18:30 2014 -0600 @@ -67,8 +67,6 @@ Source: contrib\hgweb.fcgi; DestDir: {app}/Contrib Source: contrib\hgweb.wsgi; DestDir: {app}/Contrib Source: contrib\win32\ReadMe.html; DestDir: {app}; Flags: isreadme -Source: contrib\mergetools.hgrc; DestDir: {tmp}; -Source: contrib\win32\mercurial.ini; DestDir: {app}; DestName: Mercurial.ini; Check: CheckFile; AfterInstall: ConcatenateFiles; Source: contrib\win32\postinstall.txt; DestDir: {app}; DestName: ReleaseNotes.txt Source: dist\hg.exe; DestDir: {app}; AfterInstall: Touch('{app}\hg.exe.local') #if ARCH == "x64" @@ -86,6 +84,7 @@ Source: doc\*.html; DestDir: {app}\Docs Source: doc\style.css; DestDir: {app}\Docs Source: mercurial\help\*.txt; DestDir: {app}\help +Source: mercurial\default.d\*.rc; DestDir: {app}\default.d Source: mercurial\locale\*.*; DestDir: {app}\locale; Flags: recursesubdirs createallsubdirs skipifsourcedoesntexist Source: mercurial\templates\*.*; DestDir: {app}\Templates; Flags: recursesubdirs createallsubdirs Source: CONTRIBUTORS; DestDir: {app}; DestName: Contributors.txt @@ -93,10 +92,13 @@ [INI] Filename: {app}\Mercurial.url; Section: InternetShortcut; Key: URL; String: http://mercurial.selenic.com/ -Filename: {app}\Mercurial.ini; Section: web; Key: cacerts; String: {app}\cacert.pem +Filename: {app}\default.d\editor.rc; Section: ui; Key: editor; String: notepad +Filename: {app}\default.d\cacerts.rc; Section: web; Key: cacerts; String: {app}\cacert.pem [UninstallDelete] Type: files; Name: {app}\Mercurial.url +Type: filesandordirs; Name: {app}\default.d +Type: files; Name: "{app}\hg.exe.local" [Icons] Name: {group}\Uninstall Mercurial; Filename: {uninstallexe} @@ -111,35 +113,7 @@ [UninstallRun] Filename: "{app}\add_path.exe"; Parameters: "/del {app}" -[UninstallDelete] -Type: files; Name: "{app}\hg.exe.local" - [Code] -var - WriteFile: Boolean; - CheckDone: Boolean; - -function CheckFile(): Boolean; -begin - if not CheckDone then begin - WriteFile := True; - if FileExists(ExpandConstant(CurrentFileName)) then begin - WriteFile := MsgBox('' + ExpandConstant(CurrentFileName) + '' #13#13 'The file already exists.' #13#13 'Would you like Setup to overwrite it?', mbConfirmation, MB_YESNO) = idYes; - end; - CheckDone := True; - end; - Result := WriteFile; -end; - -procedure ConcatenateFiles(); -var - MergeConfigs: TArrayOfString; -begin - if LoadStringsFromFile(ExpandConstant('{tmp}\mergetools.hgrc'),MergeConfigs) then begin - SaveStringsToFile(ExpandConstant(CurrentFileName),MergeConfigs,True); - end; -end; - procedure Touch(fn: String); begin SaveStringToFile(ExpandConstant(fn), '', False);
--- a/contrib/wix/mercurial.wxs Tue Nov 11 17:25:09 2014 -0600 +++ b/contrib/wix/mercurial.wxs Wed Nov 12 15:18:30 2014 -0600 @@ -79,7 +79,7 @@ ReadOnly='yes' KeyPath='yes'/> </Component> <Component Id='mergetools.rc' Guid='$(var.mergetools.rc.guid)' Win64='$(var.IsX64)'> - <File Id='mergetools.rc' Name='MergeTools.rc' Source='contrib\mergetools.hgrc' + <File Id='mergetools.rc' Name='MergeTools.rc' Source='mercurial\default.d\mergetools.rc' ReadOnly='yes' KeyPath='yes'/> </Component> <Component Id='paths.rc' Guid='$(var.paths.rc.guid)' Win64='$(var.IsX64)'>
--- a/hgext/color.py Tue Nov 11 17:25:09 2014 -0600 +++ b/hgext/color.py Wed Nov 12 15:18:30 2014 -0600 @@ -301,6 +301,11 @@ 'histedit.remaining': 'red bold', 'ui.prompt': 'yellow', 'log.changeset': 'yellow', + 'patchbomb.finalsummary': '', + 'patchbomb.from': 'magenta', + 'patchbomb.to': 'cyan', + 'patchbomb.subject': 'green', + 'patchbomb.diffstats': '', 'rebase.rebased': 'blue', 'rebase.remaining': 'red bold', 'resolve.resolved': 'green bold',
--- a/hgext/extdiff.py Tue Nov 11 17:25:09 2014 -0600 +++ b/hgext/extdiff.py Wed Nov 12 15:18:30 2014 -0600 @@ -23,10 +23,9 @@ #cmd.cdiff = gdiff #opts.cdiff = -Nprc5 - # add new command called vdiff, runs kdiff3 - vdiff = kdiff3 - - # add new command called meld, runs meld (no need to name twice) + # add new command called meld, runs meld (no need to name twice). If + # the meld executable is not available, the meld tool in [merge-tools] + # will be used, if available meld = # add new command called vimdiff, runs gvimdiff with DirDiff plugin @@ -63,7 +62,7 @@ from mercurial.i18n import _ from mercurial.node import short, nullid -from mercurial import cmdutil, scmutil, util, commands, encoding +from mercurial import cmdutil, scmutil, util, commands, encoding, filemerge import os, shlex, shutil, tempfile, re cmdtable = {} @@ -90,7 +89,7 @@ wopener = scmutil.opener(base) fns_and_mtime = [] ctx = repo[node] - for fn in files: + for fn in sorted(files): wfn = util.pconvert(fn) if wfn not in ctx: # File doesn't exist; could be a bogus modify @@ -227,7 +226,7 @@ cmdline = util.shellquote(diffcmd) + ' ' + args ui.debug('running %r in %s\n' % (cmdline, tmproot)) - util.system(cmdline, cwd=tmproot, out=ui.fout) + ui.system(cmdline, cwd=tmproot) for copy_fn, working_fn, mtime in fns_and_mtime: if os.lstat(copy_fn).st_mtime != mtime: @@ -279,7 +278,9 @@ if cmd.startswith('cmd.'): cmd = cmd[4:] if not path: - path = cmd + path = util.findexe(cmd) + if path is None: + path = filemerge.findexternaltool(ui, cmd) or cmd diffopts = shlex.split(ui.config('extdiff', 'opts.' + cmd, '')) elif cmd.startswith('opts.'): continue @@ -289,7 +290,9 @@ diffopts = shlex.split(path) path = diffopts.pop(0) else: - path, diffopts = cmd, [] + path, diffopts = util.findexe(cmd), [] + if path is None: + path = filemerge.findexternaltool(ui, cmd) or cmd # look for diff arguments in [diff-tools] then [merge-tools] if diffopts == []: args = ui.config('diff-tools', cmd+'.diffargs') or \
--- a/hgext/hgk.py Tue Nov 11 17:25:09 2014 -0600 +++ b/hgext/hgk.py Wed Nov 12 15:18:30 2014 -0600 @@ -35,7 +35,7 @@ ''' import os -from mercurial import cmdutil, commands, util, patch, revlog, scmutil +from mercurial import cmdutil, commands, patch, revlog, scmutil from mercurial.node import nullid, nullrev, short from mercurial.i18n import _ @@ -349,4 +349,4 @@ optstr = ' '.join(['--%s %s' % (k, v) for k, v in opts.iteritems() if v]) cmd = ui.config("hgk", "path", "hgk") + " %s %s" % (optstr, " ".join(etc)) ui.debug("running %s\n" % cmd) - util.system(cmd) + ui.system(cmd)
--- a/hgext/largefiles/lfcommands.py Tue Nov 11 17:25:09 2014 -0600 +++ b/hgext/largefiles/lfcommands.py Wed Nov 12 15:18:30 2014 -0600 @@ -435,8 +435,14 @@ ui.status(_("%d largefiles failed to download\n") % totalmissing) return totalsuccess, totalmissing -def updatelfiles(ui, repo, filelist=None, printmessage=True, +def updatelfiles(ui, repo, filelist=None, printmessage=None, normallookup=False): + '''Update largefiles according to standins in the working directory + + If ``printmessage`` is other than ``None``, it means "print (or + ignore, for false) message forcibly". + ''' + statuswriter = lfutil.getstatuswriter(ui, repo, printmessage) wlock = repo.wlock() try: lfdirstate = lfutil.openlfdirstate(ui, repo) @@ -462,10 +468,10 @@ expecthash != lfutil.hashfile(abslfile))): if lfile not in repo[None]: # not switched to normal file util.unlinkpath(abslfile, ignoremissing=True) - # use normallookup() to allocate entry in largefiles + # use normallookup() to allocate an entry in largefiles # dirstate, because lack of it misleads # lfilesrepo.status() into recognition that such cache - # missing files are REMOVED. + # missing files are removed. lfdirstate.normallookup(lfile) update[lfile] = expecthash else: @@ -482,8 +488,7 @@ lfdirstate.write() if lfiles: - if printmessage: - ui.status(_('getting changed largefiles\n')) + statuswriter(_('getting changed largefiles\n')) cachelfiles(ui, repo, None, lfiles) for lfile in lfiles: @@ -527,8 +532,8 @@ lfutil.synclfdirstate(repo, lfdirstate, lfile, True) lfdirstate.write() - if printmessage and lfiles: - ui.status(_('%d largefiles updated, %d removed\n') % (updated, + if lfiles: + statuswriter(_('%d largefiles updated, %d removed\n') % (updated, removed)) finally: wlock.release()
--- a/hgext/largefiles/lfutil.py Tue Nov 11 17:25:09 2014 -0600 +++ b/hgext/largefiles/lfutil.py Wed Nov 12 15:18:30 2014 -0600 @@ -12,6 +12,7 @@ import platform import shutil import stat +import copy from mercurial import dirstate, httpconnection, match as match_, util, scmutil from mercurial.i18n import _ @@ -386,6 +387,18 @@ elif state == '?': lfdirstate.drop(lfile) +def markcommitted(orig, ctx, node): + repo = ctx._repo + + orig(node) + + lfdirstate = openlfdirstate(repo.ui, repo) + for f in ctx.files(): + if isstandin(f): + lfile = splitstandin(f) + synclfdirstate(repo, lfdirstate, lfile, False) + lfdirstate.write() + def getlfilestoupdate(oldstandins, newstandins): changedstandins = set(oldstandins).symmetric_difference(set(newstandins)) filelist = [] @@ -415,3 +428,149 @@ for fn in files: if isstandin(fn) and fn in ctx: addfunc(fn, ctx[fn].data().strip()) + +def updatestandinsbymatch(repo, match): + '''Update standins in the working directory according to specified match + + This returns (possibly modified) ``match`` object to be used for + subsequent commit process. + ''' + + ui = repo.ui + + # Case 0: Automated committing + # + # While automated committing (like rebase, transplant + # and so on), this code path is used to avoid: + # (1) updating standins, because standins should + # be already updated at this point + # (2) aborting when standins are matched by "match", + # because automated committing may specify them directly + # + if getattr(repo, "_istransplanting", False): + return match + + # Case 1: user calls commit with no specific files or + # include/exclude patterns: refresh and commit all files that + # are "dirty". + if match is None or match.always(): + # Spend a bit of time here to get a list of files we know + # are modified so we can compare only against those. + # It can cost a lot of time (several seconds) + # otherwise to update all standins if the largefiles are + # large. + lfdirstate = openlfdirstate(ui, repo) + dirtymatch = match_.always(repo.root, repo.getcwd()) + unsure, s = lfdirstate.status(dirtymatch, [], False, False, + False) + modifiedfiles = unsure + s.modified + s.added + s.removed + lfiles = listlfiles(repo) + # this only loops through largefiles that exist (not + # removed/renamed) + for lfile in lfiles: + if lfile in modifiedfiles: + if os.path.exists( + repo.wjoin(standin(lfile))): + # this handles the case where a rebase is being + # performed and the working copy is not updated + # yet. + if os.path.exists(repo.wjoin(lfile)): + updatestandin(repo, + standin(lfile)) + + return match + + lfiles = listlfiles(repo) + match._files = repo._subdirlfs(match.files(), lfiles) + + # Case 2: user calls commit with specified patterns: refresh + # any matching big files. + smatcher = composestandinmatcher(repo, match) + standins = repo.dirstate.walk(smatcher, [], False, False) + + # No matching big files: get out of the way and pass control to + # the usual commit() method. + if not standins: + return match + + # Refresh all matching big files. It's possible that the + # commit will end up failing, in which case the big files will + # stay refreshed. No harm done: the user modified them and + # asked to commit them, so sooner or later we're going to + # refresh the standins. Might as well leave them refreshed. + lfdirstate = openlfdirstate(ui, repo) + for fstandin in standins: + lfile = splitstandin(fstandin) + if lfdirstate[lfile] != 'r': + updatestandin(repo, fstandin) + + # Cook up a new matcher that only matches regular files or + # standins corresponding to the big files requested by the + # user. Have to modify _files to prevent commit() from + # complaining "not tracked" for big files. + match = copy.copy(match) + origmatchfn = match.matchfn + + # Check both the list of largefiles and the list of + # standins because if a largefile was removed, it + # won't be in the list of largefiles at this point + match._files += sorted(standins) + + actualfiles = [] + for f in match._files: + fstandin = standin(f) + + # ignore known largefiles and standins + if f in lfiles or fstandin in standins: + continue + + actualfiles.append(f) + match._files = actualfiles + + def matchfn(f): + if origmatchfn(f): + return f not in lfiles + else: + return f in standins + + match.matchfn = matchfn + + return match + +class automatedcommithook(object): + '''Statefull hook to update standins at the 1st commit of resuming + + For efficiency, updating standins in the working directory should + be avoided while automated committing (like rebase, transplant and + so on), because they should be updated before committing. + + But the 1st commit of resuming automated committing (e.g. ``rebase + --continue``) should update them, because largefiles may be + modified manually. + ''' + def __init__(self, resuming): + self.resuming = resuming + + def __call__(self, repo, match): + if self.resuming: + self.resuming = False # avoids updating at subsequent commits + return updatestandinsbymatch(repo, match) + else: + return match + +def getstatuswriter(ui, repo, forcibly=None): + '''Return the function to write largefiles specific status out + + If ``forcibly`` is ``None``, this returns the last element of + ``repo._lfupdatereporters`` as "default" writer function. + + Otherwise, this returns the function to always write out (or + ignore if ``not forcibly``) status. + ''' + if forcibly is None: + return repo._lfstatuswriters[-1] + else: + if forcibly: + return ui.status # forcibly WRITE OUT + else: + return lambda *msg, **opts: None # forcibly IGNORE
--- a/hgext/largefiles/overrides.py Tue Nov 11 17:25:09 2014 -0600 +++ b/hgext/largefiles/overrides.py Wed Nov 12 15:18:30 2014 -0600 @@ -11,11 +11,10 @@ import os import copy -from mercurial import hg, commands, util, cmdutil, scmutil, match as match_, \ +from mercurial import hg, util, cmdutil, scmutil, match as match_, \ archival, pathutil, revset from mercurial.i18n import _ from mercurial.node import hex -from hgext import rebase import lfutil import lfcommands @@ -35,7 +34,7 @@ m._fmap = set(m._files) m._always = False origmatchfn = m.matchfn - m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None + m.matchfn = lambda f: notlfile(f) and origmatchfn(f) return m oldmatch = installmatchfn(overridematch) @@ -63,10 +62,10 @@ def restorematchandpatsfn(): '''restores scmutil.matchandpats to what it was before - installnormalfilesmatchandpatsfn was called. no-op if scmutil.matchandpats + installmatchandpatsfn was called. No-op if scmutil.matchandpats is its original function. - Note that n calls to installnormalfilesmatchandpatsfn will require n calls + Note that n calls to installmatchandpatsfn will require n calls to restore matchfn to reverse''' scmutil.matchandpats = getattr(scmutil.matchandpats, 'oldmatchandpats', scmutil.matchandpats) @@ -576,7 +575,6 @@ lfile = lambda f: lfutil.standin(f) in manifest m._files = [lfutil.standin(f) for f in m._files if lfile(f)] m._fmap = set(m._files) - m._always = False origmatchfn = m.matchfn m.matchfn = lambda f: (lfutil.isstandin(f) and (f in manifest) and @@ -684,7 +682,6 @@ m._files = [tostandin(f) for f in m._files] m._files = [f for f in m._files if f is not None] m._fmap = set(m._files) - m._always = False origmatchfn = m.matchfn def matchfn(f): if lfutil.isstandin(f): @@ -712,37 +709,14 @@ finally: wlock.release() -# When we rebase a repository with remotely changed largefiles, we need to -# take some extra care so that the largefiles are correctly updated in the -# working copy +# after pulling changesets, we need to take some extra care to get +# largefiles updated remotely def overridepull(orig, ui, repo, source=None, **opts): revsprepull = len(repo) if not source: source = 'default' repo.lfpullsource = source - if opts.get('rebase', False): - repo._isrebasing = True - try: - if opts.get('update'): - del opts['update'] - ui.debug('--update and --rebase are not compatible, ignoring ' - 'the update flag\n') - del opts['rebase'] - origpostincoming = commands.postincoming - def _dummy(*args, **kwargs): - pass - commands.postincoming = _dummy - try: - result = commands.pull(ui, repo, source, **opts) - finally: - commands.postincoming = origpostincoming - revspostpull = len(repo) - if revspostpull > revsprepull: - result = result or rebase.rebase(ui, repo) - finally: - repo._isrebasing = False - else: - result = orig(ui, repo, source, **opts) + result = orig(ui, repo, source, **opts) revspostpull = len(repo) lfrevs = opts.get('lfrev', []) if opts.get('all_largefiles'): @@ -816,11 +790,14 @@ return result def overriderebase(orig, ui, repo, **opts): - repo._isrebasing = True + resuming = opts.get('continue') + repo._lfcommithooks.append(lfutil.automatedcommithook(resuming)) + repo._lfstatuswriters.append(lambda *msg, **opts: None) try: return orig(ui, repo, **opts) finally: - repo._isrebasing = False + repo._lfstatuswriters.pop() + repo._lfcommithooks.pop() def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None, prefix=None, mtime=None, subrepos=None): @@ -1302,9 +1279,10 @@ newstandins = lfutil.getstandinsstate(repo) filelist = lfutil.getlfilestoupdate(oldstandins, newstandins) - # suppress status message while automated committing - printmessage = not (getattr(repo, "_isrebasing", False) or - getattr(repo, "_istransplanting", False)) + printmessage = None + if getattr(repo, "_istransplanting", False): + # suppress status message while automated committing + printmessage = False lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, printmessage=printmessage, normallookup=partial)
--- a/hgext/largefiles/reposetup.py Tue Nov 11 17:25:09 2014 -0600 +++ b/hgext/largefiles/reposetup.py Wed Nov 12 15:18:30 2014 -0600 @@ -102,12 +102,12 @@ except error.LockError: pass - # First check if there were files specified on the - # command line. If there were, and none of them were + # First check if paths or patterns were specified on the + # command line. If there were, and they don't match any # largefiles, we should just bail here and let super # handle it -- thus gaining a big performance boost. lfdirstate = lfutil.openlfdirstate(ui, self) - if match.files() and not match.anypats(): + if not match.always(): for f in lfdirstate: if match(f): break @@ -243,9 +243,14 @@ # As part of committing, copy all of the largefiles into the # cache. - def commitctx(self, *args, **kwargs): - node = super(lfilesrepo, self).commitctx(*args, **kwargs) + def commitctx(self, ctx, *args, **kwargs): + node = super(lfilesrepo, self).commitctx(ctx, *args, **kwargs) lfutil.copyalltostore(self, node) + class lfilesctx(ctx.__class__): + def markcommitted(self, node): + orig = super(lfilesctx, self).markcommitted + return lfutil.markcommitted(orig, self, node) + ctx.__class__ = lfilesctx return node # Before commit, largefile standins have not had their @@ -257,139 +262,10 @@ wlock = self.wlock() try: - # Case 0: Automated committing - # - # While automated committing (like rebase, transplant - # and so on), this code path is used to avoid: - # (1) updating standins, because standins should - # be already updated at this point - # (2) aborting when stadnins are matched by "match", - # because automated committing may specify them directly - # - if getattr(self, "_isrebasing", False) or \ - getattr(self, "_istransplanting", False): - result = orig(text=text, user=user, date=date, match=match, - force=force, editor=editor, extra=extra) - - if result: - lfdirstate = lfutil.openlfdirstate(ui, self) - for f in self[result].files(): - if lfutil.isstandin(f): - lfile = lfutil.splitstandin(f) - lfutil.synclfdirstate(self, lfdirstate, lfile, - False) - lfdirstate.write() - - return result - # Case 1: user calls commit with no specific files or - # include/exclude patterns: refresh and commit all files that - # are "dirty". - if ((match is None) or - (not match.anypats() and not match.files())): - # Spend a bit of time here to get a list of files we know - # are modified so we can compare only against those. - # It can cost a lot of time (several seconds) - # otherwise to update all standins if the largefiles are - # large. - lfdirstate = lfutil.openlfdirstate(ui, self) - dirtymatch = match_.always(self.root, self.getcwd()) - unsure, s = lfdirstate.status(dirtymatch, [], False, False, - False) - modifiedfiles = unsure + s.modified + s.added + s.removed - lfiles = lfutil.listlfiles(self) - # this only loops through largefiles that exist (not - # removed/renamed) - for lfile in lfiles: - if lfile in modifiedfiles: - if os.path.exists( - self.wjoin(lfutil.standin(lfile))): - # this handles the case where a rebase is being - # performed and the working copy is not updated - # yet. - if os.path.exists(self.wjoin(lfile)): - lfutil.updatestandin(self, - lfutil.standin(lfile)) - lfdirstate.normal(lfile) - - result = orig(text=text, user=user, date=date, match=match, - force=force, editor=editor, extra=extra) - - if result is not None: - for lfile in lfdirstate: - if lfile in modifiedfiles: - if (not os.path.exists(self.wjoin( - lfutil.standin(lfile)))) or \ - (not os.path.exists(self.wjoin(lfile))): - lfdirstate.drop(lfile) - - # This needs to be after commit; otherwise precommit hooks - # get the wrong status - lfdirstate.write() - return result - - lfiles = lfutil.listlfiles(self) - match._files = self._subdirlfs(match.files(), lfiles) - - # Case 2: user calls commit with specified patterns: refresh - # any matching big files. - smatcher = lfutil.composestandinmatcher(self, match) - standins = self.dirstate.walk(smatcher, [], False, False) - - # No matching big files: get out of the way and pass control to - # the usual commit() method. - if not standins: - return orig(text=text, user=user, date=date, match=match, - force=force, editor=editor, extra=extra) - - # Refresh all matching big files. It's possible that the - # commit will end up failing, in which case the big files will - # stay refreshed. No harm done: the user modified them and - # asked to commit them, so sooner or later we're going to - # refresh the standins. Might as well leave them refreshed. - lfdirstate = lfutil.openlfdirstate(ui, self) - for standin in standins: - lfile = lfutil.splitstandin(standin) - if lfdirstate[lfile] != 'r': - lfutil.updatestandin(self, standin) - lfdirstate.normal(lfile) - else: - lfdirstate.drop(lfile) - - # Cook up a new matcher that only matches regular files or - # standins corresponding to the big files requested by the - # user. Have to modify _files to prevent commit() from - # complaining "not tracked" for big files. - match = copy.copy(match) - origmatchfn = match.matchfn - - # Check both the list of largefiles and the list of - # standins because if a largefile was removed, it - # won't be in the list of largefiles at this point - match._files += sorted(standins) - - actualfiles = [] - for f in match._files: - fstandin = lfutil.standin(f) - - # ignore known largefiles and standins - if f in lfiles or fstandin in standins: - continue - - actualfiles.append(f) - match._files = actualfiles - - def matchfn(f): - if origmatchfn(f): - return f not in lfiles - else: - return f in standins - - match.matchfn = matchfn + lfcommithook = self._lfcommithooks[-1] + match = lfcommithook(self, match) result = orig(text=text, user=user, date=date, match=match, force=force, editor=editor, extra=extra) - # This needs to be after commit; otherwise precommit hooks - # get the wrong status - lfdirstate.write() return result finally: wlock.release() @@ -405,6 +281,8 @@ return super(lfilesrepo, self).push(remote, force=force, revs=revs, newbranch=newbranch) + # TODO: _subdirlfs should be moved into "lfutil.py", because + # it is referred only from "lfutil.updatestandinsbymatch" def _subdirlfs(self, files, lfiles): ''' Adjust matched file list @@ -461,6 +339,15 @@ repo.__class__ = lfilesrepo + # stack of hooks being executed before committing. + # only last element ("_lfcommithooks[-1]") is used for each committing. + repo._lfcommithooks = [lfutil.updatestandinsbymatch] + + # Stack of status writer functions taking "*msg, **opts" arguments + # like "ui.status()". Only last element ("_lfupdatereporters[-1]") + # is used to write status out. + repo._lfstatuswriters = [ui.status] + def prepushoutgoinghook(local, remote, outgoing): if outgoing.missing: toupload = set()
--- a/hgext/largefiles/uisetup.py Tue Nov 11 17:25:09 2014 -0600 +++ b/hgext/largefiles/uisetup.py Wed Nov 12 15:18:30 2014 -0600 @@ -169,6 +169,8 @@ if name == 'rebase': extensions.wrapcommand(getattr(module, 'cmdtable'), 'rebase', overrides.overriderebase) + extensions.wrapfunction(module, 'rebase', + overrides.overriderebase) if name == 'transplant': extensions.wrapcommand(getattr(module, 'cmdtable'), 'transplant', overrides.overridetransplant)
--- a/hgext/patchbomb.py Tue Nov 11 17:25:09 2014 -0600 +++ b/hgext/patchbomb.py Wed Nov 12 15:18:30 2014 -0600 @@ -153,6 +153,159 @@ msg['X-Mercurial-Series-Total'] = '%i' % total return msg, subj, ds +def _getpatches(repo, revs, **opts): + """return a list of patches for a list of revisions + + Each patch in the list is itself a list of lines. + """ + ui = repo.ui + prev = repo['.'].rev() + for r in scmutil.revrange(repo, revs): + if r == prev and (repo[None].files() or repo[None].deleted()): + ui.warn(_('warning: working directory has ' + 'uncommitted changes\n')) + output = cStringIO.StringIO() + cmdutil.export(repo, [r], fp=output, + opts=patch.diffopts(ui, opts)) + yield output.getvalue().split('\n') +def _getbundle(repo, dest, **opts): + """return a bundle containing changesets missing in "dest" + + The `opts` keyword-arguments are the same as the one accepted by the + `bundle` command. + + The bundle is a returned as a single in-memory binary blob. + """ + ui = repo.ui + tmpdir = tempfile.mkdtemp(prefix='hg-email-bundle-') + tmpfn = os.path.join(tmpdir, 'bundle') + try: + commands.bundle(ui, repo, tmpfn, dest, **opts) + fp = open(tmpfn, 'rb') + data = fp.read() + fp.close() + return data + finally: + try: + os.unlink(tmpfn) + except OSError: + pass + os.rmdir(tmpdir) + +def _getdescription(repo, defaultbody, sender, **opts): + """obtain the body of the introduction message and return it + + This is also used for the body of email with an attached bundle. + + The body can be obtained either from the command line option or entered by + the user through the editor. + """ + ui = repo.ui + if opts.get('desc'): + body = open(opts.get('desc')).read() + else: + ui.write(_('\nWrite the introductory message for the ' + 'patch series.\n\n')) + body = ui.edit(defaultbody, sender) + # Save series description in case sendmail fails + msgfile = repo.opener('last-email.txt', 'wb') + msgfile.write(body) + msgfile.close() + return body + +def _getbundlemsgs(repo, sender, bundle, **opts): + """Get the full email for sending a given bundle + + This function returns a list of "email" tuples (subject, content, None). + The list is always one message long in that case. + """ + ui = repo.ui + _charsets = mail._charsets(ui) + subj = (opts.get('subject') + or prompt(ui, 'Subject:', 'A bundle for your repository')) + + body = _getdescription(repo, '', sender, **opts) + msg = email.MIMEMultipart.MIMEMultipart() + if body: + msg.attach(mail.mimeencode(ui, body, _charsets, opts.get('test'))) + datapart = email.MIMEBase.MIMEBase('application', 'x-mercurial-bundle') + datapart.set_payload(bundle) + bundlename = '%s.hg' % opts.get('bundlename', 'bundle') + datapart.add_header('Content-Disposition', 'attachment', + filename=bundlename) + email.Encoders.encode_base64(datapart) + msg.attach(datapart) + msg['Subject'] = mail.headencode(ui, subj, _charsets, opts.get('test')) + return [(msg, subj, None)] + +def _makeintro(repo, sender, patches, **opts): + """make an introduction email, asking the user for content if needed + + email is returned as (subject, body, cumulative-diffstat)""" + ui = repo.ui + _charsets = mail._charsets(ui) + tlen = len(str(len(patches))) + + flag = opts.get('flag') or '' + if flag: + flag = ' ' + ' '.join(flag) + prefix = '[PATCH %0*d of %d%s]' % (tlen, 0, len(patches), flag) + + subj = (opts.get('subject') or + prompt(ui, '(optional) Subject: ', rest=prefix, default='')) + if not subj: + return None # skip intro if the user doesn't bother + + subj = prefix + ' ' + subj + + body = '' + if opts.get('diffstat'): + # generate a cumulative diffstat of the whole patch series + diffstat = patch.diffstat(sum(patches, [])) + body = '\n' + diffstat + else: + diffstat = None + + body = _getdescription(repo, body, sender, **opts) + msg = mail.mimeencode(ui, body, _charsets, opts.get('test')) + msg['Subject'] = mail.headencode(ui, subj, _charsets, + opts.get('test')) + return (msg, subj, diffstat) + +def _getpatchmsgs(repo, sender, patches, patchnames=None, **opts): + """return a list of emails from a list of patches + + This involves introduction message creation if necessary. + + This function returns a list of "email" tuples (subject, content, None). + """ + ui = repo.ui + _charsets = mail._charsets(ui) + msgs = [] + + ui.write(_('this patch series consists of %d patches.\n\n') + % len(patches)) + + # build the intro message, or skip it if the user declines + if introwanted(opts, len(patches)): + msg = _makeintro(repo, sender, patches, **opts) + if msg: + msgs.append(msg) + + # are we going to send more than one message? + numbered = len(msgs) + len(patches) > 1 + + # now generate the actual patch messages + name = None + for i, p in enumerate(patches): + if patchnames: + name = patchnames[i] + msg = makepatch(ui, repo, p, opts, _charsets, i + 1, + len(patches), numbered, name) + msgs.append(msg) + + return msgs + emailopts = [ ('', 'body', None, _('send patches as inline message text (default)')), ('a', 'attach', None, _('send patches as attachments')), @@ -292,33 +445,6 @@ return [] return [str(r) for r in revs] - def getpatches(revs): - prev = repo['.'].rev() - for r in scmutil.revrange(repo, revs): - if r == prev and (repo[None].files() or repo[None].deleted()): - ui.warn(_('warning: working directory has ' - 'uncommitted changes\n')) - output = cStringIO.StringIO() - cmdutil.export(repo, [r], fp=output, - opts=patch.diffopts(ui, opts)) - yield output.getvalue().split('\n') - - def getbundle(dest): - tmpdir = tempfile.mkdtemp(prefix='hg-email-bundle-') - tmpfn = os.path.join(tmpdir, 'bundle') - try: - commands.bundle(ui, repo, tmpfn, dest, **opts) - fp = open(tmpfn, 'rb') - data = fp.read() - fp.close() - return data - finally: - try: - os.unlink(tmpfn) - except OSError: - pass - os.rmdir(tmpdir) - if not (opts.get('test') or mbox): # really sending mail.validateconfig(ui) @@ -355,102 +481,21 @@ def genmsgid(id): return '<%s.%s@%s>' % (id[:20], int(start_time[0]), socket.getfqdn()) - def getdescription(body, sender): - if opts.get('desc'): - body = open(opts.get('desc')).read() - else: - ui.write(_('\nWrite the introductory message for the ' - 'patch series.\n\n')) - body = ui.edit(body, sender) - # Save series description in case sendmail fails - msgfile = repo.opener('last-email.txt', 'wb') - msgfile.write(body) - msgfile.close() - return body - - def getpatchmsgs(patches, patchnames=None): - msgs = [] - - ui.write(_('this patch series consists of %d patches.\n\n') - % len(patches)) - - # build the intro message, or skip it if the user declines - if introwanted(opts, len(patches)): - msg = makeintro(patches) - if msg: - msgs.append(msg) - - # are we going to send more than one message? - numbered = len(msgs) + len(patches) > 1 - - # now generate the actual patch messages - name = None - for i, p in enumerate(patches): - if patchnames: - name = patchnames[i] - msg = makepatch(ui, repo, p, opts, _charsets, i + 1, - len(patches), numbered, name) - msgs.append(msg) - - return msgs - - def makeintro(patches): - tlen = len(str(len(patches))) - - flag = opts.get('flag') or '' - if flag: - flag = ' ' + ' '.join(flag) - prefix = '[PATCH %0*d of %d%s]' % (tlen, 0, len(patches), flag) - - subj = (opts.get('subject') or - prompt(ui, '(optional) Subject: ', rest=prefix, default='')) - if not subj: - return None # skip intro if the user doesn't bother - - subj = prefix + ' ' + subj - - body = '' - if opts.get('diffstat'): - # generate a cumulative diffstat of the whole patch series - diffstat = patch.diffstat(sum(patches, [])) - body = '\n' + diffstat - else: - diffstat = None - - body = getdescription(body, sender) - msg = mail.mimeencode(ui, body, _charsets, opts.get('test')) - msg['Subject'] = mail.headencode(ui, subj, _charsets, - opts.get('test')) - return (msg, subj, diffstat) - - def getbundlemsgs(bundle): - subj = (opts.get('subject') - or prompt(ui, 'Subject:', 'A bundle for your repository')) - - body = getdescription('', sender) - msg = email.MIMEMultipart.MIMEMultipart() - if body: - msg.attach(mail.mimeencode(ui, body, _charsets, opts.get('test'))) - datapart = email.MIMEBase.MIMEBase('application', 'x-mercurial-bundle') - datapart.set_payload(bundle) - bundlename = '%s.hg' % opts.get('bundlename', 'bundle') - datapart.add_header('Content-Disposition', 'attachment', - filename=bundlename) - email.Encoders.encode_base64(datapart) - msg.attach(datapart) - msg['Subject'] = mail.headencode(ui, subj, _charsets, opts.get('test')) - return [(msg, subj, None)] - sender = (opts.get('from') or ui.config('email', 'from') or ui.config('patchbomb', 'from') or prompt(ui, 'From', ui.username())) if patches: - msgs = getpatchmsgs(patches, opts.get('patchnames')) + msgs = _getpatchmsgs(repo, sender, patches, opts.get('patchnames'), + **opts) elif bundle: - msgs = getbundlemsgs(getbundle(dest)) + bundledata = _getbundle(repo, dest, **opts) + bundleopts = opts.copy() + bundleopts.pop('bundle', None) # already processed + msgs = _getbundlemsgs(repo, sender, bundledata, **bundleopts) else: - msgs = getpatchmsgs(list(getpatches(revs))) + _patches = list(_getpatches(repo, revs, **opts)) + msgs = _getpatchmsgs(repo, sender, _patches, **opts) showaddrs = [] @@ -483,14 +528,14 @@ replyto = getaddrs('Reply-To') if opts.get('diffstat') or opts.get('confirm'): - ui.write(_('\nFinal summary:\n\n')) - ui.write(('From: %s\n' % sender)) + ui.write(_('\nFinal summary:\n\n'), label='patchbomb.finalsummary') + ui.write(('From: %s\n' % sender), label='patchbomb.from') for addr in showaddrs: - ui.write('%s\n' % addr) + ui.write('%s\n' % addr, label='patchbomb.to') for m, subj, ds in msgs: - ui.write(('Subject: %s\n' % subj)) + ui.write(('Subject: %s\n' % subj), label='patchbomb.subject') if ds: - ui.write(ds) + ui.write(ds, label='patchbomb.diffstats') ui.write('\n') if ui.promptchoice(_('are you sure you want to send (yn)?' '$$ &Yes $$ &No')):
--- a/hgext/rebase.py Tue Nov 11 17:25:09 2014 -0600 +++ b/hgext/rebase.py Wed Nov 12 15:18:30 2014 -0600 @@ -282,7 +282,7 @@ if not rebaseset: # transform to list because smartsets are not comparable to - # lists. This should be improved to honor lazyness of + # lists. This should be improved to honor laziness of # smartset. if list(base) == [dest.rev()]: if basef:
--- a/hgext/record.py Tue Nov 11 17:25:09 2014 -0600 +++ b/hgext/record.py Wed Nov 12 15:18:30 2014 -0600 @@ -328,10 +328,9 @@ f.close() # Start the editor and wait for it to complete editor = ui.geteditor() - util.system("%s \"%s\"" % (editor, patchfn), - environ={'HGUSER': ui.username()}, - onerr=util.Abort, errprefix=_("edit failed"), - out=ui.fout) + ui.system("%s \"%s\"" % (editor, patchfn), + environ={'HGUSER': ui.username()}, + onerr=util.Abort, errprefix=_("edit failed")) # Remove comment lines patchfp = open(patchfn) ncpatchfp = cStringIO.StringIO()
--- a/hgext/strip.py Tue Nov 11 17:25:09 2014 -0600 +++ b/hgext/strip.py Wed Nov 12 15:18:30 2014 -0600 @@ -1,4 +1,4 @@ -"""strip changesets and their descendents from history +"""strip changesets and their descendants from history This extension allows you to strip changesets and all their descendants from the repository. See the command help for details.
--- a/hgext/transplant.py Tue Nov 11 17:25:09 2014 -0600 +++ b/hgext/transplant.py Wed Nov 12 15:18:30 2014 -0600 @@ -233,13 +233,12 @@ fp.close() try: - util.system('%s %s %s' % (filter, util.shellquote(headerfile), - util.shellquote(patchfile)), - environ={'HGUSER': changelog[1], - 'HGREVISION': revlog.hex(node), - }, - onerr=util.Abort, errprefix=_('filter failed'), - out=self.ui.fout) + self.ui.system('%s %s %s' % (filter, util.shellquote(headerfile), + util.shellquote(patchfile)), + environ={'HGUSER': changelog[1], + 'HGREVISION': revlog.hex(node), + }, + onerr=util.Abort, errprefix=_('filter failed')) user, date, msg = self.parselog(file(headerfile))[1:4] finally: os.unlink(headerfile)
--- a/i18n/polib.py Tue Nov 11 17:25:09 2014 -0600 +++ b/i18n/polib.py Wed Nov 12 15:18:30 2014 -0600 @@ -396,7 +396,7 @@ def ordered_metadata(self): """ Convenience method that returns an ordered version of the metadata - dictionnary. The return value is list of tuples (metadata name, + dictionary. The return value is list of tuples (metadata name, metadata_value). """ # copy the dict first
--- a/mercurial/bundle2.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/bundle2.py Wed Nov 12 15:18:30 2014 -0600 @@ -229,7 +229,7 @@ self.getreplies(inreplyto).add(category, entry) def getreplies(self, partid): - """get the subrecords that replies to a specific part""" + """get the records that are replies to a specific part""" return self._replies.setdefault(partid, unbundlerecords()) def __getitem__(self, cat): @@ -303,7 +303,7 @@ # consume the bundle content part.read() # Small hack to let caller code distinguish exceptions from bundle2 - # processing fron the ones from bundle1 processing. This is mostly + # processing from processing the old format. This is mostly # needed to handle different return codes to unbundle according to the # type of bundle. We should probably clean up or drop this return code # craziness in a future version. @@ -359,7 +359,7 @@ def decodecaps(blob): - """decode a bundle2 caps bytes blob into a dictionnary + """decode a bundle2 caps bytes blob into a dictionary The blob is a list of capabilities (one per line) Capabilities may have values using a line of the form:: @@ -741,7 +741,7 @@ self.ui.debug('bundle2 stream interruption, looking for a part.\n') headerblock = self._readpartheader() if headerblock is None: - self.ui.debug('no part found during iterruption.\n') + self.ui.debug('no part found during interruption.\n') return part = unbundlepart(self.ui, headerblock, self._fp) op = interruptoperation(self.ui) @@ -828,7 +828,7 @@ # split mandatory from advisory mansizes = paramsizes[:mancount] advsizes = paramsizes[mancount:] - # retrive param value + # retrieve param value manparams = [] for key, value in mansizes: manparams.append((self._fromheader(key), self._fromheader(value))) @@ -871,7 +871,6 @@ capabilities = {'HG2Y': (), 'b2x:listkeys': (), 'b2x:pushkey': (), - 'b2x:changegroup': (), 'digests': tuple(sorted(util.DIGESTS.keys())), 'b2x:remote-changegroup': ('http', 'https'), } @@ -882,13 +881,14 @@ Exists to allow extensions (like evolution) to mutate the capabilities. """ caps = capabilities.copy() + caps['b2x:changegroup'] = tuple(sorted(changegroup.packermap.keys())) if obsolete.isenabled(repo, obsolete.exchangeopt): supportedformat = tuple('V%i' % v for v in obsolete.formats) caps['b2x:obsmarkers'] = supportedformat return caps def bundle2caps(remote): - """return the bundlecapabilities of a peer as dict""" + """return the bundle capabilities of a peer as dict""" raw = remote.capable('bundle2-exp') if not raw and raw != '': return {} @@ -901,7 +901,7 @@ obscaps = caps.get('b2x:obsmarkers', ()) return [int(c[1:]) for c in obscaps if c.startswith('V')] -@parthandler('b2x:changegroup') +@parthandler('b2x:changegroup', ('version',)) def handlechangegroup(op, inpart): """apply a changegroup part on the repo @@ -914,13 +914,16 @@ # we need to make sure we trigger the creation of a transaction object used # for the whole processing scope. op.gettransaction() - cg = changegroup.cg1unpacker(inpart, 'UN') + unpackerversion = inpart.params.get('version', '01') + # We should raise an appropriate exception here + unpacker = changegroup.packermap[unpackerversion][1] + cg = unpacker(inpart, 'UN') # the source and url passed here are overwritten by the one contained in # the transaction.hookargs argument. So 'bundle2' is a placeholder ret = changegroup.addchangegroup(op.repo, cg, 'bundle2', 'bundle2') op.records.add('changegroup', {'return': ret}) if op.reply is not None: - # This is definitly not the final form of this + # This is definitely not the final form of this # return. But one need to start somewhere. part = op.reply.newpart('b2x:reply:changegroup') part.addparam('in-reply-to', str(inpart.id), mandatory=False) @@ -989,7 +992,7 @@ ret = changegroup.addchangegroup(op.repo, cg, 'bundle2', 'bundle2') op.records.add('changegroup', {'return': ret}) if op.reply is not None: - # This is definitly not the final form of this + # This is definitely not the final form of this # return. But one need to start somewhere. part = op.reply.newpart('b2x:reply:changegroup') part.addparam('in-reply-to', str(inpart.id), mandatory=False)
--- a/mercurial/changegroup.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/changegroup.py Wed Nov 12 15:18:30 2014 -0600 @@ -13,6 +13,7 @@ import discovery, error, phases, branchmap _CHANGEGROUPV1_DELTA_HEADER = "20s20s20s20s" +_CHANGEGROUPV2_DELTA_HEADER = "20s20s20s20s20s" def readexactly(stream, n): '''read n bytes from stream.read and abort if less was available''' @@ -215,6 +216,14 @@ pos = next yield closechunk() +class cg2unpacker(cg1unpacker): + deltaheader = _CHANGEGROUPV2_DELTA_HEADER + deltaheadersize = struct.calcsize(deltaheader) + + def _deltaheader(self, headertuple, prevnode): + node, p1, p2, deltabase, cs = headertuple + return node, p1, p2, deltabase, cs + class headerlessfixup(object): def __init__(self, fh, h): self._h = h @@ -408,10 +417,13 @@ reorder=reorder): yield chunk + def deltaparent(self, revlog, rev, p1, p2, prev): + return prev + def revchunk(self, revlog, rev, prev, linknode): node = revlog.node(rev) p1, p2 = revlog.parentrevs(rev) - base = prev + base = self.deltaparent(revlog, rev, p1, p2, prev) prefix = '' if base == nullrev: @@ -431,6 +443,30 @@ # do nothing with basenode, it is implicitly the previous one in HG10 return struct.pack(self.deltaheader, node, p1n, p2n, linknode) +class cg2packer(cg1packer): + + deltaheader = _CHANGEGROUPV2_DELTA_HEADER + + def group(self, nodelist, revlog, lookup, units=None, reorder=None): + if (revlog._generaldelta and reorder is not True): + reorder = False + return super(cg2packer, self).group(nodelist, revlog, lookup, + units=units, reorder=reorder) + + def deltaparent(self, revlog, rev, p1, p2, prev): + dp = revlog.deltaparent(rev) + # avoid storing full revisions; pick prev in those cases + # also pick prev when we can't be sure remote has dp + if dp == nullrev or (dp != p1 and dp != p2 and dp != prev): + return prev + return dp + + def builddeltaheader(self, node, p1n, p2n, basenode, linknode): + return struct.pack(self.deltaheader, node, p1n, p2n, basenode, linknode) + +packermap = {'01': (cg1packer, cg1unpacker), + '02': (cg2packer, cg2unpacker)} + def _changegroupinfo(repo, nodes, source): if repo.ui.verbose or source == 'bundle': repo.ui.status(_("%d changesets found\n") % len(nodes)) @@ -439,7 +475,7 @@ for node in nodes: repo.ui.debug("%s\n" % hex(node)) -def getsubset(repo, outgoing, bundler, source, fastpath=False): +def getsubsetraw(repo, outgoing, bundler, source, fastpath=False): repo = repo.unfiltered() commonrevs = outgoing.common csets = outgoing.missing @@ -453,7 +489,10 @@ repo.hook('preoutgoing', throw=True, source=source) _changegroupinfo(repo, csets, source) - gengroup = bundler.generate(commonrevs, csets, fastpathlinkrev, source) + return bundler.generate(commonrevs, csets, fastpathlinkrev, source) + +def getsubset(repo, outgoing, bundler, source, fastpath=False): + gengroup = getsubsetraw(repo, outgoing, bundler, source, fastpath) return cg1unpacker(util.chunkbuffer(gengroup), 'UN') def changegroupsubset(repo, roots, heads, source): @@ -481,6 +520,17 @@ bundler = cg1packer(repo) return getsubset(repo, outgoing, bundler, source) +def getlocalchangegroupraw(repo, source, outgoing, bundlecaps=None, + version='01'): + """Like getbundle, but taking a discovery.outgoing as an argument. + + This is only implemented for local repos and reuses potentially + precomputed sets in outgoing. Returns a raw changegroup generator.""" + if not outgoing.missing: + return None + bundler = packermap[version][0](repo, bundlecaps) + return getsubsetraw(repo, outgoing, bundler, source) + def getlocalchangegroup(repo, source, outgoing, bundlecaps=None): """Like getbundle, but taking a discovery.outgoing as an argument. @@ -510,6 +560,22 @@ heads = cl.heads() return discovery.outgoing(cl, common, heads) +def getchangegroupraw(repo, source, heads=None, common=None, bundlecaps=None, + version='01'): + """Like changegroupsubset, but returns the set difference between the + ancestors of heads and the ancestors common. + + If heads is None, use the local heads. If common is None, use [nullid]. + + If version is None, use a version '1' changegroup. + + The nodes in common might not all be known locally due to the way the + current discovery protocol works. Returns a raw changegroup generator. + """ + outgoing = _computeoutgoing(repo, heads, common) + return getlocalchangegroupraw(repo, source, outgoing, bundlecaps=bundlecaps, + version=version) + def getchangegroup(repo, source, heads=None, common=None, bundlecaps=None): """Like changegroupsubset, but returns the set difference between the ancestors of heads and the ancestors common. @@ -593,12 +659,6 @@ changesets = files = revisions = 0 efiles = set() - # write changelog data to temp files so concurrent readers will not see - # inconsistent view - cl = repo.changelog - cl.delayupdate() - oldheads = cl.heads() - tr = repo.transaction("\n".join([srctype, util.hidepassword(url)])) # The transaction could have been created before and already carries source # information. In this case we use the top level data. We overwrite the @@ -606,6 +666,12 @@ # this function. srctype = tr.hookargs.setdefault('source', srctype) url = tr.hookargs.setdefault('url', url) + + # write changelog data to temp files so concurrent readers will not see + # inconsistent view + cl = repo.changelog + cl.delayupdate(tr) + oldheads = cl.heads() try: repo.hook('prechangegroup', throw=True, **tr.hookargs) @@ -688,7 +754,7 @@ repo.invalidatevolatilesets() if changesets > 0: - p = lambda: cl.writepending() and repo.root or "" + p = lambda: tr.writepending() and repo.root or "" if 'node' not in tr.hookargs: tr.hookargs['node'] = hex(cl.node(clstart)) hookargs = dict(tr.hookargs) @@ -720,11 +786,6 @@ # strip should not touch boundary at all phases.retractboundary(repo, tr, targetphase, added) - # make changelog see real files again - cl.finalize(trp) - - tr.close() - if changesets > 0: if srctype != 'strip': # During strip, branchcache is invalid but coming call to @@ -753,7 +814,11 @@ "%s incoming changes - new heads: %s\n", len(added), ', '.join([hex(c[:6]) for c in newheads])) - repo._afterlock(runhooks) + + tr.addpostclose('changegroup-runhooks-%020i' % clstart, + lambda: repo._afterlock(runhooks)) + + tr.close() finally: tr.release()
--- a/mercurial/changelog.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/changelog.py Wed Nov 12 15:18:30 2014 -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. +import weakref from node import bin, hex, nullid from i18n import _ import util, error, revlog, encoding @@ -108,15 +109,21 @@ self.data.append(str(s)) self.offset += len(s) -def delayopener(opener, target, divert, buf): - def o(name, mode='r'): +def _divertopener(opener, target): + """build an opener that writes in 'target.a' instead of 'target'""" + def _divert(name, mode='r'): if name != target: return opener(name, mode) - if divert: - return opener(name + ".a", mode.replace('a', 'w')) - # otherwise, divert to memory + return opener(name + ".a", mode) + return _divert + +def _delayopener(opener, target, buf): + """build an opener that stores chunks in 'buf' instead of 'target'""" + def _delay(name, mode='r'): + if name != target: + return opener(name, mode) return appender(opener, name, mode, buf) - return o + return _delay class changelog(revlog.revlog): def __init__(self, opener): @@ -127,7 +134,7 @@ self._generaldelta = False self._realopener = opener self._delayed = False - self._delaybuf = [] + self._delaybuf = None self._divert = False self.filteredrevs = frozenset() @@ -218,20 +225,31 @@ raise error.FilteredIndexError(rev) return super(changelog, self).flags(rev) - def delayupdate(self): + def delayupdate(self, tr): "delay visibility of index updates to other readers" + + if not self._delayed: + if len(self) == 0: + self._divert = True + if self._realopener.exists(self.indexfile + '.a'): + self._realopener.unlink(self.indexfile + '.a') + self.opener = _divertopener(self._realopener, self.indexfile) + else: + self._delaybuf = [] + self.opener = _delayopener(self._realopener, self.indexfile, + self._delaybuf) self._delayed = True - self._divert = (len(self) == 0) - self._delaybuf = [] - self.opener = delayopener(self._realopener, self.indexfile, - self._divert, self._delaybuf) + tr.addpending('cl-%i' % id(self), self._writepending) + trp = weakref.proxy(tr) + tr.addfinalize('cl-%i' % id(self), lambda: self._finalize(trp)) - def finalize(self, tr): + def _finalize(self, tr): "finalize index updates" self._delayed = False self.opener = self._realopener # move redirected index data back into place if self._divert: + assert not self._delaybuf tmpname = self.indexfile + ".a" nfile = self.opener.open(tmpname) nfile.close() @@ -240,7 +258,8 @@ fp = self.opener(self.indexfile, 'a') fp.write("".join(self._delaybuf)) fp.close() - self._delaybuf = [] + self._delaybuf = None + self._divert = False # split when we're done self.checkinlinesize(tr) @@ -251,7 +270,7 @@ self._nodecache = r._nodecache self._chunkcache = r._chunkcache - def writepending(self): + def _writepending(self): "create a file containing the unfinalized state for pretxnchangegroup" if self._delaybuf: # make a temporary copy of the index @@ -262,8 +281,9 @@ fp2.write("".join(self._delaybuf)) fp2.close() # switch modes so finalize can simply rename - self._delaybuf = [] + self._delaybuf = None self._divert = True + self.opener = _divertopener(self._realopener, self.indexfile) if self._divert: return True
--- a/mercurial/cmdutil.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/cmdutil.py Wed Nov 12 15:18:30 2014 -0600 @@ -113,7 +113,7 @@ def mergeeditform(ctxorbool, baseform): """build appropriate editform from ctxorbool and baseform - 'cxtorbool' is one of a ctx to be committed, or a bool whether + 'ctxorbool' is one of a ctx to be committed, or a bool whether merging is committed. This returns editform 'baseform' with '.merge' if merging is @@ -1783,8 +1783,8 @@ # If we're forced to take the slowpath it means we're following # at least one pattern/directory, so don't bother with rename tracking. if follow and not match.always() and not slowpath: - # _makelogfilematcher expects its files argument to be relative to - # the repo root, so use match.files(), not pats. + # _makefollowlogfilematcher expects its files argument to be + # relative to the repo root, so use match.files(), not pats. filematcher = _makefollowlogfilematcher(repo, match.files(), followfirst) else: @@ -1982,9 +1982,9 @@ abort, warn = scmutil.checkportabilityalert(ui) if abort or warn: cca = scmutil.casecollisionauditor(ui, abort, repo.dirstate) - for f in repo.walk(match): + for f in wctx.walk(match): exact = match.exact(f) - if exact or not explicitonly and f not in repo.dirstate: + if exact or not explicitonly and f not in wctx: if cca: cca(f) names.append(f) @@ -2522,11 +2522,11 @@ deladded = _deleted - smf deleted = _deleted - deladded - # We need to account for the state of file in the dirstate + # We need to account for the state of file in the dirstate. # - # Even, when we revert agains something else than parent. this will + # Even, when we revert against something else than parent. This will # slightly alter the behavior of revert (doing back up or not, delete - # or just forget etc) + # or just forget etc). if parent == node: dsmodified = modified dsadded = added
--- a/mercurial/commands.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/commands.py Wed Nov 12 15:18:30 2014 -0600 @@ -743,9 +743,7 @@ # update state state['current'] = [node] hbisect.save_state(repo, state) - status = util.system(command, - environ={'HG_NODE': hex(node)}, - out=ui.fout) + status = ui.system(command, environ={'HG_NODE': hex(node)}) if status == 125: transition = "skip" elif status == 0: @@ -1573,9 +1571,8 @@ fp.close() editor = ui.geteditor() - util.system("%s \"%s\"" % (editor, f), - onerr=util.Abort, errprefix=_("edit failed"), - out=ui.fout) + ui.system("%s \"%s\"" % (editor, f), + onerr=util.Abort, errprefix=_("edit failed")) return for f in scmutil.rcpath(): @@ -2653,22 +2650,13 @@ " rawsize totalsize compression heads chainlen\n") ts = 0 heads = set() - rindex = r.index - - def chainbaseandlen(rev): - clen = 0 - base = rindex[rev][3] - while base != rev: - clen += 1 - rev = base - base = rindex[rev][3] - return base, clen for rev in xrange(numrevs): dbase = r.deltaparent(rev) if dbase == -1: dbase = rev - cbase, clen = chainbaseandlen(rev) + cbase = r.chainbase(rev) + clen = r.chainlen(rev) p1, p2 = r.parentrevs(rev) rs = r.rawsize(rev) ts = ts + rs
--- a/mercurial/context.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/context.py Wed Nov 12 15:18:30 2014 -0600 @@ -85,8 +85,7 @@ del mf[fn] return mf - def _matchstatus(self, other, s, match, listignored, listclean, - listunknown): + def _matchstatus(self, other, match): """return match.always if match is none This internal method provides a way for child objects to override the @@ -94,28 +93,17 @@ """ return match or matchmod.always(self._repo.root, self._repo.getcwd()) - def _prestatus(self, other, s, match, listignored, listclean, listunknown): - """provide a hook to allow child objects to preprocess status results - - For example, this allows other contexts, such as workingctx, to query - the dirstate before comparing the manifests. - """ - # load earliest manifest first for caching reasons - if self.rev() < other.rev(): - self.manifest() - return s - - def _poststatus(self, other, s, match, listignored, listclean, listunknown): - """provide a hook to allow child objects to postprocess status results - - For example, this allows other contexts, such as workingctx, to filter - suspect symlinks in the case of FAT32 and NTFS filesytems. - """ - return s - def _buildstatus(self, other, s, match, listignored, listclean, listunknown): """build a status with respect to another context""" + # Load earliest manifest first for caching reasons. More specifically, + # if you have revisions 1000 and 1001, 1001 is probably stored as a + # delta against 1000. Thus, if you read 1000 first, we'll reconstruct + # 1000 and cache it so that when you read 1001, we just need to apply a + # delta to what's in the cache. So that's one full reconstruction + one + # delta application. + if self.rev() is not None and self.rev() < other.rev(): + self.manifest() mf1 = other._manifestmatches(match, s) mf2 = self._manifestmatches(match, s) @@ -311,14 +299,10 @@ reversed = True ctx1, ctx2 = ctx2, ctx1 + match = ctx2._matchstatus(ctx1, match) r = [[], [], [], [], [], [], []] - match = ctx2._matchstatus(ctx1, r, match, listignored, listclean, - listunknown) - r = ctx2._prestatus(ctx1, r, match, listignored, listclean, listunknown) r = ctx2._buildstatus(ctx1, r, match, listignored, listclean, listunknown) - r = ctx2._poststatus(ctx1, r, match, listignored, listclean, - listunknown) if reversed: # reverse added and removed @@ -1412,28 +1396,6 @@ del mf[f] return mf - def _prestatus(self, other, s, match, listignored, listclean, listunknown): - """override the parent hook with a dirstate query - - We use this prestatus hook to populate the status with information from - the dirstate. - """ - # doesn't need to call super; if that changes, be aware that super - # calls self.manifest which would slow down the common case of calling - # status against a workingctx's parent - return self._dirstatestatus(match, listignored, listclean, listunknown) - - def _poststatus(self, other, s, match, listignored, listclean, listunknown): - """override the parent hook with a filter for suspect symlinks - - We use this poststatus hook to filter out symlinks that might have - accidentally ended up with the entire contents of the file they are - susposed to be linking to. - """ - s[0] = self._filtersuspectsymlink(s[0]) - self._status = scmutil.status(*s) - return s - def _dirstatestatus(self, match=None, ignored=False, clean=False, unknown=False): '''Gets the status from the dirstate -- internal use only.''' @@ -1466,14 +1428,19 @@ building a new manifest if self (working directory) is not comparing against its parent (repo['.']). """ + s = self._dirstatestatus(match, listignored, listclean, listunknown) + # Filter out symlinks that, in the case of FAT32 and NTFS filesytems, + # might have accidentally ended up with the entire contents of the file + # they are susposed to be linking to. + s[0] = self._filtersuspectsymlink(s[0]) if other != self._repo['.']: s = super(workingctx, self)._buildstatus(other, s, match, listignored, listclean, listunknown) + self._status = scmutil.status(*s) return s - def _matchstatus(self, other, s, match, listignored, listclean, - listunknown): + def _matchstatus(self, other, match): """override the match method with a filter for directory patterns We use inheritance to customize the match.bad method only in cases of @@ -1484,8 +1451,7 @@ just use the default match object sent to us. """ superself = super(workingctx, self) - match = superself._matchstatus(other, s, match, listignored, listclean, - listunknown) + match = superself._matchstatus(other, match) if other != self._repo['.']: def bad(f, msg): # 'f' may be a directory pattern from 'match.files()', @@ -1496,14 +1462,6 @@ match.bad = bad return match - def status(self, other='.', match=None, listignored=False, - listclean=False, listunknown=False, listsubrepos=False): - # yet to be determined: what to do if 'other' is a 'workingctx' or a - # 'memctx'? - return super(workingctx, self).status(other, match, listignored, - listclean, listunknown, - listsubrepos) - class committablefilectx(basefilectx): """A committablefilectx provides common functionality for a file context that wants the ability to commit, e.g. workingfilectx or memfilectx.""" @@ -1693,7 +1651,7 @@ class memfilectx(committablefilectx): """memfilectx represents an in-memory file to commit. - See memctx and commitablefilectx for more details. + See memctx and committablefilectx for more details. """ def __init__(self, repo, path, data, islink=False, isexec=False, copied=None, memctx=None):
--- a/mercurial/copies.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/copies.py Wed Nov 12 15:18:30 2014 -0600 @@ -97,7 +97,7 @@ # |/ # o 0 a0 # - # When findlimit is called, a and b are revs 3 and 0, so limit will be 2, + # When _findlimit is called, a and b are revs 3 and 0, so limit will be 2, # yet the filelog has the copy information in rev 1 and we will not look # back far enough unless we also look at the a and b as candidates. # This only occurs when a is a descendent of b or visa-versa.
--- a/mercurial/dagutil.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/dagutil.py Wed Nov 12 15:18:30 2014 -0600 @@ -25,7 +25,7 @@ self._inverse = None def nodeset(self): - '''set of all node idxs''' + '''set of all node ixs''' raise NotImplementedError def heads(self): @@ -77,7 +77,7 @@ return self._internalize(id) def internalizeall(self, ids, filterunknown=False): - '''return a list of (or set if given a set) of node ids''' + '''return a list of (or set if given a set) of node ixs''' ixs = self._internalizeall(ids, filterunknown) if isinstance(ids, set): return set(ixs)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/default.d/mergetools.rc Wed Nov 12 15:18:30 2014 -0600 @@ -0,0 +1,135 @@ +# Some default global settings for common merge tools + +[merge-tools] +kdiff3.args=--auto --L1 base --L2 local --L3 other $base $local $other -o $output +kdiff3.regkey=Software\KDiff3 +kdiff3.regkeyalt=Software\Wow6432Node\KDiff3 +kdiff3.regappend=\kdiff3.exe +kdiff3.fixeol=True +kdiff3.gui=True +kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child + +gvimdiff.args=--nofork -d -g -O $local $other $base +gvimdiff.regkey=Software\Vim\GVim +gvimdiff.regkeyalt=Software\Wow6432Node\Vim\GVim +gvimdiff.regname=path +gvimdiff.priority=-9 +gvimdiff.diffargs=--nofork -d -g -O $parent $child + +vimdiff.args=$local $other $base -c 'redraw | echomsg "hg merge conflict, type \":cq\" to abort vimdiff"' +vimdiff.check=changed +vimdiff.priority=-10 + +merge.check=conflicts +merge.priority=-100 + +gpyfm.gui=True + +meld.gui=True +meld.args=--label='local' $local --label='merged' $base --label='other' $other -o $output +meld.check=changed +meld.diffargs=-a --label='$plabel1' $parent --label='$clabel' $child + +tkdiff.args=$local $other -a $base -o $output +tkdiff.gui=True +tkdiff.priority=-8 +tkdiff.diffargs=-L '$plabel1' $parent -L '$clabel' $child + +xxdiff.args=--show-merged-pane --exit-with-merge-status --title1 local --title2 base --title3 other --merged-filename $output --merge $local $base $other +xxdiff.gui=True +xxdiff.priority=-8 +xxdiff.diffargs=--title1 '$plabel1' $parent --title2 '$clabel' $child + +diffmerge.regkey=Software\SourceGear\SourceGear DiffMerge\ +diffmerge.regkeyalt=Software\Wow6432Node\SourceGear\SourceGear DiffMerge\ +diffmerge.regname=Location +diffmerge.priority=-7 +diffmerge.args=-nosplash -merge -title1=local -title2=merged -title3=other $local $base $other -result=$output +diffmerge.check=changed +diffmerge.gui=True +diffmerge.diffargs=--nosplash --title1='$plabel1' --title2='$clabel' $parent $child + +p4merge.args=$base $local $other $output +p4merge.regkey=Software\Perforce\Environment +p4merge.regkeyalt=Software\Wow6432Node\Perforce\Environment +p4merge.regname=P4INSTROOT +p4merge.regappend=\p4merge.exe +p4merge.gui=True +p4merge.priority=-8 +p4merge.diffargs=$parent $child + +p4mergeosx.executable = /Applications/p4merge.app/Contents/MacOS/p4merge +p4mergeosx.args = $base $local $other $output +p4mergeosx.gui = True +p4mergeosx.priority=-8 +p4mergeosx.diffargs=$parent $child + +tortoisemerge.args=/base:$base /mine:$local /theirs:$other /merged:$output +tortoisemerge.regkey=Software\TortoiseSVN +tortoisemerge.regkeyalt=Software\Wow6432Node\TortoiseSVN +tortoisemerge.check=changed +tortoisemerge.gui=True +tortoisemerge.priority=-8 +tortoisemerge.diffargs=/base:$parent /mine:$child /basename:'$plabel1' /minename:'$clabel' + +ecmerge.args=$base $local $other --mode=merge3 --title0=base --title1=local --title2=other --to=$output +ecmerge.regkey=Software\Elli\xc3\xa9 Computing\Merge +ecmerge.regkeyalt=Software\Wow6432Node\Elli\xc3\xa9 Computing\Merge +ecmerge.gui=True +ecmerge.diffargs=$parent $child --mode=diff2 --title1='$plabel1' --title2='$clabel' + +# editmerge is a small script shipped in contrib. +# It needs this config otherwise it behaves the same as internal:local +editmerge.args=$output +editmerge.check=changed +editmerge.premerge=keep + +filemerge.executable=/Developer/Applications/Utilities/FileMerge.app/Contents/MacOS/FileMerge +filemerge.args=-left $other -right $local -ancestor $base -merge $output +filemerge.gui=True + +; Windows version of Beyond Compare +beyondcompare3.args=$local $other $base $output /ro /lefttitle=local /centertitle=base /righttitle=other /automerge /reviewconflicts /solo +beyondcompare3.regkey=Software\Scooter Software\Beyond Compare 3 +beyondcompare3.regname=ExePath +beyondcompare3.gui=True +beyondcompare3.priority=-2 +beyondcompare3.diffargs=/lro /lefttitle='$plabel1' /righttitle='$clabel' /solo /expandall $parent $child + +; Linux version of Beyond Compare +bcompare.args=$local $other $base -mergeoutput=$output -ro -lefttitle=parent1 -centertitle=base -righttitle=parent2 -outputtitle=merged -automerge -reviewconflicts -solo +bcompare.gui=True +bcompare.priority=-1 +bcompare.diffargs=-lro -lefttitle='$plabel1' -righttitle='$clabel' -solo -expandall $parent $child + +winmerge.args=/e /x /wl /ub /dl other /dr local $other $local $output +winmerge.regkey=Software\Thingamahoochie\WinMerge +winmerge.regkeyalt=Software\Wow6432Node\Thingamahoochie\WinMerge\ +winmerge.regname=Executable +winmerge.check=changed +winmerge.gui=True +winmerge.priority=-10 +winmerge.diffargs=/r /e /x /ub /wl /dl '$plabel1' /dr '$clabel' $parent $child + +araxis.regkey=SOFTWARE\Classes\TypeLib\{46799e0a-7bd1-4330-911c-9660bb964ea2}\7.0\HELPDIR +araxis.regappend=\ConsoleCompare.exe +araxis.priority=-2 +araxis.args=/3 /a2 /wait /merge /title1:"Other" /title2:"Base" /title3:"Local :"$local $other $base $local $output +araxis.checkconflict=True +araxis.binary=True +araxis.gui=True +araxis.diffargs=/2 /wait /title1:"$plabel1" /title2:"$clabel" $parent $child + +diffuse.priority=-3 +diffuse.args=$local $base $other +diffuse.gui=True +diffuse.diffargs=$parent $child + +UltraCompare.regkey=Software\Microsoft\Windows\CurrentVersion\App Paths\UC.exe +UltraCompare.regkeyalt=Software\Wow6432Node\Microsoft\Windows\CurrentVersion\App Paths\UC.exe +UltraCompare.args = $base $local $other -title1 base -title3 other +UltraCompare.priority = -2 +UltraCompare.gui = True +UltraCompare.binary = True +UltraCompare.check = conflicts,changed +UltraCompare.diffargs=$child $parent -title1 $clabel -title2 $plabel1
--- a/mercurial/dispatch.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/dispatch.py Wed Nov 12 15:18:30 2014 -0600 @@ -402,7 +402,7 @@ return '' cmd = re.sub(r'\$(\d+|\$)', _checkvar, self.definition[1:]) cmd = aliasinterpolate(self.name, args, cmd) - return util.system(cmd, environ=env, out=ui.fout) + return ui.system(cmd, environ=env) self.fn = fn return
--- a/mercurial/exchange.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/exchange.py Wed Nov 12 15:18:30 2014 -0600 @@ -298,7 +298,7 @@ else: # adds changeset we are going to push as draft # - # should not be necessary for pushblishing server, but because of an + # should not be necessary for publishing server, but because of an # issue fixed in xxxxx we have to do it anyway. fdroots = list(unfi.set('roots(%ln + %ln::)', outgoing.missing, droots)) @@ -445,10 +445,25 @@ pushop.outgoing) if not pushop.force: bundler.newpart('B2X:CHECK:HEADS', data=iter(pushop.remoteheads)) - cg = changegroup.getlocalchangegroup(pushop.repo, 'push', pushop.outgoing) - cgpart = bundler.newpart('B2X:CHANGEGROUP', data=cg.getchunks()) + b2caps = bundle2.bundle2caps(pushop.remote) + version = None + cgversions = b2caps.get('b2x:changegroup') + if not cgversions: # 3.1 and 3.2 ship with an empty value + cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push', + pushop.outgoing) + else: + cgversions = [v for v in cgversions if v in changegroup.packermap] + if not cgversions: + raise ValueError(_('no common changegroup version')) + version = max(cgversions) + cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push', + pushop.outgoing, + version=version) + cgpart = bundler.newpart('B2X:CHANGEGROUP', data=cg) + if version is not None: + cgpart.addparam('version', version) def handlereply(op): - """extract addchangroup returns from server reply""" + """extract addchangegroup returns from server reply""" cgreplies = op.records.getreplies(cgpart.id) assert len(cgreplies['changegroup']) == 1 pushop.cgresult = cgreplies['changegroup'][0]['return'] @@ -702,7 +717,7 @@ pushop.ui.warn(msg) else: - # fallback to independant pushkey command + # fallback to independent pushkey command for newremotehead in outdated: r = pushop.remote.pushkey('phases', newremotehead.hex(), @@ -775,7 +790,7 @@ class pulloperation(object): """A object that represent a single pull operation - It purpose is to carry push related state and very common operation. + It purpose is to carry pull related state and very common operation. A new should be created at the beginning of each pull and discarded afterward. @@ -839,16 +854,15 @@ """close transaction if created""" if self._tr is not None: repo = self.repo - cl = repo.unfiltered().changelog - p = cl.writepending() and repo.root or "" - p = cl.writepending() and repo.root or "" + p = lambda: self._tr.writepending() and repo.root or "" repo.hook('b2x-pretransactionclose', throw=True, pending=p, **self._tr.hookargs) - self._tr.close() hookargs = dict(self._tr.hookargs) def runhooks(): repo.hook('b2x-transactionclose', **hookargs) - repo._afterlock(runhooks) + self._tr.addpostclose('b2x-hook-transactionclose', + lambda: repo._afterlock(runhooks)) + self._tr.close() def releasetransaction(self): """release transaction if created""" @@ -1001,9 +1015,9 @@ return pullop.stepsdone.add('changegroup') if not pullop.fetch: - pullop.repo.ui.status(_("no changes found\n")) - pullop.cgresult = 0 - return + pullop.repo.ui.status(_("no changes found\n")) + pullop.cgresult = 0 + return pullop.gettransaction() if pullop.heads is None and list(pullop.common) == [nullid]: pullop.repo.ui.status(_("requesting all changes\n")) @@ -1169,10 +1183,11 @@ b2caps.update(bundle2.decodecaps(blob)) bundler = bundle2.bundle20(repo.ui, b2caps) + kwargs['heads'] = heads + kwargs['common'] = common + for name in getbundle2partsorder: func = getbundle2partsmapping[name] - kwargs['heads'] = heads - kwargs['common'] = common func(bundler, repo, source, bundlecaps=bundlecaps, b2caps=b2caps, **kwargs) @@ -1185,11 +1200,26 @@ cg = None if kwargs.get('cg', True): # build changegroup bundle here. - cg = changegroup.getchangegroup(repo, source, heads=heads, - common=common, bundlecaps=bundlecaps) + version = None + cgversions = b2caps.get('b2x:changegroup') + if not cgversions: # 3.1 and 3.2 ship with an empty value + cg = changegroup.getchangegroupraw(repo, source, heads=heads, + common=common, + bundlecaps=bundlecaps) + else: + cgversions = [v for v in cgversions if v in changegroup.packermap] + if not cgversions: + raise ValueError(_('no common changegroup version')) + version = max(cgversions) + cg = changegroup.getchangegroupraw(repo, source, heads=heads, + common=common, + bundlecaps=bundlecaps, + version=version) if cg: - bundler.newpart('b2x:changegroup', data=cg.getchunks()) + part = bundler.newpart('b2x:changegroup', data=cg) + if version is not None: + part.addparam('version', version) @getbundle2partsgenerator('listkeys') def _getbundlelistkeysparts(bundler, repo, source, bundlecaps=None, @@ -1249,15 +1279,15 @@ tr.hookargs['url'] = url tr.hookargs['bundle2-exp'] = '1' r = bundle2.processbundle(repo, cg, lambda: tr).reply - cl = repo.unfiltered().changelog - p = cl.writepending() and repo.root or "" + p = lambda: tr.writepending() and repo.root or "" repo.hook('b2x-pretransactionclose', throw=True, pending=p, **tr.hookargs) - tr.close() hookargs = dict(tr.hookargs) def runhooks(): repo.hook('b2x-transactionclose', **hookargs) - repo._afterlock(runhooks) + tr.addpostclose('b2x-hook-transactionclose', + lambda: repo._afterlock(runhooks)) + tr.close() except Exception, exc: exc.duringunbundle2 = True raise
--- a/mercurial/filemerge.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/filemerge.py Wed Nov 12 15:18:30 2014 -0600 @@ -37,6 +37,9 @@ def _findtool(ui, tool): if tool in internals: return tool + return findexternaltool(ui, tool) + +def findexternaltool(ui, tool): for kn in ("regkey", "regkeyalt"): k = _toolstr(ui, tool, kn) if not k: @@ -298,8 +301,7 @@ replace = {'local': a, 'base': b, 'other': c, 'output': out} args = util.interpolate(r'\$', replace, args, lambda s: util.shellquote(util.localpath(s))) - r = util.system(toolpath + ' ' + args, cwd=repo.root, environ=env, - out=ui.fout) + r = ui.system(toolpath + ' ' + args, cwd=repo.root, environ=env) return True, r return False, 0
--- a/mercurial/help/config.txt Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/help/config.txt Wed Nov 12 15:18:30 2014 -0600 @@ -38,6 +38,7 @@ - ``<install-root>/etc/mercurial/hgrc.d/*.rc`` (per-installation) - ``/etc/mercurial/hgrc`` (per-system) - ``/etc/mercurial/hgrc.d/*.rc`` (per-system) + - ``<internal>/default.d/*.rc`` (defaults) .. container:: verbose.windows @@ -51,6 +52,7 @@ - ``<install-dir>\Mercurial.ini`` (per-installation) - ``<install-dir>\hgrc.d\*.rc`` (per-installation) - ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` (per-installation) + - ``<internal>/default.d/*.rc`` (defaults) .. note:: @@ -67,6 +69,7 @@ - ``<install-root>/lib/mercurial/hgrc.d/*.rc`` (per-installation) - ``/lib/mercurial/hgrc`` (per-system) - ``/lib/mercurial/hgrc.d/*.rc`` (per-system) + - ``<internal>/default.d/*.rc`` (defaults) Per-repository configuration options only apply in a particular repository. This file is not version-controlled, and @@ -102,6 +105,13 @@ executed by any user in any directory. Options in these files override per-installation options. +Mercurial comes with some default configuration. The default configuration +files are installed with Mercurial and will be overwritten on upgrades. Default +configuration files should never be edited by users or administrators but can +be overridden in other configuration files. So far the directory only contains +merge tool configuration but packagers can also put other default configuration +there. + Syntax ======
--- a/mercurial/hg.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/hg.py Wed Nov 12 15:18:30 2014 -0600 @@ -390,7 +390,7 @@ dstcachedir = os.path.join(destpath, 'cache') # In local clones we're copying all nodes, not just served - # ones. Therefore copy all branchcaches over. + # ones. Therefore copy all branch caches over. copybranchcache('branch2') for cachename in repoview.filtertable: copybranchcache('branch2-%s' % cachename)
--- a/mercurial/hook.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/hook.py Wed Nov 12 15:18:30 2014 -0600 @@ -131,10 +131,7 @@ cwd = repo.root else: cwd = os.getcwd() - if 'HG_URL' in env and env['HG_URL'].startswith('remote:http'): - r = util.system(cmd, environ=env, cwd=cwd, out=ui) - else: - r = util.system(cmd, environ=env, cwd=cwd, out=ui.fout) + r = ui.system(cmd, environ=env, cwd=cwd) duration = time.time() - starttime ui.log('exthook', 'exthook-%s: %s finished in %0.2f seconds\n',
--- a/mercurial/localrepo.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/localrepo.py Wed Nov 12 15:18:30 2014 -0600 @@ -316,6 +316,9 @@ chunkcachesize = self.ui.configint('format', 'chunkcachesize') if chunkcachesize is not None: self.sopener.options['chunkcachesize'] = chunkcachesize + maxchainlen = self.ui.configint('format', 'maxchainlen') + if maxchainlen is not None: + self.sopener.options['maxchainlen'] = maxchainlen def _writerequirements(self): reqfile = self.opener("requires", "w") @@ -1437,15 +1440,14 @@ files = [] # update changelog - self.changelog.delayupdate() + self.changelog.delayupdate(tr) n = self.changelog.add(mn, files, ctx.description(), trp, p1.node(), p2.node(), user, ctx.date(), ctx.extra().copy()) - p = lambda: self.changelog.writepending() and self.root or "" + p = lambda: tr.writepending() and self.root or "" xp1, xp2 = p1.hex(), p2 and p2.hex() or '' self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1, parent2=xp2, pending=p) - self.changelog.finalize(trp) # set the new commit is proper phase targetphase = subrepo.newcommitphase(self.ui, ctx) if targetphase:
--- a/mercurial/pathutil.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/pathutil.py Wed Nov 12 15:18:30 2014 -0600 @@ -146,7 +146,7 @@ def normasprefix(path): '''normalize the specified path as path prefix - Returned vaule can be used safely for "p.startswith(prefix)", + Returned value can be used safely for "p.startswith(prefix)", "p[len(prefix):]", and so on. For efficiency, this expects "path" argument to be already
--- a/mercurial/revlog.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/revlog.py Wed Nov 12 15:18:30 2014 -0600 @@ -204,6 +204,7 @@ self._basecache = None self._chunkcache = (0, '') self._chunkcachesize = 65536 + self._maxchainlen = None self.index = [] self._pcache = {} self._nodecache = {nullid: nullrev} @@ -219,6 +220,8 @@ v = 0 if 'chunkcachesize' in opts: self._chunkcachesize = opts['chunkcachesize'] + if 'maxchainlen' in opts: + self._maxchainlen = opts['maxchainlen'] if self._chunkcachesize <= 0: raise RevlogError(_('revlog chunk cache size %r is not greater ' @@ -350,6 +353,20 @@ rev = base base = index[rev][3] return base + def chainlen(self, rev): + index = self.index + generaldelta = self._generaldelta + iterrev = rev + e = index[iterrev] + clen = 0 + while iterrev != e[3]: + clen += 1 + if generaldelta: + iterrev = e[3] + else: + iterrev -= 1 + e = index[iterrev] + return clen def flags(self, rev): return self.index[rev][0] & 0xFFFF def rawsize(self, rev): @@ -1202,11 +1219,13 @@ base = rev else: base = chainbase - return dist, l, data, base, chainbase + chainlen = self.chainlen(rev) + 1 + return dist, l, data, base, chainbase, chainlen curr = len(self) prev = curr - 1 base = chainbase = curr + chainlen = None offset = self.end(prev) flags = 0 d = None @@ -1226,7 +1245,7 @@ d = builddelta(prev) else: d = builddelta(prev) - dist, l, data, base, chainbase = d + dist, l, data, base, chainbase, chainlen = d # full versions are inserted when the needed deltas # become comparable to the uncompressed text @@ -1235,7 +1254,8 @@ cachedelta[1]) else: textlen = len(text) - if d is None or dist > textlen * 2: + if (d is None or dist > textlen * 2 or + self._maxchainlen and chainlen > self._maxchainlen): text = buildtext() data = self.compress(text) l = len(data[1]) + len(data[0])
--- a/mercurial/revset.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/revset.py Wed Nov 12 15:18:30 2014 -0600 @@ -265,9 +265,8 @@ return stringset(repo, subset, x) def rangeset(repo, subset, x, y): - cl = baseset(repo.changelog) - m = getset(repo, cl, x) - n = getset(repo, cl, y) + m = getset(repo, fullreposet(repo), x) + n = getset(repo, fullreposet(repo), y) if not m or not n: return baseset() @@ -371,7 +370,7 @@ raise error.ParseError(_("~ expects a number")) ps = set() cl = repo.changelog - for r in getset(repo, baseset(cl), x): + for r in getset(repo, fullreposet(repo), x): for i in range(n): r = cl.parentrevs(r)[0] ps.add(r) @@ -573,7 +572,7 @@ """``children(set)`` Child changesets of changesets in set. """ - s = getset(repo, baseset(repo), x) + s = getset(repo, fullreposet(repo), x) cs = _children(repo, subset, s) return subset & cs @@ -1258,7 +1257,7 @@ raise error.ParseError(_("^ expects a number 0, 1, or 2")) ps = set() cl = repo.changelog - for r in getset(repo, baseset(cl), x): + for r in getset(repo, fullreposet(repo), x): if n == 0: ps.add(r) elif n == 1: @@ -1384,7 +1383,7 @@ # i18n: "matching" is a keyword l = getargs(x, 1, 2, _("matching takes 1 or 2 arguments")) - revs = getset(repo, baseset(repo.changelog), l[0]) + revs = getset(repo, fullreposet(repo), l[0]) fieldlist = ['metadata'] if len(l) > 1: @@ -2551,7 +2550,7 @@ return it() def _trysetasclist(self): - """populate the _asclist attribut if possible and necessary""" + """populate the _asclist attribute if possible and necessary""" if self._genlist is not None and self._asclist is None: self._asclist = sorted(self._genlist) @@ -2744,7 +2743,7 @@ # We have to use this complex iteration strategy to allow multiple # iterations at the same time. We need to be able to catch revision - # removed from `consumegen` and added to genlist in another instance. + # removed from _consumegen and added to genlist in another instance. # # Getting rid of it would provide an about 15% speed up on this # iteration. @@ -2939,17 +2938,15 @@ class fullreposet(_spanset): """a set containing all revisions in the repo - This class exists to host special optimisation. + This class exists to host special optimization. """ def __init__(self, repo): super(fullreposet, self).__init__(repo) def __and__(self, other): - """fullrepo & other -> other - - As self contains the whole repo, all of the other set should also be in - self. Therefor `self & other = other`. + """As self contains the whole repo, all of the other set should also be + in self. Therefore `self & other = other`. This boldly assumes the other contains valid revs only. """
--- a/mercurial/scmutil.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/scmutil.py Wed Nov 12 15:18:30 2014 -0600 @@ -495,7 +495,13 @@ def osrcpath(): '''return default os-specific hgrc search path''' - path = systemrcpath() + path = [] + defaultpath = os.path.join(util.datapath, 'default.d') + if os.path.isdir(defaultpath): + for f, kind in osutil.listdir(defaultpath): + if f.endswith('.rc'): + path.append(os.path.join(defaultpath, f)) + path.extend(systemrcpath()) path.extend(userrcpath()) path = [os.path.normpath(f) for f in path] return path @@ -680,9 +686,9 @@ rejected = [] m.bad = lambda x, y: rejected.append(x) - added, unknown, deleted, removed = _interestingfiles(repo, m) + added, unknown, deleted, removed, forgotten = _interestingfiles(repo, m) - unknownset = set(unknown) + unknownset = set(unknown + forgotten) toprint = unknownset.copy() toprint.update(deleted) for abs in sorted(toprint): @@ -698,7 +704,7 @@ similarity) if not dry_run: - _markchanges(repo, unknown, deleted, renames) + _markchanges(repo, unknown + forgotten, deleted, renames) for f in rejected: if f in m.files(): @@ -712,10 +718,10 @@ rejected = [] m.bad = lambda x, y: rejected.append(x) - added, unknown, deleted, removed = _interestingfiles(repo, m) + added, unknown, deleted, removed, forgotten = _interestingfiles(repo, m) if repo.ui.verbose: - unknownset = set(unknown) + unknownset = set(unknown + forgotten) toprint = unknownset.copy() toprint.update(deleted) for abs in sorted(toprint): @@ -728,7 +734,7 @@ renames = _findrenames(repo, m, added + unknown, removed + deleted, similarity) - _markchanges(repo, unknown, deleted, renames) + _markchanges(repo, unknown + forgotten, deleted, renames) for f in rejected: if f in m.files(): @@ -741,7 +747,7 @@ This is different from dirstate.status because it doesn't care about whether files are modified or clean.''' - added, unknown, deleted, removed = [], [], [], [] + added, unknown, deleted, removed, forgotten = [], [], [], [], [] audit_path = pathutil.pathauditor(repo.root) ctx = repo[None] @@ -754,13 +760,15 @@ unknown.append(abs) elif dstate != 'r' and not st: deleted.append(abs) + elif dstate == 'r' and st: + forgotten.append(abs) # for finding renames - elif dstate == 'r': + elif dstate == 'r' and not st: removed.append(abs) elif dstate == 'a': added.append(abs) - return added, unknown, deleted, removed + return added, unknown, deleted, removed, forgotten def _findrenames(repo, matcher, added, removed, similarity): '''Find renames from removed files to added ones.'''
--- a/mercurial/sshpeer.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/sshpeer.py Wed Nov 12 15:18:30 2014 -0600 @@ -52,7 +52,7 @@ util.shellquote("%s init %s" % (_serverquote(remotecmd), _serverquote(self.path)))) ui.debug('running %s\n' % cmd) - res = util.system(cmd, out=ui.fout) + res = ui.system(cmd) if res != 0: self._abort(error.RepoError(_("could not create remote repo")))
--- a/mercurial/tagmerge.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/tagmerge.py Wed Nov 12 15:18:30 2014 -0600 @@ -39,7 +39,7 @@ # and between base and p2, possibly on separate clones # 4. for each tag found both on p1 and p2 perform the following merge algorithm: # - the tags conflict if their tag "histories" have the same "rank" (i.e. -# length) _AND_ the last (current) tag is _NOT_ the same +# length) AND the last (current) tag is NOT the same # - for non conflicting tags: # - choose which are the high and the low ranking nodes # - the high ranking list of nodes is the one that is longer. @@ -57,7 +57,7 @@ # 5. write the merged tags taking into account to their positions in the first # parent (i.e. try to keep the relative ordering of the nodes that come # from p1). This minimizes the diff between the merged and the p1 tag files -# This is donw by using the following algorithm +# This is done by using the following algorithm # - group the nodes for a given tag that must be written next to each other # - A: nodes that come from consecutive lines on p1 # - B: nodes that come from p2 (i.e. whose associated line number is @@ -81,9 +81,9 @@ def readtagsformerge(ui, repo, lines, fn='', keeplinenums=False): '''read the .hgtags file into a structure that is suitable for merging - Sepending on the keeplinenumbers flag, clear the line numbers associated - with each tag. Rhis is done because only the line numbers of the first - parent are useful for merging + Depending on the keeplinenums flag, clear the line numbers associated + with each tag. This is done because only the line numbers of the first + parent are useful for merging. ''' filetags = tagsmod._readtaghist(ui, repo, lines, fn=fn, recode=None, calcnodelines=True)[1]
--- a/mercurial/tags.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/tags.py Wed Nov 12 15:18:30 2014 -0600 @@ -87,7 +87,7 @@ def _readtaghist(ui, repo, lines, fn, recode=None, calcnodelines=False): '''Read tag definitions from a file (or any source of lines). This function returns two sortdicts with similar information: - - the first dict, bingtaglist, contains the tag information as expected by + - the first dict, bintaghist, contains the tag information as expected by the _readtags function, i.e. a mapping from tag name to (node, hist): - node is the node id from the last line read for that name, - hist is the list of node ids previously associated with it (in file
--- a/mercurial/transaction.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/transaction.py Wed Nov 12 15:18:30 2014 -0600 @@ -43,7 +43,7 @@ raise backupfiles = [] - for f, b, _ignore in backupentries: + for f, b in backupentries: filepath = opener.join(f) backuppath = opener.join(b) try: @@ -83,24 +83,33 @@ self.onclose = onclose self.onabort = onabort self.entries = [] - self.backupentries = [] self.map = {} - self.backupmap = {} + # a list of ('path', 'backuppath') entries. + self._backupentries = [] + self._backupmap = {} self.journal = journal self._queue = [] # a dict of arguments to be passed to hooks self.hookargs = {} - self.backupjournal = "%s.backupfiles" % journal + self._backupjournal = "%s.backupfiles" % journal self.file = opener.open(self.journal, "w") - self.backupsfile = opener.open(self.backupjournal, 'w') - self.backupsfile.write('%d\n' % version) + self._backupsfile = opener.open(self._backupjournal, 'w') + self._backupsfile.write('%d\n' % version) if createmode is not None: opener.chmod(self.journal, createmode & 0666) - opener.chmod(self.backupjournal, createmode & 0666) + opener.chmod(self._backupjournal, createmode & 0666) # hold file generations to be performed on commit self._filegenerators = {} + # hold callbalk to write pending data for hooks + self._pendingcallback = {} + # True is any pending data have been written ever + self._anypending = False + # holds callback to call when writing the transaction + self._finalizecallback = {} + # hold callbalk for post transaction close + self._postclosecallback = {} def __del__(self): if self.journal: @@ -108,38 +117,37 @@ @active def startgroup(self): - self._queue.append(([], [])) + """delay registration of file entry + + This is used by strip to delay vision of strip offset. The transaction + sees either none or all of the strip actions to be done.""" + self._queue.append([]) @active def endgroup(self): - q = self._queue.pop() - self.entries.extend(q[0]) - self.backupentries.extend(q[1]) - - offsets = [] - backups = [] - for f, o, _data in q[0]: - offsets.append((f, o)) + """apply delayed registration of file entry. - for f, b, _data in q[1]: - backups.append((f, b)) - - d = ''.join(['%s\0%d\n' % (f, o) for f, o in offsets]) - self.file.write(d) - self.file.flush() - - d = ''.join(['%s\0%s\n' % (f, b) for f, b in backups]) - self.backupsfile.write(d) - self.backupsfile.flush() + This is used by strip to delay vision of strip offset. The transaction + sees either none or all of the strip actions to be done.""" + q = self._queue.pop() + for f, o, data in q: + self._addentry(f, o, data) @active def add(self, file, offset, data=None): - if file in self.map or file in self.backupmap: + """record the state of an append-only file before update""" + if file in self.map or file in self._backupmap: return if self._queue: - self._queue[-1][0].append((file, offset, data)) + self._queue[-1].append((file, offset, data)) return + self._addentry(file, offset, data) + + def _addentry(self, file, offset, data): + """add a append-only entry to memory and on-disk state""" + if file in self.map or file in self._backupmap: + return self.entries.append((file, offset, data)) self.map[file] = len(self.entries) - 1 # add enough data to the journal to do the truncate @@ -157,8 +165,11 @@ * `file`: the file path, relative to .hg/store * `hardlink`: use a hardlink to quickly create the backup """ + if self._queue: + msg = 'cannot use transaction.addbackup inside "group"' + raise RuntimeError(msg) - if file in self.map or file in self.backupmap: + if file in self.map or file in self._backupmap: return backupfile = "%s.backup.%s" % (self.journal, file) if vfs is None: @@ -171,14 +182,10 @@ self.add(file, 0) return - if self._queue: - self._queue[-1][1].append((file, backupfile)) - return - - self.backupentries.append((file, backupfile, None)) - self.backupmap[file] = len(self.backupentries) - 1 - self.backupsfile.write("%s\0%s\n" % (file, backupfile)) - self.backupsfile.flush() + self._backupentries.append((file, backupfile)) + self._backupmap[file] = len(self._backupentries) - 1 + self._backupsfile.write("%s\0%s\n" % (file, backupfile)) + self._backupsfile.flush() @active def addfilegenerator(self, genid, filenames, genfunc, order=0, vfs=None): @@ -229,8 +236,8 @@ def find(self, file): if file in self.map: return self.entries[self.map[file]] - if file in self.backupmap: - return self.backupentries[self.backupmap[file]] + if file in self._backupmap: + return self._backupentries[self._backupmap[file]] return None @active @@ -263,29 +270,74 @@ def running(self): return self.count > 0 + def addpending(self, category, callback): + """add a callback to be called when the transaction is pending + + Category is a unique identifier to allow overwriting an old callback + with a newer callback. + """ + self._pendingcallback[category] = callback + + @active + def writepending(self): + '''write pending file to temporary version + + This is used to allow hooks to view a transaction before commit''' + categories = sorted(self._pendingcallback) + for cat in categories: + # remove callback since the data will have been flushed + any = self._pendingcallback.pop(cat)() + self._anypending = self._anypending or any + return self._anypending + + @active + def addfinalize(self, category, callback): + """add a callback to be called when the transaction is closed + + Category is a unique identifier to allow overwriting old callbacks with + newer callbacks. + """ + self._finalizecallback[category] = callback + + @active + def addpostclose(self, category, callback): + """add a callback to be called after the transaction is closed + + Category is a unique identifier to allow overwriting an old callback + with a newer callback. + """ + self._postclosecallback[category] = callback + @active def close(self): '''commit the transaction''' if self.count == 1 and self.onclose is not None: self._generatefiles() + categories = sorted(self._finalizecallback) + for cat in categories: + self._finalizecallback[cat]() self.onclose() self.count -= 1 if self.count != 0: return self.file.close() - self.backupsfile.close() + self._backupsfile.close() self.entries = [] if self.after: self.after() if self.opener.isfile(self.journal): self.opener.unlink(self.journal) - if self.opener.isfile(self.backupjournal): - self.opener.unlink(self.backupjournal) - for _f, b, _ignore in self.backupentries: + if self.opener.isfile(self._backupjournal): + self.opener.unlink(self._backupjournal) + for _f, b in self._backupentries: self.opener.unlink(b) - self.backupentries = [] + self._backupentries = [] self.journal = None + # run post close action + categories = sorted(self._postclosecallback) + for cat in categories: + self._postclosecallback[cat]() @active def abort(self): @@ -298,24 +350,24 @@ self.count = 0 self.usages = 0 self.file.close() - self.backupsfile.close() + self._backupsfile.close() if self.onabort is not None: self.onabort() try: - if not self.entries and not self.backupentries: + if not self.entries and not self._backupentries: if self.journal: self.opener.unlink(self.journal) - if self.backupjournal: - self.opener.unlink(self.backupjournal) + if self._backupjournal: + self.opener.unlink(self._backupjournal) return self.report(_("transaction abort!\n")) try: _playback(self.journal, self.report, self.opener, - self.entries, self.backupentries, False) + self.entries, self._backupentries, False) self.report(_("rollback completed\n")) except Exception: self.report(_("rollback failed - please run hg recover\n")) @@ -360,7 +412,7 @@ # Shave off the trailing newline line = line[:-1] f, b = line.split('\0') - backupentries.append((f, b, None)) + backupentries.append((f, b)) else: report(_("journal was created by a newer version of " "Mercurial"))
--- a/mercurial/ui.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/ui.py Wed Nov 12 15:18:30 2014 -0600 @@ -537,7 +537,7 @@ return path or loc def pushbuffer(self, error=False): - """install a buffer to capture standar output of the ui object + """install a buffer to capture standard output of the ui object If error is True, the error output will be captured too.""" self._buffers.append([]) @@ -814,10 +814,9 @@ editor = self.geteditor() - util.system("%s \"%s\"" % (editor, name), + self.system("%s \"%s\"" % (editor, name), environ=environ, - onerr=util.Abort, errprefix=_("edit failed"), - out=self.fout) + onerr=util.Abort, errprefix=_("edit failed")) f = open(name) t = f.read() @@ -827,6 +826,13 @@ return t + def system(self, cmd, environ={}, cwd=None, onerr=None, errprefix=None): + '''execute shell command with appropriate output stream. command + output will be redirected if fout is not stdout. + ''' + return util.system(cmd, environ=environ, cwd=cwd, onerr=onerr, + errprefix=errprefix, out=self.fout) + def traceback(self, exc=None, force=False): '''print exception traceback if traceback printing enabled or forced. only to call in exception handler. returns true if traceback
--- a/mercurial/util.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/util.py Wed Nov 12 15:18:30 2014 -0600 @@ -369,6 +369,12 @@ return self._list def iterkeys(self): return self._list.__iter__() + def iteritems(self): + for k in self._list: + yield k, self[k] + def insert(self, index, key, val): + self._list.insert(index, key) + dict.__setitem__(self, key, val) class lrucachedict(object): '''cache most recent gets from or sets to this dictionary''' @@ -613,9 +619,8 @@ '''enhanced shell command execution. run with environment maybe modified, maybe in different dir. - if command fails and onerr is None, return status. if ui object, - print error message and return status, else raise onerr object as - exception. + if command fails and onerr is None, return status, else raise onerr + object as exception. if out is specified, it is assumed to be a file-like object that has a write() method. stdout and stderr will be redirected to out.''' @@ -664,10 +669,7 @@ explainexit(rc)[0]) if errprefix: errmsg = '%s: %s' % (errprefix, errmsg) - try: - onerr.warn(errmsg + '\n') - except AttributeError: - raise onerr(errmsg) + raise onerr(errmsg) return rc def checksignature(func): @@ -1148,7 +1150,7 @@ """Read L bytes of data from the iterator of chunks of data. Returns less than L bytes if the iterator runs dry. - If size parameter is ommited, read everything""" + If size parameter is omitted, read everything""" left = l buf = [] queue = self._queue
--- a/mercurial/wireproto.py Tue Nov 11 17:25:09 2014 -0600 +++ b/mercurial/wireproto.py Wed Nov 12 15:18:30 2014 -0600 @@ -827,7 +827,7 @@ r = exchange.unbundle(repo, gen, their_heads, 'serve', proto._client()) if util.safehasattr(r, 'addpart'): - # The return looks streameable, we are in the bundle2 case and + # The return looks streamable, we are in the bundle2 case and # should return a stream. return streamres(r.getchunks()) return pushres(r)
--- a/setup.py Tue Nov 11 17:25:09 2014 -0600 +++ b/setup.py Wed Nov 12 15:18:30 2014 -0600 @@ -517,6 +517,7 @@ packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo', 'help/*.txt', + 'default.d/*.rc', 'dummycert.pem']} def ordinarypath(p):
--- a/tests/dumbhttp.py Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/dumbhttp.py Wed Nov 12 15:18:30 2014 -0600 @@ -5,15 +5,18 @@ """ from optparse import OptionParser -import BaseHTTPServer, SimpleHTTPServer, os, signal, subprocess, sys +import BaseHTTPServer, SimpleHTTPServer, signal, sys +from mercurial import cmdutil -def run(server_class=BaseHTTPServer.HTTPServer, - handler_class=SimpleHTTPServer.SimpleHTTPRequestHandler, - server_address=('localhost', 8000)): - httpd = server_class(server_address, handler_class) - httpd.serve_forever() - +class simplehttpservice(object): + def __init__(self, host, port): + self.address = (host, port) + def init(self): + self.httpd = BaseHTTPServer.HTTPServer( + self.address, SimpleHTTPServer.SimpleHTTPRequestHandler) + def run(self): + self.httpd.serve_forever() if __name__ == '__main__': parser = OptionParser() @@ -26,6 +29,7 @@ parser.add_option('-f', '--foreground', dest='foreground', action='store_true', help='do not start the HTTP server in the background') + parser.add_option('--daemon-pipefds') (options, args) = parser.parse_args() @@ -34,21 +38,9 @@ if options.foreground and options.pid: parser.error("options --pid and --foreground are mutually exclusive") - if options.foreground: - run(server_address=(options.host, options.port)) - else: - # This doesn't attempt to cleanly detach the process, as it's not - # meant to be a long-lived, independent process. As a consequence, - # it's still part of the same process group, and keeps any file - # descriptors it might have inherited besided stdin/stdout/stderr. - # Trying to do things cleanly is more complicated, requires - # OS-dependent code, and is not worth the effort. - proc = subprocess.Popen([sys.executable, __file__, '-f', - '-H', options.host, '-p', str(options.port)], - stdin=open(os.devnull, 'r'), - stdout=open(os.devnull, 'w'), - stderr=subprocess.STDOUT) - if options.pid: - fp = file(options.pid, 'wb') - fp.write(str(proc.pid) + '\n') - fp.close() + opts = {'pid_file': options.pid, + 'daemon': not options.foreground, + 'daemon_pipefds': options.daemon_pipefds} + service = simplehttpservice(options.host, options.port) + cmdutil.service(opts, initfn=service.init, runfn=service.run, + runargs=[sys.executable, __file__] + sys.argv[1:])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/generate-working-copy-states.py Wed Nov 12 15:18:30 2014 -0600 @@ -0,0 +1,50 @@ +# generate proper file state to test working copy behavior +import sys +import os + +# build the combination of possible states +combination = [] +for base in [None, 'content1']: + for parent in set([None, 'content2']) | set([base]): + for wcc in set([None, 'content3']) | set([base, parent]): + for tracked in (False, True): + def statestring(content): + return content is None and 'missing' or content + trackedstring = tracked and 'tracked' or 'untracked' + filename = "%s_%s_%s-%s" % (statestring(base), + statestring(parent), + statestring(wcc), + trackedstring) + combination.append((filename, base, parent, wcc)) + +# make sure we have stable output +combination.sort() + +# retrieve the state we must generate +target = sys.argv[1] + +# compute file content +content = [] +for filename, base, parent, wcc in combination: + if target == 'filelist': + print filename + elif target == 'base': + content.append((filename, base)) + elif target == 'parent': + content.append((filename, parent)) + elif target == 'wc': + # Make sure there is content so the file gets written and can be + # tracked. It will be deleted outside of this script. + content.append((filename, wcc or 'TOBEDELETED')) + else: + print >> sys.stderr, "unknown target:", target + sys.exit(1) + +# write actual content +for filename, data in content: + if data is not None: + f = open(filename, 'w') + f.write(data + '\n') + f.close() + elif os.path.exists(filename): + os.remove(filename)
--- a/tests/hghave.py Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/hghave.py Wed Nov 12 15:18:30 2014 -0600 @@ -289,14 +289,17 @@ @check("json", "some json module available") def has_json(): try: - if sys.version_info < (2, 7): - import simplejson as json - else: - import json + import json json.dumps return True except ImportError: - return False + try: + import simplejson as json + json.dumps + return True + except ImportError: + pass + return False @check("outer-repo", "outer repo") def has_outer_repo():
--- a/tests/run-tests.py Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/run-tests.py Wed Nov 12 15:18:30 2014 -0600 @@ -61,12 +61,12 @@ import unittest try: - if sys.version_info < (2, 7): + import json +except ImportError: + try: import simplejson as json - else: - import json -except ImportError: - json = None + except ImportError: + json = None processlock = threading.Lock() @@ -500,7 +500,7 @@ except self.failureException, e: # This differs from unittest in that we don't capture # the stack trace. This is for historical reasons and - # this decision could be revisted in the future, + # this decision could be revisited in the future, # especially for PythonTest instances. if result.addFailure(self, str(e)): success = True @@ -1263,7 +1263,7 @@ iolock.release() class TestSuite(unittest.TestSuite): - """Custom unitest TestSuite that knows how to execute Mercurial tests.""" + """Custom unittest TestSuite that knows how to execute Mercurial tests.""" def __init__(self, testdir, jobs=1, whitelist=None, blacklist=None, retest=False, keywords=None, loop=False, @@ -1895,8 +1895,8 @@ the one we expect it to be. If not, print a warning to stderr.""" if ((self._bindir == self._pythondir) and (self._bindir != self._tmpbindir)): - # The pythondir has been infered from --with-hg flag. - # We cannot expect anything sensible here + # The pythondir has been inferred from --with-hg flag. + # We cannot expect anything sensible here. return expecthg = os.path.join(self._pythondir, 'mercurial') actualhg = self._gethgpath()
--- a/tests/test-abort-checkin.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-abort-checkin.t Wed Nov 12 15:18:30 2014 -0600 @@ -7,9 +7,11 @@ > EOF $ abspath=`pwd`/abortcommit.py - $ echo "[extensions]" >> $HGRCPATH - $ echo "mq=" >> $HGRCPATH - $ echo "abortcommit = $abspath" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > mq = + > abortcommit = $abspath + > EOF $ hg init foo $ cd foo
--- a/tests/test-add.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-add.t Wed Nov 12 15:18:30 2014 -0600 @@ -126,6 +126,19 @@ M a ? a.orig +Forgotten file can be added back (as either clean or modified) + + $ hg forget b + $ hg add b + $ hg st -A b + C b + $ hg forget b + $ echo modified > b + $ hg add b + $ hg st -A b + M b + $ hg revert -qC b + $ hg add c && echo "unexpected addition of missing file" c: * (glob) [1]
--- a/tests/test-addremove.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-addremove.t Wed Nov 12 15:18:30 2014 -0600 @@ -18,7 +18,11 @@ dir/bar_2 foo_2 committed changeset 1:e65414bf35c5 - $ cd ../.. + $ cd .. + $ hg forget foo + $ hg -v addremove + adding foo + $ cd .. $ hg init sim $ cd sim @@ -45,4 +49,9 @@ adding d recording removal of a as rename to b (100% similar) $ hg commit -mb + $ cp b c + $ hg forget b + $ hg addremove -s 50 + adding b + adding c $ cd ..
--- a/tests/test-bad-extension.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-bad-extension.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,11 +1,13 @@ $ echo 'raise Exception("bit bucket overflow")' > badext.py $ abspath=`pwd`/badext.py - $ echo '[extensions]' >> $HGRCPATH - $ echo "gpg =" >> $HGRCPATH - $ echo "hgext.gpg =" >> $HGRCPATH - $ echo "badext = $abspath" >> $HGRCPATH - $ echo "badext2 =" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > gpg = + > hgext.gpg = + > badext = $abspath + > badext2 = + > EOF $ hg -q help help *** failed to import extension badext from $TESTTMP/badext.py: bit bucket overflow
--- a/tests/test-branches.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-branches.t Wed Nov 12 15:18:30 2014 -0600 @@ -419,10 +419,12 @@ default branch colors: - $ echo "[extensions]" >> $HGRCPATH - $ echo "color =" >> $HGRCPATH - $ echo "[color]" >> $HGRCPATH - $ echo "mode = ansi" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > color = + > [color] + > mode = ansi + > EOF $ hg up -C c 3 files updated, 0 files merged, 2 files removed, 0 files unresolved @@ -444,14 +446,16 @@ \x1b[0;0ma\x1b[0m\x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc) \x1b[0;0mdefault\x1b[0m\x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc) - $ echo "[extensions]" >> $HGRCPATH - $ echo "color =" >> $HGRCPATH - $ echo "[color]" >> $HGRCPATH - $ echo "branches.active = green" >> $HGRCPATH - $ echo "branches.closed = blue" >> $HGRCPATH - $ echo "branches.current = red" >> $HGRCPATH - $ echo "branches.inactive = magenta" >> $HGRCPATH - $ echo "log.changeset = cyan" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > color = + > [color] + > branches.active = green + > branches.closed = blue + > branches.current = red + > branches.inactive = magenta + > log.changeset = cyan + > EOF custom branch colors:
--- a/tests/test-bundle2-exchange.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-bundle2-exchange.t Wed Nov 12 15:18:30 2014 -0600 @@ -59,8 +59,8 @@ adding file changes added 2 changesets with 2 changes to 2 files 1 new obsolescence markers + b2x-transactionclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=file:$TESTTMP/main changegroup hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_SOURCE=pull HG_URL=file:$TESTTMP/main - b2x-transactionclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=file:$TESTTMP/main updating to branch default 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg -R other log -G @@ -82,8 +82,8 @@ adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) 1 new obsolescence markers + b2x-transactionclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=file:$TESTTMP/main changegroup hook: HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_SOURCE=pull HG_URL=file:$TESTTMP/main - b2x-transactionclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=file:$TESTTMP/main (run 'hg heads' to see heads, 'hg merge' to merge) $ hg -R other log -G o 2:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F @@ -156,8 +156,8 @@ $ hg -R main push other --rev eea13746799a --bookmark book_eea1 pushing to other searching for changes + b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2-EXP=1 HG_NEW_OBSMARKERS=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_PHASES_MOVED=1 HG_SOURCE=push HG_URL=push changegroup hook: HG_BUNDLE2-EXP=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_SOURCE=push HG_URL=push - b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2-EXP=1 HG_NEW_OBSMARKERS=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_PHASES_MOVED=1 HG_SOURCE=push HG_URL=push remote: adding changesets remote: adding manifests remote: adding file changes @@ -189,8 +189,8 @@ added 1 changesets with 1 changes to 1 files (+1 heads) 1 new obsolescence markers updating bookmark book_02de + b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_NEW_OBSMARKERS=1 HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=ssh://user@dummy/main changegroup hook: HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_SOURCE=pull HG_URL=ssh://user@dummy/main - b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_NEW_OBSMARKERS=1 HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=ssh://user@dummy/main (run 'hg heads' to see heads, 'hg merge' to merge) $ hg -R other debugobsolete 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} @@ -212,8 +212,8 @@ added 1 changesets with 1 changes to 1 files (+1 heads) 1 new obsolescence markers updating bookmark book_42cc + b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_NEW_OBSMARKERS=1 HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=http://localhost:$HGPORT/ changegroup hook: HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_SOURCE=pull HG_URL=http://localhost:$HGPORT/ - b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_NEW_OBSMARKERS=1 HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=http://localhost:$HGPORT/ (run 'hg heads .' to see heads, 'hg merge' to merge) $ cat main-error.log $ hg -R other debugobsolete @@ -234,8 +234,8 @@ remote: added 1 changesets with 1 changes to 1 files remote: 1 new obsolescence markers updating bookmark book_5fdd + remote: b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2-EXP=1 HG_NEW_OBSMARKERS=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1 remote: changegroup hook: HG_BUNDLE2-EXP=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1 - remote: b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2-EXP=1 HG_NEW_OBSMARKERS=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1 $ hg -R other log -G o 6:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C | @@ -462,7 +462,6 @@ searching for changes transaction abort! rollback completed - changegroup hook: HG_BUNDLE2-EXP=1 HG_NODE=e7ec4e813ba6b07be2a0516ce1a74bb4e503f91a HG_SOURCE=push HG_URL=push abort: b2x-pretransactionclose.failpush hook exited with status 1 [255] @@ -472,7 +471,6 @@ abort: b2x-pretransactionclose.failpush hook exited with status 1 remote: transaction abort! remote: rollback completed - remote: changegroup hook: HG_BUNDLE2-EXP=1 HG_NODE=e7ec4e813ba6b07be2a0516ce1a74bb4e503f91a HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1 [255] $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
--- a/tests/test-bundle2-format.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-bundle2-format.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,4 +1,4 @@ -This test is decicated to test the bundle2 container format +This test is dedicated to test the bundle2 container format It test multiple existing parts to test different feature of the container. You probably do not need to touch this test unless you change the binary encoding
--- a/tests/test-check-code.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-check-code.t Wed Nov 12 15:18:30 2014 -0600 @@ -261,7 +261,7 @@ > print _("concatenating " " by " " space %s" % v) > print _("concatenating " + " by " + " '+' %s" % v) > - > print _("maping operation in different line %s" + > print _("mapping operation in different line %s" > % v) > > print _( @@ -278,7 +278,7 @@ > print _("concatenating " + " by " + " '+' %s" % v) don't use % inside _() ./map-inside-gettext.py:6: - > print _("maping operation in different line %s" + > print _("mapping operation in different line %s" don't use % inside _() ./map-inside-gettext.py:9: > print _(
--- a/tests/test-commit-amend.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-commit-amend.t Wed Nov 12 15:18:30 2014 -0600 @@ -889,9 +889,9 @@ The way mercurial does amends is to create a temporary commit (rev 3) and then fold the new and old commits together into another commit (rev 4). During this -process, findlimit is called to check how far back to look for the transitive +process, _findlimit is called to check how far back to look for the transitive closure of file copy information, but due to the divergence of the filelog -and changelog graph topologies, before findlimit was fixed, it returned a rev +and changelog graph topologies, before _findlimit was fixed, it returned a rev which was not far enough back in this case. $ hg mv a1 a2 $ hg status --copies --rev 0
--- a/tests/test-config.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-config.t Wed Nov 12 15:18:30 2014 -0600 @@ -44,9 +44,11 @@ Test case sensitive configuration - $ echo '[Section]' >> $HGRCPATH - $ echo 'KeY = Case Sensitive' >> $HGRCPATH - $ echo 'key = lower case' >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [Section] + > KeY = Case Sensitive + > key = lower case + > EOF $ hg showconfig Section Section.KeY=Case Sensitive
--- a/tests/test-convert-clonebranches.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-convert-clonebranches.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,8 +1,10 @@ - $ echo "[extensions]" >> $HGRCPATH - $ echo "convert = " >> $HGRCPATH - $ echo "[convert]" >> $HGRCPATH - $ echo "hg.tagsbranch=0" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > convert = + > [convert] + > hg.tagsbranch = 0 + > EOF $ hg init source $ cd source $ echo a > a
--- a/tests/test-convert-cvs-branch.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-convert-cvs-branch.t Wed Nov 12 15:18:30 2014 -0600 @@ -7,10 +7,12 @@ > { > cvs -f "$@" > /dev/null > } - $ echo "[extensions]" >> $HGRCPATH - $ echo "convert = " >> $HGRCPATH - $ echo "[convert]" >> $HGRCPATH - $ echo "cvsps.cache=0" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > convert = + > [convert] + > cvsps.cache = 0 + > EOF create cvs repository
--- a/tests/test-convert-cvs-detectmerge.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-convert-cvs-detectmerge.t Wed Nov 12 15:18:30 2014 -0600 @@ -23,11 +23,13 @@ XXX copied from test-convert-cvs-synthetic - $ echo "[extensions]" >> $HGRCPATH - $ echo "convert = " >> $HGRCPATH - $ echo "[convert]" >> $HGRCPATH - $ echo "cvsps.cache=0" >> $HGRCPATH - $ echo "cvsps.mergefrom=\[MERGE from (\S+)\]" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > convert = + > [convert] + > cvsps.cache = 0 + > cvsps.mergefrom = \[MERGE from (\S+)\] + > EOF create cvs repository with one project
--- a/tests/test-convert-cvs.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-convert-cvs.t Wed Nov 12 15:18:30 2014 -0600 @@ -18,9 +18,11 @@ > print "%s hook: %d changesets"%(hooktype,len(changesets)) > EOF $ hookpath=`pwd` - $ echo "[hooks]" >> $HGRCPATH - $ echo "cvslog=python:$hookpath/cvshooks.py:cvslog" >> $HGRCPATH - $ echo "cvschangesets=python:$hookpath/cvshooks.py:cvschangesets" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [hooks] + > cvslog = python:$hookpath/cvshooks.py:cvslog + > cvschangesets = python:$hookpath/cvshooks.py:cvschangesets + > EOF create cvs repository
--- a/tests/test-convert-hg-svn.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-convert-hg-svn.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,8 +1,10 @@ #require svn svn-bindings - $ echo "[extensions]" >> $HGRCPATH - $ echo "convert = " >> $HGRCPATH - $ echo "mq = " >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > convert = + > mq = + > EOF $ SVNREPOPATH=`pwd`/svn-repo #if windows
--- a/tests/test-convert-tagsbranch-topology.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-convert-tagsbranch-topology.t Wed Nov 12 15:18:30 2014 -0600 @@ -4,11 +4,13 @@ $ echo "autocrlf = false" >> $HOME/.gitconfig $ echo "[core]" >> $HOME/.gitconfig $ echo "autocrlf = false" >> $HOME/.gitconfig - $ echo "[extensions]" >> $HGRCPATH - $ echo "convert=" >> $HGRCPATH - $ echo '[convert]' >> $HGRCPATH - $ echo 'hg.usebranchnames = True' >> $HGRCPATH - $ echo 'hg.tagsbranch = tags-update' >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > convert = + > [convert] + > hg.usebranchnames = True + > hg.tagsbranch = tags-update + > EOF $ GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME $ GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL $ GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0000"; export GIT_AUTHOR_DATE
--- a/tests/test-debugcommands.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-debugcommands.t Wed Nov 12 15:18:30 2014 -0600 @@ -24,6 +24,40 @@ full revision size (min/max/avg) : 44 / 44 / 44 delta size (min/max/avg) : 0 / 0 / 0 +Test max chain len + $ cat >> $HGRCPATH << EOF + > [format] + > maxchainlen=4 + > EOF + + $ printf "This test checks if maxchainlen config value is respected also it can serve as basic test for debugrevlog -d <file>.\n" >> a + $ hg ci -m a + $ printf "b\n" >> a + $ hg ci -m a + $ printf "c\n" >> a + $ hg ci -m a + $ printf "d\n" >> a + $ hg ci -m a + $ printf "e\n" >> a + $ hg ci -m a + $ printf "f\n" >> a + $ hg ci -m a + $ printf 'g\n' >> a + $ hg ci -m a + $ printf 'h\n' >> a + $ hg ci -m a + $ hg debugrevlog -d a + # rev p1rev p2rev start end deltastart base p1 p2 rawsize totalsize compression heads chainlen + 0 -1 -1 0 ??? 0 0 0 0 ??? ???? ? 1 0 (glob) + 1 0 -1 ??? ??? 0 0 0 0 ??? ???? ? 1 1 (glob) + 2 1 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 2 (glob) + 3 2 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 3 (glob) + 4 3 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 4 (glob) + 5 4 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 0 (glob) + 6 5 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 1 (glob) + 7 6 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 2 (glob) + 8 7 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 3 (glob) + $ cd .. Test internal debugstacktrace command
--- a/tests/test-diff-color.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-diff-color.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,9 +1,11 @@ Setup - $ echo "[color]" >> $HGRCPATH - $ echo "mode = ansi" >> $HGRCPATH - $ echo "[extensions]" >> $HGRCPATH - $ echo "color=" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [color] + > mode = ansi + > [extensions] + > color = + > EOF $ hg init repo $ cd repo $ cat > a <<EOF @@ -66,11 +68,13 @@ $ hg diff --stat --color=always a | 2 \x1b[0;32m+\x1b[0m\x1b[0;31m-\x1b[0m (esc) 1 files changed, 1 insertions(+), 1 deletions(-) - $ echo "record=" >> $HGRCPATH - $ echo "[ui]" >> $HGRCPATH - $ echo "interactive=true" >> $HGRCPATH - $ echo "[diff]" >> $HGRCPATH - $ echo "git=True" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > record = + > [ui] + > interactive = true + > [diff] + > git = True + > EOF #if execbit
--- a/tests/test-diff-upgrade.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-diff-upgrade.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,9 +1,11 @@ #require execbit - $ echo "[extensions]" >> $HGRCPATH - $ echo "autodiff=$TESTDIR/autodiff.py" >> $HGRCPATH - $ echo "[diff]" >> $HGRCPATH - $ echo "nodates=1" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > autodiff = $TESTDIR/autodiff.py + > [diff] + > nodates = 1 + > EOF $ hg init repo $ cd repo
--- a/tests/test-eol.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-eol.t Wed Nov 12 15:18:30 2014 -0600 @@ -408,10 +408,12 @@ Test cleverencode: and cleverdecode: aliases for win32text extension - $ echo '[encode]' >> $HGRCPATH - $ echo '**.txt = cleverencode:' >> $HGRCPATH - $ echo '[decode]' >> $HGRCPATH - $ echo '**.txt = cleverdecode:' >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [encode] + > **.txt = cleverencode: + > [decode] + > **.txt = cleverdecode: + > EOF $ hg init win32compat $ cd win32compat
--- a/tests/test-eolfilename.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-eolfilename.t Wed Nov 12 15:18:30 2014 -0600 @@ -59,10 +59,12 @@ $ hg init bar $ cd bar - $ echo "[extensions]" >> $HGRCPATH - $ echo "color=" >> $HGRCPATH - $ echo "[color]" >> $HGRCPATH - $ echo "mode = ansi" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > color = + > [color] + > mode = ansi + > EOF $ A=`printf 'foo\nbar'` $ B=`printf 'foo\nbar.baz'` $ touch "$A"
--- a/tests/test-export.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-export.t Wed Nov 12 15:18:30 2014 -0600 @@ -176,10 +176,12 @@ [255] Check for color output - $ echo "[color]" >> $HGRCPATH - $ echo "mode = ansi" >> $HGRCPATH - $ echo "[extensions]" >> $HGRCPATH - $ echo "color=" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [color] + > mode = ansi + > [extensions] + > color = + > EOF $ hg export --color always --nodates tip # HG changeset patch
--- a/tests/test-extdiff.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-extdiff.t Wed Nov 12 15:18:30 2014 -0600 @@ -16,11 +16,13 @@ Only in a: b [1] - $ echo "[extdiff]" >> $HGRCPATH - $ echo "cmd.falabala=echo" >> $HGRCPATH - $ echo "opts.falabala=diffing" >> $HGRCPATH - $ echo "cmd.edspace=echo" >> $HGRCPATH - $ echo 'opts.edspace="name <user@example.com>"' >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extdiff] + > cmd.falabala = echo + > opts.falabala = diffing + > cmd.edspace = echo + > opts.edspace = "name <user@example.com>" + > EOF $ hg falabala diffing a.000000000000 a @@ -190,6 +192,26 @@ */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob) [1] +Fallback to merge-tools.tool.executable|regkey + $ mkdir dir + $ cat > 'dir/tool.sh' << EOF + > #!/bin/sh + > echo "** custom diff **" + > EOF + $ chmod +x dir/tool.sh + $ tool=`pwd`/dir/tool.sh + $ hg --debug tl --config extdiff.tl= --config merge-tools.tl.executable=$tool + making snapshot of 2 files from rev * (glob) + a + b + making snapshot of 2 files from working directory + a + b + running "'$TESTTMP/a/dir/tool.sh' 'a.*' 'a'" in */extdiff.* (glob) + ** custom diff ** + cleaning up temp directory + [1] + $ cd .. #endif
--- a/tests/test-extension.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-extension.t Wed Nov 12 15:18:30 2014 -0600 @@ -424,10 +424,9 @@ #cmd.cdiff = gdiff #opts.cdiff = -Nprc5 - # add new command called vdiff, runs kdiff3 - vdiff = kdiff3 - - # add new command called meld, runs meld (no need to name twice) + # add new command called meld, runs meld (no need to name twice). If + # the meld executable is not available, the meld tool in [merge-tools] + # will be used, if available meld = # add new command called vimdiff, runs gvimdiff with DirDiff plugin @@ -558,11 +557,13 @@ > "yet another debug command" > ui.write("%s\n" % '\n'.join([x for x, y in extensions.extensions()])) > EOF - $ echo "debugissue811 = $debugpath" >> $HGRCPATH - $ echo "mq=" >> $HGRCPATH - $ echo "strip=" >> $HGRCPATH - $ echo "hgext.mq=" >> $HGRCPATH - $ echo "hgext/mq=" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > debugissue811 = $debugpath + > mq = + > strip = + > hgext.mq = + > hgext/mq = + > EOF Show extensions: (note that mq force load strip, also checking it's not loaded twice) @@ -813,9 +814,11 @@ $ hg -q -R pull-src1 pull src reposetup() for $TESTTMP/reposetup-test/src (glob) - $ echo '[extensions]' >> $HGRCPATH - $ echo '# disable extension globally and explicitly' >> $HGRCPATH - $ echo 'reposetuptest = !' >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > # disable extension globally and explicitly + > reposetuptest = ! + > EOF $ hg clone -U src clone-dst2 reposetup() for $TESTTMP/reposetup-test/src (glob) $ hg init push-dst2 @@ -825,9 +828,11 @@ $ hg -q -R pull-src2 pull src reposetup() for $TESTTMP/reposetup-test/src (glob) - $ echo '[extensions]' >> $HGRCPATH - $ echo '# enable extension globally' >> $HGRCPATH - $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > # enable extension globally + > reposetuptest = $TESTTMP/reposetuptest.py + > EOF $ hg clone -U src clone-dst3 reposetup() for $TESTTMP/reposetup-test/src (glob) reposetup() for $TESTTMP/reposetup-test/clone-dst3 (glob) @@ -863,9 +868,11 @@ $ hg --config extensions.reposetuptest=! init pull-src5 $ hg --config extensions.reposetuptest=! -q -R pull-src5 pull src - $ echo '[extensions]' >> $HGRCPATH - $ echo '# disable extension globally and explicitly' >> $HGRCPATH - $ echo 'reposetuptest = !' >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > # disable extension globally and explicitly + > reposetuptest = ! + > EOF $ hg init parent $ hg init parent/sub1 $ echo 1 > parent/sub1/1
--- a/tests/test-help.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-help.t Wed Nov 12 15:18:30 2014 -0600 @@ -272,7 +272,7 @@ schemes extend schemes with shortcuts to repository swarms share share a common history between several working directories shelve save and restore changes to the working directory - strip strip changesets and their descendents from history + strip strip changesets and their descendants from history transplant command to transplant changesets from another branch win32mbcs allow the use of MBCS paths with problematic encodings zeroconf discover and advertise repositories on the local network
--- a/tests/test-largefiles-misc.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-largefiles-misc.t Wed Nov 12 15:18:30 2014 -0600 @@ -589,7 +589,7 @@ 89e6c98d92887913cadf06b2adb97f26cde4849b -Pusing revision #1 causes uploading entity 89e6c98d9288, which is +Pushing revision #1 causes uploading entity 89e6c98d9288, which is shared also by largefiles b1, b2 in revision #2 and b in revision #5. Then, entity 89e6c98d9288 is not treated as "outgoing entity" at "hg @@ -832,4 +832,33 @@ $ cd .. +Test "pull --rebase" when rebase is enabled before largefiles (issue3861) +========================================================================= + $ hg showconfig extensions | grep largefiles + extensions.largefiles=! + + $ mkdir issue3861 + $ cd issue3861 + $ hg init src + $ hg clone -q src dst + $ echo a > src/a + $ hg -R src commit -Aqm "#0" + Invoking status precommit hook + A a + + $ cat >> dst/.hg/hgrc <<EOF + > [extensions] + > largefiles= + > EOF + $ hg -R dst pull --rebase + pulling from $TESTTMP/issue3861/src (glob) + requesting all changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + nothing to rebase - working directory parent is already an ancestor of destination bf5e395ced2c + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ cd ..
--- a/tests/test-largefiles-update.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-largefiles-update.t Wed Nov 12 15:18:30 2014 -0600 @@ -509,8 +509,25 @@ $ cat large1 large1 in #1 - $ hg rebase -q --abort - rebase aborted +Test that rebase updates standins for manually modified largefiles at +the 1st commit of resuming. + + $ echo "manually modified before 'hg rebase --continue'" > large1 + $ hg resolve -m normal1 + (no more unresolved files) + $ hg rebase --continue --config ui.interactive=True <<EOF + > c + > EOF + local changed .hglf/large1 which remote deleted + use (c)hanged version or (d)elete? c + + $ hg diff -c "tip~1" --nodates .hglf/large1 | grep '^[+-][0-9a-z]' + -e5bb990443d6a92aaf7223813720f7566c9dd05b + +8a4f783556e7dea21139ca0466eafce954c75c13 + $ rm -f large1 + $ hg update -q -C tip + $ cat large1 + manually modified before 'hg rebase --continue' Test that transplant updates largefiles, of which standins are safely changed, even if it is aborted by conflict of other.
--- a/tests/test-largefiles-wireproto.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-largefiles-wireproto.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,5 +1,5 @@ -This file contains testcases that tend to be related to the wireprotocol part of -largefile. +This file contains testcases that tend to be related to the wire protocol part +of largefiles. $ USERCACHE="$TESTTMP/cache"; export USERCACHE $ mkdir "${USERCACHE}"
--- a/tests/test-largefiles.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-largefiles.t Wed Nov 12 15:18:30 2014 -0600 @@ -1172,12 +1172,11 @@ adding manifests adding file changes added 1 changesets with 2 changes to 2 files (+1 heads) + 0 largefiles cached Invoking status precommit hook M sub/normal4 M sub2/large6 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob) - 0 largefiles cached - nothing to rebase - working directory parent is also destination $ [ -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ] $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 9:598410d3eb9a modify normal file largefile in repo d
--- a/tests/test-mq-eol.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-mq-eol.t Wed Nov 12 15:18:30 2014 -0600 @@ -2,10 +2,12 @@ Test interactions between mq and patch.eol - $ echo "[extensions]" >> $HGRCPATH - $ echo "mq=" >> $HGRCPATH - $ echo "[diff]" >> $HGRCPATH - $ echo "nodates=1" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > mq = + > [diff] + > nodates = 1 + > EOF $ cat > makepatch.py <<EOF > f = file('eol.diff', 'wb')
--- a/tests/test-mq-git.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-mq-git.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,10 +1,12 @@ # Test the plumbing of mq.git option # Automatic upgrade itself is tested elsewhere. - $ echo "[extensions]" >> $HGRCPATH - $ echo "mq=" >> $HGRCPATH - $ echo "[diff]" >> $HGRCPATH - $ echo "nodates=1" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > mq = + > [diff] + > nodates = 1 + > EOF $ hg init repo-auto $ cd repo-auto
--- a/tests/test-mq-guards.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-mq-guards.t Wed Nov 12 15:18:30 2014 -0600 @@ -568,7 +568,7 @@ 3 G b.patch test that "qselect --reapply" checks applied patches correctly when no -applied patche becomes guarded but some of unapplied ones become +applied patches becomes guarded but some of unapplied ones become unguarded. $ hg qpop -q -a
--- a/tests/test-mq-header-date.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-mq-header-date.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,8 +1,10 @@ - $ echo "[extensions]" >> $HGRCPATH - $ echo "mq=" >> $HGRCPATH - $ echo "[diff]" >> $HGRCPATH - $ echo "nodates=true" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > mq = + > [diff] + > nodates = true + > EOF $ catpatch() { > cat .hg/patches/$1.patch | sed -e "s/^diff \-r [0-9a-f]* /diff -r ... /" \ > -e "s/^\(# Parent \).*/\1/"
--- a/tests/test-mq-merge.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-mq-merge.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,9 +1,11 @@ Setup extension: - $ echo "[extensions]" >> $HGRCPATH - $ echo "mq =" >> $HGRCPATH - $ echo "[mq]" >> $HGRCPATH - $ echo "git = keep" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > mq = + > [mq] + > git = keep + > EOF Test merge with mq changeset as the second parent:
--- a/tests/test-mq-qdiff.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-mq-qdiff.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,7 +1,9 @@ - $ echo "[extensions]" >> $HGRCPATH - $ echo "mq=" >> $HGRCPATH - $ echo "[mq]" >> $HGRCPATH - $ echo "git=keep" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > mq = + > [mq] + > git = keep + > EOF $ hg init a $ cd a
--- a/tests/test-mq-qfold.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-mq-qfold.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,9 +1,11 @@ - $ echo "[extensions]" >> $HGRCPATH - $ echo "mq=" >> $HGRCPATH - $ echo "[mq]" >> $HGRCPATH - $ echo "git=keep" >> $HGRCPATH - $ echo "[diff]" >> $HGRCPATH - $ echo "nodates=1" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > mq = + > [mq] + > git = keep + > [diff] + > nodates = 1 + > EOF init:
--- a/tests/test-mq-qimport.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-mq-qimport.t Wed Nov 12 15:18:30 2014 -0600 @@ -15,10 +15,12 @@ > f.close() > > EOF - $ echo "[extensions]" >> $HGRCPATH - $ echo "mq=" >> $HGRCPATH - $ echo "[diff]" >> $HGRCPATH - $ echo "git=1" >> $HGRCPATH + > cat <<EOF >> $HGRCPATH + > [extensions] + > mq = + > [diff] + > git = 1 + > EOF $ hg init repo $ cd repo
--- a/tests/test-mq-qrefresh.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-mq-qrefresh.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,7 +1,9 @@ - $ echo "[extensions]" >> $HGRCPATH - $ echo "mq=" >> $HGRCPATH - $ echo "[diff]" >> $HGRCPATH - $ echo "nodates=1" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > mq = + > [diff] + > nodates = 1 + > EOF $ hg init a $ cd a
--- a/tests/test-mq-subrepo-svn.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-mq-subrepo-svn.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,9 +1,11 @@ #require svn13 - $ echo "[extensions]" >> $HGRCPATH - $ echo "mq=" >> $HGRCPATH - $ echo "[diff]" >> $HGRCPATH - $ echo "nodates=1" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > mq = + > [diff] + > nodates = 1 + > EOF fn to create new repository, and cd into it $ mkrepo() {
--- a/tests/test-mq-subrepo.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-mq-subrepo.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,10 +1,12 @@ - $ echo "[ui]" >> $HGRCPATH - $ echo "commitsubrepos = Yes" >> $HGRCPATH - $ echo "[extensions]" >> $HGRCPATH - $ echo "mq=" >> $HGRCPATH - $ echo "record=" >> $HGRCPATH - $ echo "[diff]" >> $HGRCPATH - $ echo "nodates=1" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [ui] + > commitsubrepos = Yes + > [extensions] + > mq = + > record = + > [diff] + > nodates = 1 + > EOF $ stdin=`pwd`/stdin.tmp
--- a/tests/test-mq.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-mq.t Wed Nov 12 15:18:30 2014 -0600 @@ -5,11 +5,12 @@ > fi > } - $ echo "[extensions]" >> $HGRCPATH - $ echo "mq=" >> $HGRCPATH - - $ echo "[mq]" >> $HGRCPATH - $ echo "plain=true" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > mq = + > [mq] + > plain = true + > EOF help @@ -1582,7 +1583,7 @@ $ cd .. -Test interraction with revset (issue4426) +Test interaction with revset (issue4426) $ hg init issue4426 $ cd issue4426
--- a/tests/test-phases-exchange.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-phases-exchange.t Wed Nov 12 15:18:30 2014 -0600 @@ -755,7 +755,7 @@ Bare push with next changeset and common changeset needing sync (issue3575) -(reset some stat on remot repo to not confused other test) +(reset some stat on remote repo to avoid confusing other tests) $ hg -R ../alpha --config extensions.strip= strip --no-backup 967b449fbc94 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-progress.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-progress.t Wed Nov 12 15:18:30 2014 -0600 @@ -296,7 +296,7 @@ \xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88 [=====> ]\r (no-eol) (esc) \r (no-eol) (esc) -test triming progress items, when they contain multi-byte characters, +test trimming progress items, when they contain multi-byte characters, of which length of byte sequence and columns in display are different from each other.
--- a/tests/test-record.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-record.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,9 +1,11 @@ Set up a repo - $ echo "[ui]" >> $HGRCPATH - $ echo "interactive=true" >> $HGRCPATH - $ echo "[extensions]" >> $HGRCPATH - $ echo "record=" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [ui] + > interactive = true + > [extensions] + > record = + > EOF $ hg init a $ cd a
--- a/tests/test-revert.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-revert.t Wed Nov 12 15:18:30 2014 -0600 @@ -398,157 +398,63 @@ Systematic behavior validation of most possible cases ===================================================== -This section tests most of the possible combinations of working directory -changes and inter-revision changes. The number of possible cases is significant -but they all have a slighly different handling. So this section commits to -generating and testing all of them to allow safe refactoring of the revert code. +This section tests most of the possible combinations of revision states and +working directory states. The number of possible cases is significant but they +but they all have a slightly different handling. So this section commits to +and testing all of them to allow safe refactoring of the revert code. A python script is used to generate a file history for each combination of -changes between, on one side the working directory and its parent and on -the other side, changes between a revert target (--rev) and working directory -parent. The three states generated are: +states, on one side the content (or lack thereof) in two revisions, and +on the other side, the content and "tracked-ness" of the working directory. The +three states generated are: - a "base" revision - a "parent" revision - the working directory (based on "parent") -The file generated have names of the form: +The files generated have names of the form: - <changeset-state>_<working-copy-state> - -Here, "changeset-state" conveys the state in "base" and "parent" (or the change -that happen between them), "working-copy-state" is self explanatory. + <rev1-content>_<rev2-content>_<working-copy-content>-<tracked-ness> All known states are not tested yet. See inline documentation for details. Special cases from merge and rename are not tested by this section. -There are also multiple cases where the current revert implementation is known to -slightly misbehave. - Write the python script to disk ------------------------------- - $ cat << EOF > gen-revert-cases.py - > # generate proper file state to test revert behavior - > import sys - > import os - > - > # content of the file in "base" and "parent" - > # None means no file at all - > ctxcontent = { - > # clean: no change from base to parent - > 'clean': ['base', 'base'], - > # modified: file content change from base to parent - > 'modified': ['base', 'parent'], - > # added: file is missing from base and added in parent - > 'added': [None, 'parent'], - > # removed: file exist in base but is removed from parent - > 'removed': ['base', None], - > # file exist neither in base not in parent - > 'missing': [None, None], - > } - > - > # content of file in working copy - > wccontent = { - > # clean: wc content is the same as parent - > 'clean': lambda cc: cc[1], - > # revert: wc content is the same as base - > 'revert': lambda cc: cc[0], - > # wc: file exist with a content different from base and parent - > 'wc': lambda cc: 'wc', - > # removed: file is missing and marked as untracked - > 'removed': lambda cc: None, - > # deleted: file is recorded as tracked but missing - > # rely on file deletion outside of this script - > 'deleted': lambda cc:'TOBEDELETED', - > } - > # untracked-X is a version of X where the file is not tracked (? unknown) - > wccontent['untracked-clean'] = wccontent['clean'] - > wccontent['untracked-revert'] = wccontent['revert'] - > wccontent['untracked-wc'] = wccontent['wc'] - > - > # build the combination of possible states - > combination = [] - > for ctxkey in ctxcontent: - > for wckey in wccontent: - > filename = "%s_%s" % (ctxkey, wckey) - > combination.append((filename, ctxkey, wckey)) - > - > # make sure we have stable output - > combination.sort() - > - > # retrieve the state we must generate - > target = sys.argv[1] - > - > # compute file content - > content = [] - > for filename, ctxkey, wckey in combination: - > cc = ctxcontent[ctxkey] - > if target == 'filelist': - > print filename - > elif target == 'base': - > content.append((filename, cc[0])) - > elif target == 'parent': - > content.append((filename, cc[1])) - > elif target == 'wc': - > content.append((filename, wccontent[wckey](cc))) - > else: - > print >> sys.stderr, "unknown target:", target - > sys.exit(1) - > - > # write actual content - > for filename, data in content: - > if data is not None: - > f = open(filename, 'w') - > f.write(data + '\n') - > f.close() - > elif os.path.exists(filename): - > os.remove(filename) - > EOF - check list of planned files - $ python gen-revert-cases.py filelist - added_clean - added_deleted - added_removed - added_revert - added_untracked-clean - added_untracked-revert - added_untracked-wc - added_wc - clean_clean - clean_deleted - clean_removed - clean_revert - clean_untracked-clean - clean_untracked-revert - clean_untracked-wc - clean_wc - missing_clean - missing_deleted - missing_removed - missing_revert - missing_untracked-clean - missing_untracked-revert - missing_untracked-wc - missing_wc - modified_clean - modified_deleted - modified_removed - modified_revert - modified_untracked-clean - modified_untracked-revert - modified_untracked-wc - modified_wc - removed_clean - removed_deleted - removed_removed - removed_revert - removed_untracked-clean - removed_untracked-revert - removed_untracked-wc - removed_wc + $ python $TESTDIR/generate-working-copy-states.py filelist + content1_content1_content1-tracked + content1_content1_content1-untracked + content1_content1_content3-tracked + content1_content1_content3-untracked + content1_content1_missing-tracked + content1_content1_missing-untracked + content1_content2_content1-tracked + content1_content2_content1-untracked + content1_content2_content2-tracked + content1_content2_content2-untracked + content1_content2_content3-tracked + content1_content2_content3-untracked + content1_content2_missing-tracked + content1_content2_missing-untracked + content1_missing_content1-tracked + content1_missing_content1-untracked + content1_missing_content3-tracked + content1_missing_content3-untracked + content1_missing_missing-tracked + content1_missing_missing-untracked + missing_content2_content2-tracked + missing_content2_content2-untracked + missing_content2_content3-tracked + missing_content2_content3-untracked + missing_content2_missing-tracked + missing_content2_missing-untracked + missing_missing_content3-tracked + missing_missing_content3-untracked + missing_missing_missing-tracked + missing_missing_missing-untracked Script to make a simple text version of the content --------------------------------------------------- @@ -573,268 +479,233 @@ Generate base changeset - $ python ../gen-revert-cases.py base + $ python $TESTDIR/generate-working-copy-states.py base $ hg addremove --similarity 0 - adding clean_clean - adding clean_deleted - adding clean_removed - adding clean_revert - adding clean_untracked-clean - adding clean_untracked-revert - adding clean_untracked-wc - adding clean_wc - adding modified_clean - adding modified_deleted - adding modified_removed - adding modified_revert - adding modified_untracked-clean - adding modified_untracked-revert - adding modified_untracked-wc - adding modified_wc - adding removed_clean - adding removed_deleted - adding removed_removed - adding removed_revert - adding removed_untracked-clean - adding removed_untracked-revert - adding removed_untracked-wc - adding removed_wc + adding content1_content1_content1-tracked + adding content1_content1_content1-untracked + adding content1_content1_content3-tracked + adding content1_content1_content3-untracked + adding content1_content1_missing-tracked + adding content1_content1_missing-untracked + adding content1_content2_content1-tracked + adding content1_content2_content1-untracked + adding content1_content2_content2-tracked + adding content1_content2_content2-untracked + adding content1_content2_content3-tracked + adding content1_content2_content3-untracked + adding content1_content2_missing-tracked + adding content1_content2_missing-untracked + adding content1_missing_content1-tracked + adding content1_missing_content1-untracked + adding content1_missing_content3-tracked + adding content1_missing_content3-untracked + adding content1_missing_missing-tracked + adding content1_missing_missing-untracked $ hg status - A clean_clean - A clean_deleted - A clean_removed - A clean_revert - A clean_untracked-clean - A clean_untracked-revert - A clean_untracked-wc - A clean_wc - A modified_clean - A modified_deleted - A modified_removed - A modified_revert - A modified_untracked-clean - A modified_untracked-revert - A modified_untracked-wc - A modified_wc - A removed_clean - A removed_deleted - A removed_removed - A removed_revert - A removed_untracked-clean - A removed_untracked-revert - A removed_untracked-wc - A removed_wc + A content1_content1_content1-tracked + A content1_content1_content1-untracked + A content1_content1_content3-tracked + A content1_content1_content3-untracked + A content1_content1_missing-tracked + A content1_content1_missing-untracked + A content1_content2_content1-tracked + A content1_content2_content1-untracked + A content1_content2_content2-tracked + A content1_content2_content2-untracked + A content1_content2_content3-tracked + A content1_content2_content3-untracked + A content1_content2_missing-tracked + A content1_content2_missing-untracked + A content1_missing_content1-tracked + A content1_missing_content1-untracked + A content1_missing_content3-tracked + A content1_missing_content3-untracked + A content1_missing_missing-tracked + A content1_missing_missing-untracked $ hg commit -m 'base' (create a simple text version of the content) $ python ../dircontent.py > ../content-base.txt $ cat ../content-base.txt - base clean_clean - base clean_deleted - base clean_removed - base clean_revert - base clean_untracked-clean - base clean_untracked-revert - base clean_untracked-wc - base clean_wc - base modified_clean - base modified_deleted - base modified_removed - base modified_revert - base modified_untracked-clean - base modified_untracked-revert - base modified_untracked-wc - base modified_wc - base removed_clean - base removed_deleted - base removed_removed - base removed_revert - base removed_untracked-clean - base removed_untracked-revert - base removed_untracked-wc - base removed_wc + content1 content1_content1_content1-tracked + content1 content1_content1_content1-untracked + content1 content1_content1_content3-tracked + content1 content1_content1_content3-untracked + content1 content1_content1_missing-tracked + content1 content1_content1_missing-untracked + content1 content1_content2_content1-tracked + content1 content1_content2_content1-untracked + content1 content1_content2_content2-tracked + content1 content1_content2_content2-untracked + content1 content1_content2_content3-tracked + content1 content1_content2_content3-untracked + content1 content1_content2_missing-tracked + content1 content1_content2_missing-untracked + content1 content1_missing_content1-tracked + content1 content1_missing_content1-untracked + content1 content1_missing_content3-tracked + content1 content1_missing_content3-untracked + content1 content1_missing_missing-tracked + content1 content1_missing_missing-untracked Create parent changeset - $ python ../gen-revert-cases.py parent + $ python $TESTDIR/generate-working-copy-states.py parent $ hg addremove --similarity 0 - adding added_clean - adding added_deleted - adding added_removed - adding added_revert - adding added_untracked-clean - adding added_untracked-revert - adding added_untracked-wc - adding added_wc - removing removed_clean - removing removed_deleted - removing removed_removed - removing removed_revert - removing removed_untracked-clean - removing removed_untracked-revert - removing removed_untracked-wc - removing removed_wc + removing content1_missing_content1-tracked + removing content1_missing_content1-untracked + removing content1_missing_content3-tracked + removing content1_missing_content3-untracked + removing content1_missing_missing-tracked + removing content1_missing_missing-untracked + adding missing_content2_content2-tracked + adding missing_content2_content2-untracked + adding missing_content2_content3-tracked + adding missing_content2_content3-untracked + adding missing_content2_missing-tracked + adding missing_content2_missing-untracked $ hg status - M modified_clean - M modified_deleted - M modified_removed - M modified_revert - M modified_untracked-clean - M modified_untracked-revert - M modified_untracked-wc - M modified_wc - A added_clean - A added_deleted - A added_removed - A added_revert - A added_untracked-clean - A added_untracked-revert - A added_untracked-wc - A added_wc - R removed_clean - R removed_deleted - R removed_removed - R removed_revert - R removed_untracked-clean - R removed_untracked-revert - R removed_untracked-wc - R removed_wc + M content1_content2_content1-tracked + M content1_content2_content1-untracked + M content1_content2_content2-tracked + M content1_content2_content2-untracked + M content1_content2_content3-tracked + M content1_content2_content3-untracked + M content1_content2_missing-tracked + M content1_content2_missing-untracked + A missing_content2_content2-tracked + A missing_content2_content2-untracked + A missing_content2_content3-tracked + A missing_content2_content3-untracked + A missing_content2_missing-tracked + A missing_content2_missing-untracked + R content1_missing_content1-tracked + R content1_missing_content1-untracked + R content1_missing_content3-tracked + R content1_missing_content3-untracked + R content1_missing_missing-tracked + R content1_missing_missing-untracked $ hg commit -m 'parent' (create a simple text version of the content) $ python ../dircontent.py > ../content-parent.txt $ cat ../content-parent.txt - parent added_clean - parent added_deleted - parent added_removed - parent added_revert - parent added_untracked-clean - parent added_untracked-revert - parent added_untracked-wc - parent added_wc - base clean_clean - base clean_deleted - base clean_removed - base clean_revert - base clean_untracked-clean - base clean_untracked-revert - base clean_untracked-wc - base clean_wc - parent modified_clean - parent modified_deleted - parent modified_removed - parent modified_revert - parent modified_untracked-clean - parent modified_untracked-revert - parent modified_untracked-wc - parent modified_wc + content1 content1_content1_content1-tracked + content1 content1_content1_content1-untracked + content1 content1_content1_content3-tracked + content1 content1_content1_content3-untracked + content1 content1_content1_missing-tracked + content1 content1_content1_missing-untracked + content2 content1_content2_content1-tracked + content2 content1_content2_content1-untracked + content2 content1_content2_content2-tracked + content2 content1_content2_content2-untracked + content2 content1_content2_content3-tracked + content2 content1_content2_content3-untracked + content2 content1_content2_missing-tracked + content2 content1_content2_missing-untracked + content2 missing_content2_content2-tracked + content2 missing_content2_content2-untracked + content2 missing_content2_content3-tracked + content2 missing_content2_content3-untracked + content2 missing_content2_missing-tracked + content2 missing_content2_missing-untracked Setup working directory - $ python ../gen-revert-cases.py wc | cat + $ python $TESTDIR/generate-working-copy-states.py wc $ hg addremove --similarity 0 - removing added_removed - removing added_revert - removing added_untracked-revert - removing clean_removed - adding missing_deleted - adding missing_untracked-wc - adding missing_wc - removing modified_removed - adding removed_deleted - adding removed_revert - adding removed_untracked-revert - adding removed_untracked-wc - adding removed_wc - $ hg forget *untracked* - $ rm *deleted* + adding content1_missing_content1-tracked + adding content1_missing_content1-untracked + adding content1_missing_content3-tracked + adding content1_missing_content3-untracked + adding content1_missing_missing-tracked + adding content1_missing_missing-untracked + adding missing_missing_content3-tracked + adding missing_missing_content3-untracked + adding missing_missing_missing-tracked + adding missing_missing_missing-untracked + $ hg forget *_*_*-untracked + $ rm *_*_missing-* $ hg status - M added_wc - M clean_wc - M modified_revert - M modified_wc - A missing_wc - A removed_revert - A removed_wc - R added_removed - R added_revert - R added_untracked-clean - R added_untracked-revert - R added_untracked-wc - R clean_removed - R clean_untracked-clean - R clean_untracked-revert - R clean_untracked-wc - R modified_removed - R modified_untracked-clean - R modified_untracked-revert - R modified_untracked-wc - ! added_deleted - ! clean_deleted - ! missing_deleted - ! modified_deleted - ! removed_deleted - ? missing_untracked-wc - ? removed_untracked-revert - ? removed_untracked-wc + M content1_content1_content3-tracked + M content1_content2_content1-tracked + M content1_content2_content3-tracked + M missing_content2_content3-tracked + A content1_missing_content1-tracked + A content1_missing_content3-tracked + A missing_missing_content3-tracked + R content1_content1_content1-untracked + R content1_content1_content3-untracked + R content1_content1_missing-untracked + R content1_content2_content1-untracked + R content1_content2_content2-untracked + R content1_content2_content3-untracked + R content1_content2_missing-untracked + R missing_content2_content2-untracked + R missing_content2_content3-untracked + R missing_content2_missing-untracked + ! content1_content1_missing-tracked + ! content1_content2_missing-tracked + ! content1_missing_missing-tracked + ! missing_content2_missing-tracked + ! missing_missing_missing-tracked + ? content1_missing_content1-untracked + ? content1_missing_content3-untracked + ? missing_missing_content3-untracked $ hg status --rev 'desc("base")' - M clean_wc - M modified_clean - M modified_wc - M removed_wc - A added_clean - A added_wc - A missing_wc - R clean_removed - R clean_untracked-clean - R clean_untracked-revert - R clean_untracked-wc - R modified_removed - R modified_untracked-clean - R modified_untracked-revert - R modified_untracked-wc - R removed_clean - R removed_deleted - R removed_removed - R removed_untracked-clean - R removed_untracked-revert - R removed_untracked-wc - ! added_deleted - ! clean_deleted - ! missing_deleted - ! modified_deleted - ! removed_deleted - ? missing_untracked-wc + M content1_content1_content3-tracked + M content1_content2_content2-tracked + M content1_content2_content3-tracked + M content1_missing_content3-tracked + A missing_content2_content2-tracked + A missing_content2_content3-tracked + A missing_missing_content3-tracked + R content1_content1_content1-untracked + R content1_content1_content3-untracked + R content1_content1_missing-untracked + R content1_content2_content1-untracked + R content1_content2_content2-untracked + R content1_content2_content3-untracked + R content1_content2_missing-untracked + R content1_missing_content1-untracked + R content1_missing_content3-untracked + R content1_missing_missing-tracked + R content1_missing_missing-untracked + ! content1_content1_missing-tracked + ! content1_content2_missing-tracked + ! content1_missing_missing-tracked + ! missing_content2_missing-tracked + ! missing_missing_missing-tracked + ? missing_missing_content3-untracked (create a simple text version of the content) $ python ../dircontent.py > ../content-wc.txt $ cat ../content-wc.txt - parent added_clean - parent added_untracked-clean - wc added_untracked-wc - wc added_wc - base clean_clean - base clean_revert - base clean_untracked-clean - base clean_untracked-revert - wc clean_untracked-wc - wc clean_wc - wc missing_untracked-wc - wc missing_wc - parent modified_clean - base modified_revert - parent modified_untracked-clean - base modified_untracked-revert - wc modified_untracked-wc - wc modified_wc - base removed_revert - base removed_untracked-revert - wc removed_untracked-wc - wc removed_wc + content1 content1_content1_content1-tracked + content1 content1_content1_content1-untracked + content3 content1_content1_content3-tracked + content3 content1_content1_content3-untracked + content1 content1_content2_content1-tracked + content1 content1_content2_content1-untracked + content2 content1_content2_content2-tracked + content2 content1_content2_content2-untracked + content3 content1_content2_content3-tracked + content3 content1_content2_content3-untracked + content1 content1_missing_content1-tracked + content1 content1_missing_content1-untracked + content3 content1_missing_content3-tracked + content3 content1_missing_content3-untracked + content2 missing_content2_content2-tracked + content2 missing_content2_content2-untracked + content3 missing_content2_content3-tracked + content3 missing_content2_content3-untracked + content3 missing_missing_content3-tracked + content3 missing_missing_content3-untracked $ cd .. @@ -849,31 +720,28 @@ check revert output $ hg revert --all - reverting added_deleted - undeleting added_removed - undeleting added_revert - undeleting added_untracked-clean - undeleting added_untracked-revert - undeleting added_untracked-wc - reverting added_wc - reverting clean_deleted - undeleting clean_removed - undeleting clean_untracked-clean - undeleting clean_untracked-revert - undeleting clean_untracked-wc - reverting clean_wc - forgetting missing_deleted - forgetting missing_wc - reverting modified_deleted - undeleting modified_removed - reverting modified_revert - undeleting modified_untracked-clean - undeleting modified_untracked-revert - undeleting modified_untracked-wc - reverting modified_wc - forgetting removed_deleted - forgetting removed_revert - forgetting removed_wc + undeleting content1_content1_content1-untracked + reverting content1_content1_content3-tracked + undeleting content1_content1_content3-untracked + reverting content1_content1_missing-tracked + undeleting content1_content1_missing-untracked + reverting content1_content2_content1-tracked + undeleting content1_content2_content1-untracked + undeleting content1_content2_content2-untracked + reverting content1_content2_content3-tracked + undeleting content1_content2_content3-untracked + reverting content1_content2_missing-tracked + undeleting content1_content2_missing-untracked + forgetting content1_missing_content1-tracked + forgetting content1_missing_content3-tracked + forgetting content1_missing_missing-tracked + undeleting missing_content2_content2-untracked + reverting missing_content2_content3-tracked + undeleting missing_content2_content3-untracked + reverting missing_content2_missing-tracked + undeleting missing_content2_missing-untracked + forgetting missing_missing_content3-tracked + forgetting missing_missing_missing-tracked Compare resulting directory with revert target. @@ -883,20 +751,20 @@ $ python ../dircontent.py > ../content-parent-all.txt $ cd .. $ diff -U 0 -- content-parent.txt content-parent-all.txt | grep _ - +wc added_untracked-wc.orig - +wc added_wc.orig - +wc clean_untracked-wc.orig - +wc clean_wc.orig - +wc missing_untracked-wc - +wc missing_wc - +base modified_revert.orig - +base modified_untracked-revert.orig - +wc modified_untracked-wc.orig - +wc modified_wc.orig - +base removed_revert - +base removed_untracked-revert - +wc removed_untracked-wc - +wc removed_wc + +content3 content1_content1_content3-tracked.orig + +content3 content1_content1_content3-untracked.orig + +content1 content1_content2_content1-tracked.orig + +content1 content1_content2_content1-untracked.orig + +content3 content1_content2_content3-tracked.orig + +content3 content1_content2_content3-untracked.orig + +content1 content1_missing_content1-tracked + +content1 content1_missing_content1-untracked + +content3 content1_missing_content3-tracked + +content3 content1_missing_content3-untracked + +content3 missing_content2_content3-tracked.orig + +content3 missing_content2_content3-untracked.orig + +content3 missing_missing_content3-tracked + +content3 missing_missing_content3-untracked Test revert --all to "base" content ----------------------------------- @@ -909,31 +777,28 @@ check revert output $ hg revert --all --rev 'desc(base)' - removing added_clean - removing added_deleted - removing added_wc - reverting clean_deleted - undeleting clean_removed - undeleting clean_untracked-clean - undeleting clean_untracked-revert - undeleting clean_untracked-wc - reverting clean_wc - forgetting missing_deleted - forgetting missing_wc - reverting modified_clean - reverting modified_deleted - undeleting modified_removed - undeleting modified_untracked-clean - undeleting modified_untracked-revert - undeleting modified_untracked-wc - reverting modified_wc - adding removed_clean - reverting removed_deleted - adding removed_removed - adding removed_untracked-clean - adding removed_untracked-revert - adding removed_untracked-wc - reverting removed_wc + undeleting content1_content1_content1-untracked + reverting content1_content1_content3-tracked + undeleting content1_content1_content3-untracked + reverting content1_content1_missing-tracked + undeleting content1_content1_missing-untracked + undeleting content1_content2_content1-untracked + reverting content1_content2_content2-tracked + undeleting content1_content2_content2-untracked + reverting content1_content2_content3-tracked + undeleting content1_content2_content3-untracked + reverting content1_content2_missing-tracked + undeleting content1_content2_missing-untracked + adding content1_missing_content1-untracked + reverting content1_missing_content3-tracked + adding content1_missing_content3-untracked + reverting content1_missing_missing-tracked + adding content1_missing_missing-untracked + removing missing_content2_content2-tracked + removing missing_content2_content3-tracked + removing missing_content2_missing-tracked + forgetting missing_missing_content3-tracked + forgetting missing_missing_missing-tracked Compare resulting directory with revert target. @@ -943,18 +808,18 @@ $ python ../dircontent.py > ../content-base-all.txt $ cd .. $ diff -U 0 -- content-base.txt content-base-all.txt | grep _ - +parent added_untracked-clean - +wc added_untracked-wc - +wc added_wc.orig - +wc clean_untracked-wc.orig - +wc clean_wc.orig - +wc missing_untracked-wc - +wc missing_wc - +parent modified_untracked-clean.orig - +wc modified_untracked-wc.orig - +wc modified_wc.orig - +wc removed_untracked-wc.orig - +wc removed_wc.orig + +content3 content1_content1_content3-tracked.orig + +content3 content1_content1_content3-untracked.orig + +content2 content1_content2_content2-untracked.orig + +content3 content1_content2_content3-tracked.orig + +content3 content1_content2_content3-untracked.orig + +content3 content1_missing_content3-tracked.orig + +content3 content1_missing_content3-untracked.orig + +content2 missing_content2_content2-untracked + +content3 missing_content2_content3-tracked.orig + +content3 missing_content2_content3-untracked + +content3 missing_missing_content3-tracked + +content3 missing_missing_content3-untracked Test revert to parent content with explicit file name ----------------------------------------------------- @@ -967,108 +832,81 @@ revert all files individually and check the output (output is expected to be different than in the --all case) - $ for file in `python ../gen-revert-cases.py filelist`; do + $ for file in `python $TESTDIR/generate-working-copy-states.py filelist`; do > echo '### revert for:' $file; > hg revert $file; > echo > done - ### revert for: added_clean - no changes needed to added_clean - - ### revert for: added_deleted + ### revert for: content1_content1_content1-tracked + no changes needed to content1_content1_content1-tracked - ### revert for: added_removed + ### revert for: content1_content1_content1-untracked - ### revert for: added_revert - - ### revert for: added_untracked-clean + ### revert for: content1_content1_content3-tracked - ### revert for: added_untracked-revert + ### revert for: content1_content1_content3-untracked - ### revert for: added_untracked-wc + ### revert for: content1_content1_missing-tracked - ### revert for: added_wc + ### revert for: content1_content1_missing-untracked - ### revert for: clean_clean - no changes needed to clean_clean - - ### revert for: clean_deleted + ### revert for: content1_content2_content1-tracked - ### revert for: clean_removed - - ### revert for: clean_revert - no changes needed to clean_revert + ### revert for: content1_content2_content1-untracked - ### revert for: clean_untracked-clean + ### revert for: content1_content2_content2-tracked + no changes needed to content1_content2_content2-tracked - ### revert for: clean_untracked-revert - - ### revert for: clean_untracked-wc + ### revert for: content1_content2_content2-untracked - ### revert for: clean_wc + ### revert for: content1_content2_content3-tracked - ### revert for: missing_clean - missing_clean: no such file in rev * (glob) + ### revert for: content1_content2_content3-untracked - ### revert for: missing_deleted + ### revert for: content1_content2_missing-tracked - ### revert for: missing_removed - missing_removed: no such file in rev * (glob) + ### revert for: content1_content2_missing-untracked - ### revert for: missing_revert - missing_revert: no such file in rev * (glob) + ### revert for: content1_missing_content1-tracked - ### revert for: missing_untracked-clean - missing_untracked-clean: no such file in rev * (glob) + ### revert for: content1_missing_content1-untracked + file not managed: content1_missing_content1-untracked - ### revert for: missing_untracked-revert - missing_untracked-revert: no such file in rev * (glob) + ### revert for: content1_missing_content3-tracked - ### revert for: missing_untracked-wc - file not managed: missing_untracked-wc - - ### revert for: missing_wc + ### revert for: content1_missing_content3-untracked + file not managed: content1_missing_content3-untracked - ### revert for: modified_clean - no changes needed to modified_clean + ### revert for: content1_missing_missing-tracked - ### revert for: modified_deleted + ### revert for: content1_missing_missing-untracked + content1_missing_missing-untracked: no such file in rev * (glob) - ### revert for: modified_removed - - ### revert for: modified_revert + ### revert for: missing_content2_content2-tracked + no changes needed to missing_content2_content2-tracked - ### revert for: modified_untracked-clean - - ### revert for: modified_untracked-revert + ### revert for: missing_content2_content2-untracked - ### revert for: modified_untracked-wc + ### revert for: missing_content2_content3-tracked - ### revert for: modified_wc + ### revert for: missing_content2_content3-untracked - ### revert for: removed_clean - removed_clean: no such file in rev * (glob) + ### revert for: missing_content2_missing-tracked - ### revert for: removed_deleted - - ### revert for: removed_removed - removed_removed: no such file in rev * (glob) + ### revert for: missing_content2_missing-untracked - ### revert for: removed_revert + ### revert for: missing_missing_content3-tracked - ### revert for: removed_untracked-clean - removed_untracked-clean: no such file in rev * (glob) + ### revert for: missing_missing_content3-untracked + file not managed: missing_missing_content3-untracked - ### revert for: removed_untracked-revert - file not managed: removed_untracked-revert + ### revert for: missing_missing_missing-tracked - ### revert for: removed_untracked-wc - file not managed: removed_untracked-wc - - ### revert for: removed_wc + ### revert for: missing_missing_missing-untracked + missing_missing_missing-untracked: no such file in rev * (glob) -check resulting directory againt the --all run +check resulting directory against the --all run (There should be no difference) $ python ../dircontent.py > ../content-parent-explicit.txt @@ -1087,108 +925,81 @@ revert all files individually and check the output (output is expected to be different than in the --all case) - $ for file in `python ../gen-revert-cases.py filelist`; do + $ for file in `python $TESTDIR/generate-working-copy-states.py filelist`; do > echo '### revert for:' $file; > hg revert $file --rev 'desc(base)'; > echo > done - ### revert for: added_clean - - ### revert for: added_deleted + ### revert for: content1_content1_content1-tracked + no changes needed to content1_content1_content1-tracked - ### revert for: added_removed - no changes needed to added_removed + ### revert for: content1_content1_content1-untracked - ### revert for: added_revert - no changes needed to added_revert + ### revert for: content1_content1_content3-tracked - ### revert for: added_untracked-clean - no changes needed to added_untracked-clean + ### revert for: content1_content1_content3-untracked + + ### revert for: content1_content1_missing-tracked - ### revert for: added_untracked-revert - no changes needed to added_untracked-revert + ### revert for: content1_content1_missing-untracked - ### revert for: added_untracked-wc - no changes needed to added_untracked-wc - - ### revert for: added_wc + ### revert for: content1_content2_content1-tracked + no changes needed to content1_content2_content1-tracked - ### revert for: clean_clean - no changes needed to clean_clean + ### revert for: content1_content2_content1-untracked - ### revert for: clean_deleted + ### revert for: content1_content2_content2-tracked - ### revert for: clean_removed + ### revert for: content1_content2_content2-untracked - ### revert for: clean_revert - no changes needed to clean_revert - - ### revert for: clean_untracked-clean + ### revert for: content1_content2_content3-tracked - ### revert for: clean_untracked-revert + ### revert for: content1_content2_content3-untracked - ### revert for: clean_untracked-wc - - ### revert for: clean_wc + ### revert for: content1_content2_missing-tracked - ### revert for: missing_clean - missing_clean: no such file in rev * (glob) + ### revert for: content1_content2_missing-untracked - ### revert for: missing_deleted - - ### revert for: missing_removed - missing_removed: no such file in rev * (glob) + ### revert for: content1_missing_content1-tracked + no changes needed to content1_missing_content1-tracked - ### revert for: missing_revert - missing_revert: no such file in rev * (glob) + ### revert for: content1_missing_content1-untracked + + ### revert for: content1_missing_content3-tracked - ### revert for: missing_untracked-clean - missing_untracked-clean: no such file in rev * (glob) + ### revert for: content1_missing_content3-untracked - ### revert for: missing_untracked-revert - missing_untracked-revert: no such file in rev * (glob) + ### revert for: content1_missing_missing-tracked - ### revert for: missing_untracked-wc - file not managed: missing_untracked-wc + ### revert for: content1_missing_missing-untracked - ### revert for: missing_wc - - ### revert for: modified_clean + ### revert for: missing_content2_content2-tracked - ### revert for: modified_deleted + ### revert for: missing_content2_content2-untracked + no changes needed to missing_content2_content2-untracked - ### revert for: modified_removed - - ### revert for: modified_revert - no changes needed to modified_revert + ### revert for: missing_content2_content3-tracked - ### revert for: modified_untracked-clean - - ### revert for: modified_untracked-revert - - ### revert for: modified_untracked-wc + ### revert for: missing_content2_content3-untracked + no changes needed to missing_content2_content3-untracked - ### revert for: modified_wc + ### revert for: missing_content2_missing-tracked - ### revert for: removed_clean - - ### revert for: removed_deleted + ### revert for: missing_content2_missing-untracked + no changes needed to missing_content2_missing-untracked - ### revert for: removed_removed + ### revert for: missing_missing_content3-tracked - ### revert for: removed_revert - no changes needed to removed_revert + ### revert for: missing_missing_content3-untracked + file not managed: missing_missing_content3-untracked - ### revert for: removed_untracked-clean - - ### revert for: removed_untracked-revert + ### revert for: missing_missing_missing-tracked - ### revert for: removed_untracked-wc - - ### revert for: removed_wc + ### revert for: missing_missing_missing-untracked + missing_missing_missing-untracked: no such file in rev * (glob) -check resulting directory againt the --all run +check resulting directory against the --all run (There should be no difference) $ python ../dircontent.py > ../content-base-explicit.txt
--- a/tests/test-setdiscovery.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-setdiscovery.t Wed Nov 12 15:18:30 2014 -0600 @@ -357,3 +357,52 @@ $ cat errors.log $ cd .. + + +Issue 4438 - test coverage for 3ef893520a85 issues. + + $ mkdir issue4438 + $ cd issue4438 +#if false +generate new bundles: + $ hg init r1 + $ for i in `seq 101`; do hg -R r1 up -qr null && hg -R r1 branch -q b$i && hg -R r1 ci -qmb$i; done + $ hg clone -q r1 r2 + $ for i in `seq 10`; do hg -R r1 up -qr null && hg -R r1 branch -q c$i && hg -R r1 ci -qmc$i; done + $ hg -R r2 branch -q r2change && hg -R r2 ci -qmr2change + $ hg -R r1 bundle -qa $TESTDIR/bundles/issue4438-r1.hg + $ hg -R r2 bundle -qa $TESTDIR/bundles/issue4438-r2.hg +#else +use existing bundles: + $ hg clone -q $TESTDIR/bundles/issue4438-r1.hg r1 + $ hg clone -q $TESTDIR/bundles/issue4438-r2.hg r2 +#endif + +Set iteration order could cause wrong and unstable results - fixed in 73cfaa348650: + + $ hg -R r1 outgoing r2 -T'{rev} ' + comparing with r2 + searching for changes + 101 102 103 104 105 106 107 108 109 110 (no-eol) + +The case where all the 'initialsamplesize' samples already were common would +give 'all remote heads known locally' without checking the remaining heads - +fixed in 86c35b7ae300: + + $ cat >> $TESTTMP/unrandomsample.py << EOF + > import random + > def sample(population, k): + > return sorted(population)[:k] + > random.sample = sample + > EOF + + $ cat >> r1/.hg/hgrc << EOF + > [extensions] + > unrandomsample = $TESTTMP/unrandomsample.py + > EOF + + $ hg -R r1 outgoing r2 -T'{rev} ' + comparing with r2 + searching for changes + 101 102 103 104 105 106 107 108 109 110 (no-eol) + $ cd ..
--- a/tests/test-shelve.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-shelve.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,9 +1,11 @@ - $ echo "[extensions]" >> $HGRCPATH - $ echo "mq=" >> $HGRCPATH - $ echo "shelve=" >> $HGRCPATH - $ echo "[defaults]" >> $HGRCPATH - $ echo "diff = --nodates --git" >> $HGRCPATH - $ echo "qnew = --date '0 0'" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > mq = + > shelve = + > [defaults] + > diff = --nodates --git + > qnew = --date '0 0' + > EOF $ hg init repo $ cd repo
--- a/tests/test-status-color.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-status-color.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,7 +1,9 @@ - $ echo "[extensions]" >> $HGRCPATH - $ echo "color=" >> $HGRCPATH - $ echo "[color]" >> $HGRCPATH - $ echo "mode=ansi" >> $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [extensions] + > color = + > [color] + > mode = ansi + > EOF Terminfo codes compatibility fix $ echo "color.none=0" >> $HGRCPATH
--- a/tests/test-status-rev.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-status-rev.t Wed Nov 12 15:18:30 2014 -0600 @@ -1,156 +1,161 @@ Tests of 'hg status --rev <rev>' to make sure status between <rev> and '.' get combined correctly with the dirstate status. -Sets up a history for a number of files where the filename describes the file's -history. The first two letters of the filename describe the first two commits; -the third letter describes the dirstate for the file. For example, a file called -'amr' was added in the first commit, modified in the second and then removed in -the dirstate. + $ hg init -These codes are used for commits: -x: does not exist -a: added -c: clean -m: modified -r: removed +First commit -These codes are used for dirstate: -d: in dirstate, but deleted from disk -f: removed from dirstate, but file exists (forgotten) -r: removed from dirstate and disk -q: added, but deleted from disk (q for q-rious?) -u: not in dirstate, but file exists (unknown) + $ python $TESTDIR/generate-working-copy-states.py base + $ hg addremove --similarity 0 + adding content1_content1_content1-tracked + adding content1_content1_content1-untracked + adding content1_content1_content3-tracked + adding content1_content1_content3-untracked + adding content1_content1_missing-tracked + adding content1_content1_missing-untracked + adding content1_content2_content1-tracked + adding content1_content2_content1-untracked + adding content1_content2_content2-tracked + adding content1_content2_content2-untracked + adding content1_content2_content3-tracked + adding content1_content2_content3-untracked + adding content1_content2_missing-tracked + adding content1_content2_missing-untracked + adding content1_missing_content1-tracked + adding content1_missing_content1-untracked + adding content1_missing_content3-tracked + adding content1_missing_content3-untracked + adding content1_missing_missing-tracked + adding content1_missing_missing-untracked + $ hg commit -m first - $ hg init - $ touch .hgignore - $ hg add .hgignore - $ hg commit -m initial - -First letter: first commit +Second commit - $ echo a >acc - $ echo a >acd - $ echo a >acf - $ echo a >acm - $ echo a >acr - $ echo a >amc - $ echo a >amd - $ echo a >amf - $ echo a >amm - $ echo a >amr - $ echo a >ara - $ echo a >arq - $ echo a >aru - $ hg commit -Aqm first - -Second letter: second commit + $ python $TESTDIR/generate-working-copy-states.py parent + $ hg addremove --similarity 0 + removing content1_missing_content1-tracked + removing content1_missing_content1-untracked + removing content1_missing_content3-tracked + removing content1_missing_content3-untracked + removing content1_missing_missing-tracked + removing content1_missing_missing-untracked + adding missing_content2_content2-tracked + adding missing_content2_content2-untracked + adding missing_content2_content3-tracked + adding missing_content2_content3-untracked + adding missing_content2_missing-tracked + adding missing_content2_missing-untracked + $ hg commit -m second - $ echo b >xad - $ echo b >xaf - $ echo b >xam - $ echo b >xar - $ echo b >amc - $ echo b >amd - $ echo b >amf - $ echo b >amm - $ echo b >amr - $ hg rm ara - $ hg rm arq - $ hg rm aru - $ hg commit -Aqm second - -Third letter: dirstate +Working copy - $ echo c >acm - $ echo c >amm - $ echo c >xam - $ echo c >ara && hg add ara - $ echo c >arq && hg add arq && rm arq - $ echo c >aru - $ hg rm amr - $ hg rm acr - $ hg rm xar - $ rm acd - $ rm amd - $ rm xad - $ hg forget acf - $ hg forget amf - $ hg forget xaf - $ touch xxu + $ python $TESTDIR/generate-working-copy-states.py wc + $ hg addremove --similarity 0 + adding content1_missing_content1-tracked + adding content1_missing_content1-untracked + adding content1_missing_content3-tracked + adding content1_missing_content3-untracked + adding content1_missing_missing-tracked + adding content1_missing_missing-untracked + adding missing_missing_content3-tracked + adding missing_missing_content3-untracked + adding missing_missing_missing-tracked + adding missing_missing_missing-untracked + $ hg forget *_*_*-untracked + $ rm *_*_missing-* + +Status compared to parent of the working copy, i.e. the dirstate status -Status compared to one revision back + $ hg status -A --rev 1 'glob:missing_content2_content3-tracked' + M missing_content2_content3-tracked + $ hg status -A --rev 1 'glob:missing_content2_content2-tracked' + C missing_content2_content2-tracked + $ hg status -A --rev 1 'glob:missing_missing_content3-tracked' + A missing_missing_content3-tracked + $ hg status -A --rev 1 'glob:missing_missing_content3-untracked' + ? missing_missing_content3-untracked + $ hg status -A --rev 1 'glob:missing_content2_*-untracked' + R missing_content2_content2-untracked + R missing_content2_content3-untracked + R missing_content2_missing-untracked + $ hg status -A --rev 1 'glob:missing_*_missing-tracked' + ! missing_content2_missing-tracked + ! missing_missing_missing-tracked + $ hg status -A --rev 1 'glob:missing_missing_missing-untracked' + missing_missing_missing-untracked: No such file or directory + +Status between first and second commit. Should ignore dirstate status. - $ hg status -A --rev 1 acc - C acc -BROKEN: file appears twice; should be '!' - $ hg status -A --rev 1 acd - ! acd - C acd - $ hg status -A --rev 1 acf - R acf - $ hg status -A --rev 1 acm - M acm - $ hg status -A --rev 1 acr - R acr - $ hg status -A --rev 1 amc - M amc -BROKEN: file appears twice; should be '!' - $ hg status -A --rev 1 amd - ! amd - C amd - $ hg status -A --rev 1 amf - R amf - $ hg status -A --rev 1 amm - M amm - $ hg status -A --rev 1 amr - R amr - $ hg status -A --rev 1 ara - M ara -BROKEN: file appears twice; should be '!' - $ hg status -A --rev 1 arq - R arq - ! arq - $ hg status -A --rev 1 aru - R aru - $ hg status -A --rev 1 xad - ! xad - $ hg status -A --rev 1 xaf - $ hg status -A --rev 1 xam - A xam - $ hg status -A --rev 1 xar - $ hg status -A --rev 1 xxu - ? xxu + $ hg status -A --rev 0:1 'glob:content1_content2_*' + M content1_content2_content1-tracked + M content1_content2_content1-untracked + M content1_content2_content2-tracked + M content1_content2_content2-untracked + M content1_content2_content3-tracked + M content1_content2_content3-untracked + M content1_content2_missing-tracked + M content1_content2_missing-untracked + $ hg status -A --rev 0:1 'glob:content1_content1_*' + C content1_content1_content1-tracked + C content1_content1_content1-untracked + C content1_content1_content3-tracked + C content1_content1_content3-untracked + C content1_content1_missing-tracked + C content1_content1_missing-untracked + $ hg status -A --rev 0:1 'glob:missing_content2_*' + A missing_content2_content2-tracked + A missing_content2_content2-untracked + A missing_content2_content3-tracked + A missing_content2_content3-untracked + A missing_content2_missing-tracked + A missing_content2_missing-untracked + $ hg status -A --rev 0:1 'glob:content1_missing_*' + R content1_missing_content1-tracked + R content1_missing_content1-untracked + R content1_missing_content3-tracked + R content1_missing_content3-untracked + R content1_missing_missing-tracked + R content1_missing_missing-untracked + $ hg status -A --rev 0:1 'glob:missing_missing_*' + +Status compared to one revision back, checking that the dirstate status +is correctly combined with the inter-revision status -Status compared to two revisions back - - $ hg status -A --rev 0 acc - A acc - $ hg status -A --rev 0 acd - ! acd -BROKEN: file exists, so should be listed (as '?') - $ hg status -A --rev 0 acf - $ hg status -A --rev 0 acm - A acm - $ hg status -A --rev 0 acr - $ hg status -A --rev 0 amc - A amc - $ hg status -A --rev 0 amd - ! amd -BROKEN: file exists, so should be listed (as '?') - $ hg status -A --rev 0 amf - $ hg status -A --rev 0 amm - A amm - $ hg status -A --rev 0 amr - $ hg status -A --rev 0 ara - A ara - $ hg status -A --rev 0 arq - ! arq - $ hg status -A --rev 0 aru - ? aru - $ hg status -A --rev 0 xad - ! xad -BROKEN: file exists, so should be listed (as '?') - $ hg status -A --rev 0 xaf - $ hg status -A --rev 0 xam - A xam - $ hg status -A --rev 0 xar + $ hg status -A --rev 0 'glob:content1_*_content[23]-tracked' + M content1_content1_content3-tracked + M content1_content2_content2-tracked + M content1_content2_content3-tracked + M content1_missing_content3-tracked + $ hg status -A --rev 0 'glob:content1_*_content1-tracked' + C content1_content1_content1-tracked + C content1_content2_content1-tracked + C content1_missing_content1-tracked + $ hg status -A --rev 0 'glob:missing_*_content?-tracked' + A missing_content2_content2-tracked + A missing_content2_content3-tracked + A missing_missing_content3-tracked +BROKEN: missing_content2_content[23]-untracked exist, so should be listed + $ hg status -A --rev 0 'glob:missing_*_content?-untracked' + ? missing_missing_content3-untracked + $ hg status -A --rev 0 'glob:content1_*_*-untracked' + R content1_content1_content1-untracked + R content1_content1_content3-untracked + R content1_content1_missing-untracked + R content1_content2_content1-untracked + R content1_content2_content2-untracked + R content1_content2_content3-untracked + R content1_content2_missing-untracked + R content1_missing_content1-untracked + R content1_missing_content3-untracked + R content1_missing_missing-untracked +BROKEN: content1_*_missing-tracked appear twice; should just be '!' + $ hg status -A --rev 0 'glob:*_*_missing-tracked' + R content1_missing_missing-tracked + ! content1_content1_missing-tracked + ! content1_content2_missing-tracked + ! content1_missing_missing-tracked + ! missing_content2_missing-tracked + ! missing_missing_missing-tracked + C content1_content1_missing-tracked + C content1_content2_missing-tracked + $ hg status -A --rev 0 'glob:missing_*_missing-untracked'
--- a/tests/test-tag.t Tue Nov 11 17:25:09 2014 -0600 +++ b/tests/test-tag.t Wed Nov 12 15:18:30 2014 -0600 @@ -479,7 +479,7 @@ 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3 79505d5360b07e3e79d1052e347e73c02b8afa5b t3 -check that the merge tried to minimize the diff witht he first merge parent +check that the merge tried to minimize the diff with the first merge parent $ hg diff --git -r 'p1()' .hgtags diff --git a/.hgtags b/.hgtags