Skip to content

Commit 37f975a

Browse files
Timergaearon
authored andcommitted
Properly extract package name
1 parent 2f7e3a2 commit 37f975a

File tree

2 files changed

+54
-16
lines changed

2 files changed

+54
-16
lines changed

packages/create-react-app/index.js

+52-16
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ var execSync = require('child_process').execSync;
6060
var spawn = require('cross-spawn');
6161
var semver = require('semver');
6262
var dns = require('dns');
63+
var tmp = require('tmp');
64+
var unpack = require('tar-pack').unpack;
6365

6466
var projectName;
6567

@@ -201,20 +203,25 @@ function install(useYarn, dependencies, verbose, isOnline) {
201203

202204
function run(root, appName, version, verbose, originalDirectory, template) {
203205
var packageToInstall = getInstallPackage(version);
204-
var packageName = getPackageName(packageToInstall);
206+
var packageName = packageToInstall;
205207

206208
var allDependencies = ['react', 'react-dom', packageToInstall];
207209

208210
console.log('Installing packages. This might take a couple minutes.');
209-
console.log(
210-
'Installing ' + chalk.cyan('react') + ', ' + chalk.cyan('react-dom') +
211-
', and ' + chalk.cyan(packageName) + '...'
212-
);
213-
console.log();
214-
211+
215212
var useYarn = shouldUseYarn();
216-
checkIfOnline(useYarn)
213+
getPackageName(packageToInstall)
214+
.then(function(_packageName) {
215+
packageName = _packageName;
216+
return checkIfOnline(useYarn);
217+
})
217218
.then(function(isOnline) {
219+
console.log(
220+
'Installing ' + chalk.cyan('react') + ', ' + chalk.cyan('react-dom') +
221+
', and ' + chalk.cyan(packageName) + '...'
222+
);
223+
console.log();
224+
218225
return install(useYarn, allDependencies, verbose, isOnline);
219226
})
220227
.then(function() {
@@ -288,19 +295,48 @@ function getInstallPackage(version) {
288295
// Extract package name from tarball url or path.
289296
function getPackageName(installPackage) {
290297
if (installPackage.indexOf('.tgz') > -1) {
291-
// The package name could be with or without semver version, e.g. react-scripts-0.2.0-alpha.1.tgz
292-
// However, this function returns package name only without semver version.
293-
return installPackage.match(/^.+\/(.+?)(?:-\d+.+)?\.tgz$/)[1];
298+
return new Promise(function(resolve, reject) {
299+
tmp.dir({ unsafeCleanup: true }, function(err, tmpdir, callback) {
300+
if (err) {
301+
reject(err);
302+
} else {
303+
resolve({
304+
tmpdir: tmpdir,
305+
callback: callback
306+
});
307+
}
308+
});
309+
}).then(function(obj) {
310+
return new Promise(function(resolve, reject) {
311+
fs.createReadStream(installPackage).pipe(unpack(obj.tmpdir, function(err) {
312+
if (err) {
313+
reject(err);
314+
} else {
315+
var packageName = require(path.join(obj.tmpdir, 'package.json')).name;
316+
try {
317+
obj.callback();
318+
} catch (ignored) {}
319+
resolve(packageName);
320+
}
321+
}));
322+
});
323+
}).catch(function(err) {
324+
// The package name could be with or without semver version, e.g. react-scripts-0.2.0-alpha.1.tgz
325+
// However, this function returns package name only without semver version.
326+
console.log('Failed to extract package: ' + err.message);
327+
console.log('Falling back to naive behavior ...')
328+
return Promise.resolve(installPackage.match(/^.+\/(.+?)(?:-\d+.+)?\.tgz$/)[1]);
329+
});
294330
} else if (installPackage.indexOf('git+') === 0) {
295331
// Pull package name out of git urls e.g:
296332
// git+https://github.com/mycompany/react-scripts.git
297333
// git+ssh://github.com/mycompany/react-scripts.git#v1.2.3
298-
return installPackage.match(/([^\/]+)\.git(#.*)?$/)[1];
334+
return Promise.resolve(installPackage.match(/([^\/]+)\.git(#.*)?$/)[1]);
299335
} else if (installPackage.indexOf('@') > 0) {
300336
// Do not match @scope/ when stripping off @version or @tag
301-
return installPackage.charAt(0) + installPackage.substr(1).split('@')[0];
337+
return Promise.resolve(installPackage.charAt(0) + installPackage.substr(1).split('@')[0]);
302338
}
303-
return installPackage;
339+
return Promise.resolve(installPackage);
304340
}
305341

306342
function checkNpmVersion() {
@@ -356,7 +392,7 @@ function checkAppName(appName) {
356392
printValidationResults(validationResult.warnings);
357393
process.exit(1);
358394
}
359-
395+
360396
// TODO: there should be a single place that holds the dependencies
361397
var dependencies = ['react', 'react-dom'];
362398
var devDependencies = ['react-scripts'];
@@ -449,7 +485,7 @@ function checkIfOnline(useYarn) {
449485
// We'll just assume the best case.
450486
return Promise.resolve(true);
451487
}
452-
488+
453489
return new Promise(function(resolve) {
454490
dns.resolve('registry.yarnpkg.com', function(err) {
455491
resolve(err === null);

packages/create-react-app/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
"cross-spawn": "^4.0.0",
2626
"fs-extra": "^1.0.0",
2727
"semver": "^5.0.3",
28+
"tar-pack": "^3.4.0",
29+
"tmp": "0.0.31",
2830
"validate-npm-package-name": "^3.0.0"
2931
}
3032
}

0 commit comments

Comments
 (0)