GuPM to manage your Go project

Yann s
4 min readJul 15, 2019

--

Introduction to GuPM

GuPM is a package manager written with the goal to unify the package management scene. Unifying doesn’t mean centralising: the point of GuPM is also ensuring a community-driven development scene by working with decentralised repositories, and a powerful scripting/plugin system for customising the behaviours of the tools.

This guide assumes you are familiar with Go, Go Get or Go Mods

In order to follow this article, you will need to have both GuPM and the Go provider installed in your machine.

# Install GUPM
curl -fsSL https://azukaar.github.io/GuPM/install.sh | bash
# Install the Go Provider
g plugin install https://azukaar.github.io/GuPM-official/repo:provider-go

What can it do

  • Dependency management (Go get)
  • Scripts (g myscript.gs will execute your script in a cross-platform way)
  • Misc. (g env / g run / g ci / …)
  • Publish to git with versionning

Getting started

Let’s start a cli in your project and type:

g b -p go
# short-hand for g bootstrap --provider go

Using this plugin, GuPM will manage your dependencies thought the gupm.json file. It is essentially a file that (among other things) will hold your dependency list (a bit like go.mod would do)

Once done, GuPM will also have generated a Readme containing basic instructions.

g make # Install your project's dependenciesg i github.com/json-iterator/go # shorthand for g install github.com/json-iterator/go

You might wonder: Tell me, if GuPM is a generic package manager, how does it know to install those dependencies from Go/git? Let’s dive a bit deeper in the project to find out what it the scaffolding does!

Understanding GuPM

So what did we generate here? Most importantly, we generated a gupm.json .

{
"name": "test"
"author": "",
"description": "",
"licence": "ISC",
"cli": {
"aliases": {
"start": "build/bin"
}
},
"dependencies": {
"defaultProvider": "go"
},
}

If you are familiar with the package.json in node, or the go.mod, there’s already a few things here that should be able to pick up. First of all, name/author/description/license are pretty self explanatory.

the cli option allow you to customise how different cli commands will work inside your project. We can for example set aliases. Here we set an alias to provide an easy “start” command to our project.

g start # run the built bin

You can also here tell GuPM to use specific providers when using specific commands using the defaultProvider.

In the first example, you can notice that we haven’t set a defaultProvider in the cli options, but yet, we can still install our modules directly as go modules. That’s because in the dependencies we have another option to set a defaultProvider. The difference with that one, is that this is set to be the default provider at resolution stage. To understand better, let’s imagine we have set no config:

# First, let's try to install github.com/json-iterator/go
# this will not use Git/Go
# because no defaultProvider is set in gupm.json
g i github.com/json-iterator/go# We can tell GuPM to use Git/Go to INSTALL a dependency
# If you do this, Git/Go will take over the whole install process
# This is what happens when you set cli.defaultProviders
g -p go i github.com/json-iterator/go# A better way to do this, is to still use GuPM's default INSTALL
# But tell it to resolve the dependency from Git/Go
# Here, only the RESOLVE stage gets overwritten by Go
# This is what happens when you set dependencies.defaultProvider
g i go://github.com/json-iterator/go

Note that you can also just do an install without the go provider if the target module has a gupm.json file.

Next, we have a build.gs file. This file will be called everytime you execute g build . Inside of it, you can easily read a very short / customisable code that build your src/ folder with the go binary:

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

Finally, last but not least, we have a .gupm_rc . This file acts the same a .bash_rc it is executed first, every-time you run a g command.

env("GOPATH", run("go", ["env", "GOROOT"]) + ":" + pwd() + "/go_modules")

Here we simply add the go_modules folder to the GOROOT, because unlike the usual go get , GuPM doesn’t install your modules globally and instead install them in your project to avoid any clash.

Conclusion

GuPM has been built with seamlessness in mind, for maximum flexibility and customisation around your projects. This article gave you a quick overview of how you can easily use it with Go, but of course, feel free to check our github (and ⭐ it!) for the rest of the documentation on how to make you a GuPM ninja!

Don’t hesitate to also visit me on Twitter:

Thanks for reading!

--

--