~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_dirstate_helpers_pyx.pyx

  • Committer: Andrew Bennetts
  • Date: 2010-07-29 11:17:57 UTC
  • mfrom: (5050.3.17 2.2)
  • mto: This revision was merged to the branch mainline in revision 5365.
  • Revision ID: andrew.bennetts@canonical.com-20100729111757-018h3pcefo7z0dnq
Merge lp:bzr/2.2 into lp:bzr.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2010 Canonical Ltd
 
1
# Copyright (C) 2007, 2008, 2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
97
97
    object PyTuple_GetItem_void_object "PyTuple_GET_ITEM" (void* tpl, int index)
98
98
    object PyTuple_GET_ITEM(object tpl, Py_ssize_t index)
99
99
 
100
 
    unsigned long PyInt_AsUnsignedLongMask(object number) except? -1
101
100
 
102
101
    char *PyString_AsString(object p)
103
102
    char *PyString_AsString_obj "PyString_AsString" (PyObject *string)
119
118
    # ??? memrchr is a GNU extension :(
120
119
    # void *memrchr(void *s, int c, size_t len)
121
120
 
122
 
# cimport all of the definitions we will need to access
123
 
from _static_tuple_c cimport import_static_tuple_c, StaticTuple, \
124
 
    StaticTuple_New, StaticTuple_SET_ITEM
125
 
 
126
 
import_static_tuple_c()
127
121
 
128
122
cdef void* _my_memrchr(void *s, int c, size_t n): # cannot_raise
129
123
    # memrchr seems to be a GNU extension, so we have to implement it ourselves
616
610
        :param new_block: This is to let the caller know that it needs to
617
611
            create a new directory block to store the next entry.
618
612
        """
619
 
        cdef StaticTuple path_name_file_id_key
620
 
        cdef StaticTuple tmp
 
613
        cdef object path_name_file_id_key
621
614
        cdef char *entry_size_cstr
622
615
        cdef unsigned long int entry_size
623
616
        cdef char* executable_cstr
657
650
        # Build up the key that will be used.
658
651
        # By using <object>(void *) Pyrex will automatically handle the
659
652
        # Py_INCREF that we need.
660
 
        cur_dirname = <object>p_current_dirname[0]
661
 
        # Use StaticTuple_New to pre-allocate, rather than creating a regular
662
 
        # tuple and passing it to the StaticTuple constructor.
663
 
        # path_name_file_id_key = StaticTuple(<object>p_current_dirname[0],
664
 
        #                          self.get_next_str(),
665
 
        #                          self.get_next_str(),
666
 
        #                         )
667
 
        tmp = StaticTuple_New(3)
668
 
        Py_INCREF(cur_dirname); StaticTuple_SET_ITEM(tmp, 0, cur_dirname)
669
 
        cur_basename = self.get_next_str()
670
 
        cur_file_id = self.get_next_str()
671
 
        Py_INCREF(cur_basename); StaticTuple_SET_ITEM(tmp, 1, cur_basename)
672
 
        Py_INCREF(cur_file_id); StaticTuple_SET_ITEM(tmp, 2, cur_file_id)
673
 
        path_name_file_id_key = tmp
 
653
        path_name_file_id_key = (<object>p_current_dirname[0],
 
654
                                 self.get_next_str(),
 
655
                                 self.get_next_str(),
 
656
                                )
674
657
 
675
658
        # Parse all of the per-tree information. current has the information in
676
659
        # the same location as parent trees. The only difference is that 'info'
694
677
            executable_cstr = self.get_next(&cur_size)
695
678
            is_executable = (executable_cstr[0] == c'y')
696
679
            info = self.get_next_str()
697
 
            # TODO: If we want to use StaticTuple_New here we need to be pretty
698
 
            #       careful. We are relying on a bit of Pyrex
699
 
            #       automatic-conversion from 'int' to PyInt, and that doesn't
700
 
            #       play well with the StaticTuple_SET_ITEM macro.
701
 
            #       Timing doesn't (yet) show a worthwile improvement in speed
702
 
            #       versus complexity and maintainability.
703
 
            # tmp = StaticTuple_New(5)
704
 
            # Py_INCREF(minikind); StaticTuple_SET_ITEM(tmp, 0, minikind)
705
 
            # Py_INCREF(fingerprint); StaticTuple_SET_ITEM(tmp, 1, fingerprint)
706
 
            # Py_INCREF(entry_size); StaticTuple_SET_ITEM(tmp, 2, entry_size)
707
 
            # Py_INCREF(is_executable); StaticTuple_SET_ITEM(tmp, 3, is_executable)
708
 
            # Py_INCREF(info); StaticTuple_SET_ITEM(tmp, 4, info)
709
 
            # PyList_Append(trees, tmp)
710
 
            PyList_Append(trees, StaticTuple(
 
680
            PyList_Append(trees, (
711
681
                minikind,     # minikind
712
682
                fingerprint,  # fingerprint
713
683
                entry_size,   # size
812
782
_encode = binascii.b2a_base64
813
783
 
814
784
 
 
785
from struct import pack
815
786
cdef _pack_stat(stat_value):
816
787
    """return a string representing the stat value's key fields.
817
788
 
821
792
    cdef char result[6*4] # 6 long ints
822
793
    cdef int *aliased
823
794
    aliased = <int *>result
824
 
    aliased[0] = htonl(PyInt_AsUnsignedLongMask(stat_value.st_size))
825
 
    # mtime and ctime will often be floats but get converted to PyInt within
826
 
    aliased[1] = htonl(PyInt_AsUnsignedLongMask(stat_value.st_mtime))
827
 
    aliased[2] = htonl(PyInt_AsUnsignedLongMask(stat_value.st_ctime))
828
 
    aliased[3] = htonl(PyInt_AsUnsignedLongMask(stat_value.st_dev))
829
 
    aliased[4] = htonl(PyInt_AsUnsignedLongMask(stat_value.st_ino))
830
 
    aliased[5] = htonl(PyInt_AsUnsignedLongMask(stat_value.st_mode))
 
795
    aliased[0] = htonl(stat_value.st_size)
 
796
    aliased[1] = htonl(int(stat_value.st_mtime))
 
797
    aliased[2] = htonl(int(stat_value.st_ctime))
 
798
    aliased[3] = htonl(stat_value.st_dev)
 
799
    aliased[4] = htonl(stat_value.st_ino & 0xFFFFFFFF)
 
800
    aliased[5] = htonl(stat_value.st_mode)
831
801
    packed = PyString_FromStringAndSize(result, 6*4)
832
802
    return _encode(packed)[:-1]
833
803
 
834
804
 
835
 
def pack_stat(stat_value):
836
 
    """Convert stat value into a packed representation quickly with pyrex"""
837
 
    return _pack_stat(stat_value)
838
 
 
839
 
 
840
805
def update_entry(self, entry, abspath, stat_value):
841
806
    """Update the entry based on what is actually on disk.
842
807
 
872
837
    # _st mode of the compiled stat objects.
873
838
    cdef int minikind, saved_minikind
874
839
    cdef void * details
875
 
    cdef int worth_saving
876
840
    minikind = minikind_from_mode(stat_value.st_mode)
877
841
    if 0 == minikind:
878
842
        return None
907
871
    # If we have gotten this far, that means that we need to actually
908
872
    # process this entry.
909
873
    link_or_sha1 = None
910
 
    worth_saving = 1
911
874
    if minikind == c'f':
912
875
        executable = self._is_executable(stat_value.st_mode,
913
876
                                         saved_executable)
924
887
            entry[1][0] = ('f', link_or_sha1, stat_value.st_size,
925
888
                           executable, packed_stat)
926
889
        else:
927
 
            # This file is not worth caching the sha1. Either it is too new, or
928
 
            # it is newly added. Regardless, the only things we are changing
929
 
            # are derived from the stat, and so are not worth caching. So we do
930
 
            # *not* set the IN_MEMORY_MODIFIED flag. (But we'll save the
931
 
            # updated values if there is *other* data worth saving.)
932
 
            entry[1][0] = ('f', '', stat_value.st_size, executable,
933
 
                           DirState.NULLSTAT)
934
 
            worth_saving = 0
 
890
            entry[1][0] = ('f', '', stat_value.st_size,
 
891
                           executable, DirState.NULLSTAT)
935
892
    elif minikind == c'd':
 
893
        link_or_sha1 = None
936
894
        entry[1][0] = ('d', '', 0, False, packed_stat)
937
895
        if saved_minikind != c'd':
938
896
            # This changed from something into a directory. Make sure we
942
900
                self._get_block_entry_index(entry[0][0], entry[0][1], 0)
943
901
            self._ensure_block(block_index, entry_index,
944
902
                               pathjoin(entry[0][0], entry[0][1]))
945
 
        else:
946
 
            # Any changes are derived trivially from the stat object, not worth
947
 
            # re-writing a dirstate for just this
948
 
            worth_saving = 0
949
903
    elif minikind == c'l':
950
 
        if saved_minikind == c'l':
951
 
            # If the object hasn't changed kind, it isn't worth saving the
952
 
            # dirstate just for a symlink. The default is 'fast symlinks' which
953
 
            # save the target in the inode entry, rather than separately. So to
954
 
            # stat, we've already read everything off disk.
955
 
            worth_saving = 0
956
904
        link_or_sha1 = self._read_link(abspath, saved_link_or_sha1)
957
905
        if self._cutoff_time is None:
958
906
            self._sha_cutoff_time()
963
911
        else:
964
912
            entry[1][0] = ('l', '', stat_value.st_size,
965
913
                           False, DirState.NULLSTAT)
966
 
    if worth_saving:
967
 
        # Note, even though _mark_modified will only set
968
 
        # IN_MEMORY_HASH_MODIFIED, it still isn't worth 
969
 
        self._mark_modified([entry])
 
914
    self._dirblock_state = DirState.IN_MEMORY_MODIFIED
970
915
    return link_or_sha1
971
916
 
972
917
 
1799
1744
                advance_entry = -1
1800
1745
                advance_path = -1
1801
1746
                result = None
1802
 
                changed = None
1803
1747
                path_handled = 0
1804
1748
                if current_entry is None:
1805
1749
                    # unversioned -  the check for path_handled when the path