| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 1044116 commit 69dd875
13 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,6 +5,13 @@ CHANGES | |||
| 5 | 5 | === | |
| 6 | 6 | * ConcurrentWriteOperation was removed, and replaced by LockedFD | |
| 7 | 7 | * 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 | + | ||
| 8 | 15 | ||
| 9 | 16 | 0.2 Beta 2 | |
| 10 | 17 | =========== | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -28,7 +28,7 @@ def _init_externals(): | |||
| 28 | 28 | from git.objects import * | |
| 29 | 29 | from git.refs import * | |
| 30 | 30 | from git.diff import * | |
| 31 | - from git.errors import InvalidGitRepositoryError, NoSuchPathError, GitCommandError | ||
| 31 | + from git.errors import * | ||
| 32 | 32 | from git.cmd import Git | |
| 33 | 33 | from git.repo import Repo | |
| 34 | 34 | from git.remote import * | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,9 +4,12 @@ | |||
| 4 | 4 | OStream | |
| 5 | 5 | ) | |
| 6 | 6 | ||
| 7 | + from gitdb.util import to_hex_sha | ||
| 8 | + | ||
| 7 | 9 | from gitdb.db import GitDB | |
| 8 | 10 | from gitdb.db import LooseObjectDB | |
| 9 | 11 | ||
| 12 | + | ||
| 10 | 13 | __all__ = ('GitCmdObjectDB', 'GitDB' ) | |
| 11 | 14 | ||
| 12 | 15 | #class GitCmdObjectDB(CompoundDB, ObjectDBW): | |
@@ -24,11 +27,11 @@ def __init__(self, root_path, git): | |||
| 24 | 27 | self._git = git | |
| 25 | 28 | ||
| 26 | 29 | def info(self, sha): | |
| 27 | - t = self._git.get_object_header(sha) | ||
| 30 | + t = self._git.get_object_header(to_hex_sha(sha)) | ||
| 28 | 31 | return OInfo(*t) | |
| 29 | 32 | ||
| 30 | 33 | def stream(self, sha): | |
| 31 | 34 | """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)) | ||
| 33 | 36 | return OStream(*t) | |
| 34 | 37 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -196,7 +196,7 @@ class Diff(object): | |||
| 196 | 196 | \.\.(?P<b_blob_id>[0-9A-Fa-f]+)[ ]?(?P<b_mode>.+)?(?:\n|$))? | |
| 197 | 197 | """, re.VERBOSE | re.MULTILINE) | |
| 198 | 198 | # can be used for comparisons | |
| 199 | - null_hex_sha = "0"*40 | ||
| 199 | + NULL_HEX_SHA = "0"*40 | ||
| 200 | 200 | ||
| 201 | 201 | __slots__ = ("a_blob", "b_blob", "a_mode", "b_mode", "new_file", "deleted_file", | |
| 202 | 202 | "rename_from", "rename_to", "diff") | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,43 +6,51 @@ | |||
| 6 | 6 | """ Module containing all exceptions thrown througout the git package, """ | |
| 7 | 7 | ||
| 8 | 8 | class InvalidGitRepositoryError(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. """ | ||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | class NoSuchPathError(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. """ | ||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | 16 | class GitCommandError(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) for i in self.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) for i in self.command), self.status, self.stderr)) | ||
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | 28 | class CheckoutError( 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 | - return Exception.__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 | + return Exception.__str__(self) + ":%s" % self.failed_files | ||
| 49 | + | ||
| 50 | + | ||
| 51 | + class CacheError(Exception): | ||
| 52 | + """Base for all errors related to the git index, which is called cache internally""" | ||
| 53 | + | ||
| 54 | + class UnmergedEntriesError(CacheError): | ||
| 55 | + """Thrown if an operation cannot proceed as there are still unmerged | ||
| 56 | + entries in the cache""" | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,13 +5,13 @@ | |||
| 5 | 5 | # the BSD License: http://www.opensource.org/licenses/bsd-license.php | |
| 6 | 6 | """Module containing Index implementation, allowing to perform all kinds of index | |
| 7 | 7 | manipulations such as querying and merging. """ | |
| 8 | - import binascii | ||
| 9 | 8 | import tempfile | |
| 10 | 9 | import os | |
| 11 | 10 | import sys | |
| 12 | 11 | import subprocess | |
| 13 | 12 | import glob | |
| 14 | 13 | from cStringIO import StringIO | |
| 14 | + from binascii import b2a_hex | ||
| 15 | 15 | ||
| 16 | 16 | from stat import ( | |
| 17 | 17 | S_ISLNK, | |
@@ -25,16 +25,12 @@ | |||
| 25 | 25 | from typ import ( | |
| 26 | 26 | BaseIndexEntry, | |
| 27 | 27 | IndexEntry, | |
| 28 | - CE_NAMEMASK, | ||
| 29 | - CE_STAGESHIFT | ||
| 30 | 28 | ) | |
| 31 | 29 | ||
| 32 | 30 | from util import ( | |
| 33 | 31 | TemporaryFileSwap, | |
| 34 | 32 | post_clear_cache, | |
| 35 | 33 | default_index, | |
| 36 | - pack, | ||
| 37 | - unpack | ||
| 38 | 34 | ) | |
| 39 | 35 | ||
| 40 | 36 | import git.objects | |
@@ -60,20 +56,17 @@ | |||
| 60 | 56 | LockedFD, | |
| 61 | 57 | join_path_native, | |
| 62 | 58 | file_contents_ro, | |
| 63 | - LockFile | ||
| 64 | - ) | ||
| 65 | - | ||
| 66 | - | ||
| 67 | - from gitdb.base import ( | ||
| 68 | - IStream | ||
| 69 | 59 | ) | |
| 70 | 60 | ||
| 71 | 61 | from fun import ( | |
| 72 | 62 | write_cache, | |
| 73 | 63 | read_cache, | |
| 64 | + write_tree_from_cache, | ||
| 74 | 65 | entry_key | |
| 75 | 66 | ) | |
| 76 | 67 | ||
| 68 | + from gitdb.base import IStream | ||
| 69 | + | ||
| 77 | 70 | __all__ = ( 'IndexFile', 'CheckoutError' ) | |
| 78 | 71 | ||
| 79 | 72 | ||
@@ -161,10 +154,15 @@ def _deserialize(self, stream): | |||
| 161 | 154 | self.version, self.entries, self._extension_data, conten_sha = read_cache(stream) | |
| 162 | 155 | return self | |
| 163 | 156 | ||
| 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""" | ||
| 165 | 159 | entries_sorted = self.entries.values() | |
| 166 | - entries_sorted.sort(key=lambda e: (e[3], e.stage)) # use path/stage as sort key | ||
| 167 | - write_cache(entries_sorted, | ||
| 160 | + entries_sorted.sort(key=lambda e: (e.path, e.stage)) # use path/stage as sort key | ||
| 161 | + return entries_sorted | ||
| 162 | + | ||
| 163 | + def _serialize(self, stream, ignore_tree_extension_data=False): | ||
| 164 | + entries = self._entries_sorted() | ||
| 165 | + write_cache(entries, | ||
| 168 | 166 | stream, | |
| 169 | 167 | (ignore_tree_extension_data and None) or self._extension_data) | |
| 170 | 168 | return self | |
@@ -403,7 +401,7 @@ def iter_blobs(self, predicate = lambda t: True): | |||
| 403 | 401 | # TODO: is it necessary to convert the mode ? We did that when adding | |
| 404 | 402 | # it to the index, right ? | |
| 405 | 403 | 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) | ||
| 407 | 405 | blob.size = entry.size | |
| 408 | 406 | output = (entry.stage, blob) | |
| 409 | 407 | if predicate(output): | |
@@ -490,33 +488,31 @@ def update(self): | |||
| 490 | 488 | # allows to lazily reread on demand | |
| 491 | 489 | return self | |
| 492 | 490 | ||
| 493 | - def _write_tree(self, missing_ok=False): | ||
| 491 | + def write_tree(self): | ||
| 494 | 492 | """Writes this index to a corresponding Tree object into the repository's | |
| 495 | 493 | 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: """ | ||
| 502 | 501 | # we obtain no lock as we just flush our contents to disk as tree | |
| 503 | 502 | if not self.entries: | |
| 504 | 503 | raise ValueError("Cannot write empty index") | |
| 505 | 504 | ||
| 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))) | ||
| 506 | 509 | ||
| 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 | + return root_tree | ||
| 507 | 515 | ||
| 508 | - return Tree(self.repo, tree_sha, 0, '') | ||
| 509 | - | ||
| 510 | - def write_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 | - return Tree(self.repo, tree_sha, 0, '') | ||
| 519 | - | ||
| 520 | 516 | def _process_diff_args(self, args): | |
| 521 | 517 | try: | |
| 522 | 518 | args.pop(args.index(self)) | |
@@ -525,7 +521,6 @@ def _process_diff_args(self, args): | |||
| 525 | 521 | # END remove self | |
| 526 | 522 | return args | |
| 527 | 523 | ||
| 528 | - | ||
| 529 | 524 | def _to_relative_path(self, path): | |
| 530 | 525 | """:return: Version of path relative to our git directory or raise ValueError | |
| 531 | 526 | 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 | |||
| 599 | 594 | ||
| 600 | 595 | - BaseIndexEntry or type | |
| 601 | 596 | 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. | ||
| 603 | 598 | ||
| 604 | 599 | :param force: | |
| 605 | 600 | If True, otherwise ignored or excluded files will be | |
@@ -666,7 +661,7 @@ def store_path(filepath): | |||
| 666 | 661 | fprogress(filepath, True, filepath) | |
| 667 | 662 | ||
| 668 | 663 | return BaseIndexEntry((self._stat_mode_to_index_mode(st.st_mode), | |
| 669 | - istream.sha, 0, filepath)) | ||
| 664 | + istream.binsha, 0, filepath)) | ||
| 670 | 665 | # END utility method | |
| 671 | 666 | ||
| 672 | 667 | ||
@@ -691,14 +686,14 @@ def store_path(filepath): | |||
| 691 | 686 | ||
| 692 | 687 | # HANLDE ENTRY OBJECT CREATION | |
| 693 | 688 | # create objects if required, otherwise go with the existing shas | |
| 694 | - null_entries_indices = [ i for i,e in enumerate(entries) if e.sha == Object.NULL_HEX_SHA ] | ||
| 689 | + null_entries_indices = [ i for i,e in enumerate(entries) if e.binsha == Object.NULL_BIN_SHA ] | ||
| 695 | 690 | if null_entries_indices: | |
| 696 | 691 | for ei in null_entries_indices: | |
| 697 | 692 | null_entry = entries[ei] | |
| 698 | 693 | new_entry = store_path(null_entry.path) | |
| 699 | 694 | ||
| 700 | 695 | # 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)) | ||
| 702 | 697 | # END for each entry index | |
| 703 | 698 | # END null_entry handling | |
| 704 | 699 | ||
@@ -707,7 +702,7 @@ def store_path(filepath): | |||
| 707 | 702 | # all object sha's | |
| 708 | 703 | if path_rewriter: | |
| 709 | 704 | for i,e in enumerate(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))) | ||
| 711 | 706 | # END for each entry | |
| 712 | 707 | # END handle path rewriting | |
| 713 | 708 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments