BREAKING CHANGE(pypi,rubygems): Revise PyPI and RubyGems handling: normalize error payloads, fix .gem parsing/packing, adjust PyPI JSON API and tests, and export smartarchive plugin

This commit is contained in:
2025-11-25 15:07:59 +00:00
parent fcd95677a0
commit 6291ebf79b
10 changed files with 403 additions and 59 deletions

View File

@@ -543,7 +543,8 @@ end
},
];
return tarTools.packFilesToTarGz(gemEntries);
// RubyGems .gem files are plain tar archives (NOT gzipped), containing metadata.gz and data.tar.gz
return tarTools.packFiles(gemEntries);
}
/**

View File

@@ -80,6 +80,7 @@ tap.test('PyPI: should upload wheel file (POST /pypi/)', async () => {
pyversion: 'py3',
metadata_version: '2.1',
sha256_digest: hashes.sha256,
requires_python: '>=3.7',
content: testWheelData,
filename: filename,
},
@@ -212,6 +213,7 @@ tap.test('PyPI: should upload sdist file (POST /pypi/)', async () => {
pyversion: 'source',
metadata_version: '2.1',
sha256_digest: hashes.sha256,
requires_python: '>=3.7',
content: testSdistData,
filename: filename,
},
@@ -233,10 +235,11 @@ tap.test('PyPI: should list both wheel and sdist in Simple API', async () => {
expect(response.status).toEqual(200);
const json = response.body as any;
expect(Object.keys(json.files).length).toEqual(2);
// PEP 691: files is an array of file objects
expect(json.files.length).toEqual(2);
const hasWheel = Object.keys(json.files).some(f => f.endsWith('.whl'));
const hasSdist = Object.keys(json.files).some(f => f.endsWith('.tar.gz'));
const hasWheel = json.files.some((f: any) => f.filename.endsWith('.whl'));
const hasSdist = json.files.some((f: any) => f.filename.endsWith('.tar.gz'));
expect(hasWheel).toEqual(true);
expect(hasSdist).toEqual(true);
@@ -265,6 +268,7 @@ tap.test('PyPI: should upload a second version', async () => {
pyversion: 'py3',
metadata_version: '2.1',
sha256_digest: hashes.sha256,
requires_python: '>=3.7',
content: newWheelData,
filename: filename,
},
@@ -286,10 +290,11 @@ tap.test('PyPI: should list multiple versions in Simple API', async () => {
expect(response.status).toEqual(200);
const json = response.body as any;
expect(Object.keys(json.files).length).toBeGreaterThan(2);
// PEP 691: files is an array of file objects
expect(json.files.length).toBeGreaterThan(2);
const hasVersion1 = Object.keys(json.files).some(f => f.includes('1.0.0'));
const hasVersion2 = Object.keys(json.files).some(f => f.includes('2.0.0'));
const hasVersion1 = json.files.some((f: any) => f.filename.includes('1.0.0'));
const hasVersion2 = json.files.some((f: any) => f.filename.includes('2.0.0'));
expect(hasVersion1).toEqual(true);
expect(hasVersion2).toEqual(true);
@@ -422,7 +427,8 @@ tap.test('PyPI: should handle package with requires-python metadata', async () =
const html = getResponse.body as string;
expect(html).toContain('data-requires-python');
expect(html).toContain('>=3.8');
// Note: >= gets HTML-escaped to >= in attribute values
expect(html).toContain('>=3.8');
});
tap.test('PyPI: should support JSON API for package metadata', async () => {