mirror of
https://github.com/octoleo/restic.git
synced 2024-11-26 06:46:34 +00:00
Merge pull request #2206 from garrmcnu/fs-stdin-directory
fs: Handle absolute pathname for --stdin-filename
This commit is contained in:
commit
5bd5db4294
6
changelog/unreleased/issue-2063
Normal file
6
changelog/unreleased/issue-2063
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Bugfix: Allow absolute path for filename when backing up from stdin
|
||||||
|
|
||||||
|
When backing up from stdin, handle directory path for `--stdin-filename`.
|
||||||
|
This can be used to specify the full path for the backed-up file.
|
||||||
|
|
||||||
|
https://github.com/restic/restic/issues/2063
|
@ -8,6 +8,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -523,13 +524,14 @@ func runBackup(opts BackupOptions, gopts GlobalOptions, term *termstatus.Termina
|
|||||||
if !gopts.JSON {
|
if !gopts.JSON {
|
||||||
p.V("read data from stdin")
|
p.V("read data from stdin")
|
||||||
}
|
}
|
||||||
|
filename := path.Join("/", opts.StdinFilename)
|
||||||
targetFS = &fs.Reader{
|
targetFS = &fs.Reader{
|
||||||
ModTime: timeStamp,
|
ModTime: timeStamp,
|
||||||
Name: opts.StdinFilename,
|
Name: filename,
|
||||||
Mode: 0644,
|
Mode: 0644,
|
||||||
ReadCloser: os.Stdin,
|
ReadCloser: os.Stdin,
|
||||||
}
|
}
|
||||||
targets = []string{opts.StdinFilename}
|
targets = []string{filename}
|
||||||
}
|
}
|
||||||
|
|
||||||
sc := archiver.NewScanner(targetFS)
|
sc := archiver.NewScanner(targetFS)
|
||||||
|
@ -103,17 +103,32 @@ func (fs *Reader) Stat(name string) (os.FileInfo, error) {
|
|||||||
// describes the symbolic link. Lstat makes no attempt to follow the link.
|
// describes the symbolic link. Lstat makes no attempt to follow the link.
|
||||||
// If there is an error, it will be of type *PathError.
|
// If there is an error, it will be of type *PathError.
|
||||||
func (fs *Reader) Lstat(name string) (os.FileInfo, error) {
|
func (fs *Reader) Lstat(name string) (os.FileInfo, error) {
|
||||||
|
getDirInfo := func(name string) os.FileInfo {
|
||||||
|
fi := fakeFileInfo{
|
||||||
|
name: fs.Base(name),
|
||||||
|
size: 0,
|
||||||
|
mode: os.ModeDir | 0755,
|
||||||
|
modtime: time.Now(),
|
||||||
|
}
|
||||||
|
return fi
|
||||||
|
}
|
||||||
|
|
||||||
switch name {
|
switch name {
|
||||||
case fs.Name:
|
case fs.Name:
|
||||||
return fs.fi(), nil
|
return fs.fi(), nil
|
||||||
case "/", ".":
|
case "/", ".":
|
||||||
fi := fakeFileInfo{
|
return getDirInfo(name), nil
|
||||||
name: name,
|
|
||||||
size: 0,
|
|
||||||
mode: 0755,
|
|
||||||
modtime: time.Now(),
|
|
||||||
}
|
}
|
||||||
return fi, nil
|
|
||||||
|
dir := fs.Dir(fs.Name)
|
||||||
|
for {
|
||||||
|
if dir == "/" || dir == "." {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if name == dir {
|
||||||
|
return getDirInfo(name), nil
|
||||||
|
}
|
||||||
|
dir = fs.Dir(dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, os.ErrNotExist
|
return nil, os.ErrNotExist
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@ -151,8 +152,8 @@ func verifyDirectoryContentsFI(t testing.TB, fs FS, dir string, want []os.FileIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
func checkFileInfo(t testing.TB, fi os.FileInfo, filename string, modtime time.Time, mode os.FileMode, isdir bool) {
|
func checkFileInfo(t testing.TB, fi os.FileInfo, filename string, modtime time.Time, mode os.FileMode, isdir bool) {
|
||||||
if fi.IsDir() {
|
if fi.IsDir() != isdir {
|
||||||
t.Errorf("IsDir returned true, want false")
|
t.Errorf("IsDir returned %t, want %t", fi.IsDir(), isdir)
|
||||||
}
|
}
|
||||||
|
|
||||||
if fi.Mode() != mode {
|
if fi.Mode() != mode {
|
||||||
@ -163,8 +164,12 @@ func checkFileInfo(t testing.TB, fi os.FileInfo, filename string, modtime time.T
|
|||||||
t.Errorf("ModTime() returned wrong value, want %v, got %v", modtime, fi.ModTime())
|
t.Errorf("ModTime() returned wrong value, want %v, got %v", modtime, fi.ModTime())
|
||||||
}
|
}
|
||||||
|
|
||||||
if fi.Name() != filename {
|
if path.Base(fi.Name()) != fi.Name() {
|
||||||
t.Errorf("Name() returned wrong value, want %q, got %q", filename, fi.Name())
|
t.Errorf("Name() returned is not base, want %q, got %q", path.Base(fi.Name()), fi.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
if fi.Name() != path.Base(filename) {
|
||||||
|
t.Errorf("Name() returned wrong value, want %q, got %q", path.Base(filename), fi.Name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +270,7 @@ func TestFSReader(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFileInfo(t, fi, "/", time.Time{}, 0755, false)
|
checkFileInfo(t, fi, "/", time.Time{}, os.ModeDir|0755, true)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -276,7 +281,16 @@ func TestFSReader(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFileInfo(t, fi, ".", time.Time{}, 0755, false)
|
checkFileInfo(t, fi, ".", time.Time{}, os.ModeDir|0755, true)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "dir/Lstat-error-not-exist",
|
||||||
|
f: func(t *testing.T, fs FS) {
|
||||||
|
_, err := fs.Lstat("other")
|
||||||
|
if err != os.ErrNotExist {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -287,7 +301,7 @@ func TestFSReader(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFileInfo(t, fi, "/", time.Time{}, 0755, false)
|
checkFileInfo(t, fi, "/", time.Time{}, os.ModeDir|0755, true)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -298,7 +312,7 @@ func TestFSReader(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFileInfo(t, fi, ".", time.Time{}, 0755, false)
|
checkFileInfo(t, fi, ".", time.Time{}, os.ModeDir|0755, true)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -319,6 +333,54 @@ func TestFSReader(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFSReaderDir(t *testing.T) {
|
||||||
|
data := test.Random(55, 1<<18+588)
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
var tests = []struct {
|
||||||
|
name string
|
||||||
|
filename string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Lstat-absolute",
|
||||||
|
filename: "/path/to/foobar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Lstat-relative",
|
||||||
|
filename: "path/to/foobar",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
fs := &Reader{
|
||||||
|
Name: test.filename,
|
||||||
|
ReadCloser: ioutil.NopCloser(bytes.NewReader(data)),
|
||||||
|
|
||||||
|
Mode: 0644,
|
||||||
|
Size: int64(len(data)),
|
||||||
|
ModTime: now,
|
||||||
|
}
|
||||||
|
|
||||||
|
dir := path.Dir(fs.Name)
|
||||||
|
for {
|
||||||
|
if dir == "/" || dir == "." {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
fi, err := fs.Lstat(dir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
checkFileInfo(t, fi, dir, time.Time{}, os.ModeDir|0755, true)
|
||||||
|
|
||||||
|
dir = path.Dir(dir)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestFSReaderMinFileSize(t *testing.T) {
|
func TestFSReaderMinFileSize(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
name string
|
name string
|
||||||
|
Loading…
Reference in New Issue
Block a user