Skip to content

Instantly share code, notes, and snippets.

@alexhsamuel
Last active August 10, 2016 15:15
Show Gist options
  • Save alexhsamuel/d477ab16caf87a42f0ea8357f4546bc6 to your computer and use it in GitHub Desktop.
Save alexhsamuel/d477ab16caf87a42f0ea8357f4546bc6 to your computer and use it in GitHub Desktop.
Tool to clone all open PRs of a GitHub repo into a subdirectory.
#!/usr/bin/env node
// -*- javascript -*-
/**
* Tool to clone all open PRs of a GitHub repo into a subdirectory.
*
* Usage:
*
* clone-open-prs USER/REPO DIR
*
* USER/REPO is the GitHub username and repo name, and DIR is the output
* directory name, which must not already exist.
*
* For each PR, creates a subdirectory under DIR, clones the corresponding head
* repo into it, and resets it to the PR's head SHA hash.
*
*/
//------------------------------------------------------------------------------
var spawnSync = require('child_process').spawnSync;
var fs = require('fs');
var https = require('https');
var path = require('path');
var API_HOST = 'api.github.com';
//------------------------------------------------------------------------------
/**
* Gets all open pulls for `repo` from GitHub.
*/
function getPulls(repo, callback) {
https.request({
host: API_HOST,
path: '/repos/' + repo + '/pulls?state=open',
headers: {
'User-Agent': 'node.js'
}
}, function (response) {
var data = [];
response.on('data', function (chunk) {
data.push(chunk);
});
response.on('end', function() {
var pulls = JSON.parse(data.join(''));
callback(pulls);
});
}).end();
}
/**
* Clones a git repo with URL `repo` into `dir` and resets it to SHA `hash`.
*/
function cloneRepoHash(repo, hash, dir) {
var clone = spawnSync('git', ['clone', repo, dir]);
if (clone.status !== 0) {
console.warn('failed to clone repo: ' + repo);
return false;
}
var reset = spawnSync('git', ['reset', '--hard', hash], {cwd: dir});
if (reset.status !== 0) {
console.warn('failed to reset ' + dir + ' to hash: ' + hash);
return false;
}
return true;
}
//------------------------------------------------------------------------------
if (process.argv.length != 4) {
console.error('usage: clone-open-prs REPONAME OUTDIR');
process.exit(2);
}
var repo = process.argv[2];
var outDir = process.argv[3];
fs.mkdirSync(outDir, function (err) {
if (err) {
console.log('failed to create ' + outDir + ': ' + err);
process.exit(1);
}
});
getPulls(repo, function (pulls) {
for (var i = 0; i < pulls.length; ++i) {
var pull = pulls[i];
var number = pull.number;
var username = pull.user.login;
var repoUrl = pull.head.repo.git_url;
var hash = pull.head.sha;
// The clone goes here.
var subdir = path.join(outDir, username + '-' + number);
cloneRepoHash(repoUrl, hash, subdir);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment