Centralize definition of all Gitiles related flags.

Change-Id: If7468279d763115a453865c33f58bde91b3dce6e
diff --git a/cmd/slothfs-expand-manifest/main.go b/cmd/slothfs-expand-manifest/main.go
index 48ac2e1..c58b508 100644
--- a/cmd/slothfs-expand-manifest/main.go
+++ b/cmd/slothfs-expand-manifest/main.go
@@ -27,26 +27,12 @@
 )
 
 func main() {
-	gitilesURL := flag.String("gitiles", "", "URL for gitiles")
+	gitilesOptions := gitiles.DefineFlags()
 	branch := flag.String("branch", "master", "branch to use for manifest")
 	repo := flag.String("repo", "platform/manifest", "manifest repository")
-	cookieJarPath := flag.String("cookies", "", "path to cURL-style cookie jar file.")
-	agent := flag.String("agent", "slothfs-expand", "gitiles User-Agent string to use.")
 	flag.Parse()
 
-	if *gitilesURL == "" {
-		log.Fatal("must set --gitiles")
-	}
-
-	opts := gitiles.Options{
-		UserAgent: *agent,
-	}
-
-	if err := opts.LoadCookieJar(*cookieJarPath); err != nil {
-		log.Fatalf("LoadCookieJar(%s): %v", *cookieJarPath, err)
-	}
-
-	service, err := gitiles.NewService(*gitilesURL, opts)
+	service, err := gitiles.NewService(*gitilesOptions)
 	if err != nil {
 		log.Fatalf("NewService: %v", err)
 	}
diff --git a/cmd/slothfs-gitiles-test/main.go b/cmd/slothfs-gitiles-test/main.go
index 4262998..8bfe36f 100644
--- a/cmd/slothfs-gitiles-test/main.go
+++ b/cmd/slothfs-gitiles-test/main.go
@@ -29,27 +29,14 @@
 )
 
 func main() {
-	gitilesURL := flag.String("gitiles", "", "URL for gitiles")
-	cookieJarPath := flag.String("cookies", "", "path to cURL-style cookie jar file.")
-	agent := flag.String("agent", "slothfs-expand", "gitiles User-Agent string to use.")
 	tap := flag.Bool("tap", false, "if set, tap traffic exchanged with $http_proxy")
+	gitilesOptions := gitiles.DefineFlags()
 	flag.Parse()
 
 	if *tap {
 		tapTraffic()
 	}
-	if *gitilesURL == "" {
-		log.Fatal("must set --gitiles")
-	}
-
-	opts := gitiles.Options{
-		UserAgent: *agent,
-	}
-	if err := opts.LoadCookieJar(*cookieJarPath); err != nil {
-		log.Fatalf("LoadCookieJar(%s): %v", *cookieJarPath, err)
-	}
-
-	service, err := gitiles.NewService(*gitilesURL, opts)
+	service, err := gitiles.NewService(*gitilesOptions)
 	if err != nil {
 		log.Fatalf("NewService: %v", err)
 	}
diff --git a/cmd/slothfs-gitilesfs/main.go b/cmd/slothfs-gitilesfs/main.go
index ebe6ca7..52e2543 100644
--- a/cmd/slothfs-gitilesfs/main.go
+++ b/cmd/slothfs-gitilesfs/main.go
@@ -28,11 +28,11 @@
 )
 
 func main() {
-	url := flag.String("gitiles", "", "URL of gitiles service")
 	branch := flag.String("branch", "master", "branch name")
 	repo := flag.String("repo", "", "repository name")
 	debug := flag.Bool("debug", false, "print debug info")
 	cacheDir := flag.String("cache", filepath.Join(os.Getenv("HOME"), ".cache", "slothfs"), "cache dir")
+	gitilesOptions := gitiles.DefineFlags()
 	flag.Parse()
 
 	if *cacheDir == "" {
@@ -48,7 +48,7 @@
 		log.Printf("NewCache: %v", err)
 	}
 
-	service, err := gitiles.NewService(*url, gitiles.Options{})
+	service, err := gitiles.NewService(*gitilesOptions)
 	if err != nil {
 		log.Printf("NewService: %v", err)
 	}
diff --git a/cmd/slothfs-manifestfs/main.go b/cmd/slothfs-manifestfs/main.go
index dfd1a0e..e0e9c07 100644
--- a/cmd/slothfs-manifestfs/main.go
+++ b/cmd/slothfs-manifestfs/main.go
@@ -31,10 +31,10 @@
 
 func main() {
 	manifestPath := flag.String("manifest", "", "expanded manifest file path")
-	gitilesURL := flag.String("gitiles", "", "gitiles URL. If unset, derive from manifest location.")
 	cacheDir := flag.String("cache", filepath.Join(os.Getenv("HOME"), ".cache", "slothfs"), "cache dir")
 	debug := flag.Bool("debug", false, "print debug info")
 	config := flag.String("config", "", "JSON file configuring what repositories should be cloned.")
+	gitilesOptions := gitiles.DefineFlags()
 	flag.Parse()
 
 	if *manifestPath == "" {
@@ -43,12 +43,9 @@
 	if *cacheDir == "" {
 		log.Fatal("must set --cache")
 	}
-	if *gitilesURL == "" {
-		log.Fatal("must set --gitiles")
-	}
 
 	if len(flag.Args()) < 1 {
-		log.Fatal("usage: main -gitiles URL -repo REPO [-branch BRANCH] MOUNT-POINT")
+		log.Fatal("mountpoint argument missing.")
 	}
 	mntDir := flag.Arg(0)
 
@@ -57,7 +54,7 @@
 		log.Printf("NewCache: %v", err)
 	}
 
-	service, err := gitiles.NewService(*gitilesURL, gitiles.Options{})
+	service, err := gitiles.NewService(*gitilesOptions)
 	if err != nil {
 		log.Printf("NewService: %v", err)
 	}
diff --git a/cmd/slothfs-multifs/main.go b/cmd/slothfs-multifs/main.go
index 5dbad99..93dcb20 100644
--- a/cmd/slothfs-multifs/main.go
+++ b/cmd/slothfs-multifs/main.go
@@ -29,20 +29,15 @@
 )
 
 func main() {
-	gitilesURL := flag.String("gitiles", "", "gitiles URL. If unset, derive from manifest location.")
 	cacheDir := flag.String("cache", filepath.Join(os.Getenv("HOME"), ".cache", "slothfs"), "cache dir")
 	debug := flag.Bool("debug", false, "print debug info")
 	config := flag.String("config", filepath.Join(os.Getenv("HOME"), ".config", "slothfs"), "directory with configuration files.")
-	cookieJarPath := flag.String("cookies", "", "path to cURL-style cookie jar file.")
-	agent := flag.String("agent", "slothfs-multifs", "gitiles User-Agent string to use.")
+	gitilesOptions := gitiles.DefineFlags()
 	flag.Parse()
 
 	if *cacheDir == "" {
 		log.Fatal("must set --cache")
 	}
-	if *gitilesURL == "" {
-		log.Fatal("must set --gitiles")
-	}
 
 	if len(flag.Args()) < 1 {
 		log.Fatal("mountpoint argument missing.")
@@ -55,14 +50,7 @@
 		log.Printf("NewCache: %v", err)
 	}
 
-	gitilesOpts := gitiles.Options{
-		UserAgent: *agent,
-	}
-	if err := gitilesOpts.LoadCookieJar(*cookieJarPath); err != nil {
-		log.Fatalf("LoadCookieJar(%s): %v", *cookieJarPath, err)
-	}
-
-	service, err := gitiles.NewService(*gitilesURL, gitilesOpts)
+	service, err := gitiles.NewService(*gitilesOptions)
 	if err != nil {
 		log.Printf("NewService: %v", err)
 	}
diff --git a/fs/gitilesfs_test.go b/fs/gitilesfs_test.go
index b39ea25..a07b96d 100644
--- a/fs/gitilesfs_test.go
+++ b/fs/gitilesfs_test.go
@@ -639,9 +639,9 @@
 		return nil, err
 	}
 
-	fixture.service, err = gitiles.NewService(
-		fmt.Sprintf("http://%s", fixture.testServer.listener.Addr().String()),
-		gitiles.Options{})
+	fixture.service, err = gitiles.NewService(gitiles.Options{
+		Address: fmt.Sprintf("http://%s", fixture.testServer.listener.Addr().String()),
+	})
 	if err != nil {
 		return nil, err
 	}
diff --git a/gitiles/client.go b/gitiles/client.go
index 9422540..36b4424 100644
--- a/gitiles/client.go
+++ b/gitiles/client.go
@@ -19,6 +19,7 @@
 	"bytes"
 	"encoding/base64"
 	"encoding/json"
+	"flag"
 	"fmt"
 	"io/ioutil"
 	"log"
@@ -37,6 +38,7 @@
 	addr    url.URL
 	client  http.Client
 	agent   string
+	jar     http.CookieJar
 }
 
 // Addr returns the address of the gitiles service.
@@ -44,39 +46,47 @@
 	return s.addr.String()
 }
 
-// Options specifies how much load we can put on remote Gitiles servers.
+// Options configures the the Gitiles service.
 type Options struct {
+	// A URL for the Gitiles service.
+	Address string
+
 	BurstQPS     int
 	SustainedQPS float64
 
-	// A writable cookie jar for storing (among others) authentication cookies.
-	CookieJar http.CookieJar
+	// Path to a Netscape/Mozilla style cookie file.
+	CookieJar string
 
 	// UserAgent defines how we present ourself to the server.
 	UserAgent string
 }
 
-// LoadCookieJar sets up a cookiejar file to load and watch for
-// changes.
-func (o *Options) LoadCookieJar(nm string) error {
-	if nm == "" {
-		return nil
-	}
+var defaultOptions Options
 
-	jar, err := cookie.NewJar(nm)
-	if err != nil {
-		return err
-	}
-	if err := cookie.WatchJar(jar, nm); err != nil {
-		return err
-	}
-
-	o.CookieJar = jar
-	return nil
+// DefineFlags sets up standard command line flags, and returns the
+// options struct in which the values are put.
+func DefineFlags() *Options {
+	flag.StringVar(&defaultOptions.Address, "gitiles_url", "https://android.googlesource.com", "URL of the gitiles service.")
+	flag.StringVar(&defaultOptions.CookieJar, "gitiles_cookies", "", "path to cURL-style cookie jar file.")
+	flag.StringVar(&defaultOptions.UserAgent, "gitiles_agent", "slothfs", "gitiles User-Agent string to use.")
+	flag.IntVar(&defaultOptions.BurstQPS, "gitiles_qps", 4, "maximum Gitiles QPS")
+	return &defaultOptions
 }
 
 // NewService returns a new Gitiles JSON client.
-func NewService(addr string, opts Options) (*Service, error) {
+func NewService(opts Options) (*Service, error) {
+	var jar http.CookieJar
+	if nm := opts.CookieJar; nm != "" {
+		var err error
+		jar, err = cookie.NewJar(nm)
+		if err != nil {
+			return nil, err
+		}
+		if err := cookie.WatchJar(jar, nm); err != nil {
+			return nil, err
+		}
+	}
+
 	if opts.BurstQPS == 0 {
 		opts.BurstQPS = 4
 	}
@@ -84,7 +94,7 @@
 		opts.SustainedQPS = 0.5
 	}
 
-	url, err := url.Parse(addr)
+	url, err := url.Parse(opts.Address)
 	if err != nil {
 		return nil, err
 	}
@@ -94,7 +104,7 @@
 		agent:   opts.UserAgent,
 	}
 
-	s.client.Jar = opts.CookieJar
+	s.client.Jar = jar
 	s.client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
 		req.Header.Set("User-Agent", s.agent)
 		return nil
diff --git a/populate/e2e_test.go b/populate/e2e_test.go
index 3b51536..619e630 100644
--- a/populate/e2e_test.go
+++ b/populate/e2e_test.go
@@ -115,7 +115,9 @@
 	}
 	go abortListener(fix.abortGitiles)
 
-	service, err := gitiles.NewService(fmt.Sprintf("http://%s/", fix.abortGitiles.Addr()), gitiles.Options{})
+	service, err := gitiles.NewService(gitiles.Options{
+		Address: fmt.Sprintf("http://%s/", fix.abortGitiles.Addr()),
+	})
 	if err != nil {
 		log.Printf("NewService: %v", err)
 	}