code.gitea.io/gitea@v1.22.3/tests/integration/repofiles_change_test.go (about) 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package integration 5 6 import ( 7 "net/url" 8 "path/filepath" 9 "strings" 10 "testing" 11 "time" 12 13 repo_model "code.gitea.io/gitea/models/repo" 14 "code.gitea.io/gitea/models/unittest" 15 "code.gitea.io/gitea/modules/git" 16 "code.gitea.io/gitea/modules/gitrepo" 17 "code.gitea.io/gitea/modules/setting" 18 api "code.gitea.io/gitea/modules/structs" 19 "code.gitea.io/gitea/services/contexttest" 20 files_service "code.gitea.io/gitea/services/repository/files" 21 22 "github.com/stretchr/testify/assert" 23 ) 24 25 func getCreateRepoFilesOptions(repo *repo_model.Repository) *files_service.ChangeRepoFilesOptions { 26 return &files_service.ChangeRepoFilesOptions{ 27 Files: []*files_service.ChangeRepoFile{ 28 { 29 Operation: "create", 30 TreePath: "new/file.txt", 31 ContentReader: strings.NewReader("This is a NEW file"), 32 }, 33 }, 34 OldBranch: repo.DefaultBranch, 35 NewBranch: repo.DefaultBranch, 36 Message: "Creates new/file.txt", 37 Author: nil, 38 Committer: nil, 39 } 40 } 41 42 func getUpdateRepoFilesOptions(repo *repo_model.Repository) *files_service.ChangeRepoFilesOptions { 43 return &files_service.ChangeRepoFilesOptions{ 44 Files: []*files_service.ChangeRepoFile{ 45 { 46 Operation: "update", 47 TreePath: "README.md", 48 SHA: "4b4851ad51df6a7d9f25c979345979eaeb5b349f", 49 ContentReader: strings.NewReader("This is UPDATED content for the README file"), 50 }, 51 }, 52 OldBranch: repo.DefaultBranch, 53 NewBranch: repo.DefaultBranch, 54 Message: "Updates README.md", 55 Author: nil, 56 Committer: nil, 57 } 58 } 59 60 func getDeleteRepoFilesOptions(repo *repo_model.Repository) *files_service.ChangeRepoFilesOptions { 61 return &files_service.ChangeRepoFilesOptions{ 62 Files: []*files_service.ChangeRepoFile{ 63 { 64 Operation: "delete", 65 TreePath: "README.md", 66 SHA: "4b4851ad51df6a7d9f25c979345979eaeb5b349f", 67 }, 68 }, 69 LastCommitID: "", 70 OldBranch: repo.DefaultBranch, 71 NewBranch: repo.DefaultBranch, 72 Message: "Deletes README.md", 73 Author: &files_service.IdentityOptions{ 74 Name: "Bob Smith", 75 Email: "bob@smith.com", 76 }, 77 Committer: nil, 78 } 79 } 80 81 func getExpectedFileResponseForRepofilesDelete(u *url.URL) *api.FileResponse { 82 // Just returns fields that don't change, i.e. fields with commit SHAs and dates can't be determined 83 return &api.FileResponse{ 84 Content: nil, 85 Commit: &api.FileCommitResponse{ 86 Author: &api.CommitUser{ 87 Identity: api.Identity{ 88 Name: "Bob Smith", 89 Email: "bob@smith.com", 90 }, 91 }, 92 Committer: &api.CommitUser{ 93 Identity: api.Identity{ 94 Name: "Bob Smith", 95 Email: "bob@smith.com", 96 }, 97 }, 98 Message: "Deletes README.md\n", 99 }, 100 Verification: &api.PayloadCommitVerification{ 101 Verified: false, 102 Reason: "gpg.error.not_signed_commit", 103 Signature: "", 104 Payload: "", 105 }, 106 } 107 } 108 109 func getExpectedFileResponseForRepofilesCreate(commitID, lastCommitSHA string) *api.FileResponse { 110 treePath := "new/file.txt" 111 encoding := "base64" 112 content := "VGhpcyBpcyBhIE5FVyBmaWxl" 113 selfURL := setting.AppURL + "api/v1/repos/user2/repo1/contents/" + treePath + "?ref=master" 114 htmlURL := setting.AppURL + "user2/repo1/src/branch/master/" + treePath 115 gitURL := setting.AppURL + "api/v1/repos/user2/repo1/git/blobs/103ff9234cefeee5ec5361d22b49fbb04d385885" 116 downloadURL := setting.AppURL + "user2/repo1/raw/branch/master/" + treePath 117 return &api.FileResponse{ 118 Content: &api.ContentsResponse{ 119 Name: filepath.Base(treePath), 120 Path: treePath, 121 SHA: "103ff9234cefeee5ec5361d22b49fbb04d385885", 122 LastCommitSHA: lastCommitSHA, 123 Type: "file", 124 Size: 18, 125 Encoding: &encoding, 126 Content: &content, 127 URL: &selfURL, 128 HTMLURL: &htmlURL, 129 GitURL: &gitURL, 130 DownloadURL: &downloadURL, 131 Links: &api.FileLinksResponse{ 132 Self: &selfURL, 133 GitURL: &gitURL, 134 HTMLURL: &htmlURL, 135 }, 136 }, 137 Commit: &api.FileCommitResponse{ 138 CommitMeta: api.CommitMeta{ 139 URL: setting.AppURL + "api/v1/repos/user2/repo1/git/commits/" + commitID, 140 SHA: commitID, 141 }, 142 HTMLURL: setting.AppURL + "user2/repo1/commit/" + commitID, 143 Author: &api.CommitUser{ 144 Identity: api.Identity{ 145 Name: "User Two", 146 Email: "user2@noreply.example.org", 147 }, 148 Date: time.Now().UTC().Format(time.RFC3339), 149 }, 150 Committer: &api.CommitUser{ 151 Identity: api.Identity{ 152 Name: "User Two", 153 Email: "user2@noreply.example.org", 154 }, 155 Date: time.Now().UTC().Format(time.RFC3339), 156 }, 157 Parents: []*api.CommitMeta{ 158 { 159 URL: setting.AppURL + "api/v1/repos/user2/repo1/git/commits/65f1bf27bc3bf70f64657658635e66094edbcb4d", 160 SHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d", 161 }, 162 }, 163 Message: "Updates README.md\n", 164 Tree: &api.CommitMeta{ 165 URL: setting.AppURL + "api/v1/repos/user2/repo1/git/trees/f93e3a1a1525fb5b91020da86e44810c87a2d7bc", 166 SHA: "f93e3a1a1525fb5b91020git dda86e44810c87a2d7bc", 167 }, 168 }, 169 Verification: &api.PayloadCommitVerification{ 170 Verified: false, 171 Reason: "gpg.error.not_signed_commit", 172 Signature: "", 173 Payload: "", 174 }, 175 } 176 } 177 178 func getExpectedFileResponseForRepofilesUpdate(commitID, filename, lastCommitSHA string) *api.FileResponse { 179 encoding := "base64" 180 content := "VGhpcyBpcyBVUERBVEVEIGNvbnRlbnQgZm9yIHRoZSBSRUFETUUgZmlsZQ==" 181 selfURL := setting.AppURL + "api/v1/repos/user2/repo1/contents/" + filename + "?ref=master" 182 htmlURL := setting.AppURL + "user2/repo1/src/branch/master/" + filename 183 gitURL := setting.AppURL + "api/v1/repos/user2/repo1/git/blobs/dbf8d00e022e05b7e5cf7e535de857de57925647" 184 downloadURL := setting.AppURL + "user2/repo1/raw/branch/master/" + filename 185 return &api.FileResponse{ 186 Content: &api.ContentsResponse{ 187 Name: filename, 188 Path: filename, 189 SHA: "dbf8d00e022e05b7e5cf7e535de857de57925647", 190 LastCommitSHA: lastCommitSHA, 191 Type: "file", 192 Size: 43, 193 Encoding: &encoding, 194 Content: &content, 195 URL: &selfURL, 196 HTMLURL: &htmlURL, 197 GitURL: &gitURL, 198 DownloadURL: &downloadURL, 199 Links: &api.FileLinksResponse{ 200 Self: &selfURL, 201 GitURL: &gitURL, 202 HTMLURL: &htmlURL, 203 }, 204 }, 205 Commit: &api.FileCommitResponse{ 206 CommitMeta: api.CommitMeta{ 207 URL: setting.AppURL + "api/v1/repos/user2/repo1/git/commits/" + commitID, 208 SHA: commitID, 209 }, 210 HTMLURL: setting.AppURL + "user2/repo1/commit/" + commitID, 211 Author: &api.CommitUser{ 212 Identity: api.Identity{ 213 Name: "User Two", 214 Email: "user2@noreply.example.org", 215 }, 216 Date: time.Now().UTC().Format(time.RFC3339), 217 }, 218 Committer: &api.CommitUser{ 219 Identity: api.Identity{ 220 Name: "User Two", 221 Email: "user2@noreply.example.org", 222 }, 223 Date: time.Now().UTC().Format(time.RFC3339), 224 }, 225 Parents: []*api.CommitMeta{ 226 { 227 URL: setting.AppURL + "api/v1/repos/user2/repo1/git/commits/65f1bf27bc3bf70f64657658635e66094edbcb4d", 228 SHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d", 229 }, 230 }, 231 Message: "Updates README.md\n", 232 Tree: &api.CommitMeta{ 233 URL: setting.AppURL + "api/v1/repos/user2/repo1/git/trees/f93e3a1a1525fb5b91020da86e44810c87a2d7bc", 234 SHA: "f93e3a1a1525fb5b91020da86e44810c87a2d7bc", 235 }, 236 }, 237 Verification: &api.PayloadCommitVerification{ 238 Verified: false, 239 Reason: "gpg.error.not_signed_commit", 240 Signature: "", 241 Payload: "", 242 }, 243 } 244 } 245 246 func TestChangeRepoFilesForCreate(t *testing.T) { 247 // setup 248 onGiteaRun(t, func(t *testing.T, u *url.URL) { 249 ctx, _ := contexttest.MockContext(t, "user2/repo1") 250 ctx.SetParams(":id", "1") 251 contexttest.LoadRepo(t, ctx, 1) 252 contexttest.LoadRepoCommit(t, ctx) 253 contexttest.LoadUser(t, ctx, 2) 254 contexttest.LoadGitRepo(t, ctx) 255 defer ctx.Repo.GitRepo.Close() 256 257 repo := ctx.Repo.Repository 258 doer := ctx.Doer 259 opts := getCreateRepoFilesOptions(repo) 260 261 // test 262 filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) 263 264 // asserts 265 assert.NoError(t, err) 266 gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) 267 defer gitRepo.Close() 268 269 commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch) 270 lastCommit, _ := gitRepo.GetCommitByPath("new/file.txt") 271 expectedFileResponse := getExpectedFileResponseForRepofilesCreate(commitID, lastCommit.ID.String()) 272 assert.NotNil(t, expectedFileResponse) 273 if expectedFileResponse != nil { 274 assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0]) 275 assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA) 276 assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL) 277 assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email) 278 assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name) 279 } 280 }) 281 } 282 283 func TestChangeRepoFilesForUpdate(t *testing.T) { 284 // setup 285 onGiteaRun(t, func(t *testing.T, u *url.URL) { 286 ctx, _ := contexttest.MockContext(t, "user2/repo1") 287 ctx.SetParams(":id", "1") 288 contexttest.LoadRepo(t, ctx, 1) 289 contexttest.LoadRepoCommit(t, ctx) 290 contexttest.LoadUser(t, ctx, 2) 291 contexttest.LoadGitRepo(t, ctx) 292 defer ctx.Repo.GitRepo.Close() 293 294 repo := ctx.Repo.Repository 295 doer := ctx.Doer 296 opts := getUpdateRepoFilesOptions(repo) 297 298 // test 299 filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) 300 301 // asserts 302 assert.NoError(t, err) 303 gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) 304 defer gitRepo.Close() 305 306 commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) 307 lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) 308 expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String()) 309 assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0]) 310 assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA) 311 assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL) 312 assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email) 313 assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name) 314 }) 315 } 316 317 func TestChangeRepoFilesForUpdateWithFileMove(t *testing.T) { 318 // setup 319 onGiteaRun(t, func(t *testing.T, u *url.URL) { 320 ctx, _ := contexttest.MockContext(t, "user2/repo1") 321 ctx.SetParams(":id", "1") 322 contexttest.LoadRepo(t, ctx, 1) 323 contexttest.LoadRepoCommit(t, ctx) 324 contexttest.LoadUser(t, ctx, 2) 325 contexttest.LoadGitRepo(t, ctx) 326 defer ctx.Repo.GitRepo.Close() 327 328 repo := ctx.Repo.Repository 329 doer := ctx.Doer 330 opts := getUpdateRepoFilesOptions(repo) 331 opts.Files[0].FromTreePath = "README.md" 332 opts.Files[0].TreePath = "README_new.md" // new file name, README_new.md 333 334 // test 335 filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) 336 337 // asserts 338 assert.NoError(t, err) 339 gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) 340 defer gitRepo.Close() 341 342 commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) 343 lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) 344 expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String()) 345 // assert that the old file no longer exists in the last commit of the branch 346 fromEntry, err := commit.GetTreeEntryByPath(opts.Files[0].FromTreePath) 347 switch err.(type) { 348 case git.ErrNotExist: 349 // correct, continue 350 default: 351 t.Fatalf("expected git.ErrNotExist, got:%v", err) 352 } 353 toEntry, err := commit.GetTreeEntryByPath(opts.Files[0].TreePath) 354 assert.NoError(t, err) 355 assert.Nil(t, fromEntry) // Should no longer exist here 356 assert.NotNil(t, toEntry) // Should exist here 357 // assert SHA has remained the same but paths use the new file name 358 assert.EqualValues(t, expectedFileResponse.Content.SHA, filesResponse.Files[0].SHA) 359 assert.EqualValues(t, expectedFileResponse.Content.Name, filesResponse.Files[0].Name) 360 assert.EqualValues(t, expectedFileResponse.Content.Path, filesResponse.Files[0].Path) 361 assert.EqualValues(t, expectedFileResponse.Content.URL, filesResponse.Files[0].URL) 362 assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA) 363 assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL) 364 }) 365 } 366 367 // Test opts with branch names removed, should get same results as above test 368 func TestChangeRepoFilesWithoutBranchNames(t *testing.T) { 369 // setup 370 onGiteaRun(t, func(t *testing.T, u *url.URL) { 371 ctx, _ := contexttest.MockContext(t, "user2/repo1") 372 ctx.SetParams(":id", "1") 373 contexttest.LoadRepo(t, ctx, 1) 374 contexttest.LoadRepoCommit(t, ctx) 375 contexttest.LoadUser(t, ctx, 2) 376 contexttest.LoadGitRepo(t, ctx) 377 defer ctx.Repo.GitRepo.Close() 378 379 repo := ctx.Repo.Repository 380 doer := ctx.Doer 381 opts := getUpdateRepoFilesOptions(repo) 382 opts.OldBranch = "" 383 opts.NewBranch = "" 384 385 // test 386 filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) 387 388 // asserts 389 assert.NoError(t, err) 390 gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) 391 defer gitRepo.Close() 392 393 commit, _ := gitRepo.GetBranchCommit(repo.DefaultBranch) 394 lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) 395 expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String()) 396 assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0]) 397 }) 398 } 399 400 func TestChangeRepoFilesForDelete(t *testing.T) { 401 onGiteaRun(t, testDeleteRepoFiles) 402 } 403 404 func testDeleteRepoFiles(t *testing.T, u *url.URL) { 405 // setup 406 unittest.PrepareTestEnv(t) 407 ctx, _ := contexttest.MockContext(t, "user2/repo1") 408 ctx.SetParams(":id", "1") 409 contexttest.LoadRepo(t, ctx, 1) 410 contexttest.LoadRepoCommit(t, ctx) 411 contexttest.LoadUser(t, ctx, 2) 412 contexttest.LoadGitRepo(t, ctx) 413 defer ctx.Repo.GitRepo.Close() 414 repo := ctx.Repo.Repository 415 doer := ctx.Doer 416 opts := getDeleteRepoFilesOptions(repo) 417 418 t.Run("Delete README.md file", func(t *testing.T) { 419 filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) 420 assert.NoError(t, err) 421 expectedFileResponse := getExpectedFileResponseForRepofilesDelete(u) 422 assert.NotNil(t, filesResponse) 423 assert.Nil(t, filesResponse.Files[0]) 424 assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message) 425 assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity) 426 assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity) 427 assert.EqualValues(t, expectedFileResponse.Verification, filesResponse.Verification) 428 }) 429 430 t.Run("Verify README.md has been deleted", func(t *testing.T) { 431 filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) 432 assert.Nil(t, filesResponse) 433 expectedError := "repository file does not exist [path: " + opts.Files[0].TreePath + "]" 434 assert.EqualError(t, err, expectedError) 435 }) 436 } 437 438 // Test opts with branch names removed, same results 439 func TestChangeRepoFilesForDeleteWithoutBranchNames(t *testing.T) { 440 onGiteaRun(t, testDeleteRepoFilesWithoutBranchNames) 441 } 442 443 func testDeleteRepoFilesWithoutBranchNames(t *testing.T, u *url.URL) { 444 // setup 445 unittest.PrepareTestEnv(t) 446 ctx, _ := contexttest.MockContext(t, "user2/repo1") 447 ctx.SetParams(":id", "1") 448 contexttest.LoadRepo(t, ctx, 1) 449 contexttest.LoadRepoCommit(t, ctx) 450 contexttest.LoadUser(t, ctx, 2) 451 contexttest.LoadGitRepo(t, ctx) 452 defer ctx.Repo.GitRepo.Close() 453 454 repo := ctx.Repo.Repository 455 doer := ctx.Doer 456 opts := getDeleteRepoFilesOptions(repo) 457 opts.OldBranch = "" 458 opts.NewBranch = "" 459 460 t.Run("Delete README.md without Branch Name", func(t *testing.T) { 461 filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) 462 assert.NoError(t, err) 463 expectedFileResponse := getExpectedFileResponseForRepofilesDelete(u) 464 assert.NotNil(t, filesResponse) 465 assert.Nil(t, filesResponse.Files[0]) 466 assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message) 467 assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity) 468 assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity) 469 assert.EqualValues(t, expectedFileResponse.Verification, filesResponse.Verification) 470 }) 471 } 472 473 func TestChangeRepoFilesErrors(t *testing.T) { 474 // setup 475 onGiteaRun(t, func(t *testing.T, u *url.URL) { 476 ctx, _ := contexttest.MockContext(t, "user2/repo1") 477 ctx.SetParams(":id", "1") 478 contexttest.LoadRepo(t, ctx, 1) 479 contexttest.LoadRepoCommit(t, ctx) 480 contexttest.LoadUser(t, ctx, 2) 481 contexttest.LoadGitRepo(t, ctx) 482 defer ctx.Repo.GitRepo.Close() 483 484 repo := ctx.Repo.Repository 485 doer := ctx.Doer 486 487 t.Run("bad branch", func(t *testing.T) { 488 opts := getUpdateRepoFilesOptions(repo) 489 opts.OldBranch = "bad_branch" 490 filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) 491 assert.Error(t, err) 492 assert.Nil(t, filesResponse) 493 expectedError := "branch does not exist [name: " + opts.OldBranch + "]" 494 assert.EqualError(t, err, expectedError) 495 }) 496 497 t.Run("bad SHA", func(t *testing.T) { 498 opts := getUpdateRepoFilesOptions(repo) 499 origSHA := opts.Files[0].SHA 500 opts.Files[0].SHA = "bad_sha" 501 filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) 502 assert.Nil(t, filesResponse) 503 assert.Error(t, err) 504 expectedError := "sha does not match [given: " + opts.Files[0].SHA + ", expected: " + origSHA + "]" 505 assert.EqualError(t, err, expectedError) 506 }) 507 508 t.Run("new branch already exists", func(t *testing.T) { 509 opts := getUpdateRepoFilesOptions(repo) 510 opts.NewBranch = "develop" 511 filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) 512 assert.Nil(t, filesResponse) 513 assert.Error(t, err) 514 expectedError := "branch already exists [name: " + opts.NewBranch + "]" 515 assert.EqualError(t, err, expectedError) 516 }) 517 518 t.Run("treePath is empty:", func(t *testing.T) { 519 opts := getUpdateRepoFilesOptions(repo) 520 opts.Files[0].TreePath = "" 521 filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) 522 assert.Nil(t, filesResponse) 523 assert.Error(t, err) 524 expectedError := "path contains a malformed path component [path: ]" 525 assert.EqualError(t, err, expectedError) 526 }) 527 528 t.Run("treePath is a git directory:", func(t *testing.T) { 529 opts := getUpdateRepoFilesOptions(repo) 530 opts.Files[0].TreePath = ".git" 531 filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) 532 assert.Nil(t, filesResponse) 533 assert.Error(t, err) 534 expectedError := "path contains a malformed path component [path: " + opts.Files[0].TreePath + "]" 535 assert.EqualError(t, err, expectedError) 536 }) 537 538 t.Run("create file that already exists", func(t *testing.T) { 539 opts := getCreateRepoFilesOptions(repo) 540 opts.Files[0].TreePath = "README.md" // already exists 541 fileResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) 542 assert.Nil(t, fileResponse) 543 assert.Error(t, err) 544 expectedError := "repository file already exists [path: " + opts.Files[0].TreePath + "]" 545 assert.EqualError(t, err, expectedError) 546 }) 547 }) 548 }