summaryrefslogtreecommitdiffstats
path: root/manifest_xml.py
diff options
context:
space:
mode:
authorPeter Kjellerstedt <pkj@axis.com>2025-11-08 02:36:56 +0100
committerLUCI <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com>2025-11-26 02:08:07 -0800
commit75773b8b9d265bc8ef113586be5c3e2d36250983 (patch)
treea8525157425c4732962f89cdbd0315a9c9a46dbe /manifest_xml.py
parent412367bfafd9de014cfeb37475e0f97b1f6a2509 (diff)
downloadgit-repo-75773b8b9d265bc8ef113586be5c3e2d36250983.tar.gz
manifest, project: Store project groups as sets
This helps a lot when including common manifests with groups and they use extend-project. Change-Id: Ic574e7d6696139d0eb90d9915e8c7048d5e89c07 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/525323 Reviewed-by: Gavin Mak <gavinmak@google.com> Tested-by: Peter Kjellerstedt <peter.kjellerstedt@axis.com> Reviewed-by: Mike Frysinger <vapier@google.com> Commit-Queue: Peter Kjellerstedt <peter.kjellerstedt@axis.com>
Diffstat (limited to 'manifest_xml.py')
-rw-r--r--manifest_xml.py90
1 files changed, 46 insertions, 44 deletions
diff --git a/manifest_xml.py b/manifest_xml.py
index 33a55282..2d476748 100644
--- a/manifest_xml.py
+++ b/manifest_xml.py
@@ -255,7 +255,7 @@ class _XmlSubmanifest:
255 project: a string, the name of the manifest project. 255 project: a string, the name of the manifest project.
256 revision: a string, the commitish. 256 revision: a string, the commitish.
257 manifestName: a string, the submanifest file name. 257 manifestName: a string, the submanifest file name.
258 groups: a list of strings, the groups to add to all projects in the 258 groups: a set of strings, the groups to add to all projects in the
259 submanifest. 259 submanifest.
260 default_groups: a list of strings, the default groups to sync. 260 default_groups: a list of strings, the default groups to sync.
261 path: a string, the relative path for the submanifest checkout. 261 path: a string, the relative path for the submanifest checkout.
@@ -281,7 +281,7 @@ class _XmlSubmanifest:
281 self.project = project 281 self.project = project
282 self.revision = revision 282 self.revision = revision
283 self.manifestName = manifestName 283 self.manifestName = manifestName
284 self.groups = groups 284 self.groups = groups or set()
285 self.default_groups = default_groups 285 self.default_groups = default_groups
286 self.path = path 286 self.path = path
287 self.parent = parent 287 self.parent = parent
@@ -304,7 +304,7 @@ class _XmlSubmanifest:
304 self.repo_client = RepoClient( 304 self.repo_client = RepoClient(
305 parent.repodir, 305 parent.repodir,
306 linkFile, 306 linkFile,
307 parent_groups=",".join(groups) or "", 307 parent_groups=groups,
308 submanifest_path=os.path.join(parent.path_prefix, self.relpath), 308 submanifest_path=os.path.join(parent.path_prefix, self.relpath),
309 outer_client=outer_client, 309 outer_client=outer_client,
310 default_groups=default_groups, 310 default_groups=default_groups,
@@ -345,7 +345,7 @@ class _XmlSubmanifest:
345 manifestName = self.manifestName or "default.xml" 345 manifestName = self.manifestName or "default.xml"
346 revision = self.revision or self.name 346 revision = self.revision or self.name
347 path = self.path or revision.split("/")[-1] 347 path = self.path or revision.split("/")[-1]
348 groups = self.groups or [] 348 groups = self.groups
349 349
350 return SubmanifestSpec( 350 return SubmanifestSpec(
351 self.name, manifestUrl, manifestName, revision, path, groups 351 self.name, manifestUrl, manifestName, revision, path, groups
@@ -359,9 +359,7 @@ class _XmlSubmanifest:
359 359
360 def GetGroupsStr(self): 360 def GetGroupsStr(self):
361 """Returns the `groups` given for this submanifest.""" 361 """Returns the `groups` given for this submanifest."""
362 if self.groups: 362 return ",".join(sorted(self.groups))
363 return ",".join(self.groups)
364 return ""
365 363
366 def GetDefaultGroupsStr(self): 364 def GetDefaultGroupsStr(self):
367 """Returns the `default-groups` given for this submanifest.""" 365 """Returns the `default-groups` given for this submanifest."""
@@ -381,7 +379,7 @@ class SubmanifestSpec:
381 self.manifestName = manifestName 379 self.manifestName = manifestName
382 self.revision = revision 380 self.revision = revision
383 self.path = path 381 self.path = path
384 self.groups = groups or [] 382 self.groups = groups
385 383
386 384
387class XmlManifest: 385class XmlManifest:
@@ -393,7 +391,7 @@ class XmlManifest:
393 manifest_file, 391 manifest_file,
394 local_manifests=None, 392 local_manifests=None,
395 outer_client=None, 393 outer_client=None,
396 parent_groups="", 394 parent_groups=None,
397 submanifest_path="", 395 submanifest_path="",
398 default_groups=None, 396 default_groups=None,
399 ): 397 ):
@@ -409,7 +407,8 @@ class XmlManifest:
409 manifests. This will usually be 407 manifests. This will usually be
410 |repodir|/|LOCAL_MANIFESTS_DIR_NAME|. 408 |repodir|/|LOCAL_MANIFESTS_DIR_NAME|.
411 outer_client: RepoClient of the outer manifest. 409 outer_client: RepoClient of the outer manifest.
412 parent_groups: a string, the groups to apply to this projects. 410 parent_groups: a set of strings, the groups to apply to this
411 manifest.
413 submanifest_path: The submanifest root relative to the repo root. 412 submanifest_path: The submanifest root relative to the repo root.
414 default_groups: a string, the default manifest groups to use. 413 default_groups: a string, the default manifest groups to use.
415 """ 414 """
@@ -432,7 +431,7 @@ class XmlManifest:
432 self.manifestFileOverrides = {} 431 self.manifestFileOverrides = {}
433 self.local_manifests = local_manifests 432 self.local_manifests = local_manifests
434 self._load_local_manifests = True 433 self._load_local_manifests = True
435 self.parent_groups = parent_groups 434 self.parent_groups = parent_groups or set()
436 self.default_groups = default_groups 435 self.default_groups = default_groups
437 436
438 if submanifest_path and not outer_client: 437 if submanifest_path and not outer_client:
@@ -567,6 +566,14 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
567 """ 566 """
568 return [x for x in re.split(r"[,\s]+", field) if x] 567 return [x for x in re.split(r"[,\s]+", field) if x]
569 568
569 def _ParseSet(self, field):
570 """Parse fields that contain flattened sets.
571
572 These are whitespace & comma separated. Empty elements will be
573 discarded.
574 """
575 return set(self._ParseList(field))
576
570 def ToXml( 577 def ToXml(
571 self, 578 self,
572 peg_rev=False, 579 peg_rev=False,
@@ -725,10 +732,9 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
725 le.setAttribute("dest", lf.dest) 732 le.setAttribute("dest", lf.dest)
726 e.appendChild(le) 733 e.appendChild(le)
727 734
728 default_groups = ["all", "name:%s" % p.name, "path:%s" % p.relpath] 735 egroups = p.groups - {"all", f"name:{p.name}", f"path:{p.relpath}"}
729 egroups = [g for g in p.groups if g not in default_groups]
730 if egroups: 736 if egroups:
731 e.setAttribute("groups", ",".join(egroups)) 737 e.setAttribute("groups", ",".join(sorted(egroups)))
732 738
733 for a in p.annotations: 739 for a in p.annotations:
734 if a.keep == "true": 740 if a.keep == "true":
@@ -1171,12 +1177,12 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
1171 b = b[len(R_HEADS) :] 1177 b = b[len(R_HEADS) :]
1172 self.branch = b 1178 self.branch = b
1173 1179
1174 parent_groups = self.parent_groups 1180 parent_groups = self.parent_groups.copy()
1175 if self.path_prefix: 1181 if self.path_prefix:
1176 parent_groups = ( 1182 parent_groups |= {
1177 f"{SUBMANIFEST_GROUP_PREFIX}:path:" 1183 f"{SUBMANIFEST_GROUP_PREFIX}:path:"
1178 f"{self.path_prefix},{parent_groups}" 1184 f"{self.path_prefix}"
1179 ) 1185 }
1180 1186
1181 # The manifestFile was specified by the user which is why we 1187 # The manifestFile was specified by the user which is why we
1182 # allow include paths to point anywhere. 1188 # allow include paths to point anywhere.
@@ -1202,16 +1208,16 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
1202 # Since local manifests are entirely managed by 1208 # Since local manifests are entirely managed by
1203 # the user, allow them to point anywhere the 1209 # the user, allow them to point anywhere the
1204 # user wants. 1210 # user wants.
1205 local_group = ( 1211 local_group = {
1206 f"{LOCAL_MANIFEST_GROUP_PREFIX}:" 1212 f"{LOCAL_MANIFEST_GROUP_PREFIX}:"
1207 f"{local_file[:-4]}" 1213 f"{local_file[:-4]}"
1208 ) 1214 }
1209 nodes.append( 1215 nodes.append(
1210 self._ParseManifestXml( 1216 self._ParseManifestXml(
1211 local, 1217 local,
1212 self.subdir, 1218 self.subdir,
1213 parent_groups=( 1219 parent_groups=(
1214 f"{local_group},{parent_groups}" 1220 local_group | parent_groups
1215 ), 1221 ),
1216 restrict_includes=False, 1222 restrict_includes=False,
1217 ) 1223 )
@@ -1262,7 +1268,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
1262 self, 1268 self,
1263 path, 1269 path,
1264 include_root, 1270 include_root,
1265 parent_groups="", 1271 parent_groups=None,
1266 restrict_includes=True, 1272 restrict_includes=True,
1267 parent_node=None, 1273 parent_node=None,
1268 ): 1274 ):
@@ -1271,11 +1277,11 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
1271 Args: 1277 Args:
1272 path: The XML file to read & parse. 1278 path: The XML file to read & parse.
1273 include_root: The path to interpret include "name"s relative to. 1279 include_root: The path to interpret include "name"s relative to.
1274 parent_groups: The groups to apply to this projects. 1280 parent_groups: The set of groups to apply to this manifest.
1275 restrict_includes: Whether to constrain the "name" attribute of 1281 restrict_includes: Whether to constrain the "name" attribute of
1276 includes. 1282 includes.
1277 parent_node: The parent include node, to apply attribute to this 1283 parent_node: The parent include node, to apply attributes to this
1278 projects. 1284 manifest.
1279 1285
1280 Returns: 1286 Returns:
1281 List of XML nodes. 1287 List of XML nodes.
@@ -1307,12 +1313,10 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
1307 raise ManifestInvalidPathError( 1313 raise ManifestInvalidPathError(
1308 f'<include> invalid "name": {name}: {msg}' 1314 f'<include> invalid "name": {name}: {msg}'
1309 ) 1315 )
1310 include_groups = "" 1316 include_groups = (parent_groups or set()).copy()
1311 if parent_groups:
1312 include_groups = parent_groups
1313 if node.hasAttribute("groups"): 1317 if node.hasAttribute("groups"):
1314 include_groups = ( 1318 include_groups |= self._ParseSet(
1315 node.getAttribute("groups") + "," + include_groups 1319 node.getAttribute("groups")
1316 ) 1320 )
1317 fp = os.path.join(include_root, name) 1321 fp = os.path.join(include_root, name)
1318 if not os.path.isfile(fp): 1322 if not os.path.isfile(fp):
@@ -1339,12 +1343,12 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
1339 "project", 1343 "project",
1340 "extend-project", 1344 "extend-project",
1341 ): 1345 ):
1342 nodeGroups = parent_groups 1346 nodeGroups = parent_groups.copy()
1343 if node.hasAttribute("groups"): 1347 if node.hasAttribute("groups"):
1344 nodeGroups = ( 1348 nodeGroups |= self._ParseSet(
1345 node.getAttribute("groups") + "," + nodeGroups 1349 node.getAttribute("groups")
1346 ) 1350 )
1347 node.setAttribute("groups", nodeGroups) 1351 node.setAttribute("groups", ",".join(sorted(nodeGroups)))
1348 if ( 1352 if (
1349 parent_node 1353 parent_node
1350 and node.nodeName == "project" 1354 and node.nodeName == "project"
@@ -1461,7 +1465,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
1461 dest_path = node.getAttribute("dest-path") 1465 dest_path = node.getAttribute("dest-path")
1462 groups = node.getAttribute("groups") 1466 groups = node.getAttribute("groups")
1463 if groups: 1467 if groups:
1464 groups = self._ParseList(groups) 1468 groups = self._ParseSet(groups or "")
1465 revision = node.getAttribute("revision") 1469 revision = node.getAttribute("revision")
1466 remote_name = node.getAttribute("remote") 1470 remote_name = node.getAttribute("remote")
1467 if not remote_name: 1471 if not remote_name:
@@ -1482,7 +1486,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
1482 if path and p.relpath != path: 1486 if path and p.relpath != path:
1483 continue 1487 continue
1484 if groups: 1488 if groups:
1485 p.groups.extend(groups) 1489 p.groups |= groups
1486 if revision: 1490 if revision:
1487 if base_revision: 1491 if base_revision:
1488 if p.revisionExpr != base_revision: 1492 if p.revisionExpr != base_revision:
@@ -1813,7 +1817,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
1813 groups = "" 1817 groups = ""
1814 if node.hasAttribute("groups"): 1818 if node.hasAttribute("groups"):
1815 groups = node.getAttribute("groups") 1819 groups = node.getAttribute("groups")
1816 groups = self._ParseList(groups) 1820 groups = self._ParseSet(groups)
1817 default_groups = self._ParseList(node.getAttribute("default-groups")) 1821 default_groups = self._ParseList(node.getAttribute("default-groups"))
1818 path = node.getAttribute("path") 1822 path = node.getAttribute("path")
1819 if path == "": 1823 if path == "":
@@ -1922,11 +1926,6 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
1922 1926
1923 upstream = node.getAttribute("upstream") or self._default.upstreamExpr 1927 upstream = node.getAttribute("upstream") or self._default.upstreamExpr
1924 1928
1925 groups = ""
1926 if node.hasAttribute("groups"):
1927 groups = node.getAttribute("groups")
1928 groups = self._ParseList(groups)
1929
1930 if parent is None: 1929 if parent is None:
1931 ( 1930 (
1932 relpath, 1931 relpath,
@@ -1941,8 +1940,11 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
1941 parent, name, path 1940 parent, name, path
1942 ) 1941 )
1943 1942
1944 default_groups = ["all", "name:%s" % name, "path:%s" % relpath] 1943 groups = ""
1945 groups.extend(set(default_groups).difference(groups)) 1944 if node.hasAttribute("groups"):
1945 groups = node.getAttribute("groups")
1946 groups = self._ParseSet(groups)
1947 groups |= {"all", f"name:{name}", f"path:{relpath}"}
1946 1948
1947 if self.IsMirror and node.hasAttribute("force-path"): 1949 if self.IsMirror and node.hasAttribute("force-path"):
1948 if XmlBool(node, "force-path", False): 1950 if XmlBool(node, "force-path", False):