Skip to content

Commit 84901cd

Browse files
committed
Merge pull request #568 from jdgarcia/fix-rebase
Fix Rebase issues
2 parents 1f25a21 + 2ab75df commit 84901cd

File tree

6 files changed

+1180
-3
lines changed

6 files changed

+1180
-3
lines changed

generate/input/descriptor.json

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,6 +1278,53 @@
12781278
}
12791279
}
12801280
},
1281+
"rebase": {
1282+
"functions": {
1283+
"git_rebase_commit": {
1284+
"args": {
1285+
"id": {
1286+
"isReturn": true,
1287+
"shouldAlloc": true
1288+
},
1289+
"author": {
1290+
"isOptional": true
1291+
},
1292+
"message_encoding": {
1293+
"isOptional": true
1294+
},
1295+
"message": {
1296+
"isOptional": true
1297+
}
1298+
}
1299+
},
1300+
"git_rebase_finish": {
1301+
"args": {
1302+
"signature": {
1303+
"isOptional": true
1304+
}
1305+
}
1306+
},
1307+
"git_rebase_free": {
1308+
"ignore": true
1309+
},
1310+
"git_rebase_init": {
1311+
"args": {
1312+
"upstream": {
1313+
"isOptional": true
1314+
},
1315+
"onto": {
1316+
"isOptional": true
1317+
},
1318+
"signature": {
1319+
"isOptional": true
1320+
},
1321+
"opts": {
1322+
"isOptional": true
1323+
}
1324+
}
1325+
}
1326+
}
1327+
},
12811328
"refdb": {
12821329
"functions": {
12831330
"git_refdb_backend_fs": {

generate/input/libgit2-supplement.json

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,28 @@
108108
},
109109
"new" : {
110110
"functions": {
111+
"git_rebase_next": {
112+
"type": "function",
113+
"file": "rebase.h",
114+
"args": [
115+
{
116+
"name": "out",
117+
"type": "git_rebase_operation **"
118+
},
119+
{
120+
"name": "rebase",
121+
"type": "git_rebase *"
122+
},
123+
{
124+
"name": "checkout_opts",
125+
"type": "git_checkout_options *"
126+
}
127+
],
128+
"return": {
129+
"type": "int"
130+
},
131+
"group": "rebase"
132+
},
111133
"git_reset": {
112134
"type": "function",
113135
"file": "reset.h",
@@ -175,7 +197,7 @@
175197
},
176198
"groups": [
177199
[
178-
"annotated",
200+
"annotated_commit",
179201
[
180202
"git_annotated_commit_free",
181203
"git_annotated_commit_from_fetchhead",
@@ -498,6 +520,9 @@
498520
}
499521
},
500522
"groups": {
523+
"rebase": [
524+
"git_rebase_next"
525+
],
501526
"reset": [
502527
"git_reset"
503528
],

lib/rebase.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
var NodeGit = require("../");
2+
var Rebase = NodeGit.Rebase;
3+
var normalizeOptions = NodeGit.Utils.normalizeOptions;
4+
5+
// Override Rebase.prototype.finish to normalize opts
6+
var finish = Rebase.prototype.finish;
7+
Rebase.prototype.finish = function(signature, opts) {
8+
opts = normalizeOptions(opts || {}, NodeGit.RebaseOptions);
9+
return finish.call(this, signature, opts);
10+
};
11+
12+
// Override Rebase.prototype.next to normalize opts and provide good defaults
13+
var next = Rebase.prototype.next;
14+
Rebase.prototype.next = function(checkoutOpts) {
15+
if (!checkoutOpts) {
16+
checkoutOpts = {
17+
checkoutStrategy: NodeGit.Checkout.STRATEGY.SAFE_CREATE
18+
};
19+
}
20+
21+
checkoutOpts = normalizeOptions(checkoutOpts, NodeGit.CheckoutOptions);
22+
return next.call(this, checkoutOpts);
23+
};

lib/repository.js

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,117 @@ Repository.prototype.mergeBranches = function(to, from, signature) {
747747
});
748748
};
749749

750+
/**
751+
* Goes through a rebase's rebase operations and commits them if there are
752+
* no merge conflicts
753+
*
754+
* @param {Repository} repository The repository that the rebase is being
755+
* performed in
756+
* @param {Rebase} rebase The current rebase being performed
757+
* @param {Signature} signature Identity of the one performing the rebase
758+
* @return {Int|Index} An error code for an unsuccesful rebase or an index for
759+
* a rebase with conflicts
760+
*/
761+
function performRebase(repository, rebase, signature) {
762+
return rebase.next()
763+
.then(function(rebaseOperation) {
764+
return repository.openIndex()
765+
.then(function(index) {
766+
if (index.hasConflicts()) {
767+
throw index;
768+
}
769+
770+
if (rebaseOperation) {
771+
rebase.commit(null, signature);
772+
773+
return performRebase(repository, rebase, signature);
774+
}
775+
776+
return rebase.finish(signature);
777+
});
778+
});
779+
}
780+
781+
/**
782+
* Rebases a branch onto another branch
783+
*
784+
* @param {String} branch
785+
* @param {String} upstream
786+
* @param {String} onto
787+
* @param {Signature} signature Identity of the one performing the rebase
788+
* @return {Oid|Index} A commit id for a succesful merge or an index for a
789+
* rebase with conflicts
790+
*/
791+
Repository.prototype.rebaseBranches = function(
792+
branch,
793+
upstream,
794+
onto,
795+
signature)
796+
{
797+
var repo = this;
798+
799+
signature = signature || repo.defaultSignature();
800+
801+
return Promise.all([
802+
repo.getReference(branch),
803+
upstream ? repo.getReference(upstream) : null,
804+
onto ? repo.getReference(upstream) : null
805+
])
806+
.then(function(refs) {
807+
return Promise.all([
808+
NodeGit.AnnotatedCommit.fromRef(repo, refs[0]),
809+
upstream ? NodeGit.AnnotatedCommit.fromRef(repo, refs[1]) : null,
810+
onto ? NodeGit.AnnotatedCommit.fromRef(repo, refs[2]) : null
811+
]);
812+
})
813+
.then(function(annotatedCommits) {
814+
return NodeGit.Rebase.init(repo, annotatedCommits[0], annotatedCommits[1],
815+
annotatedCommits[2], signature, null);
816+
})
817+
.then(function(rebase) {
818+
return performRebase(repo, rebase, signature);
819+
})
820+
.then(function(error) {
821+
if (error) {
822+
throw error;
823+
}
824+
825+
return repo.getBranchCommit("HEAD");
826+
});
827+
};
828+
829+
/**
830+
* Continues an existing rebase
831+
*
832+
* @param {Signature} signature Identity of the one performing the rebase
833+
* @return {Oid|Index} A commit id for a succesful merge or an index for a
834+
* rebase with conflicts
835+
*/
836+
Repository.prototype.continueRebase = function(signature) {
837+
var repo = this;
838+
839+
return repo.openIndex()
840+
.then(function(index) {
841+
if (index.hasConflicts()) {
842+
throw index;
843+
}
844+
845+
return NodeGit.Rebase.open(repo);
846+
})
847+
.then(function(rebase) {
848+
rebase.commit(null, signature);
849+
850+
return performRebase(repo, rebase, signature);
851+
})
852+
.then(function(error) {
853+
if (error) {
854+
throw error;
855+
}
856+
857+
return repo.getBranchCommit("HEAD");
858+
});
859+
};
860+
750861
// Override Repository.initExt to normalize initoptions
751862
var initExt = Repository.initExt;
752863
Repository.initExt = function(repo_path, opts) {

lib/utils/normalize_options.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,16 @@ var NodeGit = require("../../");
77
* @return {Object} An Oid instance.
88
*/
99
function normalizeOptions(options, Ctor) {
10-
var instance = options instanceof Ctor ? options : new Ctor();
11-
1210
if (!options) {
1311
return null;
1412
}
1513

14+
if (options instanceof Ctor) {
15+
return options;
16+
}
17+
18+
var instance = new Ctor();
19+
1620
Object.keys(options).forEach(function(key) {
1721
instance[key] = options[key];
1822
});

0 commit comments

Comments
 (0)