diff options
Diffstat (limited to 'morphlib/sysbranchdir.py')
-rw-r--r-- | morphlib/sysbranchdir.py | 275 |
1 files changed, 0 insertions, 275 deletions
diff --git a/morphlib/sysbranchdir.py b/morphlib/sysbranchdir.py deleted file mode 100644 index d466f065..00000000 --- a/morphlib/sysbranchdir.py +++ /dev/null @@ -1,275 +0,0 @@ -# Copyright (C) 2013-2015 Codethink Limited -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see <http://www.gnu.org/licenses/>. -# -# =*= License: GPL-2 =*= - - -import cliapp -import os -import urlparse -import uuid - -import morphlib - - -class SystemBranchDirectoryAlreadyExists(morphlib.Error): - - def __init__(self, root_directory): - self.msg = ( - "%s: File exists" % - root_directory) - - -class NotInSystemBranch(morphlib.Error): - - def __init__(self, dirname): - self.msg = ( - "Can't find the system branch directory.\n" - "Morph must be built and deployed within " - "the system branch checkout.") - - -class SystemBranchDirectory(object): - - '''A directory containing a checked out system branch.''' - - def __init__(self, - root_directory, root_repository_url, system_branch_name): - self.system_branch_name = system_branch_name - - # The 'root repo' is the definitions repo. This attribute is named this - # way for historical reasons. - self.root_repository_url = root_repository_url - assert root_repository_url is not None - - # The 'root directory' is the parent directory of all checked-out - # repos. For example, the root directory of branch 'sam/test' in - # workspace '/src/ws' would be '/src/ws/sam/test' (at the time it was - # created by `morph branch` or `morph checkout`, anyway). - self.root_directory = os.path.abspath(root_directory) - - self.config = morphlib.gitdir.Config(config_file=self._config_path) - - # In order to handle newly-created system branch directories (and for - # the unit tests) we don't raise an error here if the definitions repo - # isn't cloned yet. Some methods won't work if it doesn't exist though. - definitions_repo_dir = self.get_git_directory_name(root_repository_url) - self.definitions_repo = morphlib.definitions_repo.DefinitionsRepo( - definitions_repo_dir, system_branch=self, allow_missing=True) - - @property - def _magic_path(self): - return os.path.join(self.root_directory, '.morph-system-branch') - - @property - def _config_path(self): - return os.path.join(self._magic_path, 'config') - - def set_config(self, key, value): - '''Set a configuration key/value pair.''' - self.config[key] = value - - def get_config(self, key): - '''Get a configuration value for a given key.''' - return self.config[key] - - def _find_git_directory(self, repo_url): - for gd in self.list_git_directories(): - try: - gd_repo_url = gd.get_config('morph.repository') - except cliapp.AppException: # pragma: no cover - continue - if gd_repo_url == repo_url: - return gd.dirname - return None - - def _fabricate_git_directory_name(self, repo_url): - # Parse the URL. If the path component is absolute, we assume - # it's a real URL; otherwise, an aliased URL. - parts = urlparse.urlparse(repo_url) - - if os.path.isabs(parts.path): - # Remove .git suffix, if any. - path = parts.path - if path.endswith('.git'): - path = path[:-len('.git')] - - # Add the domain name etc (netloc). Ignore any other parts. - # Note that we _know_ the path starts with a slash, so we avoid - # adding one here. - relative = '%s%s' % (parts.netloc, path) - else: - relative = repo_url - - # Replace colons with slashes. - relative = '/'.join(relative.split(':')) - - # Remove anyleading slashes, or os.path.join below will only - # use the relative part (since it's absolute, not relative). - relative = relative.lstrip('/') - - return os.path.join(self.root_directory, relative) - - def get_git_directory_name(self, repo_url): - '''Return directory pathname for a given git repository. - - If the repository has already been cloned, then it returns the - path to that, if not it will fabricate a path based on the url. - - If the URL is a real one (not aliased), the schema and leading // - are removed from it, as is a .git suffix. - - Any colons in the URL path or network location are replaced - with slashes, so that directory paths do not contain colons. - This avoids problems with PYTHONPATH, PATH, and other things - that use colon as a separator. - - ''' - found_repo = self._find_git_directory(repo_url) - - if not found_repo: - return self._fabricate_git_directory_name(repo_url) - return found_repo - - def get_filename(self, repo_url, relative): - '''Return full pathname to a file in a checked out repository. - - This is a convenience function. - - ''' - - return os.path.join(self.get_git_directory_name(repo_url), relative) - - def clone_cached_repo(self, cached_repo, checkout_ref): - '''Clone a cached git repository into the system branch directory. - - The cloned repository will NOT have the system branch's git branch - checked out: instead, checkout_ref is checked out (this is for - backwards compatibility with older implementation of "morph - branch"; it may change later). The system branch's git branch - is NOT created: the caller will need to do that. Submodules are - NOT checked out. - - The "origin" remote will be set to follow the cached repository's - upstream. Remotes are not updated. - - ''' - - # Do the clone. - dirname = self.get_git_directory_name(cached_repo.original_name) - gd = morphlib.gitdir.clone_from_cached_repo( - cached_repo, dirname, checkout_ref) - - # Remember the repo name we cloned from in order to be able - # to identify the repo again later using the same name, even - # if the user happens to rename the directory. - gd.set_config('morph.repository', cached_repo.original_name) - - # Create a UUID for the clone. We will use this for naming - # temporary refs, e.g. for building. - gd.set_config('morph.uuid', uuid.uuid4().hex) - - # Configure the "origin" remote to use the upstream git repository, - # and not the locally cached copy. - resolver = morphlib.repoaliasresolver.RepoAliasResolver( - cached_repo.app.settings['repo-alias']) - remote = gd.get_remote('origin') - remote.set_fetch_url(resolver.pull_url(cached_repo.url)) - gd.set_config( - 'url.%s.pushInsteadOf' % - resolver.push_url(cached_repo.original_name), - resolver.pull_url(cached_repo.url)) - - return gd - - def list_git_directories(self): - '''List all git directories in a system branch directory. - - The list will contain zero or more GitDirectory objects. - - ''' - - return (morphlib.gitdir.GitDirectory(dirname) - for dirname in - morphlib.util.find_leaves(self.root_directory, '.git')) - - def get_morphology_loader(self): # pragma: no cover - return self.definitions_repo.get_morphology_loader() - - def load_all_morphologies(self): # pragma: no cover - return self.definitions_repo.load_all_morphologies() - - -def create(root_directory, root_repository_url, system_branch_name): - '''Create a new system branch directory on disk. - - Return a SystemBranchDirectory object that represents the directory. - - The directory MUST NOT exist already. If it does, - SystemBranchDirectoryAlreadyExists is raised. - - Note that this does NOT check out the root repository, or do any - other git cloning. - - ''' - - if os.path.exists(root_directory): - raise SystemBranchDirectoryAlreadyExists(root_directory) - - magic_dir = os.path.join(root_directory, '.morph-system-branch') - os.makedirs(root_directory) - os.mkdir(magic_dir) - - sb = SystemBranchDirectory( - root_directory, root_repository_url, system_branch_name) - sb.set_config('branch.name', system_branch_name) - sb.set_config('branch.root', root_repository_url) - sb.set_config('branch.uuid', uuid.uuid4().hex) - - return sb - - -def open(root_directory): - '''Open an existing system branch directory.''' - - config_file_path = os.path.join( - root_directory, '.morph-system-branch', 'config') - config = morphlib.gitdir.Config(config_file=config_file_path) - - root_repository_url = config['branch.root'] - system_branch_name = config['branch.name'] - - return SystemBranchDirectory( - root_directory, root_repository_url, system_branch_name) - - -def open_from_within(dirname): - '''Open a system branch directory, given any directory. - - The directory can be within the system branch root directory, - or it can be a parent, in some cases. If each parent on the - path from dirname to the system branch root directory has no - siblings, this function will find it. - - ''' - - root_directory = morphlib.util.find_root( - dirname, '.morph-system-branch') - if root_directory is None: - root_directory = morphlib.util.find_leaf( - dirname, '.morph-system-branch') - if root_directory is None: - raise NotInSystemBranch(dirname) - return morphlib.sysbranchdir.open(root_directory) - |