diff --git a/checksum.go b/checksum.go index 705d5576d..d10ab2c0b 100644 --- a/checksum.go +++ b/checksum.go @@ -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 { diff --git a/client.go b/client.go index 7a43d492e..a6a1bf2bd 100644 --- a/client.go +++ b/client.go @@ -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 @@ -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 @@ -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 @@ -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 { @@ -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 } } diff --git a/client_option_progress_test.go b/client_option_progress_test.go index a7b644dc2..8309f9091 100644 --- a/client_option_progress_test.go +++ b/client_option_progress_test.go @@ -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) @@ -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) diff --git a/cmd/go-getter/main.go b/cmd/go-getter/main.go index 9c03f1ec2..9c52d6bf6 100644 --- a/cmd/go-getter/main.go +++ b/cmd/go-getter/main.go @@ -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) diff --git a/get.go b/get.go index 5f9ce7afd..c82f52f05 100644 --- a/get.go +++ b/get.go @@ -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 @@ -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) } @@ -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) } @@ -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) } diff --git a/get_file.go b/get_file.go index eccd41210..f11d13ecf 100644 --- a/get_file.go +++ b/get_file.go @@ -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 @@ -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 { @@ -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() @@ -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 diff --git a/get_file_symlink_windows.go b/get_file_symlink_windows.go index 5b8032a2a..dd0b7fe84 100644 --- a/get_file_symlink_windows.go +++ b/get_file_symlink_windows.go @@ -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() @@ -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) -} diff --git a/get_file_test.go b/get_file_test.go index 02fa03419..f18fe8d57 100644 --- a/get_file_test.go +++ b/get_file_test.go @@ -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") } } diff --git a/get_gcs.go b/get_gcs.go index f81913890..a1c6409c1 100644 --- a/get_gcs.go +++ b/get_gcs.go @@ -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) @@ -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 { diff --git a/get_gcs_test.go b/get_gcs_test.go index 54b16b09d..9874cd305 100644 --- a/get_gcs_test.go +++ b/get_gcs_test.go @@ -122,41 +122,41 @@ 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) @@ -164,13 +164,13 @@ func TestGCSGetter_ClientMode_notfound(t *testing.T) { // 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") } } diff --git a/get_git.go b/get_git.go index e236067bc..4a0b044f7 100644 --- a/get_git.go +++ b/get_git.go @@ -28,8 +28,8 @@ type GitGetter struct { var defaultBranchRegexp = regexp.MustCompile(`\s->\sorigin/(.*)`) -func (g *GitGetter) ClientMode(_ context.Context, u *url.URL) (ClientMode, error) { - return ClientModeDir, nil +func (g *GitGetter) Mode(_ context.Context, u *url.URL) (Mode, error) { + return ModeDir, nil } func (g *GitGetter) Get(ctx context.Context, req *Request) error { diff --git a/get_git_test.go b/get_git_test.go index fde606863..eedba0ed4 100644 --- a/get_git_test.go +++ b/get_git_test.go @@ -409,7 +409,7 @@ func TestGitGetter_sshSCPStyle(t *testing.T) { Dst: dst, Pwd: ".", - Mode: ClientModeDir, + Mode: ModeDir, } client := &Client{ Detectors: []Detector{ @@ -452,7 +452,7 @@ func TestGitGetter_sshExplicitPort(t *testing.T) { Dst: dst, Pwd: ".", - Mode: ClientModeDir, + Mode: ModeDir, } client := &Client{ @@ -496,7 +496,7 @@ func TestGitGetter_sshSCPStyleInvalidScheme(t *testing.T) { Dst: dst, Pwd: ".", - Mode: ClientModeDir, + Mode: ModeDir, } client := &Client{ diff --git a/get_hg.go b/get_hg.go index 365c3caae..4532113e4 100644 --- a/get_hg.go +++ b/get_hg.go @@ -19,8 +19,8 @@ type HgGetter struct { getter } -func (g *HgGetter) ClientMode(ctx context.Context, _ *url.URL) (ClientMode, error) { - return ClientModeDir, nil +func (g *HgGetter) Mode(ctx context.Context, _ *url.URL) (Mode, error) { + return ModeDir, nil } func (g *HgGetter) Get(ctx context.Context, req *Request) error { diff --git a/get_http.go b/get_http.go index a80ad2502..27671b32d 100644 --- a/get_http.go +++ b/get_http.go @@ -52,11 +52,11 @@ type HttpGetter struct { Header http.Header } -func (g *HttpGetter) ClientMode(ctx context.Context, u *url.URL) (ClientMode, error) { +func (g *HttpGetter) Mode(ctx context.Context, u *url.URL) (Mode, error) { if strings.HasSuffix(u.Path, "/") { - return ClientModeDir, nil + return ModeDir, nil } - return ClientModeFile, nil + return ModeFile, nil } func (g *HttpGetter) Get(ctx context.Context, req *Request) error { @@ -117,9 +117,9 @@ func (g *HttpGetter) Get(ctx context.Context, req *Request) error { // into a temporary directory, then copy over the proper subdir. source, subDir := SourceDirSubdir(source) req = &Request{ - Dir: true, - Src: source, - Dst: req.Dst, + Mode: ModeDir, + Src: source, + Dst: req.Dst, } if subDir == "" { _, err = DefaultClient.Get(ctx, req) diff --git a/get_mock.go b/get_mock.go index 786677e35..26ea38143 100644 --- a/get_mock.go +++ b/get_mock.go @@ -47,9 +47,9 @@ func (g *MockGetter) GetFile(ctx context.Context, req *Request) error { return g.GetFileErr } -func (g *MockGetter) ClientMode(ctx context.Context, u *url.URL) (ClientMode, error) { +func (g *MockGetter) Mode(ctx context.Context, u *url.URL) (Mode, error) { if l := len(u.Path); l > 0 && u.Path[l-1:] == "/" { - return ClientModeDir, nil + return ModeDir, nil } - return ClientModeFile, nil + return ModeFile, nil } diff --git a/get_s3.go b/get_s3.go index d45962a57..77d8fb317 100644 --- a/get_s3.go +++ b/get_s3.go @@ -22,7 +22,7 @@ type S3Getter struct { getter } -func (g *S3Getter) ClientMode(ctx context.Context, u *url.URL) (ClientMode, error) { +func (g *S3Getter) Mode(ctx context.Context, u *url.URL) (Mode, error) { // Parse URL region, bucket, path, _, creds, err := g.parseUrl(u) if err != nil { @@ -47,18 +47,18 @@ func (g *S3Getter) ClientMode(ctx context.Context, u *url.URL) (ClientMode, erro for _, o := range resp.Contents { // Use file mode on exact match. if *o.Key == path { - return ClientModeFile, nil + return ModeFile, nil } // Use dir mode if child keys are found. if strings.HasPrefix(*o.Key, path+"/") { - return ClientModeDir, nil + return ModeDir, nil } } // There was no match, so just return file mode. The download is going // to fail but we will let S3 return the proper error later. - return ClientModeFile, nil + return ModeFile, nil } func (g *S3Getter) Get(ctx context.Context, req *Request) error { diff --git a/get_s3_test.go b/get_s3_test.go index 303b1ce04..67d3b5ea3 100644 --- a/get_s3_test.go +++ b/get_s3_test.go @@ -136,39 +136,39 @@ func TestS3Getter_GetFile_notfound(t *testing.T) { } } -func TestS3Getter_ClientMode_dir(t *testing.T) { +func TestS3Getter_Mode_dir(t *testing.T) { ctx := context.Background() g := new(S3Getter) // Check client mode on a key prefix with only a single key. - mode, err := g.ClientMode(ctx, + mode, err := g.Mode(ctx, testURL("https://s3.amazonaws.com/hc-oss-test/go-getter/folder")) if err != nil { t.Fatalf("err: %s", err) } - if mode != ClientModeDir { - t.Fatal("expect ClientModeDir") + if mode != ModeDir { + t.Fatal("expect ModeDir") } } -func TestS3Getter_ClientMode_file(t *testing.T) { +func TestS3Getter_Mode_file(t *testing.T) { ctx := context.Background() g := new(S3Getter) // Check client mode on a key prefix which contains sub-keys. - mode, err := g.ClientMode(ctx, + mode, err := g.Mode(ctx, testURL("https://s3.amazonaws.com/hc-oss-test/go-getter/folder/main.tf")) if err != nil { t.Fatalf("err: %s", err) } - if mode != ClientModeFile { - t.Fatal("expect ClientModeFile") + if mode != ModeFile { + t.Fatal("expect ModeFile") } } -func TestS3Getter_ClientMode_notfound(t *testing.T) { +func TestS3Getter_Mode_notfound(t *testing.T) { ctx := context.Background() g := new(S3Getter) @@ -178,30 +178,30 @@ func TestS3Getter_ClientMode_notfound(t *testing.T) { // can return an appropriate error later on. This also checks that the // prefix is handled properly (e.g., "/fold" and "/folder" don't put the // client mode into "dir". - mode, err := g.ClientMode(ctx, + mode, err := g.Mode(ctx, testURL("https://s3.amazonaws.com/hc-oss-test/go-getter/fold")) if err != nil { t.Fatalf("err: %s", err) } - if mode != ClientModeFile { - t.Fatal("expect ClientModeFile") + if mode != ModeFile { + t.Fatal("expect ModeFile") } } -func TestS3Getter_ClientMode_collision(t *testing.T) { +func TestS3Getter_Mode_collision(t *testing.T) { ctx := context.Background() g := new(S3Getter) // Check that the client mode is "file" if there is both an object and a // folder with a common prefix (i.e., a "collision" in the namespace). - mode, err := g.ClientMode(ctx, + mode, err := g.Mode(ctx, testURL("https://s3.amazonaws.com/hc-oss-test/go-getter/collision/foo")) if err != nil { t.Fatalf("err: %s", err) } - if mode != ClientModeFile { - t.Fatal("expect ClientModeFile") + if mode != ModeFile { + t.Fatal("expect ModeFile") } } diff --git a/get_test.go b/get_test.go index 8a23b47eb..7b35dd02d 100644 --- a/get_test.go +++ b/get_test.go @@ -99,10 +99,10 @@ func TestGet_fileDetect(t *testing.T) { } req := &Request{ - Src: u, - Dst: dst, - Pwd: pwd, - Dir: true, + Src: u, + Dst: dst, + Pwd: pwd, + Mode: ModeAny, } client := &Client{} @@ -261,7 +261,7 @@ func TestGet_archiveSubdirWildMultiMatch(t *testing.T) { t.Fatalf("err: %s", err) } if op != nil { - t.Fatal("operation should be nil") + t.Fatal("GetResult should be nil") } } } @@ -583,9 +583,9 @@ func TestGetFile_checksumURL(t *testing.T) { getter := &MockGetter{Proxy: new(FileGetter)} req := &Request{ - Src: u, - Dst: dst, - Dir: false, + Src: u, + Dst: dst, + Mode: ModeFile, } client := &Client{ Getters: map[string]Getter{ @@ -638,9 +638,9 @@ func TestGetFile_checksumSkip(t *testing.T) { getter := &MockGetter{Proxy: new(FileGetter)} req := &Request{ - Src: u, - Dst: dst, - Dir: false, + Src: u, + Dst: dst, + Mode: ModeFile, } client := &Client{ Getters: map[string]Getter{ @@ -677,3 +677,86 @@ func TestGetFile_checksumSkip(t *testing.T) { t.Fatalf("get should not have been called") } } + +func TestGetFile_inplace(t *testing.T) { + ctx := context.Background() + + dst := tempTestFile(t) + defer os.RemoveAll(filepath.Dir(dst)) + src := testModule("basic-file/foo.txt") + + getter := &MockGetter{Proxy: new(FileGetter)} + req := &Request{ + Src: src + "?checksum=md5:09f7e02f1290be211da707a266f153b3", + Dst: dst, + Mode: ModeFile, + Inplace: true, + } + client := &Client{ + Getters: map[string]Getter{ + "file": getter, + }, + } + + // get the file + op, err := client.Get(ctx, req) + if err != nil { + t.Fatalf("err: %s", err) + } + if diff := cmp.Diff(&GetResult{Dst: strings.ReplaceAll(src, "file://", "")}, op); diff != "" { + t.Fatalf("unexpected op: %s", diff) + } + + if v := getter.GetFileURL.Query().Get("checksum"); v != "" { + t.Fatalf("bad: %s", v) + } + + // remove proxy file getter and reset GetFileCalled so that we can re-test. + getter.Proxy = nil + getter.GetFileCalled = false + + op, err = client.Get(ctx, req) + if err != nil { + t.Fatalf("err: %s", err) + } + if diff := cmp.Diff(&GetResult{Dst: strings.ReplaceAll(src, "file://", "")}, op); diff != "" { + t.Fatalf("unexpected op: %s", diff) + } + + if getter.GetFileCalled { + t.Fatalf("get should not have been called") + } +} + +func TestGetFile_inplace_badChecksum(t *testing.T) { + ctx := context.Background() + + dst := tempTestFile(t) + defer os.RemoveAll(filepath.Dir(dst)) + src := testModule("basic-file/foo.txt") + + getter := &MockGetter{Proxy: new(FileGetter)} + req := &Request{ + Src: src + "?checksum=md5:09f7e02f1290be211da707a266f153b4", + Dst: dst, + Mode: ModeFile, + Inplace: true, + } + client := &Client{ + Getters: map[string]Getter{ + "file": getter, + }, + } + + // get the file + op, err := client.Get(ctx, req) + if err == nil { + t.Fatalf("err is nil") + } + if _, ok := err.(*ChecksumError); !ok { + t.Fatalf("err is not a checksum error: %v", err) + } + if op != nil { + t.Fatalf("op is not nil") + } +} diff --git a/go.mod b/go.mod index 30606f9b8..495d5ad72 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/cheggaaa/pb v1.0.27 github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.7.0 // indirect + github.com/google/go-cmp v0.3.0 github.com/hashicorp/go-cleanhttp v0.5.0 github.com/hashicorp/go-safetemp v1.0.0 github.com/hashicorp/go-version v1.1.0 diff --git a/client_mode.go b/mode.go similarity index 53% rename from client_mode.go rename to mode.go index 7f02509a7..c9fd2d9c7 100644 --- a/client_mode.go +++ b/mode.go @@ -1,24 +1,24 @@ package getter -// ClientMode is the mode that the client operates in. -type ClientMode uint +// Mode is the mode that the client operates in. +type Mode uint const ( - ClientModeInvalid ClientMode = iota + ModeInvalid Mode = iota - // ClientModeAny downloads anything it can. In this mode, dst must + // ModeAny downloads anything it can. In this mode, dst must // be a directory. If src is a file, it is saved into the directory // with the basename of the URL. If src is a directory or archive, // it is unpacked directly into dst. - ClientModeAny + ModeAny - // ClientModeFile downloads a single file. In this mode, dst must + // ModeFile downloads a single file. In this mode, dst must // be a file path (doesn't have to exist). src must point to a single // file. It is saved as dst. - ClientModeFile + ModeFile - // ClientModeDir downloads a directory. In this mode, dst must be + // ModeDir downloads a directory. In this mode, dst must be // a directory path (doesn't have to exist). src must point to an // archive or directory (such as in s3). - ClientModeDir + ModeDir ) diff --git a/request.go b/request.go index a93d2ba33..f8f24d592 100644 --- a/request.go +++ b/request.go @@ -16,9 +16,9 @@ type Request struct { Dst string Pwd string - // Mode is the method of download the client will use. See ClientMode + // Mode is the method of download the client will use. See Mode // for documentation. - Mode ClientMode + Mode Mode // Copy, in local file mode if set to true, will copy data instead of using // a symlink. If false, attempts to symlink to speed up the operation and @@ -26,13 +26,10 @@ type Request struct { // on windows. Copy bool - // Dir, if true, tells the Client it is downloading a directory (versus - // a single file). This distinction is necessary since filenames and - // directory names follow the same format so disambiguating is impossible - // without knowing ahead of time. - // - // WARNING: deprecated. If Mode is set, that will take precedence. - Dir bool + // Inplace, in local file mode if set to true, do nothing and the returned + // operation will simply contain the source file path. Inplace has precedence + // over Copy. + Inplace bool // ProgressListener allows to track file downloads. // By default a no op progress listener is used.