GoPLS Viewer

Home|gopls/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
5package buildutil
6
7import (
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.
32func OverlayContext(orig *build.Contextoverlay map[string][]byte) *build.Context {
33    // TODO(dominikh): Implement IsDir, HasSubdir and ReadDir
34
35    rc := func(data []byte) (io.ReadClosererror) {
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.ReadClosererror) {
42        // Fast path: names match exactly.
43        if contentok := 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 filenamecontent := range overlay {
50            if sameFile(pathfilename) {
51                return rc(content)
52            }
53        }
54
55        return OpenFile(origpath)
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// # Archive format
64//
65// The archive consists of a series of files. Each file consists of a
66// name, a decimal file size and the file contents, separated by
67// newlines. No newline follows after the file contents.
68func ParseOverlayArchive(archive io.Reader) (map[string][]byteerror) {
69    overlay := make(map[string][]byte)
70    r := bufio.NewReader(archive)
71    for {
72        // Read file name.
73        filenameerr := r.ReadString('\n')
74        if err != nil {
75            if err == io.EOF {
76                break // OK
77            }
78            return nilfmt.Errorf("reading archive file name: %v"err)
79        }
80        filename = filepath.Clean(strings.TrimSpace(filename))
81
82        // Read file size.
83        szerr := r.ReadString('\n')
84        if err != nil {
85            return nilfmt.Errorf("reading size of archive file %s: %v"filenameerr)
86        }
87        sz = strings.TrimSpace(sz)
88        sizeerr := strconv.ParseUint(sz1032)
89        if err != nil {
90            return nilfmt.Errorf("parsing size of archive file %s: %v"filenameerr)
91        }
92
93        // Read file content.
94        content := make([]bytesize)
95        if _err := io.ReadFull(rcontent); err != nil {
96            return nilfmt.Errorf("reading archive file %s: %v"filenameerr)
97        }
98        overlay[filename] = content
99    }
100
101    return overlaynil
102}
103
MembersX
ParseOverlayArchive
ParseOverlayArchive.r
ParseOverlayArchive.BlockStmt.err
ParseOverlayArchive.BlockStmt.sz
ParseOverlayArchive.BlockStmt._
bufio
OverlayContext.ctxt
ParseOverlayArchive.overlay
ParseOverlayArchive.archive
ParseOverlayArchive.BlockStmt.filename
ParseOverlayArchive.BlockStmt.size
ParseOverlayArchive.BlockStmt.content
OverlayContext
OverlayContext.overlay
OverlayContext.BlockStmt.RangeStmt_1468.content
OverlayContext.copy
OverlayContext.BlockStmt.RangeStmt_1468.filename
bytes
strconv
OverlayContext.orig
Members
X