Merge pull request 'fix/skillset-audit-compliance-and-guard-fixes' (#17) from fix/skillset-audit-compliance-and-guard-fixes into develop
Reviewed-on: #17
This commit was merged in pull request #17.
This commit is contained in:
@@ -43,7 +43,7 @@
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/hooks.git"
|
||||
},
|
||||
"description": "跨 CLI hooks:STE100 語言強制、工時計時、技能用量記錄"
|
||||
"description": "跨 CLI hooks:STE100 語言強制、工時計時、技能用量記錄、SDLC 模型鎖、版本前置檢查"
|
||||
},
|
||||
{
|
||||
"name": "jsc-log",
|
||||
@@ -75,7 +75,7 @@
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/review.git"
|
||||
},
|
||||
"description": "程式碼審查:Refactoring 壞味道六組 + 註解規範 + 淺模組"
|
||||
"description": "程式碼審查:Refactoring 壞味道六組、註解規範、淺模組"
|
||||
},
|
||||
{
|
||||
"name": "jsc-sdlc",
|
||||
@@ -83,7 +83,7 @@
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/sdlc.git"
|
||||
},
|
||||
"description": "開發生命週期:規劃/分析/實作/維護(wiki 追蹤)"
|
||||
"description": "開發生命週期:規劃、分析、實作、維護(wiki 追蹤)"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/hooks.git"
|
||||
},
|
||||
"description": "跨 CLI hooks:STE100 語言強制、工時計時、技能用量記錄"
|
||||
"description": "跨 CLI hooks:STE100 語言強制、工時計時、技能用量記錄、SDLC 模型鎖、版本前置檢查"
|
||||
},
|
||||
{
|
||||
"name": "jsc-log",
|
||||
@@ -75,7 +75,7 @@
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/review.git"
|
||||
},
|
||||
"description": "程式碼審查:Refactoring 壞味道六組 + 註解規範 + 淺模組"
|
||||
"description": "程式碼審查:Refactoring 壞味道六組、註解規範、淺模組"
|
||||
},
|
||||
{
|
||||
"name": "jsc-sdlc",
|
||||
@@ -83,7 +83,7 @@
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/sdlc.git"
|
||||
},
|
||||
"description": "開發生命週期:規劃/分析/實作/維護(wiki 追蹤)"
|
||||
"description": "開發生命週期:規劃、分析、實作、維護(wiki 追蹤)"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jsc-gitea",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.2",
|
||||
"description": "Gitea API 工具、Wiki 讀寫與存取庫批次同步",
|
||||
"skills": "./skills",
|
||||
"author": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jsc-gitea",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.2",
|
||||
"description": "Gitea API 工具、Wiki 讀寫與存取庫批次同步",
|
||||
"skills": "./skills"
|
||||
}
|
||||
|
||||
@@ -35,12 +35,21 @@ gitea.sh wiki-put <owner>/<repo> <page> <file> # 自動判斷新建或更新
|
||||
gitea.sh wiki-url <owner>/<repo> <page> # 印出 wiki 頁絕對網址(取自 API 的 html_url);跨存取庫連結用
|
||||
gitea.sh pr-create <owner>/<repo> <head> <base> <title> <body-file>
|
||||
gitea.sh pr-status <owner>/<repo> <pr-index> # 印出 {state} {merged} {mergeable}
|
||||
gitea.sh pr-comments <owner>/<repo> <pr-index> # 所有留言(issue/審查/行內),依時間排序
|
||||
gitea.sh pr-comments <owner>/<repo> <pr-index> # 印出所有留言(issue 留言、審查評語、行內留言),依時間排序
|
||||
gitea.sh pr-depend <owner>/<repo> <pr-index> <dep-owner>/<dep-repo> <dep-index>
|
||||
# 把 PR 掛上前置 PR 依賴;依賴未關閉前 Gitea 會阻擋合併
|
||||
gitea.sh repo-set <owner>/<repo> <description> [website] # 設定 repo 描述與網頁
|
||||
gitea.sh api <METHOD> <path> [json-file]
|
||||
hash-id <text> # 與 gitea.sh hash-id 相同
|
||||
repo-sync.sh <owner>/<repo> [target-dir] # 同步單一存取庫;印出 cloned、updated、dirty {分支} 或 failed {原因}
|
||||
# 基準分支的優先序只在這支腳本裡;dirty 會把解析好的分支帶出來當 PR 的 base
|
||||
check-wiki-rules.sh # 驗證 wiki repo 解析與 hash fallback 規則
|
||||
```
|
||||
|
||||
## 參考資料
|
||||
|
||||
- `references/wiki-links.md`:寫 wiki 頁才需要的連結規則。同類型用 `[[顯示文字|頁名]]`(顯示文字在左),跨類型用 `wiki-url` 給的絕對網址。
|
||||
|
||||
## Skills 目錄
|
||||
|
||||
呼叫方式:Claude / Antigravity `/jsc-gitea:{name}`;Codex `${name}`;Copilot / Kiro 描述需求自動觸發。
|
||||
@@ -49,11 +58,11 @@ check-wiki-rules.sh # 驗證 wiki repo 解析與 ha
|
||||
|
||||
### `wiki`
|
||||
|
||||
Gitea wiki 頁讀寫的統一入口:依頁面類型(QUESTION / PLAN / ANALYZE / DELIVER / MAINTAIN / REPO / LOG / LEARN / ERROR)解析 wiki 所在的 `{owner}/{repo}`,先讀對應的 `JSC_WIKI_REPO_{TYPE}`,再退回 `JSC_WIKI_REPO`,不同類型不可互相代用。頁面內容以圖表優先(mermaid 圖、markdown 表格),純文字為最後手段。
|
||||
Gitea wiki 頁讀寫的統一入口:依頁面類型(QUESTION / PLAN / ANALYZE / DELIVER / MAINTAIN / REPO / LOG / LEARN / ERROR)解析 wiki 所在的 `{owner}/{repo}`,先讀對應的 `JSC_WIKI_REPO_{TYPE}`,再退回 `JSC_WIKI_REPO`,不同類型不可互相代用。頁面內容以圖表優先(mermaid 圖、markdown 表格),純文字每節最多三句。
|
||||
|
||||
### `repo-sync`
|
||||
|
||||
存取庫批次同步:列出 owner → 使用者選擇 → 逐 repo(sub agent)clone 或切 develop/master 更新;有變更就開分支 commit、push、PR。
|
||||
存取庫批次同步:列出 owner → 使用者選擇 → 逐 repo(sub agent)呼叫 `tools/repo-sync.sh` clone 或更新;回報 `dirty {分支}` 的存取庫交給 `jsc-git:pr`,base 直接用腳本帶出來的那個分支。
|
||||
|
||||
<!-- JSC-SKILLS:END -->
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jsc-gitea",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.2",
|
||||
"description": "Gitea API 工具、Wiki 讀寫與存取庫批次同步",
|
||||
"skills": "./skills/"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Wiki 頁之間的連結
|
||||
|
||||
寫 wiki 頁才需要這份規則。兩條規則任一條寫錯,連結會指向一個不存在的頁,畫面上看不出異常。
|
||||
|
||||
## 方向:顯示文字在左,頁名在右
|
||||
|
||||
Gitea 採 GitHub/Gollum 慣例:`[[顯示文字|頁名]]`。方向與 MediaWiki 相反。Gitea 原始碼(`modules/markup/html_link.go`)寫得很清楚:
|
||||
|
||||
> MediaWiki uses [[link|text]], while GitHub uses [[text|link]] … we prefer GitHub syntax
|
||||
|
||||
所以 `[[PLAN_H1234567|我的計畫]]` 會顯示成文字 `PLAN_H1234567`,連到一個叫「我的計畫」的頁——這是壞連結。要寫 `[[我的計畫|PLAN_H1234567]]`。
|
||||
|
||||
顯示文字與頁名相同時,用不帶豎線的 `[[PLAN_H1234567]]`,這種寫法不會寫錯。
|
||||
|
||||
## 範圍:`[[...]]` 只在同一個 wiki 內解析
|
||||
|
||||
`[[...]]` 與 markdown 相對連結都只在目前這個 wiki 內解析。跨存取庫沒有 wiki 連結語法。
|
||||
|
||||
| 連結 | 同一個 wiki? | 寫法 |
|
||||
| --- | --- | --- |
|
||||
| 同頁面類型(例:`PLAN_CONTENTS` → `PLAN_{HASH}`) | 一定同一個:一個類型一個存取庫 | `[[顯示文字\|頁名]]` 或 `[[頁名]]` |
|
||||
| 不同頁面類型(例:`LOG_{HASH}` → `PLAN_{HASH}`) | **只有兩個類型解析到同一個存取庫時才同一個** | `wiki-url` 給的絕對網址:`[顯示文字](https://…/wiki/PLAN_…)` |
|
||||
|
||||
每個類型各自解析自己的 `JSC_WIKI_REPO_{TYPE}`,所以跨類型連結**一律**用絕對網址:兩個類型剛好同存取庫也照樣正確,不必分兩種寫法。網址一律取自 `tools/gitea.sh wiki-url`,不要自己組路徑。
|
||||
@@ -1,18 +1,17 @@
|
||||
---
|
||||
name: repo-sync
|
||||
description: Batch-sync all readable repos of a chosen Gitea owner into the working directory. List owners, let the user pick, then clone or update each repo; local changes become a branch, commit, push, and PR to develop or master. Use for workspace bootstrap or bulk refresh; not for a single repo.
|
||||
description: Batch-sync all readable repos of a chosen Gitea owner into the working directory. List owners, let the user pick, then clone or update each repo through tools/repo-sync.sh; a repo reported dirty goes to jsc-git:pr against the base branch that same script reports. Use for workspace bootstrap or bulk refresh; not for a single repo.
|
||||
---
|
||||
|
||||
# repo-sync — batch-sync repositories
|
||||
|
||||
## Steps
|
||||
|
||||
1. Before calling `tools/gitea.sh`, resolve `GITEA_HOST` and `GITEA_TOKEN` from the current shell environment (also check `tea login list` for a usable login token when `GITEA_TOKEN` is unset). If `GITEA_HOST` is unresolvable, or `GITEA_TOKEN` is unset and no tea login token exists either, ask the user for the missing value per the `jsc-ask:ask` rules before proceeding to any `tools/gitea.sh` call.
|
||||
2. Run `tools/gitea.sh owners` to list every `{owner}` the user can read.
|
||||
3. Ask the user which `{owner}` to sync, per the `jsc-ask:ask` rules. Every option states the owner's repo count and impact scope.
|
||||
4. Run `tools/gitea.sh repos {owner}` to list every readable `{repo}` under that owner.
|
||||
1. Before calling `tools/gitea.sh`, resolve `GITEA_HOST` and `GITEA_TOKEN` from the current shell environment (also check `tea login list` for a usable login token when `GITEA_TOKEN` is unset). If `GITEA_HOST` is unresolvable, or `GITEA_TOKEN` is unset and no tea login token exists either, ask the user for the missing value per the `jsc-ask:ask` rules before proceeding to any `tools/gitea.sh` call. Done when `GITEA_HOST` holds a value and either `GITEA_TOKEN` or a tea login token is available.
|
||||
2. Run `tools/gitea.sh owners` to list every `{owner}` the user can read. Done when the command has printed at least one `{owner}`.
|
||||
3. Ask the user which `{owner}` to sync, per the `jsc-ask:ask` rules. Every option states the owner's repo count and impact scope. Done when the user has named exactly one `{owner}` from that list.
|
||||
4. Run `tools/gitea.sh repos {owner}` to list every readable `{repo}` under that owner. Done when the command has printed the full `{owner}/{repo}` list for the chosen owner.
|
||||
5. Sync each `{repo}` one by one. This step **MUST run as a sub agent** (one sub agent per repo):
|
||||
1. Missing locally → `git clone` into the working directory (clone URL from `tools/gitea.sh clone-url`).
|
||||
2. Present locally → switch to `develop`, else `master` (or the result of `tools/gitea.sh default-branch`), then `git pull`.
|
||||
3. Local file changes → create a branch from develop or master, commit via `jsc-git:commit`, push, then open a PR back to develop or master via `jsc-git:pr`.
|
||||
6. Report the sync result for every repo: cloned, updated, PR created, or the failure reason.
|
||||
1. Run `tools/repo-sync.sh {owner}/{repo}`. The script owns the clone-versus-pull decision and the base-branch precedence, so run no `git clone`, `git checkout` or `git pull` by hand, and derive no branch name yourself. Route on its single line of output: `cloned` or `updated` → this repo is done; `dirty {branch}` → go to substep 2; `failed {reason}` → record that reason and stop this repo. Done when exactly one of those four outcomes is recorded for this repo.
|
||||
2. `dirty {branch}` → call `jsc-git:pr` with `{branch}` from that same output line as the base, passed through verbatim. It commits, branches, pushes and opens the PR itself, so add none of those steps. Done when `jsc-git:pr` returns the PR URL.
|
||||
6. Report the sync result for every repo: cloned, updated, PR URL, or the failure reason. Done when every `{repo}` from step 4 carries one of those four results.
|
||||
|
||||
+8
-21
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: wiki
|
||||
description: Read or write a Gitea wiki page through tools/gitea.sh and tools/hash-id. Resolve the wiki repo per page type with JSC_WIKI_REPO_{TYPE} first, then JSC_WIKI_REPO, and ask only when neither is set. Page content is chart-first - prefer mermaid diagrams and markdown tables over plain prose. Used by jsc-ask, jsc-sdlc, and jsc-log for wiki pages, including ERROR pages, not for repo code files.
|
||||
description: Read or write a Gitea wiki page through tools/gitea.sh and tools/hash-id. Resolve the wiki repo per page type with JSC_WIKI_REPO_{TYPE} first, then JSC_WIKI_REPO, and ask only when neither is set. Page content is chart-first - prefer mermaid diagrams and markdown tables over plain prose. Callers are jsc-ask, jsc-sdlc, jsc-log, and jsc-hooks for its ERROR pages. Use for any wiki page in the skill set; not for repo code files.
|
||||
---
|
||||
|
||||
# wiki — read and write Gitea wiki pages
|
||||
@@ -9,11 +9,11 @@ Every wiki operation in the jsc skill set goes through this skill. One entry poi
|
||||
|
||||
## Resolve the wiki location
|
||||
|
||||
Different page types can live in different `{owner}/{repo}` repos, classified by page-name prefix: `QUESTION`, `PLAN`, `ANALYZE`, `DELIVER`, `MAINTAIN`, `REPO`, `LOG`, `LEARN`, `ERROR`.
|
||||
Different page types can live in different `{owner}/{repo}` repos, classified by the page-name prefix.
|
||||
|
||||
1. Before asking the user, inspect the current shell environment for the needed repo variables and Gitea connection variables: `JSC_WIKI_REPO_{TYPE}`, `JSC_WIKI_REPO`, `GITEA_HOST`, and `GITEA_TOKEN` (also check `tea login list` for a usable login token when `GITEA_TOKEN` is unset). Use inherited shell values first; only ask when the needed repo or connection value cannot be resolved after that check. `GITEA_HOST` and `GITEA_TOKEN` are both covered by this ask-if-unresolvable rule, the same as the wiki-repo variables below.
|
||||
2. Run `tools/gitea.sh wiki-repo {TYPE}` (TYPE = the page-name prefix). Allowed types are `QUESTION`, `PLAN`, `ANALYZE`, `DELIVER`, `MAINTAIN`, `REPO`, `LOG`, `LEARN`, and `ERROR`. Resolution order is `JSC_WIKI_REPO_{TYPE}` first, then `JSC_WIKI_REPO`. Never borrow another type's repo.
|
||||
3. On exit 3 (neither is set after env inspection), ask the user for that page type's `{owner}/{repo}` per the `jsc-ask:ask` rules, and suggest setting `JSC_WIKI_REPO_{TYPE}` (can differ per type) or `JSC_WIKI_REPO` (shared default).
|
||||
1. Before asking the user, inspect the current shell environment for the needed repo variables and Gitea connection variables: `JSC_WIKI_REPO_{TYPE}`, `JSC_WIKI_REPO`, `GITEA_HOST`, and `GITEA_TOKEN` (also check `tea login list` for a usable login token when `GITEA_TOKEN` is unset). Use inherited shell values first; only ask when the needed repo or connection value cannot be resolved after that check. Done when every one of those variables is either resolved from the environment or listed as missing.
|
||||
2. Run `tools/gitea.sh wiki-repo {TYPE}` (TYPE = the page-name prefix). Allowed types are `QUESTION`, `PLAN`, `ANALYZE`, `DELIVER`, `MAINTAIN`, `REPO`, `LOG`, `LEARN`, and `ERROR`. Resolution order is `JSC_WIKI_REPO_{TYPE}` first, then `JSC_WIKI_REPO`. Never borrow another type's repo. Done when the command has printed exactly one `{owner}/{repo}`, or exited 3 and sent this page type to step 3.
|
||||
3. On exit 3 (neither is set after env inspection), ask the user for that page type's `{owner}/{repo}` per the `jsc-ask:ask` rules, and suggest setting `JSC_WIKI_REPO_{TYPE}` (can differ per type) or `JSC_WIKI_REPO` (shared default). Done when the user has supplied one `{owner}/{repo}` for that page type.
|
||||
|
||||
## Operations
|
||||
|
||||
@@ -24,20 +24,7 @@ Different page types can live in different `{owner}/{repo}` repos, classified by
|
||||
| write page | write the content to a temp file first, then `tools/gitea.sh wiki-put {owner}/{repo} {page} {file}` (creates or updates automatically) |
|
||||
| page URL | `tools/gitea.sh wiki-url {owner}/{repo} {page}` — the page's absolute URL, taken from the API's `html_url` (exit 4 when the page is missing) |
|
||||
|
||||
## Linking between wiki pages
|
||||
|
||||
Two rules, and getting either wrong produces a link that silently points at a page that does not exist.
|
||||
|
||||
**Direction**: Gitea uses the GitHub/Gollum convention — `[[display text|page name]]`, **display text on the LEFT, page name on the RIGHT**. This is the opposite of MediaWiki. Gitea's own source says so (`modules/markup/html_link.go`): *"MediaWiki uses [[link|text]], while GitHub uses [[text|link]] … we prefer GitHub syntax"*. So `[[PLAN_H1234567|我的計畫]]` renders as the text `PLAN_H1234567` linking to a page named 我的計畫 — broken. Write `[[我的計畫|PLAN_H1234567]]`. When display text and page name are the same, use the no-pipe form `[[PLAN_H1234567]]`, which cannot be got wrong.
|
||||
|
||||
**Scope**: `[[...]]` and relative markdown links both resolve **only inside the current wiki**. There is no cross-repo wiki-link syntax.
|
||||
|
||||
| Link | Same wiki? | Use |
|
||||
| --- | --- | --- |
|
||||
| Same page type (e.g. `PLAN_CONTENTS` → `PLAN_{HASH}`) | Always — one type, one repo | `[[display\|page]]` or `[[page]]` |
|
||||
| Different page type (e.g. `LOG_{HASH}` → `PLAN_{HASH}`) | **Only when both types resolve to the same repo** | Absolute URL from `wiki-url`: `[display](https://…/wiki/PLAN_…)` |
|
||||
|
||||
Because each type resolves its own `JSC_WIKI_REPO_{TYPE}`, a cross-type link **must** use the absolute URL — it stays correct whether or not the two types happen to share a repo, so never branch on that. Get the URL from `wiki-url`, never hand-assemble the path.
|
||||
When writing a page, link same-type pages with the `[[display|page]]` form (display text on the LEFT) and cross-type pages with the absolute URL from `wiki-url`, because `[[...]]` resolves only inside one wiki. Full rules and the direction trap: `references/wiki-links.md`.
|
||||
|
||||
## Rules
|
||||
|
||||
@@ -45,5 +32,5 @@ Because each type resolves its own `JSC_WIKI_REPO_{TYPE}`, a cross-type link **m
|
||||
2. Use `tools/hash-id` for `{HASH}` values. It returns the first 8 uppercase SHA-1 hex chars, or `H` plus the first 7 chars when the raw hash starts with `0-9`, `A`, `B`, or `C`.
|
||||
3. To update a contents page (`*_CONTENTS`): `wiki-get` it first, apply the template to append or modify, then `wiki-put` the whole page back. Never overwrite entries owned by others.
|
||||
4. Write all wiki content in UTF-8 Traditional Chinese, per the STE100 output rule.
|
||||
5. Prefer visual forms for page content: use mermaid diagrams (flowchart, sequence, gantt, pie) and markdown tables wherever the information allows. Plain running text is the last resort, kept short.
|
||||
6. Authentication fallback is built into `tools/gitea.sh`: on a missing GITEA_TOKEN or a 401/403 response it retries with the tea CLI login token automatically. But before calling it, resolve `GITEA_HOST` and `GITEA_TOKEN` per rule 1: if `GITEA_HOST` is unresolvable, or `GITEA_TOKEN` is unset and no tea login token exists either, ask the user for the missing value per the `jsc-ask:ask` rules — same decision-tree pattern as the missing-wiki-repo case above — before calling `tools/gitea.sh`. Only report a genuine failure when the user has no answer to give or Gitea itself rejects the request (e.g. a 401/403 even after the tea fallback).
|
||||
5. Prefer visual forms for page content: use mermaid diagrams (flowchart, sequence, gantt, pie) and markdown tables wherever the information allows. Prose is capped at 3 sentences per section, and a sentence stays only when neither a mermaid diagram nor a markdown table can carry the same information.
|
||||
6. `tools/gitea.sh` retries once with the tea CLI login token when `GITEA_TOKEN` is missing or the response is 401/403. Report a failure only after that retry also fails.
|
||||
|
||||
+46
-34
@@ -1,11 +1,15 @@
|
||||
#!/usr/bin/env sh
|
||||
# check-wiki-rules — 驗證 wiki repo 解析與 hash-id 規則。
|
||||
# 涵蓋全部九種頁面類型,每種三項:專用變數優先、退回共用變數、不得跨類型代用。
|
||||
# 全部通過印 OK 並 exit 0;任一項不符印出差異並 exit 1。
|
||||
set -eu
|
||||
|
||||
dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
gitea="$dir/gitea.sh"
|
||||
hash_id="$dir/hash-id"
|
||||
|
||||
TYPES='QUESTION PLAN ANALYZE DELIVER MAINTAIN REPO LOG LEARN ERROR'
|
||||
|
||||
fail() {
|
||||
printf '%s\n' "$1" >&2
|
||||
exit 1
|
||||
@@ -18,7 +22,7 @@ expect_eq() {
|
||||
[ "$got" = "$want" ] || fail "$label: want=$want got=$got"
|
||||
}
|
||||
|
||||
check_repo() {
|
||||
check_repo() { # type label want [VAR=值...]
|
||||
type=$1
|
||||
label=$2
|
||||
want=$3
|
||||
@@ -27,6 +31,19 @@ check_repo() {
|
||||
expect_eq "$got" "$want" "$label"
|
||||
}
|
||||
|
||||
check_no_repo() { # type label [VAR=值...]:期望 exit 3 且不印出任何 {owner}/{repo}
|
||||
type=$1
|
||||
label=$2
|
||||
shift 2
|
||||
if got=$(env -i PATH="${PATH:-/usr/bin:/bin}" "$@" "$gitea" wiki-repo "$type" 2>/dev/null); then
|
||||
code=0
|
||||
else
|
||||
code=$?
|
||||
fi
|
||||
[ "$code" -eq 3 ] || fail "$label: want exit=3 got exit=$code output=$got"
|
||||
[ -z "$got" ] || fail "$label: want no output got=$got"
|
||||
}
|
||||
|
||||
check_hash() {
|
||||
input=$1
|
||||
want=$2
|
||||
@@ -34,47 +51,42 @@ check_hash() {
|
||||
expect_eq "$got" "$want" "hash-id $input"
|
||||
}
|
||||
|
||||
check_repo REPO 'REPO specific wins' 'records/REPO' \
|
||||
JSC_WIKI_REPO_REPO='records/REPO' \
|
||||
JSC_WIKI_REPO_ANALYZE='knowledges/ANALYZE' \
|
||||
JSC_WIKI_REPO='shared/wiki'
|
||||
# 其他八個類型的誘餌值。跨類型代用一旦發生,回傳的就會是 decoy/{別的類型}。
|
||||
decoys() { # $1=要排除的類型
|
||||
for t in $TYPES; do
|
||||
[ "$t" = "$1" ] || printf 'JSC_WIKI_REPO_%s=decoy/%s ' "$t" "$t"
|
||||
done
|
||||
}
|
||||
|
||||
check_repo REPO 'REPO falls back to shared only' 'shared/wiki' \
|
||||
JSC_WIKI_REPO_ANALYZE='knowledges/ANALYZE' \
|
||||
JSC_WIKI_REPO='shared/wiki'
|
||||
for ty in $TYPES; do
|
||||
# 1. 自己的變數贏過共用變數,也贏過其他類型的誘餌。
|
||||
check_repo "$ty" "$ty specific wins" "own/$ty" \
|
||||
$(decoys "$ty") "JSC_WIKI_REPO_$ty=own/$ty" JSC_WIKI_REPO='shared/wiki'
|
||||
|
||||
check_repo ANALYZE 'ANALYZE specific wins' 'knowledges/ANALYZE' \
|
||||
JSC_WIKI_REPO_REPO='records/REPO' \
|
||||
JSC_WIKI_REPO_ANALYZE='knowledges/ANALYZE' \
|
||||
JSC_WIKI_REPO='shared/wiki'
|
||||
# 2. 自己的變數未設定時,只退回共用變數。
|
||||
check_repo "$ty" "$ty falls back to shared only" 'shared/wiki' \
|
||||
$(decoys "$ty") JSC_WIKI_REPO='shared/wiki'
|
||||
|
||||
check_repo ANALYZE 'ANALYZE falls back to shared only' 'shared/wiki' \
|
||||
JSC_WIKI_REPO_REPO='records/REPO' \
|
||||
JSC_WIKI_REPO='shared/wiki'
|
||||
# 3. 自己的變數與共用變數都沒有時,exit 3,不借用別的類型。
|
||||
check_no_repo "$ty" "$ty never borrows another type" $(decoys "$ty")
|
||||
done
|
||||
|
||||
check_repo LEARN 'LEARN specific wins' 'lessons/LEARN' \
|
||||
JSC_WIKI_REPO_LEARN='lessons/LEARN' \
|
||||
JSC_WIKI_REPO='shared/wiki'
|
||||
|
||||
check_repo LEARN 'LEARN falls back to shared only' 'shared/wiki' \
|
||||
JSC_WIKI_REPO_LOG='records/LOG' \
|
||||
JSC_WIKI_REPO='shared/wiki'
|
||||
|
||||
check_repo DELIVER 'DELIVER specific wins' 'handover/DELIVER' \
|
||||
JSC_WIKI_REPO_DELIVER='handover/DELIVER' \
|
||||
JSC_WIKI_REPO='shared/wiki'
|
||||
|
||||
check_repo DELIVER 'DELIVER falls back to shared only' 'shared/wiki' \
|
||||
JSC_WIKI_REPO_ANALYZE='knowledges/ANALYZE' \
|
||||
JSC_WIKI_REPO='shared/wiki'
|
||||
|
||||
check_repo ERROR 'ERROR uses its own repo' 'errors/wiki' \
|
||||
JSC_WIKI_REPO_ERROR='errors/wiki' \
|
||||
JSC_WIKI_REPO='shared/wiki'
|
||||
# 未知類型 exit 2,與「設定不足」的 exit 3 分開。
|
||||
if got=$(env -i PATH="${PATH:-/usr/bin:/bin}" JSC_WIKI_REPO='shared/wiki' \
|
||||
"$gitea" wiki-repo NOSUCH 2>/dev/null); then
|
||||
code=0
|
||||
else
|
||||
code=$?
|
||||
fi
|
||||
[ "$code" -eq 2 ] || fail "unknown type: want exit=2 got exit=$code"
|
||||
[ -z "$got" ] || fail "unknown type: want no output got=$got"
|
||||
|
||||
# hash-id:首碼 0-9/A/B/C 改成 H 加前 7 碼;其餘首碼原樣輸出 8 碼大寫。
|
||||
check_hash 'case-2' 'H5172CB7'
|
||||
check_hash 'case-11' 'HA9A6662'
|
||||
check_hash 'case-1' 'HB6EC7FD'
|
||||
check_hash 'case-12' 'HCCA8D42'
|
||||
check_hash 'case-3' 'D3E5AA27'
|
||||
check_hash 'case-7' 'D794C002'
|
||||
|
||||
printf '%s\n' 'OK'
|
||||
|
||||
Executable
+80
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env sh
|
||||
# repo-sync.sh — 把單一存取庫同步到本機。
|
||||
# 用法: repo-sync.sh <owner>/<repo> [target-dir] # target-dir 預設為 <repo>
|
||||
# 目錄不存在 → git clone(clone URL 取自 gitea.sh clone-url)
|
||||
# 目錄已存在 → git fetch、切到基準分支、git pull --ff-only
|
||||
# 有未提交變更 → 只回報 dirty 與基準分支,不動分支也不 pull
|
||||
# 基準分支的唯一優先序(呼叫端不必再判斷,也不要自己再推導一次):
|
||||
# 1. gitea.sh default-branch <owner>/<repo>(該分支要在遠端存在)
|
||||
# 2. 查不到時依序取遠端的 develop、main、master
|
||||
# 3. 都沒有 → failed no default branch
|
||||
# 輸出: 恰好一行,cloned、updated、dirty {分支} 或 failed {原因}。
|
||||
# 前三種 exit 0;failed exit 1。
|
||||
# dirty 會把解析好的基準分支一起帶出來,呼叫端直接拿去當 PR 的 base。
|
||||
set -u
|
||||
|
||||
script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
gitea="$script_dir/gitea.sh"
|
||||
|
||||
fail() { # 原因壓成一行,避免呼叫端解析多行輸出
|
||||
printf 'failed %s\n' "$(printf '%s' "$1" | tr '\n\r\t' ' ')"
|
||||
exit 1
|
||||
}
|
||||
|
||||
full="${1:-}"
|
||||
[ -n "$full" ] || fail "usage: repo-sync.sh <owner>/<repo> [target-dir]"
|
||||
case "$full" in
|
||||
*/*/*|/*|*/) fail "not owner/repo: $full" ;;
|
||||
*/*) ;;
|
||||
*) fail "not owner/repo: $full" ;;
|
||||
esac
|
||||
repo="${full#*/}"
|
||||
target="${2:-$repo}"
|
||||
|
||||
remote_has() { # 遠端是否有這個分支
|
||||
git -C "$target" rev-parse --verify --quiet "refs/remotes/origin/$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
if [ ! -e "$target" ]; then
|
||||
# clone URL 只收 stdout:把 stderr 併進來會讓任何雜訊變成網址的一部分
|
||||
err=$(mktemp)
|
||||
url=$("$gitea" clone-url "$full" 2>"$err") || url=''
|
||||
if [ -z "$url" ]; then
|
||||
reason=$(cat "$err"); rm -f "$err"
|
||||
fail "clone-url failed for $full: ${reason:-no clone URL}"
|
||||
fi
|
||||
rm -f "$err"
|
||||
out=$(git clone "$url" "$target" 2>&1) || fail "clone: $out"
|
||||
printf 'cloned\n'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git -C "$target" rev-parse --git-dir >/dev/null 2>&1 || fail "$target is not a git repo"
|
||||
|
||||
dirty=0
|
||||
[ -z "$(git -C "$target" status --porcelain 2>/dev/null)" ] || dirty=1
|
||||
|
||||
# dirty 的存取庫也要解析基準分支:呼叫端拿它當 PR 的 base,自己再推導一次就會
|
||||
# 出現第二套優先序。fetch 只更新 refs,不動工作目錄,dirty 時照樣安全;但 dirty
|
||||
# 時網路失敗不算致命,還是要把 dirty 回報出去,改用本機既有的 remote refs 判斷。
|
||||
if ! out=$(git -C "$target" fetch --prune origin 2>&1); then
|
||||
[ "$dirty" -eq 1 ] || fail "fetch: $out"
|
||||
fi
|
||||
|
||||
branch=$("$gitea" default-branch "$full" 2>/dev/null) || branch=''
|
||||
if [ -z "$branch" ] || ! remote_has "$branch"; then
|
||||
branch=''
|
||||
for b in develop main master; do
|
||||
if remote_has "$b"; then branch="$b"; break; fi
|
||||
done
|
||||
fi
|
||||
[ -n "$branch" ] || fail "no default branch"
|
||||
|
||||
if [ "$dirty" -eq 1 ]; then
|
||||
printf 'dirty %s\n' "$branch"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
out=$(git -C "$target" checkout "$branch" 2>&1) || fail "checkout $branch: $out"
|
||||
out=$(git -C "$target" pull --ff-only origin "$branch" 2>&1) || fail "pull $branch: $out"
|
||||
printf 'updated\n'
|
||||
Reference in New Issue
Block a user