-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: #29 #52
fix: #29 #52
Changes from 2 commits
2879abe
74ec421
8cfd807
5982eaf
8578fb7
8a81798
d2d58f1
4adf122
fa73318
9c34f4e
0eb5cc9
ce976d2
b76c79d
72d09cd
cb6d42d
d722b51
a68cabe
b5bb463
0355c56
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,10 +7,12 @@ import ( | |
"compress/gzip" | ||
"context" | ||
"encoding/hex" | ||
"errors" | ||
"fmt" | ||
"io" | ||
"io/ioutil" | ||
"math/rand" | ||
"net/url" | ||
"os" | ||
"os/exec" | ||
"path" | ||
|
@@ -22,6 +24,16 @@ import ( | |
"github.com/ulikunitz/xz" | ||
) | ||
|
||
// Errors | ||
// | ||
var ( | ||
ErrExists = errors.New("file already exist") | ||
ErrNotExists = errors.New("file doesn't exist") | ||
ErrInvalidPath = errors.New("file path invalid") | ||
ErrIsDir = errors.New("path is a directory") | ||
ErrInvalidURL = errors.New("invalid url") | ||
) | ||
|
||
//GzipFile takes the path to a file and returns a Gzip comppressed byte slice | ||
func GzipFile(path string) ([]byte, error) { | ||
var buf bytes.Buffer | ||
|
@@ -316,14 +328,25 @@ func GetBaseName(filename string) string { | |
|
||
// Getter gets a directory or file using the Hashicorp go-getter library | ||
// See https://github.com/hashicorp/go-getter | ||
func Getter(url, dst string) error { | ||
func Getter(source, dst string) error { | ||
|
||
// Validate the URL first. | ||
url, err := url.ParseRequestURI(source) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
pwd, _ := os.Getwd() | ||
|
||
// If the destination is empty, | ||
// choose the current working directory. | ||
if dst == "" { | ||
dst, _ = os.Getwd() | ||
} | ||
|
||
stashed := false | ||
if Exists(dst + "/.git") { | ||
cmd := exec.Command("git", "stash") | ||
cmd.Dir = pwd | ||
|
||
cmd.Dir = dst | ||
cmd.Stderr = os.Stderr | ||
cmd.Stdout = os.Stdout | ||
|
@@ -335,14 +358,16 @@ func Getter(url, dst string) error { | |
} | ||
client := &getter.Client{ | ||
Ctx: context.TODO(), | ||
Src: url, | ||
Src: source, | ||
Dst: dst, | ||
Pwd: pwd, | ||
Mode: getter.ClientModeDir, | ||
Options: []getter.ClientOption{}, | ||
} | ||
|
||
logger.Infof("Downloading %s -> %s", url, dst) | ||
err := client.Get() | ||
err = client.Get() | ||
|
||
if stashed { | ||
cmd := exec.Command("git", "stash", "pop") | ||
cmd.Dir = dst | ||
|
@@ -359,3 +384,79 @@ func TempFileName(prefix, suffix string) string { | |
rand.Read(randBytes) | ||
return filepath.Join(os.TempDir(), prefix+hex.EncodeToString(randBytes)+suffix) | ||
} | ||
|
||
// Resolve File | ||
// | ||
// If file location passed as argument is a valid, | ||
// then it returns the contents of the file. | ||
// Otherwise, an error. | ||
func ResolveFile(file string) (string, error) { | ||
|
||
var payload string | ||
|
||
// Ensure it is a valid file path, | ||
// by ensuring there an extension suffixed at the end. | ||
// | ||
// This will validate both a file in the filesystem, | ||
// as well as the URL source for a file. | ||
if filepath.Ext(file) == "" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does a file or URL need an extension?
And likewise There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aah, I only added the extension check to return an error if its a directory instead of a file. I totally forgot about files like |
||
return payload, ErrInvalidPath | ||
} | ||
|
||
// Try to parse the file as a URL, | ||
// and go-get the file if it a valid URL. | ||
// | ||
// For some reason, this inbuilt parser is broken | ||
// and it even matches relative paths that need not be URLs. | ||
// But we still need to parse the URL so that we can | ||
// validate the scheme to detect a URL. | ||
url, err := url.ParseRequestURI(file) | ||
|
||
// Ensure the scheme is HTTP or HTTPS. | ||
if err == nil && | ||
url.Scheme != "" && | ||
(strings.ToLower(url.Scheme) == "http" || | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about the other schemes supported by go-getter ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I only added the scheme check because FS files came with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, wait! I didn't know that This calls for changing the entire function code now. Apologies for this mishap! I'll get this done. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @moshloop, should I add an extra argument for the destination to where we have to resolve the file? The issue description doesn't mention it, that's why I am asking. In absence of a valid destination, I'll initialize a temporary directory to resolve the files over there. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pushed new changes. Supports all |
||
strings.ToLower(url.Scheme) == "https") { | ||
|
||
// Try to go-get the file. | ||
return payload, Getter(filepath.Dir(file), "") | ||
} | ||
|
||
// Since, it is not a URL, | ||
// we must validate as a source in the filesystem. | ||
|
||
// Ensure the file exists. | ||
if !Exists(file) { | ||
return payload, ErrNotExists | ||
} | ||
|
||
data, err := os.ReadFile(file) | ||
if err != nil { | ||
return payload, err | ||
} | ||
|
||
// Update the response payload. | ||
payload = string(data) | ||
|
||
return payload, nil | ||
} | ||
|
||
// ResolveFiles | ||
// | ||
// Calls ResolveFile(filepath) function on an array of files. | ||
func ResolveFiles(files []string) (map[string]string, error) { | ||
|
||
var payload map[string]string | ||
|
||
for _, source := range files { | ||
|
||
response, err := ResolveFile(source) | ||
if err != nil { | ||
return nil, errors.New(strings.Join([]string{source, err.Error()}, " : ")) | ||
} | ||
|
||
payload[source] = response | ||
} | ||
|
||
return payload, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to validate the URL first? Are we sure that url.ParseRequestURI will not return an error for all URLS/URI's supported by go-getter ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you are right. I added the URI parser primarily for branching the code to handle local files and URLs separately. But then I forgot I shifted it to
ResolveFile()
function. I'm pushing the change.