hgext/git/manifest.py
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
Thu, 02 Jan 2025 11:27:45 -0500
changeset 52619 b9f47b685e90
parent 52495 6412dcec52d3
child 52620 2b65c9228dc0
permissions -rw-r--r--
git: add stubs for gittreemanifestctx methods $ hg log ** unknown exception encountered, please report by visiting ** https://mercurial-scm.org/wiki/BugTracker ** Python 3.11.10 (main, Oct 31 2024, 01:10:40) [Clang 18.1.5 (https://github.com/llvm/llvm-project.git llvmorg-18.1.5-0-g617a15 ** Mercurial Distributed SCM (version 6.9.post1.dev337+hg.72af9fa34832) ** Extensions loaded: absorb, churn, git (pygit2 1.14.1), githelp, gpg, hgk, histedit, patchbomb, rebase Traceback (most recent call last): File "/home/jeffpc/src/oss/hg-gitext-test/../hg-gitext/hg", line 61, in <module> dispatch.run() ... File "/usr/home/jeffpc/src/oss/hg-gitext/hgext/git/gitlog.py", line 564, in get return gitmanifest.gittreemanifestctx(self.gitrepo, t) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TypeError: Can't instantiate abstract class gittreemanifestctx with abstract methods node, read_any_fast_delta, read_delta_new_entries, read_delta_parents, readdelta
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
51859
f4733654f144 typing: add `from __future__ import annotations` to most files
Matt Harbison <matt_harbison@yahoo.com>
parents: 48946
diff changeset
     1
from __future__ import annotations
f4733654f144 typing: add `from __future__ import annotations` to most files
Matt Harbison <matt_harbison@yahoo.com>
parents: 48946
diff changeset
     2
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
     3
import typing
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
     4
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
     5
from typing import (
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
     6
    Any,
52619
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
     7
    Collection,
52494
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
     8
    Iterable,
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
     9
    Iterator,
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    10
    Set,
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    11
)
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    12
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    13
from mercurial import (
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    14
    match as matchmod,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    15
    pathutil,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    16
    pycompat,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    17
    util,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    18
)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    19
from mercurial.interfaces import (
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    20
    repository,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    21
)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    22
from . import gitutil
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    23
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    24
if typing.TYPE_CHECKING:
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    25
    from typing import (
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    26
        ByteString,  # TODO: change to Buffer for 3.14
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    27
    )
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    28
44484
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44479
diff changeset
    29
pygit2 = gitutil.get_pygit2()
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44479
diff changeset
    30
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44479
diff changeset
    31
52495
6412dcec52d3 manifest: subclass the new `repository.imanifestdict` Protocol class
Matt Harbison <matt_harbison@yahoo.com>
parents: 52494
diff changeset
    32
class gittreemanifest(repository.imanifestdict):
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    33
    """Expose git trees (and optionally a builder's overlay) as a manifestdict.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    34
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    35
    Very similar to mercurial.manifest.treemanifest.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    36
    """
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    37
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    38
    def __init__(self, git_repo, root_tree, pending_changes):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    39
        """Initializer.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    40
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    41
        Args:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    42
          git_repo: The git_repo we're walking (required to look up child
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    43
              trees).
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    44
          root_tree: The root Git tree object for this manifest.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    45
          pending_changes: A dict in which pending changes will be
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    46
              tracked. The enclosing memgittreemanifestctx will use this to
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    47
              construct any required Tree objects in Git during it's
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    48
              `write()` method.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    49
        """
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    50
        self._git_repo = git_repo
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    51
        self._tree = root_tree
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    52
        if pending_changes is None:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    53
            pending_changes = {}
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    54
        # dict of path: Optional[Tuple(node, flags)]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    55
        self._pending_changes = pending_changes
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    56
52491
c855943e334b git: fix `repository.imanifestdict` implementation flaws detected by pytype
Matt Harbison <matt_harbison@yahoo.com>
parents: 52481
diff changeset
    57
    def _resolve_entry(self, path) -> tuple[bytes, bytes]:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    58
        """Given a path, load its node and flags, or raise KeyError if missing.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    59
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    60
        This takes into account any pending writes in the builder.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    61
        """
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    62
        upath = pycompat.fsdecode(path)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    63
        ent = None
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    64
        if path in self._pending_changes:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    65
            val = self._pending_changes[path]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    66
            if val is None:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    67
                raise KeyError
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    68
            return val
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    69
        t = self._tree
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    70
        comps = upath.split('/')
44930
47ce28a78f4a git: properly visit child tree objects when resolving a path
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44929
diff changeset
    71
        te = self._tree
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    72
        for comp in comps[:-1]:
44930
47ce28a78f4a git: properly visit child tree objects when resolving a path
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44929
diff changeset
    73
            te = te[comp]
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    74
            t = self._git_repo[te.id]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    75
        ent = t[comps[-1]]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    76
        if ent.filemode == pygit2.GIT_FILEMODE_BLOB:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    77
            flags = b''
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    78
        elif ent.filemode == pygit2.GIT_FILEMODE_BLOB_EXECUTABLE:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    79
            flags = b'x'
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    80
        elif ent.filemode == pygit2.GIT_FILEMODE_LINK:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    81
            flags = b'l'
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    82
        else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    83
            raise ValueError('unsupported mode %s' % oct(ent.filemode))
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    84
        return ent.id.raw, flags
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    85
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    86
    def __getitem__(self, path: bytes) -> bytes:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    87
        return self._resolve_entry(path)[0]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    88
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    89
    def find(self, path: bytes) -> tuple[bytes, bytes]:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    90
        return self._resolve_entry(path)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    91
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    92
    def __len__(self) -> int:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    93
        return len(list(self.walk(matchmod.always())))
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    94
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    95
    def __nonzero__(self) -> bool:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    96
        try:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    97
            next(iter(self))
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    98
            return True
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    99
        except StopIteration:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   100
            return False
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   101
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   102
    __bool__ = __nonzero__
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   103
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   104
    def __contains__(self, path: bytes) -> bool:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   105
        try:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   106
            self._resolve_entry(path)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   107
            return True
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   108
        except KeyError:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   109
            return False
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   110
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   111
    def iterkeys(self) -> Iterator[bytes]:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   112
        return self.walk(matchmod.always())
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   113
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   114
    def keys(self) -> list[bytes]:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   115
        return list(self.iterkeys())
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   116
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   117
    def __iter__(self) -> Iterator[bytes]:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   118
        return self.iterkeys()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   119
52494
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   120
    def set(self, path: bytes, node: bytes, flags: bytes) -> None:
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   121
        raise NotImplementedError  # TODO: implement this
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   122
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   123
    def __setitem__(self, path: bytes, node: bytes) -> None:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   124
        self._pending_changes[path] = node, self.flags(path)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   125
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   126
    def __delitem__(self, path: bytes) -> None:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   127
        # TODO: should probably KeyError for already-deleted  files?
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   128
        self._pending_changes[path] = None
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   129
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   130
    def filesnotin(self, other, match=None) -> Set[bytes]:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   131
        if match is not None:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   132
            match = matchmod.badmatch(match, lambda path, msg: None)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   133
            sm2 = set(other.walk(match))
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   134
            return {f for f in self.walk(match) if f not in sm2}
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   135
        return {f for f in self if f not in other}
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   136
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   137
    @util.propertycache
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   138
    def _dirs(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   139
        return pathutil.dirs(self)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   140
52494
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   141
    def dirs(self) -> pathutil.dirs:
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   142
        return self._dirs  # TODO: why is there a prpoertycache?
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   143
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   144
    def hasdir(self, dir: bytes) -> bool:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   145
        return dir in self._dirs
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   146
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   147
    def diff(
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   148
        self,
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   149
        other: Any,  # TODO: 'manifestdict' or (better) equivalent interface
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   150
        match: Any = lambda x: True,  # TODO: Optional[matchmod.basematcher] = None,
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   151
        clean: bool = False,
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   152
    ) -> dict[
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   153
        bytes,
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   154
        tuple[tuple[bytes | None, bytes], tuple[bytes | None, bytes]] | None,
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   155
    ]:
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45516
diff changeset
   156
        """Finds changes between the current manifest and m2.
44931
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   157
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   158
        The result is returned as a dict with filename as key and
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   159
        values of the form ((n1,fl1),(n2,fl2)), where n1/n2 is the
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   160
        nodeid in the current/other manifest and fl1/fl2 is the flag
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   161
        in the current/other manifest. Where the file does not exist,
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   162
        the nodeid will be None and the flags will be the empty
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   163
        string.
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45516
diff changeset
   164
        """
44931
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   165
        result = {}
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   166
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   167
        def _iterativediff(t1, t2, subdir):
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   168
            """compares two trees and appends new tree nodes to examine to
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   169
            the stack"""
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   170
            if t1 is None:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   171
                t1 = {}
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   172
            if t2 is None:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   173
                t2 = {}
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   174
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   175
            for e1 in t1:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   176
                realname = subdir + pycompat.fsencode(e1.name)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   177
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   178
                if e1.type == pygit2.GIT_OBJ_TREE:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   179
                    try:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   180
                        e2 = t2[e1.name]
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   181
                        if e2.type != pygit2.GIT_OBJ_TREE:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   182
                            e2 = None
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   183
                    except KeyError:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   184
                        e2 = None
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   185
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   186
                    stack.append((realname + b'/', e1, e2))
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   187
                else:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   188
                    n1, fl1 = self.find(realname)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   189
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   190
                    try:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   191
                        e2 = t2[e1.name]
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   192
                        n2, fl2 = other.find(realname)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   193
                    except KeyError:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   194
                        e2 = None
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   195
                        n2, fl2 = (None, b'')
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   196
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   197
                    if e2 is not None and e2.type == pygit2.GIT_OBJ_TREE:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   198
                        stack.append((realname + b'/', None, e2))
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   199
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   200
                    if not match(realname):
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   201
                        continue
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   202
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   203
                    if n1 != n2 or fl1 != fl2:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   204
                        result[realname] = ((n1, fl1), (n2, fl2))
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   205
                    elif clean:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   206
                        result[realname] = None
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   207
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   208
            for e2 in t2:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   209
                if e2.name in t1:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   210
                    continue
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   211
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   212
                realname = subdir + pycompat.fsencode(e2.name)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   213
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   214
                if e2.type == pygit2.GIT_OBJ_TREE:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   215
                    stack.append((realname + b'/', None, e2))
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   216
                elif match(realname):
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   217
                    n2, fl2 = other.find(realname)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   218
                    result[realname] = ((None, b''), (n2, fl2))
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   219
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   220
        stack = []
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   221
        _iterativediff(self._tree, other._tree, b'')
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   222
        while stack:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   223
            subdir, t1, t2 = stack.pop()
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   224
            # stack is populated in the function call
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   225
            _iterativediff(t1, t2, subdir)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   226
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   227
        return result
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   228
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   229
    def setflag(self, path: bytes, flag: bytes) -> None:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   230
        node, unused_flag = self._resolve_entry(path)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   231
        self._pending_changes[path] = node, flag
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   232
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   233
    def get(self, path: bytes, default=None) -> bytes | None:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   234
        try:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   235
            return self._resolve_entry(path)[0]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   236
        except KeyError:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   237
            return default
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   238
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   239
    def flags(self, path: bytes) -> bytes:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   240
        try:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   241
            return self._resolve_entry(path)[1]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   242
        except KeyError:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   243
            return b''
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   244
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   245
    def copy(self) -> 'gittreemanifest':
45417
c8695439d7e3 git: actually copy treemanifest instances in .copy() (issue6398)
Augie Fackler <raf@durin42.com>
parents: 44931
diff changeset
   246
        return gittreemanifest(
c8695439d7e3 git: actually copy treemanifest instances in .copy() (issue6398)
Augie Fackler <raf@durin42.com>
parents: 44931
diff changeset
   247
            self._git_repo, self._tree, dict(self._pending_changes)
c8695439d7e3 git: actually copy treemanifest instances in .copy() (issue6398)
Augie Fackler <raf@durin42.com>
parents: 44931
diff changeset
   248
        )
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   249
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   250
    def items(self) -> Iterator[tuple[bytes, bytes]]:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   251
        for f in self:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   252
            # TODO: build a proper iterator version of this
52491
c855943e334b git: fix `repository.imanifestdict` implementation flaws detected by pytype
Matt Harbison <matt_harbison@yahoo.com>
parents: 52481
diff changeset
   253
            yield f, self[f]
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   254
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   255
    def iteritems(self) -> Iterator[tuple[bytes, bytes]]:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   256
        return self.items()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   257
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   258
    def iterentries(self) -> Iterator[tuple[bytes, bytes, bytes]]:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   259
        for f in self:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   260
            # TODO: build a proper iterator version of this
52491
c855943e334b git: fix `repository.imanifestdict` implementation flaws detected by pytype
Matt Harbison <matt_harbison@yahoo.com>
parents: 52481
diff changeset
   261
            yield f, *self._resolve_entry(f)
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   262
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   263
    def text(self) -> ByteString:
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   264
        # TODO can this method move out of the manifest iface?
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   265
        raise NotImplementedError
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   266
52494
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   267
    def fastdelta(
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   268
        self, base: ByteString, changes: Iterable[tuple[bytes, bool]]
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   269
    ) -> tuple[ByteString, ByteString]:
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   270
        raise NotImplementedError  # TODO: implement this
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   271
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   272
    def _walkonetree(self, tree, match, subdir):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   273
        for te in tree:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   274
            # TODO: can we prune dir walks with the matcher?
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   275
            realname = subdir + pycompat.fsencode(te.name)
44928
935c9f347bdb git: correctly check for type of object when walking
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44843
diff changeset
   276
            if te.type == pygit2.GIT_OBJ_TREE:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   277
                for inner in self._walkonetree(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   278
                    self._git_repo[te.id], match, realname + b'/'
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   279
                ):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   280
                    yield inner
44929
3679c88b7f4e git: don't yield paths for directories when walking
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44928
diff changeset
   281
            elif match(realname):
3679c88b7f4e git: don't yield paths for directories when walking
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44928
diff changeset
   282
                yield pycompat.fsencode(realname)
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   283
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   284
    def walk(self, match: matchmod.basematcher) -> Iterator[bytes]:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   285
        # TODO: this is a very lazy way to merge in the pending
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   286
        # changes. There is absolutely room for optimization here by
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   287
        # being clever about walking over the sets...
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   288
        baseline = set(self._walkonetree(self._tree, match, b''))
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   289
        deleted = {p for p, v in self._pending_changes.items() if v is None}
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   290
        pend = {p for p in self._pending_changes if match(p)}
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   291
        return iter(sorted((baseline | pend) - deleted))
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   292
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   293
52477
d37d8dfe65bd manifest: subclass the new `repository.imanifestrevisionstored` Protocol class
Matt Harbison <matt_harbison@yahoo.com>
parents: 52474
diff changeset
   294
class gittreemanifestctx(repository.imanifestrevisionstored):
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   295
    def __init__(self, repo, gittree):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   296
        self._repo = repo
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   297
        self._tree = gittree
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   298
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   299
    def read(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   300
        return gittreemanifest(self._repo, self._tree, None)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   301
52474
048c11993d6a typing: (mostly) align the signatures of `imanifestrevisionstored` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
   302
    def readfast(self, shallow: bool = False):
44479
7518ea76eff4 git: add readfast() method to manifest
Augie Fackler <raf@durin42.com>
parents: 44477
diff changeset
   303
        return self.read()
7518ea76eff4 git: add readfast() method to manifest
Augie Fackler <raf@durin42.com>
parents: 44477
diff changeset
   304
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   305
    def copy(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   306
        # NB: it's important that we return a memgittreemanifestctx
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   307
        # because the caller expects a mutable manifest.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   308
        return memgittreemanifestctx(self._repo, self._tree)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   309
52474
048c11993d6a typing: (mostly) align the signatures of `imanifestrevisionstored` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
   310
    def find(self, path: bytes) -> tuple[bytes, bytes]:
52491
c855943e334b git: fix `repository.imanifestdict` implementation flaws detected by pytype
Matt Harbison <matt_harbison@yahoo.com>
parents: 52481
diff changeset
   311
        return self.read().find(path)
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   312
52619
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   313
    def node(self) -> bytes:
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   314
        raise NotImplementedError
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   315
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   316
    def readdelta(self, shallow: bool = False):
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   317
        raise NotImplementedError
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   318
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   319
    def read_any_fast_delta(
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   320
        self,
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   321
        valid_bases: Collection[int] | None = None,
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   322
        *,
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   323
        shallow: bool = False,
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   324
    ):
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   325
        raise NotImplementedError
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   326
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   327
    def read_delta_parents(self, *, shallow: bool = False, exact: bool = True):
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   328
        raise NotImplementedError
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   329
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   330
    def read_delta_new_entries(self, *, shallow: bool = False):
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   331
        raise NotImplementedError
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   332
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   333
52481
22f97aa5e8b2 manifest: subclass the new `imanifestrevisionwritable` Protocol class
Matt Harbison <matt_harbison@yahoo.com>
parents: 52477
diff changeset
   334
class memgittreemanifestctx(repository.imanifestrevisionwritable):
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   335
    def __init__(self, repo, tree):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   336
        self._repo = repo
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   337
        self._tree = tree
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   338
        # dict of path: Optional[Tuple(node, flags)]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   339
        self._pending_changes = {}
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   340
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   341
    def read(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   342
        return gittreemanifest(self._repo, self._tree, self._pending_changes)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   343
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   344
    def copy(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   345
        # TODO: if we have a builder in play, what should happen here?
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   346
        # Maybe we can shuffle copy() into the immutable interface.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   347
        return memgittreemanifestctx(self._repo, self._tree)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   348
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   349
    def write(self, transaction, link, p1, p2, added, removed, match=None):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   350
        # We're not (for now, anyway) going to audit filenames, so we
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   351
        # can ignore added and removed.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   352
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   353
        # TODO what does this match argument get used for? hopefully
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   354
        # just narrow?
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   355
        assert not match or isinstance(match, matchmod.alwaysmatcher)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   356
44625
e9e7156a8d6c git: pass a list to pathutil.dirs to indicate that it is a manifest
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44484
diff changeset
   357
        touched_dirs = pathutil.dirs(list(self._pending_changes))
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   358
        trees = {
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   359
            b'': self._tree,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   360
        }
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   361
        # path: treebuilder
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   362
        builders = {
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   363
            b'': self._repo.TreeBuilder(self._tree),
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   364
        }
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   365
        # get a TreeBuilder for every tree in the touched_dirs set
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   366
        for d in sorted(touched_dirs, key=lambda x: (len(x), x)):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   367
            if d == b'':
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   368
                # loaded root tree above
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   369
                continue
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   370
            comps = d.split(b'/')
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   371
            full = b''
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   372
            for part in comps:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   373
                parent = trees[full]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   374
                try:
45516
73a5aa5e1857 git: pass `id` attribute of `pygit2.Tree` object
Connor Sheehan <sheehan@mozilla.com>
parents: 45417
diff changeset
   375
                    parent_tree_id = parent[pycompat.fsdecode(part)].id
73a5aa5e1857 git: pass `id` attribute of `pygit2.Tree` object
Connor Sheehan <sheehan@mozilla.com>
parents: 45417
diff changeset
   376
                    new = self._repo[parent_tree_id]
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   377
                except KeyError:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   378
                    # new directory
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   379
                    new = None
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   380
                full += b'/' + part
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   381
                if new is not None:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   382
                    # existing directory
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   383
                    trees[full] = new
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   384
                    builders[full] = self._repo.TreeBuilder(new)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   385
                else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   386
                    # new directory, use an empty dict to easily
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   387
                    # generate KeyError as any nested new dirs get
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   388
                    # created.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   389
                    trees[full] = {}
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   390
                    builders[full] = self._repo.TreeBuilder()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   391
        for f, info in self._pending_changes.items():
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   392
            if b'/' not in f:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   393
                dirname = b''
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   394
                basename = f
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   395
            else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   396
                dirname, basename = f.rsplit(b'/', 1)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   397
                dirname = b'/' + dirname
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   398
            if info is None:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   399
                builders[dirname].remove(pycompat.fsdecode(basename))
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   400
            else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   401
                n, fl = info
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   402
                mode = {
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   403
                    b'': pygit2.GIT_FILEMODE_BLOB,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   404
                    b'x': pygit2.GIT_FILEMODE_BLOB_EXECUTABLE,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   405
                    b'l': pygit2.GIT_FILEMODE_LINK,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   406
                }[fl]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   407
                builders[dirname].insert(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   408
                    pycompat.fsdecode(basename), gitutil.togitnode(n), mode
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   409
                )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   410
        # This visits the buffered TreeBuilders in deepest-first
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   411
        # order, bubbling up the edits.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   412
        for b in sorted(builders, key=len, reverse=True):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   413
            if b == b'':
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   414
                break
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   415
            cb = builders[b]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   416
            dn, bn = b.rsplit(b'/', 1)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   417
            builders[dn].insert(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   418
                pycompat.fsdecode(bn), cb.write(), pygit2.GIT_FILEMODE_TREE
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   419
            )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   420
        return builders[b''].write().raw