subrepo: remove subrepo support

Summary:
Subrepo is another unloved features that we don't want to support.

Aggressively remove it everywhere, instead of just turning off configs.

I didn't spend much time to split this commit so it's smaller and more friendly
to review. But it seems tests are passing.

Reviewed By: sfilipco

Differential Revision: D14220099

fbshipit-source-id: adc512a047d99cd4bafd0362e3e9b24e71defe13
This commit is contained in:
Jun Wu 2019-03-11 10:37:29 -07:00 committed by Facebook Github Bot
parent dbe1d30cf0
commit 9e0a7c41a4
80 changed files with 202 additions and 8401 deletions

View File

@ -429,11 +429,7 @@ def clearfilecache(repo, attrname):
def perfwalk(ui, repo, *pats, **opts):
timer, fm = gettimer(ui, opts)
m = scmutil.match(repo[None], pats, {})
timer(
lambda: len(
list(repo.dirstate.walk(m, subrepos=[], unknown=True, ignored=False))
)
)
timer(lambda: len(list(repo.dirstate.walk(m, unknown=True, ignored=False))))
fm.end()

View File

@ -33,7 +33,6 @@
<File Name="phases.txt" />
<File Name="revisions.txt" />
<File Name="scripting.txt" />
<File Name="subrepos.txt" />
<File Name="templates.txt" />
<File Name="urls.txt" />
</Component>

View File

@ -244,8 +244,7 @@ def convert(ui, src, dest=None, revmapfile=None, **opts):
The Git importer converts commits from all reachable branches (refs
in refs/heads) and remotes (refs in refs/remotes) to Mercurial.
Branches are converted to bookmarks with the same name, with the
leading 'refs/heads' stripped. Git submodules are converted to Git
subrepos in Mercurial.
leading 'refs/heads' stripped. Git submodules are not supported.
The following options can be set with ``--config``:
@ -336,23 +335,6 @@ def convert(ui, src, dest=None, revmapfile=None, **opts):
Mercurial Destination
#####################
The Mercurial destination will recognize Mercurial subrepositories in the
destination directory, and update the .hgsubstate file automatically if the
destination subrepositories contain the <dest>/<sub>/.hg/shamap file.
Converting a repository with subrepositories requires converting a single
repository at a time, from the bottom up.
.. container:: verbose
An example showing how to convert a repository with subrepositories::
# so convert knows the type when it sees a non empty destination
$ hg init converted
$ hg convert orig/sub1 converted/sub1
$ hg convert orig/sub2 converted/sub2
$ hg convert orig converted
The following options are supported:
:convert.hg.clonebranches: dispatch source branches in separate

View File

@ -23,9 +23,6 @@ class submodule(object):
def hgsub(self):
return "%s = [git]%s" % (self.path, self.url)
def hgsubstate(self):
return "%s %s" % (self.node, self.path)
# Keys in extra fields that should not be copied if the user requests.
bannedextrakeys = {
@ -202,9 +199,6 @@ class convert_git(common.converter_source, common.commandline):
if name == ".hgsub":
data = "\n".join([m.hgsub() for m in self.submoditer()])
mode = ""
elif name == ".hgsubstate":
data = "\n".join([m.hgsubstate() for m in self.submoditer()])
mode = ""
else:
data = self.catfile(rev, "blob")
mode = self.modecache[(name, rev)]
@ -265,8 +259,6 @@ class convert_git(common.converter_source, common.commandline):
copies = {}
seen = set()
entry = None
subexists = [False]
subdeleted = [False]
difftree = output.split("\x00")
lcount = len(difftree)
i = 0
@ -283,16 +275,10 @@ class convert_git(common.converter_source, common.commandline):
if f == ".gitmodules":
if skipsubmodules:
return
subexists[0] = True
if entry[4] == "D" or renamesource:
subdeleted[0] = True
changes.append((".hgsub", nodemod.nullhex))
else:
changes.append((".hgsub", ""))
raise error.Abort(_("gitmodules are not supported"))
elif entry[1] == "160000" or entry[0] == ":160000":
if not skipsubmodules:
subexists[0] = True
raise error.Abort(_("gitmodules are not supported"))
else:
if renamesource:
h = nodemod.nullhex
@ -330,12 +316,6 @@ class convert_git(common.converter_source, common.commandline):
copies[fdest] = f
entry = None
if subexists[0]:
if subdeleted[0]:
changes.append((".hgsubstate", nodemod.nullhex))
else:
self.retrievegitmodules(version)
changes.append((".hgsubstate", ""))
return (changes, copies, set())
def getcommit(self, version):

View File

@ -153,45 +153,6 @@ class mercurial_sink(common.converter_sink):
fp.write("%s %s\n" % (revid, s[1]))
return fp.getvalue()
def _rewritesubstate(self, source, data):
fp = stringio()
for line in data.splitlines():
s = line.split(" ", 1)
if len(s) != 2:
continue
revid = s[0]
subpath = s[1]
if revid != nodemod.nullhex:
revmap = self.subrevmaps.get(subpath)
if revmap is None:
revmap = mapfile(self.ui, self.repo.wjoin(subpath, ".hg/shamap"))
self.subrevmaps[subpath] = revmap
# It is reasonable that one or more of the subrepos don't
# need to be converted, in which case they can be cloned
# into place instead of converted. Therefore, only warn
# once.
msg = _('no ".hgsubstate" updates will be made for "%s"\n')
if len(revmap) == 0:
sub = self.repo.wvfs.reljoin(subpath, ".hg")
if self.repo.wvfs.exists(sub):
self.ui.warn(msg % subpath)
newid = revmap.get(revid)
if not newid:
if len(revmap) > 0:
self.ui.warn(
_("%s is missing from %s/.hg/shamap\n") % (revid, subpath)
)
else:
revid = newid
fp.write("%s %s\n" % (revid, subpath))
return fp.getvalue()
def _calculatemergedfiles(self, source, p1ctx, p2ctx):
"""Calculates the files from p2 that we need to pull in when merging p1
and p2, given that the merge is coming from the given source.
@ -258,8 +219,6 @@ class mercurial_sink(common.converter_sink):
return None
if f == ".hgtags":
data = self._rewritetags(source, revmap, data)
if f == ".hgsubstate":
data = self._rewritesubstate(source, data)
return context.memfilectx(
self.repo, memctx, f, data, "l" in mode, "x" in mode, copies.get(f)
)

View File

@ -27,7 +27,6 @@ def debugcommitmessage(ui, repo, *args):
ctx = context.workingcommitctx(repo, status, text, user, date, extra)
subs = []
editform = form or "commit.normal.normal"
extramsg = _("Leave message empty to abort commit.")
@ -37,10 +36,10 @@ def debugcommitmessage(ui, repo, *args):
ref = ".".join(forms)
tmpl = repo.ui.config("committemplate", ref)
if tmpl:
committext = cmdutil.buildcommittemplate(repo, ctx, subs, extramsg, ref)
committext = cmdutil.buildcommittemplate(repo, ctx, extramsg, ref)
break
forms.pop()
else:
committext = cmdutil.buildcommittext(repo, ctx, subs, extramsg)
committext = cmdutil.buildcommittext(repo, ctx, extramsg)
ui.status(committext)

View File

@ -98,7 +98,7 @@ configitem("diff-tools", r".*\.diffargs$", default=None, generic=True)
testedwith = "ships-with-hg-core"
def snapshot(ui, repo, files, node, tmproot, listsubrepos):
def snapshot(ui, repo, files, node, tmproot):
"""snapshot files as of some revision
if not using snapshot, -I/-X does not work and recursive diff
in tools like kdiff3 and meld displays too many files."""
@ -124,12 +124,7 @@ def snapshot(ui, repo, files, node, tmproot, listsubrepos):
repo.ui.setconfig("ui", "archivemeta", False)
archival.archive(
repo,
base,
node,
"files",
matchfn=scmutil.matchfiles(repo, files),
subrepos=listsubrepos,
repo, base, node, "files", matchfn=scmutil.matchfiles(repo, files)
)
for fn in sorted(files):
@ -174,23 +169,15 @@ def dodiff(ui, repo, cmdline, pats, opts):
if node1b == nullid:
do3way = False
subrepos = opts.get("subrepos")
matcher = scmutil.match(repo[node2], pats, opts)
if opts.get("patch"):
if subrepos:
raise error.Abort(_("--patch cannot be used with --subrepos"))
if node2 is None:
raise error.Abort(_("--patch requires two revisions"))
else:
mod_a, add_a, rem_a = map(
set, repo.status(node1a, node2, matcher, listsubrepos=subrepos)[:3]
)
mod_a, add_a, rem_a = map(set, repo.status(node1a, node2, matcher)[:3])
if do3way:
mod_b, add_b, rem_b = map(
set, repo.status(node1b, node2, matcher, listsubrepos=subrepos)[:3]
)
mod_b, add_b, rem_b = map(set, repo.status(node1b, node2, matcher)[:3])
else:
mod_b, add_b, rem_b = set(), set(), set()
modadd = mod_a | add_a | mod_b | add_b
@ -203,11 +190,11 @@ def dodiff(ui, repo, cmdline, pats, opts):
if not opts.get("patch"):
# Always make a copy of node1a (and node1b, if applicable)
dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a)
dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot, subrepos)[0]
dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot)[0]
rev1a = "@%d" % repo[node1a].rev()
if do3way:
dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b)
dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot, subrepos)[0]
dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot)[0]
rev1b = "@%d" % repo[node1b].rev()
else:
dir1b = None
@ -219,14 +206,14 @@ def dodiff(ui, repo, cmdline, pats, opts):
dir2root = ""
rev2 = ""
if node2:
dir2 = snapshot(ui, repo, modadd, node2, tmproot, subrepos)[0]
dir2 = snapshot(ui, repo, modadd, node2, tmproot)[0]
rev2 = "@%d" % repo[node2].rev()
elif len(common) > 1:
# we only actually need to get the files to copy back to
# the working dir in this case (because the other cases
# are: diffing 2 revisions or single file -- in which case
# the file is already directly passed to the diff tool).
dir2, fnsandstat = snapshot(ui, repo, modadd, None, tmproot, subrepos)
dir2, fnsandstat = snapshot(ui, repo, modadd, None, tmproot)
else:
# This lets the diff tool open the changed file directly
dir2 = ""
@ -326,16 +313,12 @@ def dodiff(ui, repo, cmdline, pats, opts):
shutil.rmtree(tmproot)
extdiffopts = (
[
("o", "option", [], _("pass option to comparison program"), _("OPT")),
("r", "rev", [], _("revision"), _("REV")),
("c", "change", "", _("change made by revision"), _("REV")),
("", "patch", None, _("compare patches for two revisions")),
]
+ cmdutil.walkopts
+ cmdutil.subrepoopts
)
extdiffopts = [
("o", "option", [], _("pass option to comparison program"), _("OPT")),
("r", "rev", [], _("revision"), _("REV")),
("c", "change", "", _("change made by revision"), _("REV")),
("", "patch", None, _("compare patches for two revisions")),
] + cmdutil.walkopts
@command(

View File

@ -137,11 +137,11 @@ performance might regress in some cases. (default: 200)
# ============
#
# * fsmonitor will disable itself if any of the following extensions are
# enabled: largefiles, inotify, eol; or if the repository has subrepos.
# * fsmonitor will produce incorrect results if nested repos that are not
# subrepos exist. *Workaround*: add nested repo paths to your `.hgignore`.
# enabled: largefiles, inotify, eol.
# * fsmonitor will produce incorrect results if nested repos exist.
# *Workaround*: add nested repo paths to your `.hgignore`.
#
# The issues related to nested repos and subrepos are probably not fundamental
# The issues related to nested repos are probably not fundamental
# ones. Patches to fix them are welcome.
from __future__ import absolute_import
@ -302,7 +302,7 @@ def wrappurge(orig, repo, match, findfiles, finddirs, includeignored):
@util.timefunction("fsmonitorwalk", 1, "_ui")
def overridewalk(orig, self, match, subrepos, unknown, ignored, full=True):
def overridewalk(orig, self, match, unknown, ignored, full=True):
"""Replacement for dirstate.walk, hooking into Watchman.
Whenever full is False, ignored is False, and the Watchman client is
@ -311,7 +311,7 @@ def overridewalk(orig, self, match, subrepos, unknown, ignored, full=True):
def bail(reason):
self._ui.debug("fsmonitor: fallback to core status, %s\n" % reason)
return orig(match, subrepos, unknown, ignored, full=True)
return orig(match, unknown, ignored, full=True)
if full:
return bail("full rewalk requested")
@ -411,14 +411,12 @@ def overridewalk(orig, self, match, subrepos, unknown, ignored, full=True):
normalize = None
# step 1: find all explicit files
results, work, dirsnotfound = self._walkexplicit(match, subrepos)
results, work, dirsnotfound = self._walkexplicit(match)
skipstep3 = skipstep3 and not (work or dirsnotfound)
work = [d for d in work if not dirignore(d[0])]
if not work and (exact or skipstep3):
for s in subrepos:
del results[s]
del results[".hg"]
return results
@ -596,8 +594,6 @@ def overridewalk(orig, self, match, subrepos, unknown, ignored, full=True):
state.setdroplist(droplist)
state.setignorelist(ignorelist)
for s in subrepos:
del results[s]
del results[".hg"]
return results
@ -611,7 +607,6 @@ def overridestatus(
ignored=False,
clean=False,
unknown=False,
listsubrepos=False,
):
listignored = ignored
listclean = clean
@ -688,9 +683,7 @@ def overridestatus(
self._watchmanclient.clearconnection()
_handleunavailable(self.ui, self._fsmonitorstate, ex)
# boo, Watchman failed. bail
return orig(
node1, node2, match, listignored, listclean, listunknown, listsubrepos
)
return orig(node1, node2, match, listignored, listclean, listunknown)
if updatestate:
# We need info about unknown files. This may make things slower the
@ -728,7 +721,7 @@ def overridestatus(
psafter = poststatus(startclock)
self.addpostdsstatus(psafter, afterdirstatewrite=True)
r = orig(node1, node2, match, listignored, listclean, stateunknown, listsubrepos)
r = orig(node1, node2, match, listignored, listclean, stateunknown)
modified, added, removed, deleted, unknown, ignored, clean = r
if not listunknown:
@ -747,9 +740,7 @@ def overridestatus(
self.ui.fout = self.ui.ferr = open(os.devnull, "wb")
try:
rv2 = orig(
node1, node2, match, listignored, listclean, listunknown, listsubrepos
)
rv2 = orig(node1, node2, match, listignored, listclean, listunknown)
finally:
self.dirstate._fsmonitordisable = False
self.ui.quiet = quiet
@ -963,13 +954,6 @@ def reposetup(ui, repo):
if "eden" in repo.requirements:
return
# We don't work with subrepos either.
#
# if repo[None].substate can cause a dirstate parse, which is too
# slow. Instead, look for a file called hgsubstate,
if repo.wvfs.exists(".hgsubstate") or repo.wvfs.exists(".hgsub"):
return
# Check if fsmonitor is explicitly disabled for this repository
fsmonitorstate = state.state(repo)
if fsmonitorstate.mode == "off":

View File

@ -937,57 +937,6 @@ class GitHandler(object):
if detect_renames:
renames = git_renames
git_commit_tree = self.git[commit.tree]
# Analyze hgsubstate and build an updated version using SHAs from
# gitlinks. Order of application:
# - preexisting .hgsubstate in git tree
# - .hgsubstate from hg parent
# - changes in gitlinks
hgsubstate = util.parse_hgsubstate(
self.git_file_readlines(git_commit_tree, ".hgsubstate")
)
parentsubdata = ""
if gparents:
p1ctx = self.repo.changectx(gparents[0])
if ".hgsubstate" in p1ctx:
parentsubdata = p1ctx.filectx(".hgsubstate").data()
parentsubdata = parentsubdata.splitlines()
parentsubstate = util.parse_hgsubstate(parentsubdata)
for path, sha in parentsubstate.iteritems():
hgsubstate[path] = sha
for path, sha in gitlinks.iteritems():
if sha is None:
hgsubstate.pop(path, None)
else:
hgsubstate[path] = sha
# in case .hgsubstate wasn't among changed files
# force its inclusion if it wasn't already deleted
hgsubdeleted = files.get(".hgsubstate")
if hgsubdeleted:
hgsubdeleted = hgsubdeleted[0]
if hgsubdeleted or (not hgsubstate and parentsubdata):
files[".hgsubstate"] = True, None, None
elif util.serialize_hgsubstate(hgsubstate) != parentsubdata:
files[".hgsubstate"] = False, 0o100644, None
# Analyze .hgsub and merge with .gitmodules
hgsub = None
gitmodules = self.parse_gitmodules(git_commit_tree)
if gitmodules:
hgsub = util.parse_hgsub(self.git_file_readlines(git_commit_tree, ".hgsub"))
for (sm_path, sm_url, sm_name) in gitmodules:
hgsub[sm_path] = "[git]" + sm_url
files[".hgsub"] = (False, 0o100644, None)
elif (
commit.parents
and ".gitmodules" in self.git[self.git[commit.parents[0]].tree]
):
# no .gitmodules in this commit, however present in the parent
# mark its hg counterpart as deleted (assuming .hgsub is there
# due to the same import_git_commit process
files[".hgsub"] = (True, 0o100644, None)
date = (commit.author_time, -commit.author_timezone)
text = strip_message
@ -1056,10 +1005,6 @@ class GitHandler(object):
if not sha: # indicates there's no git counterpart
e = ""
copied_path = None
if ".hgsubstate" == f:
data = util.serialize_hgsubstate(hgsubstate)
elif ".hgsub" == f:
data = util.serialize_hgsub(hgsub)
else:
data = self.git[sha].data
copied_path = renames.get(f)
@ -1115,8 +1060,6 @@ class GitHandler(object):
date,
{"hg-git": "octopus"},
)
# See comment below about setting substate to None.
ctx.substate = None
return hex(self.repo.commitctx(ctx))
octopus = len(gparents) > 2
@ -1163,14 +1106,6 @@ class GitHandler(object):
date,
extra,
)
# Starting Mercurial commit d2743be1bb06, memctx imports from
# committablectx. This means that it has a 'substate' property that
# contains the subrepo state. Ordinarily, Mercurial expects the subrepo
# to be present while making a new commit -- since hg-git is importing
# purely in-memory commits without backing stores for the subrepos,
# that won't work. Forcibly set the substate to None so that there's no
# attempt to read subrepos.
ctx.substate = None
node = self.repo.commitctx(ctx)
self.swap_out_encoding(oldenc)

View File

@ -12,16 +12,6 @@ from edenscm.mercurial import util as hgutil
from edenscm.mercurial.i18n import _
def parse_subrepos(ctx):
sub = util.OrderedDict()
if ".hgsub" in ctx:
sub = util.parse_hgsub(ctx[".hgsub"].data().splitlines())
substate = util.OrderedDict()
if ".hgsubstate" in ctx:
substate = util.parse_hgsubstate(ctx[".hgsubstate"].data().splitlines())
return sub, substate
def audit_git_path(ui, path):
r"""Check for path components that case-fold to .git.
@ -247,38 +237,14 @@ class IncrementalChangesetExporter(object):
# only export those.
dirty_trees = set()
subadded, subremoved = [], []
for s in modified, added, removed:
if ".hgsub" in s or ".hgsubstate" in s:
subadded, subremoved = self._handle_subrepos(newctx)
break
# We first process subrepo and file removals so we can prune dead
# trees.
for path in subremoved:
self._remove_path(path, dirty_trees)
for path in removed:
if path == ".hgsubstate" or path == ".hgsub":
continue
self._remove_path(path, dirty_trees)
for path, sha in subadded:
d = os.path.dirname(path)
tree = self._dirs.setdefault(d, dulobjs.Tree())
dirty_trees.add(d)
tree.add(os.path.basename(path), dulobjs.S_IFGITLINK, sha)
# For every file that changed or was added, we need to calculate the
# corresponding Git blob and its tree entry. We emit the blob
# immediately and update trees to be aware of its presence.
for path in set(modified) | set(added):
audit_git_path(self._hg.ui, path)
if path == ".hgsubstate" or path == ".hgsub":
continue
d = os.path.dirname(path)
tree = self._dirs.setdefault(d, dulobjs.Tree())
dirty_trees.add(d)
@ -401,50 +367,6 @@ class IncrementalChangesetExporter(object):
# trees, this should hold true.
parent_tree[os.path.basename(d)] = (stat.S_IFDIR, tree.id)
def _handle_subrepos(self, newctx):
sub, substate = parse_subrepos(self._ctx)
newsub, newsubstate = parse_subrepos(newctx)
# For each path, the logic is described by the following table. 'no'
# stands for 'the subrepo doesn't exist', 'git' stands for 'git
# subrepo', and 'hg' stands for 'hg or other subrepo'.
#
# old new | action
# * git | link (1)
# git hg | delete (2)
# git no | delete (3)
#
# All other combinations are 'do nothing'.
#
# git links without corresponding submodule paths are stored as
# subrepos with a substate but without an entry in .hgsub.
# 'added' is both modified and added
added, removed = [], []
def isgit(sub, path):
return path not in sub or sub[path].startswith("[git]")
for path, sha in substate.iteritems():
if not isgit(sub, path):
# old = hg -- will be handled in next loop
continue
# old = git
if path not in newsubstate or not isgit(newsub, path):
# new = hg or no, case (2) or (3)
removed.append(path)
for path, sha in newsubstate.iteritems():
if not isgit(newsub, path):
# new = hg or no; the only cases we care about are handled
# above
continue
# case (1)
added.append((path, sha))
return added, removed
@staticmethod
def tree_entry(fctx, blob_cache):
"""Compute a dulwich TreeEntry from a filectx.

View File

@ -16,40 +16,11 @@ except ImportError:
gitschemes = ("git", "git+ssh", "git+http", "git+https")
def parse_hgsub(lines):
"""Fills OrderedDict with hgsub file content passed as list of lines"""
rv = OrderedDict()
for l in lines:
ls = l.strip()
if not ls or ls[0] == "#":
continue
name, value = l.split("=", 1)
rv[name.strip()] = value.strip()
return rv
def serialize_hgsub(data):
"""Produces a string from OrderedDict hgsub content"""
return "".join(["%s = %s\n" % (n, v) for n, v in data.iteritems()])
def parse_hgsubstate(lines):
"""Fills OrderedDict with hgsubtate file content passed as list of lines"""
rv = OrderedDict()
for l in lines:
ls = l.strip()
if not ls or ls[0] == "#":
continue
value, name = l.split(" ", 1)
rv[name.strip()] = value.strip()
return rv
def serialize_hgsubstate(data):
"""Produces a string from OrderedDict hgsubstate content"""
return "".join(["%s %s\n" % (data[n], n) for n in sorted(data)])
def transform_notgit(f):
"""use as a decorator around functions that call into dulwich"""

View File

@ -50,9 +50,6 @@ def verify(ui, repo, hgctx):
dirkind = stat.S_IFDIR
hgfiles = set(hgctx)
# TODO deal with submodules
hgfiles.discard(".hgsubstate")
hgfiles.discard(".hgsub")
gitfiles = set()
i = 0
@ -63,11 +60,7 @@ def verify(ui, repo, hgctx):
if gitfile.mode == dirkind:
continue
# TODO deal with submodules
if (
gitfile.mode == S_IFGITLINK
or gitfile.path == ".hgsubstate"
or gitfile.path == ".hgsub"
):
if gitfile.mode == S_IFGITLINK:
continue
prog.value = i
i += 1

View File

@ -39,7 +39,6 @@ from edenscm.mercurial import (
policy,
registrar,
revset,
subrepo,
util as hgutil,
)
@ -231,8 +230,6 @@ def extsetup(ui):
revset.symbols.update(util.revsets)
subrepo.types["hgsubversion"] = svnexternals.svnsubrepo
def reposetup(ui, repo):
if repo.local():

View File

@ -8,7 +8,7 @@ import stat
import subprocess
import util
from edenscm.mercurial import subrepo, util as hgutil
from edenscm.mercurial import util as hgutil
from edenscm.mercurial.i18n import _
@ -423,18 +423,7 @@ def getchanges(ui, repo, parentctx, exts):
if exts:
files[".hgsvnexternals"] = exts.write()
elif mode == "subrepos":
# XXX: clobering the subrepos files is good enough for now
files = {".hgsub": None, ".hgsubstate": None}
if exts:
defs = parsedefinitions(ui, repo, "", exts)
hgsub, hgsubstate = [], []
for path, rev, _source, _pegrev, norevline, base in sorted(defs):
hgsub.append("%s = [hgsubversion] %s:%s\n" % (path, base, norevline))
if rev is None:
rev = "HEAD"
hgsubstate.append("%s %s\n" % (rev, path))
files[".hgsub"] = "".join(hgsub)
files[".hgsubstate"] = "".join(hgsubstate)
raise hgutil.Abort(_("subrepos mode is no longer supported"))
elif mode == "ignore":
files = {}
else:
@ -462,14 +451,7 @@ def parse(ui, ctx):
if ".hgsvnexternals" in ctx:
external.read(ctx[".hgsvnexternals"].data())
elif mode == "subrepos":
for path in ctx.substate:
src, rev = ctx.substate[path][:2]
base, norevline = src.split(":", 1)
base = base.strip()
if rev is None:
rev = "HEAD"
line = norevline.replace("{REV}", rev)
external.setdefault(base, []).append(line)
raise hgutil.Abort(_("subrepos mode is no longer supported"))
elif mode == "ignore":
pass
else:
@ -480,75 +462,6 @@ def parse(ui, ctx):
_notset = object()
class svnsubrepo(subrepo.svnsubrepo):
def __init__(self, ctx, path, state, allowcreate=_notset):
state = (state[0].split(":", 1)[1], state[1])
if allowcreate is _notset:
# Mercurial 3.7 and earlier
super(svnsubrepo, self).__init__(ctx, path, state)
else:
# Mercurial 3.8 and later
super(svnsubrepo, self).__init__(ctx, path, state, allowcreate)
# Mercurial 3.3+ set 'ui' rather than '_ui' -- set that and use 'ui'
# everywhere to maintain compatibility across versions
if not hgutil.safehasattr(self, "ui"):
self.ui = ctx._repo.ui
def get(self, state, *args, **kwargs):
# Resolve source first
line = state[0].split(":", 1)[1]
source, pegrev = parsedefinition(line)[2:4]
try:
# Getting the root SVN repository URL is expensive.
# Assume the externals is absolute.
source = resolvesource(self.ui, None, source)
except RelativeSourceError:
svnurl = self._ctx._repo.ui.expandpath("default")
svnroot = getsvninfo(util.normalize_url(svnurl))[1]
source = resolvesource(self.ui, svnroot, source)
# hg 1.9 and higher, append the rev as a peg revision to
# the source URL, so we cannot add our own. We assume
# that "-r10 url@2" will be similar to "url@10" most of
# the time.
state = (source, state[1])
return super(svnsubrepo, self).get(state, *args, **kwargs)
def dirty(self, ignoreupdate=False, missing=False):
# You cannot compare anything with HEAD. Just accept it
# can be anything.
if hgutil.safehasattr(self, "_wcrevs"):
wcrevs = self._wcrevs()
else:
wcrev = self._wcrev()
wcrevs = (wcrev, wcrev)
shouldcheck = (
"HEAD" in wcrevs
or self._state[1] == "HEAD"
or self._state[1] in wcrevs
or ignoreupdate
or missing
)
if shouldcheck:
changes, extchanges, wcmissing = self._wcchanged()
changed = changes or (missing and wcmissing)
if not changed:
return False
return True
def commit(self, text, user, date):
rev = super(svnsubrepo, self).commit(text, user, date)
# Keep unversioned externals unversioned
if self._state[1] == "HEAD":
rev = "HEAD"
return rev
def basestate(self):
# basestate() was introduced by bcb973abcc0b in 2.2
if self._state[1] == "HEAD":
return "HEAD"
return super(svnsubrepo, self).basestate()
if __name__ == "__main__":
import doctest

View File

@ -32,7 +32,7 @@ try:
except ImportError:
smartset = None
ignoredfiles = set([".hgtags", ".hgsvnexternals", ".hgsub", ".hgsubstate"])
ignoredfiles = set([".hgtags", ".hgsvnexternals"])
b_re = re.compile(r"^\+\+\+ b\/([^\n]*)", re.MULTILINE)
a_re = re.compile(r"^--- a\/([^\n]*)", re.MULTILINE)

View File

@ -1192,8 +1192,6 @@ def expushcmd(orig, ui, repo, dest=None, **opts):
% (short(node), dest, opargs["to"])
)
# TODO: subrepo stuff
force = opts.get("force")
bookmark = opargs["to"]
pattern = ui.config("remotenames", "disallowedto")

View File

@ -291,17 +291,7 @@ archivers = {
}
def archive(
repo,
dest,
node,
kind,
decode=True,
matchfn=None,
prefix="",
mtime=None,
subrepos=False,
):
def archive(repo, dest, node, kind, decode=True, matchfn=None, prefix="", mtime=None):
"""create archive of repo as it was at node.
dest can be name of directory, name of archive file, or file
@ -317,8 +307,6 @@ def archive(
prefix is name of path to put before every archive member.
mtime is the modified time, in seconds, or None to use the changeset time.
subrepos tells whether to include subrepos.
"""
if kind == "files":
@ -357,12 +345,6 @@ def archive(
write(f, "x" in ff and 0o755 or 0o644, "l" in ff, ctx[f].data)
prog.value = (i, f)
if subrepos:
for subpath in sorted(ctx.substate):
sub = ctx.workingsub(subpath)
submatch = matchmod.subdirmatcher(subpath, matchfn)
total += sub.archive(archiver, prefix, submatch, decode)
if total == 0:
raise error.Abort(_("no files match the archive pattern"))

View File

@ -150,8 +150,6 @@ similarityopts = [
)
]
subrepoopts = [("S", "subrepos", None, _("recurse into subrepositories"))]
debugrevlogopts = [
("c", "changelog", False, _("open changelog")),
("m", "manifest", False, _("open manifest")),
@ -861,9 +859,6 @@ def bailifchanged(repo, merge=True, hint=None):
if uncommittedchanges(repo):
raise error.UncommitedChangesAbort(_("uncommitted changes"), hint=hint)
ctx = repo[None]
for s in sorted(ctx.substate):
ctx.sub(s).bailifchanged(hint=hint)
def logmessage(ui, opts):
@ -928,11 +923,11 @@ def getcommiteditor(edit=False, finishdesc=None, extramsg=None, editform="", **o
they are specific for usage in MQ.
"""
if edit or finishdesc or extramsg:
return lambda r, c, s: commitforceeditor(
r, c, s, finishdesc=finishdesc, extramsg=extramsg, editform=editform
return lambda r, c: commitforceeditor(
r, c, finishdesc=finishdesc, extramsg=extramsg, editform=editform
)
elif editform:
return lambda r, c, s: commiteditor(r, c, s, editform=editform)
return lambda r, c: commiteditor(r, c, editform=editform)
else:
return commiteditor
@ -1423,7 +1418,7 @@ def tryimportone(ui, repo, hunk, parents, opts, msgs, updatefunc):
:updatefunc: a function that update a repo to a given node
updatefunc(<repo>, <node>)
"""
# avoid cycle context -> subrepo -> cmdutil
# avoid cycle context -> cmdutil
from . import context
extractdata = patch.extract(ui, hunk)
@ -1728,7 +1723,6 @@ def diffordiffstat(
fp=None,
prefix="",
root="",
listsubrepos=False,
hunksfilterfn=None,
):
"""show diff or diffstat."""
@ -1787,31 +1781,6 @@ def diffordiffstat(
):
write(chunk, label=label)
if listsubrepos:
ctx1 = repo[node1]
ctx2 = repo[node2]
for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
tempnode2 = node2
try:
if node2 is not None:
tempnode2 = ctx2.substate[subpath][1]
except KeyError:
# A subrepo that existed in node1 was deleted between node1 and
# node2 (inclusive). Thus, ctx2's substate won't contain that
# subpath. The best we can do is to ignore it.
tempnode2 = None
submatch = matchmod.subdirmatcher(subpath, match)
sub.diff(
ui,
diffopts,
tempnode2,
submatch,
changes=changes,
stat=stat,
fp=fp,
prefix=prefix,
)
def _changesetlabels(ctx):
labels = ["log.changeset", "changeset.%s" % ctx.phasestr()]
@ -3121,7 +3090,6 @@ def graphrevs(repo, nodes, opts):
def add(ui, repo, match, prefix, explicitonly, **opts):
join = lambda f: os.path.join(prefix, f)
bad = []
badfn = lambda x, y: bad.append(x) or match.bad(x, y)
@ -3136,15 +3104,7 @@ def add(ui, repo, match, prefix, explicitonly, **opts):
dirstate = repo.dirstate
# We don't want to just call wctx.walk here, since it would return a lot of
# clean files, which we aren't interested in and takes time.
for f in sorted(
dirstate.walk(
badmatch,
subrepos=sorted(wctx.substate),
unknown=True,
ignored=False,
full=False,
)
):
for f in sorted(dirstate.walk(badmatch, unknown=True, ignored=False, full=False)):
exact = match.exact(f)
if exact or not explicitonly and f not in wctx and repo.wvfs.lexists(f):
if cca:
@ -3153,17 +3113,6 @@ def add(ui, repo, match, prefix, explicitonly, **opts):
if ui.verbose or not exact:
ui.status(_("adding %s\n") % match.rel(f))
for subpath in sorted(wctx.substate):
sub = wctx.sub(subpath)
try:
submatch = matchmod.subdirmatcher(subpath, match)
if opts.get(r"subrepos"):
bad.extend(sub.add(ui, submatch, prefix, False, **opts))
else:
bad.extend(sub.add(ui, submatch, prefix, True, **opts))
except error.LookupError:
ui.status(_("skipping missing subrepository: %s\n") % join(subpath))
if not opts.get(r"dry_run"):
rejected = wctx.add(names, prefix)
bad.extend(f for f in rejected if f in match.files())
@ -3174,14 +3123,8 @@ def addwebdirpath(repo, serverpath, webconf):
webconf[serverpath] = repo.root
repo.ui.debug("adding %s = %s\n" % (serverpath, repo.root))
for r in repo.revs('filelog("path:.hgsub")'):
ctx = repo[r]
for subpath in ctx.substate:
ctx.sub(subpath).addwebdirpath(serverpath, webconf)
def forget(ui, repo, match, prefix, explicitonly):
join = lambda f: os.path.join(prefix, f)
bad = []
badfn = lambda x, y: bad.append(x) or match.bad(x, y)
wctx = repo[None]
@ -3192,16 +3135,6 @@ def forget(ui, repo, match, prefix, explicitonly):
if explicitonly:
forget = [f for f in forget if match.exact(f)]
for subpath in sorted(wctx.substate):
sub = wctx.sub(subpath)
try:
submatch = matchmod.subdirmatcher(subpath, match)
subbad, subforgot = sub.forget(submatch, prefix)
bad.extend([subpath + "/" + f for f in subbad])
forgot.extend([subpath + "/" + f for f in subforgot])
except error.LookupError:
ui.status(_("skipping missing subrepository: %s\n") % join(subpath))
if not explicitonly:
for f in match.files():
if f not in repo.dirstate and not repo.wvfs.isdir(f):
@ -3229,7 +3162,7 @@ def forget(ui, repo, match, prefix, explicitonly):
return bad, forgot
def files(ui, ctx, m, fm, fmt, subrepos):
def files(ui, ctx, m, fm, fmt):
if (ctx.rev() is None) and (edenfs.requirement in ctx.repo().requirements):
return eden_files(ui, ctx, m, fm, fmt)
@ -3248,17 +3181,6 @@ def files(ui, ctx, m, fm, fmt, subrepos):
fm.write("path", fmt, m.rel(f))
ret = 0
for subpath in sorted(ctx.substate):
submatch = matchmod.subdirmatcher(subpath, m)
if subrepos or m.exact(subpath) or any(submatch.files()):
sub = ctx.sub(subpath)
try:
recurse = m.exact(subpath) or subrepos
if sub.printfiles(ui, submatch, fm, fmt, recurse) == 0:
ret = 0
except error.LookupError:
ui.status(_("skipping missing subrepository: %s\n") % m.abs(subpath))
return ret
@ -3282,8 +3204,7 @@ def eden_files(ui, ctx, m, fm, fmt):
return ret
def remove(ui, repo, m, prefix, after, force, subrepos, warnings=None):
join = lambda f: os.path.join(prefix, f)
def remove(ui, repo, m, prefix, after, force, warnings=None):
ret = 0
s = repo.status(match=m, clean=True)
modified, added, deleted, clean = s[0], s[1], s[3], s[6]
@ -3296,38 +3217,14 @@ def remove(ui, repo, m, prefix, after, force, subrepos, warnings=None):
else:
warn = False
subs = sorted(wctx.substate)
with progress.bar(ui, _("searching"), _("subrepos"), len(subs)) as prog:
for subpath in subs:
prog.value += 1
submatch = matchmod.subdirmatcher(subpath, m)
if subrepos or m.exact(subpath) or any(submatch.files()):
sub = wctx.sub(subpath)
try:
if sub.removefiles(
submatch, prefix, after, force, subrepos, warnings
):
ret = 1
except error.LookupError:
warnings.append(
_("skipping missing subrepository: %s\n") % join(subpath)
)
# warn about failure to delete explicit files/dirs
deleteddirs = util.dirs(deleted)
files = m.files()
with progress.bar(ui, _("deleting"), _("files"), len(files)) as prog:
for f in files:
def insubrepo():
for subpath in wctx.substate:
if f.startswith(subpath + "/"):
return True
return False
prog.value += 1
isdir = f in deleteddirs or wctx.hasdir(f)
if f in repo.dirstate or isdir or f == "." or insubrepo() or f in subs:
if f in repo.dirstate or isdir or f == ".":
continue
if repo.wvfs.exists(f):
@ -3441,25 +3338,6 @@ def cat(ui, repo, ctx, matcher, basefm, fntemplate, prefix, **opts):
write(abs)
err = 0
for subpath in sorted(ctx.substate):
sub = ctx.sub(subpath)
try:
submatch = matchmod.subdirmatcher(subpath, matcher)
if not sub.cat(
submatch,
basefm,
fntemplate,
os.path.join(prefix, sub._path),
**pycompat.strkwargs(opts)
):
err = 0
except error.RepoLookupError:
ui.status(
_("skipping missing subrepository: %s\n")
% os.path.join(prefix, subpath)
)
return err
@ -3551,20 +3429,6 @@ def amend(ui, repo, old, extra, pats, opts):
_("failed to mark all new/missing files as added/removed")
)
# Check subrepos. This depends on in-place wctx._status update in
# subrepo.precommit(). To minimize the risk of this hack, we do
# nothing if .hgsub does not exist.
if ".hgsub" in wctx or ".hgsub" in old:
from . import subrepo # avoid cycle: cmdutil -> subrepo -> cmdutil
subs, commitsubs, newsubstate = subrepo.precommit(
ui, wctx, wctx._status, matcher
)
# amend should abort if commitsubrepos is enabled
assert not commitsubs
if subs:
subrepo.writestate(repo, newsubstate)
# avoid cycle (TODO: should be removed in default branch)
from . import merge as mergemod
@ -3701,18 +3565,17 @@ def amend(ui, repo, old, extra, pats, opts):
return newid
def commiteditor(repo, ctx, subs, editform=""):
def commiteditor(repo, ctx, editform=""):
if ctx.description():
return ctx.description()
return commitforceeditor(
repo, ctx, subs, editform=editform, unchangedmessagedetection=True
repo, ctx, editform=editform, unchangedmessagedetection=True
)
def commitforceeditor(
repo,
ctx,
subs,
finishdesc=None,
extramsg=None,
editform="",
@ -3727,13 +3590,11 @@ def commitforceeditor(
while forms:
ref = ".".join(forms)
if repo.ui.config("committemplate", ref):
templatetext = committext = buildcommittemplate(
repo, ctx, subs, extramsg, ref
)
templatetext = committext = buildcommittemplate(repo, ctx, extramsg, ref)
break
forms.pop()
else:
committext = buildcommittext(repo, ctx, subs, extramsg)
committext = buildcommittext(repo, ctx, extramsg)
# run editor in the repository root
olddir = pycompat.getcwd()
@ -3779,7 +3640,7 @@ def commitforceeditor(
return text
def buildcommittemplate(repo, ctx, subs, extramsg, ref):
def buildcommittemplate(repo, ctx, extramsg, ref):
ui = repo.ui
spec = formatter.templatespec(ref, None, None)
t = changeset_templater(ui, repo, spec, None, {}, False)
@ -3800,7 +3661,7 @@ def hgprefix(msg):
return "\n".join(["HG: %s" % a for a in msg.split("\n") if a])
def buildcommittext(repo, ctx, subs, extramsg):
def buildcommittext(repo, ctx, extramsg):
edittext = []
modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
if ctx.description():
@ -3819,7 +3680,6 @@ def buildcommittext(repo, ctx, subs, extramsg):
edittext.append(hgprefix(_("branch '%s'") % ctx.branch()))
if bookmarks.isactivewdirparent(repo):
edittext.append(hgprefix(_("bookmark '%s'") % repo._activebookmark))
edittext.extend([hgprefix(_("subrepo %s") % s) for s in subs])
edittext.extend([hgprefix(_("added %s") % f) for f in added])
edittext.extend([hgprefix(_("changed %s") % f) for f in modified])
edittext.extend([hgprefix(_("removed %s") % f) for f in removed])
@ -3880,13 +3740,9 @@ def revert(ui, repo, ctx, parents, *pats, **opts):
m = scmutil.match(wctx, pats, opts)
# we'll need this later
targetsubs = sorted(s for s in wctx.substate if m(s))
badfiles = set()
def badfn(path, msg):
if path in ctx.substate:
return
# We only report errors about paths that do not exist in the original
# node.
#
@ -4143,19 +3999,6 @@ def revert(ui, repo, ctx, parents, *pats, **opts):
_revertprefetch(repo, ctx, *[actions[name][0] for name in needdata])
_performrevert(repo, parents, ctx, actions, interactive, tobackup)
if targetsubs:
# Revert the subrepos on the revert list
for sub in targetsubs:
try:
wctx.sub(sub).revert(
ctx.substate[sub], *pats, **pycompat.strkwargs(opts)
)
except KeyError:
raise error.Abort(
"subrepository '%s' does not exist in %s!"
% (sub, short(ctx.node()))
)
def _revertprefetch(repo, ctx, *files):
"""Let extension changing the storage layer prefetch content"""

View File

@ -150,7 +150,6 @@ diffwsopts = cmdutil.diffwsopts
diffopts2 = cmdutil.diffopts2
mergetoolopts = cmdutil.mergetoolopts
similarityopts = cmdutil.similarityopts
subrepoopts = cmdutil.subrepoopts
debugrevlogopts = cmdutil.debugrevlogopts
# Commands start here, listed alphabetically
@ -161,12 +160,7 @@ except NameError:
xrange = range
@command(
"^add",
walkopts + subrepoopts + dryrunopts,
_("[OPTION]... [FILE]..."),
inferrepo=True,
)
@command("^add", walkopts + dryrunopts, _("[OPTION]... [FILE]..."), inferrepo=True)
def add(ui, repo, *pats, **opts):
"""start tracking the specified files
@ -217,7 +211,7 @@ def add(ui, repo, *pats, **opts):
@command(
"addremove",
similarityopts + subrepoopts + walkopts + dryrunopts,
similarityopts + walkopts + dryrunopts,
_("[OPTION]... [FILE]..."),
inferrepo=True,
)
@ -514,7 +508,6 @@ def annotate(ui, repo, *pats, **opts):
("r", "rev", "", _("revision to distribute"), _("REV")),
("t", "type", "", _("type of distribution to create"), _("TYPE")),
]
+ subrepoopts
+ walkopts,
_("[OPTION]... DEST"),
)
@ -580,16 +573,7 @@ def archive(ui, repo, dest, **opts):
prefix = cmdutil.makefilename(repo, prefix, node)
match = scmutil.match(ctx, [], opts)
archival.archive(
repo,
dest,
node,
kind,
not opts.get("no_decode"),
match,
prefix,
subrepos=opts.get("subrepos"),
)
archival.archive(repo, dest, node, kind, not opts.get("no_decode"), match, prefix)
@command(
@ -1650,8 +1634,7 @@ def clone(ui, source, dest=None, **opts):
]
+ walkopts
+ commitopts
+ commitopts2
+ subrepoopts,
+ commitopts2,
_("[OPTION]... [FILE]..."),
inferrepo=True,
)
@ -1727,11 +1710,6 @@ def _docommit(ui, repo, *pats, **opts):
return 1 if ret == 0 else ret
opts = pycompat.byteskwargs(opts)
if opts.get("subrepos"):
if opts.get("amend"):
raise error.Abort(_("cannot amend with --subrepos"))
# Let --subrepos on the command line override config setting.
ui.setconfig("ui", "commitsubrepos", True, "commit")
# Allow the commit message from another commit to be reused.
reuserev = opts.get("reuse_message")
@ -1751,9 +1729,6 @@ def _docommit(ui, repo, *pats, **opts):
extra = {}
if opts.get("amend"):
if ui.configbool("ui", "commitsubrepos"):
raise error.Abort(_("cannot amend with ui.commitsubrepos enabled"))
old = repo["."]
rewriteutil.precheck(repo, [old.rev()], "amend")
@ -1999,8 +1974,7 @@ def debugcomplete(ui, cmd="", **opts):
]
+ diffopts
+ diffopts2
+ walkopts
+ subrepoopts,
+ walkopts,
_("[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]..."),
inferrepo=True,
cmdtype=readonly,
@ -2086,15 +2060,7 @@ def diff(ui, repo, *pats, **opts):
m = scmutil.match(repo[node2], pats, opts)
ui.pager("diff")
cmdutil.diffordiffstat(
ui,
repo,
diffopts,
node1,
node2,
m,
stat=stat,
listsubrepos=opts.get("subrepos"),
root=opts.get("root"),
ui, repo, diffopts, node1, node2, m, stat=stat, root=opts.get("root")
)
@ -2197,8 +2163,7 @@ def export(ui, repo, *changesets, **opts):
("0", "print0", None, _("end filenames with NUL, for use with xargs")),
]
+ walkopts
+ formatteropts
+ subrepoopts,
+ formatteropts,
_("[OPTION]... [FILE]..."),
cmdtype=readonly,
)
@ -2258,7 +2223,7 @@ def files(ui, repo, *pats, **opts):
m = scmutil.match(ctx, pats, opts)
ui.pager("files")
with ui.formatter("files", opts) as fm:
return cmdutil.files(ui, ctx, m, fm, fmt, opts.get("subrepos"))
return cmdutil.files(ui, ctx, m, fm, fmt)
@command("^forget", walkopts, _("[OPTION]... FILE..."), inferrepo=True)
@ -2913,7 +2878,7 @@ def grep(ui, repo, pattern, *pats, **opts):
ds = repo.dirstate
getkind = stat.S_IFMT
lnkkind = stat.S_IFLNK
results = ds.walk(m, subrepos=[], unknown=False, ignored=False)
results = ds.walk(m, unknown=False, ignored=False)
files = []
for f in sorted(results.keys()):
@ -3795,8 +3760,7 @@ def import_(ui, repo, patch1=None, *patches, **opts):
("B", "bookmarks", False, _("compare bookmarks")),
]
+ logopts
+ remoteopts
+ subrepoopts,
+ remoteopts,
_("[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]"),
)
def incoming(ui, repo, source="default", **opts):
@ -3866,12 +3830,9 @@ def incoming(ui, repo, source="default", **opts):
revdag = cmdutil.graphrevs(other, chlist, opts)
cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
hg._incoming(display, ui, repo, source, opts, buffered=True)
return 0
if opts.get("bundle") and opts.get("subrepos"):
raise error.Abort(_("cannot combine --bundle and --subrepos"))
if opts.get("bookmarks"):
source, branches = hg.parseurl(ui.expandpath(source))
other = hg.peer(repo, opts, source)
@ -4390,8 +4351,7 @@ def merge(ui, repo, node=None, **opts):
("B", "bookmarks", False, _("compare bookmarks")),
]
+ logopts
+ remoteopts
+ subrepoopts,
+ remoteopts,
_("[-M] [-p] [-n] [-f] [-r REV]... [DEST]"),
)
def outgoing(ui, repo, dest=None, **opts):
@ -4960,18 +4920,6 @@ def push(ui, repo, dest=None, **opts):
_("default push revset for path evaluates to an " "empty set")
)
repo._subtoppath = dest
try:
# push subrepos depth-first for coherent ordering
c = repo[""]
subs = c.substate # only repos that are committed
for s in sorted(subs):
result = c.sub(s).push(opts)
if result == 0:
return not result
finally:
del repo._subtoppath
opargs = dict(opts.get("opargs", {})) # copy opargs since we may mutate it
opargs.setdefault("pushvars", []).extend(opts.get("pushvars", []))
@ -5011,7 +4959,6 @@ def push(ui, repo, dest=None, **opts):
+ commitopts
+ commitopts2
+ diffwsopts
+ subrepoopts
+ walkopts,
_("hg record [OPTION]... [FILE]..."),
)
@ -5076,7 +5023,6 @@ def recover(ui, repo):
("A", "after", None, _("record delete for missing files")),
("f", "force", None, _("forget added files, delete modified files")),
]
+ subrepoopts
+ walkopts,
_("[OPTION]... FILE..."),
inferrepo=True,
@ -5126,8 +5072,7 @@ def remove(ui, repo, *pats, **opts):
raise error.Abort(_("no files specified"))
m = scmutil.match(repo[None], pats, opts)
subrepos = opts.get("subrepos")
return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
return cmdutil.remove(ui, repo, m, "", after, force)
@command(
@ -5648,8 +5593,7 @@ def root(ui, repo):
("6", "ipv6", None, _("use IPv6 in addition to IPv4")),
("", "certificate", "", _("SSL certificate file"), _("FILE")),
("", "read-only", None, _("only allow read operations")),
]
+ subrepoopts,
],
_("[OPTION]..."),
optionalrepo=True,
)
@ -5782,7 +5726,6 @@ def show(ui, repo, *args, **opts):
("", "change", "", _("list the changed files of a revision"), _("REV")),
]
+ walkopts
+ subrepoopts
+ formatteropts,
_("[OPTION]... [FILE]..."),
inferrepo=True,
@ -5915,25 +5858,13 @@ def status(ui, repo, *pats, **opts):
if terse:
# we need to compute clean and unknown to terse
stat = repo.status(
node1,
node2,
m,
"ignored" in show or "i" in terse,
True,
True,
opts.get("subrepos"),
node1, node2, m, "ignored" in show or "i" in terse, True, True
)
stat = cmdutil.tersedir(stat, terse)
else:
stat = repo.status(
node1,
node2,
m,
"ignored" in show,
"clean" in show,
"unknown" in show,
opts.get("subrepos"),
node1, node2, m, "ignored" in show, "clean" in show, "unknown" in show
)
changestates = zip(states, pycompat.iterbytestr("MAR!?IC"), stat)
@ -6057,8 +5988,6 @@ def summary(ui, repo, **opts):
if d in status.added:
status.added.remove(d)
subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
labels = [
(ui.label(_("%d modified"), "status.modified"), status.modified),
(ui.label(_("%d added"), "status.added"), status.added),
@ -6068,7 +5997,6 @@ def summary(ui, repo, **opts):
(ui.label(_("%d deleted"), "status.deleted"), status.deleted),
(ui.label(_("%d unknown"), "status.unknown"), status.unknown),
(ui.label(_("%d unresolved"), "resolve.unresolved"), unresolved),
(ui.label(_("%d subrepos"), "status.modified"), subs),
]
t = []
for l, s in labels:
@ -6084,9 +6012,7 @@ def summary(ui, repo, **opts):
t += _(" (interrupted update)")
elif len(parents) > 1:
t += _(" (merge)")
elif not (
status.modified or status.added or status.removed or renamed or copied or subs
):
elif not (status.modified or status.added or status.removed or renamed or copied):
t += _(" (clean)")
cleanworkdir = True

View File

@ -2852,19 +2852,6 @@ def debugssl(ui, repo, source=None, **opts):
s.close()
@command(
"debugsub",
[("r", "rev", "", _("revision to check"), _("REV"))],
_("[-r REV] [REV]"),
)
def debugsub(ui, repo, rev=None):
ctx = scmutil.revsingle(repo, rev, None)
for k, v in sorted(ctx.substate.items()):
ui.write(("path %s\n") % k)
ui.write((" source %s\n") % v[0])
ui.write((" revision %s\n") % v[1])
@command(
"debugsuccessorssets",
[("", "closest", False, _("return closest successors sets only"))],

View File

@ -28,22 +28,6 @@ release = lockmod.release
command = registrar.command()
def checksubstate(repo, baserev=None):
"""return list of subrepos at a different revision than substate.
Abort if any subrepos have uncommitted changes."""
inclsubs = []
wctx = repo[None]
if baserev:
bctx = repo[baserev]
else:
bctx = wctx.parents()[0]
for s in sorted(wctx.substate):
wctx.sub(s).bailifchanged(True)
if s not in bctx.substate or bctx.sub(s).dirty():
inclsubs.append(s)
return inclsubs
def checklocalchanges(repo, force=False, excsuffix=""):
cmdutil.checkunfinished(repo)
s = repo.status()
@ -51,9 +35,6 @@ def checklocalchanges(repo, force=False, excsuffix=""):
if s.modified or s.added or s.removed or s.deleted:
_("local changes found") # i18n tool detection
raise error.Abort(_("local changes found" + excsuffix))
if checksubstate(repo):
_("local changed subrepos found") # i18n tool detection
raise error.Abort(_("local changed subrepos found" + excsuffix))
return s

View File

@ -165,7 +165,7 @@ coreconfigitem("convert", "git.remoteprefix", default="remote")
coreconfigitem("convert", "git.renamelimit", default=400)
coreconfigitem("convert", "git.saverev", default=True)
coreconfigitem("convert", "git.similarity", default=50)
coreconfigitem("convert", "git.skipsubmodules", default=False)
coreconfigitem("convert", "git.skipsubmodules", default=True)
coreconfigitem("convert", "hg.clonebranches", default=False)
coreconfigitem("convert", "hg.ignoreerrors", default=False)
coreconfigitem("convert", "hg.revs", default=None)
@ -373,7 +373,6 @@ coreconfigitem("patch", "fuzz", default=2)
coreconfigitem("paths", "default", default=None)
coreconfigitem("paths", "default-push", default=None)
coreconfigitem("paths", ".*", default=None, generic=True)
coreconfigitem("phases", "checksubrepos", default="follow")
coreconfigitem("phases", "new-commit", default="draft")
coreconfigitem("phases", "publish", default=True)
coreconfigitem("profiling", "enabled", default=False)
@ -428,19 +427,12 @@ coreconfigitem("smtp", "port", default=dynamicdefault)
coreconfigitem("smtp", "tls", default="none")
coreconfigitem("smtp", "username", default=None)
coreconfigitem("sparse", "missingwarning", default=False)
coreconfigitem(
"subrepos", "allowed", default=dynamicdefault # to make backporting simpler
)
coreconfigitem("subrepos", "hg:allowed", default=dynamicdefault)
coreconfigitem("subrepos", "git:allowed", default=dynamicdefault)
coreconfigitem("subrepos", "svn:allowed", default=dynamicdefault)
coreconfigitem("templates", ".*", default=None, generic=True)
coreconfigitem("treestate", "mingcage", default=1209600)
coreconfigitem("treestate", "minrepackthreshold", default="10M")
coreconfigitem("treestate", "repackfactor", default=3)
coreconfigitem("trusted", "groups", default=list)
coreconfigitem("trusted", "users", default=list)
coreconfigitem("ui", "_usedassubrepo", default=False)
coreconfigitem("ui", "allowemptycommit", default=False)
coreconfigitem("ui", "allowmerge", default=True)
coreconfigitem("ui", "allowtags", default=True)
@ -450,7 +442,6 @@ coreconfigitem("ui", "clonebundlefallback", default=False)
coreconfigitem("ui", "clonebundleprefers", default=list)
coreconfigitem("ui", "clonebundles", default=True)
coreconfigitem("ui", "color", default="auto")
coreconfigitem("ui", "commitsubrepos", default=False)
coreconfigitem("ui", "debug", default=False)
coreconfigitem("ui", "debugger", default="ipdb")
coreconfigitem("ui", "editor", default=dynamicdefault)
@ -520,7 +511,6 @@ coreconfigitem("web", "allowgz", default=False)
coreconfigitem("web", "allow-pull", alias=[("web", "allowpull")], default=True)
coreconfigitem("web", "allow-push", alias=[("web", "allow_push")], default=list)
coreconfigitem("web", "allowzip", default=False)
coreconfigitem("web", "archivesubrepos", default=False)
coreconfigitem("web", "cache", default=True)
coreconfigitem("web", "contact", default=None)
coreconfigitem("web", "deny_push", default=list)

View File

@ -28,7 +28,6 @@ from . import (
repoview,
revlog,
scmutil,
subrepo,
util,
visibility,
)
@ -179,13 +178,6 @@ class basectx(object):
modified, added, removed, deleted, unknown, ignored, clean
)
@propertycache
def substate(self):
return subrepo.state(self, self._repo.ui)
def subrev(self, subpath):
return self.substate[subpath][1]
def rev(self):
return self._rev
@ -349,28 +341,7 @@ class basectx(object):
except error.LookupError:
return ""
def sub(self, path, allowcreate=True):
"""return a subrepo for the stored revision of path, never wdir()"""
return subrepo.subrepo(self, path, allowcreate=allowcreate)
def nullsub(self, path, pctx):
return subrepo.nullsubrepo(self, path, pctx)
def workingsub(self, path):
"""return a subrepo for the stored revision, or wdir if this is a wdir
context.
"""
return subrepo.subrepo(self, path, allowwdir=True)
def match(
self,
pats=None,
include=None,
exclude=None,
default="glob",
listsubrepos=False,
badfn=None,
):
def match(self, pats=None, include=None, exclude=None, default="glob", badfn=None):
r = self._repo
return matchmod.match(
r.root,
@ -381,7 +352,6 @@ class basectx(object):
default,
auditor=r.nofsauditor,
ctx=self,
listsubrepos=listsubrepos,
badfn=badfn,
)
@ -407,7 +377,6 @@ class basectx(object):
listignored=False,
listclean=False,
listunknown=False,
listsubrepos=False,
):
"""return status of files between two nodes or node and working
directory.
@ -447,27 +416,6 @@ class basectx(object):
# these make no sense to reverse.
r = scmutil.status(r.modified, r.removed, r.added, [], [], [], r.clean)
if listsubrepos:
for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
try:
rev2 = ctx2.subrev(subpath)
except KeyError:
# A subrepo that existed in node1 was deleted between
# node1 and node2 (inclusive). Thus, ctx2's substate
# won't contain that subpath. The best we can do ignore it.
rev2 = None
submatch = matchmod.subdirmatcher(subpath, match)
s = sub.status(
rev2,
match=submatch,
ignored=listignored,
clean=listclean,
unknown=listunknown,
listsubrepos=True,
)
for rfiles, sfiles in zip(r, s):
rfiles.extend("%s/%s" % (subpath, f) for f in sfiles)
for l in r:
l.sort()
@ -791,10 +739,6 @@ class changectx(basectx):
# Wrap match.bad method to have message with nodeid
def bad(fn, msg):
# The manifest doesn't know about subrepos, so don't complain about
# paths into valid subrepos.
if any(fn == s or fn.startswith(s + "/") for s in self.substate):
return
match.bad(fn, _("no such file in rev %s") % self)
m = matchmod.badmatch(match, bad)
@ -1544,9 +1488,6 @@ class committablectx(basectx):
date = util.makedate()
return date
def subrev(self, subpath):
return None
def manifestnode(self):
return None
@ -1625,11 +1566,7 @@ class committablectx(basectx):
def walk(self, match):
"""Generates matching file names."""
return sorted(
self._repo.dirstate.walk(
match, subrepos=sorted(self.substate), unknown=True, ignored=False
)
)
return sorted(self._repo.dirstate.walk(match, unknown=True, ignored=False))
def matches(self, match):
return sorted(self._repo.dirstate.matches(match))
@ -1704,10 +1641,6 @@ class workingctx(committablectx):
def dirty(self, missing=False, merge=True, branch=True):
"check whether a working directory is modified"
# check subrepos first
for s in sorted(self.substate):
if self.sub(s).dirty(missing=missing):
return True
# check current working dir
return (
(merge and self.p2())
@ -1813,15 +1746,7 @@ class workingctx(committablectx):
self._repo.dirstate.normallookup(dest)
self._repo.dirstate.copy(source, dest)
def match(
self,
pats=None,
include=None,
exclude=None,
default="glob",
listsubrepos=False,
badfn=None,
):
def match(self, pats=None, include=None, exclude=None, default="glob", badfn=None):
r = self._repo
# Only a case insensitive filesystem needs magic to translate user input
@ -1836,7 +1761,6 @@ class workingctx(committablectx):
default,
auditor=r.auditor,
ctx=self,
listsubrepos=listsubrepos,
badfn=badfn,
icasefs=icasefs,
)
@ -1973,11 +1897,8 @@ class workingctx(committablectx):
def _dirstatestatus(self, match, ignored=False, clean=False, unknown=False):
"""Gets the status from the dirstate -- internal use only."""
subrepos = []
if ".hgsub" in self:
subrepos = sorted(self.substate)
cmp, s = self._repo.dirstate.status(
match, subrepos, ignored=ignored, clean=clean, unknown=unknown
match, ignored=ignored, clean=clean, unknown=unknown
)
# check for any possibly clean files
@ -2744,7 +2665,6 @@ class memctx(committablectx):
self._files = files
if branch is not None:
self._extra["branch"] = encoding.fromlocal(branch)
self.substate = {}
if isinstance(filectxfn, patch.filestore):
filectxfn = memfilefrompatch(filectxfn)
@ -2756,7 +2676,7 @@ class memctx(committablectx):
self._filectxfn = makecachingfilectxfn(filectxfn)
if editor:
self._text = editor(self._repo, self, [])
self._text = editor(self._repo, self)
self._repo.savecommitmessage(self._text)
def filectx(self, path, filelog=None):
@ -3005,10 +2925,9 @@ class metadataonlyctx(committablectx):
)
self._files = originalctx.files()
self.substate = {}
if editor:
self._text = editor(self._repo, self, [])
self._text = editor(self._repo, self)
self._repo.savecommitmessage(self._text)
def manifestnode(self):

View File

@ -860,12 +860,11 @@ class dirstate(object):
visited.add(i)
return (None, -1, "")
def _walkexplicit(self, match, subrepos):
def _walkexplicit(self, match):
"""Get stat data about the files explicitly specified by match.
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.
- results is a mapping from filename to stat result.
- 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."""
@ -904,21 +903,9 @@ class dirstate(object):
normalize = None
files = sorted(match.files())
subrepos.sort()
i, j = 0, 0
while i < len(files) and j < len(subrepos):
subpath = subrepos[j] + "/"
if files[i] < subpath:
i += 1
continue
while i < len(files) and files[i].startswith(subpath):
del files[i]
j += 1
if not files or "." in files:
files = ["."]
results = dict.fromkeys(subrepos)
results[".hg"] = None
results = {".hg": None}
for ff in files:
# constructing the foldmap is expensive, so don't do it for the
@ -989,7 +976,7 @@ class dirstate(object):
return results, dirsfound, dirsnotfound
@util.timefunction("dirstatewalk", 0, "_ui")
def walk(self, match, subrepos, unknown, ignored, full=True):
def walk(self, match, unknown, ignored, full=True):
"""
Walk recursively through the directory tree, finding all files
matched by match.
@ -1042,7 +1029,7 @@ class dirstate(object):
normalizefile = None
# step 1: find all explicit files
results, work, dirsnotfound = self._walkexplicit(match, subrepos)
results, work, dirsnotfound = self._walkexplicit(match)
skipstep3 = skipstep3 and not (work or dirsnotfound)
work = [d for d in work if not dirignore(d[0])]
@ -1100,8 +1087,6 @@ class dirstate(object):
alreadynormed = not normalize or nd == d
traverse([d], alreadynormed)
for s in subrepos:
del results[s]
del results[".hg"]
# step 3: visit remaining files from dmap
@ -1150,7 +1135,7 @@ class dirstate(object):
results[next(iv)] = st
return results
def status(self, match, subrepos, ignored, clean, unknown):
def status(self, match, ignored, clean, unknown):
"""Determine the status of the working copy relative to the
dirstate and return a pair of (unsure, status), where status is of type
scmutil.status and:
@ -1202,9 +1187,7 @@ class dirstate(object):
# - match.traversedir does something, because match.traversedir should
# be called for every dir in the working dir
full = listclean or match.traversedir is not None
for fn, st in self.walk(
match, subrepos, listunknown, listignored, full=full
).iteritems():
for fn, st in self.walk(match, listunknown, listignored, full=full).iteritems():
try:
t = dget(fn)
# This "?" state is only tracked by treestate, emulate the old

View File

@ -190,7 +190,6 @@ def _preimportmodules():
"sslutil",
"store",
"streamclone",
"subrepo",
"tags",
"templatefilters",
"templatekw",

View File

@ -19,8 +19,8 @@ from . import (
scmutil,
util,
)
from .i18n import _
from .EdenThriftClient import ScmFileStatus
from .i18n import _
from .node import nullid
@ -148,7 +148,7 @@ class eden_dirstate(dirstate.dirstate):
# directories
# - we potentially should just implement purge inside Eden
#
def walk(self, match, subrepos, unknown, ignored, full=True): # override
def walk(self, match, unknown, ignored, full=True): # override
"""
Walk recursively through the directory tree, finding all files
matched by match.
@ -292,7 +292,7 @@ class eden_dirstate(dirstate.dirstate):
return False
def status(self, match, subrepos, ignored, clean, unknown): # override
def status(self, match, ignored, clean, unknown): # override
edenstatus = self.eden_client.getStatus(self.p1(), list_ignored=ignored).entries
nonnormal_copy = self._map.create_clone_of_internal_map()

View File

@ -104,18 +104,6 @@ class eden_dirstate_map(dirstate.dirstatemap):
if entry is not None:
status, mode, merge_state = entry
return (status, mode, merge_state, DUMMY_MTIME)
# TODO: Support Hg submodules.
# Mercurial has a bit of logic that depends on whether .hgsub or
# .hgsubstate is in the dirstate. Currently, Eden does not attempt to
# support submodules (and none of Hg's codepaths that use submodules
# have been tested with Eden), so don't bother to go to the server when
# either .hgsub or .hgsubstate is passed in.
#
# Because we know the Thrift call will fail, we throw the corresponding
# KeyError in this case to avoid the overhead of the Thrift call as a
# performance optimization.
if filename == ".hgsub" or filename == ".hgsubstate":
raise KeyError(filename)
try:
# TODO: Consider fetching this from the commit context rather than

View File

@ -559,24 +559,6 @@ def _pushdiscoveryphase(pushop):
outgoing = pushop.outgoing
unfi = pushop.repo.unfiltered()
remotephases = pushop.remote.listkeys("phases")
if (
pushop.ui.configbool("ui", "_usedassubrepo")
and remotephases # server supports phases
and not pushop.outgoing.missing # no changesets to be pushed
and remotephases.get("publishing", False)
):
# When:
# - this is a subrepo push
# - and remote support phase
# - and no changeset are to be pushed
# - and remote is publishing
# We may be in issue 3781 case!
# We drop the possible phase synchronisation done by
# courtesy to publish changesets possibly locally draft
# on the remote.
pushop.outdatedphases = []
pushop.fallbackoutdatedphases = []
return
pushop.remotephases = phases.remotephasessummary(
pushop.repo, pushop.fallbackheads, remotephases
@ -1121,22 +1103,6 @@ def _pushsyncphase(pushop):
cheads = pushop.commonheads
# even when we don't push, exchanging phase data is useful
remotephases = pushop.remote.listkeys("phases")
if (
pushop.ui.configbool("ui", "_usedassubrepo")
and remotephases # server supports phases
and pushop.cgresult is None # nothing was pushed
and remotephases.get("publishing", False)
):
# When:
# - this is a subrepo push
# - and remote support phase
# - and no changeset was pushed
# - and remote is publishing
# We may be in issue 3871 case!
# We drop the possible phase synchronisation done by
# courtesy to publish changesets possibly locally draft
# on the remote.
remotephases = {"publishing": "True"}
if not remotephases: # old server or public only reply from non-publishing
_localphasemove(pushop, cheads)
# don't push any phase data as there is nothing to push

View File

@ -520,33 +520,6 @@ def status(mctx, x):
return getset(mctx.switch(ctx, _buildstatus(ctx, x, basectx=basectx)), x)
@predicate("subrepo([pattern])")
def subrepo(mctx, x):
"""Subrepositories whose paths match the given pattern.
"""
# i18n: "subrepo" is a keyword
getargs(x, 0, 1, _("subrepo takes at most one argument"))
ctx = mctx.ctx
sstate = sorted(ctx.substate)
if x:
# i18n: "subrepo" is a keyword
pat = getstring(x, _("subrepo requires a pattern or no arguments"))
from . import match as matchmod # avoid circular import issues
fast = not matchmod.patkind(pat)
if fast:
def m(s):
return s == pat
else:
m = matchmod.match(ctx.repo().root, "", [pat], ctx=ctx)
return [sub for sub in sstate if m(sub)]
else:
return [sub for sub in sstate]
methods = {
"string": stringset,
"symbol": stringset,

View File

@ -274,7 +274,6 @@ helptable = sorted(
),
(["urls"], _("URL Paths"), loaddoc("urls")),
(["extensions"], _("Using Additional Features"), extshelp),
(["subrepos", "subrepo"], _("Subrepositories"), loaddoc("subrepos")),
(["hgweb"], _("Configuring hgweb"), loaddoc("hgweb")),
(["glossary"], _("Common Terms"), loaddoc("glossary")),
(

View File

@ -484,8 +484,7 @@ one shown by default::
HG: user: {author}\n{ifeq(p2rev, "-1", "",
"HG: branch merge\n")
}HG: branch '{branch}'\n{if(activebookmark,
"HG: bookmark '{activebookmark}'\n") }{subrepos %
"HG: subrepo {subrepo}\n" }{file_adds %
"HG: bookmark '{activebookmark}'\n") }{file_adds %
"HG: added {file}\n" }{file_mods %
"HG: changed {file}\n" }{file_dels %
"HG: removed {file}\n" }{if(files, "",
@ -1623,17 +1622,6 @@ information about working with phases.
Phase of newly-created commits.
(default: draft)
``checksubrepos``
Check the phase of the current revision of each subrepository. Allowed
values are "ignore", "follow" and "abort". For settings other than
"ignore", the phase of the current revision of each subrepository is
checked before committing the parent repository. If any of those phases is
greater than the phase of the parent repository (e.g. if a subrepo is in a
"secret" phase while the parent repo is in "draft" phase), the commit is
either aborted (if checksubrepos is set to "abort") or the higher phase is
used for the parent repository commit (if set to "follow").
(default: follow)
``profiling``
-------------
@ -1996,70 +1984,6 @@ Configuration for extensions that need to send email messages.
itself to the MTA.
``subpaths``
------------
Subrepository source URLs can go stale if a remote server changes name
or becomes temporarily unavailable. This section lets you define
rewrite rules of the form::
<pattern> = <replacement>
where ``pattern`` is a regular expression matching a subrepository
source URL and ``replacement`` is the replacement string used to
rewrite it. Groups can be matched in ``pattern`` and referenced in
``replacements``. For instance::
http://server/(.*)-hg/ = http://hg.server/\1/
rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
Relative subrepository paths are first made absolute, and the
rewrite rules are then applied on the full (absolute) path. If ``pattern``
doesn't match the full path, an attempt is made to apply it on the
relative path alone. The rules are applied in definition order.
``subrepos``
------------
This section contains options that control the behavior of the
subrepositories feature. See also :hg:`help subrepos`.
Security note: auditing in Mercurial is known to be insufficient to
prevent clone-time code execution with carefully constructed Git
subrepos. It is unknown if a similar detect is present in Subversion
subrepos. Both Git and Subversion subrepos are disabled by default
out of security concerns. These subrepo types can be enabled using
the respective options below.
``allowed``
Whether subrepositories are allowed in the working directory.
When false, commands involving subrepositories (like :hg:`update`)
will fail for all subrepository types.
(default: true)
``hg:allowed``
Whether Mercurial subrepositories are allowed in the working
directory. This option only has an effect if ``subrepos.allowed``
is true.
(default: true)
``git:allowed``
Whether Git subrepositories are allowed in the working directory.
This option only has an effect if ``subrepos.allowed`` is true.
See the security note above before enabling Git subrepos.
(default: false)
``svn:allowed``
Whether Subversion subrepositories are allowed in the working
directory. This option only has an effect if ``subrepos.allowed``
is true.
See the security note above before enabling Subversion subrepos.
(default: false)
``templatealias``
-----------------
@ -2165,12 +2089,6 @@ User interface controls.
"debug", or "always". (default: "yes"). "yes" will use color whenever it
seems possible. See :hg:`help color` for details.
``commitsubrepos``
Whether to commit modified subrepositories when committing the
parent repository. If False and one subrepository has uncommitted
changes, abort the commit.
(default: False)
``debug``
Print debugging information. (default: False)
@ -2496,10 +2414,6 @@ The full set of options is:
revisions. This feature creates temporary files.
(default: False)
``archivesubrepos``
Whether to recurse into subrepositories when archiving.
(default: False)
``baseurl``
Base URL to use when publishing URLs in other locations, so
third-party tools like email notification hooks can construct

View File

@ -62,15 +62,6 @@ Files
describe file names that should be ignored by **hg**. For details,
see |hgignore(5)|_.
``.hgsub``
This file defines the locations of all subrepositories, and
tells where the subrepository checkouts came from. For details, see
:hg:`help subrepos`.
``.hgsubstate``
This file is where Mercurial stores all nested repository states. *NB: This
file should not be edited manually.*
``.hgtags``
This file contains changeset hash values and text tag names (one
of each separated by spaces) that correspond to tagged versions of

View File

@ -1,169 +0,0 @@
Subrepositories let you nest external repositories or projects into a
parent Mercurial repository, and make commands operate on them as a
group.
Mercurial currently supports Mercurial, Git, and Subversion
subrepositories.
Subrepositories are made of three components:
1. Nested repository checkouts. They can appear anywhere in the
parent working directory.
2. Nested repository references. They are defined in ``.hgsub``, which
should be placed in the root of working directory, and
tell where the subrepository checkouts come from. Mercurial
subrepositories are referenced like::
path/to/nested = https://example.com/nested/repo/path
Git and Subversion subrepos are also supported::
path/to/nested = [git]git://example.com/nested/repo/path
path/to/nested = [svn]https://example.com/nested/trunk/path
where ``path/to/nested`` is the checkout location relatively to the
parent Mercurial root, and ``https://example.com/nested/repo/path``
is the source repository path. The source can also reference a
filesystem path.
Note that ``.hgsub`` does not exist by default in Mercurial
repositories, you have to create and add it to the parent
repository before using subrepositories.
3. Nested repository states. They are defined in ``.hgsubstate``, which
is placed in the root of working directory, and
capture whatever information is required to restore the
subrepositories to the state they were committed in a parent
repository changeset. Mercurial automatically record the nested
repositories states when committing in the parent repository.
.. note::
The ``.hgsubstate`` file should not be edited manually.
Adding a Subrepository
======================
If ``.hgsub`` does not exist, create it and add it to the parent
repository. Clone or checkout the external projects where you want it
to live in the parent repository. Edit ``.hgsub`` and add the
subrepository entry as described above. At this point, the
subrepository is tracked and the next commit will record its state in
``.hgsubstate`` and bind it to the committed changeset.
Synchronizing a Subrepository
=============================
Subrepos do not automatically track the latest changeset of their
sources. Instead, they are updated to the changeset that corresponds
with the changeset checked out in the top-level changeset. This is so
developers always get a consistent set of compatible code and
libraries when they update.
Thus, updating subrepos is a manual process. Simply check out target
subrepo at the desired revision, test in the top-level repo, then
commit in the parent repository to record the new combination.
Deleting a Subrepository
========================
To remove a subrepository from the parent repository, delete its
reference from ``.hgsub``, then remove its files.
Interaction with Mercurial Commands
===================================
:add: add does not recurse in subrepos unless -S/--subrepos is
specified. However, if you specify the full path of a file in a
subrepo, it will be added even without -S/--subrepos specified.
Subversion subrepositories are currently silently
ignored.
:addremove: addremove does not recurse into subrepos unless
-S/--subrepos is specified. However, if you specify the full
path of a directory in a subrepo, addremove will be performed on
it even without -S/--subrepos being specified. Git and
Subversion subrepositories will print a warning and continue.
:archive: archive does not recurse in subrepositories unless
-S/--subrepos is specified.
:cat: Git subrepositories only support exact file matches.
Subversion subrepositories are currently ignored.
:commit: commit creates a consistent snapshot of the state of the
entire project and its subrepositories. If any subrepositories
have been modified, Mercurial will abort. Mercurial can be made
to instead commit all modified subrepositories by specifying
-S/--subrepos, or setting "ui.commitsubrepos=True" in a
configuration file (see :hg:`help config`). After there are no
longer any modified subrepositories, it records their state and
finally commits it in the parent repository. The --addremove
option also honors the -S/--subrepos option. However, Git and
Subversion subrepositories will print a warning and abort.
:diff: diff does not recurse in subrepos unless -S/--subrepos is
specified. Changes are displayed as usual, on the subrepositories
elements. Subversion subrepositories are currently silently ignored.
:files: files does not recurse into subrepos unless -S/--subrepos is
specified. However, if you specify the full path of a file or
directory in a subrepo, it will be displayed even without
-S/--subrepos being specified. Git and Subversion subrepositories
are currently silently ignored.
:forget: forget currently only handles exact file matches in subrepos.
Git and Subversion subrepositories are currently silently ignored.
:incoming: incoming does not recurse in subrepos unless -S/--subrepos
is specified. Git and Subversion subrepositories are currently
silently ignored.
:outgoing: outgoing does not recurse in subrepos unless -S/--subrepos
is specified. Git and Subversion subrepositories are currently
silently ignored.
:pull: pull is not recursive since it is not clear what to pull prior
to running :hg:`update`. Listing and retrieving all
subrepositories changes referenced by the parent repository pulled
changesets is expensive at best, impossible in the Subversion
case.
:push: Mercurial will automatically push all subrepositories first
when the parent repository is being pushed. This ensures new
subrepository changes are available when referenced by top-level
repositories. Push is a no-op for Subversion subrepositories.
:serve: serve does not recurse into subrepositories unless
-S/--subrepos is specified. Git and Subversion subrepositories
are currently silently ignored.
:status: status does not recurse into subrepositories unless
-S/--subrepos is specified. Subrepository changes are displayed as
regular Mercurial changes on the subrepository
elements. Subversion subrepositories are currently silently
ignored.
:remove: remove does not recurse into subrepositories unless
-S/--subrepos is specified. However, if you specify a file or
directory path in a subrepo, it will be removed even without
-S/--subrepos. Git and Subversion subrepositories are currently
silently ignored.
:update: update restores the subrepos in the state they were
originally committed in target changeset. If the recorded
changeset is not available in the current subrepository, Mercurial
will pull it in first before updating. This means that updating
can require network access when using subrepositories.
Remapping Subrepositories Sources
=================================
A subrepository source location may change during a project life,
invalidating references stored in the parent repository history. To
fix this, rewriting rules can be defined in parent repository ``hgrc``
file or in Mercurial configuration. See the ``[subpaths]`` section in
hgrc(5) for more details.

View File

@ -306,13 +306,6 @@ def unshare(ui, repo):
repo.unfiltered().invalidatedirstate()
repo.unfiltered().__init__(repo.baseui, repo.root)
# TODO: figure out how to access subrepos that exist, but were previously
# removed from .hgsub
c = repo["."]
subs = c.substate
for s in sorted(subs):
c.sub(s).unshare()
def postshare(sourcerepo, destrepo, bookmarks=True, defaultpath=None):
"""Called after a new shared repo is created.
@ -950,7 +943,7 @@ def merge(repo, node, force=None, remind=True, mergeforce=False, labels=None):
return stats[3] > 0
def _incoming(displaychlist, subreporecurse, ui, repo, source, opts, buffered=False):
def _incoming(displaychlist, ui, repo, source, opts, buffered=False):
"""
Helper for incoming / gincoming.
displaychlist gets called with
@ -970,27 +963,17 @@ def _incoming(displaychlist, subreporecurse, ui, repo, source, opts, buffered=Fa
try:
if not chlist:
ui.status(_("no changes found\n"))
return subreporecurse()
return
ui.pager("incoming")
displayer = cmdutil.show_changeset(ui, other, opts, buffered)
displaychlist(other, chlist, displayer)
displayer.close()
finally:
cleanupfn()
subreporecurse()
return 0 # exit code is zero since we found incoming changes
def incoming(ui, repo, source, opts):
def subreporecurse():
ret = 1
if opts.get("subrepos"):
ctx = repo[None]
for subpath in sorted(ctx.substate):
sub = ctx.sub(subpath)
ret = min(ret, sub.incoming(ui, source, opts))
return ret
def display(other, chlist, displayer):
limit = cmdutil.loglimit(opts)
if opts.get("newest_first"):
@ -1005,7 +988,7 @@ def incoming(ui, repo, source, opts):
count += 1
displayer.show(other[n])
return _incoming(display, subreporecurse, ui, repo, source, opts)
return _incoming(display, ui, repo, source, opts)
def _outgoing(ui, repo, dest, opts):
@ -1034,11 +1017,6 @@ def _outgoing(ui, repo, dest, opts):
def outgoing(ui, repo, dest, opts):
def recurse():
ret = 1
if opts.get("subrepos"):
ctx = repo[None]
for subpath in sorted(ctx.substate):
sub = ctx.sub(subpath)
ret = min(ret, sub.outgoing(ui, dest, opts))
return ret
limit = cmdutil.loglimit(opts)
@ -1074,32 +1052,6 @@ def verify(repo, revs=None):
"""
ret = verifymod.verify(repo, revs)
# Broken subrepo references in hidden csets don't seem worth worrying about,
# since they can't be pushed/pulled, and --hidden can be used if they are a
# concern.
if not repo.ui.configbool("verify", "skipmanifests"):
# pathto() is needed for -R case
revs = repo.revs(
"filelog(%s)", util.pathto(repo.root, repo.getcwd(), ".hgsubstate")
)
if revs:
repo.ui.status(_("checking subrepo links\n"))
for rev in revs:
ctx = repo[rev]
try:
for subpath in ctx.substate:
try:
ret = ctx.sub(subpath, allowcreate=False).verify() or ret
except error.RepoError as e:
repo.ui.warn(("%s: %s\n") % (rev, e))
except Exception:
repo.ui.warn(
_(".hgsubstate is corrupt in revision %s\n")
% node.short(ctx.node())
)
return ret

View File

@ -1242,15 +1242,7 @@ def archive(web, req, tmpl):
req.headers.extend(headers)
req.respond(HTTP_OK, mimetype)
archival.archive(
web.repo,
req,
cnode,
artype,
prefix=name,
matchfn=match,
subrepos=web.configbool("web", "archivesubrepos"),
)
archival.archive(web.repo, req, cnode, artype, prefix=name, matchfn=match)
return []

View File

@ -53,7 +53,6 @@ from . import (
revsetlang,
scmutil,
store,
subrepo,
tags as tagsmod,
transaction,
treestate,
@ -417,13 +416,11 @@ class localrepository(object):
self.path = self.wvfs.join(".hg")
self.origroot = path
# This is only used by context.workingctx.match in order to
# detect files in subrepos.
self.auditor = pathutil.pathauditor(self.root, callback=self._checknested)
# detect files in forbidden paths.
self.auditor = pathutil.pathauditor(self.root)
# This is only used by context.basectx.match in order to detect
# files in subrepos.
self.nofsauditor = pathutil.pathauditor(
self.root, callback=self._checknested, realfs=False, cached=True
)
# files in forbidden paths..
self.nofsauditor = pathutil.pathauditor(self.root, realfs=False, cached=True)
self.baseui = baseui
self.ui = baseui.copy()
self.ui.copy = baseui.copy # prevent copying repo configuration
@ -738,44 +735,6 @@ class localrepository(object):
if "store" in self.requirements:
scmutil.writerequires(self.svfs, self.storerequirements)
def _checknested(self, path):
"""Determine if path is a legal nested repository."""
if not path.startswith(self.root):
return False
subpath = path[len(self.root) + 1 :]
normsubpath = util.pconvert(subpath)
# XXX: Checking against the current working copy is wrong in
# the sense that it can reject things like
#
# $ hg cat -r 10 sub/x.txt
#
# if sub/ is no longer a subrepository in the working copy
# parent revision.
#
# However, it can of course also allow things that would have
# been rejected before, such as the above cat command if sub/
# is a subrepository now, but was a normal directory before.
# The old path auditor would have rejected by mistake since it
# panics when it sees sub/.hg/.
#
# All in all, checking against the working copy seems sensible
# since we want to prevent access to nested repositories on
# the filesystem *now*.
ctx = self[None]
parts = util.splitpath(subpath)
while parts:
prefix = "/".join(parts)
if prefix in ctx.substate:
if prefix == normsubpath:
return True
else:
sub = ctx.sub(prefix)
return sub.checknested(subpath[len(prefix) + 1 :])
else:
parts.pop()
return False
def peer(self):
return localpeer(self) # not cached to avoid reference cycle
@ -2137,7 +2096,7 @@ class localrepository(object):
for f in match.files():
f = self.dirstate.normalize(f)
if f == "." or f in matched or f in wctx.substate:
if f == "." or f in matched:
continue
if f in status.deleted:
fail(f, _("file not found!"))
@ -2202,11 +2161,6 @@ class localrepository(object):
if force:
status.modified.extend(status.clean) # mq may commit clean files
# check subrepos
subs, commitsubs, newstate = subrepo.precommit(
self.ui, wctx, status, match, force=force
)
# make sure all explicit patterns are matched
if not force:
self.checkcommitpatterns(wctx, vdirs, match, status, fail)
@ -2231,7 +2185,7 @@ class localrepository(object):
mergeutil.checkunresolved(ms)
if editor:
cctx._text = editor(self, cctx, subs)
cctx._text = editor(self, cctx)
edited = text != cctx._text
# Save commit message in case this transaction gets rolled back
@ -2239,17 +2193,6 @@ class localrepository(object):
# the assumption that the user will use the same editor again.
msgfn = self.savecommitmessage(cctx._text)
# commit subs and write new state
if subs:
for s in sorted(commitsubs):
sub = wctx.sub(s)
self.ui.status(
_("committing subrepository %s\n") % subrepo.subrelpath(sub)
)
sr = sub.commit(cctx._text, user, date)
newstate[s] = (newstate[s][0], sr)
subrepo.writestate(self, newstate)
p1, p2 = self.dirstate.parents()
hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or "")
try:
@ -2362,7 +2305,7 @@ class localrepository(object):
xp1, xp2 = p1.hex(), p2 and p2.hex() or ""
self.hook("pretxncommit", throw=True, node=hex(n), parent1=xp1, parent2=xp2)
# set the new commit is proper phase
targetphase = subrepo.newcommitphase(self.ui, ctx)
targetphase = phases.newcommitphase(self.ui)
if targetphase:
# retract boundary do not alter parent changeset.
# if a parent have higher the resulting phase will
@ -2449,10 +2392,9 @@ class localrepository(object):
ignored=False,
clean=False,
unknown=False,
listsubrepos=False,
):
"""a convenience method that calls node1.status(node2)"""
return self[node1].status(node2, match, ignored, clean, unknown, listsubrepos)
return self[node1].status(node2, match, ignored, clean, unknown)
def addpostdsstatus(self, ps, afterdirstatewrite=True):
"""Add a callback to run within the wlock, at the point at which status

View File

@ -46,7 +46,7 @@ def _rematcher(regex):
return m.match
def _expandsets(kindpats, ctx, listsubrepos):
def _expandsets(kindpats, ctx):
"""Returns the kindpats list with the 'set' patterns expanded."""
fset = set()
other = []
@ -57,12 +57,6 @@ def _expandsets(kindpats, ctx, listsubrepos):
raise error.ProgrammingError("fileset expression with no " "context")
s = ctx.getfileset(pat)
fset.update(s)
if listsubrepos:
for subpath in ctx.substate:
s = ctx.sub(subpath).getfileset(pat)
fset.update(subpath + "/" + f for f in s)
continue
other.append((kind, pat, source))
return fset, other
@ -113,7 +107,6 @@ def match(
exact=False,
auditor=None,
ctx=None,
listsubrepos=False,
warn=None,
badfn=None,
icasefs=False,
@ -180,9 +173,7 @@ def match(
if _kindpatsalwaysmatch(kindpats):
m = alwaysmatcher(root, cwd, badfn, relativeuipath=True)
else:
m = patternmatcher(
root, cwd, kindpats, ctx=ctx, listsubrepos=listsubrepos, badfn=badfn
)
m = patternmatcher(root, cwd, kindpats, ctx=ctx, badfn=badfn)
else:
# It's a little strange that no patterns means to match everything.
# Consider changing this to match nothing (probably using nevermatcher).
@ -190,15 +181,11 @@ def match(
if include:
kindpats = normalize(include, "glob", root, cwd, auditor, warn)
im = includematcher(
root, cwd, kindpats, ctx=ctx, listsubrepos=listsubrepos, badfn=None
)
im = includematcher(root, cwd, kindpats, ctx=ctx, badfn=None)
m = intersectmatchers(m, im)
if exclude:
kindpats = normalize(exclude, "glob", root, cwd, auditor, warn)
em = includematcher(
root, cwd, kindpats, ctx=ctx, listsubrepos=listsubrepos, badfn=None
)
em = includematcher(root, cwd, kindpats, ctx=ctx, badfn=None)
m = differencematcher(m, em)
return m
@ -763,12 +750,12 @@ class gitignorematcher(basematcher):
class patternmatcher(basematcher):
def __init__(self, root, cwd, kindpats, ctx=None, listsubrepos=False, badfn=None):
def __init__(self, root, cwd, kindpats, ctx=None, badfn=None):
super(patternmatcher, self).__init__(root, cwd, badfn)
self._files = _explicitfiles(kindpats)
self._prefix = _prefix(kindpats)
self._pats, self.matchfn = _buildmatch(ctx, kindpats, "$", listsubrepos, root)
self._pats, self.matchfn = _buildmatch(ctx, kindpats, "$", root)
@propertycache
def _dirs(self):
@ -792,12 +779,10 @@ class patternmatcher(basematcher):
class includematcher(basematcher):
def __init__(self, root, cwd, kindpats, ctx=None, listsubrepos=False, badfn=None):
def __init__(self, root, cwd, kindpats, ctx=None, badfn=None):
super(includematcher, self).__init__(root, cwd, badfn)
self._pats, self.matchfn = _buildmatch(
ctx, kindpats, "(?:/|$)", listsubrepos, root
)
self._pats, self.matchfn = _buildmatch(ctx, kindpats, "(?:/|$)", root)
# prefix is True if all patterns are recursive, so certain fast paths
# can be enabled. Unfortunately, it's too easy to break it (ex. by
# using "glob:*.c", "re:...", etc).
@ -1250,7 +1235,7 @@ def _regex(kind, pat, globsuffix):
return _globre(pat) + globsuffix
def _buildmatch(ctx, kindpats, globsuffix, listsubrepos, root):
def _buildmatch(ctx, kindpats, globsuffix, root):
"""Return regexp string and a matcher function for kindpats.
globsuffix is appended to the regexp of globs."""
matchfuncs = []
@ -1273,7 +1258,7 @@ def _buildmatch(ctx, kindpats, globsuffix, listsubrepos, root):
matchfuncs.append(matchsubinclude)
fset, kindpats = _expandsets(kindpats, ctx, listsubrepos)
fset, kindpats = _expandsets(kindpats, ctx)
if fset:
matchfuncs.append(fset.__contains__)

View File

@ -25,7 +25,6 @@ from . import (
progress,
pycompat,
scmutil,
subrepo,
util,
worker,
)
@ -1111,11 +1110,6 @@ def manifestmerge(
copied = set(copy.values())
copied.update(movewithdir.values())
if ".hgsubstate" in m1:
# check whether sub state is modified
if any(wctx.sub(s).dirty() for s in wctx.substate):
m1[".hgsubstate"] = modifiednodeid
# Don't use m2-vs-ma optimization if:
# - ma is the same as m1 or m2, which we're just going to diff again later
# - The caller specifically asks for a full diff, which is useful during bid
@ -1548,8 +1542,6 @@ def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None, ancestors=No
mergeactions.extend(actions["m"])
for f, args, msg in mergeactions:
f1, f2, fa, move, anc = args
if f == ".hgsubstate": # merged internally
continue
if f1 is None:
fcl = filemerge.absentfilectx(wctx, fa)
else:
@ -1579,9 +1571,6 @@ def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None, ancestors=No
numupdates = sum(len(l) for m, l in actions.items() if m != "k")
z = 0
if [a for a in actions["r"] if a[0] == ".hgsubstate"]:
subrepo.submerge(repo, wctx, mctx, wctx, overwrite, labels)
# record path conflicts
with progress.bar(
repo.ui, _("updating"), _("files"), numupdates
@ -1640,9 +1629,6 @@ def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None, ancestors=No
prog.value = (z, item)
updated = len(actions["g"])
if [a for a in actions["g"] if a[0] == ".hgsubstate"]:
subrepo.submerge(repo, wctx, mctx, wctx, overwrite, labels)
# forget (manifest only, just log it) (must come first)
for f, args, msg in actions["f"]:
repo.ui.debug(" %s: %s -> f\n" % (f, msg))
@ -1755,11 +1741,6 @@ def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None, ancestors=No
repo.ui.debug(" %s: %s -> m (premerge)\n" % (f, msg))
z += 1
prog.value = (z, f)
if f == ".hgsubstate": # subrepo states need updating
subrepo.submerge(
repo, wctx, mctx, wctx.ancestor(mctx), overwrite, labels
)
continue
wctx[f].audit()
complete, r = ms.preresolve(f, wctx)
if not complete:
@ -2048,9 +2029,7 @@ def update(
# at all, and can use the vanilla merge logic in this case.
why_not_eden = "merge is in-memory"
else:
# TODO: We probably also need to set why_not_eden if there are
# subrepositories. (Personally I might vote for just not supporting
# subrepos in eden.)
# TODO: Figure out what's the other cases here.
why_not_eden = None
if why_not_eden:
@ -2134,9 +2113,6 @@ def update(
raise error.Abort(
_("uncommitted changes"), hint=_("use 'hg status' to list changes")
)
if not wc.isinmemory():
for s in sorted(wc.substate):
wc.sub(s).bailifchanged()
elif not overwrite:
if p1 == p2: # no-op update
@ -2212,48 +2188,6 @@ def update(
)
raise error.Abort(msg.strip(), hint=hint)
# Prompt and create actions. Most of this is in the resolve phase
# already, but we can't handle .hgsubstate in filemerge or
# subrepo.submerge yet so we have to keep prompting for it.
if ".hgsubstate" in actionbyfile:
f = ".hgsubstate"
m, args, msg = actionbyfile[f]
prompts = filemerge.partextras(labels)
prompts["f"] = f
if m == "cd":
if repo.ui.promptchoice(
_(
"local%(l)s changed %(f)s which other%(o)s deleted\n"
"use (c)hanged version or (d)elete?"
"$$ &Changed $$ &Delete"
)
% prompts,
0,
):
actionbyfile[f] = ("r", None, "prompt delete")
elif f in p1:
actionbyfile[f] = ("am", None, "prompt keep")
else:
actionbyfile[f] = ("a", None, "prompt keep")
elif m == "dc":
f1, f2, fa, move, anc = args
flags = p2[f2].flags()
if (
repo.ui.promptchoice(
_(
"other%(o)s changed %(f)s which local%(l)s deleted\n"
"use (c)hanged version or leave (d)eleted?"
"$$ &Changed $$ &Deleted"
)
% prompts,
0,
)
== 0
):
actionbyfile[f] = ("g", (flags, False), "prompt recreating")
else:
del actionbyfile[f]
# Convert to dictionary-of-lists format
actions = dict((m, []) for m in "a am f g cd dc r dm dg m e k p pr".split())
for f, (m, args, msg) in actionbyfile.iteritems():

View File

@ -1856,8 +1856,7 @@ def matching(repo, subset, x):
Valid fields are most regular revision fields and some special fields.
Regular revision fields are ``description``, ``author``, ``branch``,
``date``, ``files``, ``phase``, ``parents``, ``substate``, ``user``
and ``diff``.
``date``, ``files``, ``phase``, ``parents``, ``user`` and ``diff``.
Note that ``author`` and ``user`` are synonyms. ``diff`` refers to the
contents of the revision. Two revisions matching their ``diff`` will
also match their ``files``.
@ -1916,7 +1915,6 @@ def matching(repo, subset, x):
"summary",
"files",
"description",
"substate",
"diff",
]
@ -1941,7 +1939,6 @@ def matching(repo, subset, x):
"files": lambda r: repo[r].files(),
"parents": lambda r: repo[r].parents(),
"phase": lambda r: repo[r].phase(),
"substate": lambda r: repo[r].substate,
"summary": lambda r: repo[r].description().splitlines()[0],
"diff": lambda r: list(repo[r].diff(git=True)),
}
@ -2094,51 +2091,6 @@ def sort(repo, subset, x, order):
return baseset([c.rev() for c in ctxs])
@predicate("subrepo([pattern])", weight=10)
def subrepo(repo, subset, x):
"""Changesets that add, modify or remove the given subrepo. If no subrepo
pattern is named, any subrepo changes are returned.
"""
# i18n: "subrepo" is a keyword
args = getargs(x, 0, 1, _("subrepo takes at most one argument"))
pat = None
if len(args) != 0:
pat = getstring(args[0], _("subrepo requires a pattern"))
m = matchmod.exact(repo.root, repo.root, [".hgsubstate"])
def submatches(names):
k, p, m = util.stringmatcher(pat)
for name in names:
if m(name):
yield name
def matches(x):
c = repo[x]
s = repo.status(c.p1().node(), c.node(), match=m)
if pat is None:
return s.added or s.modified or s.removed
if s.added:
return any(submatches(c.substate.keys()))
if s.modified:
subs = set(c.p1().substate.keys())
subs.update(c.substate.keys())
for path in submatches(subs):
if c.p1().substate.get(path) != c.substate.get(path):
return True
if s.removed:
return any(submatches(c.p1().substate.keys()))
return False
return subset.filter(matches, condrepr=("<subrepo %r>", pat))
def _mapbynodefunc(repo, s, f):
"""(repo, smartset, [node] -> [node]) -> smartset

View File

@ -105,32 +105,6 @@ class status(tuple):
) % self
def itersubrepos(ctx1, ctx2):
"""find subrepos in ctx1 or ctx2"""
# Create a (subpath, ctx) mapping where we prefer subpaths from
# ctx1. The subpaths from ctx2 are important when the .hgsub file
# has been modified (in ctx2) but not yet committed (in ctx1).
subpaths = dict.fromkeys(ctx2.substate, ctx2)
subpaths.update(dict.fromkeys(ctx1.substate, ctx1))
missing = set()
for subpath in ctx2.substate:
if subpath not in ctx1.substate:
del subpaths[subpath]
missing.add(subpath)
for subpath, ctx in sorted(subpaths.iteritems()):
yield subpath, ctx.sub(subpath)
# Yield an empty subrepo based on ctx1 for anything only in ctx2. That way,
# status and diff will have an accurate result when it does
# 'sub.{status|diff}(rev2)'. Otherwise, the ctx2 subrepo is compared
# against itself.
for subpath in missing:
yield subpath, ctx2.nullsub(subpath, ctx1)
def nochangesfound(ui, repo, excluded=None):
"""Report no changes for push/pull, excluded is None or a list of
nodes excluded from the push/pull.
@ -599,14 +573,7 @@ def matchandpats(ctx, pats=(), opts=None, globbed=False, default="relpath", badf
if badfn is None:
badfn = bad
m = ctx.match(
pats,
opts.get("include"),
opts.get("exclude"),
default,
listsubrepos=opts.get("subrepos"),
badfn=badfn,
)
m = ctx.match(pats, opts.get("include"), opts.get("exclude"), default, badfn=badfn)
if m.always():
pats = []
@ -830,20 +797,6 @@ def addremove(repo, matcher, prefix, opts=None, dry_run=None, similarity=None):
similarity = float(opts.get("similarity") or 0)
ret = 0
join = lambda f: os.path.join(prefix, f)
wctx = repo[None]
for subpath in sorted(wctx.substate):
submatch = matchmod.subdirmatcher(subpath, m)
if opts.get("subrepos") or m.exact(subpath) or any(submatch.files()):
sub = wctx.sub(subpath)
try:
if sub.addremove(submatch, prefix, opts, dry_run, similarity):
ret = 1
except error.LookupError:
repo.ui.status(
_("skipping missing subrepository: %s\n") % join(subpath)
)
rejected = []
@ -915,11 +868,8 @@ def _interestingfiles(repo, matcher):
added, unknown, deleted, removed, forgotten = [], [], [], [], []
audit_path = pathutil.pathauditor(repo.root, cached=True)
ctx = repo[None]
dirstate = repo.dirstate
walkresults = dirstate.walk(
matcher, subrepos=sorted(ctx.substate), unknown=True, ignored=False, full=False
)
walkresults = dirstate.walk(matcher, unknown=True, ignored=False, full=False)
for abs, st in walkresults.iteritems():
dstate = dirstate[abs]
if dstate == "?" and audit_path.check(abs):

View File

@ -145,22 +145,11 @@ def _createhgwebservice(ui, repo, opts):
baseui = ui
webconf = opts.get("web_conf") or opts.get("webdir_conf")
if webconf:
if opts.get("subrepos"):
raise error.Abort(_("--web-conf cannot be used with --subrepos"))
# load server settings (e.g. web.port) to "copied" ui, which allows
# hgwebdir to reload webconf cleanly
servui = ui.copy()
servui.readconfig(webconf, sections=["web"])
alluis.add(servui)
elif opts.get("subrepos"):
servui = ui
# If repo is None, hgweb.createapp() already raises a proper abort
# message as long as webconf is None.
if repo:
webconf = dict()
cmdutil.addwebdirpath(repo, "", webconf)
else:
servui = ui

File diff suppressed because it is too large Load Diff

View File

@ -1081,25 +1081,6 @@ def showrevslist(name, revs, **args):
)
@templatekeyword("subrepos")
def showsubrepos(**args):
"""List of strings. Updated subrepositories in the changeset."""
args = pycompat.byteskwargs(args)
ctx = args["ctx"]
substate = ctx.substate
if not substate:
return showlist("subrepo", [], args)
psubstate = ctx.parents()[0].substate or {}
subrepos = []
for sub in substate:
if sub not in psubstate or substate[sub] != psubstate[sub]:
subrepos.append(sub) # modified or newly added in ctx
for sub in psubstate:
if sub not in substate:
subrepos.append(sub) # removed in ctx
return showlist("subrepo", sorted(subrepos), args)
# don't remove "showtags" definition, even though namespaces will put
# a helper function for "tags" keyword into "keywords" map automatically,
# because online help text is built without namespaces initialization

View File

@ -1,154 +0,0 @@
#testcases obsstore-off obsstore-on
$ cat << EOF >> $HGRCPATH
> [extensions]
> amend =
> EOF
#if obsstore-on
$ setconfig experimental.evolution=createmarkers
#else
$ setconfig experimental.evolution=
#endif
Prepare parent repo
-------------------
$ hg init r
$ cd r
$ echo a > a
$ hg ci -Am0
adding a
Link first subrepo
------------------
$ echo 's = s' >> .hgsub
$ hg add .hgsub
$ hg init s
amend without .hgsub
$ hg amend s
abort: can't commit subrepos without .hgsub
[255]
amend with subrepo
$ hg amend
saved backup bundle to * (glob) (obsstore-off !)
$ hg status --change .
A .hgsub
A .hgsubstate
A a
$ cat .hgsubstate
0000000000000000000000000000000000000000 s
Update subrepo
--------------
add new commit to be amended
$ echo a >> a
$ hg ci -m1
amend with dirty subrepo
$ echo a >> s/a
$ hg add -R s
adding s/a
$ hg amend
abort: uncommitted changes in subrepository "s"
(use --subrepos for recursive commit)
[255]
amend with modified subrepo
$ hg ci -R s -m0
$ hg amend
saved backup bundle to * (glob) (obsstore-off !)
$ hg status --change .
M .hgsubstate
M a
$ cat .hgsubstate
f7b1eb17ad24730a1651fccd46c43826d1bbc2ac s
revert subrepo change
$ hg up -R s -q null
$ hg amend
saved backup bundle to * (glob) (obsstore-off !)
$ hg status --change .
M a
Link another subrepo
--------------------
add new commit to be amended
$ echo b >> b
$ hg ci -qAm2
also checks if non-subrepo change is included
$ echo a >> a
amend with another subrepo
$ hg init t
$ echo b >> t/b
$ hg ci -R t -Am0
adding b
$ echo 't = t' >> .hgsub
$ hg amend
saved backup bundle to * (glob) (obsstore-off !)
$ hg status --change .
M .hgsub
M .hgsubstate
M a
A b
$ cat .hgsubstate
0000000000000000000000000000000000000000 s
bfb1a4fb358498a9533dabf4f2043d94162f1fcd t
Unlink one subrepo
------------------
add new commit to be amended
$ echo a >> a
$ hg ci -m3
amend with one subrepo dropped
$ echo 't = t' > .hgsub
$ hg amend
saved backup bundle to * (glob) (obsstore-off !)
$ hg status --change .
M .hgsub
M .hgsubstate
M a
$ cat .hgsubstate
bfb1a4fb358498a9533dabf4f2043d94162f1fcd t
Unlink subrepos completely
--------------------------
add new commit to be amended
$ echo a >> a
$ hg ci -m3
amend with .hgsub removed
$ hg rm .hgsub
$ hg amend
saved backup bundle to * (glob) (obsstore-off !)
$ hg status --change .
M a
R .hgsub
R .hgsubstate
$ cd ..

View File

@ -12,86 +12,14 @@
$ echo bletch>baz/bletch
$ hg commit -Am 3 -d '1000000000 0'
adding baz/bletch
$ hg init subrepo
$ touch subrepo/sub
$ hg -q -R subrepo ci -Am "init subrepo"
$ echo "subrepo = subrepo" > .hgsub
$ hg add .hgsub
$ hg ci -m "add subrepo"
$ cat >> $HGRCPATH <<EOF
> [extensions]
> share =
> EOF
hg subrepos are shared when the parent repo is shared
$ cd ..
$ hg share test shared1
updating working directory
sharing subrepo subrepo from $TESTTMP/test/subrepo
5 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cat shared1/subrepo/.hg/sharedpath
$TESTTMP/test/subrepo/.hg (no-eol)
hg subrepos are shared into existence on demand if the parent was shared
$ hg clone -qr 1 test clone1
$ hg share clone1 share2
updating working directory
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg -R clone1 -q pull
$ hg -R share2 update tip
sharing subrepo subrepo from $TESTTMP/test/subrepo
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cat share2/subrepo/.hg/sharedpath
$TESTTMP/test/subrepo/.hg (no-eol)
$ echo 'mod' > share2/subrepo/sub
$ hg -R share2 ci -Sqm 'subrepo mod'
$ hg -R clone1 update -C tip
cloning subrepo subrepo from $TESTTMP/test/subrepo
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ find share2 | egrep 'sharedpath|00.+\.i' | sort
share2/.hg/sharedpath
share2/subrepo/.hg/sharedpath
$ hg -R share2 unshare
unsharing subrepo 'subrepo'
$ find share2 | egrep 'sharedpath|00.+\.i' | sort
share2/.hg/00changelog.i
share2/.hg/sharedpath.old
share2/.hg/store/00changelog.i
share2/.hg/store/00manifest.i
share2/subrepo/.hg/00changelog.i
share2/subrepo/.hg/sharedpath.old
share2/subrepo/.hg/store/00changelog.i
share2/subrepo/.hg/store/00manifest.i
$ hg -R share2/subrepo log -r tip -T compact
1[tip] 559dcc9bfa65 1970-01-01 00:00 +0000 test
subrepo mod
$ rm -rf clone1
$ hg clone -qr 1 test clone1
$ hg share clone1 shared3
updating working directory
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg -R clone1 -q pull
$ hg -R shared3 archive --config ui.archivemeta=False -r tip -S archive
sharing subrepo subrepo from $TESTTMP/test/subrepo
$ cat shared3/subrepo/.hg/sharedpath
$TESTTMP/test/subrepo/.hg (no-eol)
$ diff -r archive test
Only in test: .hg
Common subdirectories: archive/baz and test/baz (?)
Common subdirectories: archive/subrepo and test/subrepo (?)
Only in test/subrepo: .hg
[1]
$ rm -rf archive
$ cd test
$ echo "[web]" >> .hg/hgrc
$ echo "name = test-archive" >> .hg/hgrc
$ echo "archivesubrepos = True" >> .hg/hgrc
$ cp .hg/hgrc .hg/hgrc-base
> test_archtype() {
> echo "allow_archive = $1" >> .hg/hgrc
@ -209,39 +137,30 @@ invalid arch type should give 404
> sys.stderr.write(str(e) + '\n')
> EOF
$ $PYTHON getarchive.py "$TIP" gz | gunzip | tar tf - 2>/dev/null
test-archive-1701ef1f1510/.hg_archival.txt
test-archive-1701ef1f1510/.hgsub
test-archive-1701ef1f1510/.hgsubstate
test-archive-1701ef1f1510/bar
test-archive-1701ef1f1510/baz/bletch
test-archive-1701ef1f1510/foo
test-archive-1701ef1f1510/subrepo/sub
test-archive-2c0277f05ed4/.hg_archival.txt
test-archive-2c0277f05ed4/bar
test-archive-2c0277f05ed4/baz/bletch
test-archive-2c0277f05ed4/foo
$ $PYTHON getarchive.py "$TIP" bz2 | bunzip2 | tar tf - 2>/dev/null
test-archive-1701ef1f1510/.hg_archival.txt
test-archive-1701ef1f1510/.hgsub
test-archive-1701ef1f1510/.hgsubstate
test-archive-1701ef1f1510/bar
test-archive-1701ef1f1510/baz/bletch
test-archive-1701ef1f1510/foo
test-archive-1701ef1f1510/subrepo/sub
test-archive-2c0277f05ed4/.hg_archival.txt
test-archive-2c0277f05ed4/bar
test-archive-2c0277f05ed4/baz/bletch
test-archive-2c0277f05ed4/foo
$ $PYTHON getarchive.py "$TIP" zip > archive.zip
$ unzip -t archive.zip
Archive: archive.zip
testing: test-archive-1701ef1f1510/.hg_archival.txt*OK (glob)
testing: test-archive-1701ef1f1510/.hgsub*OK (glob)
testing: test-archive-1701ef1f1510/.hgsubstate*OK (glob)
testing: test-archive-1701ef1f1510/bar*OK (glob)
testing: test-archive-1701ef1f1510/baz/bletch*OK (glob)
testing: test-archive-1701ef1f1510/foo*OK (glob)
testing: test-archive-1701ef1f1510/subrepo/sub*OK (glob)
testing: test-archive-2c0277f05ed4/.hg_archival.txt OK
testing: test-archive-2c0277f05ed4/bar OK
testing: test-archive-2c0277f05ed4/baz/bletch OK
testing: test-archive-2c0277f05ed4/foo OK
No errors detected in compressed data of archive.zip.
test that we can download single directories and files
$ $PYTHON getarchive.py "$TIP" gz baz | gunzip | tar tf - 2>/dev/null
test-archive-1701ef1f1510/baz/bletch
test-archive-2c0277f05ed4/baz/bletch
$ $PYTHON getarchive.py "$TIP" gz foo | gunzip | tar tf - 2>/dev/null
test-archive-1701ef1f1510/foo
test-archive-2c0277f05ed4/foo
test that we detect file patterns that match no files
@ -258,39 +177,29 @@ test that we reject unsafe patterns
$ hg archive -t tar test.tar
$ tar tf test.tar
test/.hg_archival.txt
test/.hgsub
test/.hgsubstate
test/bar
test/baz/bletch
test/foo
$ hg archive --debug -t tbz2 -X baz test.tar.bz2 --config progress.debug=true
progress: archiving: .hgsub 1/4 files (25.00%)
progress: archiving: .hgsubstate 2/4 files (50.00%)
progress: archiving: bar 3/4 files (75.00%)
progress: archiving: foo 4/4 files (100.00%)
progress: archiving: bar 1/2 files (50.00%)
progress: archiving: foo 2/2 files (100.00%)
progress: archiving (end)
$ bunzip2 -dc test.tar.bz2 | tar tf - 2>/dev/null
test/.hg_archival.txt
test/.hgsub
test/.hgsubstate
test/bar
test/foo
$ hg archive -t tgz -p %b-%h test-%h.tar.gz
$ gzip -dc test-$QTIP.tar.gz | tar tf - 2>/dev/null
test-1701ef1f1510/.hg_archival.txt
test-1701ef1f1510/.hgsub
test-1701ef1f1510/.hgsubstate
test-1701ef1f1510/bar
test-1701ef1f1510/baz/bletch
test-1701ef1f1510/foo
test-2c0277f05ed4/.hg_archival.txt
test-2c0277f05ed4/bar
test-2c0277f05ed4/baz/bletch
test-2c0277f05ed4/foo
$ hg archive autodetected_test.tar
$ tar tf autodetected_test.tar
autodetected_test/.hg_archival.txt
autodetected_test/.hgsub
autodetected_test/.hgsubstate
autodetected_test/bar
autodetected_test/baz/bletch
autodetected_test/foo
@ -300,8 +209,6 @@ The '-t' should override autodetection
$ hg archive -t tar autodetect_override_test.zip
$ tar tf autodetect_override_test.zip
autodetect_override_test.zip/.hg_archival.txt
autodetect_override_test.zip/.hgsub
autodetect_override_test.zip/.hgsubstate
autodetect_override_test.zip/bar
autodetect_override_test.zip/baz/bletch
autodetect_override_test.zip/foo
@ -348,12 +255,10 @@ rename them afterwards.
No errors detected in compressed data of test.zip.
$ hg archive -t tar - | tar tf - 2>/dev/null
test-1701ef1f1510/.hg_archival.txt
test-1701ef1f1510/.hgsub
test-1701ef1f1510/.hgsubstate
test-1701ef1f1510/bar
test-1701ef1f1510/baz/bletch
test-1701ef1f1510/foo
test-2c0277f05ed4/.hg_archival.txt
test-2c0277f05ed4/bar
test-2c0277f05ed4/baz/bletch
test-2c0277f05ed4/foo
$ hg archive -r 0 -t tar rev-%r.tar
$ [ -f rev-0.tar ]
@ -363,11 +268,11 @@ test .hg_archival.txt
$ hg archive ../test-tags
$ cat ../test-tags/.hg_archival.txt
repo: daa7f7c60e0a224faa4ff77ca41b2760562af264
node: 1701ef1f151069b8747038e93b5186bb43a47504
node: 2c0277f05ed49d1c8328fb9ba92fba7a5ebcb33e
branch: default
latesttag: null
latesttagdistance: 4
changessincelatesttag: 4
latesttagdistance: 3
changessincelatesttag: 3
$ hg tag -r 2 mytag
$ hg tag -r 2 anothertag
$ hg archive -r 2 ../test-lasttag

View File

@ -1,132 +0,0 @@
Test illegal name
-----------------
on commit:
$ hg init hgname
$ cd hgname
$ mkdir sub
$ hg init sub/.hg
$ echo 'sub/.hg = sub/.hg' >> .hgsub
$ hg ci -qAm 'add subrepo "sub/.hg"'
abort: path 'sub/.hg' is inside nested repo 'sub'
[255]
prepare tampered repo (including the commit above):
$ hg import --bypass -qm 'add subrepo "sub/.hg"' - <<'EOF'
> diff --git a/.hgsub b/.hgsub
> new file mode 100644
> --- /dev/null
> +++ b/.hgsub
> @@ -0,0 +1,1 @@
> +sub/.hg = sub/.hg
> diff --git a/.hgsubstate b/.hgsubstate
> new file mode 100644
> --- /dev/null
> +++ b/.hgsubstate
> @@ -0,0 +1,1 @@
> +0000000000000000000000000000000000000000 sub/.hg
> EOF
$ cd ..
on clone (and update):
$ hg clone -q hgname hgname2
abort: path 'sub/.hg' is inside nested repo 'sub'
[255]
Test direct symlink traversal
-----------------------------
#if symlink
on commit:
$ mkdir hgsymdir
$ hg init hgsymdir/root
$ cd hgsymdir/root
$ ln -s ../out
$ hg ci -qAm 'add symlink "out"'
$ hg init ../out
$ echo 'out = out' >> .hgsub
$ hg ci -qAm 'add subrepo "out"'
abort: subrepo 'out' traverses symbolic link
[255]
prepare tampered repo (including the commit above):
$ hg import --bypass -qm 'add subrepo "out"' - <<'EOF'
> diff --git a/.hgsub b/.hgsub
> new file mode 100644
> --- /dev/null
> +++ b/.hgsub
> @@ -0,0 +1,1 @@
> +out = out
> diff --git a/.hgsubstate b/.hgsubstate
> new file mode 100644
> --- /dev/null
> +++ b/.hgsubstate
> @@ -0,0 +1,1 @@
> +0000000000000000000000000000000000000000 out
> EOF
$ cd ../..
on clone (and update):
$ mkdir hgsymdir2
$ hg clone -q hgsymdir/root hgsymdir2/root
abort: subrepo 'out' traverses symbolic link
[255]
$ ls hgsymdir2
root
#endif
Test indirect symlink traversal
-------------------------------
#if symlink
on commit:
$ mkdir hgsymin
$ hg init hgsymin/root
$ cd hgsymin/root
$ ln -s ../out
$ hg ci -qAm 'add symlink "out"'
$ mkdir ../out
$ hg init ../out/sub
$ echo 'out/sub = out/sub' >> .hgsub
$ hg ci -qAm 'add subrepo "out/sub"'
abort: path 'out/sub' traverses symbolic link 'out'
[255]
prepare tampered repo (including the commit above):
$ hg import --bypass -qm 'add subrepo "out/sub"' - <<'EOF'
> diff --git a/.hgsub b/.hgsub
> new file mode 100644
> --- /dev/null
> +++ b/.hgsub
> @@ -0,0 +1,1 @@
> +out/sub = out/sub
> diff --git a/.hgsubstate b/.hgsubstate
> new file mode 100644
> --- /dev/null
> +++ b/.hgsubstate
> @@ -0,0 +1,1 @@
> +0000000000000000000000000000000000000000 out/sub
> EOF
$ cd ../..
on clone (and update):
$ mkdir hgsymin2
$ hg clone -q hgsymin/root hgsymin2/root
abort: path 'out/sub' traverses symbolic link 'out'
[255]
$ ls hgsymin2
root
#endif

View File

@ -376,7 +376,7 @@ test saving last-message.txt
$ hg init sub
$ echo a > sub/a
$ hg -R sub add sub/a
$ cat > sub/.hg/hgrc <<EOF
$ cat > .hg/hgrc <<EOF
> [hooks]
> precommit.test-saving-last-message = false
> EOF
@ -392,7 +392,7 @@ test saving last-message.txt
> EOF
$ rm -f .hg/last-message.txt
$ HGEDITOR="sh $TESTTMP/editor.sh" hg commit -S -q
$ HGEDITOR="sh $TESTTMP/editor.sh" hg commit -q
==== before editing:
@ -402,14 +402,13 @@ test saving last-message.txt
HG: user: test
HG: branch 'default'
HG: bookmark 'activebookmark'
HG: subrepo sub
HG: added .hgsub
HG: added added
HG: changed .hgsubstate
HG: changed changed
HG: removed removed
====
abort: precommit.test-saving-last-message hook exited with status 1 (in subrepository "sub")
note: commit message saved in .hg/last-message.txt
abort: precommit.test-saving-last-message hook exited with status 1
[255]
$ cat .hg/last-message.txt
@ -448,12 +447,10 @@ specific template keywords work well
$ hg -R sub2 add sub2/a
$ echo 'sub2 = sub2' >> .hgsub
$ HGEDITOR=cat hg commit -S -q
$ HGEDITOR=cat hg commit -q
HG: this is "commit.normal" template
HG: Leave message empty to abort commit.
HG: bookmark 'activebookmark' is activated
HG: subrepo 'sub' is changed
HG: subrepo 'sub2' is changed
abort: empty commit message
[255]
@ -521,14 +518,17 @@ specific template keywords work well
HG: adds=
HG: dels=
HG: files=changed
note: commit message saved in .hg/last-message.txt
abort: precommit.test-saving-last-message hook exited with status 1
[255]
$ hg status -amr
M changed
A added
R removed
$ hg parents --template "M {file_mods}\nA {file_adds}\nR {file_dels}\n"
M changed
A
M
A changed removed
R
$ hg rollback -q
$ cat >> .hg/hgrc <<EOF
> [committemplate]
@ -591,12 +591,17 @@ specific template keywords work well
HG: adds=added
HG: dels=removed
HG: files=added removed
note: commit message saved in .hg/last-message.txt
abort: precommit.test-saving-last-message hook exited with status 1
[255]
$ hg status -amr
M changed
$ hg parents --template "M {file_mods}\nA {file_adds}\nR {file_dels}\n"
M
A added
R removed
$ hg parents --template "M {file_mods}\nA {file_adds}\nR {file_dels}\n"
M
A changed removed
R
$ hg rollback -q
$ cat >> .hg/hgrc <<EOF
@ -718,8 +723,7 @@ verify pathauditor blocks evil filepaths
> HG: {extramsg}
> {if(activebookmark,
> "HG: bookmark '{activebookmark}' is activated\n",
> "HG: no bookmark is activated\n")}{subrepos %
> "HG: subrepo '{subrepo}' is changed\n"}
> "HG: no bookmark is activated\n")}
> EOF
$ cat > $TESTTMP/notouching.sh <<EOF
> true

View File

@ -129,7 +129,6 @@ Show debug commands if there are no other candidates
debugssl
debugstatus
debugstrip
debugsub
debugsuccessorssets
debugtemplate
debugtreestate
@ -213,7 +212,6 @@ Show the options for the "serve" command
--repository
--stdio
--style
--subrepos
--templates
--time
--traceback
@ -224,7 +222,6 @@ Show the options for the "serve" command
-A
-E
-R
-S
-a
-d
-h
@ -243,11 +240,11 @@ Show an error if we use --options with an ambiguous abbreviation
Show all commands + options
$ hg debugcommands
add: include, exclude, subrepos, dry-run
add: include, exclude, dry-run
annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
clone: noupdate, updaterev, rev, pull, uncompressed, stream, ssh, remotecmd, insecure
commit: addremove, amend, edit, interactive, reuse-message, include, exclude, message, logfile, date, user, subrepos
diff: rev, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, only-files-in-revs, include, exclude, subrepos
commit: addremove, amend, edit, interactive, reuse-message, include, exclude, message, logfile, date, user
diff: rev, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, only-files-in-revs, include, exclude
export: output, switch-parent, rev, text, git, binary, nodates
forget: include, exclude
githelp:
@ -256,15 +253,15 @@ Show all commands + options
merge: force, rev, preview, tool
pull: update, force, rev, bookmark, ssh, remotecmd, insecure
push: force, rev, bookmark, new-branch, pushvars, ssh, remotecmd, insecure
record: addremove, amend, secret, edit, message, logfile, date, user, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, subrepos, include, exclude
remove: after, force, subrepos, include, exclude
serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, port-file, stdio, cmdserver, templates, style, ipv6, certificate, read-only, subrepos
record: addremove, amend, secret, edit, message, logfile, date, user, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude
remove: after, force, include, exclude
serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, port-file, stdio, cmdserver, templates, style, ipv6, certificate, read-only
show: nodates, noprefix, stat, git, unified, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, style, template, include, exclude
status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, template
summary: remote
update: clean, check, merge, date, rev, inactive, tool
addremove: similarity, subrepos, include, exclude, dry-run
archive: no-decode, prefix, rev, type, subrepos, include, exclude
addremove: similarity, include, exclude, dry-run
archive: no-decode, prefix, rev, type, include, exclude
backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
bisect: reset, good, bad, skip, extend, command, noupdate, nosparseskip
bookmarks: force, rev, delete, strip, rename, inactive, template
@ -325,7 +322,6 @@ Show all commands + options
debugssl:
debugstatus: nonnormal
debugstrip: rev, force, no-backup, keep, bookmark
debugsub: rev
debugsuccessorssets: closest
debugtemplate: rev, define
debugtreestate:
@ -333,7 +329,7 @@ Show all commands + options
debugupgraderepo: optimize, run
debugwalk: include, exclude
debugwireargs: three, four, five, ssh, remotecmd, insecure
files: rev, print0, include, exclude, template, subrepos
files: rev, print0, include, exclude, template
fs:
graft: rev, continue, abort, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
grep: after-context, before-context, context, ignore-case, files-with-matches, line-number, invert-match, word-regexp, extended-regexp, fixed-strings, perl-regexp, include, exclude
@ -343,10 +339,10 @@ Show all commands + options
histgrep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, template, include, exclude
identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, message, logfile, date, user, similarity
incoming: force, newest-first, bundle, rev, bookmarks, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
incoming: force, newest-first, bundle, rev, bookmarks, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure
locate: rev, print0, fullpath, include, exclude
manifest: rev, all, template
outgoing: force, rev, newest-first, bookmarks, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
outgoing: force, rev, newest-first, bookmarks, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure
parents: rev, style, template
paths: template
phase: public, draft, secret, force, rev

View File

@ -96,13 +96,11 @@ Compare repos:
comparing with repo-a
searching for changes
no changes found
[1]
$ hg -R repo-a incoming repo-c
comparing with repo-c
searching for changes
no changes found
[1]
Test simplemerge command:

View File

@ -744,7 +744,6 @@ test missing .gitmodules
2 addsubmodule
1 remove .gitmodules
0 missing .gitmodules
warning: cannot read submodules config file in * (glob)
updating bookmarks
$ rm -rf hg-repo6
$ cd git-repo6
@ -796,7 +795,6 @@ convert sub modules
tag: tip
user: nottest <test@example.org>
date: Mon Jan 01 00:00:23 2007 +0000
files: .hgsub .hgsubstate
description:
addsubmodule
@ -806,13 +804,8 @@ convert sub modules
$ cd git-repo6-hg
$ hg up >/dev/null 2>/dev/null
$ cat .hgsubstate
* git-repo5 (glob)
$ cd git-repo5
$ cat foo
sub
$ cd ../..
$ cd $TESTTMP
make sure rename detection doesn't break removing and adding gitmodules
@ -828,13 +821,9 @@ make sure rename detection doesn't break removing and adding gitmodules
rename .gitmodules
$ hg -R git-repo6-hg status -C --change 'tip^'
A .gitmodules-renamed
R .hgsub
R .hgsubstate
$ hg -R git-repo6-hg log -r tip -T "{desc|firstline}\n"
rename .gitmodules back
$ hg -R git-repo6-hg status -C --change tip
A .hgsub
A .hgsubstate
R .gitmodules-renamed
convert the revision removing '.gitmodules' itself (and related
@ -852,7 +841,7 @@ submodules)
$ hg -R git-repo6-hg tip -T "{desc|firstline}\n"
remove .gitmodules and submodule git-repo5
$ hg -R git-repo6-hg tip -T "{file_dels}\n"
.hgsub .hgsubstate
skip submodules in the conversion

View File

@ -190,7 +190,7 @@
The Git importer converts commits from all reachable branches (refs in
refs/heads) and remotes (refs in refs/remotes) to Mercurial. Branches are
converted to bookmarks with the same name, with the leading 'refs/heads'
stripped. Git submodules are converted to Git subrepos in Mercurial.
stripped. Git submodules are not supported.
The following options can be set with "--config":
@ -285,12 +285,6 @@
Mercurial Destination
#####################
The Mercurial destination will recognize Mercurial subrepositories in the
destination directory, and update the .hgsubstate file automatically if
the destination subrepositories contain the <dest>/<sub>/.hg/shamap file.
Converting a repository with subrepositories requires converting a single
repository at a time, from the bottom up.
The following options are supported:
convert.hg.clonebranches

View File

@ -160,76 +160,6 @@ record
#endif
issue3712: test colorization of subrepo diff
$ hg init sub
$ echo b > sub/b
$ hg -R sub commit -Am 'create sub'
adding b
$ echo 'sub = sub' > .hgsub
$ hg add .hgsub
$ hg commit -m 'add subrepo sub'
$ echo aa >> a
$ echo bb >> sub/b
$ hg diff -S
\x1b[0;1mdiff --git a/a b/a\x1b[0m (esc)
\x1b[0;31;1m--- a/a\x1b[0m (esc)
\x1b[0;32;1m+++ b/a\x1b[0m (esc)
\x1b[0;35m@@ -7,3 +7,4 @@\x1b[0m (esc)
a
c
c
\x1b[0;92m+aa\x1b[0m (esc)
\x1b[0;1mdiff --git a/sub/b b/sub/b\x1b[0m (esc)
\x1b[0;31;1m--- a/sub/b\x1b[0m (esc)
\x1b[0;32;1m+++ b/sub/b\x1b[0m (esc)
\x1b[0;35m@@ -1,1 +1,2 @@\x1b[0m (esc)
b
\x1b[0;92m+bb\x1b[0m (esc)
test tabs
$ cat >> a <<EOF
> one tab
> two tabs
> end tab
> mid tab
> all tabs
> EOF
$ hg diff --nodates
\x1b[0;1mdiff --git a/a b/a\x1b[0m (esc)
\x1b[0;31;1m--- a/a\x1b[0m (esc)
\x1b[0;32;1m+++ b/a\x1b[0m (esc)
\x1b[0;35m@@ -7,3 +7,9 @@\x1b[0m (esc)
a
c
c
\x1b[0;92m+aa\x1b[0m (esc)
\x1b[0;92m+\x1b[0m \x1b[0;92mone tab\x1b[0m (esc)
\x1b[0;92m+\x1b[0m \x1b[0;92mtwo tabs\x1b[0m (esc)
\x1b[0;92m+end tab\x1b[0m\x1b[0;1;41m \x1b[0m (esc)
\x1b[0;92m+mid\x1b[0m \x1b[0;92mtab\x1b[0m (esc)
\x1b[0;92m+\x1b[0m \x1b[0;92mall\x1b[0m \x1b[0;92mtabs\x1b[0m\x1b[0;1;41m \x1b[0m (esc)
$ echo "[color]" >> $HGRCPATH
$ echo "diff.tab = bold magenta" >> $HGRCPATH
$ hg diff --nodates
\x1b[0;1mdiff --git a/a b/a\x1b[0m (esc)
\x1b[0;31;1m--- a/a\x1b[0m (esc)
\x1b[0;32;1m+++ b/a\x1b[0m (esc)
\x1b[0;35m@@ -7,3 +7,9 @@\x1b[0m (esc)
a
c
c
\x1b[0;92m+aa\x1b[0m (esc)
\x1b[0;92m+\x1b[0m\x1b[0;1;35m \x1b[0m\x1b[0;92mone tab\x1b[0m (esc)
\x1b[0;92m+\x1b[0m\x1b[0;1;35m \x1b[0m\x1b[0;92mtwo tabs\x1b[0m (esc)
\x1b[0;92m+end tab\x1b[0m\x1b[0;1;41m \x1b[0m (esc)
\x1b[0;92m+mid\x1b[0m\x1b[0;1;35m \x1b[0m\x1b[0;92mtab\x1b[0m (esc)
\x1b[0;92m+\x1b[0m\x1b[0;1;35m \x1b[0m\x1b[0;92mall\x1b[0m\x1b[0;1;35m \x1b[0m\x1b[0;92mtabs\x1b[0m\x1b[0;1;41m \x1b[0m (esc)
$ cd ..
test inline color diff
$ hg init inline

View File

@ -72,7 +72,6 @@ testmod("edenscm.mercurial.pycompat")
testmod("edenscm.mercurial.revsetlang")
testmod("edenscm.mercurial.smartset")
testmod("edenscm.mercurial.store")
testmod("edenscm.mercurial.subrepo")
testmod("edenscm.mercurial.templatefilters")
testmod("edenscm.mercurial.templater")
testmod("edenscm.mercurial.ui")

View File

@ -480,14 +480,10 @@ Test eol.only-consistent can be specified in .hgeol
$ hg ci -Am "add subrepo"
adding .hgeol
adding .hgsub
$ hg archive -S ../archive
$ hg archive ../archive
$ find ../archive/* | sort
../archive/a.txt
../archive/subrepo
../archive/subrepo/a.txt
$ cat ../archive/a.txt ../archive/subrepo/a.txt
first\r (esc)
second\r (esc)
$ cat ../archive/a.txt
first\r (esc)
second\r (esc)

View File

@ -51,7 +51,6 @@ Should diff cloned directories:
--patch compare patches for two revisions
-I --include PATTERN [+] include names matching the given patterns
-X --exclude PATTERN [+] exclude names matching the given patterns
-S --subrepos recurse into subrepositories
(some details hidden, use --verbose to show complete help)
@ -108,25 +107,6 @@ Check diff are made from the first parent:
diffing */extdiff.*/a.2a13a4d2da36/a a.46c0e4daeb72/a (glob) (no-windows !)
diff-like tools yield a non-zero exit code
issue3153: ensure using extdiff with removed subrepos doesn't crash:
$ hg init suba
$ cd suba
$ echo suba > suba
$ hg add
adding suba
$ hg ci -m "adding suba file"
$ cd ..
$ echo suba=suba > .hgsub
$ hg add
adding .hgsub
$ hg ci -Sm "adding subrepo"
$ echo > .hgsub
$ hg ci -m "removing subrepo"
$ hg falabala -r 4 -r 5 -S
diffing a.398e36faf9c6 a.5ab95fb166c4
[1]
issue4463: usage of command line configuration without additional quoting
$ cat <<EOF >> $HGRCPATH

View File

@ -710,7 +710,6 @@ Extension module help vs command help:
--patch compare patches for two revisions
-I --include PATTERN [+] include names matching the given patterns
-X --exclude PATTERN [+] exclude names matching the given patterns
-S --subrepos recurse into subrepositories
(some details hidden, use --verbose to show complete help)
@ -1380,16 +1379,9 @@ disabling in command line overlays with all configuration
$ echo '# enable extension locally' >> parent/.hg/hgrc
$ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> parent/.hg/hgrc
$ cp parent/.hg/hgrc parent/sub2/.hg/hgrc
$ hg -R parent status -S -A
$ hg -R parent status -A
reposetup() for $TESTTMP/reposetup-test/parent
reposetup() for $TESTTMP/reposetup-test/parent/sub2
C .hgsub
C .hgsubstate
C sub1/1
C sub2/.hgsub
C sub2/.hgsubstate
C sub2/sub21/21
C sub3/3
$ cd ..

View File

@ -67,7 +67,6 @@ Make some non-conflicting commits in in the client repos.
o base [public:4ced94c0a443]
$ hg push -q -r tip --to master
*FULL* manifest read for 8655e3409b0e (outside lock)
$ log
@ second commit [public:0a57cb610829] master
|
@ -99,7 +98,6 @@ Make some non-conflicting commits in in the client repos.
$ hg push -r . --to master
pushing to ssh://user@dummy/server2
*FULL* manifest read for 46410a8f6645 (outside lock)
searching for changes
remote: *FULL* manifest read for 1e4ac5512124 (outside lock)
remote: cached manifest read for 1e4ac5512124 (outside lock)
@ -197,7 +195,6 @@ Meanwhile, push from client2 -> server2.
$ hg push --to master 2>&1 | \sed "s/^/[client2 push] /"
[client2 push] pushing to ssh://user@dummy/server2
[client2 push] *FULL* manifest read for bb1129e7c430 (outside lock)
[client2 push] searching for changes
[client2 push] remote: *FULL* manifest read for 1e4ac5512124 (outside lock)
[client2 push] remote: cached manifest read for 1e4ac5512124 (outside lock)
@ -223,7 +220,6 @@ Check that the first push is still running/blocked...
$ touch .hg/flag
$ wait
[client1 push] pushing to ssh://user@dummy/server1
[client1 push] *FULL* manifest read for 9210795ca8ad (outside lock)
[client1 push] searching for changes
[client1 push] remote: *FULL* manifest read for 8655e3409b0e (outside lock)
[client1 push] remote: cached manifest read for 8655e3409b0e (outside lock)

View File

@ -211,63 +211,13 @@ Test merge states
$ fileset 'unresolved()'
$ hg ci -m merge
Test subrepo predicate
There was a commit from subrepo here. Now subrepos are gone, insert a dummy commit to take its place.
$ hg init sub
$ echo a > sub/suba
$ hg -R sub add sub/suba
$ hg -R sub ci -m sub
$ echo 'sub = sub' > .hgsub
$ hg init sub2
$ echo b > sub2/b
$ hg -R sub2 ci -Am sub2
adding b
$ echo 'sub2 = sub2' >> .hgsub
$ fileset 'subrepo()'
$ hg add .hgsub
$ fileset 'subrepo()'
sub
sub2
$ fileset 'subrepo("sub")'
sub
$ fileset 'subrepo("glob:*")'
sub
sub2
$ hg ci -m subrepo
Test that .hgsubstate is updated as appropriate during a conversion. The
saverev property is enough to alter the hashes of the subrepo.
$ hg init ../converted
$ hg --config extensions.convert= convert --config convert.hg.saverev=True \
> sub ../converted/sub
initializing destination ../converted/sub repository
scanning source...
sorting...
converting...
0 sub
$ hg clone -U sub2 ../converted/sub2
$ hg --config extensions.convert= convert --config convert.hg.saverev=True \
> . ../converted
scanning source...
sorting...
converting...
4 addfiles
3 manychanges
2 diverging
1 merge
0 subrepo
no ".hgsubstate" updates will be made for "sub2"
$ hg up -q -R ../converted -r tip
$ hg --cwd ../converted cat sub/suba sub2/b -r tip
a
b
$ oldnode=`hg log -r tip -T "{node}\n"`
$ newnode=`hg log -R ../converted -r tip -T "{node}\n"`
$ [ "$oldnode" != "$newnode" ] || echo "nothing changed"
$ hg commit -m 'subrepo' --config ui.allowemptycommit=1
Test with a revision
$ hg log -G --template '{rev} {desc}\n'
@ 4 subrepo
|
@ -315,11 +265,6 @@ Test with a revision
$ hg forget 'con.xml'
#endif
$ fileset -r4 'subrepo("re:su.*")'
sub
sub2
$ fileset -r4 'subrepo("sub")'
sub
$ fileset -r4 'b2 or c1'
b2
c1
@ -337,8 +282,6 @@ Test with a revision
mixed
$ fileset 'eol(unix)'
mixed
.hgsub
.hgsubstate
b1
b2
c1
@ -351,8 +294,6 @@ Test safety of 'encoding' on removed files
dos
mac
mixed
.hgsub
.hgsubstate
1k
2k
b1
@ -442,8 +383,6 @@ small reminder of the repository state
A con.xml (no-windows !)
R a2
$ hg status --change 4
A .hgsub
A .hgsubstate
$ hg status
A dos
A mac
@ -482,8 +421,6 @@ Test that "revs()" work for file missing in the working copy/current context
(none of the file exist in "0")
$ fileset -r 0 "revs('4', added())"
.hgsub
.hgsubstate
Call with empty revset
--------------------------
@ -498,8 +435,6 @@ Call with revset matching multiple revs
a2
b1
b2
.hgsub
.hgsubstate
overlapping set
@ -513,8 +448,6 @@ Simple case
-----------
$ fileset "status(3, 4, added())"
.hgsub
.hgsubstate
use rev to restrict matched file
-----------------------------------------
@ -565,8 +498,6 @@ test cross branch status
test with multi revs revset
---------------------------
$ hg status --added --rev 0:1 --rev 3:4
A .hgsub
A .hgsubstate
A 1k
A 2k
A b2link (no-windows !)
@ -574,8 +505,6 @@ test with multi revs revset
A c1
A con.xml (no-windows !)
$ fileset "status('0:1', '3:4', added())"
.hgsub
.hgsubstate
1k
2k
b2link (no-windows !)

View File

@ -409,7 +409,6 @@ Normal help for add
-I --include PATTERN [+] include names matching the given patterns
-X --exclude PATTERN [+] exclude names matching the given patterns
-S --subrepos recurse into subrepositories
-n --dry-run do not perform actions, just print output
(some details hidden, use --verbose to show complete help)
@ -460,7 +459,6 @@ Verbose help for add
-I --include PATTERN [+] include names matching the given patterns
-X --exclude PATTERN [+] exclude names matching the given patterns
-S --subrepos recurse into subrepositories
-n --dry-run do not perform actions, just print output
Global options ([+] can be repeated):
@ -609,7 +607,6 @@ Test command without options
requested revisions
-I --include PATTERN [+] include names matching the given patterns
-X --exclude PATTERN [+] exclude names matching the given patterns
-S --subrepos recurse into subrepositories
(some details hidden, use --verbose to show complete help)
@ -670,7 +667,6 @@ Test command without options
--change REV list the changed files of a revision
-I --include PATTERN [+] include names matching the given patterns
-X --exclude PATTERN [+] exclude names matching the given patterns
-S --subrepos recurse into subrepositories
(some details hidden, use --verbose to show complete help)
@ -1030,7 +1026,6 @@ Test list of internal help commands
debugssl test a secure connection to a server
debugstatus common performance issues for status
debugstrip strip commits and all their descendants from the repository
debugsub (no help text available)
debugsuccessorssets
show set of successors for revision
debugtemplate
@ -1545,7 +1540,6 @@ Test keyword search help
extensions Using Additional Features
glossary Common Terms
phases Working with Phases
subrepos Subrepositories
urls URL Paths
Commands:
@ -2161,13 +2155,6 @@ Dish up an empty repo; serve it cold.
Using Mercurial from scripts and automation
</td></tr>
<tr><td>
<a href="/help/subrepos">
subrepos
</a>
</td><td>
Subrepositories
</td></tr>
<tr><td>
<a href="/help/templating">
templating
</a>
@ -2725,9 +2712,6 @@ Dish up an empty repo; serve it cold.
<tr><td>-X</td>
<td>--exclude PATTERN [+]</td>
<td>exclude names matching the given patterns</td></tr>
<tr><td>-S</td>
<td>--subrepos</td>
<td>recurse into subrepositories</td></tr>
<tr><td>-n</td>
<td>--dry-run</td>
<td>do not perform actions, just print output</td></tr>
@ -2926,9 +2910,6 @@ Dish up an empty repo; serve it cold.
<tr><td>-f</td>
<td>--force</td>
<td>forget added files, delete modified files</td></tr>
<tr><td>-S</td>
<td>--subrepos</td>
<td>recurse into subrepositories</td></tr>
<tr><td>-I</td>
<td>--include PATTERN [+]</td>
<td>include names matching the given patterns</td></tr>

View File

@ -1,411 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ git init gitrepo1
Initialized empty Git repository in $TESTTMP/gitrepo1/.git/
$ cd gitrepo1
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m 'add alpha'
$ cd ..
$ git init gitsubrepo
Initialized empty Git repository in $TESTTMP/gitsubrepo/.git/
$ cd gitsubrepo
$ echo beta > beta
$ git add beta
$ fn_git_commit -m 'add beta'
$ cd ..
$ mkdir gitrepo2
$ cd gitrepo2
$ git clone ../gitrepo1 .
Cloning into '.'...
done.
$ git submodule add ../gitsubrepo subrepo
Cloning into '$TESTTMP/gitrepo2/subrepo'...
done.
$ git commit -m 'add subrepo'
[master e42b08b] add subrepo
2 files changed, 4 insertions(+)
create mode 100644 .gitmodules
create mode 160000 subrepo
$ cd subrepo
$ echo gamma > gamma
$ git add gamma
$ fn_git_commit -m 'add gamma'
$ cd ..
$ git add subrepo
$ git commit -m 'change subrepo commit'
[master a000567] change subrepo commit
1 file changed, 1 insertion(+), 1 deletion(-)
$ git submodule add ../gitsubrepo subrepo2
Cloning into '$TESTTMP/gitrepo2/subrepo2'...
done.
$ git commit -m 'add another subrepo'
[master 6e21952] add another subrepo
2 files changed, 4 insertions(+)
create mode 160000 subrepo2
remove one subrepo, replace with file
$ git rm --cached subrepo
rm 'subrepo'
we'd ordinarily use sed here, but BSD sed doesn't support two-address formats
like +2 -- so use grep with the stuff we want to keep
$ grep 'submodule "subrepo2"' -A2 .gitmodules > .gitmodules-new
$ mv .gitmodules-new .gitmodules
$ git add .gitmodules
$ git config --unset submodule.subrepo.url
$ rm -rf subrepo
$ echo subrepo > subrepo
$ git add subrepo
$ git commit -m 'replace subrepo with file'
[master f6436a4] replace subrepo with file
2 files changed, 1 insertion(+), 4 deletions(-)
mode change 160000 => 100644 subrepo
replace file with subrepo -- apparently, git complains about the subrepo if the
same name has existed at any point historically, so use alpha instead of subrepo
$ git rm alpha
rm 'alpha'
$ git submodule add ../gitsubrepo alpha
Cloning into '$TESTTMP/gitrepo2/alpha'...
done.
$ git commit -m 'replace file with subrepo'
[master 8817116] replace file with subrepo
2 files changed, 4 insertions(+), 1 deletion(-)
mode change 100644 => 160000 alpha
$ ln -s foo foolink
$ git add foolink
$ git commit -m 'add symlink'
[master 2d1c135] add symlink
1 file changed, 1 insertion(+)
create mode 120000 foolink
replace symlink with subrepo
$ git rm foolink
rm 'foolink'
$ git submodule add ../gitsubrepo foolink
Cloning into '$TESTTMP/gitrepo2/foolink'...
done.
$ git commit -m 'replace symlink with subrepo'
[master e3288fa] replace symlink with subrepo
2 files changed, 4 insertions(+), 1 deletion(-)
mode change 120000 => 160000 foolink
replace subrepo with symlink
$ cat > .gitmodules <<EOF
> [submodule "subrepo2"]
> path = subrepo2
> url = ../gitsubrepo
> [submodule "alpha"]
> path = alpha
> url = ../gitsubrepo
> EOF
$ git add .gitmodules
$ git rm --cached foolink
rm 'foolink'
$ rm -rf foolink
$ ln -s foo foolink
$ git add foolink
$ git commit -m 'replace subrepo with symlink'
[master d283640] replace subrepo with symlink
2 files changed, 1 insertion(+), 4 deletions(-)
mode change 160000 => 120000 foolink
$ git show
commit d28364013fe1a0fde56c0e1921e49ecdeee8571d
Author: test <test@example.org>
Date: Mon Jan 1 00:00:12 2007 +0000
replace subrepo with symlink
diff --git a/.gitmodules b/.gitmodules
index b511494..813e20b 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,6 +4,3 @@
[submodule "alpha"]
path = alpha
url = ../gitsubrepo
-[submodule "foolink"]
- path = foolink
- url = ../gitsubrepo
diff --git a/foolink b/foolink
deleted file mode 160000
index 6e4ad8d..0000000
--- a/foolink
+++ /dev/null
@@ -1* +0,0 @@ (glob)
-Subproject commit 6e4ad8da50204560c00fa25e4987eb2e239029ba
diff --git a/foolink b/foolink
new file mode 120000
index 0000000..1910281
--- /dev/null
+++ b/foolink
@@ -0,0 +1* @@ (glob)
+foo
\ No newline at end of file
$ git rm --cached subrepo2
rm 'subrepo2'
$ git rm --cached alpha
rm 'alpha'
$ git rm .gitmodules
rm '.gitmodules'
$ git commit -m 'remove all subrepos'
[master 15ba949] remove all subrepos
3 files changed, 8 deletions(-)
delete mode 100644 .gitmodules
delete mode 160000 alpha
delete mode 160000 subrepo2
$ git log --pretty=oneline
15ba94929481c654814178aac1dbca06ae688718 remove all subrepos
d28364013fe1a0fde56c0e1921e49ecdeee8571d replace subrepo with symlink
e3288fa737d429a60637b3b6782cb25b8298bc00 replace symlink with subrepo
2d1c135447d11df4dfe96dd5d4f37926dc5c821d add symlink
88171163bf4795b5570924e51d5f8ede33f8bc28 replace file with subrepo
f6436a472da00f581d8d257e9bbaf3c358a5e88c replace subrepo with file
6e219527869fa40eb6ffbdd013cd86d576b26b01 add another subrepo
a000567ceefbd9a2ce364e0dea6e298010b02b6d change subrepo commit
e42b08b3cb7069b4594a4ee1d9cb641ee47b2355 add subrepo
7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03 add alpha
$ cd ..
$ hg clone gitrepo2 hgrepo | grep -v '^updating'
importing git objects into hg
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd hgrepo
$ hg log --graph
@ changeset: 9:5ae8371d90fe
| bookmark: master
| tag: default/master
| tag: tip
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: remove all subrepos
|
o changeset: 8:3d35b3b681ad
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: replace subrepo with symlink
|
o changeset: 7:7ab2f3f0d2a2
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: replace symlink with subrepo
|
o changeset: 6:10077550ca45
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: add symlink
|
o changeset: 5:5ccecec21679
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: replace file with subrepo
|
o changeset: 4:a44b8fb5038d
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: replace subrepo with file
|
o changeset: 3:fa3b1061c069
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: add another subrepo
|
o changeset: 2:61810bd16e46
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: change subrepo commit
|
o changeset: 1:ab274969926a
| user: test <test@example.org>
| date: Mon Jan 01 00:00:11 2007 +0000
| summary: add subrepo
|
o changeset: 0:69982ec78c6d
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
$ hg book
* master 9:5ae8371d90fe
(add subrepo)
$ hg cat -r 1 .hgsubstate
6e4ad8da50204560c00fa25e4987eb2e239029ba subrepo
$ hg cat -r 1 .hgsub
subrepo = [git]../gitsubrepo
$ hg gverify -r 1
verifying rev ab274969926a against git commit e42b08b3cb7069b4594a4ee1d9cb641ee47b2355
(change subrepo commit)
$ hg cat -r 2 .hgsubstate
aa2ead20c29b5cc6256408e1d9ef704870033afb subrepo
$ hg cat -r 2 .hgsub
subrepo = [git]../gitsubrepo
$ hg gverify -r 2
verifying rev 61810bd16e46 against git commit a000567ceefbd9a2ce364e0dea6e298010b02b6d
(add another subrepo)
$ hg cat -r 3 .hgsubstate
aa2ead20c29b5cc6256408e1d9ef704870033afb subrepo
6e4ad8da50204560c00fa25e4987eb2e239029ba subrepo2
$ hg cat -r 3 .hgsub
subrepo = [git]../gitsubrepo
subrepo2 = [git]../gitsubrepo
$ hg gverify -r 3
verifying rev fa3b1061c069 against git commit 6e219527869fa40eb6ffbdd013cd86d576b26b01
(replace subrepo with file)
$ hg cat -r 4 .hgsubstate
6e4ad8da50204560c00fa25e4987eb2e239029ba subrepo2
$ hg cat -r 4 .hgsub
subrepo2 = [git]../gitsubrepo
$ hg manifest -r 4
.gitmodules
.hgsub
.hgsubstate
alpha
subrepo
$ hg gverify -r 4
verifying rev a44b8fb5038d against git commit f6436a472da00f581d8d257e9bbaf3c358a5e88c
(replace file with subrepo)
$ hg cat -r 5 .hgsubstate
6e4ad8da50204560c00fa25e4987eb2e239029ba alpha
6e4ad8da50204560c00fa25e4987eb2e239029ba subrepo2
$ hg cat -r 5 .hgsub
subrepo2 = [git]../gitsubrepo
alpha = [git]../gitsubrepo
$ hg manifest -r 5
.gitmodules
.hgsub
.hgsubstate
subrepo
$ hg gverify -r 5
verifying rev 5ccecec21679 against git commit 88171163bf4795b5570924e51d5f8ede33f8bc28
(replace symlink with subrepo)
XXX: The new logic in core is too strict but we don't really care about this usecase so
we just ignore this failure for now.
$ hg cat -r 7 .hgsub .hgsubstate
subrepo2 = [git]../gitsubrepo
alpha = [git]../gitsubrepo
foolink = [git]../gitsubrepo
6e4ad8da50204560c00fa25e4987eb2e239029ba alpha
6e4ad8da50204560c00fa25e4987eb2e239029ba foolink
6e4ad8da50204560c00fa25e4987eb2e239029ba subrepo2
abort: subrepo 'foolink' traverses symbolic link
[255]
$ hg gverify -r 7
verifying rev 7ab2f3f0d2a2 against git commit e3288fa737d429a60637b3b6782cb25b8298bc00
(replace subrepo with symlink)
$ hg cat -r 8 .hgsub .hgsubstate
subrepo2 = [git]../gitsubrepo
alpha = [git]../gitsubrepo
6e4ad8da50204560c00fa25e4987eb2e239029ba alpha
6e4ad8da50204560c00fa25e4987eb2e239029ba subrepo2
$ hg gverify -r 8
verifying rev 3d35b3b681ad against git commit d28364013fe1a0fde56c0e1921e49ecdeee8571d
(remove all subrepos)
$ hg cat -r 9 .hgsub .hgsubstate
.hgsub: no such file in rev 5ae8371d90fe
.hgsubstate: no such file in rev 5ae8371d90fe
[1]
$ hg gverify -r 9
verifying rev 5ae8371d90fe against git commit 15ba94929481c654814178aac1dbca06ae688718
$ hg gclear
clearing out the git cache data
$ hg gexport
$ cd .hg/git
$ git log --pretty=oneline
5029f164081f610d376405968d4588b823810838 remove all subrepos
80ac0dcee3a4f86fdb7bab740f737f2cd4b19182 replace subrepo with symlink
9c650056de9a0a417e5590a588bf4e942d378519 replace symlink with subrepo
0d13ab8294c9c35f5af94dc8af2ffc7f96fb395b add symlink
d3ce4262b9bc8e1f7f6497b8039627f073b77426 replace file with subrepo
71941511905ee6178d184519ff131468c2f84241 replace subrepo with file
83d542a647b4f08344e3937697efb936dcb1d178 add another subrepo
6e6d32168939af1a292dc85b5f737c95dbde349c change subrepo commit
14951d27ab1a586eede27e0b10e8d29f5b070743 add subrepo
205598a42833e532ad20d80414b8e3b85a65936e add alpha
test with rename detection enabled -- simply checking that the Mercurial hashes
are the same is enough
$ cd ../../..
$ hg --config git.similarity=100 clone gitrepo2 hgreporenames | grep -v '^updating'
importing git objects into hg
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd hgreporenames
$ hg log --graph
@ changeset: 9:5ae8371d90fe
| bookmark: master
| tag: default/master
| tag: tip
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: remove all subrepos
|
o changeset: 8:3d35b3b681ad
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: replace subrepo with symlink
|
o changeset: 7:7ab2f3f0d2a2
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: replace symlink with subrepo
|
o changeset: 6:10077550ca45
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: add symlink
|
o changeset: 5:5ccecec21679
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: replace file with subrepo
|
o changeset: 4:a44b8fb5038d
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: replace subrepo with file
|
o changeset: 3:fa3b1061c069
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: add another subrepo
|
o changeset: 2:61810bd16e46
| user: test <test@example.org>
| date: Mon Jan 01 00:00:12 2007 +0000
| summary: change subrepo commit
|
o changeset: 1:ab274969926a
| user: test <test@example.org>
| date: Mon Jan 01 00:00:11 2007 +0000
| summary: add subrepo
|
o changeset: 0:69982ec78c6d
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha

View File

@ -93,7 +93,7 @@ Remove the submodule and rename the file back:
$ cd hgrepo
$ hg book master -q
$ hg log -p --graph --template "{rev} {node} {desc|firstline}\n{join(extras, ' ')}\n\n"
@ 8 2e3567dd7aeb6c566bfe675119b2cc008d042c26 remove submodule and rename back
@ 8 144790f182a8d92e4134a20b0f8698854a9638b1 remove submodule and rename back
| branch=default convert_revision=50d116676a308b7c22935137d944e725d2296f2a hg-git-rename-source=git
|
| diff --git a/.gitmodules b/.gitmodules
@ -106,23 +106,11 @@ Remove the submodule and rename the file back:
| -[submodule "gamma"]
| - path = gamma
| - url = ../gitsubmodule
| diff --git a/.hgsub b/.hgsub
| --- a/.hgsub
| +++ b/.hgsub
| @@ -1,2 +1,1 @@
| gitsubmodule2 = [git]../gitsubmodule
| -gamma = [git]../gitsubmodule
| diff --git a/.hgsubstate b/.hgsubstate
| --- a/.hgsubstate
| +++ b/.hgsubstate
| @@ -1,2 +1,1 @@
| -5944b31ff85b415573d1a43eb942e2dea30ab8be gamma
| 5944b31ff85b415573d1a43eb942e2dea30ab8be gitsubmodule2
| diff --git a/gamma-new b/gamma
| rename from gamma-new
| rename to gamma
|
o 7 24a0764120d700b1701941eb3f67454157136836 rename and add submodule
o 7 f49a0c6fd69faeac5e247b5b37b8e7ce1b443e04 rename and add submodule
| branch=default convert_revision=59fb8e82ea18f79eab99196f588e8948089c134f hg-git-rename-source=git
|
| diff --git a/.gitmodules b/.gitmodules
@ -135,23 +123,11 @@ Remove the submodule and rename the file back:
| +[submodule "gamma"]
| + path = gamma
| + url = ../gitsubmodule
| diff --git a/.hgsub b/.hgsub
| --- a/.hgsub
| +++ b/.hgsub
| @@ -1,1 +1,2 @@
| gitsubmodule2 = [git]../gitsubmodule
| +gamma = [git]../gitsubmodule
| diff --git a/.hgsubstate b/.hgsubstate
| --- a/.hgsubstate
| +++ b/.hgsubstate
| @@ -1,1 +1,2 @@
| +5944b31ff85b415573d1a43eb942e2dea30ab8be gamma
| 5944b31ff85b415573d1a43eb942e2dea30ab8be gitsubmodule2
| diff --git a/gamma b/gamma-new
| rename from gamma
| rename to gamma-new
|
o 6 4dfc1ab4a0ecd9066e613d8728fc6347f910801d beta renamed back
o 6 2d38f1131e0beb3b73451640bb27e0df3cf3684e beta renamed back
| branch=default convert_revision=f95497455dfa891b4cd9b524007eb9514c3ab654 hg-git-rename-source=git
|
| diff --git a/beta b/beta
@ -192,7 +168,7 @@ Remove the submodule and rename the file back:
| -11
| -12
|
o 5 4bc4be232b3d6e53ddef658ef3d9ab142b3d0a0f beta renamed
o 5 024a72621ccff3ace020e03019c323d49c718be8 beta renamed
| branch=default convert_revision=055f482277da6cd3dd37c7093d06983bad68f782 hg-git-rename-source=git
|
| diff --git a/beta b/beta
@ -219,7 +195,7 @@ Remove the submodule and rename the file back:
| copy from beta
| copy to beta-new
|
o 4 ffad978ae6259b23aae39d566ec89d3af85a6c7a move submodule
o 4 b48620502e8b403e9d92f8ff353ee139e4e22bf8 move submodule
| branch=default convert_revision=d7f31298f27df8a9226eddb1e4feb96922c46fa5 hg-git-rename-source=git
|
| diff --git a/.gitmodules b/.gitmodules
@ -230,20 +206,8 @@ Remove the submodule and rename the file back:
| - path = gitsubmodule
| + path = gitsubmodule2
| url = ../gitsubmodule
| diff --git a/.hgsub b/.hgsub
| --- a/.hgsub
| +++ b/.hgsub
| @@ -1,1 +1,1 @@
| -gitsubmodule = [git]../gitsubmodule
| +gitsubmodule2 = [git]../gitsubmodule
| diff --git a/.hgsubstate b/.hgsubstate
| --- a/.hgsubstate
| +++ b/.hgsubstate
| @@ -1,1 +1,1 @@
| -5944b31ff85b415573d1a43eb942e2dea30ab8be gitsubmodule
| +5944b31ff85b415573d1a43eb942e2dea30ab8be gitsubmodule2
|
o 3 c8c8ef153360b7368535b6ca01b7e02a7998b67e add submodule
o 3 ea94d2142cbfdaceacb94bedfe29add896c49e47 add submodule
| branch=default convert_revision=c610256cb6959852d9e70d01902a06726317affc hg-git-rename-source=git
|
| diff --git a/.gitmodules b/.gitmodules
@ -254,18 +218,6 @@ Remove the submodule and rename the file back:
| +[submodule "gitsubmodule"]
| + path = gitsubmodule
| + url = ../gitsubmodule
| diff --git a/.hgsub b/.hgsub
| new file mode 100644
| --- /dev/null
| +++ b/.hgsub
| @@ -0,0 +1,1 @@
| +gitsubmodule = [git]../gitsubmodule
| diff --git a/.hgsubstate b/.hgsubstate
| new file mode 100644
| --- /dev/null
| +++ b/.hgsubstate
| @@ -0,0 +1,1 @@
| +5944b31ff85b415573d1a43eb942e2dea30ab8be gitsubmodule
|
o 2 e3e6b2083b5cc4382f611b16d23df93a40a19a00 gamma
| branch=default convert_revision=e1348449e0c3a417b086ed60fc13f068d4aa8b26 hg-git-rename-source=git
@ -338,8 +290,8 @@ Make a new commit with a copy and a rename in Mercurial
# User test
# Date 0 0
# Thu Jan 01 00:00:00 1970 +0000
# Node ID e01c1320d15c0a7abe4d30f3f71e03b2058a002f
# Parent 3c7e506adb7b7a2b82f887d2923ee4d955695ca2
# Node ID c84c4d95bbe6f146c5193dcf348fee3bb2bfb186
# Parent edad41eac39c7332b5981d564157cc59a46759a9
delta/epsilon
diff --git a/gamma b/delta
@ -413,8 +365,8 @@ Now make another clone and compare the hashes
# User test
# Date 0 0
# Thu Jan 01 00:00:00 1970 +0000
# Node ID 5ba38aef569229c46e403f4ab17c16520e40108e
# Parent 2423517f443d79f55da435dfc95b828bf7b56d94
# Node ID 8623d5155b015112f9ea55e0520fef982e4b488a
# Parent ae4f6d98d5bce684ec6ac796b8fd3319293b4264
delta/epsilon
diff --git a/gamma b/delta
@ -444,14 +396,14 @@ Regenerate the Git metadata and compare the hashes
$ hg gexport
$ cd .hg/git
$ git log master --pretty=oneline
9a60acf6a3a7cfaa723628d9f611f984ffdbe223 delta/epsilon
48cc0b1b9c2aa12caa72a86fd5d9a6dbbf392352 gamma2
44dbe9ba6dab7d29c312cd7001e9f1b5c52c612d remove submodule and rename back
fb9c13c5ac5994b47906f59376e999cbb7017327 rename and add submodule
dcdc3b83eec5f3b214e1cb5199edecf72d60de58 beta renamed back
e805d81c8372a4d0d6a22ec5abb35e3467043588 beta renamed
4899220730aca75da3f8f311f40bba30a7bd42ca move submodule
843e2dc46308ace4649dbc9c82ff87f2cf420e09 add submodule
a8febfd5b0396340f953924ea982b4a86a26bed3 delta/epsilon
dbda9582869f680cccbaebc680edd627a8fbc000 gamma2
15a10a2040f8f50b2d0f4f97bbffd6f05da07675 remove submodule and rename back
6dbd4a46e0da12500768f6963313d35fd19b8191 rename and add submodule
c2d6447a571e55aba88ed437051c81724500434d beta renamed back
0ea26deff913d7e9701bed3726ebf4686d9cf0cc beta renamed
8327069bf38e4ce8e8cf776a6d68fa151441916b move submodule
a49063ec760fa65a5aaf47f298a13222a0e3874d add submodule
00d2f34d2f9e2230ed49343b2b3eb14637b16c2e gamma
e3ddc25bf9b3a6a00e4379673ee2d9d6bbef720e beta
8557a753ca442f07736d74570a9cfebde4bf02e9 alpha

View File

@ -1,119 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ git init gitsubrepo
Initialized empty Git repository in $TESTTMP/gitsubrepo/.git/
$ cd gitsubrepo
$ echo beta > beta
$ git add beta
$ fn_git_commit -m 'add beta'
$ cd ..
$ git init gitrepo1
Initialized empty Git repository in $TESTTMP/gitrepo1/.git/
$ cd gitrepo1
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m 'add alpha'
$ git submodule add ../gitsubrepo subrepo1
Cloning into '*subrepo1'... (glob)
done.
$ fn_git_commit -m 'add subrepo1'
$ git submodule add ../gitsubrepo xyz/subrepo2
Cloning into '*xyz/subrepo2'... (glob)
done.
$ fn_git_commit -m 'add subrepo2'
we are going to push to this repo from our hg clone,
allow commits despite working copy presense
$ git config receive.denyCurrentBranch ignore
$ cd ..
Ensure gitlinks are transformed to .hgsubstate on hg pull from git
$ hg clone gitrepo1 hgrepo 2>&1 | egrep -v '^(Cloning into|done)'
importing git objects into hg
updating to branch default
cloning subrepo subrepo1 from $TESTTMP/gitsubrepo
cloning subrepo xyz/subrepo2 from $TESTTMP/gitsubrepo
4 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd hgrepo
$ hg bookmarks -f -r default master
1. Ensure gitlinks are transformed to .hgsubstate on hg <- git pull
.hgsub shall list two [git] subrepos
$ cat .hgsub | sort
subrepo1 = [git]../gitsubrepo
xyz/subrepo2 = [git]../gitsubrepo
.hgsubstate shall list two idenitcal revisions
$ cat .hgsubstate
56f0304c5250308f14cfbafdc27bd12d40154d17 subrepo1
56f0304c5250308f14cfbafdc27bd12d40154d17 xyz/subrepo2
hg status shall NOT report .hgsub and .hgsubstate as untracked - either ignored or unmodified
$ hg status --unknown .hgsub .hgsubstate
$ hg status --modified .hgsub .hgsubstate
$ cd ..
2. Check gitmodules are preserved during hg -> git push
$ cd gitsubrepo
$ echo gamma > gamma
$ git add gamma
$ fn_git_commit -m 'add gamma'
$ cd ..
$ cd hgrepo
$ cd xyz/subrepo2
$ git pull | sed 's/files/file/;s/insertions/insertion/;s/, 0 deletions.*//' | sed 's/| */| /'
From $TESTTMP/gitsubrepo
56f0304..aabf7cd master -> origin/master
Updating 56f0304..aabf7cd
Fast-forward
gamma | 1 +
1 file changed, 1 insertion(+)
create mode 100644 gamma
$ cd ../..
$ echo xxx >> alpha
$ hg commit -m 'Update subrepo2 from hg' | grep -v "committing subrepository" || true
$ hg push
pushing to $TESTTMP/gitrepo1
searching for changes
adding objects
added 1 commits with 2 trees and 1 blobs
updating reference refs/heads/master
$ cd ..
$ cd gitrepo1
there shall be two gitlink entries, with values matching that in .hgsubstate
$ git ls-tree -r "HEAD^{tree}" | grep 'commit'
160000 commit 56f0304c5250308f14cfbafdc27bd12d40154d17 subrepo1
160000 commit aabf7cd015089aff0b84596e69aa37b24a3d090a xyz/subrepo2
bring working copy to HEAD state (it's not bare repo)
$ git reset --hard
HEAD is now at ae335e3 Update subrepo2 from hg
$ cd ..
3. Check .hgsub and .hgsubstate from git repository are merged, not overwritten
$ hg init hgsub
$ cd hgsub
$ echo delta > delta
$ hg add delta
$ fn_hg_commit -m "add delta"
$ echo "`hg tip --template '{node}'` hgsub" > ../gitrepo1/.hgsubstate
$ echo "hgsub = `pwd`" > ../gitrepo1/.hgsub
$ cd ../gitrepo1
$ git add .hgsubstate .hgsub
$ fn_git_commit -m "Test3. Prepare .hgsub and .hgsubstate sources"
$ cd ../hgrepo
$ hg pull
pulling from $TESTTMP/gitrepo1
importing git objects into hg
(run 'hg update' to get a working copy)
$ hg checkout -C | egrep -v '^\(activating bookmark master\)$'
updating to active bookmark master
cloning subrepo hgsub from $TESTTMP/hgsub
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd ..
pull shall bring .hgsub entry which was added to the git repo
$ cat hgrepo/.hgsub | sort
hgsub = $TESTTMP/hgsub
subrepo1 = [git]../gitsubrepo
xyz/subrepo2 = [git]../gitsubrepo
.hgsubstate shall list revision of the subrepo added through git repo
$ cat hgrepo/.hgsubstate
481ec30d580f333ae3a77f94c973ce37b69d5bda hgsub
56f0304c5250308f14cfbafdc27bd12d40154d17 subrepo1
aabf7cd015089aff0b84596e69aa37b24a3d090a xyz/subrepo2

View File

@ -4,7 +4,7 @@ import os
import test_hgsubversion_util
from edenscm.hgext.hgsubversion import svnexternals
from edenscm.mercurial import commands, subrepo
from edenscm.mercurial import commands
class TestFetchExternals(test_hgsubversion_util.TestBase):
@ -191,111 +191,6 @@ class TestFetchExternals(test_hgsubversion_util.TestBase):
)
checkdeps(["subdir/deps/project1"], ["deps/project2"], repo, 4)
def test_hgsub(self):
if subrepo is None:
return
repo = self._load_fixture_and_fetch("externals.svndump", externals="subrepos")
self.assertEqual(
"""\
deps/project1 = [hgsubversion] :^/externals/project1 deps/project1
""",
repo[0][".hgsub"].data(),
)
self.assertEqual(
"""\
HEAD deps/project1
""",
repo[0][".hgsubstate"].data(),
)
self.assertEqual(
"""\
deps/project1 = [hgsubversion] :^/externals/project1 deps/project1
deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
""",
repo[1][".hgsub"].data(),
)
self.assertEqual(
"""\
HEAD deps/project1
2 deps/project2
""",
repo[1][".hgsubstate"].data(),
)
self.assertEqual(
"""\
deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
subdir/deps/project1 = [hgsubversion] subdir:^/externals/project1 deps/project1
subdir2/deps/project1 = [hgsubversion] subdir2:^/externals/project1 deps/project1
""",
repo[2][".hgsub"].data(),
)
self.assertEqual(
"""\
2 deps/project2
HEAD subdir/deps/project1
HEAD subdir2/deps/project1
""",
repo[2][".hgsubstate"].data(),
)
self.assertMultiLineEqual(
"""\
deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
subdir/deps/project1 = [hgsubversion] subdir:^/externals/project1 deps/project1
""",
repo[3][".hgsub"].data(),
)
self.assertEqual(
"""\
2 deps/project2
HEAD subdir/deps/project1
""",
repo[3][".hgsubstate"].data(),
)
self.assertEqual(
"""\
subdir/deps/project1 = [hgsubversion] subdir:^/externals/project1 deps/project1
""",
repo[4][".hgsub"].data(),
)
self.assertEqual(
"""\
HEAD subdir/deps/project1
""",
repo[4][".hgsubstate"].data(),
)
self.assertEqual(
"""\
deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
subdir2/deps/project1 = [hgsubversion] subdir2:^/externals/project1 deps/project1
""",
repo[5][".hgsub"].data(),
)
self.assertEqual(
"""\
2 deps/project2
HEAD subdir2/deps/project1
""",
repo[5][".hgsubstate"].data(),
)
self.assertEqual(
"""\
deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
""",
repo[6][".hgsub"].data(),
)
self.assertEqual(
"""\
2 deps/project2
""",
repo[6][".hgsubstate"].data(),
)
def test_ignore(self):
repo = self._load_fixture_and_fetch("externals.svndump", externals="ignore")
for rev in repo:
@ -304,63 +199,6 @@ deps/project2 = [hgsubversion] :-r{REV} ^/externals/project2@2 deps/project2
self.assertTrue(".hgsub" not in ctx)
self.assertTrue(".hgsubstate" not in ctx)
def test_updatehgsub(self):
def checkdeps(ui, repo, rev, deps, nodeps):
commands.update(ui, repo, node=str(rev))
for d in deps:
p = os.path.join(repo.root, d)
self.assertTrue(
os.path.isdir(p), "missing: %s@%r" % (d, repo[None].rev())
)
for d in nodeps:
p = os.path.join(repo.root, d)
self.assertTrue(
not os.path.isdir(p), "unexpected: %s@%r" % (d, repo[None].rev())
)
if subrepo is None:
return
ui = self.ui()
repo = self._load_fixture_and_fetch("externals.svndump", externals="subrepos")
checkdeps(ui, repo, 0, ["deps/project1"], [])
checkdeps(ui, repo, 1, ["deps/project1", "deps/project2"], [])
checkdeps(
ui,
repo,
2,
["subdir/deps/project1", "subdir2/deps/project1", "deps/project2"],
["deps/project1"],
)
checkdeps(
ui,
repo,
3,
["subdir/deps/project1", "deps/project2"],
["subdir2/deps/project1"],
)
checkdeps(ui, repo, 4, ["subdir/deps/project1"], ["deps/project2"])
# Test update --clean, used to crash
repo.wwrite("subdir/deps/project1/a", "foobar", "")
commands.update(ui, repo, node="4", clean=True)
def test_mergeexternals(self):
if subrepo is None:
return
repo = self._load_fixture_and_fetch(
"mergeexternals.svndump", externals="subrepos"
)
# Check merged directories externals are fine
self.assertEqual(
"""\
d1/ext = [hgsubversion] d1:^/trunk/common/ext ext
d2/ext = [hgsubversion] d2:^/trunk/common/ext ext
d3/ext3 = [hgsubversion] d3:^/trunk/common/ext ext3
""",
repo["tip"][".hgsub"].data(),
)
class TestPushExternals(test_hgsubversion_util.TestBase):
stupid_mode_tests = True
@ -415,108 +253,6 @@ class TestPushExternals(test_hgsubversion_util.TestBase):
self.pushrevisions()
self.assertchanges(changes, self.repo["tip"])
def test_push_hgsub(self):
if subrepo is None:
return
repo, repo_path = self.load_and_fetch(
"pushexternals.svndump", externals="subrepos"
)
# Add a new reference on an existing and non-existing directory
changes = [
(
".hgsub",
".hgsub",
"""\
dir/deps/project2 = [hgsubversion] dir:^/externals/project2 deps/project2
subdir1/deps/project1 = [hgsubversion] subdir1:^/externals/project1 deps/project1
subdir2/deps/project2 = [hgsubversion] subdir2:^/externals/project2 deps/project2
""",
),
(
".hgsubstate",
".hgsubstate",
"""\
HEAD dir/deps/project2
HEAD subdir1/deps/project1
HEAD subdir2/deps/project2
""",
),
("subdir1/a", "subdir1/a", "a"),
("subdir2/a", "subdir2/a", "a"),
]
self.svnco(repo_path, "externals/project2", "2", "dir/deps/project2")
self.svnco(repo_path, "externals/project1", "2", "subdir1/deps/project1")
self.svnco(repo_path, "externals/project2", "2", "subdir2/deps/project2")
self.commitchanges(changes)
self.pushrevisions()
self.assertchanges(changes, self.repo["tip"])
# Check .hgsub and .hgsubstate were not pushed
self.assertEqual(
["dir", "subdir1", "subdir1/a", "subdir2", "subdir2/a"],
test_hgsubversion_util.svnls(repo_path, "trunk"),
)
# Remove all references from one directory, add a new one
# to the other (test multiline entries)
changes = [
(
".hgsub",
".hgsub",
"""\
subdir1/deps/project1 = [hgsubversion] subdir1:^/externals/project1 deps/project1
subdir1/deps/project2 = [hgsubversion] subdir1:^/externals/project2 deps/project2
""",
),
(
".hgsubstate",
".hgsubstate",
"""\
HEAD subdir1/deps/project1
HEAD subdir1/deps/project2
""",
),
# This removal used to trigger the parent directory removal
("subdir1/a", None, None),
]
self.svnco(repo_path, "externals/project1", "2", "subdir1/deps/project1")
self.svnco(repo_path, "externals/project2", "2", "subdir1/deps/project2")
self.commitchanges(changes)
self.pushrevisions()
self.assertchanges(changes, self.repo["tip"])
# Check subdir2/a is still there even if the externals were removed
self.assertTrue("subdir2/a" in self.repo["tip"])
self.assertTrue("subdir1/a" not in self.repo["tip"])
# Move the externals so they are defined on the base directory,
# this used to cause full branch removal when deleting the .hgsub
changes = [
(
".hgsub",
".hgsub",
"""\
subdir1/deps/project1 = [hgsubversion] :^/externals/project1 subdir1/deps/project1
""",
),
(
".hgsubstate",
".hgsubstate",
"""\
HEAD subdir1/deps/project1
""",
),
]
self.commitchanges(changes)
self.pushrevisions()
self.assertchanges(changes, self.repo["tip"])
# Test externals removal
changes = [(".hgsub", None, None), (".hgsubstate", None, None)]
self.commitchanges(changes)
self.pushrevisions()
self.assertchanges(changes, self.repo["tip"])
if __name__ == "__main__":
import silenttestrunner

View File

@ -157,15 +157,6 @@ class MapTests(test_hgsubversion_util.TestBase):
)
return self.repo
@test_hgsubversion_util.requiresreplay
def test_file_map(self):
repo = self._loadwithfilemap(
"replace_trunk_with_branch.svndump", "include alpha\n"
)
self.assertEqual(
node.hex(repo[0].node()), "88e2c7492d83e4bf30fbb2dcbf6aa24d60ac688d"
)
@test_hgsubversion_util.requiresreplay
def test_file_map_exclude(self):
repo = self._loadwithfilemap(

View File

@ -32,9 +32,9 @@ Different encoding:
Test keyword search in translated help text:
$ HGENCODING=UTF-8 LANGUAGE=de hg help -k Aktualisiert
Themen:
subrepos Unterarchive
Abbruch: no matches
(try 'hg help' for a list of topics)
[255]
#endif

View File

@ -503,7 +503,6 @@ incoming from empty remote repository
comparing with r2
searching for changes
no changes found
[1]
Create a "split" repo that pulls from r1 and pushes to r2, using default-push

View File

@ -1,133 +0,0 @@
$ . helpers-usechg.sh
$ hg init
$ echo a > a
$ hg ci -qAm 'add a'
$ hg init subrepo
$ echo 'subrepo = http://example.net/libfoo' > .hgsub
$ hg ci -qAm 'added subrepo'
$ hg up -qC 0
$ echo ax > a
$ hg ci -m 'changed a'
$ hg up -qC 1
$ cd subrepo
$ echo b > b
$ hg add b
$ cd ..
Should fail, since there are added files to subrepo:
$ hg merge
abort: uncommitted changes in subrepository "subrepo"
[255]
Deleted files trigger a '+' marker in top level repos. Deleted files are also
noticed by `update --check` in the top level repo.
$ hg ci -Sqm 'add b'
$ echo change > subrepo/b
$ hg ci -Sm 'change b'
committing subrepository subrepo
$ rm a
$ hg id
9bfe45a197d7+ tip
$ hg sum
parent: 4:9bfe45a197d7 tip
change b
commit: 1 deleted (clean)
phases: 5 draft
$ hg up --check -r '.^'
abort: uncommitted changes
[255]
$ hg st -S
! a
$ hg up -Cq .
Test that dirty is consistent through subrepos
$ rm subrepo/b
A deleted subrepo file is flagged as dirty, like the top level repo
$ hg id --config extensions.blackbox= --config blackbox.dirty=True
9bfe45a197d7+ tip
$ cat .hg/blackbox.log
* @9bfe45a197d7b0ab09bf287729dd57e9619c9da5+ (*)> serve --cmdserver chgunix * (glob) (chg !)
* @9bfe45a197d7b0ab09bf287729dd57e9619c9da5+ (*)> id --config *extensions.blackbox=* --config *blackbox.dirty=True* (glob)
* @9bfe45a197d7b0ab09bf287729dd57e9619c9da5+ (*)> id --config *extensions.blackbox=* --config *blackbox.dirty=True* exited 0 * (glob) (?)
TODO: a deleted file should be listed as such, like the top level repo
$ hg sum
parent: 4:9bfe45a197d7 tip
change b
commit: (clean)
phases: 5 draft
Modified subrepo files are noticed by `update --check` and `summary`
$ echo mod > subrepo/b
$ hg st -S
M subrepo/b
$ hg up -r '.^' --check
abort: uncommitted changes in subrepository "subrepo"
[255]
$ hg sum
parent: 4:9bfe45a197d7 tip
change b
commit: 1 subrepos
phases: 5 draft
TODO: why is -R needed here? If it's because the subrepo is treated as a
discrete unit, then this should probably warn or something.
$ hg revert -R subrepo --no-backup subrepo/b -r .
$ rm subrepo/b
$ hg st -S
! subrepo/b
`hg update --check` notices a subrepo with a missing file, like it notices a
missing file in the top level repo.
$ hg up -r '.^' --check
abort: uncommitted changes in subrepository "subrepo"
[255]
$ hg up -r '.^' --config ui.interactive=True << EOF
> d
> EOF
other [destination] changed b which local [working copy] deleted
use (c)hanged version, leave (d)eleted, or leave (u)nresolved? d
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
XXX: There's a difference between wdir() and '.', so there should be a status.
`hg files -S` from the top is also missing 'subrepo/b'.
$ hg st -S
$ hg st -R subrepo
$ hg files -R subrepo
[1]
$ hg files -R subrepo -r '.'
subrepo/b
$ hg bookmark -r tip @other
$ echo xyz > subrepo/c
$ hg ci -SAm 'add c'
adding subrepo/c
committing subrepository subrepo
$ rm subrepo/c
Merge sees deleted subrepo files as an uncommitted change
$ hg merge @other
abort: uncommitted changes in subrepository "subrepo"
[255]

View File

@ -22,12 +22,10 @@ with paths:
$ hg in dupe
comparing with $TESTTMP/b
no changes found
[1]
$ cd ..
$ hg -R a in dupe
comparing with $TESTTMP/b
no changes found
[1]
$ cd a
$ hg paths
dupe = $TESTTMP/b#tip

View File

@ -119,18 +119,6 @@ Abort pull early with pending uncommitted merge:
[255]
$ hg update --clean --quiet
Abort pull early with unclean subrepo:
$ echo s = s > .hgsub
$ hg add .hgsub
$ hg init s
$ hg commit -m "generated a subrepo"
$ echo a > s/a
$ hg -R s add s/a
$ hg pull --rebase
abort: uncommitted changes in subrepository "s"
(cannot pull with rebase: please commit or shelve your changes first)
[255]
Invoke pull --rebase and nothing to rebase:
$ cd ../c

View File

@ -55,7 +55,6 @@ Record help
-b --ignore-space-change ignore changes in the amount of white space
-B --ignore-blank-lines ignore changes whose lines are all blank
-Z --ignore-space-at-eol ignore changes in whitespace at EOL
-S --subrepos recurse into subrepositories
-I --include PATTERN [+] include names matching the given patterns
-X --exclude PATTERN [+] exclude names matching the given patterns

View File

@ -138,61 +138,6 @@ Test pushrev configuration option
(use --allow-anon to override this warning)
[255]
Test traditional push with subrepo
$ cd ../repo1
$ hg init nested
$ cd nested
$ hg bookmark @
$ cd ..
$ cd ../repo2
$ hg init nested
$ cd nested
$ echo a > a
$ hg commit -qAm 'aa'
$ hg bookmark @
$ cd ..
$ echo nested=nested > .hgsub
$ hg add .hgsub
$ hg commit -m sub
$ hg push
pushing to ssh://user@dummy/repo1
pushing subrepo nested to ssh://user@dummy/repo1/nested
searching for changes
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 1 changesets with 1 changes to 1 files
updating bookmark @
searching for changes
abort: push would create new anonymous heads (296c645d2a63)
(use --allow-anon to override this warning)
[255]
$ hg bookmark @
$ hg push
pushing to ssh://user@dummy/repo1
no changes made to subrepo nested since last push to ssh://user@dummy/repo1/nested
searching for changes
abort: push would create new anonymous heads (296c645d2a63)
(use --allow-anon to override this warning)
[255]
$ hg push --to @
pushing rev 296c645d2a63 to destination ssh://user@dummy/repo1 bookmark @
searching for changes
abort: not creating new remote bookmark
(use --create to create a new bookmark)
[255]
$ hg push -B @
pushing to ssh://user@dummy/repo1
no changes made to subrepo nested since last push to ssh://user@dummy/repo1/nested
searching for changes
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 2 changesets with 3 changes to 3 files (+1 heads)
exporting bookmark @
$ cd ..
Set up server repo
$ hg init rnserver
$ cd rnserver
@ -226,7 +171,7 @@ creation of a new one (locally unknonw).
Force client to get data about new bookmarks without getting commits
$ cd rnclient
$ hg push
pushing to $TESTTMP/rnserver (glob)
pushing to $TESTTMP/repo2/rnserver
searching for changes
no changes found
[1]

View File

@ -1498,7 +1498,7 @@ Test matching
$ log 'matching(6)'
6
$ log 'matching(6:7, "phase parents user date branch summary files description substate")'
$ log 'matching(6:7, "phase parents user date branch summary files description")'
6
7

View File

@ -32,7 +32,6 @@ http scheme
comparing with l://
searching for changes
no changes found
[1]
check that {1} syntax works
@ -45,7 +44,6 @@ check that {1} syntax works
searching for changes
all remote heads known locally
no changes found
[1]
check that paths are expanded
@ -53,7 +51,6 @@ check that paths are expanded
comparing with z://
searching for changes
no changes found
[1]
check that debugexpandscheme outputs the canonical form

File diff suppressed because it is too large Load Diff

View File

@ -1,140 +0,0 @@
$ hg init repo
$ cd repo
$ hg init subrepo
$ echo a > subrepo/a
$ hg -R subrepo ci -Am adda
adding a
$ echo 'subrepo = subrepo' > .hgsub
$ hg ci -Am addsubrepo
adding .hgsub
$ echo b > subrepo/b
$ hg -R subrepo ci -Am addb
adding b
$ hg ci -m updatedsub
ignore blanklines in .hgsubstate
>>> file('.hgsubstate', 'wb').write('\n\n \t \n \n')
$ hg st --subrepos
M .hgsubstate
$ hg revert -qC .hgsubstate
abort more gracefully on .hgsubstate parsing error
$ cp .hgsubstate .hgsubstate.old
>>> file('.hgsubstate', 'wb').write('\ninvalid')
$ hg st --subrepos --cwd $TESTTMP -R $TESTTMP/repo
abort: invalid subrepository revision specifier in 'repo/.hgsubstate' line 2
[255]
$ mv .hgsubstate.old .hgsubstate
delete .hgsub and revert it
$ rm .hgsub
$ hg revert .hgsub
warning: subrepo spec file '.hgsub' not found
warning: subrepo spec file '.hgsub' not found
delete .hgsubstate and revert it
$ rm .hgsubstate
$ hg revert .hgsubstate
delete .hgsub and update
$ rm .hgsub
$ hg up 0 --cwd $TESTTMP -R $TESTTMP/repo
warning: subrepo spec file 'repo/.hgsub' not found
warning: subrepo spec file 'repo/.hgsub' not found
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg st
warning: subrepo spec file '.hgsub' not found
! .hgsub
$ ls subrepo
a
delete .hgsubstate and update
$ hg up -C
warning: subrepo spec file '.hgsub' not found
warning: subrepo spec file '.hgsub' not found
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ rm .hgsubstate
$ hg up 0
other [destination] changed .hgsubstate which local [working copy] deleted
use (c)hanged version or leave (d)eleted? c
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg st
$ ls subrepo
a
Enable obsolete
$ cat >> $HGRCPATH << EOF
> [ui]
> logtemplate= {rev}:{node|short} {desc|firstline}
> [phases]
> publish=False
> [experimental]
> evolution.createmarkers=True
> EOF
check that we can update parent repo with missing (amended) subrepo revision
$ hg up --repository subrepo -r tip
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg ci -m "updated subrepo to tip"
$ cd subrepo
$ hg update -r tip
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo foo > a
$ hg commit --amend -m "addb (amended)"
$ cd ..
$ hg update --clean .
revision 102a90ea7b4a in subrepository "subrepo" is hidden
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
check that --hidden is propagated to the subrepo
$ hg -R subrepo up tip
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg ci -m 'commit with amended subrepo'
$ echo bar > subrepo/a
$ hg -R subrepo ci --amend -m "amend a (again)"
$ hg --hidden cat subrepo/a
foo
verify will warn if locked-in subrepo revisions are hidden or missing
$ hg ci -m "amended subrepo (again)"
$ hg --hidden debugstrip -R subrepo -qr 'tip' --config devel.strip-obsmarkers=no
$ hg verify
checking changesets
checking manifests
crosschecking files in changesets and manifests
checking files
2 files, 5 changesets, 5 total revisions
checking subrepo links
subrepo 'subrepo' is hidden in revision a66de08943b6
subrepo 'subrepo' is hidden in revision 674d05939c1e
subrepo 'subrepo' not found in revision a7d05d9055a4
verifying shouldn't init a new subrepo if the reference doesn't exist
$ mv subrepo b
$ hg verify
checking changesets
checking manifests
crosschecking files in changesets and manifests
checking files
2 files, 5 changesets, 5 total revisions
checking subrepo links
0: repository $TESTTMP/repo/subrepo not found
1: repository $TESTTMP/repo/subrepo not found
3: repository $TESTTMP/repo/subrepo not found
4: repository $TESTTMP/repo/subrepo not found
$ ls
b
$ mv b subrepo
$ cd ..

View File

@ -1,61 +0,0 @@
$ hg init outer
$ cd outer
$ echo '[paths]' >> .hg/hgrc
$ echo 'default = http://example.net/' >> .hg/hgrc
hg debugsub with no remapping
$ echo 'sub = libfoo' > .hgsub
$ hg add .hgsub
$ hg debugsub
path sub
source libfoo
revision
hg debugsub with remapping
$ echo '[subpaths]' >> .hg/hgrc
$ printf 'http://example.net/lib(.*) = C:\\libs\\\\1-lib\\\n' >> .hg/hgrc
$ hg debugsub
path sub
source C:\libs\foo-lib\
revision
test cumulative remapping, the $HGRCPATH file is loaded first
$ echo '[subpaths]' >> $HGRCPATH
$ echo 'libfoo = libbar' >> $HGRCPATH
$ hg debugsub
path sub
source C:\libs\bar-lib\
revision
test absolute source path -- testing with a URL is important since
standard os.path.join wont treat that as an absolute path
$ echo 'abs = http://example.net/abs' > .hgsub
$ hg debugsub
path abs
source http://example.net/abs
revision
$ echo 'abs = /abs' > .hgsub
$ hg debugsub
path abs
source /abs
revision
test bad subpaths pattern
$ cat > .hg/hgrc <<EOF
> [subpaths]
> .* = \1
> EOF
$ hg debugsub
abort: bad subrepository pattern in $TESTTMP/outer/.hg/hgrc:2: invalid group reference
[255]
$ cd ..

View File

@ -1,585 +0,0 @@
#require no-fsmonitor
Create test repository:
$ hg init repo
$ cd repo
$ echo x1 > x.txt
$ hg init foo
$ cd foo
$ echo y1 > y.txt
$ hg init bar
$ cd bar
$ echo z1 > z.txt
$ cd ..
$ echo 'bar = bar' > .hgsub
$ cd ..
$ echo 'foo = foo' > .hgsub
Add files --- .hgsub files must go first to trigger subrepos:
$ hg add -S .hgsub
$ hg add -S foo/.hgsub
$ hg add -S foo/bar
adding foo/bar/z.txt
$ hg add -S
adding x.txt
adding foo/y.txt
Test recursive status without committing anything:
$ hg status -S
A .hgsub
A foo/.hgsub
A foo/bar/z.txt
A foo/y.txt
A x.txt
Test recursive diff without committing anything:
$ hg diff --nodates -S foo
diff -r 000000000000 foo/.hgsub
--- /dev/null
+++ b/foo/.hgsub
@@ -0,0 +1,1 @@
+bar = bar
diff -r 000000000000 foo/y.txt
--- /dev/null
+++ b/foo/y.txt
@@ -0,0 +1,1 @@
+y1
diff -r 000000000000 foo/bar/z.txt
--- /dev/null
+++ b/foo/bar/z.txt
@@ -0,0 +1,1 @@
+z1
Commits:
$ hg commit -m fails
abort: uncommitted changes in subrepository "foo"
(use --subrepos for recursive commit)
[255]
The --subrepos flag overwrite the config setting:
$ hg commit -m 0-0-0 --config ui.commitsubrepos=No --subrepos
committing subrepository foo
committing subrepository foo/bar
$ cd foo
$ echo y2 >> y.txt
$ hg commit -m 0-1-0
$ cd bar
$ echo z2 >> z.txt
$ hg commit -m 0-1-1
$ cd ..
$ hg commit -m 0-2-1
$ cd ..
$ hg commit -m 1-2-1
Change working directory:
$ echo y3 >> foo/y.txt
$ echo z3 >> foo/bar/z.txt
$ hg status -S
M foo/bar/z.txt
M foo/y.txt
$ hg diff --nodates -S
diff -r d254738c5f5e foo/y.txt
--- a/foo/y.txt
+++ b/foo/y.txt
@@ -1,2 +1,3 @@
y1
y2
+y3
diff -r 9647f22de499 foo/bar/z.txt
--- a/foo/bar/z.txt
+++ b/foo/bar/z.txt
@@ -1,2 +1,3 @@
z1
z2
+z3
Status call crossing repository boundaries:
$ hg status -S foo/bar/z.txt
M foo/bar/z.txt
$ hg status -S -I 'foo/?.txt'
M foo/y.txt
$ hg status -S -I '**/?.txt'
M foo/bar/z.txt
M foo/y.txt
$ hg diff --nodates -S -I '**/?.txt'
diff -r d254738c5f5e foo/y.txt
--- a/foo/y.txt
+++ b/foo/y.txt
@@ -1,2 +1,3 @@
y1
y2
+y3
diff -r 9647f22de499 foo/bar/z.txt
--- a/foo/bar/z.txt
+++ b/foo/bar/z.txt
@@ -1,2 +1,3 @@
z1
z2
+z3
Status from within a subdirectory:
$ mkdir dir
$ cd dir
$ echo a1 > a.txt
$ hg status -S
M foo/bar/z.txt
M foo/y.txt
? dir/a.txt
$ hg diff --nodates -S
diff -r d254738c5f5e foo/y.txt
--- a/foo/y.txt
+++ b/foo/y.txt
@@ -1,2 +1,3 @@
y1
y2
+y3
diff -r 9647f22de499 foo/bar/z.txt
--- a/foo/bar/z.txt
+++ b/foo/bar/z.txt
@@ -1,2 +1,3 @@
z1
z2
+z3
Status with relative path:
$ hg status -S ..
M ../foo/bar/z.txt
M ../foo/y.txt
? a.txt
$ hg diff --nodates -S ..
diff -r d254738c5f5e foo/y.txt
--- a/foo/y.txt
+++ b/foo/y.txt
@@ -1,2 +1,3 @@
y1
y2
+y3
diff -r 9647f22de499 foo/bar/z.txt
--- a/foo/bar/z.txt
+++ b/foo/bar/z.txt
@@ -1,2 +1,3 @@
z1
z2
+z3
$ cd ..
Cleanup and final commit:
$ rm -r dir
$ hg commit --subrepos -m 2-3-2
committing subrepository foo
committing subrepository foo/bar
Test explicit path commands within subrepos: add/forget
$ echo z1 > foo/bar/z2.txt
$ hg status -S
? foo/bar/z2.txt
$ hg add foo/bar/z2.txt
$ hg status -S
A foo/bar/z2.txt
$ hg forget foo/bar/z2.txt
$ hg status -S
? foo/bar/z2.txt
$ hg forget foo/bar/z2.txt
not removing foo/bar/z2.txt: file is already untracked
[1]
$ hg status -S
? foo/bar/z2.txt
$ rm foo/bar/z2.txt
Log with the relationships between repo and its subrepo:
$ hg log --template '{rev}:{node|short} {desc}\n'
2:1326fa26d0c0 2-3-2
1:4b3c9ff4f66b 1-2-1
0:23376cbba0d8 0-0-0
$ hg -R foo log --template '{rev}:{node|short} {desc}\n'
3:65903cebad86 2-3-2
2:d254738c5f5e 0-2-1
1:8629ce7dcc39 0-1-0
0:af048e97ade2 0-0-0
$ hg -R foo/bar log --template '{rev}:{node|short} {desc}\n'
2:31ecbdafd357 2-3-2
1:9647f22de499 0-1-1
0:4904098473f9 0-0-0
Status between revisions:
$ hg status -S
$ hg status -S --rev 0:1
M .hgsubstate
M foo/.hgsubstate
M foo/bar/z.txt
M foo/y.txt
$ hg diff --nodates -S -I '**/?.txt' --rev 0:1
diff -r af048e97ade2 -r d254738c5f5e foo/y.txt
--- a/foo/y.txt
+++ b/foo/y.txt
@@ -1,1 +1,2 @@
y1
+y2
diff -r 4904098473f9 -r 9647f22de499 foo/bar/z.txt
--- a/foo/bar/z.txt
+++ b/foo/bar/z.txt
@@ -1,1 +1,2 @@
z1
+z2
#if serve
$ cd ..
$ hg serve -R repo --debug -S -p 0 --port-file .p -d --pid-file=hg1.pid -E error.log -A access.log
adding = $TESTTMP/repo
adding foo = $TESTTMP/repo/foo
adding foo/bar = $TESTTMP/repo/foo/bar
listening at http://*:$HGPORT/ (bound to *:$HGPORT) (glob) (?)
adding = $TESTTMP/repo (?)
adding foo = $TESTTMP/repo/foo (?)
adding foo/bar = $TESTTMP/repo/foo/bar (?)
$ HGPORT=`cat .p`
$ rm .p
$ cat hg1.pid >> $DAEMON_PIDS
$ hg clone http://localhost:$HGPORT clone
requesting all changes
adding changesets
adding manifests
adding file changes
added 3 changesets with 5 changes to 3 files
new changesets 23376cbba0d8:1326fa26d0c0
updating to branch default
cloning subrepo foo from http://localhost:$HGPORT/foo (glob)
requesting all changes
adding changesets
adding manifests
adding file changes
added 4 changesets with 7 changes to 3 files
new changesets af048e97ade2:65903cebad86
cloning subrepo foo/bar from http://localhost:$HGPORT/foo/bar (glob)
requesting all changes
adding changesets
adding manifests
adding file changes
added 3 changesets with 3 changes to 1 files
new changesets 4904098473f9:31ecbdafd357
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cat clone/foo/bar/z.txt
z1
z2
z3
$ cat access.log
* "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
* "GET /?cmd=batch HTTP/1.1" 200 - * (glob)
* "GET /?cmd=getbundle HTTP/1.1" 200 - * (glob)
* "GET /foo?cmd=capabilities HTTP/1.1" 200 - (glob)
* "GET /foo?cmd=batch HTTP/1.1" 200 - * (glob)
* "GET /foo?cmd=getbundle HTTP/1.1" 200 - * (glob)
* "GET /foo/bar?cmd=capabilities HTTP/1.1" 200 - (glob)
* "GET /foo/bar?cmd=batch HTTP/1.1" 200 - * (glob)
* "GET /foo/bar?cmd=getbundle HTTP/1.1" 200 - * (glob)
$ killdaemons.py
$ rm hg1.pid error.log access.log
$ cd repo
#endif
Enable progress debugging archive tests:
$ cp $HGRCPATH $HGRCPATH.no-progress
$ cat >> $HGRCPATH <<EOF
> [progress]
> debug = True
> EOF
Test archiving to a directory tree (the doubled lines in the output
only show up in the test output, not in real usage):
$ hg archive --subrepos ../archive
progress: archiving: .hgsub 1/3 files (33.33%)
progress: archiving: .hgsubstate 2/3 files (66.67%)
progress: archiving: x.txt 3/3 files (100.00%)
progress: archiving (end)
progress: archiving (foo): 1/3 files (33.33%)
progress: archiving (foo): 2/3 files (66.67%)
progress: archiving (foo): 3/3 files (100.00%)
progress: archiving (foo) (end)
progress: archiving (foo/bar): 1/1 files (100.00%)
progress: archiving (foo/bar) (end)
$ find ../archive | sort
../archive
../archive/.hg_archival.txt
../archive/.hgsub
../archive/.hgsubstate
../archive/foo
../archive/foo/.hgsub
../archive/foo/.hgsubstate
../archive/foo/bar
../archive/foo/bar/z.txt
../archive/foo/y.txt
../archive/x.txt
Test archiving to zip file (unzip output is unstable):
$ hg archive --subrepos --prefix '.' ../archive.zip
progress: archiving: .hgsub 1/3 files (33.33%)
progress: archiving: .hgsubstate 2/3 files (66.67%)
progress: archiving: x.txt 3/3 files (100.00%)
progress: archiving (end)
progress: archiving (foo): 1/3 files (33.33%)
progress: archiving (foo): 2/3 files (66.67%)
progress: archiving (foo): 3/3 files (100.00%)
progress: archiving (foo) (end)
progress: archiving (foo/bar): 1/1 files (100.00%)
progress: archiving (foo/bar) (end)
(unzip date formating is unstable, we do not care about it and glob it out)
$ unzip -l ../archive.zip | grep -v -- ----- | egrep -v files$
Archive: ../archive.zip
Length [ ]* Date [ ]* Time [ ]* Name (re)
172 [0-9:\- ]* .hg_archival.txt (re)
10 [0-9:\- ]* .hgsub (re)
45 [0-9:\- ]* .hgsubstate (re)
3 [0-9:\- ]* x.txt (re)
10 [0-9:\- ]* foo/.hgsub (re)
45 [0-9:\- ]* foo/.hgsubstate (re)
9 [0-9:\- ]* foo/y.txt (re)
9 [0-9:\- ]* foo/bar/z.txt (re)
Test archiving a revision that references a subrepo that is not yet
cloned:
#if hardlink
$ hg clone -U . ../empty
progress: linking: 1
progress: linking: 2
progress: linking: 3
progress: linking: 4
progress: linking: 5
progress: linking: 6
progress: linking: 7
progress: linking: 8
progress: linking (end)
#else
$ hg clone -U . ../empty
progress: linking: 1
#endif
$ cd ../empty
#if hardlink
$ hg archive --subrepos -r tip --prefix './' ../archive.tar.gz
progress: archiving: .hgsub 1/3 files (33.33%)
progress: archiving: .hgsubstate 2/3 files (66.67%)
progress: archiving: x.txt 3/3 files (100.00%)
progress: archiving (end)
cloning subrepo foo from $TESTTMP/repo/foo
progress: linking: 1
progress: linking: 2
progress: linking: 3
progress: linking: 4
progress: linking: 5
progress: linking: 6
progress: linking: 7
progress: linking: 8
progress: linking (end)
progress: archiving (foo): 1/3 files (33.33%)
progress: archiving (foo): 2/3 files (66.67%)
progress: archiving (foo): 3/3 files (100.00%)
progress: archiving (foo) (end)
cloning subrepo foo/bar from $TESTTMP/repo/foo/bar
progress: linking: 1
progress: linking: 2
progress: linking: 3
progress: linking: 4
progress: linking: 5
progress: linking: 6
progress: linking (end)
progress: archiving (foo/bar): 1/1 files (100.00%)
progress: archiving (foo/bar) (end)
#else
Note there's a slight output glitch on non-hardlink systems: the last
"linking" progress topic never gets closed, leading to slight output corruption on that platform.
$ hg archive --subrepos -r tip --prefix './' ../archive.tar.gz
progress: archiving: .hgsub 1/3 files (33.33%)
progress: archiving: .hgsubstate 2/3 files (66.67%)
progress: archiving: x.txt 3/3 files (100.00%)
progress: archiving (end)
cloning subrepo foo/bar from $TESTTMP/repo/foo/bar
progress: linking: 1
#endif
Archive + subrepos uses '/' for all component separators
$ tar -tzf ../archive.tar.gz | sort
.hg_archival.txt
.hgsub
.hgsubstate
foo/.hgsub
foo/.hgsubstate
foo/bar/z.txt
foo/y.txt
x.txt
The newly cloned subrepos contain no working copy:
$ hg -R foo summary
parent: -1:000000000000 (no revision checked out)
commit: (clean)
Disable progress extension and cleanup:
$ mv $HGRCPATH.no-progress $HGRCPATH
Test archiving when there is a directory in the way for a subrepo
created by archive:
$ hg clone -U . ../almost-empty
$ cd ../almost-empty
$ mkdir foo
$ echo f > foo/f
$ hg archive --subrepos -r tip archive
cloning subrepo foo from $TESTTMP/empty/foo
abort: destination '$TESTTMP/almost-empty/foo' is not empty (in subrepository "foo")
[255]
Clone and test outgoing:
$ cd ..
$ hg clone repo repo2
updating to branch default
cloning subrepo foo from $TESTTMP/repo/foo
cloning subrepo foo/bar from $TESTTMP/repo/foo/bar
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd repo2
$ hg outgoing -S
comparing with $TESTTMP/repo
searching for changes
no changes found
comparing with $TESTTMP/repo/foo
searching for changes
no changes found
comparing with $TESTTMP/repo/foo/bar
searching for changes
no changes found
[1]
Make nested change:
$ echo y4 >> foo/y.txt
$ hg diff --nodates -S
diff -r 65903cebad86 foo/y.txt
--- a/foo/y.txt
+++ b/foo/y.txt
@@ -1,3 +1,4 @@
y1
y2
y3
+y4
$ hg commit --subrepos -m 3-4-2
committing subrepository foo
$ hg outgoing -S
comparing with $TESTTMP/repo
searching for changes
changeset: 3:2655b8ecc4ee
tag: tip
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: 3-4-2
comparing with $TESTTMP/repo/foo
searching for changes
changeset: 4:e96193d6cb36
tag: tip
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: 3-4-2
comparing with $TESTTMP/repo/foo/bar
searching for changes
no changes found
Switch to original repo and setup default path:
$ cd ../repo
$ echo '[paths]' >> .hg/hgrc
$ echo 'default = ../repo2' >> .hg/hgrc
Test incoming:
$ hg incoming -S
comparing with $TESTTMP/repo2
searching for changes
changeset: 3:2655b8ecc4ee
tag: tip
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: 3-4-2
comparing with $TESTTMP/repo2/foo
searching for changes
changeset: 4:e96193d6cb36
tag: tip
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: 3-4-2
comparing with $TESTTMP/repo2/foo/bar
searching for changes
no changes found
$ hg incoming -S --bundle incoming.hg
abort: cannot combine --bundle and --subrepos
[255]
Test missing subrepo:
$ rm -r foo
$ hg status -S
warning: error "unknown revision '65903cebad86f1a84bd4f1134f62fa7dcb7a1c98'" in subrepository "foo"
Issue2619: IndexError: list index out of range on hg add with subrepos
The subrepo must sorts after the explicit filename.
$ cd ..
$ hg init test
$ cd test
$ hg init x
$ echo abc > abc.txt
$ hg ci -Am "abc"
adding abc.txt
$ echo "x = x" >> .hgsub
$ hg add .hgsub
$ touch a x/a
$ hg add a x/a
$ hg ci -Sm "added x"
committing subrepository x
$ echo abc > x/a
$ hg revert --rev '.^' "set:subrepo('glob:x*')"
abort: subrepository 'x' does not exist in 25ac2c9b3180!
[255]
$ cd ..

View File

@ -1,109 +0,0 @@
#require killdaemons
Preparing the subrepository 'sub'
$ hg init sub
$ echo sub > sub/sub
$ hg add -R sub
adding sub/sub
$ hg commit -R sub -m "sub import"
Preparing the 'main' repo which depends on the subrepo 'sub'
$ hg init main
$ echo main > main/main
$ echo "sub = ../sub" > main/.hgsub
$ hg clone sub main/sub
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg add -R main
adding main/.hgsub
adding main/main
$ hg commit -R main -m "main import"
Cleaning both repositories, just as a clone -U
$ hg up -C -R sub null
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ hg up -C -R main null
0 files updated, 0 files merged, 3 files removed, 0 files unresolved
$ rm -rf main/sub
hide outer repo
$ hg init
Serving them both using hgweb
$ printf '[paths]\n/main = main\nsub = sub\n' > webdir.conf
$ hg serve --webdir-conf webdir.conf -a localhost -p 0 --port-file $TESTTMP/.port -A /dev/null -E /dev/null --pid-file hg.pid -d
$ HGPORT=`cat $TESTTMP/.port`
$ cat hg.pid >> $DAEMON_PIDS
Clone main from hgweb
$ hg clone "http://localhost:$HGPORT/main" cloned
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 3 changes to 3 files
new changesets fdfeeb3e979e
updating to branch default
cloning subrepo sub from http://localhost:$HGPORT/sub (glob)
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
new changesets 863c1745b441
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
Checking cloned repo ids
$ hg id -R cloned
fdfeeb3e979e tip
$ hg id -R cloned/sub
863c1745b441 tip
subrepo debug for 'main' clone
$ hg debugsub -R cloned
path sub
source ../sub
revision 863c1745b441bd97a8c4a096e87793073f4fb215
$ killdaemons.py
subrepo paths with ssh urls
$ hg clone -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/cloned sshclone
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 3 changes to 3 files
new changesets fdfeeb3e979e
updating to branch default
cloning subrepo sub from ssh://user@dummy/sub
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
new changesets 863c1745b441
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg -R sshclone push -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/`pwd`/cloned
pushing to ssh://user@dummy/$TESTTMP/cloned
pushing subrepo sub to ssh://user@dummy/$TESTTMP/sub
searching for changes
no changes found
searching for changes
no changes found
[1]
$ cat dummylog
Got arguments 1:user@dummy 2:hg -R cloned serve --stdio
Got arguments 1:user@dummy 2:hg -R sub serve --stdio
Got arguments 1:user@dummy 2:hg -R $TESTTMP/cloned serve --stdio
Got arguments 1:user@dummy 2:hg -R $TESTTMP/sub serve --stdio

View File

@ -1,681 +0,0 @@
#require svn15
$ SVNREPOPATH=`pwd`/svn-repo
#if windows
$ SVNREPOURL=file:///`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
#else
$ SVNREPOURL=file://`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
#endif
$ filter_svn_output () {
> egrep -v 'Committing|Transmitting|Updating|(^$)' || true
> }
create subversion repo
$ WCROOT="`pwd`/svn-wc"
$ svnadmin create svn-repo
$ svn co "$SVNREPOURL" svn-wc
Checked out revision 0.
$ cd svn-wc
$ mkdir src
$ echo alpha > src/alpha
$ svn add src
A src
A src/alpha
$ mkdir externals
$ echo other > externals/other
$ svn add externals
A externals
A externals/other
$ svn ci -qm 'Add alpha'
$ svn up -q
$ echo "externals -r1 $SVNREPOURL/externals" > extdef
$ svn propset -F extdef svn:externals src
property 'svn:externals' set on 'src'
$ svn ci -qm 'Setting externals'
$ cd ..
create hg repo
$ mkdir sub
$ cd sub
$ hg init t
$ cd t
first revision, no sub
$ echo a > a
$ hg ci -Am0
adding a
add first svn sub with leading whitespaces
$ echo "s = [svn] $SVNREPOURL/src" >> .hgsub
$ echo "subdir/s = [svn] $SVNREPOURL/src" >> .hgsub
$ svn co --quiet "$SVNREPOURL"/src s
$ mkdir subdir
$ svn co --quiet "$SVNREPOURL"/src subdir/s
$ hg add .hgsub
svn subrepo is disabled by default
$ hg ci -m1
abort: svn subrepos not allowed
(see 'hg help config.subrepos' for details)
[255]
so enable it
$ cat >> $HGRCPATH <<EOF
> [subrepos]
> svn:allowed = true
> EOF
$ hg ci -m1
make sure we avoid empty commits (issue2445)
$ hg sum
parent: 1:* tip (glob)
1
commit: (clean)
phases: 2 draft
$ hg ci -moops
nothing changed
[1]
debugsub
$ hg debugsub
path s
source file:/*/$TESTTMP/svn-repo/src (glob)
revision 2
path subdir/s
source file:/*/$TESTTMP/svn-repo/src (glob)
revision 2
change file in svn and hg, commit
$ echo a >> a
$ echo alpha >> s/alpha
$ hg sum
parent: 1:* tip (glob)
1
commit: 1 modified, 1 subrepos
phases: 2 draft
$ hg commit --subrepos -m 'Message!' | filter_svn_output
committing subrepository s
Sending*s/alpha (glob)
Committed revision 3.
Fetching external item into '*s/externals'* (glob)
External at revision 1.
At revision 3.
$ hg debugsub
path s
source file:/*/$TESTTMP/svn-repo/src (glob)
revision 3
path subdir/s
source file:/*/$TESTTMP/svn-repo/src (glob)
revision 2
missing svn file, commit should fail
$ rm s/alpha
$ hg commit --subrepos -m 'abort on missing file'
committing subrepository s
abort: cannot commit missing svn entries (in subrepository "s")
[255]
$ svn revert s/alpha > /dev/null
add an unrelated revision in svn and update the subrepo to without
bringing any changes.
$ svn mkdir "$SVNREPOURL/unrelated" -qm 'create unrelated'
$ svn up -q s
$ hg sum
parent: 2:* tip (glob)
Message!
commit: (clean)
phases: 3 draft
$ echo a > s/a
should be empty despite change to s/a
$ hg st
add a commit from svn
$ cd "$WCROOT/src"
$ svn up -q
$ echo xyz >> alpha
$ svn propset svn:mime-type 'text/xml' alpha
property 'svn:mime-type' set on 'alpha'
$ svn ci -qm 'amend a from svn'
$ cd ../../sub/t
this commit from hg will fail
$ echo zzz >> s/alpha
$ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
committing subrepository s
abort: svn:*Commit failed (details follow): (glob)
[255]
$ svn revert -q s/alpha
this commit fails because of meta changes
$ svn propset svn:mime-type 'text/html' s/alpha
property 'svn:mime-type' set on 's/alpha'
$ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date'
committing subrepository s
abort: svn:*Commit failed (details follow): (glob)
[255]
$ svn revert -q s/alpha
this commit fails because of externals changes
$ echo zzz > s/externals/other
$ hg ci --subrepos -m 'amend externals from hg'
committing subrepository s
abort: cannot commit svn externals (in subrepository "s")
[255]
$ hg diff --subrepos -r 1:2 | grep -v diff
--- a/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgsubstate Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +1,2 @@
-2 s
+3 s
2 subdir/s
--- a/a Thu Jan 01 00:00:00 1970 +0000
+++ b/a Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +1,2 @@
a
+a
$ svn revert -q s/externals/other
this commit fails because of externals meta changes
$ svn propset svn:mime-type 'text/html' s/externals/other
property 'svn:mime-type' set on 's/externals/other'
$ hg ci --subrepos -m 'amend externals from hg'
committing subrepository s
abort: cannot commit svn externals (in subrepository "s")
[255]
$ svn revert -q s/externals/other
clone
$ cd ..
$ hg clone t tc
updating to branch default
A tc/s/alpha
U tc/s
Fetching external item into 'tc/s/externals'* (glob)
A tc/s/externals/other
Checked out external at revision 1.
Checked out revision 3.
A tc/subdir/s/alpha
U tc/subdir/s
Fetching external item into 'tc/subdir/s/externals'* (glob)
A tc/subdir/s/externals/other
Checked out external at revision 1.
Checked out revision 2.
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd tc
debugsub in clone
$ hg debugsub
path s
source file:/*/$TESTTMP/svn-repo/src (glob)
revision 3
path subdir/s
source file:/*/$TESTTMP/svn-repo/src (glob)
revision 2
verify subrepo is contained within the repo directory
$ $PYTHON -c "import os.path; print os.path.exists('s')"
True
update to nullrev (must delete the subrepo)
$ hg up null
0 files updated, 0 files merged, 3 files removed, 0 files unresolved
$ ls
Check hg update --clean
$ cd "$TESTTMP/sub/t"
$ cd s
$ echo c0 > alpha
$ echo c1 > f1
$ echo c1 > f2
$ svn add f1 -q
$ svn status | sort
? * a (glob)
? * f2 (glob)
A * f1 (glob)
M * alpha (glob)
Performing status on external item at 'externals'* (glob)
X * externals (glob)
$ cd ../..
$ hg -R t update -C
Fetching external item into 't/s/externals'* (glob)
Checked out external at revision 1.
Checked out revision 3.
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd t/s
$ svn status | sort
? * a (glob)
? * f1 (glob)
? * f2 (glob)
Performing status on external item at 'externals'* (glob)
X * externals (glob)
Sticky subrepositories, no changes
$ cd "$TESTTMP/sub/t"
$ hg id -n
2
$ cd s
$ svnversion
3
$ cd ..
$ hg update 1
U *s/alpha (glob)
Fetching external item into '*s/externals'* (glob)
Checked out external at revision 1.
Checked out revision 2.
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg id -n
1
$ cd s
$ svnversion
2
$ cd ..
Sticky subrepositories, file changes
$ touch s/f1
$ cd s
$ svn add f1
A f1
$ cd ..
$ hg id -n
1+
$ cd s
$ svnversion
2M
$ cd ..
$ hg update tip
subrepository s diverged (local revision: 2, remote revision: 3)
(M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
subrepository sources for s differ
use (l)ocal source (2) or (r)emote source (3)? l
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg id -n
2+
$ cd s
$ svnversion
2M
$ cd ..
$ hg update --clean tip
U *s/alpha (glob)
Fetching external item into '*s/externals'* (glob)
Checked out external at revision 1.
Checked out revision 3.
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
Sticky subrepository, revision updates
$ hg id -n
2
$ cd s
$ svnversion
3
$ cd ..
$ cd s
$ svn update -qr 1
$ cd ..
$ hg update 1
subrepository s diverged (local revision: 3, remote revision: 2)
(M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
subrepository sources for s differ (in checked out version)
use (l)ocal source (1) or (r)emote source (2)? l
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg id -n
1+
$ cd s
$ svnversion
1
$ cd ..
Sticky subrepository, file changes and revision updates
$ touch s/f1
$ cd s
$ svn add f1
A f1
$ svnversion
1M
$ cd ..
$ hg id -n
1+
$ hg update tip
subrepository s diverged (local revision: 3, remote revision: 3)
(M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
subrepository sources for s differ
use (l)ocal source (1) or (r)emote source (3)? l
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg id -n
2+
$ cd s
$ svnversion
1M
$ cd ..
Sticky repository, update --clean
$ hg update --clean tip | grep -v 's[/\]externals[/\]other'
U *s/alpha (glob)
U *s (glob)
Fetching external item into '*s/externals'* (glob)
Checked out external at revision 1.
Checked out revision 3.
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg id -n
2
$ cd s
$ svnversion
3
$ cd ..
Test subrepo already at intended revision:
$ cd s
$ svn update -qr 2
$ cd ..
$ hg update 1
subrepository s diverged (local revision: 3, remote revision: 2)
(M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg id -n
1+
$ cd s
$ svnversion
2
$ cd ..
Test case where subversion would fail to update the subrepo because there
are unknown directories being replaced by tracked ones (happens with rebase).
$ cd "$WCROOT/src"
$ mkdir dir
$ echo epsilon.py > dir/epsilon.py
$ svn add dir
A dir
A dir/epsilon.py
$ svn ci -qm 'Add dir/epsilon.py'
$ cd ../..
$ hg init rebaserepo
$ cd rebaserepo
$ svn co -r5 --quiet "$SVNREPOURL"/src s
$ echo "s = [svn] $SVNREPOURL/src" >> .hgsub
$ hg add .hgsub
$ hg ci -m addsub
$ echo a > a
$ hg add .
adding a
$ hg ci -m adda
$ hg up 0
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ svn up -qr6 s
$ hg ci -m updatesub
$ echo pyc > s/dir/epsilon.pyc
$ hg up 1
D *s/dir (glob)
Fetching external item into '*s/externals'* (glob)
Checked out external at revision 1.
Checked out revision 5.
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg up -q 2
Modify one of the externals to point to a different path so we can
test having obstructions when switching branches on checkout:
$ hg checkout tip
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo "obstruct = [svn] $SVNREPOURL/externals" >> .hgsub
$ svn co -r5 --quiet "$SVNREPOURL"/externals obstruct
$ hg commit -m 'Start making obstructed working copy'
$ hg book other
$ hg co -r 'p1(tip)'
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
(leaving bookmark other)
$ echo "obstruct = [svn] $SVNREPOURL/src" >> .hgsub
$ svn co -r5 --quiet "$SVNREPOURL"/src obstruct
$ hg commit -m 'Other branch which will be obstructed'
Switching back to the head where we have another path mapped to the
same subrepo should work if the subrepo is clean.
$ hg co other
A *obstruct/other (glob)
Checked out revision 1.
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
(activating bookmark other)
This is surprising, but is also correct based on the current code:
$ echo "updating should (maybe) fail" > obstruct/other
$ hg co tip
abort: uncommitted changes
(commit or update --clean to discard changes)
[255]
Point to a Subversion branch which has since been deleted and recreated
First, create that condition in the repository.
$ hg ci --subrepos -m cleanup | filter_svn_output
committing subrepository obstruct
Sending obstruct/other
Committed revision 7.
At revision 7.
$ svn mkdir -qm "baseline" $SVNREPOURL/trunk
$ svn copy -qm "initial branch" $SVNREPOURL/trunk $SVNREPOURL/branch
$ svn co --quiet "$SVNREPOURL"/branch tempwc
$ cd tempwc
$ echo "something old" > somethingold
$ svn add somethingold
A somethingold
$ svn ci -qm 'Something old'
$ svn rm -qm "remove branch" $SVNREPOURL/branch
$ svn copy -qm "recreate branch" $SVNREPOURL/trunk $SVNREPOURL/branch
$ svn up -q
$ echo "something new" > somethingnew
$ svn add somethingnew
A somethingnew
$ svn ci -qm 'Something new'
$ cd ..
$ rm -rf tempwc
$ svn co "$SVNREPOURL/branch"@10 recreated
A recreated/somethingold
Checked out revision 10.
$ echo "recreated = [svn] $SVNREPOURL/branch" >> .hgsub
$ hg ci -m addsub
$ cd recreated
$ svn up -q
$ cd ..
$ hg ci -m updatesub
$ hg up -r-2
D *recreated/somethingnew (glob)
A *recreated/somethingold (glob)
Checked out revision 10.
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(leaving bookmark other)
$ test -f recreated/somethingold
Test archive
$ hg archive -S ../archive-all --debug --config progress.debug=true
progress: archiving: .hgsub 1/2 files (50.00%)
progress: archiving: .hgsubstate 2/2 files (100.00%)
progress: archiving (end)
progress: archiving (obstruct): 1/1 files (100.00%)
progress: archiving (obstruct) (end)
progress: archiving (recreated): 1/1 files (100.00%)
progress: archiving (recreated) (end)
progress: archiving (s): 1/2 files (50.00%)
progress: archiving (s): 2/2 files (100.00%)
progress: archiving (s) (end)
$ hg archive -S ../archive-exclude --debug --config progress.debug=true -X **old
progress: archiving: .hgsub 1/2 files (50.00%)
progress: archiving: .hgsubstate 2/2 files (100.00%)
progress: archiving (end)
progress: archiving (obstruct): 1/1 files (100.00%)
progress: archiving (obstruct) (end)
progress: archiving (s): 1/2 files (50.00%)
progress: archiving (s): 2/2 files (100.00%)
progress: archiving (s) (end)
$ find ../archive-exclude | sort
../archive-exclude
../archive-exclude/.hg_archival.txt
../archive-exclude/.hgsub
../archive-exclude/.hgsubstate
../archive-exclude/obstruct
../archive-exclude/obstruct/other
../archive-exclude/s
../archive-exclude/s/alpha
../archive-exclude/s/dir
../archive-exclude/s/dir/epsilon.py
Test forgetting files, not implemented in svn subrepo, used to
traceback
$ hg forget 'notafile*'
notafile*: $ENOENT$
[1]
Test a subrepo referencing a just moved svn path. Last commit rev will
be different from the revision, and the path will be different as
well.
$ cd "$WCROOT"
$ svn up > /dev/null
$ mkdir trunk/subdir branches
$ echo a > trunk/subdir/a
$ svn add trunk/subdir branches
A trunk/subdir
A trunk/subdir/a
A branches
$ svn ci -qm addsubdir
$ svn cp -qm branchtrunk $SVNREPOURL/trunk $SVNREPOURL/branches/somebranch
$ cd ..
$ hg init repo2
$ cd repo2
$ svn co $SVNREPOURL/branches/somebranch/subdir
A subdir/a
Checked out revision 15.
$ echo "subdir = [svn] $SVNREPOURL/branches/somebranch/subdir" > .hgsub
$ hg add .hgsub
$ hg ci -m addsub
$ hg up null
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
$ hg up
A *subdir/a (glob)
Checked out revision 15.
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd ..
Test sanitizing ".hg/hgrc" in subrepo
$ cd sub/t
$ hg update -q -C tip
$ cd s
$ mkdir .hg
$ echo '.hg/hgrc in svn repo' > .hg/hgrc
$ mkdir -p sub/.hg
$ echo 'sub/.hg/hgrc in svn repo' > sub/.hg/hgrc
$ svn add .hg sub
A .hg
A .hg/hgrc
A sub
A sub/.hg
A sub/.hg/hgrc
$ svn ci -qm 'add .hg/hgrc to be sanitized at hg update'
$ svn up -q
$ cd ..
$ hg commit -S -m 'commit with svn revision including .hg/hgrc'
$ grep ' s$' .hgsubstate
16 s
$ cd ..
$ hg -R tc pull -u -q 2>&1 | sort
warning: removing potentially hostile 'hgrc' in '$TESTTMP/sub/tc/s/.hg'
warning: removing potentially hostile 'hgrc' in '$TESTTMP/sub/tc/s/sub/.hg'
$ cd tc
$ grep ' s$' .hgsubstate
16 s
$ test -f s/.hg/hgrc
[1]
$ test -f s/sub/.hg/hgrc
[1]
Test that sanitizing is omitted in meta data area:
$ mkdir s/.svn/.hg
$ echo '.hg/hgrc in svn metadata area' > s/.svn/.hg/hgrc
$ hg update -q -C '.^1'
$ cd ../..
SEC: test for ssh exploit
$ hg init ssh-vuln
$ cd ssh-vuln
$ echo "s = [svn]$SVNREPOURL/src" >> .hgsub
$ svn co --quiet "$SVNREPOURL"/src s
$ hg add .hgsub
$ hg ci -m1
$ echo "s = [svn]svn+ssh://-oProxyCommand=touch%20owned%20nested" > .hgsub
$ hg ci -m2
$ cd ..
$ hg clone ssh-vuln ssh-vuln-clone
updating to branch default
abort: potentially unsafe url: 'svn+ssh://-oProxyCommand=touch owned nested' (in subrepository "s")
[255]
also check that a percent encoded '-' (%2D) doesn't work
$ cd ssh-vuln
$ echo "s = [svn]svn+ssh://%2DoProxyCommand=touch%20owned%20nested" > .hgsub
$ hg ci -m3
$ cd ..
$ rm -r ssh-vuln-clone
$ hg clone ssh-vuln ssh-vuln-clone
updating to branch default
abort: potentially unsafe url: 'svn+ssh://-oProxyCommand=touch owned nested' (in subrepository "s")
[255]
also check that hiding the attack in the username doesn't work:
$ cd ssh-vuln
$ echo "s = [svn]svn+ssh://%2DoProxyCommand=touch%20owned%20foo@example.com/nested" > .hgsub
$ hg ci -m3
$ cd ..
$ rm -r ssh-vuln-clone
$ hg clone ssh-vuln ssh-vuln-clone
updating to branch default
abort: potentially unsafe url: 'svn+ssh://-oProxyCommand=touch owned foo@example.com/nested' (in subrepository "s")
[255]

View File

@ -117,7 +117,6 @@ Changing original repo:
summary: new head of branch foo
$ hg -q --cwd ../clone incoming '../repo#foo'
[1]
$ hg --cwd ../clone summary --remote --config paths.default='../repo#foo'
parent: 1:17d330177ee9
change a