<commit_before>package suggest

import (
	"bytes"
	"go/scanner"
	"go/token"
)

type tokenIterator struct {
	tokens []tokenItem
	pos    int
}

type tokenItem struct {
	tok token.Token
	lit string
}

func (i tokenItem) String() string {
	if i.tok.IsLiteral() {
		return i.lit
	}
	return i.tok.String()
}

func newTokenIterator(src []byte, cursor int) (tokenIterator, int) {
	fset := token.NewFileSet()
	file := fset.AddFile("", fset.Base(), len(src))
	cursorPos := file.Pos(cursor)

	var s scanner.Scanner
	s.Init(file, src, nil, 0)
	tokens := make([]tokenItem, 0, 1000)
	lastPos := token.NoPos
	for {
		pos, tok, lit := s.Scan()
		if tok == token.EOF || pos >= cursorPos {
			break
		}
		tokens = append(tokens, tokenItem{
			tok: tok,
			lit: lit,
		})
		lastPos = pos
	}
	return tokenIterator{
		tokens: tokens,
		pos:    len(tokens) - 1,
	}, int(cursorPos - lastPos)
}

func (ti *tokenIterator) token() tokenItem {
	return ti.tokens[ti.pos]
}

func (ti *tokenIterator) prev() bool {
	if ti.pos <= 0 {
		return false
	}
	ti.pos--
	return true
}

var bracket_pairs_map = map[token.Token]token.Token{
	token.RPAREN: token.LPAREN,
	token.RBRACK: token.LBRACK,
	token.RBRACE: token.LBRACE,
}

func (ti *tokenIterator) skipToLeft(left, right token.Token) bool {
	if ti.token().tok == left {
		return true
	}
	balance := 1
	for balance != 0 {
		if !ti.prev() {
			return false
		}
		switch ti.token().tok {
		case right:
			balance++
		case left:
			balance--
		}
	}
	return true
}

// when the cursor is at the ')' or ']' or '}', move the cursor to an opposite
// bracket pair, this functions takes nested bracket pairs into account
func (ti *tokenIterator) skipToBalancedPair() bool {
	right := ti.token().tok
	left := bracket_pairs_map[right]
	return ti.skipToLeft(left, right)
}

// Move the cursor to the open brace of the current block, taking nested blocks
// into account.
func (ti *tokenIterator) skipToLeftCurly() bool {
	return ti.skipToLeft(token.LBRACE, token.RBRACE)
}

// Extract the type expression right before the enclosing curly bracket block.
// Examples (# - the cursor):
//   &lib.Struct{Whatever: 1, Hel#} // returns "lib.Struct"
//   X{#}                           // returns X
// The idea is that we check if this type expression is a type and it is, we
// can apply special filtering for autocompletion results.
func (ti *tokenIterator) extractLiteralType() (res string) {
	if !ti.skipToLeftCurly() {
		return ""
	}
	origPos := ti.pos
	if !ti.prev() {
		return ""
	}

	// A composite literal type must end with either "ident",
	// "ident.ident", or "struct { ... }".
	switch ti.token().tok {
	case token.IDENT:
		if !ti.prev() {
			return ""
		}
		if ti.token().tok == token.PERIOD {
			if !ti.prev() {
				return ""
			}
			if ti.token().tok != token.IDENT {
				return ""
			}
			if !ti.prev() {
				return ""
			}
		}
	case token.RBRACE:
		ti.skipToBalancedPair()
		if !ti.prev() {
			return ""
		}
		if ti.token().tok != token.STRUCT {
			return ""
		}
		if !ti.prev() {
			return ""
		}
	}

	// Continuing backwards, we might see "[]", "[...]", "[expr]",
	// or "map[T]".
	for ti.token().tok == token.RBRACK {
		ti.skipToBalancedPair()
		if !ti.prev() {
			return ""
		}
		if ti.token().tok == token.MAP {
			if !ti.prev() {
				return ""
			}
		}
	}

	return joinTokens(ti.tokens[ti.pos+1 : origPos])
}

// Starting from the token under the cursor move back and extract something
// that resembles a valid Go primary expression. Examples of primary expressions
// from Go spec:
//   x
//   2
//   (s + ".txt")
//   f(3.1415, true)
//   Point{1, 2}
//   m["foo"]
//   s[i : j + 1]
//   obj.color
//   f.p[i].x()
//
// As you can see we can move through all of them using balanced bracket
// matching and applying simple rules
// E.g.
//   Point{1, 2}.m["foo"].s[i : j + 1].MethodCall(a, func(a, b int) int { return a + b }).
// Can be seen as:
//   Point{    }.m[     ].s[         ].MethodCall(                                      ).
// Which boils the rules down to these connected via dots:
//   ident
//   ident[]
//   ident{}
//   ident()
// Of course there are also slightly more complicated rules for brackets:
//   ident{}.ident()[5][4](), etc.
func (ti *tokenIterator) extractExpr() string {
	orig := ti.pos

	// Contains the type of the previously scanned token (initialized with
	// the token right under the cursor). This is the token to the *right* of
	// the current one.
	prev := ti.token().tok
loop:
	for {
		if !ti.prev() {
			return joinTokens(ti.tokens[:orig])
		}
		switch ti.token().tok {
		case token.PERIOD:
			// If the '.' is not followed by IDENT, it's invalid.
			if prev != token.IDENT {
				break loop
			}
		case token.IDENT:
			// Valid tokens after IDENT are '.', '[', '{' and '('.
			switch prev {
			case token.PERIOD, token.LBRACK, token.LBRACE, token.LPAREN:
				// all ok
			default:
				break loop
			}
		case token.RBRACE:
			// This one can only be a part of type initialization, like:
			//   Dummy{}.Hello()
			// It is valid Go if Hello method is defined on a non-pointer receiver.
			if prev != token.PERIOD {
				break loop
			}
			ti.skipToBalancedPair()
		case token.RPAREN, token.RBRACK:
			// After ']' and ')' their opening counterparts are valid '[', '(',
			// as well as the dot.
			switch prev {
			case token.PERIOD, token.LBRACK, token.LPAREN:
				// all ok
			default:
				break loop
			}
			ti.skipToBalancedPair()
		default:
			break loop
		}
		prev = ti.token().tok
	}
	return joinTokens(ti.tokens[ti.pos+1 : orig])
}

// Given a slice of token_item, reassembles them into the original literal
// expression.
func joinTokens(tokens []tokenItem) string {
	var buf bytes.Buffer
	for i, tok := range tokens {
		if i > 0 {
			buf.WriteByte(' ')
		}
		buf.WriteString(tok.String())
	}
	return buf.String()
}

type cursorContext int

const (
	unknownContext cursorContext = iota
	selectContext
	compositeLiteralContext
)

func deduceCursorContext(file []byte, cursor int) (cursorContext, string, string) {
	iter, off := newTokenIterator(file, cursor)
	if len(iter.tokens) == 0 {
		return unknownContext, "", ""
	}

	// See if we have a partial identifier to work with.
	var partial string
	tok := iter.token()
	switch {
	case tok.tok.IsKeyword(), tok.tok == token.IDENT:
		// we're '<whatever>.<ident>'
		// parse <ident> as Partial and figure out decl

		partial = tok.String()
		// If it happens that the cursor is past the end of the literal,
		// means there is a space between the literal and the cursor, think
		// of it as no context, because that's what it really is.
		if off > len(tok.String()) {
			return unknownContext, "", ""
		}
		partial = partial[:off]

		if !iter.prev() {
			return unknownContext, "", partial
		}
	}

	switch iter.token().tok {
	case token.PERIOD:
		return selectContext, iter.extractExpr(), partial
	case token.COMMA, token.LBRACE:
		// This can happen for struct fields:
		// &Struct{Hello: 1, Wor#} // (# - the cursor)
		// Let's try to find the struct type
		return compositeLiteralContext, iter.extractLiteralType(), partial
	}

	return unknownContext, "", partial
}
<commit_msg>clean up one line<commit_after>package suggest

import (
	"bytes"
	"go/scanner"
	"go/token"
)

type tokenIterator struct {
	tokens []tokenItem
	pos    int
}

type tokenItem struct {
	tok token.Token
	lit string
}

func (i tokenItem) String() string {
	if i.tok.IsLiteral() {
		return i.lit
	}
	return i.tok.String()
}

func newTokenIterator(src []byte, cursor int) (tokenIterator, int) {
	fset := token.NewFileSet()
	file := fset.AddFile("", fset.Base(), len(src))
	cursorPos := file.Pos(cursor)

	var s scanner.Scanner
	s.Init(file, src, nil, 0)
	tokens := make([]tokenItem, 0, 1000)
	lastPos := token.NoPos
	for {
		pos, tok, lit := s.Scan()
		if tok == token.EOF || pos >= cursorPos {
			break
		}
		tokens = append(tokens, tokenItem{
			tok: tok,
			lit: lit,
		})
		lastPos = pos
	}
	return tokenIterator{
		tokens: tokens,
		pos:    len(tokens) - 1,
	}, int(cursorPos - lastPos)
}

func (ti *tokenIterator) token() tokenItem {
	return ti.tokens[ti.pos]
}

func (ti *tokenIterator) prev() bool {
	if ti.pos <= 0 {
		return false
	}
	ti.pos--
	return true
}

var bracket_pairs_map = map[token.Token]token.Token{
	token.RPAREN: token.LPAREN,
	token.RBRACK: token.LBRACK,
	token.RBRACE: token.LBRACE,
}

func (ti *tokenIterator) skipToLeft(left, right token.Token) bool {
	if ti.token().tok == left {
		return true
	}
	balance := 1
	for balance != 0 {
		if !ti.prev() {
			return false
		}
		switch ti.token().tok {
		case right:
			balance++
		case left:
			balance--
		}
	}
	return true
}

// when the cursor is at the ')' or ']' or '}', move the cursor to an opposite
// bracket pair, this functions takes nested bracket pairs into account
func (ti *tokenIterator) skipToBalancedPair() bool {
	right := ti.token().tok
	left := bracket_pairs_map[right]
	return ti.skipToLeft(left, right)
}

// Move the cursor to the open brace of the current block, taking nested blocks
// into account.
func (ti *tokenIterator) skipToLeftCurly() bool {
	return ti.skipToLeft(token.LBRACE, token.RBRACE)
}

// Extract the type expression right before the enclosing curly bracket block.
// Examples (# - the cursor):
//   &lib.Struct{Whatever: 1, Hel#} // returns "lib.Struct"
//   X{#}                           // returns X
// The idea is that we check if this type expression is a type and it is, we
// can apply special filtering for autocompletion results.
func (ti *tokenIterator) extractLiteralType() (res string) {
	if !ti.skipToLeftCurly() {
		return ""
	}
	origPos := ti.pos
	if !ti.prev() {
		return ""
	}

	// A composite literal type must end with either "ident",
	// "ident.ident", or "struct { ... }".
	switch ti.token().tok {
	case token.IDENT:
		if !ti.prev() {
			return ""
		}
		if ti.token().tok == token.PERIOD {
			if !ti.prev() {
				return ""
			}
			if ti.token().tok != token.IDENT {
				return ""
			}
			if !ti.prev() {
				return ""
			}
		}
	case token.RBRACE:
		ti.skipToBalancedPair()
		if !ti.prev() {
			return ""
		}
		if ti.token().tok != token.STRUCT {
			return ""
		}
		if !ti.prev() {
			return ""
		}
	}

	// Continuing backwards, we might see "[]", "[...]", "[expr]",
	// or "map[T]".
	for ti.token().tok == token.RBRACK {
		ti.skipToBalancedPair()
		if !ti.prev() {
			return ""
		}
		if ti.token().tok == token.MAP {
			if !ti.prev() {
				return ""
			}
		}
	}

	return joinTokens(ti.tokens[ti.pos+1 : origPos])
}

// Starting from the token under the cursor move back and extract something
// that resembles a valid Go primary expression. Examples of primary expressions
// from Go spec:
//   x
//   2
//   (s + ".txt")
//   f(3.1415, true)
//   Point{1, 2}
//   m["foo"]
//   s[i : j + 1]
//   obj.color
//   f.p[i].x()
//
// As you can see we can move through all of them using balanced bracket
// matching and applying simple rules
// E.g.
//   Point{1, 2}.m["foo"].s[i : j + 1].MethodCall(a, func(a, b int) int { return a + b }).
// Can be seen as:
//   Point{    }.m[     ].s[         ].MethodCall(                                      ).
// Which boils the rules down to these connected via dots:
//   ident
//   ident[]
//   ident{}
//   ident()
// Of course there are also slightly more complicated rules for brackets:
//   ident{}.ident()[5][4](), etc.
func (ti *tokenIterator) extractExpr() string {
	orig := ti.pos

	// Contains the type of the previously scanned token (initialized with
	// the token right under the cursor). This is the token to the *right* of
	// the current one.
	prev := ti.token().tok
loop:
	for {
		if !ti.prev() {
			return joinTokens(ti.tokens[:orig])
		}
		switch ti.token().tok {
		case token.PERIOD:
			// If the '.' is not followed by IDENT, it's invalid.
			if prev != token.IDENT {
				break loop
			}
		case token.IDENT:
			// Valid tokens after IDENT are '.', '[', '{' and '('.
			switch prev {
			case token.PERIOD, token.LBRACK, token.LBRACE, token.LPAREN:
				// all ok
			default:
				break loop
			}
		case token.RBRACE:
			// This one can only be a part of type initialization, like:
			//   Dummy{}.Hello()
			// It is valid Go if Hello method is defined on a non-pointer receiver.
			if prev != token.PERIOD {
				break loop
			}
			ti.skipToBalancedPair()
		case token.RPAREN, token.RBRACK:
			// After ']' and ')' their opening counterparts are valid '[', '(',
			// as well as the dot.
			switch prev {
			case token.PERIOD, token.LBRACK, token.LPAREN:
				// all ok
			default:
				break loop
			}
			ti.skipToBalancedPair()
		default:
			break loop
		}
		prev = ti.token().tok
	}
	return joinTokens(ti.tokens[ti.pos+1 : orig])
}

// Given a slice of token_item, reassembles them into the original literal
// expression.
func joinTokens(tokens []tokenItem) string {
	var buf bytes.Buffer
	for i, tok := range tokens {
		if i > 0 {
			buf.WriteByte(' ')
		}
		buf.WriteString(tok.String())
	}
	return buf.String()
}

type cursorContext int

const (
	unknownContext cursorContext = iota
	selectContext
	compositeLiteralContext
)

func deduceCursorContext(file []byte, cursor int) (cursorContext, string, string) {
	iter, off := newTokenIterator(file, cursor)
	if len(iter.tokens) == 0 {
		return unknownContext, "", ""
	}

	// See if we have a partial identifier to work with.
	var partial string
	switch tok := iter.token(); {
	case tok.tok.IsKeyword(), tok.tok == token.IDENT:
		// we're '<whatever>.<ident>'
		// parse <ident> as Partial and figure out decl

		partial = tok.String()
		// If it happens that the cursor is past the end of the literal,
		// means there is a space between the literal and the cursor, think
		// of it as no context, because that's what it really is.
		if off > len(tok.String()) {
			return unknownContext, "", ""
		}
		partial = partial[:off]

		if !iter.prev() {
			return unknownContext, "", partial
		}
	}

	switch iter.token().tok {
	case token.PERIOD:
		return selectContext, iter.extractExpr(), partial
	case token.COMMA, token.LBRACE:
		// This can happen for struct fields:
		// &Struct{Hello: 1, Wor#} // (# - the cursor)
		// Let's try to find the struct type
		return compositeLiteralContext, iter.extractLiteralType(), partial
	}

	return unknownContext, "", partial
}
<|endoftext|>


<commit_before>// Copyright 2019 The Go Cloud Development Kit Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Helper tool for creating new releases of the Go CDK. See -help for details.
package main

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

// TODO(eliben): add bumpversion flag that bumps version by 1, or to a version
// given on the command line
var helpText string = `
Helper tool for creating new releases of the Go CDK.

Automates the modifications required in the project's
go.mod files to create an test new releases.

The tool processes all modules listed in the 'allmodules'
file. For each module it handles all dependencies on
other gocloud.dev modules.

-replace adds 'replace' directives to point to local versions
for testing. -dropreplace removes these directives.

Run it from the root directory of the project.

Usage:
`

var doReplace = flag.Bool("replace", false, "add replace directives")
var doDropReplace = flag.Bool("dropreplace", false, "drop replace directives")

// cmdCheck invokes the command given in s, echoing the invocation to stdout.
// It checks that the command was successful and returns its standard output.
// If the command returned a non-0 status, log.Fatal is invoked.
func cmdCheck(s string) []byte {
	fmt.Printf(" -> %s\n", s)
	fields := strings.Fields(s)
	if len(fields) < 1 {
		log.Fatal(`Expected "command <arguments>"`)
	}
	b, err := exec.Command(fields[0], fields[1:]...).Output()
	if exiterr, ok := err.(*exec.ExitError); ok {
		log.Fatalf("%s; stderr: %s\n", err, string(exiterr.Stderr))
	} else if err != nil {
		log.Fatal("exec.Command", err)
	}
	return b
}

// These types are taken from "go mod help edit", in order to parse the JSON
// output of `go mod edit -json`.
type GoMod struct {
	Module  Module
	Go      string
	Require []Require
	Exclude []Module
	Replace []Replace
}

type Module struct {
	Path    string
	Version string
}

type Require struct {
	Path     string
	Version  string
	Indirect bool
}

type Replace struct {
	Old Module
	New Module
}

// parseModuleInfo parses module information from a go.mod file at path.
func parseModuleInfo(path string) GoMod {
	rawJson := cmdCheck("go mod edit -json " + path)
	var modInfo GoMod
	err := json.Unmarshal(rawJson, &modInfo)
	if err != nil {
		log.Fatal(err)
	}
	return modInfo
}

func runOnGomod(path string) {
	gomodPath := filepath.Join(path, "go.mod")
	fmt.Println("Processing", gomodPath)
	modInfo := parseModuleInfo(gomodPath)

	base := "gocloud.dev"

	for _, r := range modInfo.Require {
		// Find requirements on modules within the gocloud.dev tree.
		if strings.HasPrefix(r.Path, base) {
			// Find the relative path from 'path' and the module required here.
			var reqPath string
			if r.Path == base {
				reqPath = "."
			} else {
				reqPath = strings.TrimPrefix(r.Path, base+"/")
			}
			rel, err := filepath.Rel(path, reqPath)
			if err != nil {
				log.Fatal(err)
			}
			// When path is '.', filepath.Rel will append a /. to the result and we
			// may get paths like ../../.
			if strings.HasSuffix(rel, "/.") {
				rel, _ = filepath.Split(rel)
			}

			if *doReplace {
				cmdCheck(fmt.Sprintf("go mod edit -replace=%s=%s %s", r.Path, rel, gomodPath))
			} else if *doDropReplace {
				cmdCheck(fmt.Sprintf("go mod edit -dropreplace=%s %s", r.Path, gomodPath))
			}
		}
	}
}

func main() {
	flag.Usage = func() {
		fmt.Fprintf(flag.CommandLine.Output(), helpText)
		flag.PrintDefaults()
	}

	flag.Parse()
	if *doReplace && *doDropReplace {
		log.Fatal("Expected only one of -replace/-dropreplace")
	}

	f, err := os.Open("allmodules")
	if err != nil {
		log.Fatal(err)
	}

	input := bufio.NewScanner(f)
	input.Split(bufio.ScanLines)
	for input.Scan() {
		if len(input.Text()) > 0 && !strings.HasPrefix(input.Text(), "#") {
			runOnGomod(input.Text())
		}
	}

	if input.Err() != nil {
		log.Fatal(input.Err())
	}
}
<commit_msg>testing: refactor release helper and switch flags to commands (#2246)<commit_after>// Copyright 2019 The Go Cloud Development Kit Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Helper tool for creating new releases of the Go CDK. Run without arguments
// or with 'help' for details.
package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

// TODO(eliben): add bumpversion command that bumps version by 1, or to a version
// given on the command line
var helpText string = `
Helper tool for creating new releases of the Go CDK.

Automates the modifications required in the project's
go.mod files to create an test new releases.

The tool processes all modules listed in the 'allmodules'
file. For each module it handles all dependencies on
other gocloud.dev modules.

Run it from the root directory of the repository, as follows:

$ %s <command>

Where command is one of the following:

  addreplace    adds 'replace' directives to point to local versions
                for testing.

  dropreplace   removes these directives.

  help          prints this usage message
`

func printHelp() {
	_, binName := filepath.Split(os.Args[0])
	fmt.Fprintf(os.Stderr, helpText, binName)
	fmt.Fprintln(os.Stderr)
}

// cmdCheck invokes the command given in s, echoing the invocation to stdout.
// It checks that the command was successful and returns its standard output.
// If the command returned a non-0 status, log.Fatal is invoked.
func cmdCheck(s string) []byte {
	fmt.Printf(" -> %s\n", s)
	fields := strings.Fields(s)
	if len(fields) < 1 {
		log.Fatal(`Expected "command <arguments>"`)
	}
	b, err := exec.Command(fields[0], fields[1:]...).Output()
	if exiterr, ok := err.(*exec.ExitError); ok {
		log.Fatalf("%s; stderr: %s\n", err, string(exiterr.Stderr))
	} else if err != nil {
		log.Fatal("exec.Command", err)
	}
	return b
}

// These types are taken from "go mod help edit", in order to parse the JSON
// output of `go mod edit -json`.
type GoMod struct {
	Module  Module
	Go      string
	Require []Require
	Exclude []Module
	Replace []Replace
}

type Module struct {
	Path    string
	Version string
}

type Require struct {
	Path     string
	Version  string
	Indirect bool
}

type Replace struct {
	Old Module
	New Module
}

// parseModuleInfo parses module information from a go.mod file at path.
func parseModuleInfo(path string) GoMod {
	rawJson := cmdCheck("go mod edit -json " + path)
	var modInfo GoMod
	err := json.Unmarshal(rawJson, &modInfo)
	if err != nil {
		log.Fatal(err)
	}
	return modInfo
}

// reqHandlerFunc is a callback function type invoked by runOnGomod when it
// finds 'require' lines in go.mod files that refer to our modules. It's called
// with these arguments:
//
//   gomodPath - path to the go.mod file where this 'require' was found
//   mod - name of the module being 'require'd
//   modPath - mod's location in the filesystem relative to
//             the go.mod 'require'ing it
type reqHandlerFunc func(gomodPath, mod, modPath string)

func runOnGomod(path string, reqHandler reqHandlerFunc) {
	gomodPath := filepath.Join(path, "go.mod")
	fmt.Println("Processing", gomodPath)
	modInfo := parseModuleInfo(gomodPath)

	base := "gocloud.dev"

	for _, r := range modInfo.Require {
		// Find requirements on modules within the gocloud.dev tree.
		if strings.HasPrefix(r.Path, base) {
			// Find the relative path from 'path' and the module required here.
			var reqPath string
			if r.Path == base {
				reqPath = "."
			} else {
				reqPath = strings.TrimPrefix(r.Path, base+"/")
			}
			rel, err := filepath.Rel(path, reqPath)
			if err != nil {
				log.Fatal(err)
			}
			// When path is '.', filepath.Rel will append a /. to the result and we
			// may get paths like ../../.
			if strings.HasSuffix(rel, "/.") {
				rel, _ = filepath.Split(rel)
			}

			reqHandler(gomodPath, r.Path, rel)
		}
	}
}

func main() {
	if len(os.Args) < 2 {
		printHelp()
		os.Exit(0)
	}

	var handlerFunc reqHandlerFunc
	switch os.Args[1] {
	case "help":
		printHelp()
		os.Exit(0)
	case "addreplace":
		handlerFunc = func(gomodPath, mod, modPath string) {
			cmdCheck(fmt.Sprintf("go mod edit -replace=%s=%s %s", mod, modPath, gomodPath))
		}
	case "dropreplace":
		handlerFunc = func(gomodPath, mod, modPath string) {
			cmdCheck(fmt.Sprintf("go mod edit -dropreplace=%s %s", mod, gomodPath))
		}
	default:
		printHelp()
		os.Exit(1)
	}

	f, err := os.Open("allmodules")
	if err != nil {
		log.Fatal(err)
	}

	input := bufio.NewScanner(f)
	input.Split(bufio.ScanLines)
	for input.Scan() {
		if len(input.Text()) > 0 && !strings.HasPrefix(input.Text(), "#") {
			runOnGomod(input.Text(), handlerFunc)
		}
	}

	if input.Err() != nil {
		log.Fatal(input.Err())
	}
}
<|endoftext|>


<commit_before>// NOTE - this file is auto-generated. DO NOT EDIT.

package internal

const (
	// Version is the current version of the plaid-go library
	Version = "2.6.0"
)
<commit_msg>2.7.0 (#117)<commit_after>// NOTE - this file is auto-generated. DO NOT EDIT.

package internal

const (
	// Version is the current version of the plaid-go library
	Version = "2.7.0"
)
<|endoftext|>


<commit_before>// +build generate

package main

import (
	"fmt"
	"log"
	"os"
)

func writeQuarterRound(file *os.File, a, b, c, d int) {
	add := "x%d+=x%d\n"
	xor := "x=x%d^x%d\n"
	rotate := "x%d=(x << %d) | (x >> (32 - %d))\n"

	fmt.Fprintf(file, add, a, b)
	fmt.Fprintf(file, xor, d, a)
	fmt.Fprintf(file, rotate, d, 16, 16)

	fmt.Fprintf(file, add, c, d)
	fmt.Fprintf(file, xor, b, c)
	fmt.Fprintf(file, rotate, b, 12, 12)

	fmt.Fprintf(file, add, a, b)
	fmt.Fprintf(file, xor, d, a)
	fmt.Fprintf(file, rotate, d, 8, 8)

	fmt.Fprintf(file, add, c, d)
	fmt.Fprintf(file, xor, b, c)
	fmt.Fprintf(file, rotate, b, 7, 7)
}

func writeChacha20Block(file *os.File) {
	fmt.Fprintln(file, `
func ChaCha20Block(s *[16]uint32, out []byte, rounds int) {
  var x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15 = s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7],s[8],s[9],s[10],s[11],s[12],s[13],s[14],s[15]
	for i := 0; i < rounds; i+=2 {
    var x uint32
    `)

	writeQuarterRound(file, 0, 4, 8, 12)
	writeQuarterRound(file, 1, 5, 9, 13)
	writeQuarterRound(file, 2, 6, 10, 14)
	writeQuarterRound(file, 3, 7, 11, 15)
	writeQuarterRound(file, 0, 5, 10, 15)
	writeQuarterRound(file, 1, 6, 11, 12)
	writeQuarterRound(file, 2, 7, 8, 13)
	writeQuarterRound(file, 3, 4, 9, 14)
	fmt.Fprintln(file, "}")
	for i := 0; i < 16; i++ {
		fmt.Fprintf(file, "binary.LittleEndian.PutUint32(out[%d:%d], s[%d]+x%d)\n", i*4, i*4+4, i, i)
	}
	fmt.Fprintln(file, "}")
	fmt.Fprintln(file)
}

func main() {
	file, err := os.OpenFile("chacha_core.generated.go", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
	if err != nil {
		log.Fatalf("Failed to generate chacha_core.go: %v", err)
	}
	defer file.Close()

	fmt.Fprintln(file, "// GENERATED CODE. DO NOT MODIFY!")
	fmt.Fprintln(file, "package internal")
	fmt.Fprintln(file)
	fmt.Fprintln(file, "import \"encoding/binary\"")
	fmt.Fprintln(file)
	writeChacha20Block(file)
}
<commit_msg>remove generated package comments<commit_after>// +build generate

package main

import (
	"fmt"
	"log"
	"os"
)

func writeQuarterRound(file *os.File, a, b, c, d int) {
	add := "x%d+=x%d\n"
	xor := "x=x%d^x%d\n"
	rotate := "x%d=(x << %d) | (x >> (32 - %d))\n"

	fmt.Fprintf(file, add, a, b)
	fmt.Fprintf(file, xor, d, a)
	fmt.Fprintf(file, rotate, d, 16, 16)

	fmt.Fprintf(file, add, c, d)
	fmt.Fprintf(file, xor, b, c)
	fmt.Fprintf(file, rotate, b, 12, 12)

	fmt.Fprintf(file, add, a, b)
	fmt.Fprintf(file, xor, d, a)
	fmt.Fprintf(file, rotate, d, 8, 8)

	fmt.Fprintf(file, add, c, d)
	fmt.Fprintf(file, xor, b, c)
	fmt.Fprintf(file, rotate, b, 7, 7)
}

func writeChacha20Block(file *os.File) {
	fmt.Fprintln(file, `
func ChaCha20Block(s *[16]uint32, out []byte, rounds int) {
  var x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15 = s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7],s[8],s[9],s[10],s[11],s[12],s[13],s[14],s[15]
	for i := 0; i < rounds; i+=2 {
    var x uint32
    `)

	writeQuarterRound(file, 0, 4, 8, 12)
	writeQuarterRound(file, 1, 5, 9, 13)
	writeQuarterRound(file, 2, 6, 10, 14)
	writeQuarterRound(file, 3, 7, 11, 15)
	writeQuarterRound(file, 0, 5, 10, 15)
	writeQuarterRound(file, 1, 6, 11, 12)
	writeQuarterRound(file, 2, 7, 8, 13)
	writeQuarterRound(file, 3, 4, 9, 14)
	fmt.Fprintln(file, "}")
	for i := 0; i < 16; i++ {
		fmt.Fprintf(file, "binary.LittleEndian.PutUint32(out[%d:%d], s[%d]+x%d)\n", i*4, i*4+4, i, i)
	}
	fmt.Fprintln(file, "}")
	fmt.Fprintln(file)
}

func main() {
	file, err := os.OpenFile("chacha_core.generated.go", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
	if err != nil {
		log.Fatalf("Failed to generate chacha_core.go: %v", err)
	}
	defer file.Close()

	fmt.Fprintln(file, "package internal")
	fmt.Fprintln(file)
	fmt.Fprintln(file, "import \"encoding/binary\"")
	fmt.Fprintln(file)
	writeChacha20Block(file)
}
<|endoftext|>


<commit_before>package bloom_filter

import (
	"testing"
)

func assetEqual(t *testing.T, expected, actual interface{}) {
	if expected != actual {
		t.Errorf("Expected `%v`. Got `%v`\n", expected, actual)
	}
}

func TestNewBloomFilter(t *testing.T) {
	b := NewBloomFilter(0.001, 10)

	assetEqual(t, false, b.Check("user:35"))
	assetEqual(t, false, b.Check("user:165"))
	assetEqual(t, false, b.Check("user:55"))
	assetEqual(t, false, b.Check("user:99"))

	b.Add("user:35")

	assetEqual(t, true, b.Check("user:35"))
	assetEqual(t, false, b.Check("user:165"))
	assetEqual(t, false, b.Check("user:55"))
	assetEqual(t, false, b.Check("user:99"))

	b.Add("user:165")

	assetEqual(t, true, b.Check("user:35"))
	assetEqual(t, true, b.Check("user:165"))
	assetEqual(t, false, b.Check("user:55"))
	assetEqual(t, false, b.Check("user:99"))

	b.Add("user:55")
	b.Add("user:99")

	assetEqual(t, true, b.Check("user:35"))
	assetEqual(t, true, b.Check("user:165"))
	assetEqual(t, true, b.Check("user:55"))
	assetEqual(t, true, b.Check("user:99"))
}
<commit_msg>Rename test function<commit_after>package bloom_filter

import (
	"testing"
)

func assetEqual(t *testing.T, expected, actual interface{}) {
	if expected != actual {
		t.Errorf("Expected `%v`. Got `%v`\n", expected, actual)
	}
}

func TestSetBloomFilter(t *testing.T) {
	b := NewBloomFilter(0.001, 10)

	assetEqual(t, false, b.Check("user:35"))
	assetEqual(t, false, b.Check("user:165"))
	assetEqual(t, false, b.Check("user:55"))
	assetEqual(t, false, b.Check("user:99"))

	b.Add("user:35")

	assetEqual(t, true, b.Check("user:35"))
	assetEqual(t, false, b.Check("user:165"))
	assetEqual(t, false, b.Check("user:55"))
	assetEqual(t, false, b.Check("user:99"))

	b.Add("user:165")

	assetEqual(t, true, b.Check("user:35"))
	assetEqual(t, true, b.Check("user:165"))
	assetEqual(t, false, b.Check("user:55"))
	assetEqual(t, false, b.Check("user:99"))

	b.Add("user:55")
	b.Add("user:99")

	assetEqual(t, true, b.Check("user:35"))
	assetEqual(t, true, b.Check("user:165"))
	assetEqual(t, true, b.Check("user:55"))
	assetEqual(t, true, b.Check("user:99"))
}
<|endoftext|>


<commit_before>package schemalex

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"io"
	"io/ioutil"
	"math/big"
	"net"
	"net/url"
	"os"
	"strconv"
	"strings"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

func generateCertificate(host string, certFile, secretFile io.Writer, isCA bool) error {
	priv, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return err
	}

	notBefore := time.Now()
	notAfter := notBefore.Add(365 * 24 * time.Hour)

	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		return err
	}

	template := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Organization: []string{"Schemalex Group"},
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,

		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		BasicConstraintsValid: true,
	}

	hosts := strings.Split(host, ",")
	for _, h := range hosts {
		if ip := net.ParseIP(h); ip != nil {
			template.IPAddresses = append(template.IPAddresses, ip)
		} else {
			template.DNSNames = append(template.DNSNames, h)
		}
	}

	if isCA {
		template.IsCA = true
		template.KeyUsage |= x509.KeyUsageCertSign
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
	if err != nil {
		return err
	}

	pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	pem.Encode(secretFile, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
	return nil

}

func TestSchemaSource(t *testing.T) {
	certFile, err := ioutil.TempFile("", "schemalex-cert-")
	if !assert.NoError(t, err, "creating temporary file should succeed") {
		return
	}
	defer certFile.Close()
	defer os.Remove(certFile.Name())

	secretFile, err := ioutil.TempFile("", "schemalex-secret-")
	if !assert.NoError(t, err, "creating temporary file should succeed") {
		return
	}
	defer secretFile.Close()
	defer os.Remove(secretFile.Name())

	caCertFile, err := ioutil.TempFile("", "schemalex-ca-")
	if !assert.NoError(t, err, "creating temporary file should succeed") {
		return
	}
	defer caCertFile.Close()
	defer os.Remove(caCertFile.Name())

	if !assert.NoError(t, generateCertificate("schemalex.github.io", certFile, secretFile, false), "generating certificates should succeed") {
		return
	}
	if !assert.NoError(t, generateCertificate("schemalex.github.io", caCertFile, ioutil.Discard, true), "generating server CA should succeed") {
		return
	}

	type checker func(s SchemaSource) bool

	testcases := []struct {
		Input string
		Check []checker
		Error bool
	}{
		{
			Input: "/path/to/source.sql",
			Check: []checker{
				func(s SchemaSource) bool {
					lfs, ok := s.(localFileSource)
					if !assert.True(t, ok, `expected source to be a local file source, got %T`, s) {
						return false
					}
					if !assert.Equal(t, "/path/to/source.sql", string(lfs), "paths should match") {
						return false
					}
					return true
				},
			},
		},
		{
			Input: "file:///path/to/source.sql",
			Check: []checker{
				func(s SchemaSource) bool {
					lfs, ok := s.(localFileSource)
					if !assert.True(t, ok, `expected source to be a local file source, got %T`, s) {
						return false
					}
					if !assert.Equal(t, "/path/to/source.sql", string(lfs), "paths should match") {
						return false
					}
					return true
				},
			},
		},
		{
			Input: "-",
			Check: []checker{
				func(s SchemaSource) bool {
					_, ok := s.(*readerSource)
					if !assert.True(t, ok, `expected source to be reader source, got %T`, s) {
						return false
					}
					return true
				},
			},
		},
		{
			Input: "mysql://user:pass@tcp(1.2.3.4:9999)/dbname",
			Check: []checker{
				func(s SchemaSource) bool {
					_, ok := s.(mysqlSource)
					if !assert.True(t, ok, `expected source to be mysql source, got %T`, s) {
						return false
					}
					return true
				},
			},
		},
		{
			Input: "mysql://user:pass@tcp(1.2.3.4:9999)/dbname?tls=true",
			Check: []checker{
				func(s SchemaSource) bool {
					ms, ok := s.(mysqlSource)
					if !assert.True(t, ok, `expected source to be mysql source, got %T`, s) {
						return false
					}

					_, err := ms.MySQLConfig()
					if !assert.Error(t, err, "should error, because no tls configuration is provided") {
						return false
					}

					return true
				},
			},
		},
		{
			Input: fmt.Sprintf(
				"mysql://user:pass@tcp(1.2.3.4:9999)/dbname?tls=true&ssl-ca=%s&ssl-cert=%s&ssl-secret=%s",
				url.QueryEscape(caCertFile.Name()),
				url.QueryEscape(certFile.Name()),
				url.QueryEscape(secretFile.Name()),
			),
			Check: []checker{
				func(s SchemaSource) bool {
					ms, ok := s.(mysqlSource)
					if !assert.True(t, ok, `expected source to be mysql source, got %T`, s) {
						return false
					}

					cfg, err := ms.MySQLConfig()
					if !assert.NoError(t, err, "should be able to parse DSN") {
						return false
					}
					if !assert.True(t, strings.HasPrefix(cfg.TLSConfig, "custom-tls"), "TLSConfig should be enabled") {
						return false
					}

					return true
				},
			},
		},
		{
			Input: "local-git:///path/to/dir?file=foo/baz.sql&commitish=deadbeaf",
			Check: []checker{
				func(s SchemaSource) bool {
					lgs, ok := s.(*localGitSource)
					if !assert.True(t, ok, `expected source to be local git source, got %T`, s) {
						return false
					}

					if !assert.Equal(t, "/path/to/dir", lgs.dir, "directory should match") {
						return false
					}
					if !assert.Equal(t, "foo/baz.sql", lgs.file, "file should match") {
						return false
					}
					if !assert.Equal(t, "deadbeaf", lgs.commitish, "commit ID should match") {
						return false
					}
					return true
				},
			},
		},
		{Input: "https://github.com/schemalex/schemalex", Error: true},
	}

	for _, c := range testcases {
		t.Run(fmt.Sprintf("Parse %s", strconv.Quote(c.Input)), func(t *testing.T) {
			s, err := NewSchemaSource(c.Input)
			if c.Error {
				assert.Error(t, err, "expected '%s' to result in an error")

				// if we expected an error, we have nothing more to do in this
				// particular test case regardless of the previous assert
				return

			}

			if !assert.NoError(t, err, "expected '%s' to successfully parse") {
				return
			}

			if len(c.Check) == 0 {
				return
			}

			for _, check := range c.Check {
				if !check(s) {
					return
				}
			}
		})
	}
}
<commit_msg>Avoid 'Error call has possible formatting directive %s'.<commit_after>package schemalex

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"io"
	"io/ioutil"
	"math/big"
	"net"
	"net/url"
	"os"
	"strconv"
	"strings"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

func generateCertificate(host string, certFile, secretFile io.Writer, isCA bool) error {
	priv, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return err
	}

	notBefore := time.Now()
	notAfter := notBefore.Add(365 * 24 * time.Hour)

	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		return err
	}

	template := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Organization: []string{"Schemalex Group"},
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,

		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		BasicConstraintsValid: true,
	}

	hosts := strings.Split(host, ",")
	for _, h := range hosts {
		if ip := net.ParseIP(h); ip != nil {
			template.IPAddresses = append(template.IPAddresses, ip)
		} else {
			template.DNSNames = append(template.DNSNames, h)
		}
	}

	if isCA {
		template.IsCA = true
		template.KeyUsage |= x509.KeyUsageCertSign
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
	if err != nil {
		return err
	}

	pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	pem.Encode(secretFile, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
	return nil

}

func TestSchemaSource(t *testing.T) {
	certFile, err := ioutil.TempFile("", "schemalex-cert-")
	if !assert.NoError(t, err, "creating temporary file should succeed") {
		return
	}
	defer certFile.Close()
	defer os.Remove(certFile.Name())

	secretFile, err := ioutil.TempFile("", "schemalex-secret-")
	if !assert.NoError(t, err, "creating temporary file should succeed") {
		return
	}
	defer secretFile.Close()
	defer os.Remove(secretFile.Name())

	caCertFile, err := ioutil.TempFile("", "schemalex-ca-")
	if !assert.NoError(t, err, "creating temporary file should succeed") {
		return
	}
	defer caCertFile.Close()
	defer os.Remove(caCertFile.Name())

	if !assert.NoError(t, generateCertificate("schemalex.github.io", certFile, secretFile, false), "generating certificates should succeed") {
		return
	}
	if !assert.NoError(t, generateCertificate("schemalex.github.io", caCertFile, ioutil.Discard, true), "generating server CA should succeed") {
		return
	}

	type checker func(s SchemaSource) bool

	testcases := []struct {
		Input string
		Check []checker
		Error bool
	}{
		{
			Input: "/path/to/source.sql",
			Check: []checker{
				func(s SchemaSource) bool {
					lfs, ok := s.(localFileSource)
					if !assert.True(t, ok, `expected source to be a local file source, got %T`, s) {
						return false
					}
					if !assert.Equal(t, "/path/to/source.sql", string(lfs), "paths should match") {
						return false
					}
					return true
				},
			},
		},
		{
			Input: "file:///path/to/source.sql",
			Check: []checker{
				func(s SchemaSource) bool {
					lfs, ok := s.(localFileSource)
					if !assert.True(t, ok, `expected source to be a local file source, got %T`, s) {
						return false
					}
					if !assert.Equal(t, "/path/to/source.sql", string(lfs), "paths should match") {
						return false
					}
					return true
				},
			},
		},
		{
			Input: "-",
			Check: []checker{
				func(s SchemaSource) bool {
					_, ok := s.(*readerSource)
					if !assert.True(t, ok, `expected source to be reader source, got %T`, s) {
						return false
					}
					return true
				},
			},
		},
		{
			Input: "mysql://user:pass@tcp(1.2.3.4:9999)/dbname",
			Check: []checker{
				func(s SchemaSource) bool {
					_, ok := s.(mysqlSource)
					if !assert.True(t, ok, `expected source to be mysql source, got %T`, s) {
						return false
					}
					return true
				},
			},
		},
		{
			Input: "mysql://user:pass@tcp(1.2.3.4:9999)/dbname?tls=true",
			Check: []checker{
				func(s SchemaSource) bool {
					ms, ok := s.(mysqlSource)
					if !assert.True(t, ok, `expected source to be mysql source, got %T`, s) {
						return false
					}

					_, err := ms.MySQLConfig()
					if !assert.Error(t, err, "should error, because no tls configuration is provided") {
						return false
					}

					return true
				},
			},
		},
		{
			Input: fmt.Sprintf(
				"mysql://user:pass@tcp(1.2.3.4:9999)/dbname?tls=true&ssl-ca=%s&ssl-cert=%s&ssl-secret=%s",
				url.QueryEscape(caCertFile.Name()),
				url.QueryEscape(certFile.Name()),
				url.QueryEscape(secretFile.Name()),
			),
			Check: []checker{
				func(s SchemaSource) bool {
					ms, ok := s.(mysqlSource)
					if !assert.True(t, ok, `expected source to be mysql source, got %T`, s) {
						return false
					}

					cfg, err := ms.MySQLConfig()
					if !assert.NoError(t, err, "should be able to parse DSN") {
						return false
					}
					if !assert.True(t, strings.HasPrefix(cfg.TLSConfig, "custom-tls"), "TLSConfig should be enabled") {
						return false
					}

					return true
				},
			},
		},
		{
			Input: "local-git:///path/to/dir?file=foo/baz.sql&commitish=deadbeaf",
			Check: []checker{
				func(s SchemaSource) bool {
					lgs, ok := s.(*localGitSource)
					if !assert.True(t, ok, `expected source to be local git source, got %T`, s) {
						return false
					}

					if !assert.Equal(t, "/path/to/dir", lgs.dir, "directory should match") {
						return false
					}
					if !assert.Equal(t, "foo/baz.sql", lgs.file, "file should match") {
						return false
					}
					if !assert.Equal(t, "deadbeaf", lgs.commitish, "commit ID should match") {
						return false
					}
					return true
				},
			},
		},
		{Input: "https://github.com/schemalex/schemalex", Error: true},
	}

	for _, c := range testcases {
		t.Run(fmt.Sprintf("Parse %s", strconv.Quote(c.Input)), func(t *testing.T) {
			s, err := NewSchemaSource(c.Input)
			if c.Error {
				assertError := assert.Error // To avoid 'Error call has possible formatting directive %s'.
				assertError(t, err, "expected '%s' to result in an error")

				// if we expected an error, we have nothing more to do in this
				// particular test case regardless of the previous assert
				return

			}

			if !assert.NoError(t, err, "expected '%s' to successfully parse") {
				return
			}

			if len(c.Check) == 0 {
				return
			}

			for _, check := range c.Check {
				if !check(s) {
					return
				}
			}
		})
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Luke Shumaker

package httpentity

import (
	"bitbucket.org/ww/goautoneg"
	"fmt"
	"httpentity/util"
	"mime"
	"net/url"
	"os"
	"path"
	"runtime"
	"strings"
)

func normalizeURL(u1 *url.URL) (u *url.URL, mimetype string) {
	u, _ = u1.Parse("") // normalize
	// the file extension overrides the Accept: header
	if ext := path.Ext(u.Path); ext != "" {
		mimetype = mime.TypeByExtension(ext)
		u.Path = strings.TrimSuffix(u.Path, ext)
	}
	// add a trailing slash if there isn't one (so that relative
	// child URLs don't go to the parent)
	if !strings.HasSuffix(u.Path, "/") {
		u.Path = u.Path + "/"
	}
	return
}

// assumes that the url has already been passed to normalizeURL()
func (r *Router) route(req Request, u *url.URL) (res Response) {
	if r.LogRequest {
		fmt.Fprintf(os.Stderr, "%s %q %#v\n", req.Method, u.String(), req)
	}
	// do the routing
	res = route(r.Root, req, strings.TrimPrefix(u.Path, r.Prefix))

	// make sure the Location: header is absolute
	if l := res.Headers.Get("Location"); l != "" {
		u2, _ := u.Parse(l)
		res.Headers.Set("Location", u2.String())
		// XXX: this is pretty hacky, because it is tightly
		// integrated with the entity format used by
		// (Request).StatusCreated()
		if res.Status == 201 {
			ilist := []interface{}(res.Entity.(heutil.NetList))
			slist := make([]string, len(ilist))
			for i, iface := range ilist {
				slist[i] = iface.(string)
			}
			res.Entity = extensions2net(u2, slist)
		}
	}

	return
}

// assumes that the url has already been passed to normalizeURL()
func (r *Router) finish(req Request, u *url.URL, res *Response) {
	// generate a 500 error if we paniced
	if err := recover(); err != nil {
		reason := err
		if r.Stacktrace {
			const size = 64 << 10
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]
			reason = fmt.Sprintf("%v\n\n%s", err, string(buf))
			fmt.Fprintf(os.Stderr, "%v\n\n%s", err, string(buf))
		}
		*res = req.statusInternalServerError(reason)
	}
	// figure out the content type of the response
	if res.Entity != nil && res.Headers.Get("Content-Type") == "" {
		encoders := res.Entity.Encoders()
		mimetypes := encoders2mimetypes(encoders)
		accept := req.Headers.Get("Accept")
		if len(encoders) > 1 && accept == "" {
			*res = req.statusMultipleChoices(u, mimetypes)
		} else {
			// TODO: long term: In the event of a tie,
			// goautoneg returns the first match in the
			// mimetypes array, which in our case is
			// essentially random.  Instead, we should
			// return an HTTP 300 Multiple Choices.  This
			// means forking or re-implementing goautoneg.
			mimetype := goautoneg.Negotiate(req.Headers.Get("Accept"), mimetypes)
			if mimetype == "" {
				*res = req.statusNotAcceptable(u, mimetypes)
			} else {
				res.Headers.Set("Content-Type", mimetype+"; charset=utf-8")
			}
		}
	}
}
<commit_msg>httpentities: normalize request methods to CAPS.<commit_after>// Copyright 2015 Luke Shumaker

package httpentity

import (
	"bitbucket.org/ww/goautoneg"
	"fmt"
	"httpentity/util"
	"mime"
	"net/url"
	"os"
	"path"
	"runtime"
	"strings"
)

func normalizeURL(u1 *url.URL) (u *url.URL, mimetype string) {
	u, _ = u1.Parse("") // normalize
	// the file extension overrides the Accept: header
	if ext := path.Ext(u.Path); ext != "" {
		mimetype = mime.TypeByExtension(ext)
		u.Path = strings.TrimSuffix(u.Path, ext)
	}
	// add a trailing slash if there isn't one (so that relative
	// child URLs don't go to the parent)
	if !strings.HasSuffix(u.Path, "/") {
		u.Path = u.Path + "/"
	}
	return
}

// assumes that the url has already been passed to normalizeURL()
func (r *Router) route(req Request, u *url.URL) (res Response) {
	req.Method = strings.ToUpper(req.Method)
	if r.LogRequest {
		fmt.Fprintf(os.Stderr, "%s %q %#v\n", req.Method, u.String(), req)
	}
	// do the routing
	res = route(r.Root, req, strings.TrimPrefix(u.Path, r.Prefix))

	// make sure the Location: header is absolute
	if l := res.Headers.Get("Location"); l != "" {
		u2, _ := u.Parse(l)
		res.Headers.Set("Location", u2.String())
		// XXX: this is pretty hacky, because it is tightly
		// integrated with the entity format used by
		// (Request).StatusCreated()
		if res.Status == 201 {
			ilist := []interface{}(res.Entity.(heutil.NetList))
			slist := make([]string, len(ilist))
			for i, iface := range ilist {
				slist[i] = iface.(string)
			}
			res.Entity = extensions2net(u2, slist)
		}
	}

	return
}

// assumes that the url has already been passed to normalizeURL()
func (r *Router) finish(req Request, u *url.URL, res *Response) {
	// generate a 500 error if we paniced
	if err := recover(); err != nil {
		reason := err
		if r.Stacktrace {
			const size = 64 << 10
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]
			reason = fmt.Sprintf("%v\n\n%s", err, string(buf))
			fmt.Fprintf(os.Stderr, "%v\n\n%s", err, string(buf))
		}
		*res = req.statusInternalServerError(reason)
	}
	// figure out the content type of the response
	if res.Entity != nil && res.Headers.Get("Content-Type") == "" {
		encoders := res.Entity.Encoders()
		mimetypes := encoders2mimetypes(encoders)
		accept := req.Headers.Get("Accept")
		if len(encoders) > 1 && accept == "" {
			*res = req.statusMultipleChoices(u, mimetypes)
		} else {
			// TODO: long term: In the event of a tie,
			// goautoneg returns the first match in the
			// mimetypes array, which in our case is
			// essentially random.  Instead, we should
			// return an HTTP 300 Multiple Choices.  This
			// means forking or re-implementing goautoneg.
			mimetype := goautoneg.Negotiate(req.Headers.Get("Accept"), mimetypes)
			if mimetype == "" {
				*res = req.statusNotAcceptable(u, mimetypes)
			} else {
				res.Headers.Set("Content-Type", mimetype+"; charset=utf-8")
			}
		}
	}
}
<|endoftext|>


<commit_before>package command

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/buger/goterm"
	"github.com/gravitational/teleport/Godeps/_workspace/src/gopkg.in/alecthomas/kingpin.v2"
	"github.com/gravitational/teleport/auth"
	"github.com/gravitational/teleport/utils"
)

type Command struct {
	client *auth.Client
	out    io.Writer
	in     io.Reader
}

func NewCommand() *Command {
	return &Command{
		out: os.Stdout,
		in:  os.Stdin,
	}
}

func (cmd *Command) SetClient(client *auth.Client) {
	cmd.client = client
}

func (cmd *Command) SetOut(out io.Writer) {
	cmd.out = out
}

func (cmd *Command) Run(args []string) error {
	app := kingpin.New("tctl", "CLI for key management of teleport SSH cluster")
	authUrl := app.Flag("auth", "Teleport URL").Default(DefaultTeleportURL).String()

	// Host CA
	hostCa := app.Command("host-ca", "Operations with host certificate authority")

	hostCaReset := hostCa.Command("reset", "Reset host certificate authority keys")
	hostCaResetConfirm := hostCaReset.Flag("confirm", "Automatically apply the operation without confirmation").Bool()

	hostCaPubKey := hostCa.Command("pub-key", "print host certificate authority public key")

	// User CA
	userCa := app.Command("user-ca", "Operations with user certificate authority")

	userCaReset := userCa.Command("reset", "Reset user certificate authority keys")
	userCaResetConfirm := userCaReset.Flag("confirm", "Automatically apply the operation without confirmation").Bool()

	userCaPubKey := userCa.Command("pub-key", "Print user certificate authority public key")

	// Remote CA
	remoteCa := app.Command("remote-ca", "Operations with remote certificate authority")

	remoteCaUpsert := remoteCa.Command("upsert", "Upsert remote certificate to trust")
	remoteCaUpsertID := remoteCaUpsert.Flag("id", "Certificate id").Required().String()
	remoteCaUpsertFQDN := remoteCaUpsert.Flag("fqdn", "FQDN of the remote party").Required().String()
	remoteCaUpsertType := remoteCaUpsert.Flag("type", "Cert type (host or user)").Required().String()
	remoteCaUpsertPath := remoteCaUpsert.Flag("path", "Cert path (reads from stdout if omitted)").Required().ExistingFile()
	remoteCaUpsertTTL := remoteCaUpsert.Flag("ttl", "ttl for certificate to be trusted").Duration()

	remoteCaLs := remoteCa.Command("ls", "List trusted remote certificates")
	remoteCaLsFQDN := remoteCaLs.Flag("fqdn", "FQDN of the remote party").String()
	remoteCaLsType := remoteCaLs.Flag("type", "Cert type (host or user)").Required().String()

	remoteCaRm := remoteCa.Command("rm", "Remote remote CA from list of trusted certs")
	remoteCaRmID := remoteCaRm.Flag("id", "Certificate id").Required().String()
	remoteCaRmFQDN := remoteCaRm.Flag("fqdn", "FQDN of the remote party").Required().String()
	remoteCaRmType := remoteCaRm.Flag("type", "Cert type (host or user)").Required().String()

	// Secret
	secret := app.Command("secret", "Operations with secret tokens")

	secretNew := secret.Command("new", "Generate new secret key")

	// Token
	token := app.Command("token", "Generates provisioning tokens")

	tokenGenerate := token.Command("generate", "Generate provisioning token for server with fqdn")
	tokenGenerateFQDN := tokenGenerate.Flag("fqdn", "FQDN of the server").Required().String()
	tokenGenerateTTL := tokenGenerate.Flag("ttl", "Time to live").Default("120").Duration()
	tokenGenerateOutput := tokenGenerate.Flag("output", "Optional output file").String()

	// User
	user := app.Command("user", "Operations with registered users")

	userLs := user.Command("ls", "List users registered in teleport")

	userDelete := user.Command("delete", "Delete user")
	userDeleteUser := userDelete.Flag("user", "User to delete").Required().String()

	userUpsertKey := user.Command("upsert-key", "Grant access to the user key, returns signed certificate")
	userUpsertKeyUser := userUpsertKey.Flag("user", "User holding the key").Required().String()
	userUpsertKeyKeyID := userUpsertKey.Flag("key-id", "SSH key ID").Required().String()
	userUpsertKeyKey := userUpsertKey.Flag("key", "Path to public key").Required().ExistingFile()
	userUpsertKeyTTL := userUpsertKey.Flag("ttl", "Access time to live, certificate and access entry will expire when set").Duration()

	userLsKeys := user.Command("ls-keys", "List user's keys registered in teleport")
	userLsKeysUser := userLsKeys.Flag("user", "User to list keys form").Required().String()

	userSetPass := user.Command("set-pass", "Set user password")
	userSetPassUser := userSetPass.Flag("user", "User name").Required().String()
	userSetPassPass := userSetPass.Flag("pass", "Password").Required().String()

	selectedCommand := kingpin.MustParse(app.Parse(args[1:]))

	a, err := utils.ParseAddr(*authUrl)
	if err != nil {
		return err
	}
	clt, err := auth.NewClientFromNetAddr(*a)
	if err != nil {
		return err
	}

	cmd.client = clt

	switch selectedCommand {
	// Host CA
	case hostCaReset.FullCommand():
		cmd.ResetHostCA(*hostCaResetConfirm)
	case hostCaPubKey.FullCommand():
		cmd.GetHostCAPub()

	// User CA
	case userCaReset.FullCommand():
		cmd.ResetUserCA(*userCaResetConfirm)
	case userCaPubKey.FullCommand():
		cmd.GetUserCAPub()

	// Remote CA
	case remoteCaUpsert.FullCommand():
		cmd.UpsertRemoteCert(*remoteCaUpsertID, *remoteCaUpsertFQDN,
			*remoteCaUpsertType, *remoteCaUpsertPath, *remoteCaUpsertTTL)
	case remoteCaLs.FullCommand():
		cmd.GetRemoteCerts(*remoteCaLsFQDN, *remoteCaLsType)
	case remoteCaRm.FullCommand():
		cmd.DeleteRemoteCert(*remoteCaRmID, *remoteCaRmFQDN, *remoteCaRmType)

	// Secret
	case secretNew.FullCommand():
		cmd.NewKey()

	// Token
	case tokenGenerate.FullCommand():
		cmd.GenerateToken(*tokenGenerateFQDN, *tokenGenerateTTL,
			*tokenGenerateOutput)

	// User
	case userLs.FullCommand():
		cmd.GetUsers()
	case userDelete.FullCommand():
		cmd.DeleteUser(*userDeleteUser)
	case userUpsertKey.FullCommand():
		cmd.UpsertKey(*userUpsertKeyUser, *userUpsertKeyKeyID,
			*userUpsertKeyKey, *userUpsertKeyTTL)
	case userLsKeys.FullCommand():
		cmd.GetUserKeys(*userLsKeysUser)
	case userSetPass.FullCommand():
		cmd.SetPass(*userSetPassUser, *userSetPassPass)
	}

	return nil
}

func (cmd *Command) readInput(path string) ([]byte, error) {
	if path != "" {
		return utils.ReadPath(path)
	}
	reader := bufio.NewReader(cmd.in)
	return reader.ReadSlice('\n')
}

func (cmd *Command) confirm(message string) bool {
	reader := bufio.NewReader(cmd.in)
	fmt.Fprintf(cmd.out, fmt.Sprintf("%v (Y/N): ", message))
	text, _ := reader.ReadString('\n')
	text = strings.Trim(text, "\n\r\t")
	return text == "Y" || text == "yes" || text == "y"
}

func (cmd *Command) printResult(format string, in interface{}, err error) {
	if err != nil {
		cmd.printError(err)
	} else {
		cmd.printOK(format, fmt.Sprintf("%v", in))
	}
}

func (cmd *Command) printStatus(in interface{}, err error) {
	if err != nil {
		cmd.printError(err)
	} else {
		cmd.printOK("%s", in)
	}
}

func (cmd *Command) printError(err error) {
	fmt.Fprint(cmd.out, goterm.Color(fmt.Sprintf("ERROR: %s", err), goterm.RED)+"\n")
}

func (cmd *Command) printOK(message string, params ...interface{}) {
	fmt.Fprintf(cmd.out,
		goterm.Color(
			fmt.Sprintf("OK: %s\n", fmt.Sprintf(message, params...)), goterm.GREEN)+"\n")
}

func (cmd *Command) printInfo(message string, params ...interface{}) {
	fmt.Fprintf(cmd.out, "INFO: %s\n", fmt.Sprintf(message, params...))
}

const DefaultTeleportURL = "unix:///tmp/teleport.auth.sock"
<commit_msg>Fixed bug with tctl ttl flag<commit_after>package command

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/buger/goterm"
	"github.com/gravitational/teleport/Godeps/_workspace/src/gopkg.in/alecthomas/kingpin.v2"
	"github.com/gravitational/teleport/auth"
	"github.com/gravitational/teleport/utils"
)

type Command struct {
	client *auth.Client
	out    io.Writer
	in     io.Reader
}

func NewCommand() *Command {
	return &Command{
		out: os.Stdout,
		in:  os.Stdin,
	}
}

func (cmd *Command) SetClient(client *auth.Client) {
	cmd.client = client
}

func (cmd *Command) SetOut(out io.Writer) {
	cmd.out = out
}

func (cmd *Command) Run(args []string) error {
	app := kingpin.New("tctl", "CLI for key management of teleport SSH cluster")
	authUrl := app.Flag("auth", "Teleport URL").Default(DefaultTeleportURL).String()

	// Host CA
	hostCa := app.Command("host-ca", "Operations with host certificate authority")

	hostCaReset := hostCa.Command("reset", "Reset host certificate authority keys")
	hostCaResetConfirm := hostCaReset.Flag("confirm", "Automatically apply the operation without confirmation").Bool()

	hostCaPubKey := hostCa.Command("pub-key", "print host certificate authority public key")

	// User CA
	userCa := app.Command("user-ca", "Operations with user certificate authority")

	userCaReset := userCa.Command("reset", "Reset user certificate authority keys")
	userCaResetConfirm := userCaReset.Flag("confirm", "Automatically apply the operation without confirmation").Bool()

	userCaPubKey := userCa.Command("pub-key", "Print user certificate authority public key")

	// Remote CA
	remoteCa := app.Command("remote-ca", "Operations with remote certificate authority")

	remoteCaUpsert := remoteCa.Command("upsert", "Upsert remote certificate to trust")
	remoteCaUpsertID := remoteCaUpsert.Flag("id", "Certificate id").Required().String()
	remoteCaUpsertFQDN := remoteCaUpsert.Flag("fqdn", "FQDN of the remote party").Required().String()
	remoteCaUpsertType := remoteCaUpsert.Flag("type", "Cert type (host or user)").Required().String()
	remoteCaUpsertPath := remoteCaUpsert.Flag("path", "Cert path (reads from stdout if omitted)").Required().ExistingFile()
	remoteCaUpsertTTL := remoteCaUpsert.Flag("ttl", "ttl for certificate to be trusted").Duration()

	remoteCaLs := remoteCa.Command("ls", "List trusted remote certificates")
	remoteCaLsFQDN := remoteCaLs.Flag("fqdn", "FQDN of the remote party").String()
	remoteCaLsType := remoteCaLs.Flag("type", "Cert type (host or user)").Required().String()

	remoteCaRm := remoteCa.Command("rm", "Remote remote CA from list of trusted certs")
	remoteCaRmID := remoteCaRm.Flag("id", "Certificate id").Required().String()
	remoteCaRmFQDN := remoteCaRm.Flag("fqdn", "FQDN of the remote party").Required().String()
	remoteCaRmType := remoteCaRm.Flag("type", "Cert type (host or user)").Required().String()

	// Secret
	secret := app.Command("secret", "Operations with secret tokens")

	secretNew := secret.Command("new", "Generate new secret key")

	// Token
	token := app.Command("token", "Generates provisioning tokens")

	tokenGenerate := token.Command("generate", "Generate provisioning token for server with fqdn")
	tokenGenerateFQDN := tokenGenerate.Flag("fqdn", "FQDN of the server").Required().String()
	tokenGenerateTTL := tokenGenerate.Flag("ttl", "Time to live").Default("120s").Duration()
	tokenGenerateOutput := tokenGenerate.Flag("output", "Optional output file").String()

	// User
	user := app.Command("user", "Operations with registered users")

	userLs := user.Command("ls", "List users registered in teleport")

	userDelete := user.Command("delete", "Delete user")
	userDeleteUser := userDelete.Flag("user", "User to delete").Required().String()

	userUpsertKey := user.Command("upsert-key", "Grant access to the user key, returns signed certificate")
	userUpsertKeyUser := userUpsertKey.Flag("user", "User holding the key").Required().String()
	userUpsertKeyKeyID := userUpsertKey.Flag("key-id", "SSH key ID").Required().String()
	userUpsertKeyKey := userUpsertKey.Flag("key", "Path to public key").Required().ExistingFile()
	userUpsertKeyTTL := userUpsertKey.Flag("ttl", "Access time to live, certificate and access entry will expire when set").Duration()

	userLsKeys := user.Command("ls-keys", "List user's keys registered in teleport")
	userLsKeysUser := userLsKeys.Flag("user", "User to list keys form").Required().String()

	userSetPass := user.Command("set-pass", "Set user password")
	userSetPassUser := userSetPass.Flag("user", "User name").Required().String()
	userSetPassPass := userSetPass.Flag("pass", "Password").Required().String()

	selectedCommand := kingpin.MustParse(app.Parse(args[1:]))

	a, err := utils.ParseAddr(*authUrl)
	if err != nil {
		return err
	}
	clt, err := auth.NewClientFromNetAddr(*a)
	if err != nil {
		return err
	}

	cmd.client = clt

	switch selectedCommand {
	// Host CA
	case hostCaReset.FullCommand():
		cmd.ResetHostCA(*hostCaResetConfirm)
	case hostCaPubKey.FullCommand():
		cmd.GetHostCAPub()

	// User CA
	case userCaReset.FullCommand():
		cmd.ResetUserCA(*userCaResetConfirm)
	case userCaPubKey.FullCommand():
		cmd.GetUserCAPub()

	// Remote CA
	case remoteCaUpsert.FullCommand():
		cmd.UpsertRemoteCert(*remoteCaUpsertID, *remoteCaUpsertFQDN,
			*remoteCaUpsertType, *remoteCaUpsertPath, *remoteCaUpsertTTL)
	case remoteCaLs.FullCommand():
		cmd.GetRemoteCerts(*remoteCaLsFQDN, *remoteCaLsType)
	case remoteCaRm.FullCommand():
		cmd.DeleteRemoteCert(*remoteCaRmID, *remoteCaRmFQDN, *remoteCaRmType)

	// Secret
	case secretNew.FullCommand():
		cmd.NewKey()

	// Token
	case tokenGenerate.FullCommand():
		cmd.GenerateToken(*tokenGenerateFQDN, *tokenGenerateTTL,
			*tokenGenerateOutput)

	// User
	case userLs.FullCommand():
		cmd.GetUsers()
	case userDelete.FullCommand():
		cmd.DeleteUser(*userDeleteUser)
	case userUpsertKey.FullCommand():
		cmd.UpsertKey(*userUpsertKeyUser, *userUpsertKeyKeyID,
			*userUpsertKeyKey, *userUpsertKeyTTL)
	case userLsKeys.FullCommand():
		cmd.GetUserKeys(*userLsKeysUser)
	case userSetPass.FullCommand():
		cmd.SetPass(*userSetPassUser, *userSetPassPass)
	}

	return nil
}

func (cmd *Command) readInput(path string) ([]byte, error) {
	if path != "" {
		return utils.ReadPath(path)
	}
	reader := bufio.NewReader(cmd.in)
	return reader.ReadSlice('\n')
}

func (cmd *Command) confirm(message string) bool {
	reader := bufio.NewReader(cmd.in)
	fmt.Fprintf(cmd.out, fmt.Sprintf("%v (Y/N): ", message))
	text, _ := reader.ReadString('\n')
	text = strings.Trim(text, "\n\r\t")
	return text == "Y" || text == "yes" || text == "y"
}

func (cmd *Command) printResult(format string, in interface{}, err error) {
	if err != nil {
		cmd.printError(err)
	} else {
		cmd.printOK(format, fmt.Sprintf("%v", in))
	}
}

func (cmd *Command) printStatus(in interface{}, err error) {
	if err != nil {
		cmd.printError(err)
	} else {
		cmd.printOK("%s", in)
	}
}

func (cmd *Command) printError(err error) {
	fmt.Fprint(cmd.out, goterm.Color(fmt.Sprintf("ERROR: %s", err), goterm.RED)+"\n")
}

func (cmd *Command) printOK(message string, params ...interface{}) {
	fmt.Fprintf(cmd.out,
		goterm.Color(
			fmt.Sprintf("OK: %s\n", fmt.Sprintf(message, params...)), goterm.GREEN)+"\n")
}

func (cmd *Command) printInfo(message string, params ...interface{}) {
	fmt.Fprintf(cmd.out, "INFO: %s\n", fmt.Sprintf(message, params...))
}

const DefaultTeleportURL = "unix:///tmp/teleport.auth.sock"
<|endoftext|>


<commit_before>package main

import "testing"
import "os/user"

func Test_Add2Ints_1(t *testing.T) {
	mockuser := &user.User{Username: "vagrant", HomeDir: "/home/vagrant", Uid: "1000", Gid: "1000"}
	username, homedir, uid, gid, err := getUser(mockuser)
	if err != nil {
		t.Error("Got error from getUser " + err.Error())
	}
	if username == "vagrant" {
		t.Log("username passed.")
	} else {
		t.Errorf("Username failed: %s", username)
	}
	if homedir == "/home/vagrant" {
		t.Log("homedir passed.")
	} else {
		t.Errorf("homedir failed: %s", homedir)
	}
	if uid == 1000 {
		t.Log("uid passed.")
	} else {
		t.Errorf("uid failed: %i", uid)
	}
	if gid == 1000 {
		t.Log("git passed.")
	} else {
		t.Errorf("gid failed: %i", gid)
	}
}
<commit_msg>Cover additional cases in user_test<commit_after>package main

import "testing"
import "os/user"

func Test_getUser_1(t *testing.T) {
	mockuser := &user.User{Username: "vagrant", HomeDir: "/home/vagrant", Uid: "1000", Gid: "1000"}
	username, homedir, uid, gid, err := getUser(mockuser)
	if err != nil {
		t.Error("Got error from getUser " + err.Error())
	}
	if username == "vagrant" {
		t.Log("username passed.")
	} else {
		t.Errorf("Username failed: %s", username)
	}
	if homedir == "/home/vagrant" {
		t.Log("homedir passed.")
	} else {
		t.Errorf("homedir failed: %s", homedir)
	}
	if uid == 1000 {
		t.Log("uid passed.")
	} else {
		t.Errorf("uid failed: %i", uid)
	}
	if gid == 1000 {
		t.Log("git passed.")
	} else {
		t.Errorf("gid failed: %i", gid)
	}
}

func Test_getUser_2(t *testing.T) {
	mockuser := &user.User{Username: "", HomeDir: "/home/vagrant", Uid: "1000", Gid: "1000"}
	username, homedir, uid, gid, err := getUser(mockuser)
	if err == nil {
		t.Error("No error from getUser")
	}
}

func Test_getUser_3(t *testing.T) {
	mockuser := &user.User{Username: "Foo", HomeDir: "", Uid: "1000", Gid: "1000"}
	username, homedir, uid, gid, err := getUser(mockuser)
	if err == nil {
		t.Error("No error from getUser")
	}
}

<|endoftext|>


<commit_before>package util

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"fmt"
	"github.com/gruntwork-io/terragrunt/errors"
	"github.com/mattn/go-zglob"
)

// Return true if the given file exists
func FileExists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}

// Return the canonical version of the given path, relative to the given base path. That is, if the given path is a
// relative path, assume it is relative to the given base path. A canonical path is an absolute path with all relative
// components (e.g. "../") fully resolved, which makes it safe to compare paths as strings.
func CanonicalPath(path string, basePath string) (string, error) {
	if !filepath.IsAbs(path) {
		path = JoinPath(basePath, path)
	}
	absPath, err := filepath.Abs(path)
	if err != nil {
		return "", err
	}

	return CleanPath(absPath), nil
}

// Return the canonical version of the given paths, relative to the given base path. That is, if a given path is a
// relative path, assume it is relative to the given base path. A canonical path is an absolute path with all relative
// components (e.g. "../") fully resolved, which makes it safe to compare paths as strings.
func CanonicalPaths(paths []string, basePath string) ([]string, error) {
	canonicalPaths := []string{}

	for _, path := range paths {
		canonicalPath, err := CanonicalPath(path, basePath)
		if err != nil {
			return canonicalPaths, err
		}
		canonicalPaths = append(canonicalPaths, canonicalPath)
	}

	return canonicalPaths, nil
}

// Delete the given list of files. Note: this function ONLY deletes files and will return an error if you pass in a
// folder path.
func DeleteFiles(files []string) error {
	for _, file := range files {
		if err := os.Remove(file); err != nil {
			return errors.WithStackTrace(err)
		}
	}
	return nil
}

// Returns true if the given regex can be found in any of the files matched by the given glob
func Grep(regex *regexp.Regexp, glob string) (bool, error) {
	// Ideally, we'd use a builin Go library like filepath.Glob here, but per https://github.com/golang/go/issues/11862,
	// the current go implementation doesn't support treating ** as zero or more directories, just zero or one.
	// So we use a third-party library.
	matches, err := zglob.Glob(glob)
	if err != nil {
		return false, errors.WithStackTrace(err)
	}

	for _, match := range matches {
		if IsDir(match) {
			continue
		}
		bytes, err := ioutil.ReadFile(match)
		if err != nil {
			return false, errors.WithStackTrace(err)
		}

		if regex.Match(bytes) {
			return true, nil
		}
	}

	return false, nil
}

// Return true if the path points to a directory
func IsDir(path string) bool {
	fileInfo, err := os.Stat(path)
	return err == nil && fileInfo.IsDir()
}

// Return the relative path you would have to take to get from basePath to path
func GetPathRelativeTo(path string, basePath string) (string, error) {
	if path == "" {
		path = "."
	}
	if basePath == "" {
		basePath = "."
	}

	inputFolderAbs, err := filepath.Abs(basePath)
	if err != nil {
		return "", errors.WithStackTrace(err)
	}

	fileAbs, err := filepath.Abs(path)
	if err != nil {
		return "", errors.WithStackTrace(err)
	}

	relPath, err := filepath.Rel(inputFolderAbs, fileAbs)
	if err != nil {
		return "", errors.WithStackTrace(err)
	}

	return filepath.ToSlash(relPath), nil
}

// Return the contents of the file at the given path as a string
func ReadFileAsString(path string) (string, error) {
	bytes, err := ioutil.ReadFile(path)
	if err != nil {
		return "", errors.WithStackTraceAndPrefix(err, "Error reading file at path %s", path)
	}

	return string(bytes), nil
}

// Copy the files and folders within the source folder into the destination folder. Note that hidden files and folders
// (those starting with a dot) will be skipped.
func CopyFolderContents(source string, destination string) error {
	files, err := ioutil.ReadDir(source)
	if err != nil {
		return errors.WithStackTrace(err)
	}

	for _, file := range files {
		src := filepath.Join(source, file.Name())
		dest := filepath.Join(destination, file.Name())

		if PathContainsHiddenFileOrFolder(src) {
			continue
		} else if file.IsDir() {
			if err := os.MkdirAll(dest, file.Mode()); err != nil {
				return errors.WithStackTrace(err)
			}

			if err := CopyFolderContents(src, dest); err != nil {
				return err
			}
		} else {
			if err := CopyFile(src, dest); err != nil {
				return err
			}
		}
	}

	return nil
}

func PathContainsHiddenFileOrFolder(path string) bool {
	pathParts := strings.Split(path, string(filepath.Separator))
	for _, pathPart := range pathParts {
		if strings.HasPrefix(pathPart, ".") && pathPart != "." && pathPart != ".." {
			return true
		}
	}
	return false
}

// Copy a file from source to destination
func CopyFile(source string, destination string) error {
	contents, err := ioutil.ReadFile(source)
	if err != nil {
		return errors.WithStackTrace(err)
	}

	return WriteFileWithSamePermissions(source, destination, contents)
}

// Write a file to the given destination with the given contents using the same permissions as the file at source
func WriteFileWithSamePermissions(source string, destination string, contents []byte) error {
	fileInfo, err := os.Stat(source)
	if err != nil {
		return errors.WithStackTrace(err)
	}

	return ioutil.WriteFile(destination, contents, fileInfo.Mode())
}

// Windows systems use \ as the path separator *nix uses /
// Use this function when joining paths to force the returned path to use / as the path separator
// This will improve cross-platform compatibility
func JoinPath(elem ...string) string {
	return filepath.ToSlash(filepath.Join(elem...))
}

// Use this function when cleaning paths to ensure the returned path uses / as the path separator to improve cross-platform compatibility
func CleanPath(path string) string {
	return filepath.ToSlash(filepath.Clean(path))
}

// Join two paths together with a double-slash between them, as this is what Terraform uses to identify where a "repo"
// ends and a path within the repo begins. Note: The Terraform docs only mention two forward-slashes, so it's not clear
// if on Windows those should be two back-slashes? https://www.terraform.io/docs/modules/sources.html
func JoinTerraformModulePath(modulesFolder string, path string) string {
	cleanModulesFolder := strings.TrimRight(modulesFolder, `/\`)
	cleanPath := strings.TrimLeft(path, `/\`)
	return fmt.Sprintf("%s//%s", cleanModulesFolder, cleanPath)
}
<commit_msg>Try to fix hidden file/folder check<commit_after>package util

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"fmt"
	"github.com/gruntwork-io/terragrunt/errors"
	"github.com/mattn/go-zglob"
)

// Return true if the given file exists
func FileExists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}

// Return the canonical version of the given path, relative to the given base path. That is, if the given path is a
// relative path, assume it is relative to the given base path. A canonical path is an absolute path with all relative
// components (e.g. "../") fully resolved, which makes it safe to compare paths as strings.
func CanonicalPath(path string, basePath string) (string, error) {
	if !filepath.IsAbs(path) {
		path = JoinPath(basePath, path)
	}
	absPath, err := filepath.Abs(path)
	if err != nil {
		return "", err
	}

	return CleanPath(absPath), nil
}

// Return the canonical version of the given paths, relative to the given base path. That is, if a given path is a
// relative path, assume it is relative to the given base path. A canonical path is an absolute path with all relative
// components (e.g. "../") fully resolved, which makes it safe to compare paths as strings.
func CanonicalPaths(paths []string, basePath string) ([]string, error) {
	canonicalPaths := []string{}

	for _, path := range paths {
		canonicalPath, err := CanonicalPath(path, basePath)
		if err != nil {
			return canonicalPaths, err
		}
		canonicalPaths = append(canonicalPaths, canonicalPath)
	}

	return canonicalPaths, nil
}

// Delete the given list of files. Note: this function ONLY deletes files and will return an error if you pass in a
// folder path.
func DeleteFiles(files []string) error {
	for _, file := range files {
		if err := os.Remove(file); err != nil {
			return errors.WithStackTrace(err)
		}
	}
	return nil
}

// Returns true if the given regex can be found in any of the files matched by the given glob
func Grep(regex *regexp.Regexp, glob string) (bool, error) {
	// Ideally, we'd use a builin Go library like filepath.Glob here, but per https://github.com/golang/go/issues/11862,
	// the current go implementation doesn't support treating ** as zero or more directories, just zero or one.
	// So we use a third-party library.
	matches, err := zglob.Glob(glob)
	if err != nil {
		return false, errors.WithStackTrace(err)
	}

	for _, match := range matches {
		if IsDir(match) {
			continue
		}
		bytes, err := ioutil.ReadFile(match)
		if err != nil {
			return false, errors.WithStackTrace(err)
		}

		if regex.Match(bytes) {
			return true, nil
		}
	}

	return false, nil
}

// Return true if the path points to a directory
func IsDir(path string) bool {
	fileInfo, err := os.Stat(path)
	return err == nil && fileInfo.IsDir()
}

// Return the relative path you would have to take to get from basePath to path
func GetPathRelativeTo(path string, basePath string) (string, error) {
	if path == "" {
		path = "."
	}
	if basePath == "" {
		basePath = "."
	}

	inputFolderAbs, err := filepath.Abs(basePath)
	if err != nil {
		return "", errors.WithStackTrace(err)
	}

	fileAbs, err := filepath.Abs(path)
	if err != nil {
		return "", errors.WithStackTrace(err)
	}

	relPath, err := filepath.Rel(inputFolderAbs, fileAbs)
	if err != nil {
		return "", errors.WithStackTrace(err)
	}

	return filepath.ToSlash(relPath), nil
}

// Return the contents of the file at the given path as a string
func ReadFileAsString(path string) (string, error) {
	bytes, err := ioutil.ReadFile(path)
	if err != nil {
		return "", errors.WithStackTraceAndPrefix(err, "Error reading file at path %s", path)
	}

	return string(bytes), nil
}

// Copy the files and folders within the source folder into the destination folder. Note that hidden files and folders
// (those starting with a dot) will be skipped.
func CopyFolderContents(source string, destination string) error {
	files, err := ioutil.ReadDir(source)
	if err != nil {
		return errors.WithStackTrace(err)
	}

	for _, file := range files {
		src := filepath.Join(source, file.Name())
		dest := filepath.Join(destination, file.Name())

		if PathContainsHiddenFileOrFolder(file.Name()) {
			continue
		} else if file.IsDir() {
			if err := os.MkdirAll(dest, file.Mode()); err != nil {
				return errors.WithStackTrace(err)
			}

			if err := CopyFolderContents(src, dest); err != nil {
				return err
			}
		} else {
			if err := CopyFile(src, dest); err != nil {
				return err
			}
		}
	}

	return nil
}

func PathContainsHiddenFileOrFolder(path string) bool {
	pathParts := strings.Split(path, string(filepath.Separator))
	for _, pathPart := range pathParts {
		if strings.HasPrefix(pathPart, ".") && pathPart != "." && pathPart != ".." {
			return true
		}
	}
	return false
}

// Copy a file from source to destination
func CopyFile(source string, destination string) error {
	contents, err := ioutil.ReadFile(source)
	if err != nil {
		return errors.WithStackTrace(err)
	}

	return WriteFileWithSamePermissions(source, destination, contents)
}

// Write a file to the given destination with the given contents using the same permissions as the file at source
func WriteFileWithSamePermissions(source string, destination string, contents []byte) error {
	fileInfo, err := os.Stat(source)
	if err != nil {
		return errors.WithStackTrace(err)
	}

	return ioutil.WriteFile(destination, contents, fileInfo.Mode())
}

// Windows systems use \ as the path separator *nix uses /
// Use this function when joining paths to force the returned path to use / as the path separator
// This will improve cross-platform compatibility
func JoinPath(elem ...string) string {
	return filepath.ToSlash(filepath.Join(elem...))
}

// Use this function when cleaning paths to ensure the returned path uses / as the path separator to improve cross-platform compatibility
func CleanPath(path string) string {
	return filepath.ToSlash(filepath.Clean(path))
}

// Join two paths together with a double-slash between them, as this is what Terraform uses to identify where a "repo"
// ends and a path within the repo begins. Note: The Terraform docs only mention two forward-slashes, so it's not clear
// if on Windows those should be two back-slashes? https://www.terraform.io/docs/modules/sources.html
func JoinTerraformModulePath(modulesFolder string, path string) string {
	cleanModulesFolder := strings.TrimRight(modulesFolder, `/\`)
	cleanPath := strings.TrimLeft(path, `/\`)
	return fmt.Sprintf("%s//%s", cleanModulesFolder, cleanPath)
}
<|endoftext|>


<commit_before>package pbparser_test

import (
	"fmt"
	"testing"

	"github.com/tallstoat/pbparser"
)

func TestParseFile(t *testing.T) {
	var tests = []struct {
		file string
	}{
		{file: "./resources/enum.proto"},
		{file: "./resources/service.proto"},
	}

	for i, tt := range tests {
		fmt.Printf("Running test: %v \n\n", i)
		fmt.Printf("Parsing file: %v \n", tt.file)

		tab := indent(2)
		tab2 := indent(4)

		pf, err := pbparser.ParseFile(tt.file)
		if err != nil {
			t.Errorf("%v", err.Error())
		}

		fmt.Println("Syntax: " + pf.Syntax)
		fmt.Println("PackageName: " + pf.PackageName)
		for _, d := range pf.Dependencies {
			fmt.Println("Dependency: " + d)
		}
		for _, d := range pf.PublicDependencies {
			fmt.Println("PublicDependency: " + d)
		}
		options(pf.Options, "")

		for _, m := range pf.Messages {
			fmt.Println("Message: " + m.Name)
			fmt.Println("QualifiedName: " + m.QualifiedName)
			doc(m.Documentation)
			options(m.Options, "")
			fields(m.Fields, tab)
			for _, oo := range m.OneOfs {
				fmt.Println(tab + "OneOff: " + oo.Name)
				doc(oo.Documentation)
				options(oo.Options, tab)
				fields(oo.Fields, tab2)
			}
			for _, xe := range m.Extensions {
				fmt.Printf("%vExtensions:: Start: %v End: %v\n", tab, xe.Start, xe.End)
				doc(xe.Documentation)
			}
			for _, rn := range m.ReservedNames {
				fmt.Println(tab + "Reserved Name: " + rn)
			}
			for _, rr := range m.ReservedRanges {
				fmt.Printf("%vReserved Range:: Start: %v to End: %v\n", tab, rr.Start, rr.End)
				doc(rr.Documentation)
			}
		}

		for _, ed := range pf.ExtendDeclarations {
			fmt.Println("Extend: " + ed.Name)
			fmt.Println("QualifiedName: " + ed.QualifiedName)
			doc(ed.Documentation)
			fields(ed.Fields, tab)
		}

		for _, s := range pf.Services {
			fmt.Println("Service: " + s.Name)
			fmt.Println("QualifiedName: " + s.QualifiedName)
			doc(s.Documentation)
			options(s.Options, "")
			for _, rpc := range s.RPCs {
				fmt.Println(tab + "RPC: " + rpc.Name)
				doc(rpc.Documentation)
				if rpc.RequestType.IsStream() {
					fmt.Println(tab + "RequestType: stream " + rpc.RequestType.Name())
				} else {
					fmt.Println(tab + "RequestType: " + rpc.RequestType.Name())
				}
				if rpc.ResponseType.IsStream() {
					fmt.Println(tab + "ResponseType: stream " + rpc.ResponseType.Name())
				} else {
					fmt.Println(tab + "ResponseType: " + rpc.ResponseType.Name())
				}
				options(rpc.Options, tab)
			}
		}

		for _, en := range pf.Enums {
			fmt.Println("Enum: " + en.Name)
			fmt.Println("QualifiedName: " + en.QualifiedName)
			doc(en.Documentation)
			options(en.Options, "")
			for _, enc := range en.EnumConstants {
				fmt.Printf("%vName: %v Tag: %v\n", tab, enc.Name, enc.Tag)
				options(enc.Options, tab2)
			}
		}
		fmt.Printf("\nFinished test: %v \n\n", i)
	}

	fmt.Println("done")
}

func options(options []pbparser.OptionElement, tab string) {
	for _, op := range options {
		if op.IsParenthesized {
			fmt.Printf("%vOption:: (%v) = %v\n", tab, op.Name, op.Value)
		} else {
			fmt.Printf("%vOption:: %v = %v\n", tab, op.Name, op.Value)
		}
	}
}

func fields(fields []pbparser.FieldElement, tab string) {
	for _, f := range fields {
		fmt.Println(tab + "Field: " + f.Name)
		if f.Label != "" {
			fmt.Println(tab + "Label: " + f.Label)
		}
		fmt.Printf("%vType: %v\n", tab, f.Type)
		fmt.Printf("%vTag: %v\n", tab, f.Tag)
		doc(f.Documentation)
		options(f.Options, tab+tab)
	}
}

func doc(s string) {
	if s != "" {
		fmt.Println("Doc: " + s)
	}
}

func indent(i int) string {
	s := " "
	for j := 0; j < i; j++ {
		s += " "
	}
	return s
}
<commit_msg>Refactor parser test a bit<commit_after>package pbparser_test

import (
	"fmt"
	"testing"

	"github.com/tallstoat/pbparser"
)

// init the tabs...
var tab = indent(2)
var tab2 = indent(4)

func TestParseFile(t *testing.T) {
	var tests = []struct {
		file string
	}{
		{file: "./resources/enum.proto"},
		{file: "./resources/service.proto"},
	}

	for i, tt := range tests {
		fmt.Printf("Running test: %v \n\n", i)
		fmt.Printf("Parsing file: %v \n", tt.file)

		pf, err := pbparser.ParseFile(tt.file)
		if err != nil {
			t.Errorf("%v", err.Error())
		}

		fmt.Println("Syntax: " + pf.Syntax)
		fmt.Println("PackageName: " + pf.PackageName)
		for _, d := range pf.Dependencies {
			fmt.Println("Dependency: " + d)
		}
		for _, d := range pf.PublicDependencies {
			fmt.Println("PublicDependency: " + d)
		}
		options(pf.Options, "")

		for _, m := range pf.Messages {
			printMessage(&m)
		}

		for _, ed := range pf.ExtendDeclarations {
			fmt.Println("Extend: " + ed.Name)
			fmt.Println("QualifiedName: " + ed.QualifiedName)
			doc(ed.Documentation)
			fields(ed.Fields, tab)
		}

		for _, s := range pf.Services {
			fmt.Println("Service: " + s.Name)
			fmt.Println("QualifiedName: " + s.QualifiedName)
			doc(s.Documentation)
			options(s.Options, "")
			for _, rpc := range s.RPCs {
				printRPC(&rpc)
			}
		}

		for _, en := range pf.Enums {
			printEnum(&en)
		}
		fmt.Printf("\nFinished test: %v \n\n", i)
	}

	fmt.Println("done")
}

func printMessage(m *pbparser.MessageElement) {
	fmt.Println("Message: " + m.Name)
	fmt.Println("QualifiedName: " + m.QualifiedName)
	doc(m.Documentation)
	options(m.Options, "")
	fields(m.Fields, tab)
	for _, oo := range m.OneOfs {
		fmt.Println(tab + "OneOff: " + oo.Name)
		doc(oo.Documentation)
		options(oo.Options, tab)
		fields(oo.Fields, tab2)
	}
	for _, xe := range m.Extensions {
		fmt.Printf("%vExtensions:: Start: %v End: %v\n", tab, xe.Start, xe.End)
		doc(xe.Documentation)
	}
	for _, rn := range m.ReservedNames {
		fmt.Println(tab + "Reserved Name: " + rn)
	}
	for _, rr := range m.ReservedRanges {
		fmt.Printf("%vReserved Range:: Start: %v to End: %v\n", tab, rr.Start, rr.End)
		doc(rr.Documentation)
	}
}

func printRPC(rpc *pbparser.RPCElement) {
	fmt.Println(tab + "RPC: " + rpc.Name)
	doc(rpc.Documentation)
	if rpc.RequestType.IsStream() {
		fmt.Println(tab + "RequestType: stream " + rpc.RequestType.Name())
	} else {
		fmt.Println(tab + "RequestType: " + rpc.RequestType.Name())
	}
	if rpc.ResponseType.IsStream() {
		fmt.Println(tab + "ResponseType: stream " + rpc.ResponseType.Name())
	} else {
		fmt.Println(tab + "ResponseType: " + rpc.ResponseType.Name())
	}
	options(rpc.Options, tab)
}

func printEnum(en *pbparser.EnumElement) {
	fmt.Println("Enum: " + en.Name)
	fmt.Println("QualifiedName: " + en.QualifiedName)
	doc(en.Documentation)
	options(en.Options, "")
	for _, enc := range en.EnumConstants {
		fmt.Printf("%vName: %v Tag: %v\n", tab, enc.Name, enc.Tag)
		options(enc.Options, tab2)
	}
}

func options(options []pbparser.OptionElement, tab string) {
	for _, op := range options {
		if op.IsParenthesized {
			fmt.Printf("%vOption:: (%v) = %v\n", tab, op.Name, op.Value)
		} else {
			fmt.Printf("%vOption:: %v = %v\n", tab, op.Name, op.Value)
		}
	}
}

func fields(fields []pbparser.FieldElement, tab string) {
	for _, f := range fields {
		fmt.Println(tab + "Field: " + f.Name)
		if f.Label != "" {
			fmt.Println(tab + "Label: " + f.Label)
		}
		fmt.Printf("%vType: %v\n", tab, f.Type)
		fmt.Printf("%vTag: %v\n", tab, f.Tag)
		doc(f.Documentation)
		options(f.Options, tab+tab)
	}
}

func doc(s string) {
	if s != "" {
		fmt.Println("Doc: " + s)
	}
}

func indent(i int) string {
	s := " "
	for j := 0; j < i; j++ {
		s += " "
	}
	return s
}
<|endoftext|>