Last active
December 18, 2016 21:33
-
-
Save jrop/e974cba429ac652165a4b65a997a8988 to your computer and use it in GitHub Desktop.
A script to pull/clone all GitHub repositories for a given account
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "pull-all", | |
"version": "1.0.0", | |
"main": "index.js", | |
"license": "MIT", | |
"dependencies": { | |
"co": "^4.6.0", | |
"colors": "^1.1.2", | |
"execa": "^0.5.0", | |
"generic-pool": "^3.1.4", | |
"listr": "^0.8.0", | |
"loud-rejection": "^1.6.0", | |
"node-fetch": "^1.6.3" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict' | |
require('colors') | |
require('loud-rejection')() | |
const co = require('co') | |
const {createPool} = require('generic-pool') | |
const fetch = require('node-fetch') | |
const fs = require('fs') | |
const Listr = require('listr') | |
const execa = require('execa') | |
const qs = require('querystring') | |
const pool = (function() { | |
let resId = 0 | |
return createPool({ | |
create() { return Promise.resolve(resId++) }, | |
destroy(resId) { return Promise.resolve() }, | |
}, { | |
max: 9, | |
}) | |
})() | |
const errors = [] | |
const cloneOrPull = repo => co.wrap(function * () { | |
const res = yield pool.acquire() | |
let exists = false | |
try { | |
yield done => fs.stat(`${__dirname}/${repo.name}/`, done) | |
exists = true | |
} catch (e) { } | |
try { | |
if (exists) { | |
const opts = { cwd: `${__dirname}/${repo.name}` } | |
yield execa('git', [ 'pull' ], opts) | |
} else { | |
yield execa('git', [ 'clone', repo.git_url ]) | |
} | |
} catch (e) { | |
e.repo = repo | |
errors.push(e) | |
} | |
pool.release(res) | |
}) | |
co(function * main() { | |
// first, we need to find out how many pages of information there are: | |
const firstRequest = yield fetch('https://api.github.com/users/jrop/repos?type=owner') | |
const [lastPage] = firstRequest.headers.get('Link') | |
.split(',').map(s => s.trim()) | |
.map(s => { | |
const [all, url, rel] = /<([^>]*)>;\s+rel="([^"]*)"/.exec(s) | |
const page = parseInt(qs.parse(url).page) | |
return {url, rel, page} | |
}) | |
.filter(entry => entry.rel == 'last') | |
const repos = [] | |
yield Promise.all(new Array(lastPage.page).fill(0).map(co.wrap(function * (element, index) { | |
const pageRepos = yield fetch(`https://api.github.com/users/jrop/repos?type=owner&page=${index + 1}`).then(r => r.json()) | |
pageRepos.forEach(e => repos.push(e)) | |
}))) | |
const tasks = new Listr(repos.map(r => ({ | |
title: r.name, | |
task: cloneOrPull(r), | |
})), { concurrent: true }) | |
yield tasks.run() | |
for (const e of errors) { | |
process.exitCode = 1 | |
console.error(`\n${e.repo.name.red}`) | |
console.error(e.toString().trim()) | |
} | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment