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