Skip to content

Instantly share code, notes, and snippets.

@jrop
Last active December 18, 2016 21:33
Show Gist options
  • Save jrop/e974cba429ac652165a4b65a997a8988 to your computer and use it in GitHub Desktop.
Save jrop/e974cba429ac652165a4b65a997a8988 to your computer and use it in GitHub Desktop.
A script to pull/clone all GitHub repositories for a given account
{
"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"
}
}
'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