1028
1030
# the internal _dirblocks. So the dirblock state must have already been
1030
1032
assert self._dirblock_state != DirState.NOT_IN_MEMORY
1031
assert entry[1][0][0] == 'f', \
1032
'can only get sha1 for a file not: %s %s' % (
1033
DirState._minikind_to_kind[entry[1][0][0]], entry[0])
1033
# TODO: jam 20070301 Because we now allow kind changes (files => dirs)
1034
# we should actually base this check on the stat value, since
1035
# that is the absolute measurement of whether we have a file or
1036
# directory or link. That means that this function might actually
1037
# change an entry from being a file => dir or dir => file, etc.
1038
if entry[1][0][0] != 'f':
1034
1040
if stat_value is None:
1035
1041
stat_value = os.lstat(abspath)
1036
1042
packed_stat = pack_stat(stat_value)
1563
1569
num_entries_line = self._state_file.readline()
1564
1570
assert num_entries_line.startswith('num_entries: '), 'missing num_entries line'
1565
1571
self._num_entries = int(num_entries_line[len('num_entries: '):-1])
1567
1573
def save(self):
1568
1574
"""Save any pending changes created during this session.
1570
1576
We reuse the existing file, because that prevents race conditions with
1571
file creation, and we expect to be using oslocks on it in the near
1572
future to prevent concurrent modification and reads - because dirstates
1573
incremental data aggretation is not compatible with reading a modified
1574
file, and replacing a file in use by another process is impossible on
1577
file creation, and use oslocks on it to prevent concurrent modification
1578
and reads - because dirstates incremental data aggretation is not
1579
compatible with reading a modified file, and replacing a file in use by
1580
another process is impossible on windows.
1577
1582
A dirstate in read only mode should be smart enough though to validate
1578
1583
that the file has not changed, and otherwise discard its cache and
1582
1587
if (self._header_state == DirState.IN_MEMORY_MODIFIED or
1583
1588
self._dirblock_state == DirState.IN_MEMORY_MODIFIED):
1584
self._state_file.seek(0)
1585
self._state_file.writelines(self.get_lines())
1586
self._state_file.truncate()
1587
self._state_file.flush()
1588
self._header_state = DirState.IN_MEMORY_UNMODIFIED
1589
self._dirblock_state = DirState.IN_MEMORY_UNMODIFIED
1590
if self._lock_state == 'w':
1591
out_file = self._state_file
1594
# Try to grab a write lock so that we can update the file.
1596
wlock = lock.WriteLock(self._filename)
1597
except (errors.LockError, errors.LockContention), e:
1598
# We couldn't grab the lock, so just leave things dirty in
1602
# This may be a read-only tree, or someone else may have a
1603
# ReadLock. so handle the case when we cannot grab a write
1605
if e.errno in (errno.ENOENT, errno.EPERM, errno.EACCES,
1607
# Ignore these errors and just don't save anything
1613
out_file.writelines(self.get_lines())
1616
self._header_state = DirState.IN_MEMORY_UNMODIFIED
1617
self._dirblock_state = DirState.IN_MEMORY_UNMODIFIED
1619
if wlock is not None:
1591
1622
def _set_data(self, parent_ids, dirblocks):
1592
1623
"""Set the full dirstate data in memory.
2053
2084
"""Acquire a read lock on the dirstate"""
2054
2085
if self._lock_token is not None:
2055
2086
raise errors.LockContention(self._lock_token)
2087
# TODO: jam 20070301 Rather than wiping completely, if the blocks are
2088
# already in memory, we could read just the header and check for
2089
# any modification. If not modified, we can just leave things
2056
2091
self._lock_token = lock.ReadLock(self._filename)
2092
self._lock_state = 'r'
2057
2093
self._state_file = self._lock_token.f
2058
2094
self._wipe_state()
2061
2097
"""Acquire a write lock on the dirstate"""
2062
2098
if self._lock_token is not None:
2063
2099
raise errors.LockContention(self._lock_token)
2100
# TODO: jam 20070301 Rather than wiping completely, if the blocks are
2101
# already in memory, we could read just the header and check for
2102
# any modification. If not modified, we can just leave things
2064
2104
self._lock_token = lock.WriteLock(self._filename)
2105
self._lock_state = 'w'
2065
2106
self._state_file = self._lock_token.f
2066
2107
self._wipe_state()
2069
2110
"""Drop any locks held on the dirstate"""
2070
2111
if self._lock_token is None:
2071
2112
raise errors.LockNotHeld(self)
2113
# TODO: jam 20070301 Rather than wiping completely, if the blocks are
2114
# already in memory, we could read just the header and check for
2115
# any modification. If not modified, we can just leave things
2072
2117
self._state_file = None
2118
self._lock_state = None
2073
2119
self._lock_token.unlock()
2074
2120
self._lock_token = None
2075
2121
self._split_path_cache = {}