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:
parent
a849edf19a
commit
42ea4d257b
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user