Mercurial > hg > mercurial-crew-with-dirclash
annotate mercurial/manifest.py @ 1109:ee817c5e3ece
Merge with TAH
author | mpm@selenic.com |
---|---|
date | Sat, 27 Aug 2005 17:26:26 -0700 |
parents | 50a0a36dd48a |
children | cf9a1233738a |
rev | line source |
---|---|
1089 | 1 # manifest.py - manifest revision class for mercurial |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
2 # |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
3 # Copyright 2005 Matt Mackall <mpm@selenic.com> |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
4 # |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
5 # This software may be used and distributed according to the terms |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
6 # of the GNU General Public License, incorporated herein by reference. |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
7 |
1089 | 8 import sys, struct |
262 | 9 from revlog import * |
10 from demandload import * | |
1089 | 11 demandload(globals(), "bisect") |
79 | 12 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
13 class manifest(revlog): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
14 def __init__(self, opener): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
15 self.mapcache = None |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
16 self.listcache = None |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
17 self.addlist = None |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
18 revlog.__init__(self, opener, "00manifest.i", "00manifest.d") |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
19 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
20 def read(self, node): |
313 | 21 if node == nullid: return {} # don't upset local cache |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
22 if self.mapcache and self.mapcache[0] == node: |
561 | 23 return self.mapcache[1] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
24 text = self.revision(node) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
25 map = {} |
276 | 26 flag = {} |
25
daa724b27300
Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents:
20
diff
changeset
|
27 self.listcache = (text, text.splitlines(1)) |
daa724b27300
Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents:
20
diff
changeset
|
28 for l in self.listcache[1]: |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
29 (f, n) = l.split('\0') |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
30 map[f] = bin(n[:40]) |
276 | 31 flag[f] = (n[40:-1] == "x") |
32 self.mapcache = (node, map, flag) | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
33 return map |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
34 |
276 | 35 def readflags(self, node): |
313 | 36 if node == nullid: return {} # don't upset local cache |
358
9f4077d7ef6f
[PATCH] manifest.readflags performance buglet
mpm@selenic.com
parents:
350
diff
changeset
|
37 if not self.mapcache or self.mapcache[0] != node: |
276 | 38 self.read(node) |
39 return self.mapcache[2] | |
40 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
41 def diff(self, a, b): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
42 # this is sneaky, as we're not actually using a and b |
140 | 43 if self.listcache and self.addlist and self.listcache[0] == a: |
98 | 44 d = mdiff.diff(self.listcache[1], self.addlist, 1) |
45 if mdiff.patch(a, d) != b: | |
1098
50a0a36dd48a
manifest: convert sys.stderr bits to AssertionError
mpm@selenic.com
parents:
1089
diff
changeset
|
46 raise AssertionError("sortdiff failed!") |
98 | 47 return d |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
48 else: |
44 | 49 return mdiff.textdiff(a, b) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
50 |
741 | 51 def add(self, map, flags, transaction, link, p1=None, p2=None, |
52 changed=None): | |
644 | 53 # directly generate the mdiff delta from the data collected during |
54 # the bisect loop below | |
55 def gendelta(delta): | |
56 i = 0 | |
57 result = [] | |
58 while i < len(delta): | |
59 start = delta[i][2] | |
60 end = delta[i][3] | |
61 l = delta[i][4] | |
62 if l == None: | |
63 l = "" | |
741 | 64 while i < len(delta) - 1 and start <= delta[i+1][2] \ |
65 and end >= delta[i+1][2]: | |
644 | 66 if delta[i+1][3] > end: |
67 end = delta[i+1][3] | |
68 if delta[i+1][4]: | |
69 l += delta[i+1][4] | |
70 i += 1 | |
71 result.append(struct.pack(">lll", start, end, len(l)) + l) | |
72 i += 1 | |
73 return result | |
74 | |
75 # apply the changes collected during the bisect loop to our addlist | |
76 def addlistdelta(addlist, delta): | |
77 # apply the deltas to the addlist. start from the bottom up | |
78 # so changes to the offsets don't mess things up. | |
79 i = len(delta) | |
80 while i > 0: | |
81 i -= 1 | |
82 start = delta[i][0] | |
83 end = delta[i][1] | |
84 if delta[i][4]: | |
85 addlist[start:end] = [delta[i][4]] | |
86 else: | |
87 del addlist[start:end] | |
88 return addlist | |
89 | |
90 # calculate the byte offset of the start of each line in the | |
91 # manifest | |
92 def calcoffsets(addlist): | |
93 offsets = [0] * (len(addlist) + 1) | |
94 offset = 0 | |
95 i = 0 | |
96 while i < len(addlist): | |
97 offsets[i] = offset | |
98 offset += len(addlist[i]) | |
99 i += 1 | |
100 offsets[i] = offset | |
101 return offsets | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
102 |
644 | 103 # if we're using the listcache, make sure it is valid and |
104 # parented by the same node we're diffing against | |
741 | 105 if not changed or not self.listcache or not p1 or \ |
106 self.mapcache[0] != p1: | |
644 | 107 files = map.keys() |
108 files.sort() | |
109 | |
110 self.addlist = ["%s\000%s%s\n" % | |
111 (f, hex(map[f]), flags[f] and "x" or '') | |
112 for f in files] | |
113 cachedelta = None | |
114 else: | |
115 addlist = self.listcache[1] | |
116 | |
117 # find the starting offset for each line in the add list | |
118 offsets = calcoffsets(addlist) | |
119 | |
120 # combine the changed lists into one list for sorting | |
121 work = [[x, 0] for x in changed[0]] | |
122 work[len(work):] = [[x, 1] for x in changed[1]] | |
123 work.sort() | |
124 | |
125 delta = [] | |
126 bs = 0 | |
127 | |
128 for w in work: | |
129 f = w[0] | |
741 | 130 # bs will either be the index of the item or the insert point |
644 | 131 bs = bisect.bisect(addlist, f, bs) |
132 if bs < len(addlist): | |
133 fn = addlist[bs][:addlist[bs].index('\0')] | |
134 else: | |
135 fn = None | |
136 if w[1] == 0: | |
741 | 137 l = "%s\000%s%s\n" % (f, hex(map[f]), |
138 flags[f] and "x" or '') | |
644 | 139 else: |
140 l = None | |
141 start = bs | |
142 if fn != f: | |
143 # item not found, insert a new one | |
659 | 144 end = bs |
644 | 145 if w[1] == 1: |
1098
50a0a36dd48a
manifest: convert sys.stderr bits to AssertionError
mpm@selenic.com
parents:
1089
diff
changeset
|
146 raise AssertionError( |
50a0a36dd48a
manifest: convert sys.stderr bits to AssertionError
mpm@selenic.com
parents:
1089
diff
changeset
|
147 "failed to remove %s from manifest\n" % f) |
644 | 148 else: |
149 # item is found, replace/delete the existing line | |
150 end = bs + 1 | |
151 delta.append([start, end, offsets[start], offsets[end], l]) | |
152 | |
153 self.addlist = addlistdelta(addlist, delta) | |
154 if self.mapcache[0] == self.tip(): | |
155 cachedelta = "".join(gendelta(delta)) | |
156 else: | |
157 cachedelta = None | |
158 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
159 text = "".join(self.addlist) |
644 | 160 if cachedelta and mdiff.patch(self.listcache[0], cachedelta) != text: |
1098
50a0a36dd48a
manifest: convert sys.stderr bits to AssertionError
mpm@selenic.com
parents:
1089
diff
changeset
|
161 raise AssertionError("manifest delta failure\n") |
644 | 162 n = self.addrevision(text, transaction, link, p1, p2, cachedelta) |
302 | 163 self.mapcache = (n, map, flags) |
25
daa724b27300
Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents:
20
diff
changeset
|
164 self.listcache = (text, self.addlist) |
140 | 165 self.addlist = None |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
166 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
167 return n |