diff options
author | Richard Maw <richard.maw@codethink.co.uk> | 2014-08-21 12:58:46 +0000 |
---|---|---|
committer | Richard Maw <richard.maw@codethink.co.uk> | 2014-08-21 16:04:41 +0000 |
commit | 23e86c643a82731aba6561321b8bb5b168e80598 (patch) | |
tree | 4e50e39d30b775d3e911cfd375ec4bbcfa793eb4 /morphlib/cachedrepo.py | |
parent | 35f3a8779a316ed6a44ce5bb62bea9e2d7c67a16 (diff) | |
download | morph-23e86c643a82731aba6561321b8bb5b168e80598.tar.gz |
Prevent git-replace refs affecting git operations
We assumed that the sha1 of the tree of the commit of the ref we care
about was sufficient to cache, but `git replace` means that you need to
know the state of other branches too, since anything in refs/replace can
completely change what the tree you check-out is.
This behaviour can be disabled globally by setting
GIT_NO_REPLACE_OBJECTS, so we're going to do that.
If we need to integrate a project that uses git-replace to change the
contents of their git trees then we could support that by:
if any(refs/replace/*):
potentially_replacable_objects = [
`git rev-parse HEAD`,
`git rev-parse HEAD^{commit}`,
`git rev-parse HEAD^{tree}`]
potentially_replacable_objects.extend(
`git ls-tree -r HEAD | awk '{print $3}'`)
# NOTE: doesn't handle submodules, and you'd need to expand this
# set whenever you process a replacement
for object in refs/replace/*:
if basename(object) not in potentially_replacable_objects: continue
cache_key['replacements'][basename(object)] = `git rev-parse $object`
If we were to support this would need to traverse the tree anyway, doing
replacements, so we may as well use libgit to do the checkout anyway,
and list which replacements were used.
However, since the expected use-case of `git replace` is as a better way
to do history grafting, we're unlikely to need it, as it would only have
any effect if it replaced the commit we were using with a different one.
Rubber-stamped-by: Daniel Silverstone
Diffstat (limited to 'morphlib/cachedrepo.py')
-rw-r--r-- | morphlib/cachedrepo.py | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/morphlib/cachedrepo.py b/morphlib/cachedrepo.py index 88ceed48..2fc7cfa5 100644 --- a/morphlib/cachedrepo.py +++ b/morphlib/cachedrepo.py @@ -260,20 +260,21 @@ class CachedRepo(object): return self.app.runcmd(*args, **kwargs) def _rev_parse(self, ref): # pragma: no cover - return self._runcmd( - ['git', 'rev-parse', '--verify', '%s^{commit}' % ref])[0:40] + return morphlib.git.gitcmd(self._runcmd, 'rev-parse', '--verify', + '%s^{commit}' % ref)[0:40] def _show_tree_hash(self, absref): # pragma: no cover - return self._runcmd( - ['git', 'rev-parse', '--verify', '%s^{tree}' % absref]).strip() + return morphlib.git.gitcmd(self._runcmd, 'rev-parse', '--verify', + '%s^{tree}' % absref).strip() def _ls_tree(self, ref): # pragma: no cover - result = self._runcmd(['git', 'ls-tree', '--name-only', ref]) + result = morphlib.git.gitcmd(self._runcmd, 'ls-tree', + '--name-only', ref) return result.split('\n') def _cat_file(self, ref, filename): # pragma: no cover - return self._runcmd(['git', 'cat-file', 'blob', - '%s:%s' % (ref, filename)]) + return morphlib.git.gitcmd(self._runcmd, 'cat-file', 'blob', + '%s:%s' % (ref, filename)) def _clone_into(self, target_dir, ref): #pragma: no cover '''Actually perform the clone''' @@ -297,10 +298,11 @@ class CachedRepo(object): def _update(self): # pragma: no cover try: - self._runcmd(['git', 'remote', 'update', 'origin', '--prune']) + morphlib.git.gitcmd(self._runcmd, 'remote', 'update', + 'origin', '--prune') except cliapp.AppException, ae: - self._runcmd(['git', 'remote', 'prune', 'origin']) - self._runcmd(['git', 'remote', 'update', 'origin']) + morphlib.git.gitcmd(self._runcmd, 'remote', 'prune', 'origin') + morphlib.git.gitcmd(self._runcmd, 'remote', 'update', 'origin') def __str__(self): # pragma: no cover return self.url |