##// END OF EJS Templates
branchcache: stay silent if failing to read cache files...
Mads Kiilerich -
r24728:75688a6f default
parent child Browse files
Show More
@@ -1,441 +1,439 b''
1 # branchmap.py - logic to computes, maintain and stores branchmap for local repo
1 # branchmap.py - logic to computes, maintain and stores branchmap for local repo
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import bin, hex, nullid, nullrev
8 from node import bin, hex, nullid, nullrev
9 import encoding
9 import encoding
10 import scmutil
10 import scmutil
11 import util
11 import util
12 import time
12 import time
13 from array import array
13 from array import array
14 from struct import calcsize, pack, unpack
14 from struct import calcsize, pack, unpack
15
15
16 def _filename(repo):
16 def _filename(repo):
17 """name of a branchcache file for a given repo or repoview"""
17 """name of a branchcache file for a given repo or repoview"""
18 filename = "cache/branch2"
18 filename = "cache/branch2"
19 if repo.filtername:
19 if repo.filtername:
20 filename = '%s-%s' % (filename, repo.filtername)
20 filename = '%s-%s' % (filename, repo.filtername)
21 return filename
21 return filename
22
22
23 def read(repo):
23 def read(repo):
24 try:
24 try:
25 f = repo.vfs(_filename(repo))
25 f = repo.vfs(_filename(repo))
26 lines = f.read().split('\n')
26 lines = f.read().split('\n')
27 f.close()
27 f.close()
28 except (IOError, OSError):
28 except (IOError, OSError):
29 return None
29 return None
30
30
31 try:
31 try:
32 cachekey = lines.pop(0).split(" ", 2)
32 cachekey = lines.pop(0).split(" ", 2)
33 last, lrev = cachekey[:2]
33 last, lrev = cachekey[:2]
34 last, lrev = bin(last), int(lrev)
34 last, lrev = bin(last), int(lrev)
35 filteredhash = None
35 filteredhash = None
36 if len(cachekey) > 2:
36 if len(cachekey) > 2:
37 filteredhash = bin(cachekey[2])
37 filteredhash = bin(cachekey[2])
38 partial = branchcache(tipnode=last, tiprev=lrev,
38 partial = branchcache(tipnode=last, tiprev=lrev,
39 filteredhash=filteredhash)
39 filteredhash=filteredhash)
40 if not partial.validfor(repo):
40 if not partial.validfor(repo):
41 # invalidate the cache
41 # invalidate the cache
42 raise ValueError('tip differs')
42 raise ValueError('tip differs')
43 for l in lines:
43 for l in lines:
44 if not l:
44 if not l:
45 continue
45 continue
46 node, state, label = l.split(" ", 2)
46 node, state, label = l.split(" ", 2)
47 if state not in 'oc':
47 if state not in 'oc':
48 raise ValueError('invalid branch state')
48 raise ValueError('invalid branch state')
49 label = encoding.tolocal(label.strip())
49 label = encoding.tolocal(label.strip())
50 if not node in repo:
50 if not node in repo:
51 raise ValueError('node %s does not exist' % node)
51 raise ValueError('node %s does not exist' % node)
52 node = bin(node)
52 node = bin(node)
53 partial.setdefault(label, []).append(node)
53 partial.setdefault(label, []).append(node)
54 if state == 'c':
54 if state == 'c':
55 partial._closednodes.add(node)
55 partial._closednodes.add(node)
56 except KeyboardInterrupt:
56 except KeyboardInterrupt:
57 raise
57 raise
58 except Exception, inst:
58 except Exception, inst:
59 if repo.ui.debugflag:
59 if repo.ui.debugflag:
60 msg = 'invalid branchheads cache'
60 msg = 'invalid branchheads cache'
61 if repo.filtername is not None:
61 if repo.filtername is not None:
62 msg += ' (%s)' % repo.filtername
62 msg += ' (%s)' % repo.filtername
63 msg += ': %s\n'
63 msg += ': %s\n'
64 repo.ui.debug(msg % inst)
64 repo.ui.debug(msg % inst)
65 partial = None
65 partial = None
66 return partial
66 return partial
67
67
68 ### Nearest subset relation
68 ### Nearest subset relation
69 # Nearest subset of filter X is a filter Y so that:
69 # Nearest subset of filter X is a filter Y so that:
70 # * Y is included in X,
70 # * Y is included in X,
71 # * X - Y is as small as possible.
71 # * X - Y is as small as possible.
72 # This create and ordering used for branchmap purpose.
72 # This create and ordering used for branchmap purpose.
73 # the ordering may be partial
73 # the ordering may be partial
74 subsettable = {None: 'visible',
74 subsettable = {None: 'visible',
75 'visible': 'served',
75 'visible': 'served',
76 'served': 'immutable',
76 'served': 'immutable',
77 'immutable': 'base'}
77 'immutable': 'base'}
78
78
79 def updatecache(repo):
79 def updatecache(repo):
80 cl = repo.changelog
80 cl = repo.changelog
81 filtername = repo.filtername
81 filtername = repo.filtername
82 partial = repo._branchcaches.get(filtername)
82 partial = repo._branchcaches.get(filtername)
83
83
84 revs = []
84 revs = []
85 if partial is None or not partial.validfor(repo):
85 if partial is None or not partial.validfor(repo):
86 partial = read(repo)
86 partial = read(repo)
87 if partial is None:
87 if partial is None:
88 subsetname = subsettable.get(filtername)
88 subsetname = subsettable.get(filtername)
89 if subsetname is None:
89 if subsetname is None:
90 partial = branchcache()
90 partial = branchcache()
91 else:
91 else:
92 subset = repo.filtered(subsetname)
92 subset = repo.filtered(subsetname)
93 partial = subset.branchmap().copy()
93 partial = subset.branchmap().copy()
94 extrarevs = subset.changelog.filteredrevs - cl.filteredrevs
94 extrarevs = subset.changelog.filteredrevs - cl.filteredrevs
95 revs.extend(r for r in extrarevs if r <= partial.tiprev)
95 revs.extend(r for r in extrarevs if r <= partial.tiprev)
96 revs.extend(cl.revs(start=partial.tiprev + 1))
96 revs.extend(cl.revs(start=partial.tiprev + 1))
97 if revs:
97 if revs:
98 partial.update(repo, revs)
98 partial.update(repo, revs)
99 partial.write(repo)
99 partial.write(repo)
100
100
101 assert partial.validfor(repo), filtername
101 assert partial.validfor(repo), filtername
102 repo._branchcaches[repo.filtername] = partial
102 repo._branchcaches[repo.filtername] = partial
103
103
104 class branchcache(dict):
104 class branchcache(dict):
105 """A dict like object that hold branches heads cache.
105 """A dict like object that hold branches heads cache.
106
106
107 This cache is used to avoid costly computations to determine all the
107 This cache is used to avoid costly computations to determine all the
108 branch heads of a repo.
108 branch heads of a repo.
109
109
110 The cache is serialized on disk in the following format:
110 The cache is serialized on disk in the following format:
111
111
112 <tip hex node> <tip rev number> [optional filtered repo hex hash]
112 <tip hex node> <tip rev number> [optional filtered repo hex hash]
113 <branch head hex node> <open/closed state> <branch name>
113 <branch head hex node> <open/closed state> <branch name>
114 <branch head hex node> <open/closed state> <branch name>
114 <branch head hex node> <open/closed state> <branch name>
115 ...
115 ...
116
116
117 The first line is used to check if the cache is still valid. If the
117 The first line is used to check if the cache is still valid. If the
118 branch cache is for a filtered repo view, an optional third hash is
118 branch cache is for a filtered repo view, an optional third hash is
119 included that hashes the hashes of all filtered revisions.
119 included that hashes the hashes of all filtered revisions.
120
120
121 The open/closed state is represented by a single letter 'o' or 'c'.
121 The open/closed state is represented by a single letter 'o' or 'c'.
122 This field can be used to avoid changelog reads when determining if a
122 This field can be used to avoid changelog reads when determining if a
123 branch head closes a branch or not.
123 branch head closes a branch or not.
124 """
124 """
125
125
126 def __init__(self, entries=(), tipnode=nullid, tiprev=nullrev,
126 def __init__(self, entries=(), tipnode=nullid, tiprev=nullrev,
127 filteredhash=None, closednodes=None):
127 filteredhash=None, closednodes=None):
128 super(branchcache, self).__init__(entries)
128 super(branchcache, self).__init__(entries)
129 self.tipnode = tipnode
129 self.tipnode = tipnode
130 self.tiprev = tiprev
130 self.tiprev = tiprev
131 self.filteredhash = filteredhash
131 self.filteredhash = filteredhash
132 # closednodes is a set of nodes that close their branch. If the branch
132 # closednodes is a set of nodes that close their branch. If the branch
133 # cache has been updated, it may contain nodes that are no longer
133 # cache has been updated, it may contain nodes that are no longer
134 # heads.
134 # heads.
135 if closednodes is None:
135 if closednodes is None:
136 self._closednodes = set()
136 self._closednodes = set()
137 else:
137 else:
138 self._closednodes = closednodes
138 self._closednodes = closednodes
139
139
140 def validfor(self, repo):
140 def validfor(self, repo):
141 """Is the cache content valid regarding a repo
141 """Is the cache content valid regarding a repo
142
142
143 - False when cached tipnode is unknown or if we detect a strip.
143 - False when cached tipnode is unknown or if we detect a strip.
144 - True when cache is up to date or a subset of current repo."""
144 - True when cache is up to date or a subset of current repo."""
145 try:
145 try:
146 return ((self.tipnode == repo.changelog.node(self.tiprev))
146 return ((self.tipnode == repo.changelog.node(self.tiprev))
147 and (self.filteredhash == \
147 and (self.filteredhash == \
148 scmutil.filteredhash(repo, self.tiprev)))
148 scmutil.filteredhash(repo, self.tiprev)))
149 except IndexError:
149 except IndexError:
150 return False
150 return False
151
151
152 def _branchtip(self, heads):
152 def _branchtip(self, heads):
153 '''Return tuple with last open head in heads and false,
153 '''Return tuple with last open head in heads and false,
154 otherwise return last closed head and true.'''
154 otherwise return last closed head and true.'''
155 tip = heads[-1]
155 tip = heads[-1]
156 closed = True
156 closed = True
157 for h in reversed(heads):
157 for h in reversed(heads):
158 if h not in self._closednodes:
158 if h not in self._closednodes:
159 tip = h
159 tip = h
160 closed = False
160 closed = False
161 break
161 break
162 return tip, closed
162 return tip, closed
163
163
164 def branchtip(self, branch):
164 def branchtip(self, branch):
165 '''Return the tipmost open head on branch head, otherwise return the
165 '''Return the tipmost open head on branch head, otherwise return the
166 tipmost closed head on branch.
166 tipmost closed head on branch.
167 Raise KeyError for unknown branch.'''
167 Raise KeyError for unknown branch.'''
168 return self._branchtip(self[branch])[0]
168 return self._branchtip(self[branch])[0]
169
169
170 def branchheads(self, branch, closed=False):
170 def branchheads(self, branch, closed=False):
171 heads = self[branch]
171 heads = self[branch]
172 if not closed:
172 if not closed:
173 heads = [h for h in heads if h not in self._closednodes]
173 heads = [h for h in heads if h not in self._closednodes]
174 return heads
174 return heads
175
175
176 def iterbranches(self):
176 def iterbranches(self):
177 for bn, heads in self.iteritems():
177 for bn, heads in self.iteritems():
178 yield (bn, heads) + self._branchtip(heads)
178 yield (bn, heads) + self._branchtip(heads)
179
179
180 def copy(self):
180 def copy(self):
181 """return an deep copy of the branchcache object"""
181 """return an deep copy of the branchcache object"""
182 return branchcache(self, self.tipnode, self.tiprev, self.filteredhash,
182 return branchcache(self, self.tipnode, self.tiprev, self.filteredhash,
183 self._closednodes)
183 self._closednodes)
184
184
185 def write(self, repo):
185 def write(self, repo):
186 try:
186 try:
187 f = repo.vfs(_filename(repo), "w", atomictemp=True)
187 f = repo.vfs(_filename(repo), "w", atomictemp=True)
188 cachekey = [hex(self.tipnode), str(self.tiprev)]
188 cachekey = [hex(self.tipnode), str(self.tiprev)]
189 if self.filteredhash is not None:
189 if self.filteredhash is not None:
190 cachekey.append(hex(self.filteredhash))
190 cachekey.append(hex(self.filteredhash))
191 f.write(" ".join(cachekey) + '\n')
191 f.write(" ".join(cachekey) + '\n')
192 nodecount = 0
192 nodecount = 0
193 for label, nodes in sorted(self.iteritems()):
193 for label, nodes in sorted(self.iteritems()):
194 for node in nodes:
194 for node in nodes:
195 nodecount += 1
195 nodecount += 1
196 if node in self._closednodes:
196 if node in self._closednodes:
197 state = 'c'
197 state = 'c'
198 else:
198 else:
199 state = 'o'
199 state = 'o'
200 f.write("%s %s %s\n" % (hex(node), state,
200 f.write("%s %s %s\n" % (hex(node), state,
201 encoding.fromlocal(label)))
201 encoding.fromlocal(label)))
202 f.close()
202 f.close()
203 repo.ui.log('branchcache',
203 repo.ui.log('branchcache',
204 'wrote %s branch cache with %d labels and %d nodes\n',
204 'wrote %s branch cache with %d labels and %d nodes\n',
205 repo.filtername, len(self), nodecount)
205 repo.filtername, len(self), nodecount)
206 except (IOError, OSError, util.Abort), inst:
206 except (IOError, OSError, util.Abort), inst:
207 repo.ui.debug("couldn't write branch cache: %s\n" % inst)
207 repo.ui.debug("couldn't write branch cache: %s\n" % inst)
208 # Abort may be raise by read only opener
208 # Abort may be raise by read only opener
209 pass
209 pass
210
210
211 def update(self, repo, revgen):
211 def update(self, repo, revgen):
212 """Given a branchhead cache, self, that may have extra nodes or be
212 """Given a branchhead cache, self, that may have extra nodes or be
213 missing heads, and a generator of nodes that are strictly a superset of
213 missing heads, and a generator of nodes that are strictly a superset of
214 heads missing, this function updates self to be correct.
214 heads missing, this function updates self to be correct.
215 """
215 """
216 starttime = time.time()
216 starttime = time.time()
217 cl = repo.changelog
217 cl = repo.changelog
218 # collect new branch entries
218 # collect new branch entries
219 newbranches = {}
219 newbranches = {}
220 getbranchinfo = repo.revbranchcache().branchinfo
220 getbranchinfo = repo.revbranchcache().branchinfo
221 for r in revgen:
221 for r in revgen:
222 branch, closesbranch = getbranchinfo(r)
222 branch, closesbranch = getbranchinfo(r)
223 newbranches.setdefault(branch, []).append(r)
223 newbranches.setdefault(branch, []).append(r)
224 if closesbranch:
224 if closesbranch:
225 self._closednodes.add(cl.node(r))
225 self._closednodes.add(cl.node(r))
226
226
227 # fetch current topological heads to speed up filtering
227 # fetch current topological heads to speed up filtering
228 topoheads = set(cl.headrevs())
228 topoheads = set(cl.headrevs())
229
229
230 # if older branchheads are reachable from new ones, they aren't
230 # if older branchheads are reachable from new ones, they aren't
231 # really branchheads. Note checking parents is insufficient:
231 # really branchheads. Note checking parents is insufficient:
232 # 1 (branch a) -> 2 (branch b) -> 3 (branch a)
232 # 1 (branch a) -> 2 (branch b) -> 3 (branch a)
233 for branch, newheadrevs in newbranches.iteritems():
233 for branch, newheadrevs in newbranches.iteritems():
234 bheads = self.setdefault(branch, [])
234 bheads = self.setdefault(branch, [])
235 bheadset = set(cl.rev(node) for node in bheads)
235 bheadset = set(cl.rev(node) for node in bheads)
236
236
237 # This have been tested True on all internal usage of this function.
237 # This have been tested True on all internal usage of this function.
238 # run it again in case of doubt
238 # run it again in case of doubt
239 # assert not (set(bheadrevs) & set(newheadrevs))
239 # assert not (set(bheadrevs) & set(newheadrevs))
240 newheadrevs.sort()
240 newheadrevs.sort()
241 bheadset.update(newheadrevs)
241 bheadset.update(newheadrevs)
242
242
243 # This prunes out two kinds of heads - heads that are superseded by
243 # This prunes out two kinds of heads - heads that are superseded by
244 # a head in newheadrevs, and newheadrevs that are not heads because
244 # a head in newheadrevs, and newheadrevs that are not heads because
245 # an existing head is their descendant.
245 # an existing head is their descendant.
246 uncertain = bheadset - topoheads
246 uncertain = bheadset - topoheads
247 if uncertain:
247 if uncertain:
248 floorrev = min(uncertain)
248 floorrev = min(uncertain)
249 ancestors = set(cl.ancestors(newheadrevs, floorrev))
249 ancestors = set(cl.ancestors(newheadrevs, floorrev))
250 bheadset -= ancestors
250 bheadset -= ancestors
251 bheadrevs = sorted(bheadset)
251 bheadrevs = sorted(bheadset)
252 self[branch] = [cl.node(rev) for rev in bheadrevs]
252 self[branch] = [cl.node(rev) for rev in bheadrevs]
253 tiprev = bheadrevs[-1]
253 tiprev = bheadrevs[-1]
254 if tiprev > self.tiprev:
254 if tiprev > self.tiprev:
255 self.tipnode = cl.node(tiprev)
255 self.tipnode = cl.node(tiprev)
256 self.tiprev = tiprev
256 self.tiprev = tiprev
257
257
258 if not self.validfor(repo):
258 if not self.validfor(repo):
259 # cache key are not valid anymore
259 # cache key are not valid anymore
260 self.tipnode = nullid
260 self.tipnode = nullid
261 self.tiprev = nullrev
261 self.tiprev = nullrev
262 for heads in self.values():
262 for heads in self.values():
263 tiprev = max(cl.rev(node) for node in heads)
263 tiprev = max(cl.rev(node) for node in heads)
264 if tiprev > self.tiprev:
264 if tiprev > self.tiprev:
265 self.tipnode = cl.node(tiprev)
265 self.tipnode = cl.node(tiprev)
266 self.tiprev = tiprev
266 self.tiprev = tiprev
267 self.filteredhash = scmutil.filteredhash(repo, self.tiprev)
267 self.filteredhash = scmutil.filteredhash(repo, self.tiprev)
268
268
269 duration = time.time() - starttime
269 duration = time.time() - starttime
270 repo.ui.log('branchcache', 'updated %s branch cache in %.4f seconds\n',
270 repo.ui.log('branchcache', 'updated %s branch cache in %.4f seconds\n',
271 repo.filtername, duration)
271 repo.filtername, duration)
272
272
273 # Revision branch info cache
273 # Revision branch info cache
274
274
275 _rbcversion = '-v1'
275 _rbcversion = '-v1'
276 _rbcnames = 'cache/rbc-names' + _rbcversion
276 _rbcnames = 'cache/rbc-names' + _rbcversion
277 _rbcrevs = 'cache/rbc-revs' + _rbcversion
277 _rbcrevs = 'cache/rbc-revs' + _rbcversion
278 # [4 byte hash prefix][4 byte branch name number with sign bit indicating open]
278 # [4 byte hash prefix][4 byte branch name number with sign bit indicating open]
279 _rbcrecfmt = '>4sI'
279 _rbcrecfmt = '>4sI'
280 _rbcrecsize = calcsize(_rbcrecfmt)
280 _rbcrecsize = calcsize(_rbcrecfmt)
281 _rbcnodelen = 4
281 _rbcnodelen = 4
282 _rbcbranchidxmask = 0x7fffffff
282 _rbcbranchidxmask = 0x7fffffff
283 _rbccloseflag = 0x80000000
283 _rbccloseflag = 0x80000000
284
284
285 class revbranchcache(object):
285 class revbranchcache(object):
286 """Persistent cache, mapping from revision number to branch name and close.
286 """Persistent cache, mapping from revision number to branch name and close.
287 This is a low level cache, independent of filtering.
287 This is a low level cache, independent of filtering.
288
288
289 Branch names are stored in rbc-names in internal encoding separated by 0.
289 Branch names are stored in rbc-names in internal encoding separated by 0.
290 rbc-names is append-only, and each branch name is only stored once and will
290 rbc-names is append-only, and each branch name is only stored once and will
291 thus have a unique index.
291 thus have a unique index.
292
292
293 The branch info for each revision is stored in rbc-revs as constant size
293 The branch info for each revision is stored in rbc-revs as constant size
294 records. The whole file is read into memory, but it is only 'parsed' on
294 records. The whole file is read into memory, but it is only 'parsed' on
295 demand. The file is usually append-only but will be truncated if repo
295 demand. The file is usually append-only but will be truncated if repo
296 modification is detected.
296 modification is detected.
297 The record for each revision contains the first 4 bytes of the
297 The record for each revision contains the first 4 bytes of the
298 corresponding node hash, and the record is only used if it still matches.
298 corresponding node hash, and the record is only used if it still matches.
299 Even a completely trashed rbc-revs fill thus still give the right result
299 Even a completely trashed rbc-revs fill thus still give the right result
300 while converging towards full recovery ... assuming no incorrectly matching
300 while converging towards full recovery ... assuming no incorrectly matching
301 node hashes.
301 node hashes.
302 The record also contains 4 bytes where 31 bits contains the index of the
302 The record also contains 4 bytes where 31 bits contains the index of the
303 branch and the last bit indicate that it is a branch close commit.
303 branch and the last bit indicate that it is a branch close commit.
304 The usage pattern for rbc-revs is thus somewhat similar to 00changelog.i
304 The usage pattern for rbc-revs is thus somewhat similar to 00changelog.i
305 and will grow with it but be 1/8th of its size.
305 and will grow with it but be 1/8th of its size.
306 """
306 """
307
307
308 def __init__(self, repo, readonly=True):
308 def __init__(self, repo, readonly=True):
309 assert repo.filtername is None
309 assert repo.filtername is None
310 self._repo = repo
310 self._repo = repo
311 self._names = [] # branch names in local encoding with static index
311 self._names = [] # branch names in local encoding with static index
312 self._rbcrevs = array('c') # structs of type _rbcrecfmt
312 self._rbcrevs = array('c') # structs of type _rbcrecfmt
313 self._rbcsnameslen = 0
313 self._rbcsnameslen = 0
314 try:
314 try:
315 bndata = repo.vfs.read(_rbcnames)
315 bndata = repo.vfs.read(_rbcnames)
316 self._rbcsnameslen = len(bndata) # for verification before writing
316 self._rbcsnameslen = len(bndata) # for verification before writing
317 self._names = [encoding.tolocal(bn) for bn in bndata.split('\0')]
317 self._names = [encoding.tolocal(bn) for bn in bndata.split('\0')]
318 except (IOError, OSError), inst:
318 except (IOError, OSError), inst:
319 repo.ui.debug("couldn't read revision branch cache names: %s\n" %
320 inst)
321 if readonly:
319 if readonly:
322 # don't try to use cache - fall back to the slow path
320 # don't try to use cache - fall back to the slow path
323 self.branchinfo = self._branchinfo
321 self.branchinfo = self._branchinfo
324
322
325 if self._names:
323 if self._names:
326 try:
324 try:
327 data = repo.vfs.read(_rbcrevs)
325 data = repo.vfs.read(_rbcrevs)
328 self._rbcrevs.fromstring(data)
326 self._rbcrevs.fromstring(data)
329 except (IOError, OSError), inst:
327 except (IOError, OSError), inst:
330 repo.ui.debug("couldn't read revision branch cache: %s\n" %
328 repo.ui.debug("couldn't read revision branch cache: %s\n" %
331 inst)
329 inst)
332 # remember number of good records on disk
330 # remember number of good records on disk
333 self._rbcrevslen = min(len(self._rbcrevs) // _rbcrecsize,
331 self._rbcrevslen = min(len(self._rbcrevs) // _rbcrecsize,
334 len(repo.changelog))
332 len(repo.changelog))
335 if self._rbcrevslen == 0:
333 if self._rbcrevslen == 0:
336 self._names = []
334 self._names = []
337 self._rbcnamescount = len(self._names) # number of good names on disk
335 self._rbcnamescount = len(self._names) # number of good names on disk
338 self._namesreverse = dict((b, r) for r, b in enumerate(self._names))
336 self._namesreverse = dict((b, r) for r, b in enumerate(self._names))
339
337
340 def branchinfo(self, rev):
338 def branchinfo(self, rev):
341 """Return branch name and close flag for rev, using and updating
339 """Return branch name and close flag for rev, using and updating
342 persistent cache."""
340 persistent cache."""
343 changelog = self._repo.changelog
341 changelog = self._repo.changelog
344 rbcrevidx = rev * _rbcrecsize
342 rbcrevidx = rev * _rbcrecsize
345
343
346 # if requested rev is missing, add and populate all missing revs
344 # if requested rev is missing, add and populate all missing revs
347 if len(self._rbcrevs) < rbcrevidx + _rbcrecsize:
345 if len(self._rbcrevs) < rbcrevidx + _rbcrecsize:
348 self._rbcrevs.extend('\0' * (len(changelog) * _rbcrecsize -
346 self._rbcrevs.extend('\0' * (len(changelog) * _rbcrecsize -
349 len(self._rbcrevs)))
347 len(self._rbcrevs)))
350
348
351 # fast path: extract data from cache, use it if node is matching
349 # fast path: extract data from cache, use it if node is matching
352 reponode = changelog.node(rev)[:_rbcnodelen]
350 reponode = changelog.node(rev)[:_rbcnodelen]
353 cachenode, branchidx = unpack(
351 cachenode, branchidx = unpack(
354 _rbcrecfmt, buffer(self._rbcrevs, rbcrevidx, _rbcrecsize))
352 _rbcrecfmt, buffer(self._rbcrevs, rbcrevidx, _rbcrecsize))
355 close = bool(branchidx & _rbccloseflag)
353 close = bool(branchidx & _rbccloseflag)
356 if close:
354 if close:
357 branchidx &= _rbcbranchidxmask
355 branchidx &= _rbcbranchidxmask
358 if cachenode == '\0\0\0\0':
356 if cachenode == '\0\0\0\0':
359 pass
357 pass
360 elif cachenode == reponode:
358 elif cachenode == reponode:
361 return self._names[branchidx], close
359 return self._names[branchidx], close
362 else:
360 else:
363 # rev/node map has changed, invalidate the cache from here up
361 # rev/node map has changed, invalidate the cache from here up
364 truncate = rbcrevidx + _rbcrecsize
362 truncate = rbcrevidx + _rbcrecsize
365 del self._rbcrevs[truncate:]
363 del self._rbcrevs[truncate:]
366 self._rbcrevslen = min(self._rbcrevslen, truncate)
364 self._rbcrevslen = min(self._rbcrevslen, truncate)
367
365
368 # fall back to slow path and make sure it will be written to disk
366 # fall back to slow path and make sure it will be written to disk
369 return self._branchinfo(rev)
367 return self._branchinfo(rev)
370
368
371 def _branchinfo(self, rev):
369 def _branchinfo(self, rev):
372 """Retrieve branch info from changelog and update _rbcrevs"""
370 """Retrieve branch info from changelog and update _rbcrevs"""
373 changelog = self._repo.changelog
371 changelog = self._repo.changelog
374 b, close = changelog.branchinfo(rev)
372 b, close = changelog.branchinfo(rev)
375 if b in self._namesreverse:
373 if b in self._namesreverse:
376 branchidx = self._namesreverse[b]
374 branchidx = self._namesreverse[b]
377 else:
375 else:
378 branchidx = len(self._names)
376 branchidx = len(self._names)
379 self._names.append(b)
377 self._names.append(b)
380 self._namesreverse[b] = branchidx
378 self._namesreverse[b] = branchidx
381 reponode = changelog.node(rev)
379 reponode = changelog.node(rev)
382 if close:
380 if close:
383 branchidx |= _rbccloseflag
381 branchidx |= _rbccloseflag
384 self._setcachedata(rev, reponode, branchidx)
382 self._setcachedata(rev, reponode, branchidx)
385 return b, close
383 return b, close
386
384
387 def _setcachedata(self, rev, node, branchidx):
385 def _setcachedata(self, rev, node, branchidx):
388 """Writes the node's branch data to the in-memory cache data."""
386 """Writes the node's branch data to the in-memory cache data."""
389 rbcrevidx = rev * _rbcrecsize
387 rbcrevidx = rev * _rbcrecsize
390 rec = array('c')
388 rec = array('c')
391 rec.fromstring(pack(_rbcrecfmt, node, branchidx))
389 rec.fromstring(pack(_rbcrecfmt, node, branchidx))
392 self._rbcrevs[rbcrevidx:rbcrevidx + _rbcrecsize] = rec
390 self._rbcrevs[rbcrevidx:rbcrevidx + _rbcrecsize] = rec
393 self._rbcrevslen = min(self._rbcrevslen, rev)
391 self._rbcrevslen = min(self._rbcrevslen, rev)
394
392
395 tr = self._repo.currenttransaction()
393 tr = self._repo.currenttransaction()
396 if tr:
394 if tr:
397 tr.addfinalize('write-revbranchcache', self.write)
395 tr.addfinalize('write-revbranchcache', self.write)
398
396
399 def write(self, tr=None):
397 def write(self, tr=None):
400 """Save branch cache if it is dirty."""
398 """Save branch cache if it is dirty."""
401 repo = self._repo
399 repo = self._repo
402 if self._rbcnamescount < len(self._names):
400 if self._rbcnamescount < len(self._names):
403 try:
401 try:
404 if self._rbcnamescount != 0:
402 if self._rbcnamescount != 0:
405 f = repo.vfs.open(_rbcnames, 'ab')
403 f = repo.vfs.open(_rbcnames, 'ab')
406 if f.tell() == self._rbcsnameslen:
404 if f.tell() == self._rbcsnameslen:
407 f.write('\0')
405 f.write('\0')
408 else:
406 else:
409 f.close()
407 f.close()
410 repo.ui.debug("%s changed - rewriting it\n" % _rbcnames)
408 repo.ui.debug("%s changed - rewriting it\n" % _rbcnames)
411 self._rbcnamescount = 0
409 self._rbcnamescount = 0
412 self._rbcrevslen = 0
410 self._rbcrevslen = 0
413 if self._rbcnamescount == 0:
411 if self._rbcnamescount == 0:
414 f = repo.vfs.open(_rbcnames, 'wb')
412 f = repo.vfs.open(_rbcnames, 'wb')
415 f.write('\0'.join(encoding.fromlocal(b)
413 f.write('\0'.join(encoding.fromlocal(b)
416 for b in self._names[self._rbcnamescount:]))
414 for b in self._names[self._rbcnamescount:]))
417 self._rbcsnameslen = f.tell()
415 self._rbcsnameslen = f.tell()
418 f.close()
416 f.close()
419 except (IOError, OSError, util.Abort), inst:
417 except (IOError, OSError, util.Abort), inst:
420 repo.ui.debug("couldn't write revision branch cache names: "
418 repo.ui.debug("couldn't write revision branch cache names: "
421 "%s\n" % inst)
419 "%s\n" % inst)
422 return
420 return
423 self._rbcnamescount = len(self._names)
421 self._rbcnamescount = len(self._names)
424
422
425 start = self._rbcrevslen * _rbcrecsize
423 start = self._rbcrevslen * _rbcrecsize
426 if start != len(self._rbcrevs):
424 if start != len(self._rbcrevs):
427 revs = min(len(repo.changelog), len(self._rbcrevs) // _rbcrecsize)
425 revs = min(len(repo.changelog), len(self._rbcrevs) // _rbcrecsize)
428 try:
426 try:
429 f = repo.vfs.open(_rbcrevs, 'ab')
427 f = repo.vfs.open(_rbcrevs, 'ab')
430 if f.tell() != start:
428 if f.tell() != start:
431 repo.ui.debug("truncating %s to %s\n" % (_rbcrevs, start))
429 repo.ui.debug("truncating %s to %s\n" % (_rbcrevs, start))
432 f.seek(start)
430 f.seek(start)
433 f.truncate()
431 f.truncate()
434 end = revs * _rbcrecsize
432 end = revs * _rbcrecsize
435 f.write(self._rbcrevs[start:end])
433 f.write(self._rbcrevs[start:end])
436 f.close()
434 f.close()
437 except (IOError, OSError, util.Abort), inst:
435 except (IOError, OSError, util.Abort), inst:
438 repo.ui.debug("couldn't write revision branch cache: %s\n" %
436 repo.ui.debug("couldn't write revision branch cache: %s\n" %
439 inst)
437 inst)
440 return
438 return
441 self._rbcrevslen = revs
439 self._rbcrevslen = revs
@@ -1,223 +1,222 b''
1 #require icasefs
1 #require icasefs
2
2
3 $ hg debugfs | grep 'case-sensitive:'
3 $ hg debugfs | grep 'case-sensitive:'
4 case-sensitive: no
4 case-sensitive: no
5
5
6 test file addition with bad case
6 test file addition with bad case
7
7
8 $ hg init repo1
8 $ hg init repo1
9 $ cd repo1
9 $ cd repo1
10 $ echo a > a
10 $ echo a > a
11 $ hg add A
11 $ hg add A
12 adding a
12 adding a
13 $ hg st
13 $ hg st
14 A a
14 A a
15 $ hg ci -m adda
15 $ hg ci -m adda
16 $ hg manifest
16 $ hg manifest
17 a
17 a
18 $ cd ..
18 $ cd ..
19
19
20 test case collision on rename (issue750)
20 test case collision on rename (issue750)
21
21
22 $ hg init repo2
22 $ hg init repo2
23 $ cd repo2
23 $ cd repo2
24 $ echo a > a
24 $ echo a > a
25 $ hg --debug ci -Am adda
25 $ hg --debug ci -Am adda
26 adding a
26 adding a
27 committing files:
27 committing files:
28 a
28 a
29 committing manifest
29 committing manifest
30 committing changelog
30 committing changelog
31 couldn't read revision branch cache names: * (glob)
32 committed changeset 0:07f4944404050f47db2e5c5071e0e84e7a27bba9
31 committed changeset 0:07f4944404050f47db2e5c5071e0e84e7a27bba9
33
32
34 Case-changing renames should work:
33 Case-changing renames should work:
35
34
36 $ hg mv a A
35 $ hg mv a A
37 $ hg mv A a
36 $ hg mv A a
38 $ hg st
37 $ hg st
39
38
40 addremove after case-changing rename has no effect (issue4590)
39 addremove after case-changing rename has no effect (issue4590)
41
40
42 $ hg mv a A
41 $ hg mv a A
43 $ hg addremove
42 $ hg addremove
44 recording removal of a as rename to A (100% similar)
43 recording removal of a as rename to A (100% similar)
45 $ hg revert --all
44 $ hg revert --all
46 forgetting A
45 forgetting A
47 undeleting a
46 undeleting a
48
47
49 test changing case of path components
48 test changing case of path components
50
49
51 $ mkdir D
50 $ mkdir D
52 $ echo b > D/b
51 $ echo b > D/b
53 $ hg ci -Am addb D/b
52 $ hg ci -Am addb D/b
54 $ hg mv D/b d/b
53 $ hg mv D/b d/b
55 D/b: not overwriting - file exists
54 D/b: not overwriting - file exists
56 $ hg mv D/b d/c
55 $ hg mv D/b d/c
57 $ hg st
56 $ hg st
58 A D/c
57 A D/c
59 R D/b
58 R D/b
60 $ mv D temp
59 $ mv D temp
61 $ mv temp d
60 $ mv temp d
62 $ hg st
61 $ hg st
63 A D/c
62 A D/c
64 R D/b
63 R D/b
65 $ hg revert -aq
64 $ hg revert -aq
66 $ rm d/c
65 $ rm d/c
67 $ echo c > D/c
66 $ echo c > D/c
68 $ hg add D/c
67 $ hg add D/c
69 $ hg st
68 $ hg st
70 A D/c
69 A D/c
71 $ hg ci -m addc D/c
70 $ hg ci -m addc D/c
72 $ hg mv d/b d/e
71 $ hg mv d/b d/e
73 moving D/b to D/e (glob)
72 moving D/b to D/e (glob)
74 $ hg st
73 $ hg st
75 A D/e
74 A D/e
76 R D/b
75 R D/b
77 $ hg revert -aq
76 $ hg revert -aq
78 $ rm d/e
77 $ rm d/e
79 $ hg mv d/b D/B
78 $ hg mv d/b D/B
80 moving D/b to D/B (glob)
79 moving D/b to D/B (glob)
81 $ hg st
80 $ hg st
82 A D/B
81 A D/B
83 R D/b
82 R D/b
84 $ cd ..
83 $ cd ..
85
84
86 test case collision between revisions (issue912)
85 test case collision between revisions (issue912)
87
86
88 $ hg init repo3
87 $ hg init repo3
89 $ cd repo3
88 $ cd repo3
90 $ echo a > a
89 $ echo a > a
91 $ hg ci -Am adda
90 $ hg ci -Am adda
92 adding a
91 adding a
93 $ hg rm a
92 $ hg rm a
94 $ hg ci -Am removea
93 $ hg ci -Am removea
95 $ echo A > A
94 $ echo A > A
96
95
97 on linux hfs keeps the old case stored, force it
96 on linux hfs keeps the old case stored, force it
98
97
99 $ mv a aa
98 $ mv a aa
100 $ mv aa A
99 $ mv aa A
101 $ hg ci -Am addA
100 $ hg ci -Am addA
102 adding A
101 adding A
103
102
104 used to fail under case insensitive fs
103 used to fail under case insensitive fs
105
104
106 $ hg up -C 0
105 $ hg up -C 0
107 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
106 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
108 $ hg up -C
107 $ hg up -C
109 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
108 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
110
109
111 no clobbering of untracked files with wrong casing
110 no clobbering of untracked files with wrong casing
112
111
113 $ hg up -r null
112 $ hg up -r null
114 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
113 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
115 $ echo gold > a
114 $ echo gold > a
116 $ hg up
115 $ hg up
117 A: untracked file differs
116 A: untracked file differs
118 abort: untracked files in working directory differ from files in requested revision
117 abort: untracked files in working directory differ from files in requested revision
119 [255]
118 [255]
120 $ cat a
119 $ cat a
121 gold
120 gold
122 $ rm a
121 $ rm a
123
122
124 test that normal file in different case on target context is not
123 test that normal file in different case on target context is not
125 unlinked by largefiles extension.
124 unlinked by largefiles extension.
126
125
127 $ cat >> .hg/hgrc <<EOF
126 $ cat >> .hg/hgrc <<EOF
128 > [extensions]
127 > [extensions]
129 > largefiles=
128 > largefiles=
130 > EOF
129 > EOF
131 $ hg update -q -C 1
130 $ hg update -q -C 1
132 $ hg status -A
131 $ hg status -A
133 $ echo 'A as largefiles' > A
132 $ echo 'A as largefiles' > A
134 $ hg add --large A
133 $ hg add --large A
135 $ hg commit -m '#3'
134 $ hg commit -m '#3'
136 created new head
135 created new head
137 $ hg manifest -r 3
136 $ hg manifest -r 3
138 .hglf/A
137 .hglf/A
139 $ hg manifest -r 0
138 $ hg manifest -r 0
140 a
139 a
141 $ hg update -q -C 0
140 $ hg update -q -C 0
142 $ hg status -A
141 $ hg status -A
143 C a
142 C a
144 $ hg update -q -C 3
143 $ hg update -q -C 3
145 $ hg update -q 0
144 $ hg update -q 0
146
145
147 $ cd ..
146 $ cd ..
148
147
149 issue 3342: file in nested directory causes unexpected abort
148 issue 3342: file in nested directory causes unexpected abort
150
149
151 $ hg init issue3342
150 $ hg init issue3342
152 $ cd issue3342
151 $ cd issue3342
153
152
154 $ mkdir -p a/B/c/D
153 $ mkdir -p a/B/c/D
155 $ echo e > a/B/c/D/e
154 $ echo e > a/B/c/D/e
156 $ hg add a/B/c/D/e
155 $ hg add a/B/c/D/e
157
156
158 $ cd ..
157 $ cd ..
159
158
160 issue 3340: mq does not handle case changes correctly
159 issue 3340: mq does not handle case changes correctly
161
160
162 in addition to reported case, 'hg qrefresh' is also tested against
161 in addition to reported case, 'hg qrefresh' is also tested against
163 case changes.
162 case changes.
164
163
165 $ echo "[extensions]" >> $HGRCPATH
164 $ echo "[extensions]" >> $HGRCPATH
166 $ echo "mq=" >> $HGRCPATH
165 $ echo "mq=" >> $HGRCPATH
167
166
168 $ hg init issue3340
167 $ hg init issue3340
169 $ cd issue3340
168 $ cd issue3340
170
169
171 $ echo a > mIxEdCaSe
170 $ echo a > mIxEdCaSe
172 $ hg add mIxEdCaSe
171 $ hg add mIxEdCaSe
173 $ hg commit -m '#0'
172 $ hg commit -m '#0'
174 $ hg rename mIxEdCaSe tmp
173 $ hg rename mIxEdCaSe tmp
175 $ hg rename tmp MiXeDcAsE
174 $ hg rename tmp MiXeDcAsE
176 $ hg status -A
175 $ hg status -A
177 A MiXeDcAsE
176 A MiXeDcAsE
178 mIxEdCaSe
177 mIxEdCaSe
179 R mIxEdCaSe
178 R mIxEdCaSe
180 $ hg qnew changecase
179 $ hg qnew changecase
181 $ hg status -A
180 $ hg status -A
182 C MiXeDcAsE
181 C MiXeDcAsE
183
182
184 $ hg qpop -a
183 $ hg qpop -a
185 popping changecase
184 popping changecase
186 patch queue now empty
185 patch queue now empty
187 $ hg qnew refresh-casechange
186 $ hg qnew refresh-casechange
188 $ hg status -A
187 $ hg status -A
189 C mIxEdCaSe
188 C mIxEdCaSe
190 $ hg rename mIxEdCaSe tmp
189 $ hg rename mIxEdCaSe tmp
191 $ hg rename tmp MiXeDcAsE
190 $ hg rename tmp MiXeDcAsE
192 $ hg status -A
191 $ hg status -A
193 A MiXeDcAsE
192 A MiXeDcAsE
194 mIxEdCaSe
193 mIxEdCaSe
195 R mIxEdCaSe
194 R mIxEdCaSe
196 $ hg qrefresh
195 $ hg qrefresh
197 $ hg status -A
196 $ hg status -A
198 C MiXeDcAsE
197 C MiXeDcAsE
199
198
200 $ hg qpop -a
199 $ hg qpop -a
201 popping refresh-casechange
200 popping refresh-casechange
202 patch queue now empty
201 patch queue now empty
203 $ hg qnew refresh-pattern
202 $ hg qnew refresh-pattern
204 $ hg status
203 $ hg status
205 $ echo A > A
204 $ echo A > A
206 $ hg add
205 $ hg add
207 adding A
206 adding A
208 $ hg qrefresh a # issue 3271, qrefresh with file handled case wrong
207 $ hg qrefresh a # issue 3271, qrefresh with file handled case wrong
209 $ hg status # empty status means the qrefresh worked
208 $ hg status # empty status means the qrefresh worked
210
209
211 #if osx
210 #if osx
212
211
213 We assume anyone running the tests on a case-insensitive volume on OS
212 We assume anyone running the tests on a case-insensitive volume on OS
214 X will be using HFS+. If that's not true, this test will fail.
213 X will be using HFS+. If that's not true, this test will fail.
215
214
216 $ rm A
215 $ rm A
217 >>> open(u'a\u200c'.encode('utf-8'), 'w').write('unicode is fun')
216 >>> open(u'a\u200c'.encode('utf-8'), 'w').write('unicode is fun')
218 $ hg status
217 $ hg status
219 M A
218 M A
220
219
221 #endif
220 #endif
222
221
223 $ cd ..
222 $ cd ..
@@ -1,145 +1,144 b''
1 #require svn svn-bindings
1 #require svn svn-bindings
2
2
3 $ cat >> $HGRCPATH <<EOF
3 $ cat >> $HGRCPATH <<EOF
4 > [extensions]
4 > [extensions]
5 > convert =
5 > convert =
6 > EOF
6 > EOF
7
7
8 $ svnadmin create svn-repo
8 $ svnadmin create svn-repo
9 $ svnadmin load -q svn-repo < "$TESTDIR/svn/encoding.svndump"
9 $ svnadmin load -q svn-repo < "$TESTDIR/svn/encoding.svndump"
10
10
11 Convert while testing all possible outputs
11 Convert while testing all possible outputs
12
12
13 $ hg --debug convert svn-repo A-hg
13 $ hg --debug convert svn-repo A-hg
14 initializing destination A-hg repository
14 initializing destination A-hg repository
15 reparent to file://*/svn-repo (glob)
15 reparent to file://*/svn-repo (glob)
16 run hg sink pre-conversion action
16 run hg sink pre-conversion action
17 scanning source...
17 scanning source...
18 found trunk at 'trunk'
18 found trunk at 'trunk'
19 found tags at 'tags'
19 found tags at 'tags'
20 found branches at 'branches'
20 found branches at 'branches'
21 found branch branch\xc3\xa9 at 5 (esc)
21 found branch branch\xc3\xa9 at 5 (esc)
22 found branch branch\xc3\xa9e at 6 (esc)
22 found branch branch\xc3\xa9e at 6 (esc)
23 scanning: 1/4 revisions (25.00%)
23 scanning: 1/4 revisions (25.00%)
24 reparent to file://*/svn-repo/trunk (glob)
24 reparent to file://*/svn-repo/trunk (glob)
25 fetching revision log for "/trunk" from 4 to 0
25 fetching revision log for "/trunk" from 4 to 0
26 parsing revision 4 (2 changes)
26 parsing revision 4 (2 changes)
27 parsing revision 3 (4 changes)
27 parsing revision 3 (4 changes)
28 parsing revision 2 (3 changes)
28 parsing revision 2 (3 changes)
29 parsing revision 1 (3 changes)
29 parsing revision 1 (3 changes)
30 no copyfrom path, don't know what to do.
30 no copyfrom path, don't know what to do.
31 '/branches' is not under '/trunk', ignoring
31 '/branches' is not under '/trunk', ignoring
32 '/tags' is not under '/trunk', ignoring
32 '/tags' is not under '/trunk', ignoring
33 scanning: 2/4 revisions (50.00%)
33 scanning: 2/4 revisions (50.00%)
34 reparent to file://*/svn-repo/branches/branch%C3%A9 (glob)
34 reparent to file://*/svn-repo/branches/branch%C3%A9 (glob)
35 fetching revision log for "/branches/branch\xc3\xa9" from 5 to 0 (esc)
35 fetching revision log for "/branches/branch\xc3\xa9" from 5 to 0 (esc)
36 parsing revision 5 (1 changes)
36 parsing revision 5 (1 changes)
37 reparent to file://*/svn-repo (glob)
37 reparent to file://*/svn-repo (glob)
38 reparent to file://*/svn-repo/branches/branch%C3%A9 (glob)
38 reparent to file://*/svn-repo/branches/branch%C3%A9 (glob)
39 found parent of branch /branches/branch\xc3\xa9 at 4: /trunk (esc)
39 found parent of branch /branches/branch\xc3\xa9 at 4: /trunk (esc)
40 scanning: 3/4 revisions (75.00%)
40 scanning: 3/4 revisions (75.00%)
41 reparent to file://*/svn-repo/branches/branch%C3%A9e (glob)
41 reparent to file://*/svn-repo/branches/branch%C3%A9e (glob)
42 fetching revision log for "/branches/branch\xc3\xa9e" from 6 to 0 (esc)
42 fetching revision log for "/branches/branch\xc3\xa9e" from 6 to 0 (esc)
43 parsing revision 6 (1 changes)
43 parsing revision 6 (1 changes)
44 reparent to file://*/svn-repo (glob)
44 reparent to file://*/svn-repo (glob)
45 reparent to file://*/svn-repo/branches/branch%C3%A9e (glob)
45 reparent to file://*/svn-repo/branches/branch%C3%A9e (glob)
46 found parent of branch /branches/branch\xc3\xa9e at 5: /branches/branch\xc3\xa9 (esc)
46 found parent of branch /branches/branch\xc3\xa9e at 5: /branches/branch\xc3\xa9 (esc)
47 scanning: 4/4 revisions (100.00%)
47 scanning: 4/4 revisions (100.00%)
48 scanning: 5/4 revisions (125.00%)
48 scanning: 5/4 revisions (125.00%)
49 scanning: 6/4 revisions (150.00%)
49 scanning: 6/4 revisions (150.00%)
50 sorting...
50 sorting...
51 converting...
51 converting...
52 5 init projA
52 5 init projA
53 source: svn:afeb9c47-92ff-4c0c-9f72-e1f6eb8ac9af/trunk@1
53 source: svn:afeb9c47-92ff-4c0c-9f72-e1f6eb8ac9af/trunk@1
54 converting: 0/6 revisions (0.00%)
54 converting: 0/6 revisions (0.00%)
55 committing changelog
55 committing changelog
56 couldn't read revision branch cache names: * (glob)
57 4 hello
56 4 hello
58 source: svn:afeb9c47-92ff-4c0c-9f72-e1f6eb8ac9af/trunk@2
57 source: svn:afeb9c47-92ff-4c0c-9f72-e1f6eb8ac9af/trunk@2
59 converting: 1/6 revisions (16.67%)
58 converting: 1/6 revisions (16.67%)
60 reparent to file://*/svn-repo/trunk (glob)
59 reparent to file://*/svn-repo/trunk (glob)
61 scanning paths: /trunk/\xc3\xa0 0/3 (0.00%) (esc)
60 scanning paths: /trunk/\xc3\xa0 0/3 (0.00%) (esc)
62 scanning paths: /trunk/\xc3\xa0/e\xcc\x81 1/3 (33.33%) (esc)
61 scanning paths: /trunk/\xc3\xa0/e\xcc\x81 1/3 (33.33%) (esc)
63 scanning paths: /trunk/\xc3\xa9 2/3 (66.67%) (esc)
62 scanning paths: /trunk/\xc3\xa9 2/3 (66.67%) (esc)
64 committing files:
63 committing files:
65 \xc3\xa0/e\xcc\x81 (esc)
64 \xc3\xa0/e\xcc\x81 (esc)
66 getting files: \xc3\xa0/e\xcc\x81 1/2 (50.00%) (esc)
65 getting files: \xc3\xa0/e\xcc\x81 1/2 (50.00%) (esc)
67 \xc3\xa9 (esc)
66 \xc3\xa9 (esc)
68 getting files: \xc3\xa9 2/2 (100.00%) (esc)
67 getting files: \xc3\xa9 2/2 (100.00%) (esc)
69 committing manifest
68 committing manifest
70 committing changelog
69 committing changelog
71 3 copy files
70 3 copy files
72 source: svn:afeb9c47-92ff-4c0c-9f72-e1f6eb8ac9af/trunk@3
71 source: svn:afeb9c47-92ff-4c0c-9f72-e1f6eb8ac9af/trunk@3
73 converting: 2/6 revisions (33.33%)
72 converting: 2/6 revisions (33.33%)
74 scanning paths: /trunk/\xc3\xa0 0/4 (0.00%) (esc)
73 scanning paths: /trunk/\xc3\xa0 0/4 (0.00%) (esc)
75 gone from -1
74 gone from -1
76 reparent to file://*/svn-repo (glob)
75 reparent to file://*/svn-repo (glob)
77 reparent to file://*/svn-repo/trunk (glob)
76 reparent to file://*/svn-repo/trunk (glob)
78 scanning paths: /trunk/\xc3\xa8 1/4 (25.00%) (esc)
77 scanning paths: /trunk/\xc3\xa8 1/4 (25.00%) (esc)
79 copied to \xc3\xa8 from \xc3\xa9@2 (esc)
78 copied to \xc3\xa8 from \xc3\xa9@2 (esc)
80 scanning paths: /trunk/\xc3\xa9 2/4 (50.00%) (esc)
79 scanning paths: /trunk/\xc3\xa9 2/4 (50.00%) (esc)
81 gone from -1
80 gone from -1
82 reparent to file://*/svn-repo (glob)
81 reparent to file://*/svn-repo (glob)
83 reparent to file://*/svn-repo/trunk (glob)
82 reparent to file://*/svn-repo/trunk (glob)
84 scanning paths: /trunk/\xc3\xb9 3/4 (75.00%) (esc)
83 scanning paths: /trunk/\xc3\xb9 3/4 (75.00%) (esc)
85 mark /trunk/\xc3\xb9 came from \xc3\xa0:2 (esc)
84 mark /trunk/\xc3\xb9 came from \xc3\xa0:2 (esc)
86 getting files: \xc3\xa0/e\xcc\x81 1/4 (25.00%) (esc)
85 getting files: \xc3\xa0/e\xcc\x81 1/4 (25.00%) (esc)
87 getting files: \xc3\xa9 2/4 (50.00%) (esc)
86 getting files: \xc3\xa9 2/4 (50.00%) (esc)
88 committing files:
87 committing files:
89 \xc3\xa8 (esc)
88 \xc3\xa8 (esc)
90 getting files: \xc3\xa8 3/4 (75.00%) (esc)
89 getting files: \xc3\xa8 3/4 (75.00%) (esc)
91 \xc3\xa8: copy \xc3\xa9:6b67ccefd5ce6de77e7ead4f5292843a0255329f (esc)
90 \xc3\xa8: copy \xc3\xa9:6b67ccefd5ce6de77e7ead4f5292843a0255329f (esc)
92 \xc3\xb9/e\xcc\x81 (esc)
91 \xc3\xb9/e\xcc\x81 (esc)
93 getting files: \xc3\xb9/e\xcc\x81 4/4 (100.00%) (esc)
92 getting files: \xc3\xb9/e\xcc\x81 4/4 (100.00%) (esc)
94 \xc3\xb9/e\xcc\x81: copy \xc3\xa0/e\xcc\x81:a9092a3d84a37b9993b5c73576f6de29b7ea50f6 (esc)
93 \xc3\xb9/e\xcc\x81: copy \xc3\xa0/e\xcc\x81:a9092a3d84a37b9993b5c73576f6de29b7ea50f6 (esc)
95 committing manifest
94 committing manifest
96 committing changelog
95 committing changelog
97 2 remove files
96 2 remove files
98 source: svn:afeb9c47-92ff-4c0c-9f72-e1f6eb8ac9af/trunk@4
97 source: svn:afeb9c47-92ff-4c0c-9f72-e1f6eb8ac9af/trunk@4
99 converting: 3/6 revisions (50.00%)
98 converting: 3/6 revisions (50.00%)
100 scanning paths: /trunk/\xc3\xa8 0/2 (0.00%) (esc)
99 scanning paths: /trunk/\xc3\xa8 0/2 (0.00%) (esc)
101 gone from -1
100 gone from -1
102 reparent to file://*/svn-repo (glob)
101 reparent to file://*/svn-repo (glob)
103 reparent to file://*/svn-repo/trunk (glob)
102 reparent to file://*/svn-repo/trunk (glob)
104 scanning paths: /trunk/\xc3\xb9 1/2 (50.00%) (esc)
103 scanning paths: /trunk/\xc3\xb9 1/2 (50.00%) (esc)
105 gone from -1
104 gone from -1
106 reparent to file://*/svn-repo (glob)
105 reparent to file://*/svn-repo (glob)
107 reparent to file://*/svn-repo/trunk (glob)
106 reparent to file://*/svn-repo/trunk (glob)
108 getting files: \xc3\xa8 1/2 (50.00%) (esc)
107 getting files: \xc3\xa8 1/2 (50.00%) (esc)
109 getting files: \xc3\xb9/e\xcc\x81 2/2 (100.00%) (esc)
108 getting files: \xc3\xb9/e\xcc\x81 2/2 (100.00%) (esc)
110 committing files:
109 committing files:
111 committing manifest
110 committing manifest
112 committing changelog
111 committing changelog
113 1 branch to branch?
112 1 branch to branch?
114 source: svn:afeb9c47-92ff-4c0c-9f72-e1f6eb8ac9af/branches/branch?@5
113 source: svn:afeb9c47-92ff-4c0c-9f72-e1f6eb8ac9af/branches/branch?@5
115 converting: 4/6 revisions (66.67%)
114 converting: 4/6 revisions (66.67%)
116 reparent to file://*/svn-repo/branches/branch%C3%A9 (glob)
115 reparent to file://*/svn-repo/branches/branch%C3%A9 (glob)
117 scanning paths: /branches/branch\xc3\xa9 0/1 (0.00%) (esc)
116 scanning paths: /branches/branch\xc3\xa9 0/1 (0.00%) (esc)
118 committing changelog
117 committing changelog
119 0 branch to branch?e
118 0 branch to branch?e
120 source: svn:afeb9c47-92ff-4c0c-9f72-e1f6eb8ac9af/branches/branch?e@6
119 source: svn:afeb9c47-92ff-4c0c-9f72-e1f6eb8ac9af/branches/branch?e@6
121 converting: 5/6 revisions (83.33%)
120 converting: 5/6 revisions (83.33%)
122 reparent to file://*/svn-repo/branches/branch%C3%A9e (glob)
121 reparent to file://*/svn-repo/branches/branch%C3%A9e (glob)
123 scanning paths: /branches/branch\xc3\xa9e 0/1 (0.00%) (esc)
122 scanning paths: /branches/branch\xc3\xa9e 0/1 (0.00%) (esc)
124 committing changelog
123 committing changelog
125 reparent to file://*/svn-repo (glob)
124 reparent to file://*/svn-repo (glob)
126 reparent to file://*/svn-repo/branches/branch%C3%A9e (glob)
125 reparent to file://*/svn-repo/branches/branch%C3%A9e (glob)
127 reparent to file://*/svn-repo (glob)
126 reparent to file://*/svn-repo (glob)
128 reparent to file://*/svn-repo/branches/branch%C3%A9e (glob)
127 reparent to file://*/svn-repo/branches/branch%C3%A9e (glob)
129 updating tags
128 updating tags
130 committing files:
129 committing files:
131 .hgtags
130 .hgtags
132 committing manifest
131 committing manifest
133 committing changelog
132 committing changelog
134 run hg sink post-conversion action
133 run hg sink post-conversion action
135 $ cd A-hg
134 $ cd A-hg
136 $ hg up
135 $ hg up
137 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
136 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
138
137
139 Check tags are in UTF-8
138 Check tags are in UTF-8
140
139
141 $ cat .hgtags
140 $ cat .hgtags
142 e94e4422020e715add80525e8f0f46c9968689f1 branch\xc3\xa9e (esc)
141 e94e4422020e715add80525e8f0f46c9968689f1 branch\xc3\xa9e (esc)
143 f7e66f98380ed1e53a797c5c7a7a2616a7ab377d branch\xc3\xa9 (esc)
142 f7e66f98380ed1e53a797c5c7a7a2616a7ab377d branch\xc3\xa9 (esc)
144
143
145 $ cd ..
144 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now