13 constants, |
13 constants, |
14 shallowutil, |
14 shallowutil, |
15 ) |
15 ) |
16 |
16 |
17 # (filename hash, offset, size) |
17 # (filename hash, offset, size) |
18 INDEXFORMAT0 = '!20sQQ' |
18 INDEXFORMAT2 = '!20sQQII' |
19 INDEXENTRYLENGTH0 = struct.calcsize(INDEXFORMAT0) |
19 INDEXENTRYLENGTH2 = struct.calcsize(INDEXFORMAT2) |
20 INDEXFORMAT1 = '!20sQQII' |
|
21 INDEXENTRYLENGTH1 = struct.calcsize(INDEXFORMAT1) |
|
22 NODELENGTH = 20 |
20 NODELENGTH = 20 |
23 |
21 |
24 NODEINDEXFORMAT = '!20sQ' |
22 NODEINDEXFORMAT = '!20sQ' |
25 NODEINDEXENTRYLENGTH = struct.calcsize(NODEINDEXFORMAT) |
23 NODEINDEXENTRYLENGTH = struct.calcsize(NODEINDEXFORMAT) |
26 |
24 |
82 |
80 |
83 class historypack(basepack.basepack): |
81 class historypack(basepack.basepack): |
84 INDEXSUFFIX = INDEXSUFFIX |
82 INDEXSUFFIX = INDEXSUFFIX |
85 PACKSUFFIX = PACKSUFFIX |
83 PACKSUFFIX = PACKSUFFIX |
86 |
84 |
87 SUPPORTED_VERSIONS = [0, 1] |
85 SUPPORTED_VERSIONS = [2] |
88 |
86 |
89 def __init__(self, path): |
87 def __init__(self, path): |
90 super(historypack, self).__init__(path) |
88 super(historypack, self).__init__(path) |
91 |
89 self.INDEXFORMAT = INDEXFORMAT2 |
92 if self.VERSION == 0: |
90 self.INDEXENTRYLENGTH = INDEXENTRYLENGTH2 |
93 self.INDEXFORMAT = INDEXFORMAT0 |
|
94 self.INDEXENTRYLENGTH = INDEXENTRYLENGTH0 |
|
95 else: |
|
96 self.INDEXFORMAT = INDEXFORMAT1 |
|
97 self.INDEXENTRYLENGTH = INDEXENTRYLENGTH1 |
|
98 |
91 |
99 def getmissing(self, keys): |
92 def getmissing(self, keys): |
100 missing = [] |
93 missing = [] |
101 for name, node in keys: |
94 for name, node in keys: |
102 try: |
95 try: |
213 entry = self._bisect(namehash, start, end, self.INDEXENTRYLENGTH) |
206 entry = self._bisect(namehash, start, end, self.INDEXENTRYLENGTH) |
214 if not entry: |
207 if not entry: |
215 raise KeyError(name) |
208 raise KeyError(name) |
216 |
209 |
217 rawentry = struct.unpack(self.INDEXFORMAT, entry) |
210 rawentry = struct.unpack(self.INDEXFORMAT, entry) |
218 if self.VERSION == 0: |
211 x, offset, size, nodeindexoffset, nodeindexsize = rawentry |
219 x, offset, size = rawentry |
212 rawnamelen = self._index[nodeindexoffset:nodeindexoffset + |
220 nodeindexoffset = None |
213 constants.FILENAMESIZE] |
221 nodeindexsize = None |
214 actualnamelen = struct.unpack('!H', rawnamelen)[0] |
222 else: |
215 nodeindexoffset += constants.FILENAMESIZE |
223 x, offset, size, nodeindexoffset, nodeindexsize = rawentry |
216 actualname = self._index[nodeindexoffset:nodeindexoffset + |
224 rawnamelen = self._index[nodeindexoffset:nodeindexoffset + |
217 actualnamelen] |
225 constants.FILENAMESIZE] |
218 if actualname != name: |
226 actualnamelen = struct.unpack('!H', rawnamelen)[0] |
219 raise KeyError("found file name %s when looking for %s" % |
227 nodeindexoffset += constants.FILENAMESIZE |
220 (actualname, name)) |
228 actualname = self._index[nodeindexoffset:nodeindexoffset + |
221 nodeindexoffset += actualnamelen |
229 actualnamelen] |
|
230 if actualname != name: |
|
231 raise KeyError("found file name %s when looking for %s" % |
|
232 (actualname, name)) |
|
233 nodeindexoffset += actualnamelen |
|
234 |
222 |
235 filenamelength = struct.unpack('!H', self._data[offset:offset + |
223 filenamelength = struct.unpack('!H', self._data[offset:offset + |
236 constants.FILENAMESIZE])[0] |
224 constants.FILENAMESIZE])[0] |
237 offset += constants.FILENAMESIZE |
225 offset += constants.FILENAMESIZE |
238 |
226 |
404 [1]: new in version 1. |
392 [1]: new in version 1. |
405 """ |
393 """ |
406 INDEXSUFFIX = INDEXSUFFIX |
394 INDEXSUFFIX = INDEXSUFFIX |
407 PACKSUFFIX = PACKSUFFIX |
395 PACKSUFFIX = PACKSUFFIX |
408 |
396 |
409 SUPPORTED_VERSIONS = [0, 1] |
397 SUPPORTED_VERSIONS = [2] |
410 |
398 |
411 def __init__(self, ui, packpath, version=0): |
399 def __init__(self, ui, packpath, version=2): |
412 # internal config: remotefilelog.historypackv1 |
|
413 if version == 0 and ui.configbool('remotefilelog', 'historypackv1'): |
|
414 version = 1 |
|
415 |
|
416 super(mutablehistorypack, self).__init__(ui, packpath, version=version) |
400 super(mutablehistorypack, self).__init__(ui, packpath, version=version) |
417 self.files = {} |
401 self.files = {} |
418 self.entrylocations = {} |
402 self.entrylocations = {} |
419 self.fileentries = {} |
403 self.fileentries = {} |
420 |
404 |
421 if version == 0: |
405 self.INDEXFORMAT = INDEXFORMAT2 |
422 self.INDEXFORMAT = INDEXFORMAT0 |
406 self.INDEXENTRYLENGTH = INDEXENTRYLENGTH2 |
423 self.INDEXENTRYLENGTH = INDEXENTRYLENGTH0 |
|
424 else: |
|
425 self.INDEXFORMAT = INDEXFORMAT1 |
|
426 self.INDEXENTRYLENGTH = INDEXENTRYLENGTH1 |
|
427 |
407 |
428 self.NODEINDEXFORMAT = NODEINDEXFORMAT |
408 self.NODEINDEXFORMAT = NODEINDEXFORMAT |
429 self.NODEINDEXENTRYLENGTH = NODEINDEXENTRYLENGTH |
409 self.NODEINDEXENTRYLENGTH = NODEINDEXENTRYLENGTH |
430 |
410 |
431 def add(self, filename, node, p1, p2, linknode, copyfrom): |
411 def add(self, filename, node, p1, p2, linknode, copyfrom): |
497 def createindex(self, nodelocations, indexoffset): |
477 def createindex(self, nodelocations, indexoffset): |
498 fileindexformat = self.INDEXFORMAT |
478 fileindexformat = self.INDEXFORMAT |
499 fileindexlength = self.INDEXENTRYLENGTH |
479 fileindexlength = self.INDEXENTRYLENGTH |
500 nodeindexformat = self.NODEINDEXFORMAT |
480 nodeindexformat = self.NODEINDEXFORMAT |
501 nodeindexlength = self.NODEINDEXENTRYLENGTH |
481 nodeindexlength = self.NODEINDEXENTRYLENGTH |
502 version = self.VERSION |
|
503 |
482 |
504 files = ((hashlib.sha1(filename).digest(), filename, offset, size) |
483 files = ((hashlib.sha1(filename).digest(), filename, offset, size) |
505 for filename, (offset, size) in self.files.iteritems()) |
484 for filename, (offset, size) in self.files.iteritems()) |
506 files = sorted(files) |
485 files = sorted(files) |
507 |
486 |
513 fileindexentries = [] |
492 fileindexentries = [] |
514 nodeindexentries = [] |
493 nodeindexentries = [] |
515 nodecount = 0 |
494 nodecount = 0 |
516 for namehash, filename, offset, size in files: |
495 for namehash, filename, offset, size in files: |
517 # File section index |
496 # File section index |
518 if version == 0: |
497 nodelocations = self.entrylocations[filename] |
519 rawentry = struct.pack(fileindexformat, namehash, offset, size) |
498 |
520 else: |
499 nodeindexsize = len(nodelocations) * nodeindexlength |
521 nodelocations = self.entrylocations[filename] |
500 |
522 |
501 rawentry = struct.pack(fileindexformat, namehash, offset, size, |
523 nodeindexsize = len(nodelocations) * nodeindexlength |
502 nodeindexoffset, nodeindexsize) |
524 |
503 # Node index |
525 rawentry = struct.pack(fileindexformat, namehash, offset, size, |
504 nodeindexentries.append(struct.pack(constants.FILENAMESTRUCT, |
526 nodeindexoffset, nodeindexsize) |
505 len(filename)) + filename) |
527 # Node index |
506 nodeindexoffset += constants.FILENAMESIZE + len(filename) |
528 nodeindexentries.append(struct.pack(constants.FILENAMESTRUCT, |
507 |
529 len(filename)) + filename) |
508 for node, location in sorted(nodelocations.iteritems()): |
530 nodeindexoffset += constants.FILENAMESIZE + len(filename) |
509 nodeindexentries.append(struct.pack(nodeindexformat, node, |
531 |
510 location)) |
532 for node, location in sorted(nodelocations.iteritems()): |
511 nodecount += 1 |
533 nodeindexentries.append(struct.pack(nodeindexformat, node, |
512 |
534 location)) |
513 nodeindexoffset += len(nodelocations) * nodeindexlength |
535 nodecount += 1 |
|
536 |
|
537 nodeindexoffset += len(nodelocations) * nodeindexlength |
|
538 |
514 |
539 fileindexentries.append(rawentry) |
515 fileindexentries.append(rawentry) |
540 |
516 |
541 nodecountraw = '' |
517 nodecountraw = '' |
542 if version == 1: |
518 nodecountraw = struct.pack('!Q', nodecount) |
543 nodecountraw = struct.pack('!Q', nodecount) |
|
544 return (''.join(fileindexentries) + nodecountraw + |
519 return (''.join(fileindexentries) + nodecountraw + |
545 ''.join(nodeindexentries)) |
520 ''.join(nodeindexentries)) |