Add `last_committer_date` and `last_author_date` for file contents API (#32921)

Fix #32886

Add `last_committer_date` and `last_author_date` in the content API
which is not implemented by Github API v3 at the moment.

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
pull/34106/head^2
Lunny Xiao 2025-04-02 21:47:31 -07:00 committed by GitHub
parent c27d87a9ac
commit 45c45934aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 264 additions and 176 deletions

View File

@ -4,6 +4,8 @@
package structs
import "time"
// FileOptions options for all file APIs
type FileOptions struct {
// message (optional) for the commit of this file. if not supplied, a default message will be used
@ -121,6 +123,10 @@ type ContentsResponse struct {
Path string `json:"path"`
SHA string `json:"sha"`
LastCommitSHA string `json:"last_commit_sha"`
// swagger:strfmt date-time
LastCommitterDate time.Time `json:"last_committer_date"`
// swagger:strfmt date-time
LastAuthorDate time.Time `json:"last_author_date"`
// `type` will be `file`, `dir`, `symlink`, or `submodule`
Type string `json:"type"`
Size int64 `json:"size"`

View File

@ -188,6 +188,14 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref
},
}
// GitHub doesn't have these fields in the response, but we could follow other similar APIs to name them
// https://docs.github.com/en/rest/commits/commits?apiVersion=2022-11-28#list-commits
if lastCommit.Committer != nil {
contentsResponse.LastCommitterDate = lastCommit.Committer.When
}
if lastCommit.Author != nil {
contentsResponse.LastAuthorDate = lastCommit.Author.When
}
// Now populate the rest of the ContentsResponse based on entry type
if entry.IsRegular() || entry.IsExecutable() {
contentsResponse.Type = string(ContentTypeRegular)

View File

@ -5,6 +5,7 @@ package files
import (
"testing"
"time"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/gitrepo"
@ -30,18 +31,20 @@ 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",
LastCommitSHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d",
Type: "file",
Size: 30,
Encoding: &encoding,
Content: &content,
URL: &selfURL,
HTMLURL: &htmlURL,
GitURL: &gitURL,
DownloadURL: &downloadURL,
Name: treePath,
Path: treePath,
SHA: "4b4851ad51df6a7d9f25c979345979eaeb5b349f",
LastCommitSHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d",
LastCommitterDate: time.Date(2017, time.March, 19, 16, 47, 59, 0, time.FixedZone("", -14400)),
LastAuthorDate: time.Date(2017, time.March, 19, 16, 47, 59, 0, time.FixedZone("", -14400)),
Type: "file",
Size: 30,
Encoding: &encoding,
Content: &content,
URL: &selfURL,
HTMLURL: &htmlURL,
GitURL: &gitURL,
DownloadURL: &downloadURL,
Links: &api.FileLinksResponse{
Self: &selfURL,
GitURL: &gitURL,

View File

@ -5,6 +5,7 @@ package files
import (
"testing"
"time"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/gitrepo"
@ -42,18 +43,20 @@ 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,
LastCommitSHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d",
Type: "file",
Size: 30,
Encoding: &encoding,
Content: &content,
URL: &selfURL,
HTMLURL: &htmlURL,
GitURL: &gitURL,
DownloadURL: &downloadURL,
Name: treePath,
Path: treePath,
SHA: sha,
LastCommitSHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d",
LastCommitterDate: time.Date(2017, time.March, 19, 16, 47, 59, 0, time.FixedZone("", -14400)),
LastAuthorDate: time.Date(2017, time.March, 19, 16, 47, 59, 0, time.FixedZone("", -14400)),
Type: "file",
Size: 30,
Encoding: &encoding,
Content: &content,
URL: &selfURL,
HTMLURL: &htmlURL,
GitURL: &gitURL,
DownloadURL: &downloadURL,
Links: &api.FileLinksResponse{
Self: &selfURL,
GitURL: &gitURL,

View File

@ -20411,10 +20411,20 @@
"type": "string",
"x-go-name": "HTMLURL"
},
"last_author_date": {
"type": "string",
"format": "date-time",
"x-go-name": "LastAuthorDate"
},
"last_commit_sha": {
"type": "string",
"x-go-name": "LastCommitSHA"
},
"last_committer_date": {
"type": "string",
"format": "date-time",
"x-go-name": "LastCommitterDate"
},
"name": {
"type": "string",
"x-go-name": "Name"

View File

@ -8,7 +8,7 @@ import (
"fmt"
"net/http"
"net/url"
"path/filepath"
"path"
"testing"
"time"
@ -49,28 +49,42 @@ func getCreateFileOptions() api.CreateFileOptions {
}
}
func getExpectedFileResponseForCreate(repoFullName, commitID, treePath, latestCommitSHA string) *api.FileResponse {
func normalizeFileContentResponseCommitTime(c *api.ContentsResponse) {
// decoded JSON response may contain different timezone from the one parsed by git commit
// so we need to normalize the time to UTC to make "assert.Equal" pass
c.LastCommitterDate = c.LastCommitterDate.UTC()
c.LastAuthorDate = c.LastAuthorDate.UTC()
}
type apiFileResponseInfo struct {
repoFullName, commitID, treePath, lastCommitSHA string
lastCommitterWhen, lastAuthorWhen time.Time
}
func getExpectedFileResponseForCreate(info apiFileResponseInfo) *api.FileResponse {
sha := "a635aa942442ddfdba07468cf9661c08fbdf0ebf"
encoding := "base64"
content := "VGhpcyBpcyBuZXcgdGV4dA=="
selfURL := setting.AppURL + "api/v1/repos/" + repoFullName + "/contents/" + treePath + "?ref=master"
htmlURL := setting.AppURL + repoFullName + "/src/branch/master/" + treePath
gitURL := setting.AppURL + "api/v1/repos/" + repoFullName + "/git/blobs/" + sha
downloadURL := setting.AppURL + repoFullName + "/raw/branch/master/" + treePath
return &api.FileResponse{
selfURL := setting.AppURL + "api/v1/repos/" + info.repoFullName + "/contents/" + info.treePath + "?ref=master"
htmlURL := setting.AppURL + info.repoFullName + "/src/branch/master/" + info.treePath
gitURL := setting.AppURL + "api/v1/repos/" + info.repoFullName + "/git/blobs/" + sha
downloadURL := setting.AppURL + info.repoFullName + "/raw/branch/master/" + info.treePath
ret := &api.FileResponse{
Content: &api.ContentsResponse{
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,
Name: path.Base(info.treePath),
Path: info.treePath,
SHA: sha,
LastCommitSHA: info.lastCommitSHA,
LastCommitterDate: info.lastCommitterWhen,
LastAuthorDate: info.lastAuthorWhen,
Size: 16,
Type: "file",
Encoding: &encoding,
Content: &content,
URL: &selfURL,
HTMLURL: &htmlURL,
GitURL: &gitURL,
DownloadURL: &downloadURL,
Links: &api.FileLinksResponse{
Self: &selfURL,
GitURL: &gitURL,
@ -79,10 +93,10 @@ func getExpectedFileResponseForCreate(repoFullName, commitID, treePath, latestCo
},
Commit: &api.FileCommitResponse{
CommitMeta: api.CommitMeta{
URL: setting.AppURL + "api/v1/repos/" + repoFullName + "/git/commits/" + commitID,
SHA: commitID,
URL: setting.AppURL + "api/v1/repos/" + info.repoFullName + "/git/commits/" + info.commitID,
SHA: info.commitID,
},
HTMLURL: setting.AppURL + repoFullName + "/commit/" + commitID,
HTMLURL: setting.AppURL + info.repoFullName + "/commit/" + info.commitID,
Author: &api.CommitUser{
Identity: api.Identity{
Name: "Anne Doe",
@ -106,6 +120,8 @@ func getExpectedFileResponseForCreate(repoFullName, commitID, treePath, latestCo
Payload: "",
},
}
normalizeFileContentResponseCommitTime(ret.Content)
return ret
}
func BenchmarkAPICreateFileSmall(b *testing.B) {
@ -167,11 +183,20 @@ func TestAPICreateFile(t *testing.T) {
AddTokenAuth(token2)
resp := MakeRequest(t, req, http.StatusCreated)
gitRepo, _ := gitrepo.OpenRepository(t.Context(), repo1)
defer gitRepo.Close()
commitID, _ := gitRepo.GetBranchCommitID(createFileOptions.NewBranchName)
latestCommit, _ := gitRepo.GetCommitByPath(treePath)
expectedFileResponse := getExpectedFileResponseForCreate("user2/repo1", commitID, treePath, latestCommit.ID.String())
lastCommit, _ := gitRepo.GetCommitByPath(treePath)
expectedFileResponse := getExpectedFileResponseForCreate(apiFileResponseInfo{
repoFullName: "user2/repo1",
commitID: commitID,
treePath: treePath,
lastCommitSHA: lastCommit.ID.String(),
lastCommitterWhen: lastCommit.Committer.When,
lastAuthorWhen: lastCommit.Author.When,
})
var fileResponse api.FileResponse
DecodeJSON(t, resp, &fileResponse)
normalizeFileContentResponseCommitTime(fileResponse.Content)
assert.Equal(t, expectedFileResponse.Content, fileResponse.Content)
assert.Equal(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA)
assert.Equal(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL)
@ -181,7 +206,6 @@ func TestAPICreateFile(t *testing.T) {
assert.Equal(t, expectedFileResponse.Commit.Committer.Email, fileResponse.Commit.Committer.Email)
assert.Equal(t, expectedFileResponse.Commit.Committer.Name, fileResponse.Commit.Committer.Name)
assert.Equal(t, expectedFileResponse.Commit.Committer.Date, fileResponse.Commit.Committer.Date)
gitRepo.Close()
}
// Test creating a file in a new branch
@ -285,10 +309,19 @@ func TestAPICreateFile(t *testing.T) {
resp = MakeRequest(t, req, http.StatusCreated)
emptyRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user2", Name: "empty-repo"}) // public repo
gitRepo, _ := gitrepo.OpenRepository(t.Context(), emptyRepo)
defer gitRepo.Close()
commitID, _ := gitRepo.GetBranchCommitID(createFileOptions.NewBranchName)
latestCommit, _ := gitRepo.GetCommitByPath(treePath)
expectedFileResponse := getExpectedFileResponseForCreate("user2/empty-repo", commitID, treePath, latestCommit.ID.String())
expectedFileResponse := getExpectedFileResponseForCreate(apiFileResponseInfo{
repoFullName: "user2/empty-repo",
commitID: commitID,
treePath: treePath,
lastCommitSHA: latestCommit.ID.String(),
lastCommitterWhen: latestCommit.Committer.When,
lastAuthorWhen: latestCommit.Author.When,
})
DecodeJSON(t, resp, &fileResponse)
normalizeFileContentResponseCommitTime(fileResponse.Content)
assert.Equal(t, expectedFileResponse.Content, fileResponse.Content)
assert.Equal(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA)
assert.Equal(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL)
@ -298,6 +331,5 @@ func TestAPICreateFile(t *testing.T) {
assert.Equal(t, expectedFileResponse.Commit.Committer.Email, fileResponse.Commit.Committer.Email)
assert.Equal(t, expectedFileResponse.Commit.Committer.Name, fileResponse.Commit.Committer.Name)
assert.Equal(t, expectedFileResponse.Commit.Committer.Date, fileResponse.Commit.Committer.Date)
gitRepo.Close()
})
}

View File

@ -8,7 +8,7 @@ import (
"fmt"
"net/http"
"net/url"
"path/filepath"
"path"
"testing"
auth_model "code.gitea.io/gitea/models/auth"
@ -47,28 +47,30 @@ func getUpdateFileOptions() *api.UpdateFileOptions {
}
}
func getExpectedFileResponseForUpdate(commitID, treePath, lastCommitSHA string) *api.FileResponse {
func getExpectedFileResponseForUpdate(info apiFileResponseInfo) *api.FileResponse {
sha := "08bd14b2e2852529157324de9c226b3364e76136"
encoding := "base64"
content := "VGhpcyBpcyB1cGRhdGVkIHRleHQ="
selfURL := setting.AppURL + "api/v1/repos/user2/repo1/contents/" + treePath + "?ref=master"
htmlURL := setting.AppURL + "user2/repo1/src/branch/master/" + treePath
selfURL := setting.AppURL + "api/v1/repos/user2/repo1/contents/" + info.treePath + "?ref=master"
htmlURL := setting.AppURL + "user2/repo1/src/branch/master/" + info.treePath
gitURL := setting.AppURL + "api/v1/repos/user2/repo1/git/blobs/" + sha
downloadURL := setting.AppURL + "user2/repo1/raw/branch/master/" + treePath
return &api.FileResponse{
downloadURL := setting.AppURL + "user2/repo1/raw/branch/master/" + info.treePath
ret := &api.FileResponse{
Content: &api.ContentsResponse{
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,
Name: path.Base(info.treePath),
Path: info.treePath,
SHA: sha,
LastCommitSHA: info.lastCommitSHA,
LastCommitterDate: info.lastCommitterWhen,
LastAuthorDate: info.lastAuthorWhen,
Type: "file",
Size: 20,
Encoding: &encoding,
Content: &content,
URL: &selfURL,
HTMLURL: &htmlURL,
GitURL: &gitURL,
DownloadURL: &downloadURL,
Links: &api.FileLinksResponse{
Self: &selfURL,
GitURL: &gitURL,
@ -77,10 +79,10 @@ func getExpectedFileResponseForUpdate(commitID, treePath, lastCommitSHA string)
},
Commit: &api.FileCommitResponse{
CommitMeta: api.CommitMeta{
URL: setting.AppURL + "api/v1/repos/user2/repo1/git/commits/" + commitID,
SHA: commitID,
URL: setting.AppURL + "api/v1/repos/user2/repo1/git/commits/" + info.commitID,
SHA: info.commitID,
},
HTMLURL: setting.AppURL + "user2/repo1/commit/" + commitID,
HTMLURL: setting.AppURL + "user2/repo1/commit/" + info.commitID,
Author: &api.CommitUser{
Identity: api.Identity{
Name: "John Doe",
@ -102,6 +104,8 @@ func getExpectedFileResponseForUpdate(commitID, treePath, lastCommitSHA string)
Payload: "",
},
}
normalizeFileContentResponseCommitTime(ret.Content)
return ret
}
func TestAPIUpdateFile(t *testing.T) {
@ -135,17 +139,24 @@ func TestAPIUpdateFile(t *testing.T) {
AddTokenAuth(token2)
resp := MakeRequest(t, req, http.StatusOK)
gitRepo, _ := gitrepo.OpenRepository(t.Context(), repo1)
defer gitRepo.Close()
commitID, _ := gitRepo.GetBranchCommitID(updateFileOptions.NewBranchName)
lasCommit, _ := gitRepo.GetCommitByPath(treePath)
expectedFileResponse := getExpectedFileResponseForUpdate(commitID, treePath, lasCommit.ID.String())
expectedFileResponse := getExpectedFileResponseForUpdate(apiFileResponseInfo{
commitID: commitID,
treePath: treePath,
lastCommitSHA: lasCommit.ID.String(),
lastCommitterWhen: lasCommit.Committer.When,
lastAuthorWhen: lasCommit.Author.When,
})
var fileResponse api.FileResponse
DecodeJSON(t, resp, &fileResponse)
normalizeFileContentResponseCommitTime(fileResponse.Content)
assert.Equal(t, expectedFileResponse.Content, fileResponse.Content)
assert.Equal(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA)
assert.Equal(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL)
assert.Equal(t, expectedFileResponse.Commit.Author.Email, fileResponse.Commit.Author.Email)
assert.Equal(t, expectedFileResponse.Commit.Author.Name, fileResponse.Commit.Author.Name)
gitRepo.Close()
}
// Test updating a file in a new branch

View File

@ -77,51 +77,56 @@ func TestAPIChangeFiles(t *testing.T) {
token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
// Test changing files in repo1 which user2 owns, try both with branch and empty branch
for _, branch := range [...]string{
"master", // Branch
"", // Empty branch
} {
fileID++
createTreePath := fmt.Sprintf("new/file%d.txt", fileID)
updateTreePath := fmt.Sprintf("update/file%d.txt", fileID)
deleteTreePath := fmt.Sprintf("delete/file%d.txt", fileID)
createFile(user2, repo1, updateTreePath)
createFile(user2, repo1, deleteTreePath)
changeFilesOptions := getChangeFilesOptions()
changeFilesOptions.BranchName = branch
changeFilesOptions.Files[0].Path = createTreePath
changeFilesOptions.Files[1].Path = updateTreePath
changeFilesOptions.Files[2].Path = deleteTreePath
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/contents", user2.Name, repo1.Name), &changeFilesOptions).
AddTokenAuth(token2)
resp := MakeRequest(t, req, http.StatusCreated)
gitRepo, _ := gitrepo.OpenRepository(t.Context(), repo1)
commitID, _ := gitRepo.GetBranchCommitID(changeFilesOptions.NewBranchName)
createLasCommit, _ := gitRepo.GetCommitByPath(createTreePath)
updateLastCommit, _ := gitRepo.GetCommitByPath(updateTreePath)
expectedCreateFileResponse := getExpectedFileResponseForCreate(fmt.Sprintf("%v/%v", user2.Name, repo1.Name), commitID, createTreePath, createLasCommit.ID.String())
expectedUpdateFileResponse := getExpectedFileResponseForUpdate(commitID, updateTreePath, updateLastCommit.ID.String())
var filesResponse api.FilesResponse
DecodeJSON(t, resp, &filesResponse)
// check create file
assert.Equal(t, expectedCreateFileResponse.Content, filesResponse.Files[0])
// check update file
assert.Equal(t, expectedUpdateFileResponse.Content, filesResponse.Files[1])
// test commit info
assert.Equal(t, expectedCreateFileResponse.Commit.SHA, filesResponse.Commit.SHA)
assert.Equal(t, expectedCreateFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
assert.Equal(t, expectedCreateFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email)
assert.Equal(t, expectedCreateFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name)
assert.Equal(t, expectedCreateFileResponse.Commit.Committer.Email, filesResponse.Commit.Committer.Email)
assert.Equal(t, expectedCreateFileResponse.Commit.Committer.Name, filesResponse.Commit.Committer.Name)
// test delete file
assert.Nil(t, filesResponse.Files[2])
gitRepo.Close()
for _, branch := range []string{"master", ""} {
t.Run("Branch-"+branch, func(t *testing.T) {
fileID++
createTreePath := fmt.Sprintf("new/file%d.txt", fileID)
updateTreePath := fmt.Sprintf("update/file%d.txt", fileID)
deleteTreePath := fmt.Sprintf("delete/file%d.txt", fileID)
_, _ = createFile(user2, repo1, updateTreePath)
_, _ = createFile(user2, repo1, deleteTreePath)
changeFilesOptions := getChangeFilesOptions()
changeFilesOptions.BranchName = branch
changeFilesOptions.Files[0].Path = createTreePath
changeFilesOptions.Files[1].Path = updateTreePath
changeFilesOptions.Files[2].Path = deleteTreePath
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/contents", user2.Name, repo1.Name), &changeFilesOptions).
AddTokenAuth(token2)
resp := MakeRequest(t, req, http.StatusCreated)
gitRepo, _ := gitrepo.OpenRepository(t.Context(), repo1)
defer gitRepo.Close()
commitID, _ := gitRepo.GetBranchCommitID(changeFilesOptions.NewBranchName)
createLasCommit, _ := gitRepo.GetCommitByPath(createTreePath)
updateLastCommit, _ := gitRepo.GetCommitByPath(updateTreePath)
expectedCreateFileResponse := getExpectedFileResponseForCreate(apiFileResponseInfo{
repoFullName: fmt.Sprintf("%s/%s", user2.Name, repo1.Name),
commitID: commitID,
treePath: createTreePath,
lastCommitSHA: createLasCommit.ID.String(),
lastCommitterWhen: createLasCommit.Committer.When,
lastAuthorWhen: createLasCommit.Author.When,
})
expectedUpdateFileResponse := getExpectedFileResponseForUpdate(apiFileResponseInfo{
commitID: commitID,
treePath: updateTreePath,
lastCommitSHA: updateLastCommit.ID.String(),
lastCommitterWhen: updateLastCommit.Committer.When,
lastAuthorWhen: updateLastCommit.Author.When,
})
var filesResponse api.FilesResponse
DecodeJSON(t, resp, &filesResponse)
normalizeFileContentResponseCommitTime(filesResponse.Files[0])
normalizeFileContentResponseCommitTime(filesResponse.Files[1])
assert.Equal(t, expectedCreateFileResponse.Content, filesResponse.Files[0]) // check create file
assert.Equal(t, expectedUpdateFileResponse.Content, filesResponse.Files[1]) // check update file
assert.Equal(t, expectedCreateFileResponse.Commit.SHA, filesResponse.Commit.SHA)
assert.Equal(t, expectedCreateFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
assert.Equal(t, expectedCreateFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email)
assert.Equal(t, expectedCreateFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name)
assert.Equal(t, expectedCreateFileResponse.Commit.Committer.Email, filesResponse.Commit.Committer.Email)
assert.Equal(t, expectedCreateFileResponse.Commit.Committer.Name, filesResponse.Commit.Committer.Name)
assert.Nil(t, filesResponse.Files[2]) // test delete file
})
}
// Test changing files in a new branch

View File

@ -6,8 +6,9 @@ package integration
import (
"net/http"
"net/url"
"path/filepath"
"path"
"testing"
"time"
auth_model "code.gitea.io/gitea/models/auth"
repo_model "code.gitea.io/gitea/models/repo"
@ -31,16 +32,18 @@ func getExpectedContentsListResponseForContents(ref, refType, lastCommitSHA stri
downloadURL := setting.AppURL + "user2/repo1/raw/" + refType + "/" + ref + "/" + treePath
return []*api.ContentsResponse{
{
Name: filepath.Base(treePath),
Path: treePath,
SHA: sha,
LastCommitSHA: lastCommitSHA,
Type: "file",
Size: 30,
URL: &selfURL,
HTMLURL: &htmlURL,
GitURL: &gitURL,
DownloadURL: &downloadURL,
Name: path.Base(treePath),
Path: treePath,
SHA: sha,
LastCommitSHA: lastCommitSHA,
LastCommitterDate: time.Date(2017, time.March, 19, 16, 47, 59, 0, time.FixedZone("", -14400)),
LastAuthorDate: time.Date(2017, time.March, 19, 16, 47, 59, 0, time.FixedZone("", -14400)),
Type: "file",
Size: 30,
URL: &selfURL,
HTMLURL: &htmlURL,
GitURL: &gitURL,
DownloadURL: &downloadURL,
Links: &api.FileLinksResponse{
Self: &selfURL,
GitURL: &gitURL,

View File

@ -8,6 +8,7 @@ import (
"net/http"
"net/url"
"testing"
"time"
auth_model "code.gitea.io/gitea/models/auth"
repo_model "code.gitea.io/gitea/models/repo"
@ -33,18 +34,20 @@ func getExpectedContentsResponseForContents(ref, refType, lastCommitSHA string)
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,
LastCommitSHA: lastCommitSHA,
Type: "file",
Size: 30,
Encoding: &encoding,
Content: &content,
URL: &selfURL,
HTMLURL: &htmlURL,
GitURL: &gitURL,
DownloadURL: &downloadURL,
Name: treePath,
Path: treePath,
SHA: sha,
LastCommitSHA: lastCommitSHA,
LastCommitterDate: time.Date(2017, time.March, 19, 16, 47, 59, 0, time.FixedZone("", -14400)),
LastAuthorDate: time.Date(2017, time.March, 19, 16, 47, 59, 0, time.FixedZone("", -14400)),
Type: "file",
Size: 30,
Encoding: &encoding,
Content: &content,
URL: &selfURL,
HTMLURL: &htmlURL,
GitURL: &gitURL,
DownloadURL: &downloadURL,
Links: &api.FileLinksResponse{
Self: &selfURL,
GitURL: &gitURL,

View File

@ -6,7 +6,7 @@ package integration
import (
"fmt"
"net/url"
"path/filepath"
"path"
"strings"
"testing"
"time"
@ -79,7 +79,7 @@ func getDeleteRepoFilesOptions(repo *repo_model.Repository) *files_service.Chang
}
}
func getExpectedFileResponseForRepofilesDelete() *api.FileResponse {
func getExpectedFileResponseForRepoFilesDelete() *api.FileResponse {
// Just returns fields that don't change, i.e. fields with commit SHAs and dates can't be determined
return &api.FileResponse{
Content: nil,
@ -107,7 +107,7 @@ func getExpectedFileResponseForRepofilesDelete() *api.FileResponse {
}
}
func getExpectedFileResponseForRepofilesCreate(commitID, lastCommitSHA string) *api.FileResponse {
func getExpectedFileResponseForRepoFilesCreate(commitID string, lastCommit *git.Commit) *api.FileResponse {
treePath := "new/file.txt"
encoding := "base64"
content := "VGhpcyBpcyBhIE5FVyBmaWxl"
@ -117,18 +117,20 @@ func getExpectedFileResponseForRepofilesCreate(commitID, lastCommitSHA string) *
downloadURL := setting.AppURL + "user2/repo1/raw/branch/master/" + treePath
return &api.FileResponse{
Content: &api.ContentsResponse{
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,
Name: path.Base(treePath),
Path: treePath,
SHA: "103ff9234cefeee5ec5361d22b49fbb04d385885",
LastCommitSHA: lastCommit.ID.String(),
LastCommitterDate: lastCommit.Committer.When,
LastAuthorDate: lastCommit.Author.When,
Type: "file",
Size: 18,
Encoding: &encoding,
Content: &content,
URL: &selfURL,
HTMLURL: &htmlURL,
GitURL: &gitURL,
DownloadURL: &downloadURL,
Links: &api.FileLinksResponse{
Self: &selfURL,
GitURL: &gitURL,
@ -176,7 +178,7 @@ func getExpectedFileResponseForRepofilesCreate(commitID, lastCommitSHA string) *
}
}
func getExpectedFileResponseForRepofilesUpdate(commitID, filename, lastCommitSHA string) *api.FileResponse {
func getExpectedFileResponseForRepoFilesUpdate(commitID, filename, lastCommitSHA string, lastCommitterWhen, lastAuthorWhen time.Time) *api.FileResponse {
encoding := "base64"
content := "VGhpcyBpcyBVUERBVEVEIGNvbnRlbnQgZm9yIHRoZSBSRUFETUUgZmlsZQ=="
selfURL := setting.AppURL + "api/v1/repos/user2/repo1/contents/" + filename + "?ref=master"
@ -185,18 +187,20 @@ func getExpectedFileResponseForRepofilesUpdate(commitID, filename, lastCommitSHA
downloadURL := setting.AppURL + "user2/repo1/raw/branch/master/" + filename
return &api.FileResponse{
Content: &api.ContentsResponse{
Name: filename,
Path: filename,
SHA: "dbf8d00e022e05b7e5cf7e535de857de57925647",
LastCommitSHA: lastCommitSHA,
Type: "file",
Size: 43,
Encoding: &encoding,
Content: &content,
URL: &selfURL,
HTMLURL: &htmlURL,
GitURL: &gitURL,
DownloadURL: &downloadURL,
Name: filename,
Path: filename,
SHA: "dbf8d00e022e05b7e5cf7e535de857de57925647",
LastCommitSHA: lastCommitSHA,
LastCommitterDate: lastCommitterWhen,
LastAuthorDate: lastAuthorWhen,
Type: "file",
Size: 43,
Encoding: &encoding,
Content: &content,
URL: &selfURL,
HTMLURL: &htmlURL,
GitURL: &gitURL,
DownloadURL: &downloadURL,
Links: &api.FileLinksResponse{
Self: &selfURL,
GitURL: &gitURL,
@ -269,7 +273,7 @@ func TestChangeRepoFilesForCreate(t *testing.T) {
commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch)
lastCommit, _ := gitRepo.GetCommitByPath("new/file.txt")
expectedFileResponse := getExpectedFileResponseForRepofilesCreate(commitID, lastCommit.ID.String())
expectedFileResponse := getExpectedFileResponseForRepoFilesCreate(commitID, lastCommit)
assert.NotNil(t, expectedFileResponse)
if expectedFileResponse != nil {
assert.Equal(t, expectedFileResponse.Content, filesResponse.Files[0])
@ -306,7 +310,7 @@ func TestChangeRepoFilesForUpdate(t *testing.T) {
commit, _ := gitRepo.GetBranchCommit(opts.NewBranch)
lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath)
expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String())
expectedFileResponse := getExpectedFileResponseForRepoFilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String(), lastCommit.Committer.When, lastCommit.Author.When)
assert.Equal(t, expectedFileResponse.Content, filesResponse.Files[0])
assert.Equal(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA)
assert.Equal(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
@ -342,7 +346,7 @@ func TestChangeRepoFilesForUpdateWithFileMove(t *testing.T) {
commit, _ := gitRepo.GetBranchCommit(opts.NewBranch)
lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath)
expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String())
expectedFileResponse := getExpectedFileResponseForRepoFilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String(), lastCommit.Committer.When, lastCommit.Author.When)
// assert that the old file no longer exists in the last commit of the branch
fromEntry, err := commit.GetTreeEntryByPath(opts.Files[0].FromTreePath)
switch err.(type) {
@ -393,7 +397,7 @@ func TestChangeRepoFilesWithoutBranchNames(t *testing.T) {
commit, _ := gitRepo.GetBranchCommit(repo.DefaultBranch)
lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath)
expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String())
expectedFileResponse := getExpectedFileResponseForRepoFilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String(), lastCommit.Committer.When, lastCommit.Author.When)
assert.Equal(t, expectedFileResponse.Content, filesResponse.Files[0])
})
}
@ -419,7 +423,7 @@ func testDeleteRepoFiles(t *testing.T, u *url.URL) {
t.Run("Delete README.md file", func(t *testing.T) {
filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
assert.NoError(t, err)
expectedFileResponse := getExpectedFileResponseForRepofilesDelete()
expectedFileResponse := getExpectedFileResponseForRepoFilesDelete()
assert.NotNil(t, filesResponse)
assert.Nil(t, filesResponse.Files[0])
assert.Equal(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message)
@ -461,7 +465,7 @@ func testDeleteRepoFilesWithoutBranchNames(t *testing.T, u *url.URL) {
t.Run("Delete README.md without Branch Name", func(t *testing.T) {
filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
assert.NoError(t, err)
expectedFileResponse := getExpectedFileResponseForRepofilesDelete()
expectedFileResponse := getExpectedFileResponseForRepoFilesDelete()
assert.NotNil(t, filesResponse)
assert.Nil(t, filesResponse.Files[0])
assert.Equal(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message)