// // Preference access. Every key may be overridden per-workspace; workspace // values win when they are actually set, otherwise the global value applies. // const DEFAULTS = { "gitea.baseUrl": "https://gitea.com", "gitea.discovery.mode": "workspace", "gitea.refresh.runningIntervalSeconds": 15, "gitea.refresh.idleIntervalSeconds": 60, "gitea.maxRunsPerRepo": 20, "gitea.maxJobsPerRun": 50, "gitea.reviewComments.enabled": true, "gitea.jobLogs.saveToRepo": true, "gitea.artifacts.downloadPath": ".tmp/gitea-artifacts/", "gitea.notifications.failedRuns": true, "gitea.branchFilter": "current", }; function isUnset(value) { return value === null || value === undefined || value === ""; } function get(key, type) { let value = null; if (nova.workspace && nova.workspace.config) { value = nova.workspace.config.get(key, type); } if (isUnset(value)) { value = nova.config.get(key, type); } if (isUnset(value)) { value = DEFAULTS[key]; } return isUnset(value) ? null : value; } function num(key) { const value = Number(get(key, "number")); return Number.isFinite(value) ? value : DEFAULTS[key]; } function bool(key) { const value = get(key, "boolean"); return value === null ? DEFAULTS[key] === true : value === true; } /** List preferences merge the workspace's entries on top of the global ones. */ function arrayPref(key) { const globalEntries = nova.config.get(key, "array") || []; const workspaceEntries = (nova.workspace && nova.workspace.config && nova.workspace.config.get(key, "array")) || []; return [...globalEntries, ...workspaceEntries]; } /** Trailing slashes make every later URL join ambiguous, so strip them once here. */ function normalizeBaseUrl(url) { if (!url) return null; let trimmed = String(url).trim().replace(/\/+$/, ""); if (!trimmed) return null; if (!/^https?:\/\//i.test(trimmed)) trimmed = "https://" + trimmed; return trimmed; } /** The default instance plus any extras, de-duplicated and order-preserving. */ function instances() { const list = []; const seen = new Set(); const add = (url) => { const normalized = normalizeBaseUrl(url); if (normalized && !seen.has(normalized)) { seen.add(normalized); list.push(normalized); } }; add(get("gitea.baseUrl", "string")); for (const url of arrayPref("gitea.instances")) add(url); return list; } function setInstances(list) { const cleaned = []; const primary = normalizeBaseUrl(get("gitea.baseUrl", "string")); for (const url of list) { const normalized = normalizeBaseUrl(url); if (normalized && normalized !== primary && !cleaned.includes(normalized)) { cleaned.push(normalized); } } nova.config.set("gitea.instances", cleaned); } function branchFilter() { const custom = get("gitea.branchFilter.custom", "string"); if (!isUnset(custom)) return { mode: "custom", branch: String(custom).trim() }; const mode = get("gitea.branchFilter", "string"); return { mode: mode === "all" ? "all" : "current", branch: null }; } function setBranchFilter(mode, branch) { const scope = nova.workspace && nova.workspace.path ? nova.workspace.config : nova.config; if (mode === "custom") { scope.set("gitea.branchFilter", "current"); scope.set("gitea.branchFilter.custom", branch); } else { scope.set("gitea.branchFilter", mode); scope.remove("gitea.branchFilter.custom"); } } /** * Raw "remote-host = instance" entries. Some servers answer SSH on a different * hostname than the web UI, which would otherwise leave those remotes matching * no instance at all. */ function hostAliasEntries() { return arrayPref("gitea.hostAliases"); } /** * Appends an alias, replacing any existing entry for the same remote host. * Returns false and writes nothing when the preference already says this, so * auto-detection cannot bounce the change observers. */ function addHostAlias(host, baseUrl) { const key = String(host).trim().toLowerCase(); const entry = `${key} = ${baseUrl}`; const current = nova.config.get("gitea.hostAliases", "array") || []; const kept = current.filter((existing) => { const left = String(existing).split(/\s*(?:=>|->|=)\s*/)[0]; return String(left).trim().toLowerCase() !== key; }); const next = [...kept, entry]; if (next.length === current.length && next.every((value, i) => value === current[i])) { return false; } nova.config.set("gitea.hostAliases", next); return true; } exports.get = get; exports.num = num; exports.bool = bool; exports.instances = instances; exports.setInstances = setInstances; exports.hostAliasEntries = hostAliasEntries; exports.addHostAlias = addHostAlias; exports.normalizeBaseUrl = normalizeBaseUrl; exports.branchFilter = branchFilter; exports.setBranchFilter = setBranchFilter; exports.discoveryMode = () => get("gitea.discovery.mode", "string") || "workspace"; exports.maxRuns = () => num("gitea.maxRunsPerRepo"); exports.maxJobs = () => num("gitea.maxJobsPerRun"); exports.runningInterval = () => num("gitea.refresh.runningIntervalSeconds"); exports.idleInterval = () => num("gitea.refresh.idleIntervalSeconds"); exports.reviewCommentsEnabled = () => bool("gitea.reviewComments.enabled"); exports.saveLogsToRepo = () => bool("gitea.jobLogs.saveToRepo"); exports.notifyFailedRuns = () => bool("gitea.notifications.failedRuns"); exports.artifactDownloadPath = () => get("gitea.artifacts.downloadPath", "string") || ".tmp/gitea-artifacts/";