loop: set upstream tracking for sketch branches on outie
Fixes boldsoftware/sketch#143
Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: s782ec3188bf0856ak
diff --git a/dockerimg/dockerimg.go b/dockerimg/dockerimg.go
index 19d90cf..94ba815 100644
--- a/dockerimg/dockerimg.go
+++ b/dockerimg/dockerimg.go
@@ -207,8 +207,15 @@
// errCh receives errors from operations that this function calls in separate goroutines.
errCh := make(chan error)
+ var upstream string
+ if out, err := combinedOutput(ctx, "git", "branch", "--show-current"); err != nil {
+ slog.DebugContext(ctx, "git branch --show-current failed (continuing)", "error", err)
+ } else {
+ upstream = strings.TrimSpace(string(out))
+ }
+
// Start the git server
- gitSrv, err := newGitServer(gitRoot, config.PassthroughUpstream)
+ gitSrv, err := newGitServer(gitRoot, config.PassthroughUpstream, upstream)
if err != nil {
return fmt.Errorf("failed to start git server: %w", err)
}
@@ -241,12 +248,6 @@
commit = strings.TrimSpace(string(out))
}
- var upstream string
- if out, err := combinedOutput(ctx, "git", "branch", "--show-current"); err != nil {
- slog.DebugContext(ctx, "git branch --show-current failed (continuing)", "error", err)
- } else {
- upstream = strings.TrimSpace(string(out))
- }
if out, err := combinedOutput(ctx, "git", "config", "http.receivepack", "true"); err != nil {
return fmt.Errorf("git config http.receivepack true: %s: %w", out, err)
}
@@ -488,7 +489,7 @@
return gs.srv.Serve(gs.gitLn)
}
-func newGitServer(gitRoot string, configureUpstreamPassthrough bool) (*gitServer, error) {
+func newGitServer(gitRoot string, configureUpstreamPassthrough bool, upstream string) (*gitServer, error) {
ret := &gitServer{
pass: rand.Text(),
}
@@ -509,7 +510,7 @@
var hooksDir string
if configureUpstreamPassthrough {
- hooksDir, err = setupHooksDir(gitRoot)
+ hooksDir, err = setupHooksDir(upstream)
if err != nil {
return nil, fmt.Errorf("failed to setup hooks directory: %w", err)
}
diff --git a/dockerimg/githttp.go b/dockerimg/githttp.go
index eaeb23a..fae1678 100644
--- a/dockerimg/githttp.go
+++ b/dockerimg/githttp.go
@@ -1,6 +1,7 @@
package dockerimg
import (
+ "bytes"
"context"
"crypto/subtle"
_ "embed"
@@ -13,12 +14,16 @@
"path/filepath"
"runtime"
"strings"
+ "text/template"
"time"
)
//go:embed pre-receive.sh
var preReceiveScript string
+//go:embed post-receive.sh
+var postReceiveScript string
+
type gitHTTP struct {
gitRepoRoot string
hooksDir string
@@ -41,7 +46,7 @@
// Note:
// - Error propagation from origin push to user push
// - Session isolation with temporary hooks directory
-func setupHooksDir(gitRepoRoot string) (string, error) {
+func setupHooksDir(upstream string) (string, error) {
hooksDir, err := os.MkdirTemp("", "sketch-git-hooks-*")
if err != nil {
return "", fmt.Errorf("failed to create hooks directory: %w", err)
@@ -52,6 +57,21 @@
return "", fmt.Errorf("failed to write pre-receive hook: %w", err)
}
+ if upstream != "" {
+ tmpl, err := template.New("post-receive").Parse(postReceiveScript)
+ if err != nil {
+ return "", fmt.Errorf("failed to parse post-receive template: %w", err)
+ }
+ var buf bytes.Buffer
+ if err := tmpl.Execute(&buf, map[string]string{"Upstream": upstream}); err != nil {
+ return "", fmt.Errorf("failed to execute post-receive template: %w", err)
+ }
+ postReceiveHook := filepath.Join(hooksDir, "post-receive")
+ if err := os.WriteFile(postReceiveHook, buf.Bytes(), 0o755); err != nil {
+ return "", fmt.Errorf("failed to write post-receive hook: %w", err)
+ }
+ }
+
return hooksDir, nil
}
@@ -151,11 +171,14 @@
w.Header().Set("Cache-Control", "no-cache")
- args := []string{"http-backend"}
+ var args []string
if g.hooksDir != "" {
- // Use -c flag to set core.hooksPath for this git command only
- args = []string{"-c", "core.hooksPath=" + g.hooksDir, "-c", "receive.denyCurrentBranch=refuse", "http-backend"}
+ args = append(args,
+ "-c", "core.hooksPath="+g.hooksDir,
+ "-c", "receive.denyCurrentBranch=refuse",
+ )
}
+ args = append(args, "http-backend")
h := &cgi.Handler{
Path: gitBin,
diff --git a/dockerimg/post-receive.sh b/dockerimg/post-receive.sh
new file mode 100644
index 0000000..360600d
--- /dev/null
+++ b/dockerimg/post-receive.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Post-receive hook for sketch git http server
+# Sets upstream tracking branch for sketch branches
+
+set -e
+
+while read oldrev newrev refname; do
+ if [[ "$refname" =~ ^refs/heads/sketch/ ]]; then
+ git branch --set-upstream-to="{{ .Upstream }}" "${refname#refs/heads/}"
+ fi
+done
+
+exit 0