gopkg.in/tools/godep.v38@v38.0.0-20151216225452-4154dbb67855/save_test.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "go/build" 7 "io/ioutil" 8 "math" 9 "os" 10 "os/exec" 11 "path/filepath" 12 "reflect" 13 "runtime" 14 "strings" 15 "testing" 16 "text/template" 17 ) 18 19 // node represents a file tree or a VCS repo 20 type node struct { 21 path string // file name or commit type 22 body interface{} // file contents or commit tag 23 entries []*node // nil if the entry is a file 24 } 25 26 var ( 27 pkgtpl = template.Must(template.New("package").Parse(`package {{.Name}} 28 29 import ( 30 {{range .Imports}} {{printf "%q" .}} 31 {{end}}) 32 `)) //`Hack: Fix Atom highlighting 33 34 ) 35 36 func pkg(name string, imports ...string) string { 37 v := struct { 38 Name string 39 Tags string 40 Imports []string 41 }{name, "", imports} 42 var buf bytes.Buffer 43 err := pkgtpl.Execute(&buf, v) 44 if err != nil { 45 panic(err) 46 } 47 return buf.String() 48 } 49 50 func pkgWithTags(name, tags string, imports ...string) string { 51 return "// +build " + tags + "\n\n" + pkg(name, imports...) 52 } 53 54 func pkgWithImpossibleTag(name string, imports ...string) string { 55 return pkgWithTags(name, impossibleTag(), imports...) 56 } 57 58 func impossibleTag() string { 59 return "!" + runtime.GOOS 60 } 61 62 func decl(name string) string { 63 return "var " + name + " int\n" 64 } 65 66 func setGOPATH(paths ...string) { 67 build.Default.GOPATH = strings.Join(paths, string(os.PathListSeparator)) 68 } 69 70 func clearPkgCache() { 71 pkgCache = make(map[string]*build.Package) 72 } 73 74 func godeps(importpath string, keyval ...string) *Godeps { 75 g := &Godeps{ 76 ImportPath: importpath, 77 } 78 for i := 0; i < len(keyval); i += 2 { 79 g.Deps = append(g.Deps, Dependency{ 80 ImportPath: keyval[i], 81 Comment: keyval[i+1], 82 }) 83 } 84 return g 85 } 86 87 func TestSave(t *testing.T) { 88 var cases = []struct { 89 cwd string 90 args []string 91 flagR bool 92 flagT bool 93 start []*node 94 altstart []*node 95 want []*node 96 wdep Godeps 97 werr bool 98 }{ 99 { // simple case, one dependency 100 cwd: "C", 101 start: []*node{ 102 { 103 "C", 104 "", 105 []*node{ 106 {"main.go", pkg("main", "D"), nil}, 107 {"+git", "", nil}, 108 }, 109 }, 110 { 111 "D", 112 "", 113 []*node{ 114 {"main.go", pkg("D"), nil}, 115 {"+git", "D1", nil}, 116 }, 117 }, 118 }, 119 want: []*node{ 120 {"C/main.go", pkg("main", "D"), nil}, 121 {"C/Godeps/_workspace/src/D/main.go", pkg("D"), nil}, 122 }, 123 wdep: Godeps{ 124 ImportPath: "C", 125 Deps: []Dependency{ 126 {ImportPath: "D", Comment: "D1"}, 127 }, 128 }, 129 }, 130 { // strip import comment 131 cwd: "C", 132 start: []*node{ 133 { 134 "C", 135 "", 136 []*node{ 137 {"main.go", pkg("main", "D"), nil}, 138 {"+git", "", nil}, 139 }, 140 }, 141 { 142 "D", 143 "", 144 []*node{ 145 {"main.go", `package D // import "D"`, nil}, 146 {"+git", "D1", nil}, 147 }, 148 }, 149 }, 150 want: []*node{ 151 {"C/main.go", pkg("main", "D"), nil}, 152 {"C/Godeps/_workspace/src/D/main.go", "package D\n", nil}, 153 }, 154 wdep: Godeps{ 155 ImportPath: "C", 156 Deps: []Dependency{ 157 {ImportPath: "D", Comment: "D1"}, 158 }, 159 }, 160 }, 161 { 162 // dependency in same repo with existing manifest 163 // see bug https://github.com/tools/godep/issues/69 164 cwd: "P", 165 args: []string{"./..."}, 166 start: []*node{ 167 { 168 "P", 169 "", 170 []*node{ 171 {"main.go", pkg("P", "P/Q"), nil}, 172 {"Q/main.go", pkg("Q"), nil}, 173 {"Godeps/Godeps.json", `{}`, nil}, 174 {"+git", "C1", nil}, 175 }, 176 }, 177 }, 178 want: []*node{ 179 {"P/main.go", pkg("P", "P/Q"), nil}, 180 {"P/Q/main.go", pkg("Q"), nil}, 181 }, 182 wdep: Godeps{ 183 ImportPath: "P", 184 Deps: []Dependency{}, 185 }, 186 }, 187 { 188 // dependency on parent directory in same repo 189 // see bug https://github.com/tools/godep/issues/70 190 cwd: "P", 191 args: []string{"./..."}, 192 start: []*node{ 193 { 194 "P", 195 "", 196 []*node{ 197 {"main.go", pkg("P"), nil}, 198 {"Q/main.go", pkg("Q", "P"), nil}, 199 {"+git", "C1", nil}, 200 }, 201 }, 202 }, 203 want: []*node{ 204 {"P/main.go", pkg("P"), nil}, 205 {"P/Q/main.go", pkg("Q", "P"), nil}, 206 }, 207 wdep: Godeps{ 208 ImportPath: "P", 209 Deps: []Dependency{}, 210 }, 211 }, 212 { // transitive dependency 213 cwd: "C", 214 start: []*node{ 215 { 216 "C", 217 "", 218 []*node{ 219 {"main.go", pkg("main", "D"), nil}, 220 {"+git", "", nil}, 221 }, 222 }, 223 { 224 "D", 225 "", 226 []*node{ 227 {"main.go", pkg("D", "T"), nil}, 228 {"+git", "D1", nil}, 229 }, 230 }, 231 { 232 "T", 233 "", 234 []*node{ 235 {"main.go", pkg("T"), nil}, 236 {"+git", "T1", nil}, 237 }, 238 }, 239 }, 240 want: []*node{ 241 {"C/main.go", pkg("main", "D"), nil}, 242 {"C/Godeps/_workspace/src/D/main.go", pkg("D", "T"), nil}, 243 {"C/Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 244 }, 245 wdep: Godeps{ 246 ImportPath: "C", 247 Deps: []Dependency{ 248 {ImportPath: "D", Comment: "D1"}, 249 {ImportPath: "T", Comment: "T1"}, 250 }, 251 }, 252 }, 253 { // two packages, one in a subdirectory 254 cwd: "C", 255 start: []*node{ 256 { 257 "C", 258 "", 259 []*node{ 260 {"main.go", pkg("main", "D", "D/P"), nil}, 261 {"+git", "", nil}, 262 }, 263 }, 264 { 265 "D", 266 "", 267 []*node{ 268 {"main.go", pkg("D"), nil}, 269 {"P/main.go", pkg("P"), nil}, 270 {"+git", "D1", nil}, 271 }, 272 }, 273 }, 274 want: []*node{ 275 {"C/main.go", pkg("main", "D", "D/P"), nil}, 276 {"C/Godeps/_workspace/src/D/main.go", pkg("D"), nil}, 277 {"C/Godeps/_workspace/src/D/P/main.go", pkg("P"), nil}, 278 }, 279 wdep: Godeps{ 280 ImportPath: "C", 281 Deps: []Dependency{ 282 {ImportPath: "D", Comment: "D1"}, 283 }, 284 }, 285 }, 286 { // repo root is not a package (no go files) 287 cwd: "C", 288 start: []*node{ 289 { 290 "C", 291 "", 292 []*node{ 293 {"main.go", pkg("main", "D/P", "D/Q"), nil}, 294 {"+git", "", nil}, 295 }, 296 }, 297 { 298 "D", 299 "", 300 []*node{ 301 {"P/main.go", pkg("P"), nil}, 302 {"Q/main.go", pkg("Q"), nil}, 303 {"+git", "D1", nil}, 304 }, 305 }, 306 }, 307 want: []*node{ 308 {"C/main.go", pkg("main", "D/P", "D/Q"), nil}, 309 {"C/Godeps/_workspace/src/D/P/main.go", pkg("P"), nil}, 310 {"C/Godeps/_workspace/src/D/Q/main.go", pkg("Q"), nil}, 311 }, 312 wdep: Godeps{ 313 ImportPath: "C", 314 Deps: []Dependency{ 315 {ImportPath: "D/P", Comment: "D1"}, 316 {ImportPath: "D/Q", Comment: "D1"}, 317 }, 318 }, 319 }, 320 { // symlink 321 cwd: "C", 322 start: []*node{ 323 { 324 "C", 325 "", 326 []*node{ 327 {"main.x", pkg("main", "D"), nil}, 328 {"main.go", "symlink:main.x", nil}, 329 {"+git", "", nil}, 330 }, 331 }, 332 { 333 "D", 334 "", 335 []*node{ 336 {"main.go", pkg("D"), nil}, 337 {"+git", "D1", nil}, 338 }, 339 }, 340 }, 341 want: []*node{ 342 {"C/main.go", pkg("main", "D"), nil}, 343 {"C/Godeps/_workspace/src/D/main.go", pkg("D"), nil}, 344 }, 345 wdep: Godeps{ 346 ImportPath: "C", 347 Deps: []Dependency{ 348 {ImportPath: "D", Comment: "D1"}, 349 }, 350 }, 351 }, 352 { // add one dependency; keep other dependency version 353 cwd: "C", 354 start: []*node{ 355 { 356 "D", 357 "", 358 []*node{ 359 {"main.go", pkg("D") + decl("D1"), nil}, 360 {"+git", "D1", nil}, 361 {"main.go", pkg("D") + decl("D2"), nil}, 362 {"+git", "D2", nil}, 363 }, 364 }, 365 { 366 "E", 367 "", 368 []*node{ 369 {"main.go", pkg("E"), nil}, 370 {"+git", "E1", nil}, 371 }, 372 }, 373 { 374 "C", 375 "", 376 []*node{ 377 {"main.go", pkg("main", "D", "E"), nil}, 378 {"Godeps/Godeps.json", godeps("C", "D", "D1"), nil}, 379 {"Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 380 {"+git", "", nil}, 381 }, 382 }, 383 }, 384 want: []*node{ 385 {"C/main.go", pkg("main", "D", "E"), nil}, 386 {"C/Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 387 {"C/Godeps/_workspace/src/E/main.go", pkg("E"), nil}, 388 }, 389 wdep: Godeps{ 390 ImportPath: "C", 391 Deps: []Dependency{ 392 {ImportPath: "D", Comment: "D1"}, 393 {ImportPath: "E", Comment: "E1"}, 394 }, 395 }, 396 }, 397 { // remove one dependency; keep other dependency version 398 cwd: "C", 399 start: []*node{ 400 { 401 "D", 402 "", 403 []*node{ 404 {"main.go", pkg("D") + decl("D1"), nil}, 405 {"+git", "D1", nil}, 406 {"main.go", pkg("D") + decl("D2"), nil}, 407 {"+git", "D2", nil}, 408 }, 409 }, 410 { 411 "E", 412 "", 413 []*node{ 414 {"main.go", pkg("E") + decl("E1"), nil}, 415 {"+git", "E1", nil}, 416 }, 417 }, 418 { 419 "C", 420 "", 421 []*node{ 422 {"main.go", pkg("main", "D"), nil}, 423 {"Godeps/Godeps.json", godeps("C", "D", "D1", "E", "E1"), nil}, 424 {"Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 425 {"Godeps/_workspace/src/E/main.go", pkg("E") + decl("E1"), nil}, 426 {"+git", "", nil}, 427 }, 428 }, 429 }, 430 want: []*node{ 431 {"C/Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 432 {"C/Godeps/_workspace/src/E/main.go", "(absent)", nil}, 433 }, 434 wdep: Godeps{ 435 ImportPath: "C", 436 Deps: []Dependency{ 437 {ImportPath: "D", Comment: "D1"}, 438 }, 439 }, 440 }, 441 { // add one dependency from same repo 442 cwd: "C", 443 start: []*node{ 444 { 445 "D", 446 "", 447 []*node{ 448 {"A/main.go", pkg("A") + decl("A1"), nil}, 449 {"B/main.go", pkg("B") + decl("B1"), nil}, 450 {"+git", "D1", nil}, 451 }, 452 }, 453 { 454 "C", 455 "", 456 []*node{ 457 {"main.go", pkg("main", "D/A", "D/B"), nil}, 458 {"Godeps/Godeps.json", godeps("C", "D/A", "D1"), nil}, 459 {"Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 460 {"+git", "", nil}, 461 }, 462 }, 463 }, 464 want: []*node{ 465 {"C/Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 466 {"C/Godeps/_workspace/src/D/B/main.go", pkg("B") + decl("B1"), nil}, 467 }, 468 wdep: Godeps{ 469 ImportPath: "C", 470 Deps: []Dependency{ 471 {ImportPath: "D/A", Comment: "D1"}, 472 {ImportPath: "D/B", Comment: "D1"}, 473 }, 474 }, 475 }, 476 { // add one dependency from same repo, require same version 477 cwd: "C", 478 start: []*node{ 479 { 480 "D", 481 "", 482 []*node{ 483 {"A/main.go", pkg("A") + decl("A1"), nil}, 484 {"B/main.go", pkg("B") + decl("B1"), nil}, 485 {"+git", "D1", nil}, 486 {"A/main.go", pkg("A") + decl("A2"), nil}, 487 {"B/main.go", pkg("B") + decl("B2"), nil}, 488 {"+git", "D2", nil}, 489 }, 490 }, 491 { 492 "C", 493 "", 494 []*node{ 495 {"main.go", pkg("main", "D/A", "D/B"), nil}, 496 {"Godeps/Godeps.json", godeps("C", "D/A", "D1"), nil}, 497 {"Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 498 {"+git", "", nil}, 499 }, 500 }, 501 }, 502 want: []*node{ 503 {"C/Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 504 }, 505 wdep: Godeps{ 506 ImportPath: "C", 507 Deps: []Dependency{ 508 {ImportPath: "D/A", Comment: "D1"}, 509 }, 510 }, 511 werr: true, 512 }, 513 { // replace dependency from same repo parent dir 514 cwd: "C", 515 start: []*node{ 516 { 517 "D", 518 "", 519 []*node{ 520 {"main.go", pkg("D") + decl("D1"), nil}, 521 {"A/main.go", pkg("A") + decl("A1"), nil}, 522 {"+git", "D1", nil}, 523 }, 524 }, 525 { 526 "C", 527 "", 528 []*node{ 529 {"main.go", pkg("main", "D"), nil}, 530 {"Godeps/Godeps.json", godeps("C", "D/A", "D1"), nil}, 531 {"Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 532 {"+git", "", nil}, 533 }, 534 }, 535 }, 536 want: []*node{ 537 {"C/Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 538 {"C/Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 539 }, 540 wdep: Godeps{ 541 ImportPath: "C", 542 Deps: []Dependency{ 543 {ImportPath: "D", Comment: "D1"}, 544 }, 545 }, 546 }, 547 { // replace dependency from same repo parent dir, require same version 548 cwd: "C", 549 start: []*node{ 550 { 551 "D", 552 "", 553 []*node{ 554 {"main.go", pkg("D") + decl("D1"), nil}, 555 {"A/main.go", pkg("A") + decl("A1"), nil}, 556 {"+git", "D1", nil}, 557 {"main.go", pkg("D") + decl("D2"), nil}, 558 {"A/main.go", pkg("A") + decl("A2"), nil}, 559 {"+git", "D2", nil}, 560 }, 561 }, 562 { 563 "C", 564 "", 565 []*node{ 566 {"main.go", pkg("main", "D"), nil}, 567 {"Godeps/Godeps.json", godeps("C", "D/A", "D1"), nil}, 568 {"Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 569 {"+git", "", nil}, 570 }, 571 }, 572 }, 573 want: []*node{ 574 {"C/Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 575 }, 576 wdep: Godeps{ 577 ImportPath: "C", 578 Deps: []Dependency{ 579 {ImportPath: "D/A", Comment: "D1"}, 580 }, 581 }, 582 werr: true, 583 }, 584 { // replace dependency from same repo child dir 585 cwd: "C", 586 start: []*node{ 587 { 588 "D", 589 "", 590 []*node{ 591 {"main.go", pkg("D") + decl("D1"), nil}, 592 {"A/main.go", pkg("A") + decl("A1"), nil}, 593 {"+git", "D1", nil}, 594 }, 595 }, 596 { 597 "C", 598 "", 599 []*node{ 600 {"main.go", pkg("main", "D/A"), nil}, 601 {"Godeps/Godeps.json", godeps("C", "D", "D1"), nil}, 602 {"Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 603 {"Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 604 {"+git", "", nil}, 605 }, 606 }, 607 }, 608 want: []*node{ 609 {"C/Godeps/_workspace/src/D/main.go", "(absent)", nil}, 610 {"C/Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 611 }, 612 wdep: Godeps{ 613 ImportPath: "C", 614 Deps: []Dependency{ 615 {ImportPath: "D/A", Comment: "D1"}, 616 }, 617 }, 618 }, 619 { // replace dependency from same repo child dir, require same version 620 cwd: "C", 621 start: []*node{ 622 { 623 "D", 624 "", 625 []*node{ 626 {"main.go", pkg("D") + decl("D1"), nil}, 627 {"A/main.go", pkg("A") + decl("A1"), nil}, 628 {"+git", "D1", nil}, 629 {"main.go", pkg("D") + decl("D2"), nil}, 630 {"A/main.go", pkg("A") + decl("A2"), nil}, 631 {"+git", "D2", nil}, 632 }, 633 }, 634 { 635 "C", 636 "", 637 []*node{ 638 {"main.go", pkg("main", "D/A"), nil}, 639 {"Godeps/Godeps.json", godeps("C", "D", "D1"), nil}, 640 {"Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 641 {"Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 642 {"+git", "", nil}, 643 }, 644 }, 645 }, 646 want: []*node{ 647 {"C/Godeps/_workspace/src/D/main.go", pkg("D") + decl("D1"), nil}, 648 {"C/Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 649 }, 650 wdep: Godeps{ 651 ImportPath: "C", 652 Deps: []Dependency{ 653 {ImportPath: "D", Comment: "D1"}, 654 }, 655 }, 656 werr: true, 657 }, 658 { // Bug https://github.com/tools/godep/issues/85 659 cwd: "C", 660 start: []*node{ 661 { 662 "D", 663 "", 664 []*node{ 665 {"A/main.go", pkg("A") + decl("A1"), nil}, 666 {"B/main.go", pkg("B") + decl("B1"), nil}, 667 {"+git", "D1", nil}, 668 {"A/main.go", pkg("A") + decl("A2"), nil}, 669 {"B/main.go", pkg("B") + decl("B2"), nil}, 670 {"+git", "D2", nil}, 671 }, 672 }, 673 { 674 "C", 675 "", 676 []*node{ 677 {"main.go", pkg("main", "D/A", "D/B"), nil}, 678 {"Godeps/Godeps.json", godeps("C", "D/A", "D1", "D/B", "D1"), nil}, 679 {"Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 680 {"Godeps/_workspace/src/D/B/main.go", pkg("B") + decl("B1"), nil}, 681 {"+git", "", nil}, 682 }, 683 }, 684 }, 685 want: []*node{ 686 {"C/Godeps/_workspace/src/D/A/main.go", pkg("A") + decl("A1"), nil}, 687 {"C/Godeps/_workspace/src/D/B/main.go", pkg("B") + decl("B1"), nil}, 688 }, 689 wdep: Godeps{ 690 ImportPath: "C", 691 Deps: []Dependency{ 692 {ImportPath: "D/A", Comment: "D1"}, 693 {ImportPath: "D/B", Comment: "D1"}, 694 }, 695 }, 696 }, 697 { // intermediate dependency that uses godep save -r, main -r=false 698 cwd: "C", 699 start: []*node{ 700 { 701 "C", 702 "", 703 []*node{ 704 {"main.go", pkg("main", "D"), nil}, 705 {"+git", "", nil}, 706 }, 707 }, 708 { 709 "T", 710 "", 711 []*node{ 712 {"main.go", pkg("T"), nil}, 713 {"+git", "T1", nil}, 714 }, 715 }, 716 { 717 "D", 718 "", 719 []*node{ 720 {"main.go", pkg("D", "D/Godeps/_workspace/src/T"), nil}, 721 {"Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 722 {"Godeps/Godeps.json", godeps("D", "T", "T1"), nil}, 723 {"+git", "D1", nil}, 724 }, 725 }, 726 }, 727 want: []*node{ 728 {"C/main.go", pkg("main", "D"), nil}, 729 {"C/Godeps/_workspace/src/D/main.go", pkg("D", "T"), nil}, 730 {"C/Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 731 }, 732 wdep: Godeps{ 733 ImportPath: "C", 734 Deps: []Dependency{ 735 {ImportPath: "D", Comment: "D1"}, 736 {ImportPath: "T", Comment: "T1"}, 737 }, 738 }, 739 }, 740 { // intermediate dependency that uses godep save -r, main -r too 741 cwd: "C", 742 flagR: true, 743 start: []*node{ 744 { 745 "C", 746 "", 747 []*node{ 748 {"main.go", pkg("main", "D"), nil}, 749 {"+git", "", nil}, 750 }, 751 }, 752 { 753 "T", 754 "", 755 []*node{ 756 {"main.go", pkg("T"), nil}, 757 {"+git", "T1", nil}, 758 }, 759 }, 760 { 761 "D", 762 "", 763 []*node{ 764 {"main.go", pkg("D", "D/Godeps/_workspace/src/T"), nil}, 765 {"Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 766 {"Godeps/Godeps.json", godeps("D", "T", "T1"), nil}, 767 {"+git", "D1", nil}, 768 }, 769 }, 770 }, 771 want: []*node{ 772 {"C/main.go", pkg("main", "C/Godeps/_workspace/src/D"), nil}, 773 {"C/Godeps/_workspace/src/D/main.go", pkg("D", "C/Godeps/_workspace/src/T"), nil}, 774 {"C/Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 775 }, 776 wdep: Godeps{ 777 ImportPath: "C", 778 Deps: []Dependency{ 779 {ImportPath: "D", Comment: "D1"}, 780 {ImportPath: "T", Comment: "T1"}, 781 }, 782 }, 783 }, 784 { // rewrite files under build constraints 785 cwd: "C", 786 flagR: true, 787 start: []*node{ 788 { 789 "C", 790 "", 791 []*node{ 792 {"main.go", pkg("main", "D"), nil}, 793 {"x.go", "// +build x\n\n" + pkg("main", "D"), nil}, 794 {"+git", "", nil}, 795 }, 796 }, 797 { 798 "D", 799 "", 800 []*node{ 801 {"main.go", pkg("D"), nil}, 802 {"+git", "D1", nil}, 803 }, 804 }, 805 }, 806 want: []*node{ 807 {"C/main.go", pkg("main", "C/Godeps/_workspace/src/D"), nil}, 808 {"C/x.go", "// +build x\n\n" + pkg("main", "C/Godeps/_workspace/src/D"), nil}, 809 {"C/Godeps/_workspace/src/D/main.go", pkg("D"), nil}, 810 }, 811 wdep: Godeps{ 812 ImportPath: "C", 813 Deps: []Dependency{ 814 {ImportPath: "D", Comment: "D1"}, 815 }, 816 }, 817 }, 818 { // exclude dependency subdirectories even when obtained by a rewritten import path 819 cwd: "C", 820 start: []*node{ 821 { 822 "C", 823 "", 824 []*node{ 825 {"main.go", pkg("main", "D", "T"), nil}, 826 {"+git", "", nil}, 827 }, 828 }, 829 { 830 "T", 831 "", 832 []*node{ 833 {"main.go", pkg("T"), nil}, 834 {"X/main.go", pkg("X"), nil}, 835 {"+git", "T1", nil}, 836 }, 837 }, 838 { 839 "D", 840 "", 841 []*node{ 842 {"main.go", pkg("D", "D/Godeps/_workspace/src/T/X"), nil}, 843 {"Godeps/_workspace/src/T/X/main.go", pkg("X"), nil}, 844 {"Godeps/Godeps.json", godeps("D", "T/X", "T1"), nil}, 845 {"+git", "D1", nil}, 846 }, 847 }, 848 }, 849 want: []*node{ 850 {"C/main.go", pkg("main", "D", "T"), nil}, 851 {"C/Godeps/_workspace/src/D/main.go", pkg("D", "T/X"), nil}, 852 {"C/Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 853 }, 854 wdep: Godeps{ 855 ImportPath: "C", 856 Deps: []Dependency{ 857 {ImportPath: "D", Comment: "D1"}, 858 {ImportPath: "T", Comment: "T1"}, 859 }, 860 }, 861 }, 862 { // find transitive dependencies across roots 863 cwd: "C", 864 flagR: true, 865 altstart: []*node{ 866 { 867 "T", 868 "", 869 []*node{ 870 {"main.go", pkg("T"), nil}, 871 {"+git", "T1", nil}, 872 }, 873 }, 874 }, 875 start: []*node{ 876 { 877 "C", 878 "", 879 []*node{ 880 {"main.go", pkg("main", "D"), nil}, 881 {"+git", "", nil}, 882 }, 883 }, 884 { 885 "D", 886 "", 887 []*node{ 888 {"main.go", pkg("D", "D/Godeps/_workspace/src/T"), nil}, 889 {"Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 890 {"Godeps/Godeps.json", godeps("D", "T", "T1"), nil}, 891 {"+git", "D1", nil}, 892 }, 893 }, 894 }, 895 want: []*node{ 896 {"C/main.go", pkg("main", "C/Godeps/_workspace/src/D"), nil}, 897 {"C/Godeps/_workspace/src/D/main.go", pkg("D", "C/Godeps/_workspace/src/T"), nil}, 898 {"C/Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 899 }, 900 wdep: Godeps{ 901 ImportPath: "C", 902 Deps: []Dependency{ 903 {ImportPath: "D", Comment: "D1"}, 904 {ImportPath: "T", Comment: "T1"}, 905 }, 906 }, 907 }, 908 { // pull in minimal dependencies, see https://github.com/tools/godep/issues/93 909 cwd: "C", 910 flagR: true, 911 start: []*node{ 912 { 913 "C", 914 "", 915 []*node{ 916 {"main.go", pkg("main", "D/X"), nil}, 917 {"+git", "", nil}, 918 }, 919 }, 920 { 921 "T", 922 "", 923 []*node{ 924 {"main.go", pkg("T"), nil}, 925 {"+git", "T1", nil}, 926 }, 927 }, 928 { 929 "D", 930 "", 931 []*node{ 932 {"main.go", pkg("D", "D/Godeps/_workspace/src/T"), nil}, 933 {"X/main.go", pkg("X"), nil}, 934 {"Godeps/_workspace/src/T/main.go", pkg("T"), nil}, 935 {"Godeps/Godeps.json", godeps("D", "T", "T1"), nil}, 936 {"+git", "D1", nil}, 937 }, 938 }, 939 }, 940 want: []*node{ 941 {"C/main.go", pkg("main", "C/Godeps/_workspace/src/D/X"), nil}, 942 {"C/Godeps/_workspace/src/D/X/main.go", pkg("X"), nil}, 943 }, 944 wdep: Godeps{ 945 ImportPath: "C", 946 Deps: []Dependency{ 947 {ImportPath: "D/X", Comment: "D1"}, 948 }, 949 }, 950 }, 951 { // don't require packages contained in dest to be in VCS 952 cwd: "C", 953 flagR: true, 954 start: []*node{ 955 { 956 "C", 957 "", 958 []*node{ 959 {"main.go", pkg("main"), nil}, 960 }, 961 }, 962 }, 963 want: []*node{ 964 {"C/main.go", pkg("main"), nil}, 965 }, 966 wdep: Godeps{ 967 ImportPath: "C", 968 Deps: []Dependency{}, 969 }, 970 }, 971 { // include command line packages in the set to be copied 972 cwd: "C", 973 args: []string{"P"}, 974 flagR: true, 975 start: []*node{ 976 { 977 "C", 978 "", 979 []*node{ 980 {"main.go", pkg("main"), nil}, 981 }, 982 }, 983 { 984 "P", 985 "", 986 []*node{ 987 {"main.go", pkg("P"), nil}, 988 {"+git", "P1", nil}, 989 }, 990 }, 991 }, 992 want: []*node{ 993 {"C/main.go", pkg("main"), nil}, 994 {"C/Godeps/_workspace/src/P/main.go", pkg("P"), nil}, 995 }, 996 wdep: Godeps{ 997 ImportPath: "C", 998 Deps: []Dependency{ 999 {ImportPath: "P", Comment: "P1"}, 1000 }, 1001 }, 1002 }, 1003 { // don't copy untracked files in the source directory 1004 cwd: "C", 1005 start: []*node{ 1006 { 1007 "C", 1008 "", 1009 []*node{ 1010 {"main.go", pkg("main", "D"), nil}, 1011 {"+git", "", nil}, 1012 }, 1013 }, 1014 { 1015 "D", 1016 "", 1017 []*node{ 1018 {"main.go", pkg("D"), nil}, 1019 {"+git", "D1", nil}, 1020 {"untracked", "garbage", nil}, 1021 }, 1022 }, 1023 }, 1024 want: []*node{ 1025 {"C/main.go", pkg("main", "D"), nil}, 1026 {"C/Godeps/_workspace/src/D/main.go", pkg("D"), nil}, 1027 {"C/Godeps/_workspace/src/D/untracked", "(absent)", nil}, 1028 }, 1029 wdep: Godeps{ 1030 ImportPath: "C", 1031 Deps: []Dependency{ 1032 {ImportPath: "D", Comment: "D1"}, 1033 }, 1034 }, 1035 }, 1036 { // don't copy _test.go files 1037 cwd: "C", 1038 start: []*node{ 1039 { 1040 "C", 1041 "", 1042 []*node{ 1043 {"main.go", pkg("main", "D"), nil}, 1044 {"+git", "", nil}, 1045 }, 1046 }, 1047 { 1048 "D", 1049 "", 1050 []*node{ 1051 {"main.go", pkg("D"), nil}, 1052 {"main_test.go", pkg("D"), nil}, 1053 {"+git", "D1", nil}, 1054 }, 1055 }, 1056 }, 1057 want: []*node{ 1058 {"C/main.go", pkg("main", "D"), nil}, 1059 {"C/Godeps/_workspace/src/D/main.go", pkg("D"), nil}, 1060 }, 1061 wdep: Godeps{ 1062 ImportPath: "C", 1063 Deps: []Dependency{ 1064 {ImportPath: "D", Comment: "D1"}, 1065 }, 1066 }, 1067 }, 1068 { // do copy _test.go files 1069 cwd: "C", 1070 flagT: true, 1071 start: []*node{ 1072 { 1073 "C", 1074 "", 1075 []*node{ 1076 {"main.go", pkg("main", "D"), nil}, 1077 {"+git", "", nil}, 1078 }, 1079 }, 1080 { 1081 "D", 1082 "", 1083 []*node{ 1084 {"main.go", pkg("D"), nil}, 1085 {"main_test.go", pkg("D"), nil}, 1086 {"+git", "D1", nil}, 1087 }, 1088 }, 1089 }, 1090 want: []*node{ 1091 {"C/main.go", pkg("main", "D"), nil}, 1092 {"C/Godeps/_workspace/src/D/main.go", pkg("D"), nil}, 1093 {"C/Godeps/_workspace/src/D/main_test.go", pkg("D"), nil}, 1094 }, 1095 wdep: Godeps{ 1096 ImportPath: "C", 1097 Deps: []Dependency{ 1098 {ImportPath: "D", Comment: "D1"}, 1099 }, 1100 }, 1101 }, 1102 { // Copy legal files in parent and dependency directory 1103 cwd: "C", 1104 start: []*node{ 1105 { 1106 "C", 1107 "", 1108 []*node{ 1109 {"main.go", pkg("main", "D/P", "D/Q"), nil}, 1110 {"+git", "", nil}, 1111 }, 1112 }, 1113 { 1114 "D", 1115 "", 1116 []*node{ 1117 {"LICENSE", pkg("D"), nil}, 1118 {"P/main.go", pkg("P"), nil}, 1119 {"P/LICENSE", pkg("P"), nil}, 1120 {"Godeps/_workspace/src/E/LICENSE", pkg("E"), nil}, 1121 {"Godeps/_workspace/src/E/main.go", pkg("E"), nil}, 1122 {"Q/main.go", pkg("Q"), nil}, 1123 {"+git", "D1", nil}, 1124 }, 1125 }, 1126 }, 1127 want: []*node{ 1128 {"C/main.go", pkg("main", "D/P", "D/Q"), nil}, 1129 {"C/Godeps/_workspace/src/D/LICENSE", pkg("D"), nil}, 1130 {"C/Godeps/_workspace/src/D/P/main.go", pkg("P"), nil}, 1131 {"C/Godeps/_workspace/src/D/P/LICENSE", pkg("P"), nil}, 1132 {"C/Godeps/_workspace/src/D/Q/main.go", pkg("Q"), nil}, 1133 {"C/Godeps/_workspace/src/D/Godeps/_workspace/src/E/LICENSE", "(absent)", nil}, 1134 }, 1135 wdep: Godeps{ 1136 ImportPath: "C", 1137 Deps: []Dependency{ 1138 {ImportPath: "D/P", Comment: "D1"}, 1139 {ImportPath: "D/Q", Comment: "D1"}, 1140 }, 1141 }, 1142 }, 1143 { // two packages, one in a subdirectory that's included only on other OS 1144 cwd: "C", 1145 start: []*node{ 1146 { 1147 "C", 1148 "", 1149 []*node{ 1150 {"main.go", pkg("main", "D"), nil}, 1151 {"+git", "", nil}, 1152 }, 1153 }, 1154 { 1155 "D", 1156 "", 1157 []*node{ 1158 {"main.go", pkgWithImpossibleTag("D", "D/P"), nil}, 1159 {"P/main.go", pkg("P"), nil}, 1160 {"+git", "D1", nil}, 1161 }, 1162 }, 1163 }, 1164 want: []*node{ 1165 {"C/main.go", pkg("main", "D"), nil}, 1166 {"C/Godeps/_workspace/src/D/main.go", pkgWithImpossibleTag("D", "D/P"), nil}, 1167 {"C/Godeps/_workspace/src/D/P/main.go", pkg("P"), nil}, 1168 }, 1169 wdep: Godeps{ 1170 ImportPath: "C", 1171 Deps: []Dependency{ 1172 {ImportPath: "D", Comment: "D1"}, 1173 }, 1174 }, 1175 }, 1176 { // build +ignore: #345, #348 1177 cwd: "C", 1178 start: []*node{ 1179 { 1180 "C", 1181 "", 1182 []*node{ 1183 {"main.go", pkg("main", "D"), nil}, 1184 {"+git", "", nil}, 1185 }, 1186 }, 1187 { 1188 "D", 1189 "", 1190 []*node{ 1191 {"main.go", pkg("D"), nil}, 1192 {"ignore.go", pkgWithTags("M", "ignore"), nil}, 1193 {"+git", "D1", nil}, 1194 }, 1195 }, 1196 }, 1197 want: []*node{ 1198 {"C/main.go", pkg("main", "D"), nil}, 1199 {"C/Godeps/_workspace/src/D/main.go", pkg("D"), nil}, 1200 {"C/Godeps/_workspace/src/D/ignore.go", pkgWithTags("M", "ignore"), nil}, 1201 }, 1202 wdep: Godeps{ 1203 ImportPath: "C", 1204 Deps: []Dependency{ 1205 {ImportPath: "D", Comment: "D1"}, 1206 }, 1207 }, 1208 }, 1209 { // No buildable . #346 1210 cwd: "C", 1211 args: []string{"./..."}, 1212 start: []*node{ 1213 { 1214 "C", 1215 "", 1216 []*node{ 1217 {"sub/main.go", pkg("main"), nil}, 1218 {"+git", "C", nil}, 1219 }, 1220 }, 1221 }, 1222 want: []*node{ 1223 {"C/sub/main.go", pkg("main"), nil}, 1224 }, 1225 wdep: Godeps{ 1226 ImportPath: "C", 1227 Deps: []Dependency{}, 1228 Packages: []string{"./..."}, 1229 }, 1230 }, 1231 { // ignore `// +build appengine` as well for now: #353 1232 cwd: "C", 1233 start: []*node{ 1234 { 1235 "C", 1236 "", 1237 []*node{ 1238 {"main.go", pkg("main", "D"), nil}, 1239 {"+git", "", nil}, 1240 }, 1241 }, 1242 { 1243 "D", 1244 "", 1245 []*node{ 1246 {"main.go", pkg("D"), nil}, 1247 {"ignore.go", pkgWithTags("M", "appengine"), nil}, 1248 {"+git", "D1", nil}, 1249 }, 1250 }, 1251 }, 1252 want: []*node{ 1253 {"C/main.go", pkg("main", "D"), nil}, 1254 {"C/Godeps/_workspace/src/D/main.go", pkg("D"), nil}, 1255 {"C/Godeps/_workspace/src/D/ignore.go", pkgWithTags("M", "appengine"), nil}, 1256 }, 1257 wdep: Godeps{ 1258 ImportPath: "C", 1259 Deps: []Dependency{ 1260 {ImportPath: "D", Comment: "D1"}, 1261 }, 1262 }, 1263 }, 1264 } 1265 1266 wd, err := os.Getwd() 1267 if err != nil { 1268 t.Fatal(err) 1269 } 1270 const scratch = "godeptest" 1271 defer os.RemoveAll(scratch) 1272 for pos, test := range cases { 1273 clearPkgCache() 1274 err = os.RemoveAll(scratch) 1275 if err != nil { 1276 t.Fatal(err) 1277 } 1278 altsrc := filepath.Join(scratch, "r2", "src") 1279 if test.altstart != nil { 1280 makeTree(t, &node{altsrc, "", test.altstart}, "") 1281 } 1282 src := filepath.Join(scratch, "r1", "src") 1283 makeTree(t, &node{src, "", test.start}, altsrc) 1284 1285 dir := filepath.Join(wd, src, test.cwd) 1286 err = os.Chdir(dir) 1287 if err != nil { 1288 panic(err) 1289 } 1290 root1 := filepath.Join(wd, scratch, "r1") 1291 root2 := filepath.Join(wd, scratch, "r2") 1292 setGOPATH(root1, root2) 1293 saveR = test.flagR 1294 saveT = test.flagT 1295 err = save(test.args) 1296 if g := err != nil; g != test.werr { 1297 if err != nil { 1298 t.Log(pos, err) 1299 } 1300 t.Errorf("save err = %v want %v", g, test.werr) 1301 } 1302 err = os.Chdir(wd) 1303 if err != nil { 1304 panic(err) 1305 } 1306 1307 checkTree(t, pos, &node{src, "", test.want}) 1308 1309 f, err := os.Open(filepath.Join(dir, "Godeps/Godeps.json")) 1310 if err != nil { 1311 t.Error(err) 1312 } 1313 g := new(Godeps) 1314 err = json.NewDecoder(f).Decode(g) 1315 if err != nil { 1316 t.Error(err) 1317 } 1318 f.Close() 1319 1320 if g.ImportPath != test.wdep.ImportPath { 1321 t.Errorf("ImportPath = %s want %s", g.ImportPath, test.wdep.ImportPath) 1322 } 1323 for i := range g.Deps { 1324 g.Deps[i].Rev = "" 1325 } 1326 if !reflect.DeepEqual(g.Deps, test.wdep.Deps) { 1327 t.Errorf("Deps = %v want %v", g.Deps, test.wdep.Deps) 1328 } 1329 } 1330 } 1331 1332 func makeTree(t *testing.T, tree *node, altpath string) (gopath string) { 1333 walkTree(tree, tree.path, func(path string, n *node) { 1334 g, isGodeps := n.body.(*Godeps) 1335 body, _ := n.body.(string) 1336 switch { 1337 case isGodeps: 1338 for i, dep := range g.Deps { 1339 rel := filepath.FromSlash(dep.ImportPath) 1340 dir := filepath.Join(tree.path, rel) 1341 if _, err := os.Stat(dir); os.IsNotExist(err) { 1342 dir = filepath.Join(altpath, rel) 1343 } 1344 tag := dep.Comment 1345 rev := strings.TrimSpace(run(t, dir, "git", "rev-parse", tag)) 1346 g.Deps[i].Rev = rev 1347 } 1348 os.MkdirAll(filepath.Dir(path), 0770) 1349 f, err := os.Create(path) 1350 if err != nil { 1351 t.Errorf("makeTree: %v", err) 1352 return 1353 } 1354 defer f.Close() 1355 err = json.NewEncoder(f).Encode(g) 1356 if err != nil { 1357 t.Errorf("makeTree: %v", err) 1358 } 1359 case n.path == "+git": 1360 dir := filepath.Dir(path) 1361 run(t, dir, "git", "init") // repo might already exist, but ok 1362 run(t, dir, "git", "add", ".") 1363 run(t, dir, "git", "commit", "-m", "godep") 1364 if body != "" { 1365 run(t, dir, "git", "tag", body) 1366 } 1367 case n.entries == nil && strings.HasPrefix(body, "symlink:"): 1368 target := strings.TrimPrefix(body, "symlink:") 1369 os.Symlink(target, path) 1370 case n.entries == nil && body == "(absent)": 1371 panic("is this gonna be forever") 1372 case n.entries == nil: 1373 os.MkdirAll(filepath.Dir(path), 0770) 1374 err := ioutil.WriteFile(path, []byte(body), 0660) 1375 if err != nil { 1376 t.Errorf("makeTree: %v", err) 1377 } 1378 default: 1379 os.MkdirAll(path, 0770) 1380 } 1381 }) 1382 return gopath 1383 } 1384 1385 func checkTree(t *testing.T, pos int, want *node) { 1386 walkTree(want, want.path, func(path string, n *node) { 1387 body := n.body.(string) 1388 switch { 1389 case n.path == "+git": 1390 panic("is this real life") 1391 case n.entries == nil && strings.HasPrefix(body, "symlink:"): 1392 panic("why is this happening to me") 1393 case n.entries == nil && body == "(absent)": 1394 body, err := ioutil.ReadFile(path) 1395 if !os.IsNotExist(err) { 1396 t.Errorf("%d checkTree: %s = %s want absent", pos, path, string(body)) 1397 return 1398 } 1399 case n.entries == nil: 1400 gbody, err := ioutil.ReadFile(path) 1401 if err != nil { 1402 t.Errorf("%d checkTree: %v", pos, err) 1403 return 1404 } 1405 if got := string(gbody); got != body { 1406 t.Errorf("%d %s = got: %q want: %q", pos, path, got, body) 1407 } 1408 default: 1409 os.MkdirAll(path, 0770) 1410 } 1411 }) 1412 } 1413 1414 func walkTree(n *node, path string, f func(path string, n *node)) { 1415 f(path, n) 1416 for _, e := range n.entries { 1417 walkTree(e, filepath.Join(path, filepath.FromSlash(e.path)), f) 1418 } 1419 } 1420 1421 func run(t *testing.T, dir, name string, args ...string) string { 1422 cmd := exec.Command(name, args...) 1423 cmd.Dir = dir 1424 cmd.Stderr = os.Stderr 1425 out, err := cmd.Output() 1426 if err != nil { 1427 panic(name + " " + strings.Join(args, " ") + ": " + err.Error()) 1428 } 1429 return string(out) 1430 } 1431 1432 func TestStripImportComment(t *testing.T) { 1433 var cases = []struct{ s, w string }{ 1434 {`package foo`, `package foo`}, 1435 {`anything else`, `anything else`}, 1436 {`package foo // import "bar/foo"`, `package foo`}, 1437 {`package foo /* import "bar/foo" */`, `package foo`}, 1438 {`package foo // import "bar/foo" `, `package foo`}, 1439 {"package foo // import `bar/foo`", `package foo`}, 1440 {`package foo /* import "bar/foo" */; var x int`, `package foo; var x int`}, 1441 {`package foo // import "bar/foo" garbage`, `package foo // import "bar/foo" garbage`}, 1442 {`package xpackage foo // import "bar/foo"`, `package xpackage foo // import "bar/foo"`}, 1443 } 1444 1445 for _, test := range cases { 1446 g := string(stripImportComment([]byte(test.s))) 1447 if g != test.w { 1448 t.Errorf("stripImportComment(%q) = %q want %q", test.s, g, test.w) 1449 } 1450 } 1451 } 1452 1453 func TestCopyWithoutImportCommentLongLines(t *testing.T) { 1454 tmp := make([]byte, int(math.Pow(2, 16))) 1455 for i := range tmp { 1456 tmp[i] = 111 // fill it with "o"s 1457 } 1458 1459 iStr := `package foo` + string(tmp) + `\n` 1460 1461 o := new(bytes.Buffer) 1462 i := strings.NewReader(iStr) 1463 err := copyWithoutImportComment(o, i) 1464 if err != nil { 1465 t.Fatalf("copyWithoutImportComment errored: %s", err.Error()) 1466 } 1467 }