87 for k in sorted(d) |
88 for k in sorted(d) |
88 ] |
89 ] |
89 return b"\0".join(items) |
90 return b"\0".join(items) |
90 |
91 |
91 |
92 |
92 def encodecopies(files, copies): |
|
93 items = [] |
|
94 for i, dst in enumerate(files): |
|
95 if dst in copies: |
|
96 items.append(b'%d\0%s' % (i, copies[dst])) |
|
97 if len(items) != len(copies): |
|
98 raise error.ProgrammingError( |
|
99 b'some copy targets missing from file list' |
|
100 ) |
|
101 return b"\n".join(items) |
|
102 |
|
103 |
|
104 def decodecopies(files, data): |
|
105 try: |
|
106 copies = {} |
|
107 if not data: |
|
108 return copies |
|
109 for l in data.split(b'\n'): |
|
110 strindex, src = l.split(b'\0') |
|
111 i = int(strindex) |
|
112 dst = files[i] |
|
113 copies[dst] = src |
|
114 return copies |
|
115 except (ValueError, IndexError): |
|
116 # Perhaps someone had chosen the same key name (e.g. "p1copies") and |
|
117 # used different syntax for the value. |
|
118 return None |
|
119 |
|
120 |
|
121 def encodefileindices(files, subset): |
|
122 subset = set(subset) |
|
123 indices = [] |
|
124 for i, f in enumerate(files): |
|
125 if f in subset: |
|
126 indices.append(b'%d' % i) |
|
127 return b'\n'.join(indices) |
|
128 |
|
129 |
|
130 def decodefileindices(files, data): |
|
131 try: |
|
132 subset = [] |
|
133 if not data: |
|
134 return subset |
|
135 for strindex in data.split(b'\n'): |
|
136 i = int(strindex) |
|
137 if i < 0 or i >= len(files): |
|
138 return None |
|
139 subset.append(files[i]) |
|
140 return subset |
|
141 except (ValueError, IndexError): |
|
142 # Perhaps someone had chosen the same key name (e.g. "added") and |
|
143 # used different syntax for the value. |
|
144 return None |
|
145 |
|
146 |
|
147 def stripdesc(desc): |
93 def stripdesc(desc): |
148 """strip trailing whitespace and leading and trailing empty lines""" |
94 """strip trailing whitespace and leading and trailing empty lines""" |
149 return b'\n'.join([l.rstrip() for l in desc.splitlines()]).strip(b'\n') |
95 return b'\n'.join([l.rstrip() for l in desc.splitlines()]).strip(b'\n') |
150 |
96 |
151 |
97 |
366 rawindices = self._sidedata.get(sidedatamod.SD_FILESADDED) |
312 rawindices = self._sidedata.get(sidedatamod.SD_FILESADDED) |
367 else: |
313 else: |
368 rawindices = self.extra.get(b'filesadded') |
314 rawindices = self.extra.get(b'filesadded') |
369 if rawindices is None: |
315 if rawindices is None: |
370 return None |
316 return None |
371 return decodefileindices(self.files, rawindices) |
317 return copies.decodefileindices(self.files, rawindices) |
372 |
318 |
373 @property |
319 @property |
374 def filesremoved(self): |
320 def filesremoved(self): |
375 if sidedatamod.SD_FILESREMOVED in self._sidedata: |
321 if sidedatamod.SD_FILESREMOVED in self._sidedata: |
376 rawindices = self._sidedata.get(sidedatamod.SD_FILESREMOVED) |
322 rawindices = self._sidedata.get(sidedatamod.SD_FILESREMOVED) |
377 else: |
323 else: |
378 rawindices = self.extra.get(b'filesremoved') |
324 rawindices = self.extra.get(b'filesremoved') |
379 if rawindices is None: |
325 if rawindices is None: |
380 return None |
326 return None |
381 return decodefileindices(self.files, rawindices) |
327 return copies.decodefileindices(self.files, rawindices) |
382 |
328 |
383 @property |
329 @property |
384 def p1copies(self): |
330 def p1copies(self): |
385 if sidedatamod.SD_P1COPIES in self._sidedata: |
331 if sidedatamod.SD_P1COPIES in self._sidedata: |
386 rawcopies = self._sidedata.get(sidedatamod.SD_P1COPIES) |
332 rawcopies = self._sidedata.get(sidedatamod.SD_P1COPIES) |
387 else: |
333 else: |
388 rawcopies = self.extra.get(b'p1copies') |
334 rawcopies = self.extra.get(b'p1copies') |
389 if rawcopies is None: |
335 if rawcopies is None: |
390 return None |
336 return None |
391 return decodecopies(self.files, rawcopies) |
337 return copies.decodecopies(self.files, rawcopies) |
392 |
338 |
393 @property |
339 @property |
394 def p2copies(self): |
340 def p2copies(self): |
395 if sidedatamod.SD_P2COPIES in self._sidedata: |
341 if sidedatamod.SD_P2COPIES in self._sidedata: |
396 rawcopies = self._sidedata.get(sidedatamod.SD_P2COPIES) |
342 rawcopies = self._sidedata.get(sidedatamod.SD_P2COPIES) |
397 else: |
343 else: |
398 rawcopies = self.extra.get(b'p2copies') |
344 rawcopies = self.extra.get(b'p2copies') |
399 if rawcopies is None: |
345 if rawcopies is None: |
400 return None |
346 return None |
401 return decodecopies(self.files, rawcopies) |
347 return copies.decodecopies(self.files, rawcopies) |
402 |
348 |
403 @property |
349 @property |
404 def description(self): |
350 def description(self): |
405 return encoding.tolocal(self._text[self._offsets[3] + 2 :]) |
351 return encoding.tolocal(self._text[self._offsets[3] + 2 :]) |
406 |
352 |
709 b'filesadded', |
655 b'filesadded', |
710 b'filesremoved', |
656 b'filesremoved', |
711 ): |
657 ): |
712 extra.pop(name, None) |
658 extra.pop(name, None) |
713 if p1copies is not None: |
659 if p1copies is not None: |
714 p1copies = encodecopies(sortedfiles, p1copies) |
660 p1copies = copies.encodecopies(sortedfiles, p1copies) |
715 if p2copies is not None: |
661 if p2copies is not None: |
716 p2copies = encodecopies(sortedfiles, p2copies) |
662 p2copies = copies.encodecopies(sortedfiles, p2copies) |
717 if filesadded is not None: |
663 if filesadded is not None: |
718 filesadded = encodefileindices(sortedfiles, filesadded) |
664 filesadded = copies.encodefileindices(sortedfiles, filesadded) |
719 if filesremoved is not None: |
665 if filesremoved is not None: |
720 filesremoved = encodefileindices(sortedfiles, filesremoved) |
666 filesremoved = copies.encodefileindices(sortedfiles, filesremoved) |
721 if self._copiesstorage == b'extra': |
667 if self._copiesstorage == b'extra': |
722 extrasentries = p1copies, p2copies, filesadded, filesremoved |
668 extrasentries = p1copies, p2copies, filesadded, filesremoved |
723 if extra is None and any(x is not None for x in extrasentries): |
669 if extra is None and any(x is not None for x in extrasentries): |
724 extra = {} |
670 extra = {} |
725 if p1copies is not None: |
671 if p1copies is not None: |