Skip to content

Commit

Permalink
functions for adding netrc info to URLs
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchellh committed Aug 20, 2016
1 parent 3d6040e commit bb6b083
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 2 deletions.
2 changes: 1 addition & 1 deletion get.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ var Getters map[string]Getter
var forcedRegexp = regexp.MustCompile(`^([A-Za-z0-9]+)::(.+)$`)

func init() {
httpGetter := new(HttpGetter)
httpGetter := &HttpGetter{Netrc: true}

Getters = map[string]Getter{
"file": new(FileGetter),
Expand Down
6 changes: 5 additions & 1 deletion get_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ import (
// The source URL, whether from the header or meta tag, must be a fully
// formed URL. The shorthand syntax of "github.com/foo/bar" or relative
// paths are not allowed.
type HttpGetter struct{}
type HttpGetter struct {
// Netrc, if true, will lookup and use auth information found
// in the user's netrc file if available.
Netrc bool
}

func (g *HttpGetter) Get(dst string, u *url.URL) error {
// Copy the URL so we can modify it
Expand Down
67 changes: 67 additions & 0 deletions netrc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package getter

import (
"fmt"
"net/url"
"os"
"runtime"

"github.com/bgentry/go-netrc/netrc"
"github.com/mitchellh/go-homedir"
)

// addAuthFromNetrc adds auth information to the URL from the user's
// netrc file if it can be found. This will only add the auth info
// if the URL doesn't already have auth info specified and the
// the username is blank.
func addAuthFromNetrc(u *url.URL) error {
// If the URL already has auth information, do nothing
if u.User != nil && u.User.Username() != "" {
return nil
}

// Get the netrc file path
path := os.Getenv("NETRC")
if path == "" {
filename := ".netrc"
if runtime.GOOS == "windows" {
filename = "_netrc"
}

var err error
path, err = homedir.Expand("~/" + filename)
if err != nil {
return err
}
}

// If the file is not a file, then do nothing
if fi, err := os.Stat(path); err != nil {
// File doesn't exist, do nothing
if os.IsNotExist(err) {
return nil
}

// Some other error!
return err
} else if fi.IsDir() {
// File is directory, ignore
return nil
}

// Load up the netrc file
net, err := netrc.ParseFile(path)
if err != nil {
return fmt.Errorf("Error parsing netrc file at %q: %s", path, err)
}

machine := net.FindMachine(u.Host)
if machine == nil {
// Machine not found, no problem
return nil
}

// Set the user info
u.User = url.UserPassword(machine.Login, machine.Password)
return nil
}
63 changes: 63 additions & 0 deletions netrc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package getter

import (
"net/url"
"testing"
)

func TestAddAuthFromNetrc(t *testing.T) {
defer tempEnv(t, "NETRC", "./test-fixtures/netrc/basic")()

u, err := url.Parse("http://example.com")
if err != nil {
t.Fatalf("err: %s", err)
}

if err := addAuthFromNetrc(u); err != nil {
t.Fatalf("err: %s", err)
}

expected := "http://foo:[email protected]"
actual := u.String()
if expected != actual {
t.Fatalf("Mismatch: %q != %q", actual, expected)
}
}

func TestAddAuthFromNetrc_hasAuth(t *testing.T) {
defer tempEnv(t, "NETRC", "./test-fixtures/netrc/basic")()

u, err := url.Parse("http://username:[email protected]")
if err != nil {
t.Fatalf("err: %s", err)
}

expected := u.String()
if err := addAuthFromNetrc(u); err != nil {
t.Fatalf("err: %s", err)
}

actual := u.String()
if expected != actual {
t.Fatalf("Mismatch: %q != %q", actual, expected)
}
}

func TestAddAuthFromNetrc_hasUsername(t *testing.T) {
defer tempEnv(t, "NETRC", "./test-fixtures/netrc/basic")()

u, err := url.Parse("http://[email protected]")
if err != nil {
t.Fatalf("err: %s", err)
}

expected := u.String()
if err := addAuthFromNetrc(u); err != nil {
t.Fatalf("err: %s", err)
}

actual := u.String()
if expected != actual {
t.Fatalf("Mismatch: %q != %q", actual, expected)
}
}
3 changes: 3 additions & 0 deletions test-fixtures/netrc/basic
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
machine example.com
login foo
password bar
24 changes: 24 additions & 0 deletions util_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package getter

import (
"os"
"testing"
)

// tempEnv sets the env var temporarily and returns a function that should
// be deferred to clean it up.
func tempEnv(t *testing.T, k, v string) func() {
old := os.Getenv(k)

// Set env
if err := os.Setenv(k, v); err != nil {
t.Fatalf("err: %s", err)
}

// Easy cleanup
return func() {
if err := os.Setenv(k, old); err != nil {
t.Fatalf("err: %s", err)
}
}
}

0 comments on commit bb6b083

Please sign in to comment.