Pārlūkot izejas kodu

Merge compatibility with python2.4 from rockstar.

Jelmer Vernooij 16 gadi atpakaļ
vecāks
revīzija
dc9ce70621
2 mainītis faili ar 116 papildinājumiem un 17 dzēšanām
  1. 90 0
      dulwich/misc.py
  2. 26 17
      dulwich/pack.py

+ 90 - 0
dulwich/misc.py

@@ -0,0 +1,90 @@
+# misc.py -- For dealing with python2.4 oddness
+# Copyright (C) 2008 Canonical Ltd.
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; version 2
+# of the License or (at your option) a later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.
+'''Misc utilities to work with python2.4.
+
+These utilities can all be deleted when dulwich decides it wants to stop
+support for python 2.4.
+'''
+try:
+    import hashlib
+except ImportError:
+    import sha
+import struct
+
+
+class defaultdict(dict):
+    '''A python 2.4 equivalent of collections.defaultdict.'''
+
+    def __init__(self, default_factory=None, *a, **kw):
+        if (default_factory is not None and
+            not hasattr(default_factory, '__call__')):
+            raise TypeError('first argument must be callable')
+        dict.__init__(self, *a, **kw)
+        self.default_factory = default_factory
+
+    def __getitem__(self, key):
+        try:
+            return dict.__getitem__(self, key)
+        except KeyError:
+            return self.__missing__(key)
+
+    def __missing__(self, key):
+        if self.default_factory is None:
+            raise KeyError(key)
+        self[key] = value = self.default_factory()
+        return value
+
+    def __reduce__(self):
+        if self.default_factory is None:
+            args = tuple()
+        else:
+            args = self.default_factory,
+        return type(self), args, None, None, self.items()
+
+    def copy(self):
+        return self.__copy__()
+
+    def __copy__(self):
+        return type(self)(self.default_factory, self)
+
+    def __deepcopy__(self, memo):
+        import copy
+        return type(self)(self.default_factory,
+                          copy.deepcopy(self.items()))
+    def __repr__(self):
+        return 'defaultdict(%s, %s)' % (self.default_factory,
+                                        dict.__repr__(self))
+
+
+def make_sha(source=''):
+    '''A python2.4 workaround for the sha/hashlib module fiasco.'''
+    try:
+        return hashlib.sha1(source)
+    except NameError:
+        sha1 = sha.sha(source)
+        return sha1
+
+
+def unpack_from(fmt, buf, offset=0):
+    '''A python2.4 workaround for struct missing unpack_from.'''
+    try:
+        return struct.unpack_from(fmt, buf, offset)
+    except AttributeError:
+        b = buf[offset:offset+struct.calcsize(fmt)]
+        return struct.unpack(fmt, b)
+

+ 26 - 17
dulwich/pack.py

@@ -30,13 +30,19 @@ match for the object name. You then use the pointer got from this as
 a pointer in to the corresponding packfile.
 """
 
-from collections import defaultdict
-import hashlib
+try:
+    from collections import defaultdict
+except ImportError:
+    from misc import defaultdict
+
 from itertools import imap, izip
 import mmap
 import os
-import sha
 import struct
+try:
+    from struct import unpack_from
+except ImportError:
+    from misc import unpack_from
 import sys
 import zlib
 import difflib
@@ -47,8 +53,9 @@ from objects import (
         sha_to_hex,
         )
 from errors import ApplyDeltaError
+from misc import make_sha
 
-supports_mmap_offset = (sys.version_info[0] >= 3 or 
+supports_mmap_offset = (sys.version_info[0] >= 3 or
         (sys.version_info[0] == 2 and sys.version_info[1] >= 6))
 
 
@@ -77,10 +84,10 @@ def read_zlib(data, offset, dec_size):
 
 
 def iter_sha1(iter):
-    sha = hashlib.sha1()
+    sha1 = make_sha()
     for name in iter:
-        sha.update(name)
-    return sha.hexdigest()
+        sha1.update(name)
+    return sha1.hexdigest()
 
 
 MAX_MMAP_SIZE = 256 * 1024 * 1024
@@ -176,7 +183,7 @@ class PackIndex(object):
             self.version = 1
             self._fan_out_table = self._read_fan_out_table(0)
         else:
-            (self.version, ) = struct.unpack_from(">L", self._contents, 4)
+            (self.version, ) = unpack_from(">L", self._contents, 4)
             assert self.version in (2,), "Version was %d" % self.version
             self._fan_out_table = self._read_fan_out_table(8)
             self._name_table_offset = 8 + 0x100 * 4
@@ -208,7 +215,7 @@ class PackIndex(object):
         :return: Tuple with object name (SHA), offset in pack file and 
               CRC32 checksum (if known)."""
         if self.version == 1:
-            (offset, name) = struct.unpack_from(">L20s", self._contents, 
+            (offset, name) = unpack_from(">L20s", self._contents, 
                 (0x100 * 4) + (i * 24))
             return (name, offset, None)
         else:
@@ -219,21 +226,21 @@ class PackIndex(object):
         if self.version == 1:
             return self._unpack_entry(i)[0]
         else:
-            return struct.unpack_from("20s", self._contents, 
+            return unpack_from("20s", self._contents, 
                                       self._name_table_offset + i * 20)[0]
   
     def _unpack_offset(self, i):
         if self.version == 1:
             return self._unpack_entry(i)[1]
         else:
-            return struct.unpack_from(">L", self._contents, 
+            return unpack_from(">L", self._contents, 
                                       self._pack_offset_table_offset + i * 4)[0]
   
     def _unpack_crc32_checksum(self, i):
         if self.version == 1:
             return None
         else:
-            return struct.unpack_from(">L", self._contents, 
+            return unpack_from(">L", self._contents, 
                                       self._crc32_table_offset + i * 4)[0]
   
     def __iter__(self):
@@ -267,7 +274,7 @@ class PackIndex(object):
     def calculate_checksum(self):
         f = open(self._filename, 'r')
         try:
-            return hashlib.sha1(self._contents[:-20]).digest()
+            return make_sha(self._contents[:-20]).digest()
         finally:
             f.close()
   
@@ -314,9 +321,9 @@ class PackIndex(object):
 def read_pack_header(f):
     header = f.read(12)
     assert header[:4] == "PACK"
-    (version,) = struct.unpack_from(">L", header, 4)
+    (version,) = unpack_from(">L", header, 4)
     assert version in (2, 3), "Version was %d" % version
-    (num_objects,) = struct.unpack_from(">L", header, 8)
+    (num_objects,) = unpack_from(">L", header, 8)
     return (version, num_objects)
 
 
@@ -415,7 +422,7 @@ class PackData(object):
         f = open(self._filename, 'rb')
         try:
             map = simple_mmap(f, 0, self._size)
-            return hashlib.sha1(map[:-20]).digest()
+            return make_sha(map[:-20]).digest()
         finally:
             f.close()
   
@@ -510,7 +517,7 @@ class SHA1Writer(object):
     
     def __init__(self, f):
         self.f = f
-        self.sha1 = hashlib.sha1("")
+        self.sha1 = make_sha("")
 
     def write(self, data):
         self.sha1.update(data)
@@ -855,6 +862,8 @@ class Pack(object):
             raise KeyError(sha1)
 
         type, obj = self.data.get_object_at(offset)
+        if isinstance(offset, long):
+          offset = int(offset)
         assert isinstance(offset, int)
         return resolve_object(offset, type, obj, resolve_ref,
             self.data.get_object_at)