feature/go-rewrite : base Go avec walk GUI
- Rewrite complet en Go : exe unique sans _internal/, sans extraction temp - GUI Windows-native via github.com/lxn/walk (TableView, TextEdit, PushButton) - Meme fonctionnalites : check repos, pull, checkout, auto-update, logs - build.bat : go build -ldflags "-H windowsgui -s -w" -> 9.6 Mo, zero dependance Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
134
git.go
Normal file
134
git.go
Normal file
@@ -0,0 +1,134 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type RepoResult struct {
|
||||
Name string
|
||||
Path string
|
||||
URL string
|
||||
Pending bool
|
||||
UpToDate bool
|
||||
Offline bool
|
||||
NeedsClone bool
|
||||
Error string
|
||||
NewCommits int
|
||||
LocalChanges int
|
||||
}
|
||||
|
||||
func runGit(args []string, cwd string, timeout time.Duration) (code int, stdout string, stderr string) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
|
||||
fullArgs := append([]string{"-c", "safe.directory=*"}, args...)
|
||||
cmd := newGitCmd(ctx, fullArgs, cwd)
|
||||
|
||||
var outBuf, errBuf strings.Builder
|
||||
cmd.Stdout = &outBuf
|
||||
cmd.Stderr = &errBuf
|
||||
|
||||
err := cmd.Run()
|
||||
stdout = strings.TrimSpace(outBuf.String())
|
||||
stderr = strings.TrimSpace(errBuf.String())
|
||||
|
||||
if err != nil {
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
return 1, stdout, "Timeout"
|
||||
}
|
||||
var exitErr *exec.ExitError
|
||||
if errors.As(err, &exitErr) {
|
||||
return exitErr.ExitCode(), stdout, stderr
|
||||
}
|
||||
return -1, stdout, err.Error()
|
||||
}
|
||||
return 0, stdout, stderr
|
||||
}
|
||||
|
||||
func absRepoPath(rel string) string {
|
||||
if filepath.IsAbs(rel) {
|
||||
return rel
|
||||
}
|
||||
return filepath.Join(exeDir(), rel)
|
||||
}
|
||||
|
||||
func checkRepo(cfg RepoConfig) RepoResult {
|
||||
res := RepoResult{Name: cfg.Name, URL: cfg.URL}
|
||||
local := absRepoPath(cfg.Path)
|
||||
res.Path = local
|
||||
|
||||
if _, err := os.Stat(filepath.Join(local, ".git")); os.IsNotExist(err) {
|
||||
res.NeedsClone = true
|
||||
return res
|
||||
}
|
||||
|
||||
runGit([]string{"remote", "set-url", "origin", cfg.URL}, local, 10*time.Second)
|
||||
|
||||
code, _, stderr := runGit([]string{"fetch", "origin"}, local, 60*time.Second)
|
||||
if code != 0 {
|
||||
for _, kw := range []string{"could not resolve", "connection refused", "unable to connect", "timed out", "the remote end hung up"} {
|
||||
if strings.Contains(strings.ToLower(stderr), kw) {
|
||||
res.Offline = true
|
||||
res.Error = "Hors ligne"
|
||||
return res
|
||||
}
|
||||
}
|
||||
res.Error = "Fetch: " + stderr
|
||||
return res
|
||||
}
|
||||
|
||||
_, branch, _ := runGit([]string{"rev-parse", "--abbrev-ref", "HEAD"}, local, 5*time.Second)
|
||||
if branch == "" {
|
||||
branch = "master"
|
||||
}
|
||||
|
||||
_, countStr, _ := runGit([]string{"rev-list", "--count", "HEAD..origin/" + branch}, local, 5*time.Second)
|
||||
fmt.Sscanf(countStr, "%d", &res.NewCommits)
|
||||
|
||||
_, status, _ := runGit([]string{"status", "--porcelain"}, local, 5*time.Second)
|
||||
if status != "" {
|
||||
res.LocalChanges = len(strings.Split(strings.TrimSpace(status), "\n"))
|
||||
}
|
||||
|
||||
res.UpToDate = res.NewCommits == 0 && res.LocalChanges == 0
|
||||
return res
|
||||
}
|
||||
|
||||
func doClone(cfg RepoConfig) error {
|
||||
local := absRepoPath(cfg.Path)
|
||||
if err := os.MkdirAll(filepath.Dir(local), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
code, _, stderr := runGit([]string{"clone", cfg.URL, local}, "", 300*time.Second)
|
||||
if code != 0 {
|
||||
return fmt.Errorf("%s", stderr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func doPull(res RepoResult) error {
|
||||
_, branch, _ := runGit([]string{"rev-parse", "--abbrev-ref", "HEAD"}, res.Path, 5*time.Second)
|
||||
if branch == "" {
|
||||
branch = "master"
|
||||
}
|
||||
code, _, stderr := runGit([]string{"pull", "origin", branch}, res.Path, 120*time.Second)
|
||||
if code != 0 {
|
||||
return fmt.Errorf("%s", stderr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func doCheckout(res RepoResult) error {
|
||||
code, _, stderr := runGit([]string{"checkout", "--", "."}, res.Path, 30*time.Second)
|
||||
if code != 0 {
|
||||
return fmt.Errorf("%s", stderr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user