diff options
| author | Peter Kjellerstedt <pkj@axis.com> | 2025-11-08 02:36:56 +0100 |
|---|---|---|
| committer | LUCI <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2025-11-26 02:08:07 -0800 |
| commit | 75773b8b9d265bc8ef113586be5c3e2d36250983 (patch) | |
| tree | a8525157425c4732962f89cdbd0315a9c9a46dbe /manifest_xml.py | |
| parent | 412367bfafd9de014cfeb37475e0f97b1f6a2509 (diff) | |
| download | git-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.py | 90 |
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 | ||
| 387 | class XmlManifest: | 385 | class 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): |
