diff options
-rw-r--r-- | git/refs/remote.py | 4 | ||||
-rw-r--r-- | git/refs/symbolic.py | 44 | ||||
-rw-r--r-- | git/remote.py | 2 | ||||
-rw-r--r-- | git/repo/base.py | 22 | ||||
-rw-r--r-- | git/test/test_repo.py | 2 |
5 files changed, 45 insertions, 29 deletions
diff --git a/git/refs/remote.py b/git/refs/remote.py index ef69b5db..0164e110 100644 --- a/git/refs/remote.py +++ b/git/refs/remote.py @@ -37,6 +37,10 @@ class RemoteReference(Head): # and delete remainders manually for ref in refs: try: + os.remove(osp.join(repo.common_dir, ref.path)) + except OSError: + pass + try: os.remove(osp.join(repo.git_dir, ref.path)) except OSError: pass diff --git a/git/refs/symbolic.py b/git/refs/symbolic.py index 90ecb62c..bef6ba3c 100644 --- a/git/refs/symbolic.py +++ b/git/refs/symbolic.py @@ -26,6 +26,14 @@ from .log import RefLog __all__ = ["SymbolicReference"] +def _git_dir(repo, path): + """ Find the git dir that's appropriate for the path""" + name = "%s" % (path,) + if name in ['HEAD', 'ORIG_HEAD', 'FETCH_HEAD', 'index', 'logs']: + return repo.git_dir + return repo.common_dir + + class SymbolicReference(object): """Represents a special case of a reference such that this reference is symbolic. @@ -71,16 +79,11 @@ class SymbolicReference(object): @property def abspath(self): - return join_path_native(self.repo.git_dir, self.path) + return join_path_native(_git_dir(self.repo, self.path), self.path) @classmethod def _get_packed_refs_path(cls, repo): - try: - commondir = open(osp.join(repo.git_dir, 'commondir'), 'rt').readlines()[0].strip() - except (OSError, IOError): - commondir = '.' - repodir = osp.join(repo.git_dir, commondir) - return osp.join(repodir, 'packed-refs') + return osp.join(repo.common_dir, 'packed-refs') @classmethod def _iter_packed_refs(cls, repo): @@ -127,11 +130,12 @@ class SymbolicReference(object): # END recursive dereferencing @classmethod - def _get_ref_info_helper(cls, repo, repodir, ref_path): + def _get_ref_info_helper(cls, repo, ref_path): """Return: (str(sha), str(target_ref_path)) if available, the sha the file at rela_path points to, or None. target_ref_path is the reference we point to, or None""" tokens = None + repodir = _git_dir(repo, ref_path) try: with open(osp.join(repodir, ref_path), 'rt') as fp: value = fp.read().rstrip() @@ -169,16 +173,7 @@ class SymbolicReference(object): """Return: (str(sha), str(target_ref_path)) if available, the sha the file at rela_path points to, or None. target_ref_path is the reference we point to, or None""" - try: - return cls._get_ref_info_helper(repo, repo.git_dir, ref_path) - except ValueError: - try: - commondir = open(osp.join(repo.git_dir, 'commondir'), 'rt').readlines()[0].strip() - except (OSError, IOError): - commondir = '.' - - repodir = osp.join(repo.git_dir, commondir) - return cls._get_ref_info_helper(repo, repodir, ref_path) + return cls._get_ref_info_helper(repo, ref_path) def _get_object(self): """ @@ -433,7 +428,7 @@ class SymbolicReference(object): or just "myreference", hence 'refs/' is implied. Alternatively the symbolic reference to be deleted""" full_ref_path = cls.to_full_path(path) - abs_path = osp.join(repo.git_dir, full_ref_path) + abs_path = osp.join(repo.common_dir, full_ref_path) if osp.exists(abs_path): os.remove(abs_path) else: @@ -484,8 +479,9 @@ class SymbolicReference(object): a proper symbolic reference. Otherwise it will be resolved to the corresponding object and a detached symbolic reference will be created instead""" + git_dir = _git_dir(repo, path) full_ref_path = cls.to_full_path(path) - abs_ref_path = osp.join(repo.git_dir, full_ref_path) + abs_ref_path = osp.join(git_dir, full_ref_path) # figure out target data target = reference @@ -559,8 +555,8 @@ class SymbolicReference(object): if self.path == new_path: return self - new_abs_path = osp.join(self.repo.git_dir, new_path) - cur_abs_path = osp.join(self.repo.git_dir, self.path) + new_abs_path = osp.join(_git_dir(self.repo, new_path), new_path) + cur_abs_path = osp.join(_git_dir(self.repo, self.path), self.path) if osp.isfile(new_abs_path): if not force: # if they point to the same file, its not an error @@ -594,7 +590,7 @@ class SymbolicReference(object): # walk loose refs # Currently we do not follow links - for root, dirs, files in os.walk(join_path_native(repo.git_dir, common_path)): + for root, dirs, files in os.walk(join_path_native(repo.common_dir, common_path)): if 'refs' not in root.split(os.sep): # skip non-refs subfolders refs_id = [d for d in dirs if d == 'refs'] if refs_id: @@ -605,7 +601,7 @@ class SymbolicReference(object): if f == 'packed-refs': continue abs_path = to_native_path_linux(join_path(root, f)) - rela_paths.add(abs_path.replace(to_native_path_linux(repo.git_dir) + '/', "")) + rela_paths.add(abs_path.replace(to_native_path_linux(repo.common_dir) + '/', "")) # END for each file in root directory # END for each directory to walk diff --git a/git/remote.py b/git/remote.py index fd76e592..29c7ed92 100644 --- a/git/remote.py +++ b/git/remote.py @@ -652,7 +652,7 @@ class Remote(LazyMixin, Iterable): continue # read head information - with open(osp.join(self.repo.git_dir, 'FETCH_HEAD'), 'rb') as fp: + with open(osp.join(self.repo.common_dir, 'FETCH_HEAD'), 'rb') as fp: fetch_head_info = [l.decode(defenc) for l in fp.readlines()] l_fil = len(fetch_info_lines) diff --git a/git/repo/base.py b/git/repo/base.py index 28bb2a5d..d607deee 100644 --- a/git/repo/base.py +++ b/git/repo/base.py @@ -74,6 +74,7 @@ class Repo(object): working_dir = None _working_tree_dir = None git_dir = None + _common_dir = None # precompiled regex re_whitespace = re.compile(r'\s+') @@ -169,17 +170,23 @@ class Repo(object): # lets not assume the option exists, although it should pass + try: + common_dir = open(osp.join(self.git_dir, 'commondir'), 'rt').readlines()[0].strip() + self._common_dir = osp.join(self.git_dir, common_dir) + except (OSError, IOError): + self._common_dir = None + # adjust the wd in case we are actually bare - we didn't know that # in the first place if self._bare: self._working_tree_dir = None # END working dir handling - self.working_dir = self._working_tree_dir or self.git_dir + self.working_dir = self._working_tree_dir or self.common_dir self.git = self.GitCommandWrapperType(self.working_dir) # special handling, in special times - args = [osp.join(self.git_dir, 'objects')] + args = [osp.join(self.common_dir, 'objects')] if issubclass(odbt, GitCmdObjectDB): args.append(self.git) self.odb = odbt(*args) @@ -237,6 +244,13 @@ class Repo(object): return self._working_tree_dir @property + def common_dir(self): + """:return: The git dir that holds everything except possibly HEAD, + FETCH_HEAD, ORIG_HEAD, COMMIT_EDITMSG, index, and logs/ . + """ + return self._common_dir or self.git_dir + + @property def bare(self): """:return: True if the repository is bare""" return self._bare @@ -574,7 +588,7 @@ class Repo(object): :note: The method does not check for the existence of the paths in alts as the caller is responsible.""" - alternates_path = osp.join(self.git_dir, 'objects', 'info', 'alternates') + alternates_path = osp.join(self.common_dir, 'objects', 'info', 'alternates') if not alts: if osp.isfile(alternates_path): os.remove(alternates_path) @@ -932,7 +946,7 @@ class Repo(object): * All remaining keyword arguments are given to the git-clone command :return: ``git.Repo`` (the newly cloned repo)""" - return self._clone(self.git, self.git_dir, path, type(self.odb), progress, **kwargs) + return self._clone(self.git, self.common_dir, path, type(self.odb), progress, **kwargs) @classmethod def clone_from(cls, url, to_path, progress=None, env=None, **kwargs): diff --git a/git/test/test_repo.py b/git/test/test_repo.py index a6be4e66..312e67f9 100644 --- a/git/test/test_repo.py +++ b/git/test/test_repo.py @@ -935,6 +935,8 @@ class TestRepo(TestBase): commit = repo.head.commit self.assertIsInstance(commit, Object) + self.assertIsInstance(repo.heads['aaaaaaaa'], Head) + @with_rw_directory def test_git_work_tree_env(self, rw_dir): """Check that we yield to GIT_WORK_TREE""" |