From 667e3e04ac2c7a742274f68ac446a909f50ec5fd Mon Sep 17 00:00:00 2001 From: Wil Chung Date: Tue, 11 Mar 2014 20:42:36 -0700 Subject: [PATCH 1/3] add options to git diff --- src/repo.coffee | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/repo.coffee b/src/repo.coffee index c3a9479..85b8454 100644 --- a/src/repo.coffee +++ b/src/repo.coffee @@ -128,14 +128,32 @@ module.exports = class Repo # commitA - A Commit or String commit id. # commitB - A Commit or String commit id. # paths - A list of String paths to restrict the difference to (optional). + # options - An object of options to pass to git diff (optional) # callback - A Function which receives `(err, diffs)`. # - diff: (commitA, commitB, paths, callback) -> - [callback, paths] = [paths, callback] if !callback - paths ?= [] + # Possible forms of the method: + # + # diff(commitA, commitB, callback) + # diff(commitA, commitB, paths, callback) + # diff(commitA, commitB, options, callback) + # diff(commitA, commitB, paths, options, callback) + # + diff: (commitA, commitB) -> + [paths, options] = [[], {}] + if arguments.length is 3 + callback = arguments[2] + else if arguments.length is 4 + callback = arguments[3] + if arguments[2] instanceof Array + paths = arguments[2] + else if arguments[2] instanceof Object + options = arguments[2] + else if arguments.length is 5 + [paths, options, callback] = arguments.slice(2) + commitA = commitA.id if _.isObject(commitA) commitB = commitB.id if _.isObject(commitB) - @git "diff", {}, _.flatten([commitA, commitB, "--", paths]) + @git "diff", options, _.flatten([commitA, commitB, "--", paths]) , (err, stdout, stderr) => return callback err if err return callback err, Diff.parse(this, stdout) From c8a7addd11a3dad439896b4df0a2e39d33187b4f Mon Sep 17 00:00:00 2001 From: Wil Chung Date: Thu, 13 Mar 2014 12:56:14 -0700 Subject: [PATCH 2/3] can now parse raw diff format --- src/diff.coffee | 28 ++++++++++++++++++++++++++++ src/repo.coffee | 5 ++++- test/diff.test.coffee | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/diff.coffee b/src/diff.coffee index 0d21c86..ee2f45a 100644 --- a/src/diff.coffee +++ b/src/diff.coffee @@ -1,3 +1,4 @@ +_ = require 'underscore' Blob = require './blob' module.exports = class Diff @@ -64,3 +65,30 @@ module.exports = class Diff return diffs + # Public: Parse the raw diff format from the command output. + # + # text - String stdout of a `git diff` command. + # + # Returns Array of Diff. + @parse_raw: (repo, text) -> + lines = _.compact(text.split "\n") + diffs = [] + + for line in lines + line = line[1..-1] # get rid of leading ':' + line = line.replace(/\.\.\./g, '') + [a_mode, b_mode, a_sha, b_sha, status, a_path, b_path] = line.split(/\s/) + b_path = a_path unless b_path + new_file = status is 'M' + deleted_file = status is 'D' + renamed_file = status is 'R' + + console.log a_path, b_path, a_sha, b_sha, a_mode, b_mode, + new_file, deleted_file, null, renamed_file, null + + diffs.push new Diff( + repo, a_path, b_path, a_sha, b_sha, a_mode, b_mode, + new_file, deleted_file, null, renamed_file, null + ) + + return diffs diff --git a/src/repo.coffee b/src/repo.coffee index 85b8454..6bc7ae6 100644 --- a/src/repo.coffee +++ b/src/repo.coffee @@ -156,7 +156,10 @@ module.exports = class Repo @git "diff", options, _.flatten([commitA, commitB, "--", paths]) , (err, stdout, stderr) => return callback err if err - return callback err, Diff.parse(this, stdout) + if _.has(options, 'raw') + return callback err, Diff.parse_raw(this, stdout) + else + return callback err, Diff.parse(this, stdout) # Public: Get the repository's remotes. diff --git a/test/diff.test.coffee b/test/diff.test.coffee index 465e676..8cbf1fa 100644 --- a/test/diff.test.coffee +++ b/test/diff.test.coffee @@ -51,6 +51,45 @@ describe "Diff", -> it "has a similarity_index of 0", -> diff.similarity_index.should.eql 0 + describe ".parse_raw", -> + describe "simple editing", -> + repo = fixtures.tagged + stdout = """ + :100644 100644 95f6539... 0466f13... M file.txt + """ + diffs = Diff.parse_raw repo, stdout + + it "is an Array of Diffs", -> + diffs.should.be.an.instanceof Array + diffs[0].should.be.an.instanceof Diff + + it "has one diff", -> + diffs.should.have.lengthOf 1 + + describe "the first diff", -> + diff = diffs[0] + + it "has the repo", -> + diff.repo.should.eql repo + + for blob in ["a_blob", "b_blob"] + it "has a #{blob}", -> + diff[blob].should.be.an.instanceof Blob + + for path in ["a_path", "b_path"] + it "has a #{path}", -> + diff[path].should.eql "file.txt" + + it "has a b_mode", -> + diff.b_mode.should.eql "100644" + + for change in ["new_file", "renamed_file", "deleted_file"] + it "#{change} is false", -> + diff[change].should.be.false + + it "has a similarity_index of 0", -> + diff.similarity_index.should.eql 0 + describe "delete a file", -> repo = fixtures.branched stdout = """ From 9287ab39487b3ad1924337a2cb79b061dcc7d715 Mon Sep 17 00:00:00 2001 From: Wil Chung Date: Sat, 15 Mar 2014 11:05:56 -0700 Subject: [PATCH 3/3] removed diff raw parse's debugging line --- src/diff.coffee | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/diff.coffee b/src/diff.coffee index ee2f45a..76ca68e 100644 --- a/src/diff.coffee +++ b/src/diff.coffee @@ -83,9 +83,6 @@ module.exports = class Diff deleted_file = status is 'D' renamed_file = status is 'R' - console.log a_path, b_path, a_sha, b_sha, a_mode, b_mode, - new_file, deleted_file, null, renamed_file, null - diffs.push new Diff( repo, a_path, b_path, a_sha, b_sha, a_mode, b_mode, new_file, deleted_file, null, renamed_file, null