-
Notifications
You must be signed in to change notification settings - Fork 89
/
trivial.go
147 lines (134 loc) · 3.67 KB
/
trivial.go
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
package utils
import (
"bytes"
"compress/gzip"
"crypto/sha256"
"encoding/hex"
"io"
"io/ioutil"
"os"
"strings"
"unicode"
)
// TODO(ericsnow) Move the quoting helpers into the shell package?
// ShQuote quotes s so that when read by bash, no metacharacters
// within s will be interpreted as such.
func ShQuote(s string) string {
// single-quote becomes single-quote, double-quote, single-quote, double-quote, single-quote
return `'` + strings.Replace(s, `'`, `'"'"'`, -1) + `'`
}
// WinPSQuote quotes s so that when read by powershell, no metacharacters
// within s will be interpreted as such.
func WinPSQuote(s string) string {
// See http://ss64.com/ps/syntax-esc.html#quotes.
// Double quotes inside single quotes are fine, double single quotes inside
// single quotes, not so much so. Having double quoted strings inside single
// quoted strings, ensure no expansion happens.
return `'` + strings.Replace(s, `'`, `"`, -1) + `'`
}
// WinCmdQuote quotes s so that when read by cmd.exe, no metacharacters
// within s will be interpreted as such.
func WinCmdQuote(s string) string {
// See http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx.
quoted := winCmdQuote(s)
return winCmdEscapeMeta(quoted)
}
func winCmdQuote(s string) string {
var escaped string
for _, c := range s {
switch c {
case '\\', '"':
escaped += `\`
}
escaped += string(c)
}
return `"` + escaped + `"`
}
func winCmdEscapeMeta(str string) string {
const meta = `()%!^"<>&|`
var newStr string
for _, c := range str {
if strings.Contains(meta, string(c)) {
newStr += "^"
}
newStr += string(c)
}
return newStr
}
// CommandString flattens a sequence of command arguments into a
// string suitable for executing in a shell, escaping slashes,
// variables and quotes as necessary; each argument is double-quoted
// if and only if necessary.
func CommandString(args ...string) string {
var buf bytes.Buffer
for i, arg := range args {
needsQuotes := false
var argBuf bytes.Buffer
for _, r := range arg {
if unicode.IsSpace(r) {
needsQuotes = true
} else if r == '"' || r == '$' || r == '\\' {
needsQuotes = true
argBuf.WriteByte('\\')
}
argBuf.WriteRune(r)
}
if i > 0 {
buf.WriteByte(' ')
}
if needsQuotes {
buf.WriteByte('"')
argBuf.WriteTo(&buf)
buf.WriteByte('"')
} else {
argBuf.WriteTo(&buf)
}
}
return buf.String()
}
// Gzip compresses the given data.
func Gzip(data []byte) []byte {
var buf bytes.Buffer
w := gzip.NewWriter(&buf)
if _, err := w.Write(data); err != nil {
// Compression should never fail unless it fails
// to write to the underlying writer, which is a bytes.Buffer
// that never fails.
panic(err)
}
if err := w.Close(); err != nil {
panic(err)
}
return buf.Bytes()
}
// Gunzip uncompresses the given data.
func Gunzip(data []byte) ([]byte, error) {
r, err := gzip.NewReader(bytes.NewReader(data))
if err != nil {
return nil, err
}
return ioutil.ReadAll(r)
}
// ReadSHA256 returns the SHA256 hash of the contents read from source
// (hex encoded) and the size of the source in bytes.
func ReadSHA256(source io.Reader) (string, int64, error) {
hash := sha256.New()
size, err := io.Copy(hash, source)
if err != nil {
return "", 0, err
}
digest := hex.EncodeToString(hash.Sum(nil))
return digest, size, nil
}
// ReadFileSHA256 is like ReadSHA256 but reads the contents of the
// given file.
func ReadFileSHA256(filename string) (string, int64, error) {
f, err := os.Open(filename)
if err != nil {
return "", 0, err
}
defer f.Close()
return ReadSHA256(f)
}