Skip to content

Commit

Permalink
fix: add replacementName support for hermit (#27573)
Browse files Browse the repository at this point in the history
  • Loading branch information
lyonlai committed Feb 27, 2024
1 parent 6269932 commit 41e8b99
Show file tree
Hide file tree
Showing 3 changed files with 266 additions and 4 deletions.
1 change: 0 additions & 1 deletion docs/usage/configuration-options.md
Expand Up @@ -2995,7 +2995,6 @@ Managers which do not support replacement:
- `git-submodules`
- `gomod`
- `gradle`
- `hermit`
- `homebrew`
- `maven`
- `regex`
Expand Down
234 changes: 233 additions & 1 deletion lib/modules/manager/hermit/artifacts.spec.ts
Expand Up @@ -135,12 +135,244 @@ describe('modules/manager/hermit/artifacts', () => {
]);
});

it('should fail on error getting link content', async () => {
it('should uninstall old package for name replacement', async () => {
lstatsMock.mockResolvedValue(true);

readlinkMock.mockResolvedValue('hermit');
GlobalConfig.set({ localDir: '' });

const execSnapshots = mockExecAll();
getRepoStatusMock.mockResolvedValue(
partial<StatusResult>({
not_added: [],
deleted: [],
modified: ['bin/java', 'bin/javac', 'bin/jar'],
renamed: [
{
from: 'bin/.openjdk-17.0.3',
to: 'bin/.openjdk-17.0.4.1_1',
},
],
created: [],
}),
);

const res = await updateArtifacts(
partial<UpdateArtifact>({
updatedDeps: [
{
depName: 'openjdk',
newName: 'openjre',
currentVersion: '17.0.3',
newValue: '17.0.4.1_1',
updateType: 'replacement',
},
],
packageFileName: 'go/bin/hermit',
}),
);

expect(execSnapshots).toMatchObject([
{ cmd: './hermit uninstall openjdk' },
{ cmd: './hermit install openjre-17.0.4.1_1' },
]);

expect(res).toStrictEqual([
{
file: {
path: 'bin/.openjdk-17.0.3',
type: 'deletion',
},
},
{
file: {
contents: 'hermit',
isSymlink: true,
isExecutable: undefined,
path: 'bin/.openjdk-17.0.4.1_1',
type: 'addition',
},
},
{
file: {
path: 'bin/java',
type: 'deletion',
},
},
{
file: {
contents: 'hermit',
isSymlink: true,
isExecutable: undefined,
path: 'bin/java',
type: 'addition',
},
},
{
file: {
path: 'bin/javac',
type: 'deletion',
},
},
{
file: {
contents: 'hermit',
isSymlink: true,
isExecutable: undefined,
path: 'bin/javac',
type: 'addition',
},
},
{
file: {
path: 'bin/jar',
type: 'deletion',
},
},
{
file: {
contents: 'hermit',
isSymlink: true,
isExecutable: undefined,
path: 'bin/jar',
type: 'addition',
},
},
]);
});

it('should not uninstall package for version only replcaement', async () => {
lstatsMock.mockResolvedValue(true);

readlinkMock.mockResolvedValue('hermit');
GlobalConfig.set({ localDir: '' });

const execSnapshots = mockExecAll();
getRepoStatusMock.mockResolvedValue(
partial<StatusResult>({
not_added: [],
deleted: [],
modified: ['bin/go'],
renamed: [
{
from: 'bin/.go-1.19',
to: 'bin/.go-1.18',
},
],
created: [],
}),
);

const res = await updateArtifacts(
partial<UpdateArtifact>({
updatedDeps: [
{
depName: 'go',
newName: 'go',
currentVersion: '1.19',
newValue: '1.18',
updateType: 'replacement',
},
],
packageFileName: 'go/bin/hermit',
}),
);

expect(execSnapshots).toMatchObject([
{ cmd: './hermit install go-1.18' },
]);

expect(res).toStrictEqual([
{
file: {
path: 'bin/.go-1.19',
type: 'deletion',
},
},
{
file: {
contents: 'hermit',
isSymlink: true,
isExecutable: undefined,
path: 'bin/.go-1.18',
type: 'addition',
},
},
{
file: {
path: 'bin/go',
type: 'deletion',
},
},
{
file: {
contents: 'hermit',
isSymlink: true,
isExecutable: undefined,
path: 'bin/go',
type: 'addition',
},
},
]);
});

it('should fail if uninstallation fails', async () => {
lstatsMock.mockResolvedValue(true);

readlinkMock.mockResolvedValue(null);
GlobalConfig.set({ localDir: '' });

mockExecAll(
new ExecError('', {
stdout: '',
stderr: 'error executing hermit uninstall',
cmd: '',
options: {
encoding: 'utf-8',
},
}),
);

getRepoStatusMock.mockResolvedValue(
partial<StatusResult>({
not_added: [],
deleted: [],
modified: [],
created: [],
renamed: [],
}),
);

const res = await updateArtifacts(
partial<UpdateArtifact>({
updatedDeps: [
{
depName: 'openjdk',
newName: 'openjre',
currentVersion: '17.0.3',
newValue: '17.0.4.1_1',
updateType: 'replacement',
},
],
packageFileName: 'go/bin/hermit',
}),
);

expect(res).toEqual([
{
artifactError: {
lockFile: 'from: openjdk-17.0.3, to: openjdk',
stderr: 'error executing hermit uninstall',
},
},
]);
});

it('should fail on error getting link content', async () => {
lstatsMock.mockResolvedValue(true);

readlinkMock.mockResolvedValue(null);
GlobalConfig.set({ localDir: '' });
mockExecAll();

getRepoStatusMock.mockResolvedValue(
Expand Down
35 changes: 33 additions & 2 deletions lib/modules/manager/hermit/artifacts.ts
Expand Up @@ -177,6 +177,8 @@ async function updateHermitPackage(update: UpdateArtifact): Promise<void> {

const toInstall = [];
const from = [];
// storing the old package for replacement
const toUninstall = [];

for (const pkg of update.updatedDeps) {
if (!pkg.depName || !pkg.currentVersion || !pkg.newValue) {
Expand All @@ -197,12 +199,18 @@ async function updateHermitPackage(update: UpdateArtifact): Promise<void> {
}

const depName = pkg.depName;
const newName = pkg.newName;
const currentVersion = pkg.currentVersion;
const newValue = pkg.newValue;
const fromPackage = getHermitPackage(depName, currentVersion);
const toPackage = getHermitPackage(depName, newValue);
// newName will be available for replacement
const toPackage = getHermitPackage(newName ?? depName, newValue);
toInstall.push(toPackage);
from.push(fromPackage);
// skips uninstall for version only replacement
if (pkg.updateType === 'replacement' && newName !== depName) {
toUninstall.push(depName);
}
}

const execOptions: ExecOptions = {
Expand All @@ -211,9 +219,32 @@ async function updateHermitPackage(update: UpdateArtifact): Promise<void> {
cwdFile: update.packageFileName,
};

const packagesToInstall = toInstall.join(' ');
const fromPackages = from.map(quote).join(' ');

// when a name replacement happens, need to uninstall the old package
if (toUninstall.length > 0) {
const packagesToUninstall = toUninstall.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.join(' ');

const execCommands = `./hermit install ${packagesToInstall}`;
logger.debug(
{
Expand Down

0 comments on commit 41e8b99

Please sign in to comment.