def find_submodule_git_dir(d): """Search for a submodule repo.""" if is_git_dir(d): return d try: with open(d) as fp: content = fp.read().rstrip() except (IOError, OSError): # it's probably not a file pass else: if content.startswith('gitdir: '): path = content[8:] if Git.is_cygwin(): ## Cygwin creates submodules prefixed with `/cygdrive/...` suffixes. path = decygpath(path) if not osp.isabs(path): path = osp.join(osp.dirname(d), path) return find_submodule_git_dir(path) # end handle exception return None
def __init__(self, path=None, odbt=DefaultDBType, search_parent_directories=False, expand_vars=True): """Create a new Repo instance :param path: the path to either the root git directory or the bare git repo:: repo = Repo("/Users/mtrier/Development/git-python") repo = Repo("/Users/mtrier/Development/git-python.git") repo = Repo("~/Development/git-python.git") repo = Repo("$REPOSITORIES/Development/git-python.git") - In *Cygwin*, path may be a `'cygdrive/...'` prefixed path. - If it evaluates to false, :envvar:`GIT_DIR` is used, and if this also evals to false, the current-directory is used. :param odbt: Object DataBase type - a type which is constructed by providing the directory containing the database objects, i.e. .git/objects. It will be used to access all object data :param search_parent_directories: if True, all parent directories will be searched for a valid repo as well. Please note that this was the default behaviour in older versions of GitPython, which is considered a bug though. :raise InvalidGitRepositoryError: :raise NoSuchPathError: :return: git.Repo """ epath = path or os.getenv('GIT_DIR') if not epath: epath = os.getcwd() if Git.is_cygwin(): epath = decygpath(epath) epath = epath or path or os.getcwd() if expand_vars and ("%" in epath or "$" in epath): warnings.warn( "The use of environment variables in paths is deprecated" + "\nfor security reasons and may be removed in the future!!") epath = expand_path(epath, expand_vars) if not os.path.exists(epath): raise NoSuchPathError(epath) ## Walk up the path to find the `.git` dir. # curpath = epath while curpath: # 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. if is_git_dir(curpath): self.git_dir = curpath self._working_tree_dir = os.getenv( 'GIT_WORK_TREE', os.path.dirname(self.git_dir)) break dotgit = osp.join(curpath, '.git') sm_gitpath = find_submodule_git_dir(dotgit) if sm_gitpath is not None: self.git_dir = osp.normpath(sm_gitpath) sm_gitpath = find_submodule_git_dir(dotgit) if sm_gitpath is None: sm_gitpath = find_worktree_git_dir(dotgit) if sm_gitpath is not None: self.git_dir = expand_path(sm_gitpath, expand_vars) self._working_tree_dir = curpath break if not search_parent_directories: break curpath, tail = osp.split(curpath) if not tail: break # END while curpath if self.git_dir is None: raise InvalidGitRepositoryError(epath) self._bare = False try: self._bare = self.config_reader("repository").getboolean( 'core', 'bare') except Exception: # 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.common_dir self.git = self.GitCommandWrapperType(self.working_dir) # special handling, in special times args = [osp.join(self.common_dir, 'objects')] if issubclass(odbt, GitCmdObjectDB): args.append(self.git) self.odb = odbt(*args)
def test_decygpath(self, case): wpath, cpath = case wcpath = decygpath(cpath) self.assertEqual(wcpath, wpath.replace('/', '\\'), cpath)
def __init__(self, path=None, odbt=DefaultDBType, search_parent_directories=False): """Create a new Repo instance :param path: the path to either the root git directory or the bare git repo:: repo = Repo("/Users/mtrier/Development/git-python") repo = Repo("/Users/mtrier/Development/git-python.git") repo = Repo("~/Development/git-python.git") repo = Repo("$REPOSITORIES/Development/git-python.git") - In *Cygwin*, path may be a `'cygdrive/...'` prefixed path. - If it evaluates to false, :envvar:`GIT_DIR` is used, and if this also evals to false, the current-directory is used. :param odbt: Object DataBase type - a type which is constructed by providing the directory containing the database objects, i.e. .git/objects. It will be used to access all object data :param search_parent_directories: if True, all parent directories will be searched for a valid repo as well. Please note that this was the default behaviour in older versions of GitPython, which is considered a bug though. :raise InvalidGitRepositoryError: :raise NoSuchPathError: :return: git.Repo """ epath = path or os.getenv('GIT_DIR') if not epath: epath = 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) ## Walk up the path to find the `.git` dir. # curpath = epath while curpath: # 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. if is_git_dir(curpath): self.git_dir = curpath self._working_tree_dir = os.path.dirname(self.git_dir) break sm_gitpath = find_submodule_git_dir(osp.join(curpath, '.git')) if sm_gitpath is not None: 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 = osp.split(curpath) if not tail: break # END while curpath if self.git_dir is None: raise InvalidGitRepositoryError(epath) self._bare = False try: self._bare = self.config_reader("repository").getboolean('core', 'bare') except Exception: # lets not assume the option exists, although it should pass # 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.git = self.GitCommandWrapperType(self.working_dir) # special handling, in special times args = [osp.join(self.git_dir, 'objects')] if issubclass(odbt, GitCmdObjectDB): args.append(self.git) self.odb = odbt(*args)
def __init__(self, path: Optional[PathLike] = None, odbt: Type[GitCmdObjectDB] = GitCmdObjectDB, search_parent_directories: bool = False, expand_vars: bool = True) -> None: """Create a new Repo instance :param path: the path to either the root git directory or the bare git repo:: repo = Repo("/Users/mtrier/Development/git-python") repo = Repo("/Users/mtrier/Development/git-python.git") repo = Repo("~/Development/git-python.git") repo = Repo("$REPOSITORIES/Development/git-python.git") repo = Repo("C:\\Users\\mtrier\\Development\\git-python\\.git") - In *Cygwin*, path may be a `'cygdrive/...'` prefixed path. - If it evaluates to false, :envvar:`GIT_DIR` is used, and if this also evals to false, the current-directory is used. :param odbt: Object DataBase type - a type which is constructed by providing the directory containing the database objects, i.e. .git/objects. It will be used to access all object data :param search_parent_directories: if True, all parent directories will be searched for a valid repo as well. Please note that this was the default behaviour in older versions of GitPython, which is considered a bug though. :raise InvalidGitRepositoryError: :raise NoSuchPathError: :return: git.Repo """ epath = path or os.getenv('GIT_DIR') if not epath: epath = os.getcwd() if Git.is_cygwin(): epath = decygpath(epath) epath = epath or path or os.getcwd() if not isinstance(epath, str): epath = str(epath) if expand_vars and re.search(self.re_envvars, epath): warnings.warn("The use of environment variables in paths is deprecated" + "\nfor security reasons and may be removed in the future!!") epath = expand_path(epath, expand_vars) if epath is not None: if not os.path.exists(epath): raise NoSuchPathError(epath) ## Walk up the path to find the `.git` dir. # curpath = epath while curpath: # 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. if is_git_dir(curpath): self.git_dir = curpath # from man git-config : core.worktree # Set the path to the root of the working tree. If GIT_COMMON_DIR environment # variable is set, core.worktree is ignored and not used for determining the # root of working tree. This can be overridden by the GIT_WORK_TREE environment # variable. The value can be an absolute path or relative to the path to the .git # directory, which is either specified by GIT_DIR, or automatically discovered. # If GIT_DIR is specified but none of GIT_WORK_TREE and core.worktree is specified, # the current working directory is regarded as the top level of your working tree. self._working_tree_dir = os.path.dirname(self.git_dir) if os.environ.get('GIT_COMMON_DIR') is None: gitconf = self.config_reader("repository") if gitconf.has_option('core', 'worktree'): self._working_tree_dir = gitconf.get('core', 'worktree') if 'GIT_WORK_TREE' in os.environ: self._working_tree_dir = os.getenv('GIT_WORK_TREE') break dotgit = osp.join(curpath, '.git') sm_gitpath = find_submodule_git_dir(dotgit) if sm_gitpath is not None: self.git_dir = osp.normpath(sm_gitpath) sm_gitpath = find_submodule_git_dir(dotgit) if sm_gitpath is None: sm_gitpath = find_worktree_git_dir(dotgit) if sm_gitpath is not None: self.git_dir = expand_path(sm_gitpath, expand_vars) self._working_tree_dir = curpath break if not search_parent_directories: break curpath, tail = osp.split(curpath) if not tail: break # END while curpath if self.git_dir is None: self.git_dir = cast(PathLike, self.git_dir) raise InvalidGitRepositoryError(epath) self._bare = False try: self._bare = self.config_reader("repository").getboolean('core', 'bare') except Exception: # 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: 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.common_dir # type: Optional[PathLike] self.git = self.GitCommandWrapperType(self.working_dir) # special handling, in special times rootpath = osp.join(self.common_dir, 'objects') if issubclass(odbt, GitCmdObjectDB): self.odb = odbt(rootpath, self.git) else: self.odb = odbt(rootpath)