888 subp2 = m2._dirs.get(d, emptytree)._node |
888 subp2 = m2._dirs.get(d, emptytree)._node |
889 if subp1 == revlog.nullid: |
889 if subp1 == revlog.nullid: |
890 subp1, subp2 = subp2, subp1 |
890 subp1, subp2 = subp2, subp1 |
891 writesubtree(subm, subp1, subp2) |
891 writesubtree(subm, subp1, subp2) |
892 |
892 |
893 class manifest(revlog.revlog): |
893 class manifestrevlog(revlog.revlog): |
|
894 '''A revlog that stores manifest texts. This is responsible for caching the |
|
895 full-text manifest contents. |
|
896 ''' |
|
897 def __init__(self, opener, indexfile): |
|
898 super(manifestrevlog, self).__init__(opener, indexfile) |
|
899 |
|
900 # During normal operations, we expect to deal with not more than four |
|
901 # revs at a time (such as during commit --amend). When rebasing large |
|
902 # stacks of commits, the number can go up, hence the config knob below. |
|
903 cachesize = 4 |
|
904 opts = getattr(opener, 'options', None) |
|
905 if opts is not None: |
|
906 cachesize = opts.get('manifestcachesize', cachesize) |
|
907 self._fulltextcache = util.lrucachedict(cachesize) |
|
908 |
|
909 @property |
|
910 def fulltextcache(self): |
|
911 return self._fulltextcache |
|
912 |
|
913 def clearcaches(self): |
|
914 super(manifestrevlog, self).clearcaches() |
|
915 self._fulltextcache.clear() |
|
916 |
|
917 class manifest(manifestrevlog): |
894 def __init__(self, opener, dir='', dirlogcache=None): |
918 def __init__(self, opener, dir='', dirlogcache=None): |
895 '''The 'dir' and 'dirlogcache' arguments are for internal use by |
919 '''The 'dir' and 'dirlogcache' arguments are for internal use by |
896 manifest.manifest only. External users should create a root manifest |
920 manifest.manifest only. External users should create a root manifest |
897 log with manifest.manifest(opener) and call dirlog() on it. |
921 log with manifest.manifest(opener) and call dirlog() on it. |
898 ''' |
922 ''' |
906 if opts is not None: |
930 if opts is not None: |
907 cachesize = opts.get('manifestcachesize', cachesize) |
931 cachesize = opts.get('manifestcachesize', cachesize) |
908 usetreemanifest = opts.get('treemanifest', usetreemanifest) |
932 usetreemanifest = opts.get('treemanifest', usetreemanifest) |
909 usemanifestv2 = opts.get('manifestv2', usemanifestv2) |
933 usemanifestv2 = opts.get('manifestv2', usemanifestv2) |
910 self._mancache = util.lrucachedict(cachesize) |
934 self._mancache = util.lrucachedict(cachesize) |
911 self._fulltextcache = util.lrucachedict(cachesize) |
|
912 self._treeinmem = usetreemanifest |
935 self._treeinmem = usetreemanifest |
913 self._treeondisk = usetreemanifest |
936 self._treeondisk = usetreemanifest |
914 self._usemanifestv2 = usemanifestv2 |
937 self._usemanifestv2 = usemanifestv2 |
915 indexfile = "00manifest.i" |
938 indexfile = "00manifest.i" |
916 if dir: |
939 if dir: |
917 assert self._treeondisk, 'opts is %r' % opts |
940 assert self._treeondisk, 'opts is %r' % opts |
918 if not dir.endswith('/'): |
941 if not dir.endswith('/'): |
919 dir = dir + '/' |
942 dir = dir + '/' |
920 indexfile = "meta/" + dir + "00manifest.i" |
943 indexfile = "meta/" + dir + "00manifest.i" |
921 revlog.revlog.__init__(self, opener, indexfile) |
944 super(manifest, self).__init__(opener, indexfile) |
922 self._dir = dir |
945 self._dir = dir |
923 # The dirlogcache is kept on the root manifest log |
946 # The dirlogcache is kept on the root manifest log |
924 if dir: |
947 if dir: |
925 self._dirlogcache = dirlogcache |
948 self._dirlogcache = dirlogcache |
926 else: |
949 else: |
1014 else: |
1037 else: |
1015 text = self.revision(node) |
1038 text = self.revision(node) |
1016 m = self._newmanifest(text) |
1039 m = self._newmanifest(text) |
1017 arraytext = array.array('c', text) |
1040 arraytext = array.array('c', text) |
1018 self._mancache[node] = m |
1041 self._mancache[node] = m |
1019 self._fulltextcache[node] = arraytext |
1042 self.fulltextcache[node] = arraytext |
1020 return m |
1043 return m |
1021 |
1044 |
1022 def readshallow(self, node): |
1045 def readshallow(self, node): |
1023 '''Reads the manifest in this directory. When using flat manifests, |
1046 '''Reads the manifest in this directory. When using flat manifests, |
1024 this manifest will generally have files in subdirectories in it. Does |
1047 this manifest will generally have files in subdirectories in it. Does |
1034 return m.find(f) |
1057 return m.find(f) |
1035 except KeyError: |
1058 except KeyError: |
1036 return None, None |
1059 return None, None |
1037 |
1060 |
1038 def add(self, m, transaction, link, p1, p2, added, removed): |
1061 def add(self, m, transaction, link, p1, p2, added, removed): |
1039 if (p1 in self._fulltextcache and not self._treeinmem |
1062 if (p1 in self.fulltextcache and not self._treeinmem |
1040 and not self._usemanifestv2): |
1063 and not self._usemanifestv2): |
1041 # If our first parent is in the manifest cache, we can |
1064 # If our first parent is in the manifest cache, we can |
1042 # compute a delta here using properties we know about the |
1065 # compute a delta here using properties we know about the |
1043 # manifest up-front, which may save time later for the |
1066 # manifest up-front, which may save time later for the |
1044 # revlog layer. |
1067 # revlog layer. |
1046 _checkforbidden(added) |
1069 _checkforbidden(added) |
1047 # combine the changed lists into one sorted iterator |
1070 # combine the changed lists into one sorted iterator |
1048 work = heapq.merge([(x, False) for x in added], |
1071 work = heapq.merge([(x, False) for x in added], |
1049 [(x, True) for x in removed]) |
1072 [(x, True) for x in removed]) |
1050 |
1073 |
1051 arraytext, deltatext = m.fastdelta(self._fulltextcache[p1], work) |
1074 arraytext, deltatext = m.fastdelta(self.fulltextcache[p1], work) |
1052 cachedelta = self.rev(p1), deltatext |
1075 cachedelta = self.rev(p1), deltatext |
1053 text = util.buffer(arraytext) |
1076 text = util.buffer(arraytext) |
1054 n = self.addrevision(text, transaction, link, p1, p2, cachedelta) |
1077 n = self.addrevision(text, transaction, link, p1, p2, cachedelta) |
1055 else: |
1078 else: |
1056 # The first parent manifest isn't already loaded, so we'll |
1079 # The first parent manifest isn't already loaded, so we'll |
1066 text = m.text(self._usemanifestv2) |
1089 text = m.text(self._usemanifestv2) |
1067 n = self.addrevision(text, transaction, link, p1, p2) |
1090 n = self.addrevision(text, transaction, link, p1, p2) |
1068 arraytext = array.array('c', text) |
1091 arraytext = array.array('c', text) |
1069 |
1092 |
1070 self._mancache[n] = m |
1093 self._mancache[n] = m |
1071 self._fulltextcache[n] = arraytext |
1094 self.fulltextcache[n] = arraytext |
1072 |
1095 |
1073 return n |
1096 return n |
1074 |
1097 |
1075 def _addtree(self, m, transaction, link, m1, m2): |
1098 def _addtree(self, m, transaction, link, m1, m2): |
1076 # If the manifest is unchanged compared to one parent, |
1099 # If the manifest is unchanged compared to one parent, |