Show More
@@ -166,37 +166,44 b' class localrepository(object):' | |||||
166 | return |
|
166 | return | |
167 | s = l.split(" ", 1) |
|
167 | s = l.split(" ", 1) | |
168 | if len(s) != 2: |
|
168 | if len(s) != 2: | |
169 |
self.ui.warn(_("%s: |
|
169 | self.ui.warn(_("%s: cannot parse entry\n") % context) | |
170 | return |
|
170 | return | |
171 | node, key = s |
|
171 | node, key = s | |
|
172 | key = key.strip() | |||
172 | try: |
|
173 | try: | |
173 | bin_n = bin(node) |
|
174 | bin_n = bin(node) | |
174 | except TypeError: |
|
175 | except TypeError: | |
175 |
self.ui.warn(_("%s: |
|
176 | self.ui.warn(_("%s: node '%s' is not well formed\n") % | |
|
177 | (context, node)) | |||
176 | return |
|
178 | return | |
177 | if bin_n not in self.changelog.nodemap: |
|
179 | if bin_n not in self.changelog.nodemap: | |
178 |
self.ui.warn(_("%s: |
|
180 | self.ui.warn(_("%s: tag '%s' refers to unknown node\n") % | |
|
181 | (context, key)) | |||
179 | return |
|
182 | return | |
180 |
self.tagscache[key |
|
183 | self.tagscache[key] = bin_n | |
181 |
|
184 | |||
182 |
# read |
|
185 | # read the tags file from each head, ending with the tip, | |
183 | # and add each tag found to the map, with "newer" ones |
|
186 | # and add each tag found to the map, with "newer" ones | |
184 | # taking precedence |
|
187 | # taking precedence | |
|
188 | heads = self.heads() | |||
|
189 | heads.reverse() | |||
185 | fl = self.file(".hgtags") |
|
190 | fl = self.file(".hgtags") | |
186 |
|
|
191 | for node in heads: | |
187 | h.reverse() |
|
192 | change = self.changelog.read(node) | |
188 | for r in h: |
|
193 | rev = self.changelog.rev(node) | |
|
194 | fn, ff = self.manifest.find(change[0], '.hgtags') | |||
|
195 | if fn is None: continue | |||
189 | count = 0 |
|
196 | count = 0 | |
190 |
for l in fl.read( |
|
197 | for l in fl.read(fn).splitlines(): | |
191 | count += 1 |
|
198 | count += 1 | |
192 |
parsetag(l, ".hgtags:%d" % |
|
199 | parsetag(l, _(".hgtags (rev %d:%s), line %d") % | |
193 |
|
200 | (rev, short(node), count)) | ||
194 | try: |
|
201 | try: | |
195 | f = self.opener("localtags") |
|
202 | f = self.opener("localtags") | |
196 | count = 0 |
|
203 | count = 0 | |
197 | for l in f: |
|
204 | for l in f: | |
198 | count += 1 |
|
205 | count += 1 | |
199 |
parsetag(l, "localtags |
|
206 | parsetag(l, _("localtags, line %d") % count) | |
200 | except IOError: |
|
207 | except IOError: | |
201 | pass |
|
208 | pass | |
202 |
|
209 |
@@ -43,48 +43,61 b' class manifest(revlog):' | |||||
43 | def diff(self, a, b): |
|
43 | def diff(self, a, b): | |
44 | return mdiff.textdiff(str(a), str(b)) |
|
44 | return mdiff.textdiff(str(a), str(b)) | |
45 |
|
45 | |||
|
46 | def _search(self, m, s, lo=0, hi=None): | |||
|
47 | '''return a tuple (start, end) that says where to find s within m. | |||
|
48 | ||||
|
49 | If the string is found m[start:end] are the line containing | |||
|
50 | that string. If start == end the string was not found and | |||
|
51 | they indicate the proper sorted insertion point. This was | |||
|
52 | taken from bisect_left, and modified to find line start/end as | |||
|
53 | it goes along. | |||
|
54 | ||||
|
55 | m should be a buffer or a string | |||
|
56 | s is a string''' | |||
|
57 | def advance(i, c): | |||
|
58 | while i < lenm and m[i] != c: | |||
|
59 | i += 1 | |||
|
60 | return i | |||
|
61 | lenm = len(m) | |||
|
62 | if not hi: | |||
|
63 | hi = lenm | |||
|
64 | while lo < hi: | |||
|
65 | mid = (lo + hi) // 2 | |||
|
66 | start = mid | |||
|
67 | while start > 0 and m[start-1] != '\n': | |||
|
68 | start -= 1 | |||
|
69 | end = advance(start, '\0') | |||
|
70 | if m[start:end] < s: | |||
|
71 | # we know that after the null there are 40 bytes of sha1 | |||
|
72 | # this translates to the bisect lo = mid + 1 | |||
|
73 | lo = advance(end + 40, '\n') + 1 | |||
|
74 | else: | |||
|
75 | # this translates to the bisect hi = mid | |||
|
76 | hi = start | |||
|
77 | end = advance(lo, '\0') | |||
|
78 | found = m[lo:end] | |||
|
79 | if cmp(s, found) == 0: | |||
|
80 | # we know that after the null there are 40 bytes of sha1 | |||
|
81 | end = advance(end + 40, '\n') | |||
|
82 | return (lo, end+1) | |||
|
83 | else: | |||
|
84 | return (lo, lo) | |||
|
85 | ||||
|
86 | def find(self, node, f): | |||
|
87 | '''look up entry for a single file efficiently. | |||
|
88 | return (node, flag) pair if found, (None, None) if not.''' | |||
|
89 | if self.mapcache and node == self.mapcache[0]: | |||
|
90 | return self.mapcache[1].get(f), self.mapcache[2].get(f) | |||
|
91 | text = self.revision(node) | |||
|
92 | start, end = self._search(text, f) | |||
|
93 | if start == end: | |||
|
94 | return None, None | |||
|
95 | l = text[start:end] | |||
|
96 | f, n = l.split('\0') | |||
|
97 | return bin(n[:40]), n[40:-1] == 'x' | |||
|
98 | ||||
46 | def add(self, map, flags, transaction, link, p1=None, p2=None, |
|
99 | def add(self, map, flags, transaction, link, p1=None, p2=None, | |
47 | changed=None): |
|
100 | changed=None): | |
48 |
|
||||
49 | # returns a tuple (start, end). If the string is found |
|
|||
50 | # m[start:end] are the line containing that string. If start == end |
|
|||
51 | # the string was not found and they indicate the proper sorted |
|
|||
52 | # insertion point. This was taken from bisect_left, and modified |
|
|||
53 | # to find line start/end as it goes along. |
|
|||
54 | # |
|
|||
55 | # m should be a buffer or a string |
|
|||
56 | # s is a string |
|
|||
57 | # |
|
|||
58 | def manifestsearch(m, s, lo=0, hi=None): |
|
|||
59 | def advance(i, c): |
|
|||
60 | while i < lenm and m[i] != c: |
|
|||
61 | i += 1 |
|
|||
62 | return i |
|
|||
63 | lenm = len(m) |
|
|||
64 | if not hi: |
|
|||
65 | hi = lenm |
|
|||
66 | while lo < hi: |
|
|||
67 | mid = (lo + hi) // 2 |
|
|||
68 | start = mid |
|
|||
69 | while start > 0 and m[start-1] != '\n': |
|
|||
70 | start -= 1 |
|
|||
71 | end = advance(start, '\0') |
|
|||
72 | if m[start:end] < s: |
|
|||
73 | # we know that after the null there are 40 bytes of sha1 |
|
|||
74 | # this translates to the bisect lo = mid + 1 |
|
|||
75 | lo = advance(end + 40, '\n') + 1 |
|
|||
76 | else: |
|
|||
77 | # this translates to the bisect hi = mid |
|
|||
78 | hi = start |
|
|||
79 | end = advance(lo, '\0') |
|
|||
80 | found = m[lo:end] |
|
|||
81 | if cmp(s, found) == 0: |
|
|||
82 | # we know that after the null there are 40 bytes of sha1 |
|
|||
83 | end = advance(end + 40, '\n') |
|
|||
84 | return (lo, end+1) |
|
|||
85 | else: |
|
|||
86 | return (lo, lo) |
|
|||
87 |
|
||||
88 | # apply the changes collected during the bisect loop to our addlist |
|
101 | # apply the changes collected during the bisect loop to our addlist | |
89 | # return a delta suitable for addrevision |
|
102 | # return a delta suitable for addrevision | |
90 | def addlistdelta(addlist, x): |
|
103 | def addlistdelta(addlist, x): | |
@@ -137,7 +150,7 b' class manifest(revlog):' | |||||
137 | for w in work: |
|
150 | for w in work: | |
138 | f = w[0] |
|
151 | f = w[0] | |
139 | # bs will either be the index of the item or the insert point |
|
152 | # bs will either be the index of the item or the insert point | |
140 |
start, end = |
|
153 | start, end = self._search(addbuf, f, start) | |
141 | if w[1] == 0: |
|
154 | if w[1] == 0: | |
142 | l = "%s\000%s%s\n" % (f, hex(map[f]), |
|
155 | l = "%s\000%s%s\n" % (f, hex(map[f]), | |
143 | flags[f] and "x" or '') |
|
156 | flags[f] and "x" or '') |
@@ -32,12 +32,31 b' hg id' | |||||
32 | hg status |
|
32 | hg status | |
33 |
|
33 | |||
34 | hg commit -m "merge" -d "1000000 0" |
|
34 | hg commit -m "merge" -d "1000000 0" | |
|
35 | ||||
|
36 | # create fake head, make sure tag not visible afterwards | |||
|
37 | cp .hgtags tags | |||
|
38 | hg tag -d "1000000 0" last | |||
|
39 | hg rm .hgtags | |||
|
40 | hg commit -m "remove" -d "1000000 0" | |||
|
41 | ||||
|
42 | mv tags .hgtags | |||
|
43 | hg add .hgtags | |||
|
44 | hg commit -m "readd" -d "1000000 0" | |||
|
45 | ||||
|
46 | hg tags | |||
|
47 | ||||
35 | # invalid tags |
|
48 | # invalid tags | |
36 | echo "spam" >> .hgtags |
|
49 | echo "spam" >> .hgtags | |
37 | echo >> .hgtags |
|
50 | echo >> .hgtags | |
38 | echo "foo bar" >> .hgtags |
|
51 | echo "foo bar" >> .hgtags | |
39 | echo "$T invalid" | sed "s/..../a5a5/" >> .hg/localtags |
|
52 | echo "$T invalid" | sed "s/..../a5a5/" >> .hg/localtags | |
40 | hg commit -m "tags" -d "1000000 0" |
|
53 | hg commit -m "tags" -d "1000000 0" | |
|
54 | ||||
|
55 | # report tag parse error on other head | |||
|
56 | hg up 3 | |||
|
57 | echo 'x y' >> .hgtags | |||
|
58 | hg commit -m "head" -d "1000000 0" | |||
|
59 | ||||
41 | hg tags |
|
60 | hg tags | |
42 | hg tip |
|
61 | hg tip | |
43 |
|
62 |
@@ -16,17 +16,26 b' 1 files updated, 0 files merged, 0 files' | |||||
16 | (branch merge, don't forget to commit) |
|
16 | (branch merge, don't forget to commit) | |
17 | 8216907a933d+8a3ca90d111d+ tip |
|
17 | 8216907a933d+8a3ca90d111d+ tip | |
18 | M .hgtags |
|
18 | M .hgtags | |
19 | .hgtags:2: ignoring invalid tag |
|
19 | tip 6:c6af9d771a81bb9c7f267ec03491224a9f8ba1cd | |
20 | .hgtags:4: ignoring invalid tag |
|
|||
21 | localtags:1: ignoring invalid tag |
|
|||
22 | tip 4:fd868a874787a7b5af31e1675666ce691c803035 |
|
|||
23 | first 0:0acdaf8983679e0aac16e811534eb49d7ee1f2b4 |
|
20 | first 0:0acdaf8983679e0aac16e811534eb49d7ee1f2b4 | |
24 | changeset: 4:fd868a874787 |
|
21 | .hgtags (rev 7:39bba1bbbc4c), line 2: cannot parse entry | |
25 | .hgtags:2: ignoring invalid tag |
|
22 | .hgtags (rev 7:39bba1bbbc4c), line 4: node 'foo' is not well formed | |
26 | .hgtags:4: ignoring invalid tag |
|
23 | localtags, line 1: tag 'invalid' refers to unknown node | |
27 | localtags:1: ignoring invalid tag |
|
24 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
25 | .hgtags (rev 7:39bba1bbbc4c), line 2: cannot parse entry | |||
|
26 | .hgtags (rev 7:39bba1bbbc4c), line 4: node 'foo' is not well formed | |||
|
27 | .hgtags (rev 8:4ca6f1b1a68c), line 2: node 'x' is not well formed | |||
|
28 | localtags, line 1: tag 'invalid' refers to unknown node | |||
|
29 | tip 8:4ca6f1b1a68c77be687a03aaeb1614671ba59b20 | |||
|
30 | first 0:0acdaf8983679e0aac16e811534eb49d7ee1f2b4 | |||
|
31 | changeset: 8:4ca6f1b1a68c | |||
|
32 | .hgtags (rev 7:39bba1bbbc4c), line 2: cannot parse entry | |||
|
33 | .hgtags (rev 7:39bba1bbbc4c), line 4: node 'foo' is not well formed | |||
|
34 | .hgtags (rev 8:4ca6f1b1a68c), line 2: node 'x' is not well formed | |||
|
35 | localtags, line 1: tag 'invalid' refers to unknown node | |||
28 | tag: tip |
|
36 | tag: tip | |
|
37 | parent: 3:b2ef3841386b | |||
29 | user: test |
|
38 | user: test | |
30 | date: Mon Jan 12 13:46:40 1970 +0000 |
|
39 | date: Mon Jan 12 13:46:40 1970 +0000 | |
31 |
summary: |
|
40 | summary: head | |
32 |
|
41 |
General Comments 0
You need to be logged in to leave comments.
Login now