github.com/jonsyu1/godel@v0.0.0-20171017211503-64567a0cf169/layout/layout.go (about) 1 // Copyright 2016 Palantir Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package layout 16 17 import ( 18 "fmt" 19 "io/ioutil" 20 "os" 21 "path" 22 "runtime" 23 "strings" 24 25 s "github.com/palantir/pkg/specdir" 26 ) 27 28 const ( 29 AppName = "godel" 30 WrapperName = "godelw" 31 DistsDir = "dists" 32 DownloadsDir = "downloads" 33 gödelHomeTemplate = "gödel-home" 34 gödelHomeEnvVar = "GODEL_HOME" 35 defaultGödelHome = ".godel" 36 ) 37 38 // AllPaths returns a map that contains all of the paths in the provided directory. The paths are relative to the 39 // directory. The boolean key is true if the path is a directory, false otherwise. 40 func AllPaths(dir string) (map[string]bool, error) { 41 m := make(map[string]bool) 42 return m, allPaths(m, nil, dir) 43 } 44 45 func allPaths(paths map[string]bool, pathStack []string, dir string) error { 46 fis, err := ioutil.ReadDir(dir) 47 if err != nil { 48 return err 49 } 50 for _, fi := range fis { 51 p := path.Join(dir, fi.Name()) 52 key := path.Join(strings.Join(pathStack, "/"), fi.Name()) 53 // record current path 54 paths[key] = fi.IsDir() 55 if fi.IsDir() { 56 // if path is directory, recursively record paths 57 if err := allPaths(paths, append(pathStack, fi.Name()), p); err != nil { 58 return err 59 } 60 } 61 } 62 return nil 63 } 64 65 func GödelDistLayout(version string, mode s.Mode) (s.SpecDir, error) { 66 rootDir, err := GödelHomePath() 67 if err != nil { 68 return nil, err 69 } 70 71 values := s.TemplateValues{ 72 gödelHomeTemplate: path.Base(rootDir), 73 versionTemplate: version, 74 } 75 for key, value := range AppSpecTemplate(version) { 76 values[key] = value 77 } 78 79 return s.New(rootDir, gödelHomeSpec([]s.FileNodeProvider{AppSpec()}), values, mode) 80 } 81 82 // GödelHomePath returns the path to the gödel home directory. If $GODEL_HOME is set as an environment variable, that 83 // value is used. Otherwise, the value is "$HOME/{{defaultGödelHome}}" 84 func GödelHomePath() (string, error) { 85 // check the environment variable 86 if gödelHomeDir := os.Getenv(gödelHomeEnvVar); gödelHomeDir != "" { 87 return gödelHomeDir, nil 88 } 89 // if not present, create from home directory 90 if userHomeDir := os.Getenv("HOME"); userHomeDir != "" { 91 return path.Join(userHomeDir, defaultGödelHome), nil 92 } 93 return "", fmt.Errorf("Failed to get gödel home directory") 94 } 95 96 func GödelHomeSpecDir(mode s.Mode) (s.SpecDir, error) { 97 rootDir, err := GödelHomePath() 98 if err != nil { 99 return nil, err 100 } 101 values := s.TemplateValues{ 102 gödelHomeTemplate: path.Base(rootDir), 103 } 104 105 return s.New(rootDir, GödelHomeSpec(), values, mode) 106 } 107 108 func GödelHomeSpec() s.LayoutSpec { 109 return gödelHomeSpec(nil) 110 } 111 112 func gödelHomeSpec(providers []s.FileNodeProvider) s.LayoutSpec { 113 return s.NewLayoutSpec( 114 s.Dir(s.TemplateName(gödelHomeTemplate), "", 115 s.Dir(s.LiteralName("dists"), DistsDir, providers...), 116 s.Dir(s.LiteralName("downloads"), DownloadsDir), 117 ), 118 true, 119 ) 120 } 121 122 const ( 123 AppDir = "gödel-app" 124 AppExecutable = "app-executable" 125 osTemplate = "os" 126 archTemplate = "arch" 127 versionTemplate = "version" 128 ) 129 130 func AppSpecDir(rootDir, version string) (s.SpecDir, error) { 131 return s.New(rootDir, AppSpec(), AppSpecTemplate(version), s.Validate) 132 } 133 134 func AppSpec() s.LayoutSpec { 135 return s.NewLayoutSpec( 136 s.Dir(s.CompositeName(s.LiteralName(AppName+"-"), s.TemplateName(versionTemplate)), AppDir, 137 s.Dir(s.LiteralName("bin"), "", 138 s.Dir(s.CompositeName(s.TemplateName(osTemplate), s.LiteralName("-"), s.TemplateName(archTemplate)), "", 139 s.File(s.LiteralName(AppName), AppExecutable), 140 ), 141 ), 142 WrapperSpec(), 143 ), 144 true, 145 ) 146 } 147 148 func AppSpecTemplate(version string) s.TemplateValues { 149 return s.TemplateValues{ 150 versionTemplate: version, 151 osTemplate: runtime.GOOS, 152 archTemplate: runtime.GOARCH, 153 } 154 } 155 156 const ( 157 WrapperDir = "wrapper-dir" 158 WrapperScriptFile = "wrapper-script" 159 WrapperAppDir = "wrapper-app" 160 WrapperConfigDir = "config" 161 ) 162 163 func WrapperSpec() s.LayoutSpec { 164 return s.NewLayoutSpec( 165 s.Dir(s.LiteralName("wrapper"), WrapperDir, 166 s.File(s.LiteralName(WrapperName), WrapperScriptFile), 167 s.Dir(s.LiteralName(AppName), WrapperAppDir, 168 s.Dir(s.LiteralName(WrapperConfigDir), WrapperConfigDir), 169 ), 170 ), 171 false, 172 ) 173 }