Full Code of azukaar/GuPM for AI

master 53371f326bf9 cached
52 files
92.8 KB
28.1k tokens
138 symbols
1 requests
Download .txt
Repository: azukaar/GuPM
Branch: master
Commit: 53371f326bf9
Files: 52
Total size: 92.8 KB

Directory structure:
gitextract_o4jwiwqj/

├── .circleci/
│   └── config.yml
├── .gitignore
├── .gupm_rc.gs
├── LICENCE
├── build.gs
├── ci/
│   └── publish.gs
├── docs/
│   └── install.sh
├── gupm.json
├── plugins/
│   ├── provider-git/
│   │   ├── gupm.json
│   │   ├── postGetDependency.gs
│   │   └── resolveDependencyLocation.gs
│   ├── provider-http/
│   │   ├── gupm.json
│   │   └── resolveDependencyLocation.gs
│   └── provider-https/
│       ├── gupm.json
│       └── resolveDependencyLocation.gs
├── readme.md
├── src/
│   ├── addDependency.go
│   ├── bootstrap.go
│   ├── cache.go
│   ├── cli.go
│   ├── cli_test.go
│   ├── defaultProvider/
│   │   ├── defaultProvider.go
│   │   └── publish.go
│   ├── distribution_gupm.json
│   ├── gitHooks.go
│   ├── global.go
│   ├── index.go
│   ├── installProject.go
│   ├── jsVm/
│   │   └── jsVm.go
│   ├── plugins.go
│   ├── provider/
│   │   ├── bootstrap.go
│   │   ├── dependencyTree.go
│   │   ├── install.go
│   │   ├── provider.go
│   │   └── publish.go
│   ├── publish.go
│   ├── removeDependency.go
│   ├── self.go
│   ├── test.go
│   ├── ui/
│   │   └── log.go
│   ├── utils/
│   │   ├── files.go
│   │   ├── json.go
│   │   ├── repo.go
│   │   ├── types.go
│   │   ├── untar.go
│   │   └── utils.go
│   └── windows/
│       └── windows_install.go
└── tests/
    ├── install/
    │   └── normal.test.gs
    ├── make/
    │   ├── nodeps.test.gs
    │   └── normal.test.gs
    ├── plugins/
    │   └── normal.test.gs
    └── scripts/
        └── normal.test.gs

================================================
FILE CONTENTS
================================================

================================================
FILE: .circleci/config.yml
================================================
version: 2
jobs:
  build:
    docker:
      - image: golang:1.12.5-stretch

    steps:
      - checkout

      - run:
          name: Install GuPM
          command: curl -fsSL  https://azukaar.github.io/GuPM/install.sh | bash

      - run:
          name: Install provider
          command: g plugin install https://azukaar.github.io/GuPM-official/repo:provider-go

      - run:
          name: Make
          command: g make

      - run:
          name: Build
          command: g build

      - run:
          name: Cleanup
          command: g pl delete provider-go
      
      - run:
          name: Run tests
          command: g test

      - run:
          name: Run unit tests
          command: g gotest
      
      - run:
          name: Install provider
          command: g plugin install https://azukaar.github.io/GuPM-official/repo:provider-go

      - run:
          name: Build Linux
          command: g ci/publish
      - run:
          name: Build Mac
          command: g ci/publish mac
      - run:
          name: Build Windows
          command: g ci/publish windows
      
      - run: git config user.email "nobody@circleci.com"
      - run: git config user.name "Circle Ci"
      - run: git add docs
      - run: git commit -m "[skip ci] Release"
      - run: git push origin master

workflows:
  version: 2
  build-all:
    jobs:
      - build:
          filters:
            branches:
              only:
                - master

================================================
FILE: .gitignore
================================================
.DS_Store
.bin
build
.vscode
node_modules
temp
cache
sampleproject
test.gs
package.json
go_modules
gupm_modules

================================================
FILE: .gupm_rc.gs
================================================
env("GOPATH", run("go", ["env", "GOROOT"]) + ":" + pwd() + "/go_modules")

================================================
FILE: LICENCE
================================================
Copyright (c) Yann Stepienik (yann.stepienik@gmail.com)

Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.


================================================
FILE: build.gs
================================================
removeFiles(["build/dg", "build/plugins", "build/gupm.json"]) 

var goArgs = ["build", "-o", "build/dg"]
goArgs = goArgs.concat(dir("src/*.go"))
exec("go", goArgs)

copyFiles("plugins", "build/plugins")
copyFiles("src/distribution_gupm.json", "build/gupm.json")

console.log("\nBuild done! 💖")

================================================
FILE: ci/publish.gs
================================================
removeFiles("gupm")

var goArgs = ["build", "-o"]

if(typeof $1 != "undefined" && $1 == "windows") {
    goArgs.push("gupm/g.exe")
} else {
    goArgs.push("gupm/g")
}

goArgs = goArgs.concat(dir("src/*.go"))

copyFiles("plugins", "gupm/plugins")
copyFiles("src/distribution_gupm.json", "gupm/gupm.json")

if(typeof $1 != "undefined" && $1 == "mac") {
    env("GOOS", "darwin")
    env("go version", "amd64")
    exec("go", goArgs)
    var arch = tar("gupm")
    removeFiles("docs/gupm_mac.tar.gz")
    saveFileAt(arch, "docs/gupm_mac.tar.gz")
} 
if(typeof $1 != "undefined" && $1 == "windows") {
    env("GOOS", "windows")
    env("GOARCH", "amd64")
    exec("go", goArgs)
    var arch = tar("gupm")
    removeFiles("docs/gupm_windows.tar.gz")
    saveFileAt(arch, "docs/gupm_windows.tar.gz")
} else {
    env("GOOS", "linux")
    env("GOARCH", "amd64")
    exec("go", goArgs)
    var arch = tar("gupm")
    removeFiles("docs/gupm.tar.gz")
    saveFileAt(arch, "docs/gupm.tar.gz")
}

removeFiles("gupm")

================================================
FILE: docs/install.sh
================================================
#!/bin/sh

if [ "$(uname)" = "Darwin" ]; then
    curl --output gupm.tar.gz https://azukaar.github.io/GuPM/gupm_mac.tar.gz       
elif [ "$(uname)" = "Linux" ]; then
    curl --output gupm.tar.gz https://azukaar.github.io/GuPM/gupm.tar.gz
fi

mkdir ~/.gupm
tar -C ~/.gupm -zxvf gupm.tar.gz
chmod -R 755 ~/.gupm/gupm/
rm gupm.tar.gz

if [ -d "/usr/local/bin" ] 
then
    if [ -f "/usr/local/bin/g" ] 
    then
        rm /usr/local/bin/g
    fi
    ln -s ~/.gupm/gupm/g /usr/local/bin/g
else
    if [ -f "/bin/g" ] 
    then
        rm /bin/g
    fi
    ln -s ~/.gupm/gupm/g /bin/g
fi

if [ "$(uname)" = "Darwin" ]; then
    read -r -p "Do you want to make Homebrew your default provider? (Recommended) [y/N] " response
    if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]
    then
        g plugin install https://azukaar.github.io/GuPM-official/repo:provider-brew
        sed -ie 's/"defaultProvider": "gupm"/"defaultProvider": "os"/' ~/.gupm/gupm/gupm.json
    fi
fi

echo "------"
echo "Installaton complete"
echo "------"


================================================
FILE: gupm.json
================================================
{
    "cli": {
        "aliases": {
            "gotest": "go test ./src ./src/utils",
            "start": "./build/dg"
        }
    },
    "dependencies": {
        "default": {
            "go://github.com/Masterminds/semver": "master",
            "go://github.com/bmatcuk/doublestar": "master",
            "go://github.com/fatih/color": "master",
            "go://github.com/gosuri/uilive": "master",
            "go://github.com/mattn/go-isatty": "master",
            "go://github.com/mitchellh/go-homedir": "master",
            "go://github.com/otiai10/copy": "master",
            "go://github.com/robertkrimen/otto": "master",
            "go://github.com/stretchr/testify": "master",
            "go://gopkg.in/sourcemap.v1": "v1.0.5"
        },
        "defaultProvider": "go"
    },
    "git": {
        "hooks": {
            "precommit": "gofmt -w -s src/index.go $StagedFiles(**/*.go)",
            "prepush": [
                "g test",
                "g gotest"
            ]
        }
    },
    "name": "gupm",
    "version": "1.2.1"
}

================================================
FILE: plugins/provider-git/gupm.json
================================================
{
    "name": "provider-git",
    "version": "0.0.1",
    "config": {
        "default": {
            "entrypoint": "gupm.json",
            "installPath": "gupm_modules"
        }
    }
}

================================================
FILE: plugins/provider-git/postGetDependency.gs
================================================
// Provider : name of provider (npm)
// Name : name of downloaded package
// Version : version of downloaded package
// Url : URL of downloaded package
// Path  : Future path of downloaded package
// Result : binary downloaded

var folder = unzip(Result);

var firstChildrenName = Object.keys(folder.Children)[0];
var firstChildren = folder.Children[firstChildrenName];

saveFileAt(firstChildren, Path);
saveLockDep(Path);

Path;


================================================
FILE: plugins/provider-git/resolveDependencyLocation.gs
================================================
var name = Dependency.name;
var version = Dependency.version;

Dependency.url = 'https://' + name + '/archive/master.zip'

if(Dependency.version === "*.*.*") {
  Dependency.version = "master"
}

// https://github.com/src-d/go-git/archive/6e931e4fdefa202c76242109453447182ae16444.zip

Dependency;


================================================
FILE: plugins/provider-http/gupm.json
================================================
{
    "name": "provider-http",
    "version": "0.0.1",
    "config": {
        "default": {
            "entrypoint": "gupm.json",
            "installPath": "gupm_modules"
        }
    }
}

================================================
FILE: plugins/provider-http/resolveDependencyLocation.gs
================================================
var name = Dependency.name;

if(name.split(':').length > 1) {
    var version = Dependency.version
    var names = name.split(':')

    // exact version
    if (version.match(/^\d+\.\d+\.\d+/) && !version.match(/\sx/)) {
    }
    
    // test ranges
    else {
        var repoList = 'http://' + names[0] + '/gupm_repo.json'
        var payload = httpGetJson(repoList);

        if(payload.packages[names[1]] && payload.packages[names[1]].length) {
            var versionList = payload.packages[names[1]];
            version = semverLatestInRange(version, versionList);
        } else {
            console.error("Package "+names[1]+" not found in " + names[0])
            exit(1)
        }
    }



    var realName = names[1]
    var namespace = ''
    if( realName.split('/').length > 1) {
        namespace = (realName.split('/')[0] + '/').replace("OS", _OSNAME)
        realName = realName.split('/')[1]
    }
    Dependency.url = 'http://' + names[0] + '/' + namespace + realName + '/'  + version + '/' + realName + '-'  + version + '.tgz'

    Dependency.version = version
} else {
    Dependency.url = 'http://' + name
}

Dependency;


================================================
FILE: plugins/provider-https/gupm.json
================================================
{
    "name": "provider-https",
    "version": "0.0.1",
    "config": {
        "default": {
            "entrypoint": "gupm.json",
            "installPath": "gupm_modules"
        }
    }
}

================================================
FILE: plugins/provider-https/resolveDependencyLocation.gs
================================================
var name = Dependency.name;

if(name.split(':').length > 1) {
    var version = Dependency.version
    var names = name.split(':')

    // exact version
    if (version.match(/^\d+\.\d+\.\d+/) && !version.match(/\sx/)) {
    }
    
    // test ranges
    else {
        var repoList = 'https://' + names[0] + '/gupm_repo.json'
        var payload = httpGetJson(repoList);

        if(payload.packages[names[1]] && payload.packages[names[1]].length) {
            var versionList = payload.packages[names[1]];
            version = semverLatestInRange(version, versionList);
        } else {
            console.error("Package "+names[1]+" not found in " + names[0])
            exit(1)
        }
    }



    var realName = names[1]
    var namespace = ''
    if( realName.split('/').length > 1) {
        namespace = (realName.split('/')[0] + '/').replace("OS", _OSNAME)
        realName = realName.split('/')[1]
    }
    Dependency.url = 'https://' + names[0] + '/' + namespace + realName + '/'  + version + '/' + realName + '-'  + version + '.tgz'

    Dependency.version = version
} else {
    Dependency.url = 'https://' + name
}

Dependency;


================================================
FILE: readme.md
================================================
![dog](./docs/banner.png)

---

<br />
<p align="center">
<img src="https://img.shields.io/badge/Platform-Windows%20%7C%20Linux%20%7C%20MacOS-pink.svg?style=for-the-badge">
<img src="https://img.shields.io/badge/CircleCI-Passing-green.svg?style=for-the-badge">
<img src="https://img.shields.io/badge/GoLang-1.12.5-blue.svg?style=for-the-badge">
<br/>
<img src="https://img.shields.io/badge/Ruby-Gem-e9573f.svg?style=for-the-badge&logo=ruby">
<img src="https://img.shields.io/badge/Javascript-NPM | Entropic-25799f.svg?style=for-the-badge&logo=javascript">
<img src="https://img.shields.io/badge/Python-PIP-yellow.svg?style=for-the-badge&logo=python">
<img src="https://img.shields.io/badge/PHP-Composer-black.svg?style=for-the-badge&logo=php">
<img src="https://img.shields.io/badge/Windows-Chocolatey-2f6492.svg?style=for-the-badge&logo=windows">
<img src="https://img.shields.io/badge/MacOS-Brew-f9d094.svg?style=for-the-badge&logo=apple">
<img src="https://img.shields.io/badge/GoLang-Go Get-E0EBF5.svg?style=for-the-badge&logo=go">
</p>
<br />
<br />
Global Universal Project Manager -- Package manager, CLI tool, and scripts for all your projects and your system. Whether you are a developer managing dependencies, or a sysadmin looking for your new toolbelt (bye bash!) you are among friends. <a href="https://github.com/azukaar/GuPM/wiki">Check the Wiki for documentation.</a> <br />
<br />

 * ⏱ **Fast**. Written in native code, with real multi-threading.
 * 👓 **Smart**. Memory efficient solution using hard-link, which do not duplicate dependencies across project.
 * 🌍 **Global**. Windows, Mac and Linux compatibility.
 * 🌈 **Universal**. Usable in any kind of project (Ruby, JS, Go, C, Python, etc...)
 * 👗 **Customizable**. Flexible plugin system: make GuPM your own.
 * 👝 **Future Proof**. Let's make this the last PM you will ever need.
 * 🌳 **Decentralized**. You keep control of the sources you tap into.
 * 🐳 **No dependencies**. You don't need anythind else (you don't need NPM to use NPM's repository with GuPM)

This idea is born from the frustration of having to give up my habits whenever I would switch off Javascript and lose NPM (Whether it would be in Ruby, Go, or even situations outside of coding). GuPM is claiming to take inspiration from the best things in Brew, NPM, Gem, etc... And compile them in a single tool, usable in any project.
<br />

 * 📦 **Packages Manager**. Install packages from any repository and manage dependencies in a seamless way.
 * 🖥 **CLI Manager**. Install and use CLI tools in a flexible way without conflicts.
 * 🚏 **Scripting**. GuPM is bundled with GuScript, allowing you to build cross platform scripts for your project.
 * 🐙 **Packed with features**. Manage configs, git hooks, parallel executions, environment variables, CI, and more.
 * 🔥 **Even more to come!** See : [Next](https://github.com/azukaar/GuPM/projects/1#column-5571474) for the roadmap of feature. You are welcomed to contribute!
<br />

---

# Getting started : 

## Quick links

 * [Wiki](https://github.com/azukaar/GuPM/wiki)
 * [Quick Start](https://github.com/azukaar/GuPM/wiki/quick-start)
 * [Getting started with Node](https://medium.com/@azukaar/gupm-to-manage-your-node-js-project-b7664503f3de?sk=f901b86d888b44dcdb78c644bd5df002)
 * [Getting started with Go](https://medium.com/@azukaar/gupm-to-manage-your-go-project-5d19c341403c)
 * [Create your own repository](https://github.com/azukaar/GuPM/wiki/repositories)
 * [Official GuPM repository](https://github.com/azukaar/GuPM-official)

## Installation

### Linux and Mac OS : 

⌨️ `$ curl -fsSL  https://azukaar.github.io/GuPM/install.sh | bash`

### Windows 

💾 [Windows_install.exe](https://azukaar.github.io/GuPM/windows_install.exe)

## JS/NPM example

This example is setting up a project using the [NPM plugin](https://github.com/azukaar/GuPM-official).
More details on how to use GuPM with node [here]().

<p align="center">
<img width="824px" src="./docs/intro1.png">
</p>

## Go example

This example is setting up a project using the [Go plugin](https://github.com/azukaar/GuPM-official).
More details on how to use GuPM with Go [here]().

<p align="center">
<img width="824px" src="./docs/intro2.png">
</p>

# Dependency Manager

## New projects

In order to simply bootstrap a new project you can run `g bootstrap` you can also use `b` and add a provider `g b -p npm`

## Make

This command will set up your project by getting dependencies. Adding a -p or --provider argument allows you to specify what provider to use initially.
Please note you do NOT need to install npm / gem / whatever to use their corresponding provider, GuPM implement everything itself.

```bash
# reads gupm.json
g make

# reads package.json
g make -p npm
```

## Install

```bash
# use default repo [Config in gupm.json]

g install mysql
g i mysql

# use brew

g install brew://mysql
g install -p brew mysql

# use NPM

g install npm://react@1 # will save in gupm.json
g install -p npm react@1 # will save in package.json
```

More commands [in the wiki](https://github.com/azukaar/GuPM/wiki/cli-references)

## GuPM management

### Plugins

GuPM needs plugins to work with various repos :

```bash
# Install provider-go from the official repo
g plugin install https://azukaar.github.io/GuPM-official/repo:provider-go
```

See https://github.com/azukaar/gupm-official for a list of officially suported plugins.
See https://github.com/azukaar/GuPM/wiki/how-to-create-a-provider to create your own.

### updates

GuPM can be managed using :

```bash
g self upgrade
```

More commands [in the wiki](https://github.com/azukaar/GuPM/wiki/cli-references)

## Write GuPM scripts

You can use GuScript to write bash-like files, used for setting up your project, use it, or anything literally.
Think of GuScript as a replacement for your bash scripts.

```
// name_setup.gs

var name = input('What is your name')
echo('Welcome' + name)
saveName(name)
```

GuScript is based on javascript, and therefore allow advanced object/arrays manipulations, function definitions, etc...
Find more details about the available APIs in the [wiki](https://github.com/azukaar/GuPM/wiki) 1

## VS Code 

Add this to your `settings.json` to treat .gs file as javascript (temporary fix to plain text)

```
"files.associations": {
    "*.gs": "javascript"
}
```

# Thanks!
Package Icon made by [smashicons](https://www.smashicons.com/)
Dog Icon made by [Freepik](https://www.freepik.com/)


================================================
FILE: src/addDependency.go
================================================
package main

import (
	"./provider"
	"./ui"
	"./utils"
)

func AddDependency(path string, rls []string) error {
	var err error
	var packageConfig utils.Json
	var depList []map[string]interface{}
	var depProvider = Provider

	ui.Title("Add dependency...")

	if !ProviderWasForced && utils.FileExists(path+utils.Path("/gupm.json")) {
		config, _ := utils.ReadGupmJson(path + utils.Path("/gupm.json"))
		if config.Dependencies.DefaultProvider != "" {
			depProvider = config.Dependencies.DefaultProvider
		}
	}

	err = provider.InitProvider(Provider)

	if err != nil {
		return err
	}

	providerConfig, err = provider.GetProviderConfig(Provider)
	if err != nil {
		return err
	}

	packageConfig, err = provider.GetPackageConfig(path)
	if err != nil {
		return err
	}

	packageConfig, err = provider.PostGetPackageConfig(packageConfig)
	if err != nil {
		return err
	}

	depList, err = provider.GetDependencyList(packageConfig)
	if err != nil {
		return err
	}

	ui.Title("Adding to dependency list...")

	for _, str := range rls {
		dep := utils.BuildDependencyFromString(depProvider, str)
		resolved, err := provider.ResolveDependencyLocation(dep)
		if err != nil || resolved["url"].(string) == "" {
			ui.Error("Can't resolve", str)
			return err
		}
		dep["version"] = resolved["version"]
		depList = append(depList, dep)
	}

	if packageConfig != nil {
		err = provider.SaveDependencyList(path, depList)
		if err != nil {
			return err
		}
	}

	return nil
}


================================================
FILE: src/bootstrap.go
================================================
package main

import (
	"./provider"
	"./ui"
	// "fmt"
)

func Bootstrap(path string) error {
	err := provider.InitProvider(Provider)
	if err != nil {
		return err
	}
	ui.Title("Bootstrap project")
	errBoot := provider.Bootstrap(path)
	if errBoot != nil {
		return errBoot
	} else {
		ui.Title("Bootstrap done! ❤️")
	}
	return nil
}


================================================
FILE: src/cache.go
================================================
package main

import (
	"./ui"
	"./utils"
	"github.com/mitchellh/go-homedir"
)

func CacheClear() {
	hdir, errH := homedir.Dir()
	if errH != nil {
		ui.Error(errH)
		hdir = "."
	}

	folder := utils.Path(hdir + "/.gupm/cache/")

	utils.RemoveFiles([]string{folder})
}


================================================
FILE: src/cli.go
================================================
package main

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"./ui"
	"./utils"
)

type json = utils.Json

var ProviderWasForced = false

type Arguments map[string]string

func (a *Arguments) AsJson() json {
	res := utils.Json{}
	for i, v := range *a {
		res[i] = v
	}
	return res
}
func (a *Arguments) Join() string {
	res := ""
	for i, v := range *a {
		if v == "true" || v == "false" {
			res += "--" + strings.ToLower(i) + " "
		} else if ok, _ := regexp.MatchString(`^\$\d+`, i); ok {
			res += v + " "
		} else {
			res += "--" + strings.ToLower(i) + " " + v + " "
		}
	}
	return strings.TrimSpace(res)
}
func (a *Arguments) AsList() []string {
	res := []string{}
	i := 1

	for (*a)["$"+strconv.Itoa(i)] != "" {
		res = append(res, (*a)["$"+strconv.Itoa(i)])
		i++
	}

	return res
}
func (a *Arguments) Shift() {
	i := 2

	for (*a)["$"+strconv.Itoa(i)] != "" {
		(*a)["$"+strconv.Itoa(i-1)] = (*a)["$"+strconv.Itoa(i)]
		i++
	}

	(*a)["$"+strconv.Itoa(i-1)] = ""
}

func GetArgs(args []string) (string, Arguments) {
	arguments := make(Arguments)
	next := ""
	dolsI := 1

	if len(args) == 0 {
		arguments["$0"] = ""
		return "", arguments
	}

	command := args[0]
	if len(args) < 2 {
		arguments["$0"] = command
		return command, arguments
	}

	argsToParse := args[1:]

	for _, value := range argsToParse {
		nameCheck := regexp.MustCompile(`^--?(\w+)`)
		tryname := nameCheck.FindString(value)
		if tryname != "" {
			long, _ := regexp.MatchString(`^--`, tryname)
			if long {
				tryname = tryname[1:]
			}

			if next != "" {
				arguments[next] = "true"
				next = ""
			}
			next = strings.ToUpper(tryname[1:2]) + tryname[2:]
		} else {
			if next != "" {
				arguments[next] = value
				next = ""
			} else {
				arguments["$"+strconv.FormatInt(int64(dolsI), 10)] = value
				dolsI++
			}
		}
	}

	if next != "" {
		arguments[next] = "true"
	}

	arguments["$0"] = command + " " + arguments.Join()

	return command, arguments
}

func getProvider(c string, args Arguments) string {
	gupmConfig := utils.GupmConfig()
	defaultProvider := "gupm"

	if c == "install" || c == "global" {
		defaultProvider = gupmConfig.DefaultProvider
	}

	if defaultProvider == "os" {
		osName := utils.OSNAME()
		if gupmConfig.OsProviders[osName] != "" {
			defaultProvider = gupmConfig.OsProviders[osName]
		} else {
			ui.Error("No provider set for", osName)
			return utils.DIRNAME()
		}
	}

	if utils.FileExists("gupm.json") {
		config, err := utils.ReadGupmJson("gupm.json")
		if err != nil {
			ui.Error(err)
		} else {
			if config.Cli.DefaultProviders[c] != "" {
				defaultProvider = config.Cli.DefaultProviders[c]
			}
		}
	}

	if args["Provider"] != "" {
		ProviderWasForced = true
		return args["Provider"]
	} else if args["P"] != "" {
		ProviderWasForced = true
		return args["P"]
	} else {
		return defaultProvider
	}
}

func ExecCli(c string, args Arguments) (bool, error) {
	var err error
	notFound := "Cannot find commmand"
	shorthands := map[string]string{
		"h":  "help",
		"m":  "make",
		"i":  "install",
		"d":  "delete",
		"p":  "publish",
		"b":  "bootstrap",
		"c":  "cache",
		"s":  "self",
		"t":  "test",
		"pl": "plugin",
		"g":  "global",
	}

	if shorthands[c] != "" {
		c = shorthands[c]
	}

	if provider := getProvider(c, args); provider != "" {
		Provider = provider
	}

	if c == "help" {
		fmt.Println("make / m :", "[--provider=]", "Install projects depdencies based on info in the entry point (depends on provider)")
		fmt.Println("install / i :", "[--provider=]", "Install package")
		fmt.Println("remove / r :", "[--provider=]", "remove package from module config")
		fmt.Println("publish / p :", "[--provider=]", "publish a project based on the model of your specific provider")
		fmt.Println("bootstrap / b :", "[--provider=]", "bootstrap a new project based on the model of your specific provider")
		fmt.Println("test / t :", "[--provider=] Run project's tests in tests folder.")

		fmt.Println("global / g :", "install or delete global packages")
		fmt.Println("cache / c :", "clear or check the cache with \"cache clear\" or \"cache check\"")
		fmt.Println("self / s :", "self manage gupm. Try g \"self upgrade\" or \"g self uninstall\"")
		fmt.Println("plugin / pl :", "To install a plugin \"g pl install\". Then use \"g pl create\" to create a new one and \"g pl link\" to test your plugin")
	} else if c == "make" {
		BuildGitHooks(".")
		err = InstallProject(".")
	} else if c == "install" {
		err = AddDependency(".", args.AsList())
		if err == nil {
			err = InstallProject(".")
		}
	} else if c == "publish" {
		err = Publish(".", args["$1"])
	} else if c == "delete" {
		err = RemoveDependency(".", args.AsList())
	} else if c == "global" {
		if args["$1"] == "install" || args["$1"] == "i" {
			args.Shift()
			GlobalAdd(args.AsList())
		} else if args["$1"] == "delete" || args["$1"] == "d" {
			args.Shift()
			GlobalDelete(args.AsList())
		} else {
			ui.Error(notFound, args["$1"], "\n", "try install or delete")
		}
	} else if c == "plugin" {
		if args["$1"] == "create" {
			PluginCreate(".")
		} else if args["$1"] == "link" {
			PluginLink(".")
		} else if args["$1"] == "install" {
			err = PluginInstall(".", args.AsList()[1:])
		} else if args["$1"] == "delete" {
			PluginDelete(".", args.AsList()[1:])
		} else {
			ui.Error(notFound, args["$1"], "\n", "try cache clear or cache check")
		}
	} else if c == "cache" {
		if args["$1"] == "clear" {
			CacheClear()
		} else if args["$1"] == "check" {
			ui.Error("Not implemented yet.")
		} else {
			ui.Error(notFound, args["$1"], "\n", "try cache clear or cache check")
		}
	} else if c == "self" {
		if args["$1"] == "upgrade" {
			SelfUpgrade()
		} else if args["$1"] == "uninstall" {
			SelfUninstall()
		} else {
			ui.Error(notFound, args["$1"])
		}
	} else if c == "bootstrap" {
		err = Bootstrap(".")
	} else if c == "test" {
		RunTest("tests")
	} else if c == "hook" {
		RunHook(".", args["$1"])
	} else {
		return false, nil
	}

	return true, err
}


================================================
FILE: src/cli_test.go
================================================
package main

import (
	"testing"
	// "reflect"
	_ "fmt"
	"github.com/stretchr/testify/require"
)

func TestArgs(t *testing.T) {
	require := require.New(t)

	// Basic
	command, args := GetArgs([]string{"make", "-p", "npm"})
	require.Equal("make", command)
	require.Equal(Arguments{"$0": "make --p npm", "P": "npm"}, args)

	// Nothing
	command, args = GetArgs([]string{})
	require.Equal("", command)
	require.Equal(Arguments{"$0": ""}, args)

	// No args
	command, args = GetArgs([]string{"install"})
	require.Equal("install", command)
	require.Equal(Arguments{"$0": "install"}, args)

	// bools and long mix
	command, args = GetArgs([]string{"install", "--dev", "--provider", "npm"})
	require.Equal("install", command)
	require.Equal(Arguments{"$0": "install --dev --provider npm", "Dev": "true", "Provider": "npm"}, args)
	command, args = GetArgs([]string{"install", "--provider", "npm", "--dev"})
	require.Equal("install", command)
	require.Equal(Arguments{"$0": "install --provider npm --dev", "Dev": "true", "Provider": "npm"}, args)

	// bools at the end
	command, args = GetArgs([]string{"install", "--dev"})
	require.Equal("install", command)
	require.Equal(Arguments{"$0": "install --dev", "Dev": "true"}, args)

	// long args
	command, args = GetArgs([]string{"install", "--provider", "npm"})
	require.Equal("install", command)
	require.Equal(Arguments{"$0": "install --provider npm", "Provider": "npm"}, args)

	// anonymous
	command, args = GetArgs([]string{"install", "npm"})
	require.Equal("install", command)
	require.Equal(Arguments{"$0": "install npm", "$1": "npm"}, args)

	// asList
	command, args = GetArgs([]string{"install", "go", "npm"})
	require.Equal([]string{"go", "npm"}, args.AsList())

}


================================================
FILE: src/defaultProvider/defaultProvider.go
================================================
package defaultProvider

import (
	"encoding/json"
	"io/ioutil"
	"os"
	"reflect"
	"regexp"

	"../ui"
	"../utils"
)

func Bootstrap(path string) {
	if utils.FileExists(utils.Path(path + "/gupm.json")) {
		ui.Error("A project already exists in this folder. Aborting bootstrap.")
		return
	}

	name := ui.WaitForInput("Please enter the name of the project: ")
	description := ui.WaitForInput("Enter a description: ")
	author := ui.WaitForInput("Enter the author: ")
	licence := ui.WaitForInput("Enter the licence (ISC): ")

	if name == "" {
		ui.Error("Name cannot be empty. Try again")
		return
	} else {
		if licence == "" {
			licence = "ISC"
		}

		fileContent := `{
	"name": "` + name + `",
	"version": "0.0.1",
	"description": "` + description + `",
	"author": "` + author + `",
	"licence": "` + licence + `"
}`
		ioutil.WriteFile(utils.Path(path+"/gupm.json"), []byte(fileContent), os.ModePerm)
	}
}

func GetPackageConfig(entryPoint string) map[string]interface{} {
	var packageConfig map[string]interface{}
	b, err := ioutil.ReadFile(entryPoint)
	if err != nil {
		ui.Error(err.Error() + " : " + entryPoint)
	}

	json.Unmarshal([]byte(string(b)), &packageConfig)

	return packageConfig
}

func GetDependency(provider string, name string, version string, url string, path string) (string, error) {
	return string(utils.HttpGet(url)), nil
}

func PostGetDependency(provider string, name string, version string, url string, path string, result string) (string, error) {
	os.MkdirAll(path, os.ModePerm)
	tarCheck := regexp.MustCompile(`\.tgz$`)
	tryTar := tarCheck.FindString(url)
	gzCheck := regexp.MustCompile(`\.gz$`)
	trygz := gzCheck.FindString(url)
	zipCheck := regexp.MustCompile(`\.zip$`)
	tryZip := zipCheck.FindString(url)

	if tryTar != "" {
		resultFiles, err := utils.Untar(result)
		if err != nil {
			return path, err
		}
		resultFiles.SaveAt(path)
	} else if trygz != "" {
		resultFiles, err := utils.Ungz(result)
		if err != nil {
			return path, err
		}
		resultFiles.SaveAt(path)
	} else if tryZip != "" {
		resultFiles, err := utils.Unzip(result)
		if err != nil {
			return path, err
		}
		resultFiles.SaveAt(path)
	}

	utils.SaveLockDep(path)

	return path, nil
}

func GetDependencyList(config map[string]interface{}) []map[string]interface{} {
	if config == nil {
		ui.Error("no config found. Please bootstrap the project with `g bootstrap`")
		return nil
	}
	depEnv, ok := config["dependencies"].(map[string]interface{})
	if !ok {
		ui.Log("no dependencies")
		return nil
	}
	depList, hasDefault := depEnv["default"].(map[string]interface{})
	if !hasDefault {
		ui.Log("no dependencies")
		return nil
	}
	result := make([]map[string]interface{}, 0)
	for name, value := range depList {
		dep := utils.BuildDependencyFromString("gupm", name)
		if reflect.TypeOf(value).String() == "string" {
			dep["version"] = value
		} else {
			valueObject := value.(map[string]interface{})
			if valueObject["provider"].(string) != "" {
				dep["provider"] = valueObject["provider"]
			}
			if valueObject["version"].(string) != "" {
				dep["version"] = valueObject["version"]
			}
		}
		result = append(result, dep)
	}
	return result
}

func ExpandDependency(dependency map[string]interface{}) (map[string]interface{}, error) {
	configFilePath := utils.Path(dependency["path"].(string) + "/gupm.json")

	if utils.FileExists(configFilePath) {
		config := GetPackageConfig(configFilePath)
		dependency["dependencies"] = make(map[string]interface{})

		if config["dependencies"] != nil {
			dependency["dependencies"] = GetDependencyList(config)
		}
	}

	return dependency, nil
}

func BinaryInstall(dest string, packagePath string) error {
	packages, _ := utils.ReadDir(packagePath)

	for _, dep := range packages {
		configFilePath := utils.Path(packagePath + "/" + dep.Name() + "/gupm.json")
		if utils.FileExists(configFilePath) {
			config := GetPackageConfig(configFilePath)
			if config["binaries"] != nil {
				bins := config["binaries"].(map[string]string)
				for name, relPath := range bins {
					os.Symlink(utils.Path("/../gupm_modules/"+"/"+dep.Name()+relPath), utils.Path(dest+"/"+name))
				}
			}
		}
	}

	return nil
}

func SaveDependencyList(path string, depList []map[string]interface{}) error {
	config := GetPackageConfig(utils.Path(path + "/gupm.json"))
	if config["dependencies"] == nil {
		config["dependencies"] = make(map[string]interface{})
	}
	config["dependencies"].(map[string]interface{})["default"] = make(map[string]interface{})

	for _, dep := range depList {
		key := utils.BuildStringFromDependency(map[string]interface{}{
			"provider": dep["provider"].(string),
			"name":     dep["name"].(string),
		})

		config["dependencies"].(map[string]interface{})["default"].(map[string]interface{})[key] = dep["version"].(string)
	}

	utils.WriteJsonFile(utils.Path(path+"/"+"gupm.json"), config)

	return nil
}


================================================
FILE: src/defaultProvider/publish.go
================================================
package defaultProvider

import (
	"os"

	"../ui"
	"../utils"
)

func Publish(path string, namespace string) error {
	configPath := utils.Path(path + "/gupm.json")
	if utils.FileExists(configPath) {
		packageConfig := new(utils.GupmEntryPoint)
		errConfig := utils.ReadJSON(configPath, &packageConfig)
		if errConfig != nil {
			ui.Error("Can't read provider configuration")
			return errConfig
		}

		pname := packageConfig.Name

		if namespace != "" {
			pname = namespace + "/" + pname
		}

		ppath := utils.Path(path + "/" + packageConfig.Publish.Dest)
		repoConfig := utils.GetOrCreateRepo(ppath)
		packageList := repoConfig["packages"].(map[string]interface{})

		if packageList[pname] != nil {
			if utils.Contains(packageList[pname], packageConfig.Version) {
				ui.Error("Package " + pname + "@" + packageConfig.Version + " already published. Please bump the version number.")
				return nil
			} else {
				packageList[pname] = append(utils.ArrString(packageList[pname]), packageConfig.Version)
			}
		} else {
			packageList[pname] = make([]string, 0)
			packageList[pname] = append(utils.ArrString(packageList[pname]), packageConfig.Version)
		}

		installPath := ppath + utils.Path("/"+pname+"/"+packageConfig.Version)
		os.MkdirAll(installPath, os.ModePerm)

		sourcePaths := make([]string, 0)
		for _, src := range packageConfig.Publish.Source {
			sourcePaths = append(sourcePaths, utils.Path(path+"/"+src))
		}
		arch, _ := utils.Tar(sourcePaths)
		arch.SaveAt(installPath + utils.Path("/"+packageConfig.Name+"-"+packageConfig.Version+".tgz"))

		repoConfig["packages"] = packageList
		utils.SaveRepo(ppath, repoConfig)
	} else {
		ui.Error("Can't find provider configuration")
	}

	return nil
}


================================================
FILE: src/distribution_gupm.json
================================================
{
    "name": "gupm",
    "config": {
        "default": {
            "entrypoint": "gupm.json",
            "installPath": "gupm_modules",
            "defaultProvider": "gupm",
            "osProviders": {
                "linux": "linux",
                "mac": "brew",
                "windows": "chocolatey"
            }
        }
    }
}


================================================
FILE: src/gitHooks.go
================================================
package main

import (
	"fmt"
	"os"
	"regexp"
	"strings"

	"./utils"
	"github.com/bmatcuk/doublestar"
)

func BuildGitHooks(path string) {
	if utils.FileExists(".git") {
		if !utils.FileExists(".git/hooks/pre-commit") {
			utils.WriteFile(".git/hooks/pre-commit", "g hook precommit")
		}
		if !utils.FileExists(".git/hooks/pre-push") {
			utils.WriteFile(".git/hooks/pre-push", "g hook prepush")
		}
	}
}

func runhook(hook string) {
	commandList := strings.Split(hook, " ")
	stagedFiles, _ := utils.RunCommand("git", []string{"diff", "--cached", "--name-only"})
	unPushedFiles := ""
	fyg, _ := utils.RunCommand("git", []string{"log", "--branches", "--not", "--remotes", "--name-status", "--oneline"})
	unPushedFilesRaw := strings.Split(fyg, "\n")

	extractFileName := regexp.MustCompile(`^[AM]\b(.*)`)
	for _, v := range unPushedFilesRaw {
		if extracted := extractFileName.FindStringSubmatch(v); len(extracted) > 0 {
			unPushedFiles += strings.Trim(extracted[1], " 	") + "\n"
		}
	}
	unPushedFiles = strings.Trim(unPushedFiles, " ")

	for i, v := range commandList {
		stagedFilesCheck := regexp.MustCompile(`^\$StagedFiles(\(([\w\/\.\*\-\_]+)?\)?)?`)
		tryStagedFiles := stagedFilesCheck.FindStringSubmatch(v)
		unpushedFilesCheck := regexp.MustCompile(`^\$UnpushedFiles(\(([\w\/\.\*\-\_]+)?\)?)?`)
		tryUnpushedFiles := unpushedFilesCheck.FindStringSubmatch(v)

		if len(tryStagedFiles) == 3 {
			if tryStagedFiles[2] == "" {
				commandList[i] = strings.ReplaceAll(stagedFiles, " ", "\\ ")
				commandList[i] = strings.ReplaceAll(commandList[i], "\n", " ")
			} else {
				commandList[i] = ""
				stagedFilesList := strings.Split(stagedFiles, "\n")
				for _, s := range stagedFilesList {
					isIn, _ := doublestar.Match(tryStagedFiles[2], s)
					if isIn {
						commandList[i] += strings.ReplaceAll(s, " ", "\\ ") + " "
					}
				}
				commandList[i] = strings.Trim(commandList[i], " ")
			}
		}

		if len(tryUnpushedFiles) == 3 {
			if tryUnpushedFiles[2] == "" {
				commandList[i] = strings.ReplaceAll(unPushedFiles, " ", "\\ ")
				commandList[i] = strings.ReplaceAll(commandList[i], "\n", " ")
			} else {
				commandList[i] = ""
				unpushedFilesList := strings.Split(unPushedFiles, "\n")
				for _, s := range unpushedFilesList {
					isIn, _ := doublestar.Match(tryUnpushedFiles[2], s)
					if isIn {
						commandList[i] += strings.ReplaceAll(s, " ", "\\ ") + " "
					}
				}
				commandList[i] = strings.Trim(commandList[i], " ")
			}
		}
	}

	commandListConsolidated := strings.Trim(strings.Join(commandList, " "), " ")
	commandList = strings.Split(commandListConsolidated, " ")

	err := utils.ExecCommand(commandList[0], append(commandList[1:]))
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

func runhooklist(hooklist string) {
	hooks := strings.Split(hooklist, ";")
	for _, hook := range hooks {
		runhook(strings.Trim(hook, " "))
	}
}

func runHooks(hooks interface{}) {
	ch := make(chan int)
	listHooks, isArray := hooks.([]interface{})
	if isArray {
		for _, hook := range listHooks {
			go func(hook string) {
				runhooklist(hook)
				ch <- 0
			}(hook.(string))
		}
		for range listHooks {
			<-ch
		}
	} else {
		runhooklist(hooks.(string))
	}
}

func RunHook(path string, hook string) {
	config, _ := utils.ReadGupmJson("gupm.json")

	if hook == "precommit" && config.Git.Hooks.Precommit != nil {
		runHooks(config.Git.Hooks.Precommit)
	}
	if hook == "prepush" && config.Git.Hooks.Prepush != nil {
		runHooks(config.Git.Hooks.Prepush)
	}
}


================================================
FILE: src/global.go
================================================
package main

import (
	"os"
	"path/filepath"

	"./ui"
	"./utils"
)

func installBins(path string) {
	var GLOBAL = utils.Path(utils.HOMEDIR(".") + "/.gupm/global")
	bins := utils.RecursiveFileWalkDir(GLOBAL + "/.bin")

	for _, bin := range bins {
		name := filepath.Base(bin)
		if !utils.FileExists(path + "/" + name) {
			os.Symlink(bin, path+"/"+name)
		}
	}
}

func GlobalAdd(rls []string) {
	ui.Title("Installing global dependency...")
	var GLOBAL = utils.Path(utils.HOMEDIR(".") + "/.gupm/global")

	if !utils.FileExists(GLOBAL + utils.Path("/gupm.json")) {
		os.MkdirAll(GLOBAL, os.ModePerm)
		utils.WriteFile(GLOBAL+utils.Path("/gupm.json"), "{}")
	}

	ui.Log("Installing...")
	AddDependency(GLOBAL, rls)
	InstallProject(GLOBAL)

	ui.Log("Add binaries...")
	if utils.OSNAME() != "windows" {
		if utils.FileExists("/usr/local/bin/") {
			installBins("/usr/local/bin/")
		} else {
			installBins("/usr/bin/")
		}
	} else {
		ui.Error("Global Installation not supported on Windows yet. Please add .gupm/global/.bin to your PATH")
	}
}

func GlobalDelete(rls []string) {
	var GLOBAL = utils.Path(utils.HOMEDIR(".") + "/.gupm/global")

	if !utils.FileExists(GLOBAL + utils.Path("/gupm.json")) {
		os.MkdirAll(GLOBAL, os.ModePerm)
		utils.WriteFile(GLOBAL+utils.Path("/gupm.json"), "{}")
	}

	RemoveDependency(GLOBAL, rls)
}


================================================
FILE: src/index.go
================================================
package main

import (
	"fmt"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"./jsVm"
	"./ui"
	"./utils"
)

var Provider string

func ScriptExists(path string) string {
	if utils.FileExists(path + ".gs") {
		return path + ".gs"
	} else if utils.FileExists(path) && !utils.IsDirectory(path) {
		return path
	} else {
		return ""
	}
}

func executeFile(path string, args Arguments) {
	_, err := jsVm.Run(path, args.AsJson())
	if err != nil {
		ui.Error("File execution failed")
		ui.Error(err)
		Exit(1)
	}
}

func binFile(name string, args []string) {
	path := utils.Path("./.bin/" + name)
	realPath, _ := filepath.EvalSymlinks(path)
	err := utils.ExecCommand(realPath, args)
	if err != nil {
		ui.Error(err)
		Exit(1)
	}
}

func Exit(code int) {
	ui.Stop()
	os.Exit(code)
}

func runAlias(alias string) {
	commands := strings.Split(alias, ";")
	for _, command := range commands {
		commandList := strings.Split(command, " ")
		err := utils.ExecCommand(commandList[0], append(commandList[1:], os.Args[2:]...))
		if err != nil {
			ui.Error(err)
		}
	}
}

func runAliasList(aliasList string) {
	aliases := strings.Split(aliasList, ";")
	for _, alias := range aliases {
		runhook(strings.Trim(alias, " "))
	}
}

func main() {
	binFolder := make(map[string]bool)

	if utils.FileExists(".bin") {
		files, _ := utils.ReadDir(".bin")
		for _, file := range files {
			binFolder[file.Name()] = true
		}
	}

	c, args := GetArgs(os.Args[1:])

	if utils.FileExists(".gupm_rc.gs") {
		executeFile(".gupm_rc.gs", args)
	}

	aliases := map[string]interface{}{}
	if utils.FileExists("gupm.json") {
		packageConfig, errConfig := utils.ReadGupmJson("gupm.json")
		if errConfig != nil {
			ui.Error(errConfig)
		} else {
			aliases = packageConfig.Cli.Aliases
		}
	}

	script := ScriptExists(c)
	if didExec, err := ExecCli(c, args); didExec {
		if err != nil {
			ui.Error(err)
			Exit(1)
		}
		if script != "" {
			executeFile(script, args)
		}
	} else if c == "env" || c == "e" {
		toProcess := os.Args[2:]
		re := regexp.MustCompile(`([\w\-\_]+)=([\w\-\_]+)`)
		isEnv := re.FindAllStringSubmatch(toProcess[0], -1)
		for isEnv != nil {
			name := isEnv[0][1]
			value := isEnv[0][2]
			os.Setenv(name, value)
			toProcess = toProcess[1:]
			isEnv = re.FindAllStringSubmatch(toProcess[0], -1)
		}
		utils.ExecCommand(toProcess[0], toProcess[1:])
	} else if aliases[c] != nil {
		ch := make(chan int)
		listAlias, isArray := aliases[c].([]interface{})
		if isArray {
			for _, aliasLine := range listAlias {
				go func(aliasLine string) {
					runAliasList(aliasLine)
					ch <- 0
				}(aliasLine.(string))
			}
			for range listAlias {
				<-ch
			}
		} else {
			runAliasList(aliases[c].(string))
		}
	} else if binFolder[c] == true {
		binFile(c, os.Args[2:])
	} else if script != "" {
		executeFile(script, args)
	} else if c == "" {
		fmt.Println("Welcome to GuPM version 1.0.0 \ntry 'g help' for a list of commands. Try 'g filename' to execute a file.")
	} else {
		fmt.Println("Command not found. Try 'g help' or check filename.")
		Exit(1)
	}

	ui.Stop()
}


================================================
FILE: src/installProject.go
================================================
package main

import (
	"errors"
	"fmt"
	"sync"
	"time"

	"./provider"
	"./ui"
	"./utils"
	"github.com/mitchellh/go-homedir"
)

var cacheExpanded = make(map[string]map[string]interface{})
var lock = sync.RWMutex{}
var lockList = sync.RWMutex{}

func expandDepList(depList []map[string]interface{}) []map[string]interface{} {
	channel := make(chan int)

	for index, dep := range depList {
		go (func(channel chan int, index int, dep map[string]interface{}) {
			if dep["expanded"] != true {
				newDep := make(map[string]interface{})
				for key, value := range dep {
					newDep[key] = value
				}
				newDep, errExpand := provider.ResolveDependencyLocation(newDep)
				if newDep == nil {
					ui.Error("Provider " + dep["provider"].(string) + " didnt resolve " + dep["name"].(string) + "@" + dep["version"].(string))
					ui.Error(errExpand)
					channel <- 0
					return
				}

				hdir, errH := homedir.Dir()
				if errH != nil {
					ui.Error(errH)
					hdir = "."
				}
				_, ok := newDep["url"].(string)
				if !ok || newDep["url"].(string) == "" {
					ui.Error("Cannot resolve : " + newDep["name"].(string))
					channel <- 1
					return
				}

				newDep["path"] = hdir + "/.gupm/cache/" + newDep["provider"].(string) + "/" + newDep["name"].(string) + "/" + newDep["version"].(string)

				if !utils.FileExists(newDep["path"].(string)) || !utils.FileExists(newDep["path"].(string)+"/.gupm_locked") {
					getRes, errorGD := provider.GetDependency(
						newDep["provider"].(string),
						newDep["name"].(string),
						newDep["version"].(string),
						newDep["url"].(string),
						newDep["path"].(string),
					)
					if errorGD != nil {
						ui.Error(errorGD)
					}
					newPath, errorPGD := provider.PostGetDependency(
						newDep["provider"].(string),
						newDep["name"].(string),
						newDep["version"].(string),
						newDep["url"].(string),
						newDep["path"].(string),
						getRes,
					)

					newDep["path"] = newPath

					if errorPGD != nil {
						ui.Error(errorPGD)
					}
				}

				lock.Lock()
				if newDep["expanded"] != true {
					if cacheExpanded[newDep["url"].(string)]["expanded"] != true {
						newDep, errExpand = provider.ExpandDependency(newDep)
						if errExpand != nil || newDep == nil || len(newDep) == 0 {
							ui.Error("Provider " + dep["provider"].(string) + " didnt expand " + dep["name"].(string) + "@" + dep["version"].(string))
							ui.Error(errExpand)
							channel <- 0
							return
						}

						newDep["expanded"] = true
						cacheExpanded[newDep["url"].(string)] = newDep
					} else {
						newDep = cacheExpanded[newDep["url"].(string)]
					}
				}
				ui.Log("Get dependency " + newDep["name"].(string))
				lock.Unlock()

				lockList.Lock()

				depList[index] = newDep
				nextDepList, ok := depList[index]["dependencies"].([]map[string]interface{})
				lockList.Unlock()

				if ok {
					res := expandDepList(nextDepList)
					lockList.Lock()
					depList[index]["dependencies"] = res
					lockList.Unlock()
				}
			}
			channel <- 1
		})(channel, index, dep)
	}

	for range depList {
		i := <-channel
		if i == 0 {
			return nil
		}
	}

	return depList
}

func installDep(path string, depList []map[string]interface{}) map[string]string {
	installPaths := make(map[string]string)
	installPathsLock := sync.RWMutex{}

	var channel = make(chan int)
	for index, dep := range depList {
		go (func(channel chan int, index int, dep map[string]interface{}) {
			depProviderConfig, err := provider.GetProviderConfig(dep["provider"].(string))
			destination := utils.Path(path + "/" + depProviderConfig.Config.Default.InstallPath)

			if dep["path"] != nil {
				packageConfig, errC := utils.ReadGupmJson(utils.Path(dep["path"].(string) + "/gupm.json"))

				if errC == nil && packageConfig != nil && packageConfig.WrapInstallFolder != "" {
					destination += utils.Path("/" + packageConfig.WrapInstallFolder)
				}
			}

			ui.Error(err)
			ui.Log("Installing " + path)
			provider.InstallDependency(destination, dep)

			// if path == "." {
			installPathsLock.Lock()
			installPaths[dep["provider"].(string)] = utils.Path(path + "/" + depProviderConfig.Config.Default.InstallPath)
			installPathsLock.Unlock()
			// }

			nextDepList, ok := depList[index]["dependencies"].([]map[string]interface{})

			if ok {
				installDep(utils.Path(destination+"/"+depList[index]["name"].(string)), nextDepList)
			}
			channel <- 1
		})(channel, index, dep)
	}
	for range depList {
		<-channel
	}
	return installPaths
}

var providerConfig *utils.GupmEntryPoint

func InstallProject(path string) error {
	start := time.Now()

	ui.Title("Installing project...")

	var err error
	var packageConfig utils.Json
	var depList []map[string]interface{}

	err = provider.InitProvider(Provider)
	if err != nil {
		return err
	}

	providerConfig, err = provider.GetProviderConfig(Provider)
	ui.Error(err)
	packageConfig, _ = provider.GetPackageConfig(path)
	packageConfig, _ = provider.PostGetPackageConfig(packageConfig)

	depList, err = provider.GetDependencyList(packageConfig)
	if err != nil {
		return err
	}
	if depList == nil {
		ui.Log("No dependencies found.")
		return nil
	}

	ui.Title("Expand dependency list...")
	depList = expandDepList(depList)
	if depList == nil {
		return errors.New("Failed to expand dependancy list")
	}

	ui.Title("Build dependency list...")
	depList = provider.BuildDependencyTree(depList)
	if depList == nil {
		return errors.New("Failed to build dependancy list")
	}

	ui.Title("Install dependencies...")
	installPaths := installDep(path, depList)

	ui.Title("Install Binaries...")
	err = provider.BinaryInstall(path, installPaths)
	if err != nil {
		return err
	}

	ui.Title("Installation done ❤️")

	timeElapsed := fmt.Sprintf("%f", time.Since(start).Seconds())
	ui.Log(timeElapsed + "s elapsed\n")
	return nil
}


================================================
FILE: src/jsVm/jsVm.go
================================================
package jsVm

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"
	"time"

	"../ui"
	"../utils"
	"github.com/Masterminds/semver"
	"github.com/robertkrimen/otto"
)

var lock = sync.RWMutex{}
var scriptCache = make(map[string]string)

func Run(path string, input utils.Json) (otto.Value, error) {
	var err error
	var ret otto.Value

	lock.Lock()
	if scriptCache[path] == "" {
		file, err := ioutil.ReadFile(path)
		if err != nil {
			return otto.UndefinedValue(), err
		}
		scriptCache[path] = string(file)
	}
	script := scriptCache[path]
	lock.Unlock()

	vm := otto.New()
	vm.Interrupt = make(chan func(), 1)
	Setup(vm)
	vm.Set("_DIRNAME", filepath.Dir(path))

	for varName, varValue := range input /*.AsObject()*/ {
		vm.Set(varName, varValue)
	}

	ret, err = vm.Run(script)

	if err != nil {
		ui.Error(err)
		return otto.UndefinedValue(), errors.New("Error occured while executing the GS code")
	}

	return ret, nil
}

func Setup(vm *otto.Otto) {
	vm.Set("httpGetJson", func(call otto.FunctionCall) otto.Value {
		url, _ := call.Argument(0).ToString()
		res := utils.HttpGet(url)
		result, _ := vm.ToValue(utils.StringToJSON(string(res)))
		return result
	})

	vm.Set("httpGet", func(call otto.FunctionCall) otto.Value {
		url, _ := call.Argument(0).ToString()
		res := utils.HttpGet(url)
		result, _ := vm.ToValue(string(res))
		return result
	})

	vm.Set("dir", func(call otto.FunctionCall) otto.Value {
		glob, _ := call.Argument(0).ToString()
		res, _ := utils.Dir(glob)
		result, _ := vm.ToValue(res)
		return result
	})

	vm.Set("osSleep", func(call otto.FunctionCall) otto.Value {
		timeMs, _ := call.Argument(0).ToInteger()
		time.Sleep(time.Duration(timeMs) * time.Millisecond)
		result, _ := vm.ToValue(true)
		return result
	})

	vm.Set("readJsonFile", func(call otto.FunctionCall) otto.Value {
		path, _ := call.Argument(0).ToString()
		path = utils.Path(path)
		b, err := ioutil.ReadFile(path)
		if err != nil {
			ui.Error(err)
		}
		result, _ := vm.ToValue(utils.StringToJSON(string(b)))
		return result
	})

	vm.Set("readFile", func(call otto.FunctionCall) otto.Value {
		path, _ := call.Argument(0).ToString()
		path = utils.Path(path)
		b, err := ioutil.ReadFile(path)
		if err != nil {
			ui.Error(err)
		}
		result, _ := vm.ToValue(string(b))
		return result
	})

	vm.Set("removeFiles", func(call otto.FunctionCall) otto.Value {
		files, _ := call.Argument(0).Export()
		_, isString := files.(string)
		if isString {
			files = []string{files.(string)}
		}
		utils.RemoveFiles(files.([]string))
		result, _ := vm.ToValue(true)
		return result
	})

	vm.Set("copyFiles", func(call otto.FunctionCall) otto.Value {
		files, _ := call.Argument(0).Export()
		_, isString := files.(string)
		if isString {
			files = []string{files.(string)}
		}
		path, _ := call.Argument(1).ToString()
		path = utils.Path(path)
		utils.CopyFiles(files.([]string), path)
		result, _ := vm.ToValue(true)
		return result
	})

	vm.Set("pwd", func(call otto.FunctionCall) otto.Value {
		dir, _ := os.Getwd()
		result, _ := vm.ToValue(dir)
		return result
	})

	vm.Set("env", func(call otto.FunctionCall) otto.Value {
		name, _ := call.Argument(0).ToString()
		value, _ := call.Argument(1).ToString()

		if value == "undefined" {
			result, _ := vm.ToValue(os.Getenv(name))
			return result
		} else {
			os.Setenv(name, value)
			res, _ := vm.ToValue(true)
			return res
		}
	})

	vm.Set("exec", func(call otto.FunctionCall) otto.Value {
		exec, _ := call.Argument(0).ToString()
		args, _ := call.Argument(1).Export()
		_, ok := args.([]string)
		if !ok {
			args = make([]string, 0)
		}

		err := utils.ExecCommand(exec, args.([]string))

		result, _ := vm.ToValue(err)
		return result
	})

	vm.Set("run", func(call otto.FunctionCall) otto.Value {
		exec, _ := call.Argument(0).ToString()
		args, _ := call.Argument(1).Export()
		_, ok := args.([]string)
		if !ok {
			args = make([]string, 0)
		}

		res, err := utils.RunCommand(exec, args.([]string))

		if err != nil {
			ui.Error(err)
			result, _ := vm.ToValue(false)
			return result
		}

		if res != "" {
			res = res[:len(res)-1]
		}

		result, _ := vm.ToValue(res)
		return result
	})

	vm.Set("exit", func(call otto.FunctionCall) otto.Value {
		code, _ := call.Argument(0).ToInteger()
		os.Exit(int(code))
		result, _ := vm.ToValue(true)
		return result
	})

	vm.Set("writeJsonFile", func(call otto.FunctionCall) otto.Value {
		path, _ := call.Argument(0).ToString()
		path = utils.Path(path)
		toExport, _ := call.Argument(1).Export()
		file := JsonExport(toExport).(map[string]interface{})

		utils.WriteJsonFile(path, file)

		result, _ := vm.ToValue(true)
		return result
	})

	vm.Set("writeFile", func(call otto.FunctionCall) otto.Value {
		path, _ := call.Argument(0).ToString()
		path = utils.Path(path)
		toExport, _ := call.Argument(1).ToString()
		err := ioutil.WriteFile(path, []byte(toExport), os.ModePerm)
		if err != nil {
			ui.Error(err)
		}
		result, _ := vm.ToValue(true)
		return result
	})

	vm.Set("_OSNAME", utils.OSNAME())

	vm.Set("mkdir", func(call otto.FunctionCall) otto.Value {
		path, _ := call.Argument(0).ToString()
		path = utils.Path(path)
		os.MkdirAll(path, os.ModePerm)
		result, _ := vm.ToValue(true)
		return result
	})

	vm.Set("saveLockDep", func(call otto.FunctionCall) otto.Value {
		path, _ := call.Argument(0).ToString()
		path = utils.Path(path)
		utils.SaveLockDep(path)
		result, _ := vm.ToValue(true)
		return result
	})

	vm.Set("fileExists", func(call otto.FunctionCall) otto.Value {
		path, _ := call.Argument(0).ToString()
		path = utils.Path(path)
		res := utils.FileExists(path)
		result, _ := vm.ToValue(res)
		return result
	})

	vm.Set("waitForInput", func(call otto.FunctionCall) otto.Value {
		msg, _ := call.Argument(0).ToString()
		res := ui.WaitForInput(msg)
		result, _ := vm.ToValue(res)
		return result
	})

	vm.Set("waitForMenu", func(call otto.FunctionCall) otto.Value {
		msg, _ := call.Argument(0).Export()
		res := ui.WaitForMenu(msg.([]string))
		result, _ := vm.ToValue(res)
		return result
	})

	vm.Set("waitForKey", func(call otto.FunctionCall) otto.Value {
		ui.WaitForKey()
		result, _ := vm.ToValue(true)
		return result
	})

	vm.Set("tar", func(call otto.FunctionCall) otto.Value {
		files, _ := call.Argument(0).Export()
		_, isString := files.(string)
		if isString {
			files = []string{files.(string)}
		}
		res, err := utils.Tar(files.([]string))
		if err != nil {
			ui.Error(err)
		}
		b, _ := json.Marshal(res)
		result, _ := vm.ToValue(utils.StringToJSON(string(b)))
		return result
	})

	vm.Set("readDir", func(call otto.FunctionCall) otto.Value {
		path, _ := call.Argument(0).ToString()
		path = utils.Path(path)
		var filenames = make([]string, 0)
		files, _ := utils.ReadDir(path)
		for _, file := range files {
			filenames = append(filenames, file.Name())
		}
		result, _ := vm.ToValue(filenames)
		return result
	})

	vm.Set("createSymLink", func(call otto.FunctionCall) otto.Value {
		from, _ := call.Argument(0).ToString()
		from = utils.Path(from)
		to, _ := call.Argument(1).ToString()
		to = utils.Path(to)
		err := os.Symlink(from, to)
		if err != nil {
			ui.Error(err)
		}
		result, _ := vm.ToValue(true)
		return result
	})

	vm.Set("untar", func(call otto.FunctionCall) otto.Value {
		var res utils.FileStructure
		file, _ := call.Argument(0).ToString()
		res, _ = utils.Untar(file)
		b, _ := json.Marshal(res)
		result, _ := vm.ToValue(utils.StringToJSON(string(b)))
		return result
	})

	vm.Set("unzip", func(call otto.FunctionCall) otto.Value {
		var res utils.FileStructure
		file, _ := call.Argument(0).ToString()
		res, _ = utils.Unzip(file)
		b, _ := json.Marshal(res)
		result, _ := vm.ToValue(utils.StringToJSON(string(b)))
		return result
	})

	vm.Set("saveFileAt", func(call otto.FunctionCall) otto.Value {
		var fs utils.FileStructure
		file, _ := call.Argument(0).Export()
		path, _ := call.Argument(1).ToString()
		path = utils.Path(path)
		bytes, _ := json.Marshal(file)
		json.Unmarshal(bytes, &fs)
		fs.SaveAt(path)
		result, _ := vm.ToValue(path)
		return result
	})

	vm.Set("semverInRange", func(call otto.FunctionCall) otto.Value {
		rangeStr, _ := call.Argument(0).ToString()
		version, _ := call.Argument(1).ToString()
		rangeVer, _ := semver.NewConstraint(rangeStr)
		sver, _ := semver.NewVersion(version)
		value := rangeVer.Check(sver)
		result, _ := vm.ToValue(value)
		return result
	})

	vm.Set("semverLatestInRange", func(call otto.FunctionCall) otto.Value {
		rangeStr, _ := call.Argument(0).ToString()
		versionListUntyped, _ := call.Argument(1).Export()
		versionList := utils.ArrString(versionListUntyped)
		var version string
		var versionSem *semver.Version
		rangeVer, _ := semver.NewConstraint(rangeStr)

		for _, verCandUnk := range versionList {
			verCand := verCandUnk
			sver, err := semver.NewVersion(verCand)
			if err != nil {
				ui.Error(err)
			}

			if rangeVer.Check(sver) && (versionSem == nil || sver.GreaterThan(versionSem)) {
				version = verCand
				versionSem = sver
			}
		}

		if version != "" {
			result, _ := vm.ToValue(version)
			return result
		} else {
			return otto.UndefinedValue()
		}
	})
}

func JsonExport(input interface{}) interface{} {
	asMap, isMap := input.(map[string]interface{})
	asSlice, isSlice := input.([]interface{})
	if isMap {
		for index, value := range asMap {
			asValue, ok := value.(otto.Value)
			if ok {
				exported, _ := asValue.Export()
				asMap[index] = JsonExport(exported)
			}
		}
		return asMap
	} else if isSlice {
		for index, value := range asSlice {
			asValue, ok := value.(otto.Value)
			if ok {
				exported, _ := asValue.Export()
				asSlice[index] = JsonExport(exported)
			}
		}
		return asSlice
	} else {
		return input
	}
}


================================================
FILE: src/plugins.go
================================================
package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"./provider"
	"./ui"
	"./utils"
)

func PluginLink(path string) {
	configPath := utils.Path(path + "/gupm.json")
	if utils.FileExists(configPath) {
		packageConfig := new(utils.GupmEntryPoint)
		errConfig := utils.ReadJSON(configPath, &packageConfig)
		if errConfig != nil {
			ui.Error("Can't read provider configuration")
			ui.Error(errConfig)
			return
		}

		pluginFolder := utils.HOMEDIR(".") + utils.Path("/.gupm/plugins/")
		os.MkdirAll(pluginFolder, os.ModePerm)
		err := os.Symlink(utils.AbsPath(path), pluginFolder+packageConfig.Name)
		if err != nil {
			ui.Error(err)
		}
	} else {
		ui.Error("Can't find provider configuration")
	}
}

func PluginInstall(path string, plugins []string) error {
	ui.Title("Install plugin...")
	pluginFolder := utils.HOMEDIR(".") + utils.Path("/.gupm/plugins/")

	for _, rls := range plugins {
		ui.Log(rls)
		newDep, err := provider.ResolveDependencyLocation(utils.BuildDependencyFromString("https", rls))
		if err != nil {
			return err
		}
		pluginName := filepath.Base(newDep["name"].(string))
		if len(strings.Split(pluginName, ":")) > 1 {
			pluginName = strings.Split(pluginName, ":")[1]
		}
		if len(strings.Split(pluginName, "/")) > 1 {
			pluginName = strings.Split(pluginName, "/")[1]
		}

		newDep["path"] = pluginFolder + utils.Path(pluginName)

		getRes, errorGD := provider.GetDependency(
			newDep["provider"].(string),
			newDep["name"].(string),
			newDep["version"].(string),
			newDep["url"].(string),
			newDep["path"].(string),
		)
		if errorGD != nil {
			return errorGD
		}

		_, errorPGD := provider.PostGetDependency(
			newDep["provider"].(string),
			newDep["name"].(string),
			newDep["version"].(string),
			newDep["url"].(string),
			newDep["path"].(string),
			getRes,
		)
		if errorPGD != nil {
			return errorPGD
		}

		InstallProject(newDep["path"].(string))

		ui.Title("Installation done ❤️")
	}
	return nil
}

func PluginDelete(path string, plugins []string) {
	folders := make([]string, 0)
	pluginFolder := utils.HOMEDIR(".") + utils.Path("/.gupm/plugins/")

	for _, str := range plugins {
		folders = append(folders, pluginFolder+str)
	}

	utils.RemoveFiles(folders)
	fmt.Println("Done deleting.")
}

func PluginCreate(path string) {
	fmt.Println("Welcome to the plugin creation assistant")
	name := "provider-" + ui.WaitForInput("What is the name of the plugin? provider-")
	description := ui.WaitForInput("Enter a description: ")
	author := ui.WaitForInput("Enter the author: ")
	licence := ui.WaitForInput("Enter the licence (ISC): ")
	ppath := utils.Path(path + "/" + name)

	os.MkdirAll(ppath, os.ModePerm)
	os.MkdirAll(ppath+utils.Path("/docs/repo"), os.ModePerm)

	utils.WriteFile(ppath+utils.Path("/gupm.json"), `{
	"name": "`+name+`",
	"version": "0.0.1",
	"description": "`+description+`",
	"author": "`+author+`",
	"licence": "`+licence+`",
    "publish": {
        "source": ["."],
        "dest": "../docs/repo"
    },
    "config": {
        "default": {
            "entrypoint": "gupm.json",
            "installPath": "gupm_modules"
        }
    }
}`)

	fmt.Println("creation done.")
}


================================================
FILE: src/provider/bootstrap.go
================================================
package provider

import (
	"../defaultProvider"
	"../jsVm"
	"../utils"
	"errors"
	// "fmt"
)

func Bootstrap(path string) error {
	if Provider != "gupm" {
		var file = utils.FileExists(utils.Path(ProviderPath + "/bootstrap.gs"))
		if file {
			input := make(map[string]interface{})
			input["Path"] = path
			_, err := jsVm.Run(utils.Path(ProviderPath+"/bootstrap.gs"), input)
			if err != nil {
				return err
			}
		} else {
			return errors.New("Provider doesn't have any bootstrap function. Please use 'g bootstrap' to use the default bootstrap.")
		}
	} else {
		defaultProvider.Bootstrap(path)
	}
	return nil
}


================================================
FILE: src/provider/dependencyTree.go
================================================
package provider

func eliminateRedundancy(tree []map[string]interface{}, path map[string]bool) []map[string]interface{} {
	var cleanTree = make([]map[string]interface{}, 0)
	for index, dep := range tree {
		if dep["name"] != nil {
			_ = index
			depKey := dep["name"].(string) + "@" + dep["version"].(string)
			if path[depKey] != true {
				cleanTree = append(cleanTree, dep)
			}
		}
	}

	for index, dep := range cleanTree {
		if dep["name"] != nil {
			nextDepList, ok := dep["dependencies"].([]map[string]interface{})

			if ok {
				depKey := dep["name"].(string) + "@" + dep["version"].(string)
				newPath := make(map[string]bool)
				for key, value := range path {
					newPath[key] = value
				}
				newPath[depKey] = true
				newSubTree := eliminateRedundancy(nextDepList, newPath)
				cleanTree[index]["dependencies"] = newSubTree
			}
		}
	}
	return cleanTree
}

func flattenDependencyTree(tree []map[string]interface{}, subTree []map[string]interface{}) ([]map[string]interface{}, []map[string]interface{}) {
	var cleanTree = make([]map[string]interface{}, 0)

	for index, dep := range subTree {
		var rootDeps = make(map[string]string)

		for _, dep := range tree {
			rootDeps[dep["name"].(string)] = dep["version"].(string)
		}

		if rootDeps[dep["name"].(string)] == "" {
			tree = append(tree, dep)

			nextDepList, ok := dep["dependencies"].([]map[string]interface{})

			if ok {
				newTree, newSubTree := flattenDependencyTree(tree, nextDepList)
				tree = newTree
				subTree[index]["dependencies"] = newSubTree
			}
		} else if rootDeps[dep["name"].(string)] != dep["version"].(string) {
			nextDepList, ok := dep["dependencies"].([]map[string]interface{})

			if ok {
				newTree, newSubTree := flattenDependencyTree(tree, nextDepList)
				tree = newTree
				subTree[index]["dependencies"] = newSubTree
			}

			cleanTree = append(cleanTree, subTree[index])
		}
	}

	return tree, cleanTree
}

func BuildDependencyTree(tree []map[string]interface{}) []map[string]interface{} {
	cleanTree := eliminateRedundancy(tree, make(map[string]bool))

	for index, dep := range cleanTree {
		nextDepList, ok := dep["dependencies"].([]map[string]interface{})

		if ok {
			newCleanTree, newDepList := flattenDependencyTree(cleanTree, nextDepList)
			cleanTree = newCleanTree
			cleanTree[index]["dependencies"] = newDepList
		}
	}
	return cleanTree
}


================================================
FILE: src/provider/install.go
================================================
package provider

import (
	"io/ioutil"
	"os"
	"regexp"

	"../defaultProvider"
	"../jsVm"
	"../ui"
	"../utils"
)

func BinaryInstall(path string, paths map[string]string) error {
	dest := utils.Path(path + "/.bin")
	os.RemoveAll(dest)
	os.MkdirAll(dest, os.ModePerm)

	for pr, prdir := range paths {
		depProviderPath := GetProviderPath(pr)
		var file = utils.FileExists(depProviderPath + utils.Path("/binaryInstall.gs"))
		if pr != "gupm" && file {
			input := make(map[string]interface{})
			input["Destination"] = dest
			input["Source"] = prdir

			res, err := jsVm.Run(depProviderPath+utils.Path("/binaryInstall.gs"), input)
			if err != nil {
				return err
			}

			_, err1 := res.ToString()
			return err1
		} else {
			return defaultProvider.BinaryInstall(dest, prdir)
		}
	}
	return nil
}

func installDependencySubFolders(path string, depPath string) {
	files, _ := utils.ReadDir(path)

	for _, file := range files {
		if file.IsDir() {
			folderPath := utils.Path(depPath + "/" + file.Name())
			os.MkdirAll(folderPath, os.ModePerm)
			installDependencySubFolders(utils.Path(path+"/"+file.Name()), folderPath)
		} else {
			isFileExists := false
			err := os.Link(utils.Path(path+"/"+file.Name()), utils.Path(depPath+"/"+file.Name()))
			if err != nil {
				isFileExists, _ = regexp.MatchString(`file exists$`, err.Error())
			}

			if err != nil && !isFileExists {
				if !linkHasErrored {
					ui.Error(err)
					ui.Error("Error, cannot use hard link on your system. Falling back to copying file (Will be slower!)")
					linkHasErrored = true
				}
				input, err := ioutil.ReadFile(utils.Path(path + "/" + file.Name()))
				if err != nil {
					ui.Error(err)
					return
				}

				err = ioutil.WriteFile(utils.Path(depPath+"/"+file.Name()), input, 0644)
				if err != nil {
					ui.Error(err)
					return
				}
			}
		}
	}
}

func InstallDependency(path string, dep map[string]interface{}) {
	depPath := utils.Path(path + "/" + dep["name"].(string))
	// if(utils.FileExists(depPath)) {
	// 	// TODO: check version
	// } else {
	// }
	_, ok := dep["path"].(string)
	if ok {
		os.MkdirAll(utils.Path(depPath), os.ModePerm)
		installDependencySubFolders(utils.Path(dep["path"].(string)), depPath)
	} else {
		ui.Error(dep["name"].(string) + " Cannot be installed.")
	}
}


================================================
FILE: src/provider/provider.go
================================================
package provider

import (
	"fmt"
	"os"
	"path/filepath"
	"sync"

	"../defaultProvider"
	"../jsVm"
	"../ui"
	"../utils"
)

var Provider string
var ProviderPath string
var providerConfigCache = make(map[string]*utils.GupmEntryPoint)
var linkHasErrored = false
var pConfigLock = sync.RWMutex{}

func GetProviderPath(name string) string {
	gupmConfig := utils.GupmConfig()

	if name == "" {
		name = gupmConfig.DefaultProvider
	}

	if name == "os" {
		osName := utils.OSNAME()
		if gupmConfig.OsProviders[osName] != "" {
			name = gupmConfig.OsProviders[osName]
		} else {
			ui.Error("No provider set for", osName)
			return utils.DIRNAME()
		}
	}

	if name == "gupm" {
		return utils.DIRNAME()
	} else {
		homePlugin := utils.HOMEDIR(".") + utils.Path("/.gupm/plugins/provider-"+name)
		localPlugin := utils.DIRNAME() + utils.Path("/plugins/provider-"+name)

		if utils.FileExists(homePlugin) {
			pluginPath, err := filepath.EvalSymlinks(homePlugin)
			if err != nil {
				ui.Error(err)
				return ""
			}
			return pluginPath
		} else if utils.FileExists(localPlugin) {
			return localPlugin
		} else {
			fmt.Println("Provider cannot be found: " + name + ". Please install it before using it.")
			os.Exit(1)
			return ""
		}
	}
}

func InitProvider(provider string) error {
	Provider = provider
	ProviderPath = GetProviderPath(provider)

	if Provider != "" {
		providerConfig, err := GetProviderConfig(Provider)
		if err != nil {
			return err
		}
		ui.Log("Initialisation OK for " + providerConfig.Name)
	} else {
		providerConfig, err := GetProviderConfig("gupm")
		if err != nil {
			return err
		}
		ui.Log("Initialisation OK for " + providerConfig.Name)
	}

	return nil
}

func GetProviderConfig(providerName string) (*utils.GupmEntryPoint, error) {
	providerConfigPath := GetProviderPath(providerName) + utils.Path("/gupm.json")

	pConfigLock.Lock()
	if providerConfigCache[providerName] == nil {
		config, err := utils.ReadGupmJson(providerConfigPath)
		if err != nil {
			return nil, err
		}

		providerConfigCache[providerName] = config

		pConfigLock.Unlock()
		return config, nil
	} else {
		config := providerConfigCache[providerName]
		pConfigLock.Unlock()
		return config, nil
	}
}

func GetPackageConfig(path string) (utils.Json, error) {
	var file = utils.FileExists(ProviderPath + utils.Path("/getPackageConfig.gs"))
	if file {
		input := make(map[string]interface{})
		input["Path"] = path
		res, err := jsVm.Run(ProviderPath+utils.Path("/getPackageConfig.gs"), input)
		if err != nil {
			return nil, err
		}

		resObj, err1 := res.Export()
		return resObj.(utils.Json), err1
	} else {
		pc, err := GetProviderConfig(Provider)
		if err != nil {
			return nil, err
		}
		return defaultProvider.GetPackageConfig(utils.Path(path + "/" + pc.Config.Default.Entrypoint)), nil
	}
}

func PostGetPackageConfig(config utils.Json) (utils.Json, error) {
	var file = utils.FileExists(ProviderPath + utils.Path("/postGetPackageConfig.gs"))
	if file {
		input := make(map[string]interface{})
		input["PackageConfig"] = config

		res, err := jsVm.Run(ProviderPath+utils.Path("/postGetPackageConfig.gs"), input)
		if err != nil {
			return nil, err
		}

		resObj, err1 := res.Export()
		return resObj.(utils.Json), err1
	} else {
		return config, nil
	}
}

func SaveDependencyList(path string, depList []map[string]interface{}) error {
	var file = utils.FileExists(ProviderPath + utils.Path("/saveDependencyList.gs"))
	if file {
		input := make(map[string]interface{})
		input["Dependencies"] = depList
		input["Path"] = path

		_, err := jsVm.Run(ProviderPath+utils.Path("/saveDependencyList.gs"), input)
		if err != nil {
			return err
		}

		return nil
	} else {
		return defaultProvider.SaveDependencyList(path, depList)
	}
}

func GetDependencyList(config utils.Json) ([]map[string]interface{}, error) {
	var file = utils.FileExists(ProviderPath + utils.Path("/getDependencyList.gs"))
	if file {
		input := make(map[string]interface{})
		input["PackageConfig"] = config

		res, err := jsVm.Run(ProviderPath+utils.Path("/getDependencyList.gs"), input)
		if err != nil {
			return nil, err
		}

		resObj, err1 := res.Export()
		resMap, ok := resObj.([]map[string]interface{})

		if ok {
			return resMap, err1
		} else {
			return make([]map[string]interface{}, 0), err1
		}
	} else {
		return defaultProvider.GetDependencyList(config), nil
	}
}

func ResolveDependencyLocation(dependency map[string]interface{}) (map[string]interface{}, error) {
	depProviderPath := GetProviderPath(dependency["provider"].(string))
	var file = utils.FileExists(depProviderPath + utils.Path("/resolveDependencyLocation.gs"))
	if dependency["provider"].(string) != "gupm" && file {
		input := make(map[string]interface{})
		input["Dependency"] = dependency
		res, err := jsVm.Run(depProviderPath+utils.Path("/resolveDependencyLocation.gs"), input)
		if err != nil {
			return nil, err
		}

		resObj, err1 := res.Export()

		if resObj == nil {
			ui.Error("ERROR Failed to resolve" + dependency["name"].(string) + "Trying again.")
			return ResolveDependencyLocation(dependency)
		}
		return resObj.(map[string]interface{}), err1
	} else {
		dependency["url"] = dependency["name"].(string)
		return dependency, nil
	}
}

func ExpandDependency(dependency map[string]interface{}) (map[string]interface{}, error) {
	depProviderPath := GetProviderPath(dependency["provider"].(string))
	var file = utils.FileExists(depProviderPath + utils.Path("/expandDependency.gs"))
	if dependency["provider"].(string) != "gupm" && file {
		input := make(map[string]interface{})
		input["Dependency"] = dependency

		res, err := jsVm.Run(depProviderPath+utils.Path("/expandDependency.gs"), input)
		if err != nil {
			return nil, err
		}

		toExport, _ := res.Export()
		resObj := jsVm.JsonExport(toExport).(map[string]interface{})

		if resObj == nil {
			ui.Error("ERROR Failed to resolve" + dependency["name"].(string) + ". Trying again.")
			return ExpandDependency(dependency)
		}

		return resObj, nil
	} else {
		return defaultProvider.ExpandDependency(dependency)
	}
}

func GetDependency(provider string, name string, version string, url string, path string) (string, error) {
	depProviderPath := GetProviderPath(provider)
	var file = utils.FileExists(depProviderPath + utils.Path("/getDependency.gs"))
	if provider != "gupm" && file {
		input := make(map[string]interface{})
		input["Provider"] = provider
		input["Name"] = name
		input["Version"] = version
		input["Url"] = url
		input["Path"] = path

		res, err := jsVm.Run(depProviderPath+utils.Path("/getDependency.gs"), input)
		if err != nil {
			return "", err
		}

		resStr, err1 := res.ToString()
		return resStr, err1
	} else {
		return defaultProvider.GetDependency(provider, name, version, url, path)
	}
}

func PostGetDependency(provider string, name string, version string, url string, path string, result string) (string, error) {
	depProviderPath := GetProviderPath(provider)

	var file = utils.FileExists(depProviderPath + utils.Path("/postGetDependency.gs"))
	if provider != "gupm" && file {
		input := make(map[string]interface{})
		input["Provider"] = provider
		input["Name"] = name
		input["Version"] = version
		input["Url"] = url
		input["Path"] = path
		input["Result"] = result

		res, err := jsVm.Run(depProviderPath+utils.Path("/postGetDependency.gs"), input)
		if err != nil {
			return "", err
		}

		resStr, err1 := res.ToString()
		return resStr, err1
	} else {
		return defaultProvider.PostGetDependency(provider, name, version, url, path, result)
	}
}


================================================
FILE: src/provider/publish.go
================================================
package provider

import (
	"errors"

	"../defaultProvider"
	"../jsVm"
	"../utils"
	// "fmt"
)

func Publish(path string, namespace string) error {
	if Provider != "gupm" {
		var file = utils.FileExists(utils.Path(ProviderPath + "/publish.gs"))
		if file {
			input := make(map[string]interface{})
			input["Path"] = path
			_, err := jsVm.Run(utils.Path(ProviderPath+"/publish.gs"), input)
			return err
		} else {
			return errors.New("Provider doesn't have any publish function. Please use 'g publish' to use the default publish.")
		}
	} else {
		return defaultProvider.Publish(path, namespace)
	}
}


================================================
FILE: src/publish.go
================================================
package main

import (
	"./provider"
	"./ui"
)

func Publish(path string, namespace string) error {
	err := provider.InitProvider(Provider)
	if err != nil {
		return err
	}
	ui.Title("Publishing package...")
	errPub := provider.Publish(path, namespace)
	if errPub != nil {
		return errPub
	} else {
		ui.Title("Publish done! ❤️")
	}
	return nil
}


================================================
FILE: src/removeDependency.go
================================================
package main

import (
	"./provider"
	"./ui"
	"./utils"
)

func remove(slice []map[string]interface{}, s int) []map[string]interface{} {
	return append(slice[:s], slice[s+1:]...)
}

func RemoveDependency(path string, rls []string) error {
	var err error
	var packageConfig utils.Json
	var depList []map[string]interface{}

	ui.Title("Add dependency...")

	err = provider.InitProvider(Provider)

	if err != nil {
		return err
	}

	providerConfig, err = provider.GetProviderConfig(Provider)
	ui.Error(err)
	packageConfig, _ = provider.GetPackageConfig(path)
	packageConfig, _ = provider.PostGetPackageConfig(packageConfig)

	depList, err = provider.GetDependencyList(packageConfig)
	if err != nil {
		return err
	}

	ui.Title("Removing from dependency list...")

	for _, str := range rls {
		for index, dep := range depList {
			if dep["name"].(string) == str {
				depList = remove(depList, index)
			}
		}
	}

	err = provider.SaveDependencyList(path, depList)
	if err != nil {
		return err
	}

	// TODO: Remove from module folder

	return nil
}


================================================
FILE: src/self.go
================================================
package main

import (
	"./ui"
	"./utils"
	"io/ioutil"
	"os"
	"os/exec"
	"runtime"
)

// TODO: implemement script-free upgrade for all OSes

func SelfUpgrade() {
	SelfUninstall()

	if runtime.GOOS != "windows" {
		script := utils.HttpGet("https://azukaar.github.io/GuPM/install.sh")
		ioutil.WriteFile("TEMP_install.sh", []byte(script), os.ModePerm)
		cmd := exec.Command("/bin/sh", "TEMP_install.sh")
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		cmd.Stdin = os.Stdin
		cmd.Run()
		utils.RemoveFiles([]string{"TEMP_install.sh"})
	} else {
		ui.Error("Upgrade not fully implememnted on windows yet. Please execute windows_installer.exe again")
	}
}

func SelfUninstall() {
	utils.RemoveFiles([]string{utils.DIRNAME()})

	if runtime.GOOS != "windows" {
		utils.RemoveFiles([]string{"/usr/local/bin/g", "/bin/g"})
	}
}


================================================
FILE: src/test.go
================================================
package main

import (
	"os"
	"regexp"
	"strconv"

	"./jsVm"
	"./ui"
	"./utils"
)

func RunTest(path string) {
	_ = jsVm.Run
	files := utils.RecursiveFileWalkDir(path)
	i := 0
	for _, file := range files {
		isTest, _ := regexp.MatchString(`\.test\.gs$`, file)
		if isTest {
			os.MkdirAll(".tmp_test_gupm", os.ModePerm)
			utils.CopyFiles([]string{file}, ".tmp_test_gupm/"+strconv.Itoa(i)+".gs")
			errch := os.Chdir(".tmp_test_gupm")
			if errch != nil {
				ui.Error("Could'n execute", file)
				Exit(1)
			}
			_, err := jsVm.Run(strconv.Itoa(i)+".gs", make(map[string]interface{}))
			os.Chdir("..")
			utils.RemoveFiles([]string{".tmp_test_gupm"})
			if err != nil {
				ui.Error("Test execution failed:", file)
				Exit(1)
			}
			i++
		}
	}

	ui.Title("Test passed! ❤️")
}


================================================
FILE: src/ui/log.go
================================================
package ui

import (
	"bufio"
	"errors"
	"fmt"
	"github.com/fatih/color"
	"github.com/gosuri/uilive"
	"os"
	"strconv"
	"sync"
	"time"
)

var errorList = make([]string, 0)
var debugList = make([]string, 0)
var currentLog string
var currentTitle string
var progress int
var screenWidth int
var positionToDrawAt int
var logBox = uilive.New()

var lock = sync.RWMutex{}
var errorLock = sync.RWMutex{}

var redrawNeeded = false
var running = true

var isWaitingForInput = false

func Title(log string) {
	_ = color.Green
	currentTitle = log
	currentLog = ""
	redrawNeeded = true
}

func Log(log string) {
	currentLog = log
	redrawNeeded = true
}

func Error(errs ...interface{}) error {
	res := ""

	for _, err := range errs {
		errErr, isErr := err.(error)
		errStr, isStr := err.(string)
		if isErr && errErr != nil {
			res += " " + errErr.Error()
		} else if isStr {
			res += " " + errStr
		}
	}

	if res != "" {
		errorLock.Lock()
		errorList = append(errorList, res)
		errorLock.Unlock()
		if len(errorList) <= 10 {
			redrawNeeded = true
		}

		return errors.New(res)
	} else {
		return nil
	}
}

func Debug(err string) {
	debugList = append(debugList, err)
	if len(debugList) <= 10 {
		Draw()
	}
}

func Progress(p int) {
	progress = p
	redrawNeeded = true
}

// https://github.com/ahmetb/go-cursor/blob/master/cursor.go

var Esc = "\x1b"

func escape(format string, args ...interface{}) string {
	return fmt.Sprintf("%s%s", Esc, fmt.Sprintf(format, args...))
}

func moveCursor(x int, y int) {
	escape("[%d;%dH", x, y)
}

func init() {
	positionToDrawAt = 0

	logBox.Start()

	go (func() {
		for range time.Tick(200 * time.Millisecond) {
			if running {
				Draw()
			}
		}
	})()
}

func drawTitle() string {
	if currentTitle != "" {
		title := color.New(color.FgBlue, color.Bold)
		return title.Sprintln("🐶   " + currentTitle)
	} else {
		return ""
	}
}

func drawLog() string {
	if currentLog != "" {
		log := color.New(color.FgGreen)
		return log.Sprintln("✓   " + currentLog)
	} else {
		return ""
	}
}

func Stop() {
	redrawNeeded = true
	running = false
	Draw()
}

func WaitForKey() {
	isWaitingForInput = true
	logBox.Flush()

	reader := bufio.NewReader(os.Stdin)
	reader.ReadRune()
	isWaitingForInput = false
}

func WaitForInput(msg string) string {
	isWaitingForInput = true
	logBox.Flush()
	fmt.Printf(msg)

	scanner := bufio.NewScanner(os.Stdin)

	for scanner.Scan() {
		var result = scanner.Text()
		isWaitingForInput = false
		return result
	}

	if scanner.Err() != nil {

	}

	return ""
}

func WaitForMenu(msgs []string) int {
	lgth := len(msgs)
	i := 1
	res := 0

	for _, msg := range msgs {
		fmt.Println(strconv.Itoa(i) + " : " + msg)
		i++
	}

	for res <= 0 || res > lgth {
		resString := WaitForInput("Please input choice 1 - " + strconv.Itoa(lgth) + ": ")
		res, _ = strconv.Atoi(resString)
	}
	return res
}

func Draw() {
	if !redrawNeeded || isWaitingForInput {
		return
	}

	result := ""

	result += drawTitle()

	if progress > 0 {
		fmt.Print("📦📦")
		for i := 0; i < 20; i++ {
			if i == progress/5 {
				fmt.Print("🐕")
			} else {
				fmt.Print("-")
			}
		}
		fmt.Println("🏠")
	}

	result += drawLog()

	errorColor := color.New(color.FgRed)
	limit := 0
	errorLock.RLock()
	for _, v := range errorList {
		_ = v
		if limit == 10 {
			result += errorColor.Sprintln("❌❌❌   Too many errors to display...")
			limit++
		} else if limit < 10 {
			result += errorColor.Sprintln("❌   " + v)
			limit++
		}
	}
	errorLock.RUnlock()

	limit = 0
	for _, v := range debugList {
		_ = v
		if limit == 10 {
			result += "Too many debugs..."
			limit++
		} else if limit < 10 {
			result += v
			limit++
		}
	}

	lock.Lock()
	if running {
		fmt.Fprintf(logBox, result)
	} else {
		fmt.Fprintf(logBox, "\n")
		logBox.Stop()
		fmt.Println(result)
	}
	redrawNeeded = false
	lock.Unlock()
}


================================================
FILE: src/utils/files.go
================================================
package utils

import (
	"os"
	"strings"

	// "fmt"
	"github.com/bmatcuk/doublestar"
	"github.com/otiai10/copy"
)

var EmptyFileStructure = FileStructure{}

type FileStructure struct {
	Children map[string]FileStructure
	Name     string
	Content  []byte
	Filetype int
}

func Dir(path string) (matches []string, err error) {
	return doublestar.Glob(path)
}

func RemoveFiles(files []string) error {
	for _, file := range files {
		return os.RemoveAll(file)
	}
	return nil
}

func CopyFiles(files []string, destination string) error {
	for _, file := range files {
		return copy.Copy(file, destination)
	}
	return nil
}

func (g *FileStructure) getOrCreate(path string, options FileStructure) FileStructure {
	var folders = strings.Split(path, "/")
	var folder = folders[0]
	var child, _ = g.Children[folder]

	if child.Name == "" {
		if len(folders) > 1 {
			g.Children[folder] = FileStructure{
				Children: make(map[string]FileStructure),
				Name:     folder,
				Filetype: 0,
			}
		} else {
			g.Children[folder] = FileStructure{
				Children: make(map[string]FileStructure),
				Name:     folder,
				Filetype: options.Filetype,
				Content:  options.Content,
			}
		}
		child, _ = g.Children[folder]
	}

	if len(folders) > 1 {
		next := folders[1:]
		return child.getOrCreate(strings.Join(next[:], "/"), options)
	} else {
		return child
	}
}

func (g *FileStructure) SaveSelfAt(path string) error {
	if g.Filetype == 0 {
		newPath := Path(path + "/" + g.Name)
		os.MkdirAll(newPath, os.ModePerm)
		for _, child := range g.Children {
			child.SaveSelfAt(newPath)
		}
	} else {
		filePath := path
		if g.Name != "" {
			filePath = Path(filePath + "/" + g.Name)
		}
		f, err := os.OpenFile(filePath, os.O_CREATE|os.O_RDWR, os.FileMode(0777))

		if err != nil {
			f.Close()
			return err
		}

		if _, err := f.Write(g.Content); err != nil {
			f.Close()
			return err
		}

		f.Close()
	}
	return nil
}

func (g *FileStructure) SaveAt(path string) error {
	if g.Filetype == 0 {
		os.MkdirAll(Path(path), os.ModePerm)
		for _, child := range g.Children {
			child.SaveSelfAt(Path(path))
		}
	}
	if g.Filetype == 1 {
		g.SaveSelfAt(Path(path))
	}
	return nil
}


================================================
FILE: src/utils/json.go
================================================
package utils

// import (
// 	"reflect"
// 	"fmt"
// )

// type Json map[interface{}]interface {}
type Json map[string]interface{}

// func (j *Json) AsObject() map[string]interface {} {
// 	res := map[string]interface{}{}
// 	for i, v := range *j {
// 		res[i.(string)] = v
// 	}
// 	return res
// }

func (j *Json) Contains(test interface{}) bool {
	for i := range *j {
		if i == test {
			return true
		}
	}
	return false
}

func (j *Json) get(index interface{}) interface{} {
	return (*j)[index.(string)]
}

// func (j *Json) indexOf(test interface{}) interface{} {
// 	for i, _  := range *j {
// 		if(i == test) {
// 			return true
// 		}
// 	}
// 	return false
// }


================================================
FILE: src/utils/repo.go
================================================
package utils

import (
	"io/ioutil"
)

func GetOrCreateRepo(path string) map[string]interface{} {
	configPath := path + "/gupm_repo.json"
	if !FileExists(configPath) {
		baseConfig := `{
	"packages": {}
}`
		WriteFile(configPath, baseConfig)
		return StringToJSON(baseConfig)
	}

	file, _ := ioutil.ReadFile(configPath)
	return StringToJSON(string(file))
}

func SaveRepo(path string, file map[string]interface{}) {
	WriteJsonFile(path+"/gupm_repo.json", file)
}


================================================
FILE: src/utils/types.go
================================================
package utils

type GupmEntryPoint struct {
	Name              string
	Version           string
	WrapInstallFolder string
	Git               gupmEntryPointGit
	Publish           gupmEntryPointPublish
	Cli               gupmEntryPointCliList
	Config            gupmEntryPointConfigList
	Dependencies      gupmEntryPointDependenciesList
}

type gupmEntryPointCliList struct {
	DefaultProviders map[string]string
	Aliases          map[string]interface{}
}

type gupmEntryPointGit struct {
	Hooks gupmEntryPointGitHooks
}

type gupmEntryPointGitHooks struct {
	Precommit interface{}
	Prepush   interface{}
}

type gupmEntryPointDependenciesList struct {
	DefaultProvider string
	Default         map[string]string
}

type gupmEntryPointConfigList struct {
	Default gupmEntryPointConfig
}

type gupmEntryPointConfig struct {
	Entrypoint      string
	InstallPath     string
	DefaultProvider string
	OsProviders     map[string]string
}

type gupmEntryPointPublish struct {
	Source []string
	Dest   string
}


================================================
FILE: src/utils/untar.go
================================================
package utils

import "archive/tar"
import "archive/zip"
import "compress/gzip"

import (
	"bytes"
	"io"
	"io/ioutil"
	"strings"
)

func Ungz(r string) (FileStructure, error) {
	tr, err := gzip.NewReader(strings.NewReader(r))

	if err != nil {
		return EmptyFileStructure, err
	}

	defer tr.Close()

	buf := new(bytes.Buffer)
	buf.ReadFrom(tr)

	root := FileStructure{
		Children: make(map[string]FileStructure),
		Name:     tr.Header.Name,
		Content:  buf.Bytes(),
		Filetype: 1,
	}

	return root, nil
}

func Tar(files []string) (FileStructure, error) {
	var buf bytes.Buffer
	gzw := gzip.NewWriter(&buf)
	tw := tar.NewWriter(gzw)
	finalList := make([]string, 0)

	for _, file := range files {
		if IsDirectory(file) {
			finalList = append(finalList, RecursiveFileWalkDir(file)...)
		} else {
			finalList = append(finalList, file)
		}
	}

	for _, file := range finalList {
		content, err := ioutil.ReadFile(file)
		if err != nil {
			return EmptyFileStructure, err
		}

		hdr := &tar.Header{
			Name: file,
			Mode: 0740,
			Size: int64(len(content)),
		}

		if err := tw.WriteHeader(hdr); err != nil {
			return EmptyFileStructure, err
		}

		if _, err := tw.Write([]byte(content)); err != nil {
			return EmptyFileStructure, err
		}
	}

	if err := tw.Close(); err != nil {
		return EmptyFileStructure, err
	}

	if err := gzw.Close(); err != nil {
		return EmptyFileStructure, err
	}

	root := FileStructure{
		Content:  buf.Bytes(),
		Filetype: 1,
	}

	return root, nil
}

func Untar(r string) (FileStructure, error) {
	gzr, err := gzip.NewReader(strings.NewReader(r))
	root := FileStructure{
		Children: make(map[string]FileStructure),
		Name:     "/",
		Filetype: 0,
	}

	if err != nil {
		return EmptyFileStructure, err
	}

	defer gzr.Close()

	tr := tar.NewReader(gzr)

	for {
		header, err := tr.Next()

		switch {

		case err == io.EOF:
			return root, nil

		case err != nil:
			return root, err

		case header == nil:
			continue
		}

		switch header.Typeflag {

		// if its a dir and it doesn't exist create it
		case tar.TypeDir:
			{
				root.getOrCreate(header.Name, FileStructure{
					Filetype: 0,
				})
			}

		// if it's a file create it
		case tar.TypeReg:
			buf := new(bytes.Buffer)
			buf.ReadFrom(tr)

			root.getOrCreate(header.Name, FileStructure{
				Filetype: 1,
				Content:  buf.Bytes(),
			})
		}
	}

	return root, nil
}

func Unzip(r string) (FileStructure, error) {
	root := FileStructure{
		Children: make(map[string]FileStructure),
		Name:     "/",
		Filetype: 0,
	}

	tr, _ := zip.NewReader(strings.NewReader(r), int64(len(r)))

	for _, f := range tr.File {
		// if its a dir and it doesn't exist create it
		if f.FileInfo().IsDir() {
			root.getOrCreate(f.Name, FileStructure{
				Filetype: 0,
			})
		} else {
			rc, _ := f.Open()
			buf := new(bytes.Buffer)
			buf.ReadFrom(rc)

			root.getOrCreate(f.Name, FileStructure{
				Filetype: 1,
				Content:  buf.Bytes(),
			})

		}
	}
	return root, nil
}


================================================
FILE: src/utils/utils.go
================================================
package utils

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"reflect"
	"regexp"
	"runtime"
	"sync"
	"time"

	"../ui"
	"github.com/mitchellh/go-homedir"
)

type Dependency struct {
	Name     string
	Provider string
	Version  string
}

func buildCmd(toRun string, args []string) *exec.Cmd {
	isNode := regexp.MustCompile(`.js$`)
	var cmd *exec.Cmd
	bashargs := []string{}

	// temporary hack to make windows execute js file with node
	if isNode.FindString(toRun) != "" {
		bashargs = append(bashargs, toRun)
		bashargs = append(bashargs, args...)
		cmd = exec.Command("node", bashargs...)
	} else {
		bashargs = append(bashargs, args...)
		cmd = exec.Command(toRun, bashargs...)
	}

	return cmd
}

func ExecCommand(toRun string, args []string) error {
	cmd := buildCmd(toRun, args)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin
	err := cmd.Run()
	return err
}

func ReadGupmJson(path string) (*GupmEntryPoint, error) {
	if !FileExists(path) {
		return nil, nil
	}
	config := new(GupmEntryPoint)
	errRead := ReadJSON(path, config)
	if errRead != nil {
		ui.Error("Can't read", path, "check your file")
		return nil, errRead
	}
	return config, nil
}

func RunCommand(toRun string, args []string) (string, error) {
	cmd := buildCmd(toRun, args)
	res, err := cmd.Output()
	if err != nil {
		return "", err
	}
	return string(res), nil
}

func BuildStringFromDependency(dep map[string]interface{}) string {
	rep := dep["name"].(string)

	if dep["version"] != nil && dep["version"].(string) != "" {
		rep += "@" + dep["version"].(string)
	}

	if dep["provider"] != nil && dep["provider"].(string) != "" {
		rep = dep["provider"].(string) + "://" + rep
	}

	return rep
}

func BuildDependencyFromString(defaultProvider string, dep string) map[string]interface{} {
	result := make(map[string]interface{})
	step := dep

	versionCheck := regexp.MustCompile(`@[\w\.\-\_\^\~]+$`)
	tryversion := versionCheck.FindString(step)
	if tryversion != "" {
		result["version"] = tryversion[1:]
		step = versionCheck.ReplaceAllString(step, "")
	} else {
		result["version"] = "*.*.*"
	}

	providerCheck := regexp.MustCompile(`^[\w\-\_]+\:\/\/`)
	tryprovider := providerCheck.FindString(step)
	if tryprovider != "" {
		result["provider"] = tryprovider[:len(tryprovider)-3]
		step = providerCheck.ReplaceAllString(step, "")
	} else {
		result["provider"] = defaultProvider
	}

	result["name"] = step
	return result
}

func StringToJSON(b string) map[string]interface{} {
	var jsonString map[string]interface{}
	json.Unmarshal([]byte(string(b)), &jsonString)
	return jsonString
}

func ReadJSON(path string, target interface{}) error {
	b, err := os.Open(path) // just pass the file name

	if err != nil {
		b.Close()
		return err
	}

	defer b.Close()
	return json.NewDecoder(b).Decode(target)
}

var numberConnectionOpened = 0

func HttpGet(url string) []byte {
	if numberConnectionOpened > 50 {
		time.Sleep(1000 * time.Millisecond)
		return HttpGet(url)
	}

	numberConnectionOpened++
	resp, httperr := http.Get(url)
	if httperr != nil {
		numberConnectionOpened--
		isRateLimit, _ := regexp.MatchString(`unexpected EOF$`, httperr.Error())
		if !isRateLimit {
			ui.Error("Error accessing", url, "trying again.", httperr)
		}
		time.Sleep(1000 * time.Millisecond)
		return HttpGet(url)
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		numberConnectionOpened--
		ui.Error("Error reading HTTP response ", err)
		return HttpGet(url)
	}

	numberConnectionOpened--
	return body
}

func FileExists(path string) bool {
	_, err := os.Stat(path)
	if err == nil {
		return true
	}
	if os.IsNotExist(err) {
		return false
	}
	return true
}

func StringInSlice(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}

func RemoveIndex(s []map[string]interface{}, index int) []map[string]interface{} {
	return append(s[:index], s[index+1:]...)
}

func RecursiveFileWalkDir(source string) []string {
	result := make([]string, 0)
	err := filepath.Walk(source,
		func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if !info.IsDir() {
				result = append(result, path)
			}
			return nil
		})
	if err != nil {
		ui.Error(err)
	}
	return result
}

var lock = sync.RWMutex{}

func ReadDir(path string) ([]os.FileInfo, error) {
	lock.Lock()
	files, err := ioutil.ReadDir(path)
	lock.Unlock()
	if err != nil {
		ui.Error(err)
		return files, err
	}

	return files, nil
}

func IsDirectory(path string) bool {
	fileInfo, err := os.Stat(path)
	if err != nil {
		return false
	}
	return fileInfo.IsDir()
}

func HOMEDIR(fallback string) string {
	hdir, errH := homedir.Dir()
	if errH != nil {
		ui.Error(errH)
		hdir = fallback
	}
	return hdir
}

func DIRNAME() string {
	ex, err := os.Executable()
	exr, err := filepath.EvalSymlinks(ex)
	if err != nil {
		panic(err)
	}
	dir := filepath.Dir(exr)
	return dir
}

func WriteFile(path string, file string) error {
	return ioutil.WriteFile(Path(path), []byte(file), os.ModePerm)
}

func WriteJsonFile(path string, file map[string]interface{}) {
	bytes, _ := json.MarshalIndent(file, "", "    ")
	err := ioutil.WriteFile(path, bytes, os.ModePerm)
	if err != nil {
		ui.Error(err)
	}
}

// TODO: https://blog.golang.org/pipelines
// add proper checksum check

func SaveLockDep(path string) {
	ioutil.WriteFile(path+"/.gupm_locked", []byte("1"), os.ModePerm)
}

func AbsPath(rel string) string {
	abs, _ := filepath.Abs(rel)
	return abs
}

func Path(path string) string {
	if runtime.GOOS == "windows" {
		return filepath.FromSlash(path)
	} else {
		return filepath.ToSlash(path)
	}
}

func Contains(s interface{}, elem interface{}) bool {
	arrV := reflect.ValueOf(s)

	if arrV.Kind() == reflect.Slice {
		for i := 0; i < arrV.Len(); i++ {

			// XXX - panics if slice element points to an unexported struct field
			// see https://golang.org/pkg/reflect/#Value.Interface
			if arrV.Index(i).Interface() == elem {
				return true
			}
		}
	}

	return false
}

func ArrString(something interface{}) []string {
	_, ok := something.([]string)
	if !ok {
		res := make([]string, 0)
		for _, v := range something.([]interface{}) {
			res = append(res, v.(string))
		}
		return res
	} else {
		return something.([]string)
	}
}

func GupmConfig() gupmEntryPointConfig {
	gupmjson, _ := ReadGupmJson(Path(DIRNAME() + "/gupm.json"))
	return gupmjson.Config.Default
}

func OSNAME() string {
	osName := runtime.GOOS
	if osName == "darwin" {
		return "mac"
	}
	return osName
}


================================================
FILE: src/windows/windows_install.go
================================================
package main

import (
	"../ui"
	"../utils"
	"fmt"
)

func main() {
	arch := utils.HttpGet("https://azukaar.github.io/GuPM/gupm_windows.tar.gz")
	files, _ := utils.Untar(string(arch))
	path := ui.WaitForInput("Where do you want to save GuPM? (default C:\\)")
	if path == "" {
		path = "C:\\"
	}
	files.SaveAt(path)
	fmt.Println("GuPM saved in " + path + ". dont forget to add it to your PATH")
}


================================================
FILE: tests/install/normal.test.gs
================================================
writeJsonFile("gupm.json", {
    "dependencies": {
        "default": {
        }
    }
})


var err = exec("../build/dg", ["i", "git://github.com/Masterminds/semver"])

if(err) {
    throw new Error(JSON.stringify(err))
}

if (!fileExists('gupm_modules/github.com/Masterminds/semver')) {
    throw new Error(1)
}

================================================
FILE: tests/make/nodeps.test.gs
================================================
writeJsonFile("gupm.json", {
    "dependencies": {
        "default": {
        }
    }
})

var err = exec("../build/dg", ["make"])

if(err) {
    throw new Error(JSON.stringify(err))
}

================================================
FILE: tests/make/normal.test.gs
================================================
writeJsonFile("gupm.json", {
    "dependencies": {
        "default": {
            "git://github.com/Masterminds/semver": "master"
        }
    }
})

var err = exec("../build/dg", ["make"])

if(err) {
    throw new Error(JSON.stringify(err))
}

if (!fileExists('gupm_modules/github.com/Masterminds/semver')) {
    throw new Error(1)
}

================================================
FILE: tests/plugins/normal.test.gs
================================================
writeJsonFile("gupm.json", {
    "dependencies": {
        "default": {
            "npm://webpack": "latest"
        }
    }
})

var err = exec("../build/dg", ["pl", "install", "https://azukaar.github.io/GuPM-official/repo:provider-npm"])
var err2 = exec("../build/dg", ["make"])

if(err || err2) {
    throw new Error(JSON.stringify(err))
}

if (!fileExists('node_modules/webpack')) {
    throw new Error(1)
}

================================================
FILE: tests/scripts/normal.test.gs
================================================
writeFile("testscript.gs","writeFile('test','it works');")

var err = exec("../build/dg", ["testscript"])

if(err) {
    throw new Error(JSON.stringify(err))
}

if (!fileExists('test')) {
    throw new Error(1)
}
Download .txt
gitextract_o4jwiwqj/

├── .circleci/
│   └── config.yml
├── .gitignore
├── .gupm_rc.gs
├── LICENCE
├── build.gs
├── ci/
│   └── publish.gs
├── docs/
│   └── install.sh
├── gupm.json
├── plugins/
│   ├── provider-git/
│   │   ├── gupm.json
│   │   ├── postGetDependency.gs
│   │   └── resolveDependencyLocation.gs
│   ├── provider-http/
│   │   ├── gupm.json
│   │   └── resolveDependencyLocation.gs
│   └── provider-https/
│       ├── gupm.json
│       └── resolveDependencyLocation.gs
├── readme.md
├── src/
│   ├── addDependency.go
│   ├── bootstrap.go
│   ├── cache.go
│   ├── cli.go
│   ├── cli_test.go
│   ├── defaultProvider/
│   │   ├── defaultProvider.go
│   │   └── publish.go
│   ├── distribution_gupm.json
│   ├── gitHooks.go
│   ├── global.go
│   ├── index.go
│   ├── installProject.go
│   ├── jsVm/
│   │   └── jsVm.go
│   ├── plugins.go
│   ├── provider/
│   │   ├── bootstrap.go
│   │   ├── dependencyTree.go
│   │   ├── install.go
│   │   ├── provider.go
│   │   └── publish.go
│   ├── publish.go
│   ├── removeDependency.go
│   ├── self.go
│   ├── test.go
│   ├── ui/
│   │   └── log.go
│   ├── utils/
│   │   ├── files.go
│   │   ├── json.go
│   │   ├── repo.go
│   │   ├── types.go
│   │   ├── untar.go
│   │   └── utils.go
│   └── windows/
│       └── windows_install.go
└── tests/
    ├── install/
    │   └── normal.test.gs
    ├── make/
    │   ├── nodeps.test.gs
    │   └── normal.test.gs
    ├── plugins/
    │   └── normal.test.gs
    └── scripts/
        └── normal.test.gs
Download .txt
SYMBOL INDEX (138 symbols across 30 files)

FILE: src/addDependency.go
  function AddDependency (line 9) | func AddDependency(path string, rls []string) error {

FILE: src/bootstrap.go
  function Bootstrap (line 9) | func Bootstrap(path string) error {

FILE: src/cache.go
  function CacheClear (line 9) | func CacheClear() {

FILE: src/cli.go
  type Arguments (line 17) | type Arguments
    method AsJson (line 19) | func (a *Arguments) AsJson() json {
    method Join (line 26) | func (a *Arguments) Join() string {
    method AsList (line 39) | func (a *Arguments) AsList() []string {
    method Shift (line 50) | func (a *Arguments) Shift() {
  function GetArgs (line 61) | func GetArgs(args []string) (string, Arguments) {
  function getProvider (line 113) | func getProvider(c string, args Arguments) string {
  function ExecCli (line 153) | func ExecCli(c string, args Arguments) (bool, error) {

FILE: src/cli_test.go
  function TestArgs (line 10) | func TestArgs(t *testing.T) {

FILE: src/defaultProvider/defaultProvider.go
  function Bootstrap (line 14) | func Bootstrap(path string) {
  function GetPackageConfig (line 44) | func GetPackageConfig(entryPoint string) map[string]interface{} {
  function GetDependency (line 56) | func GetDependency(provider string, name string, version string, url str...
  function PostGetDependency (line 60) | func PostGetDependency(provider string, name string, version string, url...
  function GetDependencyList (line 94) | func GetDependencyList(config map[string]interface{}) []map[string]inter...
  function ExpandDependency (line 128) | func ExpandDependency(dependency map[string]interface{}) (map[string]int...
  function BinaryInstall (line 143) | func BinaryInstall(dest string, packagePath string) error {
  function SaveDependencyList (line 162) | func SaveDependencyList(path string, depList []map[string]interface{}) e...

FILE: src/defaultProvider/publish.go
  function Publish (line 10) | func Publish(path string, namespace string) error {

FILE: src/gitHooks.go
  function BuildGitHooks (line 13) | func BuildGitHooks(path string) {
  function runhook (line 24) | func runhook(hook string) {
  function runhooklist (line 90) | func runhooklist(hooklist string) {
  function runHooks (line 97) | func runHooks(hooks interface{}) {
  function RunHook (line 115) | func RunHook(path string, hook string) {

FILE: src/global.go
  function installBins (line 11) | func installBins(path string) {
  function GlobalAdd (line 23) | func GlobalAdd(rls []string) {
  function GlobalDelete (line 48) | func GlobalDelete(rls []string) {

FILE: src/index.go
  function ScriptExists (line 17) | func ScriptExists(path string) string {
  function executeFile (line 27) | func executeFile(path string, args Arguments) {
  function binFile (line 36) | func binFile(name string, args []string) {
  function Exit (line 46) | func Exit(code int) {
  function runAlias (line 51) | func runAlias(alias string) {
  function runAliasList (line 62) | func runAliasList(aliasList string) {
  function main (line 69) | func main() {

FILE: src/installProject.go
  function expandDepList (line 19) | func expandDepList(depList []map[string]interface{}) []map[string]interf...
  function installDep (line 125) | func installDep(path string, depList []map[string]interface{}) map[strin...
  function InstallProject (line 169) | func InstallProject(path string) error {

FILE: src/jsVm/jsVm.go
  function Run (line 21) | func Run(path string, input utils.Json) (otto.Value, error) {
  function Setup (line 55) | func Setup(vm *otto.Otto) {
  function JsonExport (line 375) | func JsonExport(input interface{}) interface{} {

FILE: src/plugins.go
  function PluginLink (line 14) | func PluginLink(path string) {
  function PluginInstall (line 36) | func PluginInstall(path string, plugins []string) error {
  function PluginDelete (line 86) | func PluginDelete(path string, plugins []string) {
  function PluginCreate (line 98) | func PluginCreate(path string) {

FILE: src/provider/bootstrap.go
  function Bootstrap (line 11) | func Bootstrap(path string) error {

FILE: src/provider/dependencyTree.go
  function eliminateRedundancy (line 3) | func eliminateRedundancy(tree []map[string]interface{}, path map[string]...
  function flattenDependencyTree (line 34) | func flattenDependencyTree(tree []map[string]interface{}, subTree []map[...
  function BuildDependencyTree (line 70) | func BuildDependencyTree(tree []map[string]interface{}) []map[string]int...

FILE: src/provider/install.go
  function BinaryInstall (line 14) | func BinaryInstall(path string, paths map[string]string) error {
  function installDependencySubFolders (line 41) | func installDependencySubFolders(path string, depPath string) {
  function InstallDependency (line 78) | func InstallDependency(path string, dep map[string]interface{}) {

FILE: src/provider/provider.go
  function GetProviderPath (line 21) | func GetProviderPath(name string) string {
  function InitProvider (line 61) | func InitProvider(provider string) error {
  function GetProviderConfig (line 82) | func GetProviderConfig(providerName string) (*utils.GupmEntryPoint, erro...
  function GetPackageConfig (line 103) | func GetPackageConfig(path string) (utils.Json, error) {
  function PostGetPackageConfig (line 124) | func PostGetPackageConfig(config utils.Json) (utils.Json, error) {
  function SaveDependencyList (line 142) | func SaveDependencyList(path string, depList []map[string]interface{}) e...
  function GetDependencyList (line 160) | func GetDependencyList(config utils.Json) ([]map[string]interface{}, err...
  function ResolveDependencyLocation (line 184) | func ResolveDependencyLocation(dependency map[string]interface{}) (map[s...
  function ExpandDependency (line 208) | func ExpandDependency(dependency map[string]interface{}) (map[string]int...
  function GetDependency (line 234) | func GetDependency(provider string, name string, version string, url str...
  function PostGetDependency (line 257) | func PostGetDependency(provider string, name string, version string, url...

FILE: src/provider/publish.go
  function Publish (line 12) | func Publish(path string, namespace string) error {

FILE: src/publish.go
  function Publish (line 8) | func Publish(path string, namespace string) error {

FILE: src/removeDependency.go
  function remove (line 9) | func remove(slice []map[string]interface{}, s int) []map[string]interfac...
  function RemoveDependency (line 13) | func RemoveDependency(path string, rls []string) error {

FILE: src/self.go
  function SelfUpgrade (line 14) | func SelfUpgrade() {
  function SelfUninstall (line 31) | func SelfUninstall() {

FILE: src/test.go
  function RunTest (line 13) | func RunTest(path string) {

FILE: src/ui/log.go
  function Title (line 32) | func Title(log string) {
  function Log (line 39) | func Log(log string) {
  function Error (line 44) | func Error(errs ...interface{}) error {
  function Debug (line 71) | func Debug(err string) {
  function Progress (line 78) | func Progress(p int) {
  function escape (line 87) | func escape(format string, args ...interface{}) string {
  function moveCursor (line 91) | func moveCursor(x int, y int) {
  function init (line 95) | func init() {
  function drawTitle (line 109) | func drawTitle() string {
  function drawLog (line 118) | func drawLog() string {
  function Stop (line 127) | func Stop() {
  function WaitForKey (line 133) | func WaitForKey() {
  function WaitForInput (line 142) | func WaitForInput(msg string) string {
  function WaitForMenu (line 162) | func WaitForMenu(msgs []string) int {
  function Draw (line 179) | func Draw() {

FILE: src/utils/files.go
  type FileStructure (line 14) | type FileStructure struct
    method getOrCreate (line 39) | func (g *FileStructure) getOrCreate(path string, options FileStructure...
    method SaveSelfAt (line 70) | func (g *FileStructure) SaveSelfAt(path string) error {
    method SaveAt (line 99) | func (g *FileStructure) SaveAt(path string) error {
  function Dir (line 21) | func Dir(path string) (matches []string, err error) {
  function RemoveFiles (line 25) | func RemoveFiles(files []string) error {
  function CopyFiles (line 32) | func CopyFiles(files []string, destination string) error {

FILE: src/utils/json.go
  type Json (line 9) | type Json
    method Contains (line 19) | func (j *Json) Contains(test interface{}) bool {
    method get (line 28) | func (j *Json) get(index interface{}) interface{} {

FILE: src/utils/repo.go
  function GetOrCreateRepo (line 7) | func GetOrCreateRepo(path string) map[string]interface{} {
  function SaveRepo (line 21) | func SaveRepo(path string, file map[string]interface{}) {

FILE: src/utils/types.go
  type GupmEntryPoint (line 3) | type GupmEntryPoint struct
  type gupmEntryPointCliList (line 14) | type gupmEntryPointCliList struct
  type gupmEntryPointGit (line 19) | type gupmEntryPointGit struct
  type gupmEntryPointGitHooks (line 23) | type gupmEntryPointGitHooks struct
  type gupmEntryPointDependenciesList (line 28) | type gupmEntryPointDependenciesList struct
  type gupmEntryPointConfigList (line 33) | type gupmEntryPointConfigList struct
  type gupmEntryPointConfig (line 37) | type gupmEntryPointConfig struct
  type gupmEntryPointPublish (line 44) | type gupmEntryPointPublish struct

FILE: src/utils/untar.go
  function Ungz (line 14) | func Ungz(r string) (FileStructure, error) {
  function Tar (line 36) | func Tar(files []string) (FileStructure, error) {
  function Untar (line 87) | func Untar(r string) (FileStructure, error) {
  function Unzip (line 143) | func Unzip(r string) (FileStructure, error) {

FILE: src/utils/utils.go
  type Dependency (line 20) | type Dependency struct
  function buildCmd (line 26) | func buildCmd(toRun string, args []string) *exec.Cmd {
  function ExecCommand (line 44) | func ExecCommand(toRun string, args []string) error {
  function ReadGupmJson (line 53) | func ReadGupmJson(path string) (*GupmEntryPoint, error) {
  function RunCommand (line 66) | func RunCommand(toRun string, args []string) (string, error) {
  function BuildStringFromDependency (line 75) | func BuildStringFromDependency(dep map[string]interface{}) string {
  function BuildDependencyFromString (line 89) | func BuildDependencyFromString(defaultProvider string, dep string) map[s...
  function StringToJSON (line 115) | func StringToJSON(b string) map[string]interface{} {
  function ReadJSON (line 121) | func ReadJSON(path string, target interface{}) error {
  function HttpGet (line 135) | func HttpGet(url string) []byte {
  function FileExists (line 166) | func FileExists(path string) bool {
  function StringInSlice (line 177) | func StringInSlice(a string, list []string) bool {
  function RemoveIndex (line 186) | func RemoveIndex(s []map[string]interface{}, index int) []map[string]int...
  function RecursiveFileWalkDir (line 190) | func RecursiveFileWalkDir(source string) []string {
  function ReadDir (line 210) | func ReadDir(path string) ([]os.FileInfo, error) {
  function IsDirectory (line 222) | func IsDirectory(path string) bool {
  function HOMEDIR (line 230) | func HOMEDIR(fallback string) string {
  function DIRNAME (line 239) | func DIRNAME() string {
  function WriteFile (line 249) | func WriteFile(path string, file string) error {
  function WriteJsonFile (line 253) | func WriteJsonFile(path string, file map[string]interface{}) {
  function SaveLockDep (line 264) | func SaveLockDep(path string) {
  function AbsPath (line 268) | func AbsPath(rel string) string {
  function Path (line 273) | func Path(path string) string {
  function Contains (line 281) | func Contains(s interface{}, elem interface{}) bool {
  function ArrString (line 298) | func ArrString(something interface{}) []string {
  function GupmConfig (line 311) | func GupmConfig() gupmEntryPointConfig {
  function OSNAME (line 316) | func OSNAME() string {

FILE: src/windows/windows_install.go
  function main (line 9) | func main() {
Condensed preview — 52 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (109K chars).
[
  {
    "path": ".circleci/config.yml",
    "chars": 1462,
    "preview": "version: 2\njobs:\n  build:\n    docker:\n      - image: golang:1.12.5-stretch\n\n    steps:\n      - checkout\n\n      - run:\n  "
  },
  {
    "path": ".gitignore",
    "chars": 111,
    "preview": ".DS_Store\n.bin\nbuild\n.vscode\nnode_modules\ntemp\ncache\nsampleproject\ntest.gs\npackage.json\ngo_modules\ngupm_modules"
  },
  {
    "path": ".gupm_rc.gs",
    "chars": 73,
    "preview": "env(\"GOPATH\", run(\"go\", [\"env\", \"GOROOT\"]) + \":\" + pwd() + \"/go_modules\")"
  },
  {
    "path": "LICENCE",
    "chars": 751,
    "preview": "Copyright (c) Yann Stepienik (yann.stepienik@gmail.com)\n\nPermission to use, copy, modify, and distribute this software f"
  },
  {
    "path": "build.gs",
    "chars": 293,
    "preview": "removeFiles([\"build/dg\", \"build/plugins\", \"build/gupm.json\"]) \n\nvar goArgs = [\"build\", \"-o\", \"build/dg\"]\ngoArgs = goArgs"
  },
  {
    "path": "ci/publish.gs",
    "chars": 1004,
    "preview": "removeFiles(\"gupm\")\n\nvar goArgs = [\"build\", \"-o\"]\n\nif(typeof $1 != \"undefined\" && $1 == \"windows\") {\n    goArgs.push(\"gu"
  },
  {
    "path": "docs/install.sh",
    "chars": 1024,
    "preview": "#!/bin/sh\n\nif [ \"$(uname)\" = \"Darwin\" ]; then\n    curl --output gupm.tar.gz https://azukaar.github.io/GuPM/gupm_mac.tar."
  },
  {
    "path": "gupm.json",
    "chars": 1060,
    "preview": "{\n    \"cli\": {\n        \"aliases\": {\n            \"gotest\": \"go test ./src ./src/utils\",\n            \"start\": \"./build/dg\""
  },
  {
    "path": "plugins/provider-git/gupm.json",
    "chars": 198,
    "preview": "{\r\n    \"name\": \"provider-git\",\r\n    \"version\": \"0.0.1\",\r\n    \"config\": {\r\n        \"default\": {\r\n            \"entrypoint\""
  },
  {
    "path": "plugins/provider-git/postGetDependency.gs",
    "chars": 446,
    "preview": "// Provider : name of provider (npm)\r\n// Name : name of downloaded package\r\n// Version : version of downloaded package\r\n"
  },
  {
    "path": "plugins/provider-git/resolveDependencyLocation.gs",
    "chars": 308,
    "preview": "var name = Dependency.name;\r\nvar version = Dependency.version;\r\n\r\nDependency.url = 'https://' + name + '/archive/master."
  },
  {
    "path": "plugins/provider-http/gupm.json",
    "chars": 190,
    "preview": "{\n    \"name\": \"provider-http\",\n    \"version\": \"0.0.1\",\n    \"config\": {\n        \"default\": {\n            \"entrypoint\": \"g"
  },
  {
    "path": "plugins/provider-http/resolveDependencyLocation.gs",
    "chars": 1146,
    "preview": "var name = Dependency.name;\n\nif(name.split(':').length > 1) {\n    var version = Dependency.version\n    var names = name."
  },
  {
    "path": "plugins/provider-https/gupm.json",
    "chars": 191,
    "preview": "{\n    \"name\": \"provider-https\",\n    \"version\": \"0.0.1\",\n    \"config\": {\n        \"default\": {\n            \"entrypoint\": \""
  },
  {
    "path": "plugins/provider-https/resolveDependencyLocation.gs",
    "chars": 1149,
    "preview": "var name = Dependency.name;\n\nif(name.split(':').length > 1) {\n    var version = Dependency.version\n    var names = name."
  },
  {
    "path": "readme.md",
    "chars": 6618,
    "preview": "![dog](./docs/banner.png)\r\n\r\n---\r\n\r\n<br />\r\n<p align=\"center\">\r\n<img src=\"https://img.shields.io/badge/Platform-Windows%"
  },
  {
    "path": "src/addDependency.go",
    "chars": 1459,
    "preview": "package main\n\nimport (\n\t\"./provider\"\n\t\"./ui\"\n\t\"./utils\"\n)\n\nfunc AddDependency(path string, rls []string) error {\n\tvar er"
  },
  {
    "path": "src/bootstrap.go",
    "chars": 333,
    "preview": "package main\n\nimport (\n\t\"./provider\"\n\t\"./ui\"\n\t// \"fmt\"\n)\n\nfunc Bootstrap(path string) error {\n\terr := provider.InitProvi"
  },
  {
    "path": "src/cache.go",
    "chars": 267,
    "preview": "package main\n\nimport (\n\t\"./ui\"\n\t\"./utils\"\n\t\"github.com/mitchellh/go-homedir\"\n)\n\nfunc CacheClear() {\n\thdir, errH := homed"
  },
  {
    "path": "src/cli.go",
    "chars": 5962,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"./ui\"\n\t\"./utils\"\n)\n\ntype json = utils.Json\n\nvar Provide"
  },
  {
    "path": "src/cli_test.go",
    "chars": 1717,
    "preview": "package main\n\nimport (\n\t\"testing\"\n\t// \"reflect\"\n\t_ \"fmt\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestArgs(t *test"
  },
  {
    "path": "src/defaultProvider/defaultProvider.go",
    "chars": 4855,
    "preview": "package defaultProvider\n\nimport (\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"reflect\"\n\t\"regexp\"\n\n\t\"../ui\"\n\t\"../utils\"\n)\n\nfunc"
  },
  {
    "path": "src/defaultProvider/publish.go",
    "chars": 1713,
    "preview": "package defaultProvider\n\nimport (\n\t\"os\"\n\n\t\"../ui\"\n\t\"../utils\"\n)\n\nfunc Publish(path string, namespace string) error {\n\tco"
  },
  {
    "path": "src/distribution_gupm.json",
    "chars": 346,
    "preview": "{\n    \"name\": \"gupm\",\n    \"config\": {\n        \"default\": {\n            \"entrypoint\": \"gupm.json\",\n            \"installPa"
  },
  {
    "path": "src/gitHooks.go",
    "chars": 3481,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"./utils\"\n\t\"github.com/bmatcuk/doublestar\"\n)\n\nfunc BuildGitHo"
  },
  {
    "path": "src/global.go",
    "chars": 1326,
    "preview": "package main\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"./ui\"\n\t\"./utils\"\n)\n\nfunc installBins(path string) {\n\tvar GLOBAL = utils"
  },
  {
    "path": "src/index.go",
    "chars": 3047,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"./jsVm\"\n\t\"./ui\"\n\t\"./utils\"\n)\n\nvar Provider "
  },
  {
    "path": "src/installProject.go",
    "chars": 5812,
    "preview": "package main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n\n\t\"./provider\"\n\t\"./ui\"\n\t\"./utils\"\n\t\"github.com/mitchellh/go-home"
  },
  {
    "path": "src/jsVm/jsVm.go",
    "chars": 9729,
    "preview": "package jsVm\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sync\"\n\t\"time\"\n\n\t\"../ui\"\n\t\"../uti"
  },
  {
    "path": "src/plugins.go",
    "chars": 3154,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"./provider\"\n\t\"./ui\"\n\t\"./utils\"\n)\n\nfunc PluginLink(pat"
  },
  {
    "path": "src/provider/bootstrap.go",
    "chars": 618,
    "preview": "package provider\n\nimport (\n\t\"../defaultProvider\"\n\t\"../jsVm\"\n\t\"../utils\"\n\t\"errors\"\n\t// \"fmt\"\n)\n\nfunc Bootstrap(path strin"
  },
  {
    "path": "src/provider/dependencyTree.go",
    "chars": 2363,
    "preview": "package provider\n\nfunc eliminateRedundancy(tree []map[string]interface{}, path map[string]bool) []map[string]interface{}"
  },
  {
    "path": "src/provider/install.go",
    "chars": 2284,
    "preview": "package provider\n\nimport (\n\t\"io/ioutil\"\n\t\"os\"\n\t\"regexp\"\n\n\t\"../defaultProvider\"\n\t\"../jsVm\"\n\t\"../ui\"\n\t\"../utils\"\n)\n\nfunc B"
  },
  {
    "path": "src/provider/provider.go",
    "chars": 7517,
    "preview": "package provider\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sync\"\n\n\t\"../defaultProvider\"\n\t\"../jsVm\"\n\t\"../ui\"\n\t\"../utils\"\n"
  },
  {
    "path": "src/provider/publish.go",
    "chars": 604,
    "preview": "package provider\n\nimport (\n\t\"errors\"\n\n\t\"../defaultProvider\"\n\t\"../jsVm\"\n\t\"../utils\"\n\t// \"fmt\"\n)\n\nfunc Publish(path string"
  },
  {
    "path": "src/publish.go",
    "chars": 347,
    "preview": "package main\n\nimport (\n\t\"./provider\"\n\t\"./ui\"\n)\n\nfunc Publish(path string, namespace string) error {\n\terr := provider.Ini"
  },
  {
    "path": "src/removeDependency.go",
    "chars": 1045,
    "preview": "package main\n\nimport (\n\t\"./provider\"\n\t\"./ui\"\n\t\"./utils\"\n)\n\nfunc remove(slice []map[string]interface{}, s int) []map[stri"
  },
  {
    "path": "src/self.go",
    "chars": 823,
    "preview": "package main\n\nimport (\n\t\"./ui\"\n\t\"./utils\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"os/exec\"\n\t\"runtime\"\n)\n\n// TODO: implemement script-free u"
  },
  {
    "path": "src/test.go",
    "chars": 781,
    "preview": "package main\n\nimport (\n\t\"os\"\n\t\"regexp\"\n\t\"strconv\"\n\n\t\"./jsVm\"\n\t\"./ui\"\n\t\"./utils\"\n)\n\nfunc RunTest(path string) {\n\t_ = jsVm"
  },
  {
    "path": "src/ui/log.go",
    "chars": 3804,
    "preview": "package ui\n\nimport (\n\t\"bufio\"\n\t\"errors\"\n\t\"fmt\"\n\t\"github.com/fatih/color\"\n\t\"github.com/gosuri/uilive\"\n\t\"os\"\n\t\"strconv\"\n\t\""
  },
  {
    "path": "src/utils/files.go",
    "chars": 2163,
    "preview": "package utils\n\nimport (\n\t\"os\"\n\t\"strings\"\n\n\t// \"fmt\"\n\t\"github.com/bmatcuk/doublestar\"\n\t\"github.com/otiai10/copy\"\n)\n\nvar E"
  },
  {
    "path": "src/utils/json.go",
    "chars": 673,
    "preview": "package utils\n\n// import (\n// \t\"reflect\"\n// \t\"fmt\"\n// )\n\n// type Json map[interface{}]interface {}\ntype Json map[string]"
  },
  {
    "path": "src/utils/repo.go",
    "chars": 464,
    "preview": "package utils\n\nimport (\n\t\"io/ioutil\"\n)\n\nfunc GetOrCreateRepo(path string) map[string]interface{} {\n\tconfigPath := path +"
  },
  {
    "path": "src/utils/types.go",
    "chars": 999,
    "preview": "package utils\n\ntype GupmEntryPoint struct {\n\tName              string\n\tVersion           string\n\tWrapInstallFolder strin"
  },
  {
    "path": "src/utils/untar.go",
    "chars": 2943,
    "preview": "package utils\n\nimport \"archive/tar\"\nimport \"archive/zip\"\nimport \"compress/gzip\"\n\nimport (\n\t\"bytes\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\""
  },
  {
    "path": "src/utils/utils.go",
    "chars": 6562,
    "preview": "package utils\n\nimport (\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"regexp\""
  },
  {
    "path": "src/windows/windows_install.go",
    "chars": 396,
    "preview": "package main\n\nimport (\n\t\"../ui\"\n\t\"../utils\"\n\t\"fmt\"\n)\n\nfunc main() {\n\tarch := utils.HttpGet(\"https://azukaar.github.io/Gu"
  },
  {
    "path": "tests/install/normal.test.gs",
    "chars": 313,
    "preview": "writeJsonFile(\"gupm.json\", {\n    \"dependencies\": {\n        \"default\": {\n        }\n    }\n})\n\n\nvar err = exec(\"../build/dg"
  },
  {
    "path": "tests/make/nodeps.test.gs",
    "chars": 185,
    "preview": "writeJsonFile(\"gupm.json\", {\n    \"dependencies\": {\n        \"default\": {\n        }\n    }\n})\n\nvar err = exec(\"../build/dg\""
  },
  {
    "path": "tests/make/normal.test.gs",
    "chars": 336,
    "preview": "writeJsonFile(\"gupm.json\", {\n    \"dependencies\": {\n        \"default\": {\n            \"git://github.com/Masterminds/semver"
  },
  {
    "path": "tests/plugins/normal.test.gs",
    "chars": 411,
    "preview": "writeJsonFile(\"gupm.json\", {\n    \"dependencies\": {\n        \"default\": {\n            \"npm://webpack\": \"latest\"\n        }\n"
  },
  {
    "path": "tests/scripts/normal.test.gs",
    "chars": 212,
    "preview": "writeFile(\"testscript.gs\",\"writeFile('test','it works');\")\n\nvar err = exec(\"../build/dg\", [\"testscript\"])\n\nif(err) {\n   "
  }
]

About this extraction

This page contains the full source code of the azukaar/GuPM GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 52 files (92.8 KB), approximately 28.1k tokens, and a symbol index with 138 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!