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  }