<commit_before>package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"github.com/google/subcommands"
	"github.com/linuxboot/fiano/uefi"
)

// Parse subcommand
type parseCmd struct {
}

func (*parseCmd) Name() string {
	return "parse"
}

func (*parseCmd) Synopsis() string {
	return "Parse rom file and print JSON summary to stdout"
}

func (*parseCmd) Usage() string {
	return "parse <path-to-rom-file>\n"
}

func (*parseCmd) SetFlags(_ *flag.FlagSet) {}

func (*parseCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
	args := f.Args()
	if len(args) == 0 {
		log.Print("A file name is required")
		return subcommands.ExitUsageError
	}

	romfile := args[0]
	buf, err := ioutil.ReadFile(romfile)
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}

	flash, err := uefi.Parse(buf)
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}
	errlist := flash.Validate()
	for _, err := range errlist {
		log.Printf("Error found: %v\n", err.Error())
	}
	if len(errlist) > 0 {
		return subcommands.ExitFailure
	}

	b, err := json.MarshalIndent(flash, "", "    ")
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}
	fmt.Println(string(b))
	return subcommands.ExitSuccess
}

// Extract subcommand
type extractCmd struct {
	force bool
}

func (*extractCmd) Name() string {
	return "extract"
}

func (*extractCmd) Synopsis() string {
	return "Extract rom file and print JSON summary to stdout"
}

func (*extractCmd) Usage() string {
	return "extract <path-to-rom-file> <directory-to-extract-into>\n"
}

func (e *extractCmd) SetFlags(f *flag.FlagSet) {
	f.BoolVar(&e.force, "force", false, "force extract to non empty directory")
}

func (e *extractCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
	args := f.Args()
	if len(args) < 2 {
		log.Print(e.Usage())
		return subcommands.ExitUsageError
	}

	romfile := args[0]
	buf, err := ioutil.ReadFile(romfile)
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}

	flash, err := uefi.Parse(buf)
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}
	errlist := flash.Validate()
	for _, err := range errlist {
		log.Printf("Error found: %v\n", err.Error())
	}
	if len(errlist) > 0 {
		return subcommands.ExitFailure
	}

	if !e.force {
		// check that directory doesn't exist or is empty
		files, err := ioutil.ReadDir(args[1])
		if err == nil {
			if len(files) != 0 {
				log.Print("Existing directory not empty, use --force to override")
				return subcommands.ExitFailure
			}
		} else if !os.IsNotExist(err) {
			// error was not EEXIST, we don't know what went wrong.
			log.Print(err)
			return subcommands.ExitFailure
		}
	}

	err = flash.Extract(args[1])
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}
	return subcommands.ExitSuccess
}

// Assemble subcommand
type assembleCmd struct {
}

func (*assembleCmd) Name() string {
	return "assemble"
}

func (*assembleCmd) Synopsis() string {
	return "Assemble rom file from directory tree."
}

func (*assembleCmd) Usage() string {
	return "assemble <directory-to-assemble-from> <newromfile>\n"
}

func (*assembleCmd) SetFlags(_ *flag.FlagSet) {}

func (a *assembleCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
	args := f.Args()
	if len(args) < 2 {
		log.Print(a.Usage())
		return subcommands.ExitUsageError
	}

	dir := args[0]
	jsonFile := filepath.Join(dir, "summary.json")
	jsonbuf, err := ioutil.ReadFile(jsonFile)
	var flash uefi.FlashImage
	if err := json.Unmarshal(jsonbuf, &flash); err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}

	buf, err := flash.Assemble()
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}
	romfile := args[1]
	err = ioutil.WriteFile(romfile, buf, 0644)
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}

	return subcommands.ExitSuccess
}

func main() {
	subcommands.Register(subcommands.HelpCommand(), "")
	subcommands.Register(subcommands.FlagsCommand(), "")
	subcommands.Register(subcommands.CommandsCommand(), "")
	subcommands.Register(&parseCmd{}, "")
	subcommands.Register(&extractCmd{}, "")
	subcommands.Register(&assembleCmd{}, "")
	flag.Parse()

	ctx := context.Background()
	os.Exit(int(subcommands.Execute(ctx)))
}
<commit_msg>Add warn flag for validate (#32)<commit_after>package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"github.com/google/subcommands"
	"github.com/linuxboot/fiano/uefi"
)

// Parse subcommand
type parseCmd struct {
	warn bool
}

func (*parseCmd) Name() string {
	return "parse"
}

func (*parseCmd) Synopsis() string {
	return "Parse rom file and print JSON summary to stdout"
}

func (*parseCmd) Usage() string {
	return "parse <path-to-rom-file>\n"
}

func (p *parseCmd) SetFlags(f *flag.FlagSet) {
	f.BoolVar(&p.warn, "warn", false, "warn instead of fail on validation errors")
}

func (p *parseCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
	args := f.Args()
	if len(args) == 0 {
		log.Print("A file name is required")
		return subcommands.ExitUsageError
	}

	romfile := args[0]
	buf, err := ioutil.ReadFile(romfile)
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}

	flash, err := uefi.Parse(buf)
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}
	errlist := flash.Validate()
	for _, err := range errlist {
		log.Printf("Error found: %v\n", err.Error())
	}
	errlen := len(errlist)
	if !p.warn && errlen > 0 {
		return subcommands.ExitFailure
	}

	b, err := json.MarshalIndent(flash, "", "    ")
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}
	fmt.Println(string(b))
	if errlen > 0 {
		return subcommands.ExitFailure
	}
	return subcommands.ExitSuccess
}

// Extract subcommand
type extractCmd struct {
	force bool
	warn  bool
}

func (*extractCmd) Name() string {
	return "extract"
}

func (*extractCmd) Synopsis() string {
	return "Extract rom file and print JSON summary to stdout"
}

func (*extractCmd) Usage() string {
	return "extract <path-to-rom-file> <directory-to-extract-into>\n"
}

func (e *extractCmd) SetFlags(f *flag.FlagSet) {
	f.BoolVar(&e.force, "force", false, "force extract to non empty directory")
	f.BoolVar(&e.warn, "warn", false, "warn instead of fail on validation errors")
}

func (e *extractCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
	args := f.Args()
	if len(args) < 2 {
		log.Print(e.Usage())
		return subcommands.ExitUsageError
	}

	romfile := args[0]
	buf, err := ioutil.ReadFile(romfile)
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}

	flash, err := uefi.Parse(buf)
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}
	errlist := flash.Validate()
	for _, err := range errlist {
		log.Printf("Error found: %v\n", err.Error())
	}
	errlen := len(errlist)
	if !e.warn && errlen > 0 {
		return subcommands.ExitFailure
	}

	if !e.force {
		// check that directory doesn't exist or is empty
		files, err := ioutil.ReadDir(args[1])
		if err == nil {
			if len(files) != 0 {
				log.Print("Existing directory not empty, use --force to override")
				return subcommands.ExitFailure
			}
		} else if !os.IsNotExist(err) {
			// error was not EEXIST, we don't know what went wrong.
			log.Print(err)
			return subcommands.ExitFailure
		}
	}

	err = flash.Extract(args[1])
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}
	if errlen > 0 {
		// Return failure even if warn is set.
		return subcommands.ExitFailure
	}
	return subcommands.ExitSuccess
}

// Assemble subcommand
type assembleCmd struct {
}

func (*assembleCmd) Name() string {
	return "assemble"
}

func (*assembleCmd) Synopsis() string {
	return "Assemble rom file from directory tree."
}

func (*assembleCmd) Usage() string {
	return "assemble <directory-to-assemble-from> <newromfile>\n"
}

func (*assembleCmd) SetFlags(_ *flag.FlagSet) {}

func (a *assembleCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
	args := f.Args()
	if len(args) < 2 {
		log.Print(a.Usage())
		return subcommands.ExitUsageError
	}

	dir := args[0]
	jsonFile := filepath.Join(dir, "summary.json")
	jsonbuf, err := ioutil.ReadFile(jsonFile)
	var flash uefi.FlashImage
	if err := json.Unmarshal(jsonbuf, &flash); err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}

	buf, err := flash.Assemble()
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}
	romfile := args[1]
	err = ioutil.WriteFile(romfile, buf, 0644)
	if err != nil {
		log.Print(err)
		return subcommands.ExitFailure
	}

	return subcommands.ExitSuccess
}

func main() {
	subcommands.Register(subcommands.HelpCommand(), "")
	subcommands.Register(subcommands.FlagsCommand(), "")
	subcommands.Register(subcommands.CommandsCommand(), "")
	subcommands.Register(&parseCmd{}, "")
	subcommands.Register(&extractCmd{}, "")
	subcommands.Register(&assembleCmd{}, "")
	flag.Parse()

	ctx := context.Background()
	os.Exit(int(subcommands.Execute(ctx)))
}
<|endoftext|>


<commit_before>package network

import (
	"github.com/Nekitosss/authorization/network/controller/structures"
	"encoding/json"
	"io"
	"net/http"
	"time"

	"github.com/gorilla/mux"
	"github.com/satori/go.uuid"
)

type serverResponse map[string]interface{}

func AuthVerifiedUser(writer http.ResponseWriter, request *http.Request) {

	var params structures.AuthInfo

	err := json.NewDecoder(request.Body).Decode(&params)

	if err != nil && err != io.EOF {
		setErrorResult(writer, err)
		return
	}

	session, err := executor.AuthUser(params)

	if err != nil {
		setErrorResult(writer, err)

	} else {
		expiration := time.Now().AddDate(10, 0, 0)
		cookie := http.Cookie{Name: "session", Value: session.SessionID.String(), Expires: expiration}
		http.SetCookie(writer, &cookie)

		var result = serverResponse{"userID" : session.UserModelID.String()}
		json.NewEncoder(writer).Encode(result)
	}
}

func VerifyRegistration(w http.ResponseWriter, r *http.Request) {

	var registrationIDString = mux.Vars(r)["id"]

	var registrationID, err = uuid.FromString(registrationIDString)

	if err != nil {
		setErrorResult(w, err)
		return
	}

	err = executor.VerifyRegister(registrationID)

	if err != nil {
		setErrorResult(w, err)
		return
	}

	http.Redirect(w, r, "http://pikabu.ru", 301)
}

func Login(writer http.ResponseWriter, request *http.Request) {

	var params structures.LoginInfo

	err := json.NewDecoder(request.Body).Decode(&params)

	if err != nil && err != io.EOF {
		setErrorResult(writer, err)
		return
	}

	registrationID, err := executor.Login(params)

	if err != nil {
		setErrorResult(writer, err)

	} else {
		result := serverResponse{"registrationID": registrationID.String()}
		json.NewEncoder(writer).Encode(result)
	}
}

func ValidateSession(writer http.ResponseWriter, request *http.Request) {

	var info structures.ValidateSessionInfo
	err := json.NewDecoder(request.Body).Decode(&info)

	if err != nil {
		setErrorResult(writer, err)
		return
	}

	userID, err := executor.ValidateSession(info)

	if err != nil {
		setErrorResult(writer, err)
		return
	}

	var result = serverResponse{"userID": userID.String()}
	json.NewEncoder(writer).Encode(&result)
}

func sendSimpleSuccess(w http.ResponseWriter) {
	result := serverResponse{"success": true}

	json.NewEncoder(w).Encode(result)
}
<commit_msg>new redirect url<commit_after>package network

import (
	"github.com/Nekitosss/authorization/network/controller/structures"
	"encoding/json"
	"io"
	"net/http"
	"time"

	"github.com/gorilla/mux"
	"github.com/satori/go.uuid"
)

type serverResponse map[string]interface{}

func AuthVerifiedUser(writer http.ResponseWriter, request *http.Request) {

	var params structures.AuthInfo

	err := json.NewDecoder(request.Body).Decode(&params)

	if err != nil && err != io.EOF {
		setErrorResult(writer, err)
		return
	}

	session, err := executor.AuthUser(params)

	if err != nil {
		setErrorResult(writer, err)

	} else {
		expiration := time.Now().AddDate(10, 0, 0)
		cookie := http.Cookie{Name: "session", Value: session.SessionID.String(), Expires: expiration}
		http.SetCookie(writer, &cookie)

		var result = serverResponse{"userID" : session.UserModelID.String()}
		json.NewEncoder(writer).Encode(result)
	}
}

func VerifyRegistration(w http.ResponseWriter, r *http.Request) {

	var registrationIDString = mux.Vars(r)["id"]

	var registrationID, err = uuid.FromString(registrationIDString)

	if err != nil {
		setErrorResult(w, err)
		return
	}

	err = executor.VerifyRegister(registrationID)

	if err != nil {
		setErrorResult(w, err)
		return
	}

	http.Redirect(w, r, "fooddly://authorization", 301)
}

func Login(writer http.ResponseWriter, request *http.Request) {

	var params structures.LoginInfo

	err := json.NewDecoder(request.Body).Decode(&params)

	if err != nil && err != io.EOF {
		setErrorResult(writer, err)
		return
	}

	registrationID, err := executor.Login(params)

	if err != nil {
		setErrorResult(writer, err)

	} else {
		result := serverResponse{"registrationID": registrationID.String()}
		json.NewEncoder(writer).Encode(result)
	}
}

func ValidateSession(writer http.ResponseWriter, request *http.Request) {

	var info structures.ValidateSessionInfo
	err := json.NewDecoder(request.Body).Decode(&info)

	if err != nil {
		setErrorResult(writer, err)
		return
	}

	userID, err := executor.ValidateSession(info)

	if err != nil {
		setErrorResult(writer, err)
		return
	}

	var result = serverResponse{"userID": userID.String()}
	json.NewEncoder(writer).Encode(&result)
}

func sendSimpleSuccess(w http.ResponseWriter) {
	result := serverResponse{"success": true}

	json.NewEncoder(w).Encode(result)
}
<|endoftext|>


<commit_before>// +build windows

package ole

import "unsafe"

func NewVariant(vt VT, val int64) VARIANT {
	return VARIANT{VT: vt, Val: val}
}

func (v *VARIANT) ToIUnknown() *IUnknown {
	if v.VT != VT_UNKNOWN {
		return nil
	}
	return (*IUnknown)(unsafe.Pointer(uintptr(v.Val)))
}

func (v *VARIANT) ToIDispatch() *IDispatch {
	if v.VT != VT_DISPATCH {
		return nil
	}
	return (*IDispatch)(unsafe.Pointer(uintptr(v.Val)))
}

func (v *VARIANT) ToArray() *SafeArrayConversion {
	if v.VT != VT_SAFEARRAY {
		return nil
	}
	var safeArray *SafeArray = (*SafeArray)(unsafe.Pointer(uintptr(v.Val)))
	return &SafeArrayConversion{safeArray}
}

func (v *VARIANT) ToString() string {
	if v.VT != VT_BSTR {
		return ""
	}
	return BstrToString(*(**uint16)(unsafe.Pointer(&v.Val)))
}

func (v *VARIANT) Clear() error {
	return VariantClear(v)
}

// Returns v's value based on its VALTYPE.
// Currently supported types: 2- and 4-byte integers, strings, bools.
// Note that 64-bit integers, datetimes, and other types are stored as strings
// and will be returned as strings.
func (v *VARIANT) Value() interface{} {
	switch v.VT {
	case VT_I2, VT_I4:
		return v.Val
	case VT_BSTR:
		return v.ToString()
	case VT_BOOL:
		return v.Val != 0
	}
	return nil
}
<commit_msg>Add some type conversion for Value()<commit_after>// +build windows

package ole

import "unsafe"

func NewVariant(vt VT, val int64) VARIANT {
	return VARIANT{VT: vt, Val: val}
}

func (v *VARIANT) ToIUnknown() *IUnknown {
	if v.VT != VT_UNKNOWN {
		return nil
	}
	return (*IUnknown)(unsafe.Pointer(uintptr(v.Val)))
}

func (v *VARIANT) ToIDispatch() *IDispatch {
	if v.VT != VT_DISPATCH {
		return nil
	}
	return (*IDispatch)(unsafe.Pointer(uintptr(v.Val)))
}

func (v *VARIANT) ToArray() *SafeArrayConversion {
	if v.VT != VT_SAFEARRAY {
		return nil
	}
	var safeArray *SafeArray = (*SafeArray)(unsafe.Pointer(uintptr(v.Val)))
	return &SafeArrayConversion{safeArray}
}

func (v *VARIANT) ToString() string {
	if v.VT != VT_BSTR {
		return ""
	}
	return BstrToString(*(**uint16)(unsafe.Pointer(&v.Val)))
}

func (v *VARIANT) Clear() error {
	return VariantClear(v)
}

// Returns v's value based on its VALTYPE.
// Currently supported types: 2- and 4-byte integers, strings, bools.
// Note that 64-bit integers, datetimes, and other types are stored as strings
// and will be returned as strings.
func (v *VARIANT) Value() interface{} {
	switch v.VT {
	case VT_I1:
		return int8(v.Val)
	case VT_UI1:
		return uint8(v.Val)
	case VT_I2:
		return int16(v.Val)
	case VT_UI2:
		return uint16(v.Val)
	case VT_I4:
		return int32(v.Val)
	case VT_UINT:
		return uint32(v.Val)
	case VT_INT_PTR:
		return uintptr(v.Val) // TODO
	case VT_UINT_PTR:
		return uintptr(v.Val)
	case VT_UI4:
		return uint32(v.Val)
	case VT_I8:
		return int64(v.Val)
	case VT_UI8:
		return uint64(v.Val)
	case VT_R4:
		return float32(v.Val)
	case VT_R8:
		return float64(v.Val)
	case VT_BSTR:
		return v.ToString()
	//case VT_DATE:
	//	return v.ToIDispatch() // TODO: use VariantTimeToSystemTime
	case VT_UNKNOWN:
		return v.ToIUnknown()
	case VT_DISPATCH:
		return v.ToIDispatch()
	case VT_BOOL:
		return v.Val != 0
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"testing"
)

func TestEnvDiff(t *testing.T) {
	diff := &EnvDiff{map[string]string{"FOO": "bar"}, map[string]string{"BAR": "baz"}}

	out := diff.Serialize()

	diff2, err := LoadEnvDiff(out)
	if err != nil {
		t.Errorf("parse error", err)
	}

	if len(diff2.Prev) != 1 {
		t.Errorf("len(diff2.prev) != 1", len(diff2.Prev))
	}

	if len(diff2.Next) != 1 {
		t.Errorf("len(diff2.next) != 0", len(diff2.Next))
	}
}

func TestIgnoredEnv(t *testing.T) {
	if !IgnoredEnv(DIRENV_BASH) {
		t.Fail()
	}
	if IgnoredEnv(DIRENV_DIFF) {
		t.Fail()
	}
	if !IgnoredEnv("_") {
		t.Fail()
	}
	if !IgnoredEnv("__fish_foo") {
		t.Fail()
	}
	if !IgnoredEnv("__fishx") {
		t.Fail()
	}
}
<commit_msg>Add TestEnvDiffEmptyValue<commit_after>package main

import (
	"reflect"
	"testing"
)

func TestEnvDiff(t *testing.T) {
	diff := &EnvDiff{map[string]string{"FOO": "bar"}, map[string]string{"BAR": "baz"}}

	out := diff.Serialize()

	diff2, err := LoadEnvDiff(out)
	if err != nil {
		t.Errorf("parse error", err)
	}

	if len(diff2.Prev) != 1 {
		t.Errorf("len(diff2.prev) != 1", len(diff2.Prev))
	}

	if len(diff2.Next) != 1 {
		t.Errorf("len(diff2.next) != 0", len(diff2.Next))
	}
}

// Issue #114
// Check that empty environment variables correctly appear in the diff
func TestEnvDiffEmptyValue(t *testing.T) {
	before := Env{}
	after := Env{"FOO": ""}

	diff := BuildEnvDiff(before, after)

	if !reflect.DeepEqual(diff.Next, map[string]string(after)) {
		t.Errorf("diff.Next != after (%#+v != %#+v)", diff.Next, after)
	}
}

func TestIgnoredEnv(t *testing.T) {
	if !IgnoredEnv(DIRENV_BASH) {
		t.Fail()
	}
	if IgnoredEnv(DIRENV_DIFF) {
		t.Fail()
	}
	if !IgnoredEnv("_") {
		t.Fail()
	}
	if !IgnoredEnv("__fish_foo") {
		t.Fail()
	}
	if !IgnoredEnv("__fishx") {
		t.Fail()
	}
}
<|endoftext|>


<commit_before>package vcs

import (
	"fmt"
	"os"
	"path/filepath"
	"text/template"

	"github.com/hashicorp/errwrap"
)

var PostCheckoutTmpl = template.Must(template.New("name").Parse(`#!/bin/sh
# @todo handle checkout files endge case

sourceclock start
`))

var PrepCommitTmpl = template.Must(template.New("name").Parse(`#!/bin/sh
# @todo handle merge/rebase kind of commits

printf "$(cat $1) [$(sourceclock split)]" > "$1"
`))

var PostCommitTmpl = template.Must(template.New("name").Parse(`#!/bin/sh
# @todo handle merge/rebase kind of commits

sourceclock lap
`))

type Git struct {
	dir string
}

func NewGit(dir string) *Git {
	return &Git{
		dir: filepath.Join(dir, ".git"),
	}
}

func (g *Git) Name() string { return "git" }
func (g *Git) Supported() bool {
	fi, err := os.Stat(g.dir)
	if err != nil || !fi.IsDir() {
		return false
	}

	return true
}

func (g *Git) Hook() error {
	hpath := filepath.Join(g.dir, "hooks")

	//post checkout: start()
	postchf, err := os.Create(filepath.Join(hpath, "post-checkout"))
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to create post-checkout '%s': {{err}}", postchf.Name()), err)
	}

	err = postchf.Chmod(0766)
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to make post-checkout file '%s' executable: {{err}}", hpath), err)
	}

	err = PostCheckoutTmpl.Execute(postchf, struct{}{})
	if err != nil {
		return errwrap.Wrapf("Failed to run post-checkout template: {{err}}", err)
	}

	//prepare commit msg: split()
	prepcof, err := os.Create(filepath.Join(hpath, "prepare-commit-msg"))
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to create prepare-commit-msg  '%s': {{err}}", postchf.Name()), err)
	}

	err = prepcof.Chmod(0766)
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to make prepare-commit-msg file '%s' executable: {{err}}", hpath), err)
	}

	err = PrepCommitTmpl.Execute(prepcof, struct{}{})
	if err != nil {
		return errwrap.Wrapf("Failed to run post-commit template: {{err}}", err)
	}

	//post commit: lap()
	postcof, err := os.Create(filepath.Join(hpath, "post-commit"))
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to create post-commit  '%s': {{err}}", postchf.Name()), err)
	}

	err = postcof.Chmod(0766)
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to make post-commit file '%s' executable: {{err}}", hpath), err)
	}

	err = PostCommitTmpl.Execute(postcof, struct{}{})
	if err != nil {
		return errwrap.Wrapf("Failed to run post-commit template: {{err}}", err)
	}

	return nil
}
<commit_msg>only start on checkouts that involve branches [19m20s]<commit_after>package vcs

import (
	"fmt"
	"os"
	"path/filepath"
	"text/template"

	"github.com/hashicorp/errwrap"
)

var PostCheckoutTmpl = template.Must(template.New("name").Parse(`#!/bin/sh
# when checkout is a branch, start timer
if [ $3 -eq 1 ]; then
   sourceclock start;
fi
`))

var PrepCommitTmpl = template.Must(template.New("name").Parse(`#!/bin/sh
# @todo handle merge/rebase kind of commits

printf "$(cat $1) [$(sourceclock split)]" > "$1"
`))

var PostCommitTmpl = template.Must(template.New("name").Parse(`#!/bin/sh
# @todo handle merge/rebase kind of commits

sourceclock lap
`))

type Git struct {
	dir string
}

func NewGit(dir string) *Git {
	return &Git{
		dir: filepath.Join(dir, ".git"),
	}
}

func (g *Git) Name() string { return "git" }
func (g *Git) Supported() bool {
	fi, err := os.Stat(g.dir)
	if err != nil || !fi.IsDir() {
		return false
	}

	return true
}

func (g *Git) Hook() error {
	hpath := filepath.Join(g.dir, "hooks")

	//post checkout: start()
	postchf, err := os.Create(filepath.Join(hpath, "post-checkout"))
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to create post-checkout '%s': {{err}}", postchf.Name()), err)
	}

	err = postchf.Chmod(0766)
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to make post-checkout file '%s' executable: {{err}}", hpath), err)
	}

	err = PostCheckoutTmpl.Execute(postchf, struct{}{})
	if err != nil {
		return errwrap.Wrapf("Failed to run post-checkout template: {{err}}", err)
	}

	//prepare commit msg: split()
	prepcof, err := os.Create(filepath.Join(hpath, "prepare-commit-msg"))
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to create prepare-commit-msg  '%s': {{err}}", postchf.Name()), err)
	}

	err = prepcof.Chmod(0766)
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to make prepare-commit-msg file '%s' executable: {{err}}", hpath), err)
	}

	err = PrepCommitTmpl.Execute(prepcof, struct{}{})
	if err != nil {
		return errwrap.Wrapf("Failed to run post-commit template: {{err}}", err)
	}

	//post commit: lap()
	postcof, err := os.Create(filepath.Join(hpath, "post-commit"))
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to create post-commit  '%s': {{err}}", postchf.Name()), err)
	}

	err = postcof.Chmod(0766)
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to make post-commit file '%s' executable: {{err}}", hpath), err)
	}

	err = PostCommitTmpl.Execute(postcof, struct{}{})
	if err != nil {
		return errwrap.Wrapf("Failed to run post-commit template: {{err}}", err)
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"container/heap"
	"errors"
	"fmt"
)

type rod int

const (
	RodDigging rod = iota
	RodBlink
	RodTeleportOther
	RodLightningBolt
	RodFireball
	RodFog
	RodShatter
	// below unimplemented
	RodConfusingClouds
	RodFear
	RodFreezingClouds
)

func (r rod) Letter() rune {
	return '/'
}

func (r rod) Rare() bool {
	switch r {
	case RodDigging, RodTeleportOther, RodShatter:
		return true
	default:
		return false
	}
}

func (r rod) String() string {
	var text string
	switch r {
	case RodDigging:
		text = "rod of digging"
	case RodBlink:
		text = "rod of blinking"
	case RodTeleportOther:
		text = "rod of teleport other"
	case RodFog:
		text = "rod of fog"
	case RodFear:
		text = "rod of fear"
	case RodFireball:
		text = "rod of fireball"
	case RodLightningBolt:
		text = "rod of lightning bolt"
	case RodShatter:
		text = "rod of shatter"
	case RodFreezingClouds:
		text = "rod of freezing clouds"
	case RodConfusingClouds:
		text = "rod of confusing clouds"
	}
	return text
}

func (r rod) Desc() string {
	var text string
	switch r {
	case RodDigging:
		text = "digs through walls."
	case RodBlink:
		text = "makes you blink away within your line of sight."
	case RodTeleportOther:
		text = "teleports away one of your foes."
	case RodFog:
		text = "creates a dense fog that reduces your (and monster's) line of sight."
	case RodFireball:
		text = "throws a 1-radius fireball at your foes."
	case RodLightningBolt:
		text = "throws a lightning bolt through one or more ennemies."
	case RodShatter:
		text = "induces an explosion around a wall. The wall can disintegrate."
	case RodFear:
		text = "TODO"
	case RodFreezingClouds:
		text = "TODO"
	case RodConfusingClouds:
		text = "TODO"
	}
	return fmt.Sprintf("The %s %s", r, text)
}

type rodProps struct {
	Charge int
}

func (r rod) MaxCharge() (charges int) {
	switch r {
	case RodBlink:
		charges = 5
	case RodTeleportOther, RodDigging:
		charges = 3
	default:
		charges = 4
	}
	return charges
}

func (r rod) Rate() int {
	rate := r.MaxCharge() - 2
	if rate < 1 {
		rate = 1
	}
	return rate
}

func (r rod) MPCost() (mp int) {
	switch r {
	case RodBlink:
		mp = 3
	case RodTeleportOther, RodDigging, RodShatter:
		mp = 5
	default:
		mp = 4
	}
	return mp
}

func (r rod) Use(g *game, ev event) error {
	rods := g.Player.Rods
	if rods[r].Charge <= 0 {
		return errors.New("No charges remaining on this rod.")
	}
	if r.MPCost() > g.Player.MP {
		return errors.New("Not enough magic points for using this rod.")
	}
	var err error
	switch r {
	case RodBlink:
		err = g.EvokeRodBlink(ev)
	case RodTeleportOther:
		err = g.EvokeRodTeleportOther(ev)
	case RodLightningBolt:
		err = g.EvokeRodLightningBolt(ev)
	case RodFireball:
		err = g.EvokeRodFireball(ev)
	case RodFog:
		err = g.EvokeRodFog(ev)
	case RodDigging:
		err = g.EvokeRodDigging(ev)
	case RodShatter:
		err = g.EvokeRodShatter(ev)
	}

	if err != nil {
		return err
	}
	rods[r].Charge--
	g.Player.MP -= r.MPCost()
	g.FairAction()
	ev.Renew(g, 5)
	return nil
}

func (g *game) EvokeRodBlink(ev event) error {
	if g.Player.HasStatus(StatusLignification) {
		return errors.New("You cannot blink while lignified.")
	}
	losPos := []position{}
	for pos, b := range g.Player.LOS {
		if !b {
			continue
		}
		if g.Dungeon.Cell(pos).T != FreeCell {
			continue
		}
		mons, _ := g.MonsterAt(pos)
		if mons.Exists() {
			continue
		}
		losPos = append(losPos, pos)
	}
	if len(losPos) == 0 {
		return errors.New("Something went wrong with the blinking.")
	}
	npos := losPos[RandInt(len(losPos))]
	if npos.Distance(g.Player.Pos) <= 3 {
		// Give close cells less chance to make blinking more useful
		npos = losPos[RandInt(len(losPos))]
	}
	g.Player.Pos = npos
	g.Print("You blink away.")
	g.ComputeLOS()
	g.MakeMonstersAware()
	return nil
}

func (g *game) EvokeRodTeleportOther(ev event) error {
	if !g.ui.ChooseTarget(g, &chooser{}) {
		return errors.New("Ok, then.")
	}
	mons, _ := g.MonsterAt(g.Player.Target)
	if mons == nil {
		// should not happen (done in the targeter)
		return errors.New("You must target a monster for using this rod.")
	}
	pos := mons.Pos
	i := 0
	count := 0
	for {
		count++
		if count > 1000 {
			panic("TeleportOther")
		}
		pos = g.FreeCell()
		if pos.Distance(mons.Pos) < 15 && i < 1000 {
			i++
			continue
		}
		break
	}

	switch mons.State {
	case Hunting:
		mons.State = Wandering
		// TODO: change the target?
	case Resting, Wandering:
		mons.State = Wandering
		mons.Target = mons.Pos
	}
	mons.Pos = pos
	g.Printf("The %s teleports away.", mons.Kind)
	return nil
}

func (g *game) EvokeRodLightningBolt(ev event) error {
	if !g.ui.ChooseTarget(g, &chooser{}) {
		return errors.New("Ok, then.")
	}
	ray := g.Ray(g.Player.Target)
	g.Print("A lightning bolt emerges straight from the rod.")
	for _, pos := range ray {
		mons, _ := g.MonsterAt(pos)
		if mons == nil {
			continue
		}
		mons.HP -= RandInt(21)
		if mons.HP <= 0 {
			g.Printf("A %s is killed by the bolt.", mons.Kind)
			g.Killed++
		}
		g.MakeNoise(12, mons.Pos)
		mons.MakeHuntIfHurt(g)
	}
	return nil
}

func (g *game) EvokeRodFireball(ev event) error {
	if !g.ui.ChooseTarget(g, &chooser{area: true, minDist: true}) {
		return errors.New("Ok, then.")
	}
	neighbors := g.Dungeon.FreeNeighbors(g.Player.Target)
	g.Print("A fireball emerges straight from the rod.")
	for _, pos := range append(neighbors, g.Player.Target) {
		mons, _ := g.MonsterAt(pos)
		if mons == nil {
			continue
		}
		mons.HP -= RandInt(21)
		if mons.HP <= 0 {
			g.Printf("A %s is killed by the fireball.", mons.Kind)
			g.Killed++
		}
		g.MakeNoise(12, mons.Pos)
		mons.MakeHuntIfHurt(g)
	}
	return nil
}

type cloud int

const (
	CloudFog cloud = iota
)

func (g *game) EvokeRodFog(ev event) error {
	dij := &normalPath{game: g}
	nm := Dijkstra(dij, []position{g.Player.Pos}, 3)
	for pos := range nm {
		_, ok := g.Clouds[pos]
		if !ok {
			g.Clouds[pos] = CloudFog
			heap.Push(g.Events, &cloudEvent{ERank: ev.Rank() + 100 + RandInt(100), EAction: CloudEnd, Pos: pos})
		}
	}
	g.ComputeLOS()
	g.Print("You are surrounded by a dense fog.")
	return nil
}

func (g *game) EvokeRodDigging(ev event) error {
	if !g.ui.ChooseTarget(g, &wallChooser{}) {
		return errors.New("Ok, then.")
	}
	pos := g.Player.Target
	for i := 0; i < 3; i++ {
		g.Dungeon.SetCell(pos, FreeCell)
		g.MakeNoise(17, pos)
		pos = pos.To(pos.Dir(g.Player.Pos))
		if !g.Player.LOS[pos] {
			g.UnknownDig[pos] = true
		}
		if !g.Dungeon.Valid(pos) || g.Dungeon.Cell(pos).T != WallCell {
			break
		}
	}
	g.Print("You see the wall disintegrate with a crash.")
	g.ComputeLOS()
	g.MakeMonstersAware()
	return nil
}

func (g *game) EvokeRodShatter(ev event) error {
	if !g.ui.ChooseTarget(g, &wallChooser{minDist: true}) {
		return errors.New("Ok, then.")
	}
	neighbors := g.Dungeon.FreeNeighbors(g.Player.Target)
	if RandInt(2) == 0 {
		g.Dungeon.SetCell(g.Player.Target, FreeCell)
		g.ComputeLOS()
		g.MakeMonstersAware()
		g.MakeNoise(19, g.Player.Target)
		g.Print("You see the wall disappear in a noisy explosion.")
	} else {
		g.MakeNoise(15, g.Player.Target)
		g.Print("You see an explosion around the wall.")
	}
	for _, pos := range neighbors {
		mons, _ := g.MonsterAt(pos)
		if mons == nil {
			continue
		}
		mons.HP -= RandInt(30)
		if mons.HP <= 0 {
			g.Printf("A %s is killed by the explosion.", mons.Kind)
			g.Killed++
		}
		g.MakeNoise(12, mons.Pos)
		mons.MakeHuntIfHurt(g)
	}
	return nil
}

func (g *game) GeneratedRodsCount() int {
	count := 0
	for _, b := range g.GeneratedRods {
		if b {
			count++
		}
	}
	return count
}

func (g *game) GenerateRod() {
	count := 0
	for {
		count++
		if count > 1000 {
			panic("GenerateRod")
		}
		pos := g.FreeCellForStatic()
		r := rod(RandInt(int(RodShatter) + 1))
		if r.Rare() {
			r = rod(RandInt(int(RodShatter) + 1))
		}
		if g.Player.Rods[r] == nil && !g.GeneratedRods[r] {
			g.GeneratedRods[r] = true
			g.Rods[pos] = r
			return
		}
	}
}
<commit_msg>make rod use take a little more time<commit_after>package main

import (
	"container/heap"
	"errors"
	"fmt"
)

type rod int

const (
	RodDigging rod = iota
	RodBlink
	RodTeleportOther
	RodLightningBolt
	RodFireball
	RodFog
	RodShatter
	// below unimplemented
	RodConfusingClouds
	RodFear
	RodFreezingClouds
)

func (r rod) Letter() rune {
	return '/'
}

func (r rod) Rare() bool {
	switch r {
	case RodDigging, RodTeleportOther, RodShatter:
		return true
	default:
		return false
	}
}

func (r rod) String() string {
	var text string
	switch r {
	case RodDigging:
		text = "rod of digging"
	case RodBlink:
		text = "rod of blinking"
	case RodTeleportOther:
		text = "rod of teleport other"
	case RodFog:
		text = "rod of fog"
	case RodFear:
		text = "rod of fear"
	case RodFireball:
		text = "rod of fireball"
	case RodLightningBolt:
		text = "rod of lightning bolt"
	case RodShatter:
		text = "rod of shatter"
	case RodFreezingClouds:
		text = "rod of freezing clouds"
	case RodConfusingClouds:
		text = "rod of confusing clouds"
	}
	return text
}

func (r rod) Desc() string {
	var text string
	switch r {
	case RodDigging:
		text = "digs through walls."
	case RodBlink:
		text = "makes you blink away within your line of sight."
	case RodTeleportOther:
		text = "teleports away one of your foes."
	case RodFog:
		text = "creates a dense fog that reduces your (and monster's) line of sight."
	case RodFireball:
		text = "throws a 1-radius fireball at your foes."
	case RodLightningBolt:
		text = "throws a lightning bolt through one or more ennemies."
	case RodShatter:
		text = "induces an explosion around a wall. The wall can disintegrate."
	case RodFear:
		text = "TODO"
	case RodFreezingClouds:
		text = "TODO"
	case RodConfusingClouds:
		text = "TODO"
	}
	return fmt.Sprintf("The %s %s", r, text)
}

type rodProps struct {
	Charge int
}

func (r rod) MaxCharge() (charges int) {
	switch r {
	case RodBlink:
		charges = 5
	case RodTeleportOther, RodDigging:
		charges = 3
	default:
		charges = 4
	}
	return charges
}

func (r rod) Rate() int {
	rate := r.MaxCharge() - 2
	if rate < 1 {
		rate = 1
	}
	return rate
}

func (r rod) MPCost() (mp int) {
	switch r {
	case RodBlink:
		mp = 3
	case RodTeleportOther, RodDigging, RodShatter:
		mp = 5
	default:
		mp = 4
	}
	return mp
}

func (r rod) Use(g *game, ev event) error {
	rods := g.Player.Rods
	if rods[r].Charge <= 0 {
		return errors.New("No charges remaining on this rod.")
	}
	if r.MPCost() > g.Player.MP {
		return errors.New("Not enough magic points for using this rod.")
	}
	var err error
	switch r {
	case RodBlink:
		err = g.EvokeRodBlink(ev)
	case RodTeleportOther:
		err = g.EvokeRodTeleportOther(ev)
	case RodLightningBolt:
		err = g.EvokeRodLightningBolt(ev)
	case RodFireball:
		err = g.EvokeRodFireball(ev)
	case RodFog:
		err = g.EvokeRodFog(ev)
	case RodDigging:
		err = g.EvokeRodDigging(ev)
	case RodShatter:
		err = g.EvokeRodShatter(ev)
	}

	if err != nil {
		return err
	}
	rods[r].Charge--
	g.Player.MP -= r.MPCost()
	g.FairAction()
	ev.Renew(g, 7)
	return nil
}

func (g *game) EvokeRodBlink(ev event) error {
	if g.Player.HasStatus(StatusLignification) {
		return errors.New("You cannot blink while lignified.")
	}
	losPos := []position{}
	for pos, b := range g.Player.LOS {
		if !b {
			continue
		}
		if g.Dungeon.Cell(pos).T != FreeCell {
			continue
		}
		mons, _ := g.MonsterAt(pos)
		if mons.Exists() {
			continue
		}
		losPos = append(losPos, pos)
	}
	if len(losPos) == 0 {
		return errors.New("Something went wrong with the blinking.")
	}
	npos := losPos[RandInt(len(losPos))]
	if npos.Distance(g.Player.Pos) <= 3 {
		// Give close cells less chance to make blinking more useful
		npos = losPos[RandInt(len(losPos))]
	}
	g.Player.Pos = npos
	g.Print("You blink away.")
	g.ComputeLOS()
	g.MakeMonstersAware()
	return nil
}

func (g *game) EvokeRodTeleportOther(ev event) error {
	if !g.ui.ChooseTarget(g, &chooser{}) {
		return errors.New("Ok, then.")
	}
	mons, _ := g.MonsterAt(g.Player.Target)
	if mons == nil {
		// should not happen (done in the targeter)
		return errors.New("You must target a monster for using this rod.")
	}
	pos := mons.Pos
	i := 0
	count := 0
	for {
		count++
		if count > 1000 {
			panic("TeleportOther")
		}
		pos = g.FreeCell()
		if pos.Distance(mons.Pos) < 15 && i < 1000 {
			i++
			continue
		}
		break
	}

	switch mons.State {
	case Hunting:
		mons.State = Wandering
		// TODO: change the target?
	case Resting, Wandering:
		mons.State = Wandering
		mons.Target = mons.Pos
	}
	mons.Pos = pos
	g.Printf("The %s teleports away.", mons.Kind)
	return nil
}

func (g *game) EvokeRodLightningBolt(ev event) error {
	if !g.ui.ChooseTarget(g, &chooser{}) {
		return errors.New("Ok, then.")
	}
	ray := g.Ray(g.Player.Target)
	g.Print("A lightning bolt emerges straight from the rod.")
	for _, pos := range ray {
		mons, _ := g.MonsterAt(pos)
		if mons == nil {
			continue
		}
		mons.HP -= RandInt(21)
		if mons.HP <= 0 {
			g.Printf("A %s is killed by the bolt.", mons.Kind)
			g.Killed++
		}
		g.MakeNoise(12, mons.Pos)
		mons.MakeHuntIfHurt(g)
	}
	return nil
}

func (g *game) EvokeRodFireball(ev event) error {
	if !g.ui.ChooseTarget(g, &chooser{area: true, minDist: true}) {
		return errors.New("Ok, then.")
	}
	neighbors := g.Dungeon.FreeNeighbors(g.Player.Target)
	g.Print("A fireball emerges straight from the rod.")
	for _, pos := range append(neighbors, g.Player.Target) {
		mons, _ := g.MonsterAt(pos)
		if mons == nil {
			continue
		}
		mons.HP -= RandInt(21)
		if mons.HP <= 0 {
			g.Printf("A %s is killed by the fireball.", mons.Kind)
			g.Killed++
		}
		g.MakeNoise(12, mons.Pos)
		mons.MakeHuntIfHurt(g)
	}
	return nil
}

type cloud int

const (
	CloudFog cloud = iota
)

func (g *game) EvokeRodFog(ev event) error {
	dij := &normalPath{game: g}
	nm := Dijkstra(dij, []position{g.Player.Pos}, 3)
	for pos := range nm {
		_, ok := g.Clouds[pos]
		if !ok {
			g.Clouds[pos] = CloudFog
			heap.Push(g.Events, &cloudEvent{ERank: ev.Rank() + 100 + RandInt(100), EAction: CloudEnd, Pos: pos})
		}
	}
	g.ComputeLOS()
	g.Print("You are surrounded by a dense fog.")
	return nil
}

func (g *game) EvokeRodDigging(ev event) error {
	if !g.ui.ChooseTarget(g, &wallChooser{}) {
		return errors.New("Ok, then.")
	}
	pos := g.Player.Target
	for i := 0; i < 3; i++ {
		g.Dungeon.SetCell(pos, FreeCell)
		g.MakeNoise(17, pos)
		pos = pos.To(pos.Dir(g.Player.Pos))
		if !g.Player.LOS[pos] {
			g.UnknownDig[pos] = true
		}
		if !g.Dungeon.Valid(pos) || g.Dungeon.Cell(pos).T != WallCell {
			break
		}
	}
	g.Print("You see the wall disintegrate with a crash.")
	g.ComputeLOS()
	g.MakeMonstersAware()
	return nil
}

func (g *game) EvokeRodShatter(ev event) error {
	if !g.ui.ChooseTarget(g, &wallChooser{minDist: true}) {
		return errors.New("Ok, then.")
	}
	neighbors := g.Dungeon.FreeNeighbors(g.Player.Target)
	if RandInt(2) == 0 {
		g.Dungeon.SetCell(g.Player.Target, FreeCell)
		g.ComputeLOS()
		g.MakeMonstersAware()
		g.MakeNoise(19, g.Player.Target)
		g.Print("You see the wall disappear in a noisy explosion.")
	} else {
		g.MakeNoise(15, g.Player.Target)
		g.Print("You see an explosion around the wall.")
	}
	for _, pos := range neighbors {
		mons, _ := g.MonsterAt(pos)
		if mons == nil {
			continue
		}
		mons.HP -= RandInt(30)
		if mons.HP <= 0 {
			g.Printf("A %s is killed by the explosion.", mons.Kind)
			g.Killed++
		}
		g.MakeNoise(12, mons.Pos)
		mons.MakeHuntIfHurt(g)
	}
	return nil
}

func (g *game) GeneratedRodsCount() int {
	count := 0
	for _, b := range g.GeneratedRods {
		if b {
			count++
		}
	}
	return count
}

func (g *game) GenerateRod() {
	count := 0
	for {
		count++
		if count > 1000 {
			panic("GenerateRod")
		}
		pos := g.FreeCellForStatic()
		r := rod(RandInt(int(RodShatter) + 1))
		if r.Rare() {
			r = rod(RandInt(int(RodShatter) + 1))
		}
		if g.Player.Rods[r] == nil && !g.GeneratedRods[r] {
			g.GeneratedRods[r] = true
			g.Rods[pos] = r
			return
		}
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package resourcequota

import (
	"sync"
	"time"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
	"github.com/golang/glog"
)

// ResourceQuotaManager is responsible for tracking quota usage status in the system
type ResourceQuotaManager struct {
	kubeClient client.Interface
	syncTime   <-chan time.Time

	// To allow injection of syncUsage for testing.
	syncHandler func(quota api.ResourceQuota) error
}

// NewResourceQuotaManager creates a new ResourceQuotaManager
func NewResourceQuotaManager(kubeClient client.Interface) *ResourceQuotaManager {

	rm := &ResourceQuotaManager{
		kubeClient: kubeClient,
	}

	// set the synchronization handler
	rm.syncHandler = rm.syncResourceQuota
	return rm
}

// Run begins watching and syncing.
func (rm *ResourceQuotaManager) Run(period time.Duration) {
	rm.syncTime = time.Tick(period)
	go util.Forever(func() { rm.synchronize() }, period)
}

func (rm *ResourceQuotaManager) synchronize() {
	var resourceQuotas []api.ResourceQuota
	list, err := rm.kubeClient.ResourceQuotas(api.NamespaceAll).List(labels.Everything())
	if err != nil {
		glog.Errorf("Synchronization error: %v (%#v)", err, err)
	}
	resourceQuotas = list.Items
	wg := sync.WaitGroup{}
	wg.Add(len(resourceQuotas))
	for ix := range resourceQuotas {
		go func(ix int) {
			defer wg.Done()
			glog.V(4).Infof("periodic sync of %v/%v", resourceQuotas[ix].Namespace, resourceQuotas[ix].Name)
			err := rm.syncHandler(resourceQuotas[ix])
			if err != nil {
				glog.Errorf("Error synchronizing: %v", err)
			}
		}(ix)
	}
	wg.Wait()
}

// FilterQuotaPods eliminates pods that no longer have a cost against the quota
// pods that have a restart policy of always are always returned
// pods that are in a failed state, but have a restart policy of on failure are always returned
// pods that are not in a success state or a failure state are included in quota
func FilterQuotaPods(pods []api.Pod) []*api.Pod {
	var result []*api.Pod
	for i := range pods {
		value := &pods[i]
		// a pod that has a restart policy always no matter its state counts against usage
		if value.Spec.RestartPolicy == api.RestartPolicyAlways {
			result = append(result, value)
			continue
		}
		// a failed pod with a restart policy of on failure will count against usage
		if api.PodFailed == value.Status.Phase &&
			value.Spec.RestartPolicy == api.RestartPolicyOnFailure {
			result = append(result, value)
			continue
		}
		// if the pod is not succeeded or failed, then we count it against quota
		if api.PodSucceeded != value.Status.Phase &&
			api.PodFailed != value.Status.Phase {
			result = append(result, value)
			continue
		}
	}
	return result
}

// syncResourceQuota runs a complete sync of current status
func (rm *ResourceQuotaManager) syncResourceQuota(quota api.ResourceQuota) (err error) {

	// quota is dirty if any part of spec hard limits differs from the status hard limits
	dirty := !api.Semantic.DeepEqual(quota.Spec.Hard, quota.Status.Hard)

	// dirty tracks if the usage status differs from the previous sync,
	// if so, we send a new usage with latest status
	// if this is our first sync, it will be dirty by default, since we need track usage
	dirty = dirty || (quota.Status.Hard == nil || quota.Status.Used == nil)

	// Create a usage object that is based on the quota resource version
	usage := api.ResourceQuota{
		ObjectMeta: api.ObjectMeta{
			Name:            quota.Name,
			Namespace:       quota.Namespace,
			ResourceVersion: quota.ResourceVersion,
			Labels:          quota.Labels,
			Annotations:     quota.Annotations},
		Status: api.ResourceQuotaStatus{
			Hard: api.ResourceList{},
			Used: api.ResourceList{},
		},
	}

	// set the hard values supported on the quota
	for k, v := range quota.Spec.Hard {
		usage.Status.Hard[k] = *v.Copy()
	}
	// set any last known observed status values for usage
	for k, v := range quota.Status.Used {
		usage.Status.Used[k] = *v.Copy()
	}

	set := map[api.ResourceName]bool{}
	for k := range usage.Status.Hard {
		set[k] = true
	}

	pods := &api.PodList{}
	if set[api.ResourcePods] || set[api.ResourceMemory] || set[api.ResourceCPU] {
		pods, err = rm.kubeClient.Pods(usage.Namespace).List(labels.Everything(), fields.Everything())
		if err != nil {
			return err
		}
	}

	filteredPods := FilterQuotaPods(pods.Items)

	// iterate over each resource, and update observation
	for k := range usage.Status.Hard {

		// look if there is a used value, if none, we are definitely dirty
		prevQuantity, found := usage.Status.Used[k]
		if !found {
			dirty = true
		}

		var value *resource.Quantity

		switch k {
		case api.ResourcePods:
			value = resource.NewQuantity(int64(len(filteredPods)), resource.DecimalSI)
		case api.ResourceMemory:
			val := int64(0)
			for _, pod := range filteredPods {
				val = val + PodMemory(pod).Value()
			}
			value = resource.NewQuantity(int64(val), resource.DecimalSI)
		case api.ResourceCPU:
			val := int64(0)
			for _, pod := range filteredPods {
				val = val + PodCPU(pod).MilliValue()
			}
			value = resource.NewMilliQuantity(int64(val), resource.DecimalSI)
		case api.ResourceServices:
			items, err := rm.kubeClient.Services(usage.Namespace).List(labels.Everything())
			if err != nil {
				return err
			}
			value = resource.NewQuantity(int64(len(items.Items)), resource.DecimalSI)
		case api.ResourceReplicationControllers:
			items, err := rm.kubeClient.ReplicationControllers(usage.Namespace).List(labels.Everything())
			if err != nil {
				return err
			}
			value = resource.NewQuantity(int64(len(items.Items)), resource.DecimalSI)
		case api.ResourceQuotas:
			items, err := rm.kubeClient.ResourceQuotas(usage.Namespace).List(labels.Everything())
			if err != nil {
				return err
			}
			value = resource.NewQuantity(int64(len(items.Items)), resource.DecimalSI)
		case api.ResourceSecrets:
			items, err := rm.kubeClient.Secrets(usage.Namespace).List(labels.Everything(), fields.Everything())
			if err != nil {
				return err
			}
			value = resource.NewQuantity(int64(len(items.Items)), resource.DecimalSI)
		case api.ResourcePersistentVolumeClaims:
			items, err := rm.kubeClient.PersistentVolumeClaims(usage.Namespace).List(labels.Everything(), fields.Everything())
			if err != nil {
				return err
			}
			value = resource.NewQuantity(int64(len(items.Items)), resource.DecimalSI)
		}

		// ignore fields we do not understand (assume another controller is tracking it)
		if value != nil {
			// see if the value has changed
			dirty = dirty || (value.Value() != prevQuantity.Value())
			// just update the value
			usage.Status.Used[k] = *value
		}
	}

	// update the usage only if it changed
	if dirty {
		_, err = rm.kubeClient.ResourceQuotas(usage.Namespace).UpdateStatus(&usage)
		return err
	}
	return nil
}

// PodCPU computes total cpu usage of a pod
func PodCPU(pod *api.Pod) *resource.Quantity {
	val := int64(0)
	for j := range pod.Spec.Containers {
		val = val + pod.Spec.Containers[j].Resources.Limits.Cpu().MilliValue()
	}
	return resource.NewMilliQuantity(int64(val), resource.DecimalSI)
}

// IsPodCPUUnbounded returns true if the cpu use is unbounded for any container in pod
func IsPodCPUUnbounded(pod *api.Pod) bool {
	for j := range pod.Spec.Containers {
		container := pod.Spec.Containers[j]
		if container.Resources.Limits.Cpu().MilliValue() == int64(0) {
			return true
		}
	}
	return false
}

// IsPodMemoryUnbounded returns true if the memory use is unbounded for any container in pod
func IsPodMemoryUnbounded(pod *api.Pod) bool {
	for j := range pod.Spec.Containers {
		container := pod.Spec.Containers[j]
		if container.Resources.Limits.Memory().Value() == int64(0) {
			return true
		}
	}
	return false
}

// PodMemory computes the memory usage of a pod
func PodMemory(pod *api.Pod) *resource.Quantity {
	val := int64(0)
	for j := range pod.Spec.Containers {
		val = val + pod.Spec.Containers[j].Resources.Limits.Memory().Value()
	}
	return resource.NewQuantity(int64(val), resource.DecimalSI)
}
<commit_msg>Its bad to spawn a gofunc per quota with large number of quotas<commit_after>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package resourcequota

import (
	"time"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
	"github.com/golang/glog"
)

// ResourceQuotaManager is responsible for tracking quota usage status in the system
type ResourceQuotaManager struct {
	kubeClient client.Interface
	syncTime   <-chan time.Time

	// To allow injection of syncUsage for testing.
	syncHandler func(quota api.ResourceQuota) error
}

// NewResourceQuotaManager creates a new ResourceQuotaManager
func NewResourceQuotaManager(kubeClient client.Interface) *ResourceQuotaManager {

	rm := &ResourceQuotaManager{
		kubeClient: kubeClient,
	}

	// set the synchronization handler
	rm.syncHandler = rm.syncResourceQuota
	return rm
}

// Run begins watching and syncing.
func (rm *ResourceQuotaManager) Run(period time.Duration) {
	rm.syncTime = time.Tick(period)
	go util.Forever(func() { rm.synchronize() }, period)
}

func (rm *ResourceQuotaManager) synchronize() {
	var resourceQuotas []api.ResourceQuota
	list, err := rm.kubeClient.ResourceQuotas(api.NamespaceAll).List(labels.Everything())
	if err != nil {
		glog.Errorf("Synchronization error: %v (%#v)", err, err)
	}
	resourceQuotas = list.Items
	for ix := range resourceQuotas {
		glog.V(4).Infof("periodic sync of %v/%v", resourceQuotas[ix].Namespace, resourceQuotas[ix].Name)
		err := rm.syncHandler(resourceQuotas[ix])
		if err != nil {
			glog.Errorf("Error synchronizing: %v", err)
		}
	}
}

// FilterQuotaPods eliminates pods that no longer have a cost against the quota
// pods that have a restart policy of always are always returned
// pods that are in a failed state, but have a restart policy of on failure are always returned
// pods that are not in a success state or a failure state are included in quota
func FilterQuotaPods(pods []api.Pod) []*api.Pod {
	var result []*api.Pod
	for i := range pods {
		value := &pods[i]
		// a pod that has a restart policy always no matter its state counts against usage
		if value.Spec.RestartPolicy == api.RestartPolicyAlways {
			result = append(result, value)
			continue
		}
		// a failed pod with a restart policy of on failure will count against usage
		if api.PodFailed == value.Status.Phase &&
			value.Spec.RestartPolicy == api.RestartPolicyOnFailure {
			result = append(result, value)
			continue
		}
		// if the pod is not succeeded or failed, then we count it against quota
		if api.PodSucceeded != value.Status.Phase &&
			api.PodFailed != value.Status.Phase {
			result = append(result, value)
			continue
		}
	}
	return result
}

// syncResourceQuota runs a complete sync of current status
func (rm *ResourceQuotaManager) syncResourceQuota(quota api.ResourceQuota) (err error) {

	// quota is dirty if any part of spec hard limits differs from the status hard limits
	dirty := !api.Semantic.DeepEqual(quota.Spec.Hard, quota.Status.Hard)

	// dirty tracks if the usage status differs from the previous sync,
	// if so, we send a new usage with latest status
	// if this is our first sync, it will be dirty by default, since we need track usage
	dirty = dirty || (quota.Status.Hard == nil || quota.Status.Used == nil)

	// Create a usage object that is based on the quota resource version
	usage := api.ResourceQuota{
		ObjectMeta: api.ObjectMeta{
			Name:            quota.Name,
			Namespace:       quota.Namespace,
			ResourceVersion: quota.ResourceVersion,
			Labels:          quota.Labels,
			Annotations:     quota.Annotations},
		Status: api.ResourceQuotaStatus{
			Hard: api.ResourceList{},
			Used: api.ResourceList{},
		},
	}

	// set the hard values supported on the quota
	for k, v := range quota.Spec.Hard {
		usage.Status.Hard[k] = *v.Copy()
	}
	// set any last known observed status values for usage
	for k, v := range quota.Status.Used {
		usage.Status.Used[k] = *v.Copy()
	}

	set := map[api.ResourceName]bool{}
	for k := range usage.Status.Hard {
		set[k] = true
	}

	pods := &api.PodList{}
	if set[api.ResourcePods] || set[api.ResourceMemory] || set[api.ResourceCPU] {
		pods, err = rm.kubeClient.Pods(usage.Namespace).List(labels.Everything(), fields.Everything())
		if err != nil {
			return err
		}
	}

	filteredPods := FilterQuotaPods(pods.Items)

	// iterate over each resource, and update observation
	for k := range usage.Status.Hard {

		// look if there is a used value, if none, we are definitely dirty
		prevQuantity, found := usage.Status.Used[k]
		if !found {
			dirty = true
		}

		var value *resource.Quantity

		switch k {
		case api.ResourcePods:
			value = resource.NewQuantity(int64(len(filteredPods)), resource.DecimalSI)
		case api.ResourceMemory:
			val := int64(0)
			for _, pod := range filteredPods {
				val = val + PodMemory(pod).Value()
			}
			value = resource.NewQuantity(int64(val), resource.DecimalSI)
		case api.ResourceCPU:
			val := int64(0)
			for _, pod := range filteredPods {
				val = val + PodCPU(pod).MilliValue()
			}
			value = resource.NewMilliQuantity(int64(val), resource.DecimalSI)
		case api.ResourceServices:
			items, err := rm.kubeClient.Services(usage.Namespace).List(labels.Everything())
			if err != nil {
				return err
			}
			value = resource.NewQuantity(int64(len(items.Items)), resource.DecimalSI)
		case api.ResourceReplicationControllers:
			items, err := rm.kubeClient.ReplicationControllers(usage.Namespace).List(labels.Everything())
			if err != nil {
				return err
			}
			value = resource.NewQuantity(int64(len(items.Items)), resource.DecimalSI)
		case api.ResourceQuotas:
			items, err := rm.kubeClient.ResourceQuotas(usage.Namespace).List(labels.Everything())
			if err != nil {
				return err
			}
			value = resource.NewQuantity(int64(len(items.Items)), resource.DecimalSI)
		case api.ResourceSecrets:
			items, err := rm.kubeClient.Secrets(usage.Namespace).List(labels.Everything(), fields.Everything())
			if err != nil {
				return err
			}
			value = resource.NewQuantity(int64(len(items.Items)), resource.DecimalSI)
		case api.ResourcePersistentVolumeClaims:
			items, err := rm.kubeClient.PersistentVolumeClaims(usage.Namespace).List(labels.Everything(), fields.Everything())
			if err != nil {
				return err
			}
			value = resource.NewQuantity(int64(len(items.Items)), resource.DecimalSI)
		}

		// ignore fields we do not understand (assume another controller is tracking it)
		if value != nil {
			// see if the value has changed
			dirty = dirty || (value.Value() != prevQuantity.Value())
			// just update the value
			usage.Status.Used[k] = *value
		}
	}

	// update the usage only if it changed
	if dirty {
		_, err = rm.kubeClient.ResourceQuotas(usage.Namespace).UpdateStatus(&usage)
		return err
	}
	return nil
}

// PodCPU computes total cpu usage of a pod
func PodCPU(pod *api.Pod) *resource.Quantity {
	val := int64(0)
	for j := range pod.Spec.Containers {
		val = val + pod.Spec.Containers[j].Resources.Limits.Cpu().MilliValue()
	}
	return resource.NewMilliQuantity(int64(val), resource.DecimalSI)
}

// IsPodCPUUnbounded returns true if the cpu use is unbounded for any container in pod
func IsPodCPUUnbounded(pod *api.Pod) bool {
	for j := range pod.Spec.Containers {
		container := pod.Spec.Containers[j]
		if container.Resources.Limits.Cpu().MilliValue() == int64(0) {
			return true
		}
	}
	return false
}

// IsPodMemoryUnbounded returns true if the memory use is unbounded for any container in pod
func IsPodMemoryUnbounded(pod *api.Pod) bool {
	for j := range pod.Spec.Containers {
		container := pod.Spec.Containers[j]
		if container.Resources.Limits.Memory().Value() == int64(0) {
			return true
		}
	}
	return false
}

// PodMemory computes the memory usage of a pod
func PodMemory(pod *api.Pod) *resource.Quantity {
	val := int64(0)
	for j := range pod.Spec.Containers {
		val = val + pod.Spec.Containers[j].Resources.Limits.Memory().Value()
	}
	return resource.NewQuantity(int64(val), resource.DecimalSI)
}
<|endoftext|>


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

package plugins_account_core

import (
	"gopkg.in/olivere/elastic.v5"
)

// createQueryAccountFilterPlugins creates and return a new *elastic.TermsQuery on the accountList array
func createQueryAccountFilterPlugins(accountList []string) *elastic.TermsQuery {
	accountListFormatted := make([]interface{}, len(accountList))
	for i, v := range accountList {
		accountListFormatted[i] = v
	}
	return elastic.NewTermsQuery("account", accountListFormatted...)
}

// GetElasticSearchPluginsParams is used to construct an ElasticSearch *elastic.SearchService used to perform a request on ES
// It takes as paramters :
// 	- accountList []string : A slice of strings representing aws account ids
//	- client *elastic.Client : an instance of *elastic.Client that represent an Elastic Search client.
//	It needs to be fully configured and ready to execute a client.Search()
//	- index string : The Elastic Search index on wich to execute the query.
// This function excepts arguments passed to it to be sanitize. If they are not, the following cases will make
// it crash :
//	- If the client is nil or malconfigured, it will crash
//	- If the index is not an index present in the ES, it will crash
func GetElasticSearchPluginsParams(accountList []string, client *elastic.Client, index string) *elastic.SearchService {
	query := elastic.NewBoolQuery()
	if len(accountList) > 0 {
		query = query.Filter(createQueryAccountFilterPlugins(accountList))
	}
	search := client.Search().Index(index).Size(0).Query(query)
	search.Aggregation("top_plugins_account", elastic.NewTermsAggregation().Field("accountPluginIdx").
		SubAggregation("top_reports_hits", elastic.NewTopHitsAggregation().Sort("reportDate", false).Size(1)))
	return search
}
<commit_msg>fix plugins request size<commit_after>//   Copyright 2018 MSolution.IO
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

package plugins_account_core

import (
	"gopkg.in/olivere/elastic.v5"
)

const maxAggregationSize = 0x7FFFFFFF

// createQueryAccountFilterPlugins creates and return a new *elastic.TermsQuery on the accountList array
func createQueryAccountFilterPlugins(accountList []string) *elastic.TermsQuery {
	accountListFormatted := make([]interface{}, len(accountList))
	for i, v := range accountList {
		accountListFormatted[i] = v
	}
	return elastic.NewTermsQuery("account", accountListFormatted...)
}

// GetElasticSearchPluginsParams is used to construct an ElasticSearch *elastic.SearchService used to perform a request on ES
// It takes as paramters :
// 	- accountList []string : A slice of strings representing aws account ids
//	- client *elastic.Client : an instance of *elastic.Client that represent an Elastic Search client.
//	It needs to be fully configured and ready to execute a client.Search()
//	- index string : The Elastic Search index on wich to execute the query.
// This function excepts arguments passed to it to be sanitize. If they are not, the following cases will make
// it crash :
//	- If the client is nil or malconfigured, it will crash
//	- If the index is not an index present in the ES, it will crash
func GetElasticSearchPluginsParams(accountList []string, client *elastic.Client, index string) *elastic.SearchService {
	query := elastic.NewBoolQuery()
	if len(accountList) > 0 {
		query = query.Filter(createQueryAccountFilterPlugins(accountList))
	}
	search := client.Search().Index(index).Size(0).Query(query)
	search.Aggregation("top_plugins_account", elastic.NewTermsAggregation().Field("accountPluginIdx").Size(maxAggregationSize).
		SubAggregation("top_reports_hits", elastic.NewTopHitsAggregation().Sort("reportDate", false).Size(1)))
	return search
}
<|endoftext|>


<commit_before>// Copyright 2021 The gopass Authors. All rights reserved.
// Use of this source code is governed by the MIT license,
// that can be found in the LICENSE file.

// Release is the first part of the gopass release automation. It's supposed
// to be run by a member of the gopass team. It will ensure that the repository
// is in a clean state and make it trivial to trigger a new release.
// You can run it without any parameters and as long as you pay close attention
// to the output it will be a breeze.
package main

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"regexp"
	"sort"
	"strings"
	"text/template"
	"time"

	"github.com/blang/semver/v4"
)

var (
	sleep   = time.Second
	issueRE = regexp.MustCompile(`#(\d+)\b`)
	verTmpl = `package main

import (
	"strings"

	"github.com/blang/semver/v4"
)

func getVersion() semver.Version {
	sv, err := semver.Parse(strings.TrimPrefix(version, "v"))
	if err == nil {
		return sv
	}

	return semver.Version{
		Major: {{ .Major }},
		Minor: {{ .Minor }},
		Patch: {{ .Patch }},
		Pre: []semver.PRVersion{
			{VersionStr: "git"},
		},
		Build: []string{"HEAD"},
	}
}
`
)

const logo = `
   __     _    _ _      _ _   ___   ___
 /'_ '\ /'_'\ ( '_'\  /'_' )/',__)/',__)
( (_) |( (_) )| (_) )( (_| |\__, \\__, \
'\__  |'\___/'| ,__/''\__,_)(____/(____/
( )_) |       | |
 \___/'       (_)

 `

func main() {
	fmt.Println(logo)
	fmt.Println()
	fmt.Println("🌟 Preparing a new gopass release.")
	fmt.Println("☝  Checking pre-conditions ...")
	// - check that workdir is clean
	if !isGitClean() {
		panic("❌ git is dirty")
	}
	fmt.Println("✅ git is clean")

	if sv := os.Getenv("PATCH_RELEASE"); sv == "" {
		// - check out master
		if err := gitCoMaster(); err != nil {
			panic(err)
		}
		fmt.Println("✅ Switched to master branch")
		// - pull from origin
		if err := gitPom(); err != nil {
			panic(err)
		}
		fmt.Println("✅ Fetched changes for master")
	}
	// - check that workdir is clean
	if !isGitClean() {
		panic("git is dirty")
	}
	fmt.Println("✅ git is still clean")

	prevVer, nextVer := getVersions()

	fmt.Println()
	fmt.Printf("✅ New version will be: %s\n", nextVer.String())
	fmt.Println()
	fmt.Println("❓ Do you want to continue? (press any key to continue or Ctrl+C to abort)")
	fmt.Scanln()

	// - update VERSION
	if err := writeVersion(nextVer); err != nil {
		panic(err)
	}
	fmt.Println("✅ Wrote VERSION")
	time.Sleep(sleep)
	// - update version.go
	if err := writeVersionGo(nextVer); err != nil {
		panic(err)
	}
	fmt.Println("✅ Wrote version.go")
	time.Sleep(sleep)
	// - update CHANGELOG.md
	if err := writeChangelog(prevVer, nextVer); err != nil {
		panic(err)
	}
	fmt.Println("✅ Updated CHANGELOG.md")
	time.Sleep(sleep)
	// - update shell completions
	if err := updateCompletion(); err != nil {
		panic(err)
	}
	fmt.Println("✅ Updated shell completions")
	time.Sleep(sleep)
	// - update man page
	if err := updateManpage(); err != nil {
		panic(err)
	}
	fmt.Println("✅ Updated man page")
	time.Sleep(sleep)

	// - create PR
	//   git checkout -b release/vX.Y.Z
	if err := gitCoRel(nextVer); err != nil {
		panic(err)
	}
	fmt.Printf("✅ Created branch release/v%s\n", nextVer.String())
	time.Sleep(sleep)

	// commit changes
	if err := gitCommit(nextVer); err != nil {
		panic(err)
	}
	fmt.Printf("✅ Committed changes to release/v%s\n", nextVer.String())
	time.Sleep(sleep)

	fmt.Println("🏁 Preparation finished")
	time.Sleep(sleep)

	fmt.Printf("⚠ Prepared release of gopass %s.\n", nextVer.String())
	time.Sleep(sleep)

	fmt.Printf("⚠ Run 'git push <remote> release/v%s' to push this branch and open a PR against gopasspw/gopass master.\n", nextVer.String())
	time.Sleep(sleep)

	fmt.Printf("⚠ Get the PR merged and run 'git tag -s v%s && git push origin v%s' to kick off the release process.\n", nextVer.String(), nextVer.String())
	time.Sleep(sleep)
	fmt.Println()

	fmt.Println("💎🙌 Done 🚀🚀🚀🚀🚀🚀")
}

func getVersions() (semver.Version, semver.Version) {
	nextVerFlag := ""
	if len(os.Args) > 1 {
		nextVerFlag = strings.TrimSpace(strings.TrimPrefix(os.Args[1], "v"))
	}
	prevVerFlag := ""
	if len(os.Args) > 2 {
		prevVerFlag = strings.TrimSpace(strings.TrimPrefix(os.Args[2], "v"))
	}

	// obtain the last tagged version from git
	gitVer, err := gitVersion()
	if err != nil {
		panic(err)
	}

	// read the version file to get the last committed version
	vfVer, err := versionFile()
	if err != nil {
		panic(err)
	}

	prevVer := gitVer
	if prevVerFlag != "" {
		prevVer = semver.MustParse(prevVerFlag)
	}

	if gitVer.NE(vfVer) {
		fmt.Printf("git version: %q != VERSION: %q\n", gitVer.String(), vfVer.String())
		if prevVerFlag == "" && len(vfVer.Pre) < 1 {
			usage()
			panic("version mismatch")
		}
	}

	nextVer := prevVer
	if nextVerFlag != "" {
		nextVer = semver.MustParse(nextVerFlag)
		if nextVer.LTE(prevVer) {
			usage()
			panic("next version must be greather than the previous version")
		}
	} else {
		nextVer.IncrementPatch()
		if len(vfVer.Pre) > 0 {
			nextVer = vfVer
			nextVer.Pre = nil
		}
	}

	fmt.Printf(`☝ Version overview
  Git (latest tag):  %q
  VERSION:           %q
  Next version flag: %q
  Prev version flag: %q

Will use
  Previous: %q
  Next:     %q
`,
		gitVer,
		vfVer,
		prevVerFlag,
		nextVerFlag,
		prevVer,
		nextVer)

	return prevVer, nextVer
}

func gitCoMaster() error {
	cmd := exec.Command("git", "checkout", "master")
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func gitPom() error {
	cmd := exec.Command("git", "pull", "origin", "master")
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func gitCoRel(v semver.Version) error {
	cmd := exec.Command("git", "checkout", "-b", "release/v"+v.String())
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func gitCommit(v semver.Version) error {
	cmd := exec.Command("git", "add", "CHANGELOG.md", "VERSION", "version.go", "gopass.1", "*.completion")
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		return err
	}
	cmd = exec.Command("git", "commit", "-s", "-m", "Tag v"+v.String(), "-m", "RELEASE_NOTES=n/a")
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func writeChangelog(prev, next semver.Version) error {
	cl, err := changelogEntries(prev)
	if err != nil {
		panic(err)
	}

	// prepend the new changelog entries by first writing the
	// new content in a new file ...
	fh, err := os.Create("CHANGELOG.new")
	if err != nil {
		return err
	}
	defer fh.Close()

	fmt.Fprintf(fh, "## %s / %s\n\n", next.String(), time.Now().UTC().Format("2006-01-02"))
	for _, e := range cl {
		fmt.Fprint(fh, "* ")
		fmt.Fprintln(fh, e)
	}
	fmt.Fprintln(fh)

	ofh, err := os.Open("CHANGELOG.md")
	if err != nil {
		return err
	}
	defer ofh.Close()

	// then appending any existing content from the old file and ...
	if _, err := io.Copy(fh, ofh); err != nil {
		return err
	}

	// renaming the new file to the old file
	return os.Rename("CHANGELOG.new", "CHANGELOG.md")
}

func updateCompletion() error {
	cmd := exec.Command("make", "completion")
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func updateManpage() error {
	cmd := exec.Command("make", "man")
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func writeVersion(v semver.Version) error {
	return os.WriteFile("VERSION", []byte(v.String()+"\n"), 0o644)
}

type tplPayload struct {
	Major uint64
	Minor uint64
	Patch uint64
}

func writeVersionGo(v semver.Version) error {
	tmpl, err := template.New("version").Parse(verTmpl)
	if err != nil {
		return err
	}
	fh, err := os.Create("version.go")
	if err != nil {
		return err
	}
	defer fh.Close()
	return tmpl.Execute(fh, tplPayload{
		Major: v.Major,
		Minor: v.Minor,
		Patch: v.Patch,
	})
}

func isGitClean() bool {
	buf, err := exec.Command("git", "diff", "--stat").CombinedOutput()
	if err != nil {
		panic(err)
	}
	return strings.TrimSpace(string(buf)) == ""
}

func versionFile() (semver.Version, error) {
	buf, err := os.ReadFile("VERSION")
	if err != nil {
		return semver.Version{}, err
	}
	return semver.Parse(strings.TrimSpace(string(buf)))
}

func gitVersion() (semver.Version, error) {
	buf, err := exec.Command("git", "tag", "--sort=version:refname").CombinedOutput()
	if err != nil {
		return semver.Version{}, err
	}
	lines := strings.Split(strings.TrimSpace(string(buf)), "\n")
	if len(lines) < 1 {
		return semver.Version{}, fmt.Errorf("no output")
	}
	return semver.Parse(strings.TrimPrefix(lines[len(lines)-1], "v"))
}

func changelogEntries(since semver.Version) ([]string, error) {
	gitSep := "@@@GIT-SEP@@@"
	gitDelim := "@@@GIT-DELIM@@@"
	// full hash - subject - body
	// note: we don't use the hash at the moment
	prettyFormat := gitSep + "%H" + gitDelim + "%s" + gitDelim + "%b" + gitSep
	args := []string{
		"log",
		"v" + since.String() + "..HEAD",
		"--pretty=" + prettyFormat,
	}
	buf, err := exec.Command("git", args...).CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("failed to run git %+v with error %w: %s", args, err, string(buf))
	}

	notes := make([]string, 0, 10)
	commits := strings.Split(string(buf), gitSep)
	for _, commit := range commits {
		commit := strings.TrimSpace(commit)
		if commit == "" {
			continue
		}
		p := strings.Split(commit, gitDelim)
		if len(p) < 3 {
			// invalid entry, shouldn't happen
			continue
		}

		issues := []string{}
		if m := issueRE.FindStringSubmatch(strings.TrimSpace(p[1])); len(m) > 1 {
			issues = append(issues, m[1])
		}

		for _, line := range strings.Split(p[2], "\n") {
			line := strings.TrimSpace(line)

			if m := issueRE.FindStringSubmatch(line); len(m) > 1 {
				issues = append(issues, m[1])
			}

			if !strings.HasPrefix(line, "RELEASE_NOTES=") {
				continue
			}
			p := strings.Split(line, "=")
			if len(p) < 2 {
				continue
			}
			val := p[1]
			if strings.ToLower(val) == "n/a" {
				continue
			}
			if len(issues) > 0 {
				val += " (#" + strings.Join(issues, ", #") + ")"
			}
			notes = append(notes, val)
		}
	}

	sort.Strings(notes)
	return notes, nil
}

func usage() {
	fmt.Printf("Usage: %s [next version] [prev version]\n", "go run helpers/release/main.go")
}
<commit_msg>Update dependencies during release<commit_after>// Copyright 2021 The gopass Authors. All rights reserved.
// Use of this source code is governed by the MIT license,
// that can be found in the LICENSE file.

// Release is the first part of the gopass release automation. It's supposed
// to be run by a member of the gopass team. It will ensure that the repository
// is in a clean state and make it trivial to trigger a new release.
// You can run it without any parameters and as long as you pay close attention
// to the output it will be a breeze.
package main

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"regexp"
	"sort"
	"strings"
	"text/template"
	"time"

	"github.com/blang/semver/v4"
)

var (
	sleep   = time.Second
	issueRE = regexp.MustCompile(`#(\d+)\b`)
	verTmpl = `package main

import (
	"strings"

	"github.com/blang/semver/v4"
)

func getVersion() semver.Version {
	sv, err := semver.Parse(strings.TrimPrefix(version, "v"))
	if err == nil {
		return sv
	}

	return semver.Version{
		Major: {{ .Major }},
		Minor: {{ .Minor }},
		Patch: {{ .Patch }},
		Pre: []semver.PRVersion{
			{VersionStr: "git"},
		},
		Build: []string{"HEAD"},
	}
}
`
)

const logo = `
   __     _    _ _      _ _   ___   ___
 /'_ '\ /'_'\ ( '_'\  /'_' )/',__)/',__)
( (_) |( (_) )| (_) )( (_| |\__, \\__, \
'\__  |'\___/'| ,__/''\__,_)(____/(____/
( )_) |       | |
 \___/'       (_)

 `

func main() {
	fmt.Println(logo)
	fmt.Println()
	fmt.Println("🌟 Preparing a new gopass release.")
	fmt.Println("☝  Checking pre-conditions ...")
	// - check that workdir is clean
	if !isGitClean() {
		panic("❌ git is dirty")
	}
	fmt.Println("✅ git is clean")

	if sv := os.Getenv("PATCH_RELEASE"); sv == "" {
		// - check out master
		if err := gitCoMaster(); err != nil {
			panic(err)
		}
		fmt.Println("✅ Switched to master branch")
		// - pull from origin
		if err := gitPom(); err != nil {
			panic(err)
		}
		fmt.Println("✅ Fetched changes for master")
	}
	// - check that workdir is clean
	if !isGitClean() {
		panic("git is dirty")
	}
	fmt.Println("✅ git is still clean")

	prevVer, nextVer := getVersions()

	fmt.Println()
	fmt.Printf("✅ New version will be: %s\n", nextVer.String())
	fmt.Println()
	fmt.Println("❓ Do you want to continue? (press any key to continue or Ctrl+C to abort)")
	fmt.Scanln()

	// - update deps and run tests
	if err := updateDeps(); err != nil {
		panic(err)
	}

	// - update VERSION
	if err := writeVersion(nextVer); err != nil {
		panic(err)
	}
	fmt.Println("✅ Wrote VERSION")
	time.Sleep(sleep)
	// - update version.go
	if err := writeVersionGo(nextVer); err != nil {
		panic(err)
	}
	fmt.Println("✅ Wrote version.go")
	time.Sleep(sleep)
	// - update CHANGELOG.md
	if err := writeChangelog(prevVer, nextVer); err != nil {
		panic(err)
	}
	fmt.Println("✅ Updated CHANGELOG.md")
	time.Sleep(sleep)
	// - update shell completions
	if err := updateCompletion(); err != nil {
		panic(err)
	}
	fmt.Println("✅ Updated shell completions")
	time.Sleep(sleep)
	// - update man page
	if err := updateManpage(); err != nil {
		panic(err)
	}
	fmt.Println("✅ Updated man page")
	time.Sleep(sleep)

	// - create PR
	//   git checkout -b release/vX.Y.Z
	if err := gitCoRel(nextVer); err != nil {
		panic(err)
	}
	fmt.Printf("✅ Created branch release/v%s\n", nextVer.String())
	time.Sleep(sleep)

	// commit changes
	if err := gitCommit(nextVer); err != nil {
		panic(err)
	}
	fmt.Printf("✅ Committed changes to release/v%s\n", nextVer.String())
	time.Sleep(sleep)

	fmt.Println("🏁 Preparation finished")
	time.Sleep(sleep)

	fmt.Printf("⚠ Prepared release of gopass %s.\n", nextVer.String())
	time.Sleep(sleep)

	fmt.Printf("⚠ Run 'git push <remote> release/v%s' to push this branch and open a PR against gopasspw/gopass master.\n", nextVer.String())
	time.Sleep(sleep)

	fmt.Printf("⚠ Get the PR merged and run 'git tag -s v%s && git push origin v%s' to kick off the release process.\n", nextVer.String(), nextVer.String())
	time.Sleep(sleep)
	fmt.Println()

	fmt.Println("💎🙌 Done 🚀🚀🚀🚀🚀🚀")
}

func getVersions() (semver.Version, semver.Version) {
	nextVerFlag := ""
	if len(os.Args) > 1 {
		nextVerFlag = strings.TrimSpace(strings.TrimPrefix(os.Args[1], "v"))
	}
	prevVerFlag := ""
	if len(os.Args) > 2 {
		prevVerFlag = strings.TrimSpace(strings.TrimPrefix(os.Args[2], "v"))
	}

	// obtain the last tagged version from git
	gitVer, err := gitVersion()
	if err != nil {
		panic(err)
	}

	// read the version file to get the last committed version
	vfVer, err := versionFile()
	if err != nil {
		panic(err)
	}

	prevVer := gitVer
	if prevVerFlag != "" {
		prevVer = semver.MustParse(prevVerFlag)
	}

	if gitVer.NE(vfVer) {
		fmt.Printf("git version: %q != VERSION: %q\n", gitVer.String(), vfVer.String())
		if prevVerFlag == "" && len(vfVer.Pre) < 1 {
			usage()
			panic("version mismatch")
		}
	}

	nextVer := prevVer
	if nextVerFlag != "" {
		nextVer = semver.MustParse(nextVerFlag)
		if nextVer.LTE(prevVer) {
			usage()
			panic("next version must be greather than the previous version")
		}
	} else {
		nextVer.IncrementPatch()
		if len(vfVer.Pre) > 0 {
			nextVer = vfVer
			nextVer.Pre = nil
		}
	}

	fmt.Printf(`☝ Version overview
  Git (latest tag):  %q
  VERSION:           %q
  Next version flag: %q
  Prev version flag: %q

Will use
  Previous: %q
  Next:     %q
`,
		gitVer,
		vfVer,
		prevVerFlag,
		nextVerFlag,
		prevVer,
		nextVer)

	return prevVer, nextVer
}

func updateDeps() error {
	cmd := exec.Command("make", "upgrade")
	cmd.Stderr = os.Stderr

	if err := cmd.Run(); err != nil {
		return err
	}

	cmd = exec.Command("make", "travis")
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func gitCoMaster() error {
	cmd := exec.Command("git", "checkout", "master")
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func gitPom() error {
	cmd := exec.Command("git", "pull", "origin", "master")
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func gitCoRel(v semver.Version) error {
	cmd := exec.Command("git", "checkout", "-b", "release/v"+v.String())
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func gitCommit(v semver.Version) error {
	cmd := exec.Command("git", "add", "CHANGELOG.md", "VERSION", "version.go", "gopass.1", "*.completion")
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		return err
	}
	cmd = exec.Command("git", "commit", "-s", "-m", "Tag v"+v.String(), "-m", "RELEASE_NOTES=n/a")
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func writeChangelog(prev, next semver.Version) error {
	cl, err := changelogEntries(prev)
	if err != nil {
		panic(err)
	}

	// prepend the new changelog entries by first writing the
	// new content in a new file ...
	fh, err := os.Create("CHANGELOG.new")
	if err != nil {
		return err
	}
	defer fh.Close()

	fmt.Fprintf(fh, "## %s / %s\n\n", next.String(), time.Now().UTC().Format("2006-01-02"))
	for _, e := range cl {
		fmt.Fprint(fh, "* ")
		fmt.Fprintln(fh, e)
	}
	fmt.Fprintln(fh)

	ofh, err := os.Open("CHANGELOG.md")
	if err != nil {
		return err
	}
	defer ofh.Close()

	// then appending any existing content from the old file and ...
	if _, err := io.Copy(fh, ofh); err != nil {
		return err
	}

	// renaming the new file to the old file
	return os.Rename("CHANGELOG.new", "CHANGELOG.md")
}

func updateCompletion() error {
	cmd := exec.Command("make", "completion")
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func updateManpage() error {
	cmd := exec.Command("make", "man")
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func writeVersion(v semver.Version) error {
	return os.WriteFile("VERSION", []byte(v.String()+"\n"), 0o644)
}

type tplPayload struct {
	Major uint64
	Minor uint64
	Patch uint64
}

func writeVersionGo(v semver.Version) error {
	tmpl, err := template.New("version").Parse(verTmpl)
	if err != nil {
		return err
	}
	fh, err := os.Create("version.go")
	if err != nil {
		return err
	}
	defer fh.Close()
	return tmpl.Execute(fh, tplPayload{
		Major: v.Major,
		Minor: v.Minor,
		Patch: v.Patch,
	})
}

func isGitClean() bool {
	buf, err := exec.Command("git", "diff", "--stat").CombinedOutput()
	if err != nil {
		panic(err)
	}
	return strings.TrimSpace(string(buf)) == ""
}

func versionFile() (semver.Version, error) {
	buf, err := os.ReadFile("VERSION")
	if err != nil {
		return semver.Version{}, err
	}
	return semver.Parse(strings.TrimSpace(string(buf)))
}

func gitVersion() (semver.Version, error) {
	buf, err := exec.Command("git", "tag", "--sort=version:refname").CombinedOutput()
	if err != nil {
		return semver.Version{}, err
	}
	lines := strings.Split(strings.TrimSpace(string(buf)), "\n")
	if len(lines) < 1 {
		return semver.Version{}, fmt.Errorf("no output")
	}
	return semver.Parse(strings.TrimPrefix(lines[len(lines)-1], "v"))
}

func changelogEntries(since semver.Version) ([]string, error) {
	gitSep := "@@@GIT-SEP@@@"
	gitDelim := "@@@GIT-DELIM@@@"
	// full hash - subject - body
	// note: we don't use the hash at the moment
	prettyFormat := gitSep + "%H" + gitDelim + "%s" + gitDelim + "%b" + gitSep
	args := []string{
		"log",
		"v" + since.String() + "..HEAD",
		"--pretty=" + prettyFormat,
	}
	buf, err := exec.Command("git", args...).CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("failed to run git %+v with error %w: %s", args, err, string(buf))
	}

	notes := make([]string, 0, 10)
	commits := strings.Split(string(buf), gitSep)
	for _, commit := range commits {
		commit := strings.TrimSpace(commit)
		if commit == "" {
			continue
		}
		p := strings.Split(commit, gitDelim)
		if len(p) < 3 {
			// invalid entry, shouldn't happen
			continue
		}

		issues := []string{}
		if m := issueRE.FindStringSubmatch(strings.TrimSpace(p[1])); len(m) > 1 {
			issues = append(issues, m[1])
		}

		for _, line := range strings.Split(p[2], "\n") {
			line := strings.TrimSpace(line)

			if m := issueRE.FindStringSubmatch(line); len(m) > 1 {
				issues = append(issues, m[1])
			}

			if !strings.HasPrefix(line, "RELEASE_NOTES=") {
				continue
			}
			p := strings.Split(line, "=")
			if len(p) < 2 {
				continue
			}
			val := p[1]
			if strings.ToLower(val) == "n/a" {
				continue
			}
			if len(issues) > 0 {
				val += " (#" + strings.Join(issues, ", #") + ")"
			}
			notes = append(notes, val)
		}
	}

	sort.Strings(notes)
	return notes, nil
}

func usage() {
	fmt.Printf("Usage: %s [next version] [prev version]\n", "go run helpers/release/main.go")
}
<|endoftext|>


<commit_before>package henchman

import (
	"io/ioutil"
	"os"
	"path"
	"testing"

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

func moduleTestSetup(modName string) (module *Module) {
	moduleContent := `
#!/usr/bin/env sh
ls -al $1
`
	writeTempFile([]byte(moduleContent), modName)

	mod, _ := NewModule(modName, "")
	return mod
}

func moduleTestTeardown(mod *Module) {
	os.Remove(path.Join("/tmp", mod.Name))
}

func TestValidModule(t *testing.T) {
	name := "shell"
	args := "cmd=\"ls -al\" foo=bar baz=☃"
	mod, err := NewModule(name, args)

	require.NoError(t, err)

	assert.Equal(t, name, mod.Name, "Module names should match")
	assert.Equal(t, "ls -al", mod.Params["cmd"], "Mod params wasn't initialized properly")
	assert.Equal(t, "bar", mod.Params["foo"], "Expected value for foo to be bar")
	assert.Equal(t, "☃", mod.Params["baz"], "Expected a snowman")
}

func TestValidModuleWithVariousChars(t *testing.T) {
	name := "shell"
	args := "cmd='ls -al' url=\"http://foo.com/abc\" baz='abc-def' test=\"sed -i 's,store.enable=true,store.enable=false,g'\""
	mod, err := NewModule(name, args)

	require.NoError(t, err)

	assert.Equal(t, name, mod.Name, "Module names should match")
	assert.Equal(t, "ls -al", mod.Params["cmd"], "Mod params wasn't initialized properly")
	assert.Equal(t, "http://foo.com/abc", mod.Params["url"], "Expected value for foo to be bar")
	assert.Equal(t, "abc-def", mod.Params["baz"], "Expected a snowman")
	assert.Equal(t, "sed -i s,store.enable=true,store.enable=false,g", mod.Params["test"], "Expected s,store.enable=true,store.enable=false,g")

}

func TestInvalidArgsModule(t *testing.T) {
	name := "invalid"
	args := "foo"
	_, err := NewModule(name, args)

	require.Error(t, err, "Module arg parsing should have failed")
}

func TestInvalidArgsModule2(t *testing.T) {
	name := "invalid"
	args := "foo bar=baz"
	_, err := NewModule(name, args)

	require.Error(t, err, "Module arg parsing should have failed")
}

func TestModuleResolve(t *testing.T) {
	origSearchPath := ModuleSearchPath
	ModuleSearchPath = append(ModuleSearchPath, "/tmp")
	defer func() {
		ModuleSearchPath = origSearchPath
	}()
	writeTempFile([]byte("ls -al"), "shell")
	defer rmTempFile("/tmp/shell")
	mod, err := NewModule("shell", "foo=bar")
	//mod, err := setupTestShellModule()

	require.NoError(t, err)
	require.NotNil(t, mod)

	fullPath, err := mod.Resolve()

	require.NoError(t, err)
	assert.Equal(t, "/tmp/shell", fullPath, "Got incorrect fullPath")

	err = os.Mkdir("/tmp/curl", 0777)
	assert.NoError(t, err)

	err = ioutil.WriteFile("/tmp/curl/exec", []byte("ls -al"), 0644)
	assert.NoError(t, err)
	defer os.RemoveAll("/tmp/curl")

	mod, err = NewModule("curl", "foo=bar")
	//mod, err := setupTestShellModule()
	require.NoError(t, err)
	require.NotNil(t, mod)

	fullPath, err = mod.Resolve()

	require.NoError(t, err)
	assert.Equal(t, "/tmp/curl", fullPath, "Got incorrect fullPath")
}

func setupTestShellModule() (*Module, error) {
	writeTempFile([]byte("ls -al"), "shell")
	defer rmTempFile("/tmp/shell")
	return NewModule("shell", "foo=bar")
}

func TestNonexistentModuleResolve(t *testing.T) {
	//ModuleSearchPath = append(ModuleSearchPath, "/tmp")
	mod, err := setupTestShellModule()

	require.NoError(t, err)
	require.NotNil(t, mod)

	fullPath, err := mod.Resolve()

	require.Error(t, err)
	require.Equal(t, "", fullPath, "Fullpath should have been empty")
}

func TestModuleDefaultExecOrder(t *testing.T) {
	mod, err := setupTestShellModule()

	require.NoError(t, err)
	require.NotNil(t, mod)

	execOrder, err := mod.ExecOrder()
	require.NoError(t, err)

	assert.Equal(t, "create_dir", execOrder[0], "Exec Order sequence is wrong for a default module")
	assert.Equal(t, "put_module", execOrder[1], "Exec Order sequence is wrong for a default module")
	assert.Equal(t, "exec_module", execOrder[2], "Exec Order sequence is wrong for a default module")
}

func TestModuleCopyExecOrder(t *testing.T) {
	writeTempFile([]byte("ls -al"), "copy")
	defer rmTempFile("/tmp/copy")
	mod, err := NewModule("copy", "src=foo dest=bar")

	require.NoError(t, err)
	require.NotNil(t, mod)

	execOrder, err := mod.ExecOrder()
	require.NoError(t, err)

	assert.Equal(t, "create_dir", execOrder[0], "Exec Order sequence is wrong for copy module")
	assert.Equal(t, "put_module", execOrder[1], "Exec Order sequence is wrong for copy module")
	assert.Equal(t, "put_file", execOrder[2], "Exec Order sequence is wrong for copy module")
	assert.Equal(t, "copy_remote", execOrder[3], "Exec Order sequence is wrong for copy module")
}

func TestModuleTemplateExecOrder(t *testing.T) {
	writeTempFile([]byte("ls -al"), "template")
	defer rmTempFile("/tmp/template")
	mod, err := NewModule("template", "src=foo dest=bar")

	require.NoError(t, err)
	require.NotNil(t, mod)

	execOrder, err := mod.ExecOrder()
	require.NoError(t, err)

	assert.Equal(t, "create_dir", execOrder[0], "Exec Order sequence is wrong for template module")
	assert.Equal(t, "put_module", execOrder[1], "Exec Order sequence is wrong for template module")
	assert.Equal(t, "process_template", execOrder[2], "Exec Order sequence is wrong for template module")
	assert.Equal(t, "put_file", execOrder[3], "Exec Order sequence is wrong for template module")
	assert.Equal(t, "copy_remote", execOrder[4], "Exec Order sequence is wrong for template module")
	assert.Equal(t, "reset_src", execOrder[5], "Exec Order sequence is wrong for template module")
	assert.Equal(t, "exec_module", execOrder[6], "Exec Order sequence is wrong for template module")
}
<commit_msg>fixed exec order test cases in modules_test.go<commit_after>package henchman

import (
	"io/ioutil"
	"os"
	"path"
	"testing"

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

func moduleTestSetup(modName string) (module *Module) {
	moduleContent := `
#!/usr/bin/env sh
ls -al $1
`
	writeTempFile([]byte(moduleContent), modName)

	mod, _ := NewModule(modName, "")
	return mod
}

func moduleTestTeardown(mod *Module) {
	os.Remove(path.Join("/tmp", mod.Name))
}

func TestValidModule(t *testing.T) {
	name := "shell"
	args := "cmd=\"ls -al\" foo=bar baz=☃"
	mod, err := NewModule(name, args)

	require.NoError(t, err)

	assert.Equal(t, name, mod.Name, "Module names should match")
	assert.Equal(t, "ls -al", mod.Params["cmd"], "Mod params wasn't initialized properly")
	assert.Equal(t, "bar", mod.Params["foo"], "Expected value for foo to be bar")
	assert.Equal(t, "☃", mod.Params["baz"], "Expected a snowman")
}

func TestValidModuleWithVariousChars(t *testing.T) {
	name := "shell"
	args := "cmd='ls -al' url=\"http://foo.com/abc\" baz='abc-def' test=\"sed -i 's,store.enable=true,store.enable=false,g'\""
	mod, err := NewModule(name, args)

	require.NoError(t, err)

	assert.Equal(t, name, mod.Name, "Module names should match")
	assert.Equal(t, "ls -al", mod.Params["cmd"], "Mod params wasn't initialized properly")
	assert.Equal(t, "http://foo.com/abc", mod.Params["url"], "Expected value for foo to be bar")
	assert.Equal(t, "abc-def", mod.Params["baz"], "Expected a snowman")
	assert.Equal(t, "sed -i s,store.enable=true,store.enable=false,g", mod.Params["test"], "Expected s,store.enable=true,store.enable=false,g")

}

func TestInvalidArgsModule(t *testing.T) {
	name := "invalid"
	args := "foo"
	_, err := NewModule(name, args)

	require.Error(t, err, "Module arg parsing should have failed")
}

func TestInvalidArgsModule2(t *testing.T) {
	name := "invalid"
	args := "foo bar=baz"
	_, err := NewModule(name, args)

	require.Error(t, err, "Module arg parsing should have failed")
}

func TestModuleResolve(t *testing.T) {
	origSearchPath := ModuleSearchPath
	ModuleSearchPath = append(ModuleSearchPath, "/tmp")
	defer func() {
		ModuleSearchPath = origSearchPath
	}()
	writeTempFile([]byte("ls -al"), "shell")
	defer rmTempFile("/tmp/shell")
	mod, err := NewModule("shell", "foo=bar")
	//mod, err := setupTestShellModule()

	require.NoError(t, err)
	require.NotNil(t, mod)

	fullPath, err := mod.Resolve()

	require.NoError(t, err)
	assert.Equal(t, "/tmp/shell", fullPath, "Got incorrect fullPath")

	err = os.Mkdir("/tmp/curl", 0777)
	assert.NoError(t, err)

	err = ioutil.WriteFile("/tmp/curl/exec", []byte("ls -al"), 0644)
	assert.NoError(t, err)
	defer os.RemoveAll("/tmp/curl")

	mod, err = NewModule("curl", "foo=bar")
	//mod, err := setupTestShellModule()
	require.NoError(t, err)
	require.NotNil(t, mod)

	fullPath, err = mod.Resolve()

	require.NoError(t, err)
	assert.Equal(t, "/tmp/curl", fullPath, "Got incorrect fullPath")
}

func setupTestShellModule() (*Module, error) {
	writeTempFile([]byte("ls -al"), "shell")
	defer rmTempFile("/tmp/shell")
	return NewModule("shell", "foo=bar")
}

func TestNonexistentModuleResolve(t *testing.T) {
	//ModuleSearchPath = append(ModuleSearchPath, "/tmp")
	mod, err := setupTestShellModule()

	require.NoError(t, err)
	require.NotNil(t, mod)

	fullPath, err := mod.Resolve()

	require.Error(t, err)
	require.Equal(t, "", fullPath, "Fullpath should have been empty")
}

func TestModuleDefaultExecOrder(t *testing.T) {
	mod, err := setupTestShellModule()

	require.NoError(t, err)
	require.NotNil(t, mod)

	execOrder, err := mod.ExecOrder()
	require.NoError(t, err)

	assert.Equal(t, "exec_module", execOrder[0], "Exec Order sequence is wrong for a default module")
}

func TestModuleCopyExecOrder(t *testing.T) {
	writeTempFile([]byte("ls -al"), "copy")
	defer rmTempFile("/tmp/copy")
	mod, err := NewModule("copy", "src=foo dest=bar")

	require.NoError(t, err)
	require.NotNil(t, mod)

	execOrder, err := mod.ExecOrder()
	require.NoError(t, err)

	assert.Equal(t, "put_file", execOrder[0], "Exec Order sequence is wrong for copy module")
	assert.Equal(t, "copy_remote", execOrder[1], "Exec Order sequence is wrong for copy module")
}

func TestModuleTemplateExecOrder(t *testing.T) {
	writeTempFile([]byte("ls -al"), "template")
	defer rmTempFile("/tmp/template")
	mod, err := NewModule("template", "src=foo dest=bar")

	require.NoError(t, err)
	require.NotNil(t, mod)

	execOrder, err := mod.ExecOrder()
	require.NoError(t, err)

	assert.Equal(t, "process_template", execOrder[0], "Exec Order sequence is wrong for template module")
	assert.Equal(t, "put_file", execOrder[1], "Exec Order sequence is wrong for template module")
	assert.Equal(t, "copy_remote", execOrder[2], "Exec Order sequence is wrong for template module")
	assert.Equal(t, "reset_src", execOrder[3], "Exec Order sequence is wrong for template module")
	assert.Equal(t, "exec_module", execOrder[4], "Exec Order sequence is wrong for template module")
}
<|endoftext|>


<commit_before>package main

import "math"
import "fmt"
import "image"
import "os"
import "image/color"
import "image/png"

// vector can represent a point as well, if interpreted as
//  a vector from the origin to a point or 'absolute position vector'.
//  otherwise it represents a 'relative position vector'
type vector struct {
	x, y, z float64
}

type ray struct {
	start vector
	direction vector
}

type camera struct {
	eye vector
	look_at vector
	up vector
}

type screen struct {
	w,h float64
	xres, yres int
}

type scene struct {
	center vector
	radius float64
}

func (v *vector) sub(v1 *vector) vector {
	return vector{v.x-v1.x, v.y-v1.y, v.z-v1.z}
}

func (v *vector) add(v1 *vector) vector {
	return vector{v.x+v1.x, v.y+v1.y, v.z+v1.z}
}

func (v *vector) scalarMult (c float64) vector {
	return vector{c * v.x, c * v.y, c * v.z}
}

func (v *vector) lengthSq() float64 {
	return v.x * v.x  + v.y * v.y + v.z * v.z
}

func (v *vector) length() float64 {
	return math.Sqrt(v.lengthSq())
}

func (v *vector) unit() vector {
	l := v.length()
	return vector{v.x/l, v.y/l, v.z/l}
}

func (v *vector) dot(v1 *vector) float64 {
	return v.x * v1.x + v.y * v1.y + v.z * v1.z
}

func (v1 *vector) cross(v2 *vector) vector {
	return vector{v1.y * v2.z - v2.y * v1.z,
		v2.x * v1.z - v1.x * v2.z,
		v1.x * v2.y - v2.x * v1.y}
}

func main() {
	fmt.Println("hi")
	g_screen := screen{100,100,1000,1000}
	g_camera := camera{vector{0,0,-10}, vector{0,0,0}, vector{0,1,0}}

	f, err := os.OpenFile("x.png", os.O_CREATE | os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	m := image.NewRGBA(image.Rect(0,0,g_screen.xres,g_screen.yres))

	for i:=0; i < g_screen.xres; i++ {
		for j:=0; j < g_screen.yres; j++ {
			a_to_e := g_camera.eye.sub(&g_camera.look_at)
			w := a_to_e.unit()

			up_X_a_to_e := g_camera.up.cross(&a_to_e)
			u := up_X_a_to_e.unit()
			v := w.cross(&u)

			cu := (((2.0*float64(i) + 1.0)/(2.0 * float64(g_screen.xres))) - 0.5) * g_screen.w
			cv := (((2.0*float64(j) + 1.0)/(2.0 * float64(g_screen.yres))) - 0.5) * g_screen.h

			ucu := u.scalarMult(cu)
			ucv := v.scalarMult(cv)
			a_plus_ucu := g_camera.look_at.add(&ucu)
			Pij := a_plus_ucu.add(&ucv)

			e_to_Pij := Pij.sub(&g_camera.eye)

			current_ray := ray{g_camera.eye, e_to_Pij.unit()}
			fmt.Println(current_ray)

			m.Set(i,j,color.RGBA{uint8(i%250*j%250),0,0,255})
		}
	}
	if err=png.Encode(f,m); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}<commit_msg>roughed in the computation for sphere intersection<commit_after>package main

import "math"
import "fmt"
import "image"
import "os"
import "image/color"
import "image/png"

// vector can represent a point as well, if interpreted as
//  a vector from the origin to a point or 'absolute position vector'.
//  otherwise it represents a 'relative position vector'
type vector struct {
	x, y, z float64
}

type ray struct {
	start vector
	direction vector
}

type camera struct {
	eye vector
	look_at vector
	up vector
}

type screen struct {
	w,h float64
	xres, yres int
}

type scene struct {
	center vector
	radius float64
}

func (v *vector) sub(v1 *vector) vector {
	return vector{v.x-v1.x, v.y-v1.y, v.z-v1.z}
}

func (v *vector) add(v1 *vector) vector {
	return vector{v.x+v1.x, v.y+v1.y, v.z+v1.z}
}

func (v *vector) scalarMult (c float64) vector {
	return vector{c * v.x, c * v.y, c * v.z}
}

func (v *vector) lengthSq() float64 {
	return v.x * v.x  + v.y * v.y + v.z * v.z
}

func (v *vector) length() float64 {
	return math.Sqrt(v.lengthSq())
}

func (v *vector) unit() vector {
	l := v.length()
	return vector{v.x/l, v.y/l, v.z/l}
}

func (v *vector) dot(v1 *vector) float64 {
	return v.x * v1.x + v.y * v1.y + v.z * v1.z
}

func (v1 *vector) cross(v2 *vector) vector {
	return vector{v1.y * v2.z - v2.y * v1.z,
		v2.x * v1.z - v1.x * v2.z,
		v1.x * v2.y - v2.x * v1.y}
}

func main() {
	fmt.Println("hi")
	g_screen := screen{100,100,1000,1000}
	g_camera := camera{vector{0,0,-10}, vector{0,0,0}, vector{0,1,0}}

	f, err := os.OpenFile("x.png", os.O_CREATE | os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	m := image.NewRGBA(image.Rect(0,0,g_screen.xres,g_screen.yres))

	for i:=0; i < g_screen.xres; i++ {
		for j:=0; j < g_screen.yres; j++ {
			a_to_e := g_camera.eye.sub(&g_camera.look_at)
			w := a_to_e.unit()

			up_X_a_to_e := g_camera.up.cross(&a_to_e)
			u := up_X_a_to_e.unit()
			v := w.cross(&u)

			cu := (((2.0*float64(i) + 1.0)/(2.0 * float64(g_screen.xres))) - 0.5) * g_screen.w
			cv := (((2.0*float64(j) + 1.0)/(2.0 * float64(g_screen.yres))) - 0.5) * g_screen.h

			ucu := u.scalarMult(cu)
			ucv := v.scalarMult(cv)
			a_plus_ucu := g_camera.look_at.add(&ucu)
			Pij := a_plus_ucu.add(&ucv)

			e_to_Pij := Pij.sub(&g_camera.eye)

			current_ray := ray{g_camera.eye, e_to_Pij.unit()}

			// put the sphere at the origin
			xc := 0.0
			yc := 0.0
			zc := 0.0
			r := 5.0
			a := current_ray.direction.x * current_ray.direction.x +
				current_ray.direction.y * current_ray.direction.y +
				current_ray.direction.z * current_ray.direction.z
			b := 2*((current_ray.start.x-xc)*current_ray.direction.x +
				(current_ray.start.y-yc)*current_ray.direction.y +
				(current_ray.start.z-zc)*current_ray.direction.z)
			c := (current_ray.start.x-xc) * (current_ray.start.x-xc) +
				(current_ray.start.y-yc) * (current_ray.start.y-yc) +
				(current_ray.start.z-zc) * (current_ray.start.z-zc) -
				r * r

			// test with a sphere
			if sphere_test:=b*b-4*a*c ; sphere_test > 0.0 {
				m.Set(i,j,color.RGBA{255,0,0,255})
			}else {
				m.Set(i,j,color.RGBA{0,0,0,255})
			}
		}
	}
	if err=png.Encode(f,m); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}<|endoftext|>


<commit_before>package gherkin

const VERSION = "v0.1.0"
<commit_msg>version bump v0.1.1<commit_after>package gherkin

const VERSION = "v0.1.1"
<|endoftext|>