Skip to content

Instantly share code, notes, and snippets.

@creationix
Forked from aaronpowell/find-prev.js
Last active December 28, 2015 04:29

Revisions

  1. creationix revised this gist Nov 13, 2013. 1 changed file with 93 additions and 22 deletions.
    115 changes: 93 additions & 22 deletions find-prev.js
    Original file line number Diff line number Diff line change
    @@ -1,24 +1,95 @@
    //assumes that the hash you want and the repo are obtainable via closure scope
    // repo is assumed to be in closure
    var repo;

    function findPrevious(commit, previousCommit) {
    repo.load(commit.parents[0], function (err, obj) {
    if (obj.type !== 'commit') {
    console.error(obj);
    throw 'Unexpected type returned';
    // commit - the hash of the current commit
    // path - the path to the hash in the current commit
    // callback -> the previous blob value
    function findPrevious(commit, path, callback) {
    var log; // The log stream
    var currentBlob; // The current value of the blob
    var oldBlob; // The last value of the blob
    var changeCommit; // The commit that made the last change to the blob
    var oldCommit; // The previous commit

    // First get the log stream
    repo.logWalk(commit, onLog);

    function onLog(err, result) {
    if (err) return callback(err);
    log = result;
    // Read the current commit
    log.read(onCurrentCommit);
    }

    function onCurrentCommit(err, result) {
    if (err) return callback(err);
    changeCommit = result;
    // Find the file by path in the current commit
    walkPath(changeCommit.tree, path, onCurrentBlob);
    }

    function onCurrentBlob(err, result) {
    if (err) return callback(err);
    currentBlob = result;
    // Start our search loop looking for a change in the next commit
    log.read(onCommit);
    }

    function onCommit(err, result) {
    if (err) return callback(err);
    oldCommit = result
    if (oldCommit === undefined) {
    // We've reached the beginning of history, this was created in the initial commit
    return callback(null, {
    oldBlob: undefined,
    currentBlob: currentBlob,
    changeCommit: changeCommit
    });
    }
    walkPath(oldCommit.tree, path, onBlob);
    }

    function onBlob(err, result) {
    if (err) return callback(err);
    oldBlob = result;
    if ((oldBlob && oldBlob.hash) !== currentBlob.hash) {
    return callback(null, {
    oldBlob: oldBlob,
    currentBlob: currentBlob,
    changeCommit: changeCommit
    });
    }
    repo.load(obj.body.tree, function (err, tree) {
    if (tree.type !== 'tree') {
    console.error(tree);
    throw 'Object is not a tree';
    }
    var match = tree.body.filter(function (obj) { return obj.hash == hash; });
    if (match.length) {
    console.dir(match);
    findPrevious(obj.body, commit);
    } else {
    console.log('we have a winner!');
    console.dir(obj);
    }
    })
    });
    }
    changeCommit = oldCommit;
    log.read(onCommit);
    }
    }


    function walkPath(tree, path, callback) {
    // Remove leading and trailing slashes, '.' entries, and split artifacts.
    var names = path.split("/").filter(cleanPath);
    repo.loadAs("tree", tree, onTree);

    function onTree(err, tree) {
    if (err) return callback(err);
    var name = names.shift();
    var entry = findByName(tree, name);
    // return undefined for not-found errors
    if (!entry) return callback();
    // If there are still segments left, keep reading tree paths
    if (names.length) return repo.loadAs("tree", entry.hash, onTree);
    // Otherwise, load and return the blob
    repo.loadAs("blob", entry.hash, callback);
    }
    }

    function findByName(tree, name) {
    for (var i = 0, l = tree.length; i < l; i++) {
    var entry = tree[i];
    if (entry.name === name) return entry;
    }
    }

    function cleanPath(name) {
    return name && name !== ".";
    }
  2. @aaronpowell aaronpowell created this gist Nov 13, 2013.
    24 changes: 24 additions & 0 deletions find-prev.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,24 @@
    //assumes that the hash you want and the repo are obtainable via closure scope

    function findPrevious(commit, previousCommit) {
    repo.load(commit.parents[0], function (err, obj) {
    if (obj.type !== 'commit') {
    console.error(obj);
    throw 'Unexpected type returned';
    }
    repo.load(obj.body.tree, function (err, tree) {
    if (tree.type !== 'tree') {
    console.error(tree);
    throw 'Object is not a tree';
    }
    var match = tree.body.filter(function (obj) { return obj.hash == hash; });
    if (match.length) {
    console.dir(match);
    findPrevious(obj.body, commit);
    } else {
    console.log('we have a winner!');
    console.dir(obj);
    }
    })
    });
    }