hgext/git/manifest.py
author Pierre-Yves David <pierre-yves.david@octobus.net>
Tue, 11 Mar 2025 02:29:42 +0100
branchstable
changeset 53042 cdd7bf612c7b
parent 52741 5c48fd4c0e68
permissions -rw-r--r--
bundle-spec: properly format boolean parameter (issue6960) This was breaking automatic clone bundle generation. This changeset fixes it and add a test to catch it in the future.
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
52620
2b65c9228dc0 git: add parents property to gittreemanifestctx
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52619
diff changeset
    13
from mercurial.node import sha1nodeconstants
52741
5c48fd4c0e68 typing: introduce a `types` module and a MatcherT alias
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 52691
diff changeset
    14
from mercurial.interfaces.types import MatcherT
52620
2b65c9228dc0 git: add parents property to gittreemanifestctx
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52619
diff changeset
    15
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    16
from mercurial import (
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    17
    match as matchmod,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    18
    pathutil,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    19
    pycompat,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    20
    util,
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 mercurial.interfaces import (
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    23
    repository,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    24
)
52620
2b65c9228dc0 git: add parents property to gittreemanifestctx
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52619
diff changeset
    25
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    26
from . import gitutil
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    27
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    28
if typing.TYPE_CHECKING:
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    29
    from typing import (
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    30
        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
    31
    )
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    32
44484
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44479
diff changeset
    33
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
    34
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44479
diff changeset
    35
52495
6412dcec52d3 manifest: subclass the new `repository.imanifestdict` Protocol class
Matt Harbison <matt_harbison@yahoo.com>
parents: 52494
diff changeset
    36
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
    37
    """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
    38
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    39
    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
    40
    """
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    41
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    42
    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
    43
        """Initializer.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    44
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    45
        Args:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    46
          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
    47
              trees).
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    48
          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
    49
          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
    50
              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
    51
              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
    52
              `write()` method.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    53
        """
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    54
        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
    55
        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
    56
        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
    57
            pending_changes = {}
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    58
        # 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
    59
        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
    60
52491
c855943e334b git: fix `repository.imanifestdict` implementation flaws detected by pytype
Matt Harbison <matt_harbison@yahoo.com>
parents: 52481
diff changeset
    61
    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
    62
        """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
    63
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    64
        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
    65
        """
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    66
        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
    67
        ent = None
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    68
        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
    69
            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
    70
            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
    71
                raise KeyError
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    72
            return val
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    73
        t = self._tree
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    74
        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
    75
        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
    76
        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
    77
            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
    78
            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
    79
        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
    80
        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
    81
            flags = b''
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    82
        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
    83
            flags = b'x'
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    84
        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
    85
            flags = b'l'
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    86
        else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
    87
            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
    88
        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
    89
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    90
    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
    91
        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
    92
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    93
    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
    94
        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
    95
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    96
    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
    97
        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
    98
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
    99
    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
   100
        try:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   101
            next(iter(self))
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   102
            return True
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   103
        except StopIteration:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   104
            return False
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   105
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   106
    __bool__ = __nonzero__
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   107
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   108
    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
   109
        try:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   110
            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
   111
            return True
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   112
        except KeyError:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   113
            return False
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   114
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   115
    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
   116
        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
   117
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   118
    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
   119
        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
   120
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   121
    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
   122
        return self.iterkeys()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   123
52494
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   124
    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
   125
        raise NotImplementedError  # TODO: implement this
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   126
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   127
    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
   128
        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
   129
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   130
    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
   131
        # 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
   132
        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
   133
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   134
    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
   135
        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
   136
            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
   137
            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
   138
            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
   139
        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
   140
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   141
    @util.propertycache
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   142
    def _dirs(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   143
        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
   144
52494
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   145
    def dirs(self) -> pathutil.dirs:
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   146
        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
   147
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   148
    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
   149
        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
   150
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   151
    def diff(
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   152
        self,
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   153
        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
   154
        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
   155
        clean: bool = False,
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   156
    ) -> dict[
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   157
        bytes,
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   158
        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
   159
    ]:
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45516
diff changeset
   160
        """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
   161
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   162
        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
   163
        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
   164
        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
   165
        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
   166
        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
   167
        string.
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45516
diff changeset
   168
        """
44931
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   169
        result = {}
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   170
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   171
        def _iterativediff(t1, t2, subdir):
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   172
            """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
   173
            the stack"""
52660
1c8bc6110a1a git: skip recursing into manifest subtrees that are the same
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52645
diff changeset
   174
            if t1 == t2:
1c8bc6110a1a git: skip recursing into manifest subtrees that are the same
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52645
diff changeset
   175
                # If the trees are the same (git) object, then there are no
1c8bc6110a1a git: skip recursing into manifest subtrees that are the same
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52645
diff changeset
   176
                # differences in this tree or any of its children.
1c8bc6110a1a git: skip recursing into manifest subtrees that are the same
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52645
diff changeset
   177
                return
1c8bc6110a1a git: skip recursing into manifest subtrees that are the same
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52645
diff changeset
   178
44931
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   179
            if t1 is None:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   180
                t1 = {}
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   181
            if t2 is None:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   182
                t2 = {}
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   183
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   184
            for e1 in t1:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   185
                realname = subdir + pycompat.fsencode(e1.name)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   186
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   187
                if e1.type == pygit2.GIT_OBJ_TREE:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   188
                    try:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   189
                        e2 = t2[e1.name]
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   190
                        if e2.type != pygit2.GIT_OBJ_TREE:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   191
                            e2 = None
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   192
                    except KeyError:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   193
                        e2 = None
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   194
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   195
                    stack.append((realname + b'/', e1, e2))
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   196
                else:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   197
                    n1, fl1 = self.find(realname)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   198
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   199
                    try:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   200
                        e2 = t2[e1.name]
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   201
                        n2, fl2 = other.find(realname)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   202
                    except KeyError:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   203
                        e2 = None
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   204
                        n2, fl2 = (None, b'')
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   205
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   206
                    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
   207
                        stack.append((realname + b'/', None, e2))
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   208
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   209
                    if not match(realname):
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
                    if n1 != n2 or fl1 != fl2:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   213
                        result[realname] = ((n1, fl1), (n2, fl2))
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   214
                    elif clean:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   215
                        result[realname] = None
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   216
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   217
            for e2 in t2:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   218
                if e2.name in t1:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   219
                    continue
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   220
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   221
                realname = subdir + pycompat.fsencode(e2.name)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   222
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   223
                if e2.type == pygit2.GIT_OBJ_TREE:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   224
                    stack.append((realname + b'/', None, e2))
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   225
                elif match(realname):
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   226
                    n2, fl2 = other.find(realname)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   227
                    result[realname] = ((None, b''), (n2, fl2))
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   228
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   229
        stack = []
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   230
        _iterativediff(self._tree, other._tree, b'')
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   231
        while stack:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   232
            subdir, t1, t2 = stack.pop()
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   233
            # stack is populated in the function call
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   234
            _iterativediff(t1, t2, subdir)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   235
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
   236
        return result
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   237
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   238
    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
   239
        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
   240
        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
   241
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   242
    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
   243
        try:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   244
            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
   245
        except KeyError:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   246
            return default
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   247
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   248
    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
   249
        try:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   250
            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
   251
        except KeyError:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   252
            return b''
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   253
52645
4cb75772818d pyupgrade: drop the quoting around type annotations
Matt Harbison <matt_harbison@yahoo.com>
parents: 52644
diff changeset
   254
    def copy(self) -> gittreemanifest:
45417
c8695439d7e3 git: actually copy treemanifest instances in .copy() (issue6398)
Augie Fackler <raf@durin42.com>
parents: 44931
diff changeset
   255
        return gittreemanifest(
c8695439d7e3 git: actually copy treemanifest instances in .copy() (issue6398)
Augie Fackler <raf@durin42.com>
parents: 44931
diff changeset
   256
            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
   257
        )
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   258
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   259
    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
   260
        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
   261
            # 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
   262
            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
   263
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   264
    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
   265
        return self.items()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   266
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   267
    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
   268
        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
   269
            # 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
   270
            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
   271
52492
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   272
    def text(self) -> ByteString:
48cdbd4d5443 typing: align the signatures of `repository.imanifestdict` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 52491
diff changeset
   273
        # 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
   274
        raise NotImplementedError
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   275
52494
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   276
    def fastdelta(
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   277
        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
   278
    ) -> tuple[ByteString, ByteString]:
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   279
        raise NotImplementedError  # TODO: implement this
db6efd74cf14 git: add missing `repository.imanifestdict` methods to `gittreemanifest`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52492
diff changeset
   280
52691
279e217d6041 typing: lock in the new type annotations detected with the pyupgrade changes
Matt Harbison <matt_harbison@yahoo.com>
parents: 52660
diff changeset
   281
    def _walkonetree(self, tree, match, subdir) -> Iterator[bytes]:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   282
        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
   283
            # 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
   284
            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
   285
            if te.type == pygit2.GIT_OBJ_TREE:
52644
e627cc25b6f3 pyupgrade: rewrite `yield` statements in a loop to `yield from`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52620
diff changeset
   286
                yield from self._walkonetree(
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   287
                    self._git_repo[te.id], match, realname + b'/'
52644
e627cc25b6f3 pyupgrade: rewrite `yield` statements in a loop to `yield from`
Matt Harbison <matt_harbison@yahoo.com>
parents: 52620
diff changeset
   288
                )
44929
3679c88b7f4e git: don't yield paths for directories when walking
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44928
diff changeset
   289
            elif match(realname):
3679c88b7f4e git: don't yield paths for directories when walking
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44928
diff changeset
   290
                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
   291
52741
5c48fd4c0e68 typing: introduce a `types` module and a MatcherT alias
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 52691
diff changeset
   292
    def walk(self, match: MatcherT) -> Iterator[bytes]:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   293
        # 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
   294
        # 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
   295
        # 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
   296
        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
   297
        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
   298
        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
   299
        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
   300
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   301
52477
d37d8dfe65bd manifest: subclass the new `repository.imanifestrevisionstored` Protocol class
Matt Harbison <matt_harbison@yahoo.com>
parents: 52474
diff changeset
   302
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
   303
    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
   304
        self._repo = repo
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   305
        self._tree = gittree
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   306
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   307
    def read(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   308
        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
   309
52474
048c11993d6a typing: (mostly) align the signatures of `imanifestrevisionstored` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
   310
    def readfast(self, shallow: bool = False):
44479
7518ea76eff4 git: add readfast() method to manifest
Augie Fackler <raf@durin42.com>
parents: 44477
diff changeset
   311
        return self.read()
7518ea76eff4 git: add readfast() method to manifest
Augie Fackler <raf@durin42.com>
parents: 44477
diff changeset
   312
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   313
    def copy(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   314
        # 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
   315
        # 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
   316
        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
   317
52474
048c11993d6a typing: (mostly) align the signatures of `imanifestrevisionstored` overrides
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
   318
    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
   319
        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
   320
52619
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   321
    def node(self) -> bytes:
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   322
        raise NotImplementedError
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   323
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   324
    def readdelta(self, shallow: bool = False):
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_any_fast_delta(
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   328
        self,
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   329
        valid_bases: Collection[int] | None = None,
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   330
        *,
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   331
        shallow: bool = False,
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   332
    ):
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   333
        raise NotImplementedError
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   334
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   335
    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
   336
        raise NotImplementedError
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   337
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   338
    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
   339
        raise NotImplementedError
b9f47b685e90 git: add stubs for gittreemanifestctx methods
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52495
diff changeset
   340
52620
2b65c9228dc0 git: add parents property to gittreemanifestctx
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52619
diff changeset
   341
    @property
2b65c9228dc0 git: add parents property to gittreemanifestctx
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52619
diff changeset
   342
    def parents(self):
2b65c9228dc0 git: add parents property to gittreemanifestctx
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52619
diff changeset
   343
        # FIXME: the 2 parent nodes
2b65c9228dc0 git: add parents property to gittreemanifestctx
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52619
diff changeset
   344
        return sha1nodeconstants.nullid, sha1nodeconstants.nullid
2b65c9228dc0 git: add parents property to gittreemanifestctx
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 52619
diff changeset
   345
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   346
52481
22f97aa5e8b2 manifest: subclass the new `imanifestrevisionwritable` Protocol class
Matt Harbison <matt_harbison@yahoo.com>
parents: 52477
diff changeset
   347
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
   348
    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
   349
        self._repo = repo
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   350
        self._tree = tree
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   351
        # 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
   352
        self._pending_changes = {}
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   353
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   354
    def read(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   355
        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
   356
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   357
    def copy(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   358
        # 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
   359
        # 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
   360
        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
   361
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   362
    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
   363
        # 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
   364
        # 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
   365
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   366
        # 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
   367
        # just narrow?
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   368
        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
   369
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
   370
        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
   371
        trees = {
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   372
            b'': self._tree,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   373
        }
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   374
        # path: treebuilder
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   375
        builders = {
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   376
            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
   377
        }
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   378
        # 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
   379
        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
   380
            if d == b'':
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   381
                # 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
   382
                continue
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   383
            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
   384
            full = b''
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   385
            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
   386
                parent = trees[full]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   387
                try:
45516
73a5aa5e1857 git: pass `id` attribute of `pygit2.Tree` object
Connor Sheehan <sheehan@mozilla.com>
parents: 45417
diff changeset
   388
                    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
   389
                    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
   390
                except KeyError:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   391
                    # new directory
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   392
                    new = None
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   393
                full += b'/' + part
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   394
                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
   395
                    # existing directory
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   396
                    trees[full] = new
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   397
                    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
   398
                else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   399
                    # 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
   400
                    # 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
   401
                    # created.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   402
                    trees[full] = {}
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   403
                    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
   404
        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
   405
            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
   406
                dirname = b''
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   407
                basename = f
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   408
            else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   409
                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
   410
                dirname = b'/' + dirname
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   411
            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
   412
                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
   413
            else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   414
                n, fl = info
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   415
                mode = {
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   416
                    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
   417
                    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
   418
                    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
   419
                }[fl]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   420
                builders[dirname].insert(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   421
                    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
   422
                )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   423
        # 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
   424
        # 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
   425
        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
   426
            if b == b'':
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   427
                break
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   428
            cb = builders[b]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   429
            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
   430
            builders[dn].insert(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   431
                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
   432
            )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
   433
        return builders[b''].write().raw