in build/ctags.go [31:111]
func runCTags(bin string, inputs map[string][]byte) ([]*ctags.Entry, error) {
const debug = false
if len(inputs) == 0 {
return nil, nil
}
dir, err := ioutil.TempDir("", "ctags-input")
if err != nil {
return nil, err
}
if !debug {
defer os.RemoveAll(dir)
}
// --sort shells out to sort(1).
args := []string{bin, "-n", "-f", "-", "--sort=no"}
fileCount := 0
for n, c := range inputs {
if len(c) == 0 {
continue
}
full := filepath.Join(dir, n)
if err := os.MkdirAll(filepath.Dir(full), 0o700); err != nil {
return nil, err
}
err := ioutil.WriteFile(full, c, 0o600)
if err != nil {
return nil, err
}
args = append(args, n)
fileCount++
}
if fileCount == 0 {
return nil, nil
}
cmd := exec.Command(args[0], args[1:]...)
cmd.Dir = dir
var errBuf, outBuf bytes.Buffer
cmd.Stderr = &errBuf
cmd.Stdout = &outBuf
if err := cmd.Start(); err != nil {
return nil, err
}
errChan := make(chan error, 1)
go func() {
err := cmd.Wait()
errChan <- err
}()
timeout := time.After(5 * time.Second)
select {
case <-timeout:
cmd.Process.Kill()
return nil, fmt.Errorf("timeout executing ctags")
case err := <-errChan:
if err != nil {
return nil, fmt.Errorf("exec(%s): %v, stderr: %s", cmd.Args, err, errBuf.String())
}
}
var entries []*ctags.Entry
for _, l := range bytes.Split(outBuf.Bytes(), []byte{'\n'}) {
if len(l) == 0 {
continue
}
e, err := ctags.Parse(string(l))
if err != nil {
return nil, err
}
if len(e.Sym) == 1 {
continue
}
entries = append(entries, e)
}
return entries, nil
}