You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

git_test.go 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package integrations
  5. import (
  6. "context"
  7. "crypto/rand"
  8. "fmt"
  9. "io/ioutil"
  10. "net"
  11. "net/http"
  12. "net/url"
  13. "os"
  14. "os/exec"
  15. "path/filepath"
  16. "testing"
  17. "time"
  18. "code.gitea.io/git"
  19. "code.gitea.io/gitea/models"
  20. "code.gitea.io/gitea/modules/setting"
  21. api "code.gitea.io/sdk/gitea"
  22. "github.com/Unknwon/com"
  23. "github.com/stretchr/testify/assert"
  24. )
  25. const (
  26. littleSize = 1024 //1ko
  27. bigSize = 128 * 1024 * 1024 //128Mo
  28. )
  29. func onGiteaRun(t *testing.T, callback func(*testing.T, *url.URL)) {
  30. prepareTestEnv(t)
  31. s := http.Server{
  32. Handler: mac,
  33. }
  34. u, err := url.Parse(setting.AppURL)
  35. assert.NoError(t, err)
  36. listener, err := net.Listen("tcp", u.Host)
  37. assert.NoError(t, err)
  38. defer func() {
  39. ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
  40. s.Shutdown(ctx)
  41. cancel()
  42. }()
  43. go s.Serve(listener)
  44. //Started by config go ssh.Listen(setting.SSH.ListenHost, setting.SSH.ListenPort, setting.SSH.ServerCiphers, setting.SSH.ServerKeyExchanges, setting.SSH.ServerMACs)
  45. callback(t, u)
  46. }
  47. func TestGit(t *testing.T) {
  48. onGiteaRun(t, func(t *testing.T, u *url.URL) {
  49. u.Path = "user2/repo1.git"
  50. t.Run("HTTP", func(t *testing.T) {
  51. dstPath, err := ioutil.TempDir("", "repo-tmp-17")
  52. assert.NoError(t, err)
  53. defer os.RemoveAll(dstPath)
  54. t.Run("Standard", func(t *testing.T) {
  55. t.Run("CloneNoLogin", func(t *testing.T) {
  56. dstLocalPath, err := ioutil.TempDir("", "repo1")
  57. assert.NoError(t, err)
  58. defer os.RemoveAll(dstLocalPath)
  59. err = git.Clone(u.String(), dstLocalPath, git.CloneRepoOptions{})
  60. assert.NoError(t, err)
  61. assert.True(t, com.IsExist(filepath.Join(dstLocalPath, "README.md")))
  62. })
  63. t.Run("CreateRepo", func(t *testing.T) {
  64. session := loginUser(t, "user2")
  65. token := getTokenForLoggedInUser(t, session)
  66. req := NewRequestWithJSON(t, "POST", "/api/v1/user/repos?token="+token, &api.CreateRepoOption{
  67. AutoInit: true,
  68. Description: "Temporary repo",
  69. Name: "repo-tmp-17",
  70. Private: false,
  71. Gitignores: "",
  72. License: "WTFPL",
  73. Readme: "Default",
  74. })
  75. session.MakeRequest(t, req, http.StatusCreated)
  76. })
  77. u.Path = "user2/repo-tmp-17.git"
  78. u.User = url.UserPassword("user2", userPassword)
  79. t.Run("Clone", func(t *testing.T) {
  80. err = git.Clone(u.String(), dstPath, git.CloneRepoOptions{})
  81. assert.NoError(t, err)
  82. assert.True(t, com.IsExist(filepath.Join(dstPath, "README.md")))
  83. })
  84. t.Run("PushCommit", func(t *testing.T) {
  85. t.Run("Little", func(t *testing.T) {
  86. commitAndPush(t, littleSize, dstPath)
  87. })
  88. t.Run("Big", func(t *testing.T) {
  89. commitAndPush(t, bigSize, dstPath)
  90. })
  91. })
  92. })
  93. t.Run("LFS", func(t *testing.T) {
  94. t.Run("PushCommit", func(t *testing.T) {
  95. //Setup git LFS
  96. _, err = git.NewCommand("lfs").AddArguments("install").RunInDir(dstPath)
  97. assert.NoError(t, err)
  98. _, err = git.NewCommand("lfs").AddArguments("track", "data-file-*").RunInDir(dstPath)
  99. assert.NoError(t, err)
  100. err = git.AddChanges(dstPath, false, ".gitattributes")
  101. assert.NoError(t, err)
  102. t.Run("Little", func(t *testing.T) {
  103. commitAndPush(t, littleSize, dstPath)
  104. })
  105. t.Run("Big", func(t *testing.T) {
  106. commitAndPush(t, bigSize, dstPath)
  107. })
  108. })
  109. t.Run("Locks", func(t *testing.T) {
  110. lockTest(t, u.String(), dstPath)
  111. })
  112. })
  113. })
  114. t.Run("SSH", func(t *testing.T) {
  115. //Setup remote link
  116. u.Scheme = "ssh"
  117. u.User = url.User("git")
  118. u.Host = fmt.Sprintf("%s:%d", setting.SSH.ListenHost, setting.SSH.ListenPort)
  119. u.Path = "user2/repo-tmp-18.git"
  120. //Setup key
  121. keyFile := filepath.Join(setting.AppDataPath, "my-testing-key")
  122. err := exec.Command("ssh-keygen", "-f", keyFile, "-t", "rsa", "-N", "").Run()
  123. assert.NoError(t, err)
  124. defer os.RemoveAll(keyFile)
  125. defer os.RemoveAll(keyFile + ".pub")
  126. session := loginUser(t, "user1")
  127. keyOwner := models.AssertExistsAndLoadBean(t, &models.User{Name: "user2"}).(*models.User)
  128. urlStr := fmt.Sprintf("/api/v1/admin/users/%s/keys", keyOwner.Name)
  129. dataPubKey, err := ioutil.ReadFile(keyFile + ".pub")
  130. assert.NoError(t, err)
  131. req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
  132. "key": string(dataPubKey),
  133. "title": "test-key",
  134. })
  135. session.MakeRequest(t, req, http.StatusCreated)
  136. //Setup ssh wrapper
  137. os.Setenv("GIT_SSH_COMMAND",
  138. "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i "+
  139. filepath.Join(setting.AppWorkPath, keyFile))
  140. os.Setenv("GIT_SSH_VARIANT", "ssh")
  141. //Setup clone folder
  142. dstPath, err := ioutil.TempDir("", "repo-tmp-18")
  143. assert.NoError(t, err)
  144. defer os.RemoveAll(dstPath)
  145. t.Run("Standard", func(t *testing.T) {
  146. t.Run("CreateRepo", func(t *testing.T) {
  147. session := loginUser(t, "user2")
  148. token := getTokenForLoggedInUser(t, session)
  149. req := NewRequestWithJSON(t, "POST", "/api/v1/user/repos?token="+token, &api.CreateRepoOption{
  150. AutoInit: true,
  151. Description: "Temporary repo",
  152. Name: "repo-tmp-18",
  153. Private: false,
  154. Gitignores: "",
  155. License: "WTFPL",
  156. Readme: "Default",
  157. })
  158. session.MakeRequest(t, req, http.StatusCreated)
  159. })
  160. //TODO get url from api
  161. t.Run("Clone", func(t *testing.T) {
  162. _, err = git.NewCommand("clone").AddArguments(u.String(), dstPath).Run()
  163. assert.NoError(t, err)
  164. assert.True(t, com.IsExist(filepath.Join(dstPath, "README.md")))
  165. })
  166. //time.Sleep(5 * time.Minute)
  167. t.Run("PushCommit", func(t *testing.T) {
  168. t.Run("Little", func(t *testing.T) {
  169. commitAndPush(t, littleSize, dstPath)
  170. })
  171. t.Run("Big", func(t *testing.T) {
  172. commitAndPush(t, bigSize, dstPath)
  173. })
  174. })
  175. })
  176. t.Run("LFS", func(t *testing.T) {
  177. t.Run("PushCommit", func(t *testing.T) {
  178. //Setup git LFS
  179. _, err = git.NewCommand("lfs").AddArguments("install").RunInDir(dstPath)
  180. assert.NoError(t, err)
  181. _, err = git.NewCommand("lfs").AddArguments("track", "data-file-*").RunInDir(dstPath)
  182. assert.NoError(t, err)
  183. err = git.AddChanges(dstPath, false, ".gitattributes")
  184. assert.NoError(t, err)
  185. t.Run("Little", func(t *testing.T) {
  186. commitAndPush(t, littleSize, dstPath)
  187. })
  188. t.Run("Big", func(t *testing.T) {
  189. commitAndPush(t, bigSize, dstPath)
  190. })
  191. })
  192. t.Run("Locks", func(t *testing.T) {
  193. lockTest(t, u.String(), dstPath)
  194. })
  195. })
  196. })
  197. })
  198. }
  199. func lockTest(t *testing.T, remote, repoPath string) {
  200. _, err := git.NewCommand("remote").AddArguments("set-url", "origin", remote).RunInDir(repoPath) //TODO add test ssh git-lfs-creds
  201. assert.NoError(t, err)
  202. _, err = git.NewCommand("lfs").AddArguments("locks").RunInDir(repoPath)
  203. assert.NoError(t, err)
  204. _, err = git.NewCommand("lfs").AddArguments("lock", "README.md").RunInDir(repoPath)
  205. assert.NoError(t, err)
  206. _, err = git.NewCommand("lfs").AddArguments("locks").RunInDir(repoPath)
  207. assert.NoError(t, err)
  208. _, err = git.NewCommand("lfs").AddArguments("unlock", "README.md").RunInDir(repoPath)
  209. assert.NoError(t, err)
  210. }
  211. func commitAndPush(t *testing.T, size int, repoPath string) {
  212. err := generateCommitWithNewData(size, repoPath, "user2@example.com", "User Two")
  213. assert.NoError(t, err)
  214. _, err = git.NewCommand("push").RunInDir(repoPath) //Push
  215. assert.NoError(t, err)
  216. }
  217. func generateCommitWithNewData(size int, repoPath, email, fullName string) error {
  218. //Generate random file
  219. data := make([]byte, size)
  220. _, err := rand.Read(data)
  221. if err != nil {
  222. return err
  223. }
  224. tmpFile, err := ioutil.TempFile(repoPath, "data-file-")
  225. if err != nil {
  226. return err
  227. }
  228. defer tmpFile.Close()
  229. _, err = tmpFile.Write(data)
  230. if err != nil {
  231. return err
  232. }
  233. //Commit
  234. err = git.AddChanges(repoPath, false, filepath.Base(tmpFile.Name()))
  235. if err != nil {
  236. return err
  237. }
  238. err = git.CommitChanges(repoPath, git.CommitChangesOptions{
  239. Committer: &git.Signature{
  240. Email: email,
  241. Name: fullName,
  242. When: time.Now(),
  243. },
  244. Author: &git.Signature{
  245. Email: email,
  246. Name: fullName,
  247. When: time.Now(),
  248. },
  249. Message: fmt.Sprintf("Testing commit @ %v", time.Now()),
  250. })
  251. return err
  252. }