UNPKG

11.7 kBJavaScriptView Raw
1"use strict";
2
3var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
5var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
6
7const _require = require(`child_process`),
8 execSync = _require.execSync;
9
10const execa = require(`execa`);
11
12const hostedGitInfo = require(`hosted-git-info`);
13
14const fs = require(`fs-extra`);
15
16const sysPath = require(`path`);
17
18const report = require(`./reporter`);
19
20const url = require(`url`);
21
22const isValid = require(`is-valid-path`);
23
24const existsSync = require(`fs-exists-cached`).sync;
25
26const _require2 = require(`gatsby-telemetry`),
27 trackCli = _require2.trackCli,
28 trackError = _require2.trackError;
29
30const prompts = require(`prompts`);
31
32const opn = require(`better-opn`);
33
34const _require3 = require(`./util/configstore`),
35 getPackageManager = _require3.getPackageManager,
36 promptPackageManager = _require3.promptPackageManager;
37
38const isTTY = require(`./util/is-tty`);
39
40const spawn = (cmd, options) => {
41 const _cmd$split = cmd.split(/\s+/),
42 file = _cmd$split[0],
43 args = _cmd$split.slice(1);
44
45 return spawnWithArgs(file, args, options);
46};
47
48const spawnWithArgs = (file, args, options) => execa(file, args, Object.assign({
49 stdio: `inherit`,
50 preferLocal: false
51}, options)); // Checks the existence of yarn package and user preference if it exists
52// We use yarnpkg instead of yarn to avoid conflict with Hadoop yarn
53// Refer to https://github.com/yarnpkg/yarn/issues/673
54
55
56const shouldUseYarn =
57/*#__PURE__*/
58function () {
59 var _ref = (0, _asyncToGenerator2.default)(function* () {
60 try {
61 execSync(`yarnpkg --version`, {
62 stdio: `ignore`
63 });
64 let packageManager = getPackageManager();
65
66 if (!packageManager) {
67 // if package manager is not set:
68 // - prompt user to pick package manager if in interactive console
69 // - default to yarn if not in interactive console
70 if (isTTY()) {
71 packageManager = (yield promptPackageManager()) || `yarn`;
72 } else {
73 packageManager = `yarn`;
74 }
75 }
76
77 return packageManager === `yarn`;
78 } catch (e) {
79 return false;
80 }
81 });
82
83 return function shouldUseYarn() {
84 return _ref.apply(this, arguments);
85 };
86}();
87
88const isAlreadyGitRepository =
89/*#__PURE__*/
90function () {
91 var _ref2 = (0, _asyncToGenerator2.default)(function* () {
92 try {
93 return yield spawn(`git rev-parse --is-inside-work-tree`, {
94 stdio: `pipe`
95 }).then(output => output.stdout === `true`);
96 } catch (err) {
97 return false;
98 }
99 });
100
101 return function isAlreadyGitRepository() {
102 return _ref2.apply(this, arguments);
103 };
104}(); // Initialize newly cloned directory as a git repo
105
106
107const gitInit =
108/*#__PURE__*/
109function () {
110 var _ref3 = (0, _asyncToGenerator2.default)(function* (rootPath) {
111 report.info(`Initialising git in ${rootPath}`);
112 return yield spawn(`git init`, {
113 cwd: rootPath
114 });
115 });
116
117 return function gitInit(_x) {
118 return _ref3.apply(this, arguments);
119 };
120}(); // Create a .gitignore file if it is missing in the new directory
121
122
123const maybeCreateGitIgnore =
124/*#__PURE__*/
125function () {
126 var _ref4 = (0, _asyncToGenerator2.default)(function* (rootPath) {
127 if (existsSync(sysPath.join(rootPath, `.gitignore`))) {
128 return;
129 }
130
131 report.info(`Creating minimal .gitignore in ${rootPath}`);
132 yield fs.writeFile(sysPath.join(rootPath, `.gitignore`), `.cache\nnode_modules\npublic\n`);
133 });
134
135 return function maybeCreateGitIgnore(_x2) {
136 return _ref4.apply(this, arguments);
137 };
138}(); // Create an initial git commit in the new directory
139
140
141const createInitialGitCommit =
142/*#__PURE__*/
143function () {
144 var _ref5 = (0, _asyncToGenerator2.default)(function* (rootPath, starterUrl) {
145 report.info(`Create initial git commit in ${rootPath}`);
146 yield spawn(`git add -A`, {
147 cwd: rootPath
148 }); // use execSync instead of spawn to handle git clients using
149 // pgp signatures (with password)
150
151 try {
152 execSync(`git commit -m "Initial commit from gatsby: (${starterUrl})"`, {
153 cwd: rootPath
154 });
155 } catch (_unused) {
156 // Remove git support if intial commit fails
157 report.info(`Initial git commit failed - removing git support\n`);
158 fs.removeSync(sysPath.join(rootPath, `.git`));
159 }
160 });
161
162 return function createInitialGitCommit(_x3, _x4) {
163 return _ref5.apply(this, arguments);
164 };
165}(); // Executes `npm install` or `yarn install` in rootPath.
166
167
168const install =
169/*#__PURE__*/
170function () {
171 var _ref6 = (0, _asyncToGenerator2.default)(function* (rootPath) {
172 const prevDir = process.cwd();
173 report.info(`Installing packages...`);
174 process.chdir(rootPath);
175
176 try {
177 if (yield shouldUseYarn()) {
178 yield fs.remove(`package-lock.json`);
179 yield spawn(`yarnpkg`);
180 } else {
181 yield fs.remove(`yarn.lock`);
182 yield spawn(`npm install`);
183 }
184 } finally {
185 process.chdir(prevDir);
186 }
187 });
188
189 return function install(_x5) {
190 return _ref6.apply(this, arguments);
191 };
192}();
193
194const ignored = path => !/^\.(git|hg)$/.test(sysPath.basename(path)); // Copy starter from file system.
195
196
197const copy =
198/*#__PURE__*/
199function () {
200 var _ref7 = (0, _asyncToGenerator2.default)(function* (starterPath, rootPath) {
201 // Chmod with 755.
202 // 493 = parseInt('755', 8)
203 yield fs.mkdirp(rootPath, {
204 mode: 493
205 });
206
207 if (!existsSync(starterPath)) {
208 throw new Error(`starter ${starterPath} doesn't exist`);
209 }
210
211 if (starterPath === `.`) {
212 throw new Error(`You can't create a starter from the existing directory. If you want to
213 create a new site in the current directory, the trailing dot isn't
214 necessary. If you want to create a new site from a local starter, run
215 something like "gatsby new new-gatsby-site ../my-gatsby-starter"`);
216 }
217
218 report.info(`Creating new site from local starter: ${starterPath}`);
219 report.log(`Copying local starter to ${rootPath} ...`);
220 yield fs.copy(starterPath, rootPath, {
221 filter: ignored
222 });
223 report.success(`Created starter directory layout`);
224 yield install(rootPath);
225 return true;
226 });
227
228 return function copy(_x6, _x7) {
229 return _ref7.apply(this, arguments);
230 };
231}(); // Clones starter from URI.
232
233
234const clone =
235/*#__PURE__*/
236function () {
237 var _ref8 = (0, _asyncToGenerator2.default)(function* (hostInfo, rootPath) {
238 let url; // Let people use private repos accessed over SSH.
239
240 if (hostInfo.getDefaultRepresentation() === `sshurl`) {
241 url = hostInfo.ssh({
242 noCommittish: true
243 }); // Otherwise default to normal git syntax.
244 } else {
245 url = hostInfo.https({
246 noCommittish: true,
247 noGitPlus: true
248 });
249 }
250
251 const branch = hostInfo.committish ? [`-b`, hostInfo.committish] : [];
252 report.info(`Creating new site from git: ${url}`);
253 const args = [`clone`, ...branch, url, rootPath, `--single-branch`].filter(arg => Boolean(arg));
254 yield spawnWithArgs(`git`, args);
255 report.success(`Created starter directory layout`);
256 yield fs.remove(sysPath.join(rootPath, `.git`));
257 yield install(rootPath);
258 const isGit = yield isAlreadyGitRepository();
259 if (!isGit) yield gitInit(rootPath);
260 yield maybeCreateGitIgnore(rootPath);
261 if (!isGit) yield createInitialGitCommit(rootPath, url);
262 });
263
264 return function clone(_x8, _x9) {
265 return _ref8.apply(this, arguments);
266 };
267}();
268
269const getPaths =
270/*#__PURE__*/
271function () {
272 var _ref9 = (0, _asyncToGenerator2.default)(function* (starterPath, rootPath) {
273 let selectedOtherStarter = false; // if no args are passed, prompt user for path and starter
274
275 if (!starterPath && !rootPath) {
276 const response = yield prompts.prompt([{
277 type: `text`,
278 name: `path`,
279 message: `What is your project called?`,
280 initial: `my-gatsby-project`
281 }, {
282 type: `select`,
283 name: `starter`,
284 message: `What starter would you like to use?`,
285 choices: [{
286 title: `gatsby-starter-default`,
287 value: `gatsby-starter-default`
288 }, {
289 title: `gatsby-starter-hello-world`,
290 value: `gatsby-starter-hello-world`
291 }, {
292 title: `gatsby-starter-blog`,
293 value: `gatsby-starter-blog`
294 }, {
295 title: `(Use a different starter)`,
296 value: `different`
297 }],
298 initial: 0
299 }]); // exit gracefully if responses aren't provided
300
301 if (!response.starter || !response.path.trim()) {
302 throw new Error(`Please mention both starter package and project name along with path(if its not in the root)`);
303 }
304
305 selectedOtherStarter = response.starter === `different`;
306 starterPath = `gatsbyjs/${response.starter}`;
307 rootPath = response.path;
308 } // set defaults if no root or starter has been set yet
309
310
311 rootPath = rootPath || process.cwd();
312 starterPath = starterPath || `gatsbyjs/gatsby-starter-default`;
313 return {
314 starterPath,
315 rootPath,
316 selectedOtherStarter
317 };
318 });
319
320 return function getPaths(_x10, _x11) {
321 return _ref9.apply(this, arguments);
322 };
323}();
324
325const successMessage = path => {
326 report.info(`
327Your new Gatsby site has been successfully bootstrapped. Start developing it by running:
328
329 cd ${path}
330 gatsby develop
331`);
332};
333/**
334 * Main function that clones or copies the starter.
335 */
336
337
338module.exports =
339/*#__PURE__*/
340function () {
341 var _ref10 = (0, _asyncToGenerator2.default)(function* (starter, options = {}) {
342 const _ref11 = yield getPaths(starter, options.rootPath),
343 starterPath = _ref11.starterPath,
344 rootPath = _ref11.rootPath,
345 selectedOtherStarter = _ref11.selectedOtherStarter;
346
347 const urlObject = url.parse(rootPath);
348
349 if (selectedOtherStarter) {
350 report.info(`Opening the starter library at https://gatsby.dev/starters?v=2...\nThe starter library has a variety of options for starters you can browse\n\nYou can then use the gatsby new command with the link to a repository of a starter you'd like to use, for example:\ngatsby new ${rootPath} https://github.com/gatsbyjs/gatsby-starter-default`);
351 opn(`https://gatsby.dev/starters?v=2`);
352 return;
353 }
354
355 if (urlObject.protocol && urlObject.host) {
356 trackError(`NEW_PROJECT_NAME_MISSING`);
357 const isStarterAUrl = starter && !url.parse(starter).hostname && !url.parse(starter).protocol;
358
359 if (/gatsby-starter/gi.test(rootPath) && isStarterAUrl) {
360 report.panic({
361 id: `11610`,
362 context: {
363 starter,
364 rootPath
365 }
366 });
367 return;
368 }
369
370 report.panic({
371 id: `11611`,
372 context: {
373 rootPath
374 }
375 });
376 return;
377 }
378
379 if (!isValid(rootPath)) {
380 report.panic({
381 id: `11612`,
382 context: {
383 path: sysPath.resolve(rootPath)
384 }
385 });
386 return;
387 }
388
389 if (existsSync(sysPath.join(rootPath, `package.json`))) {
390 trackError(`NEW_PROJECT_IS_NPM_PROJECT`);
391 report.panic({
392 id: `11613`,
393 context: {
394 rootPath
395 }
396 });
397 return;
398 }
399
400 const hostedInfo = hostedGitInfo.fromUrl(starterPath);
401 trackCli(`NEW_PROJECT`, {
402 starterName: hostedInfo ? hostedInfo.shortcut() : `local:starter`
403 });
404 if (hostedInfo) yield clone(hostedInfo, rootPath);else yield copy(starterPath, rootPath);
405 successMessage(rootPath);
406 trackCli(`NEW_PROJECT_END`);
407 });
408
409 return function (_x12) {
410 return _ref10.apply(this, arguments);
411 };
412}();
\No newline at end of file