Rev 3707: Some tuning of update_entry. in http://people.ubuntu.com/~robertc/baz2.0/readdir
Robert Collins
robertc at robertcollins.net
Sun Sep 14 09:51:14 BST 2008
At http://people.ubuntu.com/~robertc/baz2.0/readdir
------------------------------------------------------------
revno: 3707
revision-id: robertc at robertcollins.net-20080914085107-yfw1r5ph5g7eefmi
parent: robertc at robertcollins.net-20080913221050-9jk5c88t80w0300j
committer: Robert Collins <robertc at robertcollins.net>
branch nick: update_entry
timestamp: Sun 2008-09-14 18:51:07 +1000
message:
Some tuning of update_entry.
modified:
bzrlib/_dirstate_helpers_c.pyx dirstate_helpers.pyx-20070503201057-u425eni465q4idwn-3
=== modified file 'bzrlib/_dirstate_helpers_c.pyx'
--- a/bzrlib/_dirstate_helpers_c.pyx 2008-09-13 07:59:05 +0000
+++ b/bzrlib/_dirstate_helpers_c.pyx 2008-09-14 08:51:07 +0000
@@ -19,6 +19,8 @@
This is the python implementation for DirState functions.
"""
+import binascii
+
from bzrlib import errors, osutils
from bzrlib.dirstate import DirState, pack_stat
@@ -37,9 +39,20 @@
ctypedef int intptr_t
+cdef extern from "arpa/inet.h":
+ unsigned long htonl(unsigned long)
+
+
cdef extern from "stdlib.h":
unsigned long int strtoul(char *nptr, char **endptr, int base)
+cdef extern from "stdio.h":
+ void printf(char *format, ...)
+
+cdef extern from 'sys/stat.h':
+ int S_ISDIR(int mode)
+ int S_ISREG(int mode)
+ int S_ISLNK(int mode)
# These functions allow us access to a bit of the 'bare metal' of python
# objects, rather than going through the object abstraction. (For example,
@@ -52,19 +65,26 @@
# a very short time.
cdef extern from "Python.h":
ctypedef int Py_ssize_t
+ ctypedef struct PyObject:
+ pass
int PyList_Append(object lst, object item) except -1
void *PyList_GetItem_object_void "PyList_GET_ITEM" (object lst, int index)
+ void *PyList_GetItem_void_void "PyList_GET_ITEM" (void * lst, int index)
int PyList_CheckExact(object)
void *PyTuple_GetItem_void_void "PyTuple_GET_ITEM" (void* tpl, int index)
+ object PyTuple_GetItem_void_object "PyTuple_GET_ITEM" (void* tpl, int index)
char *PyString_AsString(object p)
+ char *PyString_AsString_obj "PyString_AsString" (PyObject *string)
char *PyString_AS_STRING_void "PyString_AS_STRING" (void *p)
object PyString_FromString(char *)
object PyString_FromStringAndSize(char *, Py_ssize_t)
int PyString_Size(object p)
int PyString_GET_SIZE_void "PyString_GET_SIZE" (void *p)
int PyString_CheckExact(object p)
+ void Py_INCREF(object o)
+ void Py_DECREF(object o)
cdef extern from "string.h":
@@ -721,12 +741,41 @@
state._dirblock_state = DirState.IN_MEMORY_UNMODIFIED
-_stat_to_minikind = DirState._stat_to_minikind
-
-
-def update_entry(self, entry, abspath, stat_value,
- _stat_to_minikind=_stat_to_minikind,
- _pack_stat=pack_stat):
+cdef int minikind_from_mode(int mode):
+ # in order of frequency:
+ if S_ISREG(mode):
+ return c"f"
+ if S_ISDIR(mode):
+ return c"d"
+ if S_ISLNK(mode):
+ return c"l"
+ return 0
+
+
+#cdef object _encode
+_encode = binascii.b2a_base64
+
+from struct import pack
+cdef _pack_stat(stat_value):
+ """return a string representing the stat value's key fields.
+
+ :param stat_value: A stat oject with st_size, st_mtime, st_ctime, st_dev,
+ st_ino and st_mode fields.
+ """
+ cdef char result[6*4] # 6 long ints
+ cdef int *aliased
+ aliased = <int *>result
+ aliased[0] = htonl(stat_value.st_size)
+ aliased[1] = htonl(int(stat_value.st_mtime))
+ aliased[2] = htonl(int(stat_value.st_ctime))
+ aliased[3] = htonl(stat_value.st_dev)
+ aliased[4] = htonl(stat_value.st_ino & 0xFFFFFFFF)
+ aliased[5] = htonl(stat_value.st_mode)
+ packed = PyString_FromStringAndSize(result, 6*4)
+ return _encode(packed)[:-1]
+
+
+def update_entry(self, entry, abspath, stat_value):
"""Update the entry based on what is actually on disk.
:param entry: This is the dirblock entry for the file in question.
@@ -736,30 +785,47 @@
:return: The sha1 hexdigest of the file (40 bytes) or link target of a
symlink.
"""
- try:
- minikind = _stat_to_minikind[stat_value.st_mode & 0170000]
- except KeyError:
- # Unhandled kind
+ # TODO - require pyrex 0.8, then use a pyd file to define access to the _st
+ # mode of the compiled stat objects.
+ cdef int minikind, saved_minikind
+ cdef void * details
+ # pyrex 0.9.7 would allow cdef list details_list, and direct access rather
+ # than PyList_GetItem_void_void below
+ minikind = minikind_from_mode(stat_value.st_mode)
+ if 0 == minikind:
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]
+ details = PyList_GetItem_void_void(PyTuple_GetItem_void_void(<void *>entry, 1), 0)
+ saved_minikind = PyString_AsString_obj(<PyObject *>PyTuple_GetItem_void_void(details, 0))[0]
+ saved_link_or_sha1 = PyTuple_GetItem_void_object(details, 1)
+ saved_file_size = PyTuple_GetItem_void_object(details, 2)
+ saved_executable = PyTuple_GetItem_void_object(details, 3)
+ saved_packed_stat = PyTuple_GetItem_void_object(details, 4)
+ # Deal with pyrex decrefing the objects
+ Py_INCREF(saved_link_or_sha1)
+ Py_INCREF(saved_file_size)
+ Py_INCREF(saved_executable)
+ Py_INCREF(saved_packed_stat)
+ #(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):
# The stat hasn't changed since we saved, so we can re-use the
# saved sha hash.
- if minikind == 'd':
+ if minikind == c'd':
return None
# size should also be in packed_stat
if saved_file_size == stat_value.st_size:
return saved_link_or_sha1
+ else:
+ print "gararar", packed_stat, saved_packed_stat
# If we have gotten this far, that means that we need to actually
# process this entry.
link_or_sha1 = None
- if minikind == 'f':
+ if minikind == c'f':
link_or_sha1 = self._sha1_file(abspath)
executable = self._is_executable(stat_value.st_mode,
saved_executable)
@@ -772,10 +838,10 @@
else:
entry[1][0] = ('f', '', stat_value.st_size,
executable, DirState.NULLSTAT)
- elif minikind == 'd':
+ elif minikind == c'd':
link_or_sha1 = None
entry[1][0] = ('d', '', 0, False, packed_stat)
- if saved_minikind != 'd':
+ if saved_minikind != c'd':
# This changed from something into a directory. Make sure we
# have a directory block for it. This doesn't happen very
# often, so this doesn't have to be super fast.
@@ -783,7 +849,7 @@
self._get_block_entry_index(entry[0][0], entry[0][1], 0)
self._ensure_block(block_index, entry_index,
osutils.pathjoin(entry[0][0], entry[0][1]))
- elif minikind == 'l':
+ elif minikind == c'l':
link_or_sha1 = self._read_link(abspath, saved_link_or_sha1)
if self._cutoff_time is None:
self._sha_cutoff_time()
More information about the bazaar-commits
mailing list