1package fakegit // import "github.com/docker/docker/internal/test/fakegit" 2 3import ( 4 "fmt" 5 "io/ioutil" 6 "net/http" 7 "net/http/httptest" 8 "os" 9 "os/exec" 10 "path/filepath" 11 12 "github.com/docker/docker/internal/test" 13 "github.com/docker/docker/internal/test/fakecontext" 14 "github.com/docker/docker/internal/test/fakestorage" 15 "gotest.tools/assert" 16) 17 18type testingT interface { 19 assert.TestingT 20 logT 21 skipT 22 Fatal(args ...interface{}) 23 Fatalf(string, ...interface{}) 24} 25 26type logT interface { 27 Logf(string, ...interface{}) 28} 29 30type skipT interface { 31 Skip(...interface{}) 32} 33 34type gitServer interface { 35 URL() string 36 Close() error 37} 38 39type localGitServer struct { 40 *httptest.Server 41} 42 43func (r *localGitServer) Close() error { 44 r.Server.Close() 45 return nil 46} 47 48func (r *localGitServer) URL() string { 49 return r.Server.URL 50} 51 52// FakeGit is a fake git server 53type FakeGit struct { 54 root string 55 server gitServer 56 RepoURL string 57} 58 59// Close closes the server, implements Closer interface 60func (g *FakeGit) Close() { 61 g.server.Close() 62 os.RemoveAll(g.root) 63} 64 65// New create a fake git server that can be used for git related tests 66func New(c testingT, name string, files map[string]string, enforceLocalServer bool) *FakeGit { 67 if ht, ok := c.(test.HelperT); ok { 68 ht.Helper() 69 } 70 ctx := fakecontext.New(c, "", fakecontext.WithFiles(files)) 71 defer ctx.Close() 72 curdir, err := os.Getwd() 73 if err != nil { 74 c.Fatal(err) 75 } 76 defer os.Chdir(curdir) 77 78 if output, err := exec.Command("git", "init", ctx.Dir).CombinedOutput(); err != nil { 79 c.Fatalf("error trying to init repo: %s (%s)", err, output) 80 } 81 err = os.Chdir(ctx.Dir) 82 if err != nil { 83 c.Fatal(err) 84 } 85 if output, err := exec.Command("git", "config", "user.name", "Fake User").CombinedOutput(); err != nil { 86 c.Fatalf("error trying to set 'user.name': %s (%s)", err, output) 87 } 88 if output, err := exec.Command("git", "config", "user.email", "fake.user@example.com").CombinedOutput(); err != nil { 89 c.Fatalf("error trying to set 'user.email': %s (%s)", err, output) 90 } 91 if output, err := exec.Command("git", "add", "*").CombinedOutput(); err != nil { 92 c.Fatalf("error trying to add files to repo: %s (%s)", err, output) 93 } 94 if output, err := exec.Command("git", "commit", "-a", "-m", "Initial commit").CombinedOutput(); err != nil { 95 c.Fatalf("error trying to commit to repo: %s (%s)", err, output) 96 } 97 98 root, err := ioutil.TempDir("", "docker-test-git-repo") 99 if err != nil { 100 c.Fatal(err) 101 } 102 repoPath := filepath.Join(root, name+".git") 103 if output, err := exec.Command("git", "clone", "--bare", ctx.Dir, repoPath).CombinedOutput(); err != nil { 104 os.RemoveAll(root) 105 c.Fatalf("error trying to clone --bare: %s (%s)", err, output) 106 } 107 err = os.Chdir(repoPath) 108 if err != nil { 109 os.RemoveAll(root) 110 c.Fatal(err) 111 } 112 if output, err := exec.Command("git", "update-server-info").CombinedOutput(); err != nil { 113 os.RemoveAll(root) 114 c.Fatalf("error trying to git update-server-info: %s (%s)", err, output) 115 } 116 err = os.Chdir(curdir) 117 if err != nil { 118 os.RemoveAll(root) 119 c.Fatal(err) 120 } 121 122 var server gitServer 123 if !enforceLocalServer { 124 // use fakeStorage server, which might be local or remote (at test daemon) 125 server = fakestorage.New(c, root) 126 } else { 127 // always start a local http server on CLI test machine 128 httpServer := httptest.NewServer(http.FileServer(http.Dir(root))) 129 server = &localGitServer{httpServer} 130 } 131 return &FakeGit{ 132 root: root, 133 server: server, 134 RepoURL: fmt.Sprintf("%s/%s.git", server.URL(), name), 135 } 136} 137