github.com/cycloidio/terraform@v1.1.10-0.20220513142504-76d5c768dc63/getmodules/git_getter_test.go (about) 1 package getmodules 2 3 import ( 4 "bytes" 5 "encoding/base64" 6 "io/ioutil" 7 "net/url" 8 "os" 9 "os/exec" 10 "path/filepath" 11 "reflect" 12 "runtime" 13 "strings" 14 "testing" 15 16 getter "github.com/hashicorp/go-getter" 17 urlhelper "github.com/hashicorp/go-getter/helper/url" 18 ) 19 20 var testHasGit bool 21 22 func init() { 23 if _, err := exec.LookPath("git"); err == nil { 24 testHasGit = true 25 } 26 } 27 28 func TestGitGetter_impl(t *testing.T) { 29 var _ getter.Getter = new(gitGetter) 30 } 31 32 func TestGitGetter(t *testing.T) { 33 if !testHasGit { 34 t.Skip("git not found, skipping") 35 } 36 37 g := new(gitGetter) 38 dst := tempDir(t) 39 40 repo := testGitRepo(t, "basic") 41 repo.commitFile("foo.txt", "hello") 42 43 // With a dir that doesn't exist 44 if err := g.Get(dst, repo.url); err != nil { 45 t.Fatalf("err: %s", err) 46 } 47 48 // Verify the main file exists 49 mainPath := filepath.Join(dst, "foo.txt") 50 if _, err := os.Stat(mainPath); err != nil { 51 t.Fatalf("err: %s", err) 52 } 53 } 54 55 func TestGitGetter_branch(t *testing.T) { 56 if !testHasGit { 57 t.Skip("git not found, skipping") 58 } 59 60 g := new(gitGetter) 61 dst := tempDir(t) 62 63 repo := testGitRepo(t, "branch") 64 repo.git("checkout", "-b", "test-branch") 65 repo.commitFile("branch.txt", "branch") 66 67 q := repo.url.Query() 68 q.Add("ref", "test-branch") 69 repo.url.RawQuery = q.Encode() 70 71 if err := g.Get(dst, repo.url); err != nil { 72 t.Fatalf("err: %s", err) 73 } 74 75 // Verify the main file exists 76 mainPath := filepath.Join(dst, "branch.txt") 77 if _, err := os.Stat(mainPath); err != nil { 78 t.Fatalf("err: %s", err) 79 } 80 81 // Get again should work 82 if err := g.Get(dst, repo.url); err != nil { 83 t.Fatalf("err: %s", err) 84 } 85 86 // Verify the main file exists 87 mainPath = filepath.Join(dst, "branch.txt") 88 if _, err := os.Stat(mainPath); err != nil { 89 t.Fatalf("err: %s", err) 90 } 91 } 92 93 func TestGitGetter_commitID(t *testing.T) { 94 if !testHasGit { 95 t.Skip("git not found, skipping") 96 } 97 98 g := new(gitGetter) 99 dst := tempDir(t) 100 101 // We're going to create different content on the main branch vs. 102 // another branch here, so that below we can recognize if we 103 // correctly cloned the commit actually requested (from the 104 // "other branch"), not the one at HEAD. 105 repo := testGitRepo(t, "commit_id") 106 repo.git("checkout", "-b", "main-branch") 107 repo.commitFile("wrong.txt", "Nope") 108 repo.git("checkout", "-b", "other-branch") 109 repo.commitFile("hello.txt", "Yep") 110 commitID, err := repo.latestCommit() 111 if err != nil { 112 t.Fatal(err) 113 } 114 // Return to the main branch so that HEAD of this repository 115 // will be that, rather than "test-branch". 116 repo.git("checkout", "main-branch") 117 118 q := repo.url.Query() 119 q.Add("ref", commitID) 120 repo.url.RawQuery = q.Encode() 121 122 t.Logf("Getting %s", repo.url) 123 if err := g.Get(dst, repo.url); err != nil { 124 t.Fatalf("err: %s", err) 125 } 126 127 // Verify the main file exists 128 mainPath := filepath.Join(dst, "hello.txt") 129 if _, err := os.Stat(mainPath); err != nil { 130 t.Fatalf("err: %s", err) 131 } 132 133 // Get again should work 134 if err := g.Get(dst, repo.url); err != nil { 135 t.Fatalf("err: %s", err) 136 } 137 138 // Verify the main file exists 139 mainPath = filepath.Join(dst, "hello.txt") 140 if _, err := os.Stat(mainPath); err != nil { 141 t.Fatalf("err: %s", err) 142 } 143 } 144 145 func TestGitGetter_remoteWithoutMaster(t *testing.T) { 146 if !testHasGit { 147 t.Log("git not found, skipping") 148 t.Skip() 149 } 150 151 g := new(gitGetter) 152 dst := tempDir(t) 153 154 repo := testGitRepo(t, "branch") 155 repo.git("checkout", "-b", "test-branch") 156 repo.commitFile("branch.txt", "branch") 157 158 q := repo.url.Query() 159 repo.url.RawQuery = q.Encode() 160 161 if err := g.Get(dst, repo.url); err != nil { 162 t.Fatalf("err: %s", err) 163 } 164 165 // Verify the main file exists 166 mainPath := filepath.Join(dst, "branch.txt") 167 if _, err := os.Stat(mainPath); err != nil { 168 t.Fatalf("err: %s", err) 169 } 170 171 // Get again should work 172 if err := g.Get(dst, repo.url); err != nil { 173 t.Fatalf("err: %s", err) 174 } 175 176 // Verify the main file exists 177 mainPath = filepath.Join(dst, "branch.txt") 178 if _, err := os.Stat(mainPath); err != nil { 179 t.Fatalf("err: %s", err) 180 } 181 } 182 183 func TestGitGetter_shallowClone(t *testing.T) { 184 if !testHasGit { 185 t.Log("git not found, skipping") 186 t.Skip() 187 } 188 189 g := new(gitGetter) 190 dst := tempDir(t) 191 192 repo := testGitRepo(t, "upstream") 193 repo.commitFile("upstream.txt", "0") 194 repo.commitFile("upstream.txt", "1") 195 196 // Specifiy a clone depth of 1 197 q := repo.url.Query() 198 q.Add("depth", "1") 199 repo.url.RawQuery = q.Encode() 200 201 if err := g.Get(dst, repo.url); err != nil { 202 t.Fatalf("err: %s", err) 203 } 204 205 // Assert rev-list count is '1' 206 cmd := exec.Command("git", "rev-list", "HEAD", "--count") 207 cmd.Dir = dst 208 b, err := cmd.Output() 209 if err != nil { 210 t.Fatalf("err: %s", err) 211 } 212 213 out := strings.TrimSpace(string(b)) 214 if out != "1" { 215 t.Fatalf("expected rev-list count to be '1' but got %v", out) 216 } 217 } 218 219 func TestGitGetter_shallowCloneWithTag(t *testing.T) { 220 if !testHasGit { 221 t.Log("git not found, skipping") 222 t.Skip() 223 } 224 225 g := new(gitGetter) 226 dst := tempDir(t) 227 228 repo := testGitRepo(t, "upstream") 229 repo.commitFile("v1.0.txt", "0") 230 repo.git("tag", "v1.0") 231 repo.commitFile("v1.1.txt", "1") 232 233 // Specifiy a clone depth of 1 with a tag 234 q := repo.url.Query() 235 q.Add("ref", "v1.0") 236 q.Add("depth", "1") 237 repo.url.RawQuery = q.Encode() 238 239 if err := g.Get(dst, repo.url); err != nil { 240 t.Fatalf("err: %s", err) 241 } 242 243 // Assert rev-list count is '1' 244 cmd := exec.Command("git", "rev-list", "HEAD", "--count") 245 cmd.Dir = dst 246 b, err := cmd.Output() 247 if err != nil { 248 t.Fatalf("err: %s", err) 249 } 250 251 out := strings.TrimSpace(string(b)) 252 if out != "1" { 253 t.Fatalf("expected rev-list count to be '1' but got %v", out) 254 } 255 256 // Verify the v1.0 file exists 257 mainPath := filepath.Join(dst, "v1.0.txt") 258 if _, err := os.Stat(mainPath); err != nil { 259 t.Fatalf("err: %s", err) 260 } 261 262 // Verify the v1.1 file does not exists 263 mainPath = filepath.Join(dst, "v1.1.txt") 264 if _, err := os.Stat(mainPath); err == nil { 265 t.Fatalf("expected v1.1 file to not exist") 266 } 267 } 268 269 func TestGitGetter_shallowCloneWithCommitID(t *testing.T) { 270 if !testHasGit { 271 t.Log("git not found, skipping") 272 t.Skip() 273 } 274 275 g := new(gitGetter) 276 dst := tempDir(t) 277 278 repo := testGitRepo(t, "upstream") 279 repo.commitFile("v1.0.txt", "0") 280 repo.git("tag", "v1.0") 281 repo.commitFile("v1.1.txt", "1") 282 283 commitID, err := repo.latestCommit() 284 if err != nil { 285 t.Fatal(err) 286 } 287 288 // Specify a clone depth of 1 with a naked commit ID 289 // This is intentionally invalid: shallow clone always requires a named ref. 290 q := repo.url.Query() 291 q.Add("ref", commitID[:8]) 292 q.Add("depth", "1") 293 repo.url.RawQuery = q.Encode() 294 295 t.Logf("Getting %s", repo.url) 296 err = g.Get(dst, repo.url) 297 if err == nil { 298 t.Fatalf("success; want error") 299 } 300 // We use a heuristic to generate an extra hint in the error message if 301 // it looks like the user was trying to combine ref=COMMIT with depth. 302 if got, want := err.Error(), "(note that setting 'depth' requires 'ref' to be a branch or tag name)"; !strings.Contains(got, want) { 303 t.Errorf("missing error message hint\ngot: %s\nwant substring: %s", got, want) 304 } 305 } 306 307 func TestGitGetter_branchUpdate(t *testing.T) { 308 if !testHasGit { 309 t.Skip("git not found, skipping") 310 } 311 312 g := new(gitGetter) 313 dst := tempDir(t) 314 315 // First setup the state with a fresh branch 316 repo := testGitRepo(t, "branch-update") 317 repo.git("checkout", "-b", "test-branch") 318 repo.commitFile("branch.txt", "branch") 319 320 // Get the "test-branch" branch 321 q := repo.url.Query() 322 q.Add("ref", "test-branch") 323 repo.url.RawQuery = q.Encode() 324 if err := g.Get(dst, repo.url); err != nil { 325 t.Fatalf("err: %s", err) 326 } 327 328 // Verify the main file exists 329 mainPath := filepath.Join(dst, "branch.txt") 330 if _, err := os.Stat(mainPath); err != nil { 331 t.Fatalf("err: %s", err) 332 } 333 334 // Commit an update to the branch 335 repo.commitFile("branch-update.txt", "branch-update") 336 337 // Get again should work 338 if err := g.Get(dst, repo.url); err != nil { 339 t.Fatalf("err: %s", err) 340 } 341 342 // Verify the main file exists 343 mainPath = filepath.Join(dst, "branch-update.txt") 344 if _, err := os.Stat(mainPath); err != nil { 345 t.Fatalf("err: %s", err) 346 } 347 } 348 349 func TestGitGetter_tag(t *testing.T) { 350 if !testHasGit { 351 t.Skip("git not found, skipping") 352 } 353 354 g := new(gitGetter) 355 dst := tempDir(t) 356 357 repo := testGitRepo(t, "tag") 358 repo.commitFile("tag.txt", "tag") 359 repo.git("tag", "v1.0") 360 361 q := repo.url.Query() 362 q.Add("ref", "v1.0") 363 repo.url.RawQuery = q.Encode() 364 365 if err := g.Get(dst, repo.url); err != nil { 366 t.Fatalf("err: %s", err) 367 } 368 369 // Verify the main file exists 370 mainPath := filepath.Join(dst, "tag.txt") 371 if _, err := os.Stat(mainPath); err != nil { 372 t.Fatalf("err: %s", err) 373 } 374 375 // Get again should work 376 if err := g.Get(dst, repo.url); err != nil { 377 t.Fatalf("err: %s", err) 378 } 379 380 // Verify the main file exists 381 mainPath = filepath.Join(dst, "tag.txt") 382 if _, err := os.Stat(mainPath); err != nil { 383 t.Fatalf("err: %s", err) 384 } 385 } 386 387 func TestGitGetter_GetFile(t *testing.T) { 388 if !testHasGit { 389 t.Skip("git not found, skipping") 390 } 391 392 g := new(gitGetter) 393 dst := tempTestFile(t) 394 defer os.RemoveAll(filepath.Dir(dst)) 395 396 repo := testGitRepo(t, "file") 397 repo.commitFile("file.txt", "hello") 398 399 // Download the file 400 repo.url.Path = filepath.Join(repo.url.Path, "file.txt") 401 if err := g.GetFile(dst, repo.url); err != nil { 402 t.Fatalf("err: %s", err) 403 } 404 405 // Verify the main file exists 406 if _, err := os.Stat(dst); err != nil { 407 t.Fatalf("err: %s", err) 408 } 409 assertContents(t, dst, "hello") 410 } 411 412 func TestGitGetter_gitVersion(t *testing.T) { 413 if !testHasGit { 414 t.Skip("git not found, skipping") 415 } 416 if runtime.GOOS == "windows" { 417 t.Skip("skipping on windows since the test requires sh") 418 } 419 dir, err := ioutil.TempDir("", "go-getter") 420 if err != nil { 421 t.Fatal(err) 422 } 423 defer os.RemoveAll(dir) 424 425 script := filepath.Join(dir, "git") 426 err = ioutil.WriteFile( 427 script, 428 []byte("#!/bin/sh\necho \"git version 2.0 (Some Metadata Here)\n\""), 429 0700) 430 if err != nil { 431 t.Fatal(err) 432 } 433 434 defer func(v string) { 435 os.Setenv("PATH", v) 436 }(os.Getenv("PATH")) 437 438 os.Setenv("PATH", dir) 439 440 // Asking for a higher version throws an error 441 if err := checkGitVersion("2.3"); err == nil { 442 t.Fatal("expect git version error") 443 } 444 445 // Passes when version is satisfied 446 if err := checkGitVersion("1.9"); err != nil { 447 t.Fatal(err) 448 } 449 } 450 451 func TestGitGetter_sshKey(t *testing.T) { 452 if !testHasGit { 453 t.Skip("git not found, skipping") 454 } 455 456 g := new(gitGetter) 457 dst := tempDir(t) 458 459 encodedKey := base64.StdEncoding.EncodeToString([]byte(testGitToken)) 460 461 // avoid getting locked by a github authenticity validation prompt 462 os.Setenv("GIT_SSH_COMMAND", "ssh -o StrictHostKeyChecking=no -o IdentitiesOnly=yes") 463 defer os.Setenv("GIT_SSH_COMMAND", "") 464 465 u, err := urlhelper.Parse("ssh://git@github.com/hashicorp/test-private-repo" + 466 "?sshkey=" + encodedKey) 467 if err != nil { 468 t.Fatal(err) 469 } 470 471 if err := g.Get(dst, u); err != nil { 472 t.Fatalf("err: %s", err) 473 } 474 475 readmePath := filepath.Join(dst, "README.md") 476 if _, err := os.Stat(readmePath); err != nil { 477 t.Fatalf("err: %s", err) 478 } 479 } 480 481 func TestGitGetter_sshSCPStyle(t *testing.T) { 482 if !testHasGit { 483 t.Skip("git not found, skipping") 484 } 485 486 g := new(gitGetter) 487 dst := tempDir(t) 488 489 encodedKey := base64.StdEncoding.EncodeToString([]byte(testGitToken)) 490 491 // avoid getting locked by a github authenticity validation prompt 492 os.Setenv("GIT_SSH_COMMAND", "ssh -o StrictHostKeyChecking=no -o IdentitiesOnly=yes") 493 defer os.Setenv("GIT_SSH_COMMAND", "") 494 495 // This test exercises the combination of the git detector and the 496 // git getter, to make sure that together they make scp-style URLs work. 497 client := &getter.Client{ 498 Src: "git@github.com:hashicorp/test-private-repo?sshkey=" + encodedKey, 499 Dst: dst, 500 Pwd: ".", 501 502 Mode: getter.ClientModeDir, 503 504 Detectors: []getter.Detector{ 505 new(getter.GitDetector), 506 }, 507 Getters: map[string]getter.Getter{ 508 "git": g, 509 }, 510 } 511 512 if err := client.Get(); err != nil { 513 t.Fatalf("client.Get failed: %s", err) 514 } 515 516 readmePath := filepath.Join(dst, "README.md") 517 if _, err := os.Stat(readmePath); err != nil { 518 t.Fatalf("err: %s", err) 519 } 520 } 521 522 func TestGitGetter_sshExplicitPort(t *testing.T) { 523 if !testHasGit { 524 t.Skip("git not found, skipping") 525 } 526 527 g := new(gitGetter) 528 dst := tempDir(t) 529 530 encodedKey := base64.StdEncoding.EncodeToString([]byte(testGitToken)) 531 532 // avoid getting locked by a github authenticity validation prompt 533 os.Setenv("GIT_SSH_COMMAND", "ssh -o StrictHostKeyChecking=no -o IdentitiesOnly=yes") 534 defer os.Setenv("GIT_SSH_COMMAND", "") 535 536 // This test exercises the combination of the git detector and the 537 // git getter, to make sure that together they make scp-style URLs work. 538 client := &getter.Client{ 539 Src: "git::ssh://git@github.com:22/hashicorp/test-private-repo?sshkey=" + encodedKey, 540 Dst: dst, 541 Pwd: ".", 542 543 Mode: getter.ClientModeDir, 544 545 Detectors: []getter.Detector{ 546 new(getter.GitDetector), 547 }, 548 Getters: map[string]getter.Getter{ 549 "git": g, 550 }, 551 } 552 553 if err := client.Get(); err != nil { 554 t.Fatalf("client.Get failed: %s", err) 555 } 556 557 readmePath := filepath.Join(dst, "README.md") 558 if _, err := os.Stat(readmePath); err != nil { 559 t.Fatalf("err: %s", err) 560 } 561 } 562 563 func TestGitGetter_sshSCPStyleInvalidScheme(t *testing.T) { 564 if !testHasGit { 565 t.Skip("git not found, skipping") 566 } 567 568 g := new(gitGetter) 569 dst := tempDir(t) 570 571 encodedKey := base64.StdEncoding.EncodeToString([]byte(testGitToken)) 572 573 // avoid getting locked by a github authenticity validation prompt 574 os.Setenv("GIT_SSH_COMMAND", "ssh -o StrictHostKeyChecking=no -o IdentitiesOnly=yes") 575 defer os.Setenv("GIT_SSH_COMMAND", "") 576 577 // This test exercises the combination of the git detector and the 578 // git getter, to make sure that together they make scp-style URLs work. 579 client := &getter.Client{ 580 Src: "git::ssh://git@github.com:hashicorp/test-private-repo?sshkey=" + encodedKey, 581 Dst: dst, 582 Pwd: ".", 583 584 Mode: getter.ClientModeDir, 585 586 Detectors: []getter.Detector{ 587 new(getter.GitDetector), 588 }, 589 Getters: map[string]getter.Getter{ 590 "git": g, 591 }, 592 } 593 594 err := client.Get() 595 if err == nil { 596 t.Fatalf("get succeeded; want error") 597 } 598 599 got := err.Error() 600 want1, want2 := `invalid source string`, `invalid port number "hashicorp"` 601 if !(strings.Contains(got, want1) || strings.Contains(got, want2)) { 602 t.Fatalf("wrong error\ngot: %s\nwant: %q or %q", got, want1, want2) 603 } 604 } 605 606 func TestGitGetter_submodule(t *testing.T) { 607 if !testHasGit { 608 t.Skip("git not found, skipping") 609 } 610 611 g := new(gitGetter) 612 dst := tempDir(t) 613 614 relpath := func(basepath, targpath string) string { 615 relpath, err := filepath.Rel(basepath, targpath) 616 if err != nil { 617 t.Fatal(err) 618 } 619 return strings.Replace(relpath, `\`, `/`, -1) 620 // on windows git still prefers relatives paths 621 // containing `/` for submodules 622 } 623 624 // Set up the grandchild 625 gc := testGitRepo(t, "grandchild") 626 gc.commitFile("grandchild.txt", "grandchild") 627 628 // Set up the child 629 c := testGitRepo(t, "child") 630 c.commitFile("child.txt", "child") 631 c.git("submodule", "add", "-f", relpath(c.dir, gc.dir)) 632 c.git("commit", "-m", "Add grandchild submodule") 633 634 // Set up the parent 635 p := testGitRepo(t, "parent") 636 p.commitFile("parent.txt", "parent") 637 p.git("submodule", "add", "-f", relpath(p.dir, c.dir)) 638 p.git("commit", "-m", "Add child submodule") 639 640 // Clone the root repository 641 if err := g.Get(dst, p.url); err != nil { 642 t.Fatalf("err: %s", err) 643 } 644 645 // Check that the files exist 646 for _, path := range []string{ 647 filepath.Join(dst, "parent.txt"), 648 filepath.Join(dst, "child", "child.txt"), 649 filepath.Join(dst, "child", "grandchild", "grandchild.txt"), 650 } { 651 if _, err := os.Stat(path); err != nil { 652 t.Fatalf("err: %s", err) 653 } 654 } 655 } 656 657 func TestGitGetter_setupGitEnv_sshKey(t *testing.T) { 658 if runtime.GOOS == "windows" { 659 t.Skip("skipping on windows since the test requires sh") 660 } 661 662 cmd := exec.Command("/bin/sh", "-c", "echo $GIT_SSH_COMMAND") 663 setupGitEnv(cmd, "/tmp/foo.pem") 664 out, err := cmd.Output() 665 if err != nil { 666 t.Fatal(err) 667 } 668 669 actual := strings.TrimSpace(string(out)) 670 if actual != "ssh -i /tmp/foo.pem" { 671 t.Fatalf("unexpected GIT_SSH_COMMAND: %q", actual) 672 } 673 } 674 675 func TestGitGetter_setupGitEnvWithExisting_sshKey(t *testing.T) { 676 if runtime.GOOS == "windows" { 677 t.Skipf("skipping on windows since the test requires sh") 678 return 679 } 680 681 // start with an existing ssh command configuration 682 os.Setenv("GIT_SSH_COMMAND", "ssh -o StrictHostKeyChecking=no -o IdentitiesOnly=yes") 683 defer os.Setenv("GIT_SSH_COMMAND", "") 684 685 cmd := exec.Command("/bin/sh", "-c", "echo $GIT_SSH_COMMAND") 686 setupGitEnv(cmd, "/tmp/foo.pem") 687 out, err := cmd.Output() 688 if err != nil { 689 t.Fatal(err) 690 } 691 692 actual := strings.TrimSpace(string(out)) 693 if actual != "ssh -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -i /tmp/foo.pem" { 694 t.Fatalf("unexpected GIT_SSH_COMMAND: %q", actual) 695 } 696 } 697 698 // gitRepo is a helper struct which controls a single temp git repo. 699 type gitRepo struct { 700 t *testing.T 701 url *url.URL 702 dir string 703 } 704 705 // testGitRepo creates a new test git repository. 706 func testGitRepo(t *testing.T, name string) *gitRepo { 707 t.Helper() 708 dir, err := ioutil.TempDir("", "go-getter") 709 if err != nil { 710 t.Fatal(err) 711 } 712 dir = filepath.Join(dir, name) 713 if err := os.Mkdir(dir, 0700); err != nil { 714 t.Fatal(err) 715 } 716 717 r := &gitRepo{ 718 t: t, 719 dir: dir, 720 } 721 722 url, err := urlhelper.Parse("file://" + r.dir) 723 if err != nil { 724 t.Fatal(err) 725 } 726 r.url = url 727 728 t.Logf("initializing git repo in %s", dir) 729 r.git("init") 730 r.git("config", "user.name", "go-getter") 731 r.git("config", "user.email", "go-getter@hashicorp.com") 732 733 return r 734 } 735 736 // git runs a git command against the repo. 737 func (r *gitRepo) git(args ...string) { 738 cmd := exec.Command("git", args...) 739 cmd.Dir = r.dir 740 bfr := bytes.NewBuffer(nil) 741 cmd.Stderr = bfr 742 if err := cmd.Run(); err != nil { 743 r.t.Fatal(err, bfr.String()) 744 } 745 } 746 747 // commitFile writes and commits a text file to the repo. 748 func (r *gitRepo) commitFile(file, content string) { 749 path := filepath.Join(r.dir, file) 750 if err := ioutil.WriteFile(path, []byte(content), 0600); err != nil { 751 r.t.Fatal(err) 752 } 753 r.git("add", file) 754 r.git("commit", "-m", "Adding "+file) 755 } 756 757 // latestCommit returns the full commit id of the latest commit on the current 758 // branch. 759 func (r *gitRepo) latestCommit() (string, error) { 760 cmd := exec.Command("git", "rev-parse", "HEAD") 761 cmd.Dir = r.dir 762 rawOut, err := cmd.Output() 763 if err != nil { 764 return "", err 765 } 766 rawOut = bytes.TrimSpace(rawOut) 767 return string(rawOut), nil 768 } 769 770 // This is a read-only deploy key for an empty test repository. 771 // Note: This is split over multiple lines to avoid being disabled by key 772 // scanners automatically. 773 var testGitToken = `-----BEGIN RSA PRIVATE KEY----- 774 MIIEpAIBAAKCAQEA9cHsxCl3Jjgu9DHpwvmfFOl1XEdY+ShHDR/cMnzJ5ddk5/oV 775 Wy6EWatvyHZfRSZMwzv4PtKeUPm6iXjqWp4xdWU9khlPzozyj+U9Fq70TRVUW9E5 776 T1XdQVwJE421yffr4VMMwu60wBqjI1epapH2i2inYvw9Zl9X2MXq0+jTvFvDerbT 777 mDtfStDPljenELAIZtWVETSvbI46gALwbxbM2292ZUIL4D6jRz0aZMmyy/twYv8r 778 9WGJLwmYzU518Ie7zqKW/mCTdTrV0WRiDj0MeRaPgrGY9amuHE4r9iG/cJkwpKAO 779 Ccz0Hs6i89u9vZnTqZU9V7weJqRAQcMjXXR6yQIDAQABAoIBAQDBzICKnGxiTlHw 780 rd+6qqChnAy5jWYDbZjCJ8q8YZ3RS08+g/8NXZxvHftTqM0uOaq1FviHig3gq15H 781 hHvCpBc6jXDFYoKFzq6FfO/0kFkE5HoWweIgxwRow0xBCDJAJ+ryUEyy+Ay/pQHb 782 IAjwilRS0V+WdnVw4mTjBAhPvb4jPOo97Yfy3PYUyx2F3newkqXOZy+zx3G/ANoa 783 ncypfMGyy76sfCWKqw4J1gVkVQLwbB6gQkXUFGYwY9sRrxbG93kQw76Flc/E/s52 784 62j4v1IM0fq0t/St+Y/+s6Lkw` + `aqt3ft1nsqWcRaVDdqvMfkzgJGXlw0bGzJG5MEQ 785 AIBq3dHRAoGBAP8OeG/DKG2Z1VmSfzuz1pas1fbZ+F7venOBrjez3sKlb3Pyl2aH 786 mt2wjaTUi5v10VrHgYtOEdqyhQeUSYydWXIBKNMag0NLLrfFUKZK+57wrHWFdFjn 787 VgpsdkLSNTOZpC8gA5OaJ+36IcOPfGqyyP9wuuRoaYnVT1KEzqLa9FEFAoGBAPaq 788 pglwhil2rxjJE4zq0afQLNpAfi7Xqcrepij+xvJIcIj7nawxXuPxqRFxONE/h3yX 789 zkybO8wLdbHX9Iw/wc1j50Uf1Z5gHdLf7/hQJoWKpz1RnkWRy6CYON8v1tpVp0tb 790 OAajR/kZnzebq2mfa7pyy5zDCX++2kp/dcFwHf31AoGAE8oupBVTZLWj7TBFuP8q 791 LkS40U92Sv9v09iDCQVmylmFvUxcXPM2m+7f/qMTNgWrucxzC7kB/6MMWVszHbrz 792 vrnCTibnemgx9sZTjKOSxHFOIEw7i85fSa3Cu0qOIDPSnmlwfZpfcMKQrhjLAYhf 793 uhooFiLX1X78iZ2OXup4PHUCgYEAsmBrm83sp1V1gAYBBlnVbXakyNv0pCk/Vz61 794 iFXeRt1NzDGxLxGw3kQnED8BaIh5kQcyn8Fud7sdzJMv/LAqlT4Ww60mzNYTGyjo 795 H3jOsqm3ESfRvduWFreeAQBWbiOczGjV1i8D4EbAFfWT+tjXjchwKBf+6Yt5zn/o 796 Bw/uEHUCgYAFs+JPOR25oRyBs7ujrMo/OY1z/eXTVVgZxY+tYGe1FJqDeFyR7ytK 797 +JBB1MuDwQKGm2wSIXdCzTNoIx2B9zTseiPTwT8G7vqNFhXoIaTBp4P2xIQb45mJ 798 7GkTsMBHwpSMOXgX9Weq3v5xOJ2WxVtjENmd6qzxcYCO5lP15O17hA== 799 -----END RSA PRIVATE KEY-----` 800 801 func assertContents(t *testing.T, path string, contents string) { 802 data, err := ioutil.ReadFile(path) 803 if err != nil { 804 t.Fatalf("err: %s", err) 805 } 806 807 if !reflect.DeepEqual(data, []byte(contents)) { 808 t.Fatalf("bad. expected:\n\n%s\n\nGot:\n\n%s", contents, string(data)) 809 } 810 } 811 812 func tempDir(t *testing.T) string { 813 dir, err := ioutil.TempDir("", "tf") 814 if err != nil { 815 t.Fatalf("err: %s", err) 816 } 817 if err := os.RemoveAll(dir); err != nil { 818 t.Fatalf("err: %s", err) 819 } 820 821 return dir 822 } 823 824 func tempTestFile(t *testing.T) string { 825 dir := tempDir(t) 826 return filepath.Join(dir, "foo") 827 }