4
4
# This module is part of GitPython and is released under
5
5
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
6
6
7
- from exc import InvalidGitRepositoryError , NoSuchPathError
8
- from cmd import Git
9
- from objects import Actor
10
- from refs import *
11
- from index import IndexFile
12
- from objects import *
13
- from config import GitConfigParser
14
- from remote import Remote
15
-
16
- from db import (
7
+ from git .exc import InvalidGitRepositoryError , NoSuchPathError
8
+ from git .cmd import Git
9
+ from git .objects import Actor
10
+ from git .refs import *
11
+ from git .index import IndexFile
12
+ from git .objects import *
13
+ from git .config import GitConfigParser
14
+ from git .remote import Remote
15
+ from git .db import (
17
16
GitCmdObjectDB ,
18
17
GitDB
19
18
)
20
19
20
+
21
21
from gitdb .util import (
22
22
join ,
23
- isdir ,
24
23
isfile ,
25
- join ,
26
24
hex_to_bin
27
25
)
26
+
27
+ from fun import (
28
+ rev_parse ,
29
+ is_git_dir ,
30
+ touch
31
+ )
32
+
28
33
import os
29
34
import sys
30
35
import re
31
36
32
37
33
38
__all__ = ('Repo' , )
34
39
35
- def touch (filename ):
36
- fp = open (filename , "a" )
37
- fp .close ()
38
-
39
- def is_git_dir (d ):
40
- """ This is taken from the git setup.c:is_git_directory
41
- function."""
42
-
43
- if isdir (d ) and \
44
- isdir (join (d , 'objects' )) and \
45
- isdir (join (d , 'refs' )):
46
- headref = join (d , 'HEAD' )
47
- return isfile (headref ) or \
48
- (os .path .islink (headref ) and
49
- os .readlink (headref ).startswith ('refs' ))
50
- return False
51
-
52
40
53
41
class Repo (object ):
54
42
"""Represents a git repository and allows you to query references,
@@ -70,6 +58,7 @@ class Repo(object):
70
58
# precompiled regex
71
59
re_whitespace = re .compile (r'\s+' )
72
60
re_hexsha_only = re .compile ('^[0-9A-Fa-f]{40}$' )
61
+ re_hexsha_shortened = re .compile ('^[0-9A-Fa-f]{4,40}$' )
73
62
re_author_committer_start = re .compile (r'^(author|committer)' )
74
63
re_tab_full_line = re .compile (r'^\t(.*)$' )
75
64
@@ -109,7 +98,7 @@ def __init__(self, path=None, odbt = GitDB):
109
98
self .git_dir = curpath
110
99
self ._working_tree_dir = os .path .dirname (curpath )
111
100
break
112
- gitpath = os . path . join (curpath , '.git' )
101
+ gitpath = join (curpath , '.git' )
113
102
if is_git_dir (gitpath ):
114
103
self .git_dir = gitpath
115
104
self ._working_tree_dir = curpath
@@ -139,7 +128,7 @@ def __init__(self, path=None, odbt = GitDB):
139
128
self .git = Git (self .working_dir )
140
129
141
130
# special handling, in special times
142
- args = [os . path . join (self .git_dir , 'objects' )]
131
+ args = [join (self .git_dir , 'objects' )]
143
132
if issubclass (odbt , GitCmdObjectDB ):
144
133
args .append (self .git )
145
134
self .odb = odbt (* args )
@@ -160,11 +149,11 @@ def __repr__(self):
160
149
161
150
# Description property
162
151
def _get_description (self ):
163
- filename = os . path . join (self .git_dir , 'description' )
152
+ filename = join (self .git_dir , 'description' )
164
153
return file (filename ).read ().rstrip ()
165
154
166
155
def _set_description (self , descr ):
167
- filename = os . path . join (self .git_dir , 'description' )
156
+ filename = join (self .git_dir , 'description' )
168
157
file (filename , 'w' ).write (descr + '\n ' )
169
158
170
159
description = property (_get_description , _set_description ,
@@ -334,11 +323,9 @@ def commit(self, rev=None):
334
323
:param rev: revision specifier, see git-rev-parse for viable options.
335
324
:return: ``git.Commit``"""
336
325
if rev is None :
337
- rev = self .active_branch
338
-
339
- c = Object .new (self , rev )
340
- assert c .type == "commit" , "Revision %s did not point to a commit, but to %s" % (rev , c )
341
- return c
326
+ return self .active_branch .commit
327
+ else :
328
+ return self .rev_parse (str (rev )+ "^0" )
342
329
343
330
def iter_trees (self , * args , ** kwargs ):
344
331
""":return: Iterator yielding Tree objects
@@ -359,14 +346,9 @@ def tree(self, rev=None):
359
346
it cannot know about its path relative to the repository root and subsequent
360
347
operations might have unexpected results."""
361
348
if rev is None :
362
- rev = self .active_branch
363
-
364
- c = Object .new (self , rev )
365
- if c .type == "commit" :
366
- return c .tree
367
- elif c .type == "tree" :
368
- return c
369
- raise ValueError ( "Revision %s did not point to a treeish, but to %s" % (rev , c ))
349
+ return self .active_branch .commit .tree
350
+ else :
351
+ return self .rev_parse (str (rev )+ "^{tree}" )
370
352
371
353
def iter_commits (self , rev = None , paths = '' , ** kwargs ):
372
354
"""A list of Commit objects representing the history of a given ref/commit
@@ -393,11 +375,11 @@ def iter_commits(self, rev=None, paths='', **kwargs):
393
375
return Commit .iter_items (self , rev , paths , ** kwargs )
394
376
395
377
def _get_daemon_export (self ):
396
- filename = os . path . join (self .git_dir , self .DAEMON_EXPORT_FILE )
378
+ filename = join (self .git_dir , self .DAEMON_EXPORT_FILE )
397
379
return os .path .exists (filename )
398
380
399
381
def _set_daemon_export (self , value ):
400
- filename = os . path . join (self .git_dir , self .DAEMON_EXPORT_FILE )
382
+ filename = join (self .git_dir , self .DAEMON_EXPORT_FILE )
401
383
fileexists = os .path .exists (filename )
402
384
if value and not fileexists :
403
385
touch (filename )
@@ -413,7 +395,7 @@ def _get_alternates(self):
413
395
"""The list of alternates for this repo from which objects can be retrieved
414
396
415
397
:return: list of strings being pathnames of alternates"""
416
- alternates_path = os . path . join (self .git_dir , 'objects' , 'info' , 'alternates' )
398
+ alternates_path = join (self .git_dir , 'objects' , 'info' , 'alternates' )
417
399
418
400
if os .path .exists (alternates_path ):
419
401
try :
@@ -436,9 +418,9 @@ def _set_alternates(self, alts):
436
418
:note:
437
419
The method does not check for the existance of the paths in alts
438
420
as the caller is responsible."""
439
- alternates_path = os . path . join (self .git_dir , 'objects' , 'info' , 'alternates' )
421
+ alternates_path = join (self .git_dir , 'objects' , 'info' , 'alternates' )
440
422
if not alts :
441
- if os . path . isfile (alternates_path ):
423
+ if isfile (alternates_path ):
442
424
os .remove (alternates_path )
443
425
else :
444
426
try :
@@ -466,7 +448,7 @@ def is_dirty(self, index=True, working_tree=True, untracked_files=False):
466
448
default_args = ('--abbrev=40' , '--full-index' , '--raw' )
467
449
if index :
468
450
# diff index against HEAD
469
- if os . path . isfile (self .index .path ) and self .head .is_valid () and \
451
+ if isfile (self .index .path ) and self .head .is_valid () and \
470
452
len (self .git .diff ('HEAD' , '--cached' , * default_args )):
471
453
return True
472
454
# END index handling
@@ -674,7 +656,7 @@ def clone(self, path, **kwargs):
674
656
# our git command could have a different working dir than our actual
675
657
# environment, hence we prepend its working dir if required
676
658
if not os .path .isabs (path ) and self .git .working_dir :
677
- path = os . path . join (self .git ._working_dir , path )
659
+ path = join (self .git ._working_dir , path )
678
660
return Repo (os .path .abspath (path ), odbt = odbt )
679
661
680
662
@@ -693,11 +675,13 @@ def archive(self, ostream, treeish=None, prefix=None, **kwargs):
693
675
if treeish is None :
694
676
treeish = self .active_branch
695
677
if prefix and 'prefix' not in kwargs :
696
- kwargs ['prefix' ] = prefix
678
+ kwargs ['prefix' ] = prefix
697
679
kwargs ['output_stream' ] = ostream
698
680
699
681
self .git .archive (treeish , ** kwargs )
700
682
return self
701
-
683
+
684
+ rev_parse = rev_parse
685
+
702
686
def __repr__ (self ):
703
687
return '<git.Repo "%s">' % self .git_dir
0 commit comments