Skip to content

Commit 4ab2284

Browse files
Peter Kjellerstedtgavinmak
authored andcommitted
manifest: Make extend-project support copyfile, linkfile and annotation
This allows an existing project to be extended by these elements. Change-Id: I6826e518f39ca86485301491639101943b7e2ae0 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/519781 Reviewed-by: Mike Frysinger <[email protected]> Tested-by: Peter Kjellerstedt <[email protected]> Reviewed-by: Gavin Mak <[email protected]>
1 parent 1afe96a commit 4ab2284

File tree

3 files changed

+101
-12
lines changed

3 files changed

+101
-12
lines changed

docs/manifest-format.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@ following DTD:
9898
<!ATTLIST linkfile src CDATA #REQUIRED>
9999
<!ATTLIST linkfile dest CDATA #REQUIRED>
100100

101-
<!ELEMENT extend-project EMPTY>
101+
<!ELEMENT extend-project (annotation*,
102+
copyfile*,
103+
linkfile*)>
102104
<!ATTLIST extend-project name CDATA #REQUIRED>
103105
<!ATTLIST extend-project path CDATA #IMPLIED>
104106
<!ATTLIST extend-project dest-path CDATA #IMPLIED>
@@ -427,19 +429,20 @@ Same syntax as the corresponding element of `project`.
427429
### Element annotation
428430

429431
Zero or more annotation elements may be specified as children of a
430-
project or remote element. Each element describes a name-value pair.
431-
For projects, this name-value pair will be exported into each project's
432-
environment during a 'forall' command, prefixed with `REPO__`. In addition,
433-
there is an optional attribute "keep" which accepts the case insensitive values
434-
"true" (default) or "false". This attribute determines whether or not the
432+
project element, an extend-project element, or a remote element. Each
433+
element describes a name-value pair. For projects, this name-value pair
434+
will be exported into each project's environment during a 'forall'
435+
command, prefixed with `REPO__`. In addition, there is an optional
436+
attribute "keep" which accepts the case insensitive values "true"
437+
(default) or "false". This attribute determines whether or not the
435438
annotation will be kept when exported with the manifest subcommand.
436439

437440
### Element copyfile
438441

439442
Zero or more copyfile elements may be specified as children of a
440-
project element. Each element describes a src-dest pair of files;
441-
the "src" file will be copied to the "dest" place during `repo sync`
442-
command.
443+
project element, or an extend-project element. Each element describes a
444+
src-dest pair of files; the "src" file will be copied to the "dest"
445+
place during `repo sync` command.
443446

444447
"src" is project relative, "dest" is relative to the top of the tree.
445448
Copying from paths outside of the project or to paths outside of the repo

manifest_xml.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,6 +1509,14 @@ def recursively_add_projects(project):
15091509
p.UpdatePaths(relpath, worktree, gitdir, objdir)
15101510
self._paths[p.relpath] = p
15111511

1512+
for n in node.childNodes:
1513+
if n.nodeName == "copyfile":
1514+
self._ParseCopyFile(p, n)
1515+
elif n.nodeName == "linkfile":
1516+
self._ParseLinkFile(p, n)
1517+
elif n.nodeName == "annotation":
1518+
self._ParseAnnotation(p, n)
1519+
15121520
if node.nodeName == "repo-hooks":
15131521
# Only one project can be the hooks project
15141522
if repo_hooks_project is not None:
@@ -1963,11 +1971,11 @@ def _ParseProject(self, node, parent=None, **extra_proj_attrs):
19631971
for n in node.childNodes:
19641972
if n.nodeName == "copyfile":
19651973
self._ParseCopyFile(project, n)
1966-
if n.nodeName == "linkfile":
1974+
elif n.nodeName == "linkfile":
19671975
self._ParseLinkFile(project, n)
1968-
if n.nodeName == "annotation":
1976+
elif n.nodeName == "annotation":
19691977
self._ParseAnnotation(project, n)
1970-
if n.nodeName == "project":
1978+
elif n.nodeName == "project":
19711979
project.subprojects.append(
19721980
self._ParseProject(n, parent=project)
19731981
)

tests/test_manifest_xml.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,84 @@ def test_extend_project_upstream(self):
12141214
self.assertEqual(len(manifest.projects), 1)
12151215
self.assertEqual(manifest.projects[0].upstream, "bar")
12161216

1217+
def test_extend_project_copyfiles(self):
1218+
manifest = self.getXmlManifest(
1219+
"""
1220+
<manifest>
1221+
<remote name="default-remote" fetch="http://localhost" />
1222+
<default remote="default-remote" revision="refs/heads/main" />
1223+
<project name="myproject" />
1224+
<extend-project name="myproject">
1225+
<copyfile src="foo" dest="bar" />
1226+
</extend-project>
1227+
</manifest>
1228+
"""
1229+
)
1230+
self.assertEqual(manifest.projects[0].copyfiles[0].src, "foo")
1231+
self.assertEqual(manifest.projects[0].copyfiles[0].dest, "bar")
1232+
self.assertEqual(
1233+
sort_attributes(manifest.ToXml().toxml()),
1234+
'<?xml version="1.0" ?><manifest>'
1235+
'<remote fetch="http://localhost" name="default-remote"/>'
1236+
'<default remote="default-remote" revision="refs/heads/main"/>'
1237+
'<project name="myproject">'
1238+
'<copyfile dest="bar" src="foo"/>'
1239+
"</project>"
1240+
"</manifest>",
1241+
)
1242+
1243+
def test_extend_project_linkfiles(self):
1244+
manifest = self.getXmlManifest(
1245+
"""
1246+
<manifest>
1247+
<remote name="default-remote" fetch="http://localhost" />
1248+
<default remote="default-remote" revision="refs/heads/main" />
1249+
<project name="myproject" />
1250+
<extend-project name="myproject">
1251+
<linkfile src="foo" dest="bar" />
1252+
</extend-project>
1253+
</manifest>
1254+
"""
1255+
)
1256+
self.assertEqual(manifest.projects[0].linkfiles[0].src, "foo")
1257+
self.assertEqual(manifest.projects[0].linkfiles[0].dest, "bar")
1258+
self.assertEqual(
1259+
sort_attributes(manifest.ToXml().toxml()),
1260+
'<?xml version="1.0" ?><manifest>'
1261+
'<remote fetch="http://localhost" name="default-remote"/>'
1262+
'<default remote="default-remote" revision="refs/heads/main"/>'
1263+
'<project name="myproject">'
1264+
'<linkfile dest="bar" src="foo"/>'
1265+
"</project>"
1266+
"</manifest>",
1267+
)
1268+
1269+
def test_extend_project_annotations(self):
1270+
manifest = self.getXmlManifest(
1271+
"""
1272+
<manifest>
1273+
<remote name="default-remote" fetch="http://localhost" />
1274+
<default remote="default-remote" revision="refs/heads/main" />
1275+
<project name="myproject" />
1276+
<extend-project name="myproject">
1277+
<annotation name="foo" value="bar" />
1278+
</extend-project>
1279+
</manifest>
1280+
"""
1281+
)
1282+
self.assertEqual(manifest.projects[0].annotations[0].name, "foo")
1283+
self.assertEqual(manifest.projects[0].annotations[0].value, "bar")
1284+
self.assertEqual(
1285+
sort_attributes(manifest.ToXml().toxml()),
1286+
'<?xml version="1.0" ?><manifest>'
1287+
'<remote fetch="http://localhost" name="default-remote"/>'
1288+
'<default remote="default-remote" revision="refs/heads/main"/>'
1289+
'<project name="myproject">'
1290+
'<annotation name="foo" value="bar"/>'
1291+
"</project>"
1292+
"</manifest>",
1293+
)
1294+
12171295

12181296
class NormalizeUrlTests(ManifestParseTestCase):
12191297
"""Tests for normalize_url() in manifest_xml.py"""

0 commit comments

Comments
 (0)