Commit 60ecbcc5 authored by Tyler Wanek's avatar Tyler Wanek

Cleaned up callbacks, descriptor, supplement, Stash implementation

Added features to nodegit that are now in libgit2:

NodeGit.Stash.apply(repository, index, options)
NodeGit.Stash.drop(repository, index)
NodeGit.Stash.pop(repository, index, options)
NodeGit.Stash.save(repository, index, options)

As well as added in StashApplyOptions which contains:
a CheckoutOptions field, and a stash progress callback.

The stash progress takes 1 parameter: progress, which is of type NodeGit.Stash.APPLY_PROGRESS

All the stash operations are tested.
parent 33e72a0c
......@@ -545,6 +545,24 @@
"error": -1
}
},
"git_stash_apply_progress_cb": {
"args": [
{
"name": "progress",
"cType": "git_stash_apply_progress_t"
},
{
"name": "payload",
"cType": "void *"
}
],
"return": {
"type": "int",
"noResults":0,
"success": 0,
"error": -1
}
},
"git_stash_cb": {
"args": [
{
......
......@@ -161,6 +161,19 @@
}
}
},
"git_branch_create_from_annotated": {
"args": {
"ref_out": {
"isReturn": true
},
"repository": {},
"branch_name": {},
"commit": {},
"force": {
"isOptional": true
}
}
},
"git_branch_next": {
"ignore": true
},
......@@ -1685,6 +1698,9 @@
"git_repository_hashfile": {
"ignore": true
},
"git_repository_ident": {
"ignore": true
},
"git_repository_mergehead_foreach": {
"ignore": true
},
......@@ -1815,10 +1831,16 @@
"stash": {
"functions": {
"git_stash_apply": {
"ignore": true
"isAsync": true,
"return": {
"isErrorCode": true
}
},
"git_stash_apply_init_options": {
"ignore": true
"git_stash_drop": {
"isAsync": true,
"return": {
"isErrorCode": true
}
},
"git_stash_foreach": {
"isAsync": true,
......@@ -1827,7 +1849,16 @@
}
},
"git_stash_pop": {
"ignore": true
"isAsync": true,
"return": {
"isErrorCode": true
}
},
"git_stash_save": {
"isAsync": true,
"return": {
"isErrorCode": true
}
}
}
},
......
......@@ -190,6 +190,7 @@
"git_annotated_commit_free",
"git_annotated_commit_from_fetchhead",
"git_annotated_commit_from_ref",
"git_annotated_commit_from_revspec",
"git_annotated_commit_id",
"git_annotated_commit_lookup"
]
......@@ -217,46 +218,73 @@
],
"types": [
[
"git_config_entry",
"git_stash_apply_progress_t",
{
"type": "enum",
"fields": [
{
"type": "const char *",
"name": "name"
"type": "int",
"name": "GIT_STASH_APPLY_PROGRESS_NONE",
"value": 0
},
{
"type": "const char *",
"name": "value"
"type": "int",
"name": "GIT_STASH_APPLY_PROGRESS_LOADING_STASH",
"value": 1
},
{
"type": "git_config_level_t",
"name": "level"
"type": "int",
"name": "GIT_STASH_APPLY_PROGRESS_ANALYZE_INDEX",
"value": 2
},
{
"type": "void (*)(struct git_config_entry *)",
"name": "free",
"ignore": true
"type": "int",
"name": "GIT_STASH_APPLY_PROGRESS_ANALYZE_MODIFIED",
"value": 3
},
{
"type": "int",
"name": "GIT_STASH_APPLY_PROGRESS_ANALYZE_UNTRACKED",
"value": 4
},
{
"type": "int",
"name": "GIT_STASH_APPLY_PROGRESS_CHECKOUT_UNTRACKED",
"value": 5
},
{
"type": "int",
"name": "GIT_STASH_APPLY_PROGRESS_CHECKOUT_MODIFIED",
"value": 6
},
{
"type": "int",
"name": "GIT_STASH_APPLY_PROGRESS_DONE",
"value": 7
}
]
}
],
[
"git_direction",
"git_config_entry",
{
"type": "enum",
"description": "Enum to indicate the direction that a remote connection is going to go",
"fields": [
{
"type": "int",
"name": "GIT_DIRECTION_FETCH",
"comments": "Fetching from the remote repository",
"value": 0
"type": "const char *",
"name": "name"
},
{
"type": "int",
"name": "GIT_DIRECTION_PUSH",
"comments": "Pushing to a remote repository",
"value": 1
"type": "const char *",
"name": "value"
},
{
"type": "git_config_level_t",
"name": "level"
},
{
"type": "void (*)(struct git_config_entry *)",
"name": "free",
"ignore": true
}
]
}
......@@ -529,40 +557,6 @@
}
}
],
[
"git_sort_t",
{
"type": "enum",
"description": "Flags to specify the sorting which a revwalk should perform.",
"fields": [
{
"type": "int",
"name": "GIT_SORT_NONE",
"comments": "Sort the repository contents in no particular ordering; this sorting is arbitrary, implementation-specific and subject to change at any time. This is the default sorting for new walkers.",
"value": 0
},
{
"type": "int",
"name": "GIT_SORT_TOPOLOGICAL",
"comments": "Sort the repository contents in topological order (parents before children); this sorting mode can be combined with time sorting.",
"value": 1
},
{
"type": "int",
"name": "GIT_SORT_TIME",
"comments": "Sort the repository contents by commit time; this sorting mode can be combined with topological sorting.",
"value": 2
},
{
"type": "int",
"name": "GIT_SORT_REVERSE",
"comments": "Iterate through the repository contents in reverse order; this sorting mode can be combined with any of the above.",
"value": 4
}
],
"comments": ""
}
],
[
"git_time_t",
{
......@@ -669,6 +663,40 @@
]
}
}
],
[
"git_stash_apply_options",
{
"type": "struct",
"fields": [
{
"type": "unsigned int",
"name": "version"
},
{
"type": "git_stash_apply_flags",
"name": "flags"
},
{
"type": "git_checkout_options",
"name": "checkout_options"
},
{
"type": "git_stash_apply_progress_cb",
"name": "progress_cb"
},
{
"type": "void *",
"name": "progress_payload"
}
],
"used": {
"needs": [
"git_stash_apply_init_options",
"git_checkout_init_options"
]
}
}
]
]
},
......@@ -678,6 +706,7 @@
"git_annotated_commit_free",
"git_annotated_commit_from_fetchhead",
"git_annotated_commit_from_ref",
"git_annotated_commit_from_revspec",
"git_annotated_commit_id",
"git_annotated_commit_lookup"
]
......
var NodeGit = require("../");
var normalizeOptions = NodeGit.Utils.normalizeOptions;
var shallowClone = require("./utils/shallow_clone");
var Stash = NodeGit.Stash;
// Override Stash.foreach to eliminate the need to pass null payload
......@@ -14,3 +15,47 @@ Stash.foreach = function(repo, callback) {
return foreach(repo, wrappedCallback, null);
};
var sApply = Stash.apply;
Stash.apply = function(repo, index, options) {
var checkoutOptions;
if (options) {
options = shallowClone(options);
checkoutOptions = options.checkoutOptions;
delete options.checkoutOptions;
} else {
options = {};
}
options = normalizeOptions(options, NodeGit.StashApplyOptions);
if (checkoutOptions) {
options.checkoutOptions =
normalizeOptions(checkoutOptions, NodeGit.checkoutOptions);
}
return sApply(repo, index, options);
};
var pop = Stash.pop;
Stash.pop = function(repo, index, options) {
var checkoutOptions;
if (options) {
options = shallowClone(options);
checkoutOptions = options.checkoutOptions;
delete options.checkoutOptions;
} else {
options = {};
}
options = normalizeOptions(options, NodeGit.StashApplyOptions);
if (checkoutOptions) {
options.checkoutOptions =
normalizeOptions(checkoutOptions, NodeGit.CheckoutOptions);
}
return pop(repo, index, options);
};
......@@ -84,4 +84,164 @@ describe("Stash", function() {
});
});
});
it("can save and pop a stash", function() {
var fileNameA = "README.md";
var fileNameB = "install.js";
var oldContentA;
var oldContentB;
var fileContent = "Cha-cha-cha-chaaaaaangessssss";
var repo = this.repository;
var filePathA = path.join(repo.workdir(), fileNameA);
var filePathB = path.join(repo.workdir(), fileNameB);
var stashMessage = "stash test";
return fse.readFile(filePathA, "utf-8")
.then(function(content) {
oldContentA = content;
return fse.writeFile(filePathA, fileContent);
})
.then(function() {
return fse.readFile(filePathB, "utf-8");
})
.then(function(content) {
oldContentB = content;
return fse.writeFile(filePathB, fileContent);
})
.then(function() {
return Stash.save(repo, repo.defaultSignature(), stashMessage, 0);
})
.then(function() {
return fse.readFile(filePathA, "utf-8");
})
.then(function(content) {
assert.equal(oldContentA, content);
return fse.readFile(filePathB, "utf-8");
})
.then(function(content) {
assert.equal(oldContentB, content);
return Stash.pop(repo, 0);
})
.then(function() {
return fse.readFile(filePathA, "utf-8");
})
.then(function(content) {
assert.equal(fileContent, content);
return fse.readFile(filePathB, "utf-8");
})
.then(function(content) {
assert.equal(fileContent, content);
});
});
it("can save a stash, change files, and fail to pop stash", function() {
var fileName = "README.md";
var fileContent = "Cha-cha-cha-chaaaaaangessssss";
var fileContent2 = "Somewhere over the repo, changes were made.";
var repo = this.repository;
var filePath = path.join(repo.workdir(), fileName);
var oldContent;
var stashMessage = "stash test";
return fse.readFile(filePath)
.then(function(content) {
oldContent = content;
return fse.writeFile(filePath, fileContent);
})
.then(function() {
return Stash.save(repo, repo.defaultSignature(), stashMessage, 0);
})
.then(function() {
return fse.writeFile(filePath, fileContent2);
})
.then(function() {
return Stash.pop(repo, 0);
})
.catch(function(reason) {
if (reason.message !== "1 conflict prevents checkout") {
throw reason;
} else {
return Promise.resolve();
}
});
});
it("can save, apply, then drop the stash", function() {
var fileName = "README.md";
var fileContent = "Cha-cha-cha-chaaaaaangessssss";
var repo = this.repository;
var filePath = path.join(repo.workdir(), fileName);
var oldContent;
var stashMessage = "stash test";
return fse.readFile(filePath)
.then(function(content) {
oldContent = content;
return fse.writeFile(filePath, fileContent);
})
.then(function() {
return Stash.save(repo, repo.defaultSignature(), stashMessage, 0);
})
.then(function() {
return Stash.apply(repo, 0);
})
.then(function() {
return Stash.drop(repo, 0);
}, function() {
throw new Error("Unable to drop stash after apply.");
})
.then(function() {
return Stash.drop(repo, 0);
})
.catch(function(reason) {
if (reason.message !== "Reference 'refs/stash' not found") {
Promise.reject();
}
});
});
it("can save multiple stashes and pop an arbitrary stash", function() {
var fileName = "README.md";
var fileContentA = "Hi. It's me. I'm the dog. My name is the dog.";
var fileContentB = "Everyone likes me. I'm cute.";
var fileContentC = "I think I will bark at nothing now. Ba. Ba. Baba Baba.";
var repo = this.repository;
var filePath = path.join(repo.workdir(), fileName);
var oldContent;
var stashMessageA = "stash test A";
var stashMessageB = "stash test B";
var stashMessageC = "stash test C";
function writeAndStash(path, content, message) {
return fse.writeFile(path, content)
.then(function() {
return Stash.save(repo, repo.defaultSignature(), message, 0);
});
}
return fse.readFile(filePath, "utf-8")
.then(function (content) {
oldContent = content;
return writeAndStash(filePath, fileContentA, stashMessageA);
})
.then(function() {
return writeAndStash(filePath, fileContentB, stashMessageB);
})
.then(function() {
return writeAndStash(filePath, fileContentC, stashMessageC);
})
.then(function() {
return fse.readFile(filePath, "utf-8");
})
.then(function(content) {
assert.equal(oldContent, content);
return Stash.pop(repo, 1);
})
.then(function() {
return fse.readFile(filePath, "utf-8");
})
.then(function(content) {
assert.equal(fileContentB, content);
});
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment