Mercurial > hg
changeset 19184:05390cfe678a
merge with stable
author | Kevin Bullock <kbullock@ringworld.org> |
---|---|
date | Mon, 13 May 2013 13:02:01 -0500 |
parents | fae47ecaa952 (diff) 9d88916fb56f (current diff) |
children | f7eff455da03 |
files | mercurial/commands.py |
diffstat | 41 files changed, 655 insertions(+), 285 deletions(-) [+] |
line wrap: on
line diff
--- a/contrib/check-code.py Sun May 12 10:09:34 2013 +0100 +++ b/contrib/check-code.py Mon May 13 13:02:01 2013 -0500 @@ -109,6 +109,16 @@ (r'^ changeset .* references (corrupted|missing) \$TESTTMP/.*[^)]$', winglobmsg), (r'^ pulling from \$TESTTMP/.*[^)]$', winglobmsg, '\$TESTTMP/unix-repo$'), + (r'^ reverting .*/.*[^)]$', winglobmsg, '\$TESTTMP/unix-repo$'), + (r'^ cloning subrepo \S+/.*[^)]$', winglobmsg, '\$TESTTMP/unix-repo$'), + (r'^ pushing to \$TESTTMP/.*[^)]$', winglobmsg, '\$TESTTMP/unix-repo$'), + (r'^ pushing subrepo \S+/\S+ to.*[^)]$', winglobmsg, + '\$TESTTMP/unix-repo$'), + (r'^ moving \S+/.*[^)]$', winglobmsg), + (r'^ no changes made to subrepo since.*/.*[^)]$', + winglobmsg, '\$TESTTMP/unix-repo$'), + (r'^ .*: largefile \S+ not available from file:.*/.*[^)]$', + winglobmsg, '\$TESTTMP/unix-repo$'), ], # warnings [
--- a/hgext/convert/common.py Sun May 12 10:09:34 2013 +0100 +++ b/hgext/convert/common.py Mon May 13 13:02:01 2013 -0500 @@ -5,7 +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 base64, errno, subprocess, os, datetime +import base64, errno, subprocess, os, datetime, re import cPickle as pickle from mercurial import util from mercurial.i18n import _ @@ -63,6 +63,14 @@ self.encoding = 'utf-8' + def checkhexformat(self, revstr): + """ fails if revstr is not a 40 byte hex. mercurial and git both uses + such format for their revision numbering + """ + if not re.match(r'[0-9a-fA-F]{40,40}$', revstr): + raise util.Abort(_('splicemap entry %s is not a valid revision' + ' identifier') % revstr) + def before(self): pass @@ -164,6 +172,13 @@ """ return {} + def checkrevformat(self, revstr): + """revstr is a string that describes a revision in the given + source control system. Return true if revstr has correct + format. + """ + return True + class converter_sink(object): """Conversion sink (target) interface""" @@ -424,34 +439,6 @@ self.fp.close() self.fp = None -def parsesplicemap(path): - """Parse a splicemap, return a child/parents dictionary.""" - if not path: - return {} - m = {} - try: - fp = open(path, 'r') - for i, line in enumerate(fp): - line = line.splitlines()[0].rstrip() - if not line: - # Ignore blank lines - continue - try: - child, parents = line.split(' ', 1) - parents = parents.replace(',', ' ').split() - except ValueError: - raise util.Abort(_('syntax error in %s(%d): child parent1' - '[,parent2] expected') % (path, i + 1)) - pp = [] - for p in parents: - if p not in pp: - pp.append(p) - m[child] = pp - except IOError, e: - if e.errno != errno.ENOENT: - raise - return m - def makedatetimestamp(t): """Like util.makedate() but for time t instead of current time""" delta = (datetime.datetime.utcfromtimestamp(t) -
--- a/hgext/convert/convcmd.py Sun May 12 10:09:34 2013 +0100 +++ b/hgext/convert/convcmd.py Mon May 13 13:02:01 2013 -0500 @@ -15,9 +15,9 @@ from gnuarch import gnuarch_source from bzr import bzr_source from p4 import p4_source -import filemap, common +import filemap -import os, shutil +import os, shutil, shlex from mercurial import hg, util, encoding from mercurial.i18n import _ @@ -118,9 +118,53 @@ self.readauthormap(opts.get('authormap')) self.authorfile = self.dest.authorfile() - self.splicemap = common.parsesplicemap(opts.get('splicemap')) + self.splicemap = self.parsesplicemap(opts.get('splicemap')) self.branchmap = mapfile(ui, opts.get('branchmap')) + def parsesplicemap(self, path): + """ check and validate the splicemap format and + return a child/parents dictionary. + Format checking has two parts. + 1. generic format which is same across all source types + 2. specific format checking which may be different for + different source type. This logic is implemented in + checkrevformat function in source files like + hg.py, subversion.py etc. + """ + + if not path: + return {} + m = {} + try: + fp = open(path, 'r') + for i, line in enumerate(fp): + line = line.splitlines()[0].rstrip() + if not line: + # Ignore blank lines + continue + # split line + lex = shlex.shlex(line, posix=True) + lex.whitespace_split = True + lex.whitespace += ',' + line = list(lex) + # check number of parents + if not (2 <= len(line) <= 3): + raise util.Abort(_('syntax error in %s(%d): child parent1' + '[,parent2] expected') % (path, i + 1)) + for part in line: + self.source.checkrevformat(part) + child, p1, p2 = line[0], line[1:2], line[2:] + if p1 == p2: + m[child] = p1 + else: + m[child] = p1 + p2 + # if file does not exist or error reading, exit + except IOError: + raise util.Abort(_('splicemap file not found or error reading %s:') + % path) + return m + + def walktree(self, heads): '''Return a mapping that identifies the uncommitted parents of every uncommitted changeset.'''
--- a/hgext/convert/git.py Sun May 12 10:09:34 2013 +0100 +++ b/hgext/convert/git.py Mon May 13 13:02:01 2013 -0500 @@ -296,3 +296,8 @@ pass return bookmarks + + def checkrevformat(self, revstr): + """ git revision string is a 40 byte hex """ + self.checkhexformat(revstr) +
--- a/hgext/convert/hg.py Sun May 12 10:09:34 2013 +0100 +++ b/hgext/convert/hg.py Mon May 13 13:02:01 2013 -0500 @@ -397,3 +397,7 @@ def getbookmarks(self): return bookmarks.listbookmarks(self.repo) + + def checkrevformat(self, revstr): + """ Mercurial, revision string is a 40 byte hex """ + self.checkhexformat(revstr)
--- a/hgext/convert/subversion.py Sun May 12 10:09:34 2013 +0100 +++ b/hgext/convert/subversion.py Mon May 13 13:02:01 2013 -0500 @@ -452,6 +452,14 @@ del self.commits[rev] return commit + def checkrevformat(self, revstr): + """ fails if revision format does not match the correct format""" + if not re.match(r'svn:[0-9a-f]{8,8}-[0-9a-f]{4,4}-' + '[0-9a-f]{4,4}-[0-9a-f]{4,4}-[0-9a-f]' + '{12,12}(.*)\@[0-9]+$',revstr): + raise util.Abort(_('splicemap entry %s is not a valid revision' + ' identifier') % revstr) + def gettags(self): tags = {} if self.tags is None:
--- a/hgext/inotify/client.py Sun May 12 10:09:34 2013 +0100 +++ b/hgext/inotify/client.py Mon May 13 13:02:01 2013 -0500 @@ -159,7 +159,8 @@ vdirs = cs.read(nbytes) if vdirs: for vdir in vdirs.split('\0'): - match.dir(vdir) + if match.explicitdir: + match.explicitdir(vdir) return results
--- a/hgext/purge.py Sun May 12 10:09:34 2013 +0100 +++ b/hgext/purge.py Mon May 13 13:02:01 2013 -0500 @@ -97,7 +97,7 @@ directories = [] match = scmutil.match(repo[None], dirs, opts) - match.dir = directories.append + match.explicitdir = match.traversedir = directories.append status = repo.status(match=match, ignored=opts['all'], unknown=True) for f in sorted(status[4] + status[5]):
--- a/mercurial/commands.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/commands.py Mon May 13 13:02:01 2013 -0500 @@ -767,9 +767,8 @@ ('d', 'delete', False, _('delete a given bookmark')), ('m', 'rename', '', _('rename a given bookmark'), _('NAME')), ('i', 'inactive', False, _('mark a bookmark inactive'))], - _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]')) -def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False, - rename=None, inactive=False): + _('hg bookmarks [OPTIONS]... [NAME]...')) +def bookmark(ui, repo, *names, **opts): '''track a line of development with movable markers Bookmarks are pointers to certain commits that move when committing. @@ -796,6 +795,12 @@ active even if -i/--inactive is not given. If no NAME is given, the current active bookmark will be marked inactive. ''' + force = opts.get('force') + rev = opts.get('rev') + delete = opts.get('delete') + rename = opts.get('rename') + inactive = opts.get('inactive') + hexfn = ui.debugflag and hex or short marks = repo._bookmarks cur = repo.changectx('.').node() @@ -846,21 +851,24 @@ raise util.Abort(_("--rev is incompatible with --delete")) if rename and rev: raise util.Abort(_("--rev is incompatible with --rename")) - if mark is None and (delete or rev): + if not names and (delete or rev): raise util.Abort(_("bookmark name required")) if delete: - if mark not in marks: - raise util.Abort(_("bookmark '%s' does not exist") % mark) - if mark == repo._bookmarkcurrent: - bookmarks.setcurrent(repo, None) - del marks[mark] + for mark in names: + if mark not in marks: + raise util.Abort(_("bookmark '%s' does not exist") % mark) + if mark == repo._bookmarkcurrent: + bookmarks.setcurrent(repo, None) + del marks[mark] marks.write() elif rename: - if mark is None: + if not names: raise util.Abort(_("new bookmark name required")) - mark = checkformat(mark) + elif len(names) > 1: + raise util.Abort(_("only one new bookmark name allowed")) + mark = checkformat(names[0]) if rename not in marks: raise util.Abort(_("bookmark '%s' does not exist") % rename) checkconflict(repo, mark, force) @@ -870,19 +878,23 @@ del marks[rename] marks.write() - elif mark is not None: - mark = checkformat(mark) - if inactive and mark == repo._bookmarkcurrent: - bookmarks.setcurrent(repo, None) - return - tgt = cur - if rev: - tgt = scmutil.revsingle(repo, rev).node() - checkconflict(repo, mark, force, tgt) - marks[mark] = tgt - if not inactive and cur == marks[mark] and not rev: - bookmarks.setcurrent(repo, mark) - elif cur != tgt and mark == repo._bookmarkcurrent: + elif names: + newact = None + for mark in names: + mark = checkformat(mark) + if newact is None: + newact = mark + if inactive and mark == repo._bookmarkcurrent: + bookmarks.setcurrent(repo, None) + return + tgt = cur + if rev: + tgt = scmutil.revsingle(repo, rev).node() + checkconflict(repo, mark, force, tgt) + marks[mark] = tgt + if not inactive and cur == marks[newact] and not rev: + bookmarks.setcurrent(repo, newact) + elif cur != tgt and newact == repo._bookmarkcurrent: bookmarks.setcurrent(repo, None) marks.write()
--- a/mercurial/context.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/context.py Mon May 13 13:02:01 2013 -0500 @@ -398,7 +398,7 @@ ("bad args: changeid=%r, fileid=%r, changectx=%r" % (changeid, fileid, changectx)) - if filelog: + if filelog is not None: self._filelog = filelog if changeid is not None: @@ -437,7 +437,9 @@ @propertycache def _changeid(self): - if '_changectx' in self.__dict__: + if '_changeid' in self.__dict__: + return self._changeid + elif '_changectx' in self.__dict__: return self._changectx.rev() else: return self._filelog.linkrev(self._filerev) @@ -1167,7 +1169,7 @@ self._changeid = None self._filerev = self._filenode = None - if filelog: + if filelog is not None: self._filelog = filelog if workingctx: self._changectx = workingctx
--- a/mercurial/copies.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/copies.py Mon May 13 13:02:01 2013 -0500 @@ -222,65 +222,8 @@ fullcopy = {} diverge = {} - def related(f1, f2, limit): - # Walk back to common ancestor to see if the two files originate - # from the same file. Since workingfilectx's rev() is None it messes - # up the integer comparison logic, hence the pre-step check for - # None (f1 and f2 can only be workingfilectx's initially). - - if f1 == f2: - return f1 # a match - - g1, g2 = f1.ancestors(), f2.ancestors() - try: - f1r, f2r = f1.rev(), f2.rev() - - if f1r is None: - f1 = g1.next() - if f2r is None: - f2 = g2.next() - - while True: - f1r, f2r = f1.rev(), f2.rev() - if f1r > f2r: - f1 = g1.next() - elif f2r > f1r: - f2 = g2.next() - elif f1 == f2: - return f1 # a match - elif f1r == f2r or f1r < limit or f2r < limit: - return False # copy no longer relevant - except StopIteration: - return False - - def checkcopies(f, m1, m2): - '''check possible copies of f from m1 to m2''' - of = None - seen = set([f]) - for oc in ctx(f, m1[f]).ancestors(): - ocr = oc.rev() - of = oc.path() - if of in seen: - # check limit late - grab last rename before - if ocr < limit: - break - continue - seen.add(of) - - fullcopy[f] = of # remember for dir rename detection - if of not in m2: - continue # no match, keep looking - if m2[of] == ma.get(of): - break # no merge needed, quit early - c2 = ctx(of, m2[of]) - cr = related(oc, c2, ca.rev()) - if cr and (of == f or of == c2.path()): # non-divergent - copy[f] = of - of = None - break - - if of in ma: - diverge.setdefault(of, []).append(f) + def _checkcopies(f, m1, m2): + checkcopies(ctx, f, m1, m2, ca, limit, diverge, copy, fullcopy) repo.ui.debug(" searching for copies back to rev %d\n" % limit) @@ -295,9 +238,9 @@ % "\n ".join(u2)) for f in u1: - checkcopies(f, m1, m2) + _checkcopies(f, m1, m2) for f in u2: - checkcopies(f, m2, m1) + _checkcopies(f, m2, m1) renamedelete = {} renamedelete2 = set() @@ -386,3 +329,78 @@ break return copy, movewithdir, diverge, renamedelete + +def checkcopies(ctx, f, m1, m2, ca, limit, diverge, copy, fullcopy): + """ + check possible copies of f from m1 to m2 + + ctx = function accepting (filename, node) that returns a filectx. + f = the filename to check + m1 = the source manifest + m2 = the destination manifest + ca = the changectx of the common ancestor + limit = the rev number to not search beyond + diverge = record all diverges in this dict + copy = record all non-divergent copies in this dict + fullcopy = record all copies in this dict + """ + + ma = ca.manifest() + + def _related(f1, f2, limit): + # Walk back to common ancestor to see if the two files originate + # from the same file. Since workingfilectx's rev() is None it messes + # up the integer comparison logic, hence the pre-step check for + # None (f1 and f2 can only be workingfilectx's initially). + + if f1 == f2: + return f1 # a match + + g1, g2 = f1.ancestors(), f2.ancestors() + try: + f1r, f2r = f1.rev(), f2.rev() + + if f1r is None: + f1 = g1.next() + if f2r is None: + f2 = g2.next() + + while True: + f1r, f2r = f1.rev(), f2.rev() + if f1r > f2r: + f1 = g1.next() + elif f2r > f1r: + f2 = g2.next() + elif f1 == f2: + return f1 # a match + elif f1r == f2r or f1r < limit or f2r < limit: + return False # copy no longer relevant + except StopIteration: + return False + + of = None + seen = set([f]) + for oc in ctx(f, m1[f]).ancestors(): + ocr = oc.rev() + of = oc.path() + if of in seen: + # check limit late - grab last rename before + if ocr < limit: + break + continue + seen.add(of) + + fullcopy[f] = of # remember for dir rename detection + if of not in m2: + continue # no match, keep looking + if m2[of] == ma.get(of): + break # no merge needed, quit early + c2 = ctx(of, m2[of]) + cr = _related(oc, c2, ca.rev()) + if cr and (of == f or of == c2.path()): # non-divergent + copy[f] = of + of = None + break + + if of in ma: + diverge.setdefault(of, []).append(f)
--- a/mercurial/dirstate.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/dirstate.py Mon May 13 13:02:01 2013 -0500 @@ -522,18 +522,15 @@ return True return False - def walk(self, match, subrepos, unknown, ignored): - ''' - Walk recursively through the directory tree, finding all files - matched by match. + def _walkexplicit(self, match, subrepos): + '''Get stat data about the files explicitly specified by match. - Return a dict mapping filename to stat-like object (either - mercurial.osutil.stat instance or return value of os.stat()). - ''' - - def fwarn(f, msg): - self._ui.warn('%s: %s\n' % (self.pathto(f), msg)) - return False + Return a triple (results, dirsfound, dirsnotfound). + - results is a mapping from filename to stat result. It also contains + listings mapping subrepos and .hg to None. + - dirsfound is a list of files found to be directories. + - dirsnotfound is a list of files that the dirstate thinks are + directories and that were not found.''' def badtype(mode): kind = _('unknown') @@ -549,41 +546,23 @@ kind = _('directory') return _('unsupported file type (type is %s)') % kind - ignore = self._ignore - dirignore = self._dirignore - if ignored: - ignore = util.never - dirignore = util.never - elif not unknown: - # if unknown and ignored are False, skip step 2 - ignore = util.always - dirignore = util.always - - matchfn = match.matchfn - matchalways = match.always() + matchedir = match.explicitdir badfn = match.bad dmap = self._map normpath = util.normpath - listdir = osutil.listdir lstat = os.lstat getkind = stat.S_IFMT dirkind = stat.S_IFDIR regkind = stat.S_IFREG lnkkind = stat.S_IFLNK join = self._join - work = [] - wadd = work.append + dirsfound = [] + foundadd = dirsfound.append + dirsnotfound = [] + notfoundadd = dirsnotfound.append - 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 - - if not exact and self._checkcase: + if match.matchfn != match.exact and self._checkcase: normalize = self._normalize - skipstep3 = False else: normalize = None @@ -604,7 +583,6 @@ results = dict.fromkeys(subrepos) results['.hg'] = None - # step 1: find all explicit files for ff in files: if normalize: nf = normalize(normpath(ff), False, True) @@ -617,13 +595,12 @@ st = lstat(join(nf)) kind = getkind(st.st_mode) if kind == dirkind: - skipstep3 = False if nf in dmap: #file deleted on disk but still in dirstate results[nf] = None - match.dir(nf) - if not dirignore(nf): - wadd(nf) + if matchedir: + matchedir(nf) + foundadd(nf) elif kind == regkind or kind == lnkkind: results[nf] = st else: @@ -637,12 +614,69 @@ prefix = nf + "/" for fn in dmap: if fn.startswith(prefix): - match.dir(nf) - skipstep3 = False + if matchedir: + matchedir(nf) + notfoundadd(nf) break else: badfn(ff, inst.strerror) + return results, dirsfound, dirsnotfound + + def walk(self, match, subrepos, unknown, ignored): + ''' + Walk recursively through the directory tree, finding all files + matched by match. + + Return a dict mapping filename to stat-like object (either + mercurial.osutil.stat instance or return value of os.stat()). + ''' + + def fwarn(f, msg): + self._ui.warn('%s: %s\n' % (self.pathto(f), msg)) + return False + + ignore = self._ignore + dirignore = self._dirignore + if ignored: + ignore = util.never + dirignore = util.never + elif not unknown: + # if unknown and ignored are False, skip step 2 + ignore = util.always + dirignore = util.always + + matchfn = match.matchfn + matchalways = match.always() + matchtdir = match.traversedir + dmap = self._map + listdir = osutil.listdir + lstat = os.lstat + dirkind = stat.S_IFDIR + regkind = stat.S_IFREG + lnkkind = stat.S_IFLNK + join = self._join + + 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 + + if not exact and self._checkcase: + normalize = self._normalize + skipstep3 = False + else: + normalize = None + + # step 1: find all explicit files + results, work, dirsnotfound = self._walkexplicit(match, subrepos) + + skipstep3 = skipstep3 and not (work or dirsnotfound) + work = [d for d in work if not dirignore(d)] + wadd = work.append + # step 2: visit subdirectories while work: nd = work.pop() @@ -666,7 +700,8 @@ if nf not in results: if kind == dirkind: if not ignore(nf): - match.dir(nf) + if matchtdir: + matchtdir(nf) wadd(nf) if nf in dmap and (matchalways or matchfn(nf)): results[nf] = None
--- a/mercurial/filelog.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/filelog.py Mon May 13 13:02:01 2013 -0500 @@ -31,7 +31,7 @@ class filelog(revlog.revlog): def __init__(self, opener, path): - revlog.revlog.__init__(self, opener, + super(filelog, self).__init__(opener, "/".join(("data", path + ".i"))) def read(self, node): @@ -64,7 +64,7 @@ return len(self.read(node)) # XXX if self.read(node).startswith("\1\n"), this returns (size+4) - return revlog.revlog.size(self, rev) + return super(filelog, self).size(rev) def cmp(self, node, text): """compare text with a given file revision @@ -76,7 +76,7 @@ if text.startswith('\1\n'): t = '\1\n\1\n' + text - samehashes = not revlog.revlog.cmp(self, node, t) + samehashes = not super(filelog, self).cmp(node, t) if samehashes: return False
--- a/mercurial/help/templates.txt Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/help/templates.txt Mon May 13 13:02:01 2013 -0500 @@ -6,8 +6,8 @@ You can customize output for any "log-like" command: log, outgoing, incoming, tip, parents, heads and glog. -Four styles are packaged with Mercurial: default (the style used -when no explicit preference is passed), compact, changelog, +Five styles are packaged with Mercurial: default (the style used +when no explicit preference is passed), compact, changelog, phases and xml. Usage::
--- a/mercurial/httpclient/__init__.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/httpclient/__init__.py Mon May 13 13:02:01 2013 -0500 @@ -37,6 +37,9 @@ * implements ssl inline instead of in a different class """ +# Many functions in this file have too many arguments. +# pylint: disable=R0913 + import cStringIO import errno import httplib @@ -117,6 +120,8 @@ def _close(self): if self._reader is not None: + # We're a friend of the reader class here. + # pylint: disable=W0212 self._reader._close() def readline(self): @@ -137,6 +142,7 @@ return ''.join(blocks) def read(self, length=None): + """Read data from the response body.""" # if length is None, unbounded read while (not self.complete() # never select on a finished read and (not length # unbounded, so we wait for complete() @@ -150,7 +156,8 @@ return r def _select(self): - r, _, _ = select.select([self.sock], [], [], self._timeout) + r, unused_write, unused_err = select.select( + [self.sock], [], [], self._timeout) if not r: # socket was not readable. If the response is not # complete, raise a timeout. @@ -170,13 +177,16 @@ # raise an exception if this is an invalid situation. if not data: if self._reader: + # We're a friend of the reader class here. + # pylint: disable=W0212 self._reader._close() return False else: self._load_response(data) return True - def _load_response(self, data): + # This method gets replaced by _load later, which confuses pylint. + def _load_response(self, data): # pylint: disable=E0202 # Being here implies we're not at the end of the headers yet, # since at the end of this method if headers were completely # loaded we replace this method with the load() method of the @@ -201,7 +211,7 @@ # handle 100-continue response hdrs, body = self.raw_response.split(self._end_headers, 1) - http_ver, status = hdrs.split(' ', 1) + unused_http_ver, status = hdrs.split(' ', 1) if status.startswith('100'): self.raw_response = body self.continued = True @@ -260,9 +270,13 @@ self.will_close = True if body: + # We're a friend of the reader class here. + # pylint: disable=W0212 self._reader._load(body) logger.debug('headers complete') self.headers = headers + # We're a friend of the reader class here. + # pylint: disable=W0212 self._load_response = self._reader._load @@ -335,9 +349,9 @@ self._proxy_port)) if self.ssl: # TODO proxy header support - data = self.buildheaders('CONNECT', '%s:%d' % (self.host, - self.port), - {}, HTTP_VER_1_0) + data = self._buildheaders('CONNECT', '%s:%d' % (self.host, + self.port), + {}, HTTP_VER_1_0) sock.send(data) sock.setblocking(0) r = self.response_class(sock, self.timeout, 'CONNECT') @@ -345,6 +359,9 @@ 'Timed out waiting for CONNECT response from proxy') while not r.complete(): try: + # We're a friend of the response class, so let + # us use the private attribute. + # pylint: disable=W0212 if not r._select(): if not r.complete(): raise timeout_exc @@ -376,7 +393,7 @@ sock.setblocking(0) self.sock = sock - def buildheaders(self, method, path, headers, http_ver): + def _buildheaders(self, method, path, headers, http_ver): if self.ssl and self.port == 443 or self.port == 80: # default port for protocol, so leave it out hdrhost = self.host @@ -437,6 +454,11 @@ return True return False + def _reconnect(self, where): + logger.info('reconnecting during %s', where) + self.close() + self._connect() + def request(self, method, path, body=None, headers={}, expect_continue=False): """Send a request to the server. @@ -474,16 +496,11 @@ raise BadRequestData('body has no __len__() nor read()') self._connect() - outgoing_headers = self.buildheaders( + outgoing_headers = self._buildheaders( method, path, hdrs, self.http_version) response = None first = True - def reconnect(where): - logger.info('reconnecting during %s', where) - self.close() - self._connect() - while ((outgoing_headers or body) and not (response and response.complete())): select_timeout = self.timeout @@ -523,14 +540,17 @@ except socket.sslerror, e: if e.args[0] != socket.SSL_ERROR_WANT_READ: raise - logger.debug( - 'SSL_ERROR_WANT_READ while sending data, retrying...') + logger.debug('SSL_ERROR_WANT_READ while sending ' + 'data, retrying...') continue if not data: logger.info('socket appears closed in read') self.sock = None self._current_response = None if response is not None: + # We're a friend of the response class, so let + # us use the private attribute. + # pylint: disable=W0212 response._close() # This if/elif ladder is a bit subtle, # comments in each branch should help. @@ -550,7 +570,7 @@ logger.info( 'Connection appeared closed in read on first' ' request loop iteration, will retry.') - reconnect('read') + self._reconnect('read') continue else: # We didn't just send the first data hunk, @@ -563,7 +583,11 @@ 'response was missing or incomplete!') logger.debug('read %d bytes in request()', len(data)) if response is None: - response = self.response_class(r[0], self.timeout, method) + response = self.response_class( + r[0], self.timeout, method) + # We're a friend of the response class, so let us + # use the private attribute. + # pylint: disable=W0212 response._load_response(data) # Jump to the next select() call so we load more # data if the server is still sending us content. @@ -576,6 +600,8 @@ if w and out: try: if getattr(out, 'read', False): + # pylint guesses the type of out incorrectly here + # pylint: disable=E1103 data = out.read(OUTGOING_BUFFER_SIZE) if not data: continue @@ -599,14 +625,10 @@ elif (e[0] not in (errno.ECONNRESET, errno.EPIPE) and not first): raise - reconnect('write') + self._reconnect('write') amt = self.sock.send(out) logger.debug('sent %d', amt) first = False - # stash data we think we sent in case the socket breaks - # when we read from it - if was_first: - sent_data = out[:amt] if out is body: body = out[amt:] else: @@ -616,7 +638,6 @@ # the whole request if response is None: response = self.response_class(self.sock, self.timeout, method) - complete = response.complete() data_left = bool(outgoing_headers or body) if data_left: logger.info('stopped sending request early, ' @@ -629,10 +650,14 @@ self._current_response = response def getresponse(self): + """Returns the response to the most recent request.""" if self._current_response is None: raise httplib.ResponseNotReady() r = self._current_response while r.headers is None: + # We're a friend of the response class, so let us use the + # private attribute. + # pylint: disable=W0212 if not r._select() and not r.complete(): raise _readers.HTTPRemoteClosedError() if r.will_close:
--- a/mercurial/httpclient/_readers.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/httpclient/_readers.py Mon May 13 13:02:01 2013 -0500 @@ -33,7 +33,6 @@ """ import httplib -import itertools import logging logger = logging.getLogger(__name__) @@ -59,33 +58,35 @@ self._done_chunks = [] self.available_data = 0 - def addchunk(self, data): + def _addchunk(self, data): self._done_chunks.append(data) self.available_data += len(data) - def pushchunk(self, data): + def _pushchunk(self, data): self._done_chunks.insert(0, data) self.available_data += len(data) - def popchunk(self): + def _popchunk(self): b = self._done_chunks.pop(0) self.available_data -= len(b) return b def done(self): + """Returns true if the response body is entirely read.""" return self._finished def read(self, amt): + """Read amt bytes from the response body.""" if self.available_data < amt and not self._finished: raise ReadNotReady() blocks = [] need = amt while self._done_chunks: - b = self.popchunk() + b = self._popchunk() if len(b) > need: nb = b[:need] - self.pushchunk(b[need:]) + self._pushchunk(b[need:]) b = nb blocks.append(b) need -= len(b) @@ -107,11 +108,11 @@ blocks = [] while self._done_chunks: - b = self.popchunk() + b = self._popchunk() i = b.find(delimstr) + len(delimstr) if i: if i < len(b): - self.pushchunk(b[i:]) + self._pushchunk(b[i:]) blocks.append(b[:i]) break else: @@ -154,8 +155,9 @@ if data: assert not self._finished, ( 'tried to add data (%r) to a closed reader!' % data) - logger.debug('%s read an additional %d data', self.name, len(data)) - self.addchunk(data) + logger.debug('%s read an additional %d data', + self.name, len(data)) # pylint: disable=E1101 + self._addchunk(data) class CloseIsEndReader(AbstractSimpleReader): @@ -172,7 +174,7 @@ name = 'content-length' def __init__(self, amount): - AbstractReader.__init__(self) + AbstractSimpleReader.__init__(self) self._amount = amount if amount == 0: self._finished = True @@ -199,7 +201,8 @@ logger.debug('chunked read an additional %d data', len(data)) position = 0 if self._leftover_data: - logger.debug('chunked reader trying to finish block from leftover data') + logger.debug( + 'chunked reader trying to finish block from leftover data') # TODO: avoid this string concatenation if possible data = self._leftover_data + data position = self._leftover_skip_amt @@ -224,6 +227,6 @@ self._finished = True logger.debug('closing chunked reader due to chunk of length 0') return - self.addchunk(data[block_start:block_start + amt]) + self._addchunk(data[block_start:block_start + amt]) position = block_start + amt + len(self._eol) # no-check-code
--- a/mercurial/httpclient/socketutil.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/httpclient/socketutil.py Mon May 13 13:02:01 2013 -0500 @@ -39,7 +39,8 @@ try: import ssl - ssl.wrap_socket # make demandimporters load the module + # make demandimporters load the module + ssl.wrap_socket # pylint: disable=W0104 have_ssl = True except ImportError: import httplib @@ -52,12 +53,13 @@ create_connection = socket.create_connection except AttributeError: def create_connection(address): + """Backport of socket.create_connection from Python 2.6.""" host, port = address msg = "getaddrinfo returns an empty list" sock = None for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM): - af, socktype, proto, _canonname, sa = res + af, socktype, proto, unused_canonname, sa = res try: sock = socket.socket(af, socktype, proto) logger.info("connect: (%s, %s)", host, port) @@ -80,8 +82,11 @@ CERT_REQUIRED = ssl.CERT_REQUIRED else: class FakeSocket(httplib.FakeSocket): - """Socket wrapper that supports SSL. - """ + """Socket wrapper that supports SSL.""" + + # Silence lint about this goofy backport class + # pylint: disable=W0232,E1101,R0903,R0913,C0111 + # backport the behavior from Python 2.6, which is to busy wait # on the socket instead of anything nice. Sigh. # See http://bugs.python.org/issue3890 for more info. @@ -107,11 +112,16 @@ CERT_OPTIONAL = 1 CERT_REQUIRED = 2 + # Disable unused-argument because we're making a dumb wrapper + # that's like an upstream method. + # + # pylint: disable=W0613,R0913 def wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version=_PROTOCOL_SSLv23, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True): + """Backport of ssl.wrap_socket from Python 2.6.""" if cert_reqs != CERT_NONE and ca_certs: raise CertificateValidationUnsupported( 'SSL certificate validation requires the ssl module' @@ -120,6 +130,7 @@ # borrow httplib's workaround for no ssl.wrap_socket sock = FakeSocket(sock, sslob) return sock + # pylint: enable=W0613,R0913 class CertificateValidationUnsupported(Exception):
--- a/mercurial/localrepo.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/localrepo.py Mon May 13 13:02:01 2013 -0500 @@ -1145,7 +1145,7 @@ if not force: vdirs = [] - match.dir = vdirs.append + match.explicitdir = vdirs.append match.bad = fail wlock = self.wlock()
--- a/mercurial/match.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/match.py Mon May 13 13:02:01 2013 -0500 @@ -119,8 +119,12 @@ found/accessed, with an error message ''' pass - def dir(self, f): - pass + # If this is set, it will be called when an explicitly listed directory is + # visited. + explicitdir = None + # If this is set, it will be called when a directory discovered by recursive + # traversal is visited. + traversedir = None def missing(self, f): pass def exact(self, f):
--- a/mercurial/merge.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/merge.py Mon May 13 13:02:01 2013 -0500 @@ -95,6 +95,7 @@ def _checkunknownfile(repo, wctx, mctx, f): return (not repo.dirstate._ignore(f) and os.path.isfile(repo.wjoin(f)) + and repo.wopener.audit.check(f) and repo.dirstate.normalize(f) not in repo.dirstate and mctx[f].cmp(wctx[f]))
--- a/mercurial/patch.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/patch.py Mon May 13 13:02:01 2013 -0500 @@ -481,7 +481,7 @@ def close(self): wctx = self.repo[None] - addremoved = set(self.changed) + changed = set(self.changed) for src, dst in self.copied: scmutil.dirstatecopy(self.ui, self.repo, wctx, src, dst) if self.removed: @@ -491,14 +491,10 @@ # File was deleted and no longer belongs to the # dirstate, it was probably marked added then # deleted, and should not be considered by - # addremove(). - addremoved.discard(f) - if addremoved: - cwd = self.repo.getcwd() - if cwd: - addremoved = [util.pathto(self.repo.root, cwd, f) - for f in addremoved] - scmutil.addremove(self.repo, addremoved, similarity=self.similarity) + # marktouched(). + changed.discard(f) + if changed: + scmutil.marktouched(self.repo, changed, self.similarity) return sorted(self.changed) class filestore(object): @@ -1397,12 +1393,7 @@ ui.warn(line + '\n') finally: if files: - cfiles = list(files) - cwd = repo.getcwd() - if cwd: - cfiles = [util.pathto(repo.root, cwd, f) - for f in cfiles] - scmutil.addremove(repo, cfiles, similarity=similarity) + scmutil.marktouched(repo, files, similarity) code = fp.close() if code: raise PatchError(_("patch command failed: %s") %
--- a/mercurial/scmutil.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/scmutil.py Mon May 13 13:02:01 2013 -0500 @@ -685,26 +685,11 @@ if similarity is None: similarity = float(opts.get('similarity') or 0) # we'd use status here, except handling of symlinks and ignore is tricky - added, unknown, deleted, removed = [], [], [], [] - audit_path = pathauditor(repo.root) m = match(repo[None], pats, opts) rejected = [] m.bad = lambda x, y: rejected.append(x) - ctx = repo[None] - dirstate = repo.dirstate - walkresults = dirstate.walk(m, sorted(ctx.substate), True, False) - for abs, st in walkresults.iteritems(): - dstate = dirstate[abs] - if dstate == '?' and audit_path.check(abs): - unknown.append(abs) - elif dstate != 'r' and not st: - deleted.append(abs) - # for finding renames - elif dstate == 'r': - removed.append(abs) - elif dstate == 'a': - added.append(abs) + added, unknown, deleted, removed = _interestingfiles(repo, m) unknownset = set(unknown) toprint = unknownset.copy() @@ -718,32 +703,101 @@ status = _('removing %s\n') % ((pats and rel) or abs) repo.ui.status(status) - copies = {} - if similarity > 0: - for old, new, score in similar.findrenames(repo, - added + unknown, removed + deleted, similarity): - if repo.ui.verbose or not m.exact(old) or not m.exact(new): - repo.ui.status(_('recording removal of %s as rename to %s ' - '(%d%% similar)\n') % - (m.rel(old), m.rel(new), score * 100)) - copies[new] = old + renames = _findrenames(repo, m, added + unknown, removed + deleted, + similarity) if not dry_run: - wctx = repo[None] - wlock = repo.wlock() - try: - wctx.forget(deleted) - wctx.add(unknown) - for new, old in copies.iteritems(): - wctx.copy(old, new) - finally: - wlock.release() + _markchanges(repo, unknown, deleted, renames) + + for f in rejected: + if f in m.files(): + return 1 + return 0 + +def marktouched(repo, files, similarity=0.0): + '''Assert that files have somehow been operated upon. files are relative to + the repo root.''' + m = matchfiles(repo, files) + rejected = [] + m.bad = lambda x, y: rejected.append(x) + + added, unknown, deleted, removed = _interestingfiles(repo, m) + + if repo.ui.verbose: + unknownset = set(unknown) + toprint = unknownset.copy() + toprint.update(deleted) + for abs in sorted(toprint): + if abs in unknownset: + status = _('adding %s\n') % abs + else: + status = _('removing %s\n') % abs + repo.ui.status(status) + + renames = _findrenames(repo, m, added + unknown, removed + deleted, + similarity) + + _markchanges(repo, unknown, deleted, renames) for f in rejected: if f in m.files(): return 1 return 0 +def _interestingfiles(repo, matcher): + '''Walk dirstate with matcher, looking for files that addremove would care + about. + + This is different from dirstate.status because it doesn't care about + whether files are modified or clean.''' + added, unknown, deleted, removed = [], [], [], [] + audit_path = pathauditor(repo.root) + + ctx = repo[None] + dirstate = repo.dirstate + walkresults = dirstate.walk(matcher, sorted(ctx.substate), True, False) + for abs, st in walkresults.iteritems(): + dstate = dirstate[abs] + if dstate == '?' and audit_path.check(abs): + unknown.append(abs) + elif dstate != 'r' and not st: + deleted.append(abs) + # for finding renames + elif dstate == 'r': + removed.append(abs) + elif dstate == 'a': + added.append(abs) + + return added, unknown, deleted, removed + +def _findrenames(repo, matcher, added, removed, similarity): + '''Find renames from removed files to added ones.''' + renames = {} + if similarity > 0: + for old, new, score in similar.findrenames(repo, added, removed, + similarity): + if (repo.ui.verbose or not matcher.exact(old) + or not matcher.exact(new)): + repo.ui.status(_('recording removal of %s as rename to %s ' + '(%d%% similar)\n') % + (matcher.rel(old), matcher.rel(new), + score * 100)) + renames[new] = old + return renames + +def _markchanges(repo, unknown, deleted, renames): + '''Marks the files in unknown as added, the files in deleted as removed, + and the files in renames as copied.''' + wctx = repo[None] + wlock = repo.wlock() + try: + wctx.forget(deleted) + wctx.add(unknown) + for new, old in renames.iteritems(): + wctx.copy(old, new) + finally: + wlock.release() + def dirstatecopy(ui, repo, wctx, src, dst, dryrun=False, cwd=None): """Update the dirstate to reflect the intent of copying src to dst. For different reasons it might not end with dst being marked as copied from src.
--- a/mercurial/store.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/store.py Mon May 13 13:02:01 2013 -0500 @@ -322,13 +322,16 @@ def datafiles(self): return self._walk('data', True) + def topfiles(self): + # yield manifest before changelog + return reversed(self._walk('', False)) + def walk(self): '''yields (unencoded, encoded, size)''' # yield data files first for x in self.datafiles(): yield x - # yield manifest before changelog - for x in reversed(self._walk('', False)): + for x in self.topfiles(): yield x def copylist(self):
--- a/mercurial/templater.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/templater.py Mon May 13 13:02:01 2013 -0500 @@ -394,6 +394,16 @@ engines = {'default': engine} +def stylelist(): + path = templatepath()[0] + dirlist = os.listdir(path) + stylelist = [] + for file in dirlist: + split = file.split(".") + if split[0] == "map-cmdline": + stylelist.append(split[1]) + return ", ".join(sorted(stylelist)) + class templater(object): def __init__(self, mapfile, filters={}, defaults={}, cache={}, @@ -415,7 +425,8 @@ if not mapfile: return if not os.path.exists(mapfile): - raise util.Abort(_('style not found: %s') % mapfile) + raise util.Abort(_("style '%s' not found") % mapfile, + hint=_("available styles: %s") % stylelist()) conf = config.config() conf.read(mapfile)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/templates/map-cmdline.phases Mon May 13 13:02:01 2013 -0500 @@ -0,0 +1,25 @@ +changeset = 'changeset: {rev}:{node|short}\n{branches}{bookmarks}{tags}phase: {phase}\n{parents}user: {author}\ndate: {date|date}\nsummary: {desc|firstline}\n\n' +changeset_quiet = '{rev}:{node|short}\n' +changeset_verbose = 'changeset: {rev}:{node|short}\n{branches}{bookmarks}{tags}{parents}user: {author}\ndate: {date|date}\n{files}{file_copies_switch}description:\n{desc|strip}\n\n\n' +changeset_debug = 'changeset: {rev}:{node}\n{branches}{bookmarks}{tags}phase: {phase}\n{parents}{manifest}user: {author}\ndate: {date|date}\n{file_mods}{file_adds}{file_dels}{file_copies_switch}{extras}description:\n{desc|strip}\n\n\n' +start_files = 'files: ' +file = ' {file}' +end_files = '\n' +start_file_mods = 'files: ' +file_mod = ' {file_mod}' +end_file_mods = '\n' +start_file_adds = 'files+: ' +file_add = ' {file_add}' +end_file_adds = '\n' +start_file_dels = 'files-: ' +file_del = ' {file_del}' +end_file_dels = '\n' +start_file_copies = 'copies: ' +file_copy = ' {name} ({source})' +end_file_copies = '\n' +parent = 'parent: {rev}:{node|formatnode}\n' +manifest = 'manifest: {rev}:{node}\n' +branch = 'branch: {branch}\n' +tag = 'tag: {tag}\n' +bookmark = 'bookmark: {bookmark}\n' +extra = 'extra: {key}={value|stringescape}\n'
--- a/mercurial/wireproto.py Sun May 12 10:09:34 2013 +0100 +++ b/mercurial/wireproto.py Mon May 13 13:02:01 2013 -0500 @@ -523,6 +523,10 @@ def _allowstream(ui): return ui.configbool('server', 'uncompressed', True, untrusted=True) +def _walkstreamfiles(repo): + # this is it's own function so extensions can override it + return repo.store.walk() + def stream(repo, proto): '''If the server supports streaming clone, it advertises the "stream" capability with a value representing the version and flags of the repo @@ -544,7 +548,7 @@ lock = repo.lock() try: repo.ui.debug('scanning\n') - for name, ename, size in repo.store.walk(): + for name, ename, size in _walkstreamfiles(repo): if size: entries.append((name, size)) total_bytes += size
--- a/tests/run-tests.py Sun May 12 10:09:34 2013 +0100 +++ b/tests/run-tests.py Mon May 13 13:02:01 2013 -0500 @@ -1120,6 +1120,8 @@ childopts = ['--child=%d' % wfd, '--port=%d' % (options.port + j * 3)] childtmp = os.path.join(HGTMP, 'child%d' % j) childopts += ['--tmpdir', childtmp] + if options.keep_tmpdir: + childopts.append('--keep-tmpdir') cmdline = [PYTHON, sys.argv[0]] + opts + childopts + job vlog(' '.join(cmdline)) proc = subprocess.Popen(cmdline, executable=cmdline[0]) @@ -1288,7 +1290,8 @@ global TESTDIR, HGTMP, INST, BINDIR, PYTHONDIR, COVERAGE_FILE TESTDIR = os.environ["TESTDIR"] = os.getcwd() if options.tmpdir: - options.keep_tmpdir = True + if not options.child: + options.keep_tmpdir = True tmpdir = options.tmpdir if os.path.exists(tmpdir): # Meaning of tmpdir has changed since 1.3: we used to create
--- a/tests/test-bookmarks-current.t Sun May 12 10:09:34 2013 +0100 +++ b/tests/test-bookmarks-current.t Mon May 13 13:02:01 2013 -0500 @@ -43,16 +43,19 @@ $ hg bookmarks * Z -1:000000000000 -new bookmark Y +new bookmarks X and Y, first one made active - $ hg bookmark Y + $ hg bookmark Y X list bookmarks $ hg bookmark + X -1:000000000000 * Y -1:000000000000 Z -1:000000000000 + $ hg bookmark -d X + commit $ echo 'b' > b
--- a/tests/test-bookmarks.t Sun May 12 10:09:34 2013 +0100 +++ b/tests/test-bookmarks.t Mon May 13 13:02:01 2013 -0500 @@ -168,11 +168,14 @@ $ hg bookmark -d REVSET $ hg bookmark -d TIP -rename without new name +rename without new name or multiple names $ hg bookmark -m Y abort: new bookmark name required [255] + $ hg bookmark -m Y Y2 Y3 + abort: only one new bookmark name allowed + [255] delete without name @@ -417,8 +420,9 @@ a@ 2:db815d6d32e6 x y 2:db815d6d32e6 - $ hg bookmark -d @ - $ hg bookmark -d a@ +delete multiple bookmarks at once + + $ hg bookmark -d @ a@ test clone with a bookmark named "default" (issue3677)
--- a/tests/test-command-template.t Sun May 12 10:09:34 2013 +0100 +++ b/tests/test-command-template.t Mon May 13 13:02:01 2013 -0500 @@ -458,7 +458,8 @@ Error if no style: $ hg log --style notexist - abort: style not found: notexist + abort: style 'notexist' not found + (available styles: bisect, changelog, compact, default, phases, xml) [255] Error if style missing key:
--- a/tests/test-commandserver.py Sun May 12 10:09:34 2013 +0100 +++ b/tests/test-commandserver.py Mon May 13 13:02:01 2013 -0500 @@ -25,7 +25,11 @@ else: return channel, server.stdout.read(length) -def runcommand(server, args, output=sys.stdout, error=sys.stderr, input=None): +def sep(text): + return text.replace('\\', '/') + +def runcommand(server, args, output=sys.stdout, error=sys.stderr, input=None, + outfilter=lambda x: x): print ' runcommand', ' '.join(args) sys.stdout.flush() server.stdin.write('runcommand\n') @@ -37,7 +41,7 @@ while True: ch, data = readchannel(server) if ch == 'o': - output.write(data) + output.write(outfilter(data)) output.flush() elif ch == 'e': error.write(data) @@ -249,7 +253,8 @@ # make it public; draft marker moves to 4:7966c8e3734d runcommand(server, ['phase', '-p', '.']) - runcommand(server, ['phase', '.']) # load _phasecache.phaseroots + # load _phasecache.phaseroots + runcommand(server, ['phase', '.'], outfilter=sep) # strip 1::4 outside server os.system('hg -q --config extensions.mq= strip 1')
--- a/tests/test-convert-git.t Sun May 12 10:09:34 2013 +0100 +++ b/tests/test-convert-git.t Mon May 13 13:02:01 2013 -0500 @@ -13,6 +13,10 @@ $ GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME $ GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL $ GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE + $ INVALIDID1=afd12345af + $ INVALIDID2=28173x36ddd1e67bf7098d541130558ef5534a86 + $ VALIDID1=39b3d83f9a69a9ba4ebb111461071a0af0027357 + $ VALIDID2=8dd6476bd09d9c7776355dc454dafe38efaec5da $ count=10 $ commit() > { @@ -298,6 +302,36 @@ $ commit -a -m 'addsubmodule' >/dev/null 2>/dev/null $ cd .. +test invalid splicemap1 + + $ cat > splicemap <<EOF + > $VALIDID1 + > EOF + $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap1-hg + initializing destination git-repo2-splicemap1-hg repository + abort: syntax error in splicemap(1): child parent1[,parent2] expected + [255] + +test invalid splicemap2 + + $ cat > splicemap <<EOF + > $VALIDID1 $VALIDID2, $VALIDID2, $VALIDID2 + > EOF + $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap2-hg + initializing destination git-repo2-splicemap2-hg repository + abort: syntax error in splicemap(1): child parent1[,parent2] expected + [255] + +test invalid splicemap3 + + $ cat > splicemap <<EOF + > $INVALIDID1 $INVALIDID2 + > EOF + $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap3-hg + initializing destination git-repo2-splicemap3-hg repository + abort: splicemap entry afd12345af is not a valid revision identifier + [255] + convert sub modules $ hg convert git-repo6 git-repo6-hg initializing destination git-repo6-hg repository
--- a/tests/test-convert-splicemap.t Sun May 12 10:09:34 2013 +0100 +++ b/tests/test-convert-splicemap.t Mon May 13 13:02:01 2013 -0500 @@ -37,6 +37,8 @@ $ hg ci -Am addaandd adding a adding d + $ INVALIDID1=afd12345af + $ INVALIDID2=28173x36ddd1e67bf7098d541130558ef5534a86 $ CHILDID1=`hg id --debug -i` $ echo d >> d $ hg ci -Am changed @@ -53,7 +55,7 @@ o 0:527cdedf31fb "addaandd" files: a d -test invalid splicemap +test invalid splicemap1 $ cat > splicemap <<EOF > $CHILDID2 @@ -62,6 +64,24 @@ abort: syntax error in splicemap(1): child parent1[,parent2] expected [255] +test invalid splicemap2 + + $ cat > splicemap <<EOF + > $CHILDID2 $PARENTID1, $PARENTID2, $PARENTID2 + > EOF + $ hg convert --splicemap splicemap repo2 repo1 + abort: syntax error in splicemap(1): child parent1[,parent2] expected + [255] + +test invalid splicemap3 + + $ cat > splicemap <<EOF + > $INVALIDID1 $INVALIDID2 + > EOF + $ hg convert --splicemap splicemap repo2 repo1 + abort: splicemap entry afd12345af is not a valid revision identifier + [255] + splice repo2 on repo1 $ cat > splicemap <<EOF
--- a/tests/test-convert-svn-source.t Sun May 12 10:09:34 2013 +0100 +++ b/tests/test-convert-svn-source.t Mon May 13 13:02:01 2013 -0500 @@ -16,6 +16,8 @@ #else $ SVNREPOURL=file://`python -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"` #endif + $ INVALIDREVISIONID=svn:x2147622-4a9f-4db4-a8d3-13562ff547b2/proj%20B/mytrunk@1 + $ VALIDREVISIONID=svn:a2147622-4a9f-4db4-a8d3-13562ff547b2/proj%20B/mytrunk/mytrunk@1 Now test that it works with trunk/tags layout, but no branches yet. @@ -168,6 +170,15 @@ | o 0 second letter files: letter2.txt +test invalid splicemap1 + + $ cat > splicemap <<EOF + > $INVALIDREVISIONID $VALIDREVISIONID + > EOF + $ hg convert --splicemap splicemap "$SVNREPOURL/proj%20B/mytrunk" smap + initializing destination smap repository + abort: splicemap entry svn:x2147622-4a9f-4db4-a8d3-13562ff547b2/proj%20B/mytrunk@1 is not a valid revision identifier + [255] Test stop revision $ hg convert --rev 1 "$SVNREPOURL/proj%20B/mytrunk" stoprev
--- a/tests/test-log.t Sun May 12 10:09:34 2013 +0100 +++ b/tests/test-log.t Mon May 13 13:02:01 2013 -0500 @@ -84,6 +84,25 @@ abort: cannot follow file not in parent revision: "dir" [255] +-f, a wrong style + + $ hg log -f -l1 --style something + abort: style 'something' not found + (available styles: bisect, changelog, compact, default, phases, xml) + [255] + +-f, phases style + + + $ hg log -f -l1 --style phases + changeset: 4:7e4639b4691b + tag: tip + phase: draft + user: test + date: Thu Jan 01 00:00:05 1970 +0000 + summary: e + + -f, but no args $ hg log -f
--- a/tests/test-nested-repo.t Sun May 12 10:09:34 2013 +0100 +++ b/tests/test-nested-repo.t Mon May 13 13:02:01 2013 -0500 @@ -8,6 +8,9 @@ $ hg add b $ hg st + $ echo y > b/y + $ hg st + Should fail: $ hg st b/x
--- a/tests/test-rebase-rename.t Sun May 12 10:09:34 2013 +0100 +++ b/tests/test-rebase-rename.t Mon May 13 13:02:01 2013 -0500 @@ -22,7 +22,7 @@ adding d/b $ hg mv d d-renamed - moving d/b to d-renamed/b + moving d/b to d-renamed/b (glob) $ hg ci -m 'rename B' $ hg up -q -C 1
--- a/tests/test-rename-dir-merge.t Sun May 12 10:09:34 2013 +0100 +++ b/tests/test-rename-dir-merge.t Mon May 13 13:02:01 2013 -0500 @@ -51,7 +51,7 @@ getting b/b updating: b/b 4/5 files (80.00%) updating: a/c 5/5 files (100.00%) - moving a/c to b/c + moving a/c to b/c (glob) 3 files updated, 0 files merged, 2 files removed, 0 files unresolved (branch merge, don't forget to commit)
--- a/tests/test-subrepo.t Sun May 12 10:09:34 2013 +0100 +++ b/tests/test-subrepo.t Mon May 13 13:02:01 2013 -0500 @@ -391,7 +391,7 @@ $ hg -R s update '.^' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg push - pushing to $TESTTMP/t + pushing to $TESTTMP/t (glob) no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob) no changes made to subrepo s since last push to $TESTTMP/t/s no changes made to subrepo t since last push to $TESTTMP/t/t @@ -400,7 +400,7 @@ [1] $ echo foo >> s/a $ hg push - pushing to $TESTTMP/t + pushing to $TESTTMP/t (glob) no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob) no changes made to subrepo s since last push to $TESTTMP/t/s no changes made to subrepo t since last push to $TESTTMP/t/t @@ -415,7 +415,7 @@ $ echo foo >> s/ss/a $ hg -R s/ss commit -m 'test dirty store detection' $ hg push - pushing to $TESTTMP/t + pushing to $TESTTMP/t (glob) pushing subrepo s/ss to $TESTTMP/t/s/ss (glob) searching for changes adding changesets @@ -431,7 +431,7 @@ a subrepo store may be clean versus one repo but not versus another $ hg push - pushing to $TESTTMP/t + pushing to $TESTTMP/t (glob) no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob) no changes made to subrepo s since last push to $TESTTMP/t/s no changes made to subrepo t since last push to $TESTTMP/t/t @@ -798,7 +798,7 @@ Try to push from the other side $ hg -R issue1852a push `pwd`/issue1852c - pushing to $TESTTMP/issue1852c + pushing to $TESTTMP/issue1852c (glob) pushing subrepo sub/repo to $TESTTMP/issue1852c/sub/repo (glob) searching for changes no changes found
--- a/tests/test-symlinks.t Sun May 12 10:09:34 2013 +0100 +++ b/tests/test-symlinks.t Mon May 13 13:02:01 2013 -0500 @@ -160,6 +160,15 @@ adding bar/a adding foo removing foo/a + +commit and update back + + $ hg ci -mb + $ hg up '.^' + 1 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ hg up tip + 2 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ cd .. == root of repository is symlinked ==
--- a/tests/test-tag.t Sun May 12 10:09:34 2013 +0100 +++ b/tests/test-tag.t Mon May 13 13:02:01 2013 -0500 @@ -316,7 +316,7 @@ adding test $ hg init repo-tag-target $ hg -R repo-tag --config hooks.commit="\"hg\" push \"`pwd`/repo-tag-target\"" tag tag - pushing to $TESTTMP/repo-tag-target + pushing to $TESTTMP/repo-tag-target (glob) searching for changes adding changesets adding manifests