tools: Use luci auth layer with gerrit

Bug: dawn:1940
Change-Id: Ibefc4260134ba5fc23ee38eb7145acdd6b0a6ebd
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/147540
Auto-Submit: Austin Eng <enga@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Austin Eng <enga@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/tools/src/auth/auth.go b/tools/src/auth/auth.go
new file mode 100644
index 0000000..531f7e5
--- /dev/null
+++ b/tools/src/auth/auth.go
@@ -0,0 +1,30 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package auth
+
+import (
+	"dawn.googlesource.com/dawn/tools/src/fileutils"
+	"go.chromium.org/luci/auth"
+	"go.chromium.org/luci/hardcoded/chromeinfra"
+)
+
+// DefaultAuthOptions returns the default authentication options for use by
+// command line arguments.
+func DefaultAuthOptions() auth.Options {
+	def := chromeinfra.DefaultAuthOptions()
+	def.SecretsDir = fileutils.ExpandHome("~/.config/dawn-cts")
+	def.Scopes = append(def.Scopes, "https://www.googleapis.com/auth/gerritcodereview", auth.OAuthScopeEmail)
+	return def
+}
diff --git a/tools/src/cmd/add-gerrit-hashtags/main.go b/tools/src/cmd/add-gerrit-hashtags/main.go
index e0ae0b2..11ea09b 100644
--- a/tools/src/cmd/add-gerrit-hashtags/main.go
+++ b/tools/src/cmd/add-gerrit-hashtags/main.go
@@ -16,6 +16,7 @@
 package main
 
 import (
+	"context"
 	"flag"
 	"fmt"
 	"os"
@@ -24,10 +25,12 @@
 	"strings"
 	"time"
 
+	"dawn.googlesource.com/dawn/tools/src/auth"
 	"dawn.googlesource.com/dawn/tools/src/container"
 	"dawn.googlesource.com/dawn/tools/src/dawn"
 	"dawn.googlesource.com/dawn/tools/src/gerrit"
 	"dawn.googlesource.com/dawn/tools/src/git"
+	"go.chromium.org/luci/auth/client/authcli"
 )
 
 const (
@@ -36,10 +39,6 @@
 )
 
 var (
-	// See https://dawn-review.googlesource.com/new-password for obtaining
-	// username and password for gerrit.
-	gerritUser  = flag.String("gerrit-user", "", "gerrit authentication username")
-	gerritPass  = flag.String("gerrit-pass", "", "gerrit authentication password")
 	repoFlag    = flag.String("repo", "dawn", "the project (tint or dawn)")
 	userFlag    = flag.String("user", defaultUser(), "user name / email")
 	afterFlag   = flag.String("after", "", "start date")
@@ -47,6 +46,7 @@
 	daysFlag    = flag.Int("days", 30, "interval in days (used if --after is not specified)")
 	verboseFlag = flag.Bool("v", false, "verbose mode - lists all the changes")
 	dryrunFlag  = flag.Bool("dry", false, "dry mode. Don't apply any changes")
+	authFlags   = authcli.Flags{}
 )
 
 func defaultUser() string {
@@ -65,6 +65,8 @@
 }
 
 func main() {
+	authFlags.Register(flag.CommandLine, auth.DefaultAuthOptions())
+
 	flag.Usage = func() {
 		out := flag.CommandLine.Output()
 		fmt.Fprintf(out, "%v adds any missing hashtags parsed from the CL description to the Gerrit change.\n", toolName)
@@ -102,9 +104,13 @@
 		after = before.Add(-time.Hour * time.Duration(24**daysFlag))
 	}
 
-	g, err := gerrit.New(dawn.GerritURL, gerrit.Credentials{
-		Username: *gerritUser, Password: *gerritPass,
-	})
+	ctx := context.Background()
+	auth, err := authFlags.Options()
+	if err != nil {
+		return err
+	}
+
+	g, err := gerrit.New(ctx, auth, dawn.GerritURL)
 	if err != nil {
 		return err
 	}
diff --git a/tools/src/cmd/auto-submit/main.go b/tools/src/cmd/auto-submit/main.go
index 051bb9a..a49a941 100644
--- a/tools/src/cmd/auto-submit/main.go
+++ b/tools/src/cmd/auto-submit/main.go
@@ -17,6 +17,7 @@
 package main
 
 import (
+	"context"
 	"flag"
 	"fmt"
 	"log"
@@ -25,9 +26,11 @@
 	"strings"
 	"time"
 
+	"dawn.googlesource.com/dawn/tools/src/auth"
 	"dawn.googlesource.com/dawn/tools/src/dawn"
 	"dawn.googlesource.com/dawn/tools/src/gerrit"
 	"dawn.googlesource.com/dawn/tools/src/git"
+	"go.chromium.org/luci/auth/client/authcli"
 )
 
 const (
@@ -36,14 +39,11 @@
 )
 
 var (
-	// See https://dawn-review.googlesource.com/new-password for obtaining
-	// username and password for gerrit.
-	gerritUser  = flag.String("gerrit-user", "", "gerrit authentication username")
-	gerritPass  = flag.String("gerrit-pass", "", "gerrit authentication password")
 	repoFlag    = flag.String("repo", "dawn", "the repo")
 	userFlag    = flag.String("user", defaultUser(), "user name / email")
 	verboseFlag = flag.Bool("v", false, "verbose mode")
 	dryrunFlag  = flag.Bool("dry", false, "dry mode. Don't apply any labels")
+	authFlags   = authcli.Flags{}
 )
 
 func defaultUser() string {
@@ -62,6 +62,8 @@
 }
 
 func main() {
+	authFlags.Register(flag.CommandLine, auth.DefaultAuthOptions())
+
 	flag.Usage = func() {
 		out := flag.CommandLine.Output()
 		fmt.Fprintf(out,
@@ -86,9 +88,13 @@
 		return fmt.Errorf("Missing required 'user' flag")
 	}
 
-	g, err := gerrit.New(dawn.GerritURL, gerrit.Credentials{
-		Username: *gerritUser, Password: *gerritPass,
-	})
+	ctx := context.Background()
+	auth, err := authFlags.Options()
+	if err != nil {
+		return err
+	}
+
+	g, err := gerrit.New(ctx, auth, dawn.GerritURL)
 	if err != nil {
 		return err
 	}
diff --git a/tools/src/cmd/cts/common/constants.go b/tools/src/cmd/cts/common/constants.go
index 88f150a..8a0a7e2 100644
--- a/tools/src/cmd/cts/common/constants.go
+++ b/tools/src/cmd/cts/common/constants.go
@@ -14,12 +14,6 @@
 
 package common
 
-import (
-	"dawn.googlesource.com/dawn/tools/src/fileutils"
-	"go.chromium.org/luci/auth"
-	"go.chromium.org/luci/hardcoded/chromeinfra"
-)
-
 const (
 	// RollSubjectPrefix is the subject prefix for CTS roll changes
 	RollSubjectPrefix = "Roll third_party/webgpu-cts/ "
@@ -27,11 +21,3 @@
 	// DefaultCacheDir is the default directory for the results cache
 	DefaultCacheDir = "~/.cache/webgpu-cts-results"
 )
-
-// DefaultAuthOptions returns the default authentication options for use by
-// command line arguments.
-func DefaultAuthOptions() auth.Options {
-	def := chromeinfra.DefaultAuthOptions()
-	def.SecretsDir = fileutils.ExpandHome("~/.config/dawn-cts")
-	return def
-}
diff --git a/tools/src/cmd/cts/common/results.go b/tools/src/cmd/cts/common/results.go
index 3e4ed4d..df471ca 100644
--- a/tools/src/cmd/cts/common/results.go
+++ b/tools/src/cmd/cts/common/results.go
@@ -91,7 +91,7 @@
 	// CTS roll.
 	if ps.Change == 0 {
 		fmt.Println("no change specified, scanning gerrit for last CTS roll...")
-		gerrit, err := gerrit.New(cfg.Gerrit.Host, gerrit.Credentials{})
+		gerrit, err := gerrit.New(ctx, auth, cfg.Gerrit.Host)
 		if err != nil {
 			return nil, err
 		}
@@ -112,7 +112,7 @@
 	// If a change, but no patchset was specified, then query the most recent
 	// patchset.
 	if ps.Patchset == 0 {
-		gerrit, err := gerrit.New(cfg.Gerrit.Host, gerrit.Credentials{})
+		gerrit, err := gerrit.New(ctx, auth, cfg.Gerrit.Host)
 		if err != nil {
 			return nil, err
 		}
diff --git a/tools/src/cmd/cts/export/export.go b/tools/src/cmd/cts/export/export.go
index 2f85974..fdd0483 100644
--- a/tools/src/cmd/cts/export/export.go
+++ b/tools/src/cmd/cts/export/export.go
@@ -26,6 +26,7 @@
 	"strings"
 	"time"
 
+	"dawn.googlesource.com/dawn/tools/src/auth"
 	"dawn.googlesource.com/dawn/tools/src/cmd/cts/common"
 	"dawn.googlesource.com/dawn/tools/src/cts/result"
 	"dawn.googlesource.com/dawn/tools/src/fileutils"
@@ -57,7 +58,7 @@
 }
 
 func (c *cmd) RegisterFlags(ctx context.Context, cfg common.Config) ([]string, error) {
-	c.flags.auth.Register(flag.CommandLine, common.DefaultAuthOptions())
+	c.flags.auth.Register(flag.CommandLine, auth.DefaultAuthOptions())
 	c.flags.results.RegisterFlags(cfg)
 	return nil, nil
 }
diff --git a/tools/src/cmd/cts/results/results.go b/tools/src/cmd/cts/results/results.go
index 93eaf79..7bbd887 100644
--- a/tools/src/cmd/cts/results/results.go
+++ b/tools/src/cmd/cts/results/results.go
@@ -20,6 +20,7 @@
 	"fmt"
 	"os"
 
+	"dawn.googlesource.com/dawn/tools/src/auth"
 	"dawn.googlesource.com/dawn/tools/src/cmd/cts/common"
 	"dawn.googlesource.com/dawn/tools/src/cts/result"
 	"go.chromium.org/luci/auth/client/authcli"
@@ -48,7 +49,7 @@
 func (c *cmd) RegisterFlags(ctx context.Context, cfg common.Config) ([]string, error) {
 	flag.StringVar(&c.flags.output, "o", "results.txt", "output file. '-' writes to stdout")
 	c.flags.source.RegisterFlags(cfg)
-	c.flags.auth.Register(flag.CommandLine, common.DefaultAuthOptions())
+	c.flags.auth.Register(flag.CommandLine, auth.DefaultAuthOptions())
 	return nil, nil
 }
 
diff --git a/tools/src/cmd/cts/roll/roll.go b/tools/src/cmd/cts/roll/roll.go
index 244d85d..4b8db34 100644
--- a/tools/src/cmd/cts/roll/roll.go
+++ b/tools/src/cmd/cts/roll/roll.go
@@ -30,6 +30,7 @@
 	"text/tabwriter"
 	"time"
 
+	commonAuth "dawn.googlesource.com/dawn/tools/src/auth"
 	"dawn.googlesource.com/dawn/tools/src/buildbucket"
 	"dawn.googlesource.com/dawn/tools/src/cmd/cts/common"
 	"dawn.googlesource.com/dawn/tools/src/container"
@@ -90,7 +91,7 @@
 	gitPath, _ := exec.LookPath("git")
 	npmPath, _ := exec.LookPath("npm")
 	nodePath, _ := exec.LookPath("node")
-	c.flags.auth.Register(flag.CommandLine, common.DefaultAuthOptions())
+	c.flags.auth.Register(flag.CommandLine, commonAuth.DefaultAuthOptions())
 	flag.StringVar(&c.flags.gitPath, "git", gitPath, "path to git")
 	flag.StringVar(&c.flags.npmPath, "npm", npmPath, "path to npm")
 	flag.StringVar(&c.flags.nodePath, "node", nodePath, "path to node")
@@ -135,7 +136,7 @@
 	if err != nil {
 		return fmt.Errorf("failed to obtain authentication options: %w", err)
 	}
-	gerrit, err := gerrit.New(cfg.Gerrit.Host, gerrit.Credentials{})
+	gerrit, err := gerrit.New(ctx, auth, cfg.Gerrit.Host)
 	if err != nil {
 		return err
 	}
diff --git a/tools/src/cmd/cts/time/time.go b/tools/src/cmd/cts/time/time.go
index f96da47..a3f2d70 100644
--- a/tools/src/cmd/cts/time/time.go
+++ b/tools/src/cmd/cts/time/time.go
@@ -22,6 +22,7 @@
 	"sort"
 	"time"
 
+	"dawn.googlesource.com/dawn/tools/src/auth"
 	"dawn.googlesource.com/dawn/tools/src/cmd/cts/common"
 	"dawn.googlesource.com/dawn/tools/src/cts/query"
 	"dawn.googlesource.com/dawn/tools/src/cts/result"
@@ -55,7 +56,7 @@
 
 func (c *cmd) RegisterFlags(ctx context.Context, cfg common.Config) ([]string, error) {
 	c.flags.source.RegisterFlags(cfg)
-	c.flags.auth.Register(flag.CommandLine, common.DefaultAuthOptions())
+	c.flags.auth.Register(flag.CommandLine, auth.DefaultAuthOptions())
 	flag.IntVar(&c.flags.topN, "top", 0, "print the top N slowest tests")
 	flag.BoolVar(&c.flags.histogram, "histogram", false, "print a histogram of test timings")
 	flag.StringVar(&c.flags.query, "query", "", "test query to filter results")
diff --git a/tools/src/cmd/cts/update/update.go b/tools/src/cmd/cts/update/update.go
index ae242c7..65ba37a 100644
--- a/tools/src/cmd/cts/update/update.go
+++ b/tools/src/cmd/cts/update/update.go
@@ -22,6 +22,7 @@
 	"os"
 	"strings"
 
+	"dawn.googlesource.com/dawn/tools/src/auth"
 	"dawn.googlesource.com/dawn/tools/src/cmd/cts/common"
 	"dawn.googlesource.com/dawn/tools/src/cts/expectations"
 	"dawn.googlesource.com/dawn/tools/src/cts/query"
@@ -52,7 +53,7 @@
 func (c *cmd) RegisterFlags(ctx context.Context, cfg common.Config) ([]string, error) {
 	defaultExpectations := common.DefaultExpectationsPath()
 	c.flags.results.RegisterFlags(cfg)
-	c.flags.auth.Register(flag.CommandLine, common.DefaultAuthOptions())
+	c.flags.auth.Register(flag.CommandLine, auth.DefaultAuthOptions())
 	flag.StringVar(&c.flags.expectations, "expectations", defaultExpectations, "path to CTS expectations file to update")
 	return nil, nil
 }
diff --git a/tools/src/cmd/cts/validate/validate.go b/tools/src/cmd/cts/validate/validate.go
index 07c71cd..cdd7486 100644
--- a/tools/src/cmd/cts/validate/validate.go
+++ b/tools/src/cmd/cts/validate/validate.go
@@ -31,7 +31,7 @@
 type cmd struct {
 	flags struct {
 		expectations string // expectations file path
-		slow string         // slow test expectations file path
+		slow         string // slow test expectations file path
 	}
 }
 
diff --git a/tools/src/cmd/gerrit-stats/main.go b/tools/src/cmd/gerrit-stats/main.go
index 7dc816b..5c4733d 100644
--- a/tools/src/cmd/gerrit-stats/main.go
+++ b/tools/src/cmd/gerrit-stats/main.go
@@ -16,6 +16,7 @@
 package main
 
 import (
+	"context"
 	"flag"
 	"fmt"
 	"net/url"
@@ -24,24 +25,23 @@
 	"regexp"
 	"time"
 
+	"dawn.googlesource.com/dawn/tools/src/auth"
 	"dawn.googlesource.com/dawn/tools/src/dawn"
 	"dawn.googlesource.com/dawn/tools/src/gerrit"
 	"dawn.googlesource.com/dawn/tools/src/git"
+	"go.chromium.org/luci/auth/client/authcli"
 )
 
 const yyyymmdd = "2006-01-02"
 
 var (
-	// See https://dawn-review.googlesource.com/new-password for obtaining
-	// username and password for gerrit.
-	gerritUser  = flag.String("gerrit-user", "", "gerrit authentication username")
-	gerritPass  = flag.String("gerrit-pass", "", "gerrit authentication password")
 	repoFlag    = flag.String("repo", "dawn", "the project (tint or dawn)")
 	userFlag    = flag.String("user", defaultUser(), "user name / email")
 	afterFlag   = flag.String("after", "", "start date")
 	beforeFlag  = flag.String("before", "", "end date")
 	daysFlag    = flag.Int("days", 182, "interval in days (used if --after is not specified)")
 	verboseFlag = flag.Bool("v", false, "verbose mode - lists all the changes")
+	authFlags   = authcli.Flags{}
 )
 
 func defaultUser() string {
@@ -60,6 +60,8 @@
 }
 
 func main() {
+	authFlags.Register(flag.CommandLine, auth.DefaultAuthOptions())
+
 	flag.Parse()
 	if err := run(); err != nil {
 		fmt.Fprintln(os.Stderr, err)
@@ -91,9 +93,13 @@
 		after = before.Add(-time.Hour * time.Duration(24**daysFlag))
 	}
 
-	g, err := gerrit.New(dawn.GerritURL, gerrit.Credentials{
-		Username: *gerritUser, Password: *gerritPass,
-	})
+	ctx := context.Background()
+	auth, err := authFlags.Options()
+	if err != nil {
+		return err
+	}
+
+	g, err := gerrit.New(ctx, auth, dawn.GerritURL)
 	if err != nil {
 		return err
 	}
diff --git a/tools/src/cmd/snippets/main.go b/tools/src/cmd/snippets/main.go
index 97452b3..538d5b6 100644
--- a/tools/src/cmd/snippets/main.go
+++ b/tools/src/cmd/snippets/main.go
@@ -16,6 +16,7 @@
 package main
 
 import (
+	"context"
 	"flag"
 	"fmt"
 	"os"
@@ -23,22 +24,21 @@
 	"strings"
 	"time"
 
+	"dawn.googlesource.com/dawn/tools/src/auth"
 	"dawn.googlesource.com/dawn/tools/src/dawn"
 	"dawn.googlesource.com/dawn/tools/src/gerrit"
 	"dawn.googlesource.com/dawn/tools/src/git"
+	"go.chromium.org/luci/auth/client/authcli"
 )
 
 const yyyymmdd = "2006-01-02"
 
 var (
-	// See https://dawn-review.googlesource.com/new-password for obtaining
-	// username and password for gerrit.
-	gerritUser = flag.String("gerrit-user", "", "gerrit authentication username")
-	gerritPass = flag.String("gerrit-pass", "", "gerrit authentication password")
 	userFlag   = flag.String("user", defaultUser(), "user name / email")
 	afterFlag  = flag.String("after", "", "start date")
 	beforeFlag = flag.String("before", "", "end date")
 	daysFlag   = flag.Int("days", 7, "interval in days (used if --after is not specified)")
+	authFlags  = authcli.Flags{}
 )
 
 func defaultUser() string {
@@ -57,6 +57,8 @@
 }
 
 func main() {
+	authFlags.Register(flag.CommandLine, auth.DefaultAuthOptions())
+
 	flag.Parse()
 	if err := run(); err != nil {
 		fmt.Fprintln(os.Stderr, err)
@@ -88,9 +90,13 @@
 		after = before.Add(-time.Hour * time.Duration(24**daysFlag))
 	}
 
-	g, err := gerrit.New(dawn.GerritURL, gerrit.Credentials{
-		Username: *gerritUser, Password: *gerritPass,
-	})
+	ctx := context.Background()
+	auth, err := authFlags.Options()
+	if err != nil {
+		return err
+	}
+
+	g, err := gerrit.New(ctx, auth, dawn.GerritURL)
 	if err != nil {
 		return err
 	}
diff --git a/tools/src/gerrit/gerrit.go b/tools/src/gerrit/gerrit.go
index f3641eb..2777530 100644
--- a/tools/src/gerrit/gerrit.go
+++ b/tools/src/gerrit/gerrit.go
@@ -16,17 +16,16 @@
 package gerrit
 
 import (
+	"context"
 	"flag"
 	"fmt"
-	"io/ioutil"
 	"net/url"
-	"os"
-	"regexp"
 	"strconv"
 	"strings"
 
 	"dawn.googlesource.com/dawn/tools/src/container"
 	"github.com/andygrunwald/go-gerrit"
+	"go.chromium.org/luci/auth"
 )
 
 // Gerrit is the interface to gerrit
@@ -35,12 +34,6 @@
 	authenticated bool
 }
 
-// Credentials holds the user name and password used to access Gerrit.
-type Credentials struct {
-	Username string
-	Password string
-}
-
 // Patchset refers to a single gerrit patchset
 type Patchset struct {
 	// Gerrit host
@@ -88,41 +81,20 @@
 	return fmt.Sprintf("refs/changes/%v/%v/%v", shortChange, p.Change, p.Patchset)
 }
 
-// LoadCredentials attempts to load the gerrit credentials for the given gerrit
-// URL from the git cookies file. Returns an empty Credentials on failure.
-func LoadCredentials(url string) Credentials {
-	cookiesFile := os.Getenv("HOME") + "/.gitcookies"
-	if cookies, err := ioutil.ReadFile(cookiesFile); err == nil {
-		url := strings.TrimSuffix(strings.TrimPrefix(url, "https://"), "/")
-		re := regexp.MustCompile(url + `/?\s+(?:FALSE|TRUE)[\s/]+(?:FALSE|TRUE)\s+[0-9]+\s+.\s+(.*)=(.*)`)
-		matches := re.FindAllStringSubmatch(string(cookies), -1)
-		if matches != nil {
-			match := matches[len(matches)-1]
-			if len(match) == 3 {
-				return Credentials{match[1], match[2]}
-			}
-		}
-	}
-	return Credentials{}
-}
-
 // New returns a new Gerrit instance. If credentials are not provided, then
 // New() will automatically attempt to load them from the gitcookies file.
-func New(url string, cred Credentials) (*Gerrit, error) {
-	client, err := gerrit.NewClient(url, nil)
+func New(ctx context.Context, opts auth.Options, url string) (*Gerrit, error) {
+	http, err := auth.NewAuthenticator(ctx, auth.InteractiveLogin, opts).Client()
 	if err != nil {
 		return nil, fmt.Errorf("couldn't create gerrit client: %w", err)
 	}
 
-	if cred.Username == "" {
-		cred = LoadCredentials(url)
+	client, err := gerrit.NewClient(url, http)
+	if err != nil {
+		return nil, fmt.Errorf("couldn't create gerrit client: %w", err)
 	}
 
-	if cred.Username != "" {
-		client.Authentication.SetBasicAuth(cred.Username, cred.Password)
-	}
-
-	return &Gerrit{client, cred.Username != ""}, nil
+	return &Gerrit{client, true}, nil
 }
 
 // QueryExtraData holds extra data to query for with QueryChangesWith()
@@ -164,7 +136,7 @@
 			ChangeOptions: changeOpts,
 		})
 		if err != nil {
-			return nil, "", g.maybeWrapError(err)
+			return nil, "", err
 		}
 
 		changes = append(changes, *batch...)
@@ -186,7 +158,7 @@
 func (g *Gerrit) ChangesSubmittedTogether(changeID string) (changes []gerrit.ChangeInfo, err error) {
 	info, _, err := g.client.Changes.ChangesSubmittedTogether(changeID)
 	if err != nil {
-		return nil, g.maybeWrapError(err)
+		return nil, err
 	}
 	return *info, nil
 }
@@ -197,7 +169,7 @@
 		Labels:  map[string]string{label: fmt.Sprint(value)},
 	})
 	if err != nil {
-		return g.maybeWrapError(err)
+		return err
 	}
 	return nil
 }
@@ -206,7 +178,7 @@
 func (g *Gerrit) Abandon(changeID string) error {
 	_, _, err := g.client.Changes.AbandonChange(changeID, &gerrit.AbandonInput{})
 	if err != nil {
-		return g.maybeWrapError(err)
+		return err
 	}
 	return nil
 }
@@ -222,7 +194,7 @@
 		WorkInProgress: wip,
 	})
 	if err != nil {
-		return nil, g.maybeWrapError(err)
+		return nil, err
 	}
 	return change, nil
 }
@@ -236,25 +208,25 @@
 			Message: newCommitMsg,
 		})
 		if err != nil && resp.StatusCode != 409 { // 409 no changes were made
-			return Patchset{}, g.maybeWrapError(err)
+			return Patchset{}, err
 		}
 	}
 	for path, content := range files {
 		resp, err := g.client.Changes.ChangeFileContentInChangeEdit(changeID, path, content)
 		if err != nil && resp.StatusCode != 409 { // 409 no changes were made
-			return Patchset{}, g.maybeWrapError(err)
+			return Patchset{}, err
 		}
 	}
 	for _, path := range deletedFiles {
 		resp, err := g.client.Changes.DeleteFileInChangeEdit(changeID, path)
 		if err != nil && resp.StatusCode != 409 { // 409 no changes were made
-			return Patchset{}, g.maybeWrapError(err)
+			return Patchset{}, err
 		}
 	}
 
 	resp, err := g.client.Changes.PublishChangeEdit(changeID, "NONE")
 	if err != nil && resp.StatusCode != 409 { // 409 no changes were made
-		return Patchset{}, g.maybeWrapError(err)
+		return Patchset{}, err
 	}
 
 	return g.LatestPatchset(changeID)
@@ -266,7 +238,7 @@
 		AdditionalFields: []string{"CURRENT_REVISION"},
 	})
 	if err != nil {
-		return Patchset{}, g.maybeWrapError(err)
+		return Patchset{}, err
 	}
 	ps := Patchset{
 		Host:     g.client.BaseURL().Host,
@@ -283,7 +255,7 @@
 		Add: tags.List(),
 	})
 	if err != nil && resp.StatusCode != 409 { // 409: already ready
-		return g.maybeWrapError(err)
+		return err
 	}
 	return nil
 }
@@ -333,7 +305,7 @@
 	}
 	_, _, err := g.client.Changes.SetReview(strconv.Itoa(ps.Change), strconv.Itoa(ps.Patchset), input)
 	if err != nil {
-		return g.maybeWrapError(err)
+		return err
 	}
 	return nil
 }
@@ -344,18 +316,7 @@
 		Message: message,
 	})
 	if err != nil && resp.StatusCode != 409 { // 409: already ready
-		return g.maybeWrapError(err)
+		return err
 	}
 	return nil
 }
-
-func (g *Gerrit) maybeWrapError(err error) error {
-	if err != nil && !g.authenticated {
-		return fmt.Errorf(`query failed, possibly because of authentication.
-See https://dawn.googlesource.com/new-password for obtaining a username
-and password which can be provided with --gerrit-user and --gerrit-pass.
-Note: This tool will scan ~/.gitcookies for credentials.
-%w`, err)
-	}
-	return err
-}