1package git_test 2 3import ( 4 "io/ioutil" 5 "path/filepath" 6 "strings" 7 "testing" 8 9 "github.com/git-town/git-town/src/git" 10 "github.com/git-town/git-town/test" 11 "github.com/stretchr/testify/assert" 12) 13 14func TestRunner_AddRemote(t *testing.T) { 15 runner := test.CreateTestGitTownRepo(t).Runner 16 err := runner.AddRemote("foo", "bar") 17 assert.NoError(t, err) 18 remotes, err := runner.Remotes() 19 assert.NoError(t, err) 20 assert.Equal(t, []string{"foo"}, remotes) 21} 22 23func TestRunner_CheckoutBranch(t *testing.T) { 24 runner := test.CreateRepo(t).Runner 25 err := runner.CreateBranch("branch1", "master") 26 assert.NoError(t, err) 27 err = runner.CheckoutBranch("branch1") 28 assert.NoError(t, err) 29 currentBranch, err := runner.CurrentBranch() 30 assert.NoError(t, err) 31 assert.Equal(t, "branch1", currentBranch) 32 err = runner.CheckoutBranch("master") 33 assert.NoError(t, err) 34 currentBranch, err = runner.CurrentBranch() 35 assert.NoError(t, err) 36 assert.Equal(t, "master", currentBranch) 37} 38 39func TestRunner_Commits(t *testing.T) { 40 runner := test.CreateRepo(t).Runner 41 err := runner.CreateCommit(git.Commit{ 42 Branch: "master", 43 FileName: "file1", 44 FileContent: "hello", 45 Message: "first commit", 46 }) 47 assert.NoError(t, err) 48 err = runner.CreateCommit(git.Commit{ 49 Branch: "master", 50 FileName: "file2", 51 FileContent: "hello again", 52 Message: "second commit", 53 }) 54 assert.NoError(t, err) 55 commits, err := runner.Commits([]string{"FILE NAME", "FILE CONTENT"}) 56 assert.NoError(t, err) 57 assert.Len(t, commits, 2) 58 assert.Equal(t, "master", commits[0].Branch) 59 assert.Equal(t, "file1", commits[0].FileName) 60 assert.Equal(t, "hello", commits[0].FileContent) 61 assert.Equal(t, "first commit", commits[0].Message) 62 assert.Equal(t, "master", commits[1].Branch) 63 assert.Equal(t, "file2", commits[1].FileName) 64 assert.Equal(t, "hello again", commits[1].FileContent) 65 assert.Equal(t, "second commit", commits[1].Message) 66} 67 68func TestRunner_Configuration(t *testing.T) { 69 runner := test.CreateRepo(t).Runner 70 config := runner.Config 71 assert.NotNil(t, config, "first path: new config") 72 config = runner.Config 73 assert.NotNil(t, config, "second path: cached config") 74} 75 76func TestRunner_ConnectTrackingBranch(t *testing.T) { 77 // replicating the situation this is used in, 78 // connecting branches of repos with the same commits in them 79 origin := test.CreateRepo(t) 80 repoDir := filepath.Join(test.CreateTempDir(t), "repo") // need a non-existing directory 81 err := test.CopyDirectory(origin.WorkingDir(), repoDir) 82 assert.NoError(t, err) 83 runner := test.NewRepo(repoDir, repoDir, "").Runner 84 err = runner.AddRemote("origin", origin.WorkingDir()) 85 assert.NoError(t, err) 86 err = runner.Fetch() 87 assert.NoError(t, err) 88 err = runner.ConnectTrackingBranch("master") 89 assert.NoError(t, err) 90 err = runner.PushBranch() 91 assert.NoError(t, err) 92} 93 94func TestRunner_CreateBranch(t *testing.T) { 95 runner := test.CreateRepo(t).Runner 96 err := runner.CreateBranch("branch1", "master") 97 assert.NoError(t, err) 98 currentBranch, err := runner.CurrentBranch() 99 assert.NoError(t, err) 100 assert.Equal(t, "master", currentBranch) 101 branches, err := runner.LocalBranchesMainFirst() 102 assert.NoError(t, err) 103 assert.Equal(t, []string{"branch1", "master"}, branches) 104} 105 106func TestRunner_CreateChildFeatureBranch(t *testing.T) { 107 runner := test.CreateTestGitTownRepo(t).Runner 108 err := runner.CreateFeatureBranch("f1") 109 assert.NoError(t, err) 110 err = runner.CreateChildFeatureBranch("f1a", "f1") 111 assert.NoError(t, err) 112 res, err := runner.Run("git", "town", "config") 113 assert.NoError(t, err) 114 has := strings.Contains(res.OutputSanitized(), "Branch Ancestry:\n main\n f1\n f1a") 115 assert.True(t, has) 116} 117 118func TestRunner_CreateCommit(t *testing.T) { 119 runner := test.CreateRepo(t).Runner 120 err := runner.CreateCommit(git.Commit{ 121 Branch: "master", 122 FileName: "hello.txt", 123 FileContent: "hello world", 124 Message: "test commit", 125 }) 126 assert.NoError(t, err) 127 commits, err := runner.Commits([]string{"FILE NAME", "FILE CONTENT"}) 128 assert.NoError(t, err) 129 assert.Len(t, commits, 1) 130 assert.Equal(t, "hello.txt", commits[0].FileName) 131 assert.Equal(t, "hello world", commits[0].FileContent) 132 assert.Equal(t, "test commit", commits[0].Message) 133 assert.Equal(t, "master", commits[0].Branch) 134} 135 136func TestRunner_CreateCommit_Author(t *testing.T) { 137 runner := test.CreateRepo(t).Runner 138 err := runner.CreateCommit(git.Commit{ 139 Branch: "master", 140 FileName: "hello.txt", 141 FileContent: "hello world", 142 Message: "test commit", 143 Author: "developer <developer@example.com>", 144 }) 145 assert.NoError(t, err) 146 commits, err := runner.Commits([]string{"FILE NAME", "FILE CONTENT"}) 147 assert.NoError(t, err) 148 assert.Len(t, commits, 1) 149 assert.Equal(t, "hello.txt", commits[0].FileName) 150 assert.Equal(t, "hello world", commits[0].FileContent) 151 assert.Equal(t, "test commit", commits[0].Message) 152 assert.Equal(t, "master", commits[0].Branch) 153 assert.Equal(t, "developer <developer@example.com>", commits[0].Author) 154} 155 156func TestRunner_CreateFeatureBranch(t *testing.T) { 157 runner := test.CreateTestGitTownRepo(t).Runner 158 err := runner.CreateFeatureBranch("f1") 159 assert.NoError(t, err) 160 runner.Config.Reload() 161 assert.True(t, runner.Config.IsFeatureBranch("f1")) 162 assert.Equal(t, []string{"main"}, runner.Config.GetAncestorBranches("f1")) 163} 164 165func TestRunner_CreateFeatureBranchNoParent(t *testing.T) { 166 runner := test.CreateTestGitTownRepo(t).Runner 167 err := runner.CreateFeatureBranchNoParent("f1") 168 assert.NoError(t, err) 169 runner.Config.Reload() 170 assert.True(t, runner.Config.IsFeatureBranch("f1")) 171 assert.Equal(t, []string(nil), runner.Config.GetAncestorBranches("f1")) 172} 173 174func TestRunner_CreateFile(t *testing.T) { 175 runner := test.CreateRepo(t).Runner 176 err := runner.CreateFile("filename", "content") 177 assert.Nil(t, err, "cannot create file in repo") 178 content, err := ioutil.ReadFile(filepath.Join(runner.WorkingDir(), "filename")) 179 assert.Nil(t, err, "cannot read file") 180 assert.Equal(t, "content", string(content)) 181} 182 183func TestRunner_CreateFile_InSubFolder(t *testing.T) { 184 runner := test.CreateRepo(t).Runner 185 err := runner.CreateFile("folder/filename", "content") 186 assert.Nil(t, err, "cannot create file in repo") 187 content, err := ioutil.ReadFile(filepath.Join(runner.WorkingDir(), "folder/filename")) 188 assert.Nil(t, err, "cannot read file") 189 assert.Equal(t, "content", string(content)) 190} 191 192func TestRunner_CreatePerennialBranches(t *testing.T) { 193 runner := test.CreateTestGitTownRepo(t).Runner 194 err := runner.CreatePerennialBranches("p1", "p2") 195 assert.NoError(t, err) 196 branches, err := runner.LocalBranchesMainFirst() 197 assert.NoError(t, err) 198 assert.Equal(t, []string{"main", "master", "p1", "p2"}, branches) 199 runner.Config.Reload() 200 assert.True(t, runner.Config.IsPerennialBranch("p1")) 201 assert.True(t, runner.Config.IsPerennialBranch("p2")) 202} 203 204func TestRunner_CurrentBranch(t *testing.T) { 205 runner := test.CreateRepo(t).Runner 206 err := runner.CheckoutBranch("master") 207 assert.NoError(t, err) 208 err = runner.CreateBranch("b1", "master") 209 assert.NoError(t, err) 210 err = runner.CheckoutBranch("b1") 211 assert.NoError(t, err) 212 branch, err := runner.CurrentBranch() 213 assert.NoError(t, err) 214 assert.Equal(t, "b1", branch) 215 err = runner.CheckoutBranch("master") 216 assert.NoError(t, err) 217 branch, err = runner.CurrentBranch() 218 assert.NoError(t, err) 219 assert.Equal(t, "master", branch) 220} 221 222func TestRunner_Fetch(t *testing.T) { 223 runner := test.CreateRepo(t).Runner 224 origin := test.CreateRepo(t) 225 err := runner.AddRemote("origin", origin.WorkingDir()) 226 assert.NoError(t, err) 227 err = runner.Fetch() 228 assert.NoError(t, err) 229} 230 231func TestRunner_FileContentInCommit(t *testing.T) { 232 runner := test.CreateRepo(t).Runner 233 err := runner.CreateCommit(git.Commit{ 234 Branch: "master", 235 FileName: "hello.txt", 236 FileContent: "hello world", 237 Message: "commit", 238 }) 239 assert.NoError(t, err) 240 commits, err := runner.CommitsInBranch("master", []string{}) 241 assert.NoError(t, err) 242 assert.Len(t, commits, 1) 243 content, err := runner.FileContentInCommit(commits[0].SHA, "hello.txt") 244 assert.NoError(t, err) 245 assert.Equal(t, "hello world", content) 246} 247 248func TestRunner_FilesInCommit(t *testing.T) { 249 runner := test.CreateRepo(t).Runner 250 err := runner.CreateFile("f1.txt", "one") 251 assert.NoError(t, err) 252 err = runner.CreateFile("f2.txt", "two") 253 assert.NoError(t, err) 254 err = runner.StageFiles("f1.txt", "f2.txt") 255 assert.NoError(t, err) 256 err = runner.CommitStagedChanges("stuff") 257 assert.NoError(t, err) 258 commits, err := runner.Commits([]string{}) 259 assert.NoError(t, err) 260 assert.Len(t, commits, 1) 261 fileNames, err := runner.FilesInCommit(commits[0].SHA) 262 assert.NoError(t, err) 263 assert.Equal(t, []string{"f1.txt", "f2.txt"}, fileNames) 264} 265 266func TestRunner_HasBranchesOutOfSync_synced(t *testing.T) { 267 env, err := test.NewStandardGitEnvironment(test.CreateTempDir(t)) 268 assert.NoError(t, err) 269 runner := env.DevRepo.Runner 270 err = runner.CreateBranch("branch1", "main") 271 assert.NoError(t, err) 272 err = runner.CheckoutBranch("branch1") 273 assert.NoError(t, err) 274 err = runner.CreateFile("file1", "content") 275 assert.NoError(t, err) 276 err = runner.StageFiles("file1") 277 assert.NoError(t, err) 278 err = runner.CommitStagedChanges("stuff") 279 assert.NoError(t, err) 280 err = runner.PushBranchSetUpstream("branch1") 281 assert.NoError(t, err) 282 have, err := runner.HasBranchesOutOfSync() 283 assert.NoError(t, err) 284 assert.False(t, have) 285} 286 287func TestRunner_HasBranchesOutOfSync_branchAhead(t *testing.T) { 288 env, err := test.NewStandardGitEnvironment(test.CreateTempDir(t)) 289 assert.NoError(t, err) 290 runner := env.DevRepo.Runner 291 err = runner.CreateBranch("branch1", "main") 292 assert.NoError(t, err) 293 err = runner.PushBranch() 294 assert.NoError(t, err) 295 err = runner.CreateFile("file1", "content") 296 assert.NoError(t, err) 297 err = runner.StageFiles("file1") 298 assert.NoError(t, err) 299 err = runner.CommitStagedChanges("stuff") 300 assert.NoError(t, err) 301 have, err := runner.HasBranchesOutOfSync() 302 assert.NoError(t, err) 303 assert.True(t, have) 304} 305 306func TestRunner_HasBranchesOutOfSync_branchBehind(t *testing.T) { 307 env, err := test.NewStandardGitEnvironment(test.CreateTempDir(t)) 308 assert.NoError(t, err) 309 err = env.DevRepo.CreateBranch("branch1", "main") 310 assert.NoError(t, err) 311 err = env.DevRepo.PushBranch() 312 assert.NoError(t, err) 313 err = env.OriginRepo.CheckoutBranch("main") 314 assert.NoError(t, err) 315 err = env.OriginRepo.CreateFile("file1", "content") 316 assert.NoError(t, err) 317 err = env.OriginRepo.StageFiles("file1") 318 assert.NoError(t, err) 319 err = env.OriginRepo.CommitStagedChanges("stuff") 320 assert.NoError(t, err) 321 err = env.OriginRepo.CheckoutBranch("master") 322 assert.NoError(t, err) 323 err = env.DevRepo.Fetch() 324 assert.NoError(t, err) 325 have, err := env.DevRepo.Runner.HasBranchesOutOfSync() 326 assert.NoError(t, err) 327 assert.True(t, have) 328} 329 330func TestRunner_HasGitTownConfigNow(t *testing.T) { 331 runner := test.CreateRepo(t).Runner 332 res, err := runner.HasGitTownConfigNow() 333 assert.NoError(t, err) 334 assert.False(t, res) 335 err = runner.CreateBranch("main", "master") 336 assert.NoError(t, err) 337 err = runner.CreateFeatureBranch("foo") 338 assert.NoError(t, err) 339 res, err = runner.HasGitTownConfigNow() 340 assert.NoError(t, err) 341 assert.True(t, res) 342} 343 344func TestRunner_HasFile(t *testing.T) { 345 runner := test.CreateRepo(t).Runner 346 err := runner.CreateFile("f1.txt", "one") 347 assert.NoError(t, err) 348 has, err := runner.HasFile("f1.txt", "one") 349 assert.NoError(t, err) 350 assert.True(t, has) 351 _, err = runner.HasFile("f1.txt", "zonk") 352 assert.Error(t, err) 353 _, err = runner.HasFile("zonk.txt", "one") 354 assert.Error(t, err) 355} 356func TestRunner_HasLocalBranch(t *testing.T) { 357 origin := test.CreateRepo(t) 358 repoDir := test.CreateTempDir(t) 359 repo, err := origin.Clone(repoDir) 360 assert.NoError(t, err) 361 err = repo.CreateBranch("b1", "master") 362 assert.NoError(t, err) 363 err = repo.CreateBranch("b2", "master") 364 assert.NoError(t, err) 365 has, err := repo.HasLocalBranch("b1") 366 assert.NoError(t, err) 367 assert.True(t, has) 368 has, err = repo.HasLocalBranch("b2") 369 assert.NoError(t, err) 370 assert.True(t, has) 371 has, err = repo.HasLocalBranch("b3") 372 assert.NoError(t, err) 373 assert.False(t, has) 374} 375 376func TestRunner_HasOpenChanges(t *testing.T) { 377 runner := test.CreateRepo(t).Runner 378 has, err := runner.HasOpenChanges() 379 assert.NoError(t, err) 380 assert.False(t, has) 381 err = runner.CreateFile("foo", "bar") 382 assert.NoError(t, err) 383 has, err = runner.HasOpenChanges() 384 assert.NoError(t, err) 385 assert.True(t, has) 386} 387 388func TestRunner_HasRebaseInProgress(t *testing.T) { 389 runner := test.CreateRepo(t).Runner 390 has, err := runner.HasRebaseInProgress() 391 assert.NoError(t, err) 392 assert.False(t, has) 393} 394 395func TestRunner_HasRemote(t *testing.T) { 396 origin := test.CreateRepo(t) 397 repoDir := test.CreateTempDir(t) 398 repo, err := origin.Clone(repoDir) 399 assert.NoError(t, err) 400 has, err := repo.Runner.HasRemote("origin") 401 assert.NoError(t, err) 402 assert.True(t, has) 403 has, err = repo.Runner.HasRemote("zonk") 404 assert.NoError(t, err) 405 assert.False(t, has) 406} 407 408func TestRunner_HasTrackingBranch(t *testing.T) { 409 origin := test.CreateRepo(t) 410 err := origin.CreateBranch("b1", "master") 411 assert.NoError(t, err) 412 repoDir := test.CreateTempDir(t) 413 repo, err := origin.Clone(repoDir) 414 assert.NoError(t, err) 415 runner := repo.Runner 416 err = runner.CheckoutBranch("b1") 417 assert.NoError(t, err) 418 err = runner.CreateBranch("b2", "master") 419 assert.NoError(t, err) 420 has, err := runner.HasTrackingBranch("b1") 421 assert.NoError(t, err) 422 assert.True(t, has) 423 has, err = runner.HasTrackingBranch("b2") 424 assert.NoError(t, err) 425 assert.False(t, has) 426 has, err = runner.HasTrackingBranch("b3") 427 assert.NoError(t, err) 428 assert.False(t, has) 429} 430 431func TestRunner_LocalBranches(t *testing.T) { 432 origin := test.CreateRepo(t) 433 repoDir := test.CreateTempDir(t) 434 repo, err := origin.Clone(repoDir) 435 assert.NoError(t, err) 436 err = repo.CreateBranch("b1", "master") 437 assert.NoError(t, err) 438 err = repo.CreateBranch("b2", "master") 439 assert.NoError(t, err) 440 err = origin.CreateBranch("b3", "master") 441 assert.NoError(t, err) 442 err = repo.Fetch() 443 assert.NoError(t, err) 444 branches, err := repo.Runner.LocalBranchesMainFirst() 445 assert.NoError(t, err) 446 assert.Equal(t, []string{"b1", "b2", "master"}, branches) 447} 448 449func TestRunner_LocalAndRemoteBranches(t *testing.T) { 450 origin := test.CreateRepo(t) 451 repoDir := test.CreateTempDir(t) 452 repo, err := origin.Clone(repoDir) 453 assert.NoError(t, err) 454 err = repo.CreateBranch("b1", "master") 455 assert.NoError(t, err) 456 err = repo.CreateBranch("b2", "master") 457 assert.NoError(t, err) 458 err = origin.CreateBranch("b3", "master") 459 assert.NoError(t, err) 460 err = repo.Fetch() 461 assert.NoError(t, err) 462 branches, err := repo.Runner.LocalAndRemoteBranches() 463 assert.NoError(t, err) 464 assert.Equal(t, []string{"b1", "b2", "b3", "master"}, branches) 465} 466 467func TestRunner_PreviouslyCheckedOutBranch(t *testing.T) { 468 runner := test.CreateRepo(t).Runner 469 err := runner.CreateBranch("feature1", "master") 470 assert.NoError(t, err) 471 err = runner.CreateBranch("feature2", "master") 472 assert.NoError(t, err) 473 err = runner.CheckoutBranch("feature1") 474 assert.NoError(t, err) 475 err = runner.CheckoutBranch("feature2") 476 assert.NoError(t, err) 477 have, err := runner.PreviouslyCheckedOutBranch() 478 assert.NoError(t, err) 479 assert.Equal(t, "feature1", have) 480} 481 482func TestRunner_PushBranch(t *testing.T) { 483 runner := test.CreateRepo(t).Runner 484 origin := test.CreateRepo(t) 485 err := runner.AddRemote("origin", origin.WorkingDir()) 486 assert.NoError(t, err) 487 err = runner.CreateBranch("b1", "master") 488 assert.NoError(t, err) 489 err = runner.PushBranchSetUpstream("b1") 490 assert.NoError(t, err) 491 branches, err := origin.LocalBranchesMainFirst() 492 assert.NoError(t, err) 493 assert.Equal(t, []string{"b1", "master"}, branches) 494} 495 496func TestRunner_RemoteBranches(t *testing.T) { 497 origin := test.CreateRepo(t) 498 repoDir := test.CreateTempDir(t) 499 repo, err := origin.Clone(repoDir) 500 assert.NoError(t, err) 501 err = repo.CreateBranch("b1", "master") 502 assert.NoError(t, err) 503 err = repo.CreateBranch("b2", "master") 504 assert.NoError(t, err) 505 err = origin.CreateBranch("b3", "master") 506 assert.NoError(t, err) 507 err = repo.Fetch() 508 assert.NoError(t, err) 509 branches, err := repo.Runner.RemoteBranches() 510 assert.NoError(t, err) 511 assert.Equal(t, []string{"origin/b3", "origin/master"}, branches) 512} 513 514func TestRunner_Remotes(t *testing.T) { 515 runner := test.CreateRepo(t).Runner 516 origin := test.CreateRepo(t) 517 err := runner.AddRemote("origin", origin.WorkingDir()) 518 assert.NoError(t, err) 519 remotes, err := runner.Remotes() 520 assert.NoError(t, err) 521 assert.Equal(t, []string{"origin"}, remotes) 522} 523 524func TestRunner_RemoveBranch(t *testing.T) { 525 runner := test.CreateRepo(t).Runner 526 err := runner.CreateBranch("b1", "master") 527 assert.NoError(t, err) 528 branches, err := runner.LocalBranchesMainFirst() 529 assert.NoError(t, err) 530 assert.Equal(t, []string{"b1", "master"}, branches) 531 err = runner.RemoveBranch("b1") 532 assert.NoError(t, err) 533 branches, err = runner.LocalBranchesMainFirst() 534 assert.NoError(t, err) 535 assert.Equal(t, []string{"master"}, branches) 536} 537 538func TestRunner_RemoveRemote(t *testing.T) { 539 runner := test.CreateRepo(t).Runner 540 origin := test.CreateRepo(t) 541 err := runner.AddRemote("origin", origin.WorkingDir()) 542 assert.NoError(t, err) 543 err = runner.RemoveRemote("origin") 544 assert.NoError(t, err) 545 remotes, err := runner.Remotes() 546 assert.NoError(t, err) 547 assert.Len(t, remotes, 0) 548} 549 550func TestRunner_SetRemote(t *testing.T) { 551 runner := test.CreateRepo(t).Runner 552 remotes, err := runner.Remotes() 553 assert.NoError(t, err) 554 assert.Equal(t, []string{}, remotes) 555 origin := test.CreateRepo(t) 556 err = runner.AddRemote("origin", origin.WorkingDir()) 557 assert.NoError(t, err) 558 remotes, err = runner.Remotes() 559 assert.NoError(t, err) 560 assert.Equal(t, []string{"origin"}, remotes) 561} 562 563func TestRunner_ShaForCommit(t *testing.T) { 564 runner := test.CreateRepo(t).Runner 565 err := runner.CreateCommit(git.Commit{Branch: "master", FileName: "foo", FileContent: "bar", Message: "commit"}) 566 assert.NoError(t, err) 567 sha, err := runner.ShaForCommit("commit") 568 assert.NoError(t, err) 569 assert.Len(t, sha, 40) 570} 571 572func TestRunner_StageFile(t *testing.T) { 573 runner := test.CreateRepo(t).Runner 574 err := runner.CreateFile("f1.txt", "one") 575 assert.NoError(t, err) 576} 577 578func TestRunner_Stash(t *testing.T) { 579 runner := test.CreateRepo(t).Runner 580 stashSize, err := runner.StashSize() 581 assert.NoError(t, err) 582 assert.Zero(t, stashSize) 583 err = runner.CreateFile("f1.txt", "hello") 584 assert.NoError(t, err) 585 err = runner.Stash() 586 assert.NoError(t, err) 587 stashSize, err = runner.StashSize() 588 assert.NoError(t, err) 589 assert.Equal(t, 1, stashSize) 590} 591 592func TestRunner_UncommittedFiles(t *testing.T) { 593 runner := test.CreateRepo(t).Runner 594 err := runner.CreateFile("f1.txt", "one") 595 assert.NoError(t, err) 596 err = runner.CreateFile("f2.txt", "two") 597 assert.NoError(t, err) 598 files, err := runner.UncommittedFiles() 599 assert.NoError(t, err) 600 assert.Equal(t, []string{"f1.txt", "f2.txt"}, files) 601} 602