github.com/opsmatic/godep@v0.1.5/save_test.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "io/ioutil" 7 "os" 8 "os/exec" 9 "path/filepath" 10 "reflect" 11 "strings" 12 "testing" 13 "text/template" 14 ) 15 16 // node represents a file tree or a VCS repo 17 type node struct { 18 path string // file name or commit type 19 body interface{} // file contents or commit tag 20 entries []*node // nil if the entry is a file 21 } 22 23 var ( 24 pkgtpl = template.Must(template.New("package").Parse(`package {{.Name}} 25 26 import ( 27 {{range .Imports}} {{printf "%q" .}} 28 {{end}}) 29 `)) 30 ) 31 32 func pkg(name string, pkg ...string) string { 33 v := struct { 34 Name string 35 Imports []string 36 }{name, pkg} 37 var buf bytes.Buffer 38 err := pkgtpl.Execute(&buf, v) 39 if err != nil { 40 panic(err) 41 } 42 return buf.String() 43 } 44 45 func decl(name string) string { 46 return "var " + name + " int\n" 47 } 48 49 func godeps(importpath string, keyval ...string) *Godeps { 50 g := &Godeps{ 51 ImportPath: importpath, 52 } 53 for i := 0; i < len(keyval); i += 2 { 54 g.Deps = append(g.Deps, Dependency{ 55 ImportPath: keyval[i], 56 Comment: keyval[i+1], 57 }) 58 } 59 return g 60 } 61 62 func TestSave(t *testing.T) { 63 var cases = []struct { 64 cwd string 65 args []string 66 flagR bool 67 start []*node 68 altstart []*node 69 want []*node 70 wdep Godeps 71 werr bool 72 }{ 73 { // simple case, one dependency 74 cwd: "C", 75 start: []*node{ 76 { 77 "C", 78 "", 79 []*node{ 80 {"main.go", pkg("main", "D"), nil}, 81 {"+git", "", nil}, 82 }, 83 }, 84 { 85 "D", 86 "", 87 []*node{ 88 {"main.go", pkg("D"), nil}, 89 {"+git", "D1", nil}, 90 }, 91 }, 92 }, 93 want: []*node{ 94 {"C/main.go", pkg("main", "D"), nil}, 95 {"C/Godeps/_workspace/src/D/main.go", pkg("D"), nil}, 96 }, 97 wdep: Godeps{ 98 ImportPath: "C", 99 Deps: []Dependency{ 100 {ImportPath: "D", Comment: "D1"}, 101 }, 102 }, 103 }, 104 { 105 // dependency in same repo with existing manifest 106 // see bug https://github.com/tools/godep/issues/69 107 cwd: "P", 108 args: []string{"./..."}, 109 start: []*node{ 110 { 111 "P", 112 "", 113 []*node{ 114 {"main.go", pkg("P", "P/Q"), nil}, 115 {"Q/main.go", pkg("Q"), nil}, 116 {"Godeps/Godeps.json", `{}`, nil}, 117 {"+git", "C1", nil}, 118 }, 119 }, 120 }, 121 want: []*node{ 122 {"P/main.go", pkg("P", "P/Q"), nil}, 123 {"P/Q/main.go", pkg("Q"), nil}, 124 }, 125 wdep: Godeps{ 126 ImportPath: "P", 127 Deps: []Dependency{}, 128 }, 129 }, 130 { 131 // dependency on parent directory in same repo 132 // see bug https://github.com/tools/godep/issues/70 133 cwd: "P", 134 args: []string{"./..."}, 135 start: []*node{ 136 { 137 "P", 138 "", 139 []*node{ 140 {"main.go", pkg("P"), nil}, 141 {"Q/main.go", pkg("Q", "P"), nil}, 142 {"+git", "C1", nil}, 143 }, 144 }, 145 }, 146 want: []*node{ 147 {"P/main.go", pkg("P"), nil}, 148 {"P/Q/main.go", pkg("Q", "P"), nil}, 149 }, 150 wdep: Godeps{ 151 ImportPath: "P", 152 Deps: []Dependency{}, 153 }, 154 }, 155 { // transitive dependency 156 cwd: "C", 157 start: []*node{ 158 { 159 "C", 160 "", 161 []*node{ 162 {"main.go", pkg("main", "D"), nil}, 163 {"+git", "", nil}, 164 }, 165 }, 166 { 167 "D", 168 "", 169 []*node{ 170 {"main.go", pkg("D", "T"), nil}, 171 {"+git", "D1", nil}, 172 }, 173 }, 174 { 175 "T", 176 "", 177 []*node{ 178 {"main.go", pkg("T"), nil}, 179 {"+git", "T1", nil}, 180 }, 181 }, 182 }, 183 want: []*node{ 184 {"C/main.go", pkg("main", "D"), nil}, 185 {"C/Godeps/_workspace/src/D/main.go", pkg("D", "T"), nil}, 186 {"C/Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 187 }, 188 wdep: Godeps{ 189 ImportPath: "C", 190 Deps: []Dependency{ 191 {ImportPath: "D", Comment: "D1"}, 192 {ImportPath: "T", Comment: "T1"}, 193 }, 194 }, 195 }, 196 { // two packages, one in a subdirectory 197 cwd: "C", 198 start: []*node{ 199 { 200 "C", 201 "", 202 []*node{ 203 {"main.go", pkg("main", "D", "D/P"), nil}, 204 {"+git", "", nil}, 205 }, 206 }, 207 { 208 "D", 209 "", 210 []*node{ 211 {"main.go", pkg("D"), nil}, 212 {"P/main.go", pkg("P"), nil}, 213 {"+git", "D1", nil}, 214 }, 215 }, 216 }, 217 want: []*node{ 218 {"C/main.go", pkg("main", "D", "D/P"), nil}, 219 {"C/Godeps/_workspace/src/D/main.go", pkg("D"), nil}, 220 {"C/Godeps/_workspace/src/D/P/main.go", pkg("P"), nil}, 221 }, 222 wdep: Godeps{ 223 ImportPath: "C", 224 Deps: []Dependency{ 225 {ImportPath: "D", Comment: "D1"}, 226 }, 227 }, 228 }, 229 { // repo root is not a package (no go files) 230 cwd: "C", 231 start: []*node{ 232 { 233 "C", 234 "", 235 []*node{ 236 {"main.go", pkg("main", "D/P", "D/Q"), nil}, 237 {"+git", "", nil}, 238 }, 239 }, 240 { 241 "D", 242 "", 243 []*node{ 244 {"P/main.go", pkg("P"), nil}, 245 {"Q/main.go", pkg("Q"), nil}, 246 {"+git", "D1", nil}, 247 }, 248 }, 249 }, 250 want: []*node{ 251 {"C/main.go", pkg("main", "D/P", "D/Q"), nil}, 252 {"C/Godeps/_workspace/src/D/P/main.go", pkg("P"), nil}, 253 {"C/Godeps/_workspace/src/D/Q/main.go", pkg("Q"), nil}, 254 }, 255 wdep: Godeps{ 256 ImportPath: "C", 257 Deps: []Dependency{ 258 {ImportPath: "D/P", Comment: "D1"}, 259 {ImportPath: "D/Q", Comment: "D1"}, 260 }, 261 }, 262 }, 263 { // symlink 264 cwd: "C", 265 start: []*node{ 266 { 267 "C", 268 "", 269 []*node{ 270 {"main.x", pkg("main", "D"), nil}, 271 {"main.go", "symlink:main.x", nil}, 272 {"+git", "", nil}, 273 }, 274 }, 275 { 276 "D", 277 "", 278 []*node{ 279 {"main.go", pkg("D"), nil}, 280 {"+git", "D1", nil}, 281 }, 282 }, 283 }, 284 want: []*node{ 285 {"C/main.go", pkg("main", "D"), nil}, 286 {"C/Godeps/_workspace/src/D/main.go", pkg("D"), nil}, 287 }, 288 wdep: Godeps{ 289 ImportPath: "C", 290 Deps: []Dependency{ 291 {ImportPath: "D", Comment: "D1"}, 292 }, 293 }, 294 }, 295 { // add one dependency; keep other dependency version 296 cwd: "C", 297 start: []*node{ 298 { 299 "D", 300 "", 301 []*node{ 302 {"main.go", pkg("D") + decl("D1"), nil}, 303 {"+git", "D1", nil}, 304 {"main.go", pkg("D") + decl("D2"), nil}, 305 {"+git", "D2", nil}, 306 }, 307 }, 308 { 309 "E", 310 "", 311 []*node{ 312 {"main.go", pkg("E"), nil}, 313 {"+git", "E1", nil}, 314 }, 315 }, 316 { 317 "C", 318 "", 319 []*node{ 320 {"main.go", pkg("main", "D", "E"), nil}, 321 {"Godeps/Godeps.json", godeps("C", "D", "D1"), nil}, 322 {"Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 323 {"+git", "", nil}, 324 }, 325 }, 326 }, 327 want: []*node{ 328 {"C/main.go", pkg("main", "D", "E"), nil}, 329 {"C/Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 330 {"C/Godeps/_workspace/src/E/main.go", pkg("E"), nil}, 331 }, 332 wdep: Godeps{ 333 ImportPath: "C", 334 Deps: []Dependency{ 335 {ImportPath: "D", Comment: "D1"}, 336 {ImportPath: "E", Comment: "E1"}, 337 }, 338 }, 339 }, 340 { // remove one dependency; keep other dependency version 341 cwd: "C", 342 start: []*node{ 343 { 344 "D", 345 "", 346 []*node{ 347 {"main.go", pkg("D") + decl("D1"), nil}, 348 {"+git", "D1", nil}, 349 {"main.go", pkg("D") + decl("D2"), nil}, 350 {"+git", "D2", nil}, 351 }, 352 }, 353 { 354 "E", 355 "", 356 []*node{ 357 {"main.go", pkg("E") + decl("E1"), nil}, 358 {"+git", "E1", nil}, 359 }, 360 }, 361 { 362 "C", 363 "", 364 []*node{ 365 {"main.go", pkg("main", "D"), nil}, 366 {"Godeps/Godeps.json", godeps("C", "D", "D1", "E", "E1"), nil}, 367 {"Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 368 {"Godeps/_workspace/src/E/main.go", pkg("E") + decl("E1"), nil}, 369 {"+git", "", nil}, 370 }, 371 }, 372 }, 373 want: []*node{ 374 {"C/Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 375 {"C/Godeps/_workspace/src/E/main.go", "(absent)", nil}, 376 }, 377 wdep: Godeps{ 378 ImportPath: "C", 379 Deps: []Dependency{ 380 {ImportPath: "D", Comment: "D1"}, 381 }, 382 }, 383 }, 384 { // add one dependency from same repo 385 cwd: "C", 386 start: []*node{ 387 { 388 "D", 389 "", 390 []*node{ 391 {"A/main.go", pkg("A") + decl("A1"), nil}, 392 {"B/main.go", pkg("B") + decl("B1"), nil}, 393 {"+git", "D1", nil}, 394 }, 395 }, 396 { 397 "C", 398 "", 399 []*node{ 400 {"main.go", pkg("main", "D/A", "D/B"), nil}, 401 {"Godeps/Godeps.json", godeps("C", "D/A", "D1"), nil}, 402 {"Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 403 {"+git", "", nil}, 404 }, 405 }, 406 }, 407 want: []*node{ 408 {"C/Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 409 {"C/Godeps/_workspace/src/D/B/main.go", pkg("B") + decl("B1"), nil}, 410 }, 411 wdep: Godeps{ 412 ImportPath: "C", 413 Deps: []Dependency{ 414 {ImportPath: "D/A", Comment: "D1"}, 415 {ImportPath: "D/B", Comment: "D1"}, 416 }, 417 }, 418 }, 419 { // add one dependency from same repo, require same version 420 cwd: "C", 421 start: []*node{ 422 { 423 "D", 424 "", 425 []*node{ 426 {"A/main.go", pkg("A") + decl("A1"), nil}, 427 {"B/main.go", pkg("B") + decl("B1"), nil}, 428 {"+git", "D1", nil}, 429 {"A/main.go", pkg("A") + decl("A2"), nil}, 430 {"B/main.go", pkg("B") + decl("B2"), nil}, 431 {"+git", "D2", nil}, 432 }, 433 }, 434 { 435 "C", 436 "", 437 []*node{ 438 {"main.go", pkg("main", "D/A", "D/B"), nil}, 439 {"Godeps/Godeps.json", godeps("C", "D/A", "D1"), nil}, 440 {"Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 441 {"+git", "", nil}, 442 }, 443 }, 444 }, 445 want: []*node{ 446 {"C/Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 447 }, 448 wdep: Godeps{ 449 ImportPath: "C", 450 Deps: []Dependency{ 451 {ImportPath: "D/A", Comment: "D1"}, 452 }, 453 }, 454 werr: true, 455 }, 456 { // replace dependency from same repo parent dir 457 cwd: "C", 458 start: []*node{ 459 { 460 "D", 461 "", 462 []*node{ 463 {"main.go", pkg("D") + decl("D1"), nil}, 464 {"A/main.go", pkg("A") + decl("A1"), nil}, 465 {"+git", "D1", nil}, 466 }, 467 }, 468 { 469 "C", 470 "", 471 []*node{ 472 {"main.go", pkg("main", "D"), nil}, 473 {"Godeps/Godeps.json", godeps("C", "D/A", "D1"), nil}, 474 {"Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 475 {"+git", "", nil}, 476 }, 477 }, 478 }, 479 want: []*node{ 480 {"C/Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 481 {"C/Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 482 }, 483 wdep: Godeps{ 484 ImportPath: "C", 485 Deps: []Dependency{ 486 {ImportPath: "D", Comment: "D1"}, 487 }, 488 }, 489 }, 490 { // replace dependency from same repo parent dir, require same version 491 cwd: "C", 492 start: []*node{ 493 { 494 "D", 495 "", 496 []*node{ 497 {"main.go", pkg("D") + decl("D1"), nil}, 498 {"A/main.go", pkg("A") + decl("A1"), nil}, 499 {"+git", "D1", nil}, 500 {"main.go", pkg("D") + decl("D2"), nil}, 501 {"A/main.go", pkg("A") + decl("A2"), nil}, 502 {"+git", "D2", nil}, 503 }, 504 }, 505 { 506 "C", 507 "", 508 []*node{ 509 {"main.go", pkg("main", "D"), nil}, 510 {"Godeps/Godeps.json", godeps("C", "D/A", "D1"), nil}, 511 {"Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 512 {"+git", "", nil}, 513 }, 514 }, 515 }, 516 want: []*node{ 517 {"C/Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 518 }, 519 wdep: Godeps{ 520 ImportPath: "C", 521 Deps: []Dependency{ 522 {ImportPath: "D/A", Comment: "D1"}, 523 }, 524 }, 525 werr: true, 526 }, 527 { // replace dependency from same repo child dir 528 cwd: "C", 529 start: []*node{ 530 { 531 "D", 532 "", 533 []*node{ 534 {"main.go", pkg("D") + decl("D1"), nil}, 535 {"A/main.go", pkg("A") + decl("A1"), nil}, 536 {"+git", "D1", nil}, 537 }, 538 }, 539 { 540 "C", 541 "", 542 []*node{ 543 {"main.go", pkg("main", "D/A"), nil}, 544 {"Godeps/Godeps.json", godeps("C", "D", "D1"), nil}, 545 {"Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 546 {"Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 547 {"+git", "", nil}, 548 }, 549 }, 550 }, 551 want: []*node{ 552 {"C/Godeps/_workspace/src/D/main.go", "(absent)", nil}, 553 {"C/Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 554 }, 555 wdep: Godeps{ 556 ImportPath: "C", 557 Deps: []Dependency{ 558 {ImportPath: "D/A", Comment: "D1"}, 559 }, 560 }, 561 }, 562 { // replace dependency from same repo child dir, require same version 563 cwd: "C", 564 start: []*node{ 565 { 566 "D", 567 "", 568 []*node{ 569 {"main.go", pkg("D") + decl("D1"), nil}, 570 {"A/main.go", pkg("A") + decl("A1"), nil}, 571 {"+git", "D1", nil}, 572 {"main.go", pkg("D") + decl("D2"), nil}, 573 {"A/main.go", pkg("A") + decl("A2"), nil}, 574 {"+git", "D2", nil}, 575 }, 576 }, 577 { 578 "C", 579 "", 580 []*node{ 581 {"main.go", pkg("main", "D/A"), nil}, 582 {"Godeps/Godeps.json", godeps("C", "D", "D1"), nil}, 583 {"Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 584 {"Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 585 {"+git", "", nil}, 586 }, 587 }, 588 }, 589 want: []*node{ 590 {"C/Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 591 {"C/Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 592 }, 593 wdep: Godeps{ 594 ImportPath: "C", 595 Deps: []Dependency{ 596 {ImportPath: "D", Comment: "D1"}, 597 }, 598 }, 599 werr: true, 600 }, 601 { // Bug https://github.com/tools/godep/issues/85 602 cwd: "C", 603 start: []*node{ 604 { 605 "D", 606 "", 607 []*node{ 608 {"A/main.go", pkg("A") + decl("A1"), nil}, 609 {"B/main.go", pkg("B") + decl("B1"), nil}, 610 {"+git", "D1", nil}, 611 {"A/main.go", pkg("A") + decl("A2"), nil}, 612 {"B/main.go", pkg("B") + decl("B2"), nil}, 613 {"+git", "D2", nil}, 614 }, 615 }, 616 { 617 "C", 618 "", 619 []*node{ 620 {"main.go", pkg("main", "D/A", "D/B"), nil}, 621 {"Godeps/Godeps.json", godeps("C", "D/A", "D1", "D/B", "D1"), nil}, 622 {"Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 623 {"Godeps/_workspace/src/D/B/main.go", pkg("B") + decl("B1"), nil}, 624 {"+git", "", nil}, 625 }, 626 }, 627 }, 628 want: []*node{ 629 {"C/Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 630 {"C/Godeps/_workspace/src/D/B/main.go", pkg("B") + decl("B1"), nil}, 631 }, 632 wdep: Godeps{ 633 ImportPath: "C", 634 Deps: []Dependency{ 635 {ImportPath: "D/A", Comment: "D1"}, 636 {ImportPath: "D/B", Comment: "D1"}, 637 }, 638 }, 639 }, 640 { // intermediate dependency that uses godep save -r, main -r=false 641 cwd: "C", 642 start: []*node{ 643 { 644 "C", 645 "", 646 []*node{ 647 {"main.go", pkg("main", "D"), nil}, 648 {"+git", "", nil}, 649 }, 650 }, 651 { 652 "T", 653 "", 654 []*node{ 655 {"main.go", pkg("T"), nil}, 656 {"+git", "T1", nil}, 657 }, 658 }, 659 { 660 "D", 661 "", 662 []*node{ 663 {"main.go", pkg("D", "D/Godeps/_workspace/src/T"), nil}, 664 {"Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 665 {"Godeps/Godeps.json", godeps("D", "T", "T1"), nil}, 666 {"+git", "D1", nil}, 667 }, 668 }, 669 }, 670 want: []*node{ 671 {"C/main.go", pkg("main", "D"), nil}, 672 {"C/Godeps/_workspace/src/D/main.go", pkg("D", "T"), nil}, 673 {"C/Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 674 }, 675 wdep: Godeps{ 676 ImportPath: "C", 677 Deps: []Dependency{ 678 {ImportPath: "D", Comment: "D1"}, 679 {ImportPath: "T", Comment: "T1"}, 680 }, 681 }, 682 }, 683 { // intermediate dependency that uses godep save -r, main -r too 684 cwd: "C", 685 flagR: true, 686 start: []*node{ 687 { 688 "C", 689 "", 690 []*node{ 691 {"main.go", pkg("main", "D"), nil}, 692 {"+git", "", nil}, 693 }, 694 }, 695 { 696 "T", 697 "", 698 []*node{ 699 {"main.go", pkg("T"), nil}, 700 {"+git", "T1", nil}, 701 }, 702 }, 703 { 704 "D", 705 "", 706 []*node{ 707 {"main.go", pkg("D", "D/Godeps/_workspace/src/T"), nil}, 708 {"Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 709 {"Godeps/Godeps.json", godeps("D", "T", "T1"), nil}, 710 {"+git", "D1", nil}, 711 }, 712 }, 713 }, 714 want: []*node{ 715 {"C/main.go", pkg("main", "C/Godeps/_workspace/src/D"), nil}, 716 {"C/Godeps/_workspace/src/D/main.go", pkg("D", "C/Godeps/_workspace/src/T"), nil}, 717 {"C/Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 718 }, 719 wdep: Godeps{ 720 ImportPath: "C", 721 Deps: []Dependency{ 722 {ImportPath: "D", Comment: "D1"}, 723 {ImportPath: "T", Comment: "T1"}, 724 }, 725 }, 726 }, 727 { // rewrite files under build constraints 728 cwd: "C", 729 flagR: true, 730 start: []*node{ 731 { 732 "C", 733 "", 734 []*node{ 735 {"main.go", pkg("main", "D"), nil}, 736 {"x.go", "// +build x\n\n" + pkg("main", "D"), nil}, 737 {"+git", "", nil}, 738 }, 739 }, 740 { 741 "D", 742 "", 743 []*node{ 744 {"main.go", pkg("D"), nil}, 745 {"+git", "D1", nil}, 746 }, 747 }, 748 }, 749 want: []*node{ 750 {"C/main.go", pkg("main", "C/Godeps/_workspace/src/D"), nil}, 751 {"C/x.go", "// +build x\n\n" + pkg("main", "C/Godeps/_workspace/src/D"), nil}, 752 {"C/Godeps/_workspace/src/D/main.go", pkg("D"), nil}, 753 }, 754 wdep: Godeps{ 755 ImportPath: "C", 756 Deps: []Dependency{ 757 {ImportPath: "D", Comment: "D1"}, 758 }, 759 }, 760 }, 761 { // exclude dependency subdirectories even when obtained by a rewritten import path 762 cwd: "C", 763 start: []*node{ 764 { 765 "C", 766 "", 767 []*node{ 768 {"main.go", pkg("main", "D", "T"), nil}, 769 {"+git", "", nil}, 770 }, 771 }, 772 { 773 "T", 774 "", 775 []*node{ 776 {"main.go", pkg("T"), nil}, 777 {"X/main.go", pkg("X"), nil}, 778 {"+git", "T1", nil}, 779 }, 780 }, 781 { 782 "D", 783 "", 784 []*node{ 785 {"main.go", pkg("D", "D/Godeps/_workspace/src/T/X"), nil}, 786 {"Godeps/_workspace/src/T/X/main.go", pkg("X"), nil}, 787 {"Godeps/Godeps.json", godeps("D", "T/X", "T1"), nil}, 788 {"+git", "D1", nil}, 789 }, 790 }, 791 }, 792 want: []*node{ 793 {"C/main.go", pkg("main", "D", "T"), nil}, 794 {"C/Godeps/_workspace/src/D/main.go", pkg("D", "T/X"), nil}, 795 {"C/Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 796 }, 797 wdep: Godeps{ 798 ImportPath: "C", 799 Deps: []Dependency{ 800 {ImportPath: "D", Comment: "D1"}, 801 {ImportPath: "T", Comment: "T1"}, 802 }, 803 }, 804 }, 805 { // find transitive dependencies across roots 806 cwd: "C", 807 flagR: true, 808 altstart: []*node{ 809 { 810 "T", 811 "", 812 []*node{ 813 {"main.go", pkg("T"), nil}, 814 {"+git", "T1", nil}, 815 }, 816 }, 817 }, 818 start: []*node{ 819 { 820 "C", 821 "", 822 []*node{ 823 {"main.go", pkg("main", "D"), nil}, 824 {"+git", "", nil}, 825 }, 826 }, 827 { 828 "D", 829 "", 830 []*node{ 831 {"main.go", pkg("D", "D/Godeps/_workspace/src/T"), nil}, 832 {"Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 833 {"Godeps/Godeps.json", godeps("D", "T", "T1"), nil}, 834 {"+git", "D1", nil}, 835 }, 836 }, 837 }, 838 want: []*node{ 839 {"C/main.go", pkg("main", "C/Godeps/_workspace/src/D"), nil}, 840 {"C/Godeps/_workspace/src/D/main.go", pkg("D", "C/Godeps/_workspace/src/T"), nil}, 841 {"C/Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 842 }, 843 wdep: Godeps{ 844 ImportPath: "C", 845 Deps: []Dependency{ 846 {ImportPath: "D", Comment: "D1"}, 847 {ImportPath: "T", Comment: "T1"}, 848 }, 849 }, 850 }, 851 { // pull in minimal dependencies, see https://github.com/tools/godep/issues/93 852 cwd: "C", 853 flagR: true, 854 start: []*node{ 855 { 856 "C", 857 "", 858 []*node{ 859 {"main.go", pkg("main", "D/X"), nil}, 860 {"+git", "", nil}, 861 }, 862 }, 863 { 864 "T", 865 "", 866 []*node{ 867 {"main.go", pkg("T"), nil}, 868 {"+git", "T1", nil}, 869 }, 870 }, 871 { 872 "D", 873 "", 874 []*node{ 875 {"main.go", pkg("D", "D/Godeps/_workspace/src/T"), nil}, 876 {"X/main.go", pkg("X"), nil}, 877 {"Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 878 {"Godeps/Godeps.json", godeps("D", "T", "T1"), nil}, 879 {"+git", "D1", nil}, 880 }, 881 }, 882 }, 883 want: []*node{ 884 {"C/main.go", pkg("main", "C/Godeps/_workspace/src/D/X"), nil}, 885 {"C/Godeps/_workspace/src/D/X/main.go", pkg("X"), nil}, 886 }, 887 wdep: Godeps{ 888 ImportPath: "C", 889 Deps: []Dependency{ 890 {ImportPath: "D/X", Comment: "D1"}, 891 }, 892 }, 893 }, 894 } 895 896 wd, err := os.Getwd() 897 if err != nil { 898 t.Fatal(err) 899 } 900 const scratch = "godeptest" 901 defer os.RemoveAll(scratch) 902 for _, test := range cases { 903 err = os.RemoveAll(scratch) 904 if err != nil { 905 t.Fatal(err) 906 } 907 altsrc := filepath.Join(scratch, "r2", "src") 908 if test.altstart != nil { 909 makeTree(t, &node{altsrc, "", test.altstart}, "") 910 } 911 src := filepath.Join(scratch, "r1", "src") 912 makeTree(t, &node{src, "", test.start}, altsrc) 913 914 dir := filepath.Join(wd, src, test.cwd) 915 err = os.Chdir(dir) 916 if err != nil { 917 panic(err) 918 } 919 root1 := filepath.Join(wd, scratch, "r1") 920 root2 := filepath.Join(wd, scratch, "r2") 921 err = os.Setenv("GOPATH", root1+string(os.PathListSeparator)+root2) 922 if err != nil { 923 panic(err) 924 } 925 saveR = test.flagR 926 err = save(test.args) 927 if g := err != nil; g != test.werr { 928 if err != nil { 929 t.Log(err) 930 } 931 t.Errorf("save err = %v want %v", g, test.werr) 932 } 933 err = os.Chdir(wd) 934 if err != nil { 935 panic(err) 936 } 937 938 checkTree(t, &node{src, "", test.want}) 939 940 f, err := os.Open(filepath.Join(dir, "Godeps/Godeps.json")) 941 if err != nil { 942 t.Error(err) 943 } 944 g := new(Godeps) 945 err = json.NewDecoder(f).Decode(g) 946 if err != nil { 947 t.Error(err) 948 } 949 f.Close() 950 951 if g.ImportPath != test.wdep.ImportPath { 952 t.Errorf("ImportPath = %s want %s", g.ImportPath, test.wdep.ImportPath) 953 } 954 for i := range g.Deps { 955 g.Deps[i].Rev = "" 956 } 957 if !reflect.DeepEqual(g.Deps, test.wdep.Deps) { 958 t.Errorf("Deps = %v want %v", g.Deps, test.wdep.Deps) 959 } 960 } 961 } 962 963 func makeTree(t *testing.T, tree *node, altpath string) (gopath string) { 964 walkTree(tree, tree.path, func(path string, n *node) { 965 g, isGodeps := n.body.(*Godeps) 966 body, _ := n.body.(string) 967 switch { 968 case isGodeps: 969 for i, dep := range g.Deps { 970 rel := filepath.FromSlash(dep.ImportPath) 971 dir := filepath.Join(tree.path, rel) 972 if _, err := os.Stat(dir); os.IsNotExist(err) { 973 dir = filepath.Join(altpath, rel) 974 } 975 tag := dep.Comment 976 rev := strings.TrimSpace(run(t, dir, "git", "rev-parse", tag)) 977 g.Deps[i].Rev = rev 978 } 979 os.MkdirAll(filepath.Dir(path), 0770) 980 f, err := os.Create(path) 981 if err != nil { 982 t.Errorf("makeTree: %v", err) 983 return 984 } 985 defer f.Close() 986 err = json.NewEncoder(f).Encode(g) 987 if err != nil { 988 t.Errorf("makeTree: %v", err) 989 } 990 case n.path == "+git": 991 dir := filepath.Dir(path) 992 run(t, dir, "git", "init") // repo might already exist, but ok 993 run(t, dir, "git", "add", ".") 994 run(t, dir, "git", "commit", "-m", "godep") 995 if body != "" { 996 run(t, dir, "git", "tag", body) 997 } 998 case n.entries == nil && strings.HasPrefix(body, "symlink:"): 999 target := strings.TrimPrefix(body, "symlink:") 1000 os.Symlink(target, path) 1001 case n.entries == nil && body == "(absent)": 1002 panic("is this gonna be forever") 1003 case n.entries == nil: 1004 os.MkdirAll(filepath.Dir(path), 0770) 1005 err := ioutil.WriteFile(path, []byte(body), 0660) 1006 if err != nil { 1007 t.Errorf("makeTree: %v", err) 1008 } 1009 default: 1010 os.MkdirAll(path, 0770) 1011 } 1012 }) 1013 return gopath 1014 } 1015 1016 func checkTree(t *testing.T, want *node) { 1017 walkTree(want, want.path, func(path string, n *node) { 1018 body := n.body.(string) 1019 switch { 1020 case n.path == "+git": 1021 panic("is this real life") 1022 case n.entries == nil && strings.HasPrefix(body, "symlink:"): 1023 panic("why is this happening to me") 1024 case n.entries == nil && body == "(absent)": 1025 body, err := ioutil.ReadFile(path) 1026 if !os.IsNotExist(err) { 1027 t.Errorf("checkTree: %s = %s want absent", path, string(body)) 1028 return 1029 } 1030 case n.entries == nil: 1031 gbody, err := ioutil.ReadFile(path) 1032 if err != nil { 1033 t.Errorf("checkTree: %v", err) 1034 return 1035 } 1036 if got := string(gbody); got != body { 1037 t.Errorf("%s = %s want %s", path, got, body) 1038 } 1039 default: 1040 os.MkdirAll(path, 0770) 1041 } 1042 }) 1043 } 1044 1045 func walkTree(n *node, path string, f func(path string, n *node)) { 1046 f(path, n) 1047 for _, e := range n.entries { 1048 walkTree(e, filepath.Join(path, filepath.FromSlash(e.path)), f) 1049 } 1050 } 1051 1052 func run(t *testing.T, dir, name string, args ...string) string { 1053 cmd := exec.Command(name, args...) 1054 cmd.Dir = dir 1055 cmd.Stderr = os.Stderr 1056 out, err := cmd.Output() 1057 if err != nil { 1058 panic(name + " " + strings.Join(args, " ") + ": " + err.Error()) 1059 } 1060 return string(out) 1061 }