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 148 149 150
|
package build
import (
"archive/tar"
"compress/gzip"
"errors"
"io"
"io/ioutil"
"os"
"path/filepath"
"time"
)
var (
// SiaTestingDir is the directory that contains all of the files and
// folders created during testing.
SiaTestingDir = filepath.Join(os.TempDir(), "SiaTesting")
)
// TempDir joins the provided directories and prefixes them with the Sia
// testing directory.
func TempDir(dirs ...string) string {
path := filepath.Join(SiaTestingDir, filepath.Join(dirs...))
os.RemoveAll(path) // remove old test data
return path
}
// CopyFile copies a file from a source to a destination.
func CopyFile(source, dest string) error {
sf, err := os.Open(source)
if err != nil {
return err
}
defer sf.Close()
df, err := os.Create(dest)
if err != nil {
return err
}
defer df.Close()
_, err = io.Copy(df, sf)
if err != nil {
return err
}
return nil
}
// CopyDir copies a directory and all of its contents to the destination
// directory.
func CopyDir(source, dest string) error {
stat, err := os.Stat(source)
if err != nil {
return err
}
if !stat.IsDir() {
return errors.New("source is not a directory")
}
err = os.MkdirAll(dest, stat.Mode())
if err != nil {
return err
}
files, err := ioutil.ReadDir(source)
for _, file := range files {
newSource := filepath.Join(source, file.Name())
newDest := filepath.Join(dest, file.Name())
if file.IsDir() {
err = CopyDir(newSource, newDest)
if err != nil {
return err
}
} else {
err = CopyFile(newSource, newDest)
if err != nil {
return err
}
}
}
return nil
}
// ExtractTarGz extracts the specified .tar.gz file to dir, overwriting
// existing files in the event of a name conflict.
func ExtractTarGz(filename, dir string) error {
// Open the zipped archive.
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
z, err := gzip.NewReader(file)
if err != nil {
return err
}
defer z.Close()
t := tar.NewReader(z)
// Create the output directory if it does not exist.
if err := os.MkdirAll(dir, 0700); err != nil {
return err
}
// Read the file entries, writing each to dir.
for {
// Read header.
hdr, err := t.Next()
if err == io.EOF {
return nil
} else if err != nil {
return err
}
path := filepath.Join(dir, hdr.Name)
info := hdr.FileInfo()
if info.IsDir() {
// Create directory.
if err := os.MkdirAll(path, info.Mode()); err != nil {
return err
}
} else {
// Create file.
tf, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, info.Mode())
if err != nil {
return err
}
_, err = io.Copy(tf, t)
tf.Close()
if err != nil {
return err
}
}
}
}
// Retry will call 'fn' 'tries' times, waiting 'durationBetweenAttempts'
// between each attempt, returning 'nil' the first time that 'fn' returns nil.
// If 'nil' is never returned, then the final error returned by 'fn' is
// returned.
func Retry(tries int, durationBetweenAttempts time.Duration, fn func() error) (err error) {
for i := 1; i < tries; i++ {
err = fn()
if err == nil {
return nil
}
time.Sleep(durationBetweenAttempts)
}
return fn()
}
|