sftp: Rework Open/Create

This commit is contained in:
Alexander Neumann 2017-04-10 22:41:20 +02:00
parent ae290ab374
commit 27ce6a85e9

View file

@ -118,13 +118,17 @@ func (r *SFTP) clientError() error {
return nil return nil
} }
// open opens an sftp backend. When the command is started via // Open opens an sftp backend as described by the config by running
// exec.Command, it is expected to speak sftp on stdin/stdout. The backend // "ssh" with the appropriate arguments (or cfg.Command, if set).
// is expected at the given path. `dir` must be delimited by forward slashes func Open(cfg Config) (*SFTP, error) {
// ("/"), which is required by sftp. debug.Log("open backend with config %#v", cfg)
func open(dir string, program string, args ...string) (*SFTP, error) {
debug.Log("open backend with program %v, %v at %v", program, args, dir) cmd, args, err := buildSSHCommand(cfg)
sftp, err := startClient(program, args...) if err != nil {
return nil, err
}
sftp, err := startClient(cmd, args...)
if err != nil { if err != nil {
debug.Log("unable to start program: %v", err) debug.Log("unable to start program: %v", err)
return nil, err return nil, err
@ -136,19 +140,36 @@ func open(dir string, program string, args ...string) (*SFTP, error) {
} }
// test if all necessary dirs and files are there // test if all necessary dirs and files are there
for _, d := range paths(dir) { for _, d := range paths(cfg.Path) {
if _, err := sftp.c.Lstat(d); err != nil { if _, err := sftp.c.Lstat(d); err != nil {
return nil, errors.Errorf("%s does not exist", d) return nil, errors.Errorf("%s does not exist", d)
} }
} }
sftp.p = dir sftp.Config = cfg
sftp.p = cfg.Path
return sftp, nil return sftp, nil
} }
func buildSSHCommand(cfg Config) []string { // Join combines path components with slashes (according to the sftp spec).
func (r *SFTP) Join(p ...string) string {
return path.Join(p...)
}
// ReadDir returns the entries for a directory.
func (r *SFTP) ReadDir(dir string) ([]os.FileInfo, error) {
return r.c.ReadDir(dir)
}
func buildSSHCommand(cfg Config) (cmd string, args []string, err error) {
if cfg.Command != "" {
return SplitShellArgs(cfg.Command)
}
cmd = "ssh"
hostport := strings.Split(cfg.Host, ":") hostport := strings.Split(cfg.Host, ":")
args := []string{hostport[0]} args = []string{hostport[0]}
if len(hostport) > 1 { if len(hostport) > 1 {
args = append(args, "-p", hostport[1]) args = append(args, "-p", hostport[1])
} }
@ -158,44 +179,36 @@ func buildSSHCommand(cfg Config) []string {
} }
args = append(args, "-s") args = append(args, "-s")
args = append(args, "sftp") args = append(args, "sftp")
return args return cmd, args, nil
} }
// Open opens 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. // "ssh" with the appropriate arguments (or cfg.Command, if set).
func Open(cfg Config) (*SFTP, error) { func create(cfg Config) (*SFTP, error) {
debug.Log("config %#v", cfg) cmd, args, err := buildSSHCommand(cfg)
if cfg.Command == "" {
return open(cfg.Dir, "ssh", buildSSHCommand(cfg)...)
}
cmd, args, err := SplitShellArgs(cfg.Command)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return open(cfg.Dir, cmd, args...) sftp, err := startClient(cmd, args...)
} if err != nil {
debug.Log("unable to start program: %v", err)
return nil, err
}
// create creates all the necessary files and directories for a new sftp l, err := backend.ParseLayout(sftp, cfg.Layout, defaultLayout, cfg.Path)
// backend at dir. `dir` must be delimited by forward slashes ("/"), which is
// required by sftp.
func create(dir string, program string, args ...string) (*SFTP, error) {
debug.Log("create() %v %v", program, args)
sftp, err := startClient(program, args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// test if config file already exists // test if config file already exists
_, err = sftp.c.Lstat(Join(dir, backend.Paths.Config)) _, err = sftp.c.Lstat(Join(cfg.Path, backend.Paths.Config))
if err == nil { if err == nil {
return nil, errors.New("config file already exists") return nil, errors.New("config file already exists")
} }
// create paths for data, refs and temp blobs // create paths for data, refs and temp blobs
for _, d := range paths(dir) { for _, d := range paths(cfg.Path) {
err = sftp.mkdirAll(d, backend.Modes.Dir) err = sftp.mkdirAll(d, backend.Modes.Dir)
debug.Log("mkdirAll %v -> %v", d, err) debug.Log("mkdirAll %v -> %v", d, err)
if err != nil { if err != nil {
@ -209,23 +222,7 @@ func create(dir string, program string, args ...string) (*SFTP, error) {
} }
// open backend // open backend
return open(dir, program, args...) return Open(cfg)
}
// Create creates an sftp backend as described by the config by running
// "ssh" with the appropriate arguments.
func Create(cfg Config) (*SFTP, error) {
debug.Log("config %#v", cfg)
if cfg.Command == "" {
return create(cfg.Dir, "ssh", buildSSHCommand(cfg)...)
}
cmd, args, err := SplitShellArgs(cfg.Command)
if err != nil {
return nil, err
}
return create(cfg.Dir, cmd, args...)
} }
// Location returns this backend's location (the directory name). // Location returns this backend's location (the directory name).