int commit_interleaver::make_partial_tree()

in src/commit_interleaver.h [307:365]


int commit_interleaver::make_partial_tree(
    const commit_source &source, sha1_ref base, sha1_ref mono,
    std::vector<git_tree::item_type> &items, dir_mask &source_dirs) {
  // Fill in source_dirs as we go.
  if (source.has_root || source.is_repeat) {
    if (source.is_repeat) {
      assert(mono);
      assert(!base);
      assert(source.dir_index == -1);
      source_dirs.bits |= dirs.repeated_dirs.bits;
    } else {
      assert(base);
      assert(source.dir_index != -1);
      assert(dirs.list[source.dir_index].is_root);
      source_dirs.set(source.dir_index);
    }
    git_tree tree;
    tree.sha1 = source.is_repeat ? mono : base;
    if (cache.ls_tree(tree))
      return 1;

    if (source.is_repeat) {
      for (int i = 0; i < tree.num_items; ++i) {
        assert(tree.items[i].sha1);
        int d = dirs.find_dir(tree.items[i].name);
        if (d == -1)
          continue;
        if (!dirs.repeated_dirs.test(d))
          continue;
        items.push_back(tree.items[i]);
      }
      return 0;
    }

    assert(base);
    items.reserve(items.size() + tree.num_items);
    for (int i = 0; i < tree.num_items; ++i) {
      auto &item = tree.items[i];
      if (dirs.is_dir(item.name))
        return error("root dir '-' conflicts with tracked dir '" +
                     base->to_string() + "'");
      items.push_back(item);
    }
    return 0;
  }

  assert(base);
  sha1_ref base_tree;
  if (cache.compute_commit_tree(base, base_tree))
    return error("failed to look up tree for '" + base->to_string() + "'");
  assert(base_tree);
  items.emplace_back();
  items.back().sha1 = base_tree;
  items.back().name = dirs.list[source.dir_index].name;
  items.back().type = git_tree::item_type::tree;
  source_dirs.set(source.dir_index);

  return 0;
}