mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-22 17:22:47 +00:00
* feat(plugins): support prepared Git installations Let Git plugins declare explicit preparation commands without making package installation the default. Keep installation transactional, make plugin trust explicit, and use one canonical source reference for monorepos. * fix(plugins): parse Windows source references
48 lines
1.7 KiB
TypeScript
48 lines
1.7 KiB
TypeScript
export interface PluginSourceReference {
|
|
source: string;
|
|
pluginPath: string | undefined;
|
|
}
|
|
|
|
export function parsePluginSourceReference(reference: string): PluginSourceReference {
|
|
const separator = reference.lastIndexOf(":");
|
|
if (separator === -1) return { source: reference, pluginPath: undefined };
|
|
|
|
const pluginPath = reference.slice(separator + 1);
|
|
if (!isPortableRelativePluginPath(pluginPath)) {
|
|
return { source: reference, pluginPath: undefined };
|
|
}
|
|
|
|
const scheme = reference.indexOf("://");
|
|
if (scheme !== -1) {
|
|
const pathStart = reference.indexOf("/", scheme + 3);
|
|
if (pathStart === -1 || separator < pathStart) {
|
|
return { source: reference, pluginPath: undefined };
|
|
}
|
|
} else {
|
|
const scpSeparator = reference.match(/^[^/@\s]+@[^:\s]+:/)?.[0].length;
|
|
if (scpSeparator !== undefined && separator === scpSeparator - 1) {
|
|
return { source: reference, pluginPath: undefined };
|
|
}
|
|
}
|
|
|
|
return { source: reference.slice(0, separator), pluginPath };
|
|
}
|
|
|
|
export function formatPluginSourceReference(
|
|
source: string,
|
|
pluginPath: string | undefined,
|
|
): string {
|
|
if (pluginPath === undefined) return source;
|
|
if (!isPortableRelativePluginPath(pluginPath)) {
|
|
throw new Error("Plugin path must be a portable path relative to the repository");
|
|
}
|
|
return `${source}:${pluginPath}`;
|
|
}
|
|
|
|
function isPortableRelativePluginPath(pluginPath: string): boolean {
|
|
if (pluginPath === ".") return true;
|
|
if (!pluginPath || pluginPath.startsWith("/") || pluginPath.startsWith("\\")) return false;
|
|
if (/^[A-Za-z]:/.test(pluginPath) || pluginPath.includes(":")) return false;
|
|
return pluginPath.split(/[\\/]/).every((part) => part !== "" && part !== "." && part !== "..");
|
|
}
|