mercurial/manifest.py
changeset 2320 dbdce3b99988
parent 2142 8a1e2a9c7013
child 2470 fe1689273f84
equal deleted inserted replaced
2319:04a18aaaca25 2320:dbdce3b99988
    41         return self.mapcache[2]
    41         return self.mapcache[2]
    42 
    42 
    43     def diff(self, a, b):
    43     def diff(self, a, b):
    44         return mdiff.textdiff(str(a), str(b))
    44         return mdiff.textdiff(str(a), str(b))
    45 
    45 
       
    46     def _search(self, m, s, lo=0, hi=None):
       
    47         '''return a tuple (start, end) that says where to find s within m.
       
    48 
       
    49         If the string is found m[start:end] are the line containing
       
    50         that string.  If start == end the string was not found and
       
    51         they indicate the proper sorted insertion point.  This was
       
    52         taken from bisect_left, and modified to find line start/end as
       
    53         it goes along.
       
    54 
       
    55         m should be a buffer or a string
       
    56         s is a string'''
       
    57         def advance(i, c):
       
    58             while i < lenm and m[i] != c:
       
    59                 i += 1
       
    60             return i
       
    61         lenm = len(m)
       
    62         if not hi:
       
    63             hi = lenm
       
    64         while lo < hi:
       
    65             mid = (lo + hi) // 2
       
    66             start = mid
       
    67             while start > 0 and m[start-1] != '\n':
       
    68                 start -= 1
       
    69             end = advance(start, '\0')
       
    70             if m[start:end] < s:
       
    71                 # we know that after the null there are 40 bytes of sha1
       
    72                 # this translates to the bisect lo = mid + 1
       
    73                 lo = advance(end + 40, '\n') + 1
       
    74             else:
       
    75                 # this translates to the bisect hi = mid
       
    76                 hi = start
       
    77         end = advance(lo, '\0')
       
    78         found = m[lo:end]
       
    79         if cmp(s, found) == 0:
       
    80             # we know that after the null there are 40 bytes of sha1
       
    81             end = advance(end + 40, '\n')
       
    82             return (lo, end+1)
       
    83         else:
       
    84             return (lo, lo)
       
    85 
       
    86     def find(self, node, f):
       
    87         '''look up entry for a single file efficiently.
       
    88         return (node, flag) pair if found, (None, None) if not.'''
       
    89         if self.mapcache and node == self.mapcache[0]:
       
    90             return self.mapcache[1].get(f), self.mapcache[2].get(f)
       
    91         text = self.revision(node)
       
    92         start, end = self._search(text, f)
       
    93         if start == end:
       
    94             return None, None
       
    95         l = text[start:end]
       
    96         f, n = l.split('\0')
       
    97         return bin(n[:40]), n[40:-1] == 'x'
       
    98 
    46     def add(self, map, flags, transaction, link, p1=None, p2=None,
    99     def add(self, map, flags, transaction, link, p1=None, p2=None,
    47             changed=None):
   100             changed=None):
    48 
       
    49         # returns a tuple (start, end).  If the string is found
       
    50         # m[start:end] are the line containing that string.  If start == end
       
    51         # the string was not found and they indicate the proper sorted 
       
    52         # insertion point.  This was taken from bisect_left, and modified
       
    53         # to find line start/end as it goes along.
       
    54         #
       
    55         # m should be a buffer or a string
       
    56         # s is a string
       
    57         #
       
    58         def manifestsearch(m, s, lo=0, hi=None):
       
    59             def advance(i, c):
       
    60                 while i < lenm and m[i] != c:
       
    61                     i += 1
       
    62                 return i
       
    63             lenm = len(m)
       
    64             if not hi:
       
    65                 hi = lenm
       
    66             while lo < hi:
       
    67                 mid = (lo + hi) // 2
       
    68                 start = mid
       
    69                 while start > 0 and m[start-1] != '\n':
       
    70                     start -= 1
       
    71                 end = advance(start, '\0')
       
    72                 if m[start:end] < s:
       
    73                     # we know that after the null there are 40 bytes of sha1
       
    74                     # this translates to the bisect lo = mid + 1
       
    75                     lo = advance(end + 40, '\n') + 1
       
    76                 else:
       
    77                     # this translates to the bisect hi = mid
       
    78                     hi = start
       
    79             end = advance(lo, '\0')
       
    80             found = m[lo:end]
       
    81             if cmp(s, found) == 0: 
       
    82                 # we know that after the null there are 40 bytes of sha1
       
    83                 end = advance(end + 40, '\n')
       
    84                 return (lo, end+1)
       
    85             else:
       
    86                 return (lo, lo)
       
    87 
       
    88         # apply the changes collected during the bisect loop to our addlist
   101         # apply the changes collected during the bisect loop to our addlist
    89         # return a delta suitable for addrevision
   102         # return a delta suitable for addrevision
    90         def addlistdelta(addlist, x):
   103         def addlistdelta(addlist, x):
    91             # start from the bottom up
   104             # start from the bottom up
    92             # so changes to the offsets don't mess things up.
   105             # so changes to the offsets don't mess things up.
   135             # start with a readonly loop that finds the offset of
   148             # start with a readonly loop that finds the offset of
   136             # each line and creates the deltas
   149             # each line and creates the deltas
   137             for w in work:
   150             for w in work:
   138                 f = w[0]
   151                 f = w[0]
   139                 # bs will either be the index of the item or the insert point
   152                 # bs will either be the index of the item or the insert point
   140                 start, end = manifestsearch(addbuf, f, start)
   153                 start, end = self._search(addbuf, f, start)
   141                 if w[1] == 0:
   154                 if w[1] == 0:
   142                     l = "%s\000%s%s\n" % (f, hex(map[f]),
   155                     l = "%s\000%s%s\n" % (f, hex(map[f]),
   143                                           flags[f] and "x" or '')
   156                                           flags[f] and "x" or '')
   144                 else:
   157                 else:
   145                     l = ""
   158                     l = ""