github.com/s-urbaniak/glide@v0.0.0-20160527141859-5f5e941b1fc4/action/create.go (about) 1 package action 2 3 import ( 4 "os" 5 "path/filepath" 6 "sort" 7 "strings" 8 9 "github.com/Masterminds/glide/cfg" 10 "github.com/Masterminds/glide/dependency" 11 "github.com/Masterminds/glide/gb" 12 "github.com/Masterminds/glide/godep" 13 "github.com/Masterminds/glide/gpm" 14 "github.com/Masterminds/glide/msg" 15 gpath "github.com/Masterminds/glide/path" 16 "github.com/Masterminds/glide/util" 17 ) 18 19 // Create creates/initializes a new Glide repository. 20 // 21 // This will fail if a glide.yaml already exists. 22 // 23 // By default, this will scan the present source code directory for dependencies. 24 // 25 // If skipImport is set to true, this will not attempt to import from an existing 26 // GPM, Godep, or GB project if one should exist. However, it will still attempt 27 // to read the local source to determine required packages. 28 func Create(base string, skipImport bool) { 29 glidefile := gpath.GlideFile 30 // Guard against overwrites. 31 guardYAML(glidefile) 32 33 // Guess deps 34 conf := guessDeps(base, skipImport) 35 // Write YAML 36 if err := conf.WriteFile(glidefile); err != nil { 37 msg.Die("Could not save %s: %s", glidefile, err) 38 } 39 } 40 41 // guardYAML fails if the given file already exists. 42 // 43 // This prevents an important file from being overwritten. 44 func guardYAML(filename string) { 45 if _, err := os.Stat(filename); err == nil { 46 msg.Die("Cowardly refusing to overwrite existing YAML.") 47 } 48 } 49 50 // guessDeps attempts to resolve all of the dependencies for a given project. 51 // 52 // base is the directory to start with. 53 // skipImport will skip running the automatic imports. 54 // 55 // FIXME: This function is likely a one-off that has a more standard alternative. 56 // It's also long and could use a refactor. 57 func guessDeps(base string, skipImport bool) *cfg.Config { 58 buildContext, err := util.GetBuildContext() 59 if err != nil { 60 msg.Die("Failed to build an import context: %s", err) 61 } 62 name := buildContext.PackageName(base) 63 64 msg.Info("Generating a YAML configuration file and guessing the dependencies") 65 66 config := new(cfg.Config) 67 68 // Get the name of the top level package 69 config.Name = name 70 71 // Import by looking at other package managers and looking over the 72 // entire directory structure. 73 74 // Attempt to import from other package managers. 75 if !skipImport { 76 guessImportDeps(base, config) 77 } 78 79 // Resolve dependencies by looking at the tree. 80 r, err := dependency.NewResolver(base) 81 if err != nil { 82 msg.Die("Error creating a dependency resolver: %s", err) 83 } 84 85 h := &dependency.DefaultMissingPackageHandler{Missing: []string{}, Gopath: []string{}} 86 r.Handler = h 87 88 sortable, err := r.ResolveLocal(false) 89 if err != nil { 90 msg.Die("Error resolving local dependencies: %s", err) 91 } 92 93 sort.Strings(sortable) 94 95 vpath := r.VendorDir 96 if !strings.HasSuffix(vpath, "/") { 97 vpath = vpath + string(os.PathSeparator) 98 } 99 100 for _, pa := range sortable { 101 n := strings.TrimPrefix(pa, vpath) 102 root, subpkg := util.NormalizeName(n) 103 104 if !config.HasDependency(root) { 105 msg.Info("Found reference to %s\n", n) 106 d := &cfg.Dependency{ 107 Name: root, 108 } 109 if len(subpkg) > 0 { 110 d.Subpackages = []string{subpkg} 111 } 112 config.Imports = append(config.Imports, d) 113 } else { 114 if len(subpkg) > 0 { 115 subpkg = strings.TrimPrefix(subpkg, "/") 116 d := config.Imports.Get(root) 117 if !d.HasSubpackage(subpkg) { 118 msg.Info("Adding sub-package %s to %s\n", subpkg, root) 119 d.Subpackages = append(d.Subpackages, subpkg) 120 } 121 } 122 } 123 } 124 125 return config 126 } 127 128 func guessImportDeps(base string, config *cfg.Config) { 129 msg.Info("Attempting to import from other package managers (use --skip-import to skip)") 130 deps := []*cfg.Dependency{} 131 absBase, err := filepath.Abs(base) 132 if err != nil { 133 msg.Die("Failed to resolve location of %s: %s", base, err) 134 } 135 136 if d, ok := guessImportGodep(absBase); ok { 137 msg.Info("Importing Godep configuration") 138 msg.Warn("Godep uses commit id versions. Consider using Semantic Versions with Glide") 139 deps = d 140 } else if d, ok := guessImportGPM(absBase); ok { 141 msg.Info("Importing GPM configuration") 142 deps = d 143 } else if d, ok := guessImportGB(absBase); ok { 144 msg.Info("Importing GB configuration") 145 deps = d 146 } 147 148 for _, i := range deps { 149 msg.Info("Found imported reference to %s\n", i.Name) 150 config.Imports = append(config.Imports, i) 151 } 152 } 153 154 func guessImportGodep(dir string) ([]*cfg.Dependency, bool) { 155 d, err := godep.Parse(dir) 156 if err != nil || len(d) == 0 { 157 return []*cfg.Dependency{}, false 158 } 159 160 return d, true 161 } 162 163 func guessImportGPM(dir string) ([]*cfg.Dependency, bool) { 164 d, err := gpm.Parse(dir) 165 if err != nil || len(d) == 0 { 166 return []*cfg.Dependency{}, false 167 } 168 169 return d, true 170 } 171 172 func guessImportGB(dir string) ([]*cfg.Dependency, bool) { 173 d, err := gb.Parse(dir) 174 if err != nil || len(d) == 0 { 175 return []*cfg.Dependency{}, false 176 } 177 178 return d, true 179 }