@pnpm/git-resolver
Version:
Resolver for git-hosted packages
111 lines • 4.21 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const graceful_git_1 = __importDefault(require("graceful-git"));
const semver_1 = __importDefault(require("semver"));
const parsePref_1 = __importDefault(require("./parsePref"));
function default_1(opts) {
return async function resolveGit(wantedDependency) {
const parsedSpec = await (0, parsePref_1.default)(wantedDependency.pref);
if (parsedSpec == null)
return null;
const pref = parsedSpec.gitCommittish == null || parsedSpec.gitCommittish === ''
? 'HEAD'
: parsedSpec.gitCommittish;
const commit = await resolveRef(parsedSpec.fetchSpec, pref, parsedSpec.gitRange);
let resolution;
if ((parsedSpec.hosted != null) && !isSsh(parsedSpec.fetchSpec)) {
// don't use tarball for ssh url, they are likely private repo
const hosted = parsedSpec.hosted;
// use resolved committish
hosted.committish = commit;
const tarball = hosted.tarball?.();
if (tarball) {
resolution = { tarball };
}
}
if (resolution == null) {
resolution = {
commit,
repo: parsedSpec.fetchSpec,
type: 'git',
};
}
return {
id: parsedSpec.fetchSpec
.replace(/^.*:\/\/(git@)?/, '')
.replace(/:/g, '+')
.replace(/\.git$/, '') + '/' + commit,
normalizedPref: parsedSpec.normalizedPref,
resolution,
resolvedVia: 'git-repository',
};
};
}
exports.default = default_1;
function resolveVTags(vTags, range) {
return semver_1.default.maxSatisfying(vTags, range, true);
}
async function getRepoRefs(repo, ref) {
const gitArgs = [repo];
if (ref !== 'HEAD') {
gitArgs.unshift('--refs');
}
if (ref) {
gitArgs.push(ref);
}
// graceful-git by default retries 10 times, reduce to single retry
const result = await (0, graceful_git_1.default)(['ls-remote', ...gitArgs], { retries: 1 });
const refs = result.stdout.split('\n').reduce((obj, line) => {
const [commit, refName] = line.split('\t');
obj[refName] = commit;
return obj;
}, {});
return refs;
}
async function resolveRef(repo, ref, range) {
if (ref.match(/^[0-9a-f]{7,40}$/) != null) {
return ref;
}
const refs = await getRepoRefs(repo, range ? null : ref);
return resolveRefFromRefs(refs, repo, ref, range);
}
function resolveRefFromRefs(refs, repo, ref, range) {
if (!range) {
const commitId = refs[ref] ||
refs[`refs/${ref}`] ||
refs[`refs/tags/${ref}^{}`] || // prefer annotated tags
refs[`refs/tags/${ref}`] ||
refs[`refs/heads/${ref}`];
if (!commitId) {
throw new Error(`Could not resolve ${ref} to a commit of ${repo}.`);
}
return commitId;
}
else {
const vTags = Object.keys(refs)
// using the same semantics of version tags as https://github.com/zkat/pacote
.filter((key) => /^refs\/tags\/v?(\d+\.\d+\.\d+(?:[-+].+)?)(\^{})?$/.test(key))
.map((key) => {
return key
.replace(/^refs\/tags\//, '')
.replace(/\^{}$/, ''); // accept annotated tags
})
.filter((key) => semver_1.default.valid(key, true));
const refVTag = resolveVTags(vTags, range);
const commitId = refVTag &&
(refs[`refs/tags/${refVTag}^{}`] || // prefer annotated tags
refs[`refs/tags/${refVTag}`]);
if (!commitId) {
throw new Error(`Could not resolve ${range} to a commit of ${repo}. Available versions are: ${vTags.join(', ')}`);
}
return commitId;
}
}
function isSsh(gitSpec) {
return gitSpec.slice(0, 10) === 'git+ssh://' ||
gitSpec.slice(0, 4) === 'git@';
}
//# sourceMappingURL=index.js.map