[
  {
    "path": ".circleci/config.yml",
    "content": "version: 2\njobs:\n  build:\n    docker:\n      - image: golang:1.12.5-stretch\n\n    steps:\n      - checkout\n\n      - run:\n          name: Install GuPM\n          command: curl -fsSL  https://azukaar.github.io/GuPM/install.sh | bash\n\n      - run:\n          name: Install provider\n          command: g plugin install https://azukaar.github.io/GuPM-official/repo:provider-go\n\n      - run:\n          name: Make\n          command: g make\n\n      - run:\n          name: Build\n          command: g build\n\n      - run:\n          name: Cleanup\n          command: g pl delete provider-go\n      \n      - run:\n          name: Run tests\n          command: g test\n\n      - run:\n          name: Run unit tests\n          command: g gotest\n      \n      - run:\n          name: Install provider\n          command: g plugin install https://azukaar.github.io/GuPM-official/repo:provider-go\n\n      - run:\n          name: Build Linux\n          command: g ci/publish\n      - run:\n          name: Build Mac\n          command: g ci/publish mac\n      - run:\n          name: Build Windows\n          command: g ci/publish windows\n      \n      - run: git config user.email \"nobody@circleci.com\"\n      - run: git config user.name \"Circle Ci\"\n      - run: git add docs\n      - run: git commit -m \"[skip ci] Release\"\n      - run: git push origin master\n\nworkflows:\n  version: 2\n  build-all:\n    jobs:\n      - build:\n          filters:\n            branches:\n              only:\n                - master"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\n.bin\nbuild\n.vscode\nnode_modules\ntemp\ncache\nsampleproject\ntest.gs\npackage.json\ngo_modules\ngupm_modules"
  },
  {
    "path": ".gupm_rc.gs",
    "content": "env(\"GOPATH\", run(\"go\", [\"env\", \"GOROOT\"]) + \":\" + pwd() + \"/go_modules\")"
  },
  {
    "path": "LICENCE",
    "content": "Copyright (c) Yann Stepienik (yann.stepienik@gmail.com)\n\nPermission to use, copy, modify, and distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n"
  },
  {
    "path": "build.gs",
    "content": "removeFiles([\"build/dg\", \"build/plugins\", \"build/gupm.json\"]) \n\nvar goArgs = [\"build\", \"-o\", \"build/dg\"]\ngoArgs = goArgs.concat(dir(\"src/*.go\"))\nexec(\"go\", goArgs)\n\ncopyFiles(\"plugins\", \"build/plugins\")\ncopyFiles(\"src/distribution_gupm.json\", \"build/gupm.json\")\n\nconsole.log(\"\\nBuild done! 💖\")"
  },
  {
    "path": "ci/publish.gs",
    "content": "removeFiles(\"gupm\")\n\nvar goArgs = [\"build\", \"-o\"]\n\nif(typeof $1 != \"undefined\" && $1 == \"windows\") {\n    goArgs.push(\"gupm/g.exe\")\n} else {\n    goArgs.push(\"gupm/g\")\n}\n\ngoArgs = goArgs.concat(dir(\"src/*.go\"))\n\ncopyFiles(\"plugins\", \"gupm/plugins\")\ncopyFiles(\"src/distribution_gupm.json\", \"gupm/gupm.json\")\n\nif(typeof $1 != \"undefined\" && $1 == \"mac\") {\n    env(\"GOOS\", \"darwin\")\n    env(\"go version\", \"amd64\")\n    exec(\"go\", goArgs)\n    var arch = tar(\"gupm\")\n    removeFiles(\"docs/gupm_mac.tar.gz\")\n    saveFileAt(arch, \"docs/gupm_mac.tar.gz\")\n} \nif(typeof $1 != \"undefined\" && $1 == \"windows\") {\n    env(\"GOOS\", \"windows\")\n    env(\"GOARCH\", \"amd64\")\n    exec(\"go\", goArgs)\n    var arch = tar(\"gupm\")\n    removeFiles(\"docs/gupm_windows.tar.gz\")\n    saveFileAt(arch, \"docs/gupm_windows.tar.gz\")\n} else {\n    env(\"GOOS\", \"linux\")\n    env(\"GOARCH\", \"amd64\")\n    exec(\"go\", goArgs)\n    var arch = tar(\"gupm\")\n    removeFiles(\"docs/gupm.tar.gz\")\n    saveFileAt(arch, \"docs/gupm.tar.gz\")\n}\n\nremoveFiles(\"gupm\")"
  },
  {
    "path": "docs/install.sh",
    "content": "#!/bin/sh\n\nif [ \"$(uname)\" = \"Darwin\" ]; then\n    curl --output gupm.tar.gz https://azukaar.github.io/GuPM/gupm_mac.tar.gz       \nelif [ \"$(uname)\" = \"Linux\" ]; then\n    curl --output gupm.tar.gz https://azukaar.github.io/GuPM/gupm.tar.gz\nfi\n\nmkdir ~/.gupm\ntar -C ~/.gupm -zxvf gupm.tar.gz\nchmod -R 755 ~/.gupm/gupm/\nrm gupm.tar.gz\n\nif [ -d \"/usr/local/bin\" ] \nthen\n    if [ -f \"/usr/local/bin/g\" ] \n    then\n        rm /usr/local/bin/g\n    fi\n    ln -s ~/.gupm/gupm/g /usr/local/bin/g\nelse\n    if [ -f \"/bin/g\" ] \n    then\n        rm /bin/g\n    fi\n    ln -s ~/.gupm/gupm/g /bin/g\nfi\n\nif [ \"$(uname)\" = \"Darwin\" ]; then\n    read -r -p \"Do you want to make Homebrew your default provider? (Recommended) [y/N] \" response\n    if [[ \"$response\" =~ ^([yY][eE][sS]|[yY])+$ ]]\n    then\n        g plugin install https://azukaar.github.io/GuPM-official/repo:provider-brew\n        sed -ie 's/\"defaultProvider\": \"gupm\"/\"defaultProvider\": \"os\"/' ~/.gupm/gupm/gupm.json\n    fi\nfi\n\necho \"------\"\necho \"Installaton complete\"\necho \"------\"\n"
  },
  {
    "path": "gupm.json",
    "content": "{\n    \"cli\": {\n        \"aliases\": {\n            \"gotest\": \"go test ./src ./src/utils\",\n            \"start\": \"./build/dg\"\n        }\n    },\n    \"dependencies\": {\n        \"default\": {\n            \"go://github.com/Masterminds/semver\": \"master\",\n            \"go://github.com/bmatcuk/doublestar\": \"master\",\n            \"go://github.com/fatih/color\": \"master\",\n            \"go://github.com/gosuri/uilive\": \"master\",\n            \"go://github.com/mattn/go-isatty\": \"master\",\n            \"go://github.com/mitchellh/go-homedir\": \"master\",\n            \"go://github.com/otiai10/copy\": \"master\",\n            \"go://github.com/robertkrimen/otto\": \"master\",\n            \"go://github.com/stretchr/testify\": \"master\",\n            \"go://gopkg.in/sourcemap.v1\": \"v1.0.5\"\n        },\n        \"defaultProvider\": \"go\"\n    },\n    \"git\": {\n        \"hooks\": {\n            \"precommit\": \"gofmt -w -s src/index.go $StagedFiles(**/*.go)\",\n            \"prepush\": [\n                \"g test\",\n                \"g gotest\"\n            ]\n        }\n    },\n    \"name\": \"gupm\",\n    \"version\": \"1.2.1\"\n}"
  },
  {
    "path": "plugins/provider-git/gupm.json",
    "content": "{\r\n    \"name\": \"provider-git\",\r\n    \"version\": \"0.0.1\",\r\n    \"config\": {\r\n        \"default\": {\r\n            \"entrypoint\": \"gupm.json\",\r\n            \"installPath\": \"gupm_modules\"\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "plugins/provider-git/postGetDependency.gs",
    "content": "// Provider : name of provider (npm)\r\n// Name : name of downloaded package\r\n// Version : version of downloaded package\r\n// Url : URL of downloaded package\r\n// Path  : Future path of downloaded package\r\n// Result : binary downloaded\r\n\r\nvar folder = unzip(Result);\r\n\r\nvar firstChildrenName = Object.keys(folder.Children)[0];\r\nvar firstChildren = folder.Children[firstChildrenName];\r\n\r\nsaveFileAt(firstChildren, Path);\r\nsaveLockDep(Path);\r\n\r\nPath;\r\n"
  },
  {
    "path": "plugins/provider-git/resolveDependencyLocation.gs",
    "content": "var name = Dependency.name;\r\nvar version = Dependency.version;\r\n\r\nDependency.url = 'https://' + name + '/archive/master.zip'\r\n\r\nif(Dependency.version === \"*.*.*\") {\r\n  Dependency.version = \"master\"\r\n}\r\n\r\n// https://github.com/src-d/go-git/archive/6e931e4fdefa202c76242109453447182ae16444.zip\r\n\r\nDependency;\r\n"
  },
  {
    "path": "plugins/provider-http/gupm.json",
    "content": "{\n    \"name\": \"provider-http\",\n    \"version\": \"0.0.1\",\n    \"config\": {\n        \"default\": {\n            \"entrypoint\": \"gupm.json\",\n            \"installPath\": \"gupm_modules\"\n        }\n    }\n}"
  },
  {
    "path": "plugins/provider-http/resolveDependencyLocation.gs",
    "content": "var name = Dependency.name;\n\nif(name.split(':').length > 1) {\n    var version = Dependency.version\n    var names = name.split(':')\n\n    // exact version\n    if (version.match(/^\\d+\\.\\d+\\.\\d+/) && !version.match(/\\sx/)) {\n    }\n    \n    // test ranges\n    else {\n        var repoList = 'http://' + names[0] + '/gupm_repo.json'\n        var payload = httpGetJson(repoList);\n\n        if(payload.packages[names[1]] && payload.packages[names[1]].length) {\n            var versionList = payload.packages[names[1]];\n            version = semverLatestInRange(version, versionList);\n        } else {\n            console.error(\"Package \"+names[1]+\" not found in \" + names[0])\n            exit(1)\n        }\n    }\n\n\n\n    var realName = names[1]\n    var namespace = ''\n    if( realName.split('/').length > 1) {\n        namespace = (realName.split('/')[0] + '/').replace(\"OS\", _OSNAME)\n        realName = realName.split('/')[1]\n    }\n    Dependency.url = 'http://' + names[0] + '/' + namespace + realName + '/'  + version + '/' + realName + '-'  + version + '.tgz'\n\n    Dependency.version = version\n} else {\n    Dependency.url = 'http://' + name\n}\n\nDependency;\n"
  },
  {
    "path": "plugins/provider-https/gupm.json",
    "content": "{\n    \"name\": \"provider-https\",\n    \"version\": \"0.0.1\",\n    \"config\": {\n        \"default\": {\n            \"entrypoint\": \"gupm.json\",\n            \"installPath\": \"gupm_modules\"\n        }\n    }\n}"
  },
  {
    "path": "plugins/provider-https/resolveDependencyLocation.gs",
    "content": "var name = Dependency.name;\n\nif(name.split(':').length > 1) {\n    var version = Dependency.version\n    var names = name.split(':')\n\n    // exact version\n    if (version.match(/^\\d+\\.\\d+\\.\\d+/) && !version.match(/\\sx/)) {\n    }\n    \n    // test ranges\n    else {\n        var repoList = 'https://' + names[0] + '/gupm_repo.json'\n        var payload = httpGetJson(repoList);\n\n        if(payload.packages[names[1]] && payload.packages[names[1]].length) {\n            var versionList = payload.packages[names[1]];\n            version = semverLatestInRange(version, versionList);\n        } else {\n            console.error(\"Package \"+names[1]+\" not found in \" + names[0])\n            exit(1)\n        }\n    }\n\n\n\n    var realName = names[1]\n    var namespace = ''\n    if( realName.split('/').length > 1) {\n        namespace = (realName.split('/')[0] + '/').replace(\"OS\", _OSNAME)\n        realName = realName.split('/')[1]\n    }\n    Dependency.url = 'https://' + names[0] + '/' + namespace + realName + '/'  + version + '/' + realName + '-'  + version + '.tgz'\n\n    Dependency.version = version\n} else {\n    Dependency.url = 'https://' + name\n}\n\nDependency;\n"
  },
  {
    "path": "readme.md",
    "content": "![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%20%7C%20Linux%20%7C%20MacOS-pink.svg?style=for-the-badge\">\r\n<img src=\"https://img.shields.io/badge/CircleCI-Passing-green.svg?style=for-the-badge\">\r\n<img src=\"https://img.shields.io/badge/GoLang-1.12.5-blue.svg?style=for-the-badge\">\r\n<br/>\r\n<img src=\"https://img.shields.io/badge/Ruby-Gem-e9573f.svg?style=for-the-badge&logo=ruby\">\r\n<img src=\"https://img.shields.io/badge/Javascript-NPM | Entropic-25799f.svg?style=for-the-badge&logo=javascript\">\r\n<img src=\"https://img.shields.io/badge/Python-PIP-yellow.svg?style=for-the-badge&logo=python\">\r\n<img src=\"https://img.shields.io/badge/PHP-Composer-black.svg?style=for-the-badge&logo=php\">\r\n<img src=\"https://img.shields.io/badge/Windows-Chocolatey-2f6492.svg?style=for-the-badge&logo=windows\">\r\n<img src=\"https://img.shields.io/badge/MacOS-Brew-f9d094.svg?style=for-the-badge&logo=apple\">\r\n<img src=\"https://img.shields.io/badge/GoLang-Go Get-E0EBF5.svg?style=for-the-badge&logo=go\">\r\n</p>\r\n<br />\r\n<br />\r\nGlobal 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 />\r\n<br />\r\n\r\n * ⏱ **Fast**. Written in native code, with real multi-threading.\r\n * 👓 **Smart**. Memory efficient solution using hard-link, which do not duplicate dependencies across project.\r\n * 🌍 **Global**. Windows, Mac and Linux compatibility.\r\n * 🌈 **Universal**. Usable in any kind of project (Ruby, JS, Go, C, Python, etc...)\r\n * 👗 **Customizable**. Flexible plugin system: make GuPM your own.\r\n * 👝 **Future Proof**. Let's make this the last PM you will ever need.\r\n * 🌳 **Decentralized**. You keep control of the sources you tap into.\r\n * 🐳 **No dependencies**. You don't need anythind else (you don't need NPM to use NPM's repository with GuPM)\r\n\r\nThis 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.\r\n<br />\r\n\r\n * 📦 **Packages Manager**. Install packages from any repository and manage dependencies in a seamless way.\r\n * 🖥 **CLI Manager**. Install and use CLI tools in a flexible way without conflicts.\r\n * 🚏 **Scripting**. GuPM is bundled with GuScript, allowing you to build cross platform scripts for your project.\r\n * 🐙 **Packed with features**. Manage configs, git hooks, parallel executions, environment variables, CI, and more.\r\n * 🔥 **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!\r\n<br />\r\n\r\n---\r\n\r\n# Getting started : \r\n\r\n## Quick links\r\n\r\n * [Wiki](https://github.com/azukaar/GuPM/wiki)\r\n * [Quick Start](https://github.com/azukaar/GuPM/wiki/quick-start)\r\n * [Getting started with Node](https://medium.com/@azukaar/gupm-to-manage-your-node-js-project-b7664503f3de?sk=f901b86d888b44dcdb78c644bd5df002)\r\n * [Getting started with Go](https://medium.com/@azukaar/gupm-to-manage-your-go-project-5d19c341403c)\r\n * [Create your own repository](https://github.com/azukaar/GuPM/wiki/repositories)\r\n * [Official GuPM repository](https://github.com/azukaar/GuPM-official)\r\n\r\n## Installation\r\n\r\n### Linux and Mac OS : \r\n\r\n⌨️ `$ curl -fsSL  https://azukaar.github.io/GuPM/install.sh | bash`\r\n\r\n### Windows \r\n\r\n💾 [Windows_install.exe](https://azukaar.github.io/GuPM/windows_install.exe)\r\n\r\n## JS/NPM example\r\n\r\nThis example is setting up a project using the [NPM plugin](https://github.com/azukaar/GuPM-official).\r\nMore details on how to use GuPM with node [here]().\r\n\r\n<p align=\"center\">\r\n<img width=\"824px\" src=\"./docs/intro1.png\">\r\n</p>\r\n\r\n## Go example\r\n\r\nThis example is setting up a project using the [Go plugin](https://github.com/azukaar/GuPM-official).\r\nMore details on how to use GuPM with Go [here]().\r\n\r\n<p align=\"center\">\r\n<img width=\"824px\" src=\"./docs/intro2.png\">\r\n</p>\r\n\r\n# Dependency Manager\r\n\r\n## New projects\r\n\r\nIn 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`\r\n\r\n## Make\r\n\r\nThis command will set up your project by getting dependencies. Adding a -p or --provider argument allows you to specify what provider to use initially.\r\nPlease note you do NOT need to install npm / gem / whatever to use their corresponding provider, GuPM implement everything itself.\r\n\r\n```bash\r\n# reads gupm.json\r\ng make\r\n\r\n# reads package.json\r\ng make -p npm\r\n```\r\n\r\n## Install\r\n\r\n```bash\r\n# use default repo [Config in gupm.json]\r\n\r\ng install mysql\r\ng i mysql\r\n\r\n# use brew\r\n\r\ng install brew://mysql\r\ng install -p brew mysql\r\n\r\n# use NPM\r\n\r\ng install npm://react@1 # will save in gupm.json\r\ng install -p npm react@1 # will save in package.json\r\n```\r\n\r\nMore commands [in the wiki](https://github.com/azukaar/GuPM/wiki/cli-references)\r\n\r\n## GuPM management\r\n\r\n### Plugins\r\n\r\nGuPM needs plugins to work with various repos :\r\n\r\n```bash\r\n# Install provider-go from the official repo\r\ng plugin install https://azukaar.github.io/GuPM-official/repo:provider-go\r\n```\r\n\r\nSee https://github.com/azukaar/gupm-official for a list of officially suported plugins.\r\nSee https://github.com/azukaar/GuPM/wiki/how-to-create-a-provider to create your own.\r\n\r\n### updates\r\n\r\nGuPM can be managed using :\r\n\r\n```bash\r\ng self upgrade\r\n```\r\n\r\nMore commands [in the wiki](https://github.com/azukaar/GuPM/wiki/cli-references)\r\n\r\n## Write GuPM scripts\r\n\r\nYou can use GuScript to write bash-like files, used for setting up your project, use it, or anything literally.\r\nThink of GuScript as a replacement for your bash scripts.\r\n\r\n```\r\n// name_setup.gs\r\n\r\nvar name = input('What is your name')\r\necho('Welcome' + name)\r\nsaveName(name)\r\n```\r\n\r\nGuScript is based on javascript, and therefore allow advanced object/arrays manipulations, function definitions, etc...\r\nFind more details about the available APIs in the [wiki](https://github.com/azukaar/GuPM/wiki) 1\r\n\r\n## VS Code \r\n\r\nAdd this to your `settings.json` to treat .gs file as javascript (temporary fix to plain text)\r\n\r\n```\r\n\"files.associations\": {\r\n    \"*.gs\": \"javascript\"\r\n}\r\n```\r\n\r\n# Thanks!\r\nPackage Icon made by [smashicons](https://www.smashicons.com/)\r\nDog Icon made by [Freepik](https://www.freepik.com/)\r\n"
  },
  {
    "path": "src/addDependency.go",
    "content": "package main\n\nimport (\n\t\"./provider\"\n\t\"./ui\"\n\t\"./utils\"\n)\n\nfunc AddDependency(path string, rls []string) error {\n\tvar err error\n\tvar packageConfig utils.Json\n\tvar depList []map[string]interface{}\n\tvar depProvider = Provider\n\n\tui.Title(\"Add dependency...\")\n\n\tif !ProviderWasForced && utils.FileExists(path+utils.Path(\"/gupm.json\")) {\n\t\tconfig, _ := utils.ReadGupmJson(path + utils.Path(\"/gupm.json\"))\n\t\tif config.Dependencies.DefaultProvider != \"\" {\n\t\t\tdepProvider = config.Dependencies.DefaultProvider\n\t\t}\n\t}\n\n\terr = provider.InitProvider(Provider)\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tproviderConfig, err = provider.GetProviderConfig(Provider)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tpackageConfig, err = provider.GetPackageConfig(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tpackageConfig, err = provider.PostGetPackageConfig(packageConfig)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdepList, err = provider.GetDependencyList(packageConfig)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tui.Title(\"Adding to dependency list...\")\n\n\tfor _, str := range rls {\n\t\tdep := utils.BuildDependencyFromString(depProvider, str)\n\t\tresolved, err := provider.ResolveDependencyLocation(dep)\n\t\tif err != nil || resolved[\"url\"].(string) == \"\" {\n\t\t\tui.Error(\"Can't resolve\", str)\n\t\t\treturn err\n\t\t}\n\t\tdep[\"version\"] = resolved[\"version\"]\n\t\tdepList = append(depList, dep)\n\t}\n\n\tif packageConfig != nil {\n\t\terr = provider.SaveDependencyList(path, depList)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/bootstrap.go",
    "content": "package main\n\nimport (\n\t\"./provider\"\n\t\"./ui\"\n\t// \"fmt\"\n)\n\nfunc Bootstrap(path string) error {\n\terr := provider.InitProvider(Provider)\n\tif err != nil {\n\t\treturn err\n\t}\n\tui.Title(\"Bootstrap project\")\n\terrBoot := provider.Bootstrap(path)\n\tif errBoot != nil {\n\t\treturn errBoot\n\t} else {\n\t\tui.Title(\"Bootstrap done! ❤️\")\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "src/cache.go",
    "content": "package main\n\nimport (\n\t\"./ui\"\n\t\"./utils\"\n\t\"github.com/mitchellh/go-homedir\"\n)\n\nfunc CacheClear() {\n\thdir, errH := homedir.Dir()\n\tif errH != nil {\n\t\tui.Error(errH)\n\t\thdir = \".\"\n\t}\n\n\tfolder := utils.Path(hdir + \"/.gupm/cache/\")\n\n\tutils.RemoveFiles([]string{folder})\n}\n"
  },
  {
    "path": "src/cli.go",
    "content": "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 ProviderWasForced = false\n\ntype Arguments map[string]string\n\nfunc (a *Arguments) AsJson() json {\n\tres := utils.Json{}\n\tfor i, v := range *a {\n\t\tres[i] = v\n\t}\n\treturn res\n}\nfunc (a *Arguments) Join() string {\n\tres := \"\"\n\tfor i, v := range *a {\n\t\tif v == \"true\" || v == \"false\" {\n\t\t\tres += \"--\" + strings.ToLower(i) + \" \"\n\t\t} else if ok, _ := regexp.MatchString(`^\\$\\d+`, i); ok {\n\t\t\tres += v + \" \"\n\t\t} else {\n\t\t\tres += \"--\" + strings.ToLower(i) + \" \" + v + \" \"\n\t\t}\n\t}\n\treturn strings.TrimSpace(res)\n}\nfunc (a *Arguments) AsList() []string {\n\tres := []string{}\n\ti := 1\n\n\tfor (*a)[\"$\"+strconv.Itoa(i)] != \"\" {\n\t\tres = append(res, (*a)[\"$\"+strconv.Itoa(i)])\n\t\ti++\n\t}\n\n\treturn res\n}\nfunc (a *Arguments) Shift() {\n\ti := 2\n\n\tfor (*a)[\"$\"+strconv.Itoa(i)] != \"\" {\n\t\t(*a)[\"$\"+strconv.Itoa(i-1)] = (*a)[\"$\"+strconv.Itoa(i)]\n\t\ti++\n\t}\n\n\t(*a)[\"$\"+strconv.Itoa(i-1)] = \"\"\n}\n\nfunc GetArgs(args []string) (string, Arguments) {\n\targuments := make(Arguments)\n\tnext := \"\"\n\tdolsI := 1\n\n\tif len(args) == 0 {\n\t\targuments[\"$0\"] = \"\"\n\t\treturn \"\", arguments\n\t}\n\n\tcommand := args[0]\n\tif len(args) < 2 {\n\t\targuments[\"$0\"] = command\n\t\treturn command, arguments\n\t}\n\n\targsToParse := args[1:]\n\n\tfor _, value := range argsToParse {\n\t\tnameCheck := regexp.MustCompile(`^--?(\\w+)`)\n\t\ttryname := nameCheck.FindString(value)\n\t\tif tryname != \"\" {\n\t\t\tlong, _ := regexp.MatchString(`^--`, tryname)\n\t\t\tif long {\n\t\t\t\ttryname = tryname[1:]\n\t\t\t}\n\n\t\t\tif next != \"\" {\n\t\t\t\targuments[next] = \"true\"\n\t\t\t\tnext = \"\"\n\t\t\t}\n\t\t\tnext = strings.ToUpper(tryname[1:2]) + tryname[2:]\n\t\t} else {\n\t\t\tif next != \"\" {\n\t\t\t\targuments[next] = value\n\t\t\t\tnext = \"\"\n\t\t\t} else {\n\t\t\t\targuments[\"$\"+strconv.FormatInt(int64(dolsI), 10)] = value\n\t\t\t\tdolsI++\n\t\t\t}\n\t\t}\n\t}\n\n\tif next != \"\" {\n\t\targuments[next] = \"true\"\n\t}\n\n\targuments[\"$0\"] = command + \" \" + arguments.Join()\n\n\treturn command, arguments\n}\n\nfunc getProvider(c string, args Arguments) string {\n\tgupmConfig := utils.GupmConfig()\n\tdefaultProvider := \"gupm\"\n\n\tif c == \"install\" || c == \"global\" {\n\t\tdefaultProvider = gupmConfig.DefaultProvider\n\t}\n\n\tif defaultProvider == \"os\" {\n\t\tosName := utils.OSNAME()\n\t\tif gupmConfig.OsProviders[osName] != \"\" {\n\t\t\tdefaultProvider = gupmConfig.OsProviders[osName]\n\t\t} else {\n\t\t\tui.Error(\"No provider set for\", osName)\n\t\t\treturn utils.DIRNAME()\n\t\t}\n\t}\n\n\tif utils.FileExists(\"gupm.json\") {\n\t\tconfig, err := utils.ReadGupmJson(\"gupm.json\")\n\t\tif err != nil {\n\t\t\tui.Error(err)\n\t\t} else {\n\t\t\tif config.Cli.DefaultProviders[c] != \"\" {\n\t\t\t\tdefaultProvider = config.Cli.DefaultProviders[c]\n\t\t\t}\n\t\t}\n\t}\n\n\tif args[\"Provider\"] != \"\" {\n\t\tProviderWasForced = true\n\t\treturn args[\"Provider\"]\n\t} else if args[\"P\"] != \"\" {\n\t\tProviderWasForced = true\n\t\treturn args[\"P\"]\n\t} else {\n\t\treturn defaultProvider\n\t}\n}\n\nfunc ExecCli(c string, args Arguments) (bool, error) {\n\tvar err error\n\tnotFound := \"Cannot find commmand\"\n\tshorthands := map[string]string{\n\t\t\"h\":  \"help\",\n\t\t\"m\":  \"make\",\n\t\t\"i\":  \"install\",\n\t\t\"d\":  \"delete\",\n\t\t\"p\":  \"publish\",\n\t\t\"b\":  \"bootstrap\",\n\t\t\"c\":  \"cache\",\n\t\t\"s\":  \"self\",\n\t\t\"t\":  \"test\",\n\t\t\"pl\": \"plugin\",\n\t\t\"g\":  \"global\",\n\t}\n\n\tif shorthands[c] != \"\" {\n\t\tc = shorthands[c]\n\t}\n\n\tif provider := getProvider(c, args); provider != \"\" {\n\t\tProvider = provider\n\t}\n\n\tif c == \"help\" {\n\t\tfmt.Println(\"make / m :\", \"[--provider=]\", \"Install projects depdencies based on info in the entry point (depends on provider)\")\n\t\tfmt.Println(\"install / i :\", \"[--provider=]\", \"Install package\")\n\t\tfmt.Println(\"remove / r :\", \"[--provider=]\", \"remove package from module config\")\n\t\tfmt.Println(\"publish / p :\", \"[--provider=]\", \"publish a project based on the model of your specific provider\")\n\t\tfmt.Println(\"bootstrap / b :\", \"[--provider=]\", \"bootstrap a new project based on the model of your specific provider\")\n\t\tfmt.Println(\"test / t :\", \"[--provider=] Run project's tests in tests folder.\")\n\n\t\tfmt.Println(\"global / g :\", \"install or delete global packages\")\n\t\tfmt.Println(\"cache / c :\", \"clear or check the cache with \\\"cache clear\\\" or \\\"cache check\\\"\")\n\t\tfmt.Println(\"self / s :\", \"self manage gupm. Try g \\\"self upgrade\\\" or \\\"g self uninstall\\\"\")\n\t\tfmt.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\")\n\t} else if c == \"make\" {\n\t\tBuildGitHooks(\".\")\n\t\terr = InstallProject(\".\")\n\t} else if c == \"install\" {\n\t\terr = AddDependency(\".\", args.AsList())\n\t\tif err == nil {\n\t\t\terr = InstallProject(\".\")\n\t\t}\n\t} else if c == \"publish\" {\n\t\terr = Publish(\".\", args[\"$1\"])\n\t} else if c == \"delete\" {\n\t\terr = RemoveDependency(\".\", args.AsList())\n\t} else if c == \"global\" {\n\t\tif args[\"$1\"] == \"install\" || args[\"$1\"] == \"i\" {\n\t\t\targs.Shift()\n\t\t\tGlobalAdd(args.AsList())\n\t\t} else if args[\"$1\"] == \"delete\" || args[\"$1\"] == \"d\" {\n\t\t\targs.Shift()\n\t\t\tGlobalDelete(args.AsList())\n\t\t} else {\n\t\t\tui.Error(notFound, args[\"$1\"], \"\\n\", \"try install or delete\")\n\t\t}\n\t} else if c == \"plugin\" {\n\t\tif args[\"$1\"] == \"create\" {\n\t\t\tPluginCreate(\".\")\n\t\t} else if args[\"$1\"] == \"link\" {\n\t\t\tPluginLink(\".\")\n\t\t} else if args[\"$1\"] == \"install\" {\n\t\t\terr = PluginInstall(\".\", args.AsList()[1:])\n\t\t} else if args[\"$1\"] == \"delete\" {\n\t\t\tPluginDelete(\".\", args.AsList()[1:])\n\t\t} else {\n\t\t\tui.Error(notFound, args[\"$1\"], \"\\n\", \"try cache clear or cache check\")\n\t\t}\n\t} else if c == \"cache\" {\n\t\tif args[\"$1\"] == \"clear\" {\n\t\t\tCacheClear()\n\t\t} else if args[\"$1\"] == \"check\" {\n\t\t\tui.Error(\"Not implemented yet.\")\n\t\t} else {\n\t\t\tui.Error(notFound, args[\"$1\"], \"\\n\", \"try cache clear or cache check\")\n\t\t}\n\t} else if c == \"self\" {\n\t\tif args[\"$1\"] == \"upgrade\" {\n\t\t\tSelfUpgrade()\n\t\t} else if args[\"$1\"] == \"uninstall\" {\n\t\t\tSelfUninstall()\n\t\t} else {\n\t\t\tui.Error(notFound, args[\"$1\"])\n\t\t}\n\t} else if c == \"bootstrap\" {\n\t\terr = Bootstrap(\".\")\n\t} else if c == \"test\" {\n\t\tRunTest(\"tests\")\n\t} else if c == \"hook\" {\n\t\tRunHook(\".\", args[\"$1\"])\n\t} else {\n\t\treturn false, nil\n\t}\n\n\treturn true, err\n}\n"
  },
  {
    "path": "src/cli_test.go",
    "content": "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 *testing.T) {\n\trequire := require.New(t)\n\n\t// Basic\n\tcommand, args := GetArgs([]string{\"make\", \"-p\", \"npm\"})\n\trequire.Equal(\"make\", command)\n\trequire.Equal(Arguments{\"$0\": \"make --p npm\", \"P\": \"npm\"}, args)\n\n\t// Nothing\n\tcommand, args = GetArgs([]string{})\n\trequire.Equal(\"\", command)\n\trequire.Equal(Arguments{\"$0\": \"\"}, args)\n\n\t// No args\n\tcommand, args = GetArgs([]string{\"install\"})\n\trequire.Equal(\"install\", command)\n\trequire.Equal(Arguments{\"$0\": \"install\"}, args)\n\n\t// bools and long mix\n\tcommand, args = GetArgs([]string{\"install\", \"--dev\", \"--provider\", \"npm\"})\n\trequire.Equal(\"install\", command)\n\trequire.Equal(Arguments{\"$0\": \"install --dev --provider npm\", \"Dev\": \"true\", \"Provider\": \"npm\"}, args)\n\tcommand, args = GetArgs([]string{\"install\", \"--provider\", \"npm\", \"--dev\"})\n\trequire.Equal(\"install\", command)\n\trequire.Equal(Arguments{\"$0\": \"install --provider npm --dev\", \"Dev\": \"true\", \"Provider\": \"npm\"}, args)\n\n\t// bools at the end\n\tcommand, args = GetArgs([]string{\"install\", \"--dev\"})\n\trequire.Equal(\"install\", command)\n\trequire.Equal(Arguments{\"$0\": \"install --dev\", \"Dev\": \"true\"}, args)\n\n\t// long args\n\tcommand, args = GetArgs([]string{\"install\", \"--provider\", \"npm\"})\n\trequire.Equal(\"install\", command)\n\trequire.Equal(Arguments{\"$0\": \"install --provider npm\", \"Provider\": \"npm\"}, args)\n\n\t// anonymous\n\tcommand, args = GetArgs([]string{\"install\", \"npm\"})\n\trequire.Equal(\"install\", command)\n\trequire.Equal(Arguments{\"$0\": \"install npm\", \"$1\": \"npm\"}, args)\n\n\t// asList\n\tcommand, args = GetArgs([]string{\"install\", \"go\", \"npm\"})\n\trequire.Equal([]string{\"go\", \"npm\"}, args.AsList())\n\n}\n"
  },
  {
    "path": "src/defaultProvider/defaultProvider.go",
    "content": "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 Bootstrap(path string) {\n\tif utils.FileExists(utils.Path(path + \"/gupm.json\")) {\n\t\tui.Error(\"A project already exists in this folder. Aborting bootstrap.\")\n\t\treturn\n\t}\n\n\tname := ui.WaitForInput(\"Please enter the name of the project: \")\n\tdescription := ui.WaitForInput(\"Enter a description: \")\n\tauthor := ui.WaitForInput(\"Enter the author: \")\n\tlicence := ui.WaitForInput(\"Enter the licence (ISC): \")\n\n\tif name == \"\" {\n\t\tui.Error(\"Name cannot be empty. Try again\")\n\t\treturn\n\t} else {\n\t\tif licence == \"\" {\n\t\t\tlicence = \"ISC\"\n\t\t}\n\n\t\tfileContent := `{\n\t\"name\": \"` + name + `\",\n\t\"version\": \"0.0.1\",\n\t\"description\": \"` + description + `\",\n\t\"author\": \"` + author + `\",\n\t\"licence\": \"` + licence + `\"\n}`\n\t\tioutil.WriteFile(utils.Path(path+\"/gupm.json\"), []byte(fileContent), os.ModePerm)\n\t}\n}\n\nfunc GetPackageConfig(entryPoint string) map[string]interface{} {\n\tvar packageConfig map[string]interface{}\n\tb, err := ioutil.ReadFile(entryPoint)\n\tif err != nil {\n\t\tui.Error(err.Error() + \" : \" + entryPoint)\n\t}\n\n\tjson.Unmarshal([]byte(string(b)), &packageConfig)\n\n\treturn packageConfig\n}\n\nfunc GetDependency(provider string, name string, version string, url string, path string) (string, error) {\n\treturn string(utils.HttpGet(url)), nil\n}\n\nfunc PostGetDependency(provider string, name string, version string, url string, path string, result string) (string, error) {\n\tos.MkdirAll(path, os.ModePerm)\n\ttarCheck := regexp.MustCompile(`\\.tgz$`)\n\ttryTar := tarCheck.FindString(url)\n\tgzCheck := regexp.MustCompile(`\\.gz$`)\n\ttrygz := gzCheck.FindString(url)\n\tzipCheck := regexp.MustCompile(`\\.zip$`)\n\ttryZip := zipCheck.FindString(url)\n\n\tif tryTar != \"\" {\n\t\tresultFiles, err := utils.Untar(result)\n\t\tif err != nil {\n\t\t\treturn path, err\n\t\t}\n\t\tresultFiles.SaveAt(path)\n\t} else if trygz != \"\" {\n\t\tresultFiles, err := utils.Ungz(result)\n\t\tif err != nil {\n\t\t\treturn path, err\n\t\t}\n\t\tresultFiles.SaveAt(path)\n\t} else if tryZip != \"\" {\n\t\tresultFiles, err := utils.Unzip(result)\n\t\tif err != nil {\n\t\t\treturn path, err\n\t\t}\n\t\tresultFiles.SaveAt(path)\n\t}\n\n\tutils.SaveLockDep(path)\n\n\treturn path, nil\n}\n\nfunc GetDependencyList(config map[string]interface{}) []map[string]interface{} {\n\tif config == nil {\n\t\tui.Error(\"no config found. Please bootstrap the project with `g bootstrap`\")\n\t\treturn nil\n\t}\n\tdepEnv, ok := config[\"dependencies\"].(map[string]interface{})\n\tif !ok {\n\t\tui.Log(\"no dependencies\")\n\t\treturn nil\n\t}\n\tdepList, hasDefault := depEnv[\"default\"].(map[string]interface{})\n\tif !hasDefault {\n\t\tui.Log(\"no dependencies\")\n\t\treturn nil\n\t}\n\tresult := make([]map[string]interface{}, 0)\n\tfor name, value := range depList {\n\t\tdep := utils.BuildDependencyFromString(\"gupm\", name)\n\t\tif reflect.TypeOf(value).String() == \"string\" {\n\t\t\tdep[\"version\"] = value\n\t\t} else {\n\t\t\tvalueObject := value.(map[string]interface{})\n\t\t\tif valueObject[\"provider\"].(string) != \"\" {\n\t\t\t\tdep[\"provider\"] = valueObject[\"provider\"]\n\t\t\t}\n\t\t\tif valueObject[\"version\"].(string) != \"\" {\n\t\t\t\tdep[\"version\"] = valueObject[\"version\"]\n\t\t\t}\n\t\t}\n\t\tresult = append(result, dep)\n\t}\n\treturn result\n}\n\nfunc ExpandDependency(dependency map[string]interface{}) (map[string]interface{}, error) {\n\tconfigFilePath := utils.Path(dependency[\"path\"].(string) + \"/gupm.json\")\n\n\tif utils.FileExists(configFilePath) {\n\t\tconfig := GetPackageConfig(configFilePath)\n\t\tdependency[\"dependencies\"] = make(map[string]interface{})\n\n\t\tif config[\"dependencies\"] != nil {\n\t\t\tdependency[\"dependencies\"] = GetDependencyList(config)\n\t\t}\n\t}\n\n\treturn dependency, nil\n}\n\nfunc BinaryInstall(dest string, packagePath string) error {\n\tpackages, _ := utils.ReadDir(packagePath)\n\n\tfor _, dep := range packages {\n\t\tconfigFilePath := utils.Path(packagePath + \"/\" + dep.Name() + \"/gupm.json\")\n\t\tif utils.FileExists(configFilePath) {\n\t\t\tconfig := GetPackageConfig(configFilePath)\n\t\t\tif config[\"binaries\"] != nil {\n\t\t\t\tbins := config[\"binaries\"].(map[string]string)\n\t\t\t\tfor name, relPath := range bins {\n\t\t\t\t\tos.Symlink(utils.Path(\"/../gupm_modules/\"+\"/\"+dep.Name()+relPath), utils.Path(dest+\"/\"+name))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc SaveDependencyList(path string, depList []map[string]interface{}) error {\n\tconfig := GetPackageConfig(utils.Path(path + \"/gupm.json\"))\n\tif config[\"dependencies\"] == nil {\n\t\tconfig[\"dependencies\"] = make(map[string]interface{})\n\t}\n\tconfig[\"dependencies\"].(map[string]interface{})[\"default\"] = make(map[string]interface{})\n\n\tfor _, dep := range depList {\n\t\tkey := utils.BuildStringFromDependency(map[string]interface{}{\n\t\t\t\"provider\": dep[\"provider\"].(string),\n\t\t\t\"name\":     dep[\"name\"].(string),\n\t\t})\n\n\t\tconfig[\"dependencies\"].(map[string]interface{})[\"default\"].(map[string]interface{})[key] = dep[\"version\"].(string)\n\t}\n\n\tutils.WriteJsonFile(utils.Path(path+\"/\"+\"gupm.json\"), config)\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/defaultProvider/publish.go",
    "content": "package defaultProvider\n\nimport (\n\t\"os\"\n\n\t\"../ui\"\n\t\"../utils\"\n)\n\nfunc Publish(path string, namespace string) error {\n\tconfigPath := utils.Path(path + \"/gupm.json\")\n\tif utils.FileExists(configPath) {\n\t\tpackageConfig := new(utils.GupmEntryPoint)\n\t\terrConfig := utils.ReadJSON(configPath, &packageConfig)\n\t\tif errConfig != nil {\n\t\t\tui.Error(\"Can't read provider configuration\")\n\t\t\treturn errConfig\n\t\t}\n\n\t\tpname := packageConfig.Name\n\n\t\tif namespace != \"\" {\n\t\t\tpname = namespace + \"/\" + pname\n\t\t}\n\n\t\tppath := utils.Path(path + \"/\" + packageConfig.Publish.Dest)\n\t\trepoConfig := utils.GetOrCreateRepo(ppath)\n\t\tpackageList := repoConfig[\"packages\"].(map[string]interface{})\n\n\t\tif packageList[pname] != nil {\n\t\t\tif utils.Contains(packageList[pname], packageConfig.Version) {\n\t\t\t\tui.Error(\"Package \" + pname + \"@\" + packageConfig.Version + \" already published. Please bump the version number.\")\n\t\t\t\treturn nil\n\t\t\t} else {\n\t\t\t\tpackageList[pname] = append(utils.ArrString(packageList[pname]), packageConfig.Version)\n\t\t\t}\n\t\t} else {\n\t\t\tpackageList[pname] = make([]string, 0)\n\t\t\tpackageList[pname] = append(utils.ArrString(packageList[pname]), packageConfig.Version)\n\t\t}\n\n\t\tinstallPath := ppath + utils.Path(\"/\"+pname+\"/\"+packageConfig.Version)\n\t\tos.MkdirAll(installPath, os.ModePerm)\n\n\t\tsourcePaths := make([]string, 0)\n\t\tfor _, src := range packageConfig.Publish.Source {\n\t\t\tsourcePaths = append(sourcePaths, utils.Path(path+\"/\"+src))\n\t\t}\n\t\tarch, _ := utils.Tar(sourcePaths)\n\t\tarch.SaveAt(installPath + utils.Path(\"/\"+packageConfig.Name+\"-\"+packageConfig.Version+\".tgz\"))\n\n\t\trepoConfig[\"packages\"] = packageList\n\t\tutils.SaveRepo(ppath, repoConfig)\n\t} else {\n\t\tui.Error(\"Can't find provider configuration\")\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/distribution_gupm.json",
    "content": "{\n    \"name\": \"gupm\",\n    \"config\": {\n        \"default\": {\n            \"entrypoint\": \"gupm.json\",\n            \"installPath\": \"gupm_modules\",\n            \"defaultProvider\": \"gupm\",\n            \"osProviders\": {\n                \"linux\": \"linux\",\n                \"mac\": \"brew\",\n                \"windows\": \"chocolatey\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/gitHooks.go",
    "content": "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 BuildGitHooks(path string) {\n\tif utils.FileExists(\".git\") {\n\t\tif !utils.FileExists(\".git/hooks/pre-commit\") {\n\t\t\tutils.WriteFile(\".git/hooks/pre-commit\", \"g hook precommit\")\n\t\t}\n\t\tif !utils.FileExists(\".git/hooks/pre-push\") {\n\t\t\tutils.WriteFile(\".git/hooks/pre-push\", \"g hook prepush\")\n\t\t}\n\t}\n}\n\nfunc runhook(hook string) {\n\tcommandList := strings.Split(hook, \" \")\n\tstagedFiles, _ := utils.RunCommand(\"git\", []string{\"diff\", \"--cached\", \"--name-only\"})\n\tunPushedFiles := \"\"\n\tfyg, _ := utils.RunCommand(\"git\", []string{\"log\", \"--branches\", \"--not\", \"--remotes\", \"--name-status\", \"--oneline\"})\n\tunPushedFilesRaw := strings.Split(fyg, \"\\n\")\n\n\textractFileName := regexp.MustCompile(`^[AM]\\b(.*)`)\n\tfor _, v := range unPushedFilesRaw {\n\t\tif extracted := extractFileName.FindStringSubmatch(v); len(extracted) > 0 {\n\t\t\tunPushedFiles += strings.Trim(extracted[1], \" \t\") + \"\\n\"\n\t\t}\n\t}\n\tunPushedFiles = strings.Trim(unPushedFiles, \" \")\n\n\tfor i, v := range commandList {\n\t\tstagedFilesCheck := regexp.MustCompile(`^\\$StagedFiles(\\(([\\w\\/\\.\\*\\-\\_]+)?\\)?)?`)\n\t\ttryStagedFiles := stagedFilesCheck.FindStringSubmatch(v)\n\t\tunpushedFilesCheck := regexp.MustCompile(`^\\$UnpushedFiles(\\(([\\w\\/\\.\\*\\-\\_]+)?\\)?)?`)\n\t\ttryUnpushedFiles := unpushedFilesCheck.FindStringSubmatch(v)\n\n\t\tif len(tryStagedFiles) == 3 {\n\t\t\tif tryStagedFiles[2] == \"\" {\n\t\t\t\tcommandList[i] = strings.ReplaceAll(stagedFiles, \" \", \"\\\\ \")\n\t\t\t\tcommandList[i] = strings.ReplaceAll(commandList[i], \"\\n\", \" \")\n\t\t\t} else {\n\t\t\t\tcommandList[i] = \"\"\n\t\t\t\tstagedFilesList := strings.Split(stagedFiles, \"\\n\")\n\t\t\t\tfor _, s := range stagedFilesList {\n\t\t\t\t\tisIn, _ := doublestar.Match(tryStagedFiles[2], s)\n\t\t\t\t\tif isIn {\n\t\t\t\t\t\tcommandList[i] += strings.ReplaceAll(s, \" \", \"\\\\ \") + \" \"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcommandList[i] = strings.Trim(commandList[i], \" \")\n\t\t\t}\n\t\t}\n\n\t\tif len(tryUnpushedFiles) == 3 {\n\t\t\tif tryUnpushedFiles[2] == \"\" {\n\t\t\t\tcommandList[i] = strings.ReplaceAll(unPushedFiles, \" \", \"\\\\ \")\n\t\t\t\tcommandList[i] = strings.ReplaceAll(commandList[i], \"\\n\", \" \")\n\t\t\t} else {\n\t\t\t\tcommandList[i] = \"\"\n\t\t\t\tunpushedFilesList := strings.Split(unPushedFiles, \"\\n\")\n\t\t\t\tfor _, s := range unpushedFilesList {\n\t\t\t\t\tisIn, _ := doublestar.Match(tryUnpushedFiles[2], s)\n\t\t\t\t\tif isIn {\n\t\t\t\t\t\tcommandList[i] += strings.ReplaceAll(s, \" \", \"\\\\ \") + \" \"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcommandList[i] = strings.Trim(commandList[i], \" \")\n\t\t\t}\n\t\t}\n\t}\n\n\tcommandListConsolidated := strings.Trim(strings.Join(commandList, \" \"), \" \")\n\tcommandList = strings.Split(commandListConsolidated, \" \")\n\n\terr := utils.ExecCommand(commandList[0], append(commandList[1:]))\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\tos.Exit(1)\n\t}\n}\n\nfunc runhooklist(hooklist string) {\n\thooks := strings.Split(hooklist, \";\")\n\tfor _, hook := range hooks {\n\t\trunhook(strings.Trim(hook, \" \"))\n\t}\n}\n\nfunc runHooks(hooks interface{}) {\n\tch := make(chan int)\n\tlistHooks, isArray := hooks.([]interface{})\n\tif isArray {\n\t\tfor _, hook := range listHooks {\n\t\t\tgo func(hook string) {\n\t\t\t\trunhooklist(hook)\n\t\t\t\tch <- 0\n\t\t\t}(hook.(string))\n\t\t}\n\t\tfor range listHooks {\n\t\t\t<-ch\n\t\t}\n\t} else {\n\t\trunhooklist(hooks.(string))\n\t}\n}\n\nfunc RunHook(path string, hook string) {\n\tconfig, _ := utils.ReadGupmJson(\"gupm.json\")\n\n\tif hook == \"precommit\" && config.Git.Hooks.Precommit != nil {\n\t\trunHooks(config.Git.Hooks.Precommit)\n\t}\n\tif hook == \"prepush\" && config.Git.Hooks.Prepush != nil {\n\t\trunHooks(config.Git.Hooks.Prepush)\n\t}\n}\n"
  },
  {
    "path": "src/global.go",
    "content": "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(utils.HOMEDIR(\".\") + \"/.gupm/global\")\n\tbins := utils.RecursiveFileWalkDir(GLOBAL + \"/.bin\")\n\n\tfor _, bin := range bins {\n\t\tname := filepath.Base(bin)\n\t\tif !utils.FileExists(path + \"/\" + name) {\n\t\t\tos.Symlink(bin, path+\"/\"+name)\n\t\t}\n\t}\n}\n\nfunc GlobalAdd(rls []string) {\n\tui.Title(\"Installing global dependency...\")\n\tvar GLOBAL = utils.Path(utils.HOMEDIR(\".\") + \"/.gupm/global\")\n\n\tif !utils.FileExists(GLOBAL + utils.Path(\"/gupm.json\")) {\n\t\tos.MkdirAll(GLOBAL, os.ModePerm)\n\t\tutils.WriteFile(GLOBAL+utils.Path(\"/gupm.json\"), \"{}\")\n\t}\n\n\tui.Log(\"Installing...\")\n\tAddDependency(GLOBAL, rls)\n\tInstallProject(GLOBAL)\n\n\tui.Log(\"Add binaries...\")\n\tif utils.OSNAME() != \"windows\" {\n\t\tif utils.FileExists(\"/usr/local/bin/\") {\n\t\t\tinstallBins(\"/usr/local/bin/\")\n\t\t} else {\n\t\t\tinstallBins(\"/usr/bin/\")\n\t\t}\n\t} else {\n\t\tui.Error(\"Global Installation not supported on Windows yet. Please add .gupm/global/.bin to your PATH\")\n\t}\n}\n\nfunc GlobalDelete(rls []string) {\n\tvar GLOBAL = utils.Path(utils.HOMEDIR(\".\") + \"/.gupm/global\")\n\n\tif !utils.FileExists(GLOBAL + utils.Path(\"/gupm.json\")) {\n\t\tos.MkdirAll(GLOBAL, os.ModePerm)\n\t\tutils.WriteFile(GLOBAL+utils.Path(\"/gupm.json\"), \"{}\")\n\t}\n\n\tRemoveDependency(GLOBAL, rls)\n}\n"
  },
  {
    "path": "src/index.go",
    "content": "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 string\n\nfunc ScriptExists(path string) string {\n\tif utils.FileExists(path + \".gs\") {\n\t\treturn path + \".gs\"\n\t} else if utils.FileExists(path) && !utils.IsDirectory(path) {\n\t\treturn path\n\t} else {\n\t\treturn \"\"\n\t}\n}\n\nfunc executeFile(path string, args Arguments) {\n\t_, err := jsVm.Run(path, args.AsJson())\n\tif err != nil {\n\t\tui.Error(\"File execution failed\")\n\t\tui.Error(err)\n\t\tExit(1)\n\t}\n}\n\nfunc binFile(name string, args []string) {\n\tpath := utils.Path(\"./.bin/\" + name)\n\trealPath, _ := filepath.EvalSymlinks(path)\n\terr := utils.ExecCommand(realPath, args)\n\tif err != nil {\n\t\tui.Error(err)\n\t\tExit(1)\n\t}\n}\n\nfunc Exit(code int) {\n\tui.Stop()\n\tos.Exit(code)\n}\n\nfunc runAlias(alias string) {\n\tcommands := strings.Split(alias, \";\")\n\tfor _, command := range commands {\n\t\tcommandList := strings.Split(command, \" \")\n\t\terr := utils.ExecCommand(commandList[0], append(commandList[1:], os.Args[2:]...))\n\t\tif err != nil {\n\t\t\tui.Error(err)\n\t\t}\n\t}\n}\n\nfunc runAliasList(aliasList string) {\n\taliases := strings.Split(aliasList, \";\")\n\tfor _, alias := range aliases {\n\t\trunhook(strings.Trim(alias, \" \"))\n\t}\n}\n\nfunc main() {\n\tbinFolder := make(map[string]bool)\n\n\tif utils.FileExists(\".bin\") {\n\t\tfiles, _ := utils.ReadDir(\".bin\")\n\t\tfor _, file := range files {\n\t\t\tbinFolder[file.Name()] = true\n\t\t}\n\t}\n\n\tc, args := GetArgs(os.Args[1:])\n\n\tif utils.FileExists(\".gupm_rc.gs\") {\n\t\texecuteFile(\".gupm_rc.gs\", args)\n\t}\n\n\taliases := map[string]interface{}{}\n\tif utils.FileExists(\"gupm.json\") {\n\t\tpackageConfig, errConfig := utils.ReadGupmJson(\"gupm.json\")\n\t\tif errConfig != nil {\n\t\t\tui.Error(errConfig)\n\t\t} else {\n\t\t\taliases = packageConfig.Cli.Aliases\n\t\t}\n\t}\n\n\tscript := ScriptExists(c)\n\tif didExec, err := ExecCli(c, args); didExec {\n\t\tif err != nil {\n\t\t\tui.Error(err)\n\t\t\tExit(1)\n\t\t}\n\t\tif script != \"\" {\n\t\t\texecuteFile(script, args)\n\t\t}\n\t} else if c == \"env\" || c == \"e\" {\n\t\ttoProcess := os.Args[2:]\n\t\tre := regexp.MustCompile(`([\\w\\-\\_]+)=([\\w\\-\\_]+)`)\n\t\tisEnv := re.FindAllStringSubmatch(toProcess[0], -1)\n\t\tfor isEnv != nil {\n\t\t\tname := isEnv[0][1]\n\t\t\tvalue := isEnv[0][2]\n\t\t\tos.Setenv(name, value)\n\t\t\ttoProcess = toProcess[1:]\n\t\t\tisEnv = re.FindAllStringSubmatch(toProcess[0], -1)\n\t\t}\n\t\tutils.ExecCommand(toProcess[0], toProcess[1:])\n\t} else if aliases[c] != nil {\n\t\tch := make(chan int)\n\t\tlistAlias, isArray := aliases[c].([]interface{})\n\t\tif isArray {\n\t\t\tfor _, aliasLine := range listAlias {\n\t\t\t\tgo func(aliasLine string) {\n\t\t\t\t\trunAliasList(aliasLine)\n\t\t\t\t\tch <- 0\n\t\t\t\t}(aliasLine.(string))\n\t\t\t}\n\t\t\tfor range listAlias {\n\t\t\t\t<-ch\n\t\t\t}\n\t\t} else {\n\t\t\trunAliasList(aliases[c].(string))\n\t\t}\n\t} else if binFolder[c] == true {\n\t\tbinFile(c, os.Args[2:])\n\t} else if script != \"\" {\n\t\texecuteFile(script, args)\n\t} else if c == \"\" {\n\t\tfmt.Println(\"Welcome to GuPM version 1.0.0 \\ntry 'g help' for a list of commands. Try 'g filename' to execute a file.\")\n\t} else {\n\t\tfmt.Println(\"Command not found. Try 'g help' or check filename.\")\n\t\tExit(1)\n\t}\n\n\tui.Stop()\n}\n"
  },
  {
    "path": "src/installProject.go",
    "content": "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-homedir\"\n)\n\nvar cacheExpanded = make(map[string]map[string]interface{})\nvar lock = sync.RWMutex{}\nvar lockList = sync.RWMutex{}\n\nfunc expandDepList(depList []map[string]interface{}) []map[string]interface{} {\n\tchannel := make(chan int)\n\n\tfor index, dep := range depList {\n\t\tgo (func(channel chan int, index int, dep map[string]interface{}) {\n\t\t\tif dep[\"expanded\"] != true {\n\t\t\t\tnewDep := make(map[string]interface{})\n\t\t\t\tfor key, value := range dep {\n\t\t\t\t\tnewDep[key] = value\n\t\t\t\t}\n\t\t\t\tnewDep, errExpand := provider.ResolveDependencyLocation(newDep)\n\t\t\t\tif newDep == nil {\n\t\t\t\t\tui.Error(\"Provider \" + dep[\"provider\"].(string) + \" didnt resolve \" + dep[\"name\"].(string) + \"@\" + dep[\"version\"].(string))\n\t\t\t\t\tui.Error(errExpand)\n\t\t\t\t\tchannel <- 0\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\thdir, errH := homedir.Dir()\n\t\t\t\tif errH != nil {\n\t\t\t\t\tui.Error(errH)\n\t\t\t\t\thdir = \".\"\n\t\t\t\t}\n\t\t\t\t_, ok := newDep[\"url\"].(string)\n\t\t\t\tif !ok || newDep[\"url\"].(string) == \"\" {\n\t\t\t\t\tui.Error(\"Cannot resolve : \" + newDep[\"name\"].(string))\n\t\t\t\t\tchannel <- 1\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tnewDep[\"path\"] = hdir + \"/.gupm/cache/\" + newDep[\"provider\"].(string) + \"/\" + newDep[\"name\"].(string) + \"/\" + newDep[\"version\"].(string)\n\n\t\t\t\tif !utils.FileExists(newDep[\"path\"].(string)) || !utils.FileExists(newDep[\"path\"].(string)+\"/.gupm_locked\") {\n\t\t\t\t\tgetRes, errorGD := provider.GetDependency(\n\t\t\t\t\t\tnewDep[\"provider\"].(string),\n\t\t\t\t\t\tnewDep[\"name\"].(string),\n\t\t\t\t\t\tnewDep[\"version\"].(string),\n\t\t\t\t\t\tnewDep[\"url\"].(string),\n\t\t\t\t\t\tnewDep[\"path\"].(string),\n\t\t\t\t\t)\n\t\t\t\t\tif errorGD != nil {\n\t\t\t\t\t\tui.Error(errorGD)\n\t\t\t\t\t}\n\t\t\t\t\tnewPath, errorPGD := provider.PostGetDependency(\n\t\t\t\t\t\tnewDep[\"provider\"].(string),\n\t\t\t\t\t\tnewDep[\"name\"].(string),\n\t\t\t\t\t\tnewDep[\"version\"].(string),\n\t\t\t\t\t\tnewDep[\"url\"].(string),\n\t\t\t\t\t\tnewDep[\"path\"].(string),\n\t\t\t\t\t\tgetRes,\n\t\t\t\t\t)\n\n\t\t\t\t\tnewDep[\"path\"] = newPath\n\n\t\t\t\t\tif errorPGD != nil {\n\t\t\t\t\t\tui.Error(errorPGD)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlock.Lock()\n\t\t\t\tif newDep[\"expanded\"] != true {\n\t\t\t\t\tif cacheExpanded[newDep[\"url\"].(string)][\"expanded\"] != true {\n\t\t\t\t\t\tnewDep, errExpand = provider.ExpandDependency(newDep)\n\t\t\t\t\t\tif errExpand != nil || newDep == nil || len(newDep) == 0 {\n\t\t\t\t\t\t\tui.Error(\"Provider \" + dep[\"provider\"].(string) + \" didnt expand \" + dep[\"name\"].(string) + \"@\" + dep[\"version\"].(string))\n\t\t\t\t\t\t\tui.Error(errExpand)\n\t\t\t\t\t\t\tchannel <- 0\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tnewDep[\"expanded\"] = true\n\t\t\t\t\t\tcacheExpanded[newDep[\"url\"].(string)] = newDep\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnewDep = cacheExpanded[newDep[\"url\"].(string)]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tui.Log(\"Get dependency \" + newDep[\"name\"].(string))\n\t\t\t\tlock.Unlock()\n\n\t\t\t\tlockList.Lock()\n\n\t\t\t\tdepList[index] = newDep\n\t\t\t\tnextDepList, ok := depList[index][\"dependencies\"].([]map[string]interface{})\n\t\t\t\tlockList.Unlock()\n\n\t\t\t\tif ok {\n\t\t\t\t\tres := expandDepList(nextDepList)\n\t\t\t\t\tlockList.Lock()\n\t\t\t\t\tdepList[index][\"dependencies\"] = res\n\t\t\t\t\tlockList.Unlock()\n\t\t\t\t}\n\t\t\t}\n\t\t\tchannel <- 1\n\t\t})(channel, index, dep)\n\t}\n\n\tfor range depList {\n\t\ti := <-channel\n\t\tif i == 0 {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\treturn depList\n}\n\nfunc installDep(path string, depList []map[string]interface{}) map[string]string {\n\tinstallPaths := make(map[string]string)\n\tinstallPathsLock := sync.RWMutex{}\n\n\tvar channel = make(chan int)\n\tfor index, dep := range depList {\n\t\tgo (func(channel chan int, index int, dep map[string]interface{}) {\n\t\t\tdepProviderConfig, err := provider.GetProviderConfig(dep[\"provider\"].(string))\n\t\t\tdestination := utils.Path(path + \"/\" + depProviderConfig.Config.Default.InstallPath)\n\n\t\t\tif dep[\"path\"] != nil {\n\t\t\t\tpackageConfig, errC := utils.ReadGupmJson(utils.Path(dep[\"path\"].(string) + \"/gupm.json\"))\n\n\t\t\t\tif errC == nil && packageConfig != nil && packageConfig.WrapInstallFolder != \"\" {\n\t\t\t\t\tdestination += utils.Path(\"/\" + packageConfig.WrapInstallFolder)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tui.Error(err)\n\t\t\tui.Log(\"Installing \" + path)\n\t\t\tprovider.InstallDependency(destination, dep)\n\n\t\t\t// if path == \".\" {\n\t\t\tinstallPathsLock.Lock()\n\t\t\tinstallPaths[dep[\"provider\"].(string)] = utils.Path(path + \"/\" + depProviderConfig.Config.Default.InstallPath)\n\t\t\tinstallPathsLock.Unlock()\n\t\t\t// }\n\n\t\t\tnextDepList, ok := depList[index][\"dependencies\"].([]map[string]interface{})\n\n\t\t\tif ok {\n\t\t\t\tinstallDep(utils.Path(destination+\"/\"+depList[index][\"name\"].(string)), nextDepList)\n\t\t\t}\n\t\t\tchannel <- 1\n\t\t})(channel, index, dep)\n\t}\n\tfor range depList {\n\t\t<-channel\n\t}\n\treturn installPaths\n}\n\nvar providerConfig *utils.GupmEntryPoint\n\nfunc InstallProject(path string) error {\n\tstart := time.Now()\n\n\tui.Title(\"Installing project...\")\n\n\tvar err error\n\tvar packageConfig utils.Json\n\tvar depList []map[string]interface{}\n\n\terr = provider.InitProvider(Provider)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tproviderConfig, err = provider.GetProviderConfig(Provider)\n\tui.Error(err)\n\tpackageConfig, _ = provider.GetPackageConfig(path)\n\tpackageConfig, _ = provider.PostGetPackageConfig(packageConfig)\n\n\tdepList, err = provider.GetDependencyList(packageConfig)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif depList == nil {\n\t\tui.Log(\"No dependencies found.\")\n\t\treturn nil\n\t}\n\n\tui.Title(\"Expand dependency list...\")\n\tdepList = expandDepList(depList)\n\tif depList == nil {\n\t\treturn errors.New(\"Failed to expand dependancy list\")\n\t}\n\n\tui.Title(\"Build dependency list...\")\n\tdepList = provider.BuildDependencyTree(depList)\n\tif depList == nil {\n\t\treturn errors.New(\"Failed to build dependancy list\")\n\t}\n\n\tui.Title(\"Install dependencies...\")\n\tinstallPaths := installDep(path, depList)\n\n\tui.Title(\"Install Binaries...\")\n\terr = provider.BinaryInstall(path, installPaths)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tui.Title(\"Installation done ❤️\")\n\n\ttimeElapsed := fmt.Sprintf(\"%f\", time.Since(start).Seconds())\n\tui.Log(timeElapsed + \"s elapsed\\n\")\n\treturn nil\n}\n"
  },
  {
    "path": "src/jsVm/jsVm.go",
    "content": "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\"../utils\"\n\t\"github.com/Masterminds/semver\"\n\t\"github.com/robertkrimen/otto\"\n)\n\nvar lock = sync.RWMutex{}\nvar scriptCache = make(map[string]string)\n\nfunc Run(path string, input utils.Json) (otto.Value, error) {\n\tvar err error\n\tvar ret otto.Value\n\n\tlock.Lock()\n\tif scriptCache[path] == \"\" {\n\t\tfile, err := ioutil.ReadFile(path)\n\t\tif err != nil {\n\t\t\treturn otto.UndefinedValue(), err\n\t\t}\n\t\tscriptCache[path] = string(file)\n\t}\n\tscript := scriptCache[path]\n\tlock.Unlock()\n\n\tvm := otto.New()\n\tvm.Interrupt = make(chan func(), 1)\n\tSetup(vm)\n\tvm.Set(\"_DIRNAME\", filepath.Dir(path))\n\n\tfor varName, varValue := range input /*.AsObject()*/ {\n\t\tvm.Set(varName, varValue)\n\t}\n\n\tret, err = vm.Run(script)\n\n\tif err != nil {\n\t\tui.Error(err)\n\t\treturn otto.UndefinedValue(), errors.New(\"Error occured while executing the GS code\")\n\t}\n\n\treturn ret, nil\n}\n\nfunc Setup(vm *otto.Otto) {\n\tvm.Set(\"httpGetJson\", func(call otto.FunctionCall) otto.Value {\n\t\turl, _ := call.Argument(0).ToString()\n\t\tres := utils.HttpGet(url)\n\t\tresult, _ := vm.ToValue(utils.StringToJSON(string(res)))\n\t\treturn result\n\t})\n\n\tvm.Set(\"httpGet\", func(call otto.FunctionCall) otto.Value {\n\t\turl, _ := call.Argument(0).ToString()\n\t\tres := utils.HttpGet(url)\n\t\tresult, _ := vm.ToValue(string(res))\n\t\treturn result\n\t})\n\n\tvm.Set(\"dir\", func(call otto.FunctionCall) otto.Value {\n\t\tglob, _ := call.Argument(0).ToString()\n\t\tres, _ := utils.Dir(glob)\n\t\tresult, _ := vm.ToValue(res)\n\t\treturn result\n\t})\n\n\tvm.Set(\"osSleep\", func(call otto.FunctionCall) otto.Value {\n\t\ttimeMs, _ := call.Argument(0).ToInteger()\n\t\ttime.Sleep(time.Duration(timeMs) * time.Millisecond)\n\t\tresult, _ := vm.ToValue(true)\n\t\treturn result\n\t})\n\n\tvm.Set(\"readJsonFile\", func(call otto.FunctionCall) otto.Value {\n\t\tpath, _ := call.Argument(0).ToString()\n\t\tpath = utils.Path(path)\n\t\tb, err := ioutil.ReadFile(path)\n\t\tif err != nil {\n\t\t\tui.Error(err)\n\t\t}\n\t\tresult, _ := vm.ToValue(utils.StringToJSON(string(b)))\n\t\treturn result\n\t})\n\n\tvm.Set(\"readFile\", func(call otto.FunctionCall) otto.Value {\n\t\tpath, _ := call.Argument(0).ToString()\n\t\tpath = utils.Path(path)\n\t\tb, err := ioutil.ReadFile(path)\n\t\tif err != nil {\n\t\t\tui.Error(err)\n\t\t}\n\t\tresult, _ := vm.ToValue(string(b))\n\t\treturn result\n\t})\n\n\tvm.Set(\"removeFiles\", func(call otto.FunctionCall) otto.Value {\n\t\tfiles, _ := call.Argument(0).Export()\n\t\t_, isString := files.(string)\n\t\tif isString {\n\t\t\tfiles = []string{files.(string)}\n\t\t}\n\t\tutils.RemoveFiles(files.([]string))\n\t\tresult, _ := vm.ToValue(true)\n\t\treturn result\n\t})\n\n\tvm.Set(\"copyFiles\", func(call otto.FunctionCall) otto.Value {\n\t\tfiles, _ := call.Argument(0).Export()\n\t\t_, isString := files.(string)\n\t\tif isString {\n\t\t\tfiles = []string{files.(string)}\n\t\t}\n\t\tpath, _ := call.Argument(1).ToString()\n\t\tpath = utils.Path(path)\n\t\tutils.CopyFiles(files.([]string), path)\n\t\tresult, _ := vm.ToValue(true)\n\t\treturn result\n\t})\n\n\tvm.Set(\"pwd\", func(call otto.FunctionCall) otto.Value {\n\t\tdir, _ := os.Getwd()\n\t\tresult, _ := vm.ToValue(dir)\n\t\treturn result\n\t})\n\n\tvm.Set(\"env\", func(call otto.FunctionCall) otto.Value {\n\t\tname, _ := call.Argument(0).ToString()\n\t\tvalue, _ := call.Argument(1).ToString()\n\n\t\tif value == \"undefined\" {\n\t\t\tresult, _ := vm.ToValue(os.Getenv(name))\n\t\t\treturn result\n\t\t} else {\n\t\t\tos.Setenv(name, value)\n\t\t\tres, _ := vm.ToValue(true)\n\t\t\treturn res\n\t\t}\n\t})\n\n\tvm.Set(\"exec\", func(call otto.FunctionCall) otto.Value {\n\t\texec, _ := call.Argument(0).ToString()\n\t\targs, _ := call.Argument(1).Export()\n\t\t_, ok := args.([]string)\n\t\tif !ok {\n\t\t\targs = make([]string, 0)\n\t\t}\n\n\t\terr := utils.ExecCommand(exec, args.([]string))\n\n\t\tresult, _ := vm.ToValue(err)\n\t\treturn result\n\t})\n\n\tvm.Set(\"run\", func(call otto.FunctionCall) otto.Value {\n\t\texec, _ := call.Argument(0).ToString()\n\t\targs, _ := call.Argument(1).Export()\n\t\t_, ok := args.([]string)\n\t\tif !ok {\n\t\t\targs = make([]string, 0)\n\t\t}\n\n\t\tres, err := utils.RunCommand(exec, args.([]string))\n\n\t\tif err != nil {\n\t\t\tui.Error(err)\n\t\t\tresult, _ := vm.ToValue(false)\n\t\t\treturn result\n\t\t}\n\n\t\tif res != \"\" {\n\t\t\tres = res[:len(res)-1]\n\t\t}\n\n\t\tresult, _ := vm.ToValue(res)\n\t\treturn result\n\t})\n\n\tvm.Set(\"exit\", func(call otto.FunctionCall) otto.Value {\n\t\tcode, _ := call.Argument(0).ToInteger()\n\t\tos.Exit(int(code))\n\t\tresult, _ := vm.ToValue(true)\n\t\treturn result\n\t})\n\n\tvm.Set(\"writeJsonFile\", func(call otto.FunctionCall) otto.Value {\n\t\tpath, _ := call.Argument(0).ToString()\n\t\tpath = utils.Path(path)\n\t\ttoExport, _ := call.Argument(1).Export()\n\t\tfile := JsonExport(toExport).(map[string]interface{})\n\n\t\tutils.WriteJsonFile(path, file)\n\n\t\tresult, _ := vm.ToValue(true)\n\t\treturn result\n\t})\n\n\tvm.Set(\"writeFile\", func(call otto.FunctionCall) otto.Value {\n\t\tpath, _ := call.Argument(0).ToString()\n\t\tpath = utils.Path(path)\n\t\ttoExport, _ := call.Argument(1).ToString()\n\t\terr := ioutil.WriteFile(path, []byte(toExport), os.ModePerm)\n\t\tif err != nil {\n\t\t\tui.Error(err)\n\t\t}\n\t\tresult, _ := vm.ToValue(true)\n\t\treturn result\n\t})\n\n\tvm.Set(\"_OSNAME\", utils.OSNAME())\n\n\tvm.Set(\"mkdir\", func(call otto.FunctionCall) otto.Value {\n\t\tpath, _ := call.Argument(0).ToString()\n\t\tpath = utils.Path(path)\n\t\tos.MkdirAll(path, os.ModePerm)\n\t\tresult, _ := vm.ToValue(true)\n\t\treturn result\n\t})\n\n\tvm.Set(\"saveLockDep\", func(call otto.FunctionCall) otto.Value {\n\t\tpath, _ := call.Argument(0).ToString()\n\t\tpath = utils.Path(path)\n\t\tutils.SaveLockDep(path)\n\t\tresult, _ := vm.ToValue(true)\n\t\treturn result\n\t})\n\n\tvm.Set(\"fileExists\", func(call otto.FunctionCall) otto.Value {\n\t\tpath, _ := call.Argument(0).ToString()\n\t\tpath = utils.Path(path)\n\t\tres := utils.FileExists(path)\n\t\tresult, _ := vm.ToValue(res)\n\t\treturn result\n\t})\n\n\tvm.Set(\"waitForInput\", func(call otto.FunctionCall) otto.Value {\n\t\tmsg, _ := call.Argument(0).ToString()\n\t\tres := ui.WaitForInput(msg)\n\t\tresult, _ := vm.ToValue(res)\n\t\treturn result\n\t})\n\n\tvm.Set(\"waitForMenu\", func(call otto.FunctionCall) otto.Value {\n\t\tmsg, _ := call.Argument(0).Export()\n\t\tres := ui.WaitForMenu(msg.([]string))\n\t\tresult, _ := vm.ToValue(res)\n\t\treturn result\n\t})\n\n\tvm.Set(\"waitForKey\", func(call otto.FunctionCall) otto.Value {\n\t\tui.WaitForKey()\n\t\tresult, _ := vm.ToValue(true)\n\t\treturn result\n\t})\n\n\tvm.Set(\"tar\", func(call otto.FunctionCall) otto.Value {\n\t\tfiles, _ := call.Argument(0).Export()\n\t\t_, isString := files.(string)\n\t\tif isString {\n\t\t\tfiles = []string{files.(string)}\n\t\t}\n\t\tres, err := utils.Tar(files.([]string))\n\t\tif err != nil {\n\t\t\tui.Error(err)\n\t\t}\n\t\tb, _ := json.Marshal(res)\n\t\tresult, _ := vm.ToValue(utils.StringToJSON(string(b)))\n\t\treturn result\n\t})\n\n\tvm.Set(\"readDir\", func(call otto.FunctionCall) otto.Value {\n\t\tpath, _ := call.Argument(0).ToString()\n\t\tpath = utils.Path(path)\n\t\tvar filenames = make([]string, 0)\n\t\tfiles, _ := utils.ReadDir(path)\n\t\tfor _, file := range files {\n\t\t\tfilenames = append(filenames, file.Name())\n\t\t}\n\t\tresult, _ := vm.ToValue(filenames)\n\t\treturn result\n\t})\n\n\tvm.Set(\"createSymLink\", func(call otto.FunctionCall) otto.Value {\n\t\tfrom, _ := call.Argument(0).ToString()\n\t\tfrom = utils.Path(from)\n\t\tto, _ := call.Argument(1).ToString()\n\t\tto = utils.Path(to)\n\t\terr := os.Symlink(from, to)\n\t\tif err != nil {\n\t\t\tui.Error(err)\n\t\t}\n\t\tresult, _ := vm.ToValue(true)\n\t\treturn result\n\t})\n\n\tvm.Set(\"untar\", func(call otto.FunctionCall) otto.Value {\n\t\tvar res utils.FileStructure\n\t\tfile, _ := call.Argument(0).ToString()\n\t\tres, _ = utils.Untar(file)\n\t\tb, _ := json.Marshal(res)\n\t\tresult, _ := vm.ToValue(utils.StringToJSON(string(b)))\n\t\treturn result\n\t})\n\n\tvm.Set(\"unzip\", func(call otto.FunctionCall) otto.Value {\n\t\tvar res utils.FileStructure\n\t\tfile, _ := call.Argument(0).ToString()\n\t\tres, _ = utils.Unzip(file)\n\t\tb, _ := json.Marshal(res)\n\t\tresult, _ := vm.ToValue(utils.StringToJSON(string(b)))\n\t\treturn result\n\t})\n\n\tvm.Set(\"saveFileAt\", func(call otto.FunctionCall) otto.Value {\n\t\tvar fs utils.FileStructure\n\t\tfile, _ := call.Argument(0).Export()\n\t\tpath, _ := call.Argument(1).ToString()\n\t\tpath = utils.Path(path)\n\t\tbytes, _ := json.Marshal(file)\n\t\tjson.Unmarshal(bytes, &fs)\n\t\tfs.SaveAt(path)\n\t\tresult, _ := vm.ToValue(path)\n\t\treturn result\n\t})\n\n\tvm.Set(\"semverInRange\", func(call otto.FunctionCall) otto.Value {\n\t\trangeStr, _ := call.Argument(0).ToString()\n\t\tversion, _ := call.Argument(1).ToString()\n\t\trangeVer, _ := semver.NewConstraint(rangeStr)\n\t\tsver, _ := semver.NewVersion(version)\n\t\tvalue := rangeVer.Check(sver)\n\t\tresult, _ := vm.ToValue(value)\n\t\treturn result\n\t})\n\n\tvm.Set(\"semverLatestInRange\", func(call otto.FunctionCall) otto.Value {\n\t\trangeStr, _ := call.Argument(0).ToString()\n\t\tversionListUntyped, _ := call.Argument(1).Export()\n\t\tversionList := utils.ArrString(versionListUntyped)\n\t\tvar version string\n\t\tvar versionSem *semver.Version\n\t\trangeVer, _ := semver.NewConstraint(rangeStr)\n\n\t\tfor _, verCandUnk := range versionList {\n\t\t\tverCand := verCandUnk\n\t\t\tsver, err := semver.NewVersion(verCand)\n\t\t\tif err != nil {\n\t\t\t\tui.Error(err)\n\t\t\t}\n\n\t\t\tif rangeVer.Check(sver) && (versionSem == nil || sver.GreaterThan(versionSem)) {\n\t\t\t\tversion = verCand\n\t\t\t\tversionSem = sver\n\t\t\t}\n\t\t}\n\n\t\tif version != \"\" {\n\t\t\tresult, _ := vm.ToValue(version)\n\t\t\treturn result\n\t\t} else {\n\t\t\treturn otto.UndefinedValue()\n\t\t}\n\t})\n}\n\nfunc JsonExport(input interface{}) interface{} {\n\tasMap, isMap := input.(map[string]interface{})\n\tasSlice, isSlice := input.([]interface{})\n\tif isMap {\n\t\tfor index, value := range asMap {\n\t\t\tasValue, ok := value.(otto.Value)\n\t\t\tif ok {\n\t\t\t\texported, _ := asValue.Export()\n\t\t\t\tasMap[index] = JsonExport(exported)\n\t\t\t}\n\t\t}\n\t\treturn asMap\n\t} else if isSlice {\n\t\tfor index, value := range asSlice {\n\t\t\tasValue, ok := value.(otto.Value)\n\t\t\tif ok {\n\t\t\t\texported, _ := asValue.Export()\n\t\t\t\tasSlice[index] = JsonExport(exported)\n\t\t\t}\n\t\t}\n\t\treturn asSlice\n\t} else {\n\t\treturn input\n\t}\n}\n"
  },
  {
    "path": "src/plugins.go",
    "content": "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(path string) {\n\tconfigPath := utils.Path(path + \"/gupm.json\")\n\tif utils.FileExists(configPath) {\n\t\tpackageConfig := new(utils.GupmEntryPoint)\n\t\terrConfig := utils.ReadJSON(configPath, &packageConfig)\n\t\tif errConfig != nil {\n\t\t\tui.Error(\"Can't read provider configuration\")\n\t\t\tui.Error(errConfig)\n\t\t\treturn\n\t\t}\n\n\t\tpluginFolder := utils.HOMEDIR(\".\") + utils.Path(\"/.gupm/plugins/\")\n\t\tos.MkdirAll(pluginFolder, os.ModePerm)\n\t\terr := os.Symlink(utils.AbsPath(path), pluginFolder+packageConfig.Name)\n\t\tif err != nil {\n\t\t\tui.Error(err)\n\t\t}\n\t} else {\n\t\tui.Error(\"Can't find provider configuration\")\n\t}\n}\n\nfunc PluginInstall(path string, plugins []string) error {\n\tui.Title(\"Install plugin...\")\n\tpluginFolder := utils.HOMEDIR(\".\") + utils.Path(\"/.gupm/plugins/\")\n\n\tfor _, rls := range plugins {\n\t\tui.Log(rls)\n\t\tnewDep, err := provider.ResolveDependencyLocation(utils.BuildDependencyFromString(\"https\", rls))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tpluginName := filepath.Base(newDep[\"name\"].(string))\n\t\tif len(strings.Split(pluginName, \":\")) > 1 {\n\t\t\tpluginName = strings.Split(pluginName, \":\")[1]\n\t\t}\n\t\tif len(strings.Split(pluginName, \"/\")) > 1 {\n\t\t\tpluginName = strings.Split(pluginName, \"/\")[1]\n\t\t}\n\n\t\tnewDep[\"path\"] = pluginFolder + utils.Path(pluginName)\n\n\t\tgetRes, errorGD := provider.GetDependency(\n\t\t\tnewDep[\"provider\"].(string),\n\t\t\tnewDep[\"name\"].(string),\n\t\t\tnewDep[\"version\"].(string),\n\t\t\tnewDep[\"url\"].(string),\n\t\t\tnewDep[\"path\"].(string),\n\t\t)\n\t\tif errorGD != nil {\n\t\t\treturn errorGD\n\t\t}\n\n\t\t_, errorPGD := provider.PostGetDependency(\n\t\t\tnewDep[\"provider\"].(string),\n\t\t\tnewDep[\"name\"].(string),\n\t\t\tnewDep[\"version\"].(string),\n\t\t\tnewDep[\"url\"].(string),\n\t\t\tnewDep[\"path\"].(string),\n\t\t\tgetRes,\n\t\t)\n\t\tif errorPGD != nil {\n\t\t\treturn errorPGD\n\t\t}\n\n\t\tInstallProject(newDep[\"path\"].(string))\n\n\t\tui.Title(\"Installation done ❤️\")\n\t}\n\treturn nil\n}\n\nfunc PluginDelete(path string, plugins []string) {\n\tfolders := make([]string, 0)\n\tpluginFolder := utils.HOMEDIR(\".\") + utils.Path(\"/.gupm/plugins/\")\n\n\tfor _, str := range plugins {\n\t\tfolders = append(folders, pluginFolder+str)\n\t}\n\n\tutils.RemoveFiles(folders)\n\tfmt.Println(\"Done deleting.\")\n}\n\nfunc PluginCreate(path string) {\n\tfmt.Println(\"Welcome to the plugin creation assistant\")\n\tname := \"provider-\" + ui.WaitForInput(\"What is the name of the plugin? provider-\")\n\tdescription := ui.WaitForInput(\"Enter a description: \")\n\tauthor := ui.WaitForInput(\"Enter the author: \")\n\tlicence := ui.WaitForInput(\"Enter the licence (ISC): \")\n\tppath := utils.Path(path + \"/\" + name)\n\n\tos.MkdirAll(ppath, os.ModePerm)\n\tos.MkdirAll(ppath+utils.Path(\"/docs/repo\"), os.ModePerm)\n\n\tutils.WriteFile(ppath+utils.Path(\"/gupm.json\"), `{\n\t\"name\": \"`+name+`\",\n\t\"version\": \"0.0.1\",\n\t\"description\": \"`+description+`\",\n\t\"author\": \"`+author+`\",\n\t\"licence\": \"`+licence+`\",\n    \"publish\": {\n        \"source\": [\".\"],\n        \"dest\": \"../docs/repo\"\n    },\n    \"config\": {\n        \"default\": {\n            \"entrypoint\": \"gupm.json\",\n            \"installPath\": \"gupm_modules\"\n        }\n    }\n}`)\n\n\tfmt.Println(\"creation done.\")\n}\n"
  },
  {
    "path": "src/provider/bootstrap.go",
    "content": "package provider\n\nimport (\n\t\"../defaultProvider\"\n\t\"../jsVm\"\n\t\"../utils\"\n\t\"errors\"\n\t// \"fmt\"\n)\n\nfunc Bootstrap(path string) error {\n\tif Provider != \"gupm\" {\n\t\tvar file = utils.FileExists(utils.Path(ProviderPath + \"/bootstrap.gs\"))\n\t\tif file {\n\t\t\tinput := make(map[string]interface{})\n\t\t\tinput[\"Path\"] = path\n\t\t\t_, err := jsVm.Run(utils.Path(ProviderPath+\"/bootstrap.gs\"), input)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t} else {\n\t\t\treturn errors.New(\"Provider doesn't have any bootstrap function. Please use 'g bootstrap' to use the default bootstrap.\")\n\t\t}\n\t} else {\n\t\tdefaultProvider.Bootstrap(path)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "src/provider/dependencyTree.go",
    "content": "package provider\n\nfunc eliminateRedundancy(tree []map[string]interface{}, path map[string]bool) []map[string]interface{} {\n\tvar cleanTree = make([]map[string]interface{}, 0)\n\tfor index, dep := range tree {\n\t\tif dep[\"name\"] != nil {\n\t\t\t_ = index\n\t\t\tdepKey := dep[\"name\"].(string) + \"@\" + dep[\"version\"].(string)\n\t\t\tif path[depKey] != true {\n\t\t\t\tcleanTree = append(cleanTree, dep)\n\t\t\t}\n\t\t}\n\t}\n\n\tfor index, dep := range cleanTree {\n\t\tif dep[\"name\"] != nil {\n\t\t\tnextDepList, ok := dep[\"dependencies\"].([]map[string]interface{})\n\n\t\t\tif ok {\n\t\t\t\tdepKey := dep[\"name\"].(string) + \"@\" + dep[\"version\"].(string)\n\t\t\t\tnewPath := make(map[string]bool)\n\t\t\t\tfor key, value := range path {\n\t\t\t\t\tnewPath[key] = value\n\t\t\t\t}\n\t\t\t\tnewPath[depKey] = true\n\t\t\t\tnewSubTree := eliminateRedundancy(nextDepList, newPath)\n\t\t\t\tcleanTree[index][\"dependencies\"] = newSubTree\n\t\t\t}\n\t\t}\n\t}\n\treturn cleanTree\n}\n\nfunc flattenDependencyTree(tree []map[string]interface{}, subTree []map[string]interface{}) ([]map[string]interface{}, []map[string]interface{}) {\n\tvar cleanTree = make([]map[string]interface{}, 0)\n\n\tfor index, dep := range subTree {\n\t\tvar rootDeps = make(map[string]string)\n\n\t\tfor _, dep := range tree {\n\t\t\trootDeps[dep[\"name\"].(string)] = dep[\"version\"].(string)\n\t\t}\n\n\t\tif rootDeps[dep[\"name\"].(string)] == \"\" {\n\t\t\ttree = append(tree, dep)\n\n\t\t\tnextDepList, ok := dep[\"dependencies\"].([]map[string]interface{})\n\n\t\t\tif ok {\n\t\t\t\tnewTree, newSubTree := flattenDependencyTree(tree, nextDepList)\n\t\t\t\ttree = newTree\n\t\t\t\tsubTree[index][\"dependencies\"] = newSubTree\n\t\t\t}\n\t\t} else if rootDeps[dep[\"name\"].(string)] != dep[\"version\"].(string) {\n\t\t\tnextDepList, ok := dep[\"dependencies\"].([]map[string]interface{})\n\n\t\t\tif ok {\n\t\t\t\tnewTree, newSubTree := flattenDependencyTree(tree, nextDepList)\n\t\t\t\ttree = newTree\n\t\t\t\tsubTree[index][\"dependencies\"] = newSubTree\n\t\t\t}\n\n\t\t\tcleanTree = append(cleanTree, subTree[index])\n\t\t}\n\t}\n\n\treturn tree, cleanTree\n}\n\nfunc BuildDependencyTree(tree []map[string]interface{}) []map[string]interface{} {\n\tcleanTree := eliminateRedundancy(tree, make(map[string]bool))\n\n\tfor index, dep := range cleanTree {\n\t\tnextDepList, ok := dep[\"dependencies\"].([]map[string]interface{})\n\n\t\tif ok {\n\t\t\tnewCleanTree, newDepList := flattenDependencyTree(cleanTree, nextDepList)\n\t\t\tcleanTree = newCleanTree\n\t\t\tcleanTree[index][\"dependencies\"] = newDepList\n\t\t}\n\t}\n\treturn cleanTree\n}\n"
  },
  {
    "path": "src/provider/install.go",
    "content": "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 BinaryInstall(path string, paths map[string]string) error {\n\tdest := utils.Path(path + \"/.bin\")\n\tos.RemoveAll(dest)\n\tos.MkdirAll(dest, os.ModePerm)\n\n\tfor pr, prdir := range paths {\n\t\tdepProviderPath := GetProviderPath(pr)\n\t\tvar file = utils.FileExists(depProviderPath + utils.Path(\"/binaryInstall.gs\"))\n\t\tif pr != \"gupm\" && file {\n\t\t\tinput := make(map[string]interface{})\n\t\t\tinput[\"Destination\"] = dest\n\t\t\tinput[\"Source\"] = prdir\n\n\t\t\tres, err := jsVm.Run(depProviderPath+utils.Path(\"/binaryInstall.gs\"), input)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t_, err1 := res.ToString()\n\t\t\treturn err1\n\t\t} else {\n\t\t\treturn defaultProvider.BinaryInstall(dest, prdir)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc installDependencySubFolders(path string, depPath string) {\n\tfiles, _ := utils.ReadDir(path)\n\n\tfor _, file := range files {\n\t\tif file.IsDir() {\n\t\t\tfolderPath := utils.Path(depPath + \"/\" + file.Name())\n\t\t\tos.MkdirAll(folderPath, os.ModePerm)\n\t\t\tinstallDependencySubFolders(utils.Path(path+\"/\"+file.Name()), folderPath)\n\t\t} else {\n\t\t\tisFileExists := false\n\t\t\terr := os.Link(utils.Path(path+\"/\"+file.Name()), utils.Path(depPath+\"/\"+file.Name()))\n\t\t\tif err != nil {\n\t\t\t\tisFileExists, _ = regexp.MatchString(`file exists$`, err.Error())\n\t\t\t}\n\n\t\t\tif err != nil && !isFileExists {\n\t\t\t\tif !linkHasErrored {\n\t\t\t\t\tui.Error(err)\n\t\t\t\t\tui.Error(\"Error, cannot use hard link on your system. Falling back to copying file (Will be slower!)\")\n\t\t\t\t\tlinkHasErrored = true\n\t\t\t\t}\n\t\t\t\tinput, err := ioutil.ReadFile(utils.Path(path + \"/\" + file.Name()))\n\t\t\t\tif err != nil {\n\t\t\t\t\tui.Error(err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\terr = ioutil.WriteFile(utils.Path(depPath+\"/\"+file.Name()), input, 0644)\n\t\t\t\tif err != nil {\n\t\t\t\t\tui.Error(err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc InstallDependency(path string, dep map[string]interface{}) {\n\tdepPath := utils.Path(path + \"/\" + dep[\"name\"].(string))\n\t// if(utils.FileExists(depPath)) {\n\t// \t// TODO: check version\n\t// } else {\n\t// }\n\t_, ok := dep[\"path\"].(string)\n\tif ok {\n\t\tos.MkdirAll(utils.Path(depPath), os.ModePerm)\n\t\tinstallDependencySubFolders(utils.Path(dep[\"path\"].(string)), depPath)\n\t} else {\n\t\tui.Error(dep[\"name\"].(string) + \" Cannot be installed.\")\n\t}\n}\n"
  },
  {
    "path": "src/provider/provider.go",
    "content": "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)\n\nvar Provider string\nvar ProviderPath string\nvar providerConfigCache = make(map[string]*utils.GupmEntryPoint)\nvar linkHasErrored = false\nvar pConfigLock = sync.RWMutex{}\n\nfunc GetProviderPath(name string) string {\n\tgupmConfig := utils.GupmConfig()\n\n\tif name == \"\" {\n\t\tname = gupmConfig.DefaultProvider\n\t}\n\n\tif name == \"os\" {\n\t\tosName := utils.OSNAME()\n\t\tif gupmConfig.OsProviders[osName] != \"\" {\n\t\t\tname = gupmConfig.OsProviders[osName]\n\t\t} else {\n\t\t\tui.Error(\"No provider set for\", osName)\n\t\t\treturn utils.DIRNAME()\n\t\t}\n\t}\n\n\tif name == \"gupm\" {\n\t\treturn utils.DIRNAME()\n\t} else {\n\t\thomePlugin := utils.HOMEDIR(\".\") + utils.Path(\"/.gupm/plugins/provider-\"+name)\n\t\tlocalPlugin := utils.DIRNAME() + utils.Path(\"/plugins/provider-\"+name)\n\n\t\tif utils.FileExists(homePlugin) {\n\t\t\tpluginPath, err := filepath.EvalSymlinks(homePlugin)\n\t\t\tif err != nil {\n\t\t\t\tui.Error(err)\n\t\t\t\treturn \"\"\n\t\t\t}\n\t\t\treturn pluginPath\n\t\t} else if utils.FileExists(localPlugin) {\n\t\t\treturn localPlugin\n\t\t} else {\n\t\t\tfmt.Println(\"Provider cannot be found: \" + name + \". Please install it before using it.\")\n\t\t\tos.Exit(1)\n\t\t\treturn \"\"\n\t\t}\n\t}\n}\n\nfunc InitProvider(provider string) error {\n\tProvider = provider\n\tProviderPath = GetProviderPath(provider)\n\n\tif Provider != \"\" {\n\t\tproviderConfig, err := GetProviderConfig(Provider)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tui.Log(\"Initialisation OK for \" + providerConfig.Name)\n\t} else {\n\t\tproviderConfig, err := GetProviderConfig(\"gupm\")\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tui.Log(\"Initialisation OK for \" + providerConfig.Name)\n\t}\n\n\treturn nil\n}\n\nfunc GetProviderConfig(providerName string) (*utils.GupmEntryPoint, error) {\n\tproviderConfigPath := GetProviderPath(providerName) + utils.Path(\"/gupm.json\")\n\n\tpConfigLock.Lock()\n\tif providerConfigCache[providerName] == nil {\n\t\tconfig, err := utils.ReadGupmJson(providerConfigPath)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tproviderConfigCache[providerName] = config\n\n\t\tpConfigLock.Unlock()\n\t\treturn config, nil\n\t} else {\n\t\tconfig := providerConfigCache[providerName]\n\t\tpConfigLock.Unlock()\n\t\treturn config, nil\n\t}\n}\n\nfunc GetPackageConfig(path string) (utils.Json, error) {\n\tvar file = utils.FileExists(ProviderPath + utils.Path(\"/getPackageConfig.gs\"))\n\tif file {\n\t\tinput := make(map[string]interface{})\n\t\tinput[\"Path\"] = path\n\t\tres, err := jsVm.Run(ProviderPath+utils.Path(\"/getPackageConfig.gs\"), input)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tresObj, err1 := res.Export()\n\t\treturn resObj.(utils.Json), err1\n\t} else {\n\t\tpc, err := GetProviderConfig(Provider)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn defaultProvider.GetPackageConfig(utils.Path(path + \"/\" + pc.Config.Default.Entrypoint)), nil\n\t}\n}\n\nfunc PostGetPackageConfig(config utils.Json) (utils.Json, error) {\n\tvar file = utils.FileExists(ProviderPath + utils.Path(\"/postGetPackageConfig.gs\"))\n\tif file {\n\t\tinput := make(map[string]interface{})\n\t\tinput[\"PackageConfig\"] = config\n\n\t\tres, err := jsVm.Run(ProviderPath+utils.Path(\"/postGetPackageConfig.gs\"), input)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tresObj, err1 := res.Export()\n\t\treturn resObj.(utils.Json), err1\n\t} else {\n\t\treturn config, nil\n\t}\n}\n\nfunc SaveDependencyList(path string, depList []map[string]interface{}) error {\n\tvar file = utils.FileExists(ProviderPath + utils.Path(\"/saveDependencyList.gs\"))\n\tif file {\n\t\tinput := make(map[string]interface{})\n\t\tinput[\"Dependencies\"] = depList\n\t\tinput[\"Path\"] = path\n\n\t\t_, err := jsVm.Run(ProviderPath+utils.Path(\"/saveDependencyList.gs\"), input)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn nil\n\t} else {\n\t\treturn defaultProvider.SaveDependencyList(path, depList)\n\t}\n}\n\nfunc GetDependencyList(config utils.Json) ([]map[string]interface{}, error) {\n\tvar file = utils.FileExists(ProviderPath + utils.Path(\"/getDependencyList.gs\"))\n\tif file {\n\t\tinput := make(map[string]interface{})\n\t\tinput[\"PackageConfig\"] = config\n\n\t\tres, err := jsVm.Run(ProviderPath+utils.Path(\"/getDependencyList.gs\"), input)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tresObj, err1 := res.Export()\n\t\tresMap, ok := resObj.([]map[string]interface{})\n\n\t\tif ok {\n\t\t\treturn resMap, err1\n\t\t} else {\n\t\t\treturn make([]map[string]interface{}, 0), err1\n\t\t}\n\t} else {\n\t\treturn defaultProvider.GetDependencyList(config), nil\n\t}\n}\n\nfunc ResolveDependencyLocation(dependency map[string]interface{}) (map[string]interface{}, error) {\n\tdepProviderPath := GetProviderPath(dependency[\"provider\"].(string))\n\tvar file = utils.FileExists(depProviderPath + utils.Path(\"/resolveDependencyLocation.gs\"))\n\tif dependency[\"provider\"].(string) != \"gupm\" && file {\n\t\tinput := make(map[string]interface{})\n\t\tinput[\"Dependency\"] = dependency\n\t\tres, err := jsVm.Run(depProviderPath+utils.Path(\"/resolveDependencyLocation.gs\"), input)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tresObj, err1 := res.Export()\n\n\t\tif resObj == nil {\n\t\t\tui.Error(\"ERROR Failed to resolve\" + dependency[\"name\"].(string) + \"Trying again.\")\n\t\t\treturn ResolveDependencyLocation(dependency)\n\t\t}\n\t\treturn resObj.(map[string]interface{}), err1\n\t} else {\n\t\tdependency[\"url\"] = dependency[\"name\"].(string)\n\t\treturn dependency, nil\n\t}\n}\n\nfunc ExpandDependency(dependency map[string]interface{}) (map[string]interface{}, error) {\n\tdepProviderPath := GetProviderPath(dependency[\"provider\"].(string))\n\tvar file = utils.FileExists(depProviderPath + utils.Path(\"/expandDependency.gs\"))\n\tif dependency[\"provider\"].(string) != \"gupm\" && file {\n\t\tinput := make(map[string]interface{})\n\t\tinput[\"Dependency\"] = dependency\n\n\t\tres, err := jsVm.Run(depProviderPath+utils.Path(\"/expandDependency.gs\"), input)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\ttoExport, _ := res.Export()\n\t\tresObj := jsVm.JsonExport(toExport).(map[string]interface{})\n\n\t\tif resObj == nil {\n\t\t\tui.Error(\"ERROR Failed to resolve\" + dependency[\"name\"].(string) + \". Trying again.\")\n\t\t\treturn ExpandDependency(dependency)\n\t\t}\n\n\t\treturn resObj, nil\n\t} else {\n\t\treturn defaultProvider.ExpandDependency(dependency)\n\t}\n}\n\nfunc GetDependency(provider string, name string, version string, url string, path string) (string, error) {\n\tdepProviderPath := GetProviderPath(provider)\n\tvar file = utils.FileExists(depProviderPath + utils.Path(\"/getDependency.gs\"))\n\tif provider != \"gupm\" && file {\n\t\tinput := make(map[string]interface{})\n\t\tinput[\"Provider\"] = provider\n\t\tinput[\"Name\"] = name\n\t\tinput[\"Version\"] = version\n\t\tinput[\"Url\"] = url\n\t\tinput[\"Path\"] = path\n\n\t\tres, err := jsVm.Run(depProviderPath+utils.Path(\"/getDependency.gs\"), input)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\n\t\tresStr, err1 := res.ToString()\n\t\treturn resStr, err1\n\t} else {\n\t\treturn defaultProvider.GetDependency(provider, name, version, url, path)\n\t}\n}\n\nfunc PostGetDependency(provider string, name string, version string, url string, path string, result string) (string, error) {\n\tdepProviderPath := GetProviderPath(provider)\n\n\tvar file = utils.FileExists(depProviderPath + utils.Path(\"/postGetDependency.gs\"))\n\tif provider != \"gupm\" && file {\n\t\tinput := make(map[string]interface{})\n\t\tinput[\"Provider\"] = provider\n\t\tinput[\"Name\"] = name\n\t\tinput[\"Version\"] = version\n\t\tinput[\"Url\"] = url\n\t\tinput[\"Path\"] = path\n\t\tinput[\"Result\"] = result\n\n\t\tres, err := jsVm.Run(depProviderPath+utils.Path(\"/postGetDependency.gs\"), input)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\n\t\tresStr, err1 := res.ToString()\n\t\treturn resStr, err1\n\t} else {\n\t\treturn defaultProvider.PostGetDependency(provider, name, version, url, path, result)\n\t}\n}\n"
  },
  {
    "path": "src/provider/publish.go",
    "content": "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, namespace string) error {\n\tif Provider != \"gupm\" {\n\t\tvar file = utils.FileExists(utils.Path(ProviderPath + \"/publish.gs\"))\n\t\tif file {\n\t\t\tinput := make(map[string]interface{})\n\t\t\tinput[\"Path\"] = path\n\t\t\t_, err := jsVm.Run(utils.Path(ProviderPath+\"/publish.gs\"), input)\n\t\t\treturn err\n\t\t} else {\n\t\t\treturn errors.New(\"Provider doesn't have any publish function. Please use 'g publish' to use the default publish.\")\n\t\t}\n\t} else {\n\t\treturn defaultProvider.Publish(path, namespace)\n\t}\n}\n"
  },
  {
    "path": "src/publish.go",
    "content": "package main\n\nimport (\n\t\"./provider\"\n\t\"./ui\"\n)\n\nfunc Publish(path string, namespace string) error {\n\terr := provider.InitProvider(Provider)\n\tif err != nil {\n\t\treturn err\n\t}\n\tui.Title(\"Publishing package...\")\n\terrPub := provider.Publish(path, namespace)\n\tif errPub != nil {\n\t\treturn errPub\n\t} else {\n\t\tui.Title(\"Publish done! ❤️\")\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "src/removeDependency.go",
    "content": "package main\n\nimport (\n\t\"./provider\"\n\t\"./ui\"\n\t\"./utils\"\n)\n\nfunc remove(slice []map[string]interface{}, s int) []map[string]interface{} {\n\treturn append(slice[:s], slice[s+1:]...)\n}\n\nfunc RemoveDependency(path string, rls []string) error {\n\tvar err error\n\tvar packageConfig utils.Json\n\tvar depList []map[string]interface{}\n\n\tui.Title(\"Add dependency...\")\n\n\terr = provider.InitProvider(Provider)\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tproviderConfig, err = provider.GetProviderConfig(Provider)\n\tui.Error(err)\n\tpackageConfig, _ = provider.GetPackageConfig(path)\n\tpackageConfig, _ = provider.PostGetPackageConfig(packageConfig)\n\n\tdepList, err = provider.GetDependencyList(packageConfig)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tui.Title(\"Removing from dependency list...\")\n\n\tfor _, str := range rls {\n\t\tfor index, dep := range depList {\n\t\t\tif dep[\"name\"].(string) == str {\n\t\t\t\tdepList = remove(depList, index)\n\t\t\t}\n\t\t}\n\t}\n\n\terr = provider.SaveDependencyList(path, depList)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// TODO: Remove from module folder\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/self.go",
    "content": "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 upgrade for all OSes\n\nfunc SelfUpgrade() {\n\tSelfUninstall()\n\n\tif runtime.GOOS != \"windows\" {\n\t\tscript := utils.HttpGet(\"https://azukaar.github.io/GuPM/install.sh\")\n\t\tioutil.WriteFile(\"TEMP_install.sh\", []byte(script), os.ModePerm)\n\t\tcmd := exec.Command(\"/bin/sh\", \"TEMP_install.sh\")\n\t\tcmd.Stdout = os.Stdout\n\t\tcmd.Stderr = os.Stderr\n\t\tcmd.Stdin = os.Stdin\n\t\tcmd.Run()\n\t\tutils.RemoveFiles([]string{\"TEMP_install.sh\"})\n\t} else {\n\t\tui.Error(\"Upgrade not fully implememnted on windows yet. Please execute windows_installer.exe again\")\n\t}\n}\n\nfunc SelfUninstall() {\n\tutils.RemoveFiles([]string{utils.DIRNAME()})\n\n\tif runtime.GOOS != \"windows\" {\n\t\tutils.RemoveFiles([]string{\"/usr/local/bin/g\", \"/bin/g\"})\n\t}\n}\n"
  },
  {
    "path": "src/test.go",
    "content": "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.Run\n\tfiles := utils.RecursiveFileWalkDir(path)\n\ti := 0\n\tfor _, file := range files {\n\t\tisTest, _ := regexp.MatchString(`\\.test\\.gs$`, file)\n\t\tif isTest {\n\t\t\tos.MkdirAll(\".tmp_test_gupm\", os.ModePerm)\n\t\t\tutils.CopyFiles([]string{file}, \".tmp_test_gupm/\"+strconv.Itoa(i)+\".gs\")\n\t\t\terrch := os.Chdir(\".tmp_test_gupm\")\n\t\t\tif errch != nil {\n\t\t\t\tui.Error(\"Could'n execute\", file)\n\t\t\t\tExit(1)\n\t\t\t}\n\t\t\t_, err := jsVm.Run(strconv.Itoa(i)+\".gs\", make(map[string]interface{}))\n\t\t\tos.Chdir(\"..\")\n\t\t\tutils.RemoveFiles([]string{\".tmp_test_gupm\"})\n\t\t\tif err != nil {\n\t\t\t\tui.Error(\"Test execution failed:\", file)\n\t\t\t\tExit(1)\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n\n\tui.Title(\"Test passed! ❤️\")\n}\n"
  },
  {
    "path": "src/ui/log.go",
    "content": "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\"sync\"\n\t\"time\"\n)\n\nvar errorList = make([]string, 0)\nvar debugList = make([]string, 0)\nvar currentLog string\nvar currentTitle string\nvar progress int\nvar screenWidth int\nvar positionToDrawAt int\nvar logBox = uilive.New()\n\nvar lock = sync.RWMutex{}\nvar errorLock = sync.RWMutex{}\n\nvar redrawNeeded = false\nvar running = true\n\nvar isWaitingForInput = false\n\nfunc Title(log string) {\n\t_ = color.Green\n\tcurrentTitle = log\n\tcurrentLog = \"\"\n\tredrawNeeded = true\n}\n\nfunc Log(log string) {\n\tcurrentLog = log\n\tredrawNeeded = true\n}\n\nfunc Error(errs ...interface{}) error {\n\tres := \"\"\n\n\tfor _, err := range errs {\n\t\terrErr, isErr := err.(error)\n\t\terrStr, isStr := err.(string)\n\t\tif isErr && errErr != nil {\n\t\t\tres += \" \" + errErr.Error()\n\t\t} else if isStr {\n\t\t\tres += \" \" + errStr\n\t\t}\n\t}\n\n\tif res != \"\" {\n\t\terrorLock.Lock()\n\t\terrorList = append(errorList, res)\n\t\terrorLock.Unlock()\n\t\tif len(errorList) <= 10 {\n\t\t\tredrawNeeded = true\n\t\t}\n\n\t\treturn errors.New(res)\n\t} else {\n\t\treturn nil\n\t}\n}\n\nfunc Debug(err string) {\n\tdebugList = append(debugList, err)\n\tif len(debugList) <= 10 {\n\t\tDraw()\n\t}\n}\n\nfunc Progress(p int) {\n\tprogress = p\n\tredrawNeeded = true\n}\n\n// https://github.com/ahmetb/go-cursor/blob/master/cursor.go\n\nvar Esc = \"\\x1b\"\n\nfunc escape(format string, args ...interface{}) string {\n\treturn fmt.Sprintf(\"%s%s\", Esc, fmt.Sprintf(format, args...))\n}\n\nfunc moveCursor(x int, y int) {\n\tescape(\"[%d;%dH\", x, y)\n}\n\nfunc init() {\n\tpositionToDrawAt = 0\n\n\tlogBox.Start()\n\n\tgo (func() {\n\t\tfor range time.Tick(200 * time.Millisecond) {\n\t\t\tif running {\n\t\t\t\tDraw()\n\t\t\t}\n\t\t}\n\t})()\n}\n\nfunc drawTitle() string {\n\tif currentTitle != \"\" {\n\t\ttitle := color.New(color.FgBlue, color.Bold)\n\t\treturn title.Sprintln(\"🐶   \" + currentTitle)\n\t} else {\n\t\treturn \"\"\n\t}\n}\n\nfunc drawLog() string {\n\tif currentLog != \"\" {\n\t\tlog := color.New(color.FgGreen)\n\t\treturn log.Sprintln(\"✓   \" + currentLog)\n\t} else {\n\t\treturn \"\"\n\t}\n}\n\nfunc Stop() {\n\tredrawNeeded = true\n\trunning = false\n\tDraw()\n}\n\nfunc WaitForKey() {\n\tisWaitingForInput = true\n\tlogBox.Flush()\n\n\treader := bufio.NewReader(os.Stdin)\n\treader.ReadRune()\n\tisWaitingForInput = false\n}\n\nfunc WaitForInput(msg string) string {\n\tisWaitingForInput = true\n\tlogBox.Flush()\n\tfmt.Printf(msg)\n\n\tscanner := bufio.NewScanner(os.Stdin)\n\n\tfor scanner.Scan() {\n\t\tvar result = scanner.Text()\n\t\tisWaitingForInput = false\n\t\treturn result\n\t}\n\n\tif scanner.Err() != nil {\n\n\t}\n\n\treturn \"\"\n}\n\nfunc WaitForMenu(msgs []string) int {\n\tlgth := len(msgs)\n\ti := 1\n\tres := 0\n\n\tfor _, msg := range msgs {\n\t\tfmt.Println(strconv.Itoa(i) + \" : \" + msg)\n\t\ti++\n\t}\n\n\tfor res <= 0 || res > lgth {\n\t\tresString := WaitForInput(\"Please input choice 1 - \" + strconv.Itoa(lgth) + \": \")\n\t\tres, _ = strconv.Atoi(resString)\n\t}\n\treturn res\n}\n\nfunc Draw() {\n\tif !redrawNeeded || isWaitingForInput {\n\t\treturn\n\t}\n\n\tresult := \"\"\n\n\tresult += drawTitle()\n\n\tif progress > 0 {\n\t\tfmt.Print(\"📦📦\")\n\t\tfor i := 0; i < 20; i++ {\n\t\t\tif i == progress/5 {\n\t\t\t\tfmt.Print(\"🐕\")\n\t\t\t} else {\n\t\t\t\tfmt.Print(\"-\")\n\t\t\t}\n\t\t}\n\t\tfmt.Println(\"🏠\")\n\t}\n\n\tresult += drawLog()\n\n\terrorColor := color.New(color.FgRed)\n\tlimit := 0\n\terrorLock.RLock()\n\tfor _, v := range errorList {\n\t\t_ = v\n\t\tif limit == 10 {\n\t\t\tresult += errorColor.Sprintln(\"❌❌❌   Too many errors to display...\")\n\t\t\tlimit++\n\t\t} else if limit < 10 {\n\t\t\tresult += errorColor.Sprintln(\"❌   \" + v)\n\t\t\tlimit++\n\t\t}\n\t}\n\terrorLock.RUnlock()\n\n\tlimit = 0\n\tfor _, v := range debugList {\n\t\t_ = v\n\t\tif limit == 10 {\n\t\t\tresult += \"Too many debugs...\"\n\t\t\tlimit++\n\t\t} else if limit < 10 {\n\t\t\tresult += v\n\t\t\tlimit++\n\t\t}\n\t}\n\n\tlock.Lock()\n\tif running {\n\t\tfmt.Fprintf(logBox, result)\n\t} else {\n\t\tfmt.Fprintf(logBox, \"\\n\")\n\t\tlogBox.Stop()\n\t\tfmt.Println(result)\n\t}\n\tredrawNeeded = false\n\tlock.Unlock()\n}\n"
  },
  {
    "path": "src/utils/files.go",
    "content": "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 EmptyFileStructure = FileStructure{}\n\ntype FileStructure struct {\n\tChildren map[string]FileStructure\n\tName     string\n\tContent  []byte\n\tFiletype int\n}\n\nfunc Dir(path string) (matches []string, err error) {\n\treturn doublestar.Glob(path)\n}\n\nfunc RemoveFiles(files []string) error {\n\tfor _, file := range files {\n\t\treturn os.RemoveAll(file)\n\t}\n\treturn nil\n}\n\nfunc CopyFiles(files []string, destination string) error {\n\tfor _, file := range files {\n\t\treturn copy.Copy(file, destination)\n\t}\n\treturn nil\n}\n\nfunc (g *FileStructure) getOrCreate(path string, options FileStructure) FileStructure {\n\tvar folders = strings.Split(path, \"/\")\n\tvar folder = folders[0]\n\tvar child, _ = g.Children[folder]\n\n\tif child.Name == \"\" {\n\t\tif len(folders) > 1 {\n\t\t\tg.Children[folder] = FileStructure{\n\t\t\t\tChildren: make(map[string]FileStructure),\n\t\t\t\tName:     folder,\n\t\t\t\tFiletype: 0,\n\t\t\t}\n\t\t} else {\n\t\t\tg.Children[folder] = FileStructure{\n\t\t\t\tChildren: make(map[string]FileStructure),\n\t\t\t\tName:     folder,\n\t\t\t\tFiletype: options.Filetype,\n\t\t\t\tContent:  options.Content,\n\t\t\t}\n\t\t}\n\t\tchild, _ = g.Children[folder]\n\t}\n\n\tif len(folders) > 1 {\n\t\tnext := folders[1:]\n\t\treturn child.getOrCreate(strings.Join(next[:], \"/\"), options)\n\t} else {\n\t\treturn child\n\t}\n}\n\nfunc (g *FileStructure) SaveSelfAt(path string) error {\n\tif g.Filetype == 0 {\n\t\tnewPath := Path(path + \"/\" + g.Name)\n\t\tos.MkdirAll(newPath, os.ModePerm)\n\t\tfor _, child := range g.Children {\n\t\t\tchild.SaveSelfAt(newPath)\n\t\t}\n\t} else {\n\t\tfilePath := path\n\t\tif g.Name != \"\" {\n\t\t\tfilePath = Path(filePath + \"/\" + g.Name)\n\t\t}\n\t\tf, err := os.OpenFile(filePath, os.O_CREATE|os.O_RDWR, os.FileMode(0777))\n\n\t\tif err != nil {\n\t\t\tf.Close()\n\t\t\treturn err\n\t\t}\n\n\t\tif _, err := f.Write(g.Content); err != nil {\n\t\t\tf.Close()\n\t\t\treturn err\n\t\t}\n\n\t\tf.Close()\n\t}\n\treturn nil\n}\n\nfunc (g *FileStructure) SaveAt(path string) error {\n\tif g.Filetype == 0 {\n\t\tos.MkdirAll(Path(path), os.ModePerm)\n\t\tfor _, child := range g.Children {\n\t\t\tchild.SaveSelfAt(Path(path))\n\t\t}\n\t}\n\tif g.Filetype == 1 {\n\t\tg.SaveSelfAt(Path(path))\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "src/utils/json.go",
    "content": "package utils\n\n// import (\n// \t\"reflect\"\n// \t\"fmt\"\n// )\n\n// type Json map[interface{}]interface {}\ntype Json map[string]interface{}\n\n// func (j *Json) AsObject() map[string]interface {} {\n// \tres := map[string]interface{}{}\n// \tfor i, v := range *j {\n// \t\tres[i.(string)] = v\n// \t}\n// \treturn res\n// }\n\nfunc (j *Json) Contains(test interface{}) bool {\n\tfor i := range *j {\n\t\tif i == test {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc (j *Json) get(index interface{}) interface{} {\n\treturn (*j)[index.(string)]\n}\n\n// func (j *Json) indexOf(test interface{}) interface{} {\n// \tfor i, _  := range *j {\n// \t\tif(i == test) {\n// \t\t\treturn true\n// \t\t}\n// \t}\n// \treturn false\n// }\n"
  },
  {
    "path": "src/utils/repo.go",
    "content": "package utils\n\nimport (\n\t\"io/ioutil\"\n)\n\nfunc GetOrCreateRepo(path string) map[string]interface{} {\n\tconfigPath := path + \"/gupm_repo.json\"\n\tif !FileExists(configPath) {\n\t\tbaseConfig := `{\n\t\"packages\": {}\n}`\n\t\tWriteFile(configPath, baseConfig)\n\t\treturn StringToJSON(baseConfig)\n\t}\n\n\tfile, _ := ioutil.ReadFile(configPath)\n\treturn StringToJSON(string(file))\n}\n\nfunc SaveRepo(path string, file map[string]interface{}) {\n\tWriteJsonFile(path+\"/gupm_repo.json\", file)\n}\n"
  },
  {
    "path": "src/utils/types.go",
    "content": "package utils\n\ntype GupmEntryPoint struct {\n\tName              string\n\tVersion           string\n\tWrapInstallFolder string\n\tGit               gupmEntryPointGit\n\tPublish           gupmEntryPointPublish\n\tCli               gupmEntryPointCliList\n\tConfig            gupmEntryPointConfigList\n\tDependencies      gupmEntryPointDependenciesList\n}\n\ntype gupmEntryPointCliList struct {\n\tDefaultProviders map[string]string\n\tAliases          map[string]interface{}\n}\n\ntype gupmEntryPointGit struct {\n\tHooks gupmEntryPointGitHooks\n}\n\ntype gupmEntryPointGitHooks struct {\n\tPrecommit interface{}\n\tPrepush   interface{}\n}\n\ntype gupmEntryPointDependenciesList struct {\n\tDefaultProvider string\n\tDefault         map[string]string\n}\n\ntype gupmEntryPointConfigList struct {\n\tDefault gupmEntryPointConfig\n}\n\ntype gupmEntryPointConfig struct {\n\tEntrypoint      string\n\tInstallPath     string\n\tDefaultProvider string\n\tOsProviders     map[string]string\n}\n\ntype gupmEntryPointPublish struct {\n\tSource []string\n\tDest   string\n}\n"
  },
  {
    "path": "src/utils/untar.go",
    "content": "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\"strings\"\n)\n\nfunc Ungz(r string) (FileStructure, error) {\n\ttr, err := gzip.NewReader(strings.NewReader(r))\n\n\tif err != nil {\n\t\treturn EmptyFileStructure, err\n\t}\n\n\tdefer tr.Close()\n\n\tbuf := new(bytes.Buffer)\n\tbuf.ReadFrom(tr)\n\n\troot := FileStructure{\n\t\tChildren: make(map[string]FileStructure),\n\t\tName:     tr.Header.Name,\n\t\tContent:  buf.Bytes(),\n\t\tFiletype: 1,\n\t}\n\n\treturn root, nil\n}\n\nfunc Tar(files []string) (FileStructure, error) {\n\tvar buf bytes.Buffer\n\tgzw := gzip.NewWriter(&buf)\n\ttw := tar.NewWriter(gzw)\n\tfinalList := make([]string, 0)\n\n\tfor _, file := range files {\n\t\tif IsDirectory(file) {\n\t\t\tfinalList = append(finalList, RecursiveFileWalkDir(file)...)\n\t\t} else {\n\t\t\tfinalList = append(finalList, file)\n\t\t}\n\t}\n\n\tfor _, file := range finalList {\n\t\tcontent, err := ioutil.ReadFile(file)\n\t\tif err != nil {\n\t\t\treturn EmptyFileStructure, err\n\t\t}\n\n\t\thdr := &tar.Header{\n\t\t\tName: file,\n\t\t\tMode: 0740,\n\t\t\tSize: int64(len(content)),\n\t\t}\n\n\t\tif err := tw.WriteHeader(hdr); err != nil {\n\t\t\treturn EmptyFileStructure, err\n\t\t}\n\n\t\tif _, err := tw.Write([]byte(content)); err != nil {\n\t\t\treturn EmptyFileStructure, err\n\t\t}\n\t}\n\n\tif err := tw.Close(); err != nil {\n\t\treturn EmptyFileStructure, err\n\t}\n\n\tif err := gzw.Close(); err != nil {\n\t\treturn EmptyFileStructure, err\n\t}\n\n\troot := FileStructure{\n\t\tContent:  buf.Bytes(),\n\t\tFiletype: 1,\n\t}\n\n\treturn root, nil\n}\n\nfunc Untar(r string) (FileStructure, error) {\n\tgzr, err := gzip.NewReader(strings.NewReader(r))\n\troot := FileStructure{\n\t\tChildren: make(map[string]FileStructure),\n\t\tName:     \"/\",\n\t\tFiletype: 0,\n\t}\n\n\tif err != nil {\n\t\treturn EmptyFileStructure, err\n\t}\n\n\tdefer gzr.Close()\n\n\ttr := tar.NewReader(gzr)\n\n\tfor {\n\t\theader, err := tr.Next()\n\n\t\tswitch {\n\n\t\tcase err == io.EOF:\n\t\t\treturn root, nil\n\n\t\tcase err != nil:\n\t\t\treturn root, err\n\n\t\tcase header == nil:\n\t\t\tcontinue\n\t\t}\n\n\t\tswitch header.Typeflag {\n\n\t\t// if its a dir and it doesn't exist create it\n\t\tcase tar.TypeDir:\n\t\t\t{\n\t\t\t\troot.getOrCreate(header.Name, FileStructure{\n\t\t\t\t\tFiletype: 0,\n\t\t\t\t})\n\t\t\t}\n\n\t\t// if it's a file create it\n\t\tcase tar.TypeReg:\n\t\t\tbuf := new(bytes.Buffer)\n\t\t\tbuf.ReadFrom(tr)\n\n\t\t\troot.getOrCreate(header.Name, FileStructure{\n\t\t\t\tFiletype: 1,\n\t\t\t\tContent:  buf.Bytes(),\n\t\t\t})\n\t\t}\n\t}\n\n\treturn root, nil\n}\n\nfunc Unzip(r string) (FileStructure, error) {\n\troot := FileStructure{\n\t\tChildren: make(map[string]FileStructure),\n\t\tName:     \"/\",\n\t\tFiletype: 0,\n\t}\n\n\ttr, _ := zip.NewReader(strings.NewReader(r), int64(len(r)))\n\n\tfor _, f := range tr.File {\n\t\t// if its a dir and it doesn't exist create it\n\t\tif f.FileInfo().IsDir() {\n\t\t\troot.getOrCreate(f.Name, FileStructure{\n\t\t\t\tFiletype: 0,\n\t\t\t})\n\t\t} else {\n\t\t\trc, _ := f.Open()\n\t\t\tbuf := new(bytes.Buffer)\n\t\t\tbuf.ReadFrom(rc)\n\n\t\t\troot.getOrCreate(f.Name, FileStructure{\n\t\t\t\tFiletype: 1,\n\t\t\t\tContent:  buf.Bytes(),\n\t\t\t})\n\n\t\t}\n\t}\n\treturn root, nil\n}\n"
  },
  {
    "path": "src/utils/utils.go",
    "content": "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\"\n\t\"runtime\"\n\t\"sync\"\n\t\"time\"\n\n\t\"../ui\"\n\t\"github.com/mitchellh/go-homedir\"\n)\n\ntype Dependency struct {\n\tName     string\n\tProvider string\n\tVersion  string\n}\n\nfunc buildCmd(toRun string, args []string) *exec.Cmd {\n\tisNode := regexp.MustCompile(`.js$`)\n\tvar cmd *exec.Cmd\n\tbashargs := []string{}\n\n\t// temporary hack to make windows execute js file with node\n\tif isNode.FindString(toRun) != \"\" {\n\t\tbashargs = append(bashargs, toRun)\n\t\tbashargs = append(bashargs, args...)\n\t\tcmd = exec.Command(\"node\", bashargs...)\n\t} else {\n\t\tbashargs = append(bashargs, args...)\n\t\tcmd = exec.Command(toRun, bashargs...)\n\t}\n\n\treturn cmd\n}\n\nfunc ExecCommand(toRun string, args []string) error {\n\tcmd := buildCmd(toRun, args)\n\tcmd.Stdout = os.Stdout\n\tcmd.Stderr = os.Stderr\n\tcmd.Stdin = os.Stdin\n\terr := cmd.Run()\n\treturn err\n}\n\nfunc ReadGupmJson(path string) (*GupmEntryPoint, error) {\n\tif !FileExists(path) {\n\t\treturn nil, nil\n\t}\n\tconfig := new(GupmEntryPoint)\n\terrRead := ReadJSON(path, config)\n\tif errRead != nil {\n\t\tui.Error(\"Can't read\", path, \"check your file\")\n\t\treturn nil, errRead\n\t}\n\treturn config, nil\n}\n\nfunc RunCommand(toRun string, args []string) (string, error) {\n\tcmd := buildCmd(toRun, args)\n\tres, err := cmd.Output()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn string(res), nil\n}\n\nfunc BuildStringFromDependency(dep map[string]interface{}) string {\n\trep := dep[\"name\"].(string)\n\n\tif dep[\"version\"] != nil && dep[\"version\"].(string) != \"\" {\n\t\trep += \"@\" + dep[\"version\"].(string)\n\t}\n\n\tif dep[\"provider\"] != nil && dep[\"provider\"].(string) != \"\" {\n\t\trep = dep[\"provider\"].(string) + \"://\" + rep\n\t}\n\n\treturn rep\n}\n\nfunc BuildDependencyFromString(defaultProvider string, dep string) map[string]interface{} {\n\tresult := make(map[string]interface{})\n\tstep := dep\n\n\tversionCheck := regexp.MustCompile(`@[\\w\\.\\-\\_\\^\\~]+$`)\n\ttryversion := versionCheck.FindString(step)\n\tif tryversion != \"\" {\n\t\tresult[\"version\"] = tryversion[1:]\n\t\tstep = versionCheck.ReplaceAllString(step, \"\")\n\t} else {\n\t\tresult[\"version\"] = \"*.*.*\"\n\t}\n\n\tproviderCheck := regexp.MustCompile(`^[\\w\\-\\_]+\\:\\/\\/`)\n\ttryprovider := providerCheck.FindString(step)\n\tif tryprovider != \"\" {\n\t\tresult[\"provider\"] = tryprovider[:len(tryprovider)-3]\n\t\tstep = providerCheck.ReplaceAllString(step, \"\")\n\t} else {\n\t\tresult[\"provider\"] = defaultProvider\n\t}\n\n\tresult[\"name\"] = step\n\treturn result\n}\n\nfunc StringToJSON(b string) map[string]interface{} {\n\tvar jsonString map[string]interface{}\n\tjson.Unmarshal([]byte(string(b)), &jsonString)\n\treturn jsonString\n}\n\nfunc ReadJSON(path string, target interface{}) error {\n\tb, err := os.Open(path) // just pass the file name\n\n\tif err != nil {\n\t\tb.Close()\n\t\treturn err\n\t}\n\n\tdefer b.Close()\n\treturn json.NewDecoder(b).Decode(target)\n}\n\nvar numberConnectionOpened = 0\n\nfunc HttpGet(url string) []byte {\n\tif numberConnectionOpened > 50 {\n\t\ttime.Sleep(1000 * time.Millisecond)\n\t\treturn HttpGet(url)\n\t}\n\n\tnumberConnectionOpened++\n\tresp, httperr := http.Get(url)\n\tif httperr != nil {\n\t\tnumberConnectionOpened--\n\t\tisRateLimit, _ := regexp.MatchString(`unexpected EOF$`, httperr.Error())\n\t\tif !isRateLimit {\n\t\t\tui.Error(\"Error accessing\", url, \"trying again.\", httperr)\n\t\t}\n\t\ttime.Sleep(1000 * time.Millisecond)\n\t\treturn HttpGet(url)\n\t}\n\n\tdefer resp.Body.Close()\n\n\tbody, err := ioutil.ReadAll(resp.Body)\n\tif err != nil {\n\t\tnumberConnectionOpened--\n\t\tui.Error(\"Error reading HTTP response \", err)\n\t\treturn HttpGet(url)\n\t}\n\n\tnumberConnectionOpened--\n\treturn body\n}\n\nfunc FileExists(path string) bool {\n\t_, err := os.Stat(path)\n\tif err == nil {\n\t\treturn true\n\t}\n\tif os.IsNotExist(err) {\n\t\treturn false\n\t}\n\treturn true\n}\n\nfunc StringInSlice(a string, list []string) bool {\n\tfor _, b := range list {\n\t\tif b == a {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc RemoveIndex(s []map[string]interface{}, index int) []map[string]interface{} {\n\treturn append(s[:index], s[index+1:]...)\n}\n\nfunc RecursiveFileWalkDir(source string) []string {\n\tresult := make([]string, 0)\n\terr := filepath.Walk(source,\n\t\tfunc(path string, info os.FileInfo, err error) error {\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif !info.IsDir() {\n\t\t\t\tresult = append(result, path)\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\tif err != nil {\n\t\tui.Error(err)\n\t}\n\treturn result\n}\n\nvar lock = sync.RWMutex{}\n\nfunc ReadDir(path string) ([]os.FileInfo, error) {\n\tlock.Lock()\n\tfiles, err := ioutil.ReadDir(path)\n\tlock.Unlock()\n\tif err != nil {\n\t\tui.Error(err)\n\t\treturn files, err\n\t}\n\n\treturn files, nil\n}\n\nfunc IsDirectory(path string) bool {\n\tfileInfo, err := os.Stat(path)\n\tif err != nil {\n\t\treturn false\n\t}\n\treturn fileInfo.IsDir()\n}\n\nfunc HOMEDIR(fallback string) string {\n\thdir, errH := homedir.Dir()\n\tif errH != nil {\n\t\tui.Error(errH)\n\t\thdir = fallback\n\t}\n\treturn hdir\n}\n\nfunc DIRNAME() string {\n\tex, err := os.Executable()\n\texr, err := filepath.EvalSymlinks(ex)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdir := filepath.Dir(exr)\n\treturn dir\n}\n\nfunc WriteFile(path string, file string) error {\n\treturn ioutil.WriteFile(Path(path), []byte(file), os.ModePerm)\n}\n\nfunc WriteJsonFile(path string, file map[string]interface{}) {\n\tbytes, _ := json.MarshalIndent(file, \"\", \"    \")\n\terr := ioutil.WriteFile(path, bytes, os.ModePerm)\n\tif err != nil {\n\t\tui.Error(err)\n\t}\n}\n\n// TODO: https://blog.golang.org/pipelines\n// add proper checksum check\n\nfunc SaveLockDep(path string) {\n\tioutil.WriteFile(path+\"/.gupm_locked\", []byte(\"1\"), os.ModePerm)\n}\n\nfunc AbsPath(rel string) string {\n\tabs, _ := filepath.Abs(rel)\n\treturn abs\n}\n\nfunc Path(path string) string {\n\tif runtime.GOOS == \"windows\" {\n\t\treturn filepath.FromSlash(path)\n\t} else {\n\t\treturn filepath.ToSlash(path)\n\t}\n}\n\nfunc Contains(s interface{}, elem interface{}) bool {\n\tarrV := reflect.ValueOf(s)\n\n\tif arrV.Kind() == reflect.Slice {\n\t\tfor i := 0; i < arrV.Len(); i++ {\n\n\t\t\t// XXX - panics if slice element points to an unexported struct field\n\t\t\t// see https://golang.org/pkg/reflect/#Value.Interface\n\t\t\tif arrV.Index(i).Interface() == elem {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc ArrString(something interface{}) []string {\n\t_, ok := something.([]string)\n\tif !ok {\n\t\tres := make([]string, 0)\n\t\tfor _, v := range something.([]interface{}) {\n\t\t\tres = append(res, v.(string))\n\t\t}\n\t\treturn res\n\t} else {\n\t\treturn something.([]string)\n\t}\n}\n\nfunc GupmConfig() gupmEntryPointConfig {\n\tgupmjson, _ := ReadGupmJson(Path(DIRNAME() + \"/gupm.json\"))\n\treturn gupmjson.Config.Default\n}\n\nfunc OSNAME() string {\n\tosName := runtime.GOOS\n\tif osName == \"darwin\" {\n\t\treturn \"mac\"\n\t}\n\treturn osName\n}\n"
  },
  {
    "path": "src/windows/windows_install.go",
    "content": "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/GuPM/gupm_windows.tar.gz\")\n\tfiles, _ := utils.Untar(string(arch))\n\tpath := ui.WaitForInput(\"Where do you want to save GuPM? (default C:\\\\)\")\n\tif path == \"\" {\n\t\tpath = \"C:\\\\\"\n\t}\n\tfiles.SaveAt(path)\n\tfmt.Println(\"GuPM saved in \" + path + \". dont forget to add it to your PATH\")\n}\n"
  },
  {
    "path": "tests/install/normal.test.gs",
    "content": "writeJsonFile(\"gupm.json\", {\n    \"dependencies\": {\n        \"default\": {\n        }\n    }\n})\n\n\nvar err = exec(\"../build/dg\", [\"i\", \"git://github.com/Masterminds/semver\"])\n\nif(err) {\n    throw new Error(JSON.stringify(err))\n}\n\nif (!fileExists('gupm_modules/github.com/Masterminds/semver')) {\n    throw new Error(1)\n}"
  },
  {
    "path": "tests/make/nodeps.test.gs",
    "content": "writeJsonFile(\"gupm.json\", {\n    \"dependencies\": {\n        \"default\": {\n        }\n    }\n})\n\nvar err = exec(\"../build/dg\", [\"make\"])\n\nif(err) {\n    throw new Error(JSON.stringify(err))\n}"
  },
  {
    "path": "tests/make/normal.test.gs",
    "content": "writeJsonFile(\"gupm.json\", {\n    \"dependencies\": {\n        \"default\": {\n            \"git://github.com/Masterminds/semver\": \"master\"\n        }\n    }\n})\n\nvar err = exec(\"../build/dg\", [\"make\"])\n\nif(err) {\n    throw new Error(JSON.stringify(err))\n}\n\nif (!fileExists('gupm_modules/github.com/Masterminds/semver')) {\n    throw new Error(1)\n}"
  },
  {
    "path": "tests/plugins/normal.test.gs",
    "content": "writeJsonFile(\"gupm.json\", {\n    \"dependencies\": {\n        \"default\": {\n            \"npm://webpack\": \"latest\"\n        }\n    }\n})\n\nvar err = exec(\"../build/dg\", [\"pl\", \"install\", \"https://azukaar.github.io/GuPM-official/repo:provider-npm\"])\nvar err2 = exec(\"../build/dg\", [\"make\"])\n\nif(err || err2) {\n    throw new Error(JSON.stringify(err))\n}\n\nif (!fileExists('node_modules/webpack')) {\n    throw new Error(1)\n}"
  },
  {
    "path": "tests/scripts/normal.test.gs",
    "content": "writeFile(\"testscript.gs\",\"writeFile('test','it works');\")\n\nvar err = exec(\"../build/dg\", [\"testscript\"])\n\nif(err) {\n    throw new Error(JSON.stringify(err))\n}\n\nif (!fileExists('test')) {\n    throw new Error(1)\n}"
  }
]