writeTree method

Future<GitHash?> writeTree(
  1. GitIndex index
)

Implementation

Future<GitHash?> writeTree(GitIndex index) async {
  var allTreeDirs = {''};
  var treeObjects = {'': GitTree.empty()};
  var treeObjFullPath = <GitTree, String>{};

  index.entries.forEach((entry) {
    var fullPath = entry.path;
    var fileName = p.basename(fullPath);
    var dirName = p.dirname(fullPath);

    // Construct all the tree objects
    var allDirs = <String>[];
    while (dirName != '.') {
      allTreeDirs.add(dirName);
      allDirs.add(dirName);

      dirName = p.dirname(dirName);
    }

    allDirs.sort(dirSortFunc);

    for (var dir in allDirs) {
      if (!treeObjects.containsKey(dir)) {
        var tree = GitTree.empty();
        treeObjects[dir] = tree;
      }

      var parentDir = p.dirname(dir);
      if (parentDir == '.') parentDir = '';

      var parentTree = treeObjects[parentDir]!;
      var folderName = p.basename(dir);
      treeObjFullPath[parentTree] = parentDir;

      var i = parentTree.entries.indexWhere((e) => e.name == folderName);
      if (i != -1) {
        continue;
      }
      parentTree.entries.add(GitTreeEntry(
        mode: GitFileMode.Dir,
        name: folderName,
        hash: GitHash.zero(),
      ));
    }

    dirName = p.dirname(fullPath);
    if (dirName == '.') {
      dirName = '';
    }

    var leaf = GitTreeEntry(
      mode: entry.mode,
      name: fileName,
      hash: entry.hash,
    );
    treeObjects[dirName]!.entries.add(leaf);
  });
  assert(treeObjects.containsKey(''));

  // Write all the tree objects
  var hashMap = <String, GitHash>{};

  var allDirs = allTreeDirs.toList();
  allDirs.sort(dirSortFunc);

  for (var dir in allDirs.reversed) {
    var tree = treeObjects[dir]!;

    for (var i = 0; i < tree.entries.length; i++) {
      var leaf = tree.entries[i];

      if (leaf.hash.isNotEmpty) {
        //
        // Making sure the leaf is a blob
        //
        assert(await () async {
          var leafObjRes = await objStorage.read(leaf.hash);
          var leafObj = leafObjRes.get();
          return leafObj.formatStr() == 'blob';
        }());

        continue;
      }

      var fullPath = p.join(treeObjFullPath[tree]!, leaf.name);
      var hash = hashMap[fullPath]!;

      tree.entries[i] = GitTreeEntry(
        mode: leaf.mode,
        name: leaf.name,
        hash: hash,
      );
    }

    var hash = await objStorage.writeObject(tree);
    hashMap[dir] = hash;
  }

  return hashMap[''];
}