mirror of
https://gerrit.googlesource.com/git-repo
synced 2025-07-04 20:17:16 +00:00
Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
ef99ec07b4 | |||
934cb0a849 | |||
3c0931285c | |||
5413397204 |
4
error.py
4
error.py
@ -22,12 +22,12 @@ class ManifestParseError(Exception):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class ManifestInvalidRevisionError(Exception):
|
class ManifestInvalidRevisionError(ManifestParseError):
|
||||||
"""The revision value in a project is incorrect.
|
"""The revision value in a project is incorrect.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class ManifestInvalidPathError(Exception):
|
class ManifestInvalidPathError(ManifestParseError):
|
||||||
"""A path used in <copyfile> or <linkfile> is incorrect.
|
"""A path used in <copyfile> or <linkfile> is incorrect.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -41,7 +41,8 @@ class Superproject(object):
|
|||||||
lookup of commit ids for all projects. It contains _project_commit_ids which
|
lookup of commit ids for all projects. It contains _project_commit_ids which
|
||||||
is a dictionary with project/commit id entries.
|
is a dictionary with project/commit id entries.
|
||||||
"""
|
"""
|
||||||
def __init__(self, manifest, repodir, superproject_dir='exp-superproject'):
|
def __init__(self, manifest, repodir, superproject_dir='exp-superproject',
|
||||||
|
quiet=False):
|
||||||
"""Initializes superproject.
|
"""Initializes superproject.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -49,9 +50,11 @@ class Superproject(object):
|
|||||||
repodir: Path to the .repo/ dir for holding all internal checkout state.
|
repodir: Path to the .repo/ dir for holding all internal checkout state.
|
||||||
It must be in the top directory of the repo client checkout.
|
It must be in the top directory of the repo client checkout.
|
||||||
superproject_dir: Relative path under |repodir| to checkout superproject.
|
superproject_dir: Relative path under |repodir| to checkout superproject.
|
||||||
|
quiet: If True then only print the progress messages.
|
||||||
"""
|
"""
|
||||||
self._project_commit_ids = None
|
self._project_commit_ids = None
|
||||||
self._manifest = manifest
|
self._manifest = manifest
|
||||||
|
self._quiet = quiet
|
||||||
self._branch = self._GetBranch()
|
self._branch = self._GetBranch()
|
||||||
self._repodir = os.path.abspath(repodir)
|
self._repodir = os.path.abspath(repodir)
|
||||||
self._superproject_dir = superproject_dir
|
self._superproject_dir = superproject_dir
|
||||||
@ -89,6 +92,9 @@ class Superproject(object):
|
|||||||
"""
|
"""
|
||||||
if not os.path.exists(self._superproject_path):
|
if not os.path.exists(self._superproject_path):
|
||||||
os.mkdir(self._superproject_path)
|
os.mkdir(self._superproject_path)
|
||||||
|
if not self._quiet and not os.path.exists(self._work_git):
|
||||||
|
print('%s: Performing initial setup for superproject; this might take '
|
||||||
|
'several minutes.' % self._work_git)
|
||||||
cmd = ['init', '--bare', self._work_git_name]
|
cmd = ['init', '--bare', self._work_git_name]
|
||||||
p = GitCommand(None,
|
p = GitCommand(None,
|
||||||
cmd,
|
cmd,
|
||||||
@ -183,6 +189,8 @@ class Superproject(object):
|
|||||||
return False
|
return False
|
||||||
if not self._Fetch(url):
|
if not self._Fetch(url):
|
||||||
return False
|
return False
|
||||||
|
if not self._quiet:
|
||||||
|
print('%s: Initial setup for superproject completed.' % self._work_git)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _GetAllProjectsCommitIds(self):
|
def _GetAllProjectsCommitIds(self):
|
||||||
|
@ -624,16 +624,22 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
b = b[len(R_HEADS):]
|
b = b[len(R_HEADS):]
|
||||||
self.branch = b
|
self.branch = b
|
||||||
|
|
||||||
|
# The manifestFile was specified by the user which is why we allow include
|
||||||
|
# paths to point anywhere.
|
||||||
nodes = []
|
nodes = []
|
||||||
nodes.append(self._ParseManifestXml(self.manifestFile,
|
nodes.append(self._ParseManifestXml(
|
||||||
self.manifestProject.worktree))
|
self.manifestFile, self.manifestProject.worktree,
|
||||||
|
restrict_includes=False))
|
||||||
|
|
||||||
if self._load_local_manifests and self.local_manifests:
|
if self._load_local_manifests and self.local_manifests:
|
||||||
try:
|
try:
|
||||||
for local_file in sorted(platform_utils.listdir(self.local_manifests)):
|
for local_file in sorted(platform_utils.listdir(self.local_manifests)):
|
||||||
if local_file.endswith('.xml'):
|
if local_file.endswith('.xml'):
|
||||||
local = os.path.join(self.local_manifests, local_file)
|
local = os.path.join(self.local_manifests, local_file)
|
||||||
nodes.append(self._ParseManifestXml(local, self.repodir))
|
# Since local manifests are entirely managed by the user, allow
|
||||||
|
# them to point anywhere the user wants.
|
||||||
|
nodes.append(self._ParseManifestXml(
|
||||||
|
local, self.repodir, restrict_includes=False))
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -651,7 +657,19 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
|
|
||||||
self._loaded = True
|
self._loaded = True
|
||||||
|
|
||||||
def _ParseManifestXml(self, path, include_root, parent_groups=''):
|
def _ParseManifestXml(self, path, include_root, parent_groups='',
|
||||||
|
restrict_includes=True):
|
||||||
|
"""Parse a manifest XML and return the computed nodes.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path: The XML file to read & parse.
|
||||||
|
include_root: The path to interpret include "name"s relative to.
|
||||||
|
parent_groups: The groups to apply to this projects.
|
||||||
|
restrict_includes: Whether to constrain the "name" attribute of includes.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of XML nodes.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
root = xml.dom.minidom.parse(path)
|
root = xml.dom.minidom.parse(path)
|
||||||
except (OSError, xml.parsers.expat.ExpatError) as e:
|
except (OSError, xml.parsers.expat.ExpatError) as e:
|
||||||
@ -670,6 +688,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
for node in manifest.childNodes:
|
for node in manifest.childNodes:
|
||||||
if node.nodeName == 'include':
|
if node.nodeName == 'include':
|
||||||
name = self._reqatt(node, 'name')
|
name = self._reqatt(node, 'name')
|
||||||
|
if restrict_includes:
|
||||||
msg = self._CheckLocalPath(name)
|
msg = self._CheckLocalPath(name)
|
||||||
if msg:
|
if msg:
|
||||||
raise ManifestInvalidPathError(
|
raise ManifestInvalidPathError(
|
||||||
@ -681,13 +700,13 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
include_groups = node.getAttribute('groups') + ',' + include_groups
|
include_groups = node.getAttribute('groups') + ',' + include_groups
|
||||||
fp = os.path.join(include_root, name)
|
fp = os.path.join(include_root, name)
|
||||||
if not os.path.isfile(fp):
|
if not os.path.isfile(fp):
|
||||||
raise ManifestParseError("include %s doesn't exist or isn't a file"
|
raise ManifestParseError("include [%s/]%s doesn't exist or isn't a file"
|
||||||
% (name,))
|
% (include_root, name))
|
||||||
try:
|
try:
|
||||||
nodes.extend(self._ParseManifestXml(fp, include_root, include_groups))
|
nodes.extend(self._ParseManifestXml(fp, include_root, include_groups))
|
||||||
# should isolate this to the exact exception, but that's
|
# should isolate this to the exact exception, but that's
|
||||||
# tricky. actual parsing implementation may vary.
|
# tricky. actual parsing implementation may vary.
|
||||||
except (KeyboardInterrupt, RuntimeError, SystemExit):
|
except (KeyboardInterrupt, RuntimeError, SystemExit, ManifestParseError):
|
||||||
raise
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ManifestParseError(
|
raise ManifestParseError(
|
||||||
|
@ -1150,7 +1150,7 @@ class Project(object):
|
|||||||
p = GitCommand(self, cmd, bare=True, capture_stdout=bool(output_redir),
|
p = GitCommand(self, cmd, bare=True, capture_stdout=bool(output_redir),
|
||||||
merge_output=bool(output_redir))
|
merge_output=bool(output_redir))
|
||||||
if p.stdout and output_redir:
|
if p.stdout and output_redir:
|
||||||
buf.write(p.stdout)
|
output_redir.write(p.stdout)
|
||||||
if p.Wait() != 0:
|
if p.Wait() != 0:
|
||||||
return False
|
return False
|
||||||
platform_utils.remove(alternates_file)
|
platform_utils.remove(alternates_file)
|
||||||
|
@ -185,10 +185,15 @@ to update the working directory files.
|
|||||||
return {'REPO_MANIFEST_URL': 'manifest_url',
|
return {'REPO_MANIFEST_URL': 'manifest_url',
|
||||||
'REPO_MIRROR_LOCATION': 'reference'}
|
'REPO_MIRROR_LOCATION': 'reference'}
|
||||||
|
|
||||||
def _CloneSuperproject(self):
|
def _CloneSuperproject(self, opt):
|
||||||
"""Clone the superproject based on the superproject's url and branch."""
|
"""Clone the superproject based on the superproject's url and branch.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
opt: Program options returned from optparse. See _Options().
|
||||||
|
"""
|
||||||
superproject = git_superproject.Superproject(self.manifest,
|
superproject = git_superproject.Superproject(self.manifest,
|
||||||
self.repodir)
|
self.repodir,
|
||||||
|
quiet=opt.quiet)
|
||||||
if not superproject.Sync():
|
if not superproject.Sync():
|
||||||
print('error: git update of superproject failed', file=sys.stderr)
|
print('error: git update of superproject failed', file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -553,7 +558,7 @@ to update the working directory files.
|
|||||||
self._LinkManifest(opt.manifest_name)
|
self._LinkManifest(opt.manifest_name)
|
||||||
|
|
||||||
if self.manifest.manifestProject.config.GetBoolean('repo.superproject'):
|
if self.manifest.manifestProject.config.GetBoolean('repo.superproject'):
|
||||||
self._CloneSuperproject()
|
self._CloneSuperproject(opt)
|
||||||
|
|
||||||
if os.isatty(0) and os.isatty(1) and not self.manifest.IsMirror:
|
if os.isatty(0) and os.isatty(1) and not self.manifest.IsMirror:
|
||||||
if opt.config_name or self._ShouldConfigureUser(opt):
|
if opt.config_name or self._ShouldConfigureUser(opt):
|
||||||
|
@ -292,7 +292,8 @@ later is required to fix a server side protocol bug.
|
|||||||
Returns path to the overriding manifest file.
|
Returns path to the overriding manifest file.
|
||||||
"""
|
"""
|
||||||
superproject = git_superproject.Superproject(self.manifest,
|
superproject = git_superproject.Superproject(self.manifest,
|
||||||
self.repodir)
|
self.repodir,
|
||||||
|
quiet=opt.quiet)
|
||||||
all_projects = self.GetProjects(args,
|
all_projects = self.GetProjects(args,
|
||||||
missing_ok=True,
|
missing_ok=True,
|
||||||
submodules_ok=opt.fetch_submodules)
|
submodules_ok=opt.fetch_submodules)
|
||||||
|
@ -298,8 +298,8 @@ class IncludeElementTests(ManifestParseTestCase):
|
|||||||
# Check level2 proj group not removed.
|
# Check level2 proj group not removed.
|
||||||
self.assertIn('l2g1', proj.groups)
|
self.assertIn('l2g1', proj.groups)
|
||||||
|
|
||||||
def test_bad_name_checks(self):
|
def test_allow_bad_name_from_user(self):
|
||||||
"""Check handling of bad name attribute."""
|
"""Check handling of bad name attribute from the user's input."""
|
||||||
def parse(name):
|
def parse(name):
|
||||||
manifest = self.getXmlManifest(f"""
|
manifest = self.getXmlManifest(f"""
|
||||||
<manifest>
|
<manifest>
|
||||||
@ -307,6 +307,34 @@ class IncludeElementTests(ManifestParseTestCase):
|
|||||||
<default remote="default-remote" revision="refs/heads/main" />
|
<default remote="default-remote" revision="refs/heads/main" />
|
||||||
<include name="{name}" />
|
<include name="{name}" />
|
||||||
</manifest>
|
</manifest>
|
||||||
|
""")
|
||||||
|
# Force the manifest to be parsed.
|
||||||
|
manifest.ToXml()
|
||||||
|
|
||||||
|
# Setup target of the include.
|
||||||
|
target = os.path.join(self.tempdir, 'target.xml')
|
||||||
|
with open(target, 'w') as fp:
|
||||||
|
fp.write('<manifest></manifest>')
|
||||||
|
|
||||||
|
# Include with absolute path.
|
||||||
|
parse(os.path.abspath(target))
|
||||||
|
|
||||||
|
# Include with relative path.
|
||||||
|
parse(os.path.relpath(target, self.manifest_dir))
|
||||||
|
|
||||||
|
def test_bad_name_checks(self):
|
||||||
|
"""Check handling of bad name attribute."""
|
||||||
|
def parse(name):
|
||||||
|
# Setup target of the include.
|
||||||
|
with open(os.path.join(self.manifest_dir, 'target.xml'), 'w') as fp:
|
||||||
|
fp.write(f'<manifest><include name="{name}"/></manifest>')
|
||||||
|
|
||||||
|
manifest = self.getXmlManifest("""
|
||||||
|
<manifest>
|
||||||
|
<remote name="default-remote" fetch="http://localhost" />
|
||||||
|
<default remote="default-remote" revision="refs/heads/main" />
|
||||||
|
<include name="target.xml" />
|
||||||
|
</manifest>
|
||||||
""")
|
""")
|
||||||
# Force the manifest to be parsed.
|
# Force the manifest to be parsed.
|
||||||
manifest.ToXml()
|
manifest.ToXml()
|
||||||
|
@ -305,8 +305,8 @@ class Requirements(RepoWrapperTestCase):
|
|||||||
reqs = self.wrapper.Requirements({'python': {'hard': sys.version_info}})
|
reqs = self.wrapper.Requirements({'python': {'hard': sys.version_info}})
|
||||||
reqs.assert_all()
|
reqs.assert_all()
|
||||||
|
|
||||||
def test_assert_all_old_repo(self):
|
def test_assert_all_old_python(self):
|
||||||
"""Check assert_all rejects old repo."""
|
"""Check assert_all rejects old python."""
|
||||||
reqs = self.wrapper.Requirements({'python': {'hard': [99999, 0]}})
|
reqs = self.wrapper.Requirements({'python': {'hard': [99999, 0]}})
|
||||||
with self.assertRaises(SystemExit):
|
with self.assertRaises(SystemExit):
|
||||||
reqs.assert_all()
|
reqs.assert_all()
|
||||||
|
Reference in New Issue
Block a user