about summary refs log tree commit diff
path: root/users/wpcarro/gopkgs
diff options
context:
space:
mode:
Diffstat (limited to 'users/wpcarro/gopkgs')
-rw-r--r--users/wpcarro/gopkgs/kv/default.nix8
-rw-r--r--users/wpcarro/gopkgs/kv/kv.go39
-rw-r--r--users/wpcarro/gopkgs/utils/default.nix8
-rw-r--r--users/wpcarro/gopkgs/utils/utils.go131
4 files changed, 186 insertions, 0 deletions
diff --git a/users/wpcarro/gopkgs/kv/default.nix b/users/wpcarro/gopkgs/kv/default.nix
new file mode 100644
index 000000000000..72aae7827ba1
--- /dev/null
+++ b/users/wpcarro/gopkgs/kv/default.nix
@@ -0,0 +1,8 @@
+{ depot, ... }:
+
+depot.nix.buildGo.package {
+  name = "kv";
+  srcs = [
+    ./kv.go
+  ];
+}
diff --git a/users/wpcarro/gopkgs/kv/kv.go b/users/wpcarro/gopkgs/kv/kv.go
new file mode 100644
index 000000000000..040cc63e0e7c
--- /dev/null
+++ b/users/wpcarro/gopkgs/kv/kv.go
@@ -0,0 +1,39 @@
+// Supporting reading and writing key-value pairs to disk.
+package kv
+
+import (
+	"encoding/json"
+	"io/ioutil"
+	"log"
+	"path"
+)
+
+// Return the decoded store from disk.
+func getStore(storePath string) map[string]interface{} {
+	b, err := ioutil.ReadFile(path.Join(storePath, "kv.json"))
+	if err != nil {
+		log.Fatal("Could not read store: ", err)
+	}
+	var state map[string]interface{}
+	err = json.Unmarshal(b, &state)
+	if err != nil {
+		log.Fatal("Could not decode store as JSON: ", err)
+	}
+	return state
+}
+
+// Set `key` to `value` in the store.
+func Set(storePath string, key string, value interface{}) error {
+	state := getStore(storePath)
+	state[key] = value
+	b, err := json.Marshal(state)
+	if err != nil {
+		log.Fatal("Could not encode state as JSON: ", err)
+	}
+	return ioutil.WriteFile(path.Join(storePath, "kv.json"), b, 0644)
+}
+
+// Get `key` from the store.
+func Get(storePath string, key string) interface{} {
+	return getStore(path.Join(storePath, "kv.json"))[key]
+}
diff --git a/users/wpcarro/gopkgs/utils/default.nix b/users/wpcarro/gopkgs/utils/default.nix
new file mode 100644
index 000000000000..25321f50a042
--- /dev/null
+++ b/users/wpcarro/gopkgs/utils/default.nix
@@ -0,0 +1,8 @@
+{ depot, ... }:
+
+depot.nix.buildGo.package {
+  name = "utils";
+  srcs = [
+    ./utils.go
+  ];
+}
diff --git a/users/wpcarro/gopkgs/utils/utils.go b/users/wpcarro/gopkgs/utils/utils.go
new file mode 100644
index 000000000000..7d662d08668b
--- /dev/null
+++ b/users/wpcarro/gopkgs/utils/utils.go
@@ -0,0 +1,131 @@
+// Some utility functions to tidy up my Golang.
+package utils
+
+import (
+	"fmt"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"net/http/httputil"
+	"os"
+	"os/user"
+	"path/filepath"
+)
+
+// Return the absolute path to the current uesr's home directory.
+func HomeDir() string {
+	user, err := user.Current()
+	if err != nil {
+		log.Fatal(err)
+	}
+	return user.HomeDir
+}
+
+// Returns true if `info` is a symlink.
+func IsSymlink(info os.FileMode) bool {
+	return info&os.ModeSymlink != 0
+}
+
+// Return true if `path` exists and false otherwise.
+func FileExists(path string) bool {
+	if _, err := os.Stat(path); os.IsNotExist(err) {
+		return false
+	} else {
+		return true
+	}
+}
+
+// Return the absolute file path of `file` using the following resolution
+// strategy:
+// - Traverse and search upwards until you reach the user's home directory
+// - Return the first path in `backupPaths` that exists
+// - Fail
+func Resolve(fileName string, backupPaths []string) string {
+	// TODO(wpcarro): Drop hardcoding when whoami behaves as expected.
+	boundary := "/home"
+	cwd := "."
+	files, _ := ioutil.ReadDir(cwd)
+
+	for {
+		fullCwd, _ := filepath.Abs(cwd)
+		if fullCwd == boundary {
+			break
+		}
+		for _, file := range files {
+			if file.Name() == fileName {
+				path, _ := filepath.Abs(cwd + "/" + file.Name())
+				return path
+			}
+		}
+		cwd += "/.."
+		files, _ = ioutil.ReadDir(cwd)
+	}
+
+	// TODO(wpcarro): Support expanding these paths to allow the consumer to
+	// pass in relative paths, and paths with "~" in them.
+	for _, backup := range backupPaths {
+		if FileExists(backup) {
+			return backup
+		}
+	}
+	log.Fatal("Cannot find a run.json to use.")
+	// This code should be unreachable.
+	return ""
+}
+
+// Call log.Fatal with `err` when it's not nil.
+func FailOn(err error) {
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+// Prints the verbose form of an HTTP request.
+func DebugRequest(req *http.Request) {
+	bytes, _ := httputil.DumpRequest(req, true)
+	fmt.Println(string(bytes))
+}
+
+// Prints out the verbose form of an HTTP response.
+func DebugResponse(res *http.Response) {
+	bytes, _ := httputil.DumpResponse(res, true)
+	fmt.Println(string(bytes))
+}
+
+// Make a simple GET request to `url`. Fail if anything returns an error. I'd
+// like to accumulate a library of these, so that I can write scrappy Go
+// quickly. For now, this function just returns the body of the response back as
+// a string.
+func SimpleGet(url string, headers map[string]string, debug bool) string {
+	client := &http.Client{}
+	req, err := http.NewRequest("GET", url, nil)
+	if err != nil {
+		log.Fatal(err)
+	}
+	for k, v := range headers {
+		req.Header.Add(k, v)
+	}
+
+	res, err := client.Do(req)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer res.Body.Close()
+
+	if debug {
+		DebugRequest(req)
+		DebugResponse(res)
+	}
+
+	if res.StatusCode == http.StatusOK {
+		bytes, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			log.Fatal(err)
+		}
+		return string(bytes)
+	} else {
+		log.Println(res)
+		log.Fatalf("HTTP status code of response not OK: %v\n", res.StatusCode)
+		return ""
+	}
+}