Skip to content
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

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ jobs:
platform: [ubuntu-latest]
go-version:
- 1.18.x
- 1.17.x
- 1.16.x
runs-on: ${{ matrix.platform }}
steps:
- name: Install Go
Expand Down
2 changes: 1 addition & 1 deletion console/progress.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func NewTextProgress(name string, localTest *TestResults) Progress {
func NewTerminalProgress(name string, localTest *TestResults, progress *mpb.Progress) Progress {
tp := &terminalProgress{test: localTest}
filler := mpb.NewSpinnerFiller(mpb.DefaultSpinnerStyle, mpb.SpinnerOnLeft)
completedFn := mpb.BarFillerFunc(func(w io.Writer, width int, st *decor.Statistics) {
completedFn := mpb.BarFillerFunc(func(w io.Writer, width int, st decor.Statistics) {
if st.Completed {
io.WriteString(w, strings.ReplaceAll(tp.test.String(), "\n", ""))
} else {
Expand Down
175 changes: 166 additions & 9 deletions files/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,44 @@ import (
"compress/gzip"
"context"
"encoding/hex"
"errors"
"fmt"
"io"
"io/ioutil"
"math/rand"
"net/url"
"os"
"os/exec"
"path"
"path/filepath"
"strings"
"time"

"github.com/flanksource/commons/logger"
"github.com/hashicorp/go-getter"
"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")

// Setting Supported Detectors
Detectors = []getter.Detector{
new(getter.GitHubDetector),
new(getter.GitDetector),
new(getter.BitBucketDetector),
new(getter.S3Detector),
new(getter.GCSDetector),
new(getter.FileDetector),
}
)

//GzipFile takes the path to a file and returns a Gzip comppressed byte slice
func GzipFile(path string) ([]byte, error) {
var buf bytes.Buffer
Expand Down Expand Up @@ -317,13 +340,18 @@ 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 {

pwd, _ := os.Getwd()

// If the destination is empty,
// choose the current working directory.
if dst == "" {
dst = pwd
}

stashed := false
if Exists(dst + "/.git") {
if Exists(filepath.Join(dst, ".git")) {
cmd := exec.Command("git", "stash")
cmd.Dir = pwd

cmd.Dir = dst
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
Expand All @@ -333,16 +361,20 @@ func Getter(url, dst string) error {
}

}

client := &getter.Client{
Ctx: context.TODO(),
Src: url,
Dst: dst,
Pwd: pwd,
Mode: getter.ClientModeDir,
Options: []getter.ClientOption{},
Ctx: context.TODO(),
Src: url,
Dst: dst,
Pwd: pwd,
Mode: getter.ClientModeDir,
Options: []getter.ClientOption{},
Detectors: Detectors,
}

logger.Infof("Downloading %s -> %s", url, dst)
err := client.Get()

if stashed {
cmd := exec.Command("git", "stash", "pop")
cmd.Dir = dst
Expand All @@ -359,3 +391,128 @@ 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, destination string) (string, error) {

// Contents of the file that have to be returned.
var response string

var err error

// Get the current working directory
pwd, _ := os.Getwd()

// Detect turns a source string into another source string
// if it is detected to be of a known pattern.
source, err := getter.Detect(file, pwd, Detectors)
if err != nil {
return response, err
}

// If go-getter has detected it to be a local file,
// it will return the source with `file://` scheme prefixed.
// We can now parse the URI to judge the scheme.
url, err := url.ParseRequestURI(source)
if err != nil {
return response, err
}

// If it is a local file i.e. with `file://` scheme,
// then we can simply read and return the file.
if url.Scheme == "file" {

// Read the contents of the file.
data, err := os.ReadFile(file)
if err != nil {
return response, err
}

// Return the data.
return string(data), nil
}

//
// If it is a remote file, we should go-get it.
//

// If the destination is absent, initialize a temporary directory.
if destination == "" {

destination = filepath.Join(os.TempDir(), fmt.Sprint(time.Now().Unix()))
if err != nil {
return response, err
}

// Issue deletion for the same path deferred to the end of the code.
// This needs to run after go-getter has created the directory.
defer DeletePath(destination)

} else {

// If it is not a valid directory path, return an error.
path, err := os.Open(destination)
if err != nil {
return response, err
}

defer path.Close()

info, err := path.Stat()
if err != nil {
return response, err
}

if !info.IsDir() {
return response, fmt.Errorf("%s is not a directory", destination)
}
}

// go-get the file.
if err := Getter(filepath.Dir(source), destination); err != nil {
return response, err
}

// Initialize the new filepath where the file has been cloned locally.
filepath := filepath.Join(destination, filepath.Base(source))

// Finally, read the contents of the file.
data, err := os.ReadFile(filepath)
if err != nil {
return response, err
}

// Update the response response.
response = string(data)

return response, nil
}

// ResolveFiles
//
// Calls ResolveFile(filepath) function on an array of files.
func ResolveFiles(files []string) (map[string]string, error) {

response := make(map[string]string)

for _, source := range files {

data, err := ResolveFile(source, "")
if err != nil {
return nil, errors.New(strings.Join([]string{source, err.Error()}, " : "))
}

response[source] = data
}

return response, nil
}

// Deletes a filesystem path. Be it a file or a directory.
func DeletePath(source string) error {
return os.Remove(source)
}
33 changes: 32 additions & 1 deletion files/files_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package files

import "testing"
import (
"fmt"
"testing"
)

func TestIsValidPathType(t *testing.T) {
type args struct {
Expand All @@ -26,3 +29,31 @@ func TestIsValidPathType(t *testing.T) {
})
}
}

func TestResolveFile(t *testing.T) {
type args struct {
file string
dest string
}
tests := []struct {
name string
args args
wantErr bool
}{
// {"incorrectDestination", args{"/Users/mrinalwahal/go/src/github.com/flanksource/regen", "/Users/mrinalwahal/go/src/github.com/flanksource/regen/file.temp"}, true},
// {"correctFile", args{"/Users/mrinalwahal/go/src/github.com/flanksource/regen/file.temp", ""}, false},
// {"incorrectFile", args{"https/Users/mrinalwahal/go/src/github.com/flanksource/regen/file1.temp", ""}, true},
// {"url", args{"github.com/mrinalwahal/portfolio/README.md", ""}, false},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ResolveFile(tt.args.file, tt.args.dest)
if (err != nil) != tt.wantErr {
t.Errorf("%v: error = %v, wantErr %v", tt.name, err, tt.wantErr)
return
}
fmt.Println(got)
})
}
}
Loading