Move index to index-v0.11.0.db (new format) and centralize location config

This commit is contained in:
Jakob Borg 2015-03-29 12:55:27 +02:00
parent a3cf37cb2e
commit 54752deaa1
20 changed files with 184 additions and 116 deletions

View File

@ -58,7 +58,7 @@ func init() {
func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) error { func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) error {
var err error var err error
cert, err := loadCert(confDir, "https-") cert, err := tls.LoadX509KeyPair(locations[locHttpsCertFile], locations[locHttpsKeyFile])
if err != nil { if err != nil {
l.Infoln("Loading HTTPS certificate:", err) l.Infoln("Loading HTTPS certificate:", err)
l.Infoln("Creating new HTTPS certificate") l.Infoln("Creating new HTTPS certificate")
@ -71,8 +71,7 @@ func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) erro
name = tlsDefaultCommonName name = tlsDefaultCommonName
} }
newCertificate(confDir, "https-", name) cert, err = newCertificate(locations[locHttpsCertFile], locations[locHttpsKeyFile], name)
cert, err = loadCert(confDir, "https-")
} }
if err != nil { if err != nil {
return err return err

View File

@ -11,7 +11,6 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"os" "os"
"path/filepath"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -92,7 +91,7 @@ func newCsrfToken() string {
} }
func saveCsrfTokens() { func saveCsrfTokens() {
name := filepath.Join(confDir, "csrftokens.txt") name := locations[locCsrfTokens]
tmp := fmt.Sprintf("%s.tmp.%d", name, time.Now().UnixNano()) tmp := fmt.Sprintf("%s.tmp.%d", name, time.Now().UnixNano())
f, err := os.OpenFile(tmp, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644) f, err := os.OpenFile(tmp, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644)
@ -117,8 +116,7 @@ func saveCsrfTokens() {
} }
func loadCsrfTokens() { func loadCsrfTokens() {
name := filepath.Join(confDir, "csrftokens.txt") f, err := os.Open(locations[locCsrfTokens])
f, err := os.Open(name)
if err != nil { if err != nil {
return return
} }

109
cmd/syncthing/locations.go Normal file
View File

@ -0,0 +1,109 @@
// Copyright (C) 2015 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main
import (
"os"
"path/filepath"
"runtime"
"strings"
"github.com/syncthing/syncthing/internal/osutil"
)
type locationEnum string
// Use strings as keys to make printout and serialization of the locations map
// more meaningful.
const (
locConfigFile locationEnum = "config"
locCertFile = "certFile"
locKeyFile = "keyFile"
locHttpsCertFile = "httpsCertFile"
locHttpsKeyFile = "httpsKeyFile"
locDatabase = "database"
locLogFile = "logFile"
locCsrfTokens = "csrfTokens"
locPanicLog = "panicLog"
locDefFolder = "defFolder"
)
// Platform dependent directories
var baseDirs = map[string]string{
"config": defaultConfigDir(), // Overridden by -home flag
"home": homeDir(), // User's home directory, *not* -home flag
}
// Use the variables from baseDirs here
var locations = map[locationEnum]string{
locConfigFile: "${config}/config.xml",
locCertFile: "${config}/cert.pem",
locKeyFile: "${config}/key.pem",
locHttpsCertFile: "${config}/https-cert.pem",
locHttpsKeyFile: "${config}/https-key.pem",
locDatabase: "${config}/index-v0.11.0.db",
locLogFile: "${config}/syncthing.log", // -logfile on Windows
locCsrfTokens: "${config}/csrftokens.txt",
locPanicLog: "${config}/panic-20060102-150405.log", // passed through time.Format()
locDefFolder: "${home}/Sync",
}
// expandLocations replaces the variables in the location map with actual
// directory locations.
func expandLocations() error {
for key, dir := range locations {
for varName, value := range baseDirs {
dir = strings.Replace(dir, "${"+varName+"}", value, -1)
}
var err error
dir, err = osutil.ExpandTilde(dir)
if err != nil {
return err
}
locations[key] = dir
}
return nil
}
// defaultConfigDir returns the default configuration directory, as figured
// out by various the environment variables present on each platform, or dies
// trying.
func defaultConfigDir() string {
switch runtime.GOOS {
case "windows":
if p := os.Getenv("LocalAppData"); p != "" {
return filepath.Join(p, "Syncthing")
}
return filepath.Join(os.Getenv("AppData"), "Syncthing")
case "darwin":
dir, err := osutil.ExpandTilde("~/Library/Application Support/Syncthing")
if err != nil {
l.Fatalln(err)
}
return dir
default:
if xdgCfg := os.Getenv("XDG_CONFIG_HOME"); xdgCfg != "" {
return filepath.Join(xdgCfg, "syncthing")
}
dir, err := osutil.ExpandTilde("~/.config/syncthing")
if err != nil {
l.Fatalln(err)
}
return dir
}
}
// homeDir returns the user's home directory, or dies trying.
func homeDir() string {
home, err := osutil.ExpandTilde("~")
if err != nil {
l.Fatalln(err)
}
return home
}

View File

@ -196,17 +196,11 @@ var (
) )
func main() { func main() {
defConfDir, err := getDefaultConfDir()
if err != nil {
l.Fatalln("home:", err)
}
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
// On Windows, we use a log file by default. Setting the -logfile flag // On Windows, we use a log file by default. Setting the -logfile flag
// to the empty string disables this behavior. // to "-" disables this behavior.
logFile = filepath.Join(defConfDir, "syncthing.log") flag.StringVar(&logFile, "logfile", "", "Log file name (use \"-\" for stdout)")
flag.StringVar(&logFile, "logfile", logFile, "Log file name (blank for stdout)")
// We also add an option to hide the console window // We also add an option to hide the console window
flag.BoolVar(&noConsole, "no-console", false, "Hide console window") flag.BoolVar(&noConsole, "no-console", false, "Hide console window")
@ -226,23 +220,30 @@ func main() {
flag.BoolVar(&showVersion, "version", false, "Show version") flag.BoolVar(&showVersion, "version", false, "Show version")
flag.StringVar(&upgradeTo, "upgrade-to", upgradeTo, "Force upgrade directly from specified URL") flag.StringVar(&upgradeTo, "upgrade-to", upgradeTo, "Force upgrade directly from specified URL")
flag.Usage = usageFor(flag.CommandLine, usage, fmt.Sprintf(extraUsage, defConfDir)) flag.Usage = usageFor(flag.CommandLine, usage, fmt.Sprintf(extraUsage, baseDirs["config"]))
flag.Parse() flag.Parse()
if noConsole { if noConsole {
osutil.HideConsole() osutil.HideConsole()
} }
if confDir == "" { if confDir != "" {
// Not set as default above because the string can be really long. // Not set as default above because the string can be really long.
confDir = defConfDir baseDirs["config"] = confDir
} }
if confDir != defConfDir && filepath.Dir(logFile) == defConfDir { if runtime.GOOS == "windows" {
// The user changed the config dir with -home, but not the log file if logFile == "" {
// location. In this case we assume they meant for the logfile to // Use the default log file location
// still live in it's default location *relative to the config dir*. logFile = locations[locLogFile]
logFile = filepath.Join(confDir, "syncthing.log") } else if logFile == "-" {
// Don't use a logFile
logFile = ""
}
}
if err := expandLocations(); err != nil {
l.Fatalln(err)
} }
if showVersion { if showVersion {
@ -269,13 +270,13 @@ func main() {
} }
} }
cert, err := loadCert(dir, "") certFile, keyFile := filepath.Join(dir, "cert.pem"), filepath.Join(dir, "key.pem")
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err == nil { if err == nil {
l.Warnln("Key exists; will not overwrite.") l.Warnln("Key exists; will not overwrite.")
l.Infoln("Device ID:", protocol.NewDeviceID(cert.Certificate[0])) l.Infoln("Device ID:", protocol.NewDeviceID(cert.Certificate[0]))
} else { } else {
newCertificate(dir, "", tlsDefaultCommonName) cert, err = newCertificate(certFile, keyFile, tlsDefaultCommonName)
cert, err = loadCert(dir, "")
myID = protocol.NewDeviceID(cert.Certificate[0]) myID = protocol.NewDeviceID(cert.Certificate[0])
if err != nil { if err != nil {
l.Fatalln("load cert:", err) l.Fatalln("load cert:", err)
@ -301,17 +302,12 @@ func main() {
return return
} }
confDir, err := osutil.ExpandTilde(confDir) if info, err := os.Stat(baseDirs["config"]); err == nil && !info.IsDir() {
if err != nil { l.Fatalln("Config directory", baseDirs["config"], "is not a directory")
l.Fatalln("home:", err)
}
if info, err := os.Stat(confDir); err == nil && !info.IsDir() {
l.Fatalln("Config directory", confDir, "is not a directory")
} }
// Ensure that our home directory exists. // Ensure that our home directory exists.
ensureDir(confDir, 0700) ensureDir(baseDirs["config"], 0700)
if upgradeTo != "" { if upgradeTo != "" {
err := upgrade.ToURL(upgradeTo) err := upgrade.ToURL(upgradeTo)
@ -337,7 +333,7 @@ func main() {
if doUpgrade { if doUpgrade {
// Use leveldb database locks to protect against concurrent upgrades // Use leveldb database locks to protect against concurrent upgrades
_, err = leveldb.OpenFile(filepath.Join(confDir, "index"), &opt.Options{OpenFilesCacheCapacity: 100}) _, err = leveldb.OpenFile(locations[locDatabase], &opt.Options{OpenFilesCacheCapacity: 100})
if err != nil { if err != nil {
l.Fatalln("Cannot upgrade, database seems to be locked. Is another copy of Syncthing already running?") l.Fatalln("Cannot upgrade, database seems to be locked. Is another copy of Syncthing already running?")
} }
@ -371,13 +367,12 @@ func syncthingMain() {
runtime.GOMAXPROCS(runtime.NumCPU()) runtime.GOMAXPROCS(runtime.NumCPU())
} }
events.Default.Log(events.Starting, map[string]string{"home": confDir}) events.Default.Log(events.Starting, map[string]string{"home": baseDirs["config"]})
// Ensure that that we have a certificate and key. // Ensure that that we have a certificate and key.
cert, err = loadCert(confDir, "") cert, err = tls.LoadX509KeyPair(locations[locCertFile], locations[locKeyFile])
if err != nil { if err != nil {
newCertificate(confDir, "", tlsDefaultCommonName) cert, err = newCertificate(locations[locCertFile], locations[locKeyFile], tlsDefaultCommonName)
cert, err = loadCert(confDir, "")
if err != nil { if err != nil {
l.Fatalln("load cert:", err) l.Fatalln("load cert:", err)
} }
@ -395,7 +390,7 @@ func syncthingMain() {
// Prepare to be able to save configuration // Prepare to be able to save configuration
cfgFile := filepath.Join(confDir, "config.xml") cfgFile := locations[locConfigFile]
var myName string var myName string
@ -490,7 +485,7 @@ func syncthingMain() {
l.Infoln("Local networks:", strings.Join(networks, ", ")) l.Infoln("Local networks:", strings.Join(networks, ", "))
} }
dbFile := filepath.Join(confDir, "index") dbFile := locations[locDatabase]
dbOpts := &opt.Options{OpenFilesCacheCapacity: 100} dbOpts := &opt.Options{OpenFilesCacheCapacity: 100}
ldb, err := leveldb.OpenFile(dbFile, dbOpts) ldb, err := leveldb.OpenFile(dbFile, dbOpts)
if err != nil && errors.IsCorrupted(err) { if err != nil && errors.IsCorrupted(err) {
@ -665,16 +660,11 @@ func setupGUI(cfg *config.Wrapper, m *model.Model) {
} }
func defaultConfig(myName string) config.Configuration { func defaultConfig(myName string) config.Configuration {
defaultFolder, err := osutil.ExpandTilde("~/Sync")
if err != nil {
l.Fatalln("home:", err)
}
newCfg := config.New(myID) newCfg := config.New(myID)
newCfg.Folders = []config.FolderConfiguration{ newCfg.Folders = []config.FolderConfiguration{
{ {
ID: "default", ID: "default",
Path: defaultFolder, Path: locations[locDefFolder],
RescanIntervalS: 60, RescanIntervalS: 60,
Devices: []config.FolderDeviceConfiguration{{DeviceID: myID}}, Devices: []config.FolderDeviceConfiguration{{DeviceID: myID}},
}, },
@ -811,12 +801,7 @@ func renewUPnP(port int) {
} }
func resetFolders() { func resetFolders() {
confDir, err := osutil.ExpandTilde(confDir) cfgFile := locations[locConfigFile]
if err != nil {
log.Fatal(err)
}
cfgFile := filepath.Join(confDir, "config.xml")
cfg, err := config.Load(cfgFile, myID) cfg, err := config.Load(cfgFile, myID)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
@ -832,8 +817,7 @@ func resetFolders() {
} }
} }
idx := filepath.Join(confDir, "index") os.RemoveAll(locations[locDatabase])
os.RemoveAll(idx)
} }
func restart() { func restart() {
@ -879,25 +863,6 @@ func ensureDir(dir string, mode int) {
} }
} }
func getDefaultConfDir() (string, error) {
switch runtime.GOOS {
case "windows":
if p := os.Getenv("LocalAppData"); p != "" {
return filepath.Join(p, "Syncthing"), nil
}
return filepath.Join(os.Getenv("AppData"), "Syncthing"), nil
case "darwin":
return osutil.ExpandTilde("~/Library/Application Support/Syncthing")
default:
if xdgCfg := os.Getenv("XDG_CONFIG_HOME"); xdgCfg != "" {
return filepath.Join(xdgCfg, "syncthing"), nil
}
return osutil.ExpandTilde("~/.config/syncthing")
}
}
// getFreePort returns a free TCP port fort listening on. The ports given are // getFreePort returns a free TCP port fort listening on. The ports given are
// tried in succession and the first to succeed is returned. If none succeed, // tried in succession and the first to succeed is returned. If none succeed,
// a random high port is returned. // a random high port is returned.

View File

@ -12,7 +12,6 @@ import (
"os" "os"
"os/exec" "os/exec"
"os/signal" "os/signal"
"path/filepath"
"runtime" "runtime"
"strings" "strings"
"sync" "sync"
@ -164,7 +163,7 @@ func copyStderr(stderr io.ReadCloser, dst io.Writer) {
dst.Write([]byte(line)) dst.Write([]byte(line))
if strings.HasPrefix(line, "panic:") || strings.HasPrefix(line, "fatal error:") { if strings.HasPrefix(line, "panic:") || strings.HasPrefix(line, "fatal error:") {
panicFd, err = os.Create(filepath.Join(confDir, time.Now().Format("panic-20060102-150405.log"))) panicFd, err = os.Create(time.Now().Format(locations[locPanicLog]))
if err != nil { if err != nil {
l.Warnln("Create panic log:", err) l.Warnln("Create panic log:", err)
continue continue

View File

@ -19,7 +19,6 @@ import (
mr "math/rand" mr "math/rand"
"net" "net"
"os" "os"
"path/filepath"
"time" "time"
) )
@ -28,13 +27,7 @@ const (
tlsDefaultCommonName = "syncthing" tlsDefaultCommonName = "syncthing"
) )
func loadCert(dir string, prefix string) (tls.Certificate, error) { func newCertificate(certFile, keyFile, name string) (tls.Certificate, error) {
cf := filepath.Join(dir, prefix+"cert.pem")
kf := filepath.Join(dir, prefix+"key.pem")
return tls.LoadX509KeyPair(cf, kf)
}
func newCertificate(dir, prefix, name string) {
l.Infof("Generating RSA key and certificate for %s...", name) l.Infof("Generating RSA key and certificate for %s...", name)
priv, err := rsa.GenerateKey(rand.Reader, tlsRSABits) priv, err := rsa.GenerateKey(rand.Reader, tlsRSABits)
@ -63,7 +56,7 @@ func newCertificate(dir, prefix, name string) {
l.Fatalln("create cert:", err) l.Fatalln("create cert:", err)
} }
certOut, err := os.Create(filepath.Join(dir, prefix+"cert.pem")) certOut, err := os.Create(certFile)
if err != nil { if err != nil {
l.Fatalln("save cert:", err) l.Fatalln("save cert:", err)
} }
@ -76,7 +69,7 @@ func newCertificate(dir, prefix, name string) {
l.Fatalln("save cert:", err) l.Fatalln("save cert:", err)
} }
keyOut, err := os.OpenFile(filepath.Join(dir, prefix+"key.pem"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil { if err != nil {
l.Fatalln("save key:", err) l.Fatalln("save key:", err)
} }
@ -88,6 +81,8 @@ func newCertificate(dir, prefix, name string) {
if err != nil { if err != nil {
l.Fatalln("save key:", err) l.Fatalln("save key:", err)
} }
return tls.LoadX509KeyPair(certFile, keyFile)
} }
type DowngradingListener struct { type DowngradingListener struct {

2
test/.gitignore vendored
View File

@ -15,5 +15,5 @@ dirs-*
csrftokens.txt csrftokens.txt
s4d s4d
http http
index h*/index*
*.syncthing-reset* *.syncthing-reset*

View File

@ -17,7 +17,7 @@ import (
) )
func TestCLIReset(t *testing.T) { func TestCLIReset(t *testing.T) {
dirs := []string{"s1", "s12-1", "h1/index"} dirs := []string{"s1", "s12-1", "h1/index-v0.11.0.db"}
// Create directories that reset will remove // Create directories that reset will remove

View File

@ -18,7 +18,7 @@ import (
func TestConflict(t *testing.T) { func TestConflict(t *testing.T) {
log.Println("Cleaning...") log.Println("Cleaning...")
err := removeAll("s1", "s2", "h1/index", "h2/index") err := removeAll("s1", "s2", "h1/index*", "h2/index*")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -64,16 +64,11 @@ func TestConflict(t *testing.T) {
// startup, UPnP etc complete and make sure the sender has the full index // startup, UPnP etc complete and make sure the sender has the full index
// before they connect. // before they connect.
for i := 0; i < 20; i++ { for i := 0; i < 20; i++ {
resp, err := sender.post("/rest/scan?folder=default", nil) err := sender.rescan("default")
if err != nil { if err != nil {
time.Sleep(time.Second) time.Sleep(time.Second)
continue continue
} }
if resp.StatusCode != 200 {
resp.Body.Close()
time.Sleep(time.Second)
continue
}
break break
} }

View File

@ -61,7 +61,7 @@ func TestFileTypeChangeStaggeredVersioning(t *testing.T) {
func testFileTypeChange(t *testing.T) { func testFileTypeChange(t *testing.T) {
log.Println("Cleaning...") log.Println("Cleaning...")
err := removeAll("s1", "s2", "h1/index", "h2/index") err := removeAll("s1", "s2", "h1/index*", "h2/index*")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -3,7 +3,9 @@
<device id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU"></device> <device id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU"></device>
<device id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU"></device> <device id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU"></device>
<device id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU"></device> <device id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU"></device>
<versioning type="staggered"></versioning> <versioning type="simple">
<param key="keep" val="5"></param>
</versioning>
<lenientMtimes>false</lenientMtimes> <lenientMtimes>false</lenientMtimes>
<copiers>1</copiers> <copiers>1</copiers>
<pullers>16</pullers> <pullers>16</pullers>

View File

@ -23,7 +23,7 @@ import (
func TestStressHTTP(t *testing.T) { func TestStressHTTP(t *testing.T) {
log.Println("Cleaning...") log.Println("Cleaning...")
err := removeAll("s2", "h2/index") err := removeAll("s2", "h2/index*")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -22,7 +22,7 @@ func TestIgnores(t *testing.T) {
// Clean and start a syncthing instance // Clean and start a syncthing instance
log.Println("Cleaning...") log.Println("Cleaning...")
err := removeAll("s1", "h1/index") err := removeAll("s1", "h1/index*")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -22,7 +22,7 @@ import (
func TestManyPeers(t *testing.T) { func TestManyPeers(t *testing.T) {
log.Println("Cleaning...") log.Println("Cleaning...")
err := removeAll("s1", "s2", "h1/index", "h2/index") err := removeAll("s1", "s2", "h1/index*", "h2/index*")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -18,7 +18,7 @@ import (
func TestParallellScan(t *testing.T) { func TestParallellScan(t *testing.T) {
log.Println("Cleaning...") log.Println("Cleaning...")
err := removeAll("s1", "h1/index") err := removeAll("s1", "h1/index*")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -32,7 +32,7 @@ func TestRestartSenderAndReceiverDuringTransfer(t *testing.T) {
func testRestartDuringTransfer(t *testing.T, restartSender, restartReceiver bool, senderDelay, receiverDelay time.Duration) { func testRestartDuringTransfer(t *testing.T, restartSender, restartReceiver bool, senderDelay, receiverDelay time.Duration) {
log.Println("Cleaning...") log.Println("Cleaning...")
err := removeAll("s1", "s2", "h1/index", "h2/index") err := removeAll("s1", "s2", "h1/index*", "h2/index*")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -86,7 +86,7 @@ func TestSymlinksStaggeredVersioning(t *testing.T) {
func testSymlinks(t *testing.T) { func testSymlinks(t *testing.T) {
log.Println("Cleaning...") log.Println("Cleaning...")
err := removeAll("s1", "s2", "h1/index", "h2/index") err := removeAll("s1", "s2", "h1/index*", "h2/index*")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -79,7 +79,7 @@ func testSyncCluster(t *testing.T) {
err := removeAll("s1", "s12-1", err := removeAll("s1", "s12-1",
"s2", "s12-2", "s23-2", "s2", "s12-2", "s23-2",
"s3", "s23-3", "s3", "s23-3",
"h1/index", "h2/index", "h3/index") "h1/index*", "h2/index*", "h3/index*")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -16,7 +16,7 @@ import (
func TestBenchmarkTransfer(t *testing.T) { func TestBenchmarkTransfer(t *testing.T) {
log.Println("Cleaning...") log.Println("Cleaning...")
err := removeAll("s1", "s2", "h1/index", "h2/index") err := removeAll("s1", "s2", "h1/index*", "h2/index*")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -241,8 +241,13 @@ func (i *inifiteReader) Read(bs []byte) (int, error) {
// rm -rf // rm -rf
func removeAll(dirs ...string) error { func removeAll(dirs ...string) error {
for _, dir := range dirs { for _, dir := range dirs {
files, err := filepath.Glob(dir)
if err != nil {
return err
}
for _, file := range files {
// Set any non-writeable files and dirs to writeable. This is necessary for os.RemoveAll to work on Windows. // Set any non-writeable files and dirs to writeable. This is necessary for os.RemoveAll to work on Windows.
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { filepath.Walk(file, func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
return err return err
} }
@ -251,7 +256,8 @@ func removeAll(dirs ...string) error {
} }
return nil return nil
}) })
os.RemoveAll(dir) os.RemoveAll(file)
}
} }
return nil return nil
} }