renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
179 lines (178 loc) • 5.79 kB
JavaScript
import { logger } from "../../../logger/index.js";
import { localPathIsSymbolicLink, readLocalSymlink } from "../../../util/fs/index.js";
import { map } from "../../../util/promises.js";
import { exec } from "../../../util/exec/index.js";
import { getRepoStatus } from "../../../util/git/index.js";
import { quote } from "shlex";
import upath from "upath";
//#region lib/modules/manager/hermit/artifacts.ts
/**
* updateArtifacts runs hermit install for each updated dependencies
*/
async function updateArtifacts(update) {
const { packageFileName } = update;
try {
await updateHermitPackage(update);
} catch (err) {
const execErr = err;
logger.debug({ err }, `error updating hermit packages.`);
return [{ artifactError: {
fileName: `from: ${execErr.from}, to: ${execErr.to}`,
stderr: execErr.stderr
} }];
}
logger.debug(`scanning the changes after update`);
let updateResult = null;
try {
updateResult = await getUpdateResult(packageFileName);
logger.debug({ updateResult }, `update result for hermit`);
} catch (err) {
logger.debug({ err }, "Error getting hermet update results");
return [{ artifactError: { stderr: err.message } }];
}
return updateResult;
}
/**
* getContent returns the content of either link or a normal file
*/
async function getContent(file) {
let contents = "";
const isSymlink = await localPathIsSymbolicLink(file);
if (isSymlink) contents = await readLocalSymlink(file);
if (contents === null) throw new Error(`error getting content for ${file}`);
return {
isSymlink,
contents
};
}
/**
* getAddResult returns the UpdateArtifactsResult for the added files
*/
function getAddResult(path, contentRes) {
return { file: {
type: "addition",
path,
contents: contentRes.contents,
isSymlink: contentRes.isSymlink,
isExecutable: contentRes.isExecutable
} };
}
/**
* getDeleteResult returns the UpdateArtifactsResult for deleted files
*/
function getDeleteResult(path) {
return { file: {
type: "deletion",
path
} };
}
/**
* getUpdateResult will return the update result after `hermit install`
* has been performed for all packages
*/
async function getUpdateResult(packageFileName) {
const hermitFolder = `${upath.dirname(packageFileName)}/`;
const hermitChanges = await getRepoStatus(hermitFolder);
logger.debug({
hermitChanges,
hermitFolder
}, `hermit changes after package update`);
const added = await map([...hermitChanges.created, ...hermitChanges.not_added], async (path) => {
return getAddResult(path, await getContent(path));
});
const deleted = hermitChanges.deleted.map(getDeleteResult);
const modified = await map(hermitChanges.modified, async (path) => {
const contents = await getContent(path);
return [getDeleteResult(path), getAddResult(path, contents)];
});
return [
...(await map(hermitChanges.renamed, async (renamed) => {
const from = renamed.from;
const to = renamed.to;
const toContents = await getContent(to);
return [getDeleteResult(from), getAddResult(to, toContents)];
})).flat(),
...modified.flat(),
...added,
...deleted
];
}
/**
* getHermitPackage returns the hermit package for running the hermit install
*/
function getHermitPackage(name, version) {
return `${name}-${version}`;
}
/**
* updateHermitPackage runs hermit install for the given package
*/
async function updateHermitPackage(update) {
logger.trace({ update }, `hermit.updateHermitPackage()`);
const toInstall = [];
const from = [];
const toUninstall = [];
for (const pkg of update.updatedDeps) {
if (!pkg.depName || !pkg.currentVersion || !pkg.newValue) {
logger.debug({
depName: pkg.depName,
currentVersion: pkg.currentVersion,
newValue: pkg.newValue
}, "missing package update information");
throw new UpdateHermitError(getHermitPackage(pkg.depName ?? "", pkg.currentVersion ?? ""), getHermitPackage(pkg.depName ?? "", pkg.newValue ?? ""), "invalid package to update");
}
const depName = pkg.depName;
const newName = pkg.newName;
const currentVersion = pkg.currentVersion;
const newValue = pkg.newValue;
const fromPackage = getHermitPackage(depName, currentVersion);
const toPackage = getHermitPackage(newName ?? depName, newValue);
toInstall.push(toPackage);
from.push(fromPackage);
if (pkg.updateType === "replacement" && newName !== depName) toUninstall.push(depName);
}
const execOptions = {
docker: {},
cwdFile: update.packageFileName
};
const fromPackages = from.map(quote).join(" ");
if (toUninstall.length > 0) {
const packagesToUninstall = toUninstall.map(quote).join(" ");
const uninstallCommands = `./hermit uninstall ${packagesToUninstall}`;
try {
const result = await exec(uninstallCommands, execOptions);
logger.trace({ stdout: result.stdout }, `hermit uninstall command stdout`);
} catch (e) {
logger.warn({ err: e }, `error uninstall hermit package for replacement`);
throw new UpdateHermitError(fromPackages, packagesToUninstall, e.stderr, e.stdout);
}
}
const packagesToInstall = toInstall.map(quote).join(" ");
const execCommands = `./hermit install ${packagesToInstall}`;
logger.debug({
packageFile: update.packageFileName,
packagesToInstall
}, `performing updates`);
try {
const result = await exec(execCommands, execOptions);
logger.trace({ stdout: result.stdout }, `hermit command stdout`);
} catch (e) {
logger.warn({ err: e }, `error updating hermit package`);
throw new UpdateHermitError(fromPackages, packagesToInstall, e.stderr, e.stdout);
}
}
var UpdateHermitError = class extends Error {
stdout;
stderr;
from;
to;
constructor(from, to, stderr, stdout = "") {
super();
this.stdout = stdout;
this.stderr = stderr;
this.from = from;
this.to = to;
}
};
//#endregion
export { updateArtifacts };
//# sourceMappingURL=artifacts.js.map