Skip to content

Commit

Permalink
Improve handling of packages without manifest (#3701)
Browse files Browse the repository at this point in the history
- Better guessing of package names
- Support for hosted git, like github or gitlab
- Support for .tar.gz archives
  • Loading branch information
sheerun authored and bestander committed Jun 22, 2017
1 parent 73499a6 commit f404b62
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 10 deletions.
2 changes: 2 additions & 0 deletions __tests__/package-resolver.js
Expand Up @@ -62,6 +62,8 @@ addTest('https://github.com/yarnpkg/yarn/releases/download/v0.18.1/yarn-v0.18.1.
addTest('https://github.com/yarnpkg/e2e-test-repo.git#greenkeeper/cross-env-3.1.4'); // hash with slashes
addTest('https://github.com/bestander/chrome-app-livereload.git'); // no package.json
addTest('livereload@https://github.com/bestander/chrome-app-livereload.git'); // no package.json, named
addTest('bestander/chrome-app-livereload'); // no package.json, github
addTest('livereload@https://github.com/bestander/chrome-app-livereload/archive/0.0.5.tar.gz'); // no package.json, targz
addTest('gitlab:leanlabsio/kanban'); // gitlab
addTest('gist:d59975ac23e26ad4e25b'); // gist url
addTest('bitbucket:hgarcia/node-bitbucket-api'); // bitbucket url
Expand Down
33 changes: 33 additions & 0 deletions __tests__/util/guess-name.js
@@ -0,0 +1,33 @@
/* @flow */

import guessName from '../../src/util/guess-name';

const examples = [
'http://github.com/foo-bar/awesome-name',
'http://github.com/foo-bar/awesome-name.git',
'http://awesome.com/awesome-name.git',
'http://awesome.com/awesome-name.git?foo/bar#fiz/fuz',
'https://github.com/hashicorp/awesome-name/archive/v0.5.5.tar.gz',
'https://gitlab.com/foo/awesome-name/repository/archive.tar.gz?ref=3.11.0',
'https://gitlab.com/foo/awesome-name/repository/archive.tar.bz2?ref=3.11.0',
'https://gitlab.com/foo/awesome-name/repository/archive.tar?ref=3.11.0',
'https://gitlab.com/foo/awesome-name/repository/archive.zip?ref=3.11.0',
'git@gitlab.com:yolo/awesome-name.git',
'https://gitlab.com/yolo/awesome-name.git',
'https://asesome.com/yolo/awesome-name-0.2.3.tar.gz',
'/foo/bar/awesome-name',
'./foo/bar/awesome-name',
'../foo/bar/awesome-name',
'file:../foo/bar/awesome-name',
'file:../foo/bar/awesome-name.tar.gz',
'awesome-name',
'awesome-name.tar.gz',
];

describe('guessName', () => {
for (const source of examples) {
it(`guess name of ${source}`, () => {
expect(guessName(source)).toBe('awesome-name');
});
}
});
10 changes: 2 additions & 8 deletions src/resolvers/exotics/git-resolver.js
Expand Up @@ -5,6 +5,7 @@ import type PackageRequest from '../../package-request.js';
import {hostedGit as hostedGitResolvers} from '../index.js';
import * as util from '../../util/misc.js';
import * as versionUtil from '../../util/version.js';
import guessName from '../../util/guess-name.js';
import {registries} from '../../registries/index.js';
import ExoticResolver from './exotic-resolver.js';
import Git from '../../util/git.js';
Expand Down Expand Up @@ -132,16 +133,9 @@ export default class GitResolver extends ExoticResolver {
}
}

let name = '';

if (parts.path) {
const names = parts.path.split('/');
name = names[names.length - 1].split('.')[0];
}

return {
// This is just the default, it can be overridden with key of dependencies
name,
name: guessName(url),
version: '0.0.0',
_uid: commit,
_remote: {
Expand Down
14 changes: 13 additions & 1 deletion src/resolvers/exotics/hosted-git-resolver.js
Expand Up @@ -8,6 +8,7 @@ import {registries} from '../../registries/index.js';
import GitResolver from './git-resolver.js';
import ExoticResolver from './exotic-resolver.js';
import Git from '../../util/git.js';
import guessName from '../../util/guess-name.js';

export type ExplodedFragment = {
user: string,
Expand Down Expand Up @@ -183,7 +184,18 @@ export default class HostedGitResolver extends ExoticResolver {
}
}

throw new MessageError(this.reporter.lang('couldntFindManifestIn', url));
return {
name: guessName(url),
version: '0.0.0',
_uid: commit,
_remote: {
hash: commit,
resolved: url,
type: 'tarball',
reference: url,
registry: 'npm',
},
};
}

async hasHTTPCapability(url: string): Promise<boolean> {
Expand Down
7 changes: 6 additions & 1 deletion src/resolvers/exotics/tarball-resolver.js
Expand Up @@ -6,6 +6,7 @@ import TarballFetcher from '../../fetchers/tarball-fetcher.js';
import ExoticResolver from './exotic-resolver.js';
import Git from './git-resolver.js';
import {removePrefix} from '../../util/misc.js';
import guessName from '../../util/guess-name.js';
import * as versionUtil from '../../util/version.js';
import * as crypto from '../../util/crypto.js';
import * as fs from '../../util/fs.js';
Expand Down Expand Up @@ -77,7 +78,11 @@ export default class TarballResolver extends ExoticResolver {
);

// fetch file and get it's hash
const fetched: FetchedMetadata = await fetcher.fetch();
const fetched: FetchedMetadata = await fetcher.fetch({
name: guessName(url),
version: '0.0.0',
_registry: 'npm',
});
pkgJson = fetched.package;
hash = fetched.hash;

Expand Down
52 changes: 52 additions & 0 deletions src/util/guess-name.js
@@ -0,0 +1,52 @@
/* @flow */

import url from 'url';

function cleanup(name: string): string {
name = name.replace(/-\d+\.\d+\.\d+/, '');
return name.split('.')[0];
}

function guessNameFallback(source: string): string {
// If cannot parse as url, just return cleaned up last part
const parts = source.split('/');
return cleanup(parts[parts.length - 1]);
}

export default function guessName(source: string): string {
try {
const parsed = url.parse(source);

if (!parsed.pathname) {
return guessNameFallback(source);
}

const parts = parsed.pathname.split('/');

// Priority goes to part that ends with .git
for (const part of parts) {
if (part.match(/\.git$/)) {
return cleanup(part);
}
}

// Most likely a directory
if (parsed.host == null) {
return cleanup(parts[parts.length - 1]);
}

// A site like github or gitlab
if (parts.length > 2) {
return cleanup(parts[2]);
}

// Privately hosted package?
if (parts.length > 1) {
return cleanup(parts[1]);
}

return guessNameFallback(source);
} catch (e) {
return guessNameFallback(source);
}
}

0 comments on commit f404b62

Please sign in to comment.