<commit_before>// Package hu implements (an interpreter for) a language optimized for
// humans.
package hu

import (
	"fmt"
	"math/big"
	"strings"
)

type Term interface {
	String() string
}

type Reducible interface {
	Term
	Reduce(*Environment) Term
}

type Rune int

func (rune Rune) String() string {
	return string(rune)
}

type Boolean bool

func (b Boolean) String() (result string) {
	if b {
		result = "true"
	} else {
		result = "false"
	}
	return
}

type Number struct {
	value *big.Rat
}

func (n *Number) String() string {
	return n.value.RatString()
}

type Symbol string

func (s Symbol) String() string {
	return string(s)
}

func (s Symbol) Reduce(environment *Environment) Term {
	return environment.Get(s)
}

type String string

func (s String) String() string {
	return string(s)
}

type Tuple []Term

func (tuple Tuple) String() string {
	return fmt.Sprintf("(%v)", []Term(tuple))
}

type Set []Term

func (set Set) String() string {
	return fmt.Sprintf("{%v}", []Term(set))
}

type Part []Term

func (part Part) String() string {
	var terms []string
	for _, term := range part {
		terms = append(terms, term.String())
	}
	return strings.Join(terms, "")
}

type Operator interface {
	Term
	apply(*Environment, Term) Term
}

type PrimitiveFunction func(*Environment, Term) Term

func (pf PrimitiveFunction) apply(environment *Environment, term Term) Term {
	return pf(environment, term)
}

func (pf PrimitiveFunction) String() string {
	return fmt.Sprintf("#<primitive-function> %p", pf)
}

type Primitive func(*Environment) Term

func (p Primitive) String() string {
	return fmt.Sprintf("#<primitive> %p", p)
}

func (p Primitive) Reduce(environment *Environment) Term {
	return p(environment)
}

type Application []Term

func (application Application) String() string {
	return fmt.Sprintf("{%v}", []Term(application))
}

func (application Application) Reduce(environment *Environment) Term {
	for i, term := range application {
		switch operator := environment.evaluate(term).(type) {
		case Operator:
			var operands Term
			switch operator.(type) {
			case PrimitiveFunction:
				operands = Tuple(application[i+1:])
			default:
				lhs := Tuple(application[0:i])
				rhs := Tuple(application[i+1:])
				operands = Tuple([]Term{lhs, rhs})
			}
			return operator.apply(environment, operands)
		}
	}
	return nil
}

type Abstraction struct {
	parameters Term
	term       Term
}

func (a Abstraction) apply(environment *Environment, values Term) Term {
	e := environment.NewChildEnvironment()
	e.Extend(a.parameters, values)
	return Closure{a.term, e}
}

func (abstraction Abstraction) String() string {
	return fmt.Sprintf("#<abstraction> %v %v", abstraction.parameters, abstraction.term)
}

type Closure struct {
	term        Term
	environment *Environment
}

func (closure Closure) String() string {
	return fmt.Sprintf("#<Closure> %v %v\n", closure.term, closure.environment)
}

func (closure Closure) Reduce(environment *Environment) Term {
	return closure.environment.evaluate(closure.term)
}

type Error string

func (error Error) String() string {
	return string(error)
}

type UnboundVariableError struct {
	variable  Term
	operation string
}

func (e UnboundVariableError) String() string {
	return "Unbound Variable: " + e.variable.String() + " operation: " + e.operation
}

type Environment struct {
	frame  map[Symbol]Term
	parent *Environment
}

func (environment *Environment) String() string {
	return "#<environment>"
}

func NewEnvironment() *Environment {
	return &Environment{frame: make(map[Symbol]Term)}
}

// returns a new (child) environment from this environment extended
// with bindings given by variables, values.
func (environment *Environment) NewChildEnvironment() *Environment {
	child := NewEnvironment()
	child.parent = environment
	return child
}

func (environment *Environment) Closure(term Term) Term {
	switch term.(type) {
	case Application:
		return Closure{term, environment}
	}
	return term
}

func (environment *Environment) Extend(variables, values Term) {
	switch vars := variables.(type) {
	case Tuple:
		vals := values.(Tuple)
		if len(vals) != len(vars) {
			fmt.Println("type mismatch:", vals, vars)
		}
		for i, v := range vars {
			val := vals[i]
			environment.Extend(v, val)
		}
	case Symbol:
		environment.Define(vars, environment.parent.Closure(values))
	}
}

func (environment *Environment) Define(variable Symbol, value Term) {
	environment.frame[variable] = value
}

func (environment *Environment) Set(variable Symbol, value Term) {
	_, ok := environment.frame[variable]
	if ok {
		environment.Define(variable, value)
	} else if environment.parent != nil {
		environment.parent.Set(variable, value)
	} else {
		panic(UnboundVariableError{variable, "set"})
	}
}

func (environment *Environment) Get(variable Symbol) Term {
	value, ok := environment.frame[variable]
	if ok {
		return value
	} else if environment.parent != nil {
		return environment.parent.Get(variable)
	} else {
		panic(UnboundVariableError{variable, "get"})
	}
	return nil
}

func (environment *Environment) AddPrimitive(name string, function PrimitiveFunction) {
	environment.Define(Symbol(name), function)
}

func (environment *Environment) Evaluate(term Term) (result Term) {
	defer func() {
		switch x := recover().(type) {
		case Term:
			result = x
		case interface{}:
			result = Error(fmt.Sprintf("%v", x))
		}
	}()
	result = environment.evaluate(term)
	return
}

func (environment *Environment) evaluate(term Term) Term {
tailcall:
	switch t := term.(type) {
	case Reducible:
		term = t.Reduce(environment)
		goto tailcall
	}
	return term
}
<commit_msg>Made Abstraction encodable<commit_after>// Package hu implements (an interpreter for) a language optimized for
// humans.
package hu

import (
	"fmt"
	"math/big"
	"strings"
)

type Term interface {
	String() string
}

type Reducible interface {
	Term
	Reduce(*Environment) Term
}

type Rune int

func (rune Rune) String() string {
	return string(rune)
}

type Boolean bool

func (b Boolean) String() (result string) {
	if b {
		result = "true"
	} else {
		result = "false"
	}
	return
}

type Number struct {
	value *big.Rat
}

func (n *Number) String() string {
	return n.value.RatString()
}

type Symbol string

func (s Symbol) String() string {
	return string(s)
}

func (s Symbol) Reduce(environment *Environment) Term {
	return environment.Get(s)
}

type String string

func (s String) String() string {
	return string(s)
}

type Tuple []Term

func (tuple Tuple) String() string {
	return fmt.Sprintf("(%v)", []Term(tuple))
}

type Set []Term

func (set Set) String() string {
	return fmt.Sprintf("{%v}", []Term(set))
}

type Part []Term

func (part Part) String() string {
	var terms []string
	for _, term := range part {
		terms = append(terms, term.String())
	}
	return strings.Join(terms, "")
}

type Operator interface {
	Term
	apply(*Environment, Term) Term
}

type PrimitiveFunction func(*Environment, Term) Term

func (pf PrimitiveFunction) apply(environment *Environment, term Term) Term {
	return pf(environment, term)
}

func (pf PrimitiveFunction) String() string {
	return fmt.Sprintf("#<primitive-function> %p", pf)
}

type Primitive func(*Environment) Term

func (p Primitive) String() string {
	return fmt.Sprintf("#<primitive> %p", p)
}

func (p Primitive) Reduce(environment *Environment) Term {
	return p(environment)
}

type Application []Term

func (application Application) String() string {
	return fmt.Sprintf("{%v}", []Term(application))
}

func (application Application) Reduce(environment *Environment) Term {
	for i, term := range application {
		switch operator := environment.evaluate(term).(type) {
		case Operator:
			var operands Term
			switch operator.(type) {
			case PrimitiveFunction:
				operands = Tuple(application[i+1:])
			default:
				lhs := Tuple(application[0:i])
				rhs := Tuple(application[i+1:])
				operands = Tuple([]Term{lhs, rhs})
			}
			return operator.apply(environment, operands)
		}
	}
	return nil
}

type Abstraction struct {
	Parameters Term
	Term       Term
}

func (a Abstraction) apply(environment *Environment, values Term) Term {
	e := environment.NewChildEnvironment()
	e.Extend(a.Parameters, values)
	return Closure{a.Term, e}
}

func (abstraction Abstraction) String() string {
       return fmt.Sprintf("#<abstraction> %v %v", abstraction.Parameters, abstraction.Term)
}

type Closure struct {
	term        Term
	environment *Environment
}

func (closure Closure) String() string {
	return fmt.Sprintf("#<Closure> %v %v\n", closure.term, closure.environment)
}

func (closure Closure) Reduce(environment *Environment) Term {
	return closure.environment.evaluate(closure.term)
}

type Error string

func (error Error) String() string {
	return string(error)
}

type UnboundVariableError struct {
	variable  Term
	operation string
}

func (e UnboundVariableError) String() string {
	return "Unbound Variable: " + e.variable.String() + " operation: " + e.operation
}

type Environment struct {
	frame  map[Symbol]Term
	parent *Environment
}

func (environment *Environment) String() string {
	return "#<environment>"
}

func NewEnvironment() *Environment {
	return &Environment{frame: make(map[Symbol]Term)}
}

// returns a new (child) environment from this environment extended
// with bindings given by variables, values.
func (environment *Environment) NewChildEnvironment() *Environment {
	child := NewEnvironment()
	child.parent = environment
	return child
}

func (environment *Environment) Closure(term Term) Term {
	switch term.(type) {
	case Application:
		return Closure{term, environment}
	}
	return term
}

func (environment *Environment) Extend(variables, values Term) {
	switch vars := variables.(type) {
	case Tuple:
		vals := values.(Tuple)
		if len(vals) != len(vars) {
			fmt.Println("type mismatch:", vals, vars)
		}
		for i, v := range vars {
			val := vals[i]
			environment.Extend(v, val)
		}
	case Symbol:
		environment.Define(vars, environment.parent.Closure(values))
	}
}

func (environment *Environment) Define(variable Symbol, value Term) {
	environment.frame[variable] = value
}

func (environment *Environment) Set(variable Symbol, value Term) {
	_, ok := environment.frame[variable]
	if ok {
		environment.Define(variable, value)
	} else if environment.parent != nil {
		environment.parent.Set(variable, value)
	} else {
		panic(UnboundVariableError{variable, "set"})
	}
}

func (environment *Environment) Get(variable Symbol) Term {
	value, ok := environment.frame[variable]
	if ok {
		return value
	} else if environment.parent != nil {
		return environment.parent.Get(variable)
	} else {
		panic(UnboundVariableError{variable, "get"})
	}
	return nil
}

func (environment *Environment) AddPrimitive(name string, function PrimitiveFunction) {
	environment.Define(Symbol(name), function)
}

func (environment *Environment) Evaluate(term Term) (result Term) {
	defer func() {
		switch x := recover().(type) {
		case Term:
			result = x
		case interface{}:
			result = Error(fmt.Sprintf("%v", x))
		}
	}()
	result = environment.evaluate(term)
	return
}

func (environment *Environment) evaluate(term Term) Term {
tailcall:
	switch t := term.(type) {
	case Reducible:
		term = t.Reduce(environment)
		goto tailcall
	}
	return term
}
<|endoftext|>


<commit_before>//Command to run test version:
//goapp serve app.yaml
//Command to deploy/update application:
//goapp deploy -application golangnode0 -version 0

package main

import (
	"fmt"
	"net/http"
)

func helloWorld(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello World!")
}

func startPage(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "Hello, test application started.")
	fmt.Fprintln(w, "\n - /helloworld - show title page")
	fmt.Fprintln(w, "\n - /showinfo - show information about this thing")
}

func showInfo(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "Information page for test project.")
	fmt.Fprintln(w, "Language - Go;")
	fmt.Fprintln(w, "Platform - Google Application Engine;")
}

func init() {

	http.HandleFunc("/", startPage)
	http.HandleFunc("/helloworld", helloWorld)
	http.HandleFunc("/showinfo", showInfo)
	//Wrong code for App Enine - server cant understand what it need to show
	//http.ListenAndServe(":80", nil)
}

//this func not needed for deploy on Google App Engine, init() func replace main()
/*
func main() {
	fmt.Println("Hello, test server started on 8080 port.\n - /helloworld - show title page\n - /showinfo - show information about this thing")
	init()
	http.ListenAndServe(":8080", nil)
}
*/
<commit_msg>added file srv page<commit_after>//Command to run test version:
//goapp serve app.yaml
//Command to deploy/update application:
//goapp deploy -application golangnode0 -version 0

package main

import (
	"fmt"
	"net/http"
)

func helloWorld(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello World!")
}

func startPage(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "Hello, test application started.")
	fmt.Fprintln(w, "\n - /helloworld - show title page")
	fmt.Fprintln(w, "\n - /showinfo - show information about this thing")
}

func showInfo(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "Information page for test project.")
	fmt.Fprintln(w, "Language - Go;")
	fmt.Fprintln(w, "Platform - Google Application Engine;")
}

/*
func sendEmail(w http.ResponseWriter, r *http.Redirect) {

}
*/

func init() {

	http.HandleFunc("/", startPage)
	http.HandleFunc("/helloworld", helloWorld)
	http.HandleFunc("/showinfo", showInfo)
	http.HandleFunc("/files", http.FileServer(http.Dir("files")))
	//Wrong code for App Enine - server cant understand what it need to show
	//http.ListenAndServe(":80", nil)
}

//this func not needed for deploy on Google App Engine, init() func replace main()
/*
func main() {
	fmt.Println("Hello, test server started on 8080 port.\n - /helloworld - show title page\n - /showinfo - show information about this thing")
	init()
	http.ListenAndServe(":8080", nil)
}
*/
<|endoftext|>


<commit_before>package ingo

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"os/user"
	"path"
	"strings"
)

var (
	obsoleteKeys = make(map[string]string)
)

func Parse(appName string) error {
	if flag.Parsed() {
		return fmt.Errorf("flags have been parsed already.")
	}

	envname := strings.ToUpper(appName) + "RC"
	cPath := os.Getenv(envname)
	if cPath == "" {
		usr, err := user.Current()
		if err != nil {
			return fmt.Errorf("%v\nYou can set the environment variable %s to point to your config file as a workaround.", err, envname)
		}
		cPath = path.Join(usr.HomeDir, "."+strings.ToLower(appName)+"rc")
	}

	if err := loadConfig(appName, cPath); err != nil {
		return err
	}
	if err := saveConfig(appName, cPath); err != nil {
		return err
	}
	flag.Parse()
	return nil
}

func loadConfig(appName, configPath string) error {
	fin, err := os.Open(configPath)
	if _, ok := err.(*os.PathError); ok {
		fmt.Fprintf(os.Stderr, "No config file found for %s. Creating %s ...\n", appName, configPath)
		return nil
	} else if err != nil {
		return fmt.Errorf("Unable to read %s config file %v: %v", appName, configPath, err)
	}
	defer fin.Close()

	scanner := bufio.NewScanner(fin)
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if strings.HasPrefix(line, "#") {
			continue
		}

		// find first assignment symbol and parse key, val
		i := strings.IndexAny(line, "=:")
		if i == -1 {
			continue
		}
		key, val := strings.TrimSpace(line[:i]), strings.TrimSpace(line[i+1:])

		if err := flag.Set(key, val); err != nil {
			obsoleteKeys[key] = val
			continue
		}
	}
	return nil
}

func saveConfig(appName, configPath string) error {
	fout, err := os.Create(configPath)
	if err != nil {
		return fmt.Errorf("Unable to open %s config file %v for writing: %v", appName, configPath, err)
	}
	defer fout.Close()

	writer := bufio.NewWriter(fout)
	defer writer.Flush()

	// header
	fmt.Fprintf(writer, "# %s configuration\n# \n", appName)
	fmt.Fprintln(writer, "# This config has https://github.com/schachmat/ingo syntax.")
	fmt.Fprintln(writer, "# Empty lines or lines starting with # will be ignored.")
	fmt.Fprintln(writer, "# All other lines must look like `KEY=VALUE` (without the quotes).")
	fmt.Fprintf(writer, "# The VALUE must not be enclosed in quotes!\n\n")

	flag.VisitAll(func(f *flag.Flag) {
		_, usage := flag.UnquoteUsage(f)
		fmt.Fprintln(writer, "#", strings.Replace(usage, "\n    \t", "\n# ", -1))
		fmt.Fprintf(writer, "%v=%v\n", f.Name, f.Value.String())
	})

	// if we have obsolete keys left from the old config, preserve them in an
	// additional section at the end of the file
	if len(obsoleteKeys) == 0 {
		return nil
	}
	fmt.Fprintln(os.Stderr, "!!!!!!!!!!")
	fmt.Fprintln(os.Stderr, "! WARNING: The application was probably updated,")
	fmt.Fprintln(os.Stderr, "! Check and update", configPath, " as necessary and")
	fmt.Fprintln(os.Stderr, "! remove the last \"deprecated\" paragraph to disable this message!")
	fmt.Fprintln(os.Stderr, "!!!!!!!!!!")
	fmt.Fprintln(writer, "\n\n# The following options are probably deprecated and not used currently!")
	for key, val := range obsoleteKeys {
		fmt.Fprintf(writer, "%v=%v\n", key, val)
	}
	return nil
}
<commit_msg>add default value to config<commit_after>package ingo

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"os/user"
	"path"
	"strings"
)

var (
	obsoleteKeys = make(map[string]string)
)

func Parse(appName string) error {
	if flag.Parsed() {
		return fmt.Errorf("flags have been parsed already.")
	}

	envname := strings.ToUpper(appName) + "RC"
	cPath := os.Getenv(envname)
	if cPath == "" {
		usr, err := user.Current()
		if err != nil {
			return fmt.Errorf("%v\nYou can set the environment variable %s to point to your config file as a workaround.", err, envname)
		}
		cPath = path.Join(usr.HomeDir, "."+strings.ToLower(appName)+"rc")
	}

	if err := loadConfig(appName, cPath); err != nil {
		return err
	}
	if err := saveConfig(appName, cPath); err != nil {
		return err
	}
	flag.Parse()
	return nil
}

func loadConfig(appName, configPath string) error {
	fin, err := os.Open(configPath)
	if _, ok := err.(*os.PathError); ok {
		fmt.Fprintf(os.Stderr, "No config file found for %s. Creating %s ...\n", appName, configPath)
		return nil
	} else if err != nil {
		return fmt.Errorf("Unable to read %s config file %v: %v", appName, configPath, err)
	}
	defer fin.Close()

	scanner := bufio.NewScanner(fin)
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if strings.HasPrefix(line, "#") {
			continue
		}

		// find first assignment symbol and parse key, val
		i := strings.IndexAny(line, "=:")
		if i == -1 {
			continue
		}
		key, val := strings.TrimSpace(line[:i]), strings.TrimSpace(line[i+1:])

		if err := flag.Set(key, val); err != nil {
			obsoleteKeys[key] = val
			continue
		}
	}
	return nil
}

func saveConfig(appName, configPath string) error {
	fout, err := os.Create(configPath)
	if err != nil {
		return fmt.Errorf("Unable to open %s config file %v for writing: %v", appName, configPath, err)
	}
	defer fout.Close()

	writer := bufio.NewWriter(fout)
	defer writer.Flush()

	// header
	fmt.Fprintf(writer, "# %s configuration\n# \n", appName)
	fmt.Fprintln(writer, "# This config has https://github.com/schachmat/ingo syntax.")
	fmt.Fprintln(writer, "# Empty lines or lines starting with # will be ignored.")
	fmt.Fprintln(writer, "# All other lines must look like `KEY=VALUE` (without the quotes).")
	fmt.Fprintf(writer, "# The VALUE must not be enclosed in quotes!\n\n")

	flag.VisitAll(func(f *flag.Flag) {
		_, usage := flag.UnquoteUsage(f)
		fmt.Fprintf(writer, "# %s (default %v)\n", strings.Replace(usage, "\n    \t", "\n# ", -1), f.DefValue)
		fmt.Fprintf(writer, "%v=%v\n", f.Name, f.Value.String())
	})

	// if we have obsolete keys left from the old config, preserve them in an
	// additional section at the end of the file
	if len(obsoleteKeys) == 0 {
		return nil
	}
	fmt.Fprintln(os.Stderr, "!!!!!!!!!!")
	fmt.Fprintln(os.Stderr, "! WARNING: The application was probably updated,")
	fmt.Fprintln(os.Stderr, "! Check and update", configPath, " as necessary and")
	fmt.Fprintln(os.Stderr, "! remove the last \"deprecated\" paragraph to disable this message!")
	fmt.Fprintln(os.Stderr, "!!!!!!!!!!")
	fmt.Fprintln(writer, "\n\n# The following options are probably deprecated and not used currently!")
	for key, val := range obsoleteKeys {
		fmt.Fprintf(writer, "%v=%v\n", key, val)
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2022 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 fetch

import "golang.org/x/mod/module"

// knownAlternatives lists module paths that are known to be forks of other
// modules.
// For example, github.com/msopentech/azure-sdk-for-go
// is an alternative to github.com/Azure/azure-sdk-for-go.
// Map keys are case-sensitive and should not include a final major version
// like "/v3" or ".v3" for gopkg.in paths.
//
// When a module has a go.mod file, we can detect alternatives by comparing the
// module path with the path in the go.mod file. This list is for modules
// without go.mod files.
var knownAlternatives = map[string]string{
	"github.com/msopentech/azure-sdk-for-go":       "github.com/Azure/azure-sdk-for-go",
	"github.com/MSOpenTech/azure-sdk-for-go":       "github.com/Azure/azure-sdk-for-go",
	"gopkg.in/Azure/azure-sdk-for-go":              "github.com/Azure/azure-sdk-for-go",
	"github.com/masslessparticle/azure-sdk-for-go": "github.com/Azure/azure-sdk-for-go",
	"github.com/aliyun/alibaba-cloud-sdk-go":       "github.com/Azure/azure-sdk-for-go",
	"github.com/johnstairs/azure-sdk-for-go	": "github.com/Azure/azure-sdk-for-go",
	"github.com/shopify/sarama": "github.com/Shopify/sarama",
}

// knownAlternativeFor returns the module that the given module path is an alternative to,
// or the empty string if there is no such module.
//
// It consults the knownAlternatives map, ignoring version suffixes.
func knownAlternativeFor(modulePath string) string {
	key, _, ok := module.SplitPathVersion(modulePath)
	if !ok {
		return ""
	}
	return knownAlternatives[key]
}
<commit_msg>internal/fetch: add another known alternative module<commit_after>// Copyright 2022 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 fetch

import "golang.org/x/mod/module"

// knownAlternatives lists module paths that are known to be forks of other
// modules.
// For example, github.com/msopentech/azure-sdk-for-go
// is an alternative to github.com/Azure/azure-sdk-for-go.
// Map keys are case-sensitive and should not include a final major version
// like "/v3" or ".v3" for gopkg.in paths.
//
// When a module has a go.mod file, we can detect alternatives by comparing the
// module path with the path in the go.mod file. This list is for modules
// without go.mod files.
var knownAlternatives = map[string]string{
	"github.com/msopentech/azure-sdk-for-go":       "github.com/Azure/azure-sdk-for-go",
	"github.com/MSOpenTech/azure-sdk-for-go":       "github.com/Azure/azure-sdk-for-go",
	"gopkg.in/Azure/azure-sdk-for-go":              "github.com/Azure/azure-sdk-for-go",
	"gopkg.in/azure/azure-sdk-for-go":              "github.com/Azure/azure-sdk-for-go",
	"github.com/masslessparticle/azure-sdk-for-go": "github.com/Azure/azure-sdk-for-go",
	"github.com/aliyun/alibaba-cloud-sdk-go":       "github.com/Azure/azure-sdk-for-go",
	"github.com/johnstairs/azure-sdk-for-go	": "github.com/Azure/azure-sdk-for-go",
	"github.com/shopify/sarama": "github.com/Shopify/sarama",
}

// knownAlternativeFor returns the module that the given module path is an alternative to,
// or the empty string if there is no such module.
//
// It consults the knownAlternatives map, ignoring version suffixes.
func knownAlternativeFor(modulePath string) string {
	key, _, ok := module.SplitPathVersion(modulePath)
	if !ok {
		return ""
	}
	return knownAlternatives[key]
}
<|endoftext|>


<commit_before>package keysharecore

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/subtle"
	"encoding/binary"

	"github.com/fxamacker/cbor"
	"github.com/privacybydesign/gabi/big"

	"github.com/go-errors/errors"
)

type (
	unencryptedUserSecrets struct {
		Pin            []byte
		KeyshareSecret *big.Int
		ID             []byte
	}

	// UserSecrets contains the encrypted data of a keyshare user.
	UserSecrets []byte
)

var (
	ErrKeyshareSecretTooBig   = errors.New("Keyshare secret too big to store")
	ErrKeyshareSecretNegative = errors.New("Keyshare secret negative")
	ErrNoSuchKey              = errors.New("Key identifier unknown")
)

func (s *unencryptedUserSecrets) setPin(pin string) error {
	if len(pin) > 64 {
		// padBytes also checks the length, but we want to return a specific error in this case
		return ErrPinTooLong
	}
	paddedPin, err := padBytes([]byte(pin), 64)
	if err != nil {
		return err
	}
	s.Pin = paddedPin
	return nil
}

func (s *unencryptedUserSecrets) setKeyshareSecret(val *big.Int) error {
	if val.Sign() == -1 {
		return ErrKeyshareSecretNegative
	}

	// We want the result to fit into 64 bytes, so we need to round upward; hence +7
	if (val.BitLen()+7)/8 > 64 {
		return ErrKeyshareSecretTooBig
	}

	s.KeyshareSecret = new(big.Int).Set(val)

	return nil
}

func (s *unencryptedUserSecrets) setID(id []byte) error {
	paddedID, err := padBytes(id, 32)
	if err != nil {
		return err
	}
	s.ID = paddedID
	return nil
}

// MarshalCBOR implements cbor.Marshaler to ensure that all fields have a constant size, to minimize
// differences in the size of the encrypted blobs.
// (Note that no unmarshaler is necessary: the only field that gets special attention is the secret
// bigint, which is marshaled in such a way that the default unmarshaler works fine.)
func (s *unencryptedUserSecrets) MarshalCBOR() ([]byte, error) {
	secretBts, err := padBytes(s.KeyshareSecret.Bytes(), 64)
	if err != nil {
		return nil, err
	}
	return cbor.Marshal(struct {
		Pin            []byte
		KeyshareSecret []byte
		ID             []byte
	}{
		s.Pin, secretBts, s.ID,
	}, cbor.EncOptions{})
}

func (c *Core) encryptUserSecrets(secrets unencryptedUserSecrets) (UserSecrets, error) {
	encSecrets := make(UserSecrets, 16, 256)

	bts, err := cbor.Marshal(secrets, cbor.EncOptions{})
	if err != nil {
		return nil, err
	}

	// Store key id
	binary.LittleEndian.PutUint32(encSecrets[0:], c.decryptionKeyID)

	// Generate and store nonce
	_, err = rand.Read(encSecrets[4:16])
	if err != nil {
		return nil, err
	}

	// Encrypt secrets
	gcm, err := newGCM(c.decryptionKey)
	if err != nil {
		return nil, err
	}
	return gcm.Seal(encSecrets[:16], encSecrets[4:16], bts, nil), nil
}

func (c *Core) decryptUserSecrets(secrets UserSecrets) (unencryptedUserSecrets, error) {
	// determine key id
	id := binary.LittleEndian.Uint32(secrets[0:])

	// Fetch key
	key, ok := c.decryptionKeys[id]
	if !ok {
		return unencryptedUserSecrets{}, ErrNoSuchKey
	}

	// try and decrypt secrets
	gcm, err := newGCM(key)
	if err != nil {
		return unencryptedUserSecrets{}, err
	}

	bts, err := gcm.Open(nil, secrets[4:16], secrets[16:], nil)
	if err != nil {
		return unencryptedUserSecrets{}, err
	}

	var unencSecrets unencryptedUserSecrets
	err = cbor.Unmarshal(bts, &unencSecrets)
	if err != nil {
		return unencryptedUserSecrets{}, err
	}

	return unencSecrets, nil
}

func (c *Core) decryptUserSecretsIfPinOK(secrets UserSecrets, pin string) (unencryptedUserSecrets, error) {
	paddedPin, err := padBytes([]byte(pin), 64)
	if err != nil {
		return unencryptedUserSecrets{}, err
	}

	s, err := c.decryptUserSecrets(secrets)
	if err != nil {
		return unencryptedUserSecrets{}, err
	}

	if subtle.ConstantTimeCompare(s.Pin, paddedPin) != 1 {
		return unencryptedUserSecrets{}, ErrInvalidPin
	}
	return s, nil
}

func newGCM(key AESKey) (cipher.AEAD, error) {
	keyedAes, err := aes.NewCipher(key[:])
	if err != nil {
		return nil, err
	}
	gcm, err := cipher.NewGCM(keyedAes)
	if err != nil {
		return nil, err
	}
	return gcm, nil
}

// padBytes pads the given byte slice with zeros on the left such that the resulting byte slice
// has the specified length.
func padBytes(src []byte, length int) ([]byte, error) {
	if len(src) > length {
		return nil, errors.New("padBytes: source slice too long")
	}
	if len(src) == length {
		return src, nil
	}
	result := make([]byte, length)
	copy(result[length-len(src):], src)
	return result, nil
}
<commit_msg>refactor: simplify keyshare secret bounds check<commit_after>package keysharecore

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/subtle"
	"encoding/binary"

	"github.com/fxamacker/cbor"
	"github.com/privacybydesign/gabi/big"

	"github.com/go-errors/errors"
)

type (
	unencryptedUserSecrets struct {
		Pin            []byte
		KeyshareSecret *big.Int
		ID             []byte
	}

	// UserSecrets contains the encrypted data of a keyshare user.
	UserSecrets []byte
)

var (
	ErrKeyshareSecretTooBig   = errors.New("Keyshare secret too big to store")
	ErrKeyshareSecretNegative = errors.New("Keyshare secret negative")
	ErrNoSuchKey              = errors.New("Key identifier unknown")
)

func (s *unencryptedUserSecrets) setPin(pin string) error {
	if len(pin) > 64 {
		// padBytes also checks the length, but we want to return a specific error in this case
		return ErrPinTooLong
	}
	paddedPin, err := padBytes([]byte(pin), 64)
	if err != nil {
		return err
	}
	s.Pin = paddedPin
	return nil
}

func (s *unencryptedUserSecrets) setKeyshareSecret(val *big.Int) error {
	if val.Sign() == -1 {
		return ErrKeyshareSecretNegative
	}

	// We want the result to fit into 64 bytes, so we need to round upward; hence +7
	if val.BitLen() > 64*8 {
		return ErrKeyshareSecretTooBig
	}

	s.KeyshareSecret = new(big.Int).Set(val)

	return nil
}

func (s *unencryptedUserSecrets) setID(id []byte) error {
	paddedID, err := padBytes(id, 32)
	if err != nil {
		return err
	}
	s.ID = paddedID
	return nil
}

// MarshalCBOR implements cbor.Marshaler to ensure that all fields have a constant size, to minimize
// differences in the size of the encrypted blobs.
// (Note that no unmarshaler is necessary: the only field that gets special attention is the secret
// bigint, which is marshaled in such a way that the default unmarshaler works fine.)
func (s *unencryptedUserSecrets) MarshalCBOR() ([]byte, error) {
	secretBts, err := padBytes(s.KeyshareSecret.Bytes(), 64)
	if err != nil {
		return nil, err
	}
	return cbor.Marshal(struct {
		Pin            []byte
		KeyshareSecret []byte
		ID             []byte
	}{
		s.Pin, secretBts, s.ID,
	}, cbor.EncOptions{})
}

func (c *Core) encryptUserSecrets(secrets unencryptedUserSecrets) (UserSecrets, error) {
	encSecrets := make(UserSecrets, 16, 256)

	bts, err := cbor.Marshal(secrets, cbor.EncOptions{})
	if err != nil {
		return nil, err
	}

	// Store key id
	binary.LittleEndian.PutUint32(encSecrets[0:], c.decryptionKeyID)

	// Generate and store nonce
	_, err = rand.Read(encSecrets[4:16])
	if err != nil {
		return nil, err
	}

	// Encrypt secrets
	gcm, err := newGCM(c.decryptionKey)
	if err != nil {
		return nil, err
	}
	return gcm.Seal(encSecrets[:16], encSecrets[4:16], bts, nil), nil
}

func (c *Core) decryptUserSecrets(secrets UserSecrets) (unencryptedUserSecrets, error) {
	// determine key id
	id := binary.LittleEndian.Uint32(secrets[0:])

	// Fetch key
	key, ok := c.decryptionKeys[id]
	if !ok {
		return unencryptedUserSecrets{}, ErrNoSuchKey
	}

	// try and decrypt secrets
	gcm, err := newGCM(key)
	if err != nil {
		return unencryptedUserSecrets{}, err
	}

	bts, err := gcm.Open(nil, secrets[4:16], secrets[16:], nil)
	if err != nil {
		return unencryptedUserSecrets{}, err
	}

	var unencSecrets unencryptedUserSecrets
	err = cbor.Unmarshal(bts, &unencSecrets)
	if err != nil {
		return unencryptedUserSecrets{}, err
	}

	return unencSecrets, nil
}

func (c *Core) decryptUserSecretsIfPinOK(secrets UserSecrets, pin string) (unencryptedUserSecrets, error) {
	paddedPin, err := padBytes([]byte(pin), 64)
	if err != nil {
		return unencryptedUserSecrets{}, err
	}

	s, err := c.decryptUserSecrets(secrets)
	if err != nil {
		return unencryptedUserSecrets{}, err
	}

	if subtle.ConstantTimeCompare(s.Pin, paddedPin) != 1 {
		return unencryptedUserSecrets{}, ErrInvalidPin
	}
	return s, nil
}

func newGCM(key AESKey) (cipher.AEAD, error) {
	keyedAes, err := aes.NewCipher(key[:])
	if err != nil {
		return nil, err
	}
	gcm, err := cipher.NewGCM(keyedAes)
	if err != nil {
		return nil, err
	}
	return gcm, nil
}

// padBytes pads the given byte slice with zeros on the left such that the resulting byte slice
// has the specified length.
func padBytes(src []byte, length int) ([]byte, error) {
	if len(src) > length {
		return nil, errors.New("padBytes: source slice too long")
	}
	if len(src) == length {
		return src, nil
	}
	result := make([]byte, length)
	copy(result[length-len(src):], src)
	return result, nil
}
<|endoftext|>


<commit_before>package coreutils

import (
	"errors"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"strings"
)

// AbsPath get the absolute directory path, cleaning out any file names, home directory references, etc.
func AbsPath(path string) string {
	if !filepath.IsAbs(path) { // If the path provided isn't already absolute
		user, userGetErr := user.Current()

		if userGetErr == nil { // If we didn't fail getting the current user
			path = strings.Replace(path, "~", user.HomeDir+Separator, -1) // Replace any home directory reference
		}

		path, _ = filepath.Abs(path) // Get the absolute path of path

		var stripLastElement bool

		if file, openErr := os.Open(path); openErr == nil { // Attempt to open the path, to validate if it is a file or directory
			stat, statErr := file.Stat()
			stripLastElement = (statErr == nil) && !stat.IsDir() // Sets stripLastElement to true if stat.IsDir is not true
		} else { // If we failed to open the directory or file
			lastElement := filepath.Base(path)
			stripLastElement = filepath.Ext(lastElement) != "" // If lastElement is either a dotfile or has an extension, assume it is a file
		}

		if stripLastElement {
			path = filepath.Dir(path) + Separator // Strip out the last element and add the separator
		}
	}

	return path
}

// CopyDirectory will the directory specified and its contents into the destination directory
func CopyDirectory(sourceDirectory, destinationDirectory string) error {
	if !IsDir(sourceDirectory) { // If this isn't a source directory
		return errors.New(sourceDirectory + " is not a directory.")
	}

	var copyError error
	currentDirectory, _ := os.Getwd()            // Get the working directory
	currentDirectory = AbsPath(currentDirectory) // Get the absolute path of the current working directory

	os.MkdirAll(destinationDirectory, NonGlobalFileMode) // Ensure destinationDirectory exists

	finalSourceDir := filepath.Base(sourceDirectory)                              // Determine what our final source directory is. For instance, we should only copy child from test/parent/child
	parentOfFinalSourceDir := strings.TrimSuffix(sourceDirectory, finalSourceDir) // Get the parent directories we need to change to. Ex: test/parent

	os.Chdir(parentOfFinalSourceDir)

	if sourceDirectoryFile, sourceDirOpenErr := os.Open(finalSourceDir); sourceDirOpenErr == nil { // If we did not fail to open finalSourceDir
		if directoryContents, directoryReadError := sourceDirectoryFile.Readdir(-1); directoryReadError == nil { // Read the directory contents
			if len(directoryContents) != 0 { // If the directory has contents
				for _, contentItemFileInfo := range directoryContents { // For each FileInfo struct in directoryContents
					contentItemName := contentItemFileInfo.Name() // Get the name of the item
					sourceItemPath := finalSourceDir + "/" + contentItemName
					destinationItemPath := destinationDirectory + "/" + contentItemName

					if contentItemFileInfo.IsDir() { // If this is a directory
						copyError = CopyDirectory(sourceItemPath, destinationItemPath) // Copy this sub-directory and its contents
					} else { // If this is a file
						copyError = CopyFile(sourceItemPath, destinationItemPath) // Copy the directory
					}
				}
			}
		} else { // If there was a read error on the directory
			copyError = errors.New("Unable to read: " + sourceDirectory)
		}
	} else {
		copyError = errors.New("Unsable to open: " + sourceDirectory)
	}

	os.Chdir(currentDirectory)

	return copyError
}

// CopyFile will copy a file and its relevant permissions
func CopyFile(sourceFile, destinationFile string) error {
	var copyError error

	sourceFileStruct, sourceFileError := os.Open(sourceFile) // Attempt to open the sourceFile

	if sourceFileError == nil { // If there was not an error opening the source file
		sourceFileStats, _ := sourceFileStruct.Stat() // Get the stats of the file

		if sourceFileStats.IsDir() { // If this is actually a directory
			copyError = errors.New(sourceFile + " is a directory. Please use CopyDirectory instead.")
		} else { // If it is indeed a file
			var fileContent []byte
			sourceFileMode := sourceFileStats.Mode() // Get the FileMode of this file
			sourceFileStruct.Close()                 // Close the file

			fileContent, copyError = ioutil.ReadFile(sourceFile) // Read the source file
			copyError = WriteOrUpdateFile(destinationFile, fileContent, sourceFileMode)
		}
	} else { // If the file does not exist
		copyError = errors.New(sourceFile + " does not exist.")
	}

	return copyError
}

// GetFiles will get all the files from a directory.
func GetFiles(path string, recursive bool) ([]string, error) {
	var files []string      // Define files as a []string
	var getFilesError error // Define getFilesError as an error

	if directory, openErr := os.Open(path); openErr == nil {
		directoryContents, directoryReadError := directory.Readdir(-1)

		if directoryReadError == nil { // If there was no issue reading the directory contents
			for _, fileInfoStruct := range directoryContents { // For each FileInfo struct in directoryContents
				name := fileInfoStruct.Name()

				if recursive && fileInfoStruct.IsDir() { // If the FileInfo indicates the object is a directory and we're doing recursive file fetching
					additionalFiles, _ := GetFiles(path+Separator+name, true)
					files = append(files, additionalFiles...)
				} else if !fileInfoStruct.IsDir() { // FileInfo is not a directory
					files = append(files, path+Separator+name) // Add to files the file's name
				}
			}
		} else { // If there was ano issue reading the directory content
			getFilesError = errors.New("Cannot read the contents of " + path)
		}
	} else { // If path is not a directory
		getFilesError = errors.New(path + " is not a directory.")
	}

	return files, getFilesError
}

// GetFilesContains will return any files from a directory containing a particular string
func GetFilesContains(path, substring string) ([]string, error) {
	var files []string                // Define files as the parsed files
	var getFilesError error           // Define getFilesError as an error
	var allDirectoryContents []string // Define allDirectoryContents as the contents returned (if any) from GetFiles

	allDirectoryContents, getFilesError = GetFiles(path, false) // Get all the files from the path

	if getFilesError == nil { // If there was no issue getting the directory contents
		for _, fileName := range allDirectoryContents { // For each file name in directory contents
			if strings.Contains(filepath.Base(fileName), substring) { // If the file name contains our substring
				files = append(files, fileName) // Append to files
			}
		}
	}

	return files, getFilesError
}

// IsDir checks if the path provided is a directory or not
func IsDir(path string) bool {
	var isDir bool
	fileObject, fileOpenError := os.Open(path) // Open currentDirectory + path

	if fileOpenError == nil { // If there was no error opening the file object
		stat, filePathError := fileObject.Stat() // Get any stats

		if filePathError == nil { // If we got the statistics properly
			isDir = stat.IsDir() // Set isDir to result from stat
		}
	}

	return isDir
}

// WriteOrUpdateFile writes or updates the file contents of the passed file under the leading filepath with the specified sourceFileMode
func WriteOrUpdateFile(file string, fileContent []byte, sourceFileMode os.FileMode) error {
	var writeDirectory string // Directory to write file

	currentDirectory, _ := os.Getwd()            // Get the working directory
	currentDirectory = AbsPath(currentDirectory) // Get the absolute path of the current working directory
	fileName := filepath.Base(file)

	if file == fileName { // If we did not specify a directory to write to
		writeDirectory = currentDirectory // Set to the current directory
	} else {
		writeDirectory = AbsPath(filepath.Dir(file))
	}

	if currentDirectory != writeDirectory { // If the currentDirectory is not the same directory as the writeDirectory
		if createDirsErr := os.MkdirAll(writeDirectory, sourceFileMode); createDirsErr != nil { // If we failed to make all the directories needed
			return errors.New("Failed to create the path leading up to " + fileName + ": " + writeDirectory)
		}
	}

	writeErr := ioutil.WriteFile(writeDirectory+Separator+fileName, fileContent, sourceFileMode)

	if writeErr != nil {
		writeErr = errors.New("Failed to write " + fileName + " in directory " + writeDirectory)
	}

	return writeErr
}
<commit_msg>Add GetFilesContainsRecursive func.<commit_after>package coreutils

import (
	"errors"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"strings"
)

// AbsPath get the absolute directory path, cleaning out any file names, home directory references, etc.
func AbsPath(path string) string {
	if !filepath.IsAbs(path) { // If the path provided isn't already absolute
		user, userGetErr := user.Current()

		if userGetErr == nil { // If we didn't fail getting the current user
			path = strings.Replace(path, "~", user.HomeDir+Separator, -1) // Replace any home directory reference
		}

		path, _ = filepath.Abs(path) // Get the absolute path of path

		var stripLastElement bool

		if file, openErr := os.Open(path); openErr == nil { // Attempt to open the path, to validate if it is a file or directory
			stat, statErr := file.Stat()
			stripLastElement = (statErr == nil) && !stat.IsDir() // Sets stripLastElement to true if stat.IsDir is not true
		} else { // If we failed to open the directory or file
			lastElement := filepath.Base(path)
			stripLastElement = filepath.Ext(lastElement) != "" // If lastElement is either a dotfile or has an extension, assume it is a file
		}

		if stripLastElement {
			path = filepath.Dir(path) + Separator // Strip out the last element and add the separator
		}
	}

	return path
}

// CopyDirectory will the directory specified and its contents into the destination directory
func CopyDirectory(sourceDirectory, destinationDirectory string) error {
	if !IsDir(sourceDirectory) { // If this isn't a source directory
		return errors.New(sourceDirectory + " is not a directory.")
	}

	var copyError error
	currentDirectory, _ := os.Getwd()            // Get the working directory
	currentDirectory = AbsPath(currentDirectory) // Get the absolute path of the current working directory

	os.MkdirAll(destinationDirectory, NonGlobalFileMode) // Ensure destinationDirectory exists

	finalSourceDir := filepath.Base(sourceDirectory)                              // Determine what our final source directory is. For instance, we should only copy child from test/parent/child
	parentOfFinalSourceDir := strings.TrimSuffix(sourceDirectory, finalSourceDir) // Get the parent directories we need to change to. Ex: test/parent

	os.Chdir(parentOfFinalSourceDir)

	if sourceDirectoryFile, sourceDirOpenErr := os.Open(finalSourceDir); sourceDirOpenErr == nil { // If we did not fail to open finalSourceDir
		if directoryContents, directoryReadError := sourceDirectoryFile.Readdir(-1); directoryReadError == nil { // Read the directory contents
			if len(directoryContents) != 0 { // If the directory has contents
				for _, contentItemFileInfo := range directoryContents { // For each FileInfo struct in directoryContents
					contentItemName := contentItemFileInfo.Name() // Get the name of the item
					sourceItemPath := finalSourceDir + "/" + contentItemName
					destinationItemPath := destinationDirectory + "/" + contentItemName

					if contentItemFileInfo.IsDir() { // If this is a directory
						copyError = CopyDirectory(sourceItemPath, destinationItemPath) // Copy this sub-directory and its contents
					} else { // If this is a file
						copyError = CopyFile(sourceItemPath, destinationItemPath) // Copy the directory
					}
				}
			}
		} else { // If there was a read error on the directory
			copyError = errors.New("Unable to read: " + sourceDirectory)
		}
	} else {
		copyError = errors.New("Unsable to open: " + sourceDirectory)
	}

	os.Chdir(currentDirectory)

	return copyError
}

// CopyFile will copy a file and its relevant permissions
func CopyFile(sourceFile, destinationFile string) error {
	var copyError error

	sourceFileStruct, sourceFileError := os.Open(sourceFile) // Attempt to open the sourceFile

	if sourceFileError == nil { // If there was not an error opening the source file
		sourceFileStats, _ := sourceFileStruct.Stat() // Get the stats of the file

		if sourceFileStats.IsDir() { // If this is actually a directory
			copyError = errors.New(sourceFile + " is a directory. Please use CopyDirectory instead.")
		} else { // If it is indeed a file
			var fileContent []byte
			sourceFileMode := sourceFileStats.Mode() // Get the FileMode of this file
			sourceFileStruct.Close()                 // Close the file

			fileContent, copyError = ioutil.ReadFile(sourceFile) // Read the source file
			copyError = WriteOrUpdateFile(destinationFile, fileContent, sourceFileMode)
		}
	} else { // If the file does not exist
		copyError = errors.New(sourceFile + " does not exist.")
	}

	return copyError
}

// GetFiles will get all the files from a directory.
func GetFiles(path string, recursive bool) ([]string, error) {
	var files []string      // Define files as a []string
	var getFilesError error // Define getFilesError as an error

	if directory, openErr := os.Open(path); openErr == nil {
		directoryContents, directoryReadError := directory.Readdir(-1)

		if directoryReadError == nil { // If there was no issue reading the directory contents
			for _, fileInfoStruct := range directoryContents { // For each FileInfo struct in directoryContents
				name := fileInfoStruct.Name()

				if recursive && fileInfoStruct.IsDir() { // If the FileInfo indicates the object is a directory and we're doing recursive file fetching
					additionalFiles, _ := GetFiles(path+Separator+name, true)
					files = append(files, additionalFiles...)
				} else if !fileInfoStruct.IsDir() { // FileInfo is not a directory
					files = append(files, path+Separator+name) // Add to files the file's name
				}
			}
		} else { // If there was ano issue reading the directory content
			getFilesError = errors.New("Cannot read the contents of " + path)
		}
	} else { // If path is not a directory
		getFilesError = errors.New(path + " is not a directory.")
	}

	return files, getFilesError
}

// GetFilesContains will return any files from a directory containing a particular string
func GetFilesContains(path, substring string) ([]string, error) {
	var files []string                // Define files as the parsed files
	var getFilesError error           // Define getFilesError as an error
	var allDirectoryContents []string // Define allDirectoryContents as the contents returned (if any) from GetFiles

	allDirectoryContents, getFilesError = GetFiles(path, false) // Get all the files from the path

	if getFilesError == nil { // If there was no issue getting the directory contents
		for _, fileName := range allDirectoryContents { // For each file name in directory contents
			if strings.Contains(filepath.Base(fileName), substring) { // If the file name contains our substring
				files = append(files, fileName) // Append to files
			}
		}
	}

	return files, getFilesError
}

// GetFilesContainsRecursive will return any files from a directory containing a particular string, recursively
func GetFilesContainsRecursive(path, substring string) ([]string, error) {
	var files []string                // Define files as the parsed files
	var getFilesError error           // Define getFilesError as an error
	var allDirectoryContents []string // Define allDirectoryContents as the contents returned (if any) from GetFiles

	allDirectoryContents, getFilesError = GetFiles(path, true) // Get all the files from the path

	if getFilesError == nil { // If there was no issue getting the directory contents
		for _, fileName := range allDirectoryContents { // For each file name in directory contents
			if strings.Contains(filepath.Base(fileName), substring) { // If the file name contains our substring
				files = append(files, fileName) // Append to files
			}
		}
	}

	return files, getFilesError
}

// IsDir checks if the path provided is a directory or not
func IsDir(path string) bool {
	var isDir bool
	fileObject, fileOpenError := os.Open(path) // Open currentDirectory + path

	if fileOpenError == nil { // If there was no error opening the file object
		stat, filePathError := fileObject.Stat() // Get any stats

		if filePathError == nil { // If we got the statistics properly
			isDir = stat.IsDir() // Set isDir to result from stat
		}
	}

	return isDir
}

// WriteOrUpdateFile writes or updates the file contents of the passed file under the leading filepath with the specified sourceFileMode
func WriteOrUpdateFile(file string, fileContent []byte, sourceFileMode os.FileMode) error {
	var writeDirectory string // Directory to write file

	currentDirectory, _ := os.Getwd()            // Get the working directory
	currentDirectory = AbsPath(currentDirectory) // Get the absolute path of the current working directory
	fileName := filepath.Base(file)

	if file == fileName { // If we did not specify a directory to write to
		writeDirectory = currentDirectory // Set to the current directory
	} else {
		writeDirectory = AbsPath(filepath.Dir(file))
	}

	if currentDirectory != writeDirectory { // If the currentDirectory is not the same directory as the writeDirectory
		if createDirsErr := os.MkdirAll(writeDirectory, sourceFileMode); createDirsErr != nil { // If we failed to make all the directories needed
			return errors.New("Failed to create the path leading up to " + fileName + ": " + writeDirectory)
		}
	}

	writeErr := ioutil.WriteFile(writeDirectory+Separator+fileName, fileContent, sourceFileMode)

	if writeErr != nil {
		writeErr = errors.New("Failed to write " + fileName + " in directory " + writeDirectory + "\n" + writeError.Error())
	}

	return writeErr
}
<|endoftext|>


<commit_before>// Copyright 2013 Jari Takkala. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"crypto/sha1"
	"fmt"
	sysio "io"
	"launchpad.net/tomb"
	"log"
	"os"
	"path/filepath"
)

type IO struct {
	metaInfo MetaInfo
	files    []*os.File
	t        tomb.Tomb
}

// checkHash accepts a byte buffer and pieceIndex, computes the SHA-1 hash of
// the buffer and returns true or false if it's correct.
func (io *IO) checkHash(buf []byte, pieceIndex int) bool {
	h := sha1.New()
	h.Write(buf)
	if bytes.Equal(h.Sum(nil), []byte(io.metaInfo.Info.Pieces[pieceIndex:pieceIndex+h.Size()])) {
		return true
	}
	return false
}

// Verify reads in each file and verifies the SHA-1 checksum of each piece.
// Return the boolean list pieces that are correct.
func (io *IO) Verify() (finishedPieces []bool) {
	log.Println("IO : Verify : Started")
	defer log.Println("IO : Verify : Completed")

	pieceLength := io.metaInfo.Info.PieceLength
	buf := make([]byte, pieceLength)
	var pieceIndex, n int
	var err error

	if len(io.metaInfo.Info.Files) > 0 {
		// Multiple File Mode
		var m int
		// Iterate over each file
		for i, _ := range io.metaInfo.Info.Files {
			for offset := int64(0); ; offset += int64(n) {
				// Read from file at offset, up to buf size or
				// less if last read was incomplete due to EOF
				n, err = io.files[i].ReadAt(buf[m:], offset)
				if err != nil {
					if err == sysio.EOF {
						// Reached EOF. Increment partial read counter by bytes read
						m += n
						break
					}
					log.Fatal(err)
				}
				// We have a full buf, check the hash of buf and
				// append the result to the finished pieces
				finishedPieces = append(finishedPieces, io.checkHash(buf, pieceIndex))
				// Reset partial read counter
				m = 0
				// Increment piece by the length of a SHA-1 hash (20 bytes)
				pieceIndex += 20
			}
		}
		// If the final iteration resulted in a partial read, then
		// check the hash of it and append the result
		if m > 0 {
			finishedPieces = append(finishedPieces, io.checkHash(buf[:m], pieceIndex))
		}
	} else {
		// Single File Mode
		for offset := int64(0); ; offset += int64(n) {
			// Read from file at offset, up to buf size or
			// less if last read was incomplete due to EOF
			n, err = io.files[0].ReadAt(buf, offset)
			if err != nil {
				if err == sysio.EOF {
					// Reached EOF
					break
				}
				log.Fatal(err)
			}
			// We have a full buf, check the hash of buf and
			// append the result to the finished pieces
			finishedPieces = append(finishedPieces, io.checkHash(buf, pieceIndex))
			// Increment piece by the length of a SHA-1 hash (20 bytes)
			pieceIndex += 20
		}
		// If the final iteration resulted in a partial read, then compute a hash
		if n > 0 {
			finishedPieces = append(finishedPieces, io.checkHash(buf[:n], pieceIndex))
		}
	}

	return finishedPieces
}

func checkError(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

// openOrCreateFile opens the named file or creates it if it doesn't already
// exist. If successful it returns a file handle that can be used for I/O.
func openOrCreateFile(name string) (file *os.File) {
	// Create the file if it doesn't exist
	if _, err := os.Stat(name); os.IsNotExist(err) {
		// Create the file and return a handle
		file, err = os.Create(name)
		checkError(err)
	} else {
		// Open the file and return a handle
		file, err = os.Open(name)
		checkError(err)
	}
	return
}

func (io *IO) Init() {
	if len(io.metaInfo.Info.Files) > 0 {
		// Multiple File Mode
		directory := io.metaInfo.Info.Name
		// Create the directory if it doesn't exist
		if _, err := os.Stat(directory); os.IsNotExist(err) {
			err = os.Mkdir(directory, os.ModeDir|os.ModePerm)
			checkError(err)
		}
		err := os.Chdir(directory)
		checkError(err)
		for _, file := range io.metaInfo.Info.Files {
			// Create any sub-directories if required
			if len(file.Path) > 1 {
				directory = filepath.Join(file.Path[1:]...)
				if _, err := os.Stat(directory); os.IsNotExist(err) {
					err = os.MkdirAll(directory, os.ModeDir|os.ModePerm)
					checkError(err)
				}
			}
			// Create the file if it doesn't exist
			name := filepath.Join(file.Path...)
			io.files = append(io.files, openOrCreateFile(name))
		}
	} else {
		// Single File Mode
		io.files = append(io.files, openOrCreateFile(io.metaInfo.Info.Name))
	}
}

func (io *IO) Stop() error {
	log.Println("IO : Stop : Stopping")
	io.t.Kill(nil)
	return io.t.Wait()
}

func (io *IO) Run() {
	log.Println("IO : Run : Started")
	defer io.t.Done()
	defer log.Println("IO : Run : Completed")

	io.Init()
	finishedPieces := io.Verify()
	fmt.Println(finishedPieces)

	for {
		select {
		case <-io.t.Dying():
			return
		}
	}
}
<commit_msg>pieceLength not used more than once, eliminate it<commit_after>// Copyright 2013 Jari Takkala. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"crypto/sha1"
	"fmt"
	sysio "io"
	"launchpad.net/tomb"
	"log"
	"os"
	"path/filepath"
)

type IO struct {
	metaInfo MetaInfo
	files    []*os.File
	t        tomb.Tomb
}

// checkHash accepts a byte buffer and pieceIndex, computes the SHA-1 hash of
// the buffer and returns true or false if it's correct.
func (io *IO) checkHash(buf []byte, pieceIndex int) bool {
	h := sha1.New()
	h.Write(buf)
	if bytes.Equal(h.Sum(nil), []byte(io.metaInfo.Info.Pieces[pieceIndex:pieceIndex+h.Size()])) {
		return true
	}
	return false
}

// Verify reads in each file and verifies the SHA-1 checksum of each piece.
// Return the boolean list pieces that are correct.
func (io *IO) Verify() (finishedPieces []bool) {
	log.Println("IO : Verify : Started")
	defer log.Println("IO : Verify : Completed")

	buf := make([]byte, io.metaInfo.Info.PieceLength)
	var pieceIndex, n int
	var err error

	if len(io.metaInfo.Info.Files) > 0 {
		// Multiple File Mode
		var m int
		// Iterate over each file
		for i, _ := range io.metaInfo.Info.Files {
			for offset := int64(0); ; offset += int64(n) {
				// Read from file at offset, up to buf size or
				// less if last read was incomplete due to EOF
				n, err = io.files[i].ReadAt(buf[m:], offset)
				if err != nil {
					if err == sysio.EOF {
						// Reached EOF. Increment partial read counter by bytes read
						m += n
						break
					}
					log.Fatal(err)
				}
				// We have a full buf, check the hash of buf and
				// append the result to the finished pieces
				finishedPieces = append(finishedPieces, io.checkHash(buf, pieceIndex))
				// Reset partial read counter
				m = 0
				// Increment piece by the length of a SHA-1 hash (20 bytes)
				pieceIndex += 20
			}
		}
		// If the final iteration resulted in a partial read, then
		// check the hash of it and append the result
		if m > 0 {
			finishedPieces = append(finishedPieces, io.checkHash(buf[:m], pieceIndex))
		}
	} else {
		// Single File Mode
		for offset := int64(0); ; offset += int64(n) {
			// Read from file at offset, up to buf size or
			// less if last read was incomplete due to EOF
			n, err = io.files[0].ReadAt(buf, offset)
			if err != nil {
				if err == sysio.EOF {
					// Reached EOF
					break
				}
				log.Fatal(err)
			}
			// We have a full buf, check the hash of buf and
			// append the result to the finished pieces
			finishedPieces = append(finishedPieces, io.checkHash(buf, pieceIndex))
			// Increment piece by the length of a SHA-1 hash (20 bytes)
			pieceIndex += 20
		}
		// If the final iteration resulted in a partial read, then compute a hash
		if n > 0 {
			finishedPieces = append(finishedPieces, io.checkHash(buf[:n], pieceIndex))
		}
	}

	return finishedPieces
}

func checkError(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

// openOrCreateFile opens the named file or creates it if it doesn't already
// exist. If successful it returns a file handle that can be used for I/O.
func openOrCreateFile(name string) (file *os.File) {
	// Create the file if it doesn't exist
	if _, err := os.Stat(name); os.IsNotExist(err) {
		// Create the file and return a handle
		file, err = os.Create(name)
		checkError(err)
	} else {
		// Open the file and return a handle
		file, err = os.Open(name)
		checkError(err)
	}
	return
}

func (io *IO) Init() {
	if len(io.metaInfo.Info.Files) > 0 {
		// Multiple File Mode
		directory := io.metaInfo.Info.Name
		// Create the directory if it doesn't exist
		if _, err := os.Stat(directory); os.IsNotExist(err) {
			err = os.Mkdir(directory, os.ModeDir|os.ModePerm)
			checkError(err)
		}
		err := os.Chdir(directory)
		checkError(err)
		for _, file := range io.metaInfo.Info.Files {
			// Create any sub-directories if required
			if len(file.Path) > 1 {
				directory = filepath.Join(file.Path[1:]...)
				if _, err := os.Stat(directory); os.IsNotExist(err) {
					err = os.MkdirAll(directory, os.ModeDir|os.ModePerm)
					checkError(err)
				}
			}
			// Create the file if it doesn't exist
			name := filepath.Join(file.Path...)
			io.files = append(io.files, openOrCreateFile(name))
		}
	} else {
		// Single File Mode
		io.files = append(io.files, openOrCreateFile(io.metaInfo.Info.Name))
	}
}

func (io *IO) Stop() error {
	log.Println("IO : Stop : Stopping")
	io.t.Kill(nil)
	return io.t.Wait()
}

func (io *IO) Run() {
	log.Println("IO : Run : Started")
	defer io.t.Done()
	defer log.Println("IO : Run : Completed")

	io.Init()
	finishedPieces := io.Verify()

	for {
		select {
		case <-io.t.Dying():
			return
		}
	}
}
<|endoftext|>


<commit_before>package coreutils

import (
	"errors"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"strings"
)

// AbsPath get the absolute directory path, cleaning out any file names, home directory references, etc.
func AbsPath(path string) string {
	if !filepath.IsAbs(path) { // If the path provided isn't already absolute
		user, userGetErr := user.Current()

		if userGetErr == nil { // If we didn't fail getting the current user
			path = strings.Replace(path, "~", user.HomeDir+Separator, -1) // Replace any home directory reference
		}

		path, _ = filepath.Abs(path) // Get the absolute path of path

		var stripLastElement bool

		if file, openErr := os.Open(path); openErr == nil { // Attempt to open the path, to validate if it is a file or directory
			stat, statErr := file.Stat()
			stripLastElement = (statErr == nil) && !stat.IsDir() // Sets stripLastElement to true if stat.IsDir is not true
		} else { // If we failed to open the directory or file
			lastElement := filepath.Base(path)
			stripLastElement = filepath.Ext(lastElement) != "" // If lastElement is either a dotfile or has an extension, assume it is a file
		}

		if stripLastElement {
			path = filepath.Dir(path) + Separator // Strip out the last element and add the separator
		}
	}

	return path
}

// CopyDirectory will copy a directory, sub-directories, and files
func CopyDirectory(sourceDirectory, destinationDirectory string) error {
	var copyError error

	if IsDir(sourceDirectory) { // If sourceDirectory is a valid directory
		os.MkdirAll(destinationDirectory, NonGlobalFileMode)                     // Make all the needed directories to destinationDirectory
		sourceDirectoryFile, _ := os.Open(sourceDirectory)                       // Get the source directory "file" struct
		directoryContents, directoryReadError := sourceDirectoryFile.Readdir(-1) // Read the directory contents

		if directoryReadError == nil { /// If there was no read error on the directory
			if len(directoryContents) != 0 { // If there is content
				for _, contentItemFileInfo := range directoryContents { // For each FileInfo struct in directoryContents
					contentItemName := contentItemFileInfo.Name() // Get the name of the item
					sourceItemPath := sourceDirectory + "/" + contentItemName
					destinationItemPath := destinationDirectory + "/" + contentItemName

					if contentItemFileInfo.IsDir() { // If this is a directory
						copyError = CopyDirectory(sourceItemPath, destinationItemPath) // Copy this sub-directory and its contents
					} else { // If this is a file
						copyError = CopyFile(sourceItemPath, destinationItemPath) // Copy the directory
					}
				}
			}
		} else { // If there was a read error on the directory
			copyError = errors.New("Unable to read: " + sourceDirectory)
		}
	} else { // If sourceDirectory is not a valid directory
		copyError = errors.New(sourceDirectory + " is not a valid directory.")
	}

	return copyError
}

// CopyFile will copy a file and its relevant permissions
func CopyFile(sourceFile, destinationFile string) error {
	var copyError error

	sourceFileStruct, sourceFileError := os.Open(sourceFile) // Attempt to open the sourceFile

	if sourceFileError == nil { // If there was not an error opening the source file
		sourceFileStats, _ := sourceFileStruct.Stat() // Get the stats of the file

		if sourceFileStats.IsDir() { // If this is actually a directory
			copyError = errors.New(sourceFile + " is a directory. Please use CopyDirectory instead.")
		} else { // If it is indeed a file
			var fileContent []byte
			sourceFileMode := sourceFileStats.Mode() // Get the FileMode of this file
			sourceFileStruct.Close()                 // Close the file

			fileContent, copyError = ioutil.ReadFile(sourceFile) // Read the source file
			copyError = WriteOrUpdateFile(destinationFile, fileContent, sourceFileMode)
		}
	} else { // If the file does not exist
		copyError = errors.New(sourceFile + " does not exist.")
	}

	return copyError
}

// GetFiles will get all the files from a directory.
func GetFiles(path string, recursive bool) ([]string, error) {
	var files []string      // Define files as a []string
	var getFilesError error // Define getFilesError as an error

	if directory, openErr := os.Open(path); openErr == nil {
		directoryContents, directoryReadError := directory.Readdir(-1)

		if directoryReadError == nil { // If there was no issue reading the directory contents
			for _, fileInfoStruct := range directoryContents { // For each FileInfo struct in directoryContents
				name := fileInfoStruct.Name()

				if recursive && fileInfoStruct.IsDir() { // If the FileInfo indicates the object is a directory and we're doing recursive file fetching
					additionalFiles, _ := GetFiles(path + Separator + name, true)
					files = append(files, additionalFiles...)
				} else if !fileInfoStruct.IsDir() { // FileInfo is not a directory
					files = append(files, path+ Separator + name) // Add to files the file's name
				}
			}
		} else { // If there was ano issue reading the directory content
			getFilesError = errors.New("Cannot read the contents of " + path)
		}
	} else { // If path is not a directory
		getFilesError = errors.New(path + " is not a directory.")
	}

	return files, getFilesError
}

// GetFilesContains will return any files from a directory containing a particular string
func GetFilesContains(path, substring string) ([]string, error) {
	var files []string                // Define files as the parsed files
	var getFilesError error           // Define getFilesError as an error
	var allDirectoryContents []string // Define allDirectoryContents as the contents returned (if any) from GetFiles

	allDirectoryContents, getFilesError = GetFiles(path, false) // Get all the files from the path

	if getFilesError == nil { // If there was no issue getting the directory contents
		for _, fileName := range allDirectoryContents { // For each file name in directory contents
			if strings.Contains(filepath.Base(fileName), substring) { // If the file name contains our substring
				files = append(files, fileName) // Append to files
			}
		}
	}

	return files, getFilesError
}

// IsDir checks if the path provided is a directory or not
func IsDir(path string) bool {
	var isDir bool
	fileObject, fileOpenError := os.Open(path) // Open currentDirectory + path

	if fileOpenError == nil { // If there was no error opening the file object
		stat, filePathError := fileObject.Stat() // Get any stats

		if filePathError == nil { // If we got the statistics properly
			isDir = stat.IsDir() // Set isDir to result from stat
		}
	}

	return isDir
}

// WriteOrUpdateFile writes or updates the file contents of the passed file under the leading filepath with the specified sourceFileMode
func WriteOrUpdateFile(file string, fileContent []byte, sourceFileMode os.FileMode) error {
	var writeDirectory string // Directory to write file

	currentDirectory, _ := os.Getwd()            // Get the working directory
	currentDirectory = AbsPath(currentDirectory) // Get the absolute path of the current working directory
	fileName := filepath.Base(file)

	if file == fileName { // If we did not specify a directory to write to
		writeDirectory = currentDirectory // Set to the current directory
	} else {
		writeDirectory = AbsPath(filepath.Dir(file))
	}

	if currentDirectory != writeDirectory { // If the currentDirectory is not the same directory as the writeDirectory
		if createDirsErr := os.MkdirAll(writeDirectory, sourceFileMode); createDirsErr != nil { // If we failed to make all the directories needed
			return errors.New("Failed to create the path leading up to " + fileName + ": " + writeDirectory)
		}
	}

	writeErr := ioutil.WriteFile(writeDirectory+Separator+fileName, fileContent, sourceFileMode)

	if writeErr != nil {
		writeErr = errors.New("Failed to write " + fileName + " in directory " + writeDirectory)
	}

	return writeErr
}
<commit_msg>Change inner workings of CopyDirectory. We'll no longer copy each directory specified in sourceDirectory, only last.<commit_after>package coreutils

import (
	"errors"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"strings"
)

// AbsPath get the absolute directory path, cleaning out any file names, home directory references, etc.
func AbsPath(path string) string {
	if !filepath.IsAbs(path) { // If the path provided isn't already absolute
		user, userGetErr := user.Current()

		if userGetErr == nil { // If we didn't fail getting the current user
			path = strings.Replace(path, "~", user.HomeDir+Separator, -1) // Replace any home directory reference
		}

		path, _ = filepath.Abs(path) // Get the absolute path of path

		var stripLastElement bool

		if file, openErr := os.Open(path); openErr == nil { // Attempt to open the path, to validate if it is a file or directory
			stat, statErr := file.Stat()
			stripLastElement = (statErr == nil) && !stat.IsDir() // Sets stripLastElement to true if stat.IsDir is not true
		} else { // If we failed to open the directory or file
			lastElement := filepath.Base(path)
			stripLastElement = filepath.Ext(lastElement) != "" // If lastElement is either a dotfile or has an extension, assume it is a file
		}

		if stripLastElement {
			path = filepath.Dir(path) + Separator // Strip out the last element and add the separator
		}
	}

	return path
}

// CopyDirectory will the directory specified and its contents into the destination directory
func CopyDirectory(sourceDirectory, destinationDirectory string) error {
	if !IsDir(sourceDirectory) { // If this isn't a source directory
		return errors.New(sourceDirectory + " is not a directory.")
	}

	var copyError error
	currentDirectory, _ := os.Getwd()            // Get the working directory
	currentDirectory = AbsPath(currentDirectory) // Get the absolute path of the current working directory

	os.MkdirAll(destinationDirectory, NonGlobalFileMode) // Ensure destinationDirectory exists

	finalSourceDir := filepath.Base(sourceDirectory)                              // Determine what our final source directory is. For instance, we should only copy child from test/parent/child
	parentOfFinalSourceDir := strings.TrimSuffix(sourceDirectory, finalSourceDir) // Get the parent directories we need to change to. Ex: test/parent

	os.Chdir(parentOfFinalSourceDir)

	if sourceDirectoryFile, sourceDirOpenErr := os.Open(finalSourceDir); sourceDirOpenErr == nil { // If we did not fail to open finalSourceDir
		if directoryContents, directoryReadError := sourceDirectoryFile.Readdir(-1); directoryReadError == nil { // Read the directory contents
			if len(directoryContents) != 0 { // If the directory has contents
				for _, contentItemFileInfo := range directoryContents { // For each FileInfo struct in directoryContents
					contentItemName := contentItemFileInfo.Name() // Get the name of the item
					sourceItemPath := finalSourceDir + "/" + contentItemName
					destinationItemPath := destinationDirectory + "/" + contentItemName

					if contentItemFileInfo.IsDir() { // If this is a directory
						copyError = CopyDirectory(sourceItemPath, destinationItemPath) // Copy this sub-directory and its contents
					} else { // If this is a file
						copyError = CopyFile(sourceItemPath, destinationItemPath) // Copy the directory
					}
				}
			}
		} else { // If there was a read error on the directory
			copyError = errors.New("Unable to read: " + sourceDirectory)
		}
	} else {
		copyError = errors.New("Unsable to open: " + sourceDirectory)
	}

	os.Chdir(currentDirectory)

	return copyError
}

// CopyFile will copy a file and its relevant permissions
func CopyFile(sourceFile, destinationFile string) error {
	var copyError error

	sourceFileStruct, sourceFileError := os.Open(sourceFile) // Attempt to open the sourceFile

	if sourceFileError == nil { // If there was not an error opening the source file
		sourceFileStats, _ := sourceFileStruct.Stat() // Get the stats of the file

		if sourceFileStats.IsDir() { // If this is actually a directory
			copyError = errors.New(sourceFile + " is a directory. Please use CopyDirectory instead.")
		} else { // If it is indeed a file
			var fileContent []byte
			sourceFileMode := sourceFileStats.Mode() // Get the FileMode of this file
			sourceFileStruct.Close()                 // Close the file

			fileContent, copyError = ioutil.ReadFile(sourceFile) // Read the source file
			copyError = WriteOrUpdateFile(destinationFile, fileContent, sourceFileMode)
		}
	} else { // If the file does not exist
		copyError = errors.New(sourceFile + " does not exist.")
	}

	return copyError
}

// GetFiles will get all the files from a directory.
func GetFiles(path string, recursive bool) ([]string, error) {
	var files []string      // Define files as a []string
	var getFilesError error // Define getFilesError as an error

	if directory, openErr := os.Open(path); openErr == nil {
		directoryContents, directoryReadError := directory.Readdir(-1)

		if directoryReadError == nil { // If there was no issue reading the directory contents
			for _, fileInfoStruct := range directoryContents { // For each FileInfo struct in directoryContents
				name := fileInfoStruct.Name()

				if recursive && fileInfoStruct.IsDir() { // If the FileInfo indicates the object is a directory and we're doing recursive file fetching
					additionalFiles, _ := GetFiles(path+Separator+name, true)
					files = append(files, additionalFiles...)
				} else if !fileInfoStruct.IsDir() { // FileInfo is not a directory
					files = append(files, path+Separator+name) // Add to files the file's name
				}
			}
		} else { // If there was ano issue reading the directory content
			getFilesError = errors.New("Cannot read the contents of " + path)
		}
	} else { // If path is not a directory
		getFilesError = errors.New(path + " is not a directory.")
	}

	return files, getFilesError
}

// GetFilesContains will return any files from a directory containing a particular string
func GetFilesContains(path, substring string) ([]string, error) {
	var files []string                // Define files as the parsed files
	var getFilesError error           // Define getFilesError as an error
	var allDirectoryContents []string // Define allDirectoryContents as the contents returned (if any) from GetFiles

	allDirectoryContents, getFilesError = GetFiles(path, false) // Get all the files from the path

	if getFilesError == nil { // If there was no issue getting the directory contents
		for _, fileName := range allDirectoryContents { // For each file name in directory contents
			if strings.Contains(filepath.Base(fileName), substring) { // If the file name contains our substring
				files = append(files, fileName) // Append to files
			}
		}
	}

	return files, getFilesError
}

// IsDir checks if the path provided is a directory or not
func IsDir(path string) bool {
	var isDir bool
	fileObject, fileOpenError := os.Open(path) // Open currentDirectory + path

	if fileOpenError == nil { // If there was no error opening the file object
		stat, filePathError := fileObject.Stat() // Get any stats

		if filePathError == nil { // If we got the statistics properly
			isDir = stat.IsDir() // Set isDir to result from stat
		}
	}

	return isDir
}

// WriteOrUpdateFile writes or updates the file contents of the passed file under the leading filepath with the specified sourceFileMode
func WriteOrUpdateFile(file string, fileContent []byte, sourceFileMode os.FileMode) error {
	var writeDirectory string // Directory to write file

	currentDirectory, _ := os.Getwd()            // Get the working directory
	currentDirectory = AbsPath(currentDirectory) // Get the absolute path of the current working directory
	fileName := filepath.Base(file)

	if file == fileName { // If we did not specify a directory to write to
		writeDirectory = currentDirectory // Set to the current directory
	} else {
		writeDirectory = AbsPath(filepath.Dir(file))
	}

	if currentDirectory != writeDirectory { // If the currentDirectory is not the same directory as the writeDirectory
		if createDirsErr := os.MkdirAll(writeDirectory, sourceFileMode); createDirsErr != nil { // If we failed to make all the directories needed
			return errors.New("Failed to create the path leading up to " + fileName + ": " + writeDirectory)
		}
	}

	writeErr := ioutil.WriteFile(writeDirectory+Separator+fileName, fileContent, sourceFileMode)

	if writeErr != nil {
		writeErr = errors.New("Failed to write " + fileName + " in directory " + writeDirectory)
	}

	return writeErr
}
<|endoftext|>


<commit_before>package main

import (
	builder "github.com/rafecolton/bob"
	"github.com/rafecolton/bob/config"
	"github.com/rafecolton/bob/log"
	"github.com/rafecolton/bob/parser"
	"github.com/rafecolton/bob/version"
)

import (
	"github.com/benmanns/goworker"
	"github.com/onsi/gocleanup"
	"github.com/wsxiaoys/terminal/color"
)

import (
	"flag"
	"fmt"
	"os"
)

var runtime *config.Runtime
var ver *version.Version
var par *parser.Parser
var runAsWorker = flag.Bool("work", false, "Run as a Goworker")
var allTheThings = func(queue string, args ...interface{}) (fake error) {
	if queue == "docker-build" {
		first := args[0].(map[string]interface{})
		pwd := first["pwd"].(string)
		build := fmt.Sprintf("%s/%s", pwd, first["build"].(string))

		os.Setenv("PWD", pwd)

		logger := log.Initialize(false)

		par, err := parser.NewParser(build, logger)
		if err != nil {
			logger.Println(
				color.Sprintf("@{r!}Alas, could not generate parser@{|}\n----> %+v", err),
			)
			gocleanup.Exit(73)
		}

		commandSequence, err := par.Parse()
		if err != nil {
			runtime.Println(color.Sprintf("@{r!}Alas, could not parse@{|}\n----> %+v", err))
			gocleanup.Exit(23)
		}

		bob := builder.NewBuilder(logger, true)
		bob.Builderfile = build

		if err = bob.Build(commandSequence); err != nil {
			logger.Println(
				color.Sprintf(
					"@{r!}Alas, I am unable to complete my assigned build because of...@{|}\n----> %+v",
					err,
				),
			)
			gocleanup.Exit(29)
		}

		return
	}

	// if user requests version/branch/rev
	if runtime.Version {
		runtime.Println(ver.Version)
	} else if runtime.VersionFull {
		runtime.Println(ver.VersionFull)
	} else if runtime.Branch {
		runtime.Println(ver.Branch)
	} else if runtime.Rev {
		runtime.Println(ver.Rev)
	} else if runtime.Lintfile != "" {
		// lint
		par, _ = parser.NewParser(runtime.Lintfile, runtime)
		par.AssertLint()
	} else {
		if runtime.Builderfile == "" {
			runtime.Builderfile = "bob.toml"
		}
		// otherwise, build
		par, err := parser.NewParser(runtime.Builderfile, runtime)
		if err != nil {
			runtime.Println(
				color.Sprintf("@{r!}Alas, could not generate parser@{|}\n----> %+v", err),
			)
			gocleanup.Exit(73)
		}

		commandSequence, err := par.Parse()
		if err != nil {
			runtime.Println(color.Sprintf("@{r!}Alas, could not parse@{|}\n----> %+v", err))
			gocleanup.Exit(23)
		}

		bob := builder.NewBuilder(runtime, true)
		bob.Builderfile = runtime.Builderfile

		if err = bob.Build(commandSequence); err != nil {
			runtime.Println(
				color.Sprintf(
					"@{r!}Alas, I am unable to complete my assigned build because of...@{|}\n----> %+v",
					err,
				),
			)
			gocleanup.Exit(29)
		}
	}

	gocleanup.Exit(0)
	return
}

func main() {
	if len(os.Args) > 1 && os.Args[1] == "-work" {
		flag.Parse()
		goworker.Register("DockerBuild", allTheThings)

		if err := goworker.Work(); err != nil {
			fmt.Println(
				color.Sprintf("@{r!}Alas, something went wrong :'(@{|}\n----> %+v", err),
			)
		}
	} else {
		runtime = config.NewRuntime()
		ver = version.NewVersion()

		allTheThings("")
	}

	gocleanup.Exit(0)
}
<commit_msg>Clearly indicate that we are eating an error<commit_after>package main

import (
	builder "github.com/rafecolton/bob"
	"github.com/rafecolton/bob/config"
	"github.com/rafecolton/bob/log"
	"github.com/rafecolton/bob/parser"
	"github.com/rafecolton/bob/version"
)

import (
	"github.com/benmanns/goworker"
	"github.com/onsi/gocleanup"
	"github.com/wsxiaoys/terminal/color"
)

import (
	"flag"
	"fmt"
	"os"
)

var runtime *config.Runtime
var ver *version.Version
var par *parser.Parser
var runAsWorker = flag.Bool("work", false, "Run as a Goworker")
var allTheThings = func(queue string, args ...interface{}) (fake error) {
	if queue == "docker-build" {
		first := args[0].(map[string]interface{})
		pwd := first["pwd"].(string)
		build := fmt.Sprintf("%s/%s", pwd, first["build"].(string))

		os.Setenv("PWD", pwd)

		logger := log.Initialize(false)

		par, err := parser.NewParser(build, logger)
		if err != nil {
			logger.Println(
				color.Sprintf("@{r!}Alas, could not generate parser@{|}\n----> %+v", err),
			)
			gocleanup.Exit(73)
		}

		commandSequence, err := par.Parse()
		if err != nil {
			runtime.Println(color.Sprintf("@{r!}Alas, could not parse@{|}\n----> %+v", err))
			gocleanup.Exit(23)
		}

		bob := builder.NewBuilder(logger, true)
		bob.Builderfile = build

		if err = bob.Build(commandSequence); err != nil {
			logger.Println(
				color.Sprintf(
					"@{r!}Alas, I am unable to complete my assigned build because of...@{|}\n----> %+v",
					err,
				),
			)
			gocleanup.Exit(29)
		}

		return
	}

	// if user requests version/branch/rev
	if runtime.Version {
		runtime.Println(ver.Version)
	} else if runtime.VersionFull {
		runtime.Println(ver.VersionFull)
	} else if runtime.Branch {
		runtime.Println(ver.Branch)
	} else if runtime.Rev {
		runtime.Println(ver.Rev)
	} else if runtime.Lintfile != "" {
		// lint
		par, _ = parser.NewParser(runtime.Lintfile, runtime)
		par.AssertLint()
	} else {
		if runtime.Builderfile == "" {
			runtime.Builderfile = "bob.toml"
		}
		// otherwise, build
		par, err := parser.NewParser(runtime.Builderfile, runtime)
		if err != nil {
			runtime.Println(
				color.Sprintf("@{r!}Alas, could not generate parser@{|}\n----> %+v", err),
			)
			gocleanup.Exit(73)
		}

		commandSequence, err := par.Parse()
		if err != nil {
			runtime.Println(color.Sprintf("@{r!}Alas, could not parse@{|}\n----> %+v", err))
			gocleanup.Exit(23)
		}

		bob := builder.NewBuilder(runtime, true)
		bob.Builderfile = runtime.Builderfile

		if err = bob.Build(commandSequence); err != nil {
			runtime.Println(
				color.Sprintf(
					"@{r!}Alas, I am unable to complete my assigned build because of...@{|}\n----> %+v",
					err,
				),
			)
			gocleanup.Exit(29)
		}
	}

	gocleanup.Exit(0)
	return
}

func main() {
	if len(os.Args) > 1 && os.Args[1] == "-work" {
		flag.Parse()
		goworker.Register("DockerBuild", allTheThings)

		if err := goworker.Work(); err != nil {
			fmt.Println(
				color.Sprintf("@{r!}Alas, something went wrong :'(@{|}\n----> %+v", err),
			)
		}
	} else {
		runtime = config.NewRuntime()
		ver = version.NewVersion()

		_ = allTheThings("")
	}

	gocleanup.Exit(0)
}
<|endoftext|>


<commit_before>// Package restxml provides RESTful XML serialisation of AWS
// requests and responses.
package restxml

//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/input/rest-xml.json build_test.go
//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/output/rest-xml.json unmarshal_test.go

import (
	"bytes"
	"encoding/xml"

	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/request"
	"github.com/aws/aws-sdk-go/internal/protocol/query"
	"github.com/aws/aws-sdk-go/internal/protocol/rest"
	"github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil"
)

// Build builds a request payload for the REST XML protocol.
func Build(r *request.Request) {
	rest.Build(r)

	if t := rest.PayloadType(r.Params); t == "structure" || t == "" {
		var buf bytes.Buffer
		err := xmlutil.BuildXML(r.Params, xml.NewEncoder(&buf))
		if err != nil {
			r.Error = awserr.New("SerializationError", "failed to enode rest XML request", err)
			return
		}
		r.SetBufferBody(buf.Bytes())
	}
}

// Unmarshal unmarshals a payload response for the REST XML protocol.
func Unmarshal(r *request.Request) {
	if t := rest.PayloadType(r.Data); t == "structure" || t == "" {
		defer r.HTTPResponse.Body.Close()
		decoder := xml.NewDecoder(r.HTTPResponse.Body)
		err := xmlutil.UnmarshalXML(r.Data, decoder, "")
		if err != nil {
			r.Error = awserr.New("SerializationError", "failed to decode REST XML response", err)
			return
		}
	}
}

// UnmarshalMeta unmarshals response headers for the REST XML protocol.
func UnmarshalMeta(r *request.Request) {
	rest.Unmarshal(r)
}

// UnmarshalError unmarshals a response error for the REST XML protocol.
func UnmarshalError(r *request.Request) {
	query.UnmarshalError(r)
}
<commit_msg>Fix typo in restxml error message<commit_after>// Package restxml provides RESTful XML serialisation of AWS
// requests and responses.
package restxml

//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/input/rest-xml.json build_test.go
//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/output/rest-xml.json unmarshal_test.go

import (
	"bytes"
	"encoding/xml"

	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/request"
	"github.com/aws/aws-sdk-go/internal/protocol/query"
	"github.com/aws/aws-sdk-go/internal/protocol/rest"
	"github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil"
)

// Build builds a request payload for the REST XML protocol.
func Build(r *request.Request) {
	rest.Build(r)

	if t := rest.PayloadType(r.Params); t == "structure" || t == "" {
		var buf bytes.Buffer
		err := xmlutil.BuildXML(r.Params, xml.NewEncoder(&buf))
		if err != nil {
			r.Error = awserr.New("SerializationError", "failed to encode rest XML request", err)
			return
		}
		r.SetBufferBody(buf.Bytes())
	}
}

// Unmarshal unmarshals a payload response for the REST XML protocol.
func Unmarshal(r *request.Request) {
	if t := rest.PayloadType(r.Data); t == "structure" || t == "" {
		defer r.HTTPResponse.Body.Close()
		decoder := xml.NewDecoder(r.HTTPResponse.Body)
		err := xmlutil.UnmarshalXML(r.Data, decoder, "")
		if err != nil {
			r.Error = awserr.New("SerializationError", "failed to decode REST XML response", err)
			return
		}
	}
}

// UnmarshalMeta unmarshals response headers for the REST XML protocol.
func UnmarshalMeta(r *request.Request) {
	rest.Unmarshal(r)
}

// UnmarshalError unmarshals a response error for the REST XML protocol.
func UnmarshalError(r *request.Request) {
	query.UnmarshalError(r)
}
<|endoftext|>


<commit_before>package main

import (
	"math"
	"os/exec"
	"testing"
	"time"
)

// Ensure that --jitter requires an argument
func TestJitterRequiresArg(t *testing.T) {
	out, err := exec.Command("go", "run", "cronwrap.go", "--jitter").CombinedOutput()
	if err == nil {
		t.Error(string(out))
	}
}

// Ensure that the argument must be a time delta
func TestJitterArgIsDelta(t *testing.T) {
	out, err := exec.Command("go", "run", "cronwrap.go", "--jitter", "bogus", "true").CombinedOutput()
	if err == nil {
		t.Error(string(out))
	}
	out, err = exec.Command("go", "run", "cronwrap.go", "--jitter", "1r", "true").CombinedOutput()
	if err == nil {
		t.Error(string(out))
	}
	out, err = exec.Command("go", "run", "cronwrap.go", "--jitter", "1", "true").CombinedOutput()
	if err == nil {
		t.Error(string(out))
	}

	out, err = exec.Command("go", "run", "cronwrap.go", "--jitter", "0", "true").CombinedOutput()
	if err != nil {
		t.Error(string(out))
	}
	out, err = exec.Command("go", "run", "cronwrap.go", "--jitter", "1s", "true").CombinedOutput()
	if err != nil {
		t.Error(string(out))
	}
	// out, err = exec.Command("go", "run", "cronwrap.go", "--jitter", "1m", "true").CombinedOutput()
	// if err != nil {
	//   t.Error(string(out))
	// }
	// out, err = exec.Command("go", "run", "cronwrap.go", "--jitter", "1h", "true").CombinedOutput()
	// if err != nil {
	//   t.Error(string(out))
	// }
}

// I actually don't know how to test that the job was delayed, as some machines
// are going to have a jitter value very close to zero.
//
// However, we do expect the jitter to be consistent on any given machine. That
// we can test.  One minute (--jitter 1m) is good enough for testing as cronwrap
// actually sleeps for a random number of seconds, so even with one minute of
// jitter cronwrap will sleep anywhere from 0-59 seconds.
func TestJitterIsConsistent(t *testing.T) {
	// Time one run
	start := time.Now()
	err := exec.Command("go", "run", "cronwrap.go", "--jitter", "1m", "true").Run()
	end := time.Now()
	elapsed := end.Sub(start)
	if err != nil {
		t.FailNow()
	}

	// Now verify that a few more runs are within one second of the same delay
	for i := 1; i <= 2; i++ {
		start := time.Now()
		err := exec.Command("go", "run", "cronwrap.go", "--jitter", "1m", "true").Run()
		end := time.Now()
		test_elapsed := end.Sub(start)
		if err != nil {
			t.FailNow()
		}
		if math.Abs(test_elapsed.Seconds()-elapsed.Seconds()) > 1 {
			t.Fail()
		}
	}
}
<commit_msg>Increase allowed diff slightly<commit_after>package main

import (
	"fmt"
	"math"
	"os/exec"
	"testing"
	"time"
)

// Ensure that --jitter requires an argument
func TestJitterRequiresArg(t *testing.T) {
	out, err := exec.Command("go", "run", "cronwrap.go", "--jitter").CombinedOutput()
	if err == nil {
		t.Error(string(out))
	}
}

// Ensure that the argument must be a time delta
func TestJitterArgIsDelta(t *testing.T) {
	out, err := exec.Command("go", "run", "cronwrap.go", "--jitter", "bogus", "true").CombinedOutput()
	if err == nil {
		t.Error(string(out))
	}
	out, err = exec.Command("go", "run", "cronwrap.go", "--jitter", "1r", "true").CombinedOutput()
	if err == nil {
		t.Error(string(out))
	}
	out, err = exec.Command("go", "run", "cronwrap.go", "--jitter", "1", "true").CombinedOutput()
	if err == nil {
		t.Error(string(out))
	}

	out, err = exec.Command("go", "run", "cronwrap.go", "--jitter", "0", "true").CombinedOutput()
	if err != nil {
		t.Error(string(out))
	}
	out, err = exec.Command("go", "run", "cronwrap.go", "--jitter", "1s", "true").CombinedOutput()
	if err != nil {
		t.Error(string(out))
	}
	// out, err = exec.Command("go", "run", "cronwrap.go", "--jitter", "1m", "true").CombinedOutput()
	// if err != nil {
	//   t.Error(string(out))
	// }
	// out, err = exec.Command("go", "run", "cronwrap.go", "--jitter", "1h", "true").CombinedOutput()
	// if err != nil {
	//   t.Error(string(out))
	// }
}

// I actually don't know how to test that the job was delayed, as some machines
// are going to have a jitter value very close to zero.
//
// However, we do expect the jitter to be consistent on any given machine. That
// we can test.  One minute (--jitter 1m) is good enough for testing as cronwrap
// actually sleeps for a random number of seconds, so even with one minute of
// jitter cronwrap will sleep anywhere from 0-59 seconds.
func TestJitterIsConsistent(t *testing.T) {
	// FIXME: It would speed up the test suite considerably to run all three tests
	// simultaneously in goroutines and compare the results

	// Time one run
	start := time.Now()
	err := exec.Command("go", "run", "cronwrap.go", "--jitter", "1m", "true").Run()
	end := time.Now()
	elapsed := end.Sub(start)
	if err != nil {
		t.FailNow()
	}

	// Now verify that a few more runs are within one second of the same delay
	allowed_diff := 2
	for i := 1; i <= 2; i++ {
		start := time.Now()
		err := exec.Command("go", "run", "cronwrap.go", "--jitter", "1m", "true").Run()
		end := time.Now()
		test_elapsed := end.Sub(start)
		if err != nil {
			t.FailNow()
		}
		diff := math.Abs(test_elapsed.Seconds() - elapsed.Seconds())
		if diff > float64(allowed_diff) {
			t.Error(fmt.Sprintf("Expected diff <= %d, was %f", allowed_diff, diff))
		}
	}
}
<|endoftext|>


<commit_before>// +build !windows
package visibility

// HideFile is a no-op for non-Windows systems.
func HideFile(string) error {
	return nil
}
<commit_msg>Fix build constraint<commit_after>// +build !windows

package visibility

// HideFile is a no-op for non-Windows systems.
func HideFile(string) error {
	return nil
}
<|endoftext|>