-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathindex.js
129 lines (108 loc) · 3.63 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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
const Promise = require('bluebird');
const childProcess = require('child_process');
const fs = require('fs');
const tar = require('tar');
const path = require('path');
const tmp = require('tmp');
Promise.promisifyAll(childProcess);
Promise.promisifyAll(fs);
Promise.promisifyAll(tar);
Promise.promisifyAll(tmp);
const { execFileAsync, spawn } = childProcess;
const { unlinkAsync } = fs;
tmp.setGracefulCleanup();
function spawnNpmWithOutput(args, options) {
if(!options.verbose) {
return execFileAsync(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', args, options);
}
return new Promise((resolve, reject) => {
const proc = spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', args, Object.assign(options, {
stdio: ['inherit', 'pipe', 'inherit'],
env: Object.assign({}, process.env, Boolean(process.stdout.isTTY) && {
NPM_CONFIG_COLOR: 'always'
})
}));
let outData = '';
proc.on('exit', exitCode => {
if(exitCode === 0) {
resolve(outData);
}
reject(new Error(`npm failed with error code ${exitCode}`));
});
proc.on('error', reject);
proc.stdout.on('data', data => {
outData += data.toString('utf8');
});
});
}
async function packWithNpm({ sourceDir, targetDir, verbose }) {
const output = (await spawnNpmWithOutput(['pack', sourceDir], {
cwd: targetDir,
verbose
})).trim().split(/\n/);
const packedFile = output[output.length - 1];
const packedFileAbsolute = path.join(path.resolve(targetDir), packedFile);
try {
await tar.extractAsync({
strip: 1,
cwd: targetDir,
file: packedFileAbsolute
});
} finally {
await unlinkAsync(packedFileAbsolute);
}
}
async function publish({tag, branch, version, push, packOptions}, pack = packWithNpm) {
if (!tag) {
tag = `v${version}`;
}
const tmpDir = await tmp.dirAsync();
const git = (...args) => execFileAsync('git', args);
const gitInTmpDir = (...args) => execFileAsync('git', args, {
cwd: tmpDir
});
const tmpBranch = (branch)
? undefined
: `publish-to-git-temp-${Math.random().toString(36).substring(2,12)}`;
try {
if (branch) {
await git('worktree', 'add', '--no-checkout', tmpDir, branch);
} else {
await git('worktree', 'add', '--detach', tmpDir);
await gitInTmpDir('checkout', '--orphan', tmpBranch);
await gitInTmpDir('rm', '-rf', '.');
}
await pack(Object.assign({
sourceDir: process.cwd(),
targetDir: tmpDir,
}, packOptions));
await gitInTmpDir('add', '-A');
const currentCommitMessage = (await git('log', '-n', '1', '--pretty=oneline', '--decorate=full')).trim();
const message = `Published by publish-to-git
${currentCommitMessage}`;
await gitInTmpDir('commit', '-m', message);
const forceOptions = push.force ? ['-f'] : [];
await git('tag', ...forceOptions, tag, `refs/heads/${branch || tmpBranch}`);
if (push) {
console.warn(`Pushing to remote ${push.remote}`);
try {
const objectsToPush = [`refs/tags/${tag}`];
if (branch) objectsToPush.push(`refs/heads/${branch}`);
await git('push', ...forceOptions, push.remote || 'origin', ...objectsToPush);
} catch(err) {
await git('tag', '-d', tag);
if (branch) await gitInTmpDir('reset', '--hard', `HEAD~`);
throw err;
}
console.log(`Pushed tag to ${push.remote} with tag: ${tag}`);
} else {
console.log(`Created local tag: ${tag}`);
}
} finally {
try {
await git('worktree', 'remove', tmpDir);
if (tmpBranch) await git('branch', '-D', tmpBranch);
} catch(err) {}
}
}
module.exports = { publish, packWithNpm };