Mercurial > hg-stable
changeset 19146:a718a0ba6787
merge with stable
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Sun, 05 May 2013 18:51:34 -0500 |
parents | facd906caeeb (diff) 0a12e5f3a979 (current diff) |
children | 5b1835485442 |
files | |
diffstat | 26 files changed, 258 insertions(+), 56 deletions(-) [+] |
line wrap: on
line diff
--- a/contrib/check-code.py Fri May 03 19:34:59 2013 +0200 +++ b/contrib/check-code.py Sun May 05 18:51:34 2013 -0500 @@ -109,6 +109,14 @@ (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'^ 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 Fri May 03 19:34:59 2013 +0200 +++ b/hgext/convert/common.py Sun May 05 18:51:34 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 Fri May 03 19:34:59 2013 +0200 +++ b/hgext/convert/convcmd.py Sun May 05 18:51:34 2013 -0500 @@ -15,7 +15,7 @@ from gnuarch import gnuarch_source from bzr import bzr_source from p4 import p4_source -import filemap, common +import filemap import os, shutil from mercurial import hg, util, encoding @@ -118,9 +118,57 @@ 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 + try: + child, parents = line.split(' ', 1) + self.source.checkrevformat(child) + parents = parents.replace(',', ' ').split() + # check if number of parents are upto 2 max + if (len(parents) > 2): + raise util.Abort(_('syntax error in %s(%d): child '\ + 'parent1[,parent2] expected') \ + % (path, i + 1)) + for parent in parents: + self.source.checkrevformat(parent) + 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 + # 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 Fri May 03 19:34:59 2013 +0200 +++ b/hgext/convert/git.py Sun May 05 18:51:34 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 Fri May 03 19:34:59 2013 +0200 +++ b/hgext/convert/hg.py Sun May 05 18:51:34 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 Fri May 03 19:34:59 2013 +0200 +++ b/hgext/convert/subversion.py Sun May 05 18:51:34 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 Fri May 03 19:34:59 2013 +0200 +++ b/hgext/inotify/client.py Sun May 05 18:51:34 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 Fri May 03 19:34:59 2013 +0200 +++ b/hgext/purge.py Sun May 05 18:51:34 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/dirstate.py Fri May 03 19:34:59 2013 +0200 +++ b/mercurial/dirstate.py Sun May 05 18:51:34 2013 -0500 @@ -561,6 +561,8 @@ matchfn = match.matchfn matchalways = match.always() + matchedir = match.explicitdir + matchtdir = match.traversedir badfn = match.bad dmap = self._map normpath = util.normpath @@ -621,7 +623,8 @@ if nf in dmap: #file deleted on disk but still in dirstate results[nf] = None - match.dir(nf) + if matchedir: + matchedir(nf) if not dirignore(nf): wadd(nf) elif kind == regkind or kind == lnkkind: @@ -637,7 +640,8 @@ prefix = nf + "/" for fn in dmap: if fn.startswith(prefix): - match.dir(nf) + if matchedir: + matchedir(nf) skipstep3 = False break else: @@ -666,7 +670,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/help/templates.txt Fri May 03 19:34:59 2013 +0200 +++ b/mercurial/help/templates.txt Sun May 05 18:51:34 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/localrepo.py Fri May 03 19:34:59 2013 +0200 +++ b/mercurial/localrepo.py Sun May 05 18:51:34 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 Fri May 03 19:34:59 2013 +0200 +++ b/mercurial/match.py Sun May 05 18:51:34 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/templater.py Fri May 03 19:34:59 2013 +0200 +++ b/mercurial/templater.py Sun May 05 18:51:34 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 Sun May 05 18:51:34 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/tests/run-tests.py Fri May 03 19:34:59 2013 +0200 +++ b/tests/run-tests.py Sun May 05 18:51:34 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-command-template.t Fri May 03 19:34:59 2013 +0200 +++ b/tests/test-command-template.t Sun May 05 18:51:34 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 Fri May 03 19:34:59 2013 +0200 +++ b/tests/test-commandserver.py Sun May 05 18:51:34 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 --config extensions.mq= strip 1')
--- a/tests/test-convert-git.t Fri May 03 19:34:59 2013 +0200 +++ b/tests/test-convert-git.t Sun May 05 18:51:34 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 Fri May 03 19:34:59 2013 +0200 +++ b/tests/test-convert-splicemap.t Sun May 05 18:51:34 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 Fri May 03 19:34:59 2013 +0200 +++ b/tests/test-convert-svn-source.t Sun May 05 18:51:34 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 Fri May 03 19:34:59 2013 +0200 +++ b/tests/test-log.t Sun May 05 18:51:34 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 Fri May 03 19:34:59 2013 +0200 +++ b/tests/test-nested-repo.t Sun May 05 18:51:34 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 Fri May 03 19:34:59 2013 +0200 +++ b/tests/test-rebase-rename.t Sun May 05 18:51:34 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 Fri May 03 19:34:59 2013 +0200 +++ b/tests/test-rename-dir-merge.t Sun May 05 18:51:34 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 Fri May 03 19:34:59 2013 +0200 +++ b/tests/test-subrepo.t Sun May 05 18:51:34 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-tag.t Fri May 03 19:34:59 2013 +0200 +++ b/tests/test-tag.t Sun May 05 18:51:34 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