Show More
@@ -8,7 +8,6 b'' | |||||
8 | from __future__ import absolute_import |
|
8 | from __future__ import absolute_import | |
9 |
|
9 | |||
10 | from mercurial import ( |
|
10 | from mercurial import ( | |
11 | error, |
|
|||
12 | manifest, |
|
11 | manifest, | |
13 | revlog, |
|
12 | revlog, | |
14 | util, |
|
13 | util, | |
@@ -31,83 +30,6 b' def setup():' | |||||
31 | # load time. |
|
30 | # load time. | |
32 | pass |
|
31 | pass | |
33 |
|
32 | |||
34 | class excludeddir(manifest.treemanifest): |
|
|||
35 | """Stand-in for a directory that is excluded from the repository. |
|
|||
36 |
|
||||
37 | With narrowing active on a repository that uses treemanifests, |
|
|||
38 | some of the directory revlogs will be excluded from the resulting |
|
|||
39 | clone. This is a huge storage win for clients, but means we need |
|
|||
40 | some sort of pseudo-manifest to surface to internals so we can |
|
|||
41 | detect a merge conflict outside the narrowspec. That's what this |
|
|||
42 | class is: it stands in for a directory whose node is known, but |
|
|||
43 | whose contents are unknown. |
|
|||
44 | """ |
|
|||
45 | def __init__(self, dir, node): |
|
|||
46 | super(excludeddir, self).__init__(dir) |
|
|||
47 | self._node = node |
|
|||
48 | # Add an empty file, which will be included by iterators and such, |
|
|||
49 | # appearing as the directory itself (i.e. something like "dir/") |
|
|||
50 | self._files[''] = node |
|
|||
51 | self._flags[''] = 't' |
|
|||
52 |
|
||||
53 | # Manifests outside the narrowspec should never be modified, so avoid |
|
|||
54 | # copying. This makes a noticeable difference when there are very many |
|
|||
55 | # directories outside the narrowspec. Also, it makes sense for the copy to |
|
|||
56 | # be of the same type as the original, which would not happen with the |
|
|||
57 | # super type's copy(). |
|
|||
58 | def copy(self): |
|
|||
59 | return self |
|
|||
60 |
|
||||
61 | class excludeddirmanifestctx(manifest.treemanifestctx): |
|
|||
62 | """context wrapper for excludeddir - see that docstring for rationale""" |
|
|||
63 | def __init__(self, dir, node): |
|
|||
64 | self._dir = dir |
|
|||
65 | self._node = node |
|
|||
66 |
|
||||
67 | def read(self): |
|
|||
68 | return excludeddir(self._dir, self._node) |
|
|||
69 |
|
||||
70 | def write(self, *args): |
|
|||
71 | raise error.ProgrammingError( |
|
|||
72 | 'attempt to write manifest from excluded dir %s' % self._dir) |
|
|||
73 |
|
||||
74 | class excludedmanifestrevlog(manifest.manifestrevlog): |
|
|||
75 | """Stand-in for excluded treemanifest revlogs. |
|
|||
76 |
|
||||
77 | When narrowing is active on a treemanifest repository, we'll have |
|
|||
78 | references to directories we can't see due to the revlog being |
|
|||
79 | skipped. This class exists to conform to the manifestrevlog |
|
|||
80 | interface for those directories and proactively prevent writes to |
|
|||
81 | outside the narrowspec. |
|
|||
82 | """ |
|
|||
83 |
|
||||
84 | def __init__(self, dir): |
|
|||
85 | self._dir = dir |
|
|||
86 |
|
||||
87 | def __len__(self): |
|
|||
88 | raise error.ProgrammingError( |
|
|||
89 | 'attempt to get length of excluded dir %s' % self._dir) |
|
|||
90 |
|
||||
91 | def rev(self, node): |
|
|||
92 | raise error.ProgrammingError( |
|
|||
93 | 'attempt to get rev from excluded dir %s' % self._dir) |
|
|||
94 |
|
||||
95 | def linkrev(self, node): |
|
|||
96 | raise error.ProgrammingError( |
|
|||
97 | 'attempt to get linkrev from excluded dir %s' % self._dir) |
|
|||
98 |
|
||||
99 | def node(self, rev): |
|
|||
100 | raise error.ProgrammingError( |
|
|||
101 | 'attempt to get node from excluded dir %s' % self._dir) |
|
|||
102 |
|
||||
103 | def add(self, *args, **kwargs): |
|
|||
104 | # We should never write entries in dirlogs outside the narrow clone. |
|
|||
105 | # However, the method still gets called from writesubtree() in |
|
|||
106 | # _addtree(), so we need to handle it. We should possibly make that |
|
|||
107 | # avoid calling add() with a clean manifest (_dirty is always False |
|
|||
108 | # in excludeddir instances). |
|
|||
109 | pass |
|
|||
110 |
|
||||
111 | def makenarrowmanifestrevlog(mfrevlog, repo): |
|
33 | def makenarrowmanifestrevlog(mfrevlog, repo): | |
112 | if util.safehasattr(mfrevlog, '_narrowed'): |
|
34 | if util.safehasattr(mfrevlog, '_narrowed'): | |
113 | return |
|
35 | return | |
@@ -118,7 +40,7 b' def makenarrowmanifestrevlog(mfrevlog, r' | |||||
118 | # child directories when using treemanifests. |
|
40 | # child directories when using treemanifests. | |
119 | def dirlog(self, d): |
|
41 | def dirlog(self, d): | |
120 | if not repo.narrowmatch().visitdir(d[:-1] or '.'): |
|
42 | if not repo.narrowmatch().visitdir(d[:-1] or '.'): | |
121 | return excludedmanifestrevlog(d) |
|
43 | return manifest.excludedmanifestrevlog(d) | |
122 | result = super(narrowmanifestrevlog, self).dirlog(d) |
|
44 | result = super(narrowmanifestrevlog, self).dirlog(d) | |
123 | makenarrowmanifestrevlog(result, repo) |
|
45 | makenarrowmanifestrevlog(result, repo) | |
124 | return result |
|
46 | return result | |
@@ -130,7 +52,7 b' def makenarrowmanifestlog(mfl, repo):' | |||||
130 | class narrowmanifestlog(mfl.__class__): |
|
52 | class narrowmanifestlog(mfl.__class__): | |
131 | def get(self, dir, node, verify=True): |
|
53 | def get(self, dir, node, verify=True): | |
132 | if not repo.narrowmatch().visitdir(dir[:-1] or '.'): |
|
54 | if not repo.narrowmatch().visitdir(dir[:-1] or '.'): | |
133 | return excludeddirmanifestctx(dir, node) |
|
55 | return manifest.excludeddirmanifestctx(dir, node) | |
134 | return super(narrowmanifestlog, self).get(dir, node, verify=verify) |
|
56 | return super(narrowmanifestlog, self).get(dir, node, verify=verify) | |
135 | mfl.__class__ = narrowmanifestlog |
|
57 | mfl.__class__ = narrowmanifestlog | |
136 |
|
58 |
@@ -1569,3 +1569,80 b' class treemanifestctx(object):' | |||||
1569 |
|
1569 | |||
1570 | def find(self, key): |
|
1570 | def find(self, key): | |
1571 | return self.read().find(key) |
|
1571 | return self.read().find(key) | |
|
1572 | ||||
|
1573 | class excludeddir(treemanifest): | |||
|
1574 | """Stand-in for a directory that is excluded from the repository. | |||
|
1575 | ||||
|
1576 | With narrowing active on a repository that uses treemanifests, | |||
|
1577 | some of the directory revlogs will be excluded from the resulting | |||
|
1578 | clone. This is a huge storage win for clients, but means we need | |||
|
1579 | some sort of pseudo-manifest to surface to internals so we can | |||
|
1580 | detect a merge conflict outside the narrowspec. That's what this | |||
|
1581 | class is: it stands in for a directory whose node is known, but | |||
|
1582 | whose contents are unknown. | |||
|
1583 | """ | |||
|
1584 | def __init__(self, dir, node): | |||
|
1585 | super(excludeddir, self).__init__(dir) | |||
|
1586 | self._node = node | |||
|
1587 | # Add an empty file, which will be included by iterators and such, | |||
|
1588 | # appearing as the directory itself (i.e. something like "dir/") | |||
|
1589 | self._files[''] = node | |||
|
1590 | self._flags[''] = 't' | |||
|
1591 | ||||
|
1592 | # Manifests outside the narrowspec should never be modified, so avoid | |||
|
1593 | # copying. This makes a noticeable difference when there are very many | |||
|
1594 | # directories outside the narrowspec. Also, it makes sense for the copy to | |||
|
1595 | # be of the same type as the original, which would not happen with the | |||
|
1596 | # super type's copy(). | |||
|
1597 | def copy(self): | |||
|
1598 | return self | |||
|
1599 | ||||
|
1600 | class excludeddirmanifestctx(treemanifestctx): | |||
|
1601 | """context wrapper for excludeddir - see that docstring for rationale""" | |||
|
1602 | def __init__(self, dir, node): | |||
|
1603 | self._dir = dir | |||
|
1604 | self._node = node | |||
|
1605 | ||||
|
1606 | def read(self): | |||
|
1607 | return excludeddir(self._dir, self._node) | |||
|
1608 | ||||
|
1609 | def write(self, *args): | |||
|
1610 | raise error.ProgrammingError( | |||
|
1611 | 'attempt to write manifest from excluded dir %s' % self._dir) | |||
|
1612 | ||||
|
1613 | class excludedmanifestrevlog(manifestrevlog): | |||
|
1614 | """Stand-in for excluded treemanifest revlogs. | |||
|
1615 | ||||
|
1616 | When narrowing is active on a treemanifest repository, we'll have | |||
|
1617 | references to directories we can't see due to the revlog being | |||
|
1618 | skipped. This class exists to conform to the manifestrevlog | |||
|
1619 | interface for those directories and proactively prevent writes to | |||
|
1620 | outside the narrowspec. | |||
|
1621 | """ | |||
|
1622 | ||||
|
1623 | def __init__(self, dir): | |||
|
1624 | self._dir = dir | |||
|
1625 | ||||
|
1626 | def __len__(self): | |||
|
1627 | raise error.ProgrammingError( | |||
|
1628 | 'attempt to get length of excluded dir %s' % self._dir) | |||
|
1629 | ||||
|
1630 | def rev(self, node): | |||
|
1631 | raise error.ProgrammingError( | |||
|
1632 | 'attempt to get rev from excluded dir %s' % self._dir) | |||
|
1633 | ||||
|
1634 | def linkrev(self, node): | |||
|
1635 | raise error.ProgrammingError( | |||
|
1636 | 'attempt to get linkrev from excluded dir %s' % self._dir) | |||
|
1637 | ||||
|
1638 | def node(self, rev): | |||
|
1639 | raise error.ProgrammingError( | |||
|
1640 | 'attempt to get node from excluded dir %s' % self._dir) | |||
|
1641 | ||||
|
1642 | def add(self, *args, **kwargs): | |||
|
1643 | # We should never write entries in dirlogs outside the narrow clone. | |||
|
1644 | # However, the method still gets called from writesubtree() in | |||
|
1645 | # _addtree(), so we need to handle it. We should possibly make that | |||
|
1646 | # avoid calling add() with a clean manifest (_dirty is always False | |||
|
1647 | # in excludeddir instances). | |||
|
1648 | pass |
General Comments 0
You need to be logged in to leave comments.
Login now