37
39
ctypedef int intptr_t
42
cdef extern from "arpa/inet.h":
43
unsigned long htonl(unsigned long)
40
46
cdef extern from "stdlib.h":
41
47
unsigned long int strtoul(char *nptr, char **endptr, int base)
49
cdef extern from "stdio.h":
50
void printf(char *format, ...)
52
cdef extern from 'sys/stat.h':
44
57
# These functions allow us access to a bit of the 'bare metal' of python
45
58
# objects, rather than going through the object abstraction. (For example,
52
65
# a very short time.
53
66
cdef extern from "Python.h":
54
67
ctypedef int Py_ssize_t
68
ctypedef struct PyObject:
55
70
int PyList_Append(object lst, object item) except -1
56
71
void *PyList_GetItem_object_void "PyList_GET_ITEM" (object lst, int index)
72
void *PyList_GetItem_void_void "PyList_GET_ITEM" (void * lst, int index)
57
73
int PyList_CheckExact(object)
59
75
void *PyTuple_GetItem_void_void "PyTuple_GET_ITEM" (void* tpl, int index)
76
object PyTuple_GetItem_void_object "PyTuple_GET_ITEM" (void* tpl, int index)
61
78
char *PyString_AsString(object p)
79
char *PyString_AsString_obj "PyString_AsString" (PyObject *string)
62
80
char *PyString_AS_STRING_void "PyString_AS_STRING" (void *p)
63
81
object PyString_FromString(char *)
64
82
object PyString_FromStringAndSize(char *, Py_ssize_t)
65
83
int PyString_Size(object p)
66
84
int PyString_GET_SIZE_void "PyString_GET_SIZE" (void *p)
67
85
int PyString_CheckExact(object p)
86
void Py_INCREF(object o)
87
void Py_DECREF(object o)
70
90
cdef extern from "string.h":
721
741
state._dirblock_state = DirState.IN_MEMORY_UNMODIFIED
724
_stat_to_minikind = DirState._stat_to_minikind
727
def update_entry(self, entry, abspath, stat_value,
728
_stat_to_minikind=_stat_to_minikind,
729
_pack_stat=pack_stat):
744
cdef int minikind_from_mode(int mode):
745
# in order of frequency:
756
_encode = binascii.b2a_base64
758
from struct import pack
759
cdef _pack_stat(stat_value):
760
"""return a string representing the stat value's key fields.
762
:param stat_value: A stat oject with st_size, st_mtime, st_ctime, st_dev,
763
st_ino and st_mode fields.
765
cdef char result[6*4] # 6 long ints
767
aliased = <int *>result
768
aliased[0] = htonl(stat_value.st_size)
769
aliased[1] = htonl(int(stat_value.st_mtime))
770
aliased[2] = htonl(int(stat_value.st_ctime))
771
aliased[3] = htonl(stat_value.st_dev)
772
aliased[4] = htonl(stat_value.st_ino & 0xFFFFFFFF)
773
aliased[5] = htonl(stat_value.st_mode)
774
packed = PyString_FromStringAndSize(result, 6*4)
775
return _encode(packed)[:-1]
778
def update_entry(self, entry, abspath, stat_value):
730
779
"""Update the entry based on what is actually on disk.
732
781
:param entry: This is the dirblock entry for the file in question.
736
785
:return: The sha1 hexdigest of the file (40 bytes) or link target of a
740
minikind = _stat_to_minikind[stat_value.st_mode & 0170000]
788
# TODO - require pyrex 0.8, then use a pyd file to define access to the _st
789
# mode of the compiled stat objects.
790
cdef int minikind, saved_minikind
792
# pyrex 0.9.7 would allow cdef list details_list, and direct access rather
793
# than PyList_GetItem_void_void below
794
minikind = minikind_from_mode(stat_value.st_mode)
744
797
packed_stat = _pack_stat(stat_value)
745
(saved_minikind, saved_link_or_sha1, saved_file_size,
746
saved_executable, saved_packed_stat) = entry[1][0]
798
details = PyList_GetItem_void_void(PyTuple_GetItem_void_void(<void *>entry, 1), 0)
799
saved_minikind = PyString_AsString_obj(<PyObject *>PyTuple_GetItem_void_void(details, 0))[0]
800
saved_link_or_sha1 = PyTuple_GetItem_void_object(details, 1)
801
saved_file_size = PyTuple_GetItem_void_object(details, 2)
802
saved_executable = PyTuple_GetItem_void_object(details, 3)
803
saved_packed_stat = PyTuple_GetItem_void_object(details, 4)
804
# Deal with pyrex decrefing the objects
805
Py_INCREF(saved_link_or_sha1)
806
Py_INCREF(saved_file_size)
807
Py_INCREF(saved_executable)
808
Py_INCREF(saved_packed_stat)
809
#(saved_minikind, saved_link_or_sha1, saved_file_size,
810
# saved_executable, saved_packed_stat) = entry[1][0]
748
812
if (minikind == saved_minikind
749
813
and packed_stat == saved_packed_stat):
750
814
# The stat hasn't changed since we saved, so we can re-use the
751
815
# saved sha hash.
755
819
# size should also be in packed_stat
756
820
if saved_file_size == stat_value.st_size:
757
821
return saved_link_or_sha1
823
print "gararar", packed_stat, saved_packed_stat
759
825
# If we have gotten this far, that means that we need to actually
760
826
# process this entry.
761
827
link_or_sha1 = None
763
829
link_or_sha1 = self._sha1_file(abspath)
764
830
executable = self._is_executable(stat_value.st_mode,
765
831
saved_executable)
773
839
entry[1][0] = ('f', '', stat_value.st_size,
774
840
executable, DirState.NULLSTAT)
775
elif minikind == 'd':
841
elif minikind == c'd':
776
842
link_or_sha1 = None
777
843
entry[1][0] = ('d', '', 0, False, packed_stat)
778
if saved_minikind != 'd':
844
if saved_minikind != c'd':
779
845
# This changed from something into a directory. Make sure we
780
846
# have a directory block for it. This doesn't happen very
781
847
# often, so this doesn't have to be super fast.
783
849
self._get_block_entry_index(entry[0][0], entry[0][1], 0)
784
850
self._ensure_block(block_index, entry_index,
785
851
osutils.pathjoin(entry[0][0], entry[0][1]))
786
elif minikind == 'l':
852
elif minikind == c'l':
787
853
link_or_sha1 = self._read_link(abspath, saved_link_or_sha1)
788
854
if self._cutoff_time is None:
789
855
self._sha_cutoff_time()