github-cherry-pick
Advanced tools
Comparing version 0.1.10 to 0.1.11
256
lib/index.js
@@ -7,2 +7,4 @@ "use strict"; | ||
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); | ||
var _git = require("shared-github-internals/lib/git"); | ||
@@ -20,7 +22,39 @@ | ||
const createCommit = (() => { | ||
var _ref = _asyncToGenerator(function* ({ | ||
author, | ||
committer, | ||
message, | ||
octokit, | ||
owner, | ||
parent, | ||
repo, | ||
tree | ||
}) { | ||
var _ref2 = yield octokit.gitdata.createCommit({ | ||
author, | ||
committer, | ||
message, | ||
owner, | ||
parents: [parent], | ||
repo, | ||
// No PGP signature support for now. | ||
// See https://developer.github.com/v3/git/commits/#create-a-commit. | ||
tree | ||
}); | ||
const sha = _ref2.data.sha; | ||
return sha; | ||
}); | ||
return function createCommit(_x) { | ||
return _ref.apply(this, arguments); | ||
}; | ||
})(); | ||
const merge = (() => { | ||
var _ref = _asyncToGenerator(function* ({ base, commit, octokit, owner, repo }) { | ||
var _ref2 = yield octokit.repos.merge({ | ||
var _ref3 = _asyncToGenerator(function* ({ base, commit, octokit, owner, repo }) { | ||
var _ref4 = yield octokit.repos.merge({ | ||
base, | ||
commit_message: `Merge ${commit} into ${base}`, | ||
head: commit, | ||
@@ -31,22 +65,15 @@ owner, | ||
const sha = _ref2.data.commit.tree.sha; | ||
const tree = _ref4.data.commit.tree.sha; | ||
return sha; | ||
return tree; | ||
}); | ||
return function merge(_x) { | ||
return _ref.apply(this, arguments); | ||
return function merge(_x2) { | ||
return _ref3.apply(this, arguments); | ||
}; | ||
})(); | ||
const createCommitWithDifferentTree = (() => { | ||
var _ref3 = _asyncToGenerator(function* ({ | ||
commit, | ||
octokit, | ||
owner, | ||
parent, | ||
repo, | ||
tree | ||
}) { | ||
var _ref4 = yield octokit.gitdata.getCommit({ | ||
const retrieveCommitDetails = (() => { | ||
var _ref5 = _asyncToGenerator(function* ({ commit, octokit, owner, repo }) { | ||
var _ref6 = yield octokit.gitdata.getCommit({ | ||
commit_sha: commit, | ||
@@ -56,27 +83,51 @@ owner, | ||
}), | ||
_ref4$data = _ref4.data; | ||
_ref6$data = _ref6.data; | ||
const author = _ref4$data.author, | ||
committer = _ref4$data.committer, | ||
message = _ref4$data.message; | ||
const author = _ref6$data.author, | ||
committer = _ref6$data.committer, | ||
message = _ref6$data.message; | ||
var _ref5 = yield octokit.gitdata.createCommit({ | ||
var _ref6$data$parents = _slicedToArray(_ref6$data.parents, 1); | ||
const parent = _ref6$data$parents[0].sha; | ||
return { author, committer, message, parent }; | ||
}); | ||
return function retrieveCommitDetails(_x3) { | ||
return _ref5.apply(this, arguments); | ||
}; | ||
})(); | ||
const createSiblingCommit = (() => { | ||
var _ref7 = _asyncToGenerator(function* ({ | ||
commit, | ||
head: { author, committer, ref, tree }, | ||
octokit, | ||
owner, | ||
parent, | ||
repo | ||
}) { | ||
const sha = yield createCommit({ | ||
author, | ||
committer, | ||
message, | ||
message: `Sibling of ${commit}`, | ||
octokit, | ||
owner, | ||
parents: [parent], | ||
parent, | ||
repo, | ||
// No PGP signature support for now. | ||
// See https://developer.github.com/v3/git/commits/#create-a-commit. | ||
tree | ||
}); | ||
const sha = _ref5.data.sha; | ||
return sha; | ||
yield (0, _git.updateReference)({ | ||
force: true, | ||
octokit, | ||
owner, | ||
ref, | ||
repo, | ||
sha | ||
}); | ||
}); | ||
return function createCommitWithDifferentTree(_x2) { | ||
return _ref3.apply(this, arguments); | ||
return function createSiblingCommit(_x4) { | ||
return _ref7.apply(this, arguments); | ||
}; | ||
@@ -86,5 +137,6 @@ })(); | ||
const cherryPickCommit = (() => { | ||
var _ref6 = _asyncToGenerator(function* ({ | ||
var _ref8 = _asyncToGenerator(function* ({ | ||
commit, | ||
head: { ref, sha }, | ||
debug, | ||
head: { ref, sha, tree }, | ||
octokit, | ||
@@ -94,11 +146,43 @@ owner, | ||
}) { | ||
const tree = yield merge({ base: ref, commit, octokit, owner, repo }); | ||
const createdCommit = yield createCommitWithDifferentTree({ | ||
var _ref9 = yield retrieveCommitDetails({ | ||
commit, | ||
octokit, | ||
owner, | ||
repo | ||
}); | ||
const author = _ref9.author, | ||
committer = _ref9.committer, | ||
message = _ref9.message, | ||
parent = _ref9.parent; | ||
debug("creating sibling commit"); | ||
yield createSiblingCommit({ | ||
commit, | ||
head: { author, committer, ref, tree }, | ||
octokit, | ||
owner, | ||
parent, | ||
repo | ||
}); | ||
debug("merging"); | ||
const newHeadTree = yield merge({ | ||
base: ref, | ||
commit, | ||
octokit, | ||
owner, | ||
repo | ||
}); | ||
debug("creating commit with different tree", newHeadTree); | ||
const newHeadSha = yield createCommit({ | ||
author, | ||
committer, | ||
message, | ||
octokit, | ||
owner, | ||
parent: sha, | ||
repo, | ||
tree | ||
tree: newHeadTree | ||
}); | ||
debug("updating reference", newHeadSha); | ||
yield (0, _git.updateReference)({ | ||
@@ -112,41 +196,73 @@ // Overwrite the merge commit and its parent on the branch by a single commit. | ||
repo, | ||
sha: createdCommit | ||
sha: newHeadSha | ||
}); | ||
return createdCommit; | ||
return { | ||
sha: newHeadSha, | ||
tree: newHeadTree | ||
}; | ||
}); | ||
return function cherryPickCommit(_x3) { | ||
return _ref6.apply(this, arguments); | ||
return function cherryPickCommit(_x5) { | ||
return _ref8.apply(this, arguments); | ||
}; | ||
})(); | ||
const cherryPickCommitsOnReference = ({ | ||
commits, | ||
debug, | ||
head, | ||
octokit, | ||
owner, | ||
ref, | ||
repo | ||
}) => commits.reduce((() => { | ||
var _ref7 = _asyncToGenerator(function* (previousCherryPick, commit) { | ||
const sha = yield previousCherryPick; | ||
debug("cherry-picking", { commit, ref, sha }); | ||
return cherryPickCommit({ | ||
commit, | ||
head: { ref, sha }, | ||
octokit, | ||
const cherryPickCommitsOnReference = (() => { | ||
var _ref10 = _asyncToGenerator(function* ({ | ||
commits, | ||
debug, | ||
initialHeadSha, | ||
octokit, | ||
owner, | ||
ref, | ||
repo | ||
}) { | ||
var _ref11 = yield octokit.gitdata.getCommit({ | ||
commit_sha: initialHeadSha, | ||
owner, | ||
repo | ||
}); | ||
const initialHeadTree = _ref11.data.tree.sha; | ||
var _ref12 = yield commits.reduce((() => { | ||
var _ref13 = _asyncToGenerator(function* (previousCherryPick, commit) { | ||
var _ref14 = yield previousCherryPick; | ||
const sha = _ref14.sha, | ||
tree = _ref14.tree; | ||
debug("cherry-picking", { commit, ref, sha }); | ||
return cherryPickCommit({ | ||
commit, | ||
debug, | ||
head: { ref, sha, tree }, | ||
octokit, | ||
owner, | ||
repo | ||
}); | ||
}); | ||
return function (_x7, _x8) { | ||
return _ref13.apply(this, arguments); | ||
}; | ||
})(), Promise.resolve({ | ||
sha: initialHeadSha, | ||
tree: initialHeadTree | ||
})); | ||
const newHeadSha = _ref12.sha; | ||
return newHeadSha; | ||
}); | ||
return function (_x4, _x5) { | ||
return _ref7.apply(this, arguments); | ||
return function cherryPickCommitsOnReference(_x6) { | ||
return _ref10.apply(this, arguments); | ||
}; | ||
})(), Promise.resolve(head)); | ||
})(); | ||
// eslint-disable-next-line max-lines-per-function | ||
const cherryPickCommits = (() => { | ||
var _ref8 = _asyncToGenerator(function* ({ | ||
var _ref15 = _asyncToGenerator(function* ({ | ||
// Should only be used in tests. | ||
@@ -164,3 +280,3 @@ _intercept = function () { | ||
debug("starting", { commits, head, owner, repo }); | ||
const headInitialSha = yield (0, _git.fetchReferenceSha)({ | ||
const initialHeadSha = yield (0, _git.fetchReferenceSha)({ | ||
octokit, | ||
@@ -171,6 +287,6 @@ owner, | ||
}); | ||
yield _intercept({ headInitialSha }); | ||
yield _intercept({ initialHeadSha }); | ||
return (0, _git.withTemporaryReference)({ | ||
action: (() => { | ||
var _ref9 = _asyncToGenerator(function* (temporaryRef) { | ||
var _ref16 = _asyncToGenerator(function* (temporaryRef) { | ||
debug({ temporaryRef }); | ||
@@ -180,3 +296,3 @@ const newSha = yield cherryPickCommitsOnReference({ | ||
debug, | ||
head: headInitialSha, | ||
initialHeadSha, | ||
octokit, | ||
@@ -201,4 +317,4 @@ owner, | ||
return function action(_x7) { | ||
return _ref9.apply(this, arguments); | ||
return function action(_x10) { | ||
return _ref16.apply(this, arguments); | ||
}; | ||
@@ -210,8 +326,8 @@ })(), | ||
repo, | ||
sha: headInitialSha | ||
sha: initialHeadSha | ||
}); | ||
}); | ||
return function cherryPickCommits(_x6) { | ||
return _ref8.apply(this, arguments); | ||
return function cherryPickCommits(_x9) { | ||
return _ref15.apply(this, arguments); | ||
}; | ||
@@ -218,0 +334,0 @@ })(); |
@@ -54,3 +54,3 @@ { | ||
}, | ||
"version": "0.1.10" | ||
"version": "0.1.11" | ||
} |
147
README.md
@@ -38,20 +38,2 @@ [![npm version](https://img.shields.io/npm/v/github-cherry-pick.svg)](https://npmjs.org/package/github-cherry-pick) | ||
### Disclaimer | ||
`github-cherry-pick` currently only supports a subset of what `git cherry-pick` offers. | ||
For instance, starting with this Git graph: | ||
``` | ||
* 9232f06 (HEAD -> master) D | ||
| * e926f9d (feature) C | ||
| * d216f82 B | ||
|/ | ||
* 24dfa35 A | ||
``` | ||
Calling `github-cherry-pick` with `['e926f9d']` to only cherry-pick the last commit of the `feature` branch on `master` would also actually apply the changes brought by `d216f82` to `master`. | ||
If you have any suggestions for how to support all the situations handled by `git cherry-pick` by only using endpoints of the GitHub REST API, please create an issue or pull request. | ||
## Troubleshooting | ||
@@ -76,3 +58,3 @@ | ||
<!-- | ||
touch A.txt B.txt C.txt D.txt | ||
touch A.txt B.txt C.txt D.txt E.txt | ||
git init | ||
@@ -82,24 +64,29 @@ git add A.txt | ||
git checkout -b feature | ||
git checkout master | ||
git add B.txt | ||
git commit --message B | ||
git checkout feature | ||
git add C.txt | ||
git commit --message C | ||
git checkout master | ||
git add D.txt | ||
git commit --message D | ||
git add E.txt | ||
git commit --message E | ||
git checkout master | ||
--> | ||
``` | ||
* 9232f06 (HEAD -> master) D | ||
| * e926f9d (feature) C | ||
| * d216f82 B | ||
* 4620c9b (feature) E | ||
* 317c828 D | ||
* 7599421 C | ||
| * 00ad8d7 (HEAD -> master) B | ||
|/ | ||
* 24dfa35 A | ||
* 72cc07d A | ||
``` | ||
and we want to cherry-pick `d216f82` and `e926f9d` on the `master` branch. | ||
and we want to cherry-pick `317c828` and `4620c9b` on the `master` branch. | ||
`github-cherry-pick` would then take the following steps: | ||
1. Create a `temp` branch from `feature` with [POST /repos/:owner/:repo/git/refs](https://developer.github.com/v3/git/refs/#create-a-reference). | ||
1. Create a `temp` branch from `master` with [POST /repos/:owner/:repo/git/refs](https://developer.github.com/v3/git/refs/#create-a-reference). | ||
<!-- | ||
@@ -109,61 +96,84 @@ git checkout -b temp | ||
``` | ||
* 9232f06 (HEAD -> temp, master) D | ||
| * e926f9d (feature) C | ||
| * d216f82 B | ||
* 4620c9b (feature) E | ||
* 317c828 D | ||
* 7599421 C | ||
| * 00ad8d7 (HEAD -> temp, master) B | ||
|/ | ||
* 24dfa35 A | ||
* 72cc07d A | ||
``` | ||
2. Merge `d216f82` on `temp` with [POST /repos/:owner/:repo/merges](https://developer.github.com/v3/repos/merging/#perform-a-merge). | ||
2. Create a commit from the tree of `00ad8d7` with `7599421` as parent with [POST /repos/:owner/:repo/git/commits](https://developer.github.com/v3/git/commits/#create-a-commit) and update `temp`'s reference to point to this new commit with [PATCH /repos/:owner/:repo/git/refs/:ref](https://developer.github.com/v3/git/refs/#update-a-reference). | ||
<!-- | ||
git merge d216f82 | ||
git cat-file -p 00ad8d7 | ||
git commit-tree 7f89cd8 -p 7599421 -m "Use tree of 00ad8d7" | ||
git update-ref HEAD 80c410e | ||
--> | ||
``` | ||
* 5783c4c (HEAD -> temp) Merge commit 'd216f82' into temp | ||
* 80c410e (HEAD -> temp) Use tree of 00ad8d7 | ||
| * 4620c9b (feature) E | ||
| * 317c828 D | ||
|/ | ||
* 7599421 C | ||
| * 00ad8d7 (master) B | ||
|/ | ||
* 72cc07d A | ||
``` | ||
3. Merge `317c828` on `temp` with [POST /repos/:owner/:repo/merges](https://developer.github.com/v3/repos/merging/#perform-a-merge). | ||
<!-- | ||
git merge 317c828 | ||
--> | ||
``` | ||
* 55a7299 (HEAD -> temp) Merge commit '317c828' into temp | ||
|\ | ||
* | 9232f06 (master) D | ||
| | * e926f9d (feature) C | ||
* | 80c410e Tree of 00ad8d7 with 7599421 as parent | ||
| | * 4620c9b (feature) E | ||
| |/ | ||
| * d216f82 B | ||
| * 317c828 D | ||
|/ | ||
* 24dfa35 A | ||
* 7599421 C | ||
| * 00ad8d7 (master) B | ||
|/ | ||
* 72cc07d A | ||
``` | ||
3. Create another commit from `5783c4c` with `9232f06` as the only parent with [POST /repos/:owner/:repo/git/commits](https://developer.github.com/v3/git/commits/#create-a-commit) and update `temp`'s reference to point to this new commit with [PATCH /repos/:owner/:repo/git/refs/:ref](https://developer.github.com/v3/git/refs/#update-a-reference). | ||
4. Create another commit from `55a7299` with `00ad8d7` as the only parent and update `temp`'s reference to point to this new commit. | ||
<!-- | ||
git cat-file -p 6cb4aca | ||
git commit-tree db5a9e1 -p 1d3fb48 -m B | ||
git update-ref HEAD 1616ba2 | ||
git cat-file -p 55a7299 | ||
git commit-tree 9b3f8f6 -p 00ad8d7 -m D | ||
git update-ref HEAD 3698031 | ||
--> | ||
``` | ||
* 1616ba2 (HEAD -> temp) B | ||
* 9232f06 (master) D | ||
| * e926f9d (feature) C | ||
| * d216f82 B | ||
* 3698031 (HEAD -> temp) D | ||
* 00ad8d7 (master) B | ||
| * 4620c9b (feature) E | ||
| * 317c828 D | ||
| * 7599421 C | ||
|/ | ||
* 24dfa35 A | ||
* 72cc07d A | ||
``` | ||
4. Repeat steps 2. and 3. to cherry-pick `e926f9d` on `temp`. | ||
5. Repeat steps 2. and 3. to cherry-pick `4620c9b` on `temp`. | ||
``` | ||
* d82c247 (HEAD -> temp) C | ||
* 1616ba2 B | ||
* 9232f06 (master) D | ||
| * e926f9d (feature) C | ||
| * d216f82 B | ||
* d82c247 (HEAD -> temp) E | ||
* 3698031 D | ||
* 00ad8d7 (master) B | ||
| * 4620c9b (feature) E | ||
| * 317c828 D | ||
| * 7599421 C | ||
|/ | ||
* 24dfa35 A | ||
* 72cc07d A | ||
``` | ||
5. Set `master`'s reference to the same one than `temp` with [PATCH /repos/:owner/:repo/git/refs/:ref](https://developer.github.com/v3/git/refs/#update-a-reference), making sure it's a fast-forward update. | ||
6. Set `master`'s reference to the same one than `temp` with [PATCH /repos/:owner/:repo/git/refs/:ref](https://developer.github.com/v3/git/refs/#update-a-reference), making sure it's a fast-forward update. | ||
<!-- | ||
git checkout feature | ||
git checkout master | ||
git merge temp --ff-only | ||
--> | ||
``` | ||
* d82c247 (HEAD -> master, temp) C | ||
* 1616ba2 B | ||
* 9232f06 D | ||
| * e926f9d (feature) C | ||
| * d216f82 B | ||
* d82c247 (HEAD -> master, temp) E | ||
* 3698031 D | ||
* 00ad8d7 B | ||
| * 4620c9b (feature) E | ||
| * 317c828 D | ||
| * 7599421 C | ||
|/ | ||
* 24dfa35 A | ||
* 72cc07d A | ||
``` | ||
6. Delete the `temp` branch with [DELETE /repos/:owner/:repo/git/refs/:ref](https://developer.github.com/v3/git/refs/#delete-a-reference) and we're done! | ||
7. Delete the `temp` branch with [DELETE /repos/:owner/:repo/git/refs/:ref](https://developer.github.com/v3/git/refs/#delete-a-reference) and we're done! | ||
<!-- | ||
@@ -173,9 +183,10 @@ git branch --delete temp | ||
``` | ||
* d82c247 (HEAD -> master) C | ||
* 1616ba2 B | ||
* 9232f06 D | ||
| * e926f9d (feature) C | ||
| * d216f82 B | ||
* d82c247 (HEAD -> master) E | ||
* 3698031 D | ||
* 00ad8d7 B | ||
| * 4620c9b (feature) E | ||
| * 317c828 D | ||
| * 7599421 C | ||
|/ | ||
* 24dfa35 A | ||
* 72cc07d A | ||
``` | ||
@@ -182,0 +193,0 @@ |
Sorry, the diff of this file is not supported yet
21675
284
194