Example #1
0
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
Example #2
0
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
Example #3
0
    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)
Example #4
0
 def test_decygpath(self, case):
     wpath, cpath = case
     wcpath = decygpath(cpath)
     self.assertEqual(wcpath, wpath.replace('/', '\\'), cpath)
Example #5
0
 def test_decygpath(self, case):
     wpath, cpath = case
     wcpath = decygpath(cpath)
     self.assertEqual(wcpath, wpath.replace('/', '\\'), cpath)
Example #6
0
    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)