project: Use dicts to keep track of copyfiles and linkfiles

This avoids copying/linking the same file/link multiple times if a
copyfile/linkfile element with the same values has been specifed
multiple times. This can happen when including a common manifest that
uses an extend-project element that has a copyfile/linkfile element.

This uses dicts rather than sets to store the copyfiles and linkfiles to
make sure the order they are specified in the manifest is maintained.
For Python 3.7+, maintaining the order that keys are added to dicts is
guaranteed, and for Python 3.6 it happened to be true.

The _CopyFile class and the _LinkFile class are changed to inherit from
NamedTuple to be able to store them in dicts.

Change-Id: I9f5a80298b875251a81c5fe7d353e262d104fae4
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/525322
Reviewed-by: Mike Frysinger <vapier@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Peter Kjellerstedt <peter.kjellerstedt@axis.com>
Commit-Queue: Peter Kjellerstedt <peter.kjellerstedt@axis.com>
This commit is contained in:
Peter Kjellerstedt
2025-11-08 00:06:16 +01:00
committed by LUCI
parent 47c24b5c40
commit 412367bfaf
4 changed files with 131 additions and 40 deletions
+86 -4
View File
@@ -1254,8 +1254,8 @@ class ExtendProjectElementTests(ManifestParseTestCase):
</manifest>
"""
)
self.assertEqual(manifest.projects[0].copyfiles[0].src, "foo")
self.assertEqual(manifest.projects[0].copyfiles[0].dest, "bar")
self.assertEqual(list(manifest.projects[0].copyfiles)[0].src, "foo")
self.assertEqual(list(manifest.projects[0].copyfiles)[0].dest, "bar")
self.assertEqual(
sort_attributes(manifest.ToXml().toxml()),
'<?xml version="1.0" ?><manifest>'
@@ -1267,6 +1267,47 @@ class ExtendProjectElementTests(ManifestParseTestCase):
"</manifest>",
)
def test_extend_project_duplicate_copyfiles(self):
root_m = self.manifest_dir / "root.xml"
root_m.write_text(
"""
<manifest>
<remote name="test-remote" fetch="http://localhost" />
<default remote="test-remote" revision="refs/heads/main" />
<project name="myproject" />
<include name="man1.xml" />
<include name="man2.xml" />
</manifest>
"""
)
(self.manifest_dir / "man1.xml").write_text(
"""
<manifest>
<include name="common.xml" />
</manifest>
"""
)
(self.manifest_dir / "man2.xml").write_text(
"""
<manifest>
<include name="common.xml" />
</manifest>
"""
)
(self.manifest_dir / "common.xml").write_text(
"""
<manifest>
<extend-project name="myproject">
<copyfile dest="bar" src="foo"/>
</extend-project>
</manifest>
"""
)
manifest = manifest_xml.XmlManifest(str(self.repodir), str(root_m))
self.assertEqual(len(manifest.projects[0].copyfiles), 1)
self.assertEqual(list(manifest.projects[0].copyfiles)[0].src, "foo")
self.assertEqual(list(manifest.projects[0].copyfiles)[0].dest, "bar")
def test_extend_project_linkfiles(self):
manifest = self.getXmlManifest(
"""
@@ -1280,8 +1321,8 @@ class ExtendProjectElementTests(ManifestParseTestCase):
</manifest>
"""
)
self.assertEqual(manifest.projects[0].linkfiles[0].src, "foo")
self.assertEqual(manifest.projects[0].linkfiles[0].dest, "bar")
self.assertEqual(list(manifest.projects[0].linkfiles)[0].src, "foo")
self.assertEqual(list(manifest.projects[0].linkfiles)[0].dest, "bar")
self.assertEqual(
sort_attributes(manifest.ToXml().toxml()),
'<?xml version="1.0" ?><manifest>'
@@ -1293,6 +1334,47 @@ class ExtendProjectElementTests(ManifestParseTestCase):
"</manifest>",
)
def test_extend_project_duplicate_linkfiles(self):
root_m = self.manifest_dir / "root.xml"
root_m.write_text(
"""
<manifest>
<remote name="test-remote" fetch="http://localhost" />
<default remote="test-remote" revision="refs/heads/main" />
<project name="myproject" />
<include name="man1.xml" />
<include name="man2.xml" />
</manifest>
"""
)
(self.manifest_dir / "man1.xml").write_text(
"""
<manifest>
<include name="common.xml" />
</manifest>
"""
)
(self.manifest_dir / "man2.xml").write_text(
"""
<manifest>
<include name="common.xml" />
</manifest>
"""
)
(self.manifest_dir / "common.xml").write_text(
"""
<manifest>
<extend-project name="myproject">
<linkfile dest="bar" src="foo"/>
</extend-project>
</manifest>
"""
)
manifest = manifest_xml.XmlManifest(str(self.repodir), str(root_m))
self.assertEqual(len(manifest.projects[0].linkfiles), 1)
self.assertEqual(list(manifest.projects[0].linkfiles)[0].src, "foo")
self.assertEqual(list(manifest.projects[0].linkfiles)[0].dest, "bar")
def test_extend_project_annotations(self):
manifest = self.getXmlManifest(
"""