Giter VIP home page Giter VIP logo

gvm's Introduction

gvm

Build Status

By Josh Bussdieker (jbuss, jaja, jbussdieker) while working at Moovweb

Currently lovingly maintained by Benjamin Knigge

Pull requests and other any other contributions would be very much appreciated.

GVM provides an interface to manage Go versions.

Features

  • Install/Uninstall Go versions with gvm install [tag] where tag is "60.3", "go1", "weekly.2011-11-08", or "tip"
  • List added/removed files in GOROOT with gvm diff
  • Manage GOPATHs with gvm pkgset [create/use/delete] [name]. Use --local as name to manage repository under local path (/path/to/repo/.gvm_local).
  • List latest release tags with gvm listall. Use --all to list weekly as well.
  • Cache a clean copy of the latest Go source for multiple version installs.
  • Link project directories into GOPATH

Background

When we started developing in Go mismatched dependencies and API changes plagued our build process and made it extremely difficult to merge with other peoples changes.

After nuking my entire GOROOT several times and rebuilding I decided to come up with a tool to oversee the process. It eventually evolved into what gvm is today.

Installing

To install:

  1. Install Bison:

    sudo apt-get install bison
    
  2. Install gvm:

    bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
    

Or if you are using zsh just change bash with zsh

Installing Go

gvm install go1.4
gvm use go1.4 [--default]

Once this is done Go will be in the path and ready to use. $GOROOT and $GOPATH are set automatically.

Additional options can be specified when installing Go:

Usage: gvm install [version] [options]
    -s,  --source=SOURCE      Install Go from specified source.
    -n,  --name=NAME          Override the default name for this version.
    -pb, --with-protobuf      Install Go protocol buffers.
    -b,  --with-build-tools   Install package build tools.
    -B,  --binary             Only install from binary.
         --prefer-binary      Attempt a binary install, falling back to source.
    -h,  --help               Display this message.

A Note on Compiling Go 1.5+

Go 1.5+ removed the C compilers from the toolchain and replaced them with one written in Go. Obviously, this creates a bootstrapping problem if you don't already have a working Go install. In order to compile Go 1.5+, make sure Go 1.4 is installed first. If Go 1.4 won't install try a later version (e.g. go1.5), just make sure you have the -B option after the version number.

gvm install go1.4 -B
gvm use go1.4
export GOROOT_BOOTSTRAP=$GOROOT
gvm install go1.7

A Note on ARMv6 and ARMv7 architectures (32 bit)

Binary versions for ARMv6 architecture are available starting from Go 1.6. So, it is necessary to bootstrap with an existing binary version, then it will be possible compiling other versions. For instance, to bootstrap a setup, version 1.21.0 may be used:

gvm install go1.21.0 -B
gvm use go1.21.0

And then, compile any other version:

gvm install go1.20.7

To install Go 1.20+

Go 1.20+ requires go1.17.3+. Use the below:

gvm install go1.4 -B
gvm use go1.4
export GOROOT_BOOTSTRAP=$GOROOT
gvm install go1.17.13
gvm use go1.17.13
export GOROOT_BOOTSTRAP=$GOROOT
gvm install go1.20
gvm use go1.20

List Go Versions

To list all installed Go versions (The current version is prefixed with "=>"):

gvm list

To list all Go versions available for download:

gvm listall

Uninstalling

To completely remove gvm and all installed Go versions and packages:

gvm implode

If that doesn't work see the troubleshooting steps at the bottom of this page.

Mac OS X Requirements

xcode-select --install
brew update
brew install mercurial

Linux Requirements

Debian/Ubuntu

sudo apt-get install curl git mercurial make binutils bison gcc build-essential

Redhat/Centos

sudo yum install curl
sudo yum install git
sudo yum install make
sudo yum install bison
sudo yum install gcc
sudo yum install glibc-devel

FreeBSD Requirements

sudo pkg_add -r bash
sudo pkg_add -r git
sudo pkg_add -r mercurial

Vendoring Native Code and Dependencies

GVM supports vendoring package set-specific native code and related dependencies, which is useful if you need to qualify a new configuration or version of one of these dependencies against a last-known-good version in an isolated manner. Such behavior is critical to maintaining good release engineering and production environment hygiene.

As a convenience matter, GVM will furnish the following environment variables to aid in this manner if you want to decouple your work from what the operating system provides:

  1. ${GVM_OVERLAY_PREFIX} functions in a manner akin to a root directory hierarchy suitable for auto{conf,make,tools} where it could be passed in to ./configure --prefix=${GVM_OVERLAY_PREFIX} and not conflict with any existing operating system artifacts and hermetically be used by your workspace. This is suitable to use with C{PP,XX}FLAGS and LDFLAGS, but you will have to manage these yourself, since each tool that uses them is different.

  2. ${PATH} includes ${GVM_OVERLAY_PREFIX}/bin so that any tools you manually install will reside there, available for you.

  3. ${LD_LIBRARY_PATH} includes ${GVM_OVERLAY_PREFIX}/lib so that any runtime library searching can be fulfilled there on FreeBSD and Linux.

  4. ${DYLD_LIBRARY_PATH} includes ${GVM_OVERLAY_PREFIX}/lib so that any runtime library searching can be fulfilled there on Mac OS X.

  5. ${PKG_CONFIG_PATH} includes ${GVM_OVERLAY_PREFIX}/lib/pkgconfig so that pkg-config can automatically resolve any vendored dependencies.

Recipe for success:

gvm use go1.1
gvm pkgset use current-known-good
# Let's assume that this includes some C headers and native libraries, which
# Go's CGO facility wraps for us.  Let's assume that these native
# dependencies are at version V.
gvm pkgset create trial-next-version
# Let's assume that V+1 has come along and you want to safely trial it in
# your workspace.
gvm pkgset use trial-next-version
# Do your work here replicating current-known-good from above, but install
# V+1 into ${GVM_OVERLAY_PREFIX}.

See examples/native for a working example.

Troubleshooting

Sometimes especially during upgrades the state of gvm's files can get mixed up. This is mostly true for upgrade from older version than 0.0.8. Changes are slowing down and a LTR is imminent. But for now rm -rf ~/.gvm will always remove gvm. Stay tuned!

Gitter

gvm's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gvm's Issues

`gvm install` just hanging

I can download the go source tarball myself in about 30 seconds. When I try to install with gvm, nothing seems to happen.

$ gvm install go1.2
Downloading Go source...

I can leave this for several minutes without any change. What's going on?

Amending GOPATH

Previously I appended my current project to $GOPATH. GVM doesn't seem to support this. I'm only able to link single packages using gvm linkthis, but not an entire src directory, because linkthis automatically assumes a package and not a whole directory containing packages.

Unable to install any version on OSX?

Upon trying to install any version of go from gvm listall, the script hangs here:

Downloading Go source...

...and never installs anything. Any idea what the issue might be?

gvm installs wrong go on (at least) OSX

$ gvm install 1.2
Installing go1.1.2...

  • Compiling...

I'm not sure how go1.1.2 == 1.2 but ok....

I then installed go1.2 and that worked:
$ gvm install go1.2
Installing go1.2...

  • Compiling...

then I get:
$ gvm use 1.2
Now using version go1.1.2
$ go version
go version devel +1b5a82d4b552 Sun Apr 20 20:29:17 2014 +0200 darwin/amd64
$ gvm use go1.2
Now using version go1.2
$ go version
go version devel +1b5a82d4b552 Sun Apr 20 20:29:17 2014 +0200 darwin/amd64

So I think I must be missing something, because (a) neither of these versions have a tagged release version number and (b) they are both the same! go1.1.2 == go1.2 ????

zsh support?

Hello, I'm having trouble using gvm with oh-my-zsh. It seems the gvm bin path is not exported to the shell when using zsh (yes I restarted the terminal)

Does not work with go1.2

GVM can't install/find any go1.2(rcX) or tip version

  • gvm listall does not show any 1.2 versions
  • When running gvm install 1.2rc1 downloads something, but fails with ERROR: Unrecognized Go version

Unrecognized Go version

when I type gvm install gradle
it says

Updating Go source...
ERROR: Unrecognized Go version

I deleted the go_cache_dir and run again, this error still there
Debian 7.0 amd64

.gvmrc Support

This is a great project, and I can see myself using this to vendor my dependencies.

Are there any plans or thoughts around adding .gvmrc support like .rvmrc from RVM? I am working on multiple Go projects at the moment, and auto switching between pkgsets when I switch directories would be fantastic.

Thanks,
-Phil

Poor error messages

When one tries to do

gvm use [version X]

and [version X] is not installed, gvm says

Invalid version [version X]

instead of suggesting that the version is perfectly valid, just not installed. This is very misleading.

"raw.github.com" changed to "raw.githubusercontent.com"

Hi,

My computer OS is Mac OSX 10.9.2.

I can't reached the original hostname raw.github.com, it has been change to raw.githubusercontent.com.

I can fixed this issue by added curl -L parameter as following code:

bash < <(curl -s -L https://raw.github.com/moovweb/gvm/master/binscripts/gvm-installer)

or directly modify hostname as following code:

bash < <(curl -s https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)

Easily build and test same package in multiple versions

I've been trying to use gvm to support building a single package (lib/pq) on four go versions: 1.0.2, 1.0.3, 1.1, and tip. I'd like to share a source directory for these builds, since the source is exactly the same (where different code is necessary for different versions, we use build constraints to maintain a single source tree).

A colleague has been doing this with gvm since before pkgsets by just symlinking the single GOPATH into the various version-specific GOPATH directories in ~/.gvm. I'm trying to set up something similar now, and by looking at the README, I thought pkgsets might help, but I see that they are tied to a specific go version. Does gvm support the same source tree (ideally, just the same src component of GOPATH) across multiple go versions? Would that make sense? Does it present problems?

travis config breaks test of pull requests

When calling "binscripts/gvm-installer $TRAVIS_COMMIT $TRAVIS_BUILD_DIR/tmp", travis will checkout the remote master branch and attempt to checkout the commit referring to a pull request which is not yet merged. This results in a build failure.

Need a `.gvm/gos` directory

Repro:

Installed gvm

$ bash < <(curl -s https://raw.github.com/moovweb/gvm/master/binscripts/gvm-installer )
Installed GVM v

Added to my bashrc ala rvm

# gvm
[[ -s "$HOME/.gvm/scripts/gvm" ]] && source "$HOME/.gvm/scripts/gvm"

Get my go

$ gvm install 60.2
Installing version 60.2
 * Downloading...
 * Compiling...
/home/tarun/.gvm/bin/gvm-install: line 11: cd: /home/tarun/.gvm/gos/go-60.2/src: No such file or directory
/home/tarun/.gvm/bin/gvm-install: line 11: /home/tarun/.gvm/gos/go-60.2/install.log: No such file or directory
Failed to install version 60.2. See logs in /home/tarun/.gvm/gos/go-60.2/install.log for details

Works if I create the dir

mkdir ~/.gvm/gos

command not found: go

Hey Guys,

I am sorry for so many stupid questions, but after installing Go via GVM I am unable to use the go command.

Am I missing something?

Thanks,

Josh

Source line only added to bashrc

The installer adds the line [[ -s "$HOME/.gvm/scripts/gvm" ]] && source "$HOME/.gvm/scripts/gvm" to bashrc.

I use zsh (.zshrc), but the installer doesn't say anything about adding that line to your config file if you aren't using bash.

Support the existing version of Go

Many people, when switching to GVM, may already have an existing version of Go installed. This might come from the OS package system, or they may even be running tip and contributing to the language. . It would be cool if gvm could detect the 'system' version (i.e it could check for GOROOT during install).

error on implode

$ gvm version
Go Version Manager v1.0.20 installed at $HOME

$ gvm implode
gvm_implode:read:1: -p: no coprocess
Action cancelled

add support for system-wide go install

gvm is great for managing user-specific or version-specific install of go, but doesn't support management of the system's version of go (used by default if a user hasn't installed gvm).

to simplify deployment and use of go apps to app-specific VMs or docker containers, where multiple versions likely aren't necessary, it would be nice to be able to install / manage the system version of go (/usr/bin/go). this would also allow a great cross-platform method of installing go, as no OS-specific packages are supported (rpm, apt/deb, etc.).

Making a package

Hi,

I'm trying to create an unofficial Arch Linux package for gvm.
Where on the system should the various scripts go?
bin/gvm, bin/gvm-prompt and bin/gvmsudo in /usr/bin? Would that do?

The reason I ask is because the included installation script, "gvm-installer" seems to be targeting only installations in users home directory, not system-wide installations.

Instructions, or an install script, for system-wide installations would be appreciated.

Best regards,
Alexander RΓΈdseth

Doesn't install godoc

I am brand new to Go (installed it today...), and I see that GVM doesn't install other utilities such as godoc. How do I install them? If I have do an apt-get install golang-stable to get them, then how does GVM help?

Issues on OSX

Hi! Cool project πŸ‘

I notice you don't mention use on OSX, is it supported? If so, I'm having this issue:

$ gvm install go1
Installing go1...
 * Compiling...
ERROR: Failed to compile
ERROR: Failed to use installed version

Is there a way to turn verbosity up so I can see the full stack trace and figure out what's going on?

Missing directory during installation

The installer script does not create the .gvm/scripts directory, causing an error [1]. I worked around this by adding the following line before the declaration of source_line (about line 90) in the installer script:

mkdir -p ~/.gvm/scripts

It worked for me, but probably is not optimal.

Nicholas


[1]

$ uname -a
Linux pds 3.2.0-0.bpo.4-amd64 #1 SMP Debian 3.2.51-1~bpo60+1 x86_64 GNU/Linux

$ cat /etc/debian_version 
6.0.8

$ bash < <(curl -s -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
bash: line 107: /home/nicholas/.gvm/scripts/gvm: No such file or directory
bash: line 108: /home/nicholas/.gvm/scripts/gvm: No such file or directory
No existing Go versions detected
Installed GVM v

Please restart your terminal session or to get started right away run
 `source /home/nicholas/.gvm/scripts/gvm`

$ source /home/nicholas/.gvm/scripts/gvm
-bash: /home/nicholas/.gvm/scripts/gvm: No such file or directory

Installing go1.1 beta

Hi,

I was just wondering if there is a way to install 1.1 beta without installing tip?

eg. gvm install go1.1beta2

Thanks,

Josh

odd error when running gvm command

Hey @moovweb,

I installed gvm as per the instructions, and added the source line to my .zsh_profile but get the following error when I run the gvm command:

➜  ~  gvm
gvm:20: = not found

I am not sure how to diagnose this error, any help or advice would be greatly appreciated.

Thanks a bundle,

Josh

Behavior of install command varies too much

Sorry about the opinionated subject line. I'm trying to fix up the gvm situation over in Travis land and running into problems. The situation may be best illustrated with an example: https://travis-ci.org/modcloth/sqlutil/builds/7435167

In the before_install folds you should see two gvm install calls, each with an || true to essentially force a 0 exit status. I can't speak to why Travis's gvm installation is being deemed "corrupt".

When I run gvm install with a valid version number that isn't yet installed, I expect gvm to install the version and exit 0, even if it has to "uncorrupt" whatever first, but instead gvm is telling me about a corruption, trying to start an install, and the exiting with ERROR: Couldn't copy source to target folder. Subsequently calling gvm install succeeds.

When I run gvm install with a valid version number that's already installed, I expect gvm to tell me it's already installed and exit 0, but instead gvm tells me it's already installed and exits 1.

Issue with alias ls='ls -p'

When an alias has been set for ls that includes the -p parameter GVM will incorrectly try to source the environment file as a directory.

The following output is produced:

$ gvm use tip
bash: /home/jbussdieker/.gvm/environments/tip/: Not a directory
Now using version tip/

Installation fails if it's run inside a git repository

$ mkdir foo
$ cd foo
$ git init
Initialized empty Git repository in /home/asari/foo/.git/
$ touch this
$ git add this; git commit -m 'foo'
[master (root-commit) 7a55bfb] foo
 0 files changed
 create mode 100644 this
$ curl -s -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer | bash
bash: line 107: /home/asari/.gvm/scripts/gvm: No such file or directory
bash: line 108: /home/asari/.gvm/scripts/gvm: No such file or directory
No existing Go versions detected
Installed GVM v

Please restart your terminal session or to get started right away run
 `source /home/asari/.gvm/scripts/gvm`

$ source /home/asari/.gvm/scripts/gvm
-sh: 47: source: not found

https://github.com/moovweb/gvm/blob/c1ec392/binscripts/gvm-installer#L60-L75

$GIT_ROOT is going to be set in this case, but not to the value you are expecting.

Failed to install gb

Hey Guys,

Sorry to bug you again, I don't know if it is a real issue or not, and it probably isn't a gvm issue, but when I try to install I get:

➜  ~  gvm install release.r60.3
Downloading Go source...
Installing release.r60.3...
 * Compiling...
 * Installing gb...
Failed to install gb
 * Installing gpkg...

Any and all help/advice is loved :)

Thanks,

Josh

gvm install go1.1.2 on OS X 10.9 Mavericks ERROR

$ GCC=clang go get -tags zmq_3_x github.com/alecthomas/gozmq
# github.com/alecthomas/gozmq
clang: warning: argument unused during compilation: '-pthread'
# github.com/alecthomas/gozmq
clang: error: no such file or directory: 'libgcc.a'

MAYBE

export CGO_ENABLED=0

GVM workflow for newbies

As a Go newbie, I am battling to get my workflow right.

I have installed Go 1.2 as per the GVM instructions.

I want to be able to have my Go projects eg. ProjectA and ProjectB in a directory say ~/side_projects.

What I have tried so far is outlined below:

mkdir ProjectA
cd ~/side_projects/ProjectA
gvm pkgset create --local
gvm pkgset use --local

$GOPATH now returns

/home/lee/side_projects/ProjectA:/home/lee/side_projects/ProjectA/.gvm_local/pkgsets/go1.2/local:/home/lee/.gvm/pkgsets/go1.2/global

I then created a hello-world.go and a test-package.go file.

hello-world.go:

package main

import (
    "test_package"
    "fmt"
)

func main() {
    fmt.Println(test_package.HelloWorld())
}

test-package.go

package test_package

func HelloWorld() string {
    return "Hello world"
}

go run hello-world.go complained so I had to move all the code into a src directory, and then place test_package.go into a directory with the same name, and then things worked as expected

Then I installed Revel via go get github.com/robfig/revel, and the problem is best explained with a screenshot:

Here is /home/lee/side_projects/ProjectA

image

Here is /home/lee/side_projects/ProjectA/src

image

The third party packages are now mixed with my own, and now i am pretty confused.

  1. Can't the third party packages go into the .gvm-local folder?
  2. If Go projects require src and pkg directories, where do I place my application code? Directly in src? I don't want my code sitting in the same directory as external libraries as it currently happening.
  3. Where do I place my git repo? Directly in src, or in ProjectA, and add pkg to gitignore? (Assuming I can get the external packages to go into .gvm-local)?

Docker installation?

I haven't seen any documentation on how to install it on a Docker, anyone with Dockerfile (preferably without source commands on the beginning of each line)

Install defaults

I forgot to add the 'b' and 'pb' tags when doing a fresh install so now I have reinstall all my gos.

Seems like those flags should be on by default and also in the readme.

feature: 'currently enabled'

I'm looking to add to my zsh line the status of gvm e.g.

if a go version is in use --> if so what version --> if so what package set

I'm sorting through my env variables and there does not seem to be a difference whether an env is loaded or not, unless I'm missing something.

I'd suggest this as a feature, if it is missing, a gvm status/state var. If someone would suggest some guide, I'd be happy to make the attempt.

0.7 and 60.3

gvm install 60.3 fails!

Seems its not actually downloading to where its looking for it during compile...

moving .git directory/file breaks things

Hi guys, love the project. I use gvm a lot, but I like to install it with git-only. This is very actually very simple; I just need to clone the repository to ~/.gvm and add the following to my rc script:

export GVM_ROOT=$HOME/.gvm
source $GVM_ROOT/scripts/gvm-default

My problem is that the gvm script intentionally hides the .git directory, making git pulls cumbersome, and making the directory unrecognizable as a git repository to configuration management tools. This is described as a safety feature in this commit: 85db830, but without any explanation of the risks averted.

Issue #7 alludes to this as a nuisance that is worked around, but would it be possible to just remove this behavior, and allow for the dynamic management of the gvm installation?

The name conflicts with Groovy's gvm.

Hi,

How do you think about the name conflict with Groovy's gvm? Recently I'm interested in this tool but I'm also very dependent on Groovy's gvm (especially in JVM-releated development like android app or gradle plugin), so I cannot try it...

Tags and versioning

It would be great if gvm releases were versioned and tagged. This would allow to install gvm predictably and reliably across machines over time.

This would allow users to install gvm without worrying if the master is in a clean and stable state.

Thanks in advance for looking into this.

Does not work with aliased ls

I'm using zsh as my shell, and here's what happens

$ gvm list

gvm gos (installed)

   weekly.2012-03-13

$ gvm use weekly.2012-03-13
gvm_use:5: command not found: ls: aliased to ls --color
ERROR: Invalid version weekly.2012-03-13
$ which ls
ls: aliased to ls --color
$ unalias ls
$ gvm use weekly.2012-03-13
Now using version weekly.2012-03-13

cross compilation

It would be great if GVM supported cross compiling. As far as I can see this would fit pretty good with the current workflow.

There could be a command like

gvm target use linux-amd64

and when the binaries have not yet been created they are automatically built right afterwards.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.