2
2
mirror of https://github.com/octoleo/restic.git synced 2024-12-23 11:28:54 +00:00

sftp: first step of conversion to Layout

This commit is contained in:
Alexander Neumann 2017-04-10 22:17:50 +02:00
parent a849edf19a
commit 42ea4d257b
3 changed files with 59 additions and 55 deletions

View File

@ -134,7 +134,7 @@ func Open(cfg Config) (*SFTP, error) {
return nil, err
}
l, err := backend.ParseLayout(sftp, cfg.Layout, defaultLayout, cfg.Path)
sftp.Layout, err = backend.ParseLayout(sftp, cfg.Layout, defaultLayout, cfg.Path)
if err != nil {
return nil, err
}
@ -146,6 +146,8 @@ func Open(cfg Config) (*SFTP, error) {
}
}
debug.Log("layout: %v\n", sftp.Layout)
sftp.Config = cfg
sftp.p = cfg.Path
return sftp, nil
@ -161,6 +163,16 @@ func (r *SFTP) ReadDir(dir string) ([]os.FileInfo, error) {
return r.c.ReadDir(dir)
}
// IsNotExist returns true if the error is caused by a not existing file.
func (r *SFTP) IsNotExist(err error) bool {
statusError, ok := err.(*sftp.StatusError)
if !ok {
return false
}
return statusError.Error() == `sftp: "No such file" (SSH_FX_NO_SUCH_FILE)`
}
func buildSSHCommand(cfg Config) (cmd string, args []string, err error) {
if cfg.Command != "" {
return SplitShellArgs(cfg.Command)
@ -184,7 +196,7 @@ func buildSSHCommand(cfg Config) (cmd string, args []string, err error) {
// Create creates an sftp backend as described by the config by running
// "ssh" with the appropriate arguments (or cfg.Command, if set).
func create(cfg Config) (*SFTP, error) {
func Create(cfg Config) (*SFTP, error) {
cmd, args, err := buildSSHCommand(cfg)
if err != nil {
return nil, err
@ -196,7 +208,7 @@ func create(cfg Config) (*SFTP, error) {
return nil, err
}
l, err := backend.ParseLayout(sftp, cfg.Layout, defaultLayout, cfg.Path)
sftp.Layout, err = backend.ParseLayout(sftp, cfg.Layout, defaultLayout, cfg.Path)
if err != nil {
return nil, err
}
@ -351,14 +363,22 @@ func (r *SFTP) Save(h restic.Handle, rd io.Reader) (err error) {
}
}
// test if new file exists
if _, err := r.c.Lstat(filename); err == nil {
return errors.Errorf("Close(): file %v already exists", filename)
// create new file
f, err := r.c.OpenFile(filename, os.O_CREATE|os.O_EXCL|os.O_WRONLY)
if err != nil {
return errors.Wrap(err, "OpenFile")
}
err := r.c.Rename(oldname, filename)
// save data
_, err = io.Copy(f, rd)
if err != nil {
return errors.Wrap(err, "Rename")
f.Close()
return errors.Wrap(err, "Write")
}
err = f.Close()
if err != nil {
return errors.Wrap(err, "Close")
}
// set mode to read-only
@ -369,28 +389,6 @@ func (r *SFTP) Save(h restic.Handle, rd io.Reader) (err error) {
err = r.c.Chmod(filename, fi.Mode()&os.FileMode(^uint32(0222)))
return errors.Wrap(err, "Chmod")
filename, tmpfile, err := r.tempFile()
if err != nil {
return err
}
n, err := io.Copy(tmpfile, rd)
if err != nil {
return errors.Wrap(err, "Write")
}
debug.Log("saved %v (%d bytes) to %v", h, n, filename)
err = tmpfile.Close()
if err != nil {
return errors.Wrap(err, "Close")
}
err = r.renameFile(filename, h)
debug.Log("save %v: rename %v: %v",
h, path.Base(filename), err)
return err
}
// Load returns a reader that yields the contents of the file at h at the

View File

@ -61,7 +61,7 @@ func init() {
return nil, err
}
cfg.Dir = tempBackendDir
cfg.Path = tempBackendDir
return sftp.Create(cfg)
}
@ -72,7 +72,7 @@ func init() {
return nil, err
}
cfg.Dir = tempBackendDir
cfg.Path = tempBackendDir
return sftp.Open(cfg)
}

View File

@ -1,46 +1,52 @@
package sftp
import "testing"
import (
"reflect"
"testing"
)
var sshcmdTests = []struct {
cfg Config
s []string
cfg Config
cmd string
args []string
}{
{
Config{User: "user", Host: "host", Dir: "dir/subdir"},
Config{User: "user", Host: "host", Path: "dir/subdir"},
"ssh",
[]string{"host", "-l", "user", "-s", "sftp"},
},
{
Config{Host: "host", Dir: "dir/subdir"},
Config{Host: "host", Path: "dir/subdir"},
"ssh",
[]string{"host", "-s", "sftp"},
},
{
Config{Host: "host:10022", Dir: "/dir/subdir"},
Config{Host: "host:10022", Path: "/dir/subdir"},
"ssh",
[]string{"host", "-p", "10022", "-s", "sftp"},
},
{
Config{User: "user", Host: "host:10022", Dir: "/dir/subdir"},
Config{User: "user", Host: "host:10022", Path: "/dir/subdir"},
"ssh",
[]string{"host", "-p", "10022", "-l", "user", "-s", "sftp"},
},
}
func TestBuildSSHCommand(t *testing.T) {
for i, test := range sshcmdTests {
cmd := buildSSHCommand(test.cfg)
failed := false
if len(cmd) != len(test.s) {
failed = true
} else {
for l := range test.s {
if test.s[l] != cmd[l] {
failed = true
break
}
for _, test := range sshcmdTests {
t.Run("", func(t *testing.T) {
cmd, args, err := buildSSHCommand(test.cfg)
if err != nil {
t.Fatal(err)
}
}
if failed {
t.Errorf("test %d: wrong cmd, want:\n %v\ngot:\n %v",
i, test.s, cmd)
}
if cmd != test.cmd {
t.Fatalf("cmd: want %v, got %v", test.cmd, cmd)
}
if !reflect.DeepEqual(test.args, args) {
t.Fatalf("wrong args, want:\n %v\ngot:\n %v", test.args, args)
}
})
}
}