github.com/wtsi-hgi/go-softpack-builder@v1.8.1/internal/gitmock/mock.go (about) 1 package gitmock 2 3 import ( 4 crypto "crypto/rand" 5 "encoding/base64" 6 "fmt" 7 "io" 8 "math/rand" 9 "net/http" 10 11 "github.com/wtsi-hgi/go-softpack-builder/internal" 12 ) 13 14 const ( 15 refsPath = "/info/refs" 16 refsQuery = "?service=git-upload-pack" 17 headPath = "/HEAD" 18 smartContentType = "application/x-git-upload-pack-advertisement" 19 expectedHeader = "001e# service=git-upload-pack\n0000" 20 headRef = "HEAD" 21 22 numRefGen = 5 23 hashLen = 40 24 ) 25 26 const ( 27 ErrNotFound = internal.Error("not found") 28 ) 29 30 // MockGit can be used to start a pretend git server for testing custom spack 31 // repos. 32 type MockGit struct { 33 refs map[string]string 34 masterName string 35 Smart bool 36 } 37 38 // New returns a new MockGit that provides a git repo with a random number of 39 // random refs. 40 func New() (*MockGit, string) { 41 numRefs := rand.Intn(numRefGen) + numRefGen //nolint:gosec 42 43 refs := make(map[string]string, numRefs) 44 45 var ( 46 masterName, masterCommit string 47 hash [20]byte 48 ) 49 50 for i := 0; i < numRefs; i++ { 51 randChars := make([]byte, rand.Intn(numRefGen)+numRefGen) //nolint:gosec 52 crypto.Read(randChars) //nolint:errcheck 53 crypto.Read(hash[:]) //nolint:errcheck 54 55 masterName = base64.RawStdEncoding.EncodeToString(randChars) 56 masterCommit = fmt.Sprintf("%020X", hash) 57 58 refs[masterName] = masterCommit 59 } 60 61 return &MockGit{ 62 refs: refs, 63 masterName: masterName, 64 }, masterCommit 65 } 66 67 // ServeHTTP is to implement http.Handler so you can httptest.NewServer(m). 68 func (m *MockGit) ServeHTTP(w http.ResponseWriter, r *http.Request) { 69 if err := m.handle(w, r.URL.Path); err != nil { 70 http.Error(w, err.Error(), http.StatusInternalServerError) 71 } 72 } 73 74 func (m *MockGit) handle(w http.ResponseWriter, path string) error { 75 switch path { 76 case refsPath: 77 if m.Smart { 78 w.Header().Set("Content-Type", smartContentType) 79 80 return m.handleSmartRefs(w) 81 } 82 83 return m.handleRefs(w) 84 case headPath: 85 return m.handleHead(w) 86 } 87 88 return ErrNotFound 89 } 90 91 func (m *MockGit) handleSmartRefs(w io.Writer) error { 92 if _, err := fmt.Fprintf(w, "%s002D%s %s\n", expectedHeader, m.refs[m.masterName], headRef); err != nil { 93 return err 94 } 95 96 for ref, commit := range m.refs { 97 if _, err := fmt.Fprintf(w, "%04X%s %s\n", hashLen+1+len(ref), commit, ref); err != nil { 98 return err 99 } 100 } 101 102 _, err := io.WriteString(w, "0000") 103 104 return err 105 } 106 107 func (m *MockGit) handleRefs(w io.Writer) error { 108 for ref, commit := range m.refs { 109 if _, err := fmt.Fprintf(w, "%s\t%s\n", commit, ref); err != nil { 110 return err 111 } 112 } 113 114 return nil 115 } 116 117 func (m *MockGit) handleHead(w io.Writer) error { 118 _, err := io.WriteString(w, "ref: "+m.masterName) 119 120 return err 121 }