Skip to content

Commit

Permalink
(config)[Feature]: Add the possibility to set the shorthandResolver f…
Browse files Browse the repository at this point in the history
…alsy.
  • Loading branch information
Thomas Lacroix committed Nov 6, 2015
1 parent e13f957 commit 3050f88
Showing 1 changed file with 137 additions and 138 deletions.
275 changes: 137 additions & 138 deletions lib/core/resolverFactory.js
Expand Up @@ -8,156 +8,155 @@ var createError = require('../util/createError');
var pluginResolverFactory = require('./resolvers/pluginResolverFactory');

function createInstance(decEndpoint, options, registryClient) {
decEndpoint = mout.object.pick(decEndpoint, ['name', 'target', 'source']);
decEndpoint = mout.object.pick(decEndpoint, ['name', 'target', 'source']);

options.version = require('../../package.json').version;
options.version = require('../../package.json').version;

return getConstructor(decEndpoint, options, registryClient)
.spread(function(ConcreteResolver, decEndpoint) {
return new ConcreteResolver(decEndpoint, options.config, options.logger);
return getConstructor(decEndpoint, options, registryClient)
.spread(function (ConcreteResolver, decEndpoint) {
return new ConcreteResolver(decEndpoint, options.config, options.logger);
});
}

function getConstructor(decEndpoint, options, registryClient) {
var source = decEndpoint.source;
var config = options.config;

// Below we try a series of async tests to guess the type of resolver to use
// If a step was unable to guess the resolver, it returns undefined
// If a step can guess the resolver, it returns with construcotor of resolver

var promise = Q.resolve();

var addResolver = function(resolverFactory) {
promise = promise.then(function(result) {
if (result === undefined) {
return resolverFactory(decEndpoint, options);
} else {
return result;
}
});
};

// Plugin resolvers.
//
// It requires each resolver defined in config.resolvers and calls
// its "match" to check if given resolves supports given decEndpoint
addResolver(function() {
var selectedResolver;
var resolverNames;

if (Array.isArray(config.resolvers)) {
resolverNames = config.resolvers;
} else if (!!config.resolvers) {
resolverNames = config.resolvers.split(',');
} else {
resolverNames = [];
}

var resolverPromises = resolverNames.map(function(resolverName) {
var resolver = resolvers[resolverName]
|| pluginResolverFactory(require(resolverName), options);

return function() {
if (selectedResolver === undefined) {
var match = resolver.match.bind(resolver);

return Q.fcall(match, source).then(function(result) {
if (result) {
return selectedResolver = resolver;
var source = decEndpoint.source;
var config = options.config;

// Below we try a series of async tests to guess the type of resolver to use
// If a step was unable to guess the resolver, it returns undefined
// If a step can guess the resolver, it returns with construcotor of resolver

var promise = Q.resolve();

var addResolver = function (resolverFactory) {
promise = promise.then(function (result) {
if (result === undefined) {
return resolverFactory(decEndpoint, options);
} else {
return result;
}
});
});
};

// Plugin resolvers.
//
// It requires each resolver defined in config.resolvers and calls
// its "match" to check if given resolves supports given decEndpoint
addResolver(function () {
var selectedResolver;
var resolverNames;

if (Array.isArray(config.resolvers)) {
resolverNames = config.resolvers;
} else if (!!config.resolvers) {
resolverNames = config.resolvers.split(',');
} else {
return selectedResolver;
resolverNames = [];
}
};
});

return resolverPromises.reduce(Q.when, new Q(undefined)).then(function(resolver) {
if (resolver) {
return Q.fcall(resolver.locate.bind(resolver), decEndpoint.source).then(function(result) {
if (result && result !== decEndpoint.source) {
decEndpoint.source = result;
decEndpoint.registry = true;
return getConstructor(decEndpoint, options, registryClient);
} else {
return [resolver, decEndpoint];
}
var resolverPromises = resolverNames.map(function (resolverName) {
var resolver = resolvers[resolverName]
|| pluginResolverFactory(require(resolverName), options);

return function () {
if (selectedResolver === undefined) {
var match = resolver.match.bind(resolver);

return Q.fcall(match, source).then(function (result) {
if (result) {
return selectedResolver = resolver;
}
});
} else {
return selectedResolver;
}
};
});

return resolverPromises.reduce(Q.when, new Q(undefined)).then(function (resolver) {
if (resolver) {
return Q.fcall(resolver.locate.bind(resolver), decEndpoint.source).then(function (result) {
if (result && result !== decEndpoint.source) {
decEndpoint.source = result;
decEndpoint.registry = true;
return getConstructor(decEndpoint, options, registryClient);
} else {
return [resolver, decEndpoint];
}
});
}
});
}
});
});

// Git case: git git+ssh, git+http, git+https
// .git at the end (probably ssh shorthand)
// git@ at the start
addResolver(function() {
if (/^git(\+(ssh|https?))?:\/\//i.test(source) || /\.git\/?$/i.test(source) || /^git@/i.test(source)) {
decEndpoint.source = source.replace(/^git\+/, '');

// If it's a GitHub repository, return the specialized resolver
if (resolvers.GitHub.getOrgRepoPair(source)) {
return [resolvers.GitHub, decEndpoint];
}

return [resolvers.GitRemote, decEndpoint];
}
});

// SVN case: svn, svn+ssh, svn+http, svn+https, svn+file
addResolver(function() {
if (/^svn(\+(ssh|https?|file))?:\/\//i.test(source)) {
return [resolvers.Svn, decEndpoint];
}
});

// URL case
addResolver(function() {
if (/^https?:\/\//i.exec(source)) {
return [resolvers.Url, decEndpoint];
}
});

// If source is ./ or ../ or an absolute path

addResolver(function() {
var absolutePath = path.resolve(config.cwd, source);

if (/^\.\.?[\/\\]/.test(source) || /^~\//.test(source) ||
path.normalize(source).replace(/[\/\\]+$/, '') === absolutePath
) {
return Q.nfcall(fs.stat, path.join(absolutePath, '.git'))
.then(function(stats) {
decEndpoint.source = absolutePath;

if (stats.isDirectory()) {
return Q.resolve([resolvers.GitFs, decEndpoint]);
}

throw new Error('Not a Git repository');
})

// Git case: git git+ssh, git+http, git+https
// .git at the end (probably ssh shorthand)
// git@ at the start
addResolver(function() {
if (/^git(\+(ssh|https?))?:\/\//i.test(source) || /\.git\/?$/i.test(source) || /^git@/i.test(source)) {
decEndpoint.source = source.replace(/^git\+/, '');

// If it's a GitHub repository, return the specialized resolver
if (resolvers.GitHub.getOrgRepoPair(source)) {
return [resolvers.GitHub, decEndpoint];
}

return [resolvers.GitRemote, decEndpoint];
}
});

// SVN case: svn, svn+ssh, svn+http, svn+https, svn+file
addResolver(function () {
if (/^svn(\+(ssh|https?|file))?:\/\//i.test(source)) {
return [resolvers.Svn, decEndpoint];
}
});

// URL case
addResolver(function () {
if (/^https?:\/\//i.exec(source)) {
return [resolvers.Url, decEndpoint];
}
});


// If source is ./ or ../ or an absolute path

addResolver(function () {
var absolutePath = path.resolve(config.cwd, source);

if (/^\.\.?[\/\\]/.test(source) || /^~\//.test(source) ||
path.normalize(source).replace(/[\/\\]+$/, '') === absolutePath
) {
return Q.nfcall(fs.stat, path.join(absolutePath, '.git'))
.then(function (stats) {
decEndpoint.source = absolutePath;

if (stats.isDirectory()) {
return Q.resolve([resolvers.GitFs, decEndpoint]);
}

throw new Error('Not a Git repository');
})
// If not, check if source is a valid Subversion repository
.fail(function() {
return Q.nfcall(fs.stat, path.join(absolutePath, '.svn'))
.then(function(stats) {
decEndpoint.source = absolutePath;
.fail(function () {
return Q.nfcall(fs.stat, path.join(absolutePath, '.svn'))
.then(function (stats) {
decEndpoint.source = absolutePath;

if (stats.isDirectory()) {
return Q.resolve([resolvers.Svn, decEndpoint]);
}
if (stats.isDirectory()) {
return Q.resolve([resolvers.Svn, decEndpoint]);
}

throw new Error('Not a Subversion repository');
throw new Error('Not a Subversion repository');
});
})

// If not, check if source is a valid file/folder
.fail(function() {
return Q.nfcall(fs.stat, absolutePath)
.then(function() {
decEndpoint.source = absolutePath;
.fail(function () {
return Q.nfcall(fs.stat, absolutePath)
.then(function () {
decEndpoint.source = absolutePath;

return Q.resolve([resolvers.Fs, decEndpoint]);
return Q.resolve([resolvers.Fs, decEndpoint]);
});
});
}
Expand Down Expand Up @@ -211,19 +210,19 @@ function getConstructor(decEndpoint, options, registryClient) {

return getConstructor(decEndpoint, options);
});
});
});

addResolver(function() {
throw createError('Could not find appropriate resolver for ' + source, 'ENORESOLVER');
});
addResolver(function () {
throw createError('Could not find appropriate resolver for ' + source, 'ENORESOLVER');
});

return promise;
return promise;
}

function clearRuntimeCache() {
mout.object.values(resolvers).forEach(function(ConcreteResolver) {
ConcreteResolver.clearRuntimeCache();
});
mout.object.values(resolvers).forEach(function (ConcreteResolver) {
ConcreteResolver.clearRuntimeCache();
});
}

module.exports = createInstance;
Expand Down

0 comments on commit 3050f88

Please sign in to comment.