Rev 2331: Merge walkdirs-uses-path_info in file:///home/robertc/source/baz/pathinfo/
Robert Collins
robertc at robertcollins.net
Fri Mar 9 20:39:39 GMT 2007
At file:///home/robertc/source/baz/pathinfo/
------------------------------------------------------------
revno: 2331
revision-id: robertc at robertcollins.net-20070309203935-qsfuff8lf6p6e48n
parent: robertc at robertcollins.net-20070309145635-ebwqt24zw8vj2ggd
parent: robertc at robertcollins.net-20070309155213-fciselcj7bjb6swy
committer: Robert Collins <robertc at robertcollins.net>
branch nick: pathinfo
timestamp: Sat 2007-03-10 07:39:35 +1100
message:
Merge walkdirs-uses-path_info
modified:
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/osutils.py osutils.py-20050309040759-eeaff12fbf77ac86
bzrlib/tests/test_dirstate.py test_dirstate.py-20060728012006-d6mvoihjb3je9peu-2
bzrlib/tests/test_osutils.py test_osutils.py-20051201224856-e48ee24c12182989
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
------------------------------------------------------------
revno: 2326.1.2
merged: robertc at robertcollins.net-20070309155213-fciselcj7bjb6swy
parent: robertc at robertcollins.net-20070309143019-8y1a649z5hzryiuh
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate2
timestamp: Sat 2007-03-10 02:52:13 +1100
message:
Update update_entry to use the path_info API.
=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py 2007-03-09 04:23:52 +0000
+++ b/bzrlib/dirstate.py 2007-03-09 15:52:13 +0000
@@ -215,7 +215,7 @@
osutils,
trace,
)
-from bzrlib.path_info import pack_stat
+from bzrlib.path_info import pack_stat, kind_missing
class _Bisector(object):
@@ -1055,13 +1055,12 @@
raise
return result
- def update_entry(self, entry, abspath, stat_value=None):
+ def update_entry(self, entry, abspath, path_info, kind_missing=kind_missing):
"""Update the entry based on what is actually on disk.
:param entry: This is the dirblock entry for the file in question.
:param abspath: The path on disk for this file.
- :param stat_value: (optional) if we already have done a stat on the
- file, re-use it.
+ :param path_info: A tuple as returned by path_info.path_info.
:return: The sha1 hexdigest of the file (40 bytes) or link target of a
symlink.
"""
@@ -1069,31 +1068,19 @@
# the internal _dirblocks. So the dirblock state must have already been
# read.
assert self._dirblock_state != DirState.NOT_IN_MEMORY
- if stat_value is None:
- try:
- # We could inline os.lstat but the common case is that
- # stat_value will be passed in, not read here.
- stat_value = self._lstat(abspath, entry)
- except (OSError, IOError), e:
- if e.errno in (errno.ENOENT, errno.EACCES,
- errno.EPERM):
- # The entry is missing, consider it gone
- return None
- raise
-
- kind = osutils.file_kind_from_stat_mode(stat_value.st_mode)
+ if path_info[0] is kind_missing:
+ return None
try:
- minikind = DirState._kind_to_minikind[kind]
+ minikind = DirState._kind_to_minikind[path_info[0]]
except KeyError: # Unknown kind
return None
- packed_stat = pack_stat(stat_value)
(saved_minikind, saved_link_or_sha1, saved_file_size,
saved_executable, saved_packed_stat) = entry[1][0]
if (minikind == saved_minikind
- and packed_stat == saved_packed_stat
+ and path_info[4] == saved_packed_stat
# size should also be in packed_stat
- and saved_file_size == stat_value.st_size):
+ and saved_file_size == path_info[1]):
# The stat hasn't changed since we saved, so we can potentially
# re-use the saved sha hash.
if minikind == 'd':
@@ -1102,8 +1089,7 @@
if self._cutoff_time is None:
self._sha_cutoff_time()
- if (stat_value.st_mtime < self._cutoff_time
- and stat_value.st_ctime < self._cutoff_time):
+ if path_info[3] < self._cutoff_time:
# Return the existing fingerprint
return saved_link_or_sha1
@@ -1112,13 +1098,12 @@
link_or_sha1 = None
if minikind == 'f':
link_or_sha1 = self._sha1_file(abspath, entry)
- executable = self._is_executable(stat_value.st_mode,
- saved_executable)
- entry[1][0] = ('f', link_or_sha1, stat_value.st_size,
- executable, packed_stat)
+ executable = self._is_executable(path_info[2], saved_executable)
+ entry[1][0] = ('f', link_or_sha1, path_info[1],
+ executable, path_info[4])
elif minikind == 'd':
link_or_sha1 = None
- entry[1][0] = ('d', '', 0, False, packed_stat)
+ entry[1][0] = ('d', '', 0, False, path_info[4])
if saved_minikind != 'd':
# This changed from something into a directory. Make sure we
# have a directory block for it. This doesn't happen very
@@ -1129,8 +1114,7 @@
osutils.pathjoin(entry[0][0], entry[0][1]))
elif minikind == 'l':
link_or_sha1 = self._read_link(abspath, saved_link_or_sha1)
- entry[1][0] = ('l', link_or_sha1, stat_value.st_size,
- False, packed_stat)
+ entry[1][0] = ('l', link_or_sha1, 0, False, path_info[4])
self._dirblock_state = DirState.IN_MEMORY_MODIFIED
return link_or_sha1
@@ -1159,9 +1143,9 @@
finally:
f.close()
- def _is_executable(self, mode, old_executable):
+ def _is_executable(self, disk_executable, old_executable):
"""Is this file executable?"""
- return bool(S_IEXEC & mode)
+ return disk_executable
def _is_executable_win32(self, mode, old_executable):
"""On win32 the executable bit is stored in the dirstate."""
=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py 2007-03-09 06:16:08 +0000
+++ b/bzrlib/osutils.py 2007-03-09 15:52:13 +0000
@@ -49,6 +49,7 @@
from bzrlib import (
cache_utf8,
errors,
+ path_info,
win32utils,
)
""")
@@ -1047,7 +1048,7 @@
raise errors.IllegalPath(path)
-def walkdirs(top, prefix=""):
+def walkdirs(top, prefix="", path_info=path_info.path_info):
"""Yield data about all the directories in a tree.
This yields all the data about the contents of a directory at a time.
@@ -1083,11 +1084,13 @@
_lstat = os.lstat
_directory = _directory_kind
_listdir = os.listdir
- _kind_from_mode = _formats.get
- pending = [(safe_unicode(prefix), "", _directory, None, safe_unicode(top))]
+ # 0 - relpath, 1- basename, 2- kind, 3 - size, 4- exe, 5-stattime, 6- statcache, 7-toppath
+ # But we don't actually uses 1-6 in pending, so set them to None
+ pending = [(safe_unicode(prefix), "", _directory, None, None, None, None, safe_unicode(top))]
+ native_encoding = sys.getfilesystemencoding()
while pending:
- # 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
- relroot, _, _, _, top = pending.pop()
+ # 0 - relpath, 1- basename, 2- kind, 3 - size, 4- exe, 5- statcache, 6-toppath
+ relroot, _, _, _, _, _, _, top = pending.pop()
if relroot:
relprefix = relroot + u'/'
else:
@@ -1098,9 +1101,9 @@
append = dirblock.append
for name in sorted(_listdir(top)):
abspath = top_slash + name
- statvalue = _lstat(abspath)
- kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
- append((relprefix + name, name, kind, statvalue, abspath))
+ info = path_info(abspath.encode(native_encoding))
+ append((relprefix + name, name, info[0], info[1], info[2], info[3],
+ info[4], abspath))
yield (relroot, top), dirblock
# push the user specified dirs from dirblock
@@ -1129,7 +1132,7 @@
return _walkdirs_fs_utf8(top, prefix=prefix)
-def _walkdirs_fs_utf8(top, prefix=""):
+def _walkdirs_fs_utf8(top, prefix="", path_info=path_info.path_info):
"""See _walkdirs_utf8.
This sub-function is called when we know the filesystem is already in utf8
@@ -1140,11 +1143,11 @@
_listdir = os.listdir
_kind_from_mode = _formats.get
- # 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
- # But we don't actually uses 1-3 in pending, so set them to None
- pending = [(safe_utf8(prefix), None, None, None, safe_utf8(top))]
+ # 0 - relpath, 1- basename, 2- kind, 3 - size, 4- exe, 5-stattime, 6- statcache, 7-toppath
+ # But we don't actually uses 1-6 in pending, so set them to None
+ pending = [(safe_utf8(prefix), None, None, None, None, None, None, safe_utf8(top))]
while pending:
- relroot, _, _, _, top = pending.pop()
+ relroot, _, _, _, _, _, _, top = pending.pop()
if relroot:
relprefix = relroot + '/'
else:
@@ -1155,16 +1158,16 @@
append = dirblock.append
for name in sorted(_listdir(top)):
abspath = top_slash + name
- statvalue = _lstat(abspath)
- kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
- append((relprefix + name, name, kind, statvalue, abspath))
+ info = path_info(abspath)
+ append((relprefix + name, name, info[0], info[1], info[2], info[3],
+ info[4], abspath))
yield (relroot, top), dirblock
# push the user specified dirs from dirblock
pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
-def _walkdirs_unicode_to_utf8(top, prefix=""):
+def _walkdirs_unicode_to_utf8(top, prefix="", path_info=path_info.path_info):
"""See _walkdirs_utf8
Because Win32 has a Unicode api, all of the 'path-from-top' entries will be
@@ -1179,10 +1182,13 @@
_directory = _directory_kind
_listdir = os.listdir
_kind_from_mode = _formats.get
+ fs_encoder = codecs.getencoder(sys.getfilesystemencoding())
- pending = [(safe_utf8(prefix), None, None, None, safe_unicode(top))]
+ # 0 - relpath, 1- basename, 2- kind, 3 - size, 4- exe, 5-stattime, 6- statcache, 7-toppath
+ # But we don't actually uses 1-6 in pending, so set them to None
+ pending = [(safe_utf8(prefix), None, None, None, None, None, None, safe_unicode(top))]
while pending:
- relroot, _, _, _, top = pending.pop()
+ relroot, _, _, _, _, _, _, top = pending.pop()
if relroot:
relprefix = relroot + '/'
else:
@@ -1194,9 +1200,8 @@
for name in sorted(_listdir(top)):
name_utf8 = _utf8_encode(name)[0]
abspath = top_slash + name
- statvalue = _lstat(abspath)
- kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
- append((relprefix + name_utf8, name_utf8, kind, statvalue, abspath))
+ info = path_info(fs_encoder(abspath)[0])
+ append((relprefix + name_utf8, name_utf8, info[0], info[1], info[2], info[3], info[4], abspath))
yield (relroot, top), dirblock
# push the user specified dirs from dirblock
@@ -1240,8 +1245,10 @@
if not os.path.exists(to_path):
real_handlers['directory'](from_path, to_path)
+ if from_path.__class__ != str:
+ from_path = from_path.encode(sys.getfilesystemencoding())
for dir_info, entries in walkdirs(from_path, prefix=to_path):
- for relpath, name, kind, st, abspath in entries:
+ for relpath, _, kind, _, _, _, _, abspath in entries:
real_handlers[kind](abspath, relpath)
=== modified file 'bzrlib/tests/test_dirstate.py'
--- a/bzrlib/tests/test_dirstate.py 2007-03-07 08:00:48 +0000
+++ b/bzrlib/tests/test_dirstate.py 2007-03-09 15:52:13 +0000
@@ -24,6 +24,7 @@
dirstate,
errors,
osutils,
+ path_info,
)
from bzrlib.memorytree import MemoryTree
from bzrlib.tests import TestCase, TestCaseWithTransport
@@ -1138,20 +1139,17 @@
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
state._dirblock_state)
- stat_value = os.lstat('a')
- packed_stat = dirstate.pack_stat(stat_value)
- link_or_sha1 = state.update_entry(entry, abspath='a',
- stat_value=stat_value)
+ info = path_info.path_info('a')
+ link_or_sha1 = state.update_entry(entry, abspath='a', path_info=info)
self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
link_or_sha1)
# The dirblock entry should be updated with the new info
- self.assertEqual([('f', link_or_sha1, 14, False, packed_stat)],
+ self.assertEqual([('f', link_or_sha1, 14, False, info[4])],
entry[1])
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
state._dirblock_state)
- mode = stat_value.st_mode
- self.assertEqual([('sha1', 'a'), ('is_exec', mode, False)], state._log)
+ self.assertEqual([('sha1', 'a'), ('is_exec', False, False)], state._log)
state.save()
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
@@ -1162,10 +1160,9 @@
# guaranteed to look too new.
state.adjust_time(-10)
- link_or_sha1 = state.update_entry(entry, abspath='a',
- stat_value=stat_value)
- self.assertEqual([('sha1', 'a'), ('is_exec', mode, False),
- ('sha1', 'a'), ('is_exec', mode, False),
+ link_or_sha1 = state.update_entry(entry, abspath='a', path_info=info)
+ self.assertEqual([('sha1', 'a'), ('is_exec', False, False),
+ ('sha1', 'a'), ('is_exec', False, False),
], state._log)
self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
link_or_sha1)
@@ -1176,26 +1173,11 @@
# However, if we move the clock forward so the file is considered
# "stable", it should just returned the cached value.
state.adjust_time(20)
- link_or_sha1 = state.update_entry(entry, abspath='a',
- stat_value=stat_value)
- self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
- link_or_sha1)
- self.assertEqual([('sha1', 'a'), ('is_exec', mode, False),
- ('sha1', 'a'), ('is_exec', mode, False),
- ], state._log)
-
- def test_update_entry_no_stat_value(self):
- """Passing the stat_value is optional."""
- state, entry = self.get_state_with_a()
- state.adjust_time(-10) # Make sure the file looks new
- self.build_tree(['a'])
- # Add one where we don't provide the stat or sha already
- link_or_sha1 = state.update_entry(entry, abspath='a')
- self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
- link_or_sha1)
- stat_value = os.lstat('a')
- self.assertEqual([('lstat', 'a'), ('sha1', 'a'),
- ('is_exec', stat_value.st_mode, False),
+ link_or_sha1 = state.update_entry(entry, abspath='a', path_info=info)
+ self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
+ link_or_sha1)
+ self.assertEqual([('sha1', 'a'), ('is_exec', False, False),
+ ('sha1', 'a'), ('is_exec', False, False),
], state._log)
def test_update_entry_symlink(self):
@@ -1209,28 +1191,23 @@
os.symlink('target', 'a')
state.adjust_time(-10) # Make the symlink look new
- stat_value = os.lstat('a')
- packed_stat = dirstate.pack_stat(stat_value)
- link_or_sha1 = state.update_entry(entry, abspath='a',
- stat_value=stat_value)
+ info = path_info.path_info('a')
+ link_or_sha1 = state.update_entry(entry, abspath='a', path_info=info)
self.assertEqual('target', link_or_sha1)
self.assertEqual([('read_link', 'a', '')], state._log)
# Dirblock is updated
- self.assertEqual([('l', link_or_sha1, 6, False, packed_stat)],
- entry[1])
+ self.assertEqual([('l', link_or_sha1, 0, False, info[4])], entry[1])
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
state._dirblock_state)
# Because the stat_value looks new, we should re-read the target
- link_or_sha1 = state.update_entry(entry, abspath='a',
- stat_value=stat_value)
+ link_or_sha1 = state.update_entry(entry, abspath='a', path_info=info)
self.assertEqual('target', link_or_sha1)
self.assertEqual([('read_link', 'a', ''),
('read_link', 'a', 'target'),
], state._log)
state.adjust_time(+20) # Skip into the future, all files look old
- link_or_sha1 = state.update_entry(entry, abspath='a',
- stat_value=stat_value)
+ link_or_sha1 = state.update_entry(entry, abspath='a', path_info=info)
self.assertEqual('target', link_or_sha1)
# There should not be a new read_link call.
# (this is a weak assertion, because read_link is fairly inexpensive,
@@ -1242,7 +1219,8 @@
def test_update_entry_dir(self):
state, entry = self.get_state_with_a()
self.build_tree(['a/'])
- self.assertIs(None, state.update_entry(entry, 'a'))
+ info = path_info.path_info('a')
+ self.assertIs(None, state.update_entry(entry, 'a', info))
def create_and_test_file(self, state, entry):
"""Create a file at 'a' and verify the state finds it.
@@ -1251,15 +1229,12 @@
sure that state.update_entry recognizes it as a file.
"""
self.build_tree(['a'])
- stat_value = os.lstat('a')
- packed_stat = dirstate.pack_stat(stat_value)
-
- link_or_sha1 = state.update_entry(entry, abspath='a')
+ info = path_info.path_info('a')
+ link_or_sha1 = state.update_entry(entry, abspath='a', path_info=info)
self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
link_or_sha1)
- self.assertEqual([('f', link_or_sha1, 14, False, packed_stat)],
- entry[1])
- return packed_stat
+ self.assertEqual([('f', link_or_sha1, 14, False, info[4])], entry[1])
+ return info[4]
def create_and_test_dir(self, state, entry):
"""Create a directory at 'a' and verify the state finds it.
@@ -1268,14 +1243,13 @@
sure that state.update_entry recognizes it as a directory.
"""
self.build_tree(['a/'])
- stat_value = os.lstat('a')
- packed_stat = dirstate.pack_stat(stat_value)
+ info = path_info.path_info('a')
- link_or_sha1 = state.update_entry(entry, abspath='a')
+ link_or_sha1 = state.update_entry(entry, abspath='a', path_info=info)
self.assertIs(None, link_or_sha1)
- self.assertEqual([('d', '', 0, False, packed_stat)], entry[1])
+ self.assertEqual([('d', '', 0, False, info[4])], entry[1])
- return packed_stat
+ return info[4]
def create_and_test_symlink(self, state, entry):
"""Create a symlink at 'a' and verify the state finds it.
@@ -1287,15 +1261,12 @@
support.
"""
os.symlink('path/to/foo', 'a')
-
- stat_value = os.lstat('a')
- packed_stat = dirstate.pack_stat(stat_value)
-
- link_or_sha1 = state.update_entry(entry, abspath='a')
+ info = path_info.path_info('a')
+ link_or_sha1 = state.update_entry(entry, abspath='a', path_info=info)
self.assertEqual('path/to/foo', link_or_sha1)
- self.assertEqual([('l', 'path/to/foo', 11, False, packed_stat)],
+ self.assertEqual([('l', 'path/to/foo', 0, False, info[4])],
entry[1])
- return packed_stat
+ return info[4]
def test_update_missing_file(self):
state, entry = self.get_state_with_a()
@@ -1303,7 +1274,8 @@
# Now if we delete the file, update_entry should recover and
# return None.
os.remove('a')
- self.assertIs(None, state.update_entry(entry, abspath='a'))
+ info = path_info.path_info('a')
+ self.assertIs(None, state.update_entry(entry, 'a', info))
# And the record shouldn't be changed.
digest = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
self.assertEqual([('f', digest, 14, False, packed_stat)],
@@ -1315,7 +1287,8 @@
# Now if we delete the directory, update_entry should recover and
# return None.
os.rmdir('a')
- self.assertIs(None, state.update_entry(entry, abspath='a'))
+ info = path_info.path_info('a')
+ self.assertIs(None, state.update_entry(entry, 'a', info))
self.assertEqual([('d', '', 0, False, packed_stat)], entry[1])
def test_update_missing_symlink(self):
@@ -1324,9 +1297,10 @@
state, entry = self.get_state_with_a()
packed_stat = self.create_and_test_symlink(state, entry)
os.remove('a')
- self.assertIs(None, state.update_entry(entry, abspath='a'))
+ info = path_info.path_info('a')
+ self.assertIs(None, state.update_entry(entry, 'a', info))
# And the record shouldn't be changed.
- self.assertEqual([('l', 'path/to/foo', 11, False, packed_stat)],
+ self.assertEqual([('l', 'path/to/foo', 0, False, packed_stat)],
entry[1])
def test_update_file_to_dir(self):
@@ -1388,16 +1362,15 @@
# it is. With _is_executable_win32 we ignore what is on disk.
entry[1][0] = ('f', '', 0, True, dirstate.DirState.NULLSTAT)
- stat_value = os.lstat('a')
- packed_stat = dirstate.pack_stat(stat_value)
+ info = path_info.path_info('a')
state.adjust_time(-10) # Make sure everything is new
# Make sure it wants to kkkkkkkk
- state.update_entry(entry, abspath='a', stat_value=stat_value)
+ state.update_entry(entry, abspath='a', path_info=info)
# The row is updated, but the executable bit stays set.
digest = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
- self.assertEqual([('f', digest, 14, True, packed_stat)], entry[1])
+ self.assertEqual([('f', digest, 14, True, info[4])], entry[1])
class TestPackStat(TestCaseWithTransport):
=== modified file 'bzrlib/tests/test_osutils.py'
--- a/bzrlib/tests/test_osutils.py 2007-03-07 01:14:11 +0000
+++ b/bzrlib/tests/test_osutils.py 2007-03-09 15:52:13 +0000
@@ -25,6 +25,7 @@
import bzrlib
from bzrlib import (
errors,
+ path_info,
osutils,
win32utils,
)
@@ -521,16 +522,18 @@
'2file'
]
self.build_tree(tree)
+ stats = [os.lstat(path) for path in tree]
+ packs = [path_info.pack_stat(st) for st in stats]
expected_dirblocks = [
(('', '.'),
- [('0file', '0file', 'file'),
- ('1dir', '1dir', 'directory'),
- ('2file', '2file', 'file'),
+ [('0file', '0file', 'file', 18, False, stats[1].st_mtime, packs[1], './0file'),
+ ('1dir', '1dir', 'directory', 0, False, stats[2].st_mtime, packs[2], './1dir'),
+ ('2file', '2file', 'file', 18, False, stats[5].st_mtime, packs[5], './2file'),
]
),
(('1dir', './1dir'),
- [('1dir/0file', '0file', 'file'),
- ('1dir/1dir', '1dir', 'directory'),
+ [('1dir/0file', '0file', 'file', 23, False, stats[3].st_mtime, packs[3], './1dir/0file'),
+ ('1dir/1dir', '1dir', 'directory', 0, False, stats[4].st_mtime, packs[4], './1dir/1dir'),
]
),
(('1dir/1dir', './1dir/1dir'),
@@ -548,14 +551,12 @@
result.append((dirdetail, dirblock))
self.assertTrue(found_bzrdir)
- self.assertEqual(expected_dirblocks,
- [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
+ self.assertEqual(expected_dirblocks, result)
# you can search a subdir only, with a supplied prefix.
result = []
for dirblock in osutils.walkdirs('./1dir', '1dir'):
result.append(dirblock)
- self.assertEqual(expected_dirblocks[1:],
- [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
+ self.assertEqual(expected_dirblocks[1:], result)
def test__walkdirs_utf8(self):
tree = [
@@ -567,16 +568,18 @@
'2file'
]
self.build_tree(tree)
+ stats = [os.lstat(path) for path in tree]
+ packs = [path_info.pack_stat(st) for st in stats]
expected_dirblocks = [
(('', '.'),
- [('0file', '0file', 'file'),
- ('1dir', '1dir', 'directory'),
- ('2file', '2file', 'file'),
+ [('0file', '0file', 'file', 18, False, stats[1].st_mtime, packs[1], './0file'),
+ ('1dir', '1dir', 'directory', 0, False, stats[2].st_mtime, packs[2], './1dir'),
+ ('2file', '2file', 'file', 18, False, stats[5].st_mtime, packs[5], './2file'),
]
),
(('1dir', './1dir'),
- [('1dir/0file', '0file', 'file'),
- ('1dir/1dir', '1dir', 'directory'),
+ [('1dir/0file', '0file', 'file', 23, False, stats[3].st_mtime, packs[3], './1dir/0file'),
+ ('1dir/1dir', '1dir', 'directory', 0, False, stats[4].st_mtime, packs[4], './1dir/1dir'),
]
),
(('1dir/1dir', './1dir/1dir'),
@@ -594,14 +597,12 @@
result.append((dirdetail, dirblock))
self.assertTrue(found_bzrdir)
- self.assertEqual(expected_dirblocks,
- [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
+ self.assertEqual(expected_dirblocks, result)
# you can search a subdir only, with a supplied prefix.
result = []
for dirblock in osutils.walkdirs('./1dir', '1dir'):
result.append(dirblock)
- self.assertEqual(expected_dirblocks[1:],
- [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
+ self.assertEqual(expected_dirblocks[1:], result)
def _filter_out_stat(self, result):
"""Filter out the stat value from the walkdirs result"""
@@ -609,7 +610,7 @@
new_dirblock = []
for info in dirblock:
# Ignore info[3] which is the stat
- new_dirblock.append((info[0], info[1], info[2], info[4]))
+ new_dirblock.append((info[0], info[1], info[2], info[7]))
dirblock[:] = new_dirblock
def test_unicode_walkdirs(self):
@@ -712,9 +713,9 @@
for info in dirblock:
self.assertIsInstance(info[0], str)
self.assertIsInstance(info[1], str)
- self.assertIsInstance(info[4], str)
+ self.assertIsInstance(info[7], str)
# Remove the stat information
- new_dirblock.append((info[0], info[1], info[2], info[4]))
+ new_dirblock.append((info[0], info[1], info[2], info[7]))
result.append((dirdetail, new_dirblock))
self.assertEqual(expected_dirblocks, result)
=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py 2007-03-07 03:09:14 +0000
+++ b/bzrlib/workingtree_4.py 2007-03-09 15:52:13 +0000
@@ -52,6 +52,7 @@
ignores,
merge,
osutils,
+ path_info,
revisiontree,
textui,
transform,
@@ -394,8 +395,11 @@
file_abspath = self.abspath(path)
state = self.current_dirstate()
- link_or_sha1 = state.update_entry(entry, file_abspath,
- stat_value=stat_value)
+ # yes, this always stats. stat_value is not enough to update
+ # an entry, and whoever is statting should gather the info
+ # TODO: pdb if stat_value is given, and is a stat
+ info = path_info.path_info(file_abspath.encode(sys.getfilesystemencoding()))
+ link_or_sha1 = state.update_entry(entry, file_abspath, info)
if entry[1][0][0] == 'f':
return link_or_sha1
return None
@@ -1756,12 +1760,12 @@
def _process_entry(entry, path_info):
"""Compare an entry and real disk to generate delta information.
- :param path_info: top_relpath, basename, kind, lstat, abspath for
- the path of entry. If None, then the path is considered absent.
- (Perhaps we should pass in a concrete entry for this ?)
- Basename is returned as a utf8 string because we expect this
- tuple will be ignored, and don't want to take the time to
- decode.
+ :param path_info: top_relpath, basename, kind, size, exe,
+ statcache, abspath for the path of entry. If None, then the
+ path is considered absent. (Perhaps we should pass in a
+ concrete entry for this ?) Basename is returned as a utf8
+ string because we expect this tuple will be ignored, and don't
+ want to take the time to decode.
"""
if source_index is None:
source_details = NULL_PARENT_DETAILS
@@ -1770,9 +1774,10 @@
target_details = entry[1][target_index]
target_minikind = target_details[0]
if path_info is not None and target_minikind in 'fdlt':
+ # we have a versioned path here, and there is disk data for it.
assert target_index == 0
- link_or_sha1 = state.update_entry(entry, abspath=path_info[4],
- stat_value=path_info[3])
+ link_or_sha1 = state.update_entry(entry, path_info[7],
+ path_info[2:7])
# The entry may have been modified by update_entry
target_details = entry[1][target_index]
target_minikind = target_details[0]
@@ -1814,13 +1819,14 @@
else:
# source and target are both versioned and disk file is present.
target_kind = path_info[2]
+ # Target details is updated at update_entry time
+ target_exec = target_details[3]
if target_kind == 'directory':
if source_minikind != 'd':
content_change = True
else:
# directories have no fingerprint
content_change = False
- target_exec = False
elif target_kind == 'file':
if source_minikind != 'f':
content_change = True
@@ -1828,25 +1834,16 @@
# We could check the size, but we already have the
# sha1 hash.
content_change = (link_or_sha1 != source_details[1])
- # Target details is updated at update_entry time
- if use_filesystem_for_exec:
- # We don't need S_ISREG here, because we are sure
- # we are dealing with a file.
- target_exec = bool(stat.S_IEXEC & path_info[3].st_mode)
- else:
- target_exec = target_details[3]
elif target_kind == 'symlink':
if source_minikind != 'l':
content_change = True
else:
content_change = (link_or_sha1 != source_details[1])
- target_exec = False
elif target_kind == 'tree-reference':
if source_minikind != 't':
content_change = True
else:
content_change = False
- target_exec = False
else:
raise Exception, "unknown kind %s" % path_info[2]
# parent id is the entry for the path in the target tree
@@ -1898,14 +1895,8 @@
path_utf8=entry[0][0])[0][2]
if parent_id == entry[0][2]:
parent_id = None
- if use_filesystem_for_exec:
- # We need S_ISREG here, because we aren't sure if this
- # is a file or not.
- target_exec = bool(
- stat.S_ISREG(path_info[3].st_mode)
- and stat.S_IEXEC & path_info[3].st_mode)
- else:
- target_exec = target_details[3]
+ # updated at update_entry time.
+ target_exec = target_details[3]
return ((entry[0][2], (None, path), True,
(False, True),
(None, parent_id),
@@ -1959,19 +1950,12 @@
# found by their parents recursively.
root_entries = _entries_for_path(current_root)
root_abspath = self.target.abspath(current_root)
- try:
- root_stat = os.lstat(root_abspath)
- except OSError, e:
- if e.errno == errno.ENOENT:
- # the path does not exist: let _process_entry know that.
- root_dir_info = None
- else:
- # some other random error: hand it up.
- raise
+ root_abspath_native = root_abspath.encode(sys.getfilesystemencoding())
+ root_info = path_info.path_info(root_abspath_native)
+ if root_info[0] is path_info.kind_missing:
+ root_dir_info = None
else:
- root_dir_info = ('', current_root,
- osutils.file_kind_from_stat_mode(root_stat.st_mode), root_stat,
- root_abspath)
+ root_dir_info = ('', current_root, root_info[0], root_info[1], root_info[2], root_info[3], root_info[4], root_abspath)
if root_dir_info[2] == 'directory':
if self.target._directory_is_tree_reference(
current_root.decode('utf8')):
@@ -2001,13 +1985,10 @@
utf8_decode(result[1][1])[0]),) + result[2:]
yield result
if want_unversioned and not path_handled:
- new_executable = bool(
- stat.S_ISREG(root_dir_info[3].st_mode)
- and stat.S_IEXEC & root_dir_info[3].st_mode)
yield (None, (None, current_root), True, (False, False),
(None, None),
(None, splitpath(current_root)[-1]),
- (None, root_dir_info[2]), (None, new_executable))
+ (None, root_dir_info[2]), (None, root_dir_info[4]))
dir_iterator = osutils._walkdirs_utf8(root_abspath, prefix=current_root)
initial_key = (current_root, '', '')
block_index, _ = state._find_block_index_from_key(initial_key)
@@ -2189,17 +2170,13 @@
if not path_handled:
# unversioned in all regards
if want_unversioned:
- new_executable = bool(
- stat.S_ISREG(current_path_info[3].st_mode)
- and stat.S_IEXEC & current_path_info[3].st_mode)
- if want_unversioned:
- yield (None, (None, current_path_info[0]),
- True,
- (False, False),
- (None, None),
- (None, current_path_info[1]),
- (None, current_path_info[2]),
- (None, new_executable))
+ yield (None, (None, current_path_info[0]),
+ True,
+ (False, False),
+ (None, None),
+ (None, current_path_info[1]),
+ (None, current_path_info[2]),
+ (None, current_path_info[4]))
# dont descend into this unversioned path if it is
# a dir
if current_path_info[2] in (
More information about the bazaar-commits
mailing list