diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/git/cmd.py | 89 | ||||
-rw-r--r-- | lib/git/repo.py | 19 |
2 files changed, 69 insertions, 39 deletions
diff --git a/lib/git/cmd.py b/lib/git/cmd.py index 8a3de181..bd8da4ca 100644 --- a/lib/git/cmd.py +++ b/lib/git/cmd.py @@ -12,43 +12,68 @@ class Git(MethodMissingMixin): """ The Git class manages communication with the Git binary """ - def __init__(self, git_dir=None): + def __init__(self, git_dir=None, bare_repo=False): super(Git, self).__init__() if git_dir: - self.find_git_dir(git_dir) + self._location = os.path.abspath(git_dir) else: - self.find_git_dir(os.getcwd()) - - def find_git_dir(self, path): - """Find the best value for self.git_dir. - For bare repositories, this is the path to the bare repository. - For repositories with work trees, this is the work tree path. - - When barerepo.git is passed in, self.git_dir = barerepo.git - When worktree/.git is passed in, self.git_dir = worktree - When worktree is passed in, self.git_dir = worktree - """ - - path = os.path.abspath(path) - self.git_dir = path - - cdup = self.execute(["git", "rev-parse", "--show-cdup"]) - if cdup: - path = os.path.abspath(os.path.join(self.git_dir, cdup)) - else: - is_bare_repository =\ - self.rev_parse(is_bare_repository=True) == "true" - is_inside_git_dir =\ - self.rev_parse(is_inside_git_dir=True) == "true" - - if not is_bare_repository and is_inside_git_dir: - path = os.path.dirname(self.git_dir) - - self.git_dir = path + self._location = os.getcwd() + self._is_bare_repo = bare_repo + self.refresh() + + def refresh(self): + self._git_dir = None + self._is_in_repo = not not self.get_git_dir() + self._work_tree = None + self._cwd = self._git_dir + if self._git_dir and not self._is_bare_repo: + self._cwd = self.get_work_tree() + + def _is_git_dir(self, d): + """ This is taken from the git setup.c:is_git_directory + function.""" + + if os.path.isdir(d) and \ + os.path.isdir(os.path.join(d, 'objects')) and \ + os.path.isdir(os.path.join(d, 'refs')): + headref = os.path.join(d, 'HEAD') + return os.path.isfile(headref) or \ + (os.path.islink(headref) and + os.readlink(headref).startswith('refs')) + return False + + def get_git_dir(self): + if not self._git_dir: + self._git_dir = os.getenv('GIT_DIR') + if self._git_dir and self._is_git_dir(self._git_dir): + return self._git_dir + curpath = self._location + while curpath: + if self._is_git_dir(curpath): + self._git_dir = curpath + break + gitpath = os.path.join(curpath, '.git') + if self._is_git_dir(gitpath): + self._git_dir = gitpath + break + curpath, dummy = os.path.split(curpath) + if not dummy: + break + return self._git_dir + + def get_work_tree(self): + if self._is_bare_repo: + return None + if not self._work_tree: + self._work_tree = os.getenv('GIT_WORK_TREE') + if not self._work_tree or not os.path.isdir(self._work_tree): + self._work_tree = os.path.abspath( + os.path.join(self._git_dir, '..')) + return self._work_tree @property def get_dir(self): - return self.git_dir + return self._git_dir def execute(self, command, istream=None, @@ -102,7 +127,7 @@ class Git(MethodMissingMixin): if with_keep_cwd: cwd = os.getcwd() else: - cwd=self.git_dir + cwd=self._cwd # Start the process proc = subprocess.Popen(command, diff --git a/lib/git/repo.py b/lib/git/repo.py index 5853356e..5a9855ac 100644 --- a/lib/git/repo.py +++ b/lib/git/repo.py @@ -12,7 +12,7 @@ from tree import Tree class Repo(object): DAEMON_EXPORT_FILE = 'git-daemon-export-ok' - def __init__(self, path): + def __init__(self, path=None): """ Create a new Repo instance @@ -27,19 +27,24 @@ class Repo(object): Returns ``GitPython.Repo`` """ - epath = os.path.abspath(path) + if not os.path.exists(path): + raise NoSuchPathError(path) + + self.git = Git(path) + self.path = self.git.get_git_dir() + if not self.path: + raise InvalidGitRepositoryError(path) + epath = self.git.get_work_tree() if os.path.exists(os.path.join(epath, '.git')): - self.path = os.path.join(epath, '.git') self.bare = False - elif os.path.exists(epath) and re.search('\.git$', epath): - self.path = epath + elif os.path.exists(epath) and epath.endswith('.git'): self.bare = True elif os.path.exists(epath): raise InvalidGitRepositoryError(epath) else: raise NoSuchPathError(epath) - self.git = Git(self.path) + @property def description(self): @@ -275,7 +280,7 @@ class Repo(object): if mkdir and not os.path.exists(path): os.makedirs(path, 0755) - git = Git(path) + git = Git(path, bare_repo=True) output = git.init(**kwargs) return Repo(path) create = init_bare |