From f1a6b14fdc5402f9ed765a8a342d9c07c5b91e2d Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 3 Jun 2009 16:01:11 -0700 Subject: [PATCH] Create an abstract Manifest base class This will help as we add support for another manifest type. Signed-off-by: Shawn O. Pearce --- command.py | 10 +++++++- main.py | 4 ---- manifest.py | 37 ++++++++++++++++++++++++++++++ manifest_loader.py | 27 ++++++++++++++++++++++ manifest_xml.py | 57 +++++++++++++++++++--------------------------- subcmds/help.py | 1 + subcmds/sync.py | 2 +- 7 files changed, 99 insertions(+), 39 deletions(-) create mode 100644 manifest.py create mode 100644 manifest_loader.py diff --git a/command.py b/command.py index a941b95a..5ca43f20 100644 --- a/command.py +++ b/command.py @@ -17,6 +17,8 @@ import os import optparse import sys +import manifest_loader + from error import NoSuchProjectError class Command(object): @@ -24,7 +26,6 @@ class Command(object): """ common = False - manifest = None _optparse = None def WantPager(self, opt): @@ -57,6 +58,13 @@ class Command(object): """ raise NotImplementedError + @property + def manifest(self): + return self.GetManifest() + + def GetManifest(self, reparse=False): + return manifest_loader.GetManifest(self.repodir, reparse) + def GetProjects(self, args, missing_ok=False): """A list of projects that match the arguments. """ diff --git a/main.py b/main.py index 70ddeffa..a60641d7 100755 --- a/main.py +++ b/main.py @@ -32,11 +32,9 @@ from git_config import close_ssh from command import InteractiveCommand from command import MirrorSafeCommand from command import PagedCommand -from editor import Editor from error import ManifestInvalidRevisionError from error import NoSuchProjectError from error import RepoChangedException -from manifest_xml import XmlManifest from pager import RunPager from subcmds import all as all_commands @@ -97,8 +95,6 @@ class _Repo(object): sys.exit(1) cmd.repodir = self.repodir - cmd.manifest = XmlManifest(cmd.repodir) - Editor.globalConfig = cmd.manifest.globalConfig if not isinstance(cmd, MirrorSafeCommand) and cmd.manifest.IsMirror: print >>sys.stderr, \ diff --git a/manifest.py b/manifest.py new file mode 100644 index 00000000..bf801dfa --- /dev/null +++ b/manifest.py @@ -0,0 +1,37 @@ +# +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +from editor import Editor +from git_config import GitConfig +from project import MetaProject + +class Manifest(object): + """any manifest format""" + + def __init__(self, repodir): + self.repodir = os.path.abspath(repodir) + self.topdir = os.path.dirname(self.repodir) + self.globalConfig = GitConfig.ForUser() + Editor.globalConfig = self.globalConfig + + self.repoProject = MetaProject(self, 'repo', + gitdir = os.path.join(repodir, 'repo/.git'), + worktree = os.path.join(repodir, 'repo')) + + @property + def IsMirror(self): + return self.manifestProject.config.GetBoolean('repo.mirror') diff --git a/manifest_loader.py b/manifest_loader.py new file mode 100644 index 00000000..85ad3ea1 --- /dev/null +++ b/manifest_loader.py @@ -0,0 +1,27 @@ +# +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from manifest_xml import XmlManifest + +def ParseManifest(repodir): + return XmlManifest(repodir) + +_manifest = None + +def GetManifest(repodir, reparse=False): + global _manifest + if _manifest is None or reparse: + _manifest = ParseManifest(repodir) + return _manifest diff --git a/manifest_xml.py b/manifest_xml.py index 7d02f9d6..971cf212 100644 --- a/manifest_xml.py +++ b/manifest_xml.py @@ -18,6 +18,7 @@ import sys import xml.dom.minidom from git_config import GitConfig, IsId +from manifest import Manifest from project import RemoteSpec, Project, MetaProject, R_HEADS, HEAD from error import ManifestParseError @@ -46,19 +47,13 @@ class _XmlRemote(object): url += '/%s.git' % projectName return RemoteSpec(self.name, url, self.reviewUrl) -class XmlManifest(object): +class XmlManifest(Manifest): """manages the repo configuration file""" def __init__(self, repodir): - self.repodir = os.path.abspath(repodir) - self.topdir = os.path.dirname(self.repodir) - self.manifestFile = os.path.join(self.repodir, MANIFEST_FILE_NAME) - self.globalConfig = GitConfig.ForUser() - - self.repoProject = MetaProject(self, 'repo', - gitdir = os.path.join(repodir, 'repo/.git'), - worktree = os.path.join(repodir, 'repo')) + Manifest.__init__(self, repodir) + self._manifestFile = os.path.join(repodir, MANIFEST_FILE_NAME) self.manifestProject = MetaProject(self, 'manifests', gitdir = os.path.join(repodir, 'manifests.git'), worktree = os.path.join(repodir, 'manifests')) @@ -72,18 +67,18 @@ class XmlManifest(object): if not os.path.isfile(path): raise ManifestParseError('manifest %s not found' % name) - old = self.manifestFile + old = self._manifestFile try: - self.manifestFile = path + self._manifestFile = path self._Unload() self._Load() finally: - self.manifestFile = old + self._manifestFile = old try: - if os.path.exists(self.manifestFile): - os.remove(self.manifestFile) - os.symlink('manifests/%s' % name, self.manifestFile) + if os.path.exists(self._manifestFile): + os.remove(self._manifestFile) + os.symlink('manifests/%s' % name, self._manifestFile) except OSError, e: raise ManifestParseError('cannot link manifest %s' % name) @@ -168,10 +163,6 @@ class XmlManifest(object): self._Load() return self._default - @property - def IsMirror(self): - return self.manifestProject.config.GetBoolean('repo.mirror') - def _Unload(self): self._loaded = False self._projects = {} @@ -192,11 +183,11 @@ class XmlManifest(object): local = os.path.join(self.repodir, LOCAL_MANIFEST_NAME) if os.path.exists(local): try: - real = self.manifestFile - self.manifestFile = local + real = self._manifestFile + self._manifestFile = local self._ParseManifest(False) finally: - self.manifestFile = real + self._manifestFile = real if self.IsMirror: self._AddMetaProjectMirror(self.repoProject) @@ -205,17 +196,17 @@ class XmlManifest(object): self._loaded = True def _ParseManifest(self, is_root_file): - root = xml.dom.minidom.parse(self.manifestFile) + root = xml.dom.minidom.parse(self._manifestFile) if not root or not root.childNodes: raise ManifestParseError, \ "no root node in %s" % \ - self.manifestFile + self._manifestFile config = root.childNodes[0] if config.nodeName != 'manifest': raise ManifestParseError, \ "no in %s" % \ - self.manifestFile + self._manifestFile for node in config.childNodes: if node.nodeName == 'remove-project': @@ -233,7 +224,7 @@ class XmlManifest(object): if self._remotes.get(remote.name): raise ManifestParseError, \ 'duplicate remote %s in %s' % \ - (remote.name, self.manifestFile) + (remote.name, self._manifestFile) self._remotes[remote.name] = remote for node in config.childNodes: @@ -241,7 +232,7 @@ class XmlManifest(object): if self._default is not None: raise ManifestParseError, \ 'duplicate default in %s' % \ - (self.manifestFile) + (self._manifestFile) self._default = self._ParseDefault(node) if self._default is None: self._default = _Default() @@ -252,7 +243,7 @@ class XmlManifest(object): if self._projects.get(project.name): raise ManifestParseError, \ 'duplicate project %s in %s' % \ - (project.name, self.manifestFile) + (project.name, self._manifestFile) self._projects[project.name] = project def _AddMetaProjectMirror(self, m): @@ -324,7 +315,7 @@ class XmlManifest(object): if remote is None: raise ManifestParseError, \ "no remote for project %s within %s" % \ - (name, self.manifestFile) + (name, self._manifestFile) revisionExpr = node.getAttribute('revision') if not revisionExpr: @@ -332,7 +323,7 @@ class XmlManifest(object): if not revisionExpr: raise ManifestParseError, \ "no revision for project %s within %s" % \ - (name, self.manifestFile) + (name, self._manifestFile) path = node.getAttribute('path') if not path: @@ -340,7 +331,7 @@ class XmlManifest(object): if path.startswith('/'): raise ManifestParseError, \ "project %s path cannot be absolute in %s" % \ - (name, self.manifestFile) + (name, self._manifestFile) if self.IsMirror: relpath = None @@ -382,7 +373,7 @@ class XmlManifest(object): if not v: raise ManifestParseError, \ "remote %s not defined in %s" % \ - (name, self.manifestFile) + (name, self._manifestFile) return v def _reqatt(self, node, attname): @@ -393,5 +384,5 @@ class XmlManifest(object): if not v: raise ManifestParseError, \ "no %s in <%s> within %s" % \ - (attname, node.nodeName, self.manifestFile) + (attname, node.nodeName, self._manifestFile) return v diff --git a/subcmds/help.py b/subcmds/help.py index c5979fd6..01d5fa23 100644 --- a/subcmds/help.py +++ b/subcmds/help.py @@ -163,6 +163,7 @@ See 'repo help --all' for a complete list of recognized commands. print >>sys.stderr, "repo: '%s' is not a repo command." % name sys.exit(1) + cmd.repodir = self.repodir self._PrintCommandHelp(cmd) else: diff --git a/subcmds/sync.py b/subcmds/sync.py index bd07dd9f..afd44dab 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py @@ -214,7 +214,7 @@ uncommitted changes are present' % project.relpath if not syncbuf.Finish(): sys.exit(1) - self.manifest._Unload() + self.GetManifest(reparse=True) all = self.GetProjects(args, missing_ok=True) missing = [] for project in all: