summary
This commit is contained in:
@@ -291,6 +291,7 @@ func (e *Engine) LoadAll() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
e.states[name] = &repoState{cfg: cfg, status: "idle"}
|
e.states[name] = &repoState{cfg: cfg, status: "idle"}
|
||||||
|
e.restoreLastSync(e.states[name])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,6 +354,44 @@ func rotateStatIfNeeded(path string, maxLines int) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// restoreLastSync 从统计 CSV 的最后一条记录恢复 lastSync,使重启后界面不再显示「从未同步」。
|
||||||
|
func (e *Engine) restoreLastSync(s *repoState) {
|
||||||
|
path := filepath.Join(e.statsDir, s.cfg.Name+".csv")
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
recs, err := csv.NewReader(f).ReadAll()
|
||||||
|
if err != nil || len(recs) < 2 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var ts, raw string
|
||||||
|
for _, rec := range recs[1:] {
|
||||||
|
if len(rec) < 3 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ts, raw = rec[0], rec[2]
|
||||||
|
}
|
||||||
|
if ts == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
result := raw
|
||||||
|
switch raw {
|
||||||
|
case "success":
|
||||||
|
result = "ok"
|
||||||
|
case "failed":
|
||||||
|
result = "error"
|
||||||
|
}
|
||||||
|
detail := map[string]string{"ok": "同步完成", "error": "同步失败", "conflict": "存在冲突"}[result]
|
||||||
|
if detail == "" {
|
||||||
|
detail = "上次同步"
|
||||||
|
}
|
||||||
|
s.mu.Lock()
|
||||||
|
s.lastSync = &SyncResult{Time: ts, Result: result, Detail: detail}
|
||||||
|
s.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
func firstRemoteName(cfg *RepoConfig) string {
|
func firstRemoteName(cfg *RepoConfig) string {
|
||||||
if len(cfg.Remotes) > 0 {
|
if len(cfg.Remotes) > 0 {
|
||||||
return cfg.Remotes[0].Name
|
return cfg.Remotes[0].Name
|
||||||
@@ -576,6 +615,7 @@ func (e *Engine) setFail(s *repoState, msg string) {
|
|||||||
s.lastError = msg
|
s.lastError = msg
|
||||||
s.lastSync = &SyncResult{Time: now, Result: "error", Detail: msg}
|
s.lastSync = &SyncResult{Time: now, Result: "error", Detail: msg}
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
|
e.stat(s, "sync", "error", 0)
|
||||||
e.logf(s, "error", "%s", msg)
|
e.logf(s, "error", "%s", msg)
|
||||||
e.pushStatus(s)
|
e.pushStatus(s)
|
||||||
}
|
}
|
||||||
@@ -587,6 +627,7 @@ func (e *Engine) setOK(s *repoState, detail string) {
|
|||||||
s.lastError = ""
|
s.lastError = ""
|
||||||
s.lastSync = &SyncResult{Time: now, Result: "ok", Detail: detail}
|
s.lastSync = &SyncResult{Time: now, Result: "ok", Detail: detail}
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
|
e.stat(s, "sync", "ok", 0)
|
||||||
e.pushStatus(s)
|
e.pushStatus(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -915,6 +956,7 @@ func (e *Engine) pullRemote(s *repoState, cfg *RepoConfig, remote string, n int)
|
|||||||
s.lastError = "拉取产生冲突,等待在冲突处理台解决"
|
s.lastError = "拉取产生冲突,等待在冲突处理台解决"
|
||||||
s.lastSync = &SyncResult{Time: now, Result: "conflict", Detail: s.lastError}
|
s.lastSync = &SyncResult{Time: now, Result: "conflict", Detail: s.lastError}
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
|
e.stat(s, "sync", "conflict", 0)
|
||||||
e.stat(s, "pull", "conflict", n)
|
e.stat(s, "pull", "conflict", n)
|
||||||
e.logf(s, "error", "拉取产生冲突:%s(请在详情 → 冲突中处理)", strings.Join(files, ", "))
|
e.logf(s, "error", "拉取产生冲突:%s(请在详情 → 冲突中处理)", strings.Join(files, ", "))
|
||||||
e.pushStatus(s)
|
e.pushStatus(s)
|
||||||
@@ -955,6 +997,7 @@ func (e *Engine) ForcePush(name string) error {
|
|||||||
s.lastError = ""
|
s.lastError = ""
|
||||||
s.lastSync = &SyncResult{Time: time.Now().Format("2006-01-02 15:04:05"), Result: "ok", Detail: "强制推送完成"}
|
s.lastSync = &SyncResult{Time: time.Now().Format("2006-01-02 15:04:05"), Result: "ok", Detail: "强制推送完成"}
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
|
e.stat(s, "sync", "ok", 0)
|
||||||
e.pushStatus(s)
|
e.pushStatus(s)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -975,6 +1018,7 @@ func (e *Engine) AbortPush(name string) error {
|
|||||||
s.status = "ok"
|
s.status = "ok"
|
||||||
s.lastError = "用户放弃强制推送"
|
s.lastError = "用户放弃强制推送"
|
||||||
s.lastSync = &SyncResult{Time: time.Now().Format("2006-01-02 15:04:05"), Result: "ok", Detail: "放弃强制推送,状态已清除"}
|
s.lastSync = &SyncResult{Time: time.Now().Format("2006-01-02 15:04:05"), Result: "ok", Detail: "放弃强制推送,状态已清除"}
|
||||||
|
e.stat(s, "sync", "ok", 0)
|
||||||
e.logf(s, "warn", "放弃强制推送")
|
e.logf(s, "warn", "放弃强制推送")
|
||||||
e.pushStatus(s)
|
e.pushStatus(s)
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -961,6 +961,7 @@ function dateStr(d) {
|
|||||||
|
|
||||||
function loadStats(name) {
|
function loadStats(name) {
|
||||||
api(`/api/repos/${name}/stats`).then(rows => {
|
api(`/api/repos/${name}/stats`).then(rows => {
|
||||||
|
rows = rows.filter(r => r.action !== 'sync');
|
||||||
const days = [];
|
const days = [];
|
||||||
for (let i = 29; i >= 0; i--) {
|
for (let i = 29; i >= 0; i--) {
|
||||||
const d = new Date();
|
const d = new Date();
|
||||||
|
|||||||
Reference in New Issue
Block a user