Mercurial > hg-stable
changeset 8686:ad1907abf897
merge with mpm
author | Martin Geisler <mg@lazybytes.net> |
---|---|
date | Mon, 01 Jun 2009 01:24:01 +0200 |
parents | 5306c6b00e69 (current diff) 5bb7780b57c7 (diff) |
children | 78ab2a12b4d9 |
files | |
diffstat | 10 files changed, 179 insertions(+), 120 deletions(-) [+] |
line wrap: on
line diff
--- a/hgext/acl.py Mon Jun 01 00:56:29 2009 +0200 +++ b/hgext/acl.py Mon Jun 01 01:24:01 2009 +0200 @@ -61,7 +61,7 @@ (key, len(pats), user)) if pats: return match.match(repo.root, '', pats) - return match.never(repo.root, '') + return match.exact(repo.root, '', []) def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
--- a/mercurial/cmdutil.py Mon Jun 01 00:56:29 2009 +0200 +++ b/mercurial/cmdutil.py Mon Jun 01 01:24:01 2009 +0200 @@ -256,7 +256,6 @@ opts.get('include'), opts.get('exclude'), default) def badfn(f, msg): repo.ui.warn("%s: %s\n" % (m.rel(f), msg)) - return False m.bad = badfn return m
--- a/mercurial/commands.py Mon Jun 01 00:56:29 2009 +0200 +++ b/mercurial/commands.py Mon Jun 01 01:24:01 2009 +0200 @@ -29,24 +29,22 @@ If no names are given, add all files to the repository. """ - rejected = None + bad = [] exacts = {} names = [] m = cmdutil.match(repo, pats, opts) - m.bad = lambda x,y: True - for abs in repo.walk(m): - if m.exact(abs): - if ui.verbose: - ui.status(_('adding %s\n') % m.rel(abs)) - names.append(abs) - exacts[abs] = 1 - elif abs not in repo.dirstate: - ui.status(_('adding %s\n') % m.rel(abs)) - names.append(abs) + oldbad = m.bad + m.bad = lambda x,y: bad.append(x) or oldbad(x,y) + + for f in repo.walk(m): + exact = m.exact(f) + if exact or f not in repo.dirstate: + names.append(f) + if ui.verbose or not exact: + ui.status(_('adding %s\n') % m.rel(f)) if not opts.get('dry_run'): - rejected = repo.add(names) - rejected = [p for p in rejected if p in exacts] - return rejected and 1 or 0 + bad += [f for f in repo.add(names) if f in m.files()] + return bad and 1 or 0 def addremove(ui, repo, *pats, **opts): """add all new files, delete all missing files @@ -2486,13 +2484,12 @@ def badfn(path, msg): if path in names: - return False + return path_ = path + '/' for f in names: if f.startswith(path_): - return False + return ui.warn("%s: %s\n" % (m.rel(path), msg)) - return False m = cmdutil.match(repo, pats, opts) m.bad = badfn
--- a/mercurial/dirstate.py Mon Jun 01 00:56:29 2009 +0200 +++ b/mercurial/dirstate.py Mon Jun 01 01:24:01 2009 +0200 @@ -425,19 +425,15 @@ def fwarn(f, msg): self._ui.warn('%s: %s\n' % (self.pathto(f), msg)) return False - badfn = fwarn - if hasattr(match, 'bad'): - badfn = match.bad - def badtype(f, mode): + def badtype(mode): kind = _('unknown') if stat.S_ISCHR(mode): kind = _('character device') elif stat.S_ISBLK(mode): kind = _('block device') elif stat.S_ISFIFO(mode): kind = _('fifo') elif stat.S_ISSOCK(mode): kind = _('socket') elif stat.S_ISDIR(mode): kind = _('directory') - self._ui.warn(_('%s: unsupported file type (type is %s)\n') - % (self.pathto(f), kind)) + return _('unsupported file type (type is %s)') % kind ignore = self._ignore dirignore = self._dirignore @@ -450,6 +446,7 @@ dirignore = util.always matchfn = match.matchfn + badfn = match.bad dmap = self._map normpath = util.normpath normalize = self.normalize @@ -463,22 +460,12 @@ work = [] wadd = work.append - if match.anypats(): - #match.match with patterns - dostep3 = True - nomatches = False - elif not match.files(): - #match.always or match.never - dostep3 = matchfn('') - nomatches = not dostep3 - else: - #match.exact or match.match without pattern - dostep3 = False - nomatches = matchfn == match.exact - - if nomatches: - #skip step 2 - dirignore = util.always + exact = skipstep3 = False + if matchfn == match.exact: # match.exact + exact = True + dirignore = util.always # skip step 2 + elif match.files() and not match.anypats(): # match.match, no patterns + skipstep3 = True files = set(match.files()) if not files or '.' in files: @@ -495,7 +482,7 @@ st = lstat(join(nf)) kind = getkind(st.st_mode) if kind == dirkind: - dostep3 = True + skipstep3 = False if nf in dmap: #file deleted on disk but still in dirstate results[nf] = None @@ -504,28 +491,20 @@ elif kind == regkind or kind == lnkkind: results[nf] = st else: - badtype(ff, kind) + badfn(ff, badtype(kind)) if nf in dmap: results[nf] = None except OSError, inst: - keep = False - prefix = nf + "/" - for fn in dmap: - if nf == fn: - if matchfn(nf): - results[nf] = None - keep = True - break - elif fn.startswith(prefix): - dostep3 = True - keep = True - break - if not keep: - if inst.errno != errno.ENOENT: - fwarn(ff, inst.strerror) - elif badfn(ff, inst.strerror): - if nf not in results and not ignore(nf) and matchfn(nf): - results[nf] = None + if nf in dmap: # does it exactly match a file? + results[nf] = None + else: # does it match a directory? + prefix = nf + "/" + for fn in dmap: + if fn.startswith(prefix): + skipstep3 = False + break + else: + badfn(ff, inst.strerror) # step 2: visit subdirectories while work: @@ -562,7 +541,7 @@ results[nf] = None # step 3: report unseen items in the dmap hash - if dostep3 and not nomatches: + if not skipstep3 and not exact: visit = sorted([f for f in dmap if f not in results and matchfn(f)]) for nf, st in zip(visit, util.statfiles([join(i) for i in visit])): if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
--- a/mercurial/localrepo.py Mon Jun 01 00:56:29 2009 +0200 +++ b/mercurial/localrepo.py Mon Jun 01 01:24:01 2009 +0200 @@ -948,7 +948,6 @@ def bad(f, msg): if f not in ctx1: self.ui.warn('%s: %s\n' % (self.dirstate.pathto(f), msg)) - return False match.bad = bad if working: # we need to scan the working dir
--- a/mercurial/match.py Mon Jun 01 00:56:29 2009 +0200 +++ b/mercurial/match.py Mon Jun 01 01:24:01 2009 +0200 @@ -81,7 +81,10 @@ for f in self._files: yield f def bad(self, f, msg): - return True + '''callback for each explicit file that can't be + found/accessed, with an error message + ''' + pass def dir(self, f): pass def missing(self, f): @@ -103,10 +106,6 @@ def __init__(self, root, cwd): match.__init__(self, root, cwd, []) -class never(match): - def __init__(self, root, cwd): - match.__init__(self, root, cwd, [], exact = True) - def patkind(pat): return _patsplit(pat, None)[0]
--- a/tests/run-tests.py Mon Jun 01 00:56:29 2009 +0200 +++ b/tests/run-tests.py Mon Jun 01 01:24:01 2009 +0200 @@ -7,6 +7,38 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2, incorporated herein by reference. +# Modifying this script is tricky because it has many modes: +# - serial (default) vs parallel (-jN, N > 1) +# - no coverage (default) vs coverage (-c, -C, -s) +# - temp install (default) vs specific hg script (--with-hg, --local) +# - tests are a mix of shell scripts and Python scripts +# +# If you change this script, it is recommended that you ensure you +# haven't broken it by running it in various modes with a representative +# sample of test scripts. For example: +# +# 1) serial, no coverage, temp install: +# ./run-tests.py test-s* +# 2) serial, no coverage, local hg: +# ./run-tests.py --local test-s* +# 3) serial, coverage, temp install: +# ./run-tests.py -c test-s* +# 4) serial, coverage, local hg: +# ./run-tests.py -c --local test-s* # unsupported +# 5) parallel, no coverage, temp install: +# ./run-tests.py -j2 test-s* +# 6) parallel, no coverage, local hg: +# ./run-tests.py -j2 --local test-s* +# 7) parallel, coverage, temp install: +# ./run-tests.py -j2 -c test-s* # currently broken +# 8) parallel, coverage, local install +# ./run-tests.py -j2 -c --local test-s* # unsupported (and broken) +# +# (You could use any subset of the tests: test-s* happens to match +# enough that it's worth doing parallel runs, few enough that it +# completes fairly quickly, includes both shell and Python scripts, and +# includes some scripts that run daemon processes.) + import difflib import errno import optparse @@ -34,7 +66,6 @@ SKIPPED_PREFIX = 'skipped: ' FAILED_PREFIX = 'hghave check failed: ' PYTHON = sys.executable -hgpkg = None requiredtools = ["python", "diff", "grep", "unzip", "gunzip", "bunzip2", "sed"] @@ -81,7 +112,11 @@ parser.add_option("-n", "--nodiff", action="store_true", help="skip showing test changes") parser.add_option("--with-hg", type="string", - help="test existing install at given location") + metavar="HG", + help="test using specified hg script rather than a " + "temporary installation") + parser.add_option("--local", action="store_true", + help="shortcut for --with-hg=<testdir>/../hg") parser.add_option("--pure", action="store_true", help="use pure Python code instead of C extensions") @@ -90,13 +125,40 @@ parser.set_defaults(**defaults) (options, args) = parser.parse_args() - global vlog + if options.with_hg: + if not (os.path.isfile(options.with_hg) and + os.access(options.with_hg, os.X_OK)): + parser.error('--with-hg must specify an executable hg script') + if not os.path.basename(options.with_hg) == 'hg': + sys.stderr.write('warning: --with-hg should specify an hg script') + if options.local: + testdir = os.path.dirname(os.path.realpath(sys.argv[0])) + hgbin = os.path.join(os.path.dirname(testdir), 'hg') + if not os.access(hgbin, os.X_OK): + parser.error('--local specified, but %r not found or not executable' + % hgbin) + options.with_hg = hgbin + options.anycoverage = (options.cover or options.cover_stdlib or options.annotate) + if options.anycoverage and options.with_hg: + # I'm not sure if this is a fundamental limitation or just a + # bug. But I don't want to waste people's time and energy doing + # test runs that don't give the results they want. + parser.error("sorry, coverage options do not work when --with-hg " + "or --local specified") + + global vlog if options.verbose: + if options.jobs > 1 or options.child is not None: + pid = "[%d]" % os.getpid() + else: + pid = None def vlog(*msg): + if pid: + print pid, for m in msg: print m, print @@ -178,8 +240,7 @@ def cleanup(options): if not options.keep_tmpdir: - if options.verbose: - print "# Cleaning up HGTMP", HGTMP + vlog("# Cleaning up HGTMP", HGTMP) shutil.rmtree(HGTMP, True) def usecorrectpython(): @@ -200,7 +261,6 @@ shutil.copymode(sys.executable, mypython) def installhg(options): - global PYTHON vlog("# Performing temporary installation of HG") installerrs = os.path.join("tests", "install.err") pure = options.pure and "--pure" or "" @@ -223,19 +283,7 @@ sys.exit(1) os.chdir(TESTDIR) - os.environ["PATH"] = "%s%s%s" % (BINDIR, os.pathsep, os.environ["PATH"]) - - pydir = os.pathsep.join([PYTHONDIR, TESTDIR]) - pythonpath = os.environ.get("PYTHONPATH") - if pythonpath: - pythonpath = pydir + os.pathsep + pythonpath - else: - pythonpath = pydir - os.environ["PYTHONPATH"] = pythonpath - usecorrectpython() - global hgpkg - hgpkg = _hgpath() vlog("# Installing dummy diffstat") f = open(os.path.join(BINDIR, 'diffstat'), 'w') @@ -264,15 +312,6 @@ os.path.join(BINDIR, '_hg.py'))) f.close() os.chmod(os.path.join(BINDIR, 'hg'), 0700) - PYTHON = '"%s" "%s" -x -p' % (sys.executable, - os.path.join(TESTDIR, 'coverage.py')) - -def _hgpath(): - cmd = '%s -c "import mercurial; print mercurial.__path__[0]"' - hgpath = os.popen(cmd % PYTHON) - path = hgpath.read().strip() - hgpath.close() - return path def outputcoverage(options): @@ -491,15 +530,42 @@ return None return ret == 0 -def runchildren(options, expecthg, tests): - if not options.with_hg: +_hgpath = None + +def _gethgpath(): + """Return the path to the mercurial package that is actually found by + the current Python interpreter.""" + global _hgpath + if _hgpath is not None: + return _hgpath + + cmd = '%s -c "import mercurial; print mercurial.__path__[0]"' + pipe = os.popen(cmd % PYTHON) + try: + _hgpath = pipe.read().strip() + finally: + pipe.close() + return _hgpath + +def _checkhglib(verb): + """Ensure that the 'mercurial' package imported by python is + the one we expect it to be. If not, print a warning to stderr.""" + expecthg = os.path.join(PYTHONDIR, 'mercurial') + actualhg = _gethgpath() + if actualhg != expecthg: + sys.stderr.write('warning: %s with unexpected mercurial lib: %s\n' + ' (expected %s)\n' + % (verb, actualhg, expecthg)) + +def runchildren(options, tests): + if INST: installhg(options) - if hgpkg != expecthg: - print '# Testing unexpected mercurial: %s' % hgpkg + _checkhglib("Testing") optcopy = dict(options.__dict__) optcopy['jobs'] = 1 - optcopy['with_hg'] = INST + if optcopy['with_hg'] is None: + optcopy['with_hg'] = os.path.join(BINDIR, "hg") opts = [] for opt, value in optcopy.iteritems(): name = '--' + opt.replace('_', '-') @@ -549,23 +615,20 @@ for s in fails: print "Failed %s: %s" % (s[0], s[1]) - if hgpkg != expecthg: - print '# Tested unexpected mercurial: %s' % hgpkg + _checkhglib("Tested") print "# Ran %d tests, %d skipped, %d failed." % ( tested, skipped, failed) sys.exit(failures != 0) -def runtests(options, expecthg, tests): +def runtests(options, tests): global DAEMON_PIDS, HGRCPATH DAEMON_PIDS = os.environ["DAEMON_PIDS"] = os.path.join(HGTMP, 'daemon.pids') HGRCPATH = os.environ["HGRCPATH"] = os.path.join(HGTMP, '.hgrc') try: - if not options.with_hg: + if INST: installhg(options) - - if hgpkg != expecthg: - print '# Testing unexpected mercurial: %s' % hgpkg + _checkhglib("Testing") if options.timeout > 0: try: @@ -627,8 +690,7 @@ print "Skipped %s: %s" % s for s in fails: print "Failed %s: %s" % s - if hgpkg != expecthg: - print '# Tested unexpected mercurial: %s' % hgpkg + _checkhglib("Tested") print "# Ran %d tests, %d skipped, %d failed." % ( tested, skipped, failed) @@ -672,15 +734,33 @@ os.environ["HGPORT2"] = str(options.port + 2) if options.with_hg: - INST = options.with_hg + INST = None + BINDIR = os.path.dirname(os.path.realpath(options.with_hg)) + + # This looks redundant with how Python initializes sys.path from + # the location of the script being executed. Needed because the + # "hg" specified by --with-hg is not the only Python script + # executed in the test suite that needs to import 'mercurial' + # ... which means it's not really redundant at all. + PYTHONDIR = BINDIR else: INST = os.path.join(HGTMP, "install") - BINDIR = os.environ["BINDIR"] = os.path.join(INST, "bin") - PYTHONDIR = os.path.join(INST, "lib", "python") + BINDIR = os.environ["BINDIR"] = os.path.join(INST, "bin") + PYTHONDIR = os.path.join(INST, "lib", "python") + + os.environ["BINDIR"] = BINDIR + os.environ["PYTHON"] = PYTHON + + if not options.child: + path = [BINDIR] + os.environ["PATH"].split(os.pathsep) + os.environ["PATH"] = os.pathsep.join(path) + + # Deliberately override existing PYTHONPATH: do not want success + # to depend on what happens to be in caller's environment. + os.environ["PYTHONPATH"] = PYTHONDIR + COVERAGE_FILE = os.path.join(TESTDIR, ".coverage") - expecthg = os.path.join(HGTMP, 'install', 'lib', 'python', 'mercurial') - if len(args) == 0: args = os.listdir(".") args.sort() @@ -697,12 +777,14 @@ vlog("# Using TESTDIR", TESTDIR) vlog("# Using HGTMP", HGTMP) + vlog("# Using PATH", os.environ["PATH"]) + vlog("# Using PYTHONPATH", os.environ["PYTHONPATH"]) try: if len(tests) > 1 and options.jobs > 1: - runchildren(options, expecthg, tests) + runchildren(options, tests) else: - runtests(options, expecthg, tests) + runtests(options, tests) finally: cleanup(options)
--- a/tests/test-add.out Mon Jun 01 00:56:29 2009 +0200 +++ b/tests/test-add.out Mon Jun 01 01:24:01 2009 +0200 @@ -30,8 +30,8 @@ ? a.orig M a ? a.orig -c does not exist! -d does not exist! +c: No such file or directory +d: No such file or directory M a A c ? a.orig
--- a/tests/test-convert Mon Jun 01 00:56:29 2009 +0200 +++ b/tests/test-convert Mon Jun 01 01:24:01 2009 +0200 @@ -47,4 +47,6 @@ echo % converting empty dir should fail "nicely" mkdir emptydir -PATH=$BINDIR hg convert emptydir 2>&1 | sed 's,file://.*/emptydir,.../emptydir,g' +# override $PATH to ensure p4 not visible; use $PYTHON in case we're +# running from a devel copy, not a temp installation +PATH=$BINDIR $PYTHON $BINDIR/hg convert emptydir 2>&1 | sed 's,file://.*/emptydir,.../emptydir,g'
--- a/tests/test-merge-tools Mon Jun 01 00:56:29 2009 +0200 +++ b/tests/test-merge-tools Mon Jun 01 01:24:01 2009 +0200 @@ -60,7 +60,9 @@ echo "# default is internal merge:" beforemerge echo "# hg merge -r 2" -PATH=$BINDIR hg merge -r 2 +# override $PATH to ensure hgmerge not visible; use $PYTHON in case we're +# running from a devel copy, not a temp installation +PATH=$BINDIR $PYTHON $BINDIR/hg merge -r 2 aftermerge echo "# simplest hgrc using false for merge:"