fork of https://github.com/sourcegraph/zoekt
0

Configure Feed

Select the types of activity you want to include in your feed.

ctags: remove support for exuberant-ctags (#585)

We never test or use this code path. I am also unaware of any users of
this code. If we hear complaints I'd recommend adding this code back in
a way that conforms to the parser interface.

Test Plan: go test

+8 -299
+1
.bazelignore
··· 1 + .direnv
+2 -5
build/builder.go
··· 279 279 return ctags 280 280 } 281 281 282 - if ctags, err := exec.LookPath("ctags-exuberant"); err == nil { 283 - return ctags 284 - } 285 282 return "" 286 283 } 287 284 ··· 550 547 return nil, fmt.Errorf("ctags binary not found, but CTagsMustSucceed set") 551 548 } 552 549 553 - if strings.Contains(opts.CTagsPath, "universal-ctags") { 550 + if opts.CTagsPath != "" { 554 551 parser, err := ctags.NewParser(opts.CTagsPath) 555 552 if err != nil && opts.CTagsMustSucceed { 556 553 return nil, fmt.Errorf("ctags.NewParser: %v", err) ··· 998 995 999 996 func (b *Builder) buildShard(todo []*zoekt.Document, nextShardNum int) (*finishedShard, error) { 1000 997 if !b.opts.DisableCTags && b.opts.CTagsPath != "" { 1001 - err := ctagsAddSymbols(todo, b.parser, b.opts.CTagsPath) 998 + err := ctagsAddSymbolsParser(todo, b.parser) 1002 999 if b.opts.CTagsMustSucceed && err != nil { 1003 1000 return nil, err 1004 1001 }
+1 -1
build/builder_test.go
··· 482 482 }{ 483 483 { 484 484 name: "update option CTagsPath to non default", 485 - options: func(options *Options) { options.CTagsPath = "ctags_updated_test" }, 485 + options: func(options *Options) { options.CTagsPath = "ctags_updated_test/universal-ctags" }, 486 486 }, 487 487 { 488 488 name: "update option DisableCTags to non default",
-159
build/ctags.go
··· 17 17 import ( 18 18 "bytes" 19 19 "fmt" 20 - "os" 21 - "os/exec" 22 - "path/filepath" 23 - "time" 24 20 25 21 "github.com/sourcegraph/zoekt" 26 22 "github.com/sourcegraph/zoekt/ctags" 27 23 ) 28 24 29 - func runCTags(bin string, inputs map[string][]byte) ([]*ctags.Entry, error) { 30 - const debug = false 31 - if len(inputs) == 0 { 32 - return nil, nil 33 - } 34 - dir, err := os.MkdirTemp("", "ctags-input") 35 - if err != nil { 36 - return nil, err 37 - } 38 - if !debug { 39 - defer os.RemoveAll(dir) 40 - } 41 - 42 - // --sort shells out to sort(1). 43 - args := []string{bin, "-n", "-f", "-", "--sort=no"} 44 - 45 - fileCount := 0 46 - for n, c := range inputs { 47 - if len(c) == 0 { 48 - continue 49 - } 50 - 51 - full := filepath.Join(dir, n) 52 - if err := os.MkdirAll(filepath.Dir(full), 0o700); err != nil { 53 - return nil, err 54 - } 55 - err := os.WriteFile(full, c, 0o600) 56 - if err != nil { 57 - return nil, err 58 - } 59 - args = append(args, n) 60 - fileCount++ 61 - } 62 - if fileCount == 0 { 63 - return nil, nil 64 - } 65 - 66 - cmd := exec.Command(args[0], args[1:]...) 67 - cmd.Dir = dir 68 - 69 - var errBuf, outBuf bytes.Buffer 70 - cmd.Stderr = &errBuf 71 - cmd.Stdout = &outBuf 72 - 73 - if err := cmd.Start(); err != nil { 74 - return nil, err 75 - } 76 - 77 - errChan := make(chan error, 1) 78 - go func() { 79 - err := cmd.Wait() 80 - errChan <- err 81 - }() 82 - timeout := time.After(60 * time.Second) 83 - select { 84 - case <-timeout: 85 - _ = cmd.Process.Kill() 86 - return nil, fmt.Errorf("timeout executing ctags") 87 - case err := <-errChan: 88 - if err != nil { 89 - return nil, fmt.Errorf("exec(%s): %v, stderr: %s", cmd.Args, err, errBuf.String()) 90 - } 91 - } 92 - 93 - var entries []*ctags.Entry 94 - for _, l := range bytes.Split(outBuf.Bytes(), []byte{'\n'}) { 95 - if len(l) == 0 { 96 - continue 97 - } 98 - e, err := ctags.Parse(string(l)) 99 - if err != nil { 100 - return nil, err 101 - } 102 - 103 - if len(e.Name) == 1 { 104 - continue 105 - } 106 - entries = append(entries, e) 107 - } 108 - return entries, nil 109 - } 110 - 111 - func runCTagsChunked(bin string, in map[string][]byte) ([]*ctags.Entry, error) { 112 - var res []*ctags.Entry 113 - 114 - cur := map[string][]byte{} 115 - sz := 0 116 - for k, v := range in { 117 - cur[k] = v 118 - sz += len(k) 119 - 120 - // 100k seems reasonable. 121 - if sz > (100 << 10) { 122 - r, err := runCTags(bin, cur) 123 - if err != nil { 124 - return nil, err 125 - } 126 - res = append(res, r...) 127 - 128 - cur = map[string][]byte{} 129 - sz = 0 130 - } 131 - } 132 - r, err := runCTags(bin, cur) 133 - if err != nil { 134 - return nil, err 135 - } 136 - res = append(res, r...) 137 - return res, nil 138 - } 139 - 140 25 func ctagsAddSymbolsParser(todo []*zoekt.Document, parser ctags.Parser) error { 141 26 for _, doc := range todo { 142 27 if doc.Symbols != nil { ··· 159 44 doc.SymbolsMetaData = symMetaData 160 45 } 161 46 162 - return nil 163 - } 164 - 165 - func ctagsAddSymbols(todo []*zoekt.Document, parser ctags.Parser, bin string) error { 166 - if parser != nil { 167 - return ctagsAddSymbolsParser(todo, parser) 168 - } 169 - 170 - pathIndices := map[string]int{} 171 - contents := map[string][]byte{} 172 - for i, t := range todo { 173 - if t.Symbols != nil { 174 - continue 175 - } 176 - 177 - _, ok := pathIndices[t.Name] 178 - if ok { 179 - continue 180 - } 181 - 182 - pathIndices[t.Name] = i 183 - contents[t.Name] = t.Content 184 - } 185 - 186 - var err error 187 - var entries []*ctags.Entry 188 - entries, err = runCTagsChunked(bin, contents) 189 - if err != nil { 190 - return err 191 - } 192 - 193 - fileTags := map[string][]*ctags.Entry{} 194 - for _, e := range entries { 195 - fileTags[e.Path] = append(fileTags[e.Path], e) 196 - } 197 - 198 - for k, tags := range fileTags { 199 - symOffsets, symMetaData, err := tagsToSections(contents[k], tags) 200 - if err != nil { 201 - return fmt.Errorf("%s: %v", k, err) 202 - } 203 - todo[pathIndices[k]].Symbols = symOffsets 204 - todo[pathIndices[k]].SymbolsMetaData = symMetaData 205 - } 206 47 return nil 207 48 } 208 49
+2 -8
ctags/BUILD.bazel
··· 2 2 3 3 go_library( 4 4 name = "ctags", 5 - srcs = [ 6 - "json.go", 7 - "parse.go", 8 - ], 5 + srcs = ["json.go"], 9 6 importpath = "github.com/sourcegraph/zoekt/ctags", 10 7 visibility = ["//visibility:public"], 11 8 deps = ["@com_github_sourcegraph_go_ctags//:go-ctags"], ··· 13 10 14 11 go_test( 15 12 name = "ctags_test", 16 - srcs = [ 17 - "json_test.go", 18 - "parse_test.go", 19 - ], 13 + srcs = ["json_test.go"], 20 14 embed = [":ctags"], 21 15 deps = [ 22 16 "@com_github_google_go_cmp//cmp",
+1 -2
ctags/json.go
··· 133 133 }, nil 134 134 } 135 135 136 - log.Fatal("not implemented") 137 - return nil, nil 136 + return nil, fmt.Errorf("only supports universal-ctags, not %s", bin) 138 137 }
-61
ctags/parse.go
··· 1 - // Copyright 2016 Google Inc. All rights reserved. 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 ctags 16 - 17 - import ( 18 - "fmt" 19 - "strconv" 20 - "strings" 21 - ) 22 - 23 - // Parse parses a single line of exuberant "ctags -n" output. 24 - func Parse(in string) (*Entry, error) { 25 - fields := strings.Split(in, "\t") 26 - e := Entry{} 27 - 28 - if len(fields) < 3 { 29 - return nil, fmt.Errorf("too few fields: %q", in) 30 - } 31 - 32 - e.Name = fields[0] 33 - e.Path = fields[1] 34 - 35 - lstr := fields[2] 36 - if len(lstr) < 2 { 37 - return nil, fmt.Errorf("got %q for linenum field", lstr) 38 - } 39 - 40 - l, err := strconv.ParseInt(lstr[:len(lstr)-2], 10, 64) 41 - if err != nil { 42 - return nil, err 43 - } 44 - e.Line = int(l) 45 - e.Kind = fields[3] 46 - 47 - field: 48 - for _, f := range fields[3:] { 49 - if string(f) == "file:" { 50 - e.FileLimited = true 51 - } 52 - for _, p := range []string{"class", "enum"} { 53 - if strings.HasPrefix(f, p+":") { 54 - e.Parent = strings.TrimPrefix(f, p+":") 55 - e.ParentKind = p 56 - continue field 57 - } 58 - } 59 - } 60 - return &e, nil 61 - }
-61
ctags/parse_test.go
··· 1 - // Copyright 2016 Google Inc. All rights reserved. 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 ctags 16 - 17 - import ( 18 - "reflect" 19 - "testing" 20 - ) 21 - 22 - func TestParse(t *testing.T) { 23 - type testcase struct { 24 - in string 25 - out *Entry 26 - } 27 - cases := []testcase{ 28 - { 29 - `ABBREV_SHA ./gitiles-servlet/src/main/java/com/google/gitiles/CommitData.java 59;" e enum:CommitData.Field file:`, 30 - &Entry{ 31 - Name: "ABBREV_SHA", 32 - Path: "./gitiles-servlet/src/main/java/com/google/gitiles/CommitData.java", 33 - Line: 59, 34 - Kind: "e", 35 - Parent: "CommitData.Field", 36 - ParentKind: "enum", 37 - FileLimited: true, 38 - }, 39 - }, 40 - { 41 - `ACCESS_ATTRIBUTE ./gitiles-servlet/src/main/java/com/google/gitiles/CommitData.java 55;" f class:BaseServlet file:`, 42 - &Entry{ 43 - Name: "ACCESS_ATTRIBUTE", 44 - Path: "./gitiles-servlet/src/main/java/com/google/gitiles/CommitData.java", 45 - Line: 55, 46 - Kind: "f", 47 - Parent: "BaseServlet", 48 - ParentKind: "class", 49 - FileLimited: true, 50 - }, 51 - }, 52 - } 53 - for _, c := range cases { 54 - e, err := Parse(c.in) 55 - if err != nil && c.out != nil { 56 - t.Errorf("Parse(%s): %v", c.in, err) 57 - } else if !reflect.DeepEqual(c.out, e) { 58 - t.Errorf("Parse(%s): got %#v, want %#v", c.in, e, c.out) 59 - } 60 - } 61 - }
+1 -2
doc/ctags.md
··· 4 4 5 5 Ctags generates indices of symbol definitions in source files. It 6 6 started its life as part of the BSD Unix, but there are several more 7 - modern flavors. Zoekt supports both [exuberant 8 - ctags](http://ctags.sourceforge.net/) and 7 + modern flavors. Zoekt supports 9 8 [universal-ctags](https://github.com/universal-ctags). 10 9 11 10 It is strongly recommended to use Universal Ctags, [version