diff options
| author | Mike Frysinger <vapier@google.com> | 2020-09-06 14:53:18 -0400 |
|---|---|---|
| committer | Mike Frysinger <vapier@google.com> | 2020-11-18 19:10:57 +0000 |
| commit | 8c1e9cbef161f2ff12dadbacf26affd23876fde9 (patch) | |
| tree | fcfdc404568a2d8dbc9edd9ec99ecdd758f8c424 | |
| parent | a488af5ea5c53dd7cf2c90a751e77cc4ba87b7c3 (diff) | |
| download | git-repo-8c1e9cbef161f2ff12dadbacf26affd23876fde9.tar.gz | |
manifest_xml: refactor manifest parsing from client management
We conflate the manifest & parsing logic with the management of the
repo client checkout in a single class. This makes testing just one
part (the manifest parsing) hard as it requires a full checkout too.
Start splitting the two apart into separate classes to make it easy
to reason about & test.
Change-Id: Iaf897c93db9c724baba6044bfe7a589c024523b2
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/288682
Reviewed-by: Michael Mortensen <mmortensen@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
| -rwxr-xr-x | main.py | 13 | ||||
| -rw-r--r-- | manifest_xml.py | 80 | ||||
| -rw-r--r-- | project.py | 6 | ||||
| -rw-r--r-- | subcmds/diffmanifests.py | 8 | ||||
| -rw-r--r-- | subcmds/help.py | 4 | ||||
| -rw-r--r-- | subcmds/info.py | 2 | ||||
| -rw-r--r-- | subcmds/init.py | 4 | ||||
| -rw-r--r-- | subcmds/status.py | 2 | ||||
| -rw-r--r-- | tests/test_manifest_xml.py | 89 |
9 files changed, 164 insertions, 44 deletions
| @@ -63,7 +63,7 @@ from error import NoManifestException | |||
| 63 | from error import NoSuchProjectError | 63 | from error import NoSuchProjectError |
| 64 | from error import RepoChangedException | 64 | from error import RepoChangedException |
| 65 | import gitc_utils | 65 | import gitc_utils |
| 66 | from manifest_xml import GitcManifest, XmlManifest | 66 | from manifest_xml import GitcClient, RepoClient |
| 67 | from pager import RunPager, TerminatePager | 67 | from pager import RunPager, TerminatePager |
| 68 | from wrapper import WrapperPath, Wrapper | 68 | from wrapper import WrapperPath, Wrapper |
| 69 | 69 | ||
| @@ -212,14 +212,15 @@ class _Repo(object): | |||
| 212 | return 1 | 212 | return 1 |
| 213 | 213 | ||
| 214 | cmd.repodir = self.repodir | 214 | cmd.repodir = self.repodir |
| 215 | cmd.manifest = XmlManifest(cmd.repodir) | 215 | cmd.client = RepoClient(cmd.repodir) |
| 216 | cmd.manifest = cmd.client.manifest | ||
| 216 | cmd.gitc_manifest = None | 217 | cmd.gitc_manifest = None |
| 217 | gitc_client_name = gitc_utils.parse_clientdir(os.getcwd()) | 218 | gitc_client_name = gitc_utils.parse_clientdir(os.getcwd()) |
| 218 | if gitc_client_name: | 219 | if gitc_client_name: |
| 219 | cmd.gitc_manifest = GitcManifest(cmd.repodir, gitc_client_name) | 220 | cmd.gitc_manifest = GitcClient(cmd.repodir, gitc_client_name) |
| 220 | cmd.manifest.isGitcClient = True | 221 | cmd.client.isGitcClient = True |
| 221 | 222 | ||
| 222 | Editor.globalConfig = cmd.manifest.globalConfig | 223 | Editor.globalConfig = cmd.client.globalConfig |
| 223 | 224 | ||
| 224 | if not isinstance(cmd, MirrorSafeCommand) and cmd.manifest.IsMirror: | 225 | if not isinstance(cmd, MirrorSafeCommand) and cmd.manifest.IsMirror: |
| 225 | print("fatal: '%s' requires a working directory" % name, | 226 | print("fatal: '%s' requires a working directory" % name, |
| @@ -247,7 +248,7 @@ class _Repo(object): | |||
| 247 | return 1 | 248 | return 1 |
| 248 | 249 | ||
| 249 | if gopts.pager is not False and not isinstance(cmd, InteractiveCommand): | 250 | if gopts.pager is not False and not isinstance(cmd, InteractiveCommand): |
| 250 | config = cmd.manifest.globalConfig | 251 | config = cmd.client.globalConfig |
| 251 | if gopts.pager: | 252 | if gopts.pager: |
| 252 | use_pager = True | 253 | use_pager = True |
| 253 | else: | 254 | else: |
diff --git a/manifest_xml.py b/manifest_xml.py index e1ef330f..95c67d73 100644 --- a/manifest_xml.py +++ b/manifest_xml.py | |||
| @@ -187,12 +187,24 @@ class _XmlRemote(object): | |||
| 187 | class XmlManifest(object): | 187 | class XmlManifest(object): |
| 188 | """manages the repo configuration file""" | 188 | """manages the repo configuration file""" |
| 189 | 189 | ||
| 190 | def __init__(self, repodir): | 190 | def __init__(self, repodir, manifest_file, local_manifests=None): |
| 191 | """Initialize. | ||
| 192 | |||
| 193 | Args: | ||
| 194 | repodir: Path to the .repo/ dir for holding all internal checkout state. | ||
| 195 | It must be in the top directory of the repo client checkout. | ||
| 196 | manifest_file: Full path to the manifest file to parse. This will usually | ||
| 197 | be |repodir|/|MANIFEST_FILE_NAME|. | ||
| 198 | local_manifests: Full path to the directory of local override manifests. | ||
| 199 | This will usually be |repodir|/|LOCAL_MANIFESTS_DIR_NAME|. | ||
| 200 | """ | ||
| 201 | # TODO(vapier): Move this out of this class. | ||
| 202 | self.globalConfig = GitConfig.ForUser() | ||
| 203 | |||
| 191 | self.repodir = os.path.abspath(repodir) | 204 | self.repodir = os.path.abspath(repodir) |
| 192 | self.topdir = os.path.dirname(self.repodir) | 205 | self.topdir = os.path.dirname(self.repodir) |
| 193 | self.manifestFile = os.path.join(self.repodir, MANIFEST_FILE_NAME) | 206 | self.manifestFile = manifest_file |
| 194 | self.globalConfig = GitConfig.ForUser() | 207 | self.local_manifests = local_manifests |
| 195 | self.isGitcClient = False | ||
| 196 | self._load_local_manifests = True | 208 | self._load_local_manifests = True |
| 197 | 209 | ||
| 198 | self.repoProject = MetaProject(self, 'repo', | 210 | self.repoProject = MetaProject(self, 'repo', |
| @@ -602,20 +614,11 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md | |||
| 602 | nodes.append(self._ParseManifestXml(self.manifestFile, | 614 | nodes.append(self._ParseManifestXml(self.manifestFile, |
| 603 | self.manifestProject.worktree)) | 615 | self.manifestProject.worktree)) |
| 604 | 616 | ||
| 605 | if self._load_local_manifests: | 617 | if self._load_local_manifests and self.local_manifests: |
| 606 | if os.path.exists(os.path.join(self.repodir, LOCAL_MANIFEST_NAME)): | ||
| 607 | print('error: %s is not supported; put local manifests in `%s`' | ||
| 608 | 'instead' % (LOCAL_MANIFEST_NAME, | ||
| 609 | os.path.join(self.repodir, LOCAL_MANIFESTS_DIR_NAME)), | ||
| 610 | file=sys.stderr) | ||
| 611 | sys.exit(1) | ||
| 612 | |||
| 613 | local_dir = os.path.abspath(os.path.join(self.repodir, | ||
| 614 | LOCAL_MANIFESTS_DIR_NAME)) | ||
| 615 | try: | 618 | try: |
| 616 | for local_file in sorted(platform_utils.listdir(local_dir)): | 619 | for local_file in sorted(platform_utils.listdir(self.local_manifests)): |
| 617 | if local_file.endswith('.xml'): | 620 | if local_file.endswith('.xml'): |
| 618 | local = os.path.join(local_dir, local_file) | 621 | local = os.path.join(self.local_manifests, local_file) |
| 619 | nodes.append(self._ParseManifestXml(local, self.repodir)) | 622 | nodes.append(self._ParseManifestXml(local, self.repodir)) |
| 620 | except OSError: | 623 | except OSError: |
| 621 | pass | 624 | pass |
| @@ -1253,15 +1256,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md | |||
| 1253 | 1256 | ||
| 1254 | 1257 | ||
| 1255 | class GitcManifest(XmlManifest): | 1258 | class GitcManifest(XmlManifest): |
| 1256 | 1259 | """Parser for GitC (git-in-the-cloud) manifests.""" | |
| 1257 | def __init__(self, repodir, gitc_client_name): | ||
| 1258 | """Initialize the GitcManifest object.""" | ||
| 1259 | super(GitcManifest, self).__init__(repodir) | ||
| 1260 | self.isGitcClient = True | ||
| 1261 | self.gitc_client_name = gitc_client_name | ||
| 1262 | self.gitc_client_dir = os.path.join(gitc_utils.get_gitc_manifest_dir(), | ||
| 1263 | gitc_client_name) | ||
| 1264 | self.manifestFile = os.path.join(self.gitc_client_dir, '.manifest') | ||
| 1265 | 1260 | ||
| 1266 | def _ParseProject(self, node, parent=None): | 1261 | def _ParseProject(self, node, parent=None): |
| 1267 | """Override _ParseProject and add support for GITC specific attributes.""" | 1262 | """Override _ParseProject and add support for GITC specific attributes.""" |
| @@ -1272,3 +1267,38 @@ class GitcManifest(XmlManifest): | |||
| 1272 | """Output GITC Specific Project attributes""" | 1267 | """Output GITC Specific Project attributes""" |
| 1273 | if p.old_revision: | 1268 | if p.old_revision: |
| 1274 | e.setAttribute('old-revision', str(p.old_revision)) | 1269 | e.setAttribute('old-revision', str(p.old_revision)) |
| 1270 | |||
| 1271 | |||
| 1272 | class RepoClient(XmlManifest): | ||
| 1273 | """Manages a repo client checkout.""" | ||
| 1274 | |||
| 1275 | def __init__(self, repodir, manifest_file=None): | ||
| 1276 | self.isGitcClient = False | ||
| 1277 | |||
| 1278 | if os.path.exists(os.path.join(repodir, LOCAL_MANIFEST_NAME)): | ||
| 1279 | print('error: %s is not supported; put local manifests in `%s` instead' % | ||
| 1280 | (LOCAL_MANIFEST_NAME, os.path.join(repodir, LOCAL_MANIFESTS_DIR_NAME)), | ||
| 1281 | file=sys.stderr) | ||
| 1282 | sys.exit(1) | ||
| 1283 | |||
| 1284 | if manifest_file is None: | ||
| 1285 | manifest_file = os.path.join(repodir, MANIFEST_FILE_NAME) | ||
| 1286 | local_manifests = os.path.abspath(os.path.join(repodir, LOCAL_MANIFESTS_DIR_NAME)) | ||
| 1287 | super(RepoClient, self).__init__(repodir, manifest_file, local_manifests) | ||
| 1288 | |||
| 1289 | # TODO: Completely separate manifest logic out of the client. | ||
| 1290 | self.manifest = self | ||
| 1291 | |||
| 1292 | |||
| 1293 | class GitcClient(RepoClient, GitcManifest): | ||
| 1294 | """Manages a GitC client checkout.""" | ||
| 1295 | |||
| 1296 | def __init__(self, repodir, gitc_client_name): | ||
| 1297 | """Initialize the GitcManifest object.""" | ||
| 1298 | self.gitc_client_name = gitc_client_name | ||
| 1299 | self.gitc_client_dir = os.path.join(gitc_utils.get_gitc_manifest_dir(), | ||
| 1300 | gitc_client_name) | ||
| 1301 | |||
| 1302 | super(GitcManifest, self).__init__( | ||
| 1303 | repodir, os.path.join(self.gitc_client_dir, '.manifest')) | ||
| 1304 | self.isGitcClient = True | ||
| @@ -510,7 +510,7 @@ class Project(object): | |||
| 510 | with exponential backoff and jitter. | 510 | with exponential backoff and jitter. |
| 511 | old_revision: saved git commit id for open GITC projects. | 511 | old_revision: saved git commit id for open GITC projects. |
| 512 | """ | 512 | """ |
| 513 | self.manifest = manifest | 513 | self.client = self.manifest = manifest |
| 514 | self.name = name | 514 | self.name = name |
| 515 | self.remote = remote | 515 | self.remote = remote |
| 516 | self.gitdir = gitdir.replace('\\', '/') | 516 | self.gitdir = gitdir.replace('\\', '/') |
| @@ -551,7 +551,7 @@ class Project(object): | |||
| 551 | self.linkfiles = [] | 551 | self.linkfiles = [] |
| 552 | self.annotations = [] | 552 | self.annotations = [] |
| 553 | self.config = GitConfig.ForRepository(gitdir=self.gitdir, | 553 | self.config = GitConfig.ForRepository(gitdir=self.gitdir, |
| 554 | defaults=self.manifest.globalConfig) | 554 | defaults=self.client.globalConfig) |
| 555 | 555 | ||
| 556 | if self.worktree: | 556 | if self.worktree: |
| 557 | self.work_git = self._GitGetByExec(self, bare=False, gitdir=gitdir) | 557 | self.work_git = self._GitGetByExec(self, bare=False, gitdir=gitdir) |
| @@ -1168,7 +1168,7 @@ class Project(object): | |||
| 1168 | self._InitHooks() | 1168 | self._InitHooks() |
| 1169 | 1169 | ||
| 1170 | def _CopyAndLinkFiles(self): | 1170 | def _CopyAndLinkFiles(self): |
| 1171 | if self.manifest.isGitcClient: | 1171 | if self.client.isGitcClient: |
| 1172 | return | 1172 | return |
| 1173 | for copyfile in self.copyfiles: | 1173 | for copyfile in self.copyfiles: |
| 1174 | copyfile._Copy() | 1174 | copyfile._Copy() |
diff --git a/subcmds/diffmanifests.py b/subcmds/diffmanifests.py index 72c441ac..409bbdac 100644 --- a/subcmds/diffmanifests.py +++ b/subcmds/diffmanifests.py | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | from color import Coloring | 17 | from color import Coloring |
| 18 | from command import PagedCommand | 18 | from command import PagedCommand |
| 19 | from manifest_xml import XmlManifest | 19 | from manifest_xml import RepoClient |
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | class _Coloring(Coloring): | 22 | class _Coloring(Coloring): |
| @@ -183,7 +183,7 @@ synced and their revisions won't be found. | |||
| 183 | self.OptionParser.error('missing manifests to diff') | 183 | self.OptionParser.error('missing manifests to diff') |
| 184 | 184 | ||
| 185 | def Execute(self, opt, args): | 185 | def Execute(self, opt, args): |
| 186 | self.out = _Coloring(self.manifest.globalConfig) | 186 | self.out = _Coloring(self.client.globalConfig) |
| 187 | self.printText = self.out.nofmt_printer('text') | 187 | self.printText = self.out.nofmt_printer('text') |
| 188 | if opt.color: | 188 | if opt.color: |
| 189 | self.printProject = self.out.nofmt_printer('project', attr='bold') | 189 | self.printProject = self.out.nofmt_printer('project', attr='bold') |
| @@ -193,12 +193,12 @@ synced and their revisions won't be found. | |||
| 193 | else: | 193 | else: |
| 194 | self.printProject = self.printAdded = self.printRemoved = self.printRevision = self.printText | 194 | self.printProject = self.printAdded = self.printRemoved = self.printRevision = self.printText |
| 195 | 195 | ||
| 196 | manifest1 = XmlManifest(self.manifest.repodir) | 196 | manifest1 = RepoClient(self.manifest.repodir) |
| 197 | manifest1.Override(args[0], load_local_manifests=False) | 197 | manifest1.Override(args[0], load_local_manifests=False) |
| 198 | if len(args) == 1: | 198 | if len(args) == 1: |
| 199 | manifest2 = self.manifest | 199 | manifest2 = self.manifest |
| 200 | else: | 200 | else: |
| 201 | manifest2 = XmlManifest(self.manifest.repodir) | 201 | manifest2 = RepoClient(self.manifest.repodir) |
| 202 | manifest2.Override(args[1], load_local_manifests=False) | 202 | manifest2.Override(args[1], load_local_manifests=False) |
| 203 | 203 | ||
| 204 | diff = manifest1.projectsDiff(manifest2) | 204 | diff = manifest1.projectsDiff(manifest2) |
diff --git a/subcmds/help.py b/subcmds/help.py index 1e16019a..c219a763 100644 --- a/subcmds/help.py +++ b/subcmds/help.py | |||
| @@ -65,7 +65,7 @@ Displays detailed usage information about a command. | |||
| 65 | def gitc_supported(cmd): | 65 | def gitc_supported(cmd): |
| 66 | if not isinstance(cmd, GitcAvailableCommand) and not isinstance(cmd, GitcClientCommand): | 66 | if not isinstance(cmd, GitcAvailableCommand) and not isinstance(cmd, GitcClientCommand): |
| 67 | return True | 67 | return True |
| 68 | if self.manifest.isGitcClient: | 68 | if self.client.isGitcClient: |
| 69 | return True | 69 | return True |
| 70 | if isinstance(cmd, GitcClientCommand): | 70 | if isinstance(cmd, GitcClientCommand): |
| 71 | return False | 71 | return False |
| @@ -127,7 +127,7 @@ Displays detailed usage information about a command. | |||
| 127 | self.wrap.end_paragraph(1) | 127 | self.wrap.end_paragraph(1) |
| 128 | self.wrap.end_paragraph(0) | 128 | self.wrap.end_paragraph(0) |
| 129 | 129 | ||
| 130 | out = _Out(self.manifest.globalConfig) | 130 | out = _Out(self.client.globalConfig) |
| 131 | out._PrintSection('Summary', 'helpSummary') | 131 | out._PrintSection('Summary', 'helpSummary') |
| 132 | cmd.OptionParser.print_help() | 132 | cmd.OptionParser.print_help() |
| 133 | out._PrintSection('Description', 'helpDescription') | 133 | out._PrintSection('Description', 'helpDescription') |
diff --git a/subcmds/info.py b/subcmds/info.py index f4d6f98c..60149975 100644 --- a/subcmds/info.py +++ b/subcmds/info.py | |||
| @@ -44,7 +44,7 @@ class Info(PagedCommand): | |||
| 44 | help="Disable all remote operations") | 44 | help="Disable all remote operations") |
| 45 | 45 | ||
| 46 | def Execute(self, opt, args): | 46 | def Execute(self, opt, args): |
| 47 | self.out = _Coloring(self.manifest.globalConfig) | 47 | self.out = _Coloring(self.client.globalConfig) |
| 48 | self.heading = self.out.printer('heading', attr='bold') | 48 | self.heading = self.out.printer('heading', attr='bold') |
| 49 | self.headtext = self.out.nofmt_printer('headtext', fg='yellow') | 49 | self.headtext = self.out.nofmt_printer('headtext', fg='yellow') |
| 50 | self.redtext = self.out.printer('redtext', fg='red') | 50 | self.redtext = self.out.printer('redtext', fg='red') |
diff --git a/subcmds/init.py b/subcmds/init.py index 5ba0d074..f46babfe 100644 --- a/subcmds/init.py +++ b/subcmds/init.py | |||
| @@ -365,7 +365,7 @@ to update the working directory files. | |||
| 365 | return a | 365 | return a |
| 366 | 366 | ||
| 367 | def _ShouldConfigureUser(self, opt): | 367 | def _ShouldConfigureUser(self, opt): |
| 368 | gc = self.manifest.globalConfig | 368 | gc = self.client.globalConfig |
| 369 | mp = self.manifest.manifestProject | 369 | mp = self.manifest.manifestProject |
| 370 | 370 | ||
| 371 | # If we don't have local settings, get from global. | 371 | # If we don't have local settings, get from global. |
| @@ -414,7 +414,7 @@ to update the working directory files. | |||
| 414 | return False | 414 | return False |
| 415 | 415 | ||
| 416 | def _ConfigureColor(self): | 416 | def _ConfigureColor(self): |
| 417 | gc = self.manifest.globalConfig | 417 | gc = self.client.globalConfig |
| 418 | if self._HasColorSet(gc): | 418 | if self._HasColorSet(gc): |
| 419 | return | 419 | return |
| 420 | 420 | ||
diff --git a/subcmds/status.py b/subcmds/status.py index c380dba3..dfa974e9 100644 --- a/subcmds/status.py +++ b/subcmds/status.py | |||
| @@ -165,7 +165,7 @@ the following meanings: | |||
| 165 | proj_dirs, proj_dirs_parents, outstring) | 165 | proj_dirs, proj_dirs_parents, outstring) |
| 166 | 166 | ||
| 167 | if outstring: | 167 | if outstring: |
| 168 | output = StatusColoring(self.manifest.globalConfig) | 168 | output = StatusColoring(self.client.globalConfig) |
| 169 | output.project('Objects not within a project (orphans)') | 169 | output.project('Objects not within a project (orphans)') |
| 170 | output.nl() | 170 | output.nl() |
| 171 | for entry in outstring: | 171 | for entry in outstring: |
diff --git a/tests/test_manifest_xml.py b/tests/test_manifest_xml.py index aa6cb7df..40385cce 100644 --- a/tests/test_manifest_xml.py +++ b/tests/test_manifest_xml.py | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | from __future__ import print_function | 19 | from __future__ import print_function |
| 20 | 20 | ||
| 21 | import os | 21 | import os |
| 22 | import shutil | ||
| 23 | import tempfile | ||
| 22 | import unittest | 24 | import unittest |
| 23 | import xml.dom.minidom | 25 | import xml.dom.minidom |
| 24 | 26 | ||
| @@ -146,3 +148,90 @@ class ValueTests(unittest.TestCase): | |||
| 146 | with self.assertRaises(error.ManifestParseError): | 148 | with self.assertRaises(error.ManifestParseError): |
| 147 | node = self._get_node('<node a="xx"/>') | 149 | node = self._get_node('<node a="xx"/>') |
| 148 | manifest_xml.XmlInt(node, 'a') | 150 | manifest_xml.XmlInt(node, 'a') |
| 151 | |||
| 152 | |||
| 153 | class XmlManifestTests(unittest.TestCase): | ||
| 154 | """Check manifest processing.""" | ||
| 155 | |||
| 156 | def setUp(self): | ||
| 157 | self.tempdir = tempfile.mkdtemp(prefix='repo_tests') | ||
| 158 | self.repodir = os.path.join(self.tempdir, '.repo') | ||
| 159 | self.manifest_dir = os.path.join(self.repodir, 'manifests') | ||
| 160 | self.manifest_file = os.path.join( | ||
| 161 | self.repodir, manifest_xml.MANIFEST_FILE_NAME) | ||
| 162 | self.local_manifest_dir = os.path.join( | ||
| 163 | self.repodir, manifest_xml.LOCAL_MANIFESTS_DIR_NAME) | ||
| 164 | os.mkdir(self.repodir) | ||
| 165 | os.mkdir(self.manifest_dir) | ||
| 166 | |||
| 167 | # The manifest parsing really wants a git repo currently. | ||
| 168 | gitdir = os.path.join(self.repodir, 'manifests.git') | ||
| 169 | os.mkdir(gitdir) | ||
| 170 | with open(os.path.join(gitdir, 'config'), 'w') as fp: | ||
| 171 | fp.write("""[remote "origin"] | ||
| 172 | url = https://localhost:0/manifest | ||
| 173 | """) | ||
| 174 | |||
| 175 | def tearDown(self): | ||
| 176 | shutil.rmtree(self.tempdir, ignore_errors=True) | ||
| 177 | |||
| 178 | def getXmlManifest(self, data): | ||
| 179 | """Helper to initialize a manifest for testing.""" | ||
| 180 | with open(self.manifest_file, 'w') as fp: | ||
| 181 | fp.write(data) | ||
| 182 | return manifest_xml.XmlManifest(self.repodir, self.manifest_file) | ||
| 183 | |||
| 184 | def test_empty(self): | ||
| 185 | """Parse an 'empty' manifest file.""" | ||
| 186 | manifest = self.getXmlManifest( | ||
| 187 | '<?xml version="1.0" encoding="UTF-8"?>' | ||
| 188 | '<manifest></manifest>') | ||
| 189 | self.assertEqual(manifest.remotes, {}) | ||
| 190 | self.assertEqual(manifest.projects, []) | ||
| 191 | |||
| 192 | def test_link(self): | ||
| 193 | """Verify Link handling with new names.""" | ||
| 194 | manifest = manifest_xml.XmlManifest(self.repodir, self.manifest_file) | ||
| 195 | with open(os.path.join(self.manifest_dir, 'foo.xml'), 'w') as fp: | ||
| 196 | fp.write('<manifest></manifest>') | ||
| 197 | manifest.Link('foo.xml') | ||
| 198 | with open(self.manifest_file) as fp: | ||
| 199 | self.assertIn('<include name="foo.xml" />', fp.read()) | ||
| 200 | |||
| 201 | def test_toxml_empty(self): | ||
| 202 | """Verify the ToXml() helper.""" | ||
| 203 | manifest = self.getXmlManifest( | ||
| 204 | '<?xml version="1.0" encoding="UTF-8"?>' | ||
| 205 | '<manifest></manifest>') | ||
| 206 | self.assertEqual(manifest.ToXml().toxml(), '<?xml version="1.0" ?><manifest/>') | ||
| 207 | |||
| 208 | def test_todict_empty(self): | ||
| 209 | """Verify the ToDict() helper.""" | ||
| 210 | manifest = self.getXmlManifest( | ||
| 211 | '<?xml version="1.0" encoding="UTF-8"?>' | ||
| 212 | '<manifest></manifest>') | ||
| 213 | self.assertEqual(manifest.ToDict(), {}) | ||
| 214 | |||
| 215 | def test_project_group(self): | ||
| 216 | """Check project group settings.""" | ||
| 217 | manifest = self.getXmlManifest(""" | ||
| 218 | <manifest> | ||
| 219 | <remote name="test-remote" fetch="http://localhost" /> | ||
| 220 | <default remote="test-remote" revision="refs/heads/main" /> | ||
| 221 | <project name="test-name" path="test-path"/> | ||
| 222 | <project name="extras" path="path" groups="g1,g2,g1"/> | ||
| 223 | </manifest> | ||
| 224 | """) | ||
| 225 | self.assertEqual(len(manifest.projects), 2) | ||
| 226 | # Ordering isn't guaranteed. | ||
| 227 | result = { | ||
| 228 | manifest.projects[0].name: manifest.projects[0].groups, | ||
| 229 | manifest.projects[1].name: manifest.projects[1].groups, | ||
| 230 | } | ||
| 231 | project = manifest.projects[0] | ||
| 232 | self.assertCountEqual( | ||
| 233 | result['test-name'], | ||
| 234 | ['name:test-name', 'all', 'path:test-path']) | ||
| 235 | self.assertCountEqual( | ||
| 236 | result['extras'], | ||
| 237 | ['g1', 'g2', 'g1', 'name:extras', 'all', 'path:path']) | ||
