Show More
@@ -8,7 +8,6 b'' | |||
|
8 | 8 | from __future__ import absolute_import |
|
9 | 9 | |
|
10 | 10 | from mercurial import ( |
|
11 | error, | |
|
12 | 11 | manifest, |
|
13 | 12 | revlog, |
|
14 | 13 | util, |
@@ -31,83 +30,6 b' def setup():' | |||
|
31 | 30 | # load time. |
|
32 | 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 | 33 | def makenarrowmanifestrevlog(mfrevlog, repo): |
|
112 | 34 | if util.safehasattr(mfrevlog, '_narrowed'): |
|
113 | 35 | return |
@@ -118,7 +40,7 b' def makenarrowmanifestrevlog(mfrevlog, r' | |||
|
118 | 40 | # child directories when using treemanifests. |
|
119 | 41 | def dirlog(self, d): |
|
120 | 42 | if not repo.narrowmatch().visitdir(d[:-1] or '.'): |
|
121 | return excludedmanifestrevlog(d) | |
|
43 | return manifest.excludedmanifestrevlog(d) | |
|
122 | 44 | result = super(narrowmanifestrevlog, self).dirlog(d) |
|
123 | 45 | makenarrowmanifestrevlog(result, repo) |
|
124 | 46 | return result |
@@ -130,7 +52,7 b' def makenarrowmanifestlog(mfl, repo):' | |||
|
130 | 52 | class narrowmanifestlog(mfl.__class__): |
|
131 | 53 | def get(self, dir, node, verify=True): |
|
132 | 54 | if not repo.narrowmatch().visitdir(dir[:-1] or '.'): |
|
133 | return excludeddirmanifestctx(dir, node) | |
|
55 | return manifest.excludeddirmanifestctx(dir, node) | |
|
134 | 56 | return super(narrowmanifestlog, self).get(dir, node, verify=verify) |
|
135 | 57 | mfl.__class__ = narrowmanifestlog |
|
136 | 58 |
@@ -1569,3 +1569,80 b' class treemanifestctx(object):' | |||
|
1569 | 1569 | |
|
1570 | 1570 | def find(self, key): |
|
1571 | 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