summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominic <yobmod@gmail.com>2021-07-31 13:50:39 +0100
committerGitHub <noreply@github.com>2021-07-31 13:50:39 +0100
commita5a05d153ecdbd9b9bdb285a77f5b14d9c0344b0 (patch)
treef413a9c1c975c8a1aaa1a8d4f5408ba6a77c3575
parent03190098bdf0f4c0cbb90e39f464c3dd67b0ee1d (diff)
downloadgitpython-a5a05d153ecdbd9b9bdb285a77f5b14d9c0344b0.tar.gz
rvrt symbolic.py types
-rw-r--r--git/refs/symbolic.py172
1 files changed, 74 insertions, 98 deletions
diff --git a/git/refs/symbolic.py b/git/refs/symbolic.py
index 4171fe23..0e9dad5c 100644
--- a/git/refs/symbolic.py
+++ b/git/refs/symbolic.py
@@ -1,3 +1,4 @@
+from git.types import PathLike
import os
from git.compat import defenc
@@ -16,18 +17,17 @@ from gitdb.exc import (
BadName
)
-from .log import RefLog, RefLogEntry
+import os.path as osp
+
+from .log import RefLog
# typing ------------------------------------------------------------------
-from typing import Any, Iterator, List, Match, Optional, Tuple, Type, TypeVar, Union, TYPE_CHECKING, cast # NOQA
+from typing import Any, Iterator, List, Match, Optional, Tuple, Type, TypeVar, Union, TYPE_CHECKING # NOQA
from git.types import Commit_ish, PathLike, TBD, Literal # NOQA
if TYPE_CHECKING:
from git.repo import Repo
- from git.refs import Reference, Head, TagReference, RemoteReference
- from git.config import GitConfigParser
- from git.objects.commit import Actor
T_References = TypeVar('T_References', bound='SymbolicReference')
@@ -37,9 +37,9 @@ T_References = TypeVar('T_References', bound='SymbolicReference')
__all__ = ["SymbolicReference"]
-def _git_dir(repo: 'Repo', path: PathLike) -> PathLike:
+def _git_dir(repo, path):
""" Find the git dir that's appropriate for the path"""
- name = f"{path}"
+ name = "%s" % (path,)
if name in ['HEAD', 'ORIG_HEAD', 'FETCH_HEAD', 'index', 'logs']:
return repo.git_dir
return repo.common_dir
@@ -59,47 +59,46 @@ class SymbolicReference(object):
_remote_common_path_default = "refs/remotes"
_id_attribute_ = "name"
- def __init__(self, repo: 'Repo', path: PathLike, check_path: bool = False) -> None:
+ def __init__(self, repo: 'Repo', path: PathLike, check_path: bool = False):
self.repo = repo
self.path = str(path)
- self.ref = self._get_reference()
def __str__(self) -> str:
return self.path
- def __repr__(self) -> str:
+ def __repr__(self):
return '<git.%s "%s">' % (self.__class__.__name__, self.path)
- def __eq__(self, other) -> bool:
+ def __eq__(self, other):
if hasattr(other, 'path'):
return self.path == other.path
return False
- def __ne__(self, other) -> bool:
+ def __ne__(self, other):
return not (self == other)
def __hash__(self):
return hash(self.path)
@property
- def name(self) -> str:
+ def name(self):
"""
:return:
In case of symbolic references, the shortest assumable name
is the path itself."""
- return str(self.path)
+ return self.path
@property
- def abspath(self) -> PathLike:
+ def abspath(self):
return join_path_native(_git_dir(self.repo, self.path), self.path)
@classmethod
- def _get_packed_refs_path(cls, repo: 'Repo') -> str:
- return os.path.join(repo.common_dir, 'packed-refs')
+ def _get_packed_refs_path(cls, repo):
+ return osp.join(repo.common_dir, 'packed-refs')
@classmethod
- def _iter_packed_refs(cls, repo: 'Repo') -> Iterator[Tuple[str, str]]:
- """Returns an iterator yielding pairs of sha1/path pairs for the corresponding refs.
+ def _iter_packed_refs(cls, repo):
+ """Returns an iterator yielding pairs of sha1/path pairs (as bytes) for the corresponding refs.
:note: The packed refs file will be kept open as long as we iterate"""
try:
with open(cls._get_packed_refs_path(repo), 'rt', encoding='UTF-8') as fp:
@@ -127,7 +126,7 @@ class SymbolicReference(object):
if line[0] == '^':
continue
- yield cast(Tuple[str, str], tuple(line.split(' ', 1)))
+ yield tuple(line.split(' ', 1))
# END for each line
except OSError:
return None
@@ -138,26 +137,26 @@ class SymbolicReference(object):
# alright.
@classmethod
- def dereference_recursive(cls, repo: 'Repo', ref_path: PathLike) -> str:
+ def dereference_recursive(cls, repo, ref_path):
"""
:return: hexsha stored in the reference at the given ref_path, recursively dereferencing all
intermediate references as required
:param repo: the repository containing the reference at ref_path"""
while True:
- hexsha, _ref_path_out = cls._get_ref_info(repo, ref_path)
+ hexsha, ref_path = cls._get_ref_info(repo, ref_path)
if hexsha is not None:
return hexsha
# END recursive dereferencing
@classmethod
- def _get_ref_info_helper(cls, repo: 'Repo', ref_path: PathLike) -> Union[Tuple[str, None], Tuple[None, PathLike]]:
+ def _get_ref_info_helper(cls, repo, ref_path):
"""Return: (str(sha), str(target_ref_path)) if available, the sha the file at
rela_path points to, or None. target_ref_path is the reference we
point to, or None"""
- tokens: Union[List[str], Tuple[str, str], None] = None
+ tokens = None
repodir = _git_dir(repo, ref_path)
try:
- with open(os.path.join(repodir, ref_path), 'rt', encoding='UTF-8') as fp:
+ with open(osp.join(repodir, ref_path), 'rt', encoding='UTF-8') as fp:
value = fp.read().rstrip()
# Don't only split on spaces, but on whitespace, which allows to parse lines like
# 60b64ef992065e2600bfef6187a97f92398a9144 branch 'master' of git-server:/path/to/repo
@@ -189,14 +188,13 @@ class SymbolicReference(object):
raise ValueError("Failed to parse reference information from %r" % ref_path)
@classmethod
- def _get_ref_info(cls, repo: 'Repo', ref_path: PathLike
- ) -> Union[Tuple[str, None], Tuple[None, PathLike]]:
+ def _get_ref_info(cls, repo, ref_path):
"""Return: (str(sha), str(target_ref_path)) if available, the sha the file at
rela_path points to, or None. target_ref_path is the reference we
point to, or None"""
return cls._get_ref_info_helper(repo, ref_path)
- def _get_object(self) -> Commit_ish:
+ def _get_object(self):
"""
:return:
The object our ref currently refers to. Refs can be cached, they will
@@ -205,7 +203,7 @@ class SymbolicReference(object):
# Our path will be resolved to the hexsha which will be used accordingly
return Object.new_from_sha(self.repo, hex_to_bin(self.dereference_recursive(self.repo, self.path)))
- def _get_commit(self) -> 'Commit':
+ def _get_commit(self):
"""
:return:
Commit object we point to, works for detached and non-detached
@@ -220,8 +218,7 @@ class SymbolicReference(object):
# END handle type
return obj
- def set_commit(self, commit: Union[Commit, 'SymbolicReference', str],
- logmsg: Union[str, None] = None) -> None:
+ def set_commit(self, commit: Union[Commit, 'SymbolicReference', str], logmsg=None):
"""As set_object, but restricts the type of object to be a Commit
:raise ValueError: If commit is not a Commit object or doesn't point to
@@ -231,13 +228,11 @@ class SymbolicReference(object):
invalid_type = False
if isinstance(commit, Object):
invalid_type = commit.type != Commit.type
- commit = cast('Commit', commit)
elif isinstance(commit, SymbolicReference):
invalid_type = commit.object.type != Commit.type
else:
try:
- commit = self.repo.rev_parse(commit)
- invalid_type = commit.type != Commit.type
+ invalid_type = self.repo.rev_parse(commit).type != Commit.type
except (BadObject, BadName) as e:
raise ValueError("Invalid object: %s" % commit) from e
# END handle exception
@@ -250,12 +245,9 @@ class SymbolicReference(object):
# we leave strings to the rev-parse method below
self.set_object(commit, logmsg)
- # return self
- return None
+ return self
- def set_object(self, object: Union[Commit_ish, 'SymbolicReference'],
- logmsg: Union[str, None] = None
- ) -> 'SymbolicReference': # @ReservedAssignment
+ def set_object(self, object, logmsg=None): # @ReservedAssignment
"""Set the object we point to, possibly dereference our symbolic reference first.
If the reference does not exist, it will be created
@@ -282,11 +274,10 @@ class SymbolicReference(object):
# set the commit on our reference
return self._get_reference().set_object(object, logmsg)
- commit = cast('Commit', property(_get_commit, set_commit, doc="Query or set commits directly"))
- object = property(_get_object, set_object, doc="Return the object our ref currently refers to") # type: ignore
+ commit = property(_get_commit, set_commit, doc="Query or set commits directly")
+ object = property(_get_object, set_object, doc="Return the object our ref currently refers to")
- def _get_reference(self
- ) -> Union['Head', 'RemoteReference', 'TagReference', 'Reference']:
+ def _get_reference(self):
""":return: Reference Object we point to
:raise TypeError: If this symbolic reference is detached, hence it doesn't point
to a reference, but to a commit"""
@@ -295,8 +286,7 @@ class SymbolicReference(object):
raise TypeError("%s is a detached symbolic reference as it points to %r" % (self, sha))
return self.from_path(self.repo, target_ref_path)
- def set_reference(self, ref: Union[str, Commit_ish, 'SymbolicReference'], logmsg: Union[str, None] = None
- ) -> 'SymbolicReference':
+ def set_reference(self, ref, logmsg=None):
"""Set ourselves to the given ref. It will stay a symbol if the ref is a Reference.
Otherwise an Object, given as Object instance or refspec, is assumed and if valid,
will be set which effectively detaches the refererence if it was a purely
@@ -337,7 +327,7 @@ class SymbolicReference(object):
raise TypeError("Require commit, got %r" % obj)
# END verify type
- oldbinsha: bytes = b''
+ oldbinsha = None
if logmsg is not None:
try:
oldbinsha = self.commit.binsha
@@ -365,16 +355,11 @@ class SymbolicReference(object):
return self
- @ property
- def reference(self) -> Union['Head', 'RemoteReference', 'TagReference', 'Reference']:
- return self._get_reference()
+ # aliased reference
+ reference = property(_get_reference, set_reference, doc="Returns the Reference we point to")
+ ref: Union[Commit_ish] = reference # type: ignore # Union[str, Commit_ish, SymbolicReference]
- @ reference.setter
- def reference(self, ref: Union[str, Commit_ish, 'SymbolicReference'], logmsg: Union[str, None] = None
- ) -> 'SymbolicReference':
- return self.set_reference(ref=ref, logmsg=logmsg)
-
- def is_valid(self) -> bool:
+ def is_valid(self):
"""
:return:
True if the reference is valid, hence it can be read and points to
@@ -386,7 +371,7 @@ class SymbolicReference(object):
else:
return True
- @ property
+ @property
def is_detached(self):
"""
:return:
@@ -398,7 +383,7 @@ class SymbolicReference(object):
except TypeError:
return True
- def log(self) -> 'RefLog':
+ def log(self):
"""
:return: RefLog for this reference. Its last entry reflects the latest change
applied to this reference
@@ -407,8 +392,7 @@ class SymbolicReference(object):
instead of calling this method repeatedly. It should be considered read-only."""
return RefLog.from_file(RefLog.path(self))
- def log_append(self, oldbinsha: bytes, message: Union[str, None],
- newbinsha: Union[bytes, None] = None) -> 'RefLogEntry':
+ def log_append(self, oldbinsha, message, newbinsha=None):
"""Append a logentry to the logfile of this ref
:param oldbinsha: binary sha this ref used to point to
@@ -420,19 +404,15 @@ class SymbolicReference(object):
# correct to allow overriding the committer on a per-commit level.
# See https://github.com/gitpython-developers/GitPython/pull/146
try:
- committer_or_reader: Union['Actor', 'GitConfigParser'] = self.commit.committer
+ committer_or_reader = self.commit.committer
except ValueError:
committer_or_reader = self.repo.config_reader()
# end handle newly cloned repositories
- if newbinsha is None:
- newbinsha = self.commit.binsha
-
- if message is None:
- message = ''
+ return RefLog.append_entry(committer_or_reader, RefLog.path(self), oldbinsha,
+ (newbinsha is None and self.commit.binsha) or newbinsha,
+ message)
- return RefLog.append_entry(committer_or_reader, RefLog.path(self), oldbinsha, newbinsha, message)
-
- def log_entry(self, index: int) -> RefLogEntry:
+ def log_entry(self, index):
""":return: RefLogEntry at the given index
:param index: python list compatible positive or negative index
@@ -441,23 +421,22 @@ class SymbolicReference(object):
In that case, it will be faster than the ``log()`` method"""
return RefLog.entry_at(RefLog.path(self), index)
- @ classmethod
- def to_full_path(cls, path: Union[PathLike, 'SymbolicReference']) -> str:
+ @classmethod
+ def to_full_path(cls, path) -> PathLike:
"""
:return: string with a full repository-relative path which can be used to initialize
a Reference instance, for instance by using ``Reference.from_path``"""
if isinstance(path, SymbolicReference):
path = path.path
- full_ref_path = str(path)
+ full_ref_path = path
if not cls._common_path_default:
return full_ref_path
-
- if not str(path).startswith(cls._common_path_default + "/"):
+ if not path.startswith(cls._common_path_default + "/"):
full_ref_path = '%s/%s' % (cls._common_path_default, path)
return full_ref_path
- @ classmethod
- def delete(cls, repo: 'Repo', path: PathLike) -> None:
+ @classmethod
+ def delete(cls, repo, path):
"""Delete the reference at the given path
:param repo:
@@ -468,8 +447,8 @@ class SymbolicReference(object):
or just "myreference", hence 'refs/' is implied.
Alternatively the symbolic reference to be deleted"""
full_ref_path = cls.to_full_path(path)
- abs_path = os.path.join(repo.common_dir, full_ref_path)
- if os.path.exists(abs_path):
+ abs_path = osp.join(repo.common_dir, full_ref_path)
+ if osp.exists(abs_path):
os.remove(abs_path)
else:
# check packed refs
@@ -479,8 +458,8 @@ class SymbolicReference(object):
new_lines = []
made_change = False
dropped_last_line = False
- for line_bytes in reader:
- line = line_bytes.decode(defenc)
+ for line in reader:
+ line = line.decode(defenc)
_, _, line_ref = line.partition(' ')
line_ref = line_ref.strip()
# keep line if it is a comment or if the ref to delete is not
@@ -510,14 +489,12 @@ class SymbolicReference(object):
# delete the reflog
reflog_path = RefLog.path(cls(repo, full_ref_path))
- if os.path.isfile(reflog_path):
+ if osp.isfile(reflog_path):
os.remove(reflog_path)
# END remove reflog
- @ classmethod
- def _create(cls: Type[T_References], repo: 'Repo', path: PathLike, resolve: bool,
- reference: Union[str, 'SymbolicReference'],
- force: bool, logmsg: Union[str, None] = None) -> T_References:
+ @classmethod
+ def _create(cls, repo, path, resolve, reference, force, logmsg=None):
"""internal method used to create a new symbolic reference.
If resolve is False, the reference will be taken as is, creating
a proper symbolic reference. Otherwise it will be resolved to the
@@ -525,14 +502,14 @@ class SymbolicReference(object):
instead"""
git_dir = _git_dir(repo, path)
full_ref_path = cls.to_full_path(path)
- abs_ref_path = os.path.join(git_dir, full_ref_path)
+ abs_ref_path = osp.join(git_dir, full_ref_path)
# figure out target data
target = reference
if resolve:
target = repo.rev_parse(str(reference))
- if not force and os.path.isfile(abs_ref_path):
+ if not force and osp.isfile(abs_ref_path):
target_data = str(target)
if isinstance(target, SymbolicReference):
target_data = target.path
@@ -550,9 +527,8 @@ class SymbolicReference(object):
return ref
@classmethod
- def create(cls: Type[T_References], repo: 'Repo', path: PathLike,
- reference: Union[str, 'SymbolicReference'] = 'SymbolicReference',
- logmsg: Union[str, None] = None, force: bool = False, **kwargs: Any) -> T_References:
+ def create(cls, repo: 'Repo', path: PathLike, reference: Union[Commit_ish, str] = 'HEAD',
+ logmsg: Union[str, None] = None, force: bool = False, **kwargs: Any):
"""Create a new symbolic reference, hence a reference pointing , to another reference.
:param repo:
@@ -564,7 +540,7 @@ class SymbolicReference(object):
:param reference:
The reference to which the new symbolic reference should point to.
- If it is a ref to a commit'ish, the symbolic ref will be detached.
+ If it is a commit'ish, the symbolic ref will be detached.
:param force:
if True, force creation even if a symbolic reference with that name already exists.
@@ -583,7 +559,7 @@ class SymbolicReference(object):
:note: This does not alter the current HEAD, index or Working Tree"""
return cls._create(repo, path, cls._resolve_ref_on_create, reference, force, logmsg)
- def rename(self, new_path: str, force: bool = False) -> 'SymbolicReference':
+ def rename(self, new_path, force=False):
"""Rename self to a new path
:param new_path:
@@ -601,9 +577,9 @@ class SymbolicReference(object):
if self.path == new_path:
return self
- new_abs_path = os.path.join(_git_dir(self.repo, new_path), new_path)
- cur_abs_path = os.path.join(_git_dir(self.repo, self.path), self.path)
- if os.path.isfile(new_abs_path):
+ new_abs_path = osp.join(_git_dir(self.repo, new_path), new_path)
+ cur_abs_path = osp.join(_git_dir(self.repo, self.path), self.path)
+ if osp.isfile(new_abs_path):
if not force:
# if they point to the same file, its not an error
with open(new_abs_path, 'rb') as fd1:
@@ -618,8 +594,8 @@ class SymbolicReference(object):
os.remove(new_abs_path)
# END handle existing target file
- dname = os.path.dirname(new_abs_path)
- if not os.path.isdir(dname):
+ dname = osp.dirname(new_abs_path)
+ if not osp.isdir(dname):
os.makedirs(dname)
# END create directory
@@ -654,7 +630,7 @@ class SymbolicReference(object):
# read packed refs
for _sha, rela_path in cls._iter_packed_refs(repo):
- if rela_path.startswith(str(common_path)):
+ if rela_path.startswith(common_path):
rela_paths.add(rela_path)
# END relative path matches common path
# END packed refs reading
@@ -689,7 +665,7 @@ class SymbolicReference(object):
return (r for r in cls._iter_items(repo, common_path) if r.__class__ == SymbolicReference or not r.is_detached)
@classmethod
- def from_path(cls, repo: 'Repo', path: PathLike) -> Union['Head', 'RemoteReference', 'TagReference', 'Reference']:
+ def from_path(cls, repo, path):
"""
:param path: full .git-directory-relative path name to the Reference to instantiate
:note: use to_full_path() if you only have a partial path of a known Reference Type