44 propertycache = util.propertycache |
44 propertycache = util.propertycache |
45 filecache = scmutil.filecache |
45 filecache = scmutil.filecache |
46 _rangemask = 0x7FFFFFFF |
46 _rangemask = 0x7FFFFFFF |
47 |
47 |
48 dirstatetuple = parsers.dirstatetuple |
48 dirstatetuple = parsers.dirstatetuple |
|
49 |
|
50 |
|
51 # a special value used internally for `size` if the file come from the other parent |
|
52 FROM_P2 = -2 |
49 |
53 |
50 |
54 |
51 class repocache(filecache): |
55 class repocache(filecache): |
52 """filecache for files in .hg/""" |
56 """filecache for files in .hg/""" |
53 |
57 |
482 # if there is a merge going on and the file was either |
486 # if there is a merge going on and the file was either |
483 # in state 'm' (-1) or coming from other parent (-2) before |
487 # in state 'm' (-1) or coming from other parent (-2) before |
484 # being removed, restore that state. |
488 # being removed, restore that state. |
485 entry = self._map.get(f) |
489 entry = self._map.get(f) |
486 if entry is not None: |
490 if entry is not None: |
487 if entry[0] == b'r' and entry[2] in (-1, -2): |
491 if entry[0] == b'r' and entry[2] in (-1, FROM_P2): |
488 source = self._map.copymap.get(f) |
492 source = self._map.copymap.get(f) |
489 if entry[2] == -1: |
493 if entry[2] == -1: |
490 self.merge(f) |
494 self.merge(f) |
491 elif entry[2] == -2: |
495 elif entry[2] == FROM_P2: |
492 self.otherparent(f) |
496 self.otherparent(f) |
493 if source: |
497 if source: |
494 self.copy(source, f) |
498 self.copy(source, f) |
495 return |
499 return |
496 if entry[0] == b'm' or entry[0] == b'n' and entry[2] == -2: |
500 if entry[0] == b'm' or entry[0] == b'n' and entry[2] == FROM_P2: |
497 return |
501 return |
498 self._addpath(f, b'n', 0, -1, -1) |
502 self._addpath(f, b'n', 0, -1, -1) |
499 self._map.copymap.pop(f, None) |
503 self._map.copymap.pop(f, None) |
500 |
504 |
501 def otherparent(self, f): |
505 def otherparent(self, f): |
503 if self._pl[1] == self._nodeconstants.nullid: |
507 if self._pl[1] == self._nodeconstants.nullid: |
504 msg = _(b"setting %r to other parent only allowed in merges") % f |
508 msg = _(b"setting %r to other parent only allowed in merges") % f |
505 raise error.Abort(msg) |
509 raise error.Abort(msg) |
506 if f in self and self[f] == b'n': |
510 if f in self and self[f] == b'n': |
507 # merge-like |
511 # merge-like |
508 self._addpath(f, b'm', 0, -2, -1) |
512 self._addpath(f, b'm', 0, FROM_P2, -1) |
509 else: |
513 else: |
510 # add-like |
514 # add-like |
511 self._addpath(f, b'n', 0, -2, -1) |
515 self._addpath(f, b'n', 0, FROM_P2, -1) |
512 self._map.copymap.pop(f, None) |
516 self._map.copymap.pop(f, None) |
513 |
517 |
514 def add(self, f): |
518 def add(self, f): |
515 '''Mark a file added.''' |
519 '''Mark a file added.''' |
516 self._addpath(f, b'a', 0, -1, -1) |
520 self._addpath(f, b'a', 0, -1, -1) |
525 entry = self._map.get(f) |
529 entry = self._map.get(f) |
526 if entry is not None: |
530 if entry is not None: |
527 # backup the previous state |
531 # backup the previous state |
528 if entry[0] == b'm': # merge |
532 if entry[0] == b'm': # merge |
529 size = -1 |
533 size = -1 |
530 elif entry[0] == b'n' and entry[2] == -2: # other parent |
534 elif entry[0] == b'n' and entry[2] == FROM_P2: # other parent |
531 size = -2 |
535 size = FROM_P2 |
532 self._map.otherparentset.add(f) |
536 self._map.otherparentset.add(f) |
533 self._updatedfiles.add(f) |
537 self._updatedfiles.add(f) |
534 self._map.removefile(f, oldstate, size) |
538 self._map.removefile(f, oldstate, size) |
535 if size == 0: |
539 if size == 0: |
536 self._map.copymap.pop(f, None) |
540 self._map.copymap.pop(f, None) |
1300 size >= 0 |
1304 size >= 0 |
1301 and ( |
1305 and ( |
1302 (size != st.st_size and size != st.st_size & _rangemask) |
1306 (size != st.st_size and size != st.st_size & _rangemask) |
1303 or ((mode ^ st.st_mode) & 0o100 and checkexec) |
1307 or ((mode ^ st.st_mode) & 0o100 and checkexec) |
1304 ) |
1308 ) |
1305 or size == -2 # other parent |
1309 or size == FROM_P2 # other parent |
1306 or fn in copymap |
1310 or fn in copymap |
1307 ): |
1311 ): |
1308 if stat.S_ISLNK(st.st_mode) and size != st.st_size: |
1312 if stat.S_ISLNK(st.st_mode) and size != st.st_size: |
1309 # issue6456: Size returned may be longer due to |
1313 # issue6456: Size returned may be longer due to |
1310 # encryption on EXT-4 fscrypt, undecided. |
1314 # encryption on EXT-4 fscrypt, undecided. |
1530 if oldstate == b"?" and "_alldirs" in self.__dict__: |
1534 if oldstate == b"?" and "_alldirs" in self.__dict__: |
1531 self._alldirs.addpath(f) |
1535 self._alldirs.addpath(f) |
1532 self._map[f] = dirstatetuple(state, mode, size, mtime) |
1536 self._map[f] = dirstatetuple(state, mode, size, mtime) |
1533 if state != b'n' or mtime == -1: |
1537 if state != b'n' or mtime == -1: |
1534 self.nonnormalset.add(f) |
1538 self.nonnormalset.add(f) |
1535 if size == -2: |
1539 if size == FROM_P2: |
1536 self.otherparentset.add(f) |
1540 self.otherparentset.add(f) |
1537 |
1541 |
1538 def removefile(self, f, oldstate, size): |
1542 def removefile(self, f, oldstate, size): |
1539 """ |
1543 """ |
1540 Mark a file as removed in the dirstate. |
1544 Mark a file as removed in the dirstate. |
1585 nonnorm = set() |
1589 nonnorm = set() |
1586 otherparent = set() |
1590 otherparent = set() |
1587 for fname, e in pycompat.iteritems(self._map): |
1591 for fname, e in pycompat.iteritems(self._map): |
1588 if e[0] != b'n' or e[3] == -1: |
1592 if e[0] != b'n' or e[3] == -1: |
1589 nonnorm.add(fname) |
1593 nonnorm.add(fname) |
1590 if e[0] == b'n' and e[2] == -2: |
1594 if e[0] == b'n' and e[2] == FROM_P2: |
1591 otherparent.add(fname) |
1595 otherparent.add(fname) |
1592 return nonnorm, otherparent |
1596 return nonnorm, otherparent |
1593 |
1597 |
1594 @propertycache |
1598 @propertycache |
1595 def filefoldmap(self): |
1599 def filefoldmap(self): |