equal
deleted
inserted
replaced
12 This contains helper routines that are independent of the SCM core and |
12 This contains helper routines that are independent of the SCM core and |
13 hide platform-specific details from the core. |
13 hide platform-specific details from the core. |
14 """ |
14 """ |
15 |
15 |
16 from i18n import _ |
16 from i18n import _ |
17 import error, osutil, encoding |
17 import error, osutil, encoding, collections |
18 import errno, re, shutil, sys, tempfile, traceback |
18 import errno, re, shutil, sys, tempfile, traceback |
19 import os, time, datetime, calendar, textwrap, signal |
19 import os, time, datetime, calendar, textwrap, signal |
20 import imp, socket, urllib |
20 import imp, socket, urllib |
21 |
21 |
22 if os.name == 'nt': |
22 if os.name == 'nt': |
203 return f |
203 return f |
204 |
204 |
205 def lrucachefunc(func): |
205 def lrucachefunc(func): |
206 '''cache most recent results of function calls''' |
206 '''cache most recent results of function calls''' |
207 cache = {} |
207 cache = {} |
208 order = [] |
208 order = collections.deque() |
209 if func.func_code.co_argcount == 1: |
209 if func.func_code.co_argcount == 1: |
210 def f(arg): |
210 def f(arg): |
211 if arg not in cache: |
211 if arg not in cache: |
212 if len(cache) > 20: |
212 if len(cache) > 20: |
213 del cache[order.pop(0)] |
213 del cache[order.popleft()] |
214 cache[arg] = func(arg) |
214 cache[arg] = func(arg) |
215 else: |
215 else: |
216 order.remove(arg) |
216 order.remove(arg) |
217 order.append(arg) |
217 order.append(arg) |
218 return cache[arg] |
218 return cache[arg] |
219 else: |
219 else: |
220 def f(*args): |
220 def f(*args): |
221 if args not in cache: |
221 if args not in cache: |
222 if len(cache) > 20: |
222 if len(cache) > 20: |
223 del cache[order.pop(0)] |
223 del cache[order.popleft()] |
224 cache[args] = func(*args) |
224 cache[args] = func(*args) |
225 else: |
225 else: |
226 order.remove(args) |
226 order.remove(args) |
227 order.append(args) |
227 order.append(args) |
228 return cache[args] |
228 return cache[args] |
863 def read(self, l): |
863 def read(self, l): |
864 """Read L bytes of data from the iterator of chunks of data. |
864 """Read L bytes of data from the iterator of chunks of data. |
865 Returns less than L bytes if the iterator runs dry.""" |
865 Returns less than L bytes if the iterator runs dry.""" |
866 left = l |
866 left = l |
867 buf = '' |
867 buf = '' |
868 queue = self._queue |
868 queue = collections.deque(self._queue) |
869 while left > 0: |
869 while left > 0: |
870 # refill the queue |
870 # refill the queue |
871 if not queue: |
871 if not queue: |
872 target = 2**18 |
872 target = 2**18 |
873 for chunk in self.iter: |
873 for chunk in self.iter: |
876 if target <= 0: |
876 if target <= 0: |
877 break |
877 break |
878 if not queue: |
878 if not queue: |
879 break |
879 break |
880 |
880 |
881 chunk = queue.pop(0) |
881 chunk = queue.popleft() |
882 left -= len(chunk) |
882 left -= len(chunk) |
883 if left < 0: |
883 if left < 0: |
884 queue.insert(0, chunk[left:]) |
884 queue.appendleft(chunk[left:]) |
885 buf += chunk[:left] |
885 buf += chunk[:left] |
886 else: |
886 else: |
887 buf += chunk |
887 buf += chunk |
|
888 self._queue = list(queue) |
888 |
889 |
889 return buf |
890 return buf |
890 |
891 |
891 def filechunkiter(f, size=65536, limit=None): |
892 def filechunkiter(f, size=65536, limit=None): |
892 """Create a generator that produces the data in the file size |
893 """Create a generator that produces the data in the file size |