mirror of
https://github.com/octoleo/restic.git
synced 2025-01-11 02:08:44 +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
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -146,6 +146,8 @@ func Open(cfg Config) (*SFTP, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug.Log("layout: %v\n", sftp.Layout)
|
||||||
|
|
||||||
sftp.Config = cfg
|
sftp.Config = cfg
|
||||||
sftp.p = cfg.Path
|
sftp.p = cfg.Path
|
||||||
return sftp, nil
|
return sftp, nil
|
||||||
@ -161,6 +163,16 @@ func (r *SFTP) ReadDir(dir string) ([]os.FileInfo, error) {
|
|||||||
return r.c.ReadDir(dir)
|
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) {
|
func buildSSHCommand(cfg Config) (cmd string, args []string, err error) {
|
||||||
if cfg.Command != "" {
|
if cfg.Command != "" {
|
||||||
return SplitShellArgs(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
|
// Create creates an sftp backend as described by the config by running
|
||||||
// "ssh" with the appropriate arguments (or cfg.Command, if set).
|
// "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)
|
cmd, args, err := buildSSHCommand(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -196,7 +208,7 @@ func create(cfg Config) (*SFTP, error) {
|
|||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -351,14 +363,22 @@ func (r *SFTP) Save(h restic.Handle, rd io.Reader) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// test if new file exists
|
// create new file
|
||||||
if _, err := r.c.Lstat(filename); err == nil {
|
f, err := r.c.OpenFile(filename, os.O_CREATE|os.O_EXCL|os.O_WRONLY)
|
||||||
return errors.Errorf("Close(): file %v already exists", filename)
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "OpenFile")
|
||||||
}
|
}
|
||||||
|
|
||||||
err := r.c.Rename(oldname, filename)
|
// save data
|
||||||
|
_, err = io.Copy(f, rd)
|
||||||
if err != nil {
|
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
|
// 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)))
|
err = r.c.Chmod(filename, fi.Mode()&os.FileMode(^uint32(0222)))
|
||||||
return errors.Wrap(err, "Chmod")
|
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
|
// Load returns a reader that yields the contents of the file at h at the
|
||||||
|
@ -61,7 +61,7 @@ func init() {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.Dir = tempBackendDir
|
cfg.Path = tempBackendDir
|
||||||
|
|
||||||
return sftp.Create(cfg)
|
return sftp.Create(cfg)
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ func init() {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.Dir = tempBackendDir
|
cfg.Path = tempBackendDir
|
||||||
|
|
||||||
return sftp.Open(cfg)
|
return sftp.Open(cfg)
|
||||||
}
|
}
|
||||||
|
@ -1,46 +1,52 @@
|
|||||||
package sftp
|
package sftp
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
var sshcmdTests = []struct {
|
var sshcmdTests = []struct {
|
||||||
cfg Config
|
cfg Config
|
||||||
s []string
|
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"},
|
[]string{"host", "-l", "user", "-s", "sftp"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Config{Host: "host", Dir: "dir/subdir"},
|
Config{Host: "host", Path: "dir/subdir"},
|
||||||
|
"ssh",
|
||||||
[]string{"host", "-s", "sftp"},
|
[]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"},
|
[]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"},
|
[]string{"host", "-p", "10022", "-l", "user", "-s", "sftp"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildSSHCommand(t *testing.T) {
|
func TestBuildSSHCommand(t *testing.T) {
|
||||||
for i, test := range sshcmdTests {
|
for _, test := range sshcmdTests {
|
||||||
cmd := buildSSHCommand(test.cfg)
|
t.Run("", func(t *testing.T) {
|
||||||
failed := false
|
cmd, args, err := buildSSHCommand(test.cfg)
|
||||||
if len(cmd) != len(test.s) {
|
if err != nil {
|
||||||
failed = true
|
t.Fatal(err)
|
||||||
} else {
|
|
||||||
for l := range test.s {
|
|
||||||
if test.s[l] != cmd[l] {
|
|
||||||
failed = true
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
if failed {
|
})
|
||||||
t.Errorf("test %d: wrong cmd, want:\n %v\ngot:\n %v",
|
|
||||||
i, test.s, cmd)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user