Skip to content

Commit

Permalink
refactor(maven): Extract util functions from datasource index (#9727)
Browse files Browse the repository at this point in the history
  • Loading branch information
zharinov authored Apr 26, 2021
1 parent 65c3992 commit ca9ed19
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 107 deletions.
115 changes: 8 additions & 107 deletions lib/datasource/maven/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import url from 'url';
import fs from 'fs-extra';
import pAll from 'p-all';
import { XmlDocument } from 'xmldoc';
import { logger } from '../../logger';
Expand All @@ -9,7 +8,14 @@ import * as mavenVersioning from '../../versioning/maven';
import { compare } from '../../versioning/maven/compare';
import type { GetReleasesConfig, Release, ReleaseResult } from '../types';
import { MAVEN_REPO } from './common';
import { downloadHttpProtocol, isHttpResourceExists } from './util';
import type { MavenDependency } from './types';
import {
downloadMavenXml,
getDependencyInfo,
getDependencyParts,
getMavenUrl,
isHttpResourceExists,
} from './util';

export { id } from './common';

Expand All @@ -18,93 +24,6 @@ export const defaultRegistryUrls = [MAVEN_REPO];
export const defaultVersioning = mavenVersioning.id;
export const registryStrategy = 'merge';

function containsPlaceholder(str: string): boolean {
return /\${.*?}/g.test(str);
}

async function downloadFileProtocol(pkgUrl: url.URL): Promise<string | null> {
const pkgPath = pkgUrl.toString().replace('file://', '');
if (!(await fs.exists(pkgPath))) {
return null;
}
return fs.readFile(pkgPath, 'utf8');
}

function getMavenUrl(
dependency: MavenDependency,
repoUrl: string,
path: string
): url.URL | null {
return new url.URL(`${dependency.dependencyUrl}/${path}`, repoUrl);
}

interface MavenXml {
authorization?: boolean;
xml?: XmlDocument;
}

async function downloadMavenXml(
pkgUrl: url.URL | null
): Promise<MavenXml | null> {
/* istanbul ignore if */
if (!pkgUrl) {
return {};
}
let rawContent: string;
let authorization: boolean;
switch (pkgUrl.protocol) {
case 'file:':
rawContent = await downloadFileProtocol(pkgUrl);
break;
case 'http:':
case 'https:':
({ authorization, body: rawContent } = await downloadHttpProtocol(
pkgUrl
));
break;
case 's3:':
logger.debug('Skipping s3 dependency');
return {};
default:
logger.debug({ url: pkgUrl.toString() }, `Unsupported Maven protocol`);
return {};
}

if (!rawContent) {
logger.debug(`Content is not found for Maven url: ${pkgUrl.toString()}`);
return {};
}

return { authorization, xml: new XmlDocument(rawContent) };
}

async function getDependencyInfo(
dependency: MavenDependency,
repoUrl: string,
version: string
): Promise<Partial<ReleaseResult>> {
const result: Partial<ReleaseResult> = {};
const path = `${version}/${dependency.name}-${version}.pom`;

const pomUrl = getMavenUrl(dependency, repoUrl, path);
const { xml: pomContent } = await downloadMavenXml(pomUrl);
if (!pomContent) {
return result;
}

const homepage = pomContent.valueWithPath('url');
if (homepage && !containsPlaceholder(homepage)) {
result.homepage = homepage;
}

const sourceUrl = pomContent.valueWithPath('scm.url');
if (sourceUrl && !containsPlaceholder(sourceUrl)) {
result.sourceUrl = sourceUrl.replace(/^scm:/, '');
}

return result;
}

function isStableVersion(x: string): boolean {
return mavenVersion.isStable(x);
}
Expand All @@ -121,24 +40,6 @@ function getLatestStableVersion(releases: Release[]): string | null {
return null;
}

interface MavenDependency {
display: string;
group?: string;
name?: string;
dependencyUrl: string;
}

function getDependencyParts(lookupName: string): MavenDependency {
const [group, name] = lookupName.split(':');
const dependencyUrl = `${group.replace(/\./g, '/')}/${name}`;
return {
display: lookupName,
group,
name,
dependencyUrl,
};
}

function extractVersions(metadata: XmlDocument): string[] {
const versions = metadata.descendantWithPath('versioning.versions');
const elements = versions?.childrenNamed('version');
Expand Down
13 changes: 13 additions & 0 deletions lib/datasource/maven/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { XmlDocument } from 'xmldoc';

export interface MavenDependency {
display: string;
group?: string;
name?: string;
dependencyUrl: string;
}

export interface MavenXml {
authorization?: boolean;
xml?: XmlDocument;
}
97 changes: 97 additions & 0 deletions lib/datasource/maven/util.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import url from 'url';
import fs from 'fs-extra';
import { XmlDocument } from 'xmldoc';
import { HOST_DISABLED } from '../../constants/error-messages';
import { logger } from '../../logger';
import { ExternalHostError } from '../../types/errors/external-host-error';
import { Http, HttpResponse } from '../../util/http';

import type { ReleaseResult } from '../types';
import { MAVEN_REPO, id } from './common';
import type { MavenDependency, MavenXml } from './types';

const http: Record<string, Http> = {};

Expand Down Expand Up @@ -96,6 +100,14 @@ export async function downloadHttpProtocol(
}
}

async function downloadFileProtocol(pkgUrl: url.URL): Promise<string | null> {
const pkgPath = pkgUrl.toString().replace('file://', '');
if (!(await fs.exists(pkgPath))) {
return null;
}
return fs.readFile(pkgPath, 'utf8');
}

export async function isHttpResourceExists(
pkgUrl: url.URL | string,
hostType = id
Expand All @@ -119,3 +131,88 @@ export async function isHttpResourceExists(
return null;
}
}

function containsPlaceholder(str: string): boolean {
return /\${.*?}/g.test(str);
}

export function getMavenUrl(
dependency: MavenDependency,
repoUrl: string,
path: string
): url.URL | null {
return new url.URL(`${dependency.dependencyUrl}/${path}`, repoUrl);
}

export async function downloadMavenXml(
pkgUrl: url.URL | null
): Promise<MavenXml | null> {
/* istanbul ignore if */
if (!pkgUrl) {
return {};
}
let rawContent: string;
let authorization: boolean;
switch (pkgUrl.protocol) {
case 'file:':
rawContent = await downloadFileProtocol(pkgUrl);
break;
case 'http:':
case 'https:':
({ authorization, body: rawContent } = await downloadHttpProtocol(
pkgUrl
));
break;
case 's3:':
logger.debug('Skipping s3 dependency');
return {};
default:
logger.debug({ url: pkgUrl.toString() }, `Unsupported Maven protocol`);
return {};
}

if (!rawContent) {
logger.debug(`Content is not found for Maven url: ${pkgUrl.toString()}`);
return {};
}

return { authorization, xml: new XmlDocument(rawContent) };
}

export async function getDependencyInfo(
dependency: MavenDependency,
repoUrl: string,
version: string
): Promise<Partial<ReleaseResult>> {
const result: Partial<ReleaseResult> = {};
const path = `${version}/${dependency.name}-${version}.pom`;

const pomUrl = getMavenUrl(dependency, repoUrl, path);
const { xml: pomContent } = await downloadMavenXml(pomUrl);
if (!pomContent) {
return result;
}

const homepage = pomContent.valueWithPath('url');
if (homepage && !containsPlaceholder(homepage)) {
result.homepage = homepage;
}

const sourceUrl = pomContent.valueWithPath('scm.url');
if (sourceUrl && !containsPlaceholder(sourceUrl)) {
result.sourceUrl = sourceUrl.replace(/^scm:/, '');
}

return result;
}

export function getDependencyParts(lookupName: string): MavenDependency {
const [group, name] = lookupName.split(':');
const dependencyUrl = `${group.replace(/\./g, '/')}/${name}`;
return {
display: lookupName,
group,
name,
dependencyUrl,
};
}

0 comments on commit ca9ed19

Please sign in to comment.