Sync Feature: manual #2

Merged
someone merged 13 commits from sync/manual-20260425-0644 into main 2026-04-25 00:03:07 +00:00
Showing only changes of commit 057d7926be - Show all commits
+106
View File
@@ -0,0 +1,106 @@
/**
* GiteaClient - Low-level API wrapper for Gitea Git Hosting
*/
/**
* Helper to ensure the base URL always points to the Gitea API root (/api/v1)
* @return {string} Normalized API base URL
*/
function getGiteaApiBaseUrl_() {
const config = getGiteaConfig();
let baseUrl = config.baseUrl.replace(/\/$/, ''); // Remove trailing slash
// Ensure the URL ends with /api/v1
if (!baseUrl.endsWith('/api/v1')) {
baseUrl += '/api/v1';
}
return baseUrl;
}
function giteaRequest_(method, path, payload = null) {
const apiBaseUrl = getGiteaApiBaseUrl_();
const config = getGiteaConfig();
// Ensure path starts with a single slash
const normalizedPath = path.startsWith('/') ? path : '/' + path;
const url = `${apiBaseUrl}${normalizedPath}`;
console.log(`Gitea Request: [${method}] ${url}`);
const options = {
method: method,
headers: {
'Authorization': `token ${config.token}`,
'Content-Type': 'application/json'
},
muteHttpExceptions: true
};
if (payload) {
options.payload = JSON.stringify(payload);
}
try {
const response = UrlFetchApp.fetch(url, options);
const code = response.getResponseCode();
const rawContent = response.getContentText();
let json;
try {
json = JSON.parse(rawContent);
} catch (e) {
json = null; // Not a JSON response
}
if (code >= 200 && code < 300) {
return { ok: true, data: json || rawContent };
}
// Return structured error with raw body if JSON parsing failed
return {
ok: false,
message: json && json.message ? json.message : `Gitea API Error ${code}`,
code: code,
rawBody: rawContent
};
} catch (e) {
return { ok: false, message: `Gitea Connection Error: ${e.message}` };
}
}
function getGiteaRepo() {
const config = getGiteaConfig();
// Path is relative to /api/v1
return giteaRequest_('GET', `/repos/${config.owner}/${config.repo}`);
}
function createGiteaIssue(title, body) {
const config = getGiteaConfig();
return giteaRequest_('POST', `/repos/${config.owner}/${config.repo}/issues`, {
title: title,
body: body
});
}
function createOrUpdateRepoFile(path, content, message, branch) {
const config = getGiteaConfig();
const targetBranch = branch || config.branch;
// Gitea requires SHA for updates. This is a simplified boilerplate.
return giteaRequest_('POST', `/repos/${config.owner}/${config.repo}/contents/${path}`, {
content: content,
message: message,
branch: targetBranch
});
}
function createReleaseTag(tagName, name, body, target) {
const config = getGiteaConfig();
return giteaRequest_('POST', `/repos/${config.owner}/${config.repo}/releases`, {
tag_name: tagName,
name: name,
body: body,
target_commitish: target || config.branch
});
}