You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
6.2 KiB

import exclusions from "./data/exclude.json" assert { type: "json" };
import * as fs from "fs";
import { exec } from "child_process";
import { parseString } from "xml2js";
import {
SVNList,
ExternalComponent,
SVNProperties,
DirType,
InternalComponent,
} from "./types.js";
import { parseExternals } from "./parser.js";
function execShellCommand(cmd: string) {
return new Promise((resolve) => {
exec(cmd, { maxBuffer: 1024 * 500 }, (error, stdout, stderr) => {
if (error) {
console.warn(error);
}
resolve(stdout || stderr);
});
});
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function svnCmdWithResponse(
cmd: string,
baseUrl: string,
url: string,
returnRaw = false
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): Promise<any> {
return new Promise((resolve, reject) => {
const execCommand = `svn ${cmd} "${baseUrl}${url}" --xml`;
execShellCommand(execCommand)
.then((svnCmdResponse) => {
parseString(
svnCmdResponse as SVNList | SVNProperties,
(err, result) => {
if (err) {
reject(err);
return;
}
if (returnRaw) {
resolve(result);
} else {
const json = JSON.stringify(result);
const svnCmdResponseJson = JSON.parse(json);
resolve(svnCmdResponseJson);
}
}
);
})
.catch((error) => {
reject(error);
});
});
}
export async function svnList(
baseUrl: string,
url: string
): Promise<InternalComponent[]> {
try {
const svnListResponse: InternalComponent[] = await svnCmdWithResponse(
"list",
baseUrl,
url,
false
);
type arrayOfSVNList = {
name: string[];
};
const internals = svnListResponse.lists.list[0].entry.map(
({ name }: arrayOfSVNList) => `${name[0]}`
);
const excludeJson = fs.readFileSync("./dist/data/exclude.json", "utf-8");
const exclude = JSON.parse(excludeJson);
// const parsedExclusions = exclusions;
const filteredInternals = internals.filter(
(internal: string) => !exclusions.includes(internal)
);
// const internals = listResponse.lists.list[0].entry;
return filteredInternals;
} catch (error) {
console.log(error);
return [];
}
}
async function svnCmdWithoutResponse(
cmd: string,
localPath: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): Promise<any> {
return new Promise((resolve, reject) => {
const execCommand = `svn ${cmd} "${localPath}"`;
execShellCommand(execCommand)
.then((svnCmdResponse) => {
console.log(`Performed ${execCommand}`);
resolve(svnCmdResponse);
})
.catch((error) => {
reject(error);
});
});
}
export async function svnUpdate(localPath: string): Promise<void> {
try {
await svnCmdWithoutResponse("cleanup", localPath);
} catch (error) {
console.log(error);
}
try {
await svnCmdWithoutResponse("update", localPath);
} catch (error) {
console.log(error);
}
}
export async function svnPropGet(
property: string,
baseUrl: string,
url: string
): Promise<[ExternalComponent]> {
const propGetResponse = await svnCmdWithResponse(
`propget ${property}`,
baseUrl,
url,
true
);
const rawExternals: string =
propGetResponse.properties.target[0].property[0]._;
return parseExternals(rawExternals);
}
export async function svnTagsBranchesList(
dirType: DirType,
baseUrl: string,
url: string, // expects url that has tags and branches
latestOnly = false
): Promise<string[]> {
try {
url = url.replace(/trunk$/, "");
url = url.replace(/tags$/, "");
url = url.replace(/branches$/, "");
url = dirType === "tags" ? url.concat("/tags") : url.concat("/branches");
const svnListResponse: SVNList = await svnCmdWithResponse(
"list",
baseUrl,
url
);
const regex = /^[0-9.]+$/; // Regular expression for semantic version format
type arrayOfSVNList = {
name: string[];
};
if (
Object.prototype.hasOwnProperty.call(
svnListResponse.lists.list[0],
"entry"
)
) {
// filter any tag or branch version which do not comply with the format 0.0.0 / 0.0.0.0
const filteredTags = svnListResponse.lists.list[0].entry.filter(
(entry: arrayOfSVNList) => {
return regex.test(entry.name[0]);
}
);
// only leave the name in the objects, get rid of the hyrachical structure
let flattenedFilteredTags: string[] = filteredTags.map(
({ name }) => `${name[0]}`
);
flattenedFilteredTags.sort((a, b) => {
const partsA = a.split(".").map(Number);
const partsB = b.split(".").map(Number);
for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
const partA = partsA[i] || 0;
const partB = partsB[i] || 0;
if (partA > partB) {
return -1;
} else if (partA < partB) {
return 1;
}
}
return 0;
});
flattenedFilteredTags.sort((a, b) => b.localeCompare(a));
flattenedFilteredTags = flattenedFilteredTags.map(
(element) => (element = `/${dirType}/${element}`)
);
if (latestOnly) {
return [flattenedFilteredTags[0]];
} else {
return flattenedFilteredTags;
}
}
} catch (error) {
console.log(`${url} does not have a ${dirType}: ${error}`);
return [];
}
}
export async function svnGetLatestTag(
baseUrl: string,
url: string
): Promise<string[]> {
return svnTagsBranchesList(DirType.tags, baseUrl, url, true);
}
export async function svnGetLatestBranch(
baseUrl: string,
url: string
): Promise<string[]> {
return svnTagsBranchesList(DirType.branches, baseUrl, url, true);
}
export async function svnGetTagList(
baseUrl: string,
url: string
): Promise<string[]> {
return svnTagsBranchesList(DirType.tags, baseUrl, url, false);
}
export async function svnGetBranchesList(
baseUrl: string,
url: string
): Promise<string[]> {
return svnTagsBranchesList(DirType.branches, baseUrl, url, false);
}

Powered by TurnKey Linux.