forked from tangled.org/core
this repo has no description
at issues-edit 2.6 kB view raw
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}