Show More
@@ -21,9 +21,13 from . import ( | |||||
21 | mdiff, |
|
21 | mdiff, | |
22 | policy, |
|
22 | policy, | |
23 | pycompat, |
|
23 | pycompat, | |
|
24 | repository, | |||
24 | revlog, |
|
25 | revlog, | |
25 | util, |
|
26 | util, | |
26 | ) |
|
27 | ) | |
|
28 | from .utils import ( | |||
|
29 | interfaceutil, | |||
|
30 | ) | |||
27 |
|
31 | |||
28 | parsers = policy.importmod(r'parsers') |
|
32 | parsers = policy.importmod(r'parsers') | |
29 | propertycache = util.propertycache |
|
33 | propertycache = util.propertycache | |
@@ -363,6 +367,7 try: | |||||
363 | except AttributeError: |
|
367 | except AttributeError: | |
364 | pass |
|
368 | pass | |
365 |
|
369 | |||
|
370 | @interfaceutil.implementer(repository.imanifestdict) | |||
366 | class manifestdict(object): |
|
371 | class manifestdict(object): | |
367 | def __init__(self, data=''): |
|
372 | def __init__(self, data=''): | |
368 | self._lm = _lazymanifest(data) |
|
373 | self._lm = _lazymanifest(data) | |
@@ -1262,6 +1267,7 class manifestrevlog(revlog.revlog): | |||||
1262 | m.setnode(n) |
|
1267 | m.setnode(n) | |
1263 | return n |
|
1268 | return n | |
1264 |
|
1269 | |||
|
1270 | @interfaceutil.implementer(repository.imanifestlog) | |||
1265 | class manifestlog(object): |
|
1271 | class manifestlog(object): | |
1266 | """A collection class representing the collection of manifest snapshots |
|
1272 | """A collection class representing the collection of manifest snapshots | |
1267 | referenced by commits in the repository. |
|
1273 | referenced by commits in the repository. | |
@@ -1342,6 +1348,7 class manifestlog(object): | |||||
1342 | self._dirmancache.clear() |
|
1348 | self._dirmancache.clear() | |
1343 | self._revlog.clearcaches() |
|
1349 | self._revlog.clearcaches() | |
1344 |
|
1350 | |||
|
1351 | @interfaceutil.implementer(repository.imanifestrevisionwritable) | |||
1345 | class memmanifestctx(object): |
|
1352 | class memmanifestctx(object): | |
1346 | def __init__(self, manifestlog): |
|
1353 | def __init__(self, manifestlog): | |
1347 | self._manifestlog = manifestlog |
|
1354 | self._manifestlog = manifestlog | |
@@ -1365,6 +1372,7 class memmanifestctx(object): | |||||
1365 | return self._revlog().add(self._manifestdict, transaction, link, p1, p2, |
|
1372 | return self._revlog().add(self._manifestdict, transaction, link, p1, p2, | |
1366 | added, removed) |
|
1373 | added, removed) | |
1367 |
|
1374 | |||
|
1375 | @interfaceutil.implementer(repository.imanifestrevisionstored) | |||
1368 | class manifestctx(object): |
|
1376 | class manifestctx(object): | |
1369 | """A class representing a single revision of a manifest, including its |
|
1377 | """A class representing a single revision of a manifest, including its | |
1370 | contents, its parent revs, and its linkrev. |
|
1378 | contents, its parent revs, and its linkrev. | |
@@ -1441,6 +1449,7 class manifestctx(object): | |||||
1441 | def find(self, key): |
|
1449 | def find(self, key): | |
1442 | return self.read().find(key) |
|
1450 | return self.read().find(key) | |
1443 |
|
1451 | |||
|
1452 | @interfaceutil.implementer(repository.imanifestrevisionwritable) | |||
1444 | class memtreemanifestctx(object): |
|
1453 | class memtreemanifestctx(object): | |
1445 | def __init__(self, manifestlog, dir=''): |
|
1454 | def __init__(self, manifestlog, dir=''): | |
1446 | self._manifestlog = manifestlog |
|
1455 | self._manifestlog = manifestlog | |
@@ -1467,6 +1476,7 class memtreemanifestctx(object): | |||||
1467 | return self._revlog().add(self._treemanifest, transaction, link, p1, p2, |
|
1476 | return self._revlog().add(self._treemanifest, transaction, link, p1, p2, | |
1468 | added, removed, readtree=readtree) |
|
1477 | added, removed, readtree=readtree) | |
1469 |
|
1478 | |||
|
1479 | @interfaceutil.implementer(repository.imanifestrevisionstored) | |||
1470 | class treemanifestctx(object): |
|
1480 | class treemanifestctx(object): | |
1471 | def __init__(self, manifestlog, dir, node): |
|
1481 | def __init__(self, manifestlog, dir, node): | |
1472 | self._manifestlog = manifestlog |
|
1482 | self._manifestlog = manifestlog |
@@ -642,6 +642,286 class ifilestorage(ifileindex, ifiledata | |||||
642 | TODO this is used by verify and it should not be part of the interface. |
|
642 | TODO this is used by verify and it should not be part of the interface. | |
643 | """ |
|
643 | """ | |
644 |
|
644 | |||
|
645 | class idirs(interfaceutil.Interface): | |||
|
646 | """Interface representing a collection of directories from paths. | |||
|
647 | ||||
|
648 | This interface is essentially a derived data structure representing | |||
|
649 | directories from a collection of paths. | |||
|
650 | """ | |||
|
651 | ||||
|
652 | def addpath(path): | |||
|
653 | """Add a path to the collection. | |||
|
654 | ||||
|
655 | All directories in the path will be added to the collection. | |||
|
656 | """ | |||
|
657 | ||||
|
658 | def delpath(path): | |||
|
659 | """Remove a path from the collection. | |||
|
660 | ||||
|
661 | If the removal was the last path in a particular directory, the | |||
|
662 | directory is removed from the collection. | |||
|
663 | """ | |||
|
664 | ||||
|
665 | def __iter__(): | |||
|
666 | """Iterate over the directories in this collection of paths.""" | |||
|
667 | ||||
|
668 | def __contains__(path): | |||
|
669 | """Whether a specific directory is in this collection.""" | |||
|
670 | ||||
|
671 | class imanifestdict(interfaceutil.Interface): | |||
|
672 | """Interface representing a manifest data structure. | |||
|
673 | ||||
|
674 | A manifest is effectively a dict mapping paths to entries. Each entry | |||
|
675 | consists of a binary node and extra flags affecting that entry. | |||
|
676 | """ | |||
|
677 | ||||
|
678 | def __getitem__(path): | |||
|
679 | """Returns the binary node value for a path in the manifest. | |||
|
680 | ||||
|
681 | Raises ``KeyError`` if the path does not exist in the manifest. | |||
|
682 | ||||
|
683 | Equivalent to ``self.find(path)[0]``. | |||
|
684 | """ | |||
|
685 | ||||
|
686 | def find(path): | |||
|
687 | """Returns the entry for a path in the manifest. | |||
|
688 | ||||
|
689 | Returns a 2-tuple of (node, flags). | |||
|
690 | ||||
|
691 | Raises ``KeyError`` if the path does not exist in the manifest. | |||
|
692 | """ | |||
|
693 | ||||
|
694 | def __len__(): | |||
|
695 | """Return the number of entries in the manifest.""" | |||
|
696 | ||||
|
697 | def __nonzero__(): | |||
|
698 | """Returns True if the manifest has entries, False otherwise.""" | |||
|
699 | ||||
|
700 | __bool__ = __nonzero__ | |||
|
701 | ||||
|
702 | def __setitem__(path, node): | |||
|
703 | """Define the node value for a path in the manifest. | |||
|
704 | ||||
|
705 | If the path is already in the manifest, its flags will be copied to | |||
|
706 | the new entry. | |||
|
707 | """ | |||
|
708 | ||||
|
709 | def __contains__(path): | |||
|
710 | """Whether a path exists in the manifest.""" | |||
|
711 | ||||
|
712 | def __delitem__(path): | |||
|
713 | """Remove a path from the manifest. | |||
|
714 | ||||
|
715 | Raises ``KeyError`` if the path is not in the manifest. | |||
|
716 | """ | |||
|
717 | ||||
|
718 | def __iter__(): | |||
|
719 | """Iterate over paths in the manifest.""" | |||
|
720 | ||||
|
721 | def iterkeys(): | |||
|
722 | """Iterate over paths in the manifest.""" | |||
|
723 | ||||
|
724 | def keys(): | |||
|
725 | """Obtain a list of paths in the manifest.""" | |||
|
726 | ||||
|
727 | def filesnotin(other, match=None): | |||
|
728 | """Obtain the set of paths in this manifest but not in another. | |||
|
729 | ||||
|
730 | ``match`` is an optional matcher function to be applied to both | |||
|
731 | manifests. | |||
|
732 | ||||
|
733 | Returns a set of paths. | |||
|
734 | """ | |||
|
735 | ||||
|
736 | def dirs(): | |||
|
737 | """Returns an object implementing the ``idirs`` interface.""" | |||
|
738 | ||||
|
739 | def hasdir(dir): | |||
|
740 | """Returns a bool indicating if a directory is in this manifest.""" | |||
|
741 | ||||
|
742 | def matches(match): | |||
|
743 | """Generate a new manifest filtered through a matcher. | |||
|
744 | ||||
|
745 | Returns an object conforming to the ``imanifestdict`` interface. | |||
|
746 | """ | |||
|
747 | ||||
|
748 | def walk(match): | |||
|
749 | """Generator of paths in manifest satisfying a matcher. | |||
|
750 | ||||
|
751 | This is equivalent to ``self.matches(match).iterkeys()`` except a new | |||
|
752 | manifest object is not created. | |||
|
753 | ||||
|
754 | If the matcher has explicit files listed and they don't exist in | |||
|
755 | the manifest, ``match.bad()`` is called for each missing file. | |||
|
756 | """ | |||
|
757 | ||||
|
758 | def diff(other, match=None, clean=False): | |||
|
759 | """Find differences between this manifest and another. | |||
|
760 | ||||
|
761 | This manifest is compared to ``other``. | |||
|
762 | ||||
|
763 | If ``match`` is provided, the two manifests are filtered against this | |||
|
764 | matcher and only entries satisfying the matcher are compared. | |||
|
765 | ||||
|
766 | If ``clean`` is True, unchanged files are included in the returned | |||
|
767 | object. | |||
|
768 | ||||
|
769 | Returns a dict with paths as keys and values of 2-tuples of 2-tuples of | |||
|
770 | the form ``((node1, flag1), (node2, flag2))`` where ``(node1, flag1)`` | |||
|
771 | represents the node and flags for this manifest and ``(node2, flag2)`` | |||
|
772 | are the same for the other manifest. | |||
|
773 | """ | |||
|
774 | ||||
|
775 | def setflag(path, flag): | |||
|
776 | """Set the flag value for a given path. | |||
|
777 | ||||
|
778 | Raises ``KeyError`` if the path is not already in the manifest. | |||
|
779 | """ | |||
|
780 | ||||
|
781 | def get(path, default=None): | |||
|
782 | """Obtain the node value for a path or a default value if missing.""" | |||
|
783 | ||||
|
784 | def flags(path, default=''): | |||
|
785 | """Return the flags value for a path or a default value if missing.""" | |||
|
786 | ||||
|
787 | def copy(): | |||
|
788 | """Return a copy of this manifest.""" | |||
|
789 | ||||
|
790 | def items(): | |||
|
791 | """Returns an iterable of (path, node) for items in this manifest.""" | |||
|
792 | ||||
|
793 | def iteritems(): | |||
|
794 | """Identical to items().""" | |||
|
795 | ||||
|
796 | def iterentries(): | |||
|
797 | """Returns an iterable of (path, node, flags) for this manifest. | |||
|
798 | ||||
|
799 | Similar to ``iteritems()`` except items are a 3-tuple and include | |||
|
800 | flags. | |||
|
801 | """ | |||
|
802 | ||||
|
803 | def text(): | |||
|
804 | """Obtain the raw data representation for this manifest. | |||
|
805 | ||||
|
806 | Result is used to create a manifest revision. | |||
|
807 | """ | |||
|
808 | ||||
|
809 | def fastdelta(base, changes): | |||
|
810 | """Obtain a delta between this manifest and another given changes. | |||
|
811 | ||||
|
812 | ``base`` in the raw data representation for another manifest. | |||
|
813 | ||||
|
814 | ``changes`` is an iterable of ``(path, to_delete)``. | |||
|
815 | ||||
|
816 | Returns a 2-tuple containing ``bytearray(self.text())`` and the | |||
|
817 | delta between ``base`` and this manifest. | |||
|
818 | """ | |||
|
819 | ||||
|
820 | class imanifestrevisionbase(interfaceutil.Interface): | |||
|
821 | """Base interface representing a single revision of a manifest. | |||
|
822 | ||||
|
823 | Should not be used as a primary interface: should always be inherited | |||
|
824 | as part of a larger interface. | |||
|
825 | """ | |||
|
826 | ||||
|
827 | def new(): | |||
|
828 | """Obtain a new manifest instance. | |||
|
829 | ||||
|
830 | Returns an object conforming to the ``imanifestrevisionwritable`` | |||
|
831 | interface. The instance will be associated with the same | |||
|
832 | ``imanifestlog`` collection as this instance. | |||
|
833 | """ | |||
|
834 | ||||
|
835 | def copy(): | |||
|
836 | """Obtain a copy of this manifest instance. | |||
|
837 | ||||
|
838 | Returns an object conforming to the ``imanifestrevisionwritable`` | |||
|
839 | interface. The instance will be associated with the same | |||
|
840 | ``imanifestlog`` collection as this instance. | |||
|
841 | """ | |||
|
842 | ||||
|
843 | def read(): | |||
|
844 | """Obtain the parsed manifest data structure. | |||
|
845 | ||||
|
846 | The returned object conforms to the ``imanifestdict`` interface. | |||
|
847 | """ | |||
|
848 | ||||
|
849 | class imanifestrevisionstored(imanifestrevisionbase): | |||
|
850 | """Interface representing a manifest revision committed to storage.""" | |||
|
851 | ||||
|
852 | def node(): | |||
|
853 | """The binary node for this manifest.""" | |||
|
854 | ||||
|
855 | parents = interfaceutil.Attribute( | |||
|
856 | """List of binary nodes that are parents for this manifest revision.""" | |||
|
857 | ) | |||
|
858 | ||||
|
859 | def readdelta(shallow=False): | |||
|
860 | """Obtain the manifest data structure representing changes from parent. | |||
|
861 | ||||
|
862 | This manifest is compared to its 1st parent. A new manifest representing | |||
|
863 | those differences is constructed. | |||
|
864 | ||||
|
865 | The returned object conforms to the ``imanifestdict`` interface. | |||
|
866 | """ | |||
|
867 | ||||
|
868 | def readfast(shallow=False): | |||
|
869 | """Calls either ``read()`` or ``readdelta()``. | |||
|
870 | ||||
|
871 | The faster of the two options is called. | |||
|
872 | """ | |||
|
873 | ||||
|
874 | def find(key): | |||
|
875 | """Calls self.read().find(key)``. | |||
|
876 | ||||
|
877 | Returns a 2-tuple of ``(node, flags)`` or raises ``KeyError``. | |||
|
878 | """ | |||
|
879 | ||||
|
880 | class imanifestrevisionwritable(imanifestrevisionbase): | |||
|
881 | """Interface representing a manifest revision that can be committed.""" | |||
|
882 | ||||
|
883 | def write(transaction, linkrev, p1node, p2node, added, removed): | |||
|
884 | """Add this revision to storage. | |||
|
885 | ||||
|
886 | Takes a transaction object, the changeset revision number it will | |||
|
887 | be associated with, its parent nodes, and lists of added and | |||
|
888 | removed paths. | |||
|
889 | ||||
|
890 | Returns the binary node of the created revision. | |||
|
891 | """ | |||
|
892 | ||||
|
893 | class imanifestlog(interfaceutil.Interface): | |||
|
894 | """Interface representing a collection of manifest snapshots.""" | |||
|
895 | ||||
|
896 | def __getitem__(node): | |||
|
897 | """Obtain a manifest instance for a given binary node. | |||
|
898 | ||||
|
899 | Equivalent to calling ``self.get('', node)``. | |||
|
900 | ||||
|
901 | The returned object conforms to the ``imanifestrevisionstored`` | |||
|
902 | interface. | |||
|
903 | """ | |||
|
904 | ||||
|
905 | def get(dir, node, verify=True): | |||
|
906 | """Retrieve the manifest instance for a given directory and binary node. | |||
|
907 | ||||
|
908 | ``node`` always refers to the node of the root manifest (which will be | |||
|
909 | the only manifest if flat manifests are being used). | |||
|
910 | ||||
|
911 | If ``dir`` is the empty string, the root manifest is returned. Otherwise | |||
|
912 | the manifest for the specified directory will be returned (requires | |||
|
913 | tree manifests). | |||
|
914 | ||||
|
915 | If ``verify`` is True, ``LookupError`` is raised if the node is not | |||
|
916 | known. | |||
|
917 | ||||
|
918 | The returned object conforms to the ``imanifestrevisionstored`` | |||
|
919 | interface. | |||
|
920 | """ | |||
|
921 | ||||
|
922 | def clearcaches(): | |||
|
923 | """Clear caches associated with this collection.""" | |||
|
924 | ||||
645 | class completelocalrepository(interfaceutil.Interface): |
|
925 | class completelocalrepository(interfaceutil.Interface): | |
646 | """Monolithic interface for local repositories. |
|
926 | """Monolithic interface for local repositories. | |
647 |
|
927 | |||
@@ -757,7 +1037,10 class completelocalrepository(interfaceu | |||||
757 | """A handle on the changelog revlog.""") |
|
1037 | """A handle on the changelog revlog.""") | |
758 |
|
1038 | |||
759 | manifestlog = interfaceutil.Attribute( |
|
1039 | manifestlog = interfaceutil.Attribute( | |
760 |
"""A |
|
1040 | """An instance conforming to the ``imanifestlog`` interface. | |
|
1041 | ||||
|
1042 | Provides access to manifests for the repository. | |||
|
1043 | """) | |||
761 |
|
1044 | |||
762 | dirstate = interfaceutil.Attribute( |
|
1045 | dirstate = interfaceutil.Attribute( | |
763 | """Working directory state.""") |
|
1046 | """Working directory state.""") |
@@ -25,6 +25,7 from mercurial import ( | |||||
25 | filelog, |
|
25 | filelog, | |
26 | httppeer, |
|
26 | httppeer, | |
27 | localrepo, |
|
27 | localrepo, | |
|
28 | manifest, | |||
28 | pycompat, |
|
29 | pycompat, | |
29 | repository, |
|
30 | repository, | |
30 | sshpeer, |
|
31 | sshpeer, | |
@@ -164,9 +165,35 def main(): | |||||
164 | checkzobject(httpv2) |
|
165 | checkzobject(httpv2) | |
165 |
|
166 | |||
166 | ziverify.verifyClass(repository.ifilestorage, filelog.filelog) |
|
167 | ziverify.verifyClass(repository.ifilestorage, filelog.filelog) | |
|
168 | ziverify.verifyClass(repository.imanifestdict, manifest.manifestdict) | |||
|
169 | ziverify.verifyClass(repository.imanifestrevisionstored, | |||
|
170 | manifest.manifestctx) | |||
|
171 | ziverify.verifyClass(repository.imanifestrevisionwritable, | |||
|
172 | manifest.memmanifestctx) | |||
|
173 | ziverify.verifyClass(repository.imanifestrevisionstored, | |||
|
174 | manifest.treemanifestctx) | |||
|
175 | ziverify.verifyClass(repository.imanifestrevisionwritable, | |||
|
176 | manifest.memtreemanifestctx) | |||
|
177 | ziverify.verifyClass(repository.imanifestlog, manifest.manifestlog) | |||
167 |
|
178 | |||
168 | vfs = vfsmod.vfs(b'.') |
|
179 | vfs = vfsmod.vfs(b'.') | |
169 | fl = filelog.filelog(vfs, b'dummy.i') |
|
180 | fl = filelog.filelog(vfs, b'dummy.i') | |
170 | checkzobject(fl, allowextra=True) |
|
181 | checkzobject(fl, allowextra=True) | |
171 |
|
182 | |||
|
183 | # Conforms to imanifestlog. | |||
|
184 | ml = manifest.manifestlog(vfs, repo) | |||
|
185 | checkzobject(ml) | |||
|
186 | checkzobject(repo.manifestlog) | |||
|
187 | ||||
|
188 | # Conforms to imanifestrevision. | |||
|
189 | mctx = ml[repo[0].manifestnode()] | |||
|
190 | checkzobject(mctx) | |||
|
191 | ||||
|
192 | # Conforms to imanifestrevisionwritable. | |||
|
193 | checkzobject(mctx.new()) | |||
|
194 | checkzobject(mctx.copy()) | |||
|
195 | ||||
|
196 | # Conforms to imanifestdict. | |||
|
197 | checkzobject(mctx.read()) | |||
|
198 | ||||
172 | main() |
|
199 | main() |
General Comments 0
You need to be logged in to leave comments.
Login now