From 4ab2284a945d82b017c6646fca57c5973ffdabaf Mon Sep 17 00:00:00 2001 From: Peter Kjellerstedt Date: Thu, 16 Oct 2025 20:29:28 +0200 Subject: 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 Tested-by: Peter Kjellerstedt Reviewed-by: Gavin Mak --- docs/manifest-format.md | 21 +++++++------ manifest_xml.py | 14 +++++++-- tests/test_manifest_xml.py | 78 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 12 deletions(-) diff --git a/docs/manifest-format.md b/docs/manifest-format.md index 71fa04c5..06d370a3 100644 --- a/docs/manifest-format.md +++ b/docs/manifest-format.md @@ -98,7 +98,9 @@ following DTD: - + @@ -427,19 +429,20 @@ Same syntax as the corresponding element of `project`. ### Element annotation Zero or more annotation elements may be specified as children of a -project or remote element. Each element describes a name-value pair. -For projects, this name-value pair will be exported into each project's -environment during a 'forall' command, prefixed with `REPO__`. In addition, -there is an optional attribute "keep" which accepts the case insensitive values -"true" (default) or "false". This attribute determines whether or not the +project element, an extend-project element, or a remote element. Each +element describes a name-value pair. For projects, this name-value pair +will be exported into each project's environment during a 'forall' +command, prefixed with `REPO__`. In addition, there is an optional +attribute "keep" which accepts the case insensitive values "true" +(default) or "false". This attribute determines whether or not the annotation will be kept when exported with the manifest subcommand. ### Element copyfile Zero or more copyfile elements may be specified as children of a -project element. Each element describes a src-dest pair of files; -the "src" file will be copied to the "dest" place during `repo sync` -command. +project element, or an extend-project element. Each element describes a +src-dest pair of files; the "src" file will be copied to the "dest" +place during `repo sync` command. "src" is project relative, "dest" is relative to the top of the tree. Copying from paths outside of the project or to paths outside of the repo diff --git a/manifest_xml.py b/manifest_xml.py index 30c5b590..5e0b53b9 100644 --- a/manifest_xml.py +++ b/manifest_xml.py @@ -1509,6 +1509,14 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md p.UpdatePaths(relpath, worktree, gitdir, objdir) self._paths[p.relpath] = p + for n in node.childNodes: + if n.nodeName == "copyfile": + self._ParseCopyFile(p, n) + elif n.nodeName == "linkfile": + self._ParseLinkFile(p, n) + elif n.nodeName == "annotation": + self._ParseAnnotation(p, n) + if node.nodeName == "repo-hooks": # Only one project can be the hooks project if repo_hooks_project is not None: @@ -1963,11 +1971,11 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md for n in node.childNodes: if n.nodeName == "copyfile": self._ParseCopyFile(project, n) - if n.nodeName == "linkfile": + elif n.nodeName == "linkfile": self._ParseLinkFile(project, n) - if n.nodeName == "annotation": + elif n.nodeName == "annotation": self._ParseAnnotation(project, n) - if n.nodeName == "project": + elif n.nodeName == "project": project.subprojects.append( self._ParseProject(n, parent=project) ) diff --git a/tests/test_manifest_xml.py b/tests/test_manifest_xml.py index ebc0ce58..07939e16 100644 --- a/tests/test_manifest_xml.py +++ b/tests/test_manifest_xml.py @@ -1214,6 +1214,84 @@ class ExtendProjectElementTests(ManifestParseTestCase): self.assertEqual(len(manifest.projects), 1) self.assertEqual(manifest.projects[0].upstream, "bar") + def test_extend_project_copyfiles(self): + manifest = self.getXmlManifest( + """ + + + + + + + + +""" + ) + self.assertEqual(manifest.projects[0].copyfiles[0].src, "foo") + self.assertEqual(manifest.projects[0].copyfiles[0].dest, "bar") + self.assertEqual( + sort_attributes(manifest.ToXml().toxml()), + '' + '' + '' + '' + '' + "" + "", + ) + + def test_extend_project_linkfiles(self): + manifest = self.getXmlManifest( + """ + + + + + + + + +""" + ) + self.assertEqual(manifest.projects[0].linkfiles[0].src, "foo") + self.assertEqual(manifest.projects[0].linkfiles[0].dest, "bar") + self.assertEqual( + sort_attributes(manifest.ToXml().toxml()), + '' + '' + '' + '' + '' + "" + "", + ) + + def test_extend_project_annotations(self): + manifest = self.getXmlManifest( + """ + + + + + + + + +""" + ) + self.assertEqual(manifest.projects[0].annotations[0].name, "foo") + self.assertEqual(manifest.projects[0].annotations[0].value, "bar") + self.assertEqual( + sort_attributes(manifest.ToXml().toxml()), + '' + '' + '' + '' + '' + "" + "", + ) + class NormalizeUrlTests(ManifestParseTestCase): """Tests for normalize_url() in manifest_xml.py""" -- cgit v1.2.3-54-g00ecf