-
Notifications
You must be signed in to change notification settings - Fork 13
/
convert.js
170 lines (151 loc) · 5.71 KB
/
convert.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
import { copy, move, unlink } from 'fs-promise';
import { basename } from 'path';
import git from 'simple-git/promise';
import getFilesToProcess from './config/getFilesToProcess';
import prependCodePrefix from './modernize/prependCodePrefix';
import prependMochaEnv from './modernize/prependMochaEnv';
import runEslintFix from './modernize/runEslintFix';
import runFixImports from './modernize/runFixImports';
import runJscodeshiftScripts from './modernize/runJscodeshiftScripts';
import makeCLIFn from './runner/makeCLIFn';
import makeDecaffeinateVerifyFn from './runner/makeDecaffeinateVerifyFn';
import runWithProgressBar from './runner/runWithProgressBar';
import CLIError from './util/CLIError';
import {
backupPathFor,
COFFEE_FILE_RECOGNIZER,
decaffeinateOutPathFor,
jsPathFor,
} from './util/FilePaths';
import makeCommit from './util/makeCommit';
import pluralize from './util/pluralize';
export default async function convert(config) {
await assertGitWorktreeClean();
let coffeeFiles = await getFilesToProcess(config, COFFEE_FILE_RECOGNIZER);
if (coffeeFiles.length === 0) {
console.log('There were no CoffeeScript files to convert.');
return;
}
let movingCoffeeFiles = coffeeFiles.filter(p => jsPathFor(p, config) !== p);
let {decaffeinateArgs = [], decaffeinatePath} = config;
if (!config.skipVerify) {
try {
await runWithProgressBar(
config,
'Verifying that decaffeinate can successfully convert these files...',
coffeeFiles, makeDecaffeinateVerifyFn(config));
} catch (e) {
throw new CLIError(`\
Some files could not be converted with decaffeinate.
Re-run with the "check" command for more details.`);
}
}
await runWithProgressBar(
config,
'Backing up files to .original.coffee...',
coffeeFiles,
async function(coffeePath) {
await copy(`${coffeePath}`, `${backupPathFor(coffeePath)}`);
});
await runWithProgressBar(
config,
`Renaming files from .coffee to .${config.outputFileExtension}...`,
movingCoffeeFiles,
async function(coffeePath) {
await move(coffeePath, jsPathFor(coffeePath, config));
});
let shortDescription = getShortDescription(coffeeFiles);
let renameCommitMsg =
`decaffeinate: Rename ${shortDescription} from .coffee to .${config.outputFileExtension}`;
if (movingCoffeeFiles.length > 0) {
console.log(`Generating the first commit: "${renameCommitMsg}"...`);
await git().rm(movingCoffeeFiles);
await git().raw(['add', '-f', ...movingCoffeeFiles.map(p => jsPathFor(p, config))]);
await makeCommit(renameCommitMsg);
}
await runWithProgressBar(
config,
'Moving files back...',
movingCoffeeFiles,
async function(coffeePath) {
await move(jsPathFor(coffeePath, config), coffeePath);
});
await runWithProgressBar(
config,
'Running decaffeinate on all files...',
coffeeFiles,
makeCLIFn(path => `${decaffeinatePath} ${decaffeinateArgs.join(' ')} ${path}`)
);
await runWithProgressBar(
config,
'Deleting old files...',
coffeeFiles,
async function(coffeePath) {
await unlink(coffeePath);
});
await runWithProgressBar(
config,
'Setting proper extension for all files...',
coffeeFiles,
async function(coffeePath) {
let decaffeinateOutPath = decaffeinateOutPathFor(coffeePath);
let jsPath = jsPathFor(coffeePath, config);
if (decaffeinateOutPath !== jsPath) {
await move(decaffeinateOutPath, jsPath);
}
});
let decaffeinateCommitMsg =
`decaffeinate: Convert ${shortDescription} to JS`;
console.log(`Generating the second commit: ${decaffeinateCommitMsg}...`);
let jsFiles = coffeeFiles.map(f => jsPathFor(f, config));
await git().raw(['add', '-f', ...jsFiles]);
await makeCommit(decaffeinateCommitMsg);
if (config.jscodeshiftScripts) {
await runJscodeshiftScripts(jsFiles, config);
}
if (config.mochaEnvFilePattern) {
await prependMochaEnv(config, jsFiles, config.mochaEnvFilePattern);
}
let thirdCommitModifiedFiles = jsFiles.slice();
if (config.fixImportsConfig) {
thirdCommitModifiedFiles = await runFixImports(jsFiles, config);
}
if (!config.skipEslintFix) {
await runEslintFix(jsFiles, config, {isUpdate: false});
}
if (config.codePrefix) {
await prependCodePrefix(config, jsFiles, config.codePrefix);
}
let postProcessCommitMsg =
`decaffeinate: Run post-processing cleanups on ${shortDescription}`;
console.log(`Generating the third commit: ${postProcessCommitMsg}...`);
await git().raw(['add', '-f', ...thirdCommitModifiedFiles]);
await makeCommit(postProcessCommitMsg);
console.log(`Successfully ran decaffeinate on ${pluralize(coffeeFiles.length, 'file')}.`);
console.log('You should now fix lint issues in any affected files.');
console.log('All CoffeeScript files were backed up as .original.coffee files that you can use for comparison.');
console.log('You can run "bulk-decaffeinate clean" to remove those files.');
console.log('To allow git to properly track file history, you should NOT squash the generated commits together.');
}
async function assertGitWorktreeClean() {
let status = await git().status();
if (status.files.length > status.not_added.length) {
throw new CLIError(`\
You have modifications to your git worktree.
Please revert or commit them before running convert.`);
} else if (status.not_added.length > 0) {
console.log(`\
Warning: the following untracked files are present in your repository:
${status.not_added.join('\n')}
Proceeding anyway.
`);
}
}
function getShortDescription(coffeeFiles) {
let firstFile = basename(coffeeFiles[0]);
if (coffeeFiles.length === 1) {
return firstFile;
} else {
return `${firstFile} and ${pluralize(coffeeFiles.length - 1, 'other file')}`;
}
}