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 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.
"""

View File

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

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

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
sys.exit(1)
cmd.repodir = self.repodir
self._PrintCommandHelp(cmd)
else:

View File

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