◐ Shell
reader mode source ↗
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
File filter
Conversations
Jump to
Diff view
Apply and reload
Show whitespace
Diff view
Apply and reload
15 changes: 9 additions & 6 deletions git/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@
:attr:`sys.platform` checks explicitly, especially in cases where it matters which is
used.

:note: ``is_win`` is ``False`` on Cygwin, but is often wrongly assumed ``True``. To
detect Cygwin, use ``sys.platform == "cygwin"``.
"""

is_posix = os.name == "posix"
Expand All @@ -46,9 +47,10 @@
:attr:`sys.platform` checks explicitly, especially in cases where it matters which is
used.

:note: For POSIX systems, more detailed information is available in
:attr:`sys.platform`, while :attr:`os.name` is always ``"posix"`` on such systems,
including macOS (Darwin).
"""

is_darwin = sys.platform == "darwin"
Expand All @@ -57,7 +59,8 @@
This is deprecated because it clearer to write out :attr:`os.name` or
:attr:`sys.platform` checks explicitly.

:note: For macOS (Darwin), ``os.name == "posix"`` as in other Unix-like systems, while
``sys.platform == "darwin"`.
"""

Expand Down
182 changes: 111 additions & 71 deletions git/config.py
16 changes: 8 additions & 8 deletions git/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ class GitCmdObjectDB(LooseObjectDB):
objects, pack files and an alternates file.

It will create objects only in the loose object database.

:note: For now, we use the git command to do all the lookup, just until we
have packs and the other implementations.
"""

def __init__(self, root_path: PathLike, git: "Git") -> None:
Expand All @@ -53,13 +50,16 @@ def stream(self, binsha: bytes) -> OStream:

def partial_to_complete_sha_hex(self, partial_hexsha: str) -> bytes:
"""
:return: Full binary 20 byte sha from the given partial hexsha

:raise AmbiguousObjectName:
:raise BadObject:

:note: Currently we only raise :class:`BadObject` as git does not communicate
AmbiguousObjects separately.
"""
try:
hexsha, _typename, _size = self._git.get_object_header(partial_hexsha)
Expand Down
98 changes: 58 additions & 40 deletions git/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ class Diffable:
compatible type.

:note:
Subclasses require a repo member as it is the case for Object instances, for
practical reasons we do not derive from Object.
"""

__slots__ = ()
Expand All @@ -111,37 +112,38 @@ def diff(
create_patch: bool = False,
**kwargs: Any,
) -> "DiffIndex":
"""Create diffs between two items being trees, trees and index or an
index and the working tree. Detects renames automatically.

:param other:
This the item to compare us with.

* If None, we will be compared to the working tree.
* If :class:`~git.index.base.Treeish`, it will be compared against the
respective tree.
* If :class:`~Diffable.Index`, it will be compared against the index.
* If :attr:`git.NULL_TREE`, it will compare against the empty tree.
* It defaults to :class:`~Diffable.Index` so that the method will not by
default fail on bare repositories.

:param paths:
This a list of paths or a single path to limit the diff to. It will only
include at least one of the given path or paths.

:param create_patch:
If True, the returned :class:`Diff` contains a detailed patch that if
applied makes the self to other. Patches are somewhat costly as blobs have
to be read and diffed.

:param kwargs:
Additional arguments passed to git-diff, such as ``R=True`` to swap both
sides of the diff.

:return: git.DiffIndex

:note:
On a bare repository, 'other' needs to be provided as
:class:`~Diffable.Index`, or as :class:`~git.objects.tree.Tree` or
:class:`~git.objects.commit.Commit`, or a git command error will occur.
"""
Expand Down Expand Up @@ -183,7 +185,7 @@ def diff(

args.insert(0, self)

# paths is list here, or None.
if paths:
args.append("--")
args.extend(paths)
@@ -203,7 +205,7 @@ def diff(


class DiffIndex(List[T_Diff]):
"""An Index for diffs, allowing a list of Diffs to be queried by the diff
properties.

The class improves the diff handling convenience.
Expand Up @@ -255,34 +257,34 @@ def iter_change_type(self, change_type: Lit_change_type) -> Iterator[T_Diff]:
class Diff:
"""A Diff contains diff information between two Trees.

It contains two sides a and b of the diff, members are prefixed with
"a" and "b" respectively to indicate that.

Diffs keep information about the changed blob objects, the file mode, renames,
deletions and new files.

There are a few cases where None has to be expected as member variable value:

``New File``::

a_mode is None
a_blob is None
a_path is None

``Deleted File``::

b_mode is None
b_blob is None
b_path is None

``Working Tree Blobs``

When comparing to working trees, the working tree blob will have a null hexsha
as a corresponding object does not yet exist. The mode will be null as well.
The path will be available, though.

If it is listed in a diff, the working tree version of the file must
differ from the version in the index or tree, and hence has been modified.
"""

# Precompiled regex.
Expand Down Expand Up @@ -466,17 +468,20 @@ def rename_to(self) -> Optional[str]:

@property
def renamed(self) -> bool:
"""
:return: True if the blob of our diff has been renamed

:note: This property is deprecated.
Please use the :attr:`renamed_file` property instead.
"""
return self.renamed_file

@property
def renamed_file(self) -> bool:
""":return: True if the blob of our diff has been renamed"""
return self.rename_from != self.rename_to

@classmethod
Expand All @@ -494,11 +499,18 @@ def _pick_best_path(cls, path_match: bytes, rename_match: bytes, path_fallback_m

@classmethod
def _index_from_patch_format(cls, repo: "Repo", proc: Union["Popen", "Git.AutoInterrupt"]) -> DiffIndex:
"""Create a new DiffIndex from the given process output which must be in patch format.

:param repo: The repository we are operating on
:param proc: ``git diff`` process to read from (supports :class:`Git.AutoInterrupt` wrapper)
:return: git.DiffIndex
"""

# FIXME: Here SLURPING raw, need to re-phrase header-regexes linewise.
Expand Down @@ -539,14 +551,14 @@ def _index_from_patch_format(cls, repo: "Repo", proc: Union["Popen", "Git.AutoIn
a_path = cls._pick_best_path(a_path, rename_from, a_path_fallback)
b_path = cls._pick_best_path(b_path, rename_to, b_path_fallback)

# Our only means to find the actual text is to see what has not been matched by our regex,
# and then retro-actively assign it to our index.
if previous_header is not None:
index[-1].diff = text[previous_header.end() : _header.start()]
# END assign actual diff

# Make sure the mode is set if the path is set. Otherwise the resulting blob is invalid.
# We just use the one mode we should have parsed.
a_mode = old_mode or deleted_file_mode or (a_path and (b_mode or new_mode or new_file_mode))
b_mode = b_mode or new_mode or new_file_mode or (b_path and a_mode)
index.append(
Expand Down Expand Up @@ -610,7 +622,7 @@ def _handle_diff_line(lines_bytes: bytes, repo: "Repo", index: DiffIndex) -> Non
rename_from = None
rename_to = None

# NOTE: We cannot conclude from the existence of a blob to change type
# as diffs with the working do not have blobs yet.
if change_type == "D":
b_blob_id = None # Optional[str]
Expand Up @@ -654,11 +666,17 @@ def _handle_diff_line(lines_bytes: bytes, repo: "Repo", index: DiffIndex) -> Non

@classmethod
def _index_from_raw_format(cls, repo: "Repo", proc: "Popen") -> "DiffIndex":
"""Create a new DiffIndex from the given process output which must be in raw format.

:param repo: The repository we are operating on
:param proc: Process to read output from
:return: git.DiffIndex
"""
# handles
# :100644 100644 687099101... 37c5e30c8... M .gitignore
Expand Down
18 changes: 11 additions & 7 deletions git/exc.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,20 @@ class UnsafeOptionError(GitError):


class CommandError(GitError):
"""Base class for exceptions thrown at every stage of `Popen()` execution.

:param command:
A non-empty list of argv comprising the command-line.
"""

#: A unicode print-format with 2 `%s for `<cmdline>` and the rest,
#: e.g.
#: "'%s' failed%s"
_msg = "Cmd('%s') failed%s"

def __init__(
self,
Expand Down Expand Up @@ -132,8 +136,8 @@ def __str__(self) -> str:


class GitCommandNotFound(CommandError):
"""Thrown if we cannot find the `git` executable in the PATH or at the path given by
the GIT_PYTHON_GIT_EXECUTABLE environment variable."""

def __init__(self, command: Union[List[str], Tuple[str], str], cause: Union[str, Exception]) -> None:
super().__init__(command, cause)
Expand Down Expand Up @@ -184,7 +188,7 @@ def __str__(self) -> str:


class CacheError(GitError):
"""Base for all errors related to the git index, which is called cache
internally."""


Expand Down
Loading
Toggle all file notes Toggle all file annotations