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