{"id":13562192,"url":"https://github.com/GetStream/vg","last_synced_at":"2025-04-03T18:32:49.487Z","repository":{"id":57484790,"uuid":"92923096","full_name":"GetStream/vg","owner":"GetStream","description":"Virtualgo: Easy and powerful workspace based development for go","archived":false,"fork":false,"pushed_at":"2020-01-16T14:39:30.000Z","size":562,"stargazers_count":1316,"open_issues_count":8,"forks_count":44,"subscribers_count":61,"default_branch":"master","last_synced_at":"2025-03-26T06:06:02.303Z","etag":null,"topics":["bash","dep","dependency-management","fish","go","golang","gopath","isolation","shell","vendor","vg","virtualgo","workspace","zsh"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GetStream.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-05-31T08:26:20.000Z","updated_at":"2025-03-02T17:53:45.000Z","dependencies_parsed_at":"2022-08-26T11:10:32.126Z","dependency_job_id":null,"html_url":"https://github.com/GetStream/vg","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GetStream%2Fvg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GetStream%2Fvg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GetStream%2Fvg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GetStream%2Fvg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GetStream","download_url":"https://codeload.github.com/GetStream/vg/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246769961,"owners_count":20830769,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bash","dep","dependency-management","fish","go","golang","gopath","isolation","shell","vendor","vg","virtualgo","workspace","zsh"],"created_at":"2024-08-01T13:01:05.612Z","updated_at":"2025-04-03T18:32:49.451Z","avatar_url":"https://github.com/GetStream.png","language":"Go","readme":"\u003cp align=\"center\"\u003e\u003cimg src=\"docs/img/logo.png\" width=\"430\"\u003e\u003c/p\u003e\n\n\n\n# virtualgo [![Build Status](https://travis-ci.org/GetStream/vg.svg?branch=master)](https://travis-ci.org/GetStream/vg) [![codecov](https://codecov.io/gh/GetStream/vg/branch/master/graph/badge.svg)](https://codecov.io/gh/GetStream/vg) [![Go Report Card](https://goreportcard.com/badge/github.com/GetStream/vg)](https://goreportcard.com/report/github.com/GetStream/vg)\n\nVirtualgo (or `vg` for short) is a tool which provides workspace based\ndevelopment for Go. Its main feature set that makes it better than other\nsolutions is as follows:\n\n1. Extreme ease of use\n2. No interference with other go tools\n3. Version pinning for imports\n4. Version pinning for executables, such as linters (e.g. [`errcheck`](https://github.com/kisielk/errcheck)) and codegen tools (e.g. [`protoc-gen-go`](https://github.com/golang/protobuf))\n5. Importing a dependency that's locally checked out outside of the workspace\n   (also called multi project workflow)\n6. Optional full isolation for imports, see the section on [import\n   modes](#workspace-import-modes) for details.\n\nVirtualgo doesn't do dependency resolution or version pinning itself, because\nthis is a hard problem that's already being solved by other tools. Its approach\nis to build on top of these tools, such as\n[`dep`](https://github.com/golang/dep), to provide the features features listed\nabove.\nFor people coming from Python `vg` is very similar to `virtualenv`, with `dep`\nbeing respective to `pip`. The main difference is that `vg` is much easier to\nuse than `virtualenv`, because there's almost no mental overhead in using `vg`.\n\n### Go Modules\n\nThe Go community is now using Go Modules to handle dependencies. This project is now mostly unmaintained. Please read more about this [here](https://getstream.io/blog/virtual-go-to-go-modules/).\n\n## Example usage\n\nBelow is an example showing some basic usage of `vg`. See further down and `vg help`\nfor more information and examples.\n\n```bash\n$ cd $GOPATH/src/github.com/GetStream/example\n$ vg init  # initial creation of workspace\n\n# Now all commands will be executed from within the example workspace\n(example) $ go get github.com/pkg/errors # package only present in workspace\n(example) $ vg ensure  # installs the dependencies of the example project using dep\n(example) $ vg deactivate\n\n$ cd ~\n$ cd $GOPATH/src/github.com/GetStream/example\n(example) $ # The workspace is now activated automatically after cd-ing to the project directory\n```\n\n## Advantages over existing solutions\n\nThe obvious question is: Why should you use `vg`? What advantages does it\nbring over what you're using now? This obviously depends on what you're using\nnow:\n\n### Advantages over `vendor` directory\n\n1. You can pin versions of executable dependencies, such as linting and code\n   generation tools.\n2. No more issues with `go test ./...` running tests in the `vendor` directory\n   when using `go` 1.8 and below.\n3. You can easily use a dependency from your global `GOPATH` inside your\n   workspace, without running into confusing import errors.\n4. It has optional [full isolation](#workspace-import-modes). If enabled there's\n   no accidental fallbacks to regular `GOPATH` causing confusion about what\n   version of a package you're using.\n5. When using full isolation, tools such as IDEs can spend much less time on\n   indexing. This is simply because they don't have to index the packages\n   outside the workspace.\n6. You don't have problems when using plugins: https://github.com/akutz/gpd\n\n### Advantages over manually managing multiple `GOPATH`s\n\n1. Automatic activation of a `GOPATH` when you `cd` into a directory.\n2. Integration with version management tools such as `dep` and `glide` allow for\n   reproducible builds.\n3. Useful commands to manage installed packages. For instance for uninstalling\n   a package or installing a local package from another `GOPATH`.\n\n\n## Installation\n\nFirst install the package:\n\n```bash\ngo get -u github.com/GetStream/vg\n```\n\nAlthough not required, it is recommended to install\n[`bindfs`](http://bindfs.org/) as well. This gives the best experience when\nusing [full isolation](#workspace-import-modes) and when using\n`vg localInstall`. If you do this, DON'T remove things manually from\n`~/.virtualgo`. Only use `vg destroy`/`vg uninstall`, otherwise you can very\nwell lose data.\n\n```bash\n# OSX\nbrew install bindfs\n# Ubuntu\napt install bindfs\n# Arch Linux\npacaur -S bindfs  # or yaourt or whatever tool you use for AUR\n```\n\n\n### Automatic shell configuration\n\nYou can run the following command to configure all supported shells\nautomatically:\n\n```sh\nvg setup\n```\n\nAfter this you have to reload (`source`) your shell configuration file:\n\n```sh\nsource ~/.bashrc                   # for bash\nsource ~/.zshrc                    # for zsh\nsource ~/.config/fish/config.fish  # for fish\n```\n\n### Manual shell configuration\n\nYou can also edit your shell configuration file manually. Afterwards you still\nhave to `source` the file like explained above.\n\nFor bash put this in your `~/.bashrc` file:\n\n```bash\ncommand -v vg \u003e/dev/null 2\u003e\u00261 \u0026\u0026 eval \"$(vg eval --shell bash)\"\n```\n\nOr for zsh, put his in your `~/.zshrc` file:\n\n```zsh\ncommand -v vg \u003e/dev/null 2\u003e\u00261 \u0026\u0026 eval \"$(vg eval --shell zsh)\"\n```\n\nOr for fish, put this in your `~/.config/fish/config.fish` file:\n\n```fish\ncommand -v vg \u003e/dev/null 2\u003e\u00261; and vg eval --shell fish | source\n```\n\n## Usage\n\nThe following commands are the main commands to use `vg`:\n\n```bash\n# The first command to use is the one to create and activate a workspace named\n# after the current direcory\n$ cd $GOPATH/src/github.com/GetStream/example\n$ vg init\n(example) $\n# This command also links the current directory to the created workspace. This\n# way the next time you cd to this directory the workspace will be activated\n# automatically.\n# (See below in the README on how to use the workspace from an IDE)\n\n# All go commands in this shell are now executed from within your workspace. The\n# following will install the most recent version of the cobra command and\n# library inside the workspace\n(example) $ go get -u github.com/spf13/cobra/cobra\n(example) $ cobra\nCobra is a CLI library for Go that empowers applications.\n......\n\n# It's also possible to only activate a workspace and not link it to the\n# current directory. If the workspace doesn't exist it will also be\n# created on the fly. Activating a new workspace automatically deactivates\n# a previous one:\n(example) $ vg activate example2\n(example2) $ cobra\nbash: cobra: command not found\n\n# To deactivate the workspace simply run:\n(example2) $ vg deactivate\n$ vg activate\n(example) $\n\n# When a workspace is active, a go compilation will try to import packages\n# installed from the workspace first. In some cases you might want to use the\n# version of a package that is installed in your global GOPATH though. For\n# instance when you are fixing a bug in a dependency and want to test the fix.\n# In these cases you can easily install a package from your global GOPATH\n# into the workspace:\n(example) $ vg localInstall github.com/GetStream/utils\n# You can even install a package from a specific path:\n(example) $ vg localInstall github.com/GetStream/utils ~/weird/path/utils\n\n# You can also uninstall a package from your workspace again\n(example) $ vg uninstall github.com/spf13/cobra\n# NOTE: At the moment this only removes the sources and static libs in pkg/, not\n# executables. So the cobra command is still available.\n\n# See the following sections for integration with dependency management tools.\n# And for a full overview of all commands just run:\n(example) $ vg help\n# For detailed help of a specific command run:\n(example) $ vg help \u003ccommand\u003e\n\n```\n\n\n\n### `dep` integration\n\n`vg` integrates well with `dep` (https://github.com/golang/dep):\n\n```bash\n# Install the dependencies from Gopkg.lock into your workspace instead of the\n# vendor directory\nvg ensure\n\n# Pass options to `dep ensure`\nvg ensure -- -v -update\n```\n\nIt also extends `dep` with a way to install executable dependencies. The `vg`\nrepo itself uses it to install the `go-bindata` and `cobra` command. It does\nthis by adding the following in `Gopkg.toml`:\n\n```toml\nrequired = [\n    'github.com/jteeuwen/go-bindata/go-bindata',\n    'github.com/spf13/cobra/cobra'\n]\n```\nRunning `vg ensure` after adding this will install the `go-bindata` and `cobra`\ncommand in the `GOBIN` of the current workspace.\n\nAs you just saw `vg` reuses the\n[`required`](https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md#required)\nlist from `dep`.\nHowever, if you don't want to install\nall packages in the `required` list you can achieve that by putting the\nfollowing in `Gopkg.toml`:\n\n```toml\n[metadata]\ninstall-required = false\n```\n\nYou can also specify which packages to install without the `required` list:\n```toml\n[metadata]\ninstall = [\n    'github.com/jteeuwen/go-bindata/go-bindata',\n    'github.com/golang/mock/...', # supports pkg/... syntax\n]\n```\n\n### Integration with other dependency management tools (e.g glide)\n\nEven though `dep` is the main tool that virtualgo integrates with. It's also possible\nto use other dependency management tools instead, as long as they create a\n`vendor` directory. Installing executable dependencies is not supported though\n(PRs for this are welcome).\n\nTo use `vg` with `glide` works like this:\n\n```bash\n# Install dependencies into vendor with glide\nglide install\n\n# Move these dependencies into the workspace\nvg moveVendor\n```\n\n## Workspace import modes\n\nA workspace can be set up in two different import modes, global fallback or full\nisolation.\nThe import mode of a workspace determines how imports from code behave and it is\nchosen when the workspace is created.\n\n### Global fallback\nIn global fallback mode, packages are imported from the original `GOPATH` when\nthey are not found in the workspace.\nThis is the default import mode for newly created workspaces, as this interferes\nthe least with existing go tools.\n\n### Full isolation\n\nIn full isolation mode, package imports will only search in the packages that\nare installed inside the workspace.\nThis has some advantages:\n\n1. Tools such as IDE's don't have to search the global GOPATH for imports, which\n   can result in a significant speedup for operations such as indexing.\n2. You always know the location of an imported package.\n3. It's not possible to accidentally import of a package that is not managed by\n   your vendoring tool of choice.\n\nHowever, there's also some downsides to full isolation of a workspace. These are\nall caused by the fact that the project you're actually working on is not inside\nyour `GOPATH` anymore. So normally go would not be able to find any imports\nto it. This is partially worked around by locally installing the project into\nyour workspace, but it does not fix all issues.\n\nIn the sections below the remaining issues are described and you can decide for\nyourself if the above advantages are worth the disadvantages. If you want to try\nout full isolation you can create a new workspace using the `--full-isolation`\nflag:\n\n```bash\n$ vg init --full-isolation\n# To change an existing workspace, you have to destroy and recreate it\n$ vg destroy example\n$ vg activate example --full-isolation\n```\n\nThis will cause the workspace to use full isolation import mode each time it is\nactivated in the future. So there's no need to specify the\n`--full-isolation` flag on each activation afterwards.\n\n#### With `bindfs` installed\n\nIf you have [`bindfs`](http://bindfs.org/) installed the issues you will run\ninto are only a slight inconvenience, for which easy workarounds exist. However,\nit is important that you know about them, because they will probably cause\nconfusion otherwise. If you run into any other issues than the ones mentioned\nhere, [please report them](https://github.com/GetStream/vg/issues/new).\n\n##### Relative packages in commands\n\nThe first set of issues happen when using relative reference to packages in\ncommands. Some examples of this are:\n\n- `go list ./...` will return weirdly formatted paths, such\n  as `_/home/stream/go/src/github.com/GetStream/vg`.\n- `go test ./...`, might cause an `init` function to be executed twice.\n- `go build ./...` won't work when an `internal` package is present in the\n  directory. Here you can expect an error saying `use of internal package not\n  allowed`.\n\nLuckily, this can all easily be worked around by using absolute package paths\nfor these commands.\nSo for the `vg` repo you would use the following alternatives:\n\n```bash\n# go list ./...\ngo list github.com/GetStream/vg/...\n# go test ./...\ngo test github.com/GetStream/vg/...\n# go build ./...\ngo build github.com/GetStream/vg/...\n```\n\n##### `dep` commands\n\nAnother issue that pops up is that `dep` doesn't allow it's commands to be\nexecuted outside of the `GOPATH`. This is not a problem for `dep ensure`, since\nyou usually use `vg ensure`, which handles this automatically. However, this is\nan issue for other commands, such as `dep status` and `dep init`. Luckily\nthere's an easy workaround for this as well. You can simply use `vg globalExec`,\nto execute commands from your regular `GOPATH`, which fixes the issue:\n\n```bash\nvg globalExec dep init\nvg globalExec dep status\n```\n\n#### Without `bindfs` installed\n\nIf `bindfs` is not installed, symbolic links will be used to do the local\ninstall.\nThis has the same issues as described for `bindfs`, but there's also some extra\nones that cannot be worked around as easily.\nThe reason for this is that go tooling does not like symbolic links in `GOPATH`\n([golang/go#15507](https://github.com/golang/go/issues/15507), [golang/go#17451](https://github.com/golang/go/issues/17451)).\n\nCompiling will still work, but `go list github.com/...` will not list your\npackage. Other than that there are also issues when using `delve`\n([#11](https://github.com/GetStream/vg/issues/11)). Because of these issues it\nis NOT RECOMMENDED to use virtualgo in full isolation mode without `bindfs`\ninstalled.\n\n## Using a virtualgo workspace with an IDE (e.g. GoLand)\n\nBecause virtualgo is just a usability wrapper around changing your `GOPATH` for\na specific project it is usually quite easy to use it in combination with an\nIDE. Just check out your `GOPATH` after activating a workspace and configure the\nIDE accordingly. Usually if you show your `GOPATH` you will see two paths\nseparated by a colon:\n\n```bash\n$ echo $GOPATH\n/home/stream/.virtualgo/myworkspace:/home/stream/go\n```\n\nIf you can set this full string directly that is fine. For\n[GoLand](https://www.jetbrains.com/go/) you have to add the first one first and\nthen the second one.\n\nWhen using a workspace in full isolation mode it's even easier to set up as\nthere's only one `GOPATH` set.\n\n```bash\n$ echo $GOPATH\n/home/stream/.virtualgo/myworkspace\n```\n\n## License\n\nMIT\n\n## Careers @ Stream\n\nWould you like to work on cool projects like this? We are currently hiring for\ntalented Gophers in Amsterdam and Boulder, get in touch with us if you are\ninterested! tommaso@getstream.io\n","funding_links":[],"categories":["Go","Repositories"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGetStream%2Fvg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FGetStream%2Fvg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGetStream%2Fvg/lists"}