go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/client/cmd/gitiles/projects.go (about)

     1  // Copyright 2017 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package main
    16  
    17  import (
    18  	"encoding/json"
    19  	"fmt"
    20  	"os"
    21  	"strings"
    22  
    23  	"github.com/maruel/subcommands"
    24  
    25  	"go.chromium.org/luci/auth"
    26  	"go.chromium.org/luci/common/api/gitiles"
    27  	"go.chromium.org/luci/common/errors"
    28  	gitilespb "go.chromium.org/luci/common/proto/gitiles"
    29  	"go.chromium.org/luci/common/retry"
    30  	"go.chromium.org/luci/common/retry/transient"
    31  	"go.chromium.org/luci/grpc/grpcutil"
    32  )
    33  
    34  func cmdProjects(authOpts auth.Options) *subcommands.Command {
    35  	return &subcommands.Command{
    36  		UsageLine: "projects host",
    37  		ShortDesc: "list all available projects",
    38  		LongDesc: `List all available Gitiles projects.
    39  
    40  Example: projects chromium.googlesource.com`,
    41  
    42  		CommandRun: func() subcommands.CommandRun {
    43  			c := projectsRun{}
    44  			c.commonFlags.Init(authOpts)
    45  			c.Flags.StringVar(&c.jsonOutput, "json-output", "", "Path to write operation results to.")
    46  			return &c
    47  		},
    48  	}
    49  }
    50  
    51  type projectsRun struct {
    52  	commonFlags
    53  	jsonOutput string
    54  }
    55  
    56  func (c *projectsRun) Parse(a subcommands.Application, args []string) error {
    57  	switch err := c.commonFlags.Parse(); {
    58  	case err != nil:
    59  		return err
    60  	case len(args) != 1:
    61  		return errors.New("host argument is expected")
    62  	default:
    63  		return nil
    64  	}
    65  }
    66  
    67  func (c *projectsRun) main(a subcommands.Application, args []string) error {
    68  	ctx := c.defaultFlags.MakeLoggingContext(os.Stderr)
    69  
    70  	if strings.Index(args[0], "/") != -1 {
    71  		return fmt.Errorf("host mustn't contain any slashes %s", args[0])
    72  	}
    73  
    74  	authCl, err := c.createAuthClient()
    75  	if err != nil {
    76  		return err
    77  	}
    78  	g, err := gitiles.NewRESTClient(authCl, args[0], true)
    79  	if err != nil {
    80  		return err
    81  	}
    82  
    83  	var res *gitilespb.ProjectsResponse
    84  	if err := retry.Retry(ctx, transient.Only(retry.Default), func() error {
    85  		var err error
    86  		res, err = g.Projects(ctx, &gitilespb.ProjectsRequest{})
    87  		return grpcutil.WrapIfTransient(err)
    88  	}, nil); err != nil {
    89  		return err
    90  	}
    91  
    92  	if c.jsonOutput == "" {
    93  		for _, project := range res.Projects {
    94  			fmt.Println(project)
    95  		}
    96  		return nil
    97  	}
    98  
    99  	out := os.Stdout
   100  	if c.jsonOutput != "-" {
   101  		out, err = os.Create(c.jsonOutput)
   102  		if err != nil {
   103  			return err
   104  		}
   105  		defer out.Close()
   106  	}
   107  
   108  	data, err := json.MarshalIndent(res.Projects, "", "  ")
   109  	if err != nil {
   110  		return err
   111  	}
   112  	_, err = out.Write(data)
   113  	return err
   114  }
   115  
   116  func (c *projectsRun) Run(a subcommands.Application, args []string, _ subcommands.Env) int {
   117  	if err := c.Parse(a, args); err != nil {
   118  		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
   119  		return 1
   120  	}
   121  	if err := c.main(a, args); err != nil {
   122  		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
   123  		return 1
   124  	}
   125  	return 0
   126  }