15 files changed
@@ -434,7 +434,7 @@ def raise_exc(e: Exception) -> NoReturn: | |||
| 434 | 434 | # characters. | |
| 435 | 435 | if abs_path not in resolved_paths: | |
| 436 | 436 | for f in self._iter_expand_paths(glob.glob(abs_path)): | |
| 437 | - yield os.fspath(f).replace(rs, "") | ||
| 437 | + yield str(f).replace(rs, "") | ||
| 438 | 438 | continue | |
| 439 | 439 | # END glob handling | |
| 440 | 440 | try: | |
@@ -569,7 +569,7 @@ def resolve_blobs(self, iter_blobs: Iterator[Blob]) -> "IndexFile": | |||
| 569 | 569 | for blob in iter_blobs: | |
| 570 | 570 | stage_null_key = (blob.path, 0) | |
| 571 | 571 | if stage_null_key in self.entries: | |
| 572 | - raise ValueError("Path %r already exists at stage 0" % os.fspath(blob.path)) | ||
| 572 | + raise ValueError("Path %r already exists at stage 0" % str(blob.path)) | ||
| 573 | 573 | # END assert blob is not stage 0 already | |
| 574 | 574 | ||
| 575 | 575 | # Delete all possible stages. | |
@@ -652,15 +652,14 @@ def _to_relative_path(self, path: PathLike) -> PathLike: | |||
| 652 | 652 | ||
| 653 | 653 | :raise ValueError: | |
| 654 | 654 | """ | |
| 655 | - path = os.fspath(path) | ||
| 656 | 655 | if not osp.isabs(path): | |
| 657 | 656 | return path | |
| 658 | 657 | if self.repo.bare: | |
| 659 | 658 | raise InvalidGitRepositoryError("require non-bare repository") | |
| 660 | 659 | if not osp.normpath(path).startswith(os.fspath(self.repo.working_tree_dir)): | |
| 661 | 660 | raise ValueError("Absolute path %r is not in git repository at %r" % (path, self.repo.working_tree_dir)) | |
| 662 | 661 | result = os.path.relpath(path, self.repo.working_tree_dir) | |
| 663 | - if path.endswith(os.sep) and not result.endswith(os.sep): | ||
| 662 | + if os.fspath(path).endswith(os.sep) and not result.endswith(os.sep): | ||
| 664 | 663 | result += os.sep | |
| 665 | 664 | return result | |
| 666 | 665 | ||
@@ -1364,7 +1363,7 @@ def make_exc() -> GitCommandError: | |||
| 1364 | 1363 | if not folder.endswith("/"): | |
| 1365 | 1364 | folder += "/" | |
| 1366 | 1365 | for entry in self.entries.values(): | |
| 1367 | - if os.fspath(entry.path).startswith(folder): | ||
| 1366 | + if entry.path.startswith(folder): | ||
| 1368 | 1367 | p = entry.path | |
| 1369 | 1368 | self._write_path_to_stdin(proc, p, p, make_exc, fprogress, read_from_stdout=False) | |
| 1370 | 1369 | checked_out_files.append(p) | |
@@ -87,7 +87,7 @@ def run_commit_hook(name: str, index: "IndexFile", *args: str) -> None: | |||
| 87 | 87 | return | |
| 88 | 88 | ||
| 89 | 89 | env = os.environ.copy() | |
| 90 | - env["GIT_INDEX_FILE"] = safe_decode(index.path) | ||
| 90 | + env["GIT_INDEX_FILE"] = safe_decode(os.fspath(index.path)) | ||
| 91 | 91 | env["GIT_EDITOR"] = ":" | |
| 92 | 92 | cmd = [hp] | |
| 93 | 93 | try: | |
@@ -167,7 +167,7 @@ def write_cache( | |||
| 167 | 167 | beginoffset = tell() | |
| 168 | 168 | write(entry.ctime_bytes) # ctime | |
| 169 | 169 | write(entry.mtime_bytes) # mtime | |
| 170 | - path_str = os.fspath(entry.path) | ||
| 170 | + path_str = str(entry.path) | ||
| 171 | 171 | path: bytes = force_bytes(path_str, encoding=defenc) | |
| 172 | 172 | plen = len(path) & CE_NAMEMASK # Path length | |
| 173 | 173 | assert plen == len(path), "Path %s too long to fit into index" % entry.path | |
@@ -58,9 +58,9 @@ def __init__(self, paths: Sequence[PathLike]) -> None: | |||
| 58 | 58 | ||
| 59 | 59 | def __call__(self, stage_blob: Tuple[StageType, Blob]) -> bool: | |
| 60 | 60 | blob_pathlike: PathLike = stage_blob[1].path | |
| 61 | - blob_path = Path(blob_pathlike) | ||
| 61 | + blob_path: Path = blob_pathlike if isinstance(blob_pathlike, Path) else Path(blob_pathlike) | ||
| 62 | 62 | for pathlike in self.paths: | |
| 63 | - path = Path(pathlike) | ||
| 63 | + path: Path = pathlike if isinstance(pathlike, Path) else Path(pathlike) | ||
| 64 | 64 | # TODO: Change to use `PosixPath.is_relative_to` once Python 3.8 is no | |
| 65 | 65 | # longer supported. | |
| 66 | 66 | filter_parts = path.parts | |
@@ -37,8 +37,8 @@ class TemporaryFileSwap: | |||
| 37 | 37 | __slots__ = ("file_path", "tmp_file_path") | |
| 38 | 38 | ||
| 39 | 39 | def __init__(self, file_path: PathLike) -> None: | |
| 40 | - self.file_path = os.fspath(file_path) | ||
| 41 | - dirname, basename = osp.split(self.file_path) | ||
| 40 | + self.file_path = file_path | ||
| 41 | + dirname, basename = osp.split(file_path) | ||
| 42 | 42 | fd, self.tmp_file_path = tempfile.mkstemp(prefix=basename, dir=dirname) | |
| 43 | 43 | os.close(fd) | |
| 44 | 44 | with contextlib.suppress(OSError): # It may be that the source does not exist. | |
@@ -106,7 +106,7 @@ def git_working_dir(func: Callable[..., _T]) -> Callable[..., _T]: | |||
| 106 | 106 | @wraps(func) | |
| 107 | 107 | def set_git_working_dir(self: "IndexFile", *args: Any, **kwargs: Any) -> _T: | |
| 108 | 108 | cur_wd = os.getcwd() | |
| 109 | - os.chdir(os.fspath(self.repo.working_tree_dir)) | ||
| 109 | + os.chdir(self.repo.working_tree_dir) | ||
| 110 | 110 | try: | |
| 111 | 111 | return func(self, *args, **kwargs) | |
| 112 | 112 | finally: | |
@@ -352,7 +352,7 @@ def _clone_repo( | |||
| 352 | 352 | module_abspath_dir = osp.dirname(module_abspath) | |
| 353 | 353 | if not osp.isdir(module_abspath_dir): | |
| 354 | 354 | os.makedirs(module_abspath_dir) | |
| 355 | - module_checkout_path = osp.join(os.fspath(repo.working_tree_dir), path) | ||
| 355 | + module_checkout_path = osp.join(repo.working_tree_dir, path) | ||
| 356 | 356 | ||
| 357 | 357 | if url.startswith("../"): | |
| 358 | 358 | remote_name = cast("RemoteReference", repo.active_branch.tracking_branch()).remote_name | |
@@ -1016,7 +1016,7 @@ def move(self, module_path: PathLike, configuration: bool = True, module: bool = | |||
| 1016 | 1016 | return self | |
| 1017 | 1017 | # END handle no change | |
| 1018 | 1018 | ||
| 1019 | - module_checkout_abspath = join_path_native(os.fspath(self.repo.working_tree_dir), module_checkout_path) | ||
| 1019 | + module_checkout_abspath = join_path_native(str(self.repo.working_tree_dir), module_checkout_path) | ||
| 1020 | 1020 | if osp.isfile(module_checkout_abspath): | |
| 1021 | 1021 | raise ValueError("Cannot move repository onto a file: %s" % module_checkout_abspath) | |
| 1022 | 1022 | # END handle target files | |
@@ -1229,7 +1229,7 @@ def remove( | |||
| 1229 | 1229 | wtd = mod.working_tree_dir | |
| 1230 | 1230 | del mod # Release file-handles (Windows). | |
| 1231 | 1231 | gc.collect() | |
| 1232 | - rmtree(wtd) | ||
| 1232 | + rmtree(str(wtd)) | ||
| 1233 | 1233 | # END delete tree if possible | |
| 1234 | 1234 | # END handle force | |
| 1235 | 1235 | ||
@@ -1313,7 +1313,7 @@ def set_parent_commit(self, commit: Union[Commit_ish, str, None], check: bool = | |||
| 1313 | 1313 | # If check is False, we might see a parent-commit that doesn't even contain the | |
| 1314 | 1314 | # submodule anymore. in that case, mark our sha as being NULL. | |
| 1315 | 1315 | try: | |
| 1316 | - self.binsha = pctree[os.fspath(self.path)].binsha | ||
| 1316 | + self.binsha = pctree[str(self.path)].binsha | ||
| 1317 | 1317 | except KeyError: | |
| 1318 | 1318 | self.binsha = self.NULL_BIN_SHA | |
| 1319 | 1319 | ||
@@ -1395,7 +1395,7 @@ def rename(self, new_name: str) -> "Submodule": | |||
| 1395 | 1395 | destination_module_abspath = self._module_abspath(self.repo, self.path, new_name) | |
| 1396 | 1396 | source_dir = mod.git_dir | |
| 1397 | 1397 | # Let's be sure the submodule name is not so obviously tied to a directory. | |
| 1398 | - if os.fspath(destination_module_abspath).startswith(os.fspath(mod.git_dir)): | ||
| 1398 | + if str(destination_module_abspath).startswith(str(mod.git_dir)): | ||
| 1399 | 1399 | tmp_dir = self._module_abspath(self.repo, self.path, str(uuid.uuid4())) | |
| 1400 | 1400 | os.renames(source_dir, tmp_dir) | |
| 1401 | 1401 | source_dir = tmp_dir | |
@@ -8,7 +8,6 @@ | |||
| 8 | 8 | ||
| 9 | 9 | __all__ = ["HEAD", "Head"] | |
| 10 | 10 | ||
| 11 | - import os | ||
| 12 | 11 | from git.config import GitConfigParser, SectionConstraint | |
| 13 | 12 | from git.exc import GitCommandError | |
| 14 | 13 | from git.util import join_path | |
@@ -45,7 +44,6 @@ class HEAD(SymbolicReference): | |||
| 45 | 44 | __slots__ = () | |
| 46 | 45 | ||
| 47 | 46 | def __init__(self, repo: "Repo", path: PathLike = _HEAD_NAME) -> None: | |
| 48 | - path = os.fspath(path) | ||
| 49 | 47 | if path != self._HEAD_NAME: | |
| 50 | 48 | raise ValueError("HEAD instance must point to %r, got %r" % (self._HEAD_NAME, path)) | |
| 51 | 49 | super().__init__(repo, path) | |
@@ -4,7 +4,6 @@ | |||
| 4 | 4 | __all__ = ["RefLog", "RefLogEntry"] | |
| 5 | 5 | ||
| 6 | 6 | from mmap import mmap | |
| 7 | - import os | ||
| 8 | 7 | import os.path as osp | |
| 9 | 8 | import re | |
| 10 | 9 | import time as _time | |
@@ -168,7 +167,7 @@ def __init__(self, filepath: Union[PathLike, None] = None) -> None: | |||
| 168 | 167 | """Initialize this instance with an optional filepath, from which we will | |
| 169 | 168 | initialize our data. The path is also used to write changes back using the | |
| 170 | 169 | :meth:`write` method.""" | |
| 171 | - self._path = None if filepath is None else os.fspath(filepath) | ||
| 170 | + self._path = filepath | ||
| 172 | 171 | if filepath is not None: | |
| 173 | 172 | self._read_from_file() | |
| 174 | 173 | # END handle filepath | |
@@ -4,6 +4,7 @@ | |||
| 4 | 4 | __all__ = ["SymbolicReference"] | |
| 5 | 5 | ||
| 6 | 6 | import os | |
| 7 | + from pathlib import Path | ||
| 7 | 8 | ||
| 8 | 9 | from gitdb.exc import BadName, BadObject | |
| 9 | 10 | ||
@@ -76,10 +77,10 @@ class SymbolicReference: | |||
| 76 | 77 | ||
| 77 | 78 | def __init__(self, repo: "Repo", path: PathLike, check_path: bool = False) -> None: | |
| 78 | 79 | self.repo = repo | |
| 79 | - self.path = os.fspath(path) | ||
| 80 | + self.path: PathLike = path | ||
| 80 | 81 | ||
| 81 | 82 | def __str__(self) -> str: | |
| 82 | - return self.path | ||
| 83 | + return os.fspath(self.path) | ||
| 83 | 84 | ||
| 84 | 85 | def __repr__(self) -> str: | |
| 85 | 86 | return '<git.%s "%s">' % (self.__class__.__name__, self.path) | |
@@ -103,7 +104,7 @@ def name(self) -> str: | |||
| 103 | 104 | In case of symbolic references, the shortest assumable name is the path | |
| 104 | 105 | itself. | |
| 105 | 106 | """ | |
| 106 | - return self.path | ||
| 107 | + return os.fspath(self.path) | ||
| 107 | 108 | ||
| 108 | 109 | @property | |
| 109 | 110 | def abspath(self) -> PathLike: | |
@@ -212,7 +213,7 @@ def _check_ref_name_valid(ref_path: PathLike) -> None: | |||
| 212 | 213 | raise ValueError(f"Invalid reference '{ref_path}': references cannot end with a forward slash (/)") | |
| 213 | 214 | elif previous == "@" and one_before_previous is None: | |
| 214 | 215 | raise ValueError(f"Invalid reference '{ref_path}': references cannot be '@'") | |
| 215 | - elif any(component.endswith(".lock") for component in os.fspath(ref_path).split("/")): | ||
| 216 | + elif any(component.endswith(".lock") for component in Path(ref_path).parts): | ||
| 216 | 217 | raise ValueError( | |
| 217 | 218 | f"Invalid reference '{ref_path}': references cannot have slash-separated components that end with" | |
| 218 | 219 | " '.lock'" | |
@@ -235,7 +236,7 @@ def _get_ref_info_helper( | |||
| 235 | 236 | tokens: Union[None, List[str], Tuple[str, str]] = None | |
| 236 | 237 | repodir = _git_dir(repo, ref_path) | |
| 237 | 238 | try: | |
| 238 | - with open(os.path.join(repodir, os.fspath(ref_path)), "rt", encoding="UTF-8") as fp: | ||
| 239 | + with open(os.path.join(repodir, ref_path), "rt", encoding="UTF-8") as fp: | ||
| 239 | 240 | value = fp.read().rstrip() | |
| 240 | 241 | # Don't only split on spaces, but on whitespace, which allows to parse lines like: | |
| 241 | 242 | # 60b64ef992065e2600bfef6187a97f92398a9144 branch 'master' of git-server:/path/to/repo | |
@@ -706,7 +707,7 @@ def _create( | |||
| 706 | 707 | if not force and os.path.isfile(abs_ref_path): | |
| 707 | 708 | target_data = str(target) | |
| 708 | 709 | if isinstance(target, SymbolicReference): | |
| 709 | - target_data = target.path | ||
| 710 | + target_data = os.fspath(target.path) | ||
| 710 | 711 | if not resolve: | |
| 711 | 712 | target_data = "ref: " + target_data | |
| 712 | 713 | with open(abs_ref_path, "rb") as fd: | |
@@ -930,4 +931,4 @@ def from_path(cls: Type[T_References], repo: "Repo", path: PathLike) -> T_Refere | |||
| 930 | 931 | ||
| 931 | 932 | def is_remote(self) -> bool: | |
| 932 | 933 | """:return: True if this symbolic reference points to a remote branch""" | |
| 933 | - return self.path.startswith(self._remote_common_path_default + "/") | ||
| 934 | + return os.fspath(self.path).startswith(self._remote_common_path_default + "/") | ||
@@ -126,7 +126,8 @@ class Repo: | |||
| 126 | 126 | working_dir: PathLike | |
| 127 | 127 | """The working directory of the git command.""" | |
| 128 | 128 | ||
| 129 | - _working_tree_dir: Optional[str] = None | ||
| 129 | + # stored as string for easier processing, but annotated as path for clearer intention | ||
| 130 | + _working_tree_dir: Optional[PathLike] = None | ||
| 130 | 131 | ||
| 131 | 132 | git_dir: PathLike | |
| 132 | 133 | """The ``.git`` repository directory.""" | |
@@ -215,13 +216,13 @@ def __init__( | |||
| 215 | 216 | epath = path or os.getenv("GIT_DIR") | |
| 216 | 217 | if not epath: | |
| 217 | 218 | epath = os.getcwd() | |
| 219 | + epath = os.fspath(epath) | ||
| 218 | 220 | if Git.is_cygwin(): | |
| 219 | 221 | # Given how the tests are written, this seems more likely to catch Cygwin | |
| 220 | 222 | # git used from Windows than Windows git used from Cygwin. Therefore | |
| 221 | 223 | # changing to Cygwin-style paths is the relevant operation. | |
| 222 | - epath = cygpath(os.fspath(epath)) | ||
| 224 | + epath = cygpath(epath) | ||
| 223 | 225 | ||
| 224 | - epath = os.fspath(epath) | ||
| 225 | 226 | if expand_vars and re.search(self.re_envvars, epath): | |
| 226 | 227 | warnings.warn( | |
| 227 | 228 | "The use of environment variables in paths is deprecated" | |
@@ -306,7 +307,7 @@ def __init__( | |||
| 306 | 307 | self._working_tree_dir = None | |
| 307 | 308 | # END working dir handling | |
| 308 | 309 | ||
| 309 | - self.working_dir: str = self._working_tree_dir or self.common_dir | ||
| 310 | + self.working_dir: PathLike = self._working_tree_dir or self.common_dir | ||
| 310 | 311 | self.git = self.GitCommandWrapperType(self.working_dir) | |
| 311 | 312 | ||
| 312 | 313 | # Special handling, in special times. | |
@@ -366,7 +367,7 @@ def description(self, descr: str) -> None: | |||
| 366 | 367 | fp.write((descr + "\n").encode(defenc)) | |
| 367 | 368 | ||
| 368 | 369 | @property | |
| 369 | - def working_tree_dir(self) -> Optional[str]: | ||
| 370 | + def working_tree_dir(self) -> Optional[PathLike]: | ||
| 370 | 371 | """ | |
| 371 | 372 | :return: | |
| 372 | 373 | The working tree directory of our git repository. | |
@@ -554,7 +555,7 @@ def tag(self, path: PathLike) -> TagReference: | |||
| 554 | 555 | ||
| 555 | 556 | @staticmethod | |
| 556 | 557 | def _to_full_tag_path(path: PathLike) -> str: | |
| 557 | - path_str = os.fspath(path) | ||
| 558 | + path_str = str(path) | ||
| 558 | 559 | if path_str.startswith(TagReference._common_path_default + "/"): | |
| 559 | 560 | return path_str | |
| 560 | 561 | if path_str.startswith(TagReference._common_default + "/"): | |
@@ -1355,6 +1356,7 @@ def _clone( | |||
| 1355 | 1356 | ) -> "Repo": | |
| 1356 | 1357 | odbt = kwargs.pop("odbt", odb_default_type) | |
| 1357 | 1358 | ||
| 1359 | + # url may be a path and this has no effect if it is a string | ||
| 1358 | 1360 | url = os.fspath(url) | |
| 1359 | 1361 | path = os.fspath(path) | |
| 1360 | 1362 | ||
@@ -62,7 +62,6 @@ def is_git_dir(d: PathLike) -> bool: | |||
| 62 | 62 | clearly indicates that we don't support it. There is the unlikely danger to | |
| 63 | 63 | throw if we see directories which just look like a worktree dir, but are none. | |
| 64 | 64 | """ | |
| 65 | - d = os.fspath(d) | ||
| 66 | 65 | if osp.isdir(d): | |
| 67 | 66 | if (osp.isdir(osp.join(d, "objects")) or "GIT_OBJECT_DIRECTORY" in os.environ) and osp.isdir( | |
| 68 | 67 | osp.join(d, "refs") | |
0 commit comments