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 /manifest_xml.py | |
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>
Diffstat (limited to 'manifest_xml.py')
-rw-r--r-- | manifest_xml.py | 80 |
1 files changed, 55 insertions, 25 deletions
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 | ||