Skip to content

Commit

Permalink
Allow to not download local files and simply reference them 'inplace'…
Browse files Browse the repository at this point in the history
… given an option, remove the 'Dir' bool option & rename ClientMode to Mode (#232)

adds the Inplace bool field to a Request allowing to use local files 'inplace' and just setting the GetResult.Dst to the source file.

This will allow Packer to not do any operation and to use big local files 'inplace'.
  • Loading branch information
azr authored Feb 4, 2020
1 parent 8bdb487 commit e5a1b1a
Show file tree
Hide file tree
Showing 21 changed files with 214 additions and 136 deletions.
6 changes: 3 additions & 3 deletions checksum.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,9 @@ func (c *Client) ChecksumFromFile(ctx context.Context, checksumURL, checksummedP

req := &Request{
// Pwd: c.Pwd, TODO(adrien): pass pwd ?
Dir: false,
Src: checksumURL,
Dst: tempfile,
Mode: ModeFile,
Src: checksumURL,
Dst: tempfile,
// ProgressListener: c.ProgressListener, TODO(adrien): pass progress bar ?
}
if _, err = c.Get(ctx, req); err != nil {
Expand Down
26 changes: 11 additions & 15 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,8 @@ func (c *Client) Get(ctx context.Context, req *Request) (*GetResult, error) {
}

// Store this locally since there are cases we swap this
if req.Mode == ClientModeInvalid {
if req.Dir {
req.Mode = ClientModeDir
} else {
req.Mode = ClientModeFile
}
if req.Mode == ModeInvalid {
req.Mode = ModeAny
}

var err error
Expand Down Expand Up @@ -140,9 +136,9 @@ func (c *Client) Get(ctx context.Context, req *Request) (*GetResult, error) {
// Swap the download directory to be our temporary path and
// store the old values.
decompressDst = req.Dst
decompressDir = req.Mode != ClientModeFile
decompressDir = req.Mode != ModeFile
req.Dst = filepath.Join(td, "archive")
req.Mode = ClientModeFile
req.Mode = ModeFile
}

// Determine checksum if we have one
Expand All @@ -155,16 +151,16 @@ func (c *Client) Get(ctx context.Context, req *Request) (*GetResult, error) {
q.Del("checksum")
req.u.RawQuery = q.Encode()

if req.Mode == ClientModeAny {
if req.Mode == ModeAny {
// Ask the getter which client mode to use
req.Mode, err = g.ClientMode(ctx, req.u)
req.Mode, err = g.Mode(ctx, req.u)
if err != nil {
return nil, err
}

// Destination is the base name of the URL path in "any" mode when
// a file source is detected.
if req.Mode == ClientModeFile {
if req.Mode == ModeFile {
filename := filepath.Base(req.u.Path)

// Determine if we have a custom file name
Expand All @@ -182,7 +178,7 @@ func (c *Client) Get(ctx context.Context, req *Request) (*GetResult, error) {

// If we're not downloading a directory, then just download the file
// and return.
if req.Mode == ClientModeFile {
if req.Mode == ModeFile {
getFile := true
if checksum != nil {
if err := checksum.checksum(req.Dst); err == nil {
Expand Down Expand Up @@ -214,16 +210,16 @@ func (c *Client) Get(ctx context.Context, req *Request) (*GetResult, error) {
// Swap the information back
req.Dst = decompressDst
if decompressDir {
req.Mode = ClientModeAny
req.Mode = ModeAny
} else {
req.Mode = ClientModeFile
req.Mode = ModeFile
}
}

// We check the dir value again because it can be switched back
// if we were unarchiving. If we're still only Get-ing a file, then
// we're done.
if req.Mode == ClientModeFile {
if req.Mode == ModeFile {
return &GetResult{req.Dst}, nil
}
}
Expand Down
2 changes: 0 additions & 2 deletions client_option_progress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ func TestGet_progress(t *testing.T) {
Dst: dst,
Src: s.URL + "/file?thig=this&that",
ProgressListener: p,
Dir: false,
}
if _, err := DefaultClient.Get(ctx, req); err != nil {
t.Fatalf("download failed: %v", err)
Expand All @@ -63,7 +62,6 @@ func TestGet_progress(t *testing.T) {
Dst: dst,
Src: s.URL + "/otherfile?thig=this&that",
ProgressListener: p,
Dir: false,
}
if _, err := DefaultClient.Get(ctx, req); err != nil {
t.Fatalf("download failed: %v", err)
Expand Down
8 changes: 4 additions & 4 deletions cmd/go-getter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ func main() {
}

// Get the mode
var mode getter.ClientMode
var mode getter.Mode
switch *modeRaw {
case "any":
mode = getter.ClientModeAny
mode = getter.ModeAny
case "file":
mode = getter.ClientModeFile
mode = getter.ModeFile
case "dir":
mode = getter.ClientModeDir
mode = getter.ModeDir
default:
log.Fatalf("Invalid client mode, must be 'any', 'file', or 'dir': %s", *modeRaw)
os.Exit(1)
Expand Down
18 changes: 9 additions & 9 deletions get.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ type Getter interface {
// the remote end contains the same file and no-op this operation.
GetFile(context.Context, *Request) error

// ClientMode returns the mode based on the given URL. This is used to
// Mode returns the mode based on the given URL. This is used to
// allow clients to let the getters decide which mode to use.
ClientMode(context.Context, *url.URL) (ClientMode, error)
Mode(context.Context, *url.URL) (Mode, error)

// SetClient allows a getter to know it's client
// in order to access client's Get functions or
Expand Down Expand Up @@ -89,9 +89,9 @@ func init() {
// folder doesn't need to exist. It will be created if it doesn't exist.
func Get(ctx context.Context, dst, src string) (*GetResult, error) {
req := &Request{
Src: src,
Dst: dst,
Dir: true,
Src: src,
Dst: dst,
Mode: ModeDir,
}
return DefaultClient.Get(ctx, req)
}
Expand All @@ -106,7 +106,7 @@ func GetAny(ctx context.Context, dst, src string) (*GetResult, error) {
req := &Request{
Src: src,
Dst: dst,
Mode: ClientModeAny,
Mode: ModeAny,
}
return DefaultClient.Get(ctx, req)
}
Expand All @@ -115,9 +115,9 @@ func GetAny(ctx context.Context, dst, src string) (*GetResult, error) {
// dst.
func GetFile(ctx context.Context, dst, src string) (*GetResult, error) {
req := &Request{
Src: src,
Dst: dst,
Dir: false,
Src: src,
Dst: dst,
Mode: ModeFile,
}
return DefaultClient.Get(ctx, req)
}
Expand Down
16 changes: 13 additions & 3 deletions get_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type FileGetter struct {
getter
}

func (g *FileGetter) ClientMode(ctx context.Context, u *url.URL) (ClientMode, error) {
func (g *FileGetter) Mode(ctx context.Context, u *url.URL) (Mode, error) {
path := u.Path
if u.RawPath != "" {
path = u.RawPath
Expand All @@ -27,10 +27,10 @@ func (g *FileGetter) ClientMode(ctx context.Context, u *url.URL) (ClientMode, er

// Check if the source is a directory.
if fi.IsDir() {
return ClientModeDir, nil
return ModeDir, nil
}

return ClientModeFile, nil
return ModeFile, nil
}

func (g *FileGetter) Get(ctx context.Context, req *Request) error {
Expand All @@ -51,6 +51,11 @@ func (g *FileGetter) Get(ctx context.Context, req *Request) error {
return err
}

if req.Inplace {
req.Dst = path
return nil
}

// If the destination already exists, it must be a symlink
if err == nil {
mode := fi.Mode()
Expand Down Expand Up @@ -85,6 +90,11 @@ func (g *FileGetter) GetFile(ctx context.Context, req *Request) error {
return fmt.Errorf("source path must be a file")
}

if req.Inplace {
req.Dst = path
return nil
}

_, err := os.Lstat(req.Dst)
if err != nil && !os.IsNotExist(err) {
return err
Expand Down
11 changes: 2 additions & 9 deletions get_file_symlink_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package getter
import (
"fmt"
"os/exec"
"strings"
"path/filepath"
"syscall"
)

func SymlinkAny(oldname, newname string) error {
sourcePath := toBackslash(oldname)
sourcePath := filepath.FromSlash(oldname)

// Use mklink to create a junction point
output, err := exec.Command("cmd", "/c", "mklink", "/J", newname, sourcePath).CombinedOutput()
Expand All @@ -19,10 +19,3 @@ func SymlinkAny(oldname, newname string) error {
}

var ErrUnauthorized = syscall.ERROR_PRIVILEGE_NOT_HELD

// toBackslash returns the result of replacing each slash character
// in path with a backslash ('\') character. Multiple separators are
// replaced by multiple backslashes.
func toBackslash(path string) string {
return strings.Replace(path, "/", "\\", -1)
}
20 changes: 10 additions & 10 deletions get_file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,40 +217,40 @@ func TestFileGetter_percent2F(t *testing.T) {
}
}

func TestFileGetter_ClientMode_notexist(t *testing.T) {
func TestFileGetter_Mode_notexist(t *testing.T) {
g := new(FileGetter)
ctx := context.Background()

u := testURL("nonexistent")
if _, err := g.ClientMode(ctx, u); err == nil {
if _, err := g.Mode(ctx, u); err == nil {
t.Fatal("expect source file error")
}
}

func TestFileGetter_ClientMode_file(t *testing.T) {
func TestFileGetter_Mode_file(t *testing.T) {
g := new(FileGetter)
ctx := context.Background()

// Check the client mode when pointed at a file.
mode, err := g.ClientMode(ctx, testModuleURL("basic-file/foo.txt"))
mode, err := g.Mode(ctx, testModuleURL("basic-file/foo.txt"))
if err != nil {
t.Fatalf("err: %s", err)
}
if mode != ClientModeFile {
t.Fatal("expect ClientModeFile")
if mode != ModeFile {
t.Fatal("expect ModeFile")
}
}

func TestFileGetter_ClientMode_dir(t *testing.T) {
func TestFileGetter_Mode_dir(t *testing.T) {
g := new(FileGetter)
ctx := context.Background()

// Check the client mode when pointed at a directory.
mode, err := g.ClientMode(ctx, testModuleURL("basic"))
mode, err := g.Mode(ctx, testModuleURL("basic"))
if err != nil {
t.Fatalf("err: %s", err)
}
if mode != ClientModeDir {
t.Fatal("expect ClientModeDir")
if mode != ModeDir {
t.Fatal("expect ModeDir")
}
}
8 changes: 4 additions & 4 deletions get_gcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type GCSGetter struct {
getter
}

func (g *GCSGetter) ClientMode(ctx context.Context, u *url.URL) (ClientMode, error) {
func (g *GCSGetter) Mode(ctx context.Context, u *url.URL) (Mode, error) {

// Parse URL
bucket, object, err := g.parseURL(u)
Expand All @@ -42,16 +42,16 @@ func (g *GCSGetter) ClientMode(ctx context.Context, u *url.URL) (ClientMode, err
}
if strings.HasSuffix(obj.Name, "/") {
// A directory matched the prefix search, so this must be a directory
return ClientModeDir, nil
return ModeDir, nil
} else if obj.Name != object {
// A file matched the prefix search and doesn't have the same name
// as the query, so this must be a directory
return ClientModeDir, nil
return ModeDir, nil
}
}
// There are no directories or subdirectories, and if a match was returned,
// it was exactly equal to the prefix search. So return File mode
return ClientModeFile, nil
return ModeFile, nil
}

func (g *GCSGetter) Get(ctx context.Context, req *Request) error {
Expand Down
24 changes: 12 additions & 12 deletions get_gcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,55 +122,55 @@ func TestGCSGetter_GetFile_notfound(t *testing.T) {
}
}

func TestGCSGetter_ClientMode_dir(t *testing.T) {
func TestGCSGetter_Mode_dir(t *testing.T) {
defer initGCPCredentials(t)()

g := new(GCSGetter)
ctx := context.Background()

// Check client mode on a key prefix with only a single key.
mode, err := g.ClientMode(ctx,
mode, err := g.Mode(ctx,
testURL("https://www.googleapis.com/storage/v1/go-getter-test/go-getter/folder/subfolder"))
if err != nil {
t.Fatalf("err: %s", err)
}
if mode != ClientModeDir {
t.Fatal("expect ClientModeDir")
if mode != ModeDir {
t.Fatal("expect ModeDir")
}
}

func TestGCSGetter_ClientMode_file(t *testing.T) {
func TestGCSGetter_Mode_file(t *testing.T) {
defer initGCPCredentials(t)()

g := new(GCSGetter)
ctx := context.Background()

// Check client mode on a key prefix which contains sub-keys.
mode, err := g.ClientMode(ctx,
mode, err := g.Mode(ctx,
testURL("https://www.googleapis.com/storage/v1/go-getter-test/go-getter/folder/subfolder/sub.tf"))
if err != nil {
t.Fatalf("err: %s", err)
}
if mode != ClientModeFile {
t.Fatal("expect ClientModeFile")
if mode != ModeFile {
t.Fatal("expect ModeFile")
}
}

func TestGCSGetter_ClientMode_notfound(t *testing.T) {
func TestGCSGetter_Mode_notfound(t *testing.T) {
defer initGCPCredentials(t)()

g := new(GCSGetter)
ctx := context.Background()

// Check the client mode when a non-existent key is looked up. This does not
// return an error, but rather should just return the file mode.
mode, err := g.ClientMode(ctx,
mode, err := g.Mode(ctx,
testURL("https://www.googleapis.com/storage/v1/go-getter-test/go-getter/foobar"))
if err != nil {
t.Fatalf("err: %s", err)
}
if mode != ClientModeFile {
t.Fatal("expect ClientModeFile")
if mode != ModeFile {
t.Fatal("expect ModeFile")
}
}

Expand Down
Loading

0 comments on commit e5a1b1a

Please sign in to comment.