Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit69dd875

Browse files
committed
index.write_tree: initial version implemented, although its not yet working correctly, a test to explicitly compare the git version with the python implementation is still missing
Tree and Index internally use 20 byte shas, converting them only as needed to reduce memory footprint and processing timeobjects: started own 'fun' module containing the most important tree functions, more are likely to be added soon
1 parent1044116 commit69dd875

File tree

13 files changed

+298
-208
lines changed

13 files changed

+298
-208
lines changed

‎CHANGES‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ CHANGES
55
===
66
* ConcurrentWriteOperation was removed, and replaced by LockedFD
77
* IndexFile.get_entries_key was renamed to entry_key
8+
* IndexEntry instances contained in IndexFile.entries now use binary sha's. Use
9+
the .hexsha property to obtain the hexadecimal version
10+
* IndexFile.write_tree: removed missing_ok keyword, its always True now
11+
Instead of raising GitCommandError it raises UnmergedEntriesError
12+
* diff.Diff.null_hex_sha renamed to NULL_HEX_SHA, to be conforming with
13+
the naming in the Object base class
14+
815

916
0.2 Beta 2
1017
===========

‎lib/git/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def _init_externals():
2828
fromgit.objectsimport*
2929
fromgit.refsimport*
3030
fromgit.diffimport*
31-
fromgit.errorsimportInvalidGitRepositoryError,NoSuchPathError,GitCommandError
31+
fromgit.errorsimport*
3232
fromgit.cmdimportGit
3333
fromgit.repoimportRepo
3434
fromgit.remoteimport*

‎lib/git/db.py‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44
OStream
55
)
66

7+
fromgitdb.utilimportto_hex_sha
8+
79
fromgitdb.dbimportGitDB
810
fromgitdb.dbimportLooseObjectDB
911

12+
1013
__all__= ('GitCmdObjectDB','GitDB' )
1114

1215
#class GitCmdObjectDB(CompoundDB, ObjectDBW):
@@ -24,11 +27,11 @@ def __init__(self, root_path, git):
2427
self._git=git
2528

2629
definfo(self,sha):
27-
t=self._git.get_object_header(sha)
30+
t=self._git.get_object_header(to_hex_sha(sha))
2831
returnOInfo(*t)
2932

3033
defstream(self,sha):
3134
"""For now, all lookup is done by git itself"""
32-
t=self._git.stream_object_data(sha)
35+
t=self._git.stream_object_data(to_hex_sha(sha))
3336
returnOStream(*t)
3437

‎lib/git/diff.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ class Diff(object):
196196
\.\.(?P<b_blob_id>[0-9A-Fa-f]+)[ ]?(?P<b_mode>.+)?(?:\n|$))?
197197
""",re.VERBOSE|re.MULTILINE)
198198
# can be used for comparisons
199-
null_hex_sha="0"*40
199+
NULL_HEX_SHA="0"*40
200200

201201
__slots__= ("a_blob","b_blob","a_mode","b_mode","new_file","deleted_file",
202202
"rename_from","rename_to","diff")

‎lib/git/errors.py‎

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,43 +6,51 @@
66
""" Module containing all exceptions thrown througout the git package, """
77

88
classInvalidGitRepositoryError(Exception):
9-
""" Thrown if the given repository appears to have an invalid format. """
9+
""" Thrown if the given repository appears to have an invalid format. """
1010

1111

1212
classNoSuchPathError(OSError):
13-
""" Thrown if a path could not be access by the system. """
13+
""" Thrown if a path could not be access by the system. """
1414

1515

1616
classGitCommandError(Exception):
17-
""" Thrown if execution of the git command fails with non-zero status code. """
18-
def__init__(self,command,status,stderr=None):
19-
self.stderr=stderr
20-
self.status=status
21-
self.command=command
22-
23-
def__str__(self):
24-
return ("'%s' returned exit status %i: %s"%
25-
(' '.join(str(i)foriinself.command),self.status,self.stderr))
17+
""" Thrown if execution of the git command fails with non-zero status code. """
18+
def__init__(self,command,status,stderr=None):
19+
self.stderr=stderr
20+
self.status=status
21+
self.command=command
22+
23+
def__str__(self):
24+
return ("'%s' returned exit status %i: %s"%
25+
(' '.join(str(i)foriinself.command),self.status,self.stderr))
2626

2727

2828
classCheckoutError(Exception ):
29-
"""Thrown if a file could not be checked out from the index as it contained
30-
changes.
31-
32-
The .failed_files attribute contains a list of relative paths that failed
33-
to be checked out as they contained changes that did not exist in the index.
34-
35-
The .failed_reasons attribute contains a string informing about the actual
36-
cause of the issue.
37-
38-
The .valid_files attribute contains a list of relative paths to files that
39-
were checked out successfully and hence match the version stored in the
40-
index"""
41-
def__init__(self,message,failed_files,valid_files,failed_reasons):
42-
Exception.__init__(self,message)
43-
self.failed_files=failed_files
44-
self.failed_reasons=failed_reasons
45-
self.valid_files=valid_files
46-
47-
def__str__(self):
48-
returnException.__str__(self)+":%s"%self.failed_files
29+
"""Thrown if a file could not be checked out from the index as it contained
30+
changes.
31+
32+
The .failed_files attribute contains a list of relative paths that failed
33+
to be checked out as they contained changes that did not exist in the index.
34+
35+
The .failed_reasons attribute contains a string informing about the actual
36+
cause of the issue.
37+
38+
The .valid_files attribute contains a list of relative paths to files that
39+
were checked out successfully and hence match the version stored in the
40+
index"""
41+
def__init__(self,message,failed_files,valid_files,failed_reasons):
42+
Exception.__init__(self,message)
43+
self.failed_files=failed_files
44+
self.failed_reasons=failed_reasons
45+
self.valid_files=valid_files
46+
47+
def__str__(self):
48+
returnException.__str__(self)+":%s"%self.failed_files
49+
50+
51+
classCacheError(Exception):
52+
"""Base for all errors related to the git index, which is called cache internally"""
53+
54+
classUnmergedEntriesError(CacheError):
55+
"""Thrown if an operation cannot proceed as there are still unmerged
56+
entries in the cache"""

‎lib/git/index/base.py‎

Lines changed: 35 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66
"""Module containing Index implementation, allowing to perform all kinds of index
77
manipulations such as querying and merging. """
8-
importbinascii
98
importtempfile
109
importos
1110
importsys
1211
importsubprocess
1312
importglob
1413
fromcStringIOimportStringIO
14+
frombinasciiimportb2a_hex
1515

1616
fromstatimport (
1717
S_ISLNK,
@@ -25,16 +25,12 @@
2525
fromtypimport (
2626
BaseIndexEntry,
2727
IndexEntry,
28-
CE_NAMEMASK,
29-
CE_STAGESHIFT
3028
)
3129

3230
fromutilimport (
3331
TemporaryFileSwap,
3432
post_clear_cache,
3533
default_index,
36-
pack,
37-
unpack
3834
)
3935

4036
importgit.objects
@@ -60,20 +56,17 @@
6056
LockedFD,
6157
join_path_native,
6258
file_contents_ro,
63-
LockFile
64-
)
65-
66-
67-
fromgitdb.baseimport (
68-
IStream
6959
)
7060

7161
fromfunimport (
7262
write_cache,
7363
read_cache,
64+
write_tree_from_cache,
7465
entry_key
7566
)
7667

68+
fromgitdb.baseimportIStream
69+
7770
__all__= ('IndexFile','CheckoutError' )
7871

7972

@@ -161,10 +154,15 @@ def _deserialize(self, stream):
161154
self.version,self.entries,self._extension_data,conten_sha=read_cache(stream)
162155
returnself
163156

164-
def_serialize(self,stream,ignore_tree_extension_data=False):
157+
def_entries_sorted(self):
158+
""":return: list of entries, in a sorted fashion, first by path, then by stage"""
165159
entries_sorted=self.entries.values()
166-
entries_sorted.sort(key=lambdae: (e[3],e.stage))# use path/stage as sort key
167-
write_cache(entries_sorted,
160+
entries_sorted.sort(key=lambdae: (e.path,e.stage))# use path/stage as sort key
161+
returnentries_sorted
162+
163+
def_serialize(self,stream,ignore_tree_extension_data=False):
164+
entries=self._entries_sorted()
165+
write_cache(entries,
168166
stream,
169167
(ignore_tree_extension_dataandNone)orself._extension_data)
170168
returnself
@@ -403,7 +401,7 @@ def iter_blobs(self, predicate = lambda t: True):
403401
# TODO: is it necessary to convert the mode ? We did that when adding
404402
# it to the index, right ?
405403
mode=self._stat_mode_to_index_mode(entry.mode)
406-
blob=Blob(self.repo,entry.sha,mode,entry.path)
404+
blob=Blob(self.repo,entry.hexsha,mode,entry.path)
407405
blob.size=entry.size
408406
output= (entry.stage,blob)
409407
ifpredicate(output):
@@ -490,33 +488,31 @@ def update(self):
490488
# allows to lazily reread on demand
491489
returnself
492490

493-
def_write_tree(self,missing_ok=False):
491+
defwrite_tree(self):
494492
"""Writes this index to a corresponding Tree object into the repository's
495493
object database and return it.
496-
497-
:param missing_ok:
498-
If True, missing objects referenced by this index will not result
499-
in an error.
500-
501-
:return: Tree object representing this index"""
494+
495+
:return: Tree object representing this index
496+
:note: The tree will be written even if one or more objects the tree refers to
497+
does not yet exist in the object database. This could happen if you added
498+
Entries to the index directly.
499+
:raise ValueError: if there are no entries in the cache
500+
:raise UnmergedEntriesError: """
502501
# we obtain no lock as we just flush our contents to disk as tree
503502
ifnotself.entries:
504503
raiseValueError("Cannot write empty index")
505504

505+
# TODO: use memory db, this helps to prevent IO if the resulting tree
506+
# already exists
507+
entries=self._entries_sorted()
508+
binsha,tree_items=write_tree_from_cache(entries,self.repo.odb,slice(0,len(entries)))
506509

510+
# note: additional deserialization could be saved if write_tree_from_cache
511+
# would return sorted tree entries
512+
root_tree=Tree(self.repo,b2a_hex(binsha),path='')
513+
root_tree._cache=tree_items
514+
returnroot_tree
507515

508-
returnTree(self.repo,tree_sha,0,'')
509-
510-
defwrite_tree(self,missing_ok=False):
511-
index_path=self._index_path()
512-
tmp_index_mover=TemporaryFileSwap(index_path)
513-
514-
self.write(index_path,ignore_tree_extension_data=True)
515-
tree_sha=self.repo.git.write_tree(missing_ok=missing_ok)
516-
517-
del(tmp_index_mover)# as soon as possible
518-
returnTree(self.repo,tree_sha,0,'')
519-
520516
def_process_diff_args(self,args):
521517
try:
522518
args.pop(args.index(self))
@@ -525,7 +521,6 @@ def _process_diff_args(self, args):
525521
# END remove self
526522
returnargs
527523

528-
529524
def_to_relative_path(self,path):
530525
""":return: Version of path relative to our git directory or raise ValueError
531526
if it is not within our git direcotory"""
@@ -599,7 +594,7 @@ def add(self, items, force=True, fprogress=lambda *args: None, path_rewriter=Non
599594
600595
- BaseIndexEntry or type
601596
Handling equals the one of Blob objects, but the stage may be
602-
explicitly set.
597+
explicitly set. Please note that Index Entries require binary sha's.
603598
604599
:param force:
605600
If True, otherwise ignored or excluded files will be
@@ -666,7 +661,7 @@ def store_path(filepath):
666661
fprogress(filepath,True,filepath)
667662

668663
returnBaseIndexEntry((self._stat_mode_to_index_mode(st.st_mode),
669-
istream.sha,0,filepath))
664+
istream.binsha,0,filepath))
670665
# END utility method
671666

672667

@@ -691,14 +686,14 @@ def store_path(filepath):
691686

692687
# HANLDE ENTRY OBJECT CREATION
693688
# create objects if required, otherwise go with the existing shas
694-
null_entries_indices= [ifori,einenumerate(entries)ife.sha==Object.NULL_HEX_SHA ]
689+
null_entries_indices= [ifori,einenumerate(entries)ife.binsha==Object.NULL_BIN_SHA ]
695690
ifnull_entries_indices:
696691
foreiinnull_entries_indices:
697692
null_entry=entries[ei]
698693
new_entry=store_path(null_entry.path)
699694

700695
# update null entry
701-
entries[ei]=BaseIndexEntry((null_entry.mode,new_entry.sha,null_entry.stage,null_entry.path))
696+
entries[ei]=BaseIndexEntry((null_entry.mode,new_entry.binsha,null_entry.stage,null_entry.path))
702697
# END for each entry index
703698
# END null_entry handling
704699

@@ -707,7 +702,7 @@ def store_path(filepath):
707702
# all object sha's
708703
ifpath_rewriter:
709704
fori,einenumerate(entries):
710-
entries[i]=BaseIndexEntry((e.mode,e.sha,e.stage,path_rewriter(e)))
705+
entries[i]=BaseIndexEntry((e.mode,e.binsha,e.stage,path_rewriter(e)))
711706
# END for each entry
712707
# END handle path rewriting
713708

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2026 Movatter.jp