mirror of
https://github.com/facebook/sapling.git
synced 2025-01-08 14:46:47 +03:00
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:
parent
dbe1d30cf0
commit
9e0a7c41a4
@ -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()
|
||||
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
)
|
||||
|
@ -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)
|
||||
|
@ -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(
|
||||
|
@ -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":
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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"""
|
||||
|
||||
|
@ -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
|
||||
|
@ -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():
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
|
@ -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"))
|
||||
|
||||
|
@ -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"""
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"))],
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -190,7 +190,6 @@ def _preimportmodules():
|
||||
"sslutil",
|
||||
"store",
|
||||
"streamclone",
|
||||
"subrepo",
|
||||
"tags",
|
||||
"templatefilters",
|
||||
"templatekw",
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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")),
|
||||
(
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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 []
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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__)
|
||||
|
||||
|
@ -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():
|
||||
|
@ -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
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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
@ -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
|
||||
|
@ -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 ..
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 ..
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 !)
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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]
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
@ -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 ..
|
@ -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 ..
|
@ -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 ..
|
@ -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
|
@ -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]
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user