From 2fd356bde0db2c00ea911aa66fdbf66a83ff5fc2 Mon Sep 17 00:00:00 2001 From: Gusted Date: Mon, 18 Jul 2022 10:53:15 +0200 Subject: [PATCH 1/7] Add latest commit's SHA to content response - When requesting the contents of a filepath, add the latest commit's SHA to the requested file. - Resolves #12840 --- modules/structs/repo_file.go | 7 ++++--- services/repository/files/content.go | 16 +++++++++++----- services/repository/files/content_test.go | 23 ++++++++++++----------- services/repository/files/file_test.go | 23 ++++++++++++----------- 4 files changed, 39 insertions(+), 30 deletions(-) diff --git a/modules/structs/repo_file.go b/modules/structs/repo_file.go index 135e6484cd69b..ce1a9fe4be365 100644 --- a/modules/structs/repo_file.go +++ b/modules/structs/repo_file.go @@ -87,9 +87,10 @@ type FileLinksResponse struct { // ContentsResponse contains information about a repo's entry's (dir, file, symlink, submodule) metadata and content type ContentsResponse struct { - Name string `json:"name"` - Path string `json:"path"` - SHA string `json:"sha"` + Name string `json:"name"` + Path string `json:"path"` + SHA string `json:"sha"` + LastCommitSHA string `json:"last_commit_sha"` // `type` will be `file`, `dir`, `symlink`, or `submodule` Type string `json:"type"` Size int64 `json:"size"` diff --git a/services/repository/files/content.go b/services/repository/files/content.go index 2237671a60cbb..67f04cc388d2e 100644 --- a/services/repository/files/content.go +++ b/services/repository/files/content.go @@ -149,13 +149,19 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref } selfURLString := selfURL.String() + lastCommit, err := gitRepo.GetCommitByPath(treePath) + if err != nil { + return nil, err + } + // All content types have these fields in populated contentsResponse := &api.ContentsResponse{ - Name: entry.Name(), - Path: treePath, - SHA: entry.ID.String(), - Size: entry.Size(), - URL: &selfURLString, + Name: entry.Name(), + Path: treePath, + SHA: entry.ID.String(), + LastCommitSHA: lastCommit.ID.String(), + Size: entry.Size(), + URL: &selfURLString, Links: &api.FileLinksResponse{ Self: &selfURLString, }, diff --git a/services/repository/files/content_test.go b/services/repository/files/content_test.go index 342ebae329168..24fcd6c4c5d5e 100644 --- a/services/repository/files/content_test.go +++ b/services/repository/files/content_test.go @@ -33,17 +33,18 @@ func getExpectedReadmeContentsResponse() *api.ContentsResponse { gitURL := "https://try.gitea.io/api/v1/repos/user2/repo1/git/blobs/" + sha downloadURL := "https://try.gitea.io/user2/repo1/raw/branch/master/" + treePath return &api.ContentsResponse{ - Name: treePath, - Path: treePath, - SHA: "4b4851ad51df6a7d9f25c979345979eaeb5b349f", - Type: "file", - Size: 30, - Encoding: &encoding, - Content: &content, - URL: &selfURL, - HTMLURL: &htmlURL, - GitURL: &gitURL, - DownloadURL: &downloadURL, + Name: treePath, + Path: treePath, + SHA: "4b4851ad51df6a7d9f25c979345979eaeb5b349f", + LastCommitSHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d", + Type: "file", + Size: 30, + Encoding: &encoding, + Content: &content, + URL: &selfURL, + HTMLURL: &htmlURL, + GitURL: &gitURL, + DownloadURL: &downloadURL, Links: &api.FileLinksResponse{ Self: &selfURL, GitURL: &gitURL, diff --git a/services/repository/files/file_test.go b/services/repository/files/file_test.go index ee0582dfc2170..e158c63de24a7 100644 --- a/services/repository/files/file_test.go +++ b/services/repository/files/file_test.go @@ -43,17 +43,18 @@ func getExpectedFileResponse() *api.FileResponse { downloadURL := setting.AppURL + "user2/repo1/raw/branch/master/" + treePath return &api.FileResponse{ Content: &api.ContentsResponse{ - Name: treePath, - Path: treePath, - SHA: sha, - Type: "file", - Size: 30, - Encoding: &encoding, - Content: &content, - URL: &selfURL, - HTMLURL: &htmlURL, - GitURL: &gitURL, - DownloadURL: &downloadURL, + Name: treePath, + Path: treePath, + SHA: sha, + LastCommitSHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d", + Type: "file", + Size: 30, + Encoding: &encoding, + Content: &content, + URL: &selfURL, + HTMLURL: &htmlURL, + GitURL: &gitURL, + DownloadURL: &downloadURL, Links: &api.FileLinksResponse{ Self: &selfURL, GitURL: &gitURL, From 4c7d8661e6b1c9061cd6e5c5319961908ed39581 Mon Sep 17 00:00:00 2001 From: Gusted Date: Mon, 18 Jul 2022 10:59:56 +0200 Subject: [PATCH 2/7] Add swagger --- templates/swagger/v1_json.tmpl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index a3bb904845652..f6ebbc7e50916 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -13779,6 +13779,10 @@ "type": "string", "x-go-name": "HTMLURL" }, + "last_commit_sha": { + "type": "string", + "x-go-name": "LastCommitSHA" + }, "name": { "type": "string", "x-go-name": "Name" From a39cee6a2025e28b59c2ee1ce8ad2727fc6a00eb Mon Sep 17 00:00:00 2001 From: Gusted Date: Mon, 18 Jul 2022 12:44:57 +0200 Subject: [PATCH 3/7] Fix NPE --- integrations/api_repo_file_create_test.go | 31 +++++++++++++---------- services/repository/files/content.go | 2 +- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/integrations/api_repo_file_create_test.go b/integrations/api_repo_file_create_test.go index eb550f1d28d74..fd460ce5643fc 100644 --- a/integrations/api_repo_file_create_test.go +++ b/integrations/api_repo_file_create_test.go @@ -50,7 +50,7 @@ func getCreateFileOptions() api.CreateFileOptions { } } -func getExpectedFileResponseForCreate(repoFullName, commitID, treePath string) *api.FileResponse { +func getExpectedFileResponseForCreate(repoFullName, commitID, treePath, latestCommitSHA string) *api.FileResponse { sha := "a635aa942442ddfdba07468cf9661c08fbdf0ebf" encoding := "base64" content := "VGhpcyBpcyBuZXcgdGV4dA==" @@ -60,17 +60,18 @@ func getExpectedFileResponseForCreate(repoFullName, commitID, treePath string) * downloadURL := setting.AppURL + repoFullName + "/raw/branch/master/" + treePath return &api.FileResponse{ Content: &api.ContentsResponse{ - Name: filepath.Base(treePath), - Path: treePath, - SHA: sha, - Size: 16, - Type: "file", - Encoding: &encoding, - Content: &content, - URL: &selfURL, - HTMLURL: &htmlURL, - GitURL: &gitURL, - DownloadURL: &downloadURL, + Name: filepath.Base(treePath), + Path: treePath, + SHA: sha, + LastCommitSHA: latestCommitSHA, + Size: 16, + Type: "file", + Encoding: &encoding, + Content: &content, + URL: &selfURL, + HTMLURL: &htmlURL, + GitURL: &gitURL, + DownloadURL: &downloadURL, Links: &api.FileLinksResponse{ Self: &selfURL, GitURL: &gitURL, @@ -170,7 +171,8 @@ func TestAPICreateFile(t *testing.T) { resp := session.MakeRequest(t, req, http.StatusCreated) gitRepo, _ := git.OpenRepository(stdCtx.Background(), repo1.RepoPath()) commitID, _ := gitRepo.GetBranchCommitID(createFileOptions.NewBranchName) - expectedFileResponse := getExpectedFileResponseForCreate("user2/repo1", commitID, treePath) + latestCommit, _ := gitRepo.GetCommitByPath(treePath) + expectedFileResponse := getExpectedFileResponseForCreate("user2/repo1", commitID, treePath, latestCommit.ID.String()) var fileResponse api.FileResponse DecodeJSON(t, resp, &fileResponse) assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content) @@ -289,7 +291,8 @@ func TestAPICreateFile(t *testing.T) { emptyRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user2", Name: "empty-repo"}).(*repo_model.Repository) // public repo gitRepo, _ := git.OpenRepository(stdCtx.Background(), emptyRepo.RepoPath()) commitID, _ := gitRepo.GetBranchCommitID(createFileOptions.NewBranchName) - expectedFileResponse := getExpectedFileResponseForCreate("user2/empty-repo", commitID, treePath) + latestCommit, _ := gitRepo.GetCommitByPath(treePath) + expectedFileResponse := getExpectedFileResponseForCreate("user2/empty-repo", commitID, treePath, latestCommit.ID.String()) DecodeJSON(t, resp, &fileResponse) assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content) assert.EqualValues(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA) diff --git a/services/repository/files/content.go b/services/repository/files/content.go index 67f04cc388d2e..4404c38713991 100644 --- a/services/repository/files/content.go +++ b/services/repository/files/content.go @@ -149,7 +149,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref } selfURLString := selfURL.String() - lastCommit, err := gitRepo.GetCommitByPath(treePath) + lastCommit, err := commit.GetCommitByPath(treePath) if err != nil { return nil, err } From d06bc0db880ea22a8c7a46cad50d91f1a76597f9 Mon Sep 17 00:00:00 2001 From: Gusted Date: Mon, 18 Jul 2022 16:11:11 +0200 Subject: [PATCH 4/7] Fix tests --- integrations/api_repo_file_update_test.go | 28 ++++---- .../api_repo_get_contents_list_test.go | 44 ++++++++----- integrations/api_repo_get_contents_test.go | 40 ++++++----- integrations/repofiles_update_test.go | 66 ++++++++++--------- 4 files changed, 102 insertions(+), 76 deletions(-) diff --git a/integrations/api_repo_file_update_test.go b/integrations/api_repo_file_update_test.go index 0c9c0763f4671..e39d83e49e13d 100644 --- a/integrations/api_repo_file_update_test.go +++ b/integrations/api_repo_file_update_test.go @@ -48,7 +48,7 @@ func getUpdateFileOptions() *api.UpdateFileOptions { } } -func getExpectedFileResponseForUpdate(commitID, treePath string) *api.FileResponse { +func getExpectedFileResponseForUpdate(commitID, treePath, lastCommitSHA string) *api.FileResponse { sha := "08bd14b2e2852529157324de9c226b3364e76136" encoding := "base64" content := "VGhpcyBpcyB1cGRhdGVkIHRleHQ=" @@ -58,17 +58,18 @@ func getExpectedFileResponseForUpdate(commitID, treePath string) *api.FileRespon downloadURL := setting.AppURL + "user2/repo1/raw/branch/master/" + treePath return &api.FileResponse{ Content: &api.ContentsResponse{ - Name: filepath.Base(treePath), - Path: treePath, - SHA: sha, - Type: "file", - Size: 20, - Encoding: &encoding, - Content: &content, - URL: &selfURL, - HTMLURL: &htmlURL, - GitURL: &gitURL, - DownloadURL: &downloadURL, + Name: filepath.Base(treePath), + Path: treePath, + SHA: sha, + LastCommitSHA: lastCommitSHA, + Type: "file", + Size: 20, + Encoding: &encoding, + Content: &content, + URL: &selfURL, + HTMLURL: &htmlURL, + GitURL: &gitURL, + DownloadURL: &downloadURL, Links: &api.FileLinksResponse{ Self: &selfURL, GitURL: &gitURL, @@ -137,7 +138,8 @@ func TestAPIUpdateFile(t *testing.T) { resp := session.MakeRequest(t, req, http.StatusOK) gitRepo, _ := git.OpenRepository(stdCtx.Background(), repo1.RepoPath()) commitID, _ := gitRepo.GetBranchCommitID(updateFileOptions.NewBranchName) - expectedFileResponse := getExpectedFileResponseForUpdate(commitID, treePath) + lasCommit, _ := gitRepo.GetCommitByPath(treePath) + expectedFileResponse := getExpectedFileResponseForUpdate(commitID, treePath, lasCommit.ID.String()) var fileResponse api.FileResponse DecodeJSON(t, resp, &fileResponse) assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content) diff --git a/integrations/api_repo_get_contents_list_test.go b/integrations/api_repo_get_contents_list_test.go index 42227a9c4b723..97b152bf1b34d 100644 --- a/integrations/api_repo_get_contents_list_test.go +++ b/integrations/api_repo_get_contents_list_test.go @@ -21,7 +21,7 @@ import ( "github.com/stretchr/testify/assert" ) -func getExpectedContentsListResponseForContents(ref, refType string) []*api.ContentsResponse { +func getExpectedContentsListResponseForContents(ref, refType, lastCommitSHA string) []*api.ContentsResponse { treePath := "README.md" sha := "4b4851ad51df6a7d9f25c979345979eaeb5b349f" selfURL := setting.AppURL + "api/v1/repos/user2/repo1/contents/" + treePath + "?ref=" + ref @@ -30,15 +30,16 @@ func getExpectedContentsListResponseForContents(ref, refType string) []*api.Cont downloadURL := setting.AppURL + "user2/repo1/raw/" + refType + "/" + ref + "/" + treePath return []*api.ContentsResponse{ { - Name: filepath.Base(treePath), - Path: treePath, - SHA: sha, - Type: "file", - Size: 30, - URL: &selfURL, - HTMLURL: &htmlURL, - GitURL: &gitURL, - DownloadURL: &downloadURL, + Name: filepath.Base(treePath), + Path: treePath, + SHA: sha, + LastCommitSHA: lastCommitSHA, + Type: "file", + Size: 30, + URL: &selfURL, + HTMLURL: &htmlURL, + GitURL: &gitURL, + DownloadURL: &downloadURL, Links: &api.FileLinksResponse{ Self: &selfURL, GitURL: &gitURL, @@ -94,7 +95,9 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) { var contentsListResponse []*api.ContentsResponse DecodeJSON(t, resp, &contentsListResponse) assert.NotNil(t, contentsListResponse) - expectedContentsListResponse := getExpectedContentsListResponseForContents(ref, refType) + lastCommit, err := gitRepo.GetCommitByPath("README.md") + assert.NoError(t, err) + expectedContentsListResponse := getExpectedContentsListResponseForContents(ref, refType, lastCommit.ID.String()) assert.EqualValues(t, expectedContentsListResponse, contentsListResponse) // No ref @@ -103,17 +106,22 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) { resp = session.MakeRequest(t, req, http.StatusOK) DecodeJSON(t, resp, &contentsListResponse) assert.NotNil(t, contentsListResponse) - expectedContentsListResponse = getExpectedContentsListResponseForContents(repo1.DefaultBranch, refType) + + expectedContentsListResponse = getExpectedContentsListResponseForContents(repo1.DefaultBranch, refType, lastCommit.ID.String()) assert.EqualValues(t, expectedContentsListResponse, contentsListResponse) - // ref is the branch we created above in setup + // ref is the branch we created above in setup ref = newBranch refType = "branch" req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref) resp = session.MakeRequest(t, req, http.StatusOK) DecodeJSON(t, resp, &contentsListResponse) assert.NotNil(t, contentsListResponse) - expectedContentsListResponse = getExpectedContentsListResponseForContents(ref, refType) + branchCommit, err := gitRepo.GetBranchCommit(ref) + assert.NoError(t, err) + lastCommit, err = branchCommit.GetCommitByPath("README.md") + assert.NoError(t, err) + expectedContentsListResponse = getExpectedContentsListResponseForContents(ref, refType, lastCommit.ID.String()) assert.EqualValues(t, expectedContentsListResponse, contentsListResponse) // ref is the new tag we created above in setup @@ -123,7 +131,11 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) { resp = session.MakeRequest(t, req, http.StatusOK) DecodeJSON(t, resp, &contentsListResponse) assert.NotNil(t, contentsListResponse) - expectedContentsListResponse = getExpectedContentsListResponseForContents(ref, refType) + tagCommit, err := gitRepo.GetTagCommit(ref) + assert.NoError(t, err) + lastCommit, err = tagCommit.GetCommitByPath("README.md") + assert.NoError(t, err) + expectedContentsListResponse = getExpectedContentsListResponseForContents(ref, refType, lastCommit.ID.String()) assert.EqualValues(t, expectedContentsListResponse, contentsListResponse) // ref is a commit @@ -133,7 +145,7 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) { resp = session.MakeRequest(t, req, http.StatusOK) DecodeJSON(t, resp, &contentsListResponse) assert.NotNil(t, contentsListResponse) - expectedContentsListResponse = getExpectedContentsListResponseForContents(ref, refType) + expectedContentsListResponse = getExpectedContentsListResponseForContents(ref, refType, commitID) assert.EqualValues(t, expectedContentsListResponse, contentsListResponse) // Test file contents a file with a bad ref diff --git a/integrations/api_repo_get_contents_test.go b/integrations/api_repo_get_contents_test.go index 67f2cb83625a0..56f5336b7bd94 100644 --- a/integrations/api_repo_get_contents_test.go +++ b/integrations/api_repo_get_contents_test.go @@ -20,7 +20,7 @@ import ( "github.com/stretchr/testify/assert" ) -func getExpectedContentsResponseForContents(ref, refType string) *api.ContentsResponse { +func getExpectedContentsResponseForContents(ref, refType, lastCommitSHA string) *api.ContentsResponse { treePath := "README.md" sha := "4b4851ad51df6a7d9f25c979345979eaeb5b349f" encoding := "base64" @@ -30,17 +30,18 @@ func getExpectedContentsResponseForContents(ref, refType string) *api.ContentsRe gitURL := setting.AppURL + "api/v1/repos/user2/repo1/git/blobs/" + sha downloadURL := setting.AppURL + "user2/repo1/raw/" + refType + "/" + ref + "/" + treePath return &api.ContentsResponse{ - Name: treePath, - Path: treePath, - SHA: sha, - Type: "file", - Size: 30, - Encoding: &encoding, - Content: &content, - URL: &selfURL, - HTMLURL: &htmlURL, - GitURL: &gitURL, - DownloadURL: &downloadURL, + Name: treePath, + Path: treePath, + SHA: sha, + LastCommitSHA: lastCommitSHA, + Type: "file", + Size: 30, + Encoding: &encoding, + Content: &content, + URL: &selfURL, + HTMLURL: &htmlURL, + GitURL: &gitURL, + DownloadURL: &downloadURL, Links: &api.FileLinksResponse{ Self: &selfURL, GitURL: &gitURL, @@ -96,7 +97,8 @@ func testAPIGetContents(t *testing.T, u *url.URL) { var contentsResponse api.ContentsResponse DecodeJSON(t, resp, &contentsResponse) assert.NotNil(t, contentsResponse) - expectedContentsResponse := getExpectedContentsResponseForContents(ref, refType) + lastCommit, _ := gitRepo.GetCommitByPath("README.md") + expectedContentsResponse := getExpectedContentsResponseForContents(ref, refType, lastCommit.ID.String()) assert.EqualValues(t, *expectedContentsResponse, contentsResponse) // No ref @@ -105,7 +107,7 @@ func testAPIGetContents(t *testing.T, u *url.URL) { resp = session.MakeRequest(t, req, http.StatusOK) DecodeJSON(t, resp, &contentsResponse) assert.NotNil(t, contentsResponse) - expectedContentsResponse = getExpectedContentsResponseForContents(repo1.DefaultBranch, refType) + expectedContentsResponse = getExpectedContentsResponseForContents(repo1.DefaultBranch, refType, lastCommit.ID.String()) assert.EqualValues(t, *expectedContentsResponse, contentsResponse) // ref is the branch we created above in setup @@ -115,7 +117,9 @@ func testAPIGetContents(t *testing.T, u *url.URL) { resp = session.MakeRequest(t, req, http.StatusOK) DecodeJSON(t, resp, &contentsResponse) assert.NotNil(t, contentsResponse) - expectedContentsResponse = getExpectedContentsResponseForContents(ref, refType) + branchCommit, _ := gitRepo.GetBranchCommit(ref) + lastCommit, _ = branchCommit.GetCommitByPath("README.md") + expectedContentsResponse = getExpectedContentsResponseForContents(ref, refType, lastCommit.ID.String()) assert.EqualValues(t, *expectedContentsResponse, contentsResponse) // ref is the new tag we created above in setup @@ -125,7 +129,9 @@ func testAPIGetContents(t *testing.T, u *url.URL) { resp = session.MakeRequest(t, req, http.StatusOK) DecodeJSON(t, resp, &contentsResponse) assert.NotNil(t, contentsResponse) - expectedContentsResponse = getExpectedContentsResponseForContents(ref, refType) + tagCommit, _ := gitRepo.GetTagCommit(ref) + lastCommit, _ = tagCommit.GetCommitByPath("README.md") + expectedContentsResponse = getExpectedContentsResponseForContents(ref, refType, lastCommit.ID.String()) assert.EqualValues(t, *expectedContentsResponse, contentsResponse) // ref is a commit @@ -135,7 +141,7 @@ func testAPIGetContents(t *testing.T, u *url.URL) { resp = session.MakeRequest(t, req, http.StatusOK) DecodeJSON(t, resp, &contentsResponse) assert.NotNil(t, contentsResponse) - expectedContentsResponse = getExpectedContentsResponseForContents(ref, refType) + expectedContentsResponse = getExpectedContentsResponseForContents(ref, refType, commitID) assert.EqualValues(t, *expectedContentsResponse, contentsResponse) // Test file contents a file with a bad ref diff --git a/integrations/repofiles_update_test.go b/integrations/repofiles_update_test.go index 2add99cc86ff9..ac9b0509eae40 100644 --- a/integrations/repofiles_update_test.go +++ b/integrations/repofiles_update_test.go @@ -47,7 +47,7 @@ func getUpdateRepoFileOptions(repo *repo_model.Repository) *files_service.Update } } -func getExpectedFileResponseForRepofilesCreate(commitID string) *api.FileResponse { +func getExpectedFileResponseForRepofilesCreate(commitID, lastCommitSHA string) *api.FileResponse { treePath := "new/file.txt" encoding := "base64" content := "VGhpcyBpcyBhIE5FVyBmaWxl" @@ -57,17 +57,18 @@ func getExpectedFileResponseForRepofilesCreate(commitID string) *api.FileRespons downloadURL := setting.AppURL + "user2/repo1/raw/branch/master/" + treePath return &api.FileResponse{ Content: &api.ContentsResponse{ - Name: filepath.Base(treePath), - Path: treePath, - SHA: "103ff9234cefeee5ec5361d22b49fbb04d385885", - Type: "file", - Size: 18, - Encoding: &encoding, - Content: &content, - URL: &selfURL, - HTMLURL: &htmlURL, - GitURL: &gitURL, - DownloadURL: &downloadURL, + Name: filepath.Base(treePath), + Path: treePath, + SHA: "103ff9234cefeee5ec5361d22b49fbb04d385885", + LastCommitSHA: lastCommitSHA, + Type: "file", + Size: 18, + Encoding: &encoding, + Content: &content, + URL: &selfURL, + HTMLURL: &htmlURL, + GitURL: &gitURL, + DownloadURL: &downloadURL, Links: &api.FileLinksResponse{ Self: &selfURL, GitURL: &gitURL, @@ -115,7 +116,7 @@ func getExpectedFileResponseForRepofilesCreate(commitID string) *api.FileRespons } } -func getExpectedFileResponseForRepofilesUpdate(commitID, filename string) *api.FileResponse { +func getExpectedFileResponseForRepofilesUpdate(commitID, filename, lastCommitSHA string) *api.FileResponse { encoding := "base64" content := "VGhpcyBpcyBVUERBVEVEIGNvbnRlbnQgZm9yIHRoZSBSRUFETUUgZmlsZQ==" selfURL := setting.AppURL + "api/v1/repos/user2/repo1/contents/" + filename + "?ref=master" @@ -124,17 +125,18 @@ func getExpectedFileResponseForRepofilesUpdate(commitID, filename string) *api.F downloadURL := setting.AppURL + "user2/repo1/raw/branch/master/" + filename return &api.FileResponse{ Content: &api.ContentsResponse{ - Name: filename, - Path: filename, - SHA: "dbf8d00e022e05b7e5cf7e535de857de57925647", - Type: "file", - Size: 43, - Encoding: &encoding, - Content: &content, - URL: &selfURL, - HTMLURL: &htmlURL, - GitURL: &gitURL, - DownloadURL: &downloadURL, + Name: filename, + Path: filename, + SHA: "dbf8d00e022e05b7e5cf7e535de857de57925647", + LastCommitSHA: lastCommitSHA, + Type: "file", + Size: 43, + Encoding: &encoding, + Content: &content, + URL: &selfURL, + HTMLURL: &htmlURL, + GitURL: &gitURL, + DownloadURL: &downloadURL, Links: &api.FileLinksResponse{ Self: &selfURL, GitURL: &gitURL, @@ -206,7 +208,8 @@ func TestCreateOrUpdateRepoFileForCreate(t *testing.T) { defer gitRepo.Close() commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch) - expectedFileResponse := getExpectedFileResponseForRepofilesCreate(commitID) + lastCommit, _ := gitRepo.GetCommitByPath("new/file.txt") + expectedFileResponse := getExpectedFileResponseForRepofilesCreate(commitID, lastCommit.ID.String()) assert.NotNil(t, expectedFileResponse) if expectedFileResponse != nil { assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content) @@ -241,8 +244,9 @@ func TestCreateOrUpdateRepoFileForUpdate(t *testing.T) { gitRepo, _ := git.OpenRepository(git.DefaultContext, repo.RepoPath()) defer gitRepo.Close() - commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch) - expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commitID, opts.TreePath) + commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) + lastCommit, _ := commit.GetCommitByPath(opts.TreePath) + expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.TreePath, lastCommit.ID.String()) assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content) assert.EqualValues(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA) assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL) @@ -277,7 +281,8 @@ func TestCreateOrUpdateRepoFileForUpdateWithFileMove(t *testing.T) { defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) - expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.TreePath) + lastCommit, _ := commit.GetCommitByPath(opts.TreePath) + expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.TreePath, lastCommit.ID.String()) // assert that the old file no longer exists in the last commit of the branch fromEntry, err := commit.GetTreeEntryByPath(opts.FromTreePath) switch err.(type) { @@ -326,8 +331,9 @@ func TestCreateOrUpdateRepoFileWithoutBranchNames(t *testing.T) { gitRepo, _ := git.OpenRepository(git.DefaultContext, repo.RepoPath()) defer gitRepo.Close() - commitID, _ := gitRepo.GetBranchCommitID(repo.DefaultBranch) - expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commitID, opts.TreePath) + commit, _ := gitRepo.GetBranchCommit(repo.DefaultBranch) + lastCommit, _ := commit.GetCommitByPath(opts.TreePath) + expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.TreePath, lastCommit.ID.String()) assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content) }) } From b60aa056ea20042764ff1bc6bb3582679e21aa8c Mon Sep 17 00:00:00 2001 From: Gusted Date: Thu, 28 Jul 2022 13:40:03 +0200 Subject: [PATCH 5/7] Hook into LastCommitCache --- modules/git/repo_base_nogogit.go | 18 ++++++++++++++++++ routers/api/v1/utils/git.go | 17 +++-------------- services/repository/files/content.go | 5 +++++ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/modules/git/repo_base_nogogit.go b/modules/git/repo_base_nogogit.go index 56af2c640fd4a..35d70f8dbecab 100644 --- a/modules/git/repo_base_nogogit.go +++ b/modules/git/repo_base_nogogit.go @@ -13,6 +13,7 @@ import ( "errors" "path/filepath" + "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/log" ) @@ -85,6 +86,23 @@ func (repo *Repository) CatFileBatchCheck(ctx context.Context) (WriteCloserError return repo.checkWriter, repo.checkReader, func() {} } +func (repo *Repository) AddLastCommitCache(cacheKey, fullName, sha string) error { + if repo.LastCommitCache == nil { + commitsCount, err := cache.GetInt64(cacheKey, func() (int64, error) { + commit, err := repo.GetCommit(sha) + if err != nil { + return 0, err + } + return commit.CommitsCount() + }) + if err != nil { + return err + } + repo.LastCommitCache = NewLastCommitCache(commitsCount, fullName, repo, cache.GetCache()) + } + return nil +} + // Close this repository, in particular close the underlying gogitStorage if this is not nil func (repo *Repository) Close() (err error) { if repo == nil { diff --git a/routers/api/v1/utils/git.go b/routers/api/v1/utils/git.go index f18442d0468fd..7da04efe9edac 100644 --- a/routers/api/v1/utils/git.go +++ b/routers/api/v1/utils/git.go @@ -8,7 +8,6 @@ import ( "fmt" "net/http" - "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" @@ -35,19 +34,9 @@ func ResolveRefOrSha(ctx *context.APIContext, ref string) string { } } - if ctx.Repo.GitRepo != nil && ctx.Repo.GitRepo.LastCommitCache == nil { - commitsCount, err := cache.GetInt64(ctx.Repo.Repository.GetCommitsCountCacheKey(ref, true), func() (int64, error) { - commit, err := ctx.Repo.GitRepo.GetCommit(sha) - if err != nil { - return 0, err - } - return commit.CommitsCount() - }) - if err != nil { - log.Error("Unable to get commits count for %s in %s. Error: %v", sha, ctx.Repo.Repository.FullName(), err) - return sha - } - ctx.Repo.GitRepo.LastCommitCache = git.NewLastCommitCache(commitsCount, ctx.Repo.Repository.FullName(), ctx.Repo.GitRepo, cache.GetCache()) + err := ctx.Repo.GitRepo.AddLastCommitCache(ctx.Repo.Repository.GetCommitsCountCacheKey(ref, ref != sha), ctx.Repo.Repository.FullName(), sha) + if err != nil { + log.Error("Unable to get commits count for %s in %s. Error: %v", sha, ctx.Repo.Repository.FullName(), err) } return sha diff --git a/services/repository/files/content.go b/services/repository/files/content.go index 44ed6014dea73..34c8aeec25e43 100644 --- a/services/repository/files/content.go +++ b/services/repository/files/content.go @@ -165,6 +165,11 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref } selfURLString := selfURL.String() + err = gitRepo.AddLastCommitCache(repo.GetCommitsCountCacheKey(ref, refType != git.ObjectCommit), repo.FullName(), commitID) + if err != nil { + return nil, err + } + lastCommit, err := commit.GetCommitByPath(treePath) if err != nil { return nil, err From c79adcc65204f66911dbcc060d1a18d34240b57c Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Thu, 28 Jul 2022 18:41:07 +0100 Subject: [PATCH 6/7] Move AddLastCommitCache to a common nogogit and gogit file Signed-off-by: Andrew Thornton --- modules/git/repo_base_nogogit.go | 18 ------------------ modules/git/repo_commit.go | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/modules/git/repo_base_nogogit.go b/modules/git/repo_base_nogogit.go index 35d70f8dbecab..56af2c640fd4a 100644 --- a/modules/git/repo_base_nogogit.go +++ b/modules/git/repo_base_nogogit.go @@ -13,7 +13,6 @@ import ( "errors" "path/filepath" - "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/log" ) @@ -86,23 +85,6 @@ func (repo *Repository) CatFileBatchCheck(ctx context.Context) (WriteCloserError return repo.checkWriter, repo.checkReader, func() {} } -func (repo *Repository) AddLastCommitCache(cacheKey, fullName, sha string) error { - if repo.LastCommitCache == nil { - commitsCount, err := cache.GetInt64(cacheKey, func() (int64, error) { - commit, err := repo.GetCommit(sha) - if err != nil { - return 0, err - } - return commit.CommitsCount() - }) - if err != nil { - return err - } - repo.LastCommitCache = NewLastCommitCache(commitsCount, fullName, repo, cache.GetCache()) - } - return nil -} - // Close this repository, in particular close the underlying gogitStorage if this is not nil func (repo *Repository) Close() (err error) { if repo == nil { diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go index e6fec4d1a32e2..7ff23af42eb84 100644 --- a/modules/git/repo_commit.go +++ b/modules/git/repo_commit.go @@ -11,6 +11,7 @@ import ( "strconv" "strings" + "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/setting" ) @@ -434,3 +435,20 @@ func (repo *Repository) IsCommitInBranch(commitID, branch string) (r bool, err e } return len(stdout) > 0, err } + +func (repo *Repository) AddLastCommitCache(cacheKey, fullName, sha string) error { + if repo.LastCommitCache == nil { + commitsCount, err := cache.GetInt64(cacheKey, func() (int64, error) { + commit, err := repo.GetCommit(sha) + if err != nil { + return 0, err + } + return commit.CommitsCount() + }) + if err != nil { + return err + } + repo.LastCommitCache = NewLastCommitCache(commitsCount, fullName, repo, cache.GetCache()) + } + return nil +} From 035dafd00f289b880ac4e002be3c4bcb46fea3f3 Mon Sep 17 00:00:00 2001 From: Gusted Date: Sat, 30 Jul 2022 07:51:49 +0200 Subject: [PATCH 7/7] Prevent NPE --- routers/api/v1/utils/git.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/routers/api/v1/utils/git.go b/routers/api/v1/utils/git.go index 7da04efe9edac..816f8b3595f7e 100644 --- a/routers/api/v1/utils/git.go +++ b/routers/api/v1/utils/git.go @@ -34,9 +34,11 @@ func ResolveRefOrSha(ctx *context.APIContext, ref string) string { } } - err := ctx.Repo.GitRepo.AddLastCommitCache(ctx.Repo.Repository.GetCommitsCountCacheKey(ref, ref != sha), ctx.Repo.Repository.FullName(), sha) - if err != nil { - log.Error("Unable to get commits count for %s in %s. Error: %v", sha, ctx.Repo.Repository.FullName(), err) + if ctx.Repo.GitRepo != nil { + err := ctx.Repo.GitRepo.AddLastCommitCache(ctx.Repo.Repository.GetCommitsCountCacheKey(ref, ref != sha), ctx.Repo.Repository.FullName(), sha) + if err != nil { + log.Error("Unable to get commits count for %s in %s. Error: %v", sha, ctx.Repo.Repository.FullName(), err) + } } return sha