From b4f6d4000192914d7bded248b2eceb725008c74e Mon Sep 17 00:00:00 2001 From: "Billie H. Cleek" Date: Fri, 9 Sep 2016 08:38:50 -0700 Subject: [PATCH] allow ssh communicator's Upload fastpath to execute Add os.FileInfo implementation to packer/rpc, and use it to pass Upload's *os.FileInfo argument through the RPC boundary. --- packer/rpc/communicator.go | 12 ++++++++- packer/rpc/fileinfo.go | 33 +++++++++++++++++++++++++ packer/rpc/fileinfo_test.go | 49 +++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 packer/rpc/fileinfo.go create mode 100644 packer/rpc/fileinfo_test.go diff --git a/packer/rpc/communicator.go b/packer/rpc/communicator.go index 8e1852cf6..f52bd30d4 100644 --- a/packer/rpc/communicator.go +++ b/packer/rpc/communicator.go @@ -44,6 +44,7 @@ type CommunicatorDownloadArgs struct { type CommunicatorUploadArgs struct { Path string ReaderStreamId uint32 + FileInfo *fileInfo } type CommunicatorUploadDirArgs struct { @@ -121,6 +122,10 @@ func (c *communicator) Upload(path string, r io.Reader, fi *os.FileInfo) (err er ReaderStreamId: streamId, } + if fi != nil { + args.FileInfo = NewFileInfo(*fi) + } + err = c.client.Call("Communicator.Upload", &args, new(interface{})) return } @@ -267,7 +272,12 @@ func (c *CommunicatorServer) Upload(args *CommunicatorUploadArgs, reply *interfa } defer readerC.Close() - err = c.c.Upload(args.Path, readerC, nil) + var fi *os.FileInfo + if args.FileInfo != nil { + fi = new(os.FileInfo) + *fi = *args.FileInfo + } + err = c.c.Upload(args.Path, readerC, fi) return } diff --git a/packer/rpc/fileinfo.go b/packer/rpc/fileinfo.go new file mode 100644 index 000000000..299a93138 --- /dev/null +++ b/packer/rpc/fileinfo.go @@ -0,0 +1,33 @@ +package rpc + +import ( + "os" + "time" +) + +func NewFileInfo(fi os.FileInfo) *fileInfo { + if fi == nil { + return nil + } + + return &fileInfo{N: fi.Name(), S: fi.Size(), M: fi.Mode(), T: fi.ModTime()} +} + +type fileInfo struct { + N string + S int64 + M os.FileMode + T time.Time +} + +func (fi fileInfo) Name() string { return fi.N } +func (fi fileInfo) Size() int64 { return fi.S } +func (fi fileInfo) Mode() os.FileMode { return fi.M } +func (fi fileInfo) ModTime() time.Time { + if fi.T.IsZero() { + return time.Now() + } + return fi.T +} +func (fi fileInfo) IsDir() bool { return fi.M.IsDir() } +func (fi fileInfo) Sys() interface{} { return nil } diff --git a/packer/rpc/fileinfo_test.go b/packer/rpc/fileinfo_test.go new file mode 100644 index 000000000..8eefd0f57 --- /dev/null +++ b/packer/rpc/fileinfo_test.go @@ -0,0 +1,49 @@ +package rpc + +import ( + "os" + "testing" + "time" +) + +type dummyFileInfo struct{} + +func (fi dummyFileInfo) Name() string { return "dummy" } +func (fi dummyFileInfo) Size() int64 { return 64 } +func (fi dummyFileInfo) Mode() os.FileMode { return 0644 } +func (fi dummyFileInfo) ModTime() time.Time { + return time.Time{}.Add(1 * time.Minute) +} +func (fi dummyFileInfo) IsDir() bool { return false } +func (fi dummyFileInfo) Sys() interface{} { return nil } +func TestNewFileInfoNilPointer(t *testing.T) { + fi := NewFileInfo(os.FileInfo(nil)) + if fi != nil { + t.Fatalf("should be nil") + } +} + +func TestNewFileInfoValues(t *testing.T) { + in := dummyFileInfo{} + fi := NewFileInfo(in) + + if fi.Size() != in.Size() { + t.Errorf("fi.Size() = %d; want %d", fi.Size(), in.Size()) + } + + if fi.Name() != in.Name() { + t.Errorf("fi.Name() = %s; want %s", fi.Name(), in.Name()) + } + + if fi.Mode() != in.Mode() { + t.Errorf("fi.Mode() = %#o; want %#o", fi.Mode(), in.Mode()) + } + + if fi.ModTime() != in.ModTime() { + t.Errorf("fi.ModTime() = %s; want %s", fi.ModTime(), in.ModTime()) + } + + if fi.IsDir() != in.IsDir() { + t.Errorf("fi.IsDir() = %t; want %t", fi.IsDir(), in.IsDir()) + } +}