Skip to content

Commit

Permalink
Merge b7614b0 into 4ff5973
Browse files Browse the repository at this point in the history
  • Loading branch information
mingwho committed Sep 16, 2019
2 parents 4ff5973 + b7614b0 commit 45a81c3
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ builds/*
!builds/.gitkeep
.idea/
.vscode/
packages.abs.json
7 changes: 6 additions & 1 deletion evaluator/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -1573,7 +1573,12 @@ func sourceFn(tok token.Token, env *object.Environment, args ...object.Object) o

// require("file.abs")
func requireFn(tok token.Token, env *object.Environment, args ...object.Object) object.Object {
file := filepath.Join(env.Dir, args[0].Inspect())
a, error := util.FindAlias(args[0].Inspect())
if error != nil {
return newError(tok, "error unmarsalling json: %s\n", error.Error())
}

file := filepath.Join(env.Dir, a)
e := object.NewEnvironment(env.Writer, filepath.Dir(file))
return doSource(tok, e, file, args...)
}
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ require (
github.com/c-bata/go-prompt v0.2.4-0.20190826134812-0f95e1d1de2e
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-isatty v0.0.9 // indirect
github.com/mattn/go-runewidth v0.0.4 // indirect
github.com/mattn/go-tty v0.0.0-20190424173100-523744f04859 // indirect
github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942 // indirect
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
Expand Down
205 changes: 205 additions & 0 deletions install/install.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
package install

import (
"archive/zip"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strings"
"time"
)

func valid(module string) bool {
return strings.HasPrefix(module, "github.com/")
}

func Install(module string) {

if !valid(module) {
fmt.Printf(`Error reading URL. Please use "github.com/USER/REPO" format to install`)
return
}

err := getZip(module)
if err != nil {
return
}

err = unzip(module)
if err != nil {
fmt.Printf(`Error unpacking: %v`, err)
return
}

alias, err := createAlias(module)
if err != nil {
return
}

fmt.Printf("Install Success. You can use the module with `require(\"%s\")`\n", alias)
return
}

func getZip(module string) error {
fmt.Println("Downloading...")
path := fmt.Sprintf("./vendor/%s", module)
// Create all the parent directories if needed
err := os.MkdirAll(filepath.Dir(path), 0755)

if err != nil {
fmt.Printf("Error making directory %s\n", err)
return err
}

out, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, os.FileMode(0666))
if err != nil {
fmt.Printf("Error opening file %s\n", err)
return err
}
defer out.Close()

client := http.Client{
Timeout: time.Duration(10 * time.Second),
}

url := fmt.Sprintf("https://%s/archive/master.zip", module)

req, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Printf("Error creating new request %s", err)
return err
}

resp, err := client.Do(req)

if err != nil {
fmt.Printf("Could not get module: %s\n", err)
return err
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
fmt.Errorf("Bad response code: %d", resp.StatusCode)
return err
}

_, err = io.Copy(out, resp.Body)
if err != nil {
fmt.Printf("Error copying file %s", err)
return err
}
return err
}

// Unzip will decompress a zip archive
func unzip(module string) error {
fmt.Println("Unpacking...")
src := fmt.Sprintf("./vendor/%s", module)
dest := filepath.Dir(src)

r, err := zip.OpenReader(src)
if err != nil {
return err
}
defer r.Close()

for _, f := range r.File {
// Store filename/path for returning and using later on
fpath := filepath.Join(dest, f.Name)

// Check for ZipSlip. More Info: http://bit.ly/2MsjAWE
if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
return fmt.Errorf("%s: illegal file path", fpath)
}

if f.FileInfo().IsDir() {
// Make Folder
os.MkdirAll(fpath, 0755)
continue
}

// Make File
if err = os.MkdirAll(filepath.Dir(fpath), 0755); err != nil {
return err
}

outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return err
}

rc, err := f.Open()
if err != nil {
return err
}

_, err = io.Copy(outFile, rc)

// Close the file without defer to close before next iteration of loop
outFile.Close()
rc.Close()

if err != nil {
return err
}
}
return nil
}

func createAlias(module string) (string, error) {
fmt.Println("Creating alias...")
f, err := os.OpenFile("./packages.abs.json", os.O_RDWR|os.O_CREATE, 0666)
if err != nil {
fmt.Printf("Could not open alias file %s\n", err)
return "", err
}
defer f.Close()

b, err := ioutil.ReadAll(f)

data := make(map[string]string)
moduleName := filepath.Base(module)
modulePath := fmt.Sprintf("./vendor/%s-master", module)

// If package.abs.json file is empty
if len(b) == 0 {
// Appending "master" as Github zip file has "-master" suffix
// Add alias key-value pair to file
data[moduleName] = modulePath

} else {
err = json.Unmarshal(b, &data)
if err != nil {
fmt.Printf("Could not unmarshal alias json %s\n", err)
return "", err
}

// module already installed and aliased
if data[moduleName] == modulePath {
return moduleName, nil
}

if data[moduleName] != "" {
fmt.Printf("This module could not be aliased because module of same name exists\n")
moduleName = module
data[moduleName] = modulePath
}
}

newData, err := json.MarshalIndent(data, "", " ")
if err != nil {
fmt.Printf("Could not marshal alias json when installing module %s\n", err)
return "", err
}

_, err = f.WriteAt(newData, 0)
if err != nil {
fmt.Printf("Could not write to alias file %s\n", err)
return "", err
}
return moduleName, err

}
7 changes: 7 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"

"github.com/abs-lang/abs/install"
"github.com/abs-lang/abs/repl"
)

Expand All @@ -16,6 +17,12 @@ func main() {
fmt.Println(Version)
return
}

if len(args) == 3 && args[1] == "get" {
install.Install(args[2])
return
}

// begin the REPL
repl.BeginRepl(args, Version)
}
19 changes: 19 additions & 0 deletions util/util.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package util

import (
"encoding/json"
"io/ioutil"
"os"
"os/user"
"path/filepath"
Expand All @@ -10,6 +12,8 @@ import (
"github.com/abs-lang/abs/object"
)

var packageAlias map[string]string

// Checks whether the element e is in the
// list of strings s
func Contains(s []string, e string) bool {
Expand Down Expand Up @@ -40,6 +44,21 @@ func ExpandPath(path string) (string, error) {
return filepath.Join(usr.HomeDir, path[1:]), nil
}

func FindAlias(path string) (string, error) {
if len(packageAlias) == 0 {
a, _ := ioutil.ReadFile("./packages.abs.json")
err := json.Unmarshal(a, &packageAlias)
if err != nil {
return path, err
}
}

if packageAlias[path] != "" {
return packageAlias[path], nil
}
return path, nil
}

// GetEnvVar (varName, defaultVal)
// Return the varName value from the ABS env, or OS env, or default value in that order
func GetEnvVar(env *object.Environment, varName, defaultVal string) string {
Expand Down

0 comments on commit 45a81c3

Please sign in to comment.