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
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);
|
|
}
|