Skip to content

Commit

Permalink
feat: handle creating and using forks (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
hipstersmoothie authored and gr2m committed May 25, 2019
1 parent 756db9d commit efc9670
Show file tree
Hide file tree
Showing 7 changed files with 3,100 additions and 10 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Features

- Retrieves the repository’s default branch unless `base` branch is set
- Makes multiple file changes using a single commit
- Creates a fork if the authenticated user does not have write access to the repository
- See [Todos](#todos) for more cool feature ideas! Pull requests welcome!

## Usage
Expand Down Expand Up @@ -42,8 +43,6 @@ octokit.createPullRequest({

## Todos

- **Creates a fork if necessary**
If the authenticated user does not have write access to the repository then create a fork first.
- **Deleting files**
The challenge with deleting files is hat the [`base_tree` parameter](https://developer.github.com/v3/git/trees/#create-a-tree) cannot be used, meaning the entire tree has to be retrieved, changed, and sent again.
- **Editing files** based on current content
Expand Down
38 changes: 31 additions & 7 deletions lib/create-pull-request.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,37 @@
module.exports = createPullRequest

async function createPullRequest (octokit, { owner, repo, title, body, base, head, changes }) {
let response
async function createPullRequest(
octokit,
{ owner, repo, title, body, base, head, changes }
) {
let response = await octokit.repos.get({ owner, repo })

if (!base) {
response = await octokit.repos.get({ owner, repo })
base = response.data.default_branch
}

let fork = owner

if (!response.data.permissions.push) {
const user = await octokit.users.getAuthenticated()
const forks = await octokit.repos.listForks({
owner,
repo
})
const hasFork = forks.data.find(
fork => fork.owner.login === user.data.login
)

if (!hasFork) {
await octokit.repos.createFork({
owner,
repo
})
}

fork = user.data.login
}

response = await octokit.repos.listCommits({
owner,
repo,
Expand All @@ -18,7 +42,7 @@ async function createPullRequest (octokit, { owner, repo, title, body, base, hea
const treeSha = response.data[0].commit.tree.sha

response = await octokit.git.createTree({
owner,
owner: fork,
repo,
base_tree: treeSha,
tree: Object.keys(changes.files).map(path => {
Expand All @@ -32,7 +56,7 @@ async function createPullRequest (octokit, { owner, repo, title, body, base, hea
const newTreeSha = response.data.sha

response = await octokit.git.createCommit({
owner,
owner: fork,
repo,
message: changes.commit,
tree: newTreeSha,
Expand All @@ -41,7 +65,7 @@ async function createPullRequest (octokit, { owner, repo, title, body, base, hea
latestCommitSha = response.data.sha

await octokit.git.createRef({
owner,
owner: fork,
repo,
sha: latestCommitSha,
ref: `refs/heads/${head}`
Expand All @@ -50,7 +74,7 @@ async function createPullRequest (octokit, { owner, repo, title, body, base, hea
response = await octokit.pulls.create({
owner,
repo,
head,
head: `${fork}:${head}`,
base,
title,
body
Expand Down
39 changes: 39 additions & 0 deletions test/create-fork-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const { test } = require('tap')

const Octokit = require('@octokit/rest')
.plugin(require('..'))

test('create fork', async t => {
const fixtures = require('./fixtures/create-fork')
const octokit = new Octokit()

octokit.hook.wrap('request', (_, options) => {
const currentFixtures = fixtures.shift()
const { baseUrl, method, url, request, headers, mediaType, ...params } = options

t.equal(currentFixtures.request.method, options.method)
t.equal(currentFixtures.request.url, options.url)

Object.keys(params).forEach(paramName => {
t.deepEqual(currentFixtures.request[paramName], params[paramName])
})
return currentFixtures.response
})

await octokit.createPullRequest({
owner: 'gr2m',
repo: 'pull-request-test',
title: 'One comes, one goes',
body: 'because',
head: 'test-branch-u7es0',
changes: {
files: {
'path/to/file1.txt': 'Content for file1',
'path/to/file2.txt': 'Content for file2'
},
commit: 'why'
}
})

t.equal(fixtures.length, 0)
})
Loading

0 comments on commit efc9670

Please sign in to comment.