Create an abstract Manifest base class

This will help as we add support for another manifest type.

Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce 2009-06-03 16:01:11 -07:00
parent ca3d8ff4fc
commit f1a6b14fdc
7 changed files with 99 additions and 39 deletions

View File

@ -17,6 +17,8 @@ import os
import optparse import optparse
import sys import sys
import manifest_loader
from error import NoSuchProjectError from error import NoSuchProjectError
class Command(object): class Command(object):
@ -24,7 +26,6 @@ class Command(object):
""" """
common = False common = False
manifest = None
_optparse = None _optparse = None
def WantPager(self, opt): def WantPager(self, opt):
@ -57,6 +58,13 @@ class Command(object):
""" """
raise NotImplementedError 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): def GetProjects(self, args, missing_ok=False):
"""A list of projects that match the arguments. """A list of projects that match the arguments.
""" """

View File

@ -32,11 +32,9 @@ from git_config import close_ssh
from command import InteractiveCommand from command import InteractiveCommand
from command import MirrorSafeCommand from command import MirrorSafeCommand
from command import PagedCommand from command import PagedCommand
from editor import Editor
from error import ManifestInvalidRevisionError from error import ManifestInvalidRevisionError
from error import NoSuchProjectError from error import NoSuchProjectError
from error import RepoChangedException from error import RepoChangedException
from manifest_xml import XmlManifest
from pager import RunPager from pager import RunPager
from subcmds import all as all_commands from subcmds import all as all_commands
@ -97,8 +95,6 @@ class _Repo(object):
sys.exit(1) sys.exit(1)
cmd.repodir = self.repodir cmd.repodir = self.repodir
cmd.manifest = XmlManifest(cmd.repodir)
Editor.globalConfig = cmd.manifest.globalConfig
if not isinstance(cmd, MirrorSafeCommand) and cmd.manifest.IsMirror: if not isinstance(cmd, MirrorSafeCommand) and cmd.manifest.IsMirror:
print >>sys.stderr, \ print >>sys.stderr, \

37
manifest.py Normal file
View File

@ -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')

27
manifest_loader.py Normal file
View File

@ -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

View File

@ -18,6 +18,7 @@ import sys
import xml.dom.minidom import xml.dom.minidom
from git_config import GitConfig, IsId from git_config import GitConfig, IsId
from manifest import Manifest
from project import RemoteSpec, Project, MetaProject, R_HEADS, HEAD from project import RemoteSpec, Project, MetaProject, R_HEADS, HEAD
from error import ManifestParseError from error import ManifestParseError
@ -46,19 +47,13 @@ class _XmlRemote(object):
url += '/%s.git' % projectName url += '/%s.git' % projectName
return RemoteSpec(self.name, url, self.reviewUrl) return RemoteSpec(self.name, url, self.reviewUrl)
class XmlManifest(object): class XmlManifest(Manifest):
"""manages the repo configuration file""" """manages the repo configuration file"""
def __init__(self, repodir): def __init__(self, repodir):
self.repodir = os.path.abspath(repodir) Manifest.__init__(self, 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'))
self._manifestFile = os.path.join(repodir, MANIFEST_FILE_NAME)
self.manifestProject = MetaProject(self, 'manifests', self.manifestProject = MetaProject(self, 'manifests',
gitdir = os.path.join(repodir, 'manifests.git'), gitdir = os.path.join(repodir, 'manifests.git'),
worktree = os.path.join(repodir, 'manifests')) worktree = os.path.join(repodir, 'manifests'))
@ -72,18 +67,18 @@ class XmlManifest(object):
if not os.path.isfile(path): if not os.path.isfile(path):
raise ManifestParseError('manifest %s not found' % name) raise ManifestParseError('manifest %s not found' % name)
old = self.manifestFile old = self._manifestFile
try: try:
self.manifestFile = path self._manifestFile = path
self._Unload() self._Unload()
self._Load() self._Load()
finally: finally:
self.manifestFile = old self._manifestFile = old
try: try:
if os.path.exists(self.manifestFile): if os.path.exists(self._manifestFile):
os.remove(self.manifestFile) os.remove(self._manifestFile)
os.symlink('manifests/%s' % name, self.manifestFile) os.symlink('manifests/%s' % name, self._manifestFile)
except OSError, e: except OSError, e:
raise ManifestParseError('cannot link manifest %s' % name) raise ManifestParseError('cannot link manifest %s' % name)
@ -168,10 +163,6 @@ class XmlManifest(object):
self._Load() self._Load()
return self._default return self._default
@property
def IsMirror(self):
return self.manifestProject.config.GetBoolean('repo.mirror')
def _Unload(self): def _Unload(self):
self._loaded = False self._loaded = False
self._projects = {} self._projects = {}
@ -192,11 +183,11 @@ class XmlManifest(object):
local = os.path.join(self.repodir, LOCAL_MANIFEST_NAME) local = os.path.join(self.repodir, LOCAL_MANIFEST_NAME)
if os.path.exists(local): if os.path.exists(local):
try: try:
real = self.manifestFile real = self._manifestFile
self.manifestFile = local self._manifestFile = local
self._ParseManifest(False) self._ParseManifest(False)
finally: finally:
self.manifestFile = real self._manifestFile = real
if self.IsMirror: if self.IsMirror:
self._AddMetaProjectMirror(self.repoProject) self._AddMetaProjectMirror(self.repoProject)
@ -205,17 +196,17 @@ class XmlManifest(object):
self._loaded = True self._loaded = True
def _ParseManifest(self, is_root_file): 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: if not root or not root.childNodes:
raise ManifestParseError, \ raise ManifestParseError, \
"no root node in %s" % \ "no root node in %s" % \
self.manifestFile self._manifestFile
config = root.childNodes[0] config = root.childNodes[0]
if config.nodeName != 'manifest': if config.nodeName != 'manifest':
raise ManifestParseError, \ raise ManifestParseError, \
"no <manifest> in %s" % \ "no <manifest> in %s" % \
self.manifestFile self._manifestFile
for node in config.childNodes: for node in config.childNodes:
if node.nodeName == 'remove-project': if node.nodeName == 'remove-project':
@ -233,7 +224,7 @@ class XmlManifest(object):
if self._remotes.get(remote.name): if self._remotes.get(remote.name):
raise ManifestParseError, \ raise ManifestParseError, \
'duplicate remote %s in %s' % \ 'duplicate remote %s in %s' % \
(remote.name, self.manifestFile) (remote.name, self._manifestFile)
self._remotes[remote.name] = remote self._remotes[remote.name] = remote
for node in config.childNodes: for node in config.childNodes:
@ -241,7 +232,7 @@ class XmlManifest(object):
if self._default is not None: if self._default is not None:
raise ManifestParseError, \ raise ManifestParseError, \
'duplicate default in %s' % \ 'duplicate default in %s' % \
(self.manifestFile) (self._manifestFile)
self._default = self._ParseDefault(node) self._default = self._ParseDefault(node)
if self._default is None: if self._default is None:
self._default = _Default() self._default = _Default()
@ -252,7 +243,7 @@ class XmlManifest(object):
if self._projects.get(project.name): if self._projects.get(project.name):
raise ManifestParseError, \ raise ManifestParseError, \
'duplicate project %s in %s' % \ 'duplicate project %s in %s' % \
(project.name, self.manifestFile) (project.name, self._manifestFile)
self._projects[project.name] = project self._projects[project.name] = project
def _AddMetaProjectMirror(self, m): def _AddMetaProjectMirror(self, m):
@ -324,7 +315,7 @@ class XmlManifest(object):
if remote is None: if remote is None:
raise ManifestParseError, \ raise ManifestParseError, \
"no remote for project %s within %s" % \ "no remote for project %s within %s" % \
(name, self.manifestFile) (name, self._manifestFile)
revisionExpr = node.getAttribute('revision') revisionExpr = node.getAttribute('revision')
if not revisionExpr: if not revisionExpr:
@ -332,7 +323,7 @@ class XmlManifest(object):
if not revisionExpr: if not revisionExpr:
raise ManifestParseError, \ raise ManifestParseError, \
"no revision for project %s within %s" % \ "no revision for project %s within %s" % \
(name, self.manifestFile) (name, self._manifestFile)
path = node.getAttribute('path') path = node.getAttribute('path')
if not path: if not path:
@ -340,7 +331,7 @@ class XmlManifest(object):
if path.startswith('/'): if path.startswith('/'):
raise ManifestParseError, \ raise ManifestParseError, \
"project %s path cannot be absolute in %s" % \ "project %s path cannot be absolute in %s" % \
(name, self.manifestFile) (name, self._manifestFile)
if self.IsMirror: if self.IsMirror:
relpath = None relpath = None
@ -382,7 +373,7 @@ class XmlManifest(object):
if not v: if not v:
raise ManifestParseError, \ raise ManifestParseError, \
"remote %s not defined in %s" % \ "remote %s not defined in %s" % \
(name, self.manifestFile) (name, self._manifestFile)
return v return v
def _reqatt(self, node, attname): def _reqatt(self, node, attname):
@ -393,5 +384,5 @@ class XmlManifest(object):
if not v: if not v:
raise ManifestParseError, \ raise ManifestParseError, \
"no %s in <%s> within %s" % \ "no %s in <%s> within %s" % \
(attname, node.nodeName, self.manifestFile) (attname, node.nodeName, self._manifestFile)
return v return v

View File

@ -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 print >>sys.stderr, "repo: '%s' is not a repo command." % name
sys.exit(1) sys.exit(1)
cmd.repodir = self.repodir
self._PrintCommandHelp(cmd) self._PrintCommandHelp(cmd)
else: else:

View File

@ -214,7 +214,7 @@ uncommitted changes are present' % project.relpath
if not syncbuf.Finish(): if not syncbuf.Finish():
sys.exit(1) sys.exit(1)
self.manifest._Unload() self.GetManifest(reparse=True)
all = self.GetProjects(args, missing_ok=True) all = self.GetProjects(args, missing_ok=True)
missing = [] missing = []
for project in all: for project in all: