feat: teai role

This commit is contained in:
ydc3148
2026-09-14 16:13:02 +08:00
parent 8735e35db6
commit 540718dda7
12 changed files with 416 additions and 120 deletions
+11 -20
View File
@@ -1,9 +1,8 @@
// config.go — tea 相容登入組態的讀取與行級編輯。
// config.go — teai 登入組態的讀取與行級編輯。
//
// teai 與 tea 共用同一份組態檔(README 設計原則 5),因此寫入採「行級編輯」:
// 只修改目標登入項目的所屬行,其餘內容(未知欄位、註解、preferences 區段、
// 空行與縮排)逐字保留,避免改壞 tea 也在使用的檔案。新增項目依 tea 實際
// 寫出的欄位順序輸出,讓檔案外觀與 tea 一致。
// 組態由 teai 自行管理(README 設計原則 5),不依賴 tea。寫入採「行級編輯」:
// 只修改目標登入項目的所屬行,其餘內容(未知欄位、註解、空行與縮排)逐字
// 保留。新增項目只寫 teai 使用的欄位:name/url/token/default/user。
//
// token 值只會進出這個套件的資料結構與組態檔本身,永遠不出現在錯誤訊息。
package gitea
@@ -18,7 +17,7 @@ import (
"strings"
)
// LoginEntry 是組態檔中的一筆登入資料(編輯用,含 tea 的 user 欄位)。
// LoginEntry 是組態檔中的一筆登入資料(編輯用,含 user 欄位)。
type LoginEntry struct {
Name string
URL string
@@ -43,7 +42,7 @@ type configDoc struct {
}
// parseConfigDoc 掃描組態內容,定位 logins 清單與各項目的行範圍。
// 只認識 tea 實際寫出的格式:頂層 `logins:` 加縮排的 `- key: value` 項目;
// 只認識 teai 寫出的格式:頂層 `logins:` 加縮排的 `- key: value` 項目;
// 其餘行原樣保留在 lines 中。
func parseConfigDoc(data []byte) configDoc {
doc := configDoc{lines: splitLines(data), loginsHeader: -1, itemIndent: " "}
@@ -103,7 +102,7 @@ func (d configDoc) findItem(name string) int {
return -1
}
// fieldIndent 回傳項目內屬性行的縮排(項目縮排 + 兩格,tea 的格式)。
// fieldIndent 回傳項目內屬性行的縮排(項目縮排 + 兩格)。
func (d configDoc) fieldIndent() string {
return d.itemIndent + " "
}
@@ -168,7 +167,7 @@ func ListLoginsFile(path string) ([]LoginEntry, error) {
// UpsertLogin 新增或更新名為 e.Name 的登入。
//
// 已存在則就地更新 url/token/user/default(保留其他欄位與行);不存在則
// 依 tea 的欄位順序插入新項目。makeDefault 為 true 時將其設為預設並取消
// 依 teai 的欄位順序插入新項目。makeDefault 為 true 時將其設為預設並取消
// 其他登入的預設旗標;新增後若成為唯一登入也自動成為預設。
// 回傳新內容與最終生效的項目值。
func UpsertLogin(data []byte, e LoginEntry, makeDefault bool) ([]byte, LoginEntry, error) {
@@ -326,7 +325,7 @@ func setFieldInItem(lines []string, it loginItemSpan, key, value, fieldIndent st
return append(out, lines[it.end:]...)
}
// newLoginBlock 產生 tea 格式的新登入項目(欄位順序與 tea 實際寫出的一致)。
// newLoginBlock 產生 teai 格式的新登入項目(name/url/token/default/user)。
func newLoginBlock(itemIndent, name, url, token string, isDefault bool, user string) []string {
f := itemIndent + " "
return []string{
@@ -334,15 +333,7 @@ func newLoginBlock(itemIndent, name, url, token string, isDefault bool, user str
f + "url: " + yamlScalar(url),
f + "token: " + yamlScalar(token),
f + "default: " + strconv.FormatBool(isDefault),
f + `ssh_host: ""`,
f + `ssh_key: ""`,
f + "insecure: false",
f + `ssh_certificate_principal: ""`,
f + "ssh_agent: false",
f + `ssh_key_agent_pub: ""`,
f + "version_check: false",
f + "user: " + yamlScalar(user),
f + "created: 0",
}
}
@@ -385,9 +376,9 @@ func joinLines(lines []string) []byte {
return []byte(s)
}
// SaveTeaConfigFile 把組態內容原子寫入 path:先寫同目錄暫存檔(0600),
// SaveConfigFile 把組態內容原子寫入 path:先寫同目錄暫存檔(0600),
// 再 rename 取代,避免半寫入狀態。必要時建立上層目錄(0700)。
func SaveTeaConfigFile(path string, data []byte) error {
func SaveConfigFile(path string, data []byte) error {
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0o700); err != nil {
return fmt.Errorf("gitea: create config dir: %w", err)