2025-05-12 05:38:44 +09:00

117 lines
4.1 KiB
JavaScript

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const is_1 = __importDefault(require("is"));
const path_1 = __importDefault(require("path"));
const crc_1 = __importDefault(require("crc"));
const urijs_1 = __importDefault(require("urijs"));
const path_2 = __importDefault(require("./path"));
const promise_1 = __importDefault(require("./promise"));
const command_1 = __importDefault(require("./command"));
const fs_1 = __importDefault(require("./fs"));
const GIT_PREFIX = "git+";
function Git() {
this.tmpDir;
this.cloned = {};
}
// Return an unique ID for a combinaison host/ref
Git.prototype.repoID = function (host, ref) {
return crc_1.default.crc32(`${host}#${ref || ""}`).toString(16);
};
// Allocate a temporary folder for cloning repos in it
Git.prototype.allocateDir = function () {
const that = this;
if (this.tmpDir)
return (0, promise_1.default)();
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
return fs_1.default.tmpDir().then((dir) => {
that.tmpDir = dir;
});
};
// Clone a git repository if non existant
Git.prototype.clone = function (host, ref) {
const that = this;
return (this.allocateDir()
// Return or clone the git repo
.then(() => {
// Unique ID for repo/ref combinaison
const repoId = that.repoID(host, ref);
// Absolute path to the folder
const repoPath = path_1.default.join(that.tmpDir, repoId);
if (that.cloned[repoId])
return repoPath;
// Clone repo
return (command_1.default
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
.exec(`git clone ${host} ${repoPath}`)
// Checkout reference if specified
.then(() => {
that.cloned[repoId] = true;
if (!ref)
return;
return command_1.default.exec(`git checkout ${ref}`, { cwd: repoPath });
})
.thenResolve(repoPath));
}));
};
// Get file from a git repo
Git.prototype.resolve = function (giturl) {
// Path to a file in a git repo?
if (!Git.isUrl(giturl)) {
if (this.resolveRoot(giturl))
return (0, promise_1.default)(giturl);
return (0, promise_1.default)(null);
}
if (is_1.default.string(giturl))
giturl = Git.parseUrl(giturl);
if (!giturl)
return (0, promise_1.default)(null);
// Clone or get from cache
return this.clone(giturl.host, giturl.ref).then((repo) => {
return path_1.default.resolve(repo, giturl.filepath);
});
};
// Return root of git repo from a filepath
Git.prototype.resolveRoot = function (filepath) {
// No git repo cloned, or file is not in a git repository
if (!this.tmpDir || !path_2.default.isInRoot(this.tmpDir, filepath))
return null;
// Extract first directory (is the repo id)
const relativeToGit = path_1.default.relative(this.tmpDir, filepath);
const repoId = relativeToGit.split(path_1.default.sep)[0];
if (!repoId) {
return;
}
// Return an absolute file
return path_1.default.resolve(this.tmpDir, repoId);
};
// Check if an url is a git dependency url
Git.isUrl = function (giturl) {
return giturl.indexOf(GIT_PREFIX) === 0;
};
// Parse and extract infos
Git.parseUrl = function (giturl) {
if (!Git.isUrl(giturl))
return null;
giturl = giturl.slice(GIT_PREFIX.length);
const uri = new urijs_1.default(giturl);
const ref = uri.fragment() || null;
uri.fragment(null);
// Extract file inside the repo (after the .git)
const fileParts = uri.path().split(".git");
let filepath = fileParts.length > 1 ? fileParts.slice(1).join(".git") : "";
if (filepath[0] == "/") {
filepath = filepath.slice(1);
}
// Recreate pathname without the real filename
uri.path(`${fileParts[0]}.git`);
return {
host: uri.toString(),
ref: ref,
filepath: filepath
};
};
exports.default = Git;