blob: 2b02d0f0b4f6d9de9116b5e3040d8da111558645 [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package cli
import (
"context"
"fmt"
"strings"
"github.com/maruel/subcommands"
"google.golang.org/protobuf/encoding/protojson"
"go.chromium.org/luci/common/cli"
"go.chromium.org/luci/common/data/text"
"go.chromium.org/luci/common/errors"
"go.chromium.org/luci/common/system/signals"
sinkpb "go.chromium.org/luci/resultdb/sink/proto/v1"
"infra/tools/dirmd"
dirmdpb "infra/tools/dirmd/proto"
)
func cmdLocationTags() *subcommands.Command {
return &subcommands.Command{
UsageLine: `location-tags`,
ShortDesc: "generate test location tags from a directory tree",
LongDesc: text.Doc(`
Generate test location tags from a directory tree to stdout or to a file.
The output format is JSON form of luci.resultsink.v1.LocationTags protobuf
message.
`),
CommandRun: func() subcommands.CommandRun {
r := &tagRun{}
r.RegisterOutputFlag()
r.Flags.StringVar(&r.root, "root", ".", "Path to the root directory")
r.Flags.StringVar(&r.repo, "repo", "", "Gitiles URL as the identifier for a repo. In the format of https://<host>/<project>. Must not end with .git.")
return r
},
}
}
type tagRun struct {
baseCommandRun
root string
repo string
}
func (r *tagRun) Run(a subcommands.Application, args []string, env subcommands.Env) int {
ctx := cli.GetContext(a, r, env)
return r.done(ctx, r.run(ctx, args))
}
func (r *tagRun) run(ctx context.Context, args []string) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
defer signals.HandleInterrupt(cancel)()
if len(args) != 0 {
return errors.Reason("unexpected positional arguments: %q", args).Err()
}
if err := r.validate(); err != nil {
return err
}
mapping, err := dirmd.ReadMapping(ctx, dirmdpb.MappingForm_REDUCED, r.root)
if err != nil {
return err
}
tags, err := dirmd.ToLocationTags(mapping)
if err != nil {
return err
}
return r.writeTags(&sinkpb.LocationTags{
Repos: map[string]*sinkpb.LocationTags_Repo{
r.repo: tags,
},
})
}
func (r *tagRun) validate() error {
switch {
case r.repo == "":
return fmt.Errorf("-repo is required")
case strings.HasSuffix(r.repo, ".git"):
return fmt.Errorf("-repo must not end with .git")
default:
return nil
}
}
func (r *tagRun) writeTags(tags *sinkpb.LocationTags) error {
data, err := protojson.Marshal(tags)
if err != nil {
return err
}
return r.writeTextOutput(data)
}