gopkg.in/tools/godep.v41@v41.0.0-20151217180337-fe5ce707f879/save_test.go (about)

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