@@ -41,9 +41,19 @@ class Repo(object):
4141 Represents a git repository and allows you to query references,
4242 gather commit information, generate diffs, create and clone repositories query
4343 the log.
44+
45+ The following attributes are worth using:
46+
47+ 'working_dir' is the working directory of the git command, wich is the working tree
48+ directory if available or the .git directory in case of bare repositories
49+
50+ 'working_tree_dir' is the working tree directory, but will raise AssertionError
51+ if we are a bare repository.
52+
53+ 'git_dir' is the .git repository directoy, which is always set.
4454 """
4555 DAEMON_EXPORT_FILE = 'git-daemon-export-ok'
46- __slots__ = ( "wd " , "path " , "_bare" , "git" )
56+ __slots__ = ( "working_dir " , "_working_tree_dir" , "git_dir " , "_bare" , "git" )
4757
4858 # precompiled regex
4959 re_whitespace = re .compile (r'\s+' )
@@ -81,26 +91,28 @@ def __init__(self, path=None):
8191 if not os .path .exists (epath ):
8292 raise NoSuchPathError (epath )
8393
84- self .path = None
94+ self .working_dir = None
95+ self ._working_tree_dir = None
96+ self .git_dir = None
8597 curpath = epath
8698
8799 # walk up the path to find the .git dir
88100 while curpath :
89101 if is_git_dir (curpath ):
90- self .path = curpath
91- self .wd = os .path .dirname (curpath )
102+ self .git_dir = curpath
103+ self ._working_tree_dir = os .path .dirname (curpath )
92104 break
93105 gitpath = os .path .join (curpath , '.git' )
94106 if is_git_dir (gitpath ):
95- self .path = gitpath
96- self .wd = curpath
107+ self .git_dir = gitpath
108+ self ._working_tree_dir = curpath
97109 break
98110 curpath , dummy = os .path .split (curpath )
99111 if not dummy :
100112 break
101113 # END while curpath
102114
103- if self .path is None :
115+ if self .git_dir is None :
104116 raise InvalidGitRepositoryError (epath )
105117
106118 self ._bare = False
@@ -113,24 +125,38 @@ def __init__(self, path=None):
113125 # adjust the wd in case we are actually bare - we didn't know that
114126 # in the first place
115127 if self ._bare :
116- self .wd = self .path
117-
118- self .git = Git (self .wd )
128+ self ._working_tree_dir = None
129+ # END working dir handling
130+
131+ self .working_dir = self ._working_tree_dir or self .git_dir
132+ self .git = Git (self .working_dir )
119133
120134 # Description property
121135 def _get_description (self ):
122- filename = os .path .join (self .path , 'description' )
136+ filename = os .path .join (self .git_dir , 'description' )
123137 return file (filename ).read ().rstrip ()
124138
125139 def _set_description (self , descr ):
126- filename = os .path .join (self .path , 'description' )
140+ filename = os .path .join (self .git_dir , 'description' )
127141 file (filename , 'w' ).write (descr + '\n ' )
128142
129143 description = property (_get_description , _set_description ,
130144 doc = "the project's description" )
131145 del _get_description
132146 del _set_description
133147
148+ @property
149+ def working_tree_dir (self ):
150+ """
151+ Returns
152+ The working tree directory of our git repository
153+
154+ Raises AssertionError
155+ If we are a bare repository
156+ """
157+ if self ._working_tree_dir is None :
158+ raise AssertionError ( "Repository at %r is bare and does not have a working tree directory" % self .git_dir )
159+ return self ._working_tree_dir
134160
135161 @property
136162 def bare (self ):
@@ -286,7 +312,7 @@ def _get_config_path(self, config_level ):
286312 elif config_level == "global" :
287313 return os .path .expanduser ("~/.gitconfig" )
288314 elif config_level == "repository" :
289- return "%s/config" % self .path
315+ return "%s/config" % self .git_dir
290316
291317 raise ValueError ( "Invalid configuration level: %r" % config_level )
292318
@@ -413,11 +439,11 @@ def iter_commits(self, rev=None, paths='', **kwargs):
413439 return Commit .iter_items (self , rev , paths , ** kwargs )
414440
415441 def _get_daemon_export (self ):
416- filename = os .path .join (self .path , self .DAEMON_EXPORT_FILE )
442+ filename = os .path .join (self .git_dir , self .DAEMON_EXPORT_FILE )
417443 return os .path .exists (filename )
418444
419445 def _set_daemon_export (self , value ):
420- filename = os .path .join (self .path , self .DAEMON_EXPORT_FILE )
446+ filename = os .path .join (self .git_dir , self .DAEMON_EXPORT_FILE )
421447 fileexists = os .path .exists (filename )
422448 if value and not fileexists :
423449 touch (filename )
@@ -436,7 +462,7 @@ def _get_alternates(self):
436462 Returns
437463 list of strings being pathnames of alternates
438464 """
439- alternates_path = os .path .join (self .path , 'objects' , 'info' , 'alternates' )
465+ alternates_path = os .path .join (self .git_dir , 'objects' , 'info' , 'alternates' )
440466
441467 if os .path .exists (alternates_path ):
442468 try :
@@ -466,7 +492,7 @@ def _set_alternates(self, alts):
466492 Returns
467493 None
468494 """
469- alternates_path = os .path .join (self .path , 'objects' , 'info' , 'alternates' )
495+ alternates_path = os .path .join (self .git_dir , 'objects' , 'info' , 'alternates' )
470496 if not alts :
471497 if os .path .isfile (alternates_path ):
472498 os .remove (alternates_path )
@@ -706,7 +732,7 @@ def clone(self, path, **kwargs):
706732 # END windows handling
707733
708734 try :
709- self .git .clone (self .path , path , ** kwargs )
735+ self .git .clone (self .git_dir , path , ** kwargs )
710736 finally :
711737 if prev_cwd is not None :
712738 os .chdir (prev_cwd )
@@ -754,4 +780,4 @@ def archive(self, ostream, treeish=None, prefix=None, **kwargs):
754780 return self
755781
756782 def __repr__ (self ):
757- return '<git.Repo "%s">' % self .path
783+ return '<git.Repo "%s">' % self .git_dir
0 commit comments