mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-31 09:41:46 +00:00
05e1271376
Enables the vitest/prefer-expect-resolves oxlint rule and applies its autofix across the spec suite.
1006 lines
30 KiB
TypeScript
1006 lines
30 KiB
TypeScript
import { codeBlock } from 'common-tags';
|
|
import { Fixtures } from '~test/fixtures.ts';
|
|
import { fs } from '~test/util.ts';
|
|
import * as hostRules from '../../../util/host-rules.ts';
|
|
import type { ExtractConfig } from '../types.ts';
|
|
import { extractPackageFile } from './index.ts';
|
|
|
|
vi.mock('../../../util/fs/index.ts');
|
|
|
|
function mockReadLocalFile(files: Record<string, string | null>) {
|
|
fs.readLocalFile.mockImplementation((file): Promise<any> => {
|
|
let content: string | null = null;
|
|
if (file in files) {
|
|
content = files[file];
|
|
}
|
|
return Promise.resolve(content);
|
|
});
|
|
}
|
|
|
|
const cargo1toml = Fixtures.get('Cargo.1.toml');
|
|
const cargo2toml = Fixtures.get('Cargo.2.toml');
|
|
const cargo3toml = Fixtures.get('Cargo.3.toml');
|
|
const cargo4toml = Fixtures.get('Cargo.4.toml');
|
|
const cargo5toml = Fixtures.get('Cargo.5.toml');
|
|
const cargo6configtoml = Fixtures.get('cargo.6.config.toml');
|
|
const cargo6toml = Fixtures.get('Cargo.6.toml');
|
|
const cargo7toml = Fixtures.get('Cargo.7.toml');
|
|
|
|
const lockfileUpdateCargotoml = Fixtures.get('lockfile-update/Cargo.toml');
|
|
|
|
describe('modules/manager/cargo/extract', () => {
|
|
describe('extractPackageFile()', () => {
|
|
const config: ExtractConfig = {};
|
|
|
|
beforeEach(() => {
|
|
vi.stubEnv('CARGO_REGISTRIES_PRIVATE_CRATES_INDEX', undefined);
|
|
vi.stubEnv('CARGO_REGISTRIES_MCORBIN_INDEX', undefined);
|
|
|
|
hostRules.clear();
|
|
hostRules.add({
|
|
hostType: 'github',
|
|
matchHost: 'git.example.com',
|
|
});
|
|
});
|
|
|
|
it('returns null for invalid toml', async () => {
|
|
await expect(
|
|
extractPackageFile('invalid toml', 'Cargo.toml', config),
|
|
).resolves.toBeNull();
|
|
});
|
|
|
|
it('returns null for empty dependencies', async () => {
|
|
const cargotoml = '[dependencies]\n';
|
|
await expect(
|
|
extractPackageFile(cargotoml, 'Cargo.toml', config),
|
|
).resolves.toBeNull();
|
|
});
|
|
|
|
it('returns null for empty dev-dependencies', async () => {
|
|
const cargotoml = '[dev-dependencies]\n';
|
|
await expect(
|
|
extractPackageFile(cargotoml, 'Cargo.toml', config),
|
|
).resolves.toBeNull();
|
|
});
|
|
|
|
it('returns null for empty custom target', async () => {
|
|
const cargotoml = '[target."foo".dependencies]\n';
|
|
await expect(
|
|
extractPackageFile(cargotoml, 'Cargo.toml', config),
|
|
).resolves.toBeNull();
|
|
});
|
|
|
|
it('extracts multiple dependencies simple', async () => {
|
|
const res = await extractPackageFile(cargo1toml, 'Cargo.toml', config);
|
|
expect(res?.deps).toMatchObject([
|
|
{ depName: 'libc', currentValue: '=0.2.43' },
|
|
{ depName: 'bitflags', currentValue: '1.0.4' },
|
|
{
|
|
depName: 'pcap-sys',
|
|
currentValue: '=0.1',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{ depName: 'pnet', currentValue: '0.21.0' },
|
|
{
|
|
depName: 'git_dep_with_version',
|
|
datasource: 'git-refs',
|
|
packageName: 'https://github.com/foo/bar',
|
|
skipReason: 'unspecified-version',
|
|
},
|
|
{
|
|
depName: 'git_dep',
|
|
datasource: 'git-refs',
|
|
packageName: 'https://github.com/foo/bar',
|
|
skipReason: 'unspecified-version',
|
|
},
|
|
{ depName: 'path_dep_without_version', skipReason: 'path-dependency' },
|
|
{
|
|
depName: 'git_dep_with_tag',
|
|
datasource: 'github-tags',
|
|
currentValue: '1.10.3',
|
|
packageName: 'foo/bar',
|
|
registryUrls: ['https://github.com'],
|
|
},
|
|
{
|
|
depName: 'git_dep_with_rev',
|
|
datasource: 'git-refs',
|
|
currentDigest: 'abc1234',
|
|
packageName: 'https://github.com/foo/bar',
|
|
},
|
|
{
|
|
depName: 'git_dep_with_branch',
|
|
datasource: 'git-refs',
|
|
currentValue: 'next',
|
|
packageName: 'https://github.com/foo/bar',
|
|
skipReason: 'git-dependency',
|
|
},
|
|
{
|
|
depName: 'git_dep_with_custom_hostname',
|
|
datasource: 'github-tags',
|
|
currentValue: '1.0.0',
|
|
packageName: 'a/b',
|
|
registryUrls: ['https://git.example.com'],
|
|
},
|
|
{ depName: 'same_version_1__', currentValue: '0.0.0' },
|
|
{ depName: 'same_version_1_', currentValue: '0.0.0' },
|
|
{ depName: 'same_version_1', currentValue: '0.0.0' },
|
|
{ depName: 'dep1', currentValue: '0.4.2' },
|
|
{ depName: 'winapi', currentValue: '=0.3.6' },
|
|
{ depName: 'wasm-bindgen', currentValue: '0.2.37' },
|
|
{ depName: 'js-sys', currentValue: '0.3.14' },
|
|
{ depName: 'js_relative_import', skipReason: 'path-dependency' },
|
|
{ depName: 'web-sys', currentValue: '0.3.14' },
|
|
]);
|
|
});
|
|
|
|
it('extracts multiple dependencies advanced', async () => {
|
|
const res = await extractPackageFile(cargo2toml, 'Cargo.toml', config);
|
|
expect(res?.deps).toMatchObject([
|
|
{
|
|
depName: 'amethyst_animation',
|
|
currentValue: '0.2.0',
|
|
depType: 'dependencies',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{
|
|
depName: 'amethyst_assets',
|
|
currentValue: '0.3.0',
|
|
depType: 'dependencies',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{
|
|
depName: 'amethyst_audio',
|
|
currentValue: '0.2.0',
|
|
depType: 'dependencies',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{
|
|
depName: 'amethyst_config',
|
|
currentValue: '0.6.0',
|
|
depType: 'dependencies',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{
|
|
depName: 'amethyst_core',
|
|
currentValue: '0.2.0',
|
|
depType: 'dependencies',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{
|
|
depName: 'amethyst_controls',
|
|
currentValue: '0.1.0',
|
|
depType: 'dependencies',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{
|
|
depName: 'amethyst_locale',
|
|
currentValue: '0.1.0',
|
|
depType: 'dependencies',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{
|
|
depName: 'amethyst_renderer',
|
|
currentValue: '0.7',
|
|
depType: 'dependencies',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{
|
|
depName: 'amethyst_input',
|
|
currentValue: '0.3',
|
|
depType: 'dependencies',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{
|
|
depName: 'amethyst_ui',
|
|
currentValue: '0.2',
|
|
depType: 'dependencies',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{
|
|
depName: 'amethyst_utils',
|
|
currentValue: '0.2',
|
|
depType: 'dependencies',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{ depName: 'derivative', currentValue: '1.0', depType: 'dependencies' },
|
|
{ depName: 'fern', currentValue: '0.5', depType: 'dependencies' },
|
|
{ depName: 'log', currentValue: '0.4', depType: 'dependencies' },
|
|
{ depName: 'rayon', currentValue: '1.0.1', depType: 'dependencies' },
|
|
{
|
|
depName: 'rustc_version_runtime',
|
|
currentValue: '0.1',
|
|
depType: 'dependencies',
|
|
},
|
|
{ depName: 'winit', currentValue: '0.15', depType: 'dependencies' },
|
|
{
|
|
depName: 'thread_profiler',
|
|
currentValue: '0.1',
|
|
depType: 'dependencies',
|
|
},
|
|
{
|
|
depName: 'amethyst_gltf',
|
|
currentValue: '0.2',
|
|
depType: 'dev-dependencies',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{
|
|
depName: 'env_logger',
|
|
currentValue: '0.5.10',
|
|
depType: 'dev-dependencies',
|
|
},
|
|
{
|
|
depName: 'genmesh',
|
|
currentValue: '0.6',
|
|
depType: 'dev-dependencies',
|
|
},
|
|
{ depName: 'ron', currentValue: '0.2', depType: 'dev-dependencies' },
|
|
{ depName: 'serde', currentValue: '1.0', depType: 'dev-dependencies' },
|
|
{
|
|
depName: 'serde_derive',
|
|
currentValue: '1.0',
|
|
depType: 'dev-dependencies',
|
|
},
|
|
{
|
|
depName: 'vergen',
|
|
currentValue: '0.1',
|
|
depType: 'build-dependencies',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('handles inline tables', async () => {
|
|
const res = await extractPackageFile(cargo3toml, 'Cargo.toml', config);
|
|
expect(res?.deps).toMatchObject([
|
|
{
|
|
depName: 'pcap-sys',
|
|
currentValue: '0.1',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{ depName: 'pnet', currentValue: '0.21.0' },
|
|
{ depName: 'dep1', currentValue: '1.2', skipReason: 'path-dependency' },
|
|
{ depName: 'dep2', currentValue: '3.4', skipReason: 'path-dependency' },
|
|
{
|
|
depName: 'dep3',
|
|
currentValue: '~12.3.1',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{ depName: 'dep4', currentValue: 'INVALID 3.3.1 VERSION' },
|
|
{ depName: 'dep5', currentValue: '3.2.1' },
|
|
{ depName: 'dep6', skipReason: 'invalid-dependency-specification' },
|
|
]);
|
|
});
|
|
|
|
it('handles standard tables', async () => {
|
|
const res = await extractPackageFile(cargo4toml, 'Cargo.toml', config);
|
|
expect(res?.deps).toMatchObject([
|
|
{ depName: 'dep1', currentValue: '1.2', skipReason: 'path-dependency' },
|
|
{ depName: 'dep2', currentValue: '3.4', skipReason: 'path-dependency' },
|
|
{
|
|
depName: 'dep3',
|
|
currentValue: '~12.3.1',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{
|
|
depName: 'dep4',
|
|
currentValue: 'INVALID 1.3.1 VERSION',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{ depName: 'dep5', skipReason: 'path-dependency' },
|
|
{ depName: 'dep7', skipReason: 'invalid-dependency-specification' },
|
|
]);
|
|
});
|
|
|
|
it('extracts platform specific dependencies', async () => {
|
|
const res = await extractPackageFile(cargo5toml, 'Cargo.toml', config);
|
|
expect(res?.deps).toMatchObject([
|
|
{
|
|
depName: 'wasm-bindgen',
|
|
currentValue: '0.2.37',
|
|
target: 'cfg(target_arch = "wasm32")',
|
|
},
|
|
{
|
|
depName: 'js-sys',
|
|
currentValue: '0.3.14',
|
|
target: 'cfg(target_arch = "wasm32")',
|
|
},
|
|
{
|
|
depName: 'js_relative_import',
|
|
target: 'cfg(target_arch = "wasm32")',
|
|
skipReason: 'path-dependency',
|
|
},
|
|
{
|
|
depName: 'web-sys',
|
|
currentValue: '0.3.14',
|
|
target: 'cfg(target_arch = "wasm32")',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('extracts registry urls from .cargo/config.toml', async () => {
|
|
mockReadLocalFile({ '.cargo/config.toml': cargo6configtoml });
|
|
const res = await extractPackageFile(cargo6toml, 'Cargo.toml', {
|
|
...config,
|
|
});
|
|
expect(res?.deps).toMatchObject([
|
|
{
|
|
depName: 'proprietary-crate',
|
|
currentValue: '0.1.0',
|
|
registryUrls: [
|
|
'https://dl.cloudsmith.io/basic/my-org/my-repo/cargo/index.git',
|
|
],
|
|
},
|
|
{
|
|
depName: 'mcorbin-test',
|
|
currentValue: '3.0.0',
|
|
registryUrls: ['https://github.com/mcorbin/testregistry'],
|
|
},
|
|
{ depName: 'tokio', currentValue: '0.2' },
|
|
]);
|
|
});
|
|
|
|
it('extracts registry urls from .cargo/config (legacy path)', async () => {
|
|
mockReadLocalFile({ '.cargo/config.toml': cargo6configtoml });
|
|
const res = await extractPackageFile(cargo6toml, 'Cargo.toml', {
|
|
...config,
|
|
});
|
|
expect(res?.deps).toMatchObject([
|
|
{
|
|
depName: 'proprietary-crate',
|
|
currentValue: '0.1.0',
|
|
registryUrls: [
|
|
'https://dl.cloudsmith.io/basic/my-org/my-repo/cargo/index.git',
|
|
],
|
|
},
|
|
{
|
|
depName: 'mcorbin-test',
|
|
currentValue: '3.0.0',
|
|
registryUrls: ['https://github.com/mcorbin/testregistry'],
|
|
},
|
|
{ depName: 'tokio', currentValue: '0.2' },
|
|
]);
|
|
});
|
|
|
|
it('extracts overridden registry indexes from .cargo/config.toml', async () => {
|
|
mockReadLocalFile({
|
|
'.cargo/config.toml': codeBlock`[registries]
|
|
private-crates = { index = "https://dl.cloudsmith.io/basic/my-org/my-repo/cargo/index.git" }
|
|
|
|
[registries.mcorbin]
|
|
index = "https://github.com/mcorbin/testregistry"
|
|
|
|
[source.crates-io]
|
|
replace-with = "mcorbin"
|
|
|
|
[source.mcorbin]
|
|
replace-with = "private-crates"`,
|
|
});
|
|
const res = await extractPackageFile(cargo6toml, 'Cargo.toml', {
|
|
...config,
|
|
});
|
|
expect(res?.deps).toEqual([
|
|
{
|
|
currentValue: '0.1.0',
|
|
datasource: 'crate',
|
|
depName: 'proprietary-crate',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: true,
|
|
registryName: 'private-crates',
|
|
},
|
|
registryUrls: [
|
|
'https://dl.cloudsmith.io/basic/my-org/my-repo/cargo/index.git',
|
|
],
|
|
},
|
|
{
|
|
currentValue: '3.0.0',
|
|
datasource: 'crate',
|
|
depName: 'mcorbin-test',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: true,
|
|
registryName: 'mcorbin',
|
|
},
|
|
registryUrls: [
|
|
'https://dl.cloudsmith.io/basic/my-org/my-repo/cargo/index.git',
|
|
],
|
|
},
|
|
{
|
|
currentValue: '0.2',
|
|
datasource: 'crate',
|
|
depName: 'tokio',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: false,
|
|
},
|
|
registryUrls: [
|
|
'https://dl.cloudsmith.io/basic/my-org/my-repo/cargo/index.git',
|
|
],
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('extracts overridden source registry indexes from .cargo/config.toml', async () => {
|
|
mockReadLocalFile({
|
|
'.cargo/config.toml': codeBlock`[source.crates-io-replacement]
|
|
registry = "https://github.com/replacement/testregistry"
|
|
|
|
[source.crates-io]
|
|
replace-with = "crates-io-replacement"`,
|
|
});
|
|
const res = await extractPackageFile(cargo7toml, 'Cargo.toml', {
|
|
...config,
|
|
});
|
|
expect(res?.deps).toEqual([
|
|
{
|
|
currentValue: '0.2',
|
|
datasource: 'crate',
|
|
depName: 'tokio',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: false,
|
|
},
|
|
registryUrls: ['https://github.com/replacement/testregistry'],
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('extracts registries overridden to the default', async () => {
|
|
mockReadLocalFile({
|
|
'.cargo/config.toml': codeBlock`[source.mcorbin]
|
|
replace-with = "crates-io"
|
|
|
|
[source.private-crates]
|
|
replace-with = "mcorbin"`,
|
|
});
|
|
const res = await extractPackageFile(cargo6toml, 'Cargo.toml', {
|
|
...config,
|
|
});
|
|
expect(res?.deps).toEqual([
|
|
{
|
|
currentValue: '0.1.0',
|
|
datasource: 'crate',
|
|
depName: 'proprietary-crate',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: true,
|
|
registryName: 'private-crates',
|
|
},
|
|
},
|
|
{
|
|
currentValue: '3.0.0',
|
|
datasource: 'crate',
|
|
depName: 'mcorbin-test',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: true,
|
|
registryName: 'mcorbin',
|
|
},
|
|
},
|
|
{
|
|
currentValue: '0.2',
|
|
datasource: 'crate',
|
|
depName: 'tokio',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: false,
|
|
},
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('extracts registries with an empty config.toml', async () => {
|
|
mockReadLocalFile({ '.cargo/config.toml': '' });
|
|
const res = await extractPackageFile(cargo5toml, 'Cargo.toml', {
|
|
...config,
|
|
});
|
|
expect(res?.deps).toEqual([
|
|
{
|
|
currentValue: '0.2.37',
|
|
datasource: 'crate',
|
|
depName: 'wasm-bindgen',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: false,
|
|
},
|
|
target: 'cfg(target_arch = "wasm32")',
|
|
},
|
|
{
|
|
currentValue: '0.3.14',
|
|
datasource: 'crate',
|
|
depName: 'js-sys',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: false,
|
|
},
|
|
target: 'cfg(target_arch = "wasm32")',
|
|
},
|
|
{
|
|
currentValue: '',
|
|
datasource: 'crate',
|
|
depName: 'js_relative_import',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: false,
|
|
},
|
|
skipReason: 'path-dependency',
|
|
target: 'cfg(target_arch = "wasm32")',
|
|
},
|
|
{
|
|
currentValue: '0.3.14',
|
|
datasource: 'crate',
|
|
depName: 'web-sys',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: true,
|
|
},
|
|
target: 'cfg(target_arch = "wasm32")',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('extracts registry urls from environment', async () => {
|
|
vi.stubEnv(
|
|
'CARGO_REGISTRIES_PRIVATE_CRATES_INDEX',
|
|
'https://dl.cloudsmith.io/basic/my-org/my-repo/cargo/index.git',
|
|
);
|
|
vi.stubEnv(
|
|
'CARGO_REGISTRIES_MCORBIN_INDEX',
|
|
'https://github.com/mcorbin/testregistry',
|
|
);
|
|
const res = await extractPackageFile(cargo6toml, 'Cargo.toml', {
|
|
...config,
|
|
});
|
|
|
|
expect(res?.deps).toEqual([
|
|
{
|
|
currentValue: '0.1.0',
|
|
datasource: 'crate',
|
|
depName: 'proprietary-crate',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: true,
|
|
registryName: 'private-crates',
|
|
},
|
|
registryUrls: [
|
|
'https://dl.cloudsmith.io/basic/my-org/my-repo/cargo/index.git',
|
|
],
|
|
},
|
|
{
|
|
currentValue: '3.0.0',
|
|
datasource: 'crate',
|
|
depName: 'mcorbin-test',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: true,
|
|
registryName: 'mcorbin',
|
|
},
|
|
registryUrls: ['https://github.com/mcorbin/testregistry'],
|
|
},
|
|
{
|
|
currentValue: '0.2',
|
|
datasource: 'crate',
|
|
depName: 'tokio',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: false,
|
|
},
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('extracts workspace dependencies', async () => {
|
|
const cargoToml = codeBlock`
|
|
[package]
|
|
name = "renovate-test"
|
|
version = "0.1.0"
|
|
authors = ["John Doe <john.doe@example.org>"]
|
|
edition = "2018"
|
|
|
|
[dependencies]
|
|
git2 = "0.14.0"
|
|
|
|
[workspace]
|
|
members = ["pcap-sys"]
|
|
|
|
[workspace.dependencies]
|
|
serde = "1.0.146"
|
|
tokio = { version = "1.21.1" }`;
|
|
const res = await extractPackageFile(cargoToml, 'Cargo.toml', config);
|
|
expect(res?.deps).toEqual([
|
|
{
|
|
currentValue: '0.14.0',
|
|
datasource: 'crate',
|
|
depName: 'git2',
|
|
depType: 'dependencies',
|
|
managerData: { nestedVersion: false },
|
|
},
|
|
{
|
|
currentValue: '1.0.146',
|
|
datasource: 'crate',
|
|
depName: 'serde',
|
|
depType: 'workspace.dependencies',
|
|
managerData: { nestedVersion: false },
|
|
},
|
|
{
|
|
currentValue: '1.21.1',
|
|
datasource: 'crate',
|
|
depName: 'tokio',
|
|
depType: 'workspace.dependencies',
|
|
managerData: {
|
|
nestedVersion: true,
|
|
},
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('skips workspace dependency', async () => {
|
|
const cargotoml = '[dependencies]\nfoobar = { workspace = true }';
|
|
const res = await extractPackageFile(cargotoml, 'Cargo.toml', config);
|
|
expect(res?.deps).toEqual([
|
|
{
|
|
currentValue: '',
|
|
datasource: 'crate',
|
|
depName: 'foobar',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: false,
|
|
},
|
|
skipReason: 'inherited-dependency',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('skips unknown registries', async () => {
|
|
const cargotoml =
|
|
'[dependencies]\nfoobar = { version = "0.1.0", registry = "not-listed" }';
|
|
const res = await extractPackageFile(cargotoml, 'Cargo.toml', config);
|
|
expect(res?.deps).toMatchObject([
|
|
{
|
|
depName: 'foobar',
|
|
currentValue: '0.1.0',
|
|
skipReason: 'unknown-registry',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('fails to parse cargo config with invalid TOML', async () => {
|
|
mockReadLocalFile({ '.cargo/config': '[registries' });
|
|
const res = await extractPackageFile(cargo6toml, 'Cargo.toml', {
|
|
...config,
|
|
});
|
|
expect(res?.deps).toMatchObject([
|
|
{
|
|
depName: 'proprietary-crate',
|
|
currentValue: '0.1.0',
|
|
skipReason: 'unknown-registry',
|
|
},
|
|
{
|
|
depName: 'mcorbin-test',
|
|
currentValue: '3.0.0',
|
|
skipReason: 'unknown-registry',
|
|
},
|
|
{ depName: 'tokio', currentValue: '0.2' },
|
|
]);
|
|
});
|
|
|
|
it('ignore cargo config registries with missing index', async () => {
|
|
mockReadLocalFile({ '.cargo/config': '[registries.mine]\nfoo = "bar"' });
|
|
const res = await extractPackageFile(cargo6toml, 'Cargo.toml', {
|
|
...config,
|
|
});
|
|
expect(res?.deps).toMatchObject([
|
|
{
|
|
depName: 'proprietary-crate',
|
|
currentValue: '0.1.0',
|
|
skipReason: 'unknown-registry',
|
|
},
|
|
{
|
|
depName: 'mcorbin-test',
|
|
currentValue: '3.0.0',
|
|
skipReason: 'unknown-registry',
|
|
},
|
|
{ depName: 'tokio', currentValue: '0.2' },
|
|
]);
|
|
});
|
|
|
|
it('ignore cargo config source replaced registries with missing index', async () => {
|
|
mockReadLocalFile({
|
|
'.cargo/config': codeBlock`[registries.mine]
|
|
foo = "bar"
|
|
|
|
[source.crates-io]
|
|
replace-with = "mine"`,
|
|
});
|
|
|
|
const res = await extractPackageFile(cargo6toml, 'Cargo.toml', {
|
|
...config,
|
|
});
|
|
expect(res?.deps).toEqual([
|
|
{
|
|
currentValue: '0.1.0',
|
|
datasource: 'crate',
|
|
depName: 'proprietary-crate',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: true,
|
|
registryName: 'private-crates',
|
|
},
|
|
skipReason: 'unknown-registry',
|
|
},
|
|
{
|
|
currentValue: '3.0.0',
|
|
datasource: 'crate',
|
|
depName: 'mcorbin-test',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: true,
|
|
registryName: 'mcorbin',
|
|
},
|
|
skipReason: 'unknown-registry',
|
|
},
|
|
{
|
|
currentValue: '0.2',
|
|
datasource: 'crate',
|
|
depName: 'tokio',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: false,
|
|
},
|
|
skipReason: 'unknown-registry',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('ignore cargo config with circular registry source replacements', async () => {
|
|
mockReadLocalFile({
|
|
'.cargo/config': codeBlock`[registries]
|
|
private-crates = { index = "https://dl.cloudsmith.io/basic/my-org/my-repo/cargo/index.git" }
|
|
|
|
[registries.mcorbin]
|
|
index = "https://github.com/mcorbin/testregistry"
|
|
|
|
[source.crates-io]
|
|
replace-with = "mcorbin"
|
|
|
|
[source.mcorbin]
|
|
replace-with = "private-crates"
|
|
|
|
[source.private-crates]
|
|
replace-with = "mcorbin"
|
|
`,
|
|
});
|
|
|
|
const res = await extractPackageFile(cargo6toml, 'Cargo.toml', {
|
|
...config,
|
|
});
|
|
expect(res?.deps).toEqual([
|
|
{
|
|
currentValue: '0.1.0',
|
|
datasource: 'crate',
|
|
depName: 'proprietary-crate',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: true,
|
|
registryName: 'private-crates',
|
|
},
|
|
skipReason: 'unknown-registry',
|
|
},
|
|
{
|
|
currentValue: '3.0.0',
|
|
datasource: 'crate',
|
|
depName: 'mcorbin-test',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: true,
|
|
registryName: 'mcorbin',
|
|
},
|
|
skipReason: 'unknown-registry',
|
|
},
|
|
{
|
|
currentValue: '0.2',
|
|
datasource: 'crate',
|
|
depName: 'tokio',
|
|
depType: 'dependencies',
|
|
managerData: {
|
|
nestedVersion: false,
|
|
},
|
|
skipReason: 'unknown-registry',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('extracts original package name of renamed dependencies', async () => {
|
|
const cargotoml =
|
|
'[dependencies]\nboolector-solver = { package = "boolector", version = "0.4.0" }';
|
|
const res = await extractPackageFile(cargotoml, 'Cargo.toml', config);
|
|
|
|
expect(res?.deps).toMatchObject([
|
|
{
|
|
depName: 'boolector-solver',
|
|
currentValue: '0.4.0',
|
|
packageName: 'boolector',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('keeps the git source as packageName for renamed git dependencies', async () => {
|
|
const cargotoml = codeBlock`
|
|
[dependencies]
|
|
github-tag = { package = "real-crate", git = "https://github.com/foo/bar", tag = "v1.2.3" }
|
|
gitlab-tag = { package = "real-crate", git = "https://gitlab.com/foo/bar", tag = "v1.2.3" }
|
|
other-tag = { package = "real-crate", git = "https://gitea.example.com/foo/bar", tag = "v1.2.3" }
|
|
rev = { package = "real-crate", git = "https://github.com/foo/bar", rev = "abcdef0" }
|
|
crates-io = { package = "real-crate", version = "0.4.0" }
|
|
`;
|
|
|
|
const res = await extractPackageFile(cargotoml, 'Cargo.toml', config);
|
|
|
|
expect(res?.deps).toMatchObject([
|
|
{
|
|
depName: 'github-tag',
|
|
datasource: 'github-tags',
|
|
packageName: 'foo/bar',
|
|
registryUrls: ['https://github.com'],
|
|
currentValue: 'v1.2.3',
|
|
},
|
|
{
|
|
depName: 'gitlab-tag',
|
|
datasource: 'gitlab-tags',
|
|
packageName: 'foo/bar',
|
|
registryUrls: ['https://gitlab.com'],
|
|
currentValue: 'v1.2.3',
|
|
},
|
|
{
|
|
depName: 'other-tag',
|
|
datasource: 'git-tags',
|
|
packageName: 'https://gitea.example.com/foo/bar',
|
|
currentValue: 'v1.2.3',
|
|
},
|
|
{
|
|
depName: 'rev',
|
|
datasource: 'git-refs',
|
|
packageName: 'https://github.com/foo/bar',
|
|
currentDigest: 'abcdef0',
|
|
},
|
|
{
|
|
depName: 'crates-io',
|
|
datasource: 'crate',
|
|
packageName: 'real-crate',
|
|
currentValue: '0.4.0',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('extracts locked versions', async () => {
|
|
const cargolock = Fixtures.get('lockfile-update/Cargo.3.lock');
|
|
mockReadLocalFile({ 'Cargo.lock': cargolock });
|
|
fs.findLocalSiblingOrParent.mockResolvedValueOnce('Cargo.lock');
|
|
|
|
const cargotoml = codeBlock`
|
|
[package]
|
|
name = "test"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
[dependencies]
|
|
syn = "2.0"
|
|
`;
|
|
|
|
const res = await extractPackageFile(cargotoml, 'Cargo.toml', config);
|
|
expect(res?.deps).toMatchObject([{ lockedVersion: '2.0.1' }]);
|
|
});
|
|
|
|
it('does not extract locked versions for git dependencies', async () => {
|
|
const cargolock = Fixtures.get('lockfile-update/Cargo.3.lock');
|
|
mockReadLocalFile({ 'Cargo.lock': cargolock });
|
|
fs.findLocalSiblingOrParent.mockResolvedValueOnce('Cargo.lock');
|
|
|
|
const cargotoml = codeBlock`
|
|
[package]
|
|
name = "test"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
[dependencies]
|
|
git_dep = { git = "https://github.com/foo/bar" }
|
|
`;
|
|
|
|
const res = await extractPackageFile(cargotoml, 'Cargo.toml', config);
|
|
expect(res?.deps[0].lockedVersion).toBeUndefined();
|
|
});
|
|
|
|
it('extracts locked versions for renamed packages', async () => {
|
|
const cargolock = Fixtures.get('lockfile-update/Cargo.1.lock');
|
|
mockReadLocalFile({ 'Cargo.lock': cargolock });
|
|
fs.findLocalSiblingOrParent.mockResolvedValueOnce('Cargo.lock');
|
|
|
|
const res = await extractPackageFile(
|
|
lockfileUpdateCargotoml,
|
|
'Cargo.toml',
|
|
config,
|
|
);
|
|
expect(res?.deps).toMatchObject([
|
|
{ lockedVersion: '2.0.1' },
|
|
{ lockedVersion: '1.0.1' },
|
|
]);
|
|
});
|
|
|
|
it('handles missing locked versions', async () => {
|
|
const cargolock = Fixtures.get('lockfile-update/Cargo.2.lock');
|
|
mockReadLocalFile({ 'Cargo.lock': cargolock });
|
|
fs.findLocalSiblingOrParent.mockResolvedValueOnce('Cargo.lock');
|
|
|
|
const res = await extractPackageFile(
|
|
lockfileUpdateCargotoml,
|
|
'Cargo.toml',
|
|
config,
|
|
);
|
|
expect(res?.deps).toMatchObject([
|
|
{ lockedVersion: '2.0.1' },
|
|
expect.not.objectContaining({ lockedVersion: expect.anything() }),
|
|
]);
|
|
});
|
|
|
|
it('handles invalid versions in the toml file', async () => {
|
|
const cargolock = Fixtures.get('lockfile-update/Cargo.3.lock');
|
|
mockReadLocalFile({ 'Cargo.lock': cargolock });
|
|
fs.findLocalSiblingOrParent.mockResolvedValueOnce('Cargo.lock');
|
|
|
|
const cargotoml = codeBlock`
|
|
[package]
|
|
name = "test"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
[dependencies]
|
|
syn = "2.foo.1"
|
|
`;
|
|
|
|
const res = await extractPackageFile(cargotoml, 'Cargo.toml', config);
|
|
expect(res?.deps).not.toHaveProperty('lockedVersion');
|
|
});
|
|
|
|
it('handles invalid lock file', async () => {
|
|
mockReadLocalFile({ 'Cargo.lock': 'foo' });
|
|
fs.findLocalSiblingOrParent.mockResolvedValueOnce('Cargo.lock');
|
|
|
|
const res = await extractPackageFile(
|
|
lockfileUpdateCargotoml,
|
|
'Cargo.toml',
|
|
config,
|
|
);
|
|
expect(res?.deps).toMatchObject([
|
|
expect.not.objectContaining({ lockedVersion: expect.anything() }),
|
|
expect.not.objectContaining({ lockedVersion: expect.anything() }),
|
|
]);
|
|
});
|
|
|
|
it('should extract project version', async () => {
|
|
const cargotoml = codeBlock`
|
|
[package]
|
|
name = "test"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
[dependencies]
|
|
syn = "2.0"
|
|
`;
|
|
|
|
const res = await extractPackageFile(cargotoml, 'Cargo.toml', config);
|
|
expect(res?.packageFileVersion).toBe('0.1.0');
|
|
});
|
|
|
|
it('should extract project version from workspace', async () => {
|
|
const cargotoml = codeBlock`
|
|
[package]
|
|
name = "test"
|
|
version.workspace = true
|
|
edition = "2021"
|
|
[workspace.package]
|
|
version = "0.1.0"
|
|
[dependencies]
|
|
syn = "2.0"
|
|
`;
|
|
|
|
const res = await extractPackageFile(cargotoml, 'Cargo.toml', config);
|
|
expect(res?.packageFileVersion).toBe('0.1.0');
|
|
});
|
|
});
|
|
});
|