1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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 ""
}
}
|