summaryrefslogtreecommitdiff
path: root/morphlib
diff options
context:
space:
mode:
Diffstat (limited to 'morphlib')
-rw-r--r--morphlib/gitdir.py13
-rw-r--r--morphlib/morphset.py14
-rw-r--r--morphlib/morphset_tests.py15
-rw-r--r--morphlib/plugins/branch_and_merge_plugin.py119
-rw-r--r--morphlib/sysbranchdir.py38
5 files changed, 52 insertions, 147 deletions
diff --git a/morphlib/gitdir.py b/morphlib/gitdir.py
index 3966a0f0..fea26c2e 100644
--- a/morphlib/gitdir.py
+++ b/morphlib/gitdir.py
@@ -495,8 +495,17 @@ class GitDirectory(object):
raise InvalidRefError(self, ref)
def disambiguate_ref(self, ref): # pragma: no cover
- out = self._runcmd(['git', 'rev-parse', '--symbolic-full-name', ref])
- return out.strip()
+ try:
+ out = self._runcmd(['git', 'rev-parse', '--symbolic-full-name',
+ ref])
+ return out.strip()
+ except cliapp.AppException: # ref not found
+ if ref.startswith('refs/heads/'):
+ return ref
+ elif ref.startswith('heads/'):
+ return 'refs/' + ref
+ else:
+ return 'refs/heads/' + ref
def resolve_ref_to_commit(self, ref):
return self._rev_parse('%s^{commit}' % ref)
diff --git a/morphlib/morphset.py b/morphlib/morphset.py
index 590ac51e..fa525973 100644
--- a/morphlib/morphset.py
+++ b/morphlib/morphset.py
@@ -243,17 +243,3 @@ class MorphologySet(object):
return True
self.traverse_specs(process_chunk_spec, wanted_chunk_spec)
-
- def unpetrify_all(self):
- '''If a spec is petrified, unpetrify it.
-
- '''
-
- def wanted_spec(m, kind, spec):
- return ('unpetrify-ref' in spec and
- morphlib.git.is_valid_sha1(spec.get('ref')))
- def process_spec(m, kind, spec):
- spec['ref'] = spec.pop('unpetrify-ref')
- return True
-
- self.traverse_specs(process_spec, wanted_spec)
diff --git a/morphlib/morphset_tests.py b/morphlib/morphset_tests.py
index 8679c64a..af1333d8 100644
--- a/morphlib/morphset_tests.py
+++ b/morphlib/morphset_tests.py
@@ -200,18 +200,3 @@ class MorphologySetTests(unittest.TestCase):
'unpetrify-ref': 'master',
}
])
-
- def test_unpetrify_all(self):
- self.morphs.add_morphology(self.system)
- self.morphs.add_morphology(self.stratum)
- self.morphs.petrify_chunks({('test:foo-chunk', 'master'): '0'*40})
- self.morphs.unpetrify_all()
- self.assertEqual(
- self.stratum['chunks'],
- [
- {
- 'repo': 'test:foo-chunk',
- 'ref': 'master',
- 'morph': 'foo-chunk',
- }
- ])
diff --git a/morphlib/plugins/branch_and_merge_plugin.py b/morphlib/plugins/branch_and_merge_plugin.py
index a66098b8..a258cd70 100644
--- a/morphlib/plugins/branch_and_merge_plugin.py
+++ b/morphlib/plugins/branch_and_merge_plugin.py
@@ -38,10 +38,6 @@ class BranchAndMergePlugin(cliapp.Plugin):
self.app.add_subcommand(
'edit', self.edit, arg_synopsis='SYSTEM STRATUM [CHUNK]')
self.app.add_subcommand(
- 'petrify', self.petrify, arg_synopsis='')
- self.app.add_subcommand(
- 'unpetrify', self.unpetrify, arg_synopsis='')
- self.app.add_subcommand(
'show-system-branch', self.show_system_branch, arg_synopsis='')
self.app.add_subcommand(
'show-branch-root', self.show_branch_root, arg_synopsis='')
@@ -313,9 +309,17 @@ class BranchAndMergePlugin(cliapp.Plugin):
cached_repo = lrc.get_updated_repo(chunk_url)
gd = sb.clone_cached_repo(cached_repo, chunk_ref)
- if chunk_ref != sb.system_branch_name:
- gd.branch(sb.system_branch_name, chunk_ref)
- gd.checkout(sb.system_branch_name)
+ system_branch_ref = gd.disambiguate_ref(sb.system_branch_name)
+ sha1 = gd.resolve_ref_to_commit(chunk_ref)
+
+ try:
+ old_sha1 = gd.resolve_ref_to_commit(system_branch_ref)
+ except morphlib.gitdir.InvalidRefError as e:
+ pass
+ else:
+ gd.delete_ref(system_branch_ref, old_sha1)
+ gd.branch(sb.system_branch_name, sha1)
+ gd.checkout(sb.system_branch_name)
gd.update_submodules(self.app)
gd.update_remotes()
if gd.has_fat():
@@ -377,16 +381,17 @@ class BranchAndMergePlugin(cliapp.Plugin):
This would, for example, write out something like:
- /src/ws/master/baserock:baserock/morphs
+ /src/ws/master/baserock/baserock/definitions
- when the master branch of the `baserock:baserock/morphs`
+ when the master branch of the `baserock/baserock/definitions`
repository is checked out.
'''
ws = morphlib.workspace.open('.')
sb = morphlib.sysbranchdir.open_from_within('.')
- self.app.output.write('%s\n' % sb.get_config('branch.root'))
+ repo_url = sb.get_config('branch.root')
+ self.app.output.write('%s\n' % sb.get_git_directory_name(repo_url))
def _remove_branch_dir_safe(self, workspace_root, system_branch_root):
# This function avoids throwing any exceptions, so it is safe to call
@@ -486,100 +491,6 @@ class BranchAndMergePlugin(cliapp.Plugin):
morphs.add_morphology(morph)
return morphs
- def petrify(self, args):
- '''Convert all chunk refs in a system branch to be fixed SHA1s.
-
- This modifies all git commit references in system and stratum
- morphologies, in the current system branch, to be fixed SHA
- commit identifiers, rather than symbolic branch or tag names.
- This is useful for making sure none of the components in a system
- branch change accidentally.
-
- Consider the following scenario:
-
- * The `master` system branch refers to `gcc` using the
- `baserock/morph` ref. This is appropriate, since the main line
- of development should use the latest curated code.
-
- * You create a system branch to prepare for a release, called
- `TROVE_ID/release/2.0`. The reference to `gcc` is still
- `baserock/morph`.
-
- * You test everything, and make a release. You deploy the release
- images onto devices, which get shipped to your customers.
-
- * A new version GCC is committed to the `baserock/morph` branch.
-
- * Your release branch suddenly uses a new compiler, which may
- or may not work for your particular system at that release.
-
- To avoid this, you need to _petrify_ all git references
- so that they do not change accidentally. If you've tested
- your release with the GCC release that is stored in commit
- `94c50665324a7aeb32f3096393ec54b2e63bfb28`, then you should
- continue to use that version of GCC, regardless of what might
- happen in the master system branch. If, and only if, you decide
- that a new compiler would be good for your release should you
- include it in your release branch. This way, only the things
- that you change intentionally change in your release branch.
-
- '''
-
- if args:
- raise cliapp.AppException('morph petrify takes no arguments')
-
- ws = morphlib.workspace.open('.')
- sb = morphlib.sysbranchdir.open_from_within('.')
- loader = morphlib.morphloader.MorphologyLoader()
- lrc, rrc = morphlib.util.new_repo_caches(self.app)
- update_repos = not self.app.settings['no-git-update']
-
- morphs = self._load_all_sysbranch_morphologies(sb, loader)
-
- #TODO: Stop using app.resolve_ref
- def resolve_refs(morphs):
- for repo, ref in morphs.list_refs():
- # You can't resolve null refs, so don't attempt to.
- if repo is None or ref is None:
- continue
- # TODO: Handle refs that are only in workspace in general
- if (repo == sb.root_repository_url
- and ref == sb.system_branch_name):
- continue
- commit_sha1, tree_sha1 = self.app.resolve_ref(
- lrc, rrc, repo, ref, update=update_repos)
- yield ((repo, ref), commit_sha1)
-
- morphs.repoint_refs(sb.root_repository_url,
- sb.system_branch_name)
-
- morphs.petrify_chunks(dict(resolve_refs(morphs)))
-
- # Write morphologies back out again.
- self._save_dirty_morphologies(loader, sb, morphs.morphologies)
-
- def unpetrify(self, args):
- '''Reverse the process of petrification.
-
- This undoes the changes `morph petrify` did.
-
- '''
-
- if args:
- raise cliapp.AppException('morph petrify takes no arguments')
-
- ws = morphlib.workspace.open('.')
- sb = morphlib.sysbranchdir.open_from_within('.')
- loader = morphlib.morphloader.MorphologyLoader()
-
- morphs = self._load_all_sysbranch_morphologies(sb, loader)
-
- # Restore the ref for each stratum and chunk
- morphs.unpetrify_all()
-
- # Write morphologies back out again.
- self._save_dirty_morphologies(loader, sb, morphs.morphologies)
-
def status(self, args):
'''Show information about the current system branch or workspace
diff --git a/morphlib/sysbranchdir.py b/morphlib/sysbranchdir.py
index b8953c2f..19fba695 100644
--- a/morphlib/sysbranchdir.py
+++ b/morphlib/sysbranchdir.py
@@ -68,19 +68,13 @@ class SystemBranchDirectory(object):
value = cliapp.runcmd(['git', 'config', '-f', self._config_path, key])
return value.strip()
- def get_git_directory_name(self, repo_url):
- '''Return directory pathname for a given git repository.
-
- 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.
-
- '''
+ def _find_git_directory(self, repo_url):
+ for gd in self.list_git_directories():
+ if gd.get_config('morph.repository') == 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)
@@ -107,6 +101,26 @@ class SystemBranchDirectory(object):
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.