3030from git .refs import HEAD ,Head ,Reference ,TagReference
3131from git .remote import Remote ,add_progress ,to_progress_instance
3232from git .util import Actor ,finalize_process ,decygpath ,hex_to_bin
33-
3433import os .path as osp
3534
36- from .fun import rev_parse ,is_git_dir ,find_git_dir ,touch
35+ from .fun import rev_parse ,is_git_dir ,find_submodule_git_dir ,touch
3736
3837
3938log = logging .getLogger (__name__ )
5049
5150
5251def _expand_path (p ):
53- return osp .abspath (osp .expandvars (osp .expanduser (p )))
52+ return osp .normpath ( osp . abspath (osp .expandvars (osp .expanduser (p ) )))
5453
5554
5655class Repo (object ):
@@ -69,6 +68,11 @@ class Repo(object):
6968 'git_dir' is the .git repository directory, which is always set."""
7069DAEMON_EXPORT_FILE = 'git-daemon-export-ok'
7170
71+ git = None # Must exist, or __del__ will fail in case we raise on `__init__()`
72+ working_dir = None
73+ _working_tree_dir = None
74+ git_dir = None
75+
7276# precompiled regex
7377re_whitespace = re .compile (r'\s+' )
7478re_hexsha_only = re .compile ('^[0-9A-Fa-f]{40}$' )
@@ -95,8 +99,9 @@ def __init__(self, path=None, odbt=DefaultDBType, search_parent_directories=Fals
9599 repo = Repo("~/Development/git-python.git")
96100 repo = Repo("$REPOSITORIES/Development/git-python.git")
97101
98- In *Cygwin*, path may be a `'cygdrive/...'` prefixed path.
99-
102+ - In *Cygwin*, path may be a `'cygdrive/...'` prefixed path.
103+ - If it evaluates to false, :envvar:`GIT_DIR` is used, and if this also evals to false,
104+ the current-directory is used.
100105 :param odbt:
101106 Object DataBase type - a type which is constructed by providing
102107 the directory containing the database objects, i.e. .git/objects. It will
@@ -109,40 +114,41 @@ def __init__(self, path=None, odbt=DefaultDBType, search_parent_directories=Fals
109114 :raise InvalidGitRepositoryError:
110115 :raise NoSuchPathError:
111116 :return: git.Repo """
117+ epath = path or os .getenv ('GIT_DIR' )
118+ if not epath :
119+ epath = os .getcwd ()
112120if Git .is_cygwin ():
113- path = decygpath (path )
114-
115- epath = _expand_path (path or os .getcwd ())
116- self .git = None # should be set for __del__ not to fail in case we raise
117- if not osp .exists (epath ):
121+ epath = decygpath (epath )
122+ epath = _expand_path (epath or path or os .getcwd ())
123+ if not os .path .exists (epath ):
118124raise NoSuchPathError (epath )
119125
120- self .working_dir = None
121- self ._working_tree_dir = None
122- self .git_dir = None
123- curpath = os .getenv ('GIT_DIR' ,epath )
124-
125- # walk up the path to find the .git dir
126+ ## Walk up the path to find the `.git` dir.
127+ #
128+ curpath = epath
126129while curpath :
127130# ABOUT osp.NORMPATH
128131# It's important to normalize the paths, as submodules will otherwise initialize their
129132# repo instances with paths that depend on path-portions that will not exist after being
130133# removed. It's just cleaner.
131134if is_git_dir (curpath ):
132- self .git_dir = osp . normpath ( curpath )
133- self ._working_tree_dir = osp .dirname (self .git_dir )
135+ self .git_dir = curpath
136+ self ._working_tree_dir = os . path .dirname (self .git_dir )
134137break
135138
136- gitpath = find_git_dir (osp .join (curpath ,'.git' ))
137- if gitpath is not None :
138- self .git_dir = osp .normpath (gitpath )
139+ sm_gitpath = find_submodule_git_dir (osp .join (curpath ,'.git' ))
140+ if sm_gitpath is not None :
141+ self .git_dir = osp .normpath (sm_gitpath )
142+ sm_gitpath = find_submodule_git_dir (osp .join (curpath ,'.git' ))
143+ if sm_gitpath is not None :
144+ self .git_dir = _expand_path (sm_gitpath )
139145self ._working_tree_dir = curpath
140146break
141147
142148if not search_parent_directories :
143149break
144- curpath ,dummy = osp .split (curpath )
145- if not dummy :
150+ curpath ,tail = osp .split (curpath )
151+ if not tail :
146152break
147153# END while curpath
148154