├── .gitignore ├── README.md ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | backup* 2 | node_modules 3 | 4 | # Logs 5 | logs 6 | *.log 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | backup-gists 2 | ====================== 3 | Backup gists for both github.com and github enterprise. 4 | 5 | 6 | ## Installation 7 | 8 | _need node > 5.0_ https://github.com/creationix/nvm 9 | 10 | ``` 11 | npm i 12 | ``` 13 | 14 | ## Quick Start 15 | 16 | For github.com user, the following command will generate a `backup-hh-mm-ss` folder in current directory (Don't support two-factor authentication, disable it temporarily). 17 | ``` 18 | ➜ node index.js -u [username] -p [password] 19 | ➜ Backup [====================] 100% 20 | ``` 21 | 22 | 23 | #### Github Enterprise version 24 | For github enterprise version, append `-d / --domain` option to add your github enterprise domain's host. Let's say, your domain is `http://github.o-in.bbc.com/` , just append `-d github.o-in.bbc.com`. 25 | ``` 26 | ➜ node index.js -u [username] -p [password] -d [github_enterprise_domain] 27 | ➜ Backup [====================] 100% 28 | ``` 29 | 30 | ## License 31 | 32 | MIT 33 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const r = require('request') 2 | const conf = require('commander') 3 | const pkg = require('./package') 4 | const cp = require('child_process') 5 | const fs = require('fs') 6 | const path = require('path') 7 | const progress = require('progress') 8 | const sleep = require('sleep') 9 | const chalk = require('chalk') 10 | 11 | conf 12 | .version(pkg.version) 13 | .option('-u, --username ', 'github username') 14 | .option('-p, --password ', 'github password') 15 | .option('-d, --domain ' , 'github host') 16 | .parse(process.argv) 17 | 18 | const getCurrentPage = (currentPage) => { 19 | r.get({ 20 | url: conf.domain 21 | ? `http://${conf.username}:${conf.password}@${conf.domain}/api/v3/users/${conf.username}/gists?page=${currentPage}&per_page=100` 22 | : `https://${conf.username}:${conf.password}@api.github.com/users/${conf.username}/gists?page=${currentPage}&per_page=100`, 23 | json: true, 24 | headers: { 25 | 'User-Agent': 'backup-gists', 26 | 'Accept': 'application/vnd.github.v3+json' 27 | } 28 | }, (err, res, body) => { 29 | 30 | if (err || res.statusCode !== 200) { 31 | throw new Error(` 32 | Failed: 33 | err: ${err}, 34 | status: ${res && res.statusCode} 35 | body: ${body} 36 | `) 37 | } 38 | 39 | // try make backup dir 40 | const BACKUP_DIR = `backup-${(new Date()).toString().split(' ')[4].replace(/:/g, '-')}` 41 | try { 42 | fs.mkdirSync(BACKUP_DIR) 43 | } catch (e) { 44 | if (e.code !== 'EEXIST') throw new Error(`mkdir ${BACKUP_DIR} failed: ${e}`) 45 | } 46 | 47 | if(! body instanceof Array) { 48 | throw new TypeError(`unexpected body format: ${typeof body}`) 49 | } 50 | 51 | console.log(chalk.green(`Download page: ${currentPage}.`)) 52 | 53 | const pg = new progress(chalk.green('Backup [:bar] :percent'), { 54 | complete: '=', 55 | incomplete: ' ', 56 | width: 20, 57 | total: body.length 58 | }) 59 | pg.tick() 60 | 61 | body.forEach( (gist, idx) => { 62 | sleep.sleep(1) 63 | cp.exec(`git clone ${gist.git_pull_url}`, { 64 | cwd: path.join(__dirname, BACKUP_DIR) 65 | }, (err, stdout, stderr) => { 66 | if(err) { 67 | console.error(chalk.red(`clone ${gist.git_pull_url} failed: ${err || stderr}`)) 68 | } 69 | }) 70 | pg.tick() 71 | }) 72 | 73 | if (body.length === 100) { 74 | getCurrentPage(currentPage+1) 75 | } 76 | 77 | }) 78 | } 79 | 80 | getCurrentPage(1) 81 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backup-gists", 3 | "version": "0.2.0", 4 | "description": "Backup gists for both github.com and github enterprise.", 5 | "main": "index.js", 6 | "engines" : { "node" : ">=5.0" }, 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/maowug/backup-gists" 13 | }, 14 | "tags": [ 15 | "gist", 16 | "gists", 17 | "backup", 18 | "node-gists", 19 | "github enterprise" 20 | ], 21 | "author": "wu", 22 | "license": "MIT", 23 | "dependencies": { 24 | "chalk": "^1.1.1", 25 | "commander": "^2.9.0", 26 | "progress": "^1.1.8", 27 | "request": "^2.69.0", 28 | "sleep": "^3.0.1" 29 | } 30 | } 31 | --------------------------------------------------------------------------------