fix(bundler): More flexible parsing for gem lines (#7321)

Co-authored-by: Rhys Arkins <rhys@arkins.net>
This commit is contained in:
Sergio Zharinov 2020-09-21 23:30:09 +04:00 committed by GitHub
parent 689b2ff015
commit c64fe52a7e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 55 additions and 25 deletions

View file

@ -0,0 +1,5 @@
source 'https://hub.tech.my.domain.de/artifactory/api/gems/my-gems-prod-local/' do
gem 'sfn_my_dep1', "~> 1"
gem 'sfn_my_dep2', "~> 1"
end

View file

@ -2491,12 +2491,13 @@ Object {
},
},
Object {
"currentValue": "~> 0.0.2",
"datasource": "rubygems",
"depName": "omniauth-ultraauth",
"lockedVersion": "0.0.2",
"managerData": Object {
"lineNumber": 46,
},
"skipReason": "no-version",
},
Object {
"currentValue": "~> 1.0.5",
@ -4689,6 +4690,36 @@ Object {
}
`;
exports[`lib/manager/bundler/extract parse source blocks in Gemfile 1`] = `
Object {
"deps": Array [
Object {
"currentValue": "~> 1",
"datasource": "rubygems",
"depName": "sfn_my_dep1",
"managerData": Object {
"lineNumber": 1,
},
"registryUrls": Array [
"https://hub.tech.my.domain.de/artifactory/api/gems/my-gems-prod-local/",
],
},
Object {
"currentValue": "~> 1",
"datasource": "rubygems",
"depName": "sfn_my_dep2",
"managerData": Object {
"lineNumber": 2,
},
"registryUrls": Array [
"https://hub.tech.my.domain.de/artifactory/api/gems/my-gems-prod-local/",
],
},
],
"registryUrls": Array [],
}
`;
exports[`lib/manager/bundler/extract parse source blocks with spaces in Gemfile 1`] = `
Object {
"compatibility": Object {

View file

@ -51,6 +51,10 @@ const gitlabFossGemfile = readFileSync(
'lib/manager/bundler/__fixtures__/Gemfile.gitlab-foss',
'utf8'
);
const sourceBlockGemfile = readFileSync(
'lib/manager/bundler/__fixtures__/Gemfile.sourceBlock',
'utf8'
);
const sourceBlockWithNewLinesGemfileLock = readFileSync(
'lib/manager/bundler/__fixtures__/Gemfile.sourceBlockWithNewLines.lock',
'utf8'
@ -157,6 +161,11 @@ describe('lib/manager/bundler/extract', () => {
validateGems(gitlabFossGemfile, res);
});
it('parse source blocks in Gemfile', async () => {
fs.readLocalFile.mockResolvedValueOnce(sourceBlockGemfile);
const res = await extractPackageFile(sourceBlockGemfile, 'Gemfile');
expect(res).toMatchSnapshot();
});
it('parse source blocks with spaces in Gemfile', async () => {
fs.readLocalFile.mockResolvedValueOnce(sourceBlockWithNewLinesGemfileLock);
const res = await extractPackageFile(

View file

@ -38,33 +38,18 @@ export async function extractPackageFile(
if (rubyMatch) {
res.compatibility = { ruby: rubyMatch[1] };
}
let gemMatch: RegExpMatchArray;
let gemDelimiter: string;
for (const delimiter of delimiters) {
const gemMatchRegex = `^gem ${delimiter}([^${delimiter}]+)${delimiter}(,\\s+${delimiter}([^${delimiter}]+)${delimiter}){0,2}`;
if (regEx(gemMatchRegex).test(line)) {
gemDelimiter = delimiter;
gemMatch = gemMatch || regEx(gemMatchRegex).exec(line);
}
}
const gemMatchRegex = /^\s*gem\s+(['"])(?<depName>[^'"]+)\1(\s*,\s*(?<currentValue>(['"])[^'"]+\5(\s*,\s*\5[^'"]+\5)?))?/;
const gemMatch = gemMatchRegex.exec(line);
if (gemMatch) {
const dep: PackageDependency = {
depName: gemMatch[1],
depName: gemMatch.groups.depName,
managerData: { lineNumber },
};
if (gemMatch[3]) {
let currentValue = gemMatch[0]
.substring(`gem ${gemDelimiter}${dep.depName}${gemDelimiter},`.length)
.trim();
// strip quotes unless it's a complex constraint
if (
currentValue.startsWith(gemDelimiter) &&
currentValue.endsWith(gemDelimiter) &&
currentValue.split(gemDelimiter).length === 3
) {
currentValue = currentValue.slice(1, -1);
}
dep.currentValue = currentValue;
if (gemMatch.groups.currentValue) {
const currentValue = gemMatch.groups.currentValue;
dep.currentValue = /\s*,\s*/.test(currentValue)
? currentValue
: currentValue.slice(1, -1);
} else {
dep.skipReason = SkipReason.NoVersion;
}