annotate hgext/git/manifest.py @ 52316:a820a7a1fce0 default tip

setup: require TLS 1.2 support from the Python interpreter (BC) Before it was optional, and either 1.1 or 1.2 was sufficient. Now that the default minimum is 1.2, it needs to be present to work out of the box. The code here is more convoluted than the corresponding checks in `sslutil.py`, but I'm leaving it alone because it can all be simplified when py38 is dropped.
author Matt Harbison <matt_harbison@yahoo.com>
date Thu, 21 Nov 2024 11:46:10 -0500
parents f4733654f144
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
51863
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
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
3 from mercurial import (
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
4 match as matchmod,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
5 pathutil,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
6 pycompat,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
7 util,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
8 )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
9 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
10 repository,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
11 util as interfaceutil,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
12 )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
13 from . import gitutil
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
14
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
15
44484
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44479
diff changeset
16 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
17
ec54b3d2af0b git: don't fail import when pygit2 is not install
Martin von Zweigbergk <martinvonz@google.com>
parents: 44479
diff changeset
18
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
19 @interfaceutil.implementer(repository.imanifestdict)
48946
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
20 class gittreemanifest:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
21 """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
22
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
23 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
24 """
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
25
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
26 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
27 """Initializer.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
28
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
29 Args:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
30 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
31 trees).
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
32 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
33 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
34 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
35 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
36 `write()` method.
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 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
39 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
40 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
41 pending_changes = {}
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
42 # 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
43 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
44
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
45 def _resolve_entry(self, path):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
46 """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
47
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
48 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
49 """
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
50 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
51 ent = None
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
52 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
53 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
54 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
55 raise KeyError
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
56 return val
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
57 t = self._tree
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
58 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
59 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
60 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
61 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
62 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
63 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
64 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
65 flags = b''
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
66 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
67 flags = b'x'
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
68 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
69 flags = b'l'
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
70 else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
71 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
72 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
73
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
74 def __getitem__(self, path):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
75 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
76
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
77 def find(self, path):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
78 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
79
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
80 def __len__(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
81 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
82
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
83 def __nonzero__(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
84 try:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
85 next(iter(self))
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
86 return True
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
87 except StopIteration:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
88 return False
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
89
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
90 __bool__ = __nonzero__
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
91
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
92 def __contains__(self, path):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
93 try:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
94 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 return True
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
96 except KeyError:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
97 return False
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
98
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
99 def iterkeys(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
100 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
101
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
102 def keys(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
103 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
104
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
105 def __iter__(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
106 return self.iterkeys()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
107
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
108 def __setitem__(self, path, node):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
109 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
110
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
111 def __delitem__(self, path):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
112 # 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
113 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
114
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
115 def filesnotin(self, other, match=None):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
116 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
117 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
118 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
119 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
120 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
121
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
122 @util.propertycache
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
123 def _dirs(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
124 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
125
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
126 def hasdir(self, dir):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
127 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
128
44931
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
129 def diff(self, other, match=lambda x: True, clean=False):
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45516
diff changeset
130 """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
131
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
132 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
133 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
134 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
135 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
136 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
137 string.
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45516
diff changeset
138 """
44931
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
139 result = {}
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
140
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
141 def _iterativediff(t1, t2, subdir):
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
142 """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
143 the stack"""
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
144 if t1 is None:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
145 t1 = {}
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
146 if t2 is None:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
147 t2 = {}
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
148
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
149 for e1 in t1:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
150 realname = subdir + pycompat.fsencode(e1.name)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
151
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
152 if e1.type == pygit2.GIT_OBJ_TREE:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
153 try:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
154 e2 = t2[e1.name]
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
155 if e2.type != pygit2.GIT_OBJ_TREE:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
156 e2 = None
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
157 except KeyError:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
158 e2 = None
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
159
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
160 stack.append((realname + b'/', e1, e2))
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
161 else:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
162 n1, fl1 = self.find(realname)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
163
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
164 try:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
165 e2 = t2[e1.name]
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
166 n2, fl2 = other.find(realname)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
167 except KeyError:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
168 e2 = None
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
169 n2, fl2 = (None, b'')
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 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
172 stack.append((realname + b'/', None, e2))
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
173
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
174 if not match(realname):
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
175 continue
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
176
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
177 if n1 != n2 or fl1 != fl2:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
178 result[realname] = ((n1, fl1), (n2, fl2))
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
179 elif clean:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
180 result[realname] = None
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
181
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
182 for e2 in t2:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
183 if e2.name in t1:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
184 continue
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 realname = subdir + pycompat.fsencode(e2.name)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
187
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
188 if e2.type == pygit2.GIT_OBJ_TREE:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
189 stack.append((realname + b'/', None, e2))
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
190 elif match(realname):
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
191 n2, fl2 = other.find(realname)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
192 result[realname] = ((None, b''), (n2, fl2))
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
193
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
194 stack = []
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
195 _iterativediff(self._tree, other._tree, b'')
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
196 while stack:
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
197 subdir, t1, t2 = stack.pop()
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
198 # stack is populated in the function call
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
199 _iterativediff(t1, t2, subdir)
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
200
f294b4e14fd0 git: implement diff manifest method
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44930
diff changeset
201 return result
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
202
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
203 def setflag(self, path, flag):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
204 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
205 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
206
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
207 def get(self, path, default=None):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
208 try:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
209 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
210 except KeyError:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
211 return default
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
212
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
213 def flags(self, path):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
214 try:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
215 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
216 except KeyError:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
217 return b''
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
218
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
219 def copy(self):
45417
c8695439d7e3 git: actually copy treemanifest instances in .copy() (issue6398)
Augie Fackler <raf@durin42.com>
parents: 44931
diff changeset
220 return gittreemanifest(
c8695439d7e3 git: actually copy treemanifest instances in .copy() (issue6398)
Augie Fackler <raf@durin42.com>
parents: 44931
diff changeset
221 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
222 )
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
223
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
224 def items(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
225 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
226 # TODO: build a proper iterator version of this
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
227 yield self[f]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
228
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
229 def iteritems(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
230 return self.items()
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
231
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
232 def iterentries(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
233 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
234 # TODO: build a proper iterator version of this
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
235 yield self._resolve_entry(f)
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
236
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
237 def text(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
238 assert False # TODO can this method move out of the manifest iface?
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
239
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
240 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
241 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
242 # 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
243 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
244 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
245 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
246 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
247 ):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
248 yield inner
44929
3679c88b7f4e git: don't yield paths for directories when walking
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44928
diff changeset
249 elif match(realname):
3679c88b7f4e git: don't yield paths for directories when walking
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 44928
diff changeset
250 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
251
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
252 def walk(self, match):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
253 # 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
254 # 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
255 # 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
256 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
257 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
258 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
259 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
260
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
261
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
262 @interfaceutil.implementer(repository.imanifestrevisionstored)
48946
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
263 class gittreemanifestctx:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
264 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
265 self._repo = repo
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
266 self._tree = gittree
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
267
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
268 def read(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
269 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
270
44479
7518ea76eff4 git: add readfast() method to manifest
Augie Fackler <raf@durin42.com>
parents: 44477
diff changeset
271 def readfast(self, shallow=False):
7518ea76eff4 git: add readfast() method to manifest
Augie Fackler <raf@durin42.com>
parents: 44477
diff changeset
272 return self.read()
7518ea76eff4 git: add readfast() method to manifest
Augie Fackler <raf@durin42.com>
parents: 44477
diff changeset
273
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
274 def copy(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
275 # 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
276 # 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
277 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
278
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
279 def find(self, path):
44843
288328c6711b git: fix probable missing return
Romain DEP. <rom1dep@gmail.com>
parents: 44625
diff changeset
280 return self.read()[path]
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
281
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
282
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
283 @interfaceutil.implementer(repository.imanifestrevisionwritable)
48946
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
284 class memgittreemanifestctx:
44477
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
285 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
286 self._repo = repo
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
287 self._tree = tree
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
288 # 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
289 self._pending_changes = {}
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
290
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
291 def read(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
292 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
293
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
294 def copy(self):
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
295 # 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
296 # 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
297 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
298
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
299 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
300 # 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
301 # 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
302
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
303 # 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
304 # just narrow?
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
305 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
306
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
307 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
308 trees = {
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
309 b'': self._tree,
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
310 }
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
311 # path: treebuilder
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
312 builders = {
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
313 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
314 }
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
315 # 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
316 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
317 if d == b'':
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
318 # 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
319 continue
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
320 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
321 full = b''
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
322 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
323 parent = trees[full]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
324 try:
45516
73a5aa5e1857 git: pass `id` attribute of `pygit2.Tree` object
Connor Sheehan <sheehan@mozilla.com>
parents: 45417
diff changeset
325 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
326 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
327 except KeyError:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
328 # new directory
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
329 new = None
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
330 full += b'/' + part
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
331 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
332 # existing directory
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
333 trees[full] = new
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
334 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
335 else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
336 # 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
337 # 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
338 # created.
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
339 trees[full] = {}
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
340 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
341 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
342 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
343 dirname = b''
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
344 basename = f
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
345 else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
346 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
347 dirname = b'/' + dirname
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
348 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
349 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
350 else:
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
351 n, fl = info
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
352 mode = {
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
353 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
354 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
355 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
356 }[fl]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
357 builders[dirname].insert(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
358 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
359 )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
360 # 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
361 # 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
362 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
363 if b == b'':
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
364 break
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
365 cb = builders[b]
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
366 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
367 builders[dn].insert(
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
368 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
369 )
ad718271a9eb git: skeleton of a new extension to _directly_ operate on git repos
Augie Fackler <augie@google.com>
parents:
diff changeset
370 return builders[b''].write().raw