diff --git a/.travis.yml b/.travis.yml index c237f4e..72541fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +go_import_path: github.com/prep/gpg dist: xenial language: go @@ -16,11 +17,7 @@ before_install: - sudo apt-get update - sudo apt-get install -y gpgv2 -# Start the gpg-agent in the background before running the test suite. -before_script: - - gpg-agent --homedir testdata/gnupg --daemon - script: - GO_FILES=$(find . -iname '*.go' -type f | grep -v /vendor/) - test -z $(gofmt -s -l $GO_FILES) - - go test -v -race ./... + - ./runtests.sh -v -race ./... diff --git a/README.md b/README.md index 240d429..894d528 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ gpg-agent -[![TravisCI](https://travis-ci.org/prep/gpg.svg?branch=master)](https://travis-ci.org/prep/gpg.svg?branch=master) +[![TravisCI](https://travis-ci.org/prep/gpg.svg?branch=master)](https://travis-ci.org/prep/gpg?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/prep/gpg)](https://goreportcard.com/report/github.com/prep/gpg) [![GoDoc](https://godoc.org/github.com/prep/gpg/agent?status.svg)](https://godoc.org/github.com/prep/gpg/agent) ========= @@ -19,6 +19,12 @@ TODO ---- * There are possibly some unnecessary type conversions happening because `bufio.ReadString()` is used as opposed to `bufio.ReadBytes()`. +Running Tests +------------- + +The tests need a running gpg-agent with the GNUPGHOME environment variable set to the testdata/gnupg directory. To simplify running tests, +use the `runtests.sh` wrapper script which will set GNUPGHOME, start gpg-agent then run `go test` for you. + License ------- This software is distributed under the BSD-style license found in the LICENSE file. diff --git a/agent/conn.go b/agent/conn.go index c7a0586..7c6c3e2 100644 --- a/agent/conn.go +++ b/agent/conn.go @@ -3,9 +3,12 @@ package agent import ( "bufio" "crypto" + "errors" "fmt" "io/ioutil" "net" + "os/exec" + "regexp" "strings" "sync" @@ -28,7 +31,17 @@ type Conn struct { // Dial connects to the specified unix domain socket and checks if there is a // live GPG agent on the other end. +// If filename is "", try to find the path the socket automatically +// by calling gpgconf --list-dirs (see findAgentSocket). func Dial(filename string, options []string) (*Conn, error) { + if filename == "" { + var err error + filename, err = findAgentSocket() + if err != nil { + return nil, err + } + } + c, err := net.Dial("unix", filename) if err != nil { return nil, err @@ -48,6 +61,24 @@ func Dial(filename string, options []string) (*Conn, error) { return conn, nil } +// Find the agent socket by calling the gpgconf program and parse its output +func findAgentSocket() (string, error) { + re := regexp.MustCompile("agent-socket:(.*)\n") + + out, err := exec.Command("gpgconf", "--list-dirs").Output() + if err != nil { + return "", err + } + + filename := re.FindStringSubmatch(string(out)) + + if filename == nil { + return "", errors.New("agent-socket path not found in gpgconf output") + } + + return filename[1], nil +} + // request sends a request to the pgp-agent and then returns its response. func (conn *Conn) request(format string, a ...interface{}) error { req := fmt.Sprintf(format+"\n", a...) diff --git a/agent/conn_test.go b/agent/conn_test.go index e51717e..fbf36e0 100644 --- a/agent/conn_test.go +++ b/agent/conn_test.go @@ -15,7 +15,7 @@ func init() { } var err error - if conn, err = Dial("../testdata/gnupg/S.gpg-agent", options); err != nil { + if conn, err = Dial("", options); err != nil { panic(err.Error()) } } diff --git a/runtests.sh b/runtests.sh new file mode 100755 index 0000000..a508400 --- /dev/null +++ b/runtests.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +export GNUPGHOME=${DIR}/testdata/gnupg + +gpg-connect-agent reloadagent /bye + +go test $@