From ef78309b6535e4feff7b48d4b119180504616e13 Mon Sep 17 00:00:00 2001 From: Antoine GIRARD Date: Fri, 8 Dec 2017 13:21:37 +0100 Subject: [PATCH] Improve LFS tests + fix lfs url refs + keep path upper/lowercase in db. (#3092) * Add failing test * Fix urls * Improve url in tests * improve testing * Remove debug code * Add deps * LFS corner-case : Search on lower but store with case * Temporary comment of blocking action * fix hooks * Use temporary repo for git client test * Use userPassword in place of hard-coded password --- integrations/git_test.go | 153 ++++++++++++++++-- .../repo1.git/hooks/post-receive.d/gitea | 2 +- .../user2/repo1.git/hooks/pre-receive.d/gitea | 2 +- .../user2/repo1.git/hooks/update.d/gitea | 2 +- .../repo15.git/hooks/post-receive.d/gitea | 2 +- .../repo15.git/hooks/pre-receive.d/gitea | 2 +- .../user2/repo15.git/hooks/update.d/gitea | 2 +- .../repo3.git/hooks/post-receive.d/gitea | 2 +- .../user3/repo3.git/hooks/pre-receive.d/gitea | 2 +- .../user3/repo3.git/hooks/update.d/gitea | 2 +- models/lfs_lock.go | 6 +- modules/lfs/server.go | 4 +- routers/repo/view.go | 2 +- 13 files changed, 154 insertions(+), 29 deletions(-) diff --git a/integrations/git_test.go b/integrations/git_test.go index 5e6334d20..53814cf41 100644 --- a/integrations/git_test.go +++ b/integrations/git_test.go @@ -6,27 +6,32 @@ package integrations import ( "context" - "fmt" "io/ioutil" + "math/rand" "net" "net/http" + "net/url" "os" "path/filepath" "testing" "time" "code.gitea.io/git" + "code.gitea.io/gitea/modules/setting" + api "code.gitea.io/sdk/gitea" "github.com/Unknwon/com" "github.com/stretchr/testify/assert" ) -func onGiteaWebRun(t *testing.T, callback func(*testing.T, string)) { +func onGiteaWebRun(t *testing.T, callback func(*testing.T, *url.URL)) { s := http.Server{ Handler: mac, } - listener, err := net.Listen("tcp", "") + u, err := url.Parse(setting.AppURL) + assert.NoError(t, err) + listener, err := net.Listen("tcp", u.Host) assert.NoError(t, err) defer func() { @@ -37,24 +42,144 @@ func onGiteaWebRun(t *testing.T, callback func(*testing.T, string)) { go s.Serve(listener) - _, port, err := net.SplitHostPort(listener.Addr().String()) - assert.NoError(t, err) - - callback(t, fmt.Sprintf("http://localhost:%s/", port)) + callback(t, u) } -func TestClone_ViaHTTP_NoLogin(t *testing.T) { +func TestGit(t *testing.T) { prepareTestEnv(t) - onGiteaWebRun(t, func(t *testing.T, urlPrefix string) { - dstPath, err := ioutil.TempDir("", "repo1") + onGiteaWebRun(t, func(t *testing.T, u *url.URL) { + dstPath, err := ioutil.TempDir("", "repo-tmp-17") assert.NoError(t, err) defer os.RemoveAll(dstPath) + u.Path = "user2/repo1.git" - err = git.Clone(fmt.Sprintf("%suser2/repo1.git", urlPrefix), - dstPath, git.CloneRepoOptions{}) - assert.NoError(t, err) + t.Run("Standard", func(t *testing.T) { + + t.Run("CloneNoLogin", func(t *testing.T) { + dstLocalPath, err := ioutil.TempDir("", "repo1") + assert.NoError(t, err) + defer os.RemoveAll(dstLocalPath) + err = git.Clone(u.String(), dstLocalPath, git.CloneRepoOptions{}) + assert.NoError(t, err) + assert.True(t, com.IsExist(filepath.Join(dstLocalPath, "README.md"))) + }) + + t.Run("CreateRepo", func(t *testing.T) { + session := loginUser(t, "user2") + req := NewRequestWithJSON(t, "POST", "/api/v1/user/repos", &api.CreateRepoOption{ + AutoInit: true, + Description: "Temporary repo", + Name: "repo-tmp-17", + Private: false, + Gitignores: "", + License: "WTFPL", + Readme: "Default", + }) + session.MakeRequest(t, req, http.StatusCreated) + }) + + u.Path = "user2/repo-tmp-17.git" + u.User = url.UserPassword("user2", userPassword) + t.Run("Clone", func(t *testing.T) { + err = git.Clone(u.String(), dstPath, git.CloneRepoOptions{}) + assert.NoError(t, err) + assert.True(t, com.IsExist(filepath.Join(dstPath, "README.md"))) + }) + + t.Run("PushCommit", func(t *testing.T) { + data := make([]byte, 1024) + _, err := rand.Read(data) + assert.NoError(t, err) + tmpFile, err := ioutil.TempFile(dstPath, "data-file-") + defer tmpFile.Close() + _, err = tmpFile.Write(data) + assert.NoError(t, err) + + //Commit + err = git.AddChanges(dstPath, false, filepath.Base(tmpFile.Name())) + assert.NoError(t, err) + err = git.CommitChanges(dstPath, git.CommitChangesOptions{ + Committer: &git.Signature{ + Email: "user2@example.com", + Name: "User Two", + When: time.Now(), + }, + Author: &git.Signature{ + Email: "user2@example.com", + Name: "User Two", + When: time.Now(), + }, + Message: "Testing commit", + }) + assert.NoError(t, err) + + //Push + err = git.Push(dstPath, git.PushOptions{ + Branch: "master", + Remote: u.String(), + Force: false, + }) + assert.NoError(t, err) + }) + }) + t.Run("LFS", func(t *testing.T) { + t.Run("PushCommit", func(t *testing.T) { + /* Generate random file */ + data := make([]byte, 1024) + _, err := rand.Read(data) + assert.NoError(t, err) + tmpFile, err := ioutil.TempFile(dstPath, "data-file-") + defer tmpFile.Close() + _, err = tmpFile.Write(data) + assert.NoError(t, err) + + //Setup git LFS + _, err = git.NewCommand("lfs").AddArguments("install").RunInDir(dstPath) + assert.NoError(t, err) + _, err = git.NewCommand("lfs").AddArguments("track", "data-file-*").RunInDir(dstPath) + assert.NoError(t, err) + + //Commit + err = git.AddChanges(dstPath, false, ".gitattributes", filepath.Base(tmpFile.Name())) + assert.NoError(t, err) + err = git.CommitChanges(dstPath, git.CommitChangesOptions{ + Committer: &git.Signature{ + Email: "user2@example.com", + Name: "User Two", + When: time.Now(), + }, + Author: &git.Signature{ + Email: "user2@example.com", + Name: "User Two", + When: time.Now(), + }, + Message: "Testing LFS ", + }) + assert.NoError(t, err) + + //Push + u.User = url.UserPassword("user2", userPassword) + err = git.Push(dstPath, git.PushOptions{ + Branch: "master", + Remote: u.String(), + Force: false, + }) + assert.NoError(t, err) + }) + t.Run("Locks", func(t *testing.T) { + _, err = git.NewCommand("remote").AddArguments("set-url", "origin", u.String()).RunInDir(dstPath) //TODO add test ssh git-lfs-creds + assert.NoError(t, err) + _, err = git.NewCommand("lfs").AddArguments("locks").RunInDir(dstPath) + assert.NoError(t, err) + _, err = git.NewCommand("lfs").AddArguments("lock", "README.md").RunInDir(dstPath) + assert.NoError(t, err) + _, err = git.NewCommand("lfs").AddArguments("locks").RunInDir(dstPath) + assert.NoError(t, err) + _, err = git.NewCommand("lfs").AddArguments("unlock", "README.md").RunInDir(dstPath) + assert.NoError(t, err) + }) - assert.True(t, com.IsExist(filepath.Join(dstPath, "README.md"))) + }) }) } diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/hooks/post-receive.d/gitea b/integrations/gitea-repositories-meta/user2/repo1.git/hooks/post-receive.d/gitea index 2eb3be983..43a948da3 100755 --- a/integrations/gitea-repositories-meta/user2/repo1.git/hooks/post-receive.d/gitea +++ b/integrations/gitea-repositories-meta/user2/repo1.git/hooks/post-receive.d/gitea @@ -1,2 +1,2 @@ #!/usr/bin/env bash -"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' post-receive +"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" post-receive diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/hooks/pre-receive.d/gitea b/integrations/gitea-repositories-meta/user2/repo1.git/hooks/pre-receive.d/gitea index 1933f6cff..49d094063 100755 --- a/integrations/gitea-repositories-meta/user2/repo1.git/hooks/pre-receive.d/gitea +++ b/integrations/gitea-repositories-meta/user2/repo1.git/hooks/pre-receive.d/gitea @@ -1,2 +1,2 @@ #!/usr/bin/env bash -"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' pre-receive +"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" pre-receive diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/hooks/update.d/gitea b/integrations/gitea-repositories-meta/user2/repo1.git/hooks/update.d/gitea index 615b4f4b8..38101c242 100755 --- a/integrations/gitea-repositories-meta/user2/repo1.git/hooks/update.d/gitea +++ b/integrations/gitea-repositories-meta/user2/repo1.git/hooks/update.d/gitea @@ -1,2 +1,2 @@ #!/usr/bin/env bash -"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' update $1 $2 $3 +"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" update $1 $2 $3 diff --git a/integrations/gitea-repositories-meta/user2/repo15.git/hooks/post-receive.d/gitea b/integrations/gitea-repositories-meta/user2/repo15.git/hooks/post-receive.d/gitea index 2eb3be983..43a948da3 100755 --- a/integrations/gitea-repositories-meta/user2/repo15.git/hooks/post-receive.d/gitea +++ b/integrations/gitea-repositories-meta/user2/repo15.git/hooks/post-receive.d/gitea @@ -1,2 +1,2 @@ #!/usr/bin/env bash -"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' post-receive +"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" post-receive diff --git a/integrations/gitea-repositories-meta/user2/repo15.git/hooks/pre-receive.d/gitea b/integrations/gitea-repositories-meta/user2/repo15.git/hooks/pre-receive.d/gitea index 1933f6cff..49d094063 100755 --- a/integrations/gitea-repositories-meta/user2/repo15.git/hooks/pre-receive.d/gitea +++ b/integrations/gitea-repositories-meta/user2/repo15.git/hooks/pre-receive.d/gitea @@ -1,2 +1,2 @@ #!/usr/bin/env bash -"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' pre-receive +"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" pre-receive diff --git a/integrations/gitea-repositories-meta/user2/repo15.git/hooks/update.d/gitea b/integrations/gitea-repositories-meta/user2/repo15.git/hooks/update.d/gitea index 615b4f4b8..38101c242 100755 --- a/integrations/gitea-repositories-meta/user2/repo15.git/hooks/update.d/gitea +++ b/integrations/gitea-repositories-meta/user2/repo15.git/hooks/update.d/gitea @@ -1,2 +1,2 @@ #!/usr/bin/env bash -"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' update $1 $2 $3 +"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" update $1 $2 $3 diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/hooks/post-receive.d/gitea b/integrations/gitea-repositories-meta/user3/repo3.git/hooks/post-receive.d/gitea index 2eb3be983..43a948da3 100755 --- a/integrations/gitea-repositories-meta/user3/repo3.git/hooks/post-receive.d/gitea +++ b/integrations/gitea-repositories-meta/user3/repo3.git/hooks/post-receive.d/gitea @@ -1,2 +1,2 @@ #!/usr/bin/env bash -"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' post-receive +"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" post-receive diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/hooks/pre-receive.d/gitea b/integrations/gitea-repositories-meta/user3/repo3.git/hooks/pre-receive.d/gitea index 1933f6cff..49d094063 100755 --- a/integrations/gitea-repositories-meta/user3/repo3.git/hooks/pre-receive.d/gitea +++ b/integrations/gitea-repositories-meta/user3/repo3.git/hooks/pre-receive.d/gitea @@ -1,2 +1,2 @@ #!/usr/bin/env bash -"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' pre-receive +"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" pre-receive diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/hooks/update.d/gitea b/integrations/gitea-repositories-meta/user3/repo3.git/hooks/update.d/gitea index 615b4f4b8..38101c242 100755 --- a/integrations/gitea-repositories-meta/user3/repo3.git/hooks/update.d/gitea +++ b/integrations/gitea-repositories-meta/user3/repo3.git/hooks/update.d/gitea @@ -1,2 +1,2 @@ #!/usr/bin/env bash -"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' update $1 $2 $3 +"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" update $1 $2 $3 diff --git a/models/lfs_lock.go b/models/lfs_lock.go index 83811bc7b..9bb87843a 100644 --- a/models/lfs_lock.go +++ b/models/lfs_lock.go @@ -36,7 +36,7 @@ func (l *LFSLock) AfterLoad() { } func cleanPath(p string) string { - return strings.ToLower(path.Clean(p)) + return path.Clean(p) } // APIFormat convert a Release to lfs.LFSLock @@ -73,8 +73,8 @@ func CreateLFSLock(lock *LFSLock) (*LFSLock, error) { // GetLFSLock returns release by given path. func GetLFSLock(repoID int64, path string) (*LFSLock, error) { path = cleanPath(path) - rel := &LFSLock{RepoID: repoID, Path: path} - has, err := x.Get(rel) + rel := &LFSLock{RepoID: repoID} + has, err := x.Where("lower(path) = ?", strings.ToLower(path)).Get(rel) if err != nil { return nil, err } diff --git a/modules/lfs/server.go b/modules/lfs/server.go index 474a3f56c..329d6f00c 100644 --- a/modules/lfs/server.go +++ b/modules/lfs/server.go @@ -68,12 +68,12 @@ type ObjectError struct { // ObjectLink builds a URL linking to the object. func (v *RequestVars) ObjectLink() string { - return setting.AppURL + path.Join(v.User, v.Repo, "info/lfs/objects", v.Oid) + return setting.AppURL + path.Join(v.User, v.Repo+".git", "info/lfs/objects", v.Oid) } // VerifyLink builds a URL for verifying the object. func (v *RequestVars) VerifyLink() string { - return setting.AppURL + path.Join(v.User, v.Repo, "info/lfs/verify") + return setting.AppURL + path.Join(v.User, v.Repo+".git", "info/lfs/verify") } // link provides a structure used to build a hypermedia representation of an HTTP link. diff --git a/routers/repo/view.go b/routers/repo/view.go index a02acb0d6..512af27fc 100644 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -179,7 +179,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st ctx.Data["IsLFSFile"] = true ctx.Data["FileSize"] = size filenameBase64 := base64.RawURLEncoding.EncodeToString([]byte(blob.Name())) - ctx.Data["RawFileLink"] = fmt.Sprintf("%s%s/info/lfs/objects/%s/%s", setting.AppURL, ctx.Repo.Repository.FullName(), oid, filenameBase64) + ctx.Data["RawFileLink"] = fmt.Sprintf("%s%s.git/info/lfs/objects/%s/%s", setting.AppURL, ctx.Repo.Repository.FullName(), oid, filenameBase64) } } }