nodes: 0, module; 1, function_definition; 2, function_name:write_tree_from_cache; 3, parameters; 4, block; 5, identifier:entries; 6, identifier:odb; 7, identifier:sl; 8, default_parameter; 9, expression_statement; 10, expression_statement; 11, expression_statement; 12, expression_statement; 13, expression_statement; 14, while_statement; 15, comment:# END for each entry; 16, comment:# finally create the tree; 17, expression_statement; 18, expression_statement; 19, expression_statement; 20, expression_statement; 21, return_statement; 22, identifier:si; 23, integer:0; 24, comment:"""Create a tree from the given sorted list of entries and put the respective
      trees into the given object database
  
      :param entries: **sorted** list of IndexEntries
      :param odb: object database to store the trees in
      :param si: start index at which we should start creating subtrees
      :param sl: slice indicating the range we should process on the entries list
      :return: tuple(binsha, list(tree_entry, ...)) a tuple of a sha and a list of
          tree entries being a tuple of hexsha, mode, name"""; 25, assignment; 26, assignment; 27, assignment; 28, assignment; 29, comparison_operator:ci < end; 30, block; 31, assignment; 32, call; 33, call; 34, assignment; 35, tuple; 36, identifier:tree_items; 37, list; 38, identifier:tree_items_append; 39, attribute; 40, identifier:ci; 41, attribute; 42, identifier:end; 43, attribute; 44, identifier:ci; 45, identifier:end; 46, expression_statement; 47, if_statement; 48, comment:# END abort on unmerged; 49, expression_statement; 50, expression_statement; 51, if_statement; 52, comment:# END handle bounds; 53, identifier:sio; 54, call; 55, identifier:tree_to_stream; 56, argument_list; 57, attribute; 58, argument_list; 59, identifier:istream; 60, call; 61, attribute; 62, identifier:tree_items; 63, identifier:tree_items; 64, identifier:append; 65, identifier:sl; 66, identifier:start; 67, identifier:sl; 68, identifier:stop; 69, assignment; 70, comparison_operator:entry.stage != 0; 71, block; 72, augmented_assignment; 73, assignment; 74, comparison_operator:rbound == -1; 75, comment:# its not a tree; 76, block; 77, else_clause; 78, identifier:BytesIO; 79, argument_list; 80, identifier:tree_items; 81, attribute; 82, identifier:sio; 83, identifier:seek; 84, integer:0; 85, attribute; 86, argument_list; 87, identifier:istream; 88, identifier:binsha; 89, identifier:entry; 90, subscript; 91, attribute; 92, integer:0; 93, raise_statement; 94, identifier:ci; 95, integer:1; 96, identifier:rbound; 97, call; 98, identifier:rbound; 99, unary_operator; 100, expression_statement; 101, comment:# find common base range; 102, block; 103, identifier:sio; 104, identifier:write; 105, identifier:odb; 106, identifier:store; 107, call; 108, identifier:entries; 109, identifier:ci; 110, identifier:entry; 111, identifier:stage; 112, call; 113, attribute; 114, argument_list; 115, integer:1; 116, call; 117, expression_statement; 118, expression_statement; 119, while_statement; 120, comment:# END find common base; 121, comment:# enter recursion; 122, comment:# ci - 1 as we want to count our current item as well; 123, expression_statement; 124, comment:# @UnusedVariable; 125, expression_statement; 126, comment:# skip ahead; 127, expression_statement; 128, identifier:IStream; 129, argument_list; 130, identifier:UnmergedEntriesError; 131, argument_list; 132, attribute; 133, identifier:find; 134, string; 135, identifier:si; 136, identifier:tree_items_append; 137, argument_list; 138, assignment; 139, assignment; 140, comparison_operator:xi < end; 141, block; 142, assignment; 143, call; 144, assignment; 145, identifier:str_tree_type; 146, call; 147, identifier:sio; 148, identifier:entry; 149, identifier:entry; 150, identifier:path; 151, string_content:/; 152, tuple; 153, identifier:base; 154, subscript; 155, identifier:xi; 156, identifier:ci; 157, identifier:xi; 158, identifier:end; 159, expression_statement; 160, expression_statement; 161, if_statement; 162, comment:# END abort on base mismatch; 163, expression_statement; 164, pattern_list; 165, call; 166, identifier:tree_items_append; 167, argument_list; 168, identifier:ci; 169, identifier:xi; 170, identifier:len; 171, argument_list; 172, attribute; 173, attribute; 174, subscript; 175, attribute; 176, slice; 177, assignment; 178, assignment; 179, boolean_operator; 180, block; 181, augmented_assignment; 182, identifier:sha; 183, identifier:tree_entry_list; 184, identifier:write_tree_from_cache; 185, argument_list; 186, tuple; 187, call; 188, identifier:entry; 189, identifier:binsha; 190, identifier:entry; 191, identifier:mode; 192, attribute; 193, slice; 194, identifier:entry; 195, identifier:path; 196, identifier:si; 197, identifier:rbound; 198, identifier:oentry; 199, subscript; 200, identifier:orbound; 201, call; 202, comparison_operator:orbound == -1; 203, comparison_operator:oentry.path[si:orbound] != base; 204, break_statement; 205, identifier:xi; 206, integer:1; 207, identifier:entries; 208, identifier:odb; 209, call; 210, binary_operator:rbound + 1; 211, identifier:sha; 212, identifier:S_IFDIR; 213, identifier:base; 214, attribute; 215, argument_list; 216, identifier:entry; 217, identifier:path; 218, identifier:si; 219, identifier:entries; 220, identifier:xi; 221, attribute; 222, argument_list; 223, identifier:orbound; 224, unary_operator; 225, subscript; 226, identifier:base; 227, identifier:slice; 228, argument_list; 229, identifier:rbound; 230, integer:1; 231, identifier:sio; 232, identifier:getvalue; 233, attribute; 234, identifier:find; 235, string; 236, identifier:si; 237, integer:1; 238, attribute; 239, slice; 240, binary_operator:ci - 1; 241, identifier:xi; 242, identifier:oentry; 243, identifier:path; 244, string_content:/; 245, identifier:oentry; 246, identifier:path; 247, identifier:si; 248, identifier:orbound; 249, identifier:ci; 250, integer:1
code: def write_tree_from_cache(entries, odb, sl, si=0):
      """Create a tree from the given sorted list of entries and put the respective
      trees into the given object database
  
      :param entries: **sorted** list of IndexEntries
      :param odb: object database to store the trees in
      :param si: start index at which we should start creating subtrees
      :param sl: slice indicating the range we should process on the entries list
      :return: tuple(binsha, list(tree_entry, ...)) a tuple of a sha and a list of
          tree entries being a tuple of hexsha, mode, name"""
      tree_items = []
      tree_items_append = tree_items.append
      ci = sl.start
      end = sl.stop
      while ci < end:
          entry = entries[ci]
          if entry.stage != 0:
              raise UnmergedEntriesError(entry)
          # END abort on unmerged
          ci += 1
          rbound = entry.path.find('/', si)
          if rbound == -1:
              # its not a tree
              tree_items_append((entry.binsha, entry.mode, entry.path[si:]))
          else:
              # find common base range
              base = entry.path[si:rbound]
              xi = ci
              while xi < end:
                  oentry = entries[xi]
                  orbound = oentry.path.find('/', si)
                  if orbound == -1 or oentry.path[si:orbound] != base:
                      break
                  # END abort on base mismatch
                  xi += 1
              # END find common base
  
              # enter recursion
              # ci - 1 as we want to count our current item as well
              sha, tree_entry_list = write_tree_from_cache(entries, odb, slice(ci - 1, xi), rbound + 1)  # @UnusedVariable
              tree_items_append((sha, S_IFDIR, base))
  
              # skip ahead
              ci = xi
          # END handle bounds
      # END for each entry
  
      # finally create the tree
      sio = BytesIO()
      tree_to_stream(tree_items, sio.write)
      sio.seek(0)
  
      istream = odb.store(IStream(str_tree_type, len(sio.getvalue()), sio))
      return (istream.binsha, tree_items)