kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/services/cli/command_ls.go (about) 1 /* 2 * Copyright 2017 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 cli 18 19 import ( 20 "context" 21 "errors" 22 "flag" 23 "fmt" 24 "path/filepath" 25 26 "kythe.io/kythe/go/services/filetree" 27 "kythe.io/kythe/go/util/kytheuri" 28 29 ftpb "kythe.io/kythe/proto/filetree_go_proto" 30 ) 31 32 type lsCommand struct { 33 baseKytheCommand 34 lsURIs bool 35 filesOnly bool 36 dirsOnly bool 37 includeMissing bool 38 } 39 40 func (lsCommand) Name() string { return "ls" } 41 func (lsCommand) Synopsis() string { return "list a directory's contents" } 42 func (c *lsCommand) SetFlags(flag *flag.FlagSet) { 43 flag.BoolVar(&c.lsURIs, "uris", false, "Display files/directories as Kythe URIs") 44 flag.BoolVar(&c.filesOnly, "files", false, "Display only files") 45 flag.BoolVar(&c.dirsOnly, "dirs", false, "Display only directories") 46 flag.BoolVar(&c.includeMissing, "include_files_missing_text", false, "Include files missing text") 47 } 48 func (c lsCommand) Run(ctx context.Context, flag *flag.FlagSet, api API) error { 49 if c.filesOnly && c.dirsOnly { 50 return errors.New("--files and --dirs are mutually exclusive") 51 } 52 53 if len(flag.Args()) == 0 { 54 req := &ftpb.CorpusRootsRequest{} 55 LogRequest(req) 56 cr, err := api.FileTreeService.CorpusRoots(ctx, req) 57 if err != nil { 58 return err 59 } 60 return c.displayCorpusRoots(cr) 61 } 62 var corpus, root, path string 63 switch len(flag.Args()) { 64 case 1: 65 uri, err := kytheuri.Parse(flag.Arg(0)) 66 if err != nil { 67 return fmt.Errorf("invalid uri %q: %v", flag.Arg(0), err) 68 } 69 corpus = uri.Corpus 70 root = uri.Root 71 path = uri.Path 72 default: 73 return fmt.Errorf("too many arguments given: %v", flag.Args()) 74 } 75 path = filetree.CleanDirPath(path) 76 req := &ftpb.DirectoryRequest{ 77 Corpus: corpus, 78 Root: root, 79 Path: path, 80 81 IncludeFilesMissingText: c.includeMissing, 82 } 83 LogRequest(req) 84 dir, err := api.FileTreeService.Directory(ctx, req) 85 if err != nil { 86 return err 87 } 88 89 if c.filesOnly { 90 dir.Entry = filterEntries(dir.Entry, ftpb.DirectoryReply_FILE) 91 } else if c.dirsOnly { 92 dir.Entry = filterEntries(dir.Entry, ftpb.DirectoryReply_DIRECTORY) 93 } 94 95 return c.displayDirectory(dir) 96 } 97 98 func filterEntries(entries []*ftpb.DirectoryReply_Entry, kind ftpb.DirectoryReply_Kind) []*ftpb.DirectoryReply_Entry { 99 var j int 100 for _, e := range entries { 101 if e.Kind == kind { 102 entries[j] = e 103 j++ 104 } 105 } 106 return entries[:j] 107 } 108 109 func (c lsCommand) displayCorpusRoots(cr *ftpb.CorpusRootsReply) error { 110 if DisplayJSON { 111 return PrintJSONMessage(cr) 112 } 113 114 for _, corpus := range cr.Corpus { 115 for _, root := range corpus.Root { 116 var err error 117 if c.lsURIs { 118 uri := kytheuri.URI{ 119 Corpus: corpus.Name, 120 Root: root, 121 } 122 _, err = fmt.Fprintln(out, uri.String()) 123 } else { 124 _, err = fmt.Fprintln(out, filepath.Join(corpus.Name, root)) 125 } 126 if err != nil { 127 return err 128 } 129 } 130 } 131 return nil 132 } 133 134 func (c lsCommand) displayDirectory(d *ftpb.DirectoryReply) error { 135 if DisplayJSON { 136 return PrintJSONMessage(d) 137 } 138 139 for _, e := range d.Entry { 140 name := e.Name 141 if c.lsURIs { 142 uri := &kytheuri.URI{ 143 Corpus: d.Corpus, 144 Root: d.Root, 145 Path: filepath.Join(d.Path, name), 146 } 147 name = uri.String() 148 } else if e.Kind == ftpb.DirectoryReply_DIRECTORY { 149 name += "/" 150 } 151 152 if _, err := fmt.Fprintln(out, name); err != nil { 153 return err 154 } 155 } 156 return nil 157 }