From c0659faa962500b2b1785fc13ffc291011fc616a Mon Sep 17 00:00:00 2001 From: Tiago Gomes Date: Mon, 23 Nov 2015 17:05:02 +0000 Subject: Remove SystemBranchDirectory and Workspace classes Change-Id: I7766d3eac28cf34aedb7f3edbc0ff3dda26ac79a --- morphlib/sysbranchdir.py | 275 ----------------------------------------- morphlib/sysbranchdir_tests.py | 214 -------------------------------- morphlib/workspace.py | 145 ---------------------- morphlib/workspace_tests.py | 110 ----------------- 4 files changed, 744 deletions(-) delete mode 100644 morphlib/sysbranchdir.py delete mode 100644 morphlib/sysbranchdir_tests.py delete mode 100644 morphlib/workspace.py delete mode 100644 morphlib/workspace_tests.py (limited to 'morphlib') 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 . -# -# =*= 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) - diff --git a/morphlib/sysbranchdir_tests.py b/morphlib/sysbranchdir_tests.py deleted file mode 100644 index 6dd6fc6d..00000000 --- a/morphlib/sysbranchdir_tests.py +++ /dev/null @@ -1,214 +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 . -# -# =*= License: GPL-2 =*= - - -import cliapp -import os -import shutil -import tempfile -import unittest - -import morphlib - - -class SystemBranchDirectoryTests(unittest.TestCase): - - def setUp(self): - self.tempdir = tempfile.mkdtemp() - self.root_directory = os.path.join(self.tempdir, 'rootdir') - self.root_repository_url = 'test:morphs' - self.system_branch_name = 'foo/bar' - - def tearDown(self): - shutil.rmtree(self.tempdir) - - def create_fake_cached_repo(self): - - class FakeCachedRepo(object): - - def __init__(self, url, path): - self.app = self - self.settings = { - 'repo-alias': [], - } - self.original_name = url - self.url = 'git://blahlbah/blah/blahblahblah.git' - self.path = path - - os.mkdir(self.path) - morphlib.git.gitcmd(cliapp.runcmd, 'init', self.path) - with open(os.path.join(self.path, 'filename'), 'w') as f: - f.write('this is a file\n') - morphlib.git.gitcmd(cliapp.runcmd, 'add', 'filename', - cwd=self.path) - morphlib.git.gitcmd(cliapp.runcmd, 'commit', '-m', 'initial', - cwd=self.path) - - def clone_checkout(self, ref, target_dir): - morphlib.git.gitcmd(cliapp.runcmd, 'clone', '-b', ref, - self.path, target_dir) - - subdir = tempfile.mkdtemp(dir=self.tempdir) - path = os.path.join(subdir, 'foo') - return FakeCachedRepo(self.root_repository_url, path) - - def test_creates_system_branch_directory(self): - sb = morphlib.sysbranchdir.create( - self.root_directory, - self.root_repository_url, - self.system_branch_name) - self.assertEqual(sb.root_directory, self.root_directory) - self.assertEqual(sb.root_repository_url, self.root_repository_url) - self.assertEqual(sb.system_branch_name, self.system_branch_name) - - magic_dir = os.path.join(self.root_directory, '.morph-system-branch') - self.assertTrue(os.path.isdir(self.root_directory)) - self.assertTrue(os.path.isdir(magic_dir)) - self.assertTrue(os.path.isfile(os.path.join(magic_dir, 'config'))) - self.assertEqual( - sb.get_config('branch.root'), self.root_repository_url) - self.assertEqual( - sb.get_config('branch.name'), self.system_branch_name) - self.assertTrue(sb.get_config('branch.uuid')) - - def test_opens_system_branch_directory(self): - morphlib.sysbranchdir.create( - self.root_directory, - self.root_repository_url, - self.system_branch_name) - sb = morphlib.sysbranchdir.open(self.root_directory) - self.assertEqual(sb.root_directory, self.root_directory) - self.assertEqual(sb.root_repository_url, self.root_repository_url) - self.assertEqual(sb.system_branch_name, self.system_branch_name) - - def test_opens_system_branch_directory_from_a_subdirectory(self): - morphlib.sysbranchdir.create( - self.root_directory, - self.root_repository_url, - self.system_branch_name) - subdir = os.path.join(self.root_directory, 'a', 'b', 'c') - os.makedirs(subdir) - sb = morphlib.sysbranchdir.open_from_within(subdir) - self.assertEqual(sb.root_directory, self.root_directory) - self.assertEqual(sb.root_repository_url, self.root_repository_url) - self.assertEqual(sb.system_branch_name, self.system_branch_name) - - def test_fails_opening_system_branch_directory_when_none_exists(self): - self.assertRaises( - morphlib.sysbranchdir.NotInSystemBranch, - morphlib.sysbranchdir.open_from_within, - self.tempdir) - - def test_opens_system_branch_directory_when_it_is_the_only_child(self): - deep_root = os.path.join(self.tempdir, 'a', 'b', 'c') - morphlib.sysbranchdir.create( - deep_root, - self.root_repository_url, - self.system_branch_name) - sb = morphlib.sysbranchdir.open(deep_root) - self.assertEqual(sb.root_directory, deep_root) - self.assertEqual(sb.root_repository_url, self.root_repository_url) - self.assertEqual(sb.system_branch_name, self.system_branch_name) - - def test_fails_to_create_if_directory_already_exists(self): - os.mkdir(self.root_directory) - self.assertRaises( - morphlib.sysbranchdir.SystemBranchDirectoryAlreadyExists, - morphlib.sysbranchdir.create, - self.root_directory, - self.root_repository_url, - self.system_branch_name) - - def test_sets_and_gets_configuration_values(self): - sb = morphlib.sysbranchdir.create( - self.root_directory, - self.root_repository_url, - self.system_branch_name) - sb.set_config('foo.key', 'foovalue') - - sb2 = morphlib.sysbranchdir.open(self.root_directory) - self.assertEqual(sb2.get_config('foo.key'), 'foovalue') - - def test_reports_correct_name_for_git_directory_from_aliases_url(self): - sb = morphlib.sysbranchdir.create( - self.root_directory, - self.root_repository_url, - self.system_branch_name) - self.assertEqual( - sb.get_git_directory_name('baserock:baserock/morph'), - os.path.join(self.root_directory, 'baserock/baserock/morph')) - - def test_reports_correct_name_for_git_directory_from_real_url(self): - stripped = 'git.baserock.org/baserock/baserock/morph' - url = 'git://%s.git' % stripped - sb = morphlib.sysbranchdir.create( - self.root_directory, - url, - self.system_branch_name) - self.assertEqual( - sb.get_git_directory_name(url), - os.path.join(self.root_directory, stripped)) - - def test_reports_correct_path_for_file_in_repository(self): - sb = morphlib.sysbranchdir.create( - self.root_directory, - self.root_repository_url, - self.system_branch_name) - self.assertEqual( - sb.get_filename('test:chunk', 'foo'), - os.path.join(self.root_directory, 'test/chunk/foo')) - - def test_reports_correct_name_for_git_directory_from_file_url(self): - stripped = 'foobar/morphs' - url = 'file:///%s.git' % stripped - sb = morphlib.sysbranchdir.create( - self.root_directory, - url, - self.system_branch_name) - self.assertEqual( - sb.get_git_directory_name(url), - os.path.join(self.root_directory, stripped)) - - def test_clones_git_repository(self): - - sb = morphlib.sysbranchdir.create( - self.root_directory, - self.root_repository_url, - self.system_branch_name) - - cached_repo = self.create_fake_cached_repo() - gd = sb.clone_cached_repo(cached_repo, 'master') - - self.assertEqual( - gd.dirname, - sb.get_git_directory_name(cached_repo.original_name)) - - def test_lists_git_directories(self): - - sb = morphlib.sysbranchdir.create( - self.root_directory, - self.root_repository_url, - self.system_branch_name) - - cached_repo = self.create_fake_cached_repo() - sb.clone_cached_repo(cached_repo, 'master') - - gd_list = list(sb.list_git_directories()) - self.assertEqual(len(gd_list), 1) - self.assertEqual( - gd_list[0].dirname, - sb.get_git_directory_name(cached_repo.original_name)) - diff --git a/morphlib/workspace.py b/morphlib/workspace.py deleted file mode 100644 index 26986655..00000000 --- a/morphlib/workspace.py +++ /dev/null @@ -1,145 +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 . -# -# =*= License: GPL-2 =*= - - -'''A module to create, query, and manipulate Morph workspaces.''' - - -import os - -import morphlib - - -class WorkspaceDirExists(morphlib.Error): - - def __init__(self, dirname): - self.msg = ( - 'can only initialize empty directory as a workspace: %s' % - dirname) - - -class NotInWorkspace(morphlib.Error): - - def __init__(self, dirname): - self.msg = ( - "Can't find the workspace directory.\n" - "Morph must be built and deployed within the " - "system branch checkout within the workspace directory.") - - -class Workspace(object): - - '''A Morph workspace. - - This class should be instantiated with the open() or create() - functions in this module. - - ''' - - def __init__(self, root_directory): - self.root = root_directory - - def get_default_system_branch_directory_name(self, system_branch_name): - '''Determine directory where a system branch would be checked out. - - Return the fully qualified pathname to the directory where - a system branch would be checked out. The directory may or may - not exist already. - - If the system branch is checked out, but into a directory of - a different name (which is allowed), that is ignored: this method - only computed the default name. - - ''' - - return os.path.join(self.root, system_branch_name) - - def create_system_branch_directory(self, - root_repository_url, system_branch_name): - '''Create a directory for a system branch. - - Return a SystemBranchDirectory object that represents the - directory. The directory must not already exist. The directory - gets created and initialised (the .morph-system-branch/config - file gets created and populated). The root repository of the - system branch does NOT get checked out, the caller needs to - do that. - - ''' - - dirname = self.get_default_system_branch_directory_name( - system_branch_name) - sb = morphlib.sysbranchdir.create( - dirname, root_repository_url, system_branch_name) - return sb - - def list_system_branches(self): - return (morphlib.sysbranchdir.open(dirname) - for dirname in - morphlib.util.find_leaves(self.root, '.morph-system-branch')) - - -def open(dirname): - '''Open an existing workspace. - - The given directory name may be to a subdirectory of the - workspace. This makes it easy to instantiate the Workspace - class even when the user invokes Morph in a subdirectory. - The workspace MUST exist already, or NotInWorkspace is - raised. - - Return a Workspace instance. - - ''' - - root = _find_root(dirname) - if root is None: - raise NotInWorkspace(dirname) - return Workspace(root) - - -def create(dirname): - '''Create a new workspace. - - The given directory must not be inside an existing workspace. - The workspace directory is created, unless it already exists. If it - does exist, it must be empty. Otherwise WorkspaceDirExists is raised. - - ''' - - root = _find_root(dirname) - if root is not None: - raise WorkspaceDirExists(root) - - if os.path.exists(dirname): - if os.listdir(dirname): - raise WorkspaceDirExists(dirname) - else: - os.mkdir(dirname) - os.mkdir(os.path.join(dirname, '.morph')) - return Workspace(dirname) - - -def _find_root(dirname): - '''Find the workspace root directory at or above a given directory.''' - - dirname = os.path.normpath(os.path.abspath(dirname)) - while not os.path.isdir(os.path.join(dirname, '.morph')): - if dirname == '/': - return None - dirname = os.path.dirname(dirname) - return dirname - diff --git a/morphlib/workspace_tests.py b/morphlib/workspace_tests.py deleted file mode 100644 index 23d7ad5e..00000000 --- a/morphlib/workspace_tests.py +++ /dev/null @@ -1,110 +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 . -# -# =*= License: GPL-2 =*= - - -import os -import shutil -import tempfile -import unittest - -import morphlib - - -class WorkspaceTests(unittest.TestCase): - - def setUp(self): - self.tempdir = tempfile.mkdtemp() - self.workspace_dir = os.path.join(self.tempdir, 'workspace') - - def tearDown(self): - shutil.rmtree(self.tempdir) - - def assertIsWorkspace(self, dirname): - self.assertTrue(os.path.isdir(dirname)) - self.assertTrue(os.path.isdir(os.path.join(dirname, '.morph'))) - - def create_it(self): - morphlib.workspace.create(self.workspace_dir) - - def test_creates_workspace(self): - ws = morphlib.workspace.create(self.workspace_dir) - self.assertIsWorkspace(self.workspace_dir) - self.assertEqual(ws.root, self.workspace_dir) - - def test_create_initialises_existing_but_empty_directory(self): - os.mkdir(self.workspace_dir) - ws = morphlib.workspace.create(self.workspace_dir) - self.assertIsWorkspace(self.workspace_dir) - self.assertEqual(ws.root, self.workspace_dir) - - def test_fails_to_create_workspace_when_dir_exists_and_is_not_empty(self): - os.mkdir(self.workspace_dir) - os.mkdir(os.path.join(self.workspace_dir, 'somedir')) - self.assertRaises( - morphlib.workspace.WorkspaceDirExists, - morphlib.workspace.create, self.workspace_dir) - - def test_fails_to_recreate_workspace(self): - # Create it once. - morphlib.workspace.create(self.workspace_dir) - # Creating it again must fail. - self.assertRaises( - morphlib.workspace.WorkspaceDirExists, - morphlib.workspace.create, self.workspace_dir) - - def test_opens_workspace_when_given_its_root(self): - self.create_it() - ws = morphlib.workspace.open(self.workspace_dir) - self.assertEqual(ws.root, self.workspace_dir) - - def test_opens_workspace_when_given_subdirectory(self): - self.create_it() - subdir = os.path.join(self.workspace_dir, 'subdir') - os.mkdir(subdir) - ws = morphlib.workspace.open(subdir) - self.assertEqual(ws.root, self.workspace_dir) - - def test_fails_to_open_workspace_when_no_workspace_anywhere(self): - self.assertRaises( - morphlib.workspace.NotInWorkspace, - morphlib.workspace.open, self.tempdir) - - def test_invents_appropriate_name_for_system_branch_directory(self): - self.create_it() - ws = morphlib.workspace.open(self.workspace_dir) - branch = 'foo/bar' - self.assertEqual( - ws.get_default_system_branch_directory_name(branch), - os.path.join(self.workspace_dir, branch)) - - def test_creates_system_branch_directory(self): - self.create_it() - ws = morphlib.workspace.open(self.workspace_dir) - url = 'test:morphs' - branch = 'my/new/thing' - sb = ws.create_system_branch_directory(url, branch) - self.assertEqual(type(sb), morphlib.sysbranchdir.SystemBranchDirectory) - - def test_lists_created_system_branches(self): - self.create_it() - ws = morphlib.workspace.open(self.workspace_dir) - - branches = ["branch/1", "branch/2"] - for branch in branches: - ws.create_system_branch_directory('test:morphs', branch) - self.assertEqual(sorted(sb.system_branch_name - for sb in ws.list_system_branches()), - branches) -- cgit v1.2.1