@lerna/publish
Version:
Publish packages in the current project
227 lines (225 loc) • 9.01 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var import_core = require("@lerna/core");
var import_dedent = __toESM(require("dedent"));
var import_fs_extra = __toESM(require("fs-extra"));
var import_p_map_series = __toESM(require("p-map-series"));
var import_path = __toESM(require("path"));
const childProcess = require("@lerna/child-process");
module.exports = function factory(argv) {
return new ImportCommand(argv);
};
class ImportCommand extends import_core.Command {
gitParamsForTargetCommits() {
const params = ["log", "--format=%h"];
if (this.options.flatten) {
params.push("--first-parent");
}
return params;
}
initialize() {
const inputPath = this.options.dir;
const externalRepoPath = import_path.default.resolve(inputPath);
const externalRepoBase = import_path.default.basename(externalRepoPath);
this.externalExecOpts = Object.assign({}, this.execOpts, {
cwd: externalRepoPath
});
let stats;
try {
stats = import_fs_extra.default.statSync(externalRepoPath);
} catch (e) {
if (e.code === "ENOENT") {
throw new import_core.ValidationError("ENOENT", `No repository found at "${inputPath}"`);
}
throw e;
}
if (!stats.isDirectory()) {
throw new import_core.ValidationError("ENODIR", `Input path "${inputPath}" is not a directory`);
}
const packageJson = import_path.default.join(externalRepoPath, "package.json");
const packageName = require(packageJson).name;
if (!packageName) {
throw new import_core.ValidationError("ENOPKG", `No package name specified in "${packageJson}"`);
}
const targetBase = this.getTargetBase();
if (this.getPackageDirectories().indexOf(targetBase) === -1) {
throw new import_core.ValidationError(
"EDESTDIR",
`--dest does not match with the package directories: ${this.getPackageDirectories()}`
);
}
const targetDir = import_path.default.join(targetBase, externalRepoBase);
const gitRepoRoot = this.getWorkspaceRoot();
const lernaRootRelativeToGitRoot = import_path.default.relative(gitRepoRoot, this.project.rootPath);
this.targetDirRelativeToGitRoot = import_path.default.join(lernaRootRelativeToGitRoot, targetDir);
if (import_fs_extra.default.existsSync(import_path.default.resolve(this.project.rootPath, targetDir))) {
throw new import_core.ValidationError("EEXISTS", `Target directory already exists "${targetDir}"`);
}
this.commits = this.externalExecSync("git", this.gitParamsForTargetCommits()).split("\n").reverse();
if (!this.commits.length) {
throw new import_core.ValidationError("NOCOMMITS", `No git commits to import at "${inputPath}"`);
}
if (this.options.preserveCommit) {
this.origGitEmail = this.execSync("git", ["config", "user.email"]);
this.origGitName = this.execSync("git", ["config", "user.name"]);
}
this.preImportHead = this.getCurrentSHA();
if (this.execSync("git", ["diff-index", "HEAD"])) {
throw new import_core.ValidationError("ECHANGES", "Local repository has un-committed changes");
}
this.logger.info(
"",
`About to import ${this.commits.length} commits from ${inputPath} into ${targetDir}`
);
if (this.options.yes) {
return true;
}
return (0, import_core.promptConfirmation)("Are you sure you want to import these commits onto the current branch?");
}
getPackageDirectories() {
return this.project.packageConfigs.filter((p) => p.endsWith("*")).map((p) => import_path.default.dirname(p));
}
getTargetBase() {
if (this.options.dest) {
return this.options.dest;
}
return this.getPackageDirectories().shift() || "packages";
}
getCurrentSHA() {
return this.execSync("git", ["rev-parse", "HEAD"]);
}
getWorkspaceRoot() {
return this.execSync("git", ["rev-parse", "--show-toplevel"]);
}
execSync(cmd, args) {
return childProcess.execSync(cmd, args, this.execOpts);
}
externalExecSync(cmd, args) {
return childProcess.execSync(cmd, args, this.externalExecOpts);
}
createPatchForCommit(sha) {
let patch = null;
if (this.options.flatten) {
const diff = this.externalExecSync("git", [
"log",
"--reverse",
"--first-parent",
"-p",
"-m",
"--pretty=email",
"--stat",
"--binary",
"-1",
"--color=never",
sha,
// custom git prefixes for accurate parsing of filepaths (#1655)
`--src-prefix=COMPARE_A/`,
`--dst-prefix=COMPARE_B/`
]);
const version = this.externalExecSync("git", ["--version"]).replace(/git version /g, "");
patch = `${diff}
--
${version}`;
} else {
patch = this.externalExecSync("git", [
"format-patch",
"-1",
sha,
"--stdout",
// custom git prefixes for accurate parsing of filepaths (#1655)
`--src-prefix=COMPARE_A/`,
`--dst-prefix=COMPARE_B/`
]);
}
const formattedTarget = this.targetDirRelativeToGitRoot.replace(/\\/g, "/");
const replacement = `$1/${formattedTarget}`;
return patch.replace(/^([-+]{3} "?COMPARE_[AB])/gm, replacement).replace(/^(diff --git "?COMPARE_A)/gm, replacement).replace(/^(diff --git (?! "?COMPARE_B\/).+ "?COMPARE_B)/gm, replacement).replace(/^(copy (from|to)) ("?)/gm, `$1 $3${formattedTarget}/`).replace(/^(rename (from|to)) ("?)/gm, `$1 $3${formattedTarget}/`);
}
getGitUserFromSha(sha) {
return {
email: this.externalExecSync("git", ["show", "-s", "--format='%ae'", sha]),
name: this.externalExecSync("git", ["show", "-s", "--format='%an'", sha])
};
}
configureGitUser({ email, name }) {
this.execSync("git", ["config", "user.email", `"${email}"`]);
this.execSync("git", ["config", "user.name", `"${name}"`]);
}
execute() {
this.enableProgressBar();
const tracker = this.logger.newItem("execute");
const mapper = (sha) => {
tracker.info(sha);
const patch = this.createPatchForCommit(sha);
const procArgs = ["am", "-3", "--keep-non-patch"];
if (this.options.preserveCommit) {
this.configureGitUser(this.getGitUserFromSha(sha));
procArgs.push("--committer-date-is-author-date");
}
const proc = childProcess.exec("git", procArgs, this.execOpts);
proc.stdin.end(patch);
return (0, import_core.pulseTillDone)(proc).then(() => {
tracker.completeWork(1);
}).catch((err) => {
const diff = this.externalExecSync("git", ["diff", "-s", `${sha}^!`]).trim();
if (diff === "") {
tracker.completeWork(1);
return childProcess.exec("git", ["am", "--skip"], this.execOpts);
}
err.sha = sha;
throw err;
});
};
tracker.addWork(this.commits.length);
return (0, import_p_map_series.default)(this.commits, mapper).then(() => {
tracker.finish();
if (this.options.preserveCommit) {
this.configureGitUser({
email: this.origGitEmail,
name: this.origGitName
});
}
this.logger.success("import", "finished");
}).catch((err) => {
tracker.finish();
if (this.options.preserveCommit) {
this.configureGitUser({
email: this.origGitEmail,
name: this.origGitName
});
}
this.logger.error("import", `Rolling back to previous HEAD (commit ${this.preImportHead})`);
this.execSync("git", ["am", "--abort"]);
this.execSync("git", ["reset", "--hard", this.preImportHead]);
throw new import_core.ValidationError(
"EIMPORT",
import_dedent.default`
Failed to apply commit ${err.sha}.
${err.message}
You may try again with --flatten to import flat history.
`
);
});
}
}
module.exports.ImportCommand = ImportCommand;