-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
113 lines (98 loc) · 3.02 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
const os = require('os');
const child_process = require('child_process');
const path = require('path');
const { promisify } = require('util');
const fs = require('fs-extra');
const download = require('download')
const debug = require('debug')('template-down');
const exec = promisify(child_process.exec);
/**
* @todo add options.filter
*
* @param {object} opts options
* @param {string} opts.git Git repository url. If it is a github repo, only
* type '<username>/<repo>'.
* @param {string} opts.target The folder of generating to.
* @param {string} opts.cacheDir? Default `~/.template-down/${name}`, the folder
* @param {string} opts.branch? Default 'master'. Git branch.
* @param {string} opts.way? The way of install template, only 'git' or 'zip'.
* to keep cache.
* @param {string} opts.zip? Zip downloading url. If opt.git is a github
* repository, this option is unnecessary.
* @param {boolean} opts.offline? use cached files, and don't update.
*/
module.exports = function template(opts) {
const {
git,
zip,
offline = false,
target = './',
branch = 'master',
way = 'git',
} = opts;
const absolutTarget = path.isAbsolute(target) ? target : path.resolve(target);
const isGithub = /^[^\/]+\/[^\/]+$/.test(git);
const gitUrl = isGithub ? `https://github.com/${git}` : git;
const zipUrl = isGithub ? `https://github.com/${git}/archive/${branch}.zip` : zip;
const id = new Buffer(git).toString('base64').substr(0, 6);
let cacheDir = opts.cacheDir || path.join(os.homedir(), '.template-down', id);
cacheDir = path.isAbsolute(cacheDir) ? cacheDir : path.resolve(cacheDir);
debug('cache folder: %s', cacheDir);
debug('git url: %s', gitUrl);
debug('zip url: %s', zipUrl);
const cached = fs.existsSync(cacheDir);
switch(way) {
case 'git':
return createByGit();
case 'zip':
return createByZip();
default:
throw new Error(`Expect parameter opts.way is 'git' or 'zip'`);
}
/**
* opts.way === 'git'
*/
async function createByGit() {
debug('git mode');
if (!cached) {
await clone(gitUrl, cacheDir, branch);
}
if (offline) {
await fs.copy(cacheDir, absolutTarget, { filter: filterGit });
return;
}
await pull(cacheDir);
await fs.copy(cacheDir, absolutTarget, { filter: filterGit });
}
/**
* opts.way === 'zip'
* It will never use cached files, opts.cached & opts.offline will be Invalid.
*/
async function createByZip() {
debug('zip mode');
await download(zipUrl, target, { extract: true });
}
};
/**
* filter .git foler
*/
function filterGit(src) {
return !/(\\|\/)\.git\b/.test(src);
}
/**
*
* @param {string} git git repository src
* @param {string} target the target git clone to
* @param {string} branch git branch
*/
function clone(git, target, branch) {
const command = ['git', 'clone', '--depth=1', '-b', branch, git, target];
return exec(command.join(' '));
}
/**
* git pull
*/
function pull(cwd) {
return exec('git checkout -f', { cwd })
.then(() => exec('git pull', { cwd }));
}