fierj
PublicTiny personal git forge
f2199f85268b4cdef79a39553f14476a0aa3436c
diff --git a/git.go b/git.go
index 280be92..948e7d5 100644
--- a/git.go
+++ b/git.go
@@ -225,15 +225,28 @@ func (g *Git) Diff(hash string) (string, error) {
func (g *Git) DefaultBranch() string {
out, err := g.cmd("symbolic-ref", "--short", "HEAD")
- if err != nil {
- return "main"
+ if err == nil {
+ ref := strings.TrimSpace(out)
+ // Verify the default branch actually exists (HEAD might point to
+ // a not-yet-created branch in an empty/dangling-HEAD repo).
+ if _, err2 := g.cmd("rev-parse", "--verify", ref); err2 == nil {
+ return ref
+ }
+ }
+ // Fall back to the first real branch, or "main" as last resort.
+ branches := g.Branches()
+ if len(branches) > 0 {
+ return branches[0]
}
- return strings.TrimSpace(out)
+ return "main"
}
func (g *Git) IsEmpty() bool {
- _, err := g.cmd("rev-parse", "--verify", "HEAD")
- return err != nil
+ // Check if any refs exist, not just HEAD.
+ // HEAD can be a dangling symbolic ref after git init --bare.
+ branches := g.Branches()
+ tags := g.Tags()
+ return len(branches) == 0 && len(tags) == 0
}
func (g *Git) Branches() []string {
diff --git a/ssh.go b/ssh.go
index 52fe3bc..bbf6ceb 100644
--- a/ssh.go
+++ b/ssh.go
@@ -13,6 +13,7 @@ import (
"path/filepath"
"strings"
"sync"
+ "time"
"golang.org/x/crypto/ssh"
)
@@ -159,8 +160,21 @@ func (s *SSHServer) runGitCommand(channel ssh.Channel, gitCmd string) {
go func() { defer wg.Done(); io.Copy(channel, stdout) }()
go func() { io.Copy(stdin, channel); stdin.Close() }()
- cmd.Wait()
- wg.Wait() // drain stdout before returning
+ if err := cmd.Wait(); err != nil {
+ slog.Warn("git failed", "cmd", subCmd, "repo", repoName, "err", err)
+ }
+ wg.Wait()
+
+ // Send exit status so the client knows the command finished successfully.
+ // Without this, git push reports an error even when the push succeeded.
+ exitCode := uint32(0)
+ if cmd.ProcessState != nil && !cmd.ProcessState.Success() {
+ exitCode = 1
+ }
+ channel.SendRequest("exit-status", false, ssh.Marshal(&struct{ ExitStatus uint32 }{exitCode}))
+
+ // Give the SSH library time to flush before channel.Close in handleSession.
+ time.Sleep(50 * time.Millisecond)
}
func loadOrGenerateHostKey(path string) (ssh.Signer, error) {