Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / go / buildutil / overlay.go
1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package buildutil
6
7 import (
8         "bufio"
9         "bytes"
10         "fmt"
11         "go/build"
12         "io"
13         "io/ioutil"
14         "path/filepath"
15         "strconv"
16         "strings"
17 )
18
19 // OverlayContext overlays a build.Context with additional files from
20 // a map. Files in the map take precedence over other files.
21 //
22 // In addition to plain string comparison, two file names are
23 // considered equal if their base names match and their directory
24 // components point at the same directory on the file system. That is,
25 // symbolic links are followed for directories, but not files.
26 //
27 // A common use case for OverlayContext is to allow editors to pass in
28 // a set of unsaved, modified files.
29 //
30 // Currently, only the Context.OpenFile function will respect the
31 // overlay. This may change in the future.
32 func OverlayContext(orig *build.Context, overlay map[string][]byte) *build.Context {
33         // TODO(dominikh): Implement IsDir, HasSubdir and ReadDir
34
35         rc := func(data []byte) (io.ReadCloser, error) {
36                 return ioutil.NopCloser(bytes.NewBuffer(data)), nil
37         }
38
39         copy := *orig // make a copy
40         ctxt := &copy
41         ctxt.OpenFile = func(path string) (io.ReadCloser, error) {
42                 // Fast path: names match exactly.
43                 if content, ok := overlay[path]; ok {
44                         return rc(content)
45                 }
46
47                 // Slow path: check for same file under a different
48                 // alias, perhaps due to a symbolic link.
49                 for filename, content := range overlay {
50                         if sameFile(path, filename) {
51                                 return rc(content)
52                         }
53                 }
54
55                 return OpenFile(orig, path)
56         }
57         return ctxt
58 }
59
60 // ParseOverlayArchive parses an archive containing Go files and their
61 // contents. The result is intended to be used with OverlayContext.
62 //
63 //
64 // Archive format
65 //
66 // The archive consists of a series of files. Each file consists of a
67 // name, a decimal file size and the file contents, separated by
68 // newlines. No newline follows after the file contents.
69 func ParseOverlayArchive(archive io.Reader) (map[string][]byte, error) {
70         overlay := make(map[string][]byte)
71         r := bufio.NewReader(archive)
72         for {
73                 // Read file name.
74                 filename, err := r.ReadString('\n')
75                 if err != nil {
76                         if err == io.EOF {
77                                 break // OK
78                         }
79                         return nil, fmt.Errorf("reading archive file name: %v", err)
80                 }
81                 filename = filepath.Clean(strings.TrimSpace(filename))
82
83                 // Read file size.
84                 sz, err := r.ReadString('\n')
85                 if err != nil {
86                         return nil, fmt.Errorf("reading size of archive file %s: %v", filename, err)
87                 }
88                 sz = strings.TrimSpace(sz)
89                 size, err := strconv.ParseUint(sz, 10, 32)
90                 if err != nil {
91                         return nil, fmt.Errorf("parsing size of archive file %s: %v", filename, err)
92                 }
93
94                 // Read file content.
95                 content := make([]byte, size)
96                 if _, err := io.ReadFull(r, content); err != nil {
97                         return nil, fmt.Errorf("reading archive file %s: %v", filename, err)
98                 }
99                 overlay[filename] = content
100         }
101
102         return overlay, nil
103 }