UNPKG

8.59 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var Fs = require("fs-extra");
4var Handlebars = require("handlebars");
5var Minimist = require("minimist");
6var Path = require("path");
7var ReadlineSync = require("readline-sync");
8var Tmp = require("tmp");
9var ascii_1 = require("./ascii");
10var git_1 = require("./git");
11var local_storage_1 = require("./local-storage");
12var paths_1 = require("./paths");
13var submodule_1 = require("./submodule");
14var utils_1 = require("./utils");
15/**
16 Contains some essential utilities that should usually run once to create a project or
17 initialize a project.
18 */
19var exec = utils_1.Utils.exec;
20var tmpDir = Tmp.dirSync({ unsafeCleanup: true });
21var tmpPaths = paths_1.Paths.resolveProject(tmpDir.name);
22function init() {
23 if (require.main !== module) {
24 return;
25 }
26 var argv = Minimist(process.argv.slice(2), {
27 string: ['_', 'message', 'm', 'output', 'o'],
28 boolean: ['override'],
29 });
30 var method = argv._[0];
31 var arg1 = argv._[1];
32 var output = argv.output || argv.o;
33 var override = argv.override;
34 var options = {
35 output: output,
36 override: override,
37 };
38 switch (method) {
39 case 'create':
40 return createProject(arg1, options);
41 case 'ensure':
42 return ensureTortilla(arg1);
43 }
44}
45init();
46// Initialize tortilla project, it will use the skeleton as the template and it will fill
47// it up with the provided details. Usually should only run once
48function createProject(projectName, options) {
49 projectName = projectName || 'tortilla-project';
50 options = utils_1.Utils.extend({
51 output: Path.resolve(projectName),
52 }, options);
53 // In case dir already exists verify the user's decision
54 if (utils_1.Utils.exists(options.output)) {
55 options.override = options.override || ReadlineSync.keyInYN([
56 'Output path already exists.',
57 'Would you like to override it and continue?',
58 ].join('\n'));
59 if (!options.override) {
60 return;
61 }
62 }
63 Fs.emptyDirSync(tmpDir.name);
64 // Unpack skeleton
65 exec.print('tar', [
66 '--strip-components', 1, '-xf', paths_1.Paths.tortilla.skeleton, '-C', tmpDir.name
67 ]);
68 var packageName = utils_1.Utils.kebabCase(projectName);
69 var title = utils_1.Utils.startCase(projectName);
70 // Fill in template files
71 overwriteTemplateFile(tmpPaths.npm.package, {
72 name: packageName,
73 });
74 overwriteTemplateFile(tmpPaths.readme, {
75 title: title,
76 });
77 // Git chores
78 git_1.Git(['init'], { cwd: tmpDir.name });
79 git_1.Git(['add', '.'], { cwd: tmpDir.name });
80 git_1.Git(['commit', '-m', title], { cwd: tmpDir.name });
81 if (options.message) {
82 git_1.Git.print(['commit', '--amend', '-m', options.message], { cwd: tmpDir.name });
83 }
84 else {
85 git_1.Git.print(['commit', '--amend'], { cwd: tmpDir.name });
86 }
87 // Initializing
88 ensureTortilla(tmpPaths);
89 // Copy from temp to output
90 Fs.removeSync(options.output);
91 Fs.copySync(tmpDir.name, options.output);
92 tmpDir.removeCallback();
93}
94// Make sure that tortilla essentials are initialized on an existing project.
95// Used most commonly when cloning or creating a project
96function ensureTortilla(projectDir) {
97 projectDir = projectDir || utils_1.Utils.cwd();
98 var projectPaths = projectDir.resolve ? projectDir : paths_1.Paths.resolveProject(projectDir);
99 var localStorage = local_storage_1.localStorage.create(projectPaths);
100 var cwd = projectPaths.resolve();
101 // If tortilla is already initialized don't do anything
102 var isInitialized = localStorage.getItem('INIT');
103 if (isInitialized) {
104 return;
105 }
106 var hookFiles = Fs.readdirSync(projectPaths.tortilla.hooks);
107 // For each hook file in the hooks directory
108 hookFiles.forEach(function (hookFile) {
109 var handlerPath = Path.resolve(projectPaths.tortilla.hooks, hookFile);
110 var hookName = Path.basename(hookFile, '.js');
111 var hookPath = Path.resolve(projectPaths.git.hooks, hookName);
112 // Place an executor in the project's git hooks
113 var hook = [
114 '',
115 '### TORTILLA ###',
116 'cd .',
117 "node " + handlerPath + " \"$@\"",
118 ].join('\n');
119 // If exists, append logic
120 if (utils_1.Utils.exists(hookPath, 'file')) {
121 var contents = Fs.readFileSync(hookPath).toString();
122 // Don't hook logic if already initialized
123 if (!/\n### TORTILLA ###\n/.test(contents)) {
124 contents += "\n" + hook;
125 Fs.writeFileSync(hookPath, contents);
126 }
127 }
128 else { // Else, create file
129 Fs.writeFileSync(hookPath, "#!/bin/sh" + hook);
130 }
131 // Give read permissions to hooks so git can execute properly
132 Fs.chmodSync(hookPath, '755');
133 });
134 // Create root branch reference for continues integration testing
135 var activeBranchName = git_1.Git(['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: cwd });
136 try {
137 git_1.Git(['rev-parse', activeBranchName + "-root"], { cwd: cwd });
138 }
139 catch (e) {
140 git_1.Git(['branch', activeBranchName + "-root", activeBranchName], { cwd: cwd });
141 }
142 // Ensure submodules are initialized
143 submodule_1.Submodule.list().forEach(function (submodule) {
144 submodule_1.Submodule.update(submodule);
145 // If hash not found
146 if (git_1.Git(['diff', '--name-only']).split('\n').filter(Boolean).includes(submodule)) {
147 submodule_1.Submodule.reset(submodule);
148 }
149 });
150 // Mark tortilla flag as initialized
151 localStorage.setItem('INIT', true);
152 localStorage.setItem('USE_STRICT', true);
153 // The art should be printed only if the operation finished for all submodules
154 if (!submodule_1.Submodule.isOne()) {
155 ascii_1.Ascii.print('ready');
156 }
157}
158// TODO: **Add tests**
159function cloneProject(url, out) {
160 if (!out) {
161 // git@github.com:srtucker22/chatty.git -> chatty
162 out = url.split('/').pop().split('.').shift();
163 }
164 out = Path.resolve(utils_1.Utils.cwd(), out);
165 git_1.Git.print(['clone', url, out]);
166 ensureTortilla(out);
167 // List all branches in origin
168 git_1.Git(['branch', '-a'], { cwd: out })
169 .split('\n')
170 .filter(Boolean)
171 .filter(function (remoteBranch) {
172 return /remotes\/origin\/[^\s]+$/.test(remoteBranch);
173 })
174 .map(function (remoteBranch) {
175 return remoteBranch.trim();
176 })
177 .map(function (remoteBranch) {
178 return remoteBranch.split('remotes/origin/').pop();
179 })
180 .forEach(function (remoteBranch) {
181 var branchName = remoteBranch.split('/').pop();
182 // Create all branches
183 try {
184 git_1.Git(['checkout', '-b', branchName], { cwd: out });
185 }
186 catch (e) {
187 // Branch already exists. I don't care
188 }
189 });
190 // Switch back to the original branch
191 git_1.Git(['checkout', 'master'], { cwd: out });
192}
193// Will reclone the current project. By doing so, we will sync the most recent changes
194function recloneProject(remote) {
195 if (remote === void 0) { remote = 'origin'; }
196 var proceed = ReadlineSync.keyInYN([
197 '⚠ Warning ⚠',
198 'Recloning will sync your project with the most recent changes but will discard',
199 'the current git-state completely. Are you sure you would like to proceed?',
200 ].join('\n'));
201 if (!proceed) {
202 return;
203 }
204 var url = git_1.Git(['remote', 'get-url', remote]);
205 Fs.removeSync(utils_1.Utils.cwd());
206 cloneProject(url, utils_1.Utils.cwd());
207}
208// Will force push our changes to the provided remote, including branches and tags
209function pushChanges(remote) {
210 if (remote === void 0) { remote = 'origin'; }
211 var proceed = ReadlineSync.keyInYN([
212 '⚠ Warning ⚠',
213 'Pushing your changes will override the entire hosted project.',
214 'Are you sure you would like to proceed?',
215 ].join('\n'));
216 if (!proceed) {
217 return;
218 }
219 git_1.Git.print(['push', remote, '--mirror']);
220}
221function overwriteTemplateFile(path, scope) {
222 var templateContent = Fs.readFileSync(path, 'utf8');
223 var viewContent = Handlebars.compile(templateContent)(scope);
224 Fs.writeFileSync(path, viewContent);
225}
226exports.Essentials = {
227 clone: cloneProject,
228 reclone: recloneProject,
229 create: createProject,
230 ensure: ensureTortilla,
231 push: pushChanges,
232};
233//# sourceMappingURL=essentials.js.map
\No newline at end of file