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