diff --git a/lib/manager/api.ts b/lib/manager/api.ts index 7abc198d4f2bd67cf77d9b7414911a9cb793e613..0a1a2c49d2e5f64b95bedc76787b1bc26545ab38 100644 --- a/lib/manager/api.ts +++ b/lib/manager/api.ts @@ -6,6 +6,7 @@ import * as batectWrapper from './batect-wrapper'; import * as bazel from './bazel'; import * as buildkite from './buildkite'; import * as bundler from './bundler'; +import * as cake from './cake'; import * as cargo from './cargo'; import * as cdnurl from './cdnurl'; import * as circleci from './circleci'; @@ -70,6 +71,7 @@ api.set('batect-wrapper', batectWrapper); api.set('bazel', bazel); api.set('buildkite', buildkite); api.set('bundler', bundler); +api.set('cake', cake); api.set('cargo', cargo); api.set('cdnurl', cdnurl); api.set('circleci', circleci); diff --git a/lib/manager/cake/__fixtures__/build.cake b/lib/manager/cake/__fixtures__/build.cake new file mode 100644 index 0000000000000000000000000000000000000000..4cdbf4d0496313d65f13bad1695e79a623982644 --- /dev/null +++ b/lib/manager/cake/__fixtures__/build.cake @@ -0,0 +1,10 @@ +foo +#addin nuget:?package=Foo.Foo&version=1.1.1 +#tool nuget:https://example.com?package=Bar.Bar&version=2.2.2 +#module nuget:file:///tmp/?package=Baz.Baz&version=3.3.3 +// #module nuget:?package=Qux.Qux&version=4.4.4 +/* +#module nuget:?package=Quux.Quux&version=5.5.5 +*/ +bar +#module nuget:foobar!@# diff --git a/lib/manager/cake/__snapshots__/index.spec.ts.snap b/lib/manager/cake/__snapshots__/index.spec.ts.snap new file mode 100644 index 0000000000000000000000000000000000000000..a6e389b1fc832f54bac102ee750fdac63064e7d9 --- /dev/null +++ b/lib/manager/cake/__snapshots__/index.spec.ts.snap @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`manager/cake/index extracts 1`] = ` +Object { + "deps": Array [ + Object { + "currentValue": "1.1.1", + "datasource": "nuget", + "depName": "Foo.Foo", + }, + Object { + "currentValue": "2.2.2", + "datasource": "nuget", + "depName": "Bar.Bar", + "registryUrls": Array [ + "https://example.com", + ], + }, + Object { + "currentValue": "3.3.3", + "datasource": "nuget", + "depName": "Baz.Baz", + "skipReason": "unsupported-url", + }, + ], +} +`; diff --git a/lib/manager/cake/index.spec.ts b/lib/manager/cake/index.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..c354776c5e0c94d2c037d2de888f1967ad951881 --- /dev/null +++ b/lib/manager/cake/index.spec.ts @@ -0,0 +1,14 @@ +import { readFileSync } from 'fs'; +import { getName } from '../../../test/util'; +import { extractPackageFile } from '.'; + +const content = readFileSync( + 'lib/manager/cake/__fixtures__/build.cake', + 'utf8' +); + +describe(getName(__filename), () => { + it('extracts', () => { + expect(extractPackageFile(content)).toMatchSnapshot(); + }); +}); diff --git a/lib/manager/cake/index.ts b/lib/manager/cake/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..60cb08b985172dd7baa3ffbdcb898c041b5b2e64 --- /dev/null +++ b/lib/manager/cake/index.ts @@ -0,0 +1,66 @@ +import moo from 'moo'; +import { LANGUAGE_DOT_NET } from '../../constants/languages'; +import { id as datasource } from '../../datasource/nuget'; +import { SkipReason } from '../../types'; +import { PackageDependency, PackageFile } from '../types'; + +export const language = LANGUAGE_DOT_NET; + +export const defaultConfig = { + fileMatch: ['\\.cake$'], +}; + +const lexerStates = { + main: { + lineComment: { match: /\/\/.*?$/ }, + multiLineComment: { match: /\/\*[^]*?\*\//, lineBreaks: true }, + dependency: { + match: /^#(?:addin|tool|module)\s+(?:nuget|dotnet):.*$/, + }, + unknown: { match: /[^]/, lineBreaks: true }, + }, +}; + +function parseDependencyLine(line: string): PackageDependency | null { + try { + let url = line.replace(/^[^:]*:/, ''); + const isEmptyHost = url.startsWith('?'); + url = isEmptyHost ? `http://localhost/${url}` : url; + const { origin: registryUrl, protocol, searchParams } = new URL(url); + + const depName = searchParams.get('package'); + const currentValue = searchParams.get('version'); + + const result: PackageDependency = { datasource, depName, currentValue }; + + if (!isEmptyHost) { + if (protocol.startsWith('http')) { + result.registryUrls = [registryUrl]; + } else { + result.skipReason = SkipReason.UnsupportedUrl; + } + } + + return result; + } catch (err) { + return null; + } +} + +export function extractPackageFile(content: string): PackageFile { + const deps = []; + const lexer = moo.states(lexerStates); + lexer.reset(content); + let token = lexer.next(); + while (token) { + const { type, value } = token; + if (type === 'dependency') { + const dep = parseDependencyLine(value); + if (dep) { + deps.push(dep); + } + } + token = lexer.next(); + } + return { deps }; +} diff --git a/lib/manager/cake/readme.md b/lib/manager/cake/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..37d6820850a316910046e77a633333a770e86d43 --- /dev/null +++ b/lib/manager/cake/readme.md @@ -0,0 +1 @@ +Extracts dependencies from `*.cake` files.