diffCommits function

Future<CommitBlobChanges> diffCommits({
  1. required GitCommit fromCommit,
  2. required GitCommit toCommit,
  3. required ObjectStorage objStore,
})

Implementation

Future<CommitBlobChanges> diffCommits({
  required GitCommit fromCommit,
  required GitCommit toCommit,
  required ObjectStorage objStore,
}) async {
  var addedChanges = <Change>[];
  var removedChanges = <Change>[];
  var modifiedChanges = <Change>[];

  var pathMap = <GitHash, String>{
    fromCommit.treeHash: '',
    toCommit.treeHash: '',
  };

  var queue = Queue<_Item>();
  queue.add(_Item(
    fromParentHash: null,
    toParentHash: null,
    fromTreeHash: fromCommit.treeHash,
    toTreeHash: toCommit.treeHash,
  ));

  while (queue.isNotEmpty) {
    var item = queue.removeFirst();

    if (item.fromTreeHash == item.toTreeHash) {
      continue;
    }

    GitTree? fromTree;
    GitTree? toTree;

    if (item.fromTreeHash != null) {
      var from = await objStore.readTree(item.fromTreeHash!);
      fromTree = from.get();
    }
    if (item.toTreeHash != null) {
      var to = await objStore.readTree(item.toTreeHash!);
      toTree = to.get();
    }

    var diffTreeResults = diffTree(fromTree, toTree);
    for (var result in diffTreeResults.merged()) {
      if (result.mode == GitFileMode.Dir) {
        if (result.from != null) {
          var fromParentPath = pathMap[item.fromTreeHash]!;
          var fromPath = p.join(fromParentPath, result.from!.name);

          pathMap[result.from!.hash] = fromPath;
        }
        if (result.to != null) {
          var toParentPath = pathMap[item.toTreeHash]!;
          var toPath = p.join(toParentPath, result.to!.name);

          pathMap[result.to!.hash] = toPath;
        }

        queue.add(_Item(
          fromParentHash: item.fromTreeHash,
          toParentHash: item.toTreeHash,
          fromTreeHash: result.from?.hash,
          toTreeHash: result.to?.hash,
        ));
      } else {
        if (result.modified) {
          var fromParentPath = pathMap[item.fromTreeHash]!;
          var toParentPath = pathMap[item.toTreeHash]!;

          var fromPath = p.join(fromParentPath, result.from!.name);
          var toPath = p.join(toParentPath, result.to!.name);

          var from = ChangeEntry(fromPath, fromTree, result.from);
          var to = ChangeEntry(toPath, toTree, result.to);

          assert(result.from!.hash.isNotEmpty && result.to!.hash.isNotEmpty);

          modifiedChanges.add(Change(from: from, to: to));
        } else if (result.added) {
          var toParentPath = pathMap[item.toTreeHash]!;
          var toPath = p.join(toParentPath, result.to!.name);
          var to = ChangeEntry(toPath, toTree, result.to);

          assert(result.to!.hash.isNotEmpty);

          removedChanges.add(Change(from: null, to: to));
        } else if (result.deleted) {
          var fromParentPath = pathMap[item.fromTreeHash]!;
          var fromPath = p.join(fromParentPath, result.from!.name);
          var from = ChangeEntry(fromPath, fromTree, result.from);

          assert(result.from!.hash.isNotEmpty);

          addedChanges.add(Change(from: from, to: null));
        }
      }
    }
  }

  return CommitBlobChanges(
    added: addedChanges,
    removed: removedChanges,
    modified: modifiedChanges,
  );
}