diff options
Diffstat (limited to 'git/repo/base.py')
-rw-r--r-- | git/repo/base.py | 143 |
1 files changed, 66 insertions, 77 deletions
diff --git a/git/repo/base.py b/git/repo/base.py index bde9b936..f3a04cf4 100644 --- a/git/repo/base.py +++ b/git/repo/base.py @@ -4,52 +4,16 @@ # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php -from git.exc import ( - InvalidGitRepositoryError, - NoSuchPathError, - GitCommandError -) +from collections import namedtuple +import logging +import os +import re +import sys + from git.cmd import ( Git, handle_process_output ) -from git.refs import ( - HEAD, - Head, - Reference, - TagReference, -) -from git.objects import ( - Submodule, - RootModule, - Commit -) -from git.util import ( - Actor, - finalize_process -) -from git.index import IndexFile -from git.config import GitConfigParser -from git.remote import ( - Remote, - add_progress, - to_progress_instance -) - -from git.db import GitCmdObjectDB - -from gitdb.util import ( - join, - isfile, - hex_to_bin -) - -from .fun import ( - rev_parse, - is_git_dir, - find_submodule_git_dir, - touch, -) from git.compat import ( text_type, defenc, @@ -58,12 +22,18 @@ from git.compat import ( range, is_win, ) +from git.config import GitConfigParser +from git.db import GitCmdObjectDB +from git.exc import InvalidGitRepositoryError, NoSuchPathError, GitCommandError +from git.index import IndexFile +from git.objects import Submodule, RootModule, Commit +from git.refs import HEAD, Head, Reference, TagReference +from git.remote import Remote, add_progress, to_progress_instance +from git.util import Actor, finalize_process, decygpath, hex_to_bin +import os.path as osp + +from .fun import rev_parse, is_git_dir, find_submodule_git_dir, touch -import os -import sys -import re -import logging -from collections import namedtuple log = logging.getLogger(__name__) @@ -79,7 +49,7 @@ __all__ = ('Repo',) def _expand_path(p): - return os.path.normpath(os.path.abspath(os.path.expandvars(os.path.expanduser(p)))) + return osp.normpath(osp.abspath(osp.expandvars(osp.expanduser(p)))) class Repo(object): @@ -129,8 +99,9 @@ class Repo(object): repo = Repo("~/Development/git-python.git") repo = Repo("$REPOSITORIES/Development/git-python.git") - if `None, current-directory is used. - The :envvar:`GIT_DIR` if set and not empty takes precendance over this parameter. + - In *Cygwin*, path may be a `'cygdrive/...'` prefixed path. + - If `None, current-directory is used. + - The :envvar:`GIT_DIR` if set and not empty takes precendance over this parameter. :param odbt: Object DataBase type - a type which is constructed by providing the directory containing the database objects, i.e. .git/objects. It will @@ -143,7 +114,9 @@ class Repo(object): :raise InvalidGitRepositoryError: :raise NoSuchPathError: :return: git.Repo """ - epath = os.getenv('GIT_DIR') + epath = os.getenv('GIT_DIR') or path or os.getcwd() + if Git.is_cygwin(): + epath = decygpath(epath) epath = _expand_path(epath or path or os.getcwd()) if not os.path.exists(epath): raise NoSuchPathError(epath) @@ -152,7 +125,7 @@ class Repo(object): # curpath = epath while curpath: - # ABOUT os.path.NORMPATH + # ABOUT osp.NORMPATH # It's important to normalize the paths, as submodules will otherwise initialize their # repo instances with paths that depend on path-portions that will not exist after being # removed. It's just cleaner. @@ -161,15 +134,18 @@ class Repo(object): self._working_tree_dir = os.path.dirname(self.git_dir) break - sm_gitpath = find_submodule_git_dir(join(curpath, '.git')) + sm_gitpath = find_submodule_git_dir(osp.join(curpath, '.git')) if sm_gitpath is not None: - self.git_dir = os.path.normpath(sm_gitpath) + self.git_dir = osp.normpath(sm_gitpath) + sm_gitpath = find_submodule_git_dir(osp.join(curpath, '.git')) + if sm_gitpath is not None: + self.git_dir = _expand_path(sm_gitpath) self._working_tree_dir = curpath break if not search_parent_directories: break - curpath, tail = os.path.split(curpath) + curpath, tail = osp.split(curpath) if not tail: break # END while curpath @@ -194,7 +170,7 @@ class Repo(object): self.git = self.GitCommandWrapperType(self.working_dir) # special handling, in special times - args = [join(self.git_dir, 'objects')] + args = [osp.join(self.git_dir, 'objects')] if issubclass(odbt, GitCmdObjectDB): args.append(self.git) self.odb = odbt(*args) @@ -216,12 +192,12 @@ class Repo(object): # Description property def _get_description(self): - filename = join(self.git_dir, 'description') + filename = osp.join(self.git_dir, 'description') with open(filename, 'rb') as fp: return fp.read().rstrip().decode(defenc) def _set_description(self, descr): - filename = join(self.git_dir, 'description') + filename = osp.join(self.git_dir, 'description') with open(filename, 'wb') as fp: fp.write((descr + '\n').encode(defenc)) @@ -385,12 +361,12 @@ class Repo(object): if config_level == "system": return "/etc/gitconfig" elif config_level == "user": - config_home = os.environ.get("XDG_CONFIG_HOME") or os.path.join(os.environ.get("HOME", '~'), ".config") - return os.path.normpath(os.path.expanduser(join(config_home, "git", "config"))) + config_home = os.environ.get("XDG_CONFIG_HOME") or osp.join(os.environ.get("HOME", '~'), ".config") + return osp.normpath(osp.expanduser(osp.join(config_home, "git", "config"))) elif config_level == "global": - return os.path.normpath(os.path.expanduser("~/.gitconfig")) + return osp.normpath(osp.expanduser("~/.gitconfig")) elif config_level == "repository": - return os.path.normpath(join(self.git_dir, "config")) + return osp.normpath(osp.join(self.git_dir, "config")) raise ValueError("Invalid configuration level: %r" % config_level) @@ -534,12 +510,12 @@ class Repo(object): return True def _get_daemon_export(self): - filename = join(self.git_dir, self.DAEMON_EXPORT_FILE) - return os.path.exists(filename) + filename = osp.join(self.git_dir, self.DAEMON_EXPORT_FILE) + return osp.exists(filename) def _set_daemon_export(self, value): - filename = join(self.git_dir, self.DAEMON_EXPORT_FILE) - fileexists = os.path.exists(filename) + filename = osp.join(self.git_dir, self.DAEMON_EXPORT_FILE) + fileexists = osp.exists(filename) if value and not fileexists: touch(filename) elif not value and fileexists: @@ -554,9 +530,9 @@ class Repo(object): """The list of alternates for this repo from which objects can be retrieved :return: list of strings being pathnames of alternates""" - alternates_path = join(self.git_dir, 'objects', 'info', 'alternates') + alternates_path = osp.join(self.git_dir, 'objects', 'info', 'alternates') - if os.path.exists(alternates_path): + if osp.exists(alternates_path): with open(alternates_path, 'rb') as f: alts = f.read().decode(defenc) return alts.strip().splitlines() @@ -574,9 +550,9 @@ class Repo(object): :note: The method does not check for the existance of the paths in alts as the caller is responsible.""" - alternates_path = join(self.git_dir, 'objects', 'info', 'alternates') + alternates_path = osp.join(self.git_dir, 'objects', 'info', 'alternates') if not alts: - if isfile(alternates_path): + if osp.isfile(alternates_path): os.remove(alternates_path) else: with open(alternates_path, 'wb') as f: @@ -605,7 +581,7 @@ class Repo(object): default_args.append(path) if index: # diff index against HEAD - if isfile(self.index.path) and \ + if osp.isfile(self.index.path) and \ len(self.git.diff('--cached', *default_args)): return True # END index handling @@ -865,7 +841,7 @@ class Repo(object): :return: ``git.Repo`` (the newly created repo)""" if path: path = _expand_path(path) - if mkdir and path and not os.path.exists(path): + if mkdir and path and not osp.exists(path): os.makedirs(path, 0o755) # git command automatically chdir into the directory @@ -879,19 +855,32 @@ class Repo(object): progress = to_progress_instance(progress) odbt = kwargs.pop('odbt', odb_default_type) - proc = git.clone(url, path, with_extended_output=True, as_process=True, + + ## A bug win cygwin's Git, when `--bare` or `--separate-git-dir` + # it prepends the cwd or(?) the `url` into the `path, so:: + # git clone --bare /cygwin/d/foo.git C:\\Work + # becomes:: + # git clone --bare /cygwin/d/foo.git /cygwin/d/C:\\Work + # + clone_path = (Git.polish_url(path) + if Git.is_cygwin() and 'bare'in kwargs + else path) + sep_dir = kwargs.get('separate_git_dir') + if sep_dir: + kwargs['separate_git_dir'] = Git.polish_url(sep_dir) + proc = git.clone(Git.polish_url(url), clone_path, with_extended_output=True, as_process=True, v=True, **add_progress(kwargs, git, progress)) if progress: handle_process_output(proc, None, progress.new_message_handler(), finalize_process) else: - (stdout, stderr) = proc.communicate() # FIXME: Will block of outputs are big! + (stdout, stderr) = proc.communicate() # FIXME: Will block if outputs are big! log.debug("Cmd(%s)'s unused stdout: %s", getattr(proc, 'args', ''), stdout) finalize_process(proc, stderr=stderr) # our git command could have a different working dir than our actual # environment, hence we prepend its working dir if required - if not os.path.isabs(path) and git.working_dir: - path = join(git._working_dir, path) + if not osp.isabs(path) and git.working_dir: + path = osp.join(git._working_dir, path) # adjust remotes - there may be operating systems which use backslashes, # These might be given as initial paths, but when handling the config file @@ -969,7 +958,7 @@ class Repo(object): """ if self.bare: return False - return os.path.isfile(os.path.join(self.working_tree_dir, '.git')) + return osp.isfile(osp.join(self.working_tree_dir, '.git')) rev_parse = rev_parse |