@@ -17,9 +17,12 @@ import (
1717 "github.com/Sirupsen/logrus"
1818 "github.com/urfave/cli"
1919
20- "github.com/Masterminds/glide/godep"
20+ "reflect"
21+
2122 "github.com/rancher/trash/conf"
2223 "github.com/rancher/trash/util"
24+ "github.com/Masterminds/glide/godep"
25+ "gopkg.in/yaml.v2"
2326)
2427
2528var Version string = "v0.3.0-dev"
@@ -73,13 +76,21 @@ func main() {
7376 EnvVar : "GOPATH" ,
7477 },
7578 }
76- app .Action = run
79+ app .Action = runWrapper
7780
7881 app .Run (os .Args )
7982}
8083
8184var gopath string
8285
86+ func runWrapper (ctx * cli.Context ) error {
87+ if err := run (ctx ); err != nil {
88+ logrus .Error (err )
89+ return err
90+ }
91+ return nil
92+ }
93+
8394func run (c * cli.Context ) error {
8495 if c .Bool ("debug" ) {
8596 logrus .SetLevel (logrus .DebugLevel )
@@ -130,18 +141,36 @@ func run(c *cli.Context) error {
130141 if err != nil {
131142 return err
132143 }
144+ defer save (trashConf )
133145
134146 if update {
135- return updateTrash (trashDir , dir , targetDir , confFile , trashConf , insecure )
136- }
137-
138- if err := vendor (keep , trashDir , dir , targetDir , trashConf , insecure ); err != nil {
139- return err
147+ //return updateTrash(trashDir, dir, targetDir, confFile, trashConf, insecure)
148+ data , err := ioutil .ReadFile (".trash-conf" )
149+ if err != nil {
150+ logrus .Fatal ("No .trash-conf found. Make sure to run `trash` to generate .trash-conf first before you run `trash -u`" )
151+ }
152+ var export conf.ExportMap
153+ if err := yaml .Unmarshal (data , & export ); err != nil {
154+ return err
155+ }
156+ imports := []conf.Import {}
157+ for k , imp := range trashConf .ImportMap {
158+ if existingImp , ok := export .Imports [k ]; ! ok {
159+ imp .Update = true
160+ } else if ! reflect .DeepEqual (imp , existingImp ) {
161+ imp .Update = true
162+ }
163+ imports = append (imports , imp )
164+ }
165+ trashConf .Imports = imports
140166 }
141167
142168 var extraImports []conf.Import
143169 for _ , packageImport := range trashConf .Imports {
144170 if packageImport .Transitive {
171+ if update && ! packageImport .Update {
172+ continue
173+ }
145174 repoDir := path .Join (trashDir , "src" , packageImport .Package )
146175 transitiveDependencies , err := godep .Parse (repoDir )
147176 if err != nil {
@@ -154,9 +183,26 @@ func run(c *cli.Context) error {
154183 Repo : transitiveDependency .Repository ,
155184 })
156185 }
186+ if len (transitiveDependencies ) == 0 {
187+ imports , err := parseTransitiveVendor (repoDir )
188+ if err != nil {
189+ return err
190+ }
191+ extraImports = append (extraImports , imports ... )
192+ }
157193 }
158194 }
159195
196+ // clean duplicate imports
197+ importMap := map [string ]conf.Import {}
198+ for _ , i := range extraImports {
199+ importMap [i .Package ] = i
200+ }
201+ extraImports = []conf.Import {}
202+ for _ , i := range importMap {
203+ extraImports = append (extraImports , i )
204+ }
205+
160206 var filteredExtraImports []conf.Import
161207 for _ , extraImport := range extraImports {
162208 packageAlreadyImported := false
@@ -172,37 +218,57 @@ func run(c *cli.Context) error {
172218 }
173219 trashConf .Imports = append (trashConf .Imports , filteredExtraImports ... )
174220
175- if err := vendor (keep , trashDir , dir , targetDir , trashConf , insecure ); err != nil {
221+ if err := vendor (keep , update , trashDir , dir , targetDir , trashConf , insecure ); err != nil {
176222 return err
177223 }
178224
179- vendorDir := path .Join (dir , targetDir )
180- for _ , packageImport := range trashConf .Imports {
181- if ! packageImport .Staging {
182- continue
183- }
225+ if ! update {
226+ vendorDir := path .Join (dir , targetDir )
227+ for _ , packageImport := range trashConf .Imports {
228+ if ! packageImport .Staging {
229+ continue
230+ }
184231
185- packageLocation := path .Dir (packageImport .Package )
186- baseDir := path .Join (trashDir , "src" , packageImport .Package , "staging/src" , packageLocation )
232+ packageLocation := path .Dir (packageImport .Package )
233+ baseDir := path .Join (trashDir , "src" , packageImport .Package , "staging/src" , packageLocation )
187234
188- files , err := ioutil .ReadDir (baseDir )
189- if err != nil {
190- return err
191- }
192- for _ , f := range files {
193- repoDir := path .Join (baseDir , f .Name ())
194- target := path .Join (vendorDir , packageLocation )
195- os .MkdirAll (target , 0755 )
196- if bytes , err := exec .Command ("cp" , "-a" , repoDir , target ).CombinedOutput (); err != nil {
197- return fmt .Errorf ("`cp -a %s %s` failed:\n %s" , repoDir , target , bytes )
235+ files , err := ioutil .ReadDir (baseDir )
236+ if err != nil {
237+ return err
238+ }
239+ for _ , f := range files {
240+ repoDir := path .Join (baseDir , f .Name ())
241+ target := path .Join (vendorDir , packageLocation )
242+ os .MkdirAll (target , 0755 )
243+ if bytes , err := exec .Command ("cp" , "-a" , repoDir , target ).CombinedOutput (); err != nil {
244+ return fmt .Errorf ("`cp -a %s %s` failed:\n %s" , repoDir , target , bytes )
245+ }
198246 }
199247 }
200248 }
201249
202250 if keep {
203251 return nil
204252 }
205- return cleanup (dir , targetDir , trashConf )
253+ return cleanup (update , dir , targetDir , trashConf )
254+ }
255+
256+ func parseTransitiveVendor (repoDir string ) ([]conf.Import , error ) {
257+ configFile := ""
258+ for _ , f := range []string {"vendor.conf" , "trash.conf" , "vndr.cfg" , "vendor.manifest" , "trash.yml" , "glide.yaml" , "glide.yml" , "trash.yaml" } {
259+ if _ , err := os .Stat (filepath .Join (repoDir , f )); err == nil {
260+ configFile = filepath .Join (repoDir , f )
261+ break
262+ }
263+ }
264+ if configFile == "" {
265+ return []conf.Import {}, nil
266+ }
267+ trashConf , err := conf .Parse (configFile )
268+ if err != nil {
269+ return []conf.Import {}, err
270+ }
271+ return trashConf .Imports , nil
206272}
207273
208274func updateTrash (trashDir , dir , targetDir , trashFile string , trashConf * conf.Conf , insecure bool ) error {
@@ -291,7 +357,7 @@ func getLatestVersion(libRoot, pkg string) (string, error) {
291357 return s , nil
292358}
293359
294- func vendor (keep bool , trashDir , dir , targetDir string , trashConf * conf.Conf , insecure bool ) error {
360+ func vendor (keep , update bool , trashDir , dir , targetDir string , trashConf * conf.Conf , insecure bool ) error {
295361 logrus .WithFields (logrus.Fields {"keep" : keep , "dir" : dir , "trashConf" : trashConf }).Debug ("vendor" )
296362 defer os .Chdir (dir )
297363
@@ -305,21 +371,36 @@ func vendor(keep bool, trashDir, dir, targetDir string, trashConf *conf.Conf, in
305371 os .Setenv ("GOPATH" , trashDir )
306372
307373 for _ , i := range trashConf .Imports {
374+ if update && ! i .Update {
375+ continue
376+ }
308377 prepareCache (trashDir , i , insecure )
309378 checkout (trashDir , i )
310379 }
311380
312381 vendorDir := path .Join (dir , targetDir )
313- os .RemoveAll (vendorDir )
314- os .MkdirAll (vendorDir , 0755 )
382+ if update {
383+ logrus .Info ("Moving deps..." )
384+ for _ , i := range trashConf .Imports {
385+ if i .Update {
386+ if err := mv (vendorDir , trashDir , i ); err != nil {
387+ return err
388+ }
389+ }
390+ }
391+ logrus .Info ("Moving deps... Done" )
392+ } else {
393+ os .RemoveAll (vendorDir )
394+ os .MkdirAll (vendorDir , 0755 )
315395
316- logrus .Info ("Copying deps..." )
317- for _ , i := range trashConf .Imports {
318- if err := cpy (vendorDir , trashDir , i ); err != nil {
319- return err
396+ logrus .Info ("Copying deps..." )
397+ for _ , i := range trashConf .Imports {
398+ if err := cpy (vendorDir , trashDir , i ); err != nil {
399+ return err
400+ }
320401 }
402+ logrus .Info ("Copying deps... Done" )
321403 }
322- logrus .Info ("Copying deps... Done" )
323404 if ! keep {
324405 if err := filepath .Walk (vendorDir , func (path string , info os.FileInfo , err error ) error {
325406 if os .IsNotExist (err ) {
@@ -408,6 +489,18 @@ func cpy(vendorDir, trashDir string, i conf.Import) error {
408489 return nil
409490}
410491
492+ func mv (vendorDir , trashDir string , i conf.Import ) error {
493+ repoDir := path .Join (trashDir , "src" , i .Package )
494+ target := path .Join (vendorDir , i .Package )
495+ os .RemoveAll (target )
496+ os .MkdirAll (target , 0755 )
497+ logrus .Infof ("Moving %s to %s" , repoDir , filepath .Dir (target ))
498+ if bytes , err := exec .Command ("mv" , repoDir , filepath .Dir (target )).CombinedOutput (); err != nil {
499+ return fmt .Errorf ("`mv -a %s %s` failed:\n %s" , repoDir , target , bytes )
500+ }
501+ return nil
502+ }
503+
411504func checkGitRepo (trashDir , repoDir string , i conf.Import , insecure bool ) error {
412505 logrus .WithFields (logrus.Fields {"repoDir" : repoDir , "i" : i }).Debug ("checkGitRepo" )
413506 if err := os .Chdir (repoDir ); err != nil {
@@ -699,7 +792,7 @@ func collectImports(rootPackage, libRoot, targetDir string) util.Packages {
699792 return imports
700793}
701794
702- func removeUnusedImports (imports util.Packages , targetDir string ) error {
795+ func removeUnusedImports (imports util.Packages , targetDir string , updatePackages map [ string ] bool ) error {
703796 importsParents := util.Packages {}
704797 for i := range imports {
705798 importsParents .Merge (parentPackages ("" , i ))
@@ -715,6 +808,19 @@ func removeUnusedImports(imports util.Packages, targetDir string) error {
715808 if path == targetDir {
716809 return nil
717810 }
811+ shouldClean := false
812+ if updatePackages == nil || len (updatePackages ) == 0 {
813+ shouldClean = true
814+ }
815+ for pkg := range updatePackages {
816+ if strings .HasPrefix (path , filepath .Join (targetDir , pkg )) {
817+ shouldClean = true
818+ break
819+ }
820+ }
821+ if ! shouldClean {
822+ return nil
823+ }
718824 if ! info .IsDir () {
719825 pkg := path [len (targetDir + "/" ):strings .LastIndex (path , "/" )]
720826 if strings .HasSuffix (path , "_test.go" ) || strings .HasSuffix (path , ".go" ) && ! imports [pkg ] {
@@ -829,7 +935,7 @@ func guessRootPackage(dir string) string {
829935 return dir [len (srcPath + "/" ):]
830936}
831937
832- func cleanup (dir , targetDir string , trashConf * conf.Conf ) error {
938+ func cleanup (update bool , dir , targetDir string , trashConf * conf.Conf ) error {
833939 rootPackage := trashConf .Package
834940 if rootPackage == "" {
835941 rootPackage = guessRootPackage (dir )
@@ -840,10 +946,20 @@ func cleanup(dir, targetDir string, trashConf *conf.Conf) error {
840946 os .Chdir (dir )
841947
842948 imports := collectImports (rootPackage , targetDir , targetDir )
949+ var updatePackages map [string ]bool
950+ if update {
951+ updatePackages = make (map [string ]bool )
952+ for _ , i := range trashConf .Imports {
953+ if i .Update {
954+ updatePackages [i .Package ] = true
955+ }
956+ }
957+ logrus .Infof ("Updated packages %v" , updatePackages )
958+ }
843959 if err := removeExcludes (trashConf .Excludes , targetDir ); err != nil {
844960 logrus .Errorf ("Error removing excluded dirs: %v" , err )
845961 }
846- if err := removeUnusedImports (imports , targetDir ); err != nil {
962+ if err := removeUnusedImports (imports , targetDir , updatePackages ); err != nil {
847963 logrus .Errorf ("Error removing unused dirs: %v" , err )
848964 }
849965 if err := removeEmptyDirs (targetDir ); err != nil {
@@ -861,3 +977,16 @@ func cleanup(dir, targetDir string, trashConf *conf.Conf) error {
861977 }
862978 return nil
863979}
980+
981+ func save (config * conf.Conf ) {
982+ export := conf.ExportMap {
983+ Imports : config .ImportMap ,
984+ }
985+ data , err := yaml .Marshal (export )
986+ if err != nil {
987+ logrus .Fatal (err )
988+ }
989+ if err := ioutil .WriteFile (".trash-conf" , data , 0644 ); err != nil {
990+ logrus .Fatal (err )
991+ }
992+ }
0 commit comments