2019-05-11 18:29:17 +03:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2019-05-11 18:29:17 +03:00
2022-09-02 22:18:23 +03:00
package integration
2019-05-11 18:29:17 +03:00
import (
"net/url"
2019-06-29 23:51:10 +03:00
"path/filepath"
2023-07-18 21:14:47 +03:00
"strings"
2019-05-11 18:29:17 +03:00
"testing"
"time"
2021-12-10 04:27:50 +03:00
repo_model "code.gitea.io/gitea/models/repo"
2023-05-29 12:41:35 +03:00
"code.gitea.io/gitea/models/unittest"
2019-05-11 18:29:17 +03:00
"code.gitea.io/gitea/modules/git"
Simplify how git repositories are opened (#28937)
## Purpose
This is a refactor toward building an abstraction over managing git
repositories.
Afterwards, it does not matter anymore if they are stored on the local
disk or somewhere remote.
## What this PR changes
We used `git.OpenRepository` everywhere previously.
Now, we should split them into two distinct functions:
Firstly, there are temporary repositories which do not change:
```go
git.OpenRepository(ctx, diskPath)
```
Gitea managed repositories having a record in the database in the
`repository` table are moved into the new package `gitrepo`:
```go
gitrepo.OpenRepository(ctx, repo_model.Repo)
```
Why is `repo_model.Repository` the second parameter instead of file
path?
Because then we can easily adapt our repository storage strategy.
The repositories can be stored locally, however, they could just as well
be stored on a remote server.
## Further changes in other PRs
- A Git Command wrapper on package `gitrepo` could be created. i.e.
`NewCommand(ctx, repo_model.Repository, commands...)`. `git.RunOpts{Dir:
repo.RepoPath()}`, the directory should be empty before invoking this
method and it can be filled in the function only. #28940
- Remove the `RepoPath()`/`WikiPath()` functions to reduce the
possibility of mistakes.
---------
Co-authored-by: delvh <dev.lh@web.de>
2024-01-27 23:09:51 +03:00
"code.gitea.io/gitea/modules/gitrepo"
2019-05-11 18:29:17 +03:00
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
2024-02-27 10:12:22 +03:00
"code.gitea.io/gitea/services/contexttest"
2021-11-24 10:56:24 +03:00
files_service "code.gitea.io/gitea/services/repository/files"
2019-05-11 18:29:17 +03:00
"github.com/stretchr/testify/assert"
)
2023-05-29 12:41:35 +03:00
func getCreateRepoFilesOptions ( repo * repo_model . Repository ) * files_service . ChangeRepoFilesOptions {
return & files_service . ChangeRepoFilesOptions {
Files : [ ] * files_service . ChangeRepoFile {
{
2023-07-18 21:14:47 +03:00
Operation : "create" ,
TreePath : "new/file.txt" ,
ContentReader : strings . NewReader ( "This is a NEW file" ) ,
2023-05-29 12:41:35 +03:00
} ,
} ,
2019-05-11 18:29:17 +03:00
OldBranch : repo . DefaultBranch ,
NewBranch : repo . DefaultBranch ,
Message : "Creates new/file.txt" ,
Author : nil ,
Committer : nil ,
}
}
2023-05-29 12:41:35 +03:00
func getUpdateRepoFilesOptions ( repo * repo_model . Repository ) * files_service . ChangeRepoFilesOptions {
return & files_service . ChangeRepoFilesOptions {
Files : [ ] * files_service . ChangeRepoFile {
{
2023-07-18 21:14:47 +03:00
Operation : "update" ,
TreePath : "README.md" ,
SHA : "4b4851ad51df6a7d9f25c979345979eaeb5b349f" ,
ContentReader : strings . NewReader ( "This is UPDATED content for the README file" ) ,
2023-05-29 12:41:35 +03:00
} ,
} ,
2019-05-11 18:29:17 +03:00
OldBranch : repo . DefaultBranch ,
NewBranch : repo . DefaultBranch ,
Message : "Updates README.md" ,
Author : nil ,
Committer : nil ,
}
}
2023-05-29 12:41:35 +03:00
func getDeleteRepoFilesOptions ( repo * repo_model . Repository ) * files_service . ChangeRepoFilesOptions {
return & files_service . ChangeRepoFilesOptions {
Files : [ ] * files_service . ChangeRepoFile {
{
Operation : "delete" ,
TreePath : "README.md" ,
SHA : "4b4851ad51df6a7d9f25c979345979eaeb5b349f" ,
} ,
} ,
LastCommitID : "" ,
OldBranch : repo . DefaultBranch ,
NewBranch : repo . DefaultBranch ,
Message : "Deletes README.md" ,
Author : & files_service . IdentityOptions {
Name : "Bob Smith" ,
Email : "bob@smith.com" ,
} ,
Committer : nil ,
}
}
2024-04-29 11:47:56 +03:00
func getExpectedFileResponseForRepofilesDelete ( ) * api . FileResponse {
2023-05-29 12:41:35 +03:00
// Just returns fields that don't change, i.e. fields with commit SHAs and dates can't be determined
return & api . FileResponse {
Content : nil ,
Commit : & api . FileCommitResponse {
Author : & api . CommitUser {
Identity : api . Identity {
Name : "Bob Smith" ,
Email : "bob@smith.com" ,
} ,
} ,
Committer : & api . CommitUser {
Identity : api . Identity {
Name : "Bob Smith" ,
Email : "bob@smith.com" ,
} ,
} ,
Message : "Deletes README.md\n" ,
} ,
Verification : & api . PayloadCommitVerification {
Verified : false ,
Reason : "gpg.error.not_signed_commit" ,
Signature : "" ,
Payload : "" ,
} ,
}
}
2022-07-30 11:09:04 +03:00
func getExpectedFileResponseForRepofilesCreate ( commitID , lastCommitSHA string ) * api . FileResponse {
2019-06-29 23:51:10 +03:00
treePath := "new/file.txt"
encoding := "base64"
content := "VGhpcyBpcyBhIE5FVyBmaWxl"
selfURL := setting . AppURL + "api/v1/repos/user2/repo1/contents/" + treePath + "?ref=master"
htmlURL := setting . AppURL + "user2/repo1/src/branch/master/" + treePath
gitURL := setting . AppURL + "api/v1/repos/user2/repo1/git/blobs/103ff9234cefeee5ec5361d22b49fbb04d385885"
downloadURL := setting . AppURL + "user2/repo1/raw/branch/master/" + treePath
2019-05-11 18:29:17 +03:00
return & api . FileResponse {
2019-06-29 23:51:10 +03:00
Content : & api . ContentsResponse {
2022-07-30 11:09:04 +03:00
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 ,
2019-05-11 18:29:17 +03:00
Links : & api . FileLinksResponse {
2019-06-29 23:51:10 +03:00
Self : & selfURL ,
GitURL : & gitURL ,
HTMLURL : & htmlURL ,
2019-05-11 18:29:17 +03:00
} ,
} ,
Commit : & api . FileCommitResponse {
CommitMeta : api . CommitMeta {
URL : setting . AppURL + "api/v1/repos/user2/repo1/git/commits/" + commitID ,
SHA : commitID ,
} ,
HTMLURL : setting . AppURL + "user2/repo1/commit/" + commitID ,
Author : & api . CommitUser {
Identity : api . Identity {
Name : "User Two" ,
Email : "user2@noreply.example.org" ,
} ,
Date : time . Now ( ) . UTC ( ) . Format ( time . RFC3339 ) ,
} ,
Committer : & api . CommitUser {
Identity : api . Identity {
Name : "User Two" ,
Email : "user2@noreply.example.org" ,
} ,
Date : time . Now ( ) . UTC ( ) . Format ( time . RFC3339 ) ,
} ,
Parents : [ ] * api . CommitMeta {
{
URL : setting . AppURL + "api/v1/repos/user2/repo1/git/commits/65f1bf27bc3bf70f64657658635e66094edbcb4d" ,
SHA : "65f1bf27bc3bf70f64657658635e66094edbcb4d" ,
} ,
} ,
Message : "Updates README.md\n" ,
Tree : & api . CommitMeta {
URL : setting . AppURL + "api/v1/repos/user2/repo1/git/trees/f93e3a1a1525fb5b91020da86e44810c87a2d7bc" ,
SHA : "f93e3a1a1525fb5b91020git dda86e44810c87a2d7bc" ,
} ,
} ,
Verification : & api . PayloadCommitVerification {
Verified : false ,
2019-10-16 16:42:42 +03:00
Reason : "gpg.error.not_signed_commit" ,
2019-05-11 18:29:17 +03:00
Signature : "" ,
Payload : "" ,
} ,
}
}
2022-07-30 11:09:04 +03:00
func getExpectedFileResponseForRepofilesUpdate ( commitID , filename , lastCommitSHA string ) * api . FileResponse {
2019-06-29 23:51:10 +03:00
encoding := "base64"
content := "VGhpcyBpcyBVUERBVEVEIGNvbnRlbnQgZm9yIHRoZSBSRUFETUUgZmlsZQ=="
selfURL := setting . AppURL + "api/v1/repos/user2/repo1/contents/" + filename + "?ref=master"
htmlURL := setting . AppURL + "user2/repo1/src/branch/master/" + filename
gitURL := setting . AppURL + "api/v1/repos/user2/repo1/git/blobs/dbf8d00e022e05b7e5cf7e535de857de57925647"
downloadURL := setting . AppURL + "user2/repo1/raw/branch/master/" + filename
2019-05-11 18:29:17 +03:00
return & api . FileResponse {
2019-06-29 23:51:10 +03:00
Content : & api . ContentsResponse {
2022-07-30 11:09:04 +03:00
Name : filename ,
Path : filename ,
SHA : "dbf8d00e022e05b7e5cf7e535de857de57925647" ,
LastCommitSHA : lastCommitSHA ,
Type : "file" ,
Size : 43 ,
Encoding : & encoding ,
Content : & content ,
URL : & selfURL ,
HTMLURL : & htmlURL ,
GitURL : & gitURL ,
DownloadURL : & downloadURL ,
2019-05-11 18:29:17 +03:00
Links : & api . FileLinksResponse {
2019-06-29 23:51:10 +03:00
Self : & selfURL ,
GitURL : & gitURL ,
HTMLURL : & htmlURL ,
2019-05-11 18:29:17 +03:00
} ,
} ,
Commit : & api . FileCommitResponse {
CommitMeta : api . CommitMeta {
URL : setting . AppURL + "api/v1/repos/user2/repo1/git/commits/" + commitID ,
SHA : commitID ,
} ,
HTMLURL : setting . AppURL + "user2/repo1/commit/" + commitID ,
Author : & api . CommitUser {
Identity : api . Identity {
Name : "User Two" ,
Email : "user2@noreply.example.org" ,
} ,
Date : time . Now ( ) . UTC ( ) . Format ( time . RFC3339 ) ,
} ,
Committer : & api . CommitUser {
Identity : api . Identity {
Name : "User Two" ,
Email : "user2@noreply.example.org" ,
} ,
Date : time . Now ( ) . UTC ( ) . Format ( time . RFC3339 ) ,
} ,
Parents : [ ] * api . CommitMeta {
{
URL : setting . AppURL + "api/v1/repos/user2/repo1/git/commits/65f1bf27bc3bf70f64657658635e66094edbcb4d" ,
SHA : "65f1bf27bc3bf70f64657658635e66094edbcb4d" ,
} ,
} ,
Message : "Updates README.md\n" ,
Tree : & api . CommitMeta {
URL : setting . AppURL + "api/v1/repos/user2/repo1/git/trees/f93e3a1a1525fb5b91020da86e44810c87a2d7bc" ,
SHA : "f93e3a1a1525fb5b91020da86e44810c87a2d7bc" ,
} ,
} ,
Verification : & api . PayloadCommitVerification {
Verified : false ,
2019-10-16 16:42:42 +03:00
Reason : "gpg.error.not_signed_commit" ,
2019-05-11 18:29:17 +03:00
Signature : "" ,
Payload : "" ,
} ,
}
}
2023-05-29 12:41:35 +03:00
func TestChangeRepoFilesForCreate ( t * testing . T ) {
2019-05-11 18:29:17 +03:00
// setup
onGiteaRun ( t , func ( t * testing . T , u * url . URL ) {
2023-09-01 14:26:07 +03:00
ctx , _ := contexttest . MockContext ( t , "user2/repo1" )
2024-06-19 01:32:45 +03:00
ctx . SetPathParam ( ":id" , "1" )
2023-09-01 14:26:07 +03:00
contexttest . LoadRepo ( t , ctx , 1 )
contexttest . LoadRepoCommit ( t , ctx )
contexttest . LoadUser ( t , ctx , 2 )
contexttest . LoadGitRepo ( t , ctx )
2019-11-13 10:01:19 +03:00
defer ctx . Repo . GitRepo . Close ( )
2019-05-11 18:29:17 +03:00
repo := ctx . Repo . Repository
2022-03-22 10:03:22 +03:00
doer := ctx . Doer
2023-05-29 12:41:35 +03:00
opts := getCreateRepoFilesOptions ( repo )
2019-05-11 18:29:17 +03:00
// test
2023-05-29 12:41:35 +03:00
filesResponse , err := files_service . ChangeRepoFiles ( git . DefaultContext , repo , doer , opts )
2019-05-11 18:29:17 +03:00
// asserts
2020-07-19 12:53:40 +03:00
assert . NoError ( t , err )
Simplify how git repositories are opened (#28937)
## Purpose
This is a refactor toward building an abstraction over managing git
repositories.
Afterwards, it does not matter anymore if they are stored on the local
disk or somewhere remote.
## What this PR changes
We used `git.OpenRepository` everywhere previously.
Now, we should split them into two distinct functions:
Firstly, there are temporary repositories which do not change:
```go
git.OpenRepository(ctx, diskPath)
```
Gitea managed repositories having a record in the database in the
`repository` table are moved into the new package `gitrepo`:
```go
gitrepo.OpenRepository(ctx, repo_model.Repo)
```
Why is `repo_model.Repository` the second parameter instead of file
path?
Because then we can easily adapt our repository storage strategy.
The repositories can be stored locally, however, they could just as well
be stored on a remote server.
## Further changes in other PRs
- A Git Command wrapper on package `gitrepo` could be created. i.e.
`NewCommand(ctx, repo_model.Repository, commands...)`. `git.RunOpts{Dir:
repo.RepoPath()}`, the directory should be empty before invoking this
method and it can be filled in the function only. #28940
- Remove the `RepoPath()`/`WikiPath()` functions to reduce the
possibility of mistakes.
---------
Co-authored-by: delvh <dev.lh@web.de>
2024-01-27 23:09:51 +03:00
gitRepo , _ := gitrepo . OpenRepository ( git . DefaultContext , repo )
2019-11-13 10:01:19 +03:00
defer gitRepo . Close ( )
2019-05-11 18:29:17 +03:00
commitID , _ := gitRepo . GetBranchCommitID ( opts . NewBranch )
2022-07-30 11:09:04 +03:00
lastCommit , _ := gitRepo . GetCommitByPath ( "new/file.txt" )
expectedFileResponse := getExpectedFileResponseForRepofilesCreate ( commitID , lastCommit . ID . String ( ) )
2020-02-26 09:32:22 +03:00
assert . NotNil ( t , expectedFileResponse )
if expectedFileResponse != nil {
2023-05-29 12:41:35 +03:00
assert . EqualValues ( t , expectedFileResponse . Content , filesResponse . Files [ 0 ] )
assert . EqualValues ( t , expectedFileResponse . Commit . SHA , filesResponse . Commit . SHA )
assert . EqualValues ( t , expectedFileResponse . Commit . HTMLURL , filesResponse . Commit . HTMLURL )
assert . EqualValues ( t , expectedFileResponse . Commit . Author . Email , filesResponse . Commit . Author . Email )
assert . EqualValues ( t , expectedFileResponse . Commit . Author . Name , filesResponse . Commit . Author . Name )
2020-02-26 09:32:22 +03:00
}
2019-05-11 18:29:17 +03:00
} )
}
2023-05-29 12:41:35 +03:00
func TestChangeRepoFilesForUpdate ( t * testing . T ) {
2019-05-11 18:29:17 +03:00
// setup
onGiteaRun ( t , func ( t * testing . T , u * url . URL ) {
2023-09-01 14:26:07 +03:00
ctx , _ := contexttest . MockContext ( t , "user2/repo1" )
2024-06-19 01:32:45 +03:00
ctx . SetPathParam ( ":id" , "1" )
2023-09-01 14:26:07 +03:00
contexttest . LoadRepo ( t , ctx , 1 )
contexttest . LoadRepoCommit ( t , ctx )
contexttest . LoadUser ( t , ctx , 2 )
contexttest . LoadGitRepo ( t , ctx )
2019-11-13 10:01:19 +03:00
defer ctx . Repo . GitRepo . Close ( )
2019-05-11 18:29:17 +03:00
repo := ctx . Repo . Repository
2022-03-22 10:03:22 +03:00
doer := ctx . Doer
2023-05-29 12:41:35 +03:00
opts := getUpdateRepoFilesOptions ( repo )
2019-05-11 18:29:17 +03:00
// test
2023-05-29 12:41:35 +03:00
filesResponse , err := files_service . ChangeRepoFiles ( git . DefaultContext , repo , doer , opts )
2019-05-11 18:29:17 +03:00
// asserts
2020-07-19 12:53:40 +03:00
assert . NoError ( t , err )
Simplify how git repositories are opened (#28937)
## Purpose
This is a refactor toward building an abstraction over managing git
repositories.
Afterwards, it does not matter anymore if they are stored on the local
disk or somewhere remote.
## What this PR changes
We used `git.OpenRepository` everywhere previously.
Now, we should split them into two distinct functions:
Firstly, there are temporary repositories which do not change:
```go
git.OpenRepository(ctx, diskPath)
```
Gitea managed repositories having a record in the database in the
`repository` table are moved into the new package `gitrepo`:
```go
gitrepo.OpenRepository(ctx, repo_model.Repo)
```
Why is `repo_model.Repository` the second parameter instead of file
path?
Because then we can easily adapt our repository storage strategy.
The repositories can be stored locally, however, they could just as well
be stored on a remote server.
## Further changes in other PRs
- A Git Command wrapper on package `gitrepo` could be created. i.e.
`NewCommand(ctx, repo_model.Repository, commands...)`. `git.RunOpts{Dir:
repo.RepoPath()}`, the directory should be empty before invoking this
method and it can be filled in the function only. #28940
- Remove the `RepoPath()`/`WikiPath()` functions to reduce the
possibility of mistakes.
---------
Co-authored-by: delvh <dev.lh@web.de>
2024-01-27 23:09:51 +03:00
gitRepo , _ := gitrepo . OpenRepository ( git . DefaultContext , repo )
2019-11-13 10:01:19 +03:00
defer gitRepo . Close ( )
2022-07-30 11:09:04 +03:00
commit , _ := gitRepo . GetBranchCommit ( opts . NewBranch )
2023-05-29 12:41:35 +03:00
lastCommit , _ := commit . GetCommitByPath ( opts . Files [ 0 ] . TreePath )
expectedFileResponse := getExpectedFileResponseForRepofilesUpdate ( commit . ID . String ( ) , opts . Files [ 0 ] . TreePath , lastCommit . ID . String ( ) )
assert . EqualValues ( t , expectedFileResponse . Content , filesResponse . Files [ 0 ] )
assert . EqualValues ( t , expectedFileResponse . Commit . SHA , filesResponse . Commit . SHA )
assert . EqualValues ( t , expectedFileResponse . Commit . HTMLURL , filesResponse . Commit . HTMLURL )
assert . EqualValues ( t , expectedFileResponse . Commit . Author . Email , filesResponse . Commit . Author . Email )
assert . EqualValues ( t , expectedFileResponse . Commit . Author . Name , filesResponse . Commit . Author . Name )
2019-05-11 18:29:17 +03:00
} )
}
2023-05-29 12:41:35 +03:00
func TestChangeRepoFilesForUpdateWithFileMove ( t * testing . T ) {
2019-05-11 18:29:17 +03:00
// setup
onGiteaRun ( t , func ( t * testing . T , u * url . URL ) {
2023-09-01 14:26:07 +03:00
ctx , _ := contexttest . MockContext ( t , "user2/repo1" )
2024-06-19 01:32:45 +03:00
ctx . SetPathParam ( ":id" , "1" )
2023-09-01 14:26:07 +03:00
contexttest . LoadRepo ( t , ctx , 1 )
contexttest . LoadRepoCommit ( t , ctx )
contexttest . LoadUser ( t , ctx , 2 )
contexttest . LoadGitRepo ( t , ctx )
2019-11-13 10:01:19 +03:00
defer ctx . Repo . GitRepo . Close ( )
2019-05-11 18:29:17 +03:00
repo := ctx . Repo . Repository
2022-03-22 10:03:22 +03:00
doer := ctx . Doer
2023-05-29 12:41:35 +03:00
opts := getUpdateRepoFilesOptions ( repo )
opts . Files [ 0 ] . FromTreePath = "README.md"
opts . Files [ 0 ] . TreePath = "README_new.md" // new file name, README_new.md
2019-05-11 18:29:17 +03:00
// test
2023-05-29 12:41:35 +03:00
filesResponse , err := files_service . ChangeRepoFiles ( git . DefaultContext , repo , doer , opts )
2019-05-11 18:29:17 +03:00
// asserts
2020-07-19 12:53:40 +03:00
assert . NoError ( t , err )
Simplify how git repositories are opened (#28937)
## Purpose
This is a refactor toward building an abstraction over managing git
repositories.
Afterwards, it does not matter anymore if they are stored on the local
disk or somewhere remote.
## What this PR changes
We used `git.OpenRepository` everywhere previously.
Now, we should split them into two distinct functions:
Firstly, there are temporary repositories which do not change:
```go
git.OpenRepository(ctx, diskPath)
```
Gitea managed repositories having a record in the database in the
`repository` table are moved into the new package `gitrepo`:
```go
gitrepo.OpenRepository(ctx, repo_model.Repo)
```
Why is `repo_model.Repository` the second parameter instead of file
path?
Because then we can easily adapt our repository storage strategy.
The repositories can be stored locally, however, they could just as well
be stored on a remote server.
## Further changes in other PRs
- A Git Command wrapper on package `gitrepo` could be created. i.e.
`NewCommand(ctx, repo_model.Repository, commands...)`. `git.RunOpts{Dir:
repo.RepoPath()}`, the directory should be empty before invoking this
method and it can be filled in the function only. #28940
- Remove the `RepoPath()`/`WikiPath()` functions to reduce the
possibility of mistakes.
---------
Co-authored-by: delvh <dev.lh@web.de>
2024-01-27 23:09:51 +03:00
gitRepo , _ := gitrepo . OpenRepository ( git . DefaultContext , repo )
2019-11-13 10:01:19 +03:00
defer gitRepo . Close ( )
2019-05-11 18:29:17 +03:00
commit , _ := gitRepo . GetBranchCommit ( opts . NewBranch )
2023-05-29 12:41:35 +03:00
lastCommit , _ := commit . GetCommitByPath ( opts . Files [ 0 ] . TreePath )
expectedFileResponse := getExpectedFileResponseForRepofilesUpdate ( commit . ID . String ( ) , opts . Files [ 0 ] . TreePath , lastCommit . ID . String ( ) )
2019-05-11 18:29:17 +03:00
// assert that the old file no longer exists in the last commit of the branch
2023-05-29 12:41:35 +03:00
fromEntry , err := commit . GetTreeEntryByPath ( opts . Files [ 0 ] . FromTreePath )
2019-11-16 21:21:39 +03:00
switch err . ( type ) {
case git . ErrNotExist :
// correct, continue
default :
t . Fatalf ( "expected git.ErrNotExist, got:%v" , err )
}
2023-05-29 12:41:35 +03:00
toEntry , err := commit . GetTreeEntryByPath ( opts . Files [ 0 ] . TreePath )
2020-07-19 12:53:40 +03:00
assert . NoError ( t , err )
2019-05-11 18:29:17 +03:00
assert . Nil ( t , fromEntry ) // Should no longer exist here
assert . NotNil ( t , toEntry ) // Should exist here
// assert SHA has remained the same but paths use the new file name
2023-05-29 12:41:35 +03:00
assert . EqualValues ( t , expectedFileResponse . Content . SHA , filesResponse . Files [ 0 ] . SHA )
assert . EqualValues ( t , expectedFileResponse . Content . Name , filesResponse . Files [ 0 ] . Name )
assert . EqualValues ( t , expectedFileResponse . Content . Path , filesResponse . Files [ 0 ] . Path )
assert . EqualValues ( t , expectedFileResponse . Content . URL , filesResponse . Files [ 0 ] . URL )
assert . EqualValues ( t , expectedFileResponse . Commit . SHA , filesResponse . Commit . SHA )
assert . EqualValues ( t , expectedFileResponse . Commit . HTMLURL , filesResponse . Commit . HTMLURL )
2019-05-11 18:29:17 +03:00
} )
}
// Test opts with branch names removed, should get same results as above test
2023-05-29 12:41:35 +03:00
func TestChangeRepoFilesWithoutBranchNames ( t * testing . T ) {
2019-05-11 18:29:17 +03:00
// setup
onGiteaRun ( t , func ( t * testing . T , u * url . URL ) {
2023-09-01 14:26:07 +03:00
ctx , _ := contexttest . MockContext ( t , "user2/repo1" )
2024-06-19 01:32:45 +03:00
ctx . SetPathParam ( ":id" , "1" )
2023-09-01 14:26:07 +03:00
contexttest . LoadRepo ( t , ctx , 1 )
contexttest . LoadRepoCommit ( t , ctx )
contexttest . LoadUser ( t , ctx , 2 )
contexttest . LoadGitRepo ( t , ctx )
2019-11-13 10:01:19 +03:00
defer ctx . Repo . GitRepo . Close ( )
2019-05-11 18:29:17 +03:00
repo := ctx . Repo . Repository
2022-03-22 10:03:22 +03:00
doer := ctx . Doer
2023-05-29 12:41:35 +03:00
opts := getUpdateRepoFilesOptions ( repo )
2019-05-11 18:29:17 +03:00
opts . OldBranch = ""
opts . NewBranch = ""
// test
2023-05-29 12:41:35 +03:00
filesResponse , err := files_service . ChangeRepoFiles ( git . DefaultContext , repo , doer , opts )
2019-05-11 18:29:17 +03:00
// asserts
2020-07-19 12:53:40 +03:00
assert . NoError ( t , err )
Simplify how git repositories are opened (#28937)
## Purpose
This is a refactor toward building an abstraction over managing git
repositories.
Afterwards, it does not matter anymore if they are stored on the local
disk or somewhere remote.
## What this PR changes
We used `git.OpenRepository` everywhere previously.
Now, we should split them into two distinct functions:
Firstly, there are temporary repositories which do not change:
```go
git.OpenRepository(ctx, diskPath)
```
Gitea managed repositories having a record in the database in the
`repository` table are moved into the new package `gitrepo`:
```go
gitrepo.OpenRepository(ctx, repo_model.Repo)
```
Why is `repo_model.Repository` the second parameter instead of file
path?
Because then we can easily adapt our repository storage strategy.
The repositories can be stored locally, however, they could just as well
be stored on a remote server.
## Further changes in other PRs
- A Git Command wrapper on package `gitrepo` could be created. i.e.
`NewCommand(ctx, repo_model.Repository, commands...)`. `git.RunOpts{Dir:
repo.RepoPath()}`, the directory should be empty before invoking this
method and it can be filled in the function only. #28940
- Remove the `RepoPath()`/`WikiPath()` functions to reduce the
possibility of mistakes.
---------
Co-authored-by: delvh <dev.lh@web.de>
2024-01-27 23:09:51 +03:00
gitRepo , _ := gitrepo . OpenRepository ( git . DefaultContext , repo )
2019-11-13 10:01:19 +03:00
defer gitRepo . Close ( )
2022-07-30 11:09:04 +03:00
commit , _ := gitRepo . GetBranchCommit ( repo . DefaultBranch )
2023-05-29 12:41:35 +03:00
lastCommit , _ := commit . GetCommitByPath ( opts . Files [ 0 ] . TreePath )
expectedFileResponse := getExpectedFileResponseForRepofilesUpdate ( commit . ID . String ( ) , opts . Files [ 0 ] . TreePath , lastCommit . ID . String ( ) )
assert . EqualValues ( t , expectedFileResponse . Content , filesResponse . Files [ 0 ] )
} )
}
func TestChangeRepoFilesForDelete ( t * testing . T ) {
onGiteaRun ( t , testDeleteRepoFiles )
}
func testDeleteRepoFiles ( t * testing . T , u * url . URL ) {
// setup
unittest . PrepareTestEnv ( t )
2023-09-01 14:26:07 +03:00
ctx , _ := contexttest . MockContext ( t , "user2/repo1" )
2024-06-19 01:32:45 +03:00
ctx . SetPathParam ( ":id" , "1" )
2023-09-01 14:26:07 +03:00
contexttest . LoadRepo ( t , ctx , 1 )
contexttest . LoadRepoCommit ( t , ctx )
contexttest . LoadUser ( t , ctx , 2 )
contexttest . LoadGitRepo ( t , ctx )
2023-05-29 12:41:35 +03:00
defer ctx . Repo . GitRepo . Close ( )
repo := ctx . Repo . Repository
doer := ctx . Doer
opts := getDeleteRepoFilesOptions ( repo )
t . Run ( "Delete README.md file" , func ( t * testing . T ) {
filesResponse , err := files_service . ChangeRepoFiles ( git . DefaultContext , repo , doer , opts )
assert . NoError ( t , err )
2024-04-29 11:47:56 +03:00
expectedFileResponse := getExpectedFileResponseForRepofilesDelete ( )
2023-05-29 12:41:35 +03:00
assert . NotNil ( t , filesResponse )
assert . Nil ( t , filesResponse . Files [ 0 ] )
assert . EqualValues ( t , expectedFileResponse . Commit . Message , filesResponse . Commit . Message )
assert . EqualValues ( t , expectedFileResponse . Commit . Author . Identity , filesResponse . Commit . Author . Identity )
assert . EqualValues ( t , expectedFileResponse . Commit . Committer . Identity , filesResponse . Commit . Committer . Identity )
assert . EqualValues ( t , expectedFileResponse . Verification , filesResponse . Verification )
} )
t . Run ( "Verify README.md has been deleted" , func ( t * testing . T ) {
filesResponse , err := files_service . ChangeRepoFiles ( git . DefaultContext , repo , doer , opts )
assert . Nil ( t , filesResponse )
expectedError := "repository file does not exist [path: " + opts . Files [ 0 ] . TreePath + "]"
assert . EqualError ( t , err , expectedError )
2019-05-11 18:29:17 +03:00
} )
}
2023-05-29 12:41:35 +03:00
// Test opts with branch names removed, same results
func TestChangeRepoFilesForDeleteWithoutBranchNames ( t * testing . T ) {
onGiteaRun ( t , testDeleteRepoFilesWithoutBranchNames )
}
func testDeleteRepoFilesWithoutBranchNames ( t * testing . T , u * url . URL ) {
// setup
unittest . PrepareTestEnv ( t )
2023-09-01 14:26:07 +03:00
ctx , _ := contexttest . MockContext ( t , "user2/repo1" )
2024-06-19 01:32:45 +03:00
ctx . SetPathParam ( ":id" , "1" )
2023-09-01 14:26:07 +03:00
contexttest . LoadRepo ( t , ctx , 1 )
contexttest . LoadRepoCommit ( t , ctx )
contexttest . LoadUser ( t , ctx , 2 )
contexttest . LoadGitRepo ( t , ctx )
2023-05-29 12:41:35 +03:00
defer ctx . Repo . GitRepo . Close ( )
repo := ctx . Repo . Repository
doer := ctx . Doer
opts := getDeleteRepoFilesOptions ( repo )
opts . OldBranch = ""
opts . NewBranch = ""
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 )
2024-04-29 11:47:56 +03:00
expectedFileResponse := getExpectedFileResponseForRepofilesDelete ( )
2023-05-29 12:41:35 +03:00
assert . NotNil ( t , filesResponse )
assert . Nil ( t , filesResponse . Files [ 0 ] )
assert . EqualValues ( t , expectedFileResponse . Commit . Message , filesResponse . Commit . Message )
assert . EqualValues ( t , expectedFileResponse . Commit . Author . Identity , filesResponse . Commit . Author . Identity )
assert . EqualValues ( t , expectedFileResponse . Commit . Committer . Identity , filesResponse . Commit . Committer . Identity )
assert . EqualValues ( t , expectedFileResponse . Verification , filesResponse . Verification )
} )
}
func TestChangeRepoFilesErrors ( t * testing . T ) {
2019-05-11 18:29:17 +03:00
// setup
onGiteaRun ( t , func ( t * testing . T , u * url . URL ) {
2023-09-01 14:26:07 +03:00
ctx , _ := contexttest . MockContext ( t , "user2/repo1" )
2024-06-19 01:32:45 +03:00
ctx . SetPathParam ( ":id" , "1" )
2023-09-01 14:26:07 +03:00
contexttest . LoadRepo ( t , ctx , 1 )
contexttest . LoadRepoCommit ( t , ctx )
contexttest . LoadUser ( t , ctx , 2 )
contexttest . LoadGitRepo ( t , ctx )
2019-11-13 10:01:19 +03:00
defer ctx . Repo . GitRepo . Close ( )
2019-05-11 18:29:17 +03:00
repo := ctx . Repo . Repository
2022-03-22 10:03:22 +03:00
doer := ctx . Doer
2019-05-11 18:29:17 +03:00
t . Run ( "bad branch" , func ( t * testing . T ) {
2023-05-29 12:41:35 +03:00
opts := getUpdateRepoFilesOptions ( repo )
2019-05-11 18:29:17 +03:00
opts . OldBranch = "bad_branch"
2023-05-29 12:41:35 +03:00
filesResponse , err := files_service . ChangeRepoFiles ( git . DefaultContext , repo , doer , opts )
2019-05-11 18:29:17 +03:00
assert . Error ( t , err )
2023-05-29 12:41:35 +03:00
assert . Nil ( t , filesResponse )
2019-05-11 18:29:17 +03:00
expectedError := "branch does not exist [name: " + opts . OldBranch + "]"
assert . EqualError ( t , err , expectedError )
} )
t . Run ( "bad SHA" , func ( t * testing . T ) {
2023-05-29 12:41:35 +03:00
opts := getUpdateRepoFilesOptions ( repo )
origSHA := opts . Files [ 0 ] . SHA
opts . Files [ 0 ] . SHA = "bad_sha"
filesResponse , err := files_service . ChangeRepoFiles ( git . DefaultContext , repo , doer , opts )
assert . Nil ( t , filesResponse )
2019-05-11 18:29:17 +03:00
assert . Error ( t , err )
2023-05-29 12:41:35 +03:00
expectedError := "sha does not match [given: " + opts . Files [ 0 ] . SHA + ", expected: " + origSHA + "]"
2019-05-11 18:29:17 +03:00
assert . EqualError ( t , err , expectedError )
} )
t . Run ( "new branch already exists" , func ( t * testing . T ) {
2023-05-29 12:41:35 +03:00
opts := getUpdateRepoFilesOptions ( repo )
2019-05-11 18:29:17 +03:00
opts . NewBranch = "develop"
2023-05-29 12:41:35 +03:00
filesResponse , err := files_service . ChangeRepoFiles ( git . DefaultContext , repo , doer , opts )
assert . Nil ( t , filesResponse )
2019-05-11 18:29:17 +03:00
assert . Error ( t , err )
expectedError := "branch already exists [name: " + opts . NewBranch + "]"
assert . EqualError ( t , err , expectedError )
} )
t . Run ( "treePath is empty:" , func ( t * testing . T ) {
2023-05-29 12:41:35 +03:00
opts := getUpdateRepoFilesOptions ( repo )
opts . Files [ 0 ] . TreePath = ""
filesResponse , err := files_service . ChangeRepoFiles ( git . DefaultContext , repo , doer , opts )
assert . Nil ( t , filesResponse )
2019-05-11 18:29:17 +03:00
assert . Error ( t , err )
expectedError := "path contains a malformed path component [path: ]"
assert . EqualError ( t , err , expectedError )
} )
t . Run ( "treePath is a git directory:" , func ( t * testing . T ) {
2023-05-29 12:41:35 +03:00
opts := getUpdateRepoFilesOptions ( repo )
opts . Files [ 0 ] . TreePath = ".git"
filesResponse , err := files_service . ChangeRepoFiles ( git . DefaultContext , repo , doer , opts )
assert . Nil ( t , filesResponse )
2019-05-11 18:29:17 +03:00
assert . Error ( t , err )
2023-05-29 12:41:35 +03:00
expectedError := "path contains a malformed path component [path: " + opts . Files [ 0 ] . TreePath + "]"
2019-05-11 18:29:17 +03:00
assert . EqualError ( t , err , expectedError )
} )
t . Run ( "create file that already exists" , func ( t * testing . T ) {
2023-05-29 12:41:35 +03:00
opts := getCreateRepoFilesOptions ( repo )
opts . Files [ 0 ] . TreePath = "README.md" // already exists
fileResponse , err := files_service . ChangeRepoFiles ( git . DefaultContext , repo , doer , opts )
2019-05-11 18:29:17 +03:00
assert . Nil ( t , fileResponse )
assert . Error ( t , err )
2023-05-29 12:41:35 +03:00
expectedError := "repository file already exists [path: " + opts . Files [ 0 ] . TreePath + "]"
2019-05-11 18:29:17 +03:00
assert . EqualError ( t , err , expectedError )
} )
} )
}