* Update to ultraware/funlen v0.0.2. Fixes https://github.com/ultraware/funlen/pull/1. * Update to latest golang.org/x/tools. Fixes #687. Fixes https://github.com/golang/tools/pull/139.
		
			
				
	
	
		
			104 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2016 The Go Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package buildutil
 | 
						|
 | 
						|
import (
 | 
						|
	"bufio"
 | 
						|
	"bytes"
 | 
						|
	"fmt"
 | 
						|
	"go/build"
 | 
						|
	"io"
 | 
						|
	"io/ioutil"
 | 
						|
	"path/filepath"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
)
 | 
						|
 | 
						|
// OverlayContext overlays a build.Context with additional files from
 | 
						|
// a map. Files in the map take precedence over other files.
 | 
						|
//
 | 
						|
// In addition to plain string comparison, two file names are
 | 
						|
// considered equal if their base names match and their directory
 | 
						|
// components point at the same directory on the file system. That is,
 | 
						|
// symbolic links are followed for directories, but not files.
 | 
						|
//
 | 
						|
// A common use case for OverlayContext is to allow editors to pass in
 | 
						|
// a set of unsaved, modified files.
 | 
						|
//
 | 
						|
// Currently, only the Context.OpenFile function will respect the
 | 
						|
// overlay. This may change in the future.
 | 
						|
func OverlayContext(orig *build.Context, overlay map[string][]byte) *build.Context {
 | 
						|
	// TODO(dominikh): Implement IsDir, HasSubdir and ReadDir
 | 
						|
 | 
						|
	rc := func(data []byte) (io.ReadCloser, error) {
 | 
						|
		return ioutil.NopCloser(bytes.NewBuffer(data)), nil
 | 
						|
	}
 | 
						|
 | 
						|
	copy := *orig // make a copy
 | 
						|
	ctxt := ©
 | 
						|
	ctxt.OpenFile = func(path string) (io.ReadCloser, error) {
 | 
						|
		// Fast path: names match exactly.
 | 
						|
		if content, ok := overlay[path]; ok {
 | 
						|
			return rc(content)
 | 
						|
		}
 | 
						|
 | 
						|
		// Slow path: check for same file under a different
 | 
						|
		// alias, perhaps due to a symbolic link.
 | 
						|
		for filename, content := range overlay {
 | 
						|
			if sameFile(path, filename) {
 | 
						|
				return rc(content)
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		return OpenFile(orig, path)
 | 
						|
	}
 | 
						|
	return ctxt
 | 
						|
}
 | 
						|
 | 
						|
// ParseOverlayArchive parses an archive containing Go files and their
 | 
						|
// contents. The result is intended to be used with OverlayContext.
 | 
						|
//
 | 
						|
//
 | 
						|
// Archive format
 | 
						|
//
 | 
						|
// The archive consists of a series of files. Each file consists of a
 | 
						|
// name, a decimal file size and the file contents, separated by
 | 
						|
// newlines. No newline follows after the file contents.
 | 
						|
func ParseOverlayArchive(archive io.Reader) (map[string][]byte, error) {
 | 
						|
	overlay := make(map[string][]byte)
 | 
						|
	r := bufio.NewReader(archive)
 | 
						|
	for {
 | 
						|
		// Read file name.
 | 
						|
		filename, err := r.ReadString('\n')
 | 
						|
		if err != nil {
 | 
						|
			if err == io.EOF {
 | 
						|
				break // OK
 | 
						|
			}
 | 
						|
			return nil, fmt.Errorf("reading archive file name: %v", err)
 | 
						|
		}
 | 
						|
		filename = filepath.Clean(strings.TrimSpace(filename))
 | 
						|
 | 
						|
		// Read file size.
 | 
						|
		sz, err := r.ReadString('\n')
 | 
						|
		if err != nil {
 | 
						|
			return nil, fmt.Errorf("reading size of archive file %s: %v", filename, err)
 | 
						|
		}
 | 
						|
		sz = strings.TrimSpace(sz)
 | 
						|
		size, err := strconv.ParseUint(sz, 10, 32)
 | 
						|
		if err != nil {
 | 
						|
			return nil, fmt.Errorf("parsing size of archive file %s: %v", filename, err)
 | 
						|
		}
 | 
						|
 | 
						|
		// Read file content.
 | 
						|
		content := make([]byte, size)
 | 
						|
		if _, err := io.ReadFull(r, content); err != nil {
 | 
						|
			return nil, fmt.Errorf("reading archive file %s: %v", filename, err)
 | 
						|
		}
 | 
						|
		overlay[filename] = content
 | 
						|
	}
 | 
						|
 | 
						|
	return overlay, nil
 | 
						|
}
 |