diff --git a/blob/gcs.go b/blob/gcs.go index d506cde8f..3b21fa12c 100644 --- a/blob/gcs.go +++ b/blob/gcs.go @@ -10,9 +10,10 @@ "net/http" "net/http/httptest" "os" - "os/exec" "time" + "github.com/skratchdot/open-golang/open" + "golang.org/x/net/context" "golang.org/x/oauth2" "golang.org/x/oauth2/google" @@ -89,10 +90,12 @@ func (gcs *gcsStorage) PutBlock(b string, data io.ReadCloser, options PutOptions Name: gcs.getObjectNameString(b), } defer data.Close() - _, err := gcs.objectsService.Insert(gcs.BucketName, &object). - IfGenerationMatch(0). - Media(data). - Do() + + call := gcs.objectsService.Insert(gcs.BucketName, &object).Media(data) + if !options.Overwrite { + call = call.IfGenerationMatch(0) + } + _, err := call.Do() return err } @@ -328,15 +331,7 @@ func tokenFromWeb(ctx context.Context, config *oauth2.Config) (*oauth2.Token, er } func openURL(url string) error { - try := []string{"xdg-open", "google-chrome", "open"} - for _, bin := range try { - err := exec.Command(bin, url).Run() - if err == nil { - return nil - } - } - log.Printf("Error opening URL in browser.") - return fmt.Errorf("Error opening URL in browser") + return open.Start(url) } func authPrompt(url string, state string) (authenticationCode string, err error) { diff --git a/cmd/kopia/command_backup.go b/cmd/kopia/command_backup.go index c0b4b449c..4f79606f7 100644 --- a/cmd/kopia/command_backup.go +++ b/cmd/kopia/command_backup.go @@ -11,6 +11,7 @@ "os" "os/user" "path/filepath" + "runtime" "strings" "time" @@ -150,7 +151,15 @@ func getBackupUser() string { log.Fatalf("Cannot determine current user: %s", err) } - return currentUser.Username + u := currentUser.Username + if runtime.GOOS == "windows" { + if p := strings.Index(u, "\\"); p >= 0 { + // On Windows ignore domain name. + u = u[p+1:] + } + } + + return u } func getBackupHostName() string { diff --git a/cmd/kopia/command_create.go b/cmd/kopia/command_create.go index 8f327055a..2e6a9d990 100644 --- a/cmd/kopia/command_create.go +++ b/cmd/kopia/command_create.go @@ -72,7 +72,6 @@ func openStorageAndEnsureEmpty(url string) (blob.Storage, error) { } return s, nil - } func runCreateCommand(context *kingpin.ParseContext) error { diff --git a/cmd/kopia/command_genpasswd.go b/cmd/kopia/command_genpasswd.go index e691cb6c8..050f1ba77 100644 --- a/cmd/kopia/command_genpasswd.go +++ b/cmd/kopia/command_genpasswd.go @@ -8,7 +8,6 @@ "io/ioutil" "math" "net/http" - "os" "strings" "gopkg.in/alecthomas/kingpin.v2" @@ -63,27 +62,26 @@ func l33t(w string) []string { } func getWordList() ([]string, error) { - // Read the words file, that is typically 2-5MB, not a big deal. - allWords, err := ioutil.ReadFile(*genPasswordWordsSource) - if err != nil { - if os.IsNotExist(err) { - // File not found, try URL. - fmt.Printf("Downloading word list from %v ...\n", *genPasswordWordsSource) - resp, err := http.Get(*genPasswordWordsSource) - if err != nil { - return nil, err - } - defer resp.Body.Close() + var allWords []byte + var err error - allWords, err = ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - } else { + // Read the words file, that is typically 2-5MB, not a big deal. + if strings.HasPrefix(*genPasswordWordsSource, "http") { + // File not found, try URL. + fmt.Printf("Downloading word list from %v ...\n", *genPasswordWordsSource) + resp, err := http.Get(*genPasswordWordsSource) + if err != nil { return nil, err } + defer resp.Body.Close() + allWords, err = ioutil.ReadAll(resp.Body) } else { fmt.Printf("Using word list from file: %v\n", *genPasswordWordsSource) + allWords, err = ioutil.ReadFile(*genPasswordWordsSource) + } + + if err != nil { + return nil, err } words := bytes.Split(allWords, []byte("\n")) diff --git a/cmd/kopia/command_mount.go b/cmd/kopia/command_mount.go index d2fa8a774..f87a9316c 100644 --- a/cmd/kopia/command_mount.go +++ b/cmd/kopia/command_mount.go @@ -1,3 +1,5 @@ +// +build !windows + package main import ( diff --git a/cmd/kopia/config.go b/cmd/kopia/config.go index 826590864..5fd4ac8c5 100644 --- a/cmd/kopia/config.go +++ b/cmd/kopia/config.go @@ -5,13 +5,14 @@ "errors" "fmt" "io/ioutil" + "log" "os" "path/filepath" + "runtime" "strings" + "github.com/bgentry/speakeasy" "github.com/kopia/kopia/vault" - - "golang.org/x/crypto/ssh/terminal" ) var ( @@ -38,6 +39,14 @@ func mustOpenVault() *vault.Vault { } func getHomeDir() string { + if runtime.GOOS == "windows" { + home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") + if home == "" { + home = os.Getenv("USERPROFILE") + } + return home + } + return os.Getenv("HOME") } @@ -51,7 +60,13 @@ func persistVaultConfig(v *vault.Vault) error { return err } - return ioutil.WriteFile(vaultConfigFileName(), []byte(cfg), 0600) + fname := vaultConfigFileName() + log.Printf("saving configuration %v", fname) + if err := os.MkdirAll(filepath.Dir(fname), 0700); err != nil { + return err + } + + return ioutil.WriteFile(fname, []byte(cfg), 0600) } func getPersistedVaultConfig() string { @@ -128,9 +143,7 @@ func getVaultCredentials(isNew bool) (vault.Credentials, error) { } if isNew { for { - fmt.Printf("Enter password to create new vault: ") - p1, err := askPass() - fmt.Println() + p1, err := askPass("Enter password to create new vault: ") if err == errPasswordTooShort { fmt.Printf("Password too short, must be at least %v characters, you entered %v. Try again.", vault.MinPasswordLength, len(p1)) fmt.Println() @@ -139,12 +152,10 @@ func getVaultCredentials(isNew bool) (vault.Credentials, error) { if err != nil { return nil, err } - fmt.Printf("Re-enter password for verification: ") - p2, err := askPass() + p2, err := askPass("Re-enter password for verification: ") if err != nil { return nil, err } - fmt.Println() if p1 != p2 { fmt.Println("Passwords don't match!") } else { @@ -152,8 +163,7 @@ func getVaultCredentials(isNew bool) (vault.Credentials, error) { } } } else { - fmt.Printf("Enter password to open vault: ") - p1, err := askPass() + p1, err := askPass("Enter password to open vault: ") if err != nil { return nil, err } @@ -162,8 +172,8 @@ func getVaultCredentials(isNew bool) (vault.Credentials, error) { } } -func askPass() (string, error) { - b, err := terminal.ReadPassword(0) +func askPass(prompt string) (string, error) { + b, err := speakeasy.Ask(prompt) if err != nil { return "", err }