forked from
tangled.org/core
fork
Configure Feed
Select the types of activity you want to include in your feed.
Monorepo for Tangled
fork
Configure Feed
Select the types of activity you want to include in your feed.
1package service
2
3import (
4 "bytes"
5 "fmt"
6 "io"
7 "log"
8 "net/http"
9 "os/exec"
10 "strings"
11 "syscall"
12)
13
14// Mostly from charmbracelet/soft-serve and sosedoff/gitkit.
15
16type ServiceCommand struct {
17 Dir string
18 Stdin io.Reader
19 Stdout http.ResponseWriter
20}
21
22func (c *ServiceCommand) InfoRefs() error {
23 cmd := exec.Command("git", []string{
24 "upload-pack",
25 "--stateless-rpc",
26 "--advertise-refs",
27 ".",
28 }...)
29
30 cmd.Dir = c.Dir
31 cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
32 stdoutPipe, _ := cmd.StdoutPipe()
33 cmd.Stderr = cmd.Stdout
34
35 if err := cmd.Start(); err != nil {
36 log.Printf("git: failed to start git-upload-pack (info/refs): %s", err)
37 return err
38 }
39
40 if err := packLine(c.Stdout, "# service=git-upload-pack\n"); err != nil {
41 log.Printf("git: failed to write pack line: %s", err)
42 return err
43 }
44
45 if err := packFlush(c.Stdout); err != nil {
46 log.Printf("git: failed to flush pack: %s", err)
47 return err
48 }
49
50 buf := bytes.Buffer{}
51 if _, err := io.Copy(&buf, stdoutPipe); err != nil {
52 log.Printf("git: failed to copy stdout to tmp buffer: %s", err)
53 return err
54 }
55
56 if err := cmd.Wait(); err != nil {
57 out := strings.Builder{}
58 _, _ = io.Copy(&out, &buf)
59 log.Printf("git: failed to run git-upload-pack; err: %s; output: %s", err, out.String())
60 return err
61 }
62
63 if _, err := io.Copy(c.Stdout, &buf); err != nil {
64 log.Printf("git: failed to copy stdout: %s", err)
65 }
66
67 return nil
68}
69
70func (c *ServiceCommand) UploadPack() error {
71 cmd := exec.Command("git", []string{
72 "-c", "uploadpack.allowFilter=true",
73 "upload-pack",
74 "--stateless-rpc",
75 ".",
76 }...)
77 cmd.Dir = c.Dir
78 cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
79
80 stdoutPipe, _ := cmd.StdoutPipe()
81 cmd.Stderr = cmd.Stdout
82 defer stdoutPipe.Close()
83
84 stdinPipe, err := cmd.StdinPipe()
85 if err != nil {
86 return err
87 }
88 defer stdinPipe.Close()
89
90 if err := cmd.Start(); err != nil {
91 log.Printf("git: failed to start git-upload-pack: %s", err)
92 return err
93 }
94
95 if _, err := io.Copy(stdinPipe, c.Stdin); err != nil {
96 log.Printf("git: failed to copy stdin: %s", err)
97 return err
98 }
99 stdinPipe.Close()
100
101 if _, err := io.Copy(newWriteFlusher(c.Stdout), stdoutPipe); err != nil {
102 log.Printf("git: failed to copy stdout: %s", err)
103 return err
104 }
105 if err := cmd.Wait(); err != nil {
106 log.Printf("git: failed to wait for git-upload-pack: %s", err)
107 return err
108 }
109
110 return nil
111}
112
113func packLine(w io.Writer, s string) error {
114 _, err := fmt.Fprintf(w, "%04x%s", len(s)+4, s)
115 return err
116}
117
118func packFlush(w io.Writer) error {
119 _, err := fmt.Fprint(w, "0000")
120 return err
121}