You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

137 lines
3.1 KiB

package build
import (
"fmt"
"path"
"sort"
)
// ApplyUser wraps any build.Copy instructions as build.CopyAs using the given
// UID/GID.
//
func ApplyUser(uid uint, gid uint, instructions []Instruction) []Instruction {
applied := make([]Instruction, len(instructions))
for i, instruction := range instructions {
switch instruction.(type) {
case Copy, CopyFrom:
applied[i] = CopyAs{uid, gid, instruction}
default:
applied[i] = instruction
}
}
return applied
}
// Chown returns a build.Run instruction for setting ownership on the given
// path.
//
func Chown(uid uint, gid uint, path string) Run {
return Run{"chown %s:%s", []string{fmt.Sprint(uid), fmt.Sprint(gid), path}}
}
// CreateDirectories returns a build.Run instruction for creating all the
// given directories.
//
func CreateDirectories(paths []string) Run {
return Run{"mkdir -p", paths}
}
// CreateDirectory returns a build.Run instruction for creating the given
// directory.
//
func CreateDirectory(path string) Run {
return CreateDirectories([]string{path})
}
// CreateUser returns build.Run instructions for creating the given user
// account and group.
//
func CreateUser(name string, uid uint, gid uint) []Run {
return []Run{
{"groupadd -o -g %s -r", []string{fmt.Sprint(gid), name}},
{"useradd -o -m -d %s -r -g %s -u %s", []string{homeDir(name), name, fmt.Sprint(uid), name}},
}
}
// Home returns a build.Env instruction for setting the user's home directory.
//
func Home(name string) Env {
return Env{map[string]string{"HOME": homeDir(name)}}
}
func homeDir(name string) string {
if name == "root" {
return "/root"
}
return "/home/" + name
}
// SortFilesByDir returns both the given files indexed by parent directory and
// a sorted slice of those parent directories. The latter is useful in
// ensuring deterministic iteration since the ordering of map keys is not
// guaranteed.
//
func SortFilesByDir(files []string) ([]string, map[string][]string) {
bydir := make(map[string][]string)
for _, file := range files {
dir := path.Dir(file) + "/"
file = path.Clean(file)
if dirfiles, found := bydir[dir]; found {
bydir[dir] = append(dirfiles, file)
} else {
bydir[dir] = []string{file}
}
}
dirs := make([]string, len(bydir))
i := 0
for dir := range bydir {
dirs[i] = dir
i++
}
sort.Strings(dirs)
return dirs, bydir
}
// SyncFiles returns build instructions to copy over the given files after
// creating their parent directories. Parent directories are created in a
// sorted order.
//
func SyncFiles(files []string, dest string) []Instruction {
if len(files) < 1 {
return []Instruction{}
}
dirs, bydir := SortFilesByDir(files)
mkdirs := []string{}
copies := make([]Instruction, len(dirs))
// make project subdirectories for requirements files if necessary, and
// copy in requirements files
for i, dir := range dirs {
fulldir := dest + "/" + dir
fulldir = path.Clean(fulldir) + "/"
if dir != "./" {
mkdirs = append(mkdirs, fulldir)
}
copies[i] = Copy{bydir[dir], fulldir}
}
ins := []Instruction{}
if len(mkdirs) > 0 {
ins = append(ins, CreateDirectories(mkdirs))
}
return append(ins, copies...)
}