(v0.1.1) Automated packaging of release by Packagr

This commit is contained in:
packagr-io-beta
2020-08-21 06:31:48 +00:00
parent 7a10a7ee63
commit b6ca94f786
1303 changed files with 620126 additions and 109 deletions
+84
View File
@@ -0,0 +1,84 @@
package utils
import (
stderrors "errors"
"fmt"
"github.com/kvz/logstreamer"
"log"
"os"
"os/exec"
"path"
)
//http://craigwickesser.com/2015/02/golang-cmd-with-custom-environment/
//http://www.ryanday.net/2012/10/01/installing-go-and-gopath/
//
func BashCmdExec(cmd string, workingDir string, environ []string, logPrefix string) error {
return CmdExec("sh", []string{"-c", cmd}, workingDir, environ, logPrefix)
}
func CmdExec(cmdName string, cmdArgs []string, workingDir string, environ []string, logPrefix string) error {
if logPrefix == "" {
logPrefix = " >> "
} else {
logPrefix = logPrefix + " | "
}
// Create a logger (your app probably already has one)
logger := log.New(os.Stdout, logPrefix, log.Ldate|log.Ltime)
// Setup a streamer that we'll pipe cmd.Stdout to
logStreamerOut := logstreamer.NewLogstreamer(logger, "stdout", false)
defer logStreamerOut.Close()
// Setup a streamer that we'll pipe cmd.Stderr to.
// We want to record/buffer anything that's written to this (3rd argument true)
logStreamerErr := logstreamer.NewLogstreamer(logger, "stderr", true)
defer logStreamerErr.Close()
cmd := exec.Command(cmdName, cmdArgs...)
cmd.Stdout = logStreamerOut
cmd.Stderr = logStreamerErr
if environ != nil {
cmd.Env = environ
}
if workingDir != "" && path.IsAbs(workingDir) {
cmd.Dir = workingDir
} else if workingDir != "" {
return stderrors.New("Working Directory must be an absolute path")
}
//cmdReader, err := cmd.StdoutPipe()
//if err != nil {
// fmt.Fprintln(os.Stderr, "Error creating StdoutPipe for Cmd", err)
// return err
//}
//
//done := make(chan struct{})
//
//scanner := bufio.NewScanner(cmdReader)
//go func() {
// for scanner.Scan() {
// fmt.Printf("%s%s\n", logPrefix, scanner.Text())
// }
// done <- struct{}{}
//
//}()
// Reset any error we recorded
logStreamerErr.FlushRecord()
err := cmd.Start()
if err != nil {
fmt.Fprintln(os.Stderr, "Error starting Cmd", err)
return err
}
//<-done
err = cmd.Wait()
if err != nil {
fmt.Fprintln(os.Stderr, "Error waiting for Cmd", err)
return err
}
return nil
}
+153
View File
@@ -0,0 +1,153 @@
package utils
import (
"fmt"
"github.com/fatih/color"
"github.com/mitchellh/go-homedir"
"io"
"io/ioutil"
"os"
"path/filepath"
)
func ExpandPath(filePath string) (string, error) {
filePath, err := homedir.Expand(filePath)
if err != nil {
return "", err
}
filePath, err = filepath.Abs(filePath)
if err != nil {
return "", err
}
return filePath, nil
}
func FileWrite(filePath string, content string, perm os.FileMode, dryRun bool) error {
filePath, err := ExpandPath(filePath)
if err != nil {
return err
}
if dryRun {
fmt.Printf("%v %v %v:\n",
color.GreenString("[DRYRUN]"),
"Would have written content to",
color.GreenString(filePath),
)
color.Green(content)
} else {
d1 := []byte(content)
err = ioutil.WriteFile(filePath, d1, perm)
}
return err
}
func FileExists(filePath string) bool {
filePath, err := ExpandPath(filePath)
if err != nil {
return false
}
if _, err := os.Stat(filePath); err != nil {
return !os.IsNotExist(err)
}
return true
}
func FileDelete(filePath string) error {
filePath, err := ExpandPath(filePath)
if err != nil {
return err
}
return os.Remove(filePath)
}
// CopyFile copies the contents of the file named src to the file named
// by dst. The file will be created if it does not already exist. If the
// destination file exists, all it's contents will be replaced by the contents
// of the source file. The file mode will be copied from the source and
// the copied data is synced/flushed to stable storage.
func CopyFile(src, dst string) (err error) {
in, err := os.Open(src)
if err != nil {
return
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return
}
defer func() {
if e := out.Close(); e != nil {
err = e
}
}()
_, err = io.Copy(out, in)
if err != nil {
return
}
err = out.Sync()
if err != nil {
return
}
si, err := os.Stat(src)
if err != nil {
return
}
err = os.Chmod(dst, si.Mode())
if err != nil {
return
}
return
}
// CopyDir recursively copies a directory tree, attempting to preserve permissions.
// Source directory must exist, destination directory must *not* exist.
// Symlinks are ignored and skipped.
func CopyDir(src string, dst string) (err error) {
src = filepath.Clean(src)
dst = filepath.Clean(dst)
si, err := os.Stat(src)
if err != nil {
return err
}
if !si.IsDir() {
return fmt.Errorf("source is not a directory")
}
_, err = os.Stat(dst)
if err != nil && !os.IsNotExist(err) {
return
}
if err == nil {
return fmt.Errorf("destination already exists")
}
err = os.MkdirAll(dst, si.Mode())
if err != nil {
return
}
entries, err := ioutil.ReadDir(src)
if err != nil {
return
}
for _, entry := range entries {
srcPath := filepath.Join(src, entry.Name())
dstPath := filepath.Join(dst, entry.Name())
if entry.IsDir() {
err = CopyDir(srcPath, dstPath)
if err != nil {
return
}
} else {
// Skip symlinks.
if entry.Mode()&os.ModeSymlink != 0 {
continue
}
err = CopyFile(srcPath, dstPath)
if err != nil {
return
}
}
}
return
}
+30
View File
@@ -0,0 +1,30 @@
package utils
import (
"encoding/json"
"sort"
)
func MapKeys(m map[string]interface{}) []string {
var keys []string
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
return keys
}
func MapDeepCopy(m map[string]interface{}) (map[string]interface{}, error) {
jsonString, err := json.Marshal(m)
if err != nil {
return nil, err
}
nm := map[string]interface{}{}
err = json.Unmarshal([]byte(jsonString), &nm)
if err != nil {
return nil, err
}
return nm, nil
}
+19
View File
@@ -0,0 +1,19 @@
package utils
func SliceIncludes(slice []string, item string) bool {
for _, val := range slice {
if val == item {
return true
}
}
return false
}
//func indexOf(answers []interface{}, item interface{}) (int) {
// for k, v := range answers {
// if v == item {
// return k
// }
// }
// return -1
//}
+53
View File
@@ -0,0 +1,53 @@
package utils
import (
"bufio"
"fmt"
"github.com/fatih/color"
"golang.org/x/crypto/ssh/terminal"
"os"
"strings"
"syscall"
)
func StdinQueryPassword(question string) (string, error) {
fmt.Println(color.BlueString(question))
bytePassword, err := terminal.ReadPassword(int(syscall.Stdin))
if err != nil {
return "", err
}
text := strings.TrimSpace(string(bytePassword))
return text, nil
}
func StdinQuery(question string) string {
fmt.Println(color.BlueString(question))
reader := bufio.NewReader(os.Stdin)
text, _ := reader.ReadString('\n')
text = strings.TrimSpace(text)
return text
}
func StdinQueryBoolean(question string) bool {
text := StdinQuery(question)
text = strings.ToLower(text)
if text == "true" || text == "yes" || text == "y" {
return true
} else if text == "false" || text == "no" || text == "n" {
return false
} else {
color.Yellow("WARNING: invalid response only true/yes/y/false/no/n allowed not `%v`.\nAssuming `no`", text)
return false
}
}
func StdinQueryInt(question string) (int, error) {
text := StdinQuery(question)
return StringToInt(text)
}
+83
View File
@@ -0,0 +1,83 @@
package utils
import (
"strconv"
"strings"
)
func StringToInt(input string) (int, error) {
i, err := strconv.Atoi(input)
if err != nil {
return 0, err
}
return i, nil
}
func SnakeCaseToCamelCase(inputUnderScoreStr string) (camelCase string) {
//snake_case to camelCase
isToUpper := false
for k, v := range inputUnderScoreStr {
if k == 0 {
camelCase = strings.ToUpper(string(inputUnderScoreStr[0]))
} else {
if isToUpper {
camelCase += strings.ToUpper(string(v))
isToUpper = false
} else {
if v == '_' {
isToUpper = true
} else {
camelCase += string(v)
}
}
}
}
return
}
// https://github.com/DaddyOh/golang-samples/blob/master/pad.go
/*
* leftPad and rightPad just repoeat the padStr the indicated
* number of times
*
*/
func LeftPad(s string, padStr string, pLen int) string {
return strings.Repeat(padStr, pLen) + s
}
func RightPad(s string, padStr string, pLen int) string {
return s + strings.Repeat(padStr, pLen)
}
/* the Pad2Len functions are generally assumed to be padded with short sequences of strings
* in many cases with a single character sequence
*
* so we assume we can build the string out as if the char seq is 1 char and then
* just substr the string if it is longer than needed
*
* this means we are wasting some cpu and memory work
* but this always get us to want we want it to be
*
* in short not optimized to for massive string work
*
* If the overallLen is shorter than the original string length
* the string will be shortened to this length (substr)
*
*/
func RightPad2Len(s string, padStr string, overallLen int) string {
padCountInt := 1 + ((overallLen - len(padStr)) / len(padStr))
var retStr = s + strings.Repeat(padStr, padCountInt)
return retStr[:overallLen]
}
func LeftPad2Len(s string, padStr string, overallLen int) string {
padCountInt := 1 + ((overallLen - len(padStr)) / len(padStr))
var retStr = strings.Repeat(padStr, padCountInt) + s
return retStr[(len(retStr) - overallLen):]
}
func StripIndent(multilineStr string) string {
return strings.Replace(multilineStr, "\t", "", -1)
}
+71
View File
@@ -0,0 +1,71 @@
package utils
import (
"bytes"
"encoding/json"
"hash/fnv"
"text/template"
)
func PopulatePathTemplate(pathTmplContent string, data interface{}) (string, error){
tmplFilepath, err := PopulateTemplate(pathTmplContent, data)
if err != nil {
return "", nil
}
tmplFilepath, err = ExpandPath(tmplFilepath)
if err != nil {
return "", nil
}
return tmplFilepath, nil
}
func PopulateTemplate(tmplContent string, data interface{}) (string, error) {
//set functions
fns := template.FuncMap{
"uniquePort": UniquePort,
"expandPath": ExpandPath,
}
// prep the template, set the option
tmpl, err := template.New("populate").Option("missingkey=error").Funcs(fns).Parse(tmplContent)
if err != nil {
return "", err
}
//specify that any missing keys in the template will throw an error
buf := new(bytes.Buffer)
err = tmpl.Execute(buf, data)
if err != nil {
return "", err
}
//convert buffered content to string
return buf.String(), nil
}
// https://play.golang.org/p/k8bws03uid
func UniquePort(data interface{}) (int, error) {
var contentData []byte
switch in := data.(type) {
case string:
contentData = []byte(in)
default:
jsonData, err := json.Marshal(StringifyYAMLMapKeys(in))
if err != nil {
return 0, err
}
contentData = jsonData
}
hash := fnv.New32a()
hash.Write(contentData)
//last port - last privileged port.
portRange := 65535 - 1023
uniquePort := (hash.Sum32() % uint32(portRange)) + 1023
return int(uniquePort), nil
}
+34
View File
@@ -0,0 +1,34 @@
package utils
import "fmt"
// stringifyKeysMapValue recurses into in and changes all instances of
// map[interface{}]interface{} to map[string]interface{}. This is useful to
// work around the impedence mismatch between JSON and YAML unmarshaling that's
// described here: https://github.com/go-yaml/yaml/issues/139
//
// Inspired by https://github.com/stripe/stripe-mock, MIT licensed
func StringifyYAMLMapKeys(in interface{}) interface{} {
switch in := in.(type) {
case []interface{}:
res := make([]interface{}, len(in))
for i, v := range in {
res[i] = StringifyYAMLMapKeys(v)
}
return res
case map[string]interface{}:
res := make(map[string]interface{})
for k, v := range in {
res[k] = StringifyYAMLMapKeys(v)
}
return res
case map[interface{}]interface{}:
res := make(map[string]interface{})
for k, v := range in {
res[fmt.Sprintf("%v", k)] = StringifyYAMLMapKeys(v)
}
return res
default:
return in
}
}