kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/platform/tools/kzip/infocmd/infocmd.go (about) 1 /* 2 * Copyright 2019 The Kythe Authors. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // Package infocmd provides the kzip command for obtaining info about a kzip archive. 18 package infocmd // import "kythe.io/kythe/go/platform/tools/kzip/infocmd" 19 20 import ( 21 "context" 22 "flag" 23 "fmt" 24 "os" 25 "runtime" 26 "strings" 27 28 "kythe.io/kythe/go/platform/kzip" 29 "kythe.io/kythe/go/platform/kzip/info" 30 "kythe.io/kythe/go/platform/vfs" 31 "kythe.io/kythe/go/util/cmdutil" 32 33 "github.com/google/subcommands" 34 "google.golang.org/protobuf/encoding/protojson" 35 "google.golang.org/protobuf/encoding/prototext" 36 ) 37 38 type infoCommand struct { 39 cmdutil.Info 40 41 input string 42 writeFormat string 43 readConcurrency int 44 } 45 46 // New creates a new subcommand for obtaining info on a kzip file. 47 func New() subcommands.Command { 48 return &infoCommand{ 49 Info: cmdutil.NewInfo("info", "info on single kzip archive", "--input path"), 50 } 51 } 52 53 // SetFlags implements the subcommands interface and provides command-specific flags 54 // for the info command. 55 func (c *infoCommand) SetFlags(fs *flag.FlagSet) { 56 fs.StringVar(&c.input, "input", "", "Path for input kzip file (required)") 57 fs.StringVar(&c.writeFormat, "write_format", "json", "Output format, can be 'json' or 'proto'") 58 fs.IntVar(&c.readConcurrency, "read_concurrency", runtime.NumCPU(), "Max concurrency of reading compilation units from the kzip. Defaults to the number of cpu cores.") 59 } 60 61 // Execute implements the subcommands interface and gathers info from the requested file. 62 func (c *infoCommand) Execute(ctx context.Context, fs *flag.FlagSet, _ ...any) subcommands.ExitStatus { 63 if c.input == "" { 64 return c.Fail("Required --input path missing") 65 } 66 f, err := vfs.Open(ctx, c.input) 67 if err != nil { 68 return c.Fail("Opening archive: %v", err) 69 } 70 defer f.Close() 71 72 c.writeFormat = strings.ToLower(c.writeFormat) 73 if c.writeFormat != "json" && c.writeFormat != "proto" { 74 return c.Fail("Invalid --write_format. Can be 'json' or 'proto'.") 75 } 76 77 s, err := vfs.Stat(ctx, c.input) 78 if err != nil { 79 return c.Fail("Couldn't stat kzip file: %v", err) 80 } 81 kzipInfo, err := info.KzipInfo(f, s.Size(), kzip.ReadConcurrency(c.readConcurrency)) 82 if err != nil { 83 return c.Fail("Scanning kzip: %v", err) 84 } 85 var rec []byte 86 switch c.writeFormat { 87 case "json": 88 m := protojson.MarshalOptions{UseProtoNames: true} 89 rec, err = m.Marshal(kzipInfo) 90 if err != nil { 91 return c.Fail("Marshaling json: %v", err) 92 } 93 case "proto": 94 rec, err = prototext.Marshal(kzipInfo) 95 if err != nil { 96 return c.Fail("Marshaling text: %v", err) 97 } 98 } 99 // Add a new line to the output after we write the kzip info. 100 defer func() { fmt.Println() }() 101 if _, err := os.Stdout.Write(rec); err != nil { 102 return c.Fail("Writing unit: %v", err) 103 } 104 105 return subcommands.ExitSuccess 106 }