<commit_before>/*
Copyright 2019 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 out provides a mechanism for sending localized, stylized output to the console.
package out

import (
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"

	"github.com/golang/glog"
	isatty "github.com/mattn/go-isatty"
	"k8s.io/minikube/pkg/minikube/out/register"
	"k8s.io/minikube/pkg/minikube/translate"
)

// By design, this package uses global references to language and output objects, in preference
// to passing a console object throughout the code base. Typical usage is:
//
// out.SetOutFile(os.Stdout)
// out.String("Starting up!")
// out.T(out.StatusChange, "Configuring things")

// out.SetErrFile(os.Stderr)
// out.Fatal("Oh no, everything failed.")

// NOTE: If you do not want colorized output, set MINIKUBE_IN_STYLE=false in your environment.

var (
	// outFile is where Out* functions send output to. Set using SetOutFile()
	outFile fdWriter
	// errFile is where Err* functions send output to. Set using SetErrFile()
	errFile fdWriter
	// useColor is whether or not color output should be used, updated by Set*Writer.
	useColor = false
	// OverrideEnv is the environment variable used to override color/emoji usage
	OverrideEnv = "MINIKUBE_IN_STYLE"
	// JSON is whether or not we should output stdout in JSON format. Set using SetJSON()
	JSON = false
)

// MaxLogEntries controls the number of log entries to show for each source
const MaxLogEntries = 3

// fdWriter is the subset of file.File that implements io.Writer and Fd()
type fdWriter interface {
	io.Writer
	Fd() uintptr
}

// V is a convenience wrapper for templating, it represents the variable key/value pair.
type V map[string]interface{}

// T writes a stylized and templated message to stdout
func T(style StyleEnum, format string, a ...V) {
	if style == Option {
		Infof(format, a...)
		return
	}
	outStyled := ApplyTemplateFormatting(style, useColor, format, a...)
	if JSON {
		register.PrintStep(outStyled)
		return
	}
	register.RecordStep(outStyled)
	String(outStyled)
}

// Infof is used for informational logs (options, env variables, etc)
func Infof(format string, a ...V) {
	outStyled := ApplyTemplateFormatting(Option, useColor, format, a...)
	if JSON {
		register.PrintInfo(outStyled)
		return
	}
	String(outStyled)
}

// String writes a basic formatted string to stdout
func String(format string, a ...interface{}) {
	// Flush log buffer so that output order makes sense
	glog.Flush()

	if outFile == nil {
		glog.Warningf("[unset outFile]: %s", fmt.Sprintf(format, a...))
		return
	}
	_, err := fmt.Fprintf(outFile, format, a...)
	if err != nil {
		glog.Errorf("Fprintf failed: %v", err)
	}
}

// Ln writes a basic formatted string with a newline to stdout
func Ln(format string, a ...interface{}) {
	if JSON {
		glog.Warningf("please use out.T to log steps in JSON")
		return
	}
	String(format+"\n", a...)
}

// ErrWithExitCode includes the exit code in JSON output
func ErrWithExitCode(style StyleEnum, format string, exitcode int, a ...V) {
	if JSON {
		errStyled := ApplyTemplateFormatting(style, useColor, format, a...)
		register.PrintErrorExitCode(errStyled, exitcode)
		return
	}
	ErrT(style, format, a...)
}

// ErrT writes a stylized and templated error message to stderr
func ErrT(style StyleEnum, format string, a ...V) {
	errStyled := ApplyTemplateFormatting(style, useColor, format, a...)
	Err(errStyled)
}

// Err writes a basic formatted string to stderr
func Err(format string, a ...interface{}) {
	if JSON {
		register.PrintError(format)
		return
	}
	register.RecordError(format)

	if errFile == nil {
		glog.Errorf("[unset errFile]: %s", fmt.Sprintf(format, a...))
		return
	}
	_, err := fmt.Fprintf(errFile, format, a...)
	if err != nil {
		glog.Errorf("Fprint failed: %v", err)
	}
}

// ErrLn writes a basic formatted string with a newline to stderr
func ErrLn(format string, a ...interface{}) {
	Err(format+"\n", a...)
}

// SuccessT is a shortcut for writing a templated success message to stdout
func SuccessT(format string, a ...V) {
	T(SuccessType, format, a...)
}

// FatalT is a shortcut for writing a templated fatal message to stderr
func FatalT(format string, a ...V) {
	ErrT(FatalType, format, a...)
}

// WarningT is a shortcut for writing a templated warning message to stderr
func WarningT(format string, a ...V) {
	if JSON {
		register.PrintWarning(ApplyTemplateFormatting(Warning, useColor, format, a...))
		return
	}
	ErrT(Warning, format, a...)
}

// FailureT is a shortcut for writing a templated failure message to stderr
func FailureT(format string, a ...V) {
	ErrT(FailureType, format, a...)
}

// SetOutFile configures which writer standard output goes to.
func SetOutFile(w fdWriter) {
	glog.Infof("Setting OutFile to fd %d ...", w.Fd())
	outFile = w
	useColor = wantsColor(w.Fd())
}

// SetJSON configures printing to STDOUT in JSON
func SetJSON(j bool) {
	glog.Infof("Setting JSON to %v", j)
	JSON = j
}

// SetErrFile configures which writer error output goes to.
func SetErrFile(w fdWriter) {
	glog.Infof("Setting ErrFile to fd %d...", w.Fd())
	errFile = w
	useColor = wantsColor(w.Fd())
}

// wantsColor determines if the user might want colorized output.
func wantsColor(fd uintptr) bool {
	// First process the environment: we allow users to force colors on or off.
	//
	// MINIKUBE_IN_STYLE=[1, T, true, TRUE]
	// MINIKUBE_IN_STYLE=[0, f, false, FALSE]
	//
	// If unset, we try to automatically determine suitability from the environment.
	val := os.Getenv(OverrideEnv)
	if val != "" {
		glog.Infof("%s=%q\n", OverrideEnv, os.Getenv(OverrideEnv))
		override, err := strconv.ParseBool(val)
		if err != nil {
			// That's OK, we will just fall-back to automatic detection.
			glog.Errorf("ParseBool(%s): %v", OverrideEnv, err)
		} else {
			return override
		}
	}

	term := os.Getenv("TERM")
	colorTerm := os.Getenv("COLORTERM")
	// Example: term-256color
	if !strings.Contains(term, "color") && !strings.Contains(colorTerm, "truecolor") && !strings.Contains(colorTerm, "24bit") && !strings.Contains(colorTerm, "yes") {
		glog.Infof("TERM=%s,COLORTERM=%s, which probably does not support color", term, colorTerm)
		return false
	}

	isT := isatty.IsTerminal(fd)
	glog.Infof("isatty.IsTerminal(%d) = %v\n", fd, isT)
	return isT
}

// LogEntries outputs an error along with any important log entries.
func LogEntries(msg string, err error, entries map[string][]string) {
	DisplayError(msg, err)

	for name, lines := range entries {
		T(FailureType, "Problems detected in {{.entry}}:", V{"entry": name})
		if len(lines) > MaxLogEntries {
			lines = lines[:MaxLogEntries]
		}
		for _, l := range lines {
			T(LogEntry, l)
		}
	}
}

// DisplayError prints the error and displays the standard minikube error messaging
func DisplayError(msg string, err error) {
	glog.Warningf(fmt.Sprintf("%s: %v", msg, err))
	if JSON {
		FatalT("{{.msg}}: {{.err}}", V{"msg": translate.T(msg), "err": err})
		return
	}
	// use Warning because Error will display a duplicate message to stderr
	ErrT(Empty, "")
	FatalT("{{.msg}}: {{.err}}", V{"msg": translate.T(msg), "err": err})
	ErrT(Empty, "")
	ErrT(Sad, "minikube is exiting due to an error. If the above message is not useful, open an issue:")
	ErrT(URL, "https://github.com/kubernetes/minikube/issues/new/choose")
}
<commit_msg>Log output for post-mortem analysis<commit_after>/*
Copyright 2019 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 out provides a mechanism for sending localized, stylized output to the console.
package out

import (
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"

	"github.com/golang/glog"
	isatty "github.com/mattn/go-isatty"
	"k8s.io/minikube/pkg/minikube/out/register"
	"k8s.io/minikube/pkg/minikube/translate"
)

// By design, this package uses global references to language and output objects, in preference
// to passing a console object throughout the code base. Typical usage is:
//
// out.SetOutFile(os.Stdout)
// out.String("Starting up!")
// out.T(out.StatusChange, "Configuring things")

// out.SetErrFile(os.Stderr)
// out.Fatal("Oh no, everything failed.")

// NOTE: If you do not want colorized output, set MINIKUBE_IN_STYLE=false in your environment.

var (
	// outFile is where Out* functions send output to. Set using SetOutFile()
	outFile fdWriter
	// errFile is where Err* functions send output to. Set using SetErrFile()
	errFile fdWriter
	// useColor is whether or not color output should be used, updated by Set*Writer.
	useColor = false
	// OverrideEnv is the environment variable used to override color/emoji usage
	OverrideEnv = "MINIKUBE_IN_STYLE"
	// JSON is whether or not we should output stdout in JSON format. Set using SetJSON()
	JSON = false
)

// MaxLogEntries controls the number of log entries to show for each source
const MaxLogEntries = 3

// fdWriter is the subset of file.File that implements io.Writer and Fd()
type fdWriter interface {
	io.Writer
	Fd() uintptr
}

// V is a convenience wrapper for templating, it represents the variable key/value pair.
type V map[string]interface{}

// T writes a stylized and templated message to stdout
func T(style StyleEnum, format string, a ...V) {
	if style == Option {
		Infof(format, a...)
		return
	}
	outStyled := ApplyTemplateFormatting(style, useColor, format, a...)
	if JSON {
		register.PrintStep(outStyled)
		return
	}
	register.RecordStep(outStyled)
	String(outStyled)
}

// Infof is used for informational logs (options, env variables, etc)
func Infof(format string, a ...V) {
	outStyled := ApplyTemplateFormatting(Option, useColor, format, a...)
	if JSON {
		register.PrintInfo(outStyled)
		return
	}
	String(outStyled)
}

// String writes a basic formatted string to stdout
func String(format string, a ...interface{}) {
	// Flush log buffer so that output order makes sense
	glog.Flush()

	if outFile == nil {
		glog.Warningf("[unset outFile]: %s", fmt.Sprintf(format, a...))
		return
	}

	glog.Infof(format, a...)

	_, err := fmt.Fprintf(outFile, format, a...)
	if err != nil {
		glog.Errorf("Fprintf failed: %v", err)
	}
}

// Ln writes a basic formatted string with a newline to stdout
func Ln(format string, a ...interface{}) {
	if JSON {
		glog.Warningf("please use out.T to log steps in JSON")
		return
	}
	String(format+"\n", a...)
}

// ErrWithExitCode includes the exit code in JSON output
func ErrWithExitCode(style StyleEnum, format string, exitcode int, a ...V) {
	if JSON {
		errStyled := ApplyTemplateFormatting(style, useColor, format, a...)
		register.PrintErrorExitCode(errStyled, exitcode)
		return
	}
	ErrT(style, format, a...)
}

// ErrT writes a stylized and templated error message to stderr
func ErrT(style StyleEnum, format string, a ...V) {
	errStyled := ApplyTemplateFormatting(style, useColor, format, a...)
	Err(errStyled)
}

// Err writes a basic formatted string to stderr
func Err(format string, a ...interface{}) {
	if JSON {
		register.PrintError(format)
		return
	}
	register.RecordError(format)

	if errFile == nil {
		glog.Errorf("[unset errFile]: %s", fmt.Sprintf(format, a...))
		return
	}

	glog.Warningf(format, a...)

	_, err := fmt.Fprintf(errFile, format, a...)
	if err != nil {
		glog.Errorf("Fprint failed: %v", err)
	}
}

// ErrLn writes a basic formatted string with a newline to stderr
func ErrLn(format string, a ...interface{}) {
	Err(format+"\n", a...)
}

// SuccessT is a shortcut for writing a templated success message to stdout
func SuccessT(format string, a ...V) {
	T(SuccessType, format, a...)
}

// FatalT is a shortcut for writing a templated fatal message to stderr
func FatalT(format string, a ...V) {
	ErrT(FatalType, format, a...)
}

// WarningT is a shortcut for writing a templated warning message to stderr
func WarningT(format string, a ...V) {
	if JSON {
		register.PrintWarning(ApplyTemplateFormatting(Warning, useColor, format, a...))
		return
	}
	ErrT(Warning, format, a...)
}

// FailureT is a shortcut for writing a templated failure message to stderr
func FailureT(format string, a ...V) {
	ErrT(FailureType, format, a...)
}

// SetOutFile configures which writer standard output goes to.
func SetOutFile(w fdWriter) {
	glog.Infof("Setting OutFile to fd %d ...", w.Fd())
	outFile = w
	useColor = wantsColor(w.Fd())
}

// SetJSON configures printing to STDOUT in JSON
func SetJSON(j bool) {
	glog.Infof("Setting JSON to %v", j)
	JSON = j
}

// SetErrFile configures which writer error output goes to.
func SetErrFile(w fdWriter) {
	glog.Infof("Setting ErrFile to fd %d...", w.Fd())
	errFile = w
	useColor = wantsColor(w.Fd())
}

// wantsColor determines if the user might want colorized output.
func wantsColor(fd uintptr) bool {
	// First process the environment: we allow users to force colors on or off.
	//
	// MINIKUBE_IN_STYLE=[1, T, true, TRUE]
	// MINIKUBE_IN_STYLE=[0, f, false, FALSE]
	//
	// If unset, we try to automatically determine suitability from the environment.
	val := os.Getenv(OverrideEnv)
	if val != "" {
		glog.Infof("%s=%q\n", OverrideEnv, os.Getenv(OverrideEnv))
		override, err := strconv.ParseBool(val)
		if err != nil {
			// That's OK, we will just fall-back to automatic detection.
			glog.Errorf("ParseBool(%s): %v", OverrideEnv, err)
		} else {
			return override
		}
	}

	term := os.Getenv("TERM")
	colorTerm := os.Getenv("COLORTERM")
	// Example: term-256color
	if !strings.Contains(term, "color") && !strings.Contains(colorTerm, "truecolor") && !strings.Contains(colorTerm, "24bit") && !strings.Contains(colorTerm, "yes") {
		glog.Infof("TERM=%s,COLORTERM=%s, which probably does not support color", term, colorTerm)
		return false
	}

	isT := isatty.IsTerminal(fd)
	glog.Infof("isatty.IsTerminal(%d) = %v\n", fd, isT)
	return isT
}

// LogEntries outputs an error along with any important log entries.
func LogEntries(msg string, err error, entries map[string][]string) {
	DisplayError(msg, err)

	for name, lines := range entries {
		T(FailureType, "Problems detected in {{.entry}}:", V{"entry": name})
		if len(lines) > MaxLogEntries {
			lines = lines[:MaxLogEntries]
		}
		for _, l := range lines {
			T(LogEntry, l)
		}
	}
}

// DisplayError prints the error and displays the standard minikube error messaging
func DisplayError(msg string, err error) {
	glog.Warningf(fmt.Sprintf("%s: %v", msg, err))
	if JSON {
		FatalT("{{.msg}}: {{.err}}", V{"msg": translate.T(msg), "err": err})
		return
	}
	// use Warning because Error will display a duplicate message to stderr
	ErrT(Empty, "")
	FatalT("{{.msg}}: {{.err}}", V{"msg": translate.T(msg), "err": err})
	ErrT(Empty, "")
	ErrT(Sad, "minikube is exiting due to an error. If the above message is not useful, open an issue:")
	ErrT(URL, "https://github.com/kubernetes/minikube/issues/new/choose")
}
<|endoftext|>


<commit_before>package util

import (
	"bytes"
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"github.com/docker/docker/pkg/archive"
	"github.com/minio/minio-go"
	"io"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"os/exec"
	"path"
	"time"
)

type MinioConfig struct {
	AccessKey        string
	AccessSecret     string
	Host             string
	CvmfsRepo        string
	SSL              bool
	PublishStatusURL string
}

var minioConfig = readConfig()

func readConfig() (config MinioConfig) {
	fmt.Println("reading minio config")

	var out []byte
	var err error

	if out, err = ioutil.ReadFile("/minio_ext_config/config.json"); err != nil {
		fmt.Println("Failed to read minio config.")
		fmt.Println(err)
		return
	}
	if err = json.Unmarshal(out, &config); err != nil {
		fmt.Println("Failed to parse minio config.")
		fmt.Println(err)
		return
	}

	fmt.Println("Minio config read successfully!")
	sc, _ := json.MarshalIndent(config, "", "    ")
	fmt.Println(string(sc))

	return config
}

func move(src string) (string, error) {
	rand.Seed(time.Now().UTC().UnixNano())
	tmp := path.Join(os.TempDir(), fmt.Sprintf("dlcg-%d", rand.Int()))

	if err := os.MkdirAll(tmp, os.ModePerm); err != nil {
		fmt.Println("Failed to create tmp!")
		return "", err
	}

	var out bytes.Buffer
	cmd := fmt.Sprintf("mv %s/* %s", src, tmp)
	c := exec.Command("bash", "-c", cmd)
	c.Stdout = &out
	if err := c.Run(); err != nil {
		fmt.Println("Failed to move!")
		return "", err
	}

	return tmp, nil
}

func tar(src string) (string, error) {
	dstFile, err := ioutil.TempFile(os.TempDir(), "dlcg-tar-")
	defer dstFile.Close()

	if err != nil {
		fmt.Println("Failed to create temp file for tar.")
		return "", err
	}

	tarReader, err := archive.Tar(src, archive.Gzip)
	if err != nil {
		fmt.Println("Failed to create tar stream")
		return "", err
	}

	io.Copy(dstFile, tarReader)

	return dstFile.Name(), nil
}

func sha256hash(src string) (string, error) {
	tarFile, err := os.Open(src)
	defer tarFile.Close()

	if err != nil {
		fmt.Println("Failed to open file in hash()")
		return "", err
	}

	h := sha256.New()
	io.Copy(h, tarFile)
	s := fmt.Sprintf("%x", h.Sum(nil))

	return s, nil
}

func upload(src, h string) error {
	minioClient, err := minio.New(
		minioConfig.Host,
		minioConfig.AccessKey,
		minioConfig.AccessSecret,
		minioConfig.SSL)

	if err != nil {
		fmt.Println("Failed to create a minio client!")
		return err
	}

	_, err = minioClient.FPutObject("layers", h, src, "application/x-gzip")
	if err != nil {
		fmt.Println("Failed call to FPutObject()")
		return err
	}

	return nil
}

func waitForPublishing(hash string) (err error) {
	for {
		target := minioConfig.PublishStatusURL + "/" + hash
		fmt.Println("waiting for publish.....")
		fmt.Println(target)

		client := http.Client{Timeout: time.Duration(2 * time.Second)}
		resp, err := client.Get(target)
		fmt.Println("got response")

		if err != nil {
			fmt.Println(err)
			return err
		}

		defer resp.Body.Close()
		buf, err := ioutil.ReadAll(resp.Body)
		body := string(buf)

		if resp.StatusCode != 200 {
			fmt.Println("Request failed, abort.")
			fmt.Println(body)
			return fmt.Errorf("status request failed, abort.")
		}

		if body == "publishing" {
			fmt.Println("Still publishing...")
			time.Sleep(1 * time.Second)
		} else if body == "done" {
			fmt.Println("Publishing done!")
			return nil
		} else if body == "unknown" {
			fmt.Println("Unknown publish status, abort.")
			return fmt.Errorf("Unknown publish status, abort.")
		} else {
			fmt.Println("Unknown reponse, abort.")
			fmt.Println(body)
			return fmt.Errorf("Unknown publish status response, abort.")
		}

	}

}

func (cm *cvmfsManager) UploadNewLayer(orig string) (layer ThinImageLayer, err error) {
	tarFileName, err := tar(orig)

	if err != nil {
		fmt.Printf("Failed to create tar: %s\n", err.Error())
		return layer, err
	}

	h, err := sha256hash(tarFileName)
	if err != nil {
		fmt.Printf("Failed to calculate hash: %s\n", err.Error())
		return layer, err
	}

	if err := upload(tarFileName, h); err != nil {
		fmt.Printf("Failed to upload: %s\n", err.Error())
		return layer, err
	}

	if err := os.Remove(tarFileName); err != nil {
		fmt.Printf("Couldn't remove the uploaded tmp tar.")
	}

	fmt.Println("Wait for it!")
	if err := waitForPublishing(h); err != nil {
		return layer, err
	}

	if err := cm.Remount(minioConfig.CvmfsRepo); err != nil {
		fmt.Printf("Failed to remount cvmfs repo: %s\n", err.Error())
		return layer, err
	}

	layer.Digest = h
	layer.Repo = minioConfig.CvmfsRepo

	return layer, nil
}
<commit_msg>Enable layer reuploading<commit_after>package util

import (
	"bytes"
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"github.com/docker/docker/pkg/archive"
	"github.com/minio/minio-go"
	"io"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"os/exec"
	"path"
	"time"
)

type MinioConfig struct {
	AccessKey        string
	AccessSecret     string
	Host             string
	CvmfsRepo        string
	SSL              bool
	PublishStatusURL string
}

var minioConfig = readConfig()

func readConfig() (config MinioConfig) {
	fmt.Println("reading minio config")

	var out []byte
	var err error

	if out, err = ioutil.ReadFile("/minio_ext_config/config.json"); err != nil {
		fmt.Println("Failed to read minio config.")
		fmt.Println(err)
		return
	}
	if err = json.Unmarshal(out, &config); err != nil {
		fmt.Println("Failed to parse minio config.")
		fmt.Println(err)
		return
	}

	fmt.Println("Minio config read successfully!")
	sc, _ := json.MarshalIndent(config, "", "    ")
	fmt.Println(string(sc))

	return config
}

func move(src string) (string, error) {
	rand.Seed(time.Now().UTC().UnixNano())
	tmp := path.Join(os.TempDir(), fmt.Sprintf("dlcg-%d", rand.Int()))

	if err := os.MkdirAll(tmp, os.ModePerm); err != nil {
		fmt.Println("Failed to create tmp!")
		return "", err
	}

	var out bytes.Buffer
	cmd := fmt.Sprintf("mv %s/* %s", src, tmp)
	c := exec.Command("bash", "-c", cmd)
	c.Stdout = &out
	if err := c.Run(); err != nil {
		fmt.Println("Failed to move!")
		return "", err
	}

	return tmp, nil
}

func tar(src string) (string, error) {
	dstFile, err := ioutil.TempFile(os.TempDir(), "dlcg-tar-")
	defer dstFile.Close()

	if err != nil {
		fmt.Println("Failed to create temp file for tar.")
		return "", err
	}

	tarReader, err := archive.Tar(src, archive.Gzip)
	if err != nil {
		fmt.Println("Failed to create tar stream")
		return "", err
	}

	io.Copy(dstFile, tarReader)

	return dstFile.Name(), nil
}

func sha256hash(src string) (string, error) {
	tarFile, err := os.Open(src)
	defer tarFile.Close()

	if err != nil {
		fmt.Println("Failed to open file in hash()")
		return "", err
	}

	h := sha256.New()
	io.Copy(h, tarFile)
	s := fmt.Sprintf("%x", h.Sum(nil))

	return s, nil
}

func upload(src, h string) error {
	minioClient, err := minio.New(
		minioConfig.Host,
		minioConfig.AccessKey,
		minioConfig.AccessSecret,
		minioConfig.SSL)

	if err != nil {
		fmt.Println("Failed to create a minio client!")
		return err
	}

	for i := 0; i < 5; i++ {
		_, err = minioClient.FPutObject("layers", h, src, "application/x-gzip")
		if err != nil {
			fmt.Printf("Failed FPutObject(), this was attempt %d\n", i)
		} else {
			fmt.Printf("Upload successful, attempt %d\n!", i)
			return nil
		}
	}

	return fmt.Errorf("Failed to upload layer %s with hash %s\n", src, h)
}

func waitForPublishing(hash string) (err error) {
	for {
		target := minioConfig.PublishStatusURL + "/" + hash
		fmt.Println("waiting for publish.....")
		fmt.Println(target)

		client := http.Client{Timeout: time.Duration(2 * time.Second)}
		resp, err := client.Get(target)
		fmt.Println("got response")

		if err != nil {
			fmt.Println(err)
			return err
		}

		defer resp.Body.Close()
		buf, err := ioutil.ReadAll(resp.Body)
		body := string(buf)

		if resp.StatusCode != 200 {
			fmt.Println("Request failed, abort.")
			fmt.Println(body)
			return fmt.Errorf("status request failed, abort.")
		}

		if body == "publishing" {
			fmt.Println("Still publishing...")
			time.Sleep(1 * time.Second)
		} else if body == "done" {
			fmt.Println("Publishing done!")
			return nil
		} else if body == "unknown" {
			fmt.Println("Unknown publish status, abort.")
			return fmt.Errorf("Unknown publish status, abort.")
		} else {
			fmt.Println("Unknown reponse, abort.")
			fmt.Println(body)
			return fmt.Errorf("Unknown publish status response, abort.")
		}

	}

}

func (cm *cvmfsManager) UploadNewLayer(orig string) (layer ThinImageLayer, err error) {
	tarFileName, err := tar(orig)

	if err != nil {
		fmt.Printf("Failed to create tar: %s\n", err.Error())
		return layer, err
	}

	h, err := sha256hash(tarFileName)
	if err != nil {
		fmt.Printf("Failed to calculate hash: %s\n", err.Error())
		return layer, err
	}

	fmt.Printf("Uploading file: %s\n", tarFileName)
	if err := upload(tarFileName, h); err != nil {
		fmt.Printf("Failed to upload: %s\n", err.Error())
		return layer, err
	}

	if err := os.Remove(tarFileName); err != nil {
		fmt.Printf("Couldn't remove the uploaded tmp tar.")
	}

	fmt.Println("Wait for it!")
	if err := waitForPublishing(h); err != nil {
		return layer, err
	}

	if err := cm.Remount(minioConfig.CvmfsRepo); err != nil {
		fmt.Printf("Failed to remount cvmfs repo: %s\n", err.Error())
		return layer, err
	}

	layer.Digest = h
	layer.Repo = minioConfig.CvmfsRepo

	return layer, nil
}
<|endoftext|>


<commit_before>package keeper

import (
	"github.com/cosmos/cosmos-sdk/store/prefix"
	sdk "github.com/cosmos/cosmos-sdk/types"
	"github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types"
)

// SetRevokedAccount set a specific revokedAccount in the store from its index.
func (k Keeper) SetRevokedAccount(ctx sdk.Context, revokedAccount types.RevokedAccount) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))
	b := k.cdc.MustMarshal(&revokedAccount)
	store.Set(types.RevokedAccountKey(
		revokedAccount.GetAddress(),
	), b)
}

// GetRevokedAccount returns a revokedAccount from its index.
func (k Keeper) GetRevokedAccount(
	ctx sdk.Context,
	address sdk.AccAddress,
) (val types.RevokedAccount, found bool) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))

	b := store.Get(types.RevokedAccountKey(
		address,
	))
	if b == nil {
		return val, false
	}

	k.cdc.MustUnmarshal(b, &val)

	return val, true
}

// RemoveRevokedAccount removes a revokedAccount from the store.
func (k Keeper) RemoveRevokedAccount(
	ctx sdk.Context,
	address sdk.AccAddress,
) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))
	store.Delete(types.RevokedAccountKey(
		address,
	))
}

// GetAllRevokedAccount returns all revokedAccount.
func (k Keeper) GetAllRevokedAccount(ctx sdk.Context) (list []types.RevokedAccount) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))
	iterator := sdk.KVStorePrefixIterator(store, []byte{})

	defer iterator.Close()

	for ; iterator.Valid(); iterator.Next() {
		var val types.RevokedAccount
		k.cdc.MustUnmarshal(iterator.Value(), &val)
		list = append(list, val)
	}

	return
}
<commit_msg>Create function for moving account to entity revoked account<commit_after>package keeper

import (
	"github.com/cosmos/cosmos-sdk/store/prefix"
	sdk "github.com/cosmos/cosmos-sdk/types"
	"github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types"
)

// SetRevokedAccount set a specific revokedAccount in the store from its index.
func (k Keeper) SetRevokedAccount(ctx sdk.Context, revokedAccount types.RevokedAccount) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))
	b := k.cdc.MustMarshal(&revokedAccount)
	store.Set(types.RevokedAccountKey(
		revokedAccount.GetAddress(),
	), b)
}

// GetRevokedAccount returns a revokedAccount from its index.
func (k Keeper) GetRevokedAccount(
	ctx sdk.Context,
	address sdk.AccAddress,
) (val types.RevokedAccount, found bool) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))

	b := store.Get(types.RevokedAccountKey(
		address,
	))
	if b == nil {
		return val, false
	}

	k.cdc.MustUnmarshal(b, &val)

	return val, true
}

// RemoveRevokedAccount removes a revokedAccount from the store.
func (k Keeper) RemoveRevokedAccount(
	ctx sdk.Context,
	address sdk.AccAddress,
) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))
	store.Delete(types.RevokedAccountKey(
		address,
	))
}

// GetAllRevokedAccount returns all revokedAccount.
func (k Keeper) GetAllRevokedAccount(ctx sdk.Context) (list []types.RevokedAccount) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))
	iterator := sdk.KVStorePrefixIterator(store, []byte{})

	defer iterator.Close()

	for ; iterator.Valid(); iterator.Next() {
		var val types.RevokedAccount
		k.cdc.MustUnmarshal(iterator.Value(), &val)
		list = append(list, val)
	}

	return
}

func (k Keeper) MoveAccountToRevokeAccount(
	ctx sdk.Context, accAddr sdk.AccAddress,
	approvals []*types.Grant,
	reason types.RevokedAccount_Reason,
) (*types.RevokedAccount, error) {
	// get account
	account, ok := k.GetAccountO(ctx, accAddr)

	// check we can get that account or can not
	if !ok {
		return nil, types.ErrAccountDoesNotExist(accAddr)
	}

	// create revoked account record
	revokedAccount := types.NewRevokedAccount(&account, approvals)
	revokedAccount.Reason = reason

	return revokedAccount, nil
}
<|endoftext|>


<commit_before>package keeper

import (
	"github.com/cosmos/cosmos-sdk/store/prefix"
	sdk "github.com/cosmos/cosmos-sdk/types"
	"github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types"
)

const (
	RevokedReasonIsRevokedAccount    = "Revoked account"
	RevokedReasonIsValidatorDisabled = "Validator disabled"
)

// SetRevokedAccount set a specific revokedAccount in the store from its index.
func (k Keeper) SetRevokedAccount(ctx sdk.Context, revokedAccount types.RevokedAccount) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))
	b := k.cdc.MustMarshal(&revokedAccount)
	store.Set(types.RevokedAccountKey(
		revokedAccount.GetAddress(),
	), b)
}

// GetRevokedAccount returns a revokedAccount from its index.
func (k Keeper) GetRevokedAccount(
	ctx sdk.Context,
	address sdk.AccAddress,
) (val types.RevokedAccount, found bool) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))

	b := store.Get(types.RevokedAccountKey(
		address,
	))
	if b == nil {
		return val, false
	}

	k.cdc.MustUnmarshal(b, &val)

	return val, true
}

// RemoveRevokedAccount removes a revokedAccount from the store.
func (k Keeper) RemoveRevokedAccount(
	ctx sdk.Context,
	address sdk.AccAddress,
) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))
	store.Delete(types.RevokedAccountKey(
		address,
	))
}

// GetAllRevokedAccount returns all revokedAccount.
func (k Keeper) GetAllRevokedAccount(ctx sdk.Context) (list []types.RevokedAccount) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))
	iterator := sdk.KVStorePrefixIterator(store, []byte{})

	defer iterator.Close()

	for ; iterator.Valid(); iterator.Next() {
		var val types.RevokedAccount
		k.cdc.MustUnmarshal(iterator.Value(), &val)
		list = append(list, val)
	}

	return
}
<commit_msg>Remove unused constants<commit_after>package keeper

import (
	"github.com/cosmos/cosmos-sdk/store/prefix"
	sdk "github.com/cosmos/cosmos-sdk/types"
	"github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types"
)

// SetRevokedAccount set a specific revokedAccount in the store from its index.
func (k Keeper) SetRevokedAccount(ctx sdk.Context, revokedAccount types.RevokedAccount) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))
	b := k.cdc.MustMarshal(&revokedAccount)
	store.Set(types.RevokedAccountKey(
		revokedAccount.GetAddress(),
	), b)
}

// GetRevokedAccount returns a revokedAccount from its index.
func (k Keeper) GetRevokedAccount(
	ctx sdk.Context,
	address sdk.AccAddress,
) (val types.RevokedAccount, found bool) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))

	b := store.Get(types.RevokedAccountKey(
		address,
	))
	if b == nil {
		return val, false
	}

	k.cdc.MustUnmarshal(b, &val)

	return val, true
}

// RemoveRevokedAccount removes a revokedAccount from the store.
func (k Keeper) RemoveRevokedAccount(
	ctx sdk.Context,
	address sdk.AccAddress,
) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))
	store.Delete(types.RevokedAccountKey(
		address,
	))
}

// GetAllRevokedAccount returns all revokedAccount.
func (k Keeper) GetAllRevokedAccount(ctx sdk.Context) (list []types.RevokedAccount) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RevokedAccountKeyPrefix))
	iterator := sdk.KVStorePrefixIterator(store, []byte{})

	defer iterator.Close()

	for ; iterator.Valid(); iterator.Next() {
		var val types.RevokedAccount
		k.cdc.MustUnmarshal(iterator.Value(), &val)
		list = append(list, val)
	}

	return
}
<|endoftext|>


<commit_before>//  Copyright (c) 2012 Couchbase, Inc.
//  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 auth

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"regexp"

	"code.google.com/p/go.crypto/bcrypt"

	"github.com/couchbaselabs/sync_gateway/base"
	ch "github.com/couchbaselabs/sync_gateway/channels"
)

const kBcryptCostFactor = bcrypt.DefaultCost

// Actual implementation of User interface
type userImpl struct {
	roleImpl // userImpl "inherits from" Role
	userImplBody
	auth  *Authenticator
	roles []Role
}

// Marshalable data is stored in separate struct from userImpl,
// to work around limitations of JSON marshaling.
type userImplBody struct {
	Email_           string      `json:"email,omitempty"`
	Disabled_        bool        `json:"disabled,omitempty"`
	PasswordHash_    []byte      `json:"passwordhash_bcrypt,omitempty"`
	OldPasswordHash_ interface{} `json:"passwordhash,omitempty"` // For pre-beta compatibility
	ExplicitRoles_   ch.TimedSet `json:"admin_roles,omitempty"`
	RolesSince_      ch.TimedSet `json:"rolesSince"`
}

var kValidEmailRegexp *regexp.Regexp

func init() {
	var err error
	kValidEmailRegexp, err = regexp.Compile(`^[-+.\w]+@\w[-.\w]+$`)
	if err != nil {
		panic("Bad kValidEmailRegexp")
	}
}

func IsValidEmail(email string) bool {
	return kValidEmailRegexp.MatchString(email)
}

func (auth *Authenticator) defaultGuestUser() User {
	user := &userImpl{
		roleImpl: roleImpl{
			ExplicitChannels_: ch.AtSequence(ch.SetOf(), 1),
		},
		userImplBody: userImplBody{
			Disabled_: true,
		},
		auth: auth,
	}
	user.Channels_ = user.ExplicitChannels_.Copy()
	return user
}

// Creates a new User object.
func (auth *Authenticator) NewUser(username string, password string, channels base.Set) (User, error) {
	user := &userImpl{
		auth:         auth,
		userImplBody: userImplBody{RolesSince_: ch.TimedSet{}},
	}
	if err := user.initRole(username, channels); err != nil {
		return nil, err
	}
	if err := auth.rebuildChannels(user); err != nil {
		return nil, err
	}
	user.SetPassword(password)
	return user, nil
}

func (auth *Authenticator) UnmarshalUser(data []byte, defaultName string, defaultSequence uint64) (User, error) {
	user := &userImpl{auth: auth}
	if err := json.Unmarshal(data, user); err != nil {
		return nil, err
	}
	if user.Name_ == "" {
		user.Name_ = defaultName
	}
	for channel, seq := range user.ExplicitChannels_ {
		if seq == 0 {
			user.ExplicitChannels_[channel] = defaultSequence
		}
	}
	if err := user.validate(); err != nil {
		return nil, err
	}
	return user, nil
}

// Checks whether this userImpl object contains valid data; if not, returns an error.
func (user *userImpl) validate() error {
	if err := (&user.roleImpl).validate(); err != nil {
		return err
	} else if user.Email_ != "" && !IsValidEmail(user.Email_) {
		return base.HTTPErrorf(http.StatusBadRequest, "Invalid email address")
	} else if user.OldPasswordHash_ != nil {
		return base.HTTPErrorf(http.StatusBadRequest, "Obsolete password hash present")
	} else if (user.Name_ == "") != (user.PasswordHash_ == nil) {
		// Real user must have a password; anon user must not have a password
		return base.HTTPErrorf(http.StatusBadRequest, "Invalid password")
	}
	for roleName, _ := range user.ExplicitRoles_ {
		if !IsValidPrincipalName(roleName) {
			return base.HTTPErrorf(http.StatusBadRequest, "Invalid role name %q", roleName)
		}
	}
	return nil
}

// Key prefix reserved for user documents in the bucket
const UserKeyPrefix = "_sync:user:"

func docIDForUser(username string) string {
	return UserKeyPrefix + username
}

func (user *userImpl) docID() string {
	return docIDForUser(user.Name_)
}

// Key used in 'access' view (not same meaning as doc ID)
func (user *userImpl) accessViewKey() string {
	return user.Name_
}

func (user *userImpl) Disabled() bool {
	return user.Disabled_
}

func (user *userImpl) SetDisabled(disabled bool) {
	user.Disabled_ = disabled
}

func (user *userImpl) Email() string {
	return user.Email_
}

func (user *userImpl) SetEmail(email string) error {
	if email != "" && !IsValidEmail(email) {
		return base.HTTPErrorf(http.StatusBadRequest, "Invalid email address")
	}
	user.Email_ = email
	return nil
}

func (user *userImpl) RoleNames() ch.TimedSet {
	return user.RolesSince_
}

func (user *userImpl) setRolesSince(rolesSince ch.TimedSet) {
	user.RolesSince_ = rolesSince
	user.roles = nil // invalidate in-memory cache list of Role objects
}

func (user *userImpl) ExplicitRoles() ch.TimedSet {
	return user.ExplicitRoles_
}

func (user *userImpl) SetExplicitRoles(roles ch.TimedSet) {
	user.ExplicitRoles_ = roles
	user.setRolesSince(nil) // invalidate persistent cache of role names
}

// Returns true if the given password is correct for this user, and the account isn't disabled.
func (user *userImpl) Authenticate(password string) bool {
	if user == nil {
		return false
	} else if user.OldPasswordHash_ != nil {
		base.Warn("User account %q still has pre-beta password hash; need to reset password", user.Name_)
		return false // Password must be reset to use new (bcrypt) password hash
	} else if user.PasswordHash_ == nil {
		if password != "" {
			return false
		}
	} else if !compareHashAndPassword(user.PasswordHash_, []byte(password)) {
		return false
	}
	return !user.Disabled_
}

// Changes a user's password to the given string.
func (user *userImpl) SetPassword(password string) {
	if password == "" {
		user.PasswordHash_ = nil
	} else {
		hash, err := bcrypt.GenerateFromPassword([]byte(password), kBcryptCostFactor)
		if err != nil {
			panic(fmt.Sprintf("Error hashing password: %v", err))
		}
		user.PasswordHash_ = hash
	}
}

//////// CHANNEL ACCESS:

func (user *userImpl) GetRoles() []Role {
	if user.roles == nil {
		roles := make([]Role, 0, len(user.RolesSince_))
		for name, _ := range user.RolesSince_ {
			role, err := user.auth.GetRole(name)
			//base.LogTo("Access", "User %s role %q = %v", user.Name_, name, role)
			if err != nil {
				panic(fmt.Sprintf("Error getting user role %q: %v", name, err))
			} else if role != nil {
				roles = append(roles, role)
			}
		}
		user.roles = roles
	}
	return user.roles
}

func (user *userImpl) CanSeeChannel(channel string) bool {
	if user.roleImpl.CanSeeChannel(channel) {
		return true
	}
	for _, role := range user.GetRoles() {
		if role.CanSeeChannel(channel) {
			return true
		}
	}
	return false
}

func (user *userImpl) CanSeeChannelSince(channel string) uint64 {
	minSeq := user.roleImpl.CanSeeChannelSince(channel)
	for _, role := range user.GetRoles() {
		if seq := role.CanSeeChannelSince(channel); seq > 0 && (seq < minSeq || minSeq == 0) {
			minSeq = seq
		}
	}
	return minSeq
}

func (user *userImpl) AuthorizeAllChannels(channels base.Set) error {
	return authorizeAllChannels(user, channels)
}

func (user *userImpl) AuthorizeAnyChannel(channels base.Set) error {
	return authorizeAnyChannel(user, channels)
}

func (user *userImpl) InheritedChannels() ch.TimedSet {
	channels := user.Channels().Copy()
	for _, role := range user.GetRoles() {
		roleSince := user.RolesSince_[role.Name()]
		channels.AddAtSequence(role.Channels(), roleSince)
	}
	return channels
}

// If a channel list contains a wildcard ("*"), replace it with all the user's accessible channels.
func (user *userImpl) ExpandWildCardChannel(channels base.Set) base.Set {
	if channels.Contains("*") {
		channels = user.InheritedChannels().AsSet()
	}
	return channels
}

func (user *userImpl) FilterToAvailableChannels(channels base.Set) ch.TimedSet {
	output := ch.TimedSet{}
	for channel, _ := range channels {
		if channel == "*" {
			return user.InheritedChannels().Copy()
		}
		output.AddChannel(channel, user.CanSeeChannelSince(channel))
	}
	return output
}

//////// MARSHALING:

// JSON encoding/decoding -- these functions are ugly hacks to work around the current
// Go 1.0.3 limitation that the JSON package won't traverse into unnamed/embedded
// fields of structs (i.e. the Role).

func (user *userImpl) MarshalJSON() ([]byte, error) {
	var err error
	data, err := json.Marshal(user.roleImpl)
	if err != nil {
		return nil, err
	}
	userData, err := json.Marshal(user.userImplBody)
	if err != nil {
		return nil, err
	}
	if len(userData) > 2 {
		// Splice the two JSON bodies together if the user data is not just "{}"
		data = data[0 : len(data)-1]
		userData = userData[1:len(userData)]
		data, err = bytes.Join([][]byte{data, userData}, []byte(",")), nil
	}
	return data, err
}

func (user *userImpl) UnmarshalJSON(data []byte) error {
	if err := json.Unmarshal(data, &user.userImplBody); err != nil {
		return err
	} else if err := json.Unmarshal(data, &user.roleImpl); err != nil {
		return err
	}
	return nil
}
<commit_msg>Graceful migration of old user admin_roles property<commit_after>//  Copyright (c) 2012 Couchbase, Inc.
//  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 auth

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"regexp"

	"code.google.com/p/go.crypto/bcrypt"

	"github.com/couchbaselabs/sync_gateway/base"
	ch "github.com/couchbaselabs/sync_gateway/channels"
)

const kBcryptCostFactor = bcrypt.DefaultCost

// Actual implementation of User interface
type userImpl struct {
	roleImpl // userImpl "inherits from" Role
	userImplBody
	auth  *Authenticator
	roles []Role
}

// Marshalable data is stored in separate struct from userImpl,
// to work around limitations of JSON marshaling.
type userImplBody struct {
	Email_           string      `json:"email,omitempty"`
	Disabled_        bool        `json:"disabled,omitempty"`
	PasswordHash_    []byte      `json:"passwordhash_bcrypt,omitempty"`
	OldPasswordHash_ interface{} `json:"passwordhash,omitempty"` // For pre-beta compatibility
	ExplicitRoles_   ch.TimedSet `json:"explicit_roles,omitempty"`
	RolesSince_      ch.TimedSet `json:"rolesSince"`

	OldExplicitRoles_ []string `json:"admin_roles,omitempty"` // obsolete; declared for migration
}

var kValidEmailRegexp *regexp.Regexp

func init() {
	var err error
	kValidEmailRegexp, err = regexp.Compile(`^[-+.\w]+@\w[-.\w]+$`)
	if err != nil {
		panic("Bad kValidEmailRegexp")
	}
}

func IsValidEmail(email string) bool {
	return kValidEmailRegexp.MatchString(email)
}

func (auth *Authenticator) defaultGuestUser() User {
	user := &userImpl{
		roleImpl: roleImpl{
			ExplicitChannels_: ch.AtSequence(ch.SetOf(), 1),
		},
		userImplBody: userImplBody{
			Disabled_: true,
		},
		auth: auth,
	}
	user.Channels_ = user.ExplicitChannels_.Copy()
	return user
}

// Creates a new User object.
func (auth *Authenticator) NewUser(username string, password string, channels base.Set) (User, error) {
	user := &userImpl{
		auth:         auth,
		userImplBody: userImplBody{RolesSince_: ch.TimedSet{}},
	}
	if err := user.initRole(username, channels); err != nil {
		return nil, err
	}
	if err := auth.rebuildChannels(user); err != nil {
		return nil, err
	}
	user.SetPassword(password)
	return user, nil
}

func (auth *Authenticator) UnmarshalUser(data []byte, defaultName string, defaultSequence uint64) (User, error) {
	user := &userImpl{auth: auth}
	if err := json.Unmarshal(data, user); err != nil {
		return nil, err
	}
	if user.Name_ == "" {
		user.Name_ = defaultName
	}
	for channel, seq := range user.ExplicitChannels_ {
		if seq == 0 {
			user.ExplicitChannels_[channel] = defaultSequence
		}
	}
	if err := user.validate(); err != nil {
		return nil, err
	}
	return user, nil
}

// Checks whether this userImpl object contains valid data; if not, returns an error.
func (user *userImpl) validate() error {
	if err := (&user.roleImpl).validate(); err != nil {
		return err
	} else if user.Email_ != "" && !IsValidEmail(user.Email_) {
		return base.HTTPErrorf(http.StatusBadRequest, "Invalid email address")
	} else if user.OldPasswordHash_ != nil {
		return base.HTTPErrorf(http.StatusBadRequest, "Obsolete password hash present")
	} else if (user.Name_ == "") != (user.PasswordHash_ == nil) {
		// Real user must have a password; anon user must not have a password
		return base.HTTPErrorf(http.StatusBadRequest, "Invalid password")
	}
	for roleName, _ := range user.ExplicitRoles_ {
		if !IsValidPrincipalName(roleName) {
			return base.HTTPErrorf(http.StatusBadRequest, "Invalid role name %q", roleName)
		}
	}
	return nil
}

// Key prefix reserved for user documents in the bucket
const UserKeyPrefix = "_sync:user:"

func docIDForUser(username string) string {
	return UserKeyPrefix + username
}

func (user *userImpl) docID() string {
	return docIDForUser(user.Name_)
}

// Key used in 'access' view (not same meaning as doc ID)
func (user *userImpl) accessViewKey() string {
	return user.Name_
}

func (user *userImpl) Disabled() bool {
	return user.Disabled_
}

func (user *userImpl) SetDisabled(disabled bool) {
	user.Disabled_ = disabled
}

func (user *userImpl) Email() string {
	return user.Email_
}

func (user *userImpl) SetEmail(email string) error {
	if email != "" && !IsValidEmail(email) {
		return base.HTTPErrorf(http.StatusBadRequest, "Invalid email address")
	}
	user.Email_ = email
	return nil
}

func (user *userImpl) RoleNames() ch.TimedSet {
	return user.RolesSince_
}

func (user *userImpl) setRolesSince(rolesSince ch.TimedSet) {
	user.RolesSince_ = rolesSince
	user.roles = nil // invalidate in-memory cache list of Role objects
}

func (user *userImpl) ExplicitRoles() ch.TimedSet {
	return user.ExplicitRoles_
}

func (user *userImpl) SetExplicitRoles(roles ch.TimedSet) {
	user.ExplicitRoles_ = roles
	user.setRolesSince(nil) // invalidate persistent cache of role names
}

// Returns true if the given password is correct for this user, and the account isn't disabled.
func (user *userImpl) Authenticate(password string) bool {
	if user == nil {
		return false
	} else if user.OldPasswordHash_ != nil {
		base.Warn("User account %q still has pre-beta password hash; need to reset password", user.Name_)
		return false // Password must be reset to use new (bcrypt) password hash
	} else if user.PasswordHash_ == nil {
		if password != "" {
			return false
		}
	} else if !compareHashAndPassword(user.PasswordHash_, []byte(password)) {
		return false
	}
	return !user.Disabled_
}

// Changes a user's password to the given string.
func (user *userImpl) SetPassword(password string) {
	if password == "" {
		user.PasswordHash_ = nil
	} else {
		hash, err := bcrypt.GenerateFromPassword([]byte(password), kBcryptCostFactor)
		if err != nil {
			panic(fmt.Sprintf("Error hashing password: %v", err))
		}
		user.PasswordHash_ = hash
	}
}

//////// CHANNEL ACCESS:

func (user *userImpl) GetRoles() []Role {
	if user.roles == nil {
		roles := make([]Role, 0, len(user.RolesSince_))
		for name, _ := range user.RolesSince_ {
			role, err := user.auth.GetRole(name)
			//base.LogTo("Access", "User %s role %q = %v", user.Name_, name, role)
			if err != nil {
				panic(fmt.Sprintf("Error getting user role %q: %v", name, err))
			} else if role != nil {
				roles = append(roles, role)
			}
		}
		user.roles = roles
	}
	return user.roles
}

func (user *userImpl) CanSeeChannel(channel string) bool {
	if user.roleImpl.CanSeeChannel(channel) {
		return true
	}
	for _, role := range user.GetRoles() {
		if role.CanSeeChannel(channel) {
			return true
		}
	}
	return false
}

func (user *userImpl) CanSeeChannelSince(channel string) uint64 {
	minSeq := user.roleImpl.CanSeeChannelSince(channel)
	for _, role := range user.GetRoles() {
		if seq := role.CanSeeChannelSince(channel); seq > 0 && (seq < minSeq || minSeq == 0) {
			minSeq = seq
		}
	}
	return minSeq
}

func (user *userImpl) AuthorizeAllChannels(channels base.Set) error {
	return authorizeAllChannels(user, channels)
}

func (user *userImpl) AuthorizeAnyChannel(channels base.Set) error {
	return authorizeAnyChannel(user, channels)
}

func (user *userImpl) InheritedChannels() ch.TimedSet {
	channels := user.Channels().Copy()
	for _, role := range user.GetRoles() {
		roleSince := user.RolesSince_[role.Name()]
		channels.AddAtSequence(role.Channels(), roleSince)
	}
	return channels
}

// If a channel list contains a wildcard ("*"), replace it with all the user's accessible channels.
func (user *userImpl) ExpandWildCardChannel(channels base.Set) base.Set {
	if channels.Contains("*") {
		channels = user.InheritedChannels().AsSet()
	}
	return channels
}

func (user *userImpl) FilterToAvailableChannels(channels base.Set) ch.TimedSet {
	output := ch.TimedSet{}
	for channel, _ := range channels {
		if channel == "*" {
			return user.InheritedChannels().Copy()
		}
		output.AddChannel(channel, user.CanSeeChannelSince(channel))
	}
	return output
}

//////// MARSHALING:

// JSON encoding/decoding -- these functions are ugly hacks to work around the current
// Go 1.0.3 limitation that the JSON package won't traverse into unnamed/embedded
// fields of structs (i.e. the Role).

func (user *userImpl) MarshalJSON() ([]byte, error) {
	var err error
	data, err := json.Marshal(user.roleImpl)
	if err != nil {
		return nil, err
	}
	userData, err := json.Marshal(user.userImplBody)
	if err != nil {
		return nil, err
	}
	if len(userData) > 2 {
		// Splice the two JSON bodies together if the user data is not just "{}"
		data = data[0 : len(data)-1]
		userData = userData[1:len(userData)]
		data, err = bytes.Join([][]byte{data, userData}, []byte(",")), nil
	}
	return data, err
}

func (user *userImpl) UnmarshalJSON(data []byte) error {
	if err := json.Unmarshal(data, &user.userImplBody); err != nil {
		return err
	} else if err := json.Unmarshal(data, &user.roleImpl); err != nil {
		return err
	}

	// Migrate "admin_roles" field:
	if user.OldExplicitRoles_ != nil {
		user.ExplicitRoles_ = ch.AtSequence(base.SetFromArray(user.OldExplicitRoles_), 1)
		user.OldExplicitRoles_ = nil
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 TSUYUSATO Kitsune
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php

// Package hotkey provides HotKey for Go Language.
package hotkey

import (
	"fmt"
	"time"

	"github.com/lxn/win"
)

import "github.com/MakeNowJust/hotkey/win"

// A hotkey.Id is a identity number of registered hotkey.
type Id int32

// A hotkey.Modifier specifies the keyboard modifier for hotkey.Register.
type Modifier uint32

// These are all members of hotkey.Modifier.
const (
	Alt   Modifier = hotkey_win.MOD_ALT
	Ctrl  Modifier = hotkey_win.MOD_CONTROL
	Shift Modifier = hotkey_win.MOD_SHIFT
	Win   Modifier = hotkey_win.MOD_WIN
)

type reservedHotKey struct {
	id              int32
	fsModifiers, vk uint32
}

var (
	started = false

	currentId = int32(1)
	id2handle = make(map[Id]func())

	reservedHotKeys = make([]reservedHotKey, 0)

	threadId     uint32
	chRegister   = make(chan reservedHotKey, 100)
	chUnregister = make(chan int32, 100)
)

// Register a hotkey with modifiers and vk.
// mods are hotkey's modifiers such as hotkey.Alt, hotkey.Ctrl|hotkey.Shift.
// vk is a hotkey's virtual key code. See also
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
func Register(mods Modifier, vk uint32, handle func()) (id Id, err error) {
	reserved := reservedHotKey{
		id:          currentId,
		fsModifiers: uint32(mods),
		vk:          uint32(vk),
	}
	id = Id(currentId)
	id2handle[id] = handle

	currentId += 1

	if started {
		chRegister <- reserved
		hotkey_win.PostThreadMessage(threadId, win.WM_USER, 0, 0)
	} else {
		reservedHotKeys = append(reservedHotKeys, reserved)
	}
	return
}

// Unregister a hotkey from id.
func Unregister(id Id) {
	if started {
		chUnregister <- int32(id)
		delete(id2handle, id)
		hotkey_win.PostThreadMessage(threadId, win.WM_USER, 0, 0)
	} else {
		for idx, reserved := range reservedHotKeys {
			if reserved.id == int32(id) {
				reservedHotKeys[idx] = reservedHotKey{0, 0, 0}
			}
		}
	}
}

// Start hotkey's loop. It is non-blocking.
func Start() <-chan error {
	chErr := make(chan error)
	chThreadId := make(chan uint32)

	go func() {
		// register and reserve to unregister hotkeys
		count := 0
		for _, reserved := range reservedHotKeys {
			if reserved.id == 0 {
				continue
			}

			if !hotkey_win.RegisterHotKey(0, reserved.id, reserved.fsModifiers, reserved.vk) {
				chErr <- fmt.Errorf("failed to register hotkey %v", reserved)
				return
			}
			defer hotkey_win.UnregisterHotKey(0, reserved.id)
			count += 1
		}

		chThreadId <- hotkey_win.GetThreadId(hotkey_win.GetCurrentThread())

		// hotkey's loop
		for {
			select {
			case <-time.After(time.Millisecond * 10):
				var msg win.MSG
				res := win.GetMessage(&msg, 0, 0, 0)

				if res == 0 || res == -1 {
					// TODO: get system error message
					chErr <- nil
					return
				}

				switch msg.Message {
				case win.WM_HOTKEY:
					if handle := id2handle[Id(msg.WParam)]; handle != nil {
						handle()
					}
				default:
					win.TranslateMessage(&msg)
					win.DispatchMessage(&msg)
				}

			case reserved := <-chRegister:
				if !hotkey_win.RegisterHotKey(0, reserved.id, reserved.fsModifiers, reserved.vk) {
					chErr <- fmt.Errorf("failed to register hotkey %v", reserved)
					return
				}
				defer hotkey_win.UnregisterHotKey(0, reserved.id)
				count += 1

			case id := <-chUnregister:
				hotkey_win.UnregisterHotKey(0, id)
				if count -= 1; count == 0 && len(chRegister) == 0 {
					chErr <- nil
					return
				}
			}
		}
	}()

	threadId = <-chThreadId
	started = true
	return chErr
}
<commit_msg>Rewrite hotkey.Register's godoc comment more readable<commit_after>// Copyright (c) 2014 TSUYUSATO Kitsune
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php

// Package hotkey provides HotKey for Go Language.
package hotkey

import (
	"fmt"
	"time"

	"github.com/lxn/win"
)

import "github.com/MakeNowJust/hotkey/win"

// A hotkey.Id is a identity number of registered hotkey.
type Id int32

// A hotkey.Modifier specifies the keyboard modifier for hotkey.Register.
type Modifier uint32

// These are all members of hotkey.Modifier.
const (
	Alt   Modifier = hotkey_win.MOD_ALT
	Ctrl  Modifier = hotkey_win.MOD_CONTROL
	Shift Modifier = hotkey_win.MOD_SHIFT
	Win   Modifier = hotkey_win.MOD_WIN
)

type reservedHotKey struct {
	id              int32
	fsModifiers, vk uint32
}

var (
	started = false

	currentId = int32(1)
	id2handle = make(map[Id]func())

	reservedHotKeys = make([]reservedHotKey, 0)

	threadId     uint32
	chRegister   = make(chan reservedHotKey, 100)
	chUnregister = make(chan int32, 100)
)

// Register a hotkey with modifiers and vk.
//
// mods are hotkey's modifiers such as hotkey.Alt, hotkey.Ctrl+hotkey.Shift.
//
// vk is a hotkey's virtual key code. See also
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
func Register(mods Modifier, vk uint32, handle func()) (id Id, err error) {
	reserved := reservedHotKey{
		id:          currentId,
		fsModifiers: uint32(mods),
		vk:          uint32(vk),
	}
	id = Id(currentId)
	id2handle[id] = handle

	currentId += 1

	if started {
		chRegister <- reserved
		hotkey_win.PostThreadMessage(threadId, win.WM_USER, 0, 0)
	} else {
		reservedHotKeys = append(reservedHotKeys, reserved)
	}
	return
}

// Unregister a hotkey from id.
func Unregister(id Id) {
	if started {
		chUnregister <- int32(id)
		delete(id2handle, id)
		hotkey_win.PostThreadMessage(threadId, win.WM_USER, 0, 0)
	} else {
		for idx, reserved := range reservedHotKeys {
			if reserved.id == int32(id) {
				reservedHotKeys[idx] = reservedHotKey{0, 0, 0}
			}
		}
	}
}

// Start hotkey's loop. It is non-blocking.
func Start() <-chan error {
	chErr := make(chan error)
	chThreadId := make(chan uint32)

	go func() {
		// register and reserve to unregister hotkeys
		count := 0
		for _, reserved := range reservedHotKeys {
			if reserved.id == 0 {
				continue
			}

			if !hotkey_win.RegisterHotKey(0, reserved.id, reserved.fsModifiers, reserved.vk) {
				chErr <- fmt.Errorf("failed to register hotkey %v", reserved)
				return
			}
			defer hotkey_win.UnregisterHotKey(0, reserved.id)
			count += 1
		}

		chThreadId <- hotkey_win.GetThreadId(hotkey_win.GetCurrentThread())

		// hotkey's loop
		for {
			select {
			case <-time.After(time.Millisecond * 10):
				var msg win.MSG
				res := win.GetMessage(&msg, 0, 0, 0)

				if res == 0 || res == -1 {
					// TODO: get system error message
					chErr <- nil
					return
				}

				switch msg.Message {
				case win.WM_HOTKEY:
					if handle := id2handle[Id(msg.WParam)]; handle != nil {
						handle()
					}
				default:
					win.TranslateMessage(&msg)
					win.DispatchMessage(&msg)
				}

			case reserved := <-chRegister:
				if !hotkey_win.RegisterHotKey(0, reserved.id, reserved.fsModifiers, reserved.vk) {
					chErr <- fmt.Errorf("failed to register hotkey %v", reserved)
					return
				}
				defer hotkey_win.UnregisterHotKey(0, reserved.id)
				count += 1

			case id := <-chUnregister:
				hotkey_win.UnregisterHotKey(0, id)
				if count -= 1; count == 0 && len(chRegister) == 0 {
					chErr <- nil
					return
				}
			}
		}
	}()

	threadId = <-chThreadId
	started = true
	return chErr
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

	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 metricstest

import (
	"reflect"

	"go.opencensus.io/stats/view"
	"knative.dev/pkg/test"
)

// CheckStatsReported checks that there is a view registered with the given name for each string in names,
// and that each view has at least one record.
func CheckStatsReported(t test.T, names ...string) {
	t.Helper()
	for _, name := range names {
		d, err := view.RetrieveData(name)
		if err != nil {
			t.Error("For metric, Reporter.Report() error", "metric", name, "error", err)
		}
		if len(d) < 1 {
			t.Error("For metric, no data reported when data was expected, view data is empty.", "metric", name)
		}
	}
}

// CheckStatsNotReported checks that there are no records for any views that a name matching a string in names.
// Names that do not match registered views are considered not reported.
func CheckStatsNotReported(t test.T, names ...string) {
	t.Helper()
	for _, name := range names {
		d, err := view.RetrieveData(name)
		// err == nil means a valid stat exists matching "name"
		// len(d) > 0 means a component recorded metrics for that stat
		if err == nil && len(d) > 0 {
			t.Error("For metric, unexpected data reported when no data was expected.", "metric", name, "Reporter len(d)", len(d))
		}
	}
}

// CheckCountData checks the view with a name matching string name to verify that the CountData stats
// reported are tagged with the tags in wantTags and that wantValue matches reported count.
func CheckCountData(t test.T, name string, wantTags map[string]string, wantValue int64) {
	t.Helper()
	if row := checkExactlyOneRow(t, name); row != nil {
		checkRowTags(t, row, name, wantTags)

		if s, ok := row.Data.(*view.CountData); !ok {
			t.Error("want CountData", "metric", name, "got", reflect.TypeOf(row.Data))
		} else if s.Value != wantValue {
			t.Error("Wrong value", "metric", name, "value", s.Value, "want", wantValue)
		}
	}
}

// CheckDistributionData checks the view with a name matching string name to verify that the DistributionData stats reported
// are tagged with the tags in wantTags and that expectedCount number of records were reported.
// It also checks that expectedMin and expectedMax match the minimum and maximum reported values, respectively.
func CheckDistributionData(t test.T, name string, wantTags map[string]string, expectedCount int64, expectedMin float64, expectedMax float64) {
	t.Helper()
	if row := checkExactlyOneRow(t, name); row != nil {
		checkRowTags(t, row, name, wantTags)

		if s, ok := row.Data.(*view.DistributionData); !ok {
			t.Error("want DistributionData", "metric", name, "got", reflect.TypeOf(row.Data))
		} else {
			if s.Count != expectedCount {
				t.Error("reporter count wrong", "metric", name, "got", s.Count, "want", expectedCount)
			}
			if s.Min != expectedMin {
				t.Error("reporter count wrong", "metric", name, "got", s.Min, "want", expectedMin)
			}
			if s.Max != expectedMax {
				t.Error("reporter count wrong", "metric", name, "got", s.Max, "want", expectedMax)
			}
		}
	}
}

// CheckLastValueData checks the view with a name matching string name to verify that the LastValueData stats
// reported are tagged with the tags in wantTags and that wantValue matches reported last value.
func CheckLastValueData(t test.T, name string, wantTags map[string]string, wantValue float64) {
	t.Helper()
	if row := checkExactlyOneRow(t, name); row != nil {
		checkRowTags(t, row, name, wantTags)

		if s, ok := row.Data.(*view.LastValueData); !ok {
			t.Error("want LastValueData", "metric", name, "got", reflect.TypeOf(row.Data))
		} else if s.Value != wantValue {
			t.Error("Reporter.Report() wrong value", "metric", name, "got", s.Value, "want", wantValue)
		}
	}
}

// CheckSumData checks the view with a name matching string name to verify that the SumData stats
// reported are tagged with the tags in wantTags and that wantValue matches the reported sum.
func CheckSumData(t test.T, name string, wantTags map[string]string, wantValue float64) {
	t.Helper()
	if row := checkExactlyOneRow(t, name); row != nil {
		checkRowTags(t, row, name, wantTags)

		if s, ok := row.Data.(*view.SumData); !ok {
			t.Error("Wrong type", "metric", name, "got", reflect.TypeOf(row.Data), "want", "SumData")
		} else if s.Value != wantValue {
			t.Error("Wrong sumdata", "metric", name, "got", s.Value, "want", wantValue)
		}
	}
}

// Unregister unregisters the metrics that were registered.
// This is useful for testing since golang execute test iterations within the same process and
// opencensus views maintain global state. At the beginning of each test, tests should
// unregister for all metrics and then re-register for the same metrics. This effectively clears
// out any existing data and avoids a panic due to re-registering a metric.
//
// In normal process shutdown, metrics do not need to be unregistered.
func Unregister(names ...string) {
	for _, n := range names {
		if v := view.Find(n); v != nil {
			view.Unregister(v)
		}
	}
}

func checkExactlyOneRow(t test.T, name string) *view.Row {
	t.Helper()
	d, err := view.RetrieveData(name)
	if err != nil {
		t.Error("Reporter.Report() error", "metric", name, "error", err)
		return nil
	}
	if len(d) != 1 {
		t.Error("Reporter.Report() wrong length", "metric", name, "got", len(d), "want", 1)
		return nil
	}

	return d[0]
}

func checkRowTags(t test.T, row *view.Row, name string, wantTags map[string]string) {
	t.Helper()
	if wantlen, gotlen := len(wantTags), len(row.Tags); gotlen != wantlen {
		t.Error("Reporter got wrong number of tags", "metric", name, "got", gotlen, "want", wantlen)
	}
	for _, got := range row.Tags {
		n := got.Key.Name()
		if want, ok := wantTags[n]; !ok {
			t.Error("Reporter got an extra tag", "metric", name, "gotName", n, "gotValue", got.Value)
		} else if got.Value != want {
			t.Error("Reporter expected a different tag value for key", "metric", name, "key", n, "got", got.Value, "want", want)
		}
	}
}
<commit_msg>Make sure we actually check the last value. (#1041)<commit_after>/*
Copyright 2019 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

	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 metricstest

import (
	"reflect"

	"go.opencensus.io/stats/view"
	"knative.dev/pkg/test"
)

// CheckStatsReported checks that there is a view registered with the given name for each string in names,
// and that each view has at least one record.
func CheckStatsReported(t test.T, names ...string) {
	t.Helper()
	for _, name := range names {
		d, err := view.RetrieveData(name)
		if err != nil {
			t.Error("For metric, Reporter.Report() error", "metric", name, "error", err)
		}
		if len(d) < 1 {
			t.Error("For metric, no data reported when data was expected, view data is empty.", "metric", name)
		}
	}
}

// CheckStatsNotReported checks that there are no records for any views that a name matching a string in names.
// Names that do not match registered views are considered not reported.
func CheckStatsNotReported(t test.T, names ...string) {
	t.Helper()
	for _, name := range names {
		d, err := view.RetrieveData(name)
		// err == nil means a valid stat exists matching "name"
		// len(d) > 0 means a component recorded metrics for that stat
		if err == nil && len(d) > 0 {
			t.Error("For metric, unexpected data reported when no data was expected.", "metric", name, "Reporter len(d)", len(d))
		}
	}
}

// CheckCountData checks the view with a name matching string name to verify that the CountData stats
// reported are tagged with the tags in wantTags and that wantValue matches reported count.
func CheckCountData(t test.T, name string, wantTags map[string]string, wantValue int64) {
	t.Helper()
	if row := checkExactlyOneRow(t, name); row != nil {
		checkRowTags(t, row, name, wantTags)

		if s, ok := row.Data.(*view.CountData); !ok {
			t.Error("want CountData", "metric", name, "got", reflect.TypeOf(row.Data))
		} else if s.Value != wantValue {
			t.Error("Wrong value", "metric", name, "value", s.Value, "want", wantValue)
		}
	}
}

// CheckDistributionData checks the view with a name matching string name to verify that the DistributionData stats reported
// are tagged with the tags in wantTags and that expectedCount number of records were reported.
// It also checks that expectedMin and expectedMax match the minimum and maximum reported values, respectively.
func CheckDistributionData(t test.T, name string, wantTags map[string]string, expectedCount int64, expectedMin float64, expectedMax float64) {
	t.Helper()
	if row := checkExactlyOneRow(t, name); row != nil {
		checkRowTags(t, row, name, wantTags)

		if s, ok := row.Data.(*view.DistributionData); !ok {
			t.Error("want DistributionData", "metric", name, "got", reflect.TypeOf(row.Data))
		} else {
			if s.Count != expectedCount {
				t.Error("reporter count wrong", "metric", name, "got", s.Count, "want", expectedCount)
			}
			if s.Min != expectedMin {
				t.Error("reporter count wrong", "metric", name, "got", s.Min, "want", expectedMin)
			}
			if s.Max != expectedMax {
				t.Error("reporter count wrong", "metric", name, "got", s.Max, "want", expectedMax)
			}
		}
	}
}

// CheckLastValueData checks the view with a name matching string name to verify that the LastValueData stats
// reported are tagged with the tags in wantTags and that wantValue matches reported last value.
func CheckLastValueData(t test.T, name string, wantTags map[string]string, wantValue float64) {
	t.Helper()
	if row := lastRow(t, name); row != nil {
		checkRowTags(t, row, name, wantTags)

		if s, ok := row.Data.(*view.LastValueData); !ok {
			t.Error("want LastValueData", "metric", name, "got", reflect.TypeOf(row.Data))
		} else if s.Value != wantValue {
			t.Error("Reporter.Report() wrong value", "metric", name, "got", s.Value, "want", wantValue)
		}
	}
}

// CheckSumData checks the view with a name matching string name to verify that the SumData stats
// reported are tagged with the tags in wantTags and that wantValue matches the reported sum.
func CheckSumData(t test.T, name string, wantTags map[string]string, wantValue float64) {
	t.Helper()
	if row := checkExactlyOneRow(t, name); row != nil {
		checkRowTags(t, row, name, wantTags)

		if s, ok := row.Data.(*view.SumData); !ok {
			t.Error("Wrong type", "metric", name, "got", reflect.TypeOf(row.Data), "want", "SumData")
		} else if s.Value != wantValue {
			t.Error("Wrong sumdata", "metric", name, "got", s.Value, "want", wantValue)
		}
	}
}

// Unregister unregisters the metrics that were registered.
// This is useful for testing since golang execute test iterations within the same process and
// opencensus views maintain global state. At the beginning of each test, tests should
// unregister for all metrics and then re-register for the same metrics. This effectively clears
// out any existing data and avoids a panic due to re-registering a metric.
//
// In normal process shutdown, metrics do not need to be unregistered.
func Unregister(names ...string) {
	for _, n := range names {
		if v := view.Find(n); v != nil {
			view.Unregister(v)
		}
	}
}

func lastRow(t test.T, name string) *view.Row {
	t.Helper()
	d, err := view.RetrieveData(name)
	if err != nil {
		t.Error("Reporter.Report() error", "metric", name, "error", err)
		return nil
	}
	if len(d) < 1 {
		t.Error("Reporter.Report() wrong length", "metric", name, "got", len(d), "want at least", 1)
		return nil
	}

	return d[len(d)-1]
}

func checkExactlyOneRow(t test.T, name string) *view.Row {
	t.Helper()
	d, err := view.RetrieveData(name)
	if err != nil {
		t.Error("Reporter.Report() error", "metric", name, "error", err)
		return nil
	}
	if len(d) != 1 {
		t.Error("Reporter.Report() wrong length", "metric", name, "got", len(d), "want", 1)
		return nil
	}

	return d[0]
}

func checkRowTags(t test.T, row *view.Row, name string, wantTags map[string]string) {
	t.Helper()
	if wantlen, gotlen := len(wantTags), len(row.Tags); gotlen != wantlen {
		t.Error("Reporter got wrong number of tags", "metric", name, "got", gotlen, "want", wantlen)
	}
	for _, got := range row.Tags {
		n := got.Key.Name()
		if want, ok := wantTags[n]; !ok {
			t.Error("Reporter got an extra tag", "metric", name, "gotName", n, "gotValue", got.Value)
		} else if got.Value != want {
			t.Error("Reporter expected a different tag value for key", "metric", name, "key", n, "got", got.Value, "want", want)
		}
	}
}
<|endoftext|>


<commit_before>package convert

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"strings"
	"testing"

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

func TestCIDR(t *testing.T) {
	checkHeader(
		t,
		cidrHeader,
		[]string{"network"},
	)

	v4net := "1.1.1.0/24"
	checkLine(
		t,
		cidrLine,
		v4net,
		[]string{v4net},
	)

	v6net := "2001:db8:85a3:42::/64"
	checkLine(
		t,
		cidrLine,
		v6net,
		[]string{v6net},
	)
}

func TestRange(t *testing.T) {
	checkHeader(
		t,
		rangeHeader,
		[]string{"network_start_ip", "network_last_ip"},
	)

	checkLine(
		t,
		rangeLine,
		"1.1.1.0/24",
		[]string{"1.1.1.0", "1.1.1.255"},
	)

	checkLine(
		t,
		rangeLine,
		"2001:0db8:85a3:0042::/64",
		[]string{"2001:db8:85a3:42::", "2001:db8:85a3:42:ffff:ffff:ffff:ffff"},
	)
}

func TestIntRange(t *testing.T) {
	checkHeader(
		t,
		intRangeHeader,
		[]string{"network_start_integer", "network_last_integer"},
	)

	checkLine(
		t,
		intRangeLine,
		"1.1.1.0/24",
		[]string{"16843008", "16843263"},
	)

	checkLine(
		t,
		intRangeLine,
		"2001:0db8:85a3:0042::/64",
		[]string{
			"42540766452641155289225172512357220352",
			"42540766452641155307671916586066771967",
		},
	)
}

func TestHexRange(t *testing.T) {
	checkHeader(
		t,
		hexRangeHeader,
		[]string{"network_start_hex", "network_last_hex"},
	)

	checkLine(
		t,
		hexRangeLine,
		"1.1.1.0/24",
		[]string{"1010100", "10101ff"},
	)

	checkLine(
		t,
		hexRangeLine,
		"2001:0db8:85a3:0042::/64",
		[]string{
			"20010db885a300420000000000000000",
			"20010db885a30042ffffffffffffffff",
		},
	)
}

func checkHeader(
	t *testing.T,
	makeHeader headerFunc,
	expected []string,
) {
	suffix := []string{"city", "country"}
	assert.Equal(
		t,
		append(expected, suffix...),
		makeHeader(suffix),
	)
}

func checkLine(
	t *testing.T,
	makeLine lineFunc,
	network string,
	expected []string,
) {
	p, err := makePrefix(network)
	if err != nil {
		t.Fatal(err)
	}

	suffix := []string{"1", "2"}
	assert.Equal(
		t,
		append(expected, suffix...),
		makeLine(p, suffix),
	)
}

func TestCIDROutput(t *testing.T) {
	checkOutput(
		t,
		"CIDR only",
		true,
		false,
		false,
		false,
		[]interface{}{
			"network",
			"1.0.0.0/24",
			"4.69.140.16/29",
			"5.61.192.0/21",
			"2001:4220::/32",
			"2402:d000::/32",
			"2406:4000::/32",
		},
	)
}

func TestRangeOutput(t *testing.T) {
	checkOutput(
		t,
		"range only",
		false,
		true,
		false,
		false,
		[]interface{}{
			"network_start_ip,network_last_ip",
			"1.0.0.0,1.0.0.255",
			"4.69.140.16,4.69.140.23",
			"5.61.192.0,5.61.199.255",
			"2001:4220::,2001:4220:ffff:ffff:ffff:ffff:ffff:ffff",
			"2402:d000::,2402:d000:ffff:ffff:ffff:ffff:ffff:ffff",
			"2406:4000::,2406:4000:ffff:ffff:ffff:ffff:ffff:ffff",
		},
	)
}

func TestIntRangeOutput(t *testing.T) {
	checkOutput(
		t,
		"integer range only",
		false,
		false,
		true,
		false,
		[]interface{}{
			"network_start_integer,network_last_integer",
			"16777216,16777471",
			"71666704,71666711",
			"87932928,87934975",
			"42541829336310884227257139937291534336,42541829415539046741521477530835484671",
			"47866811183171600627242296191018336256,47866811262399763141506633784562286591",
			"47884659703622814097215369772150030336,47884659782850976611479707365693980671",
		},
	)
}

func TestHexRangeOutput(t *testing.T) {
	checkOutput(
		t,
		"hex range only",
		false,
		false,
		false,
		true,
		[]interface{}{
			"network_start_hex,network_last_hex",
			"1000000,10000ff",
			"4458c10,4458c17",
			"53dc000,53dc7ff",
			"20014220000000000000000000000000,20014220ffffffffffffffffffffffff",
			"2402d000000000000000000000000000,2402d000ffffffffffffffffffffffff",
			"24064000000000000000000000000000,24064000ffffffffffffffffffffffff",
		},
	)
}

func TestAllOutput(t *testing.T) {
	checkOutput(
		t,
		"all output options",
		true,
		true,
		true,
		true,
		[]interface{}{
			//nolint: lll
			"network,network_start_ip,network_last_ip,network_start_integer,network_last_integer,network_start_hex,network_last_hex",
			"1.0.0.0/24,1.0.0.0,1.0.0.255,16777216,16777471,1000000,10000ff",
			"4.69.140.16/29,4.69.140.16,4.69.140.23,71666704,71666711,4458c10,4458c17",
			"5.61.192.0/21,5.61.192.0,5.61.199.255,87932928,87934975,53dc000,53dc7ff",
			//nolint: lll
			"2001:4220::/32,2001:4220::,2001:4220:ffff:ffff:ffff:ffff:ffff:ffff,42541829336310884227257139937291534336,42541829415539046741521477530835484671,20014220000000000000000000000000,20014220ffffffffffffffffffffffff",
			//nolint: lll
			"2402:d000::/32,2402:d000::,2402:d000:ffff:ffff:ffff:ffff:ffff:ffff,47866811183171600627242296191018336256,47866811262399763141506633784562286591,2402d000000000000000000000000000,2402d000ffffffffffffffffffffffff",
			//nolint: lll
			"2406:4000::/32,2406:4000::,2406:4000:ffff:ffff:ffff:ffff:ffff:ffff,47884659703622814097215369772150030336,47884659782850976611479707365693980671,24064000000000000000000000000000,24064000ffffffffffffffffffffffff",
		},
	)
}

func checkOutput(
	t *testing.T,
	name string,
	cidr bool,
	ipRange bool,
	intRange bool,
	hexRange bool,
	expected []interface{},
) {
	//nolint: lll
	input := `network,geoname_id,registered_country_geoname_id,represented_country_geoname_id,is_anonymous_proxy,is_satellite_provider
1.0.0.0/24,2077456,2077456,,0,0
4.69.140.16/29,6252001,6252001,,0,0
5.61.192.0/21,2635167,2635167,,0,0
2001:4220::/32,357994,357994,,0,0
2402:d000::/32,1227603,1227603,,0,0
2406:4000::/32,1835841,1835841,,0,0
`
	var outbuf bytes.Buffer

	err := Convert(strings.NewReader(input), &outbuf, cidr, ipRange, intRange, hexRange)
	if err != nil {
		t.Fatal(err)
	}

	// This is a regexp as Go 1.4 does not quote empty fields while earlier
	// versions do
	//nolint: lll
	outTMPL := `%s,geoname_id,registered_country_geoname_id,represented_country_geoname_id,is_anonymous_proxy,is_satellite_provider
%s,2077456,2077456,(?:"")?,0,0
%s,6252001,6252001,(?:"")?,0,0
%s,2635167,2635167,(?:"")?,0,0
%s,357994,357994,(?:"")?,0,0
%s,1227603,1227603,(?:"")?,0,0
%s,1835841,1835841,(?:"")?,0,0
`

	assert.Regexp(
		t,
		fmt.Sprintf(outTMPL, expected...),
		outbuf.String(),
		name,
	)
}

func TestFileWriting(t *testing.T) {
	input := `network,something
1.0.0.0/24,"some more"
`

	//nolint: lll
	expected := `network,network_start_ip,network_last_ip,network_start_integer,network_last_integer,network_start_hex,network_last_hex,something
1.0.0.0/24,1.0.0.0,1.0.0.255,16777216,16777471,1000000,10000ff,some more
`

	inFile, err := ioutil.TempFile("", "input")
	if err != nil {
		t.Fatal(err)
	}
	defer inFile.Close() //nolint: gosec

	outFile, err := ioutil.TempFile("", "output")
	if err != nil {
		t.Fatal(err)
	}
	defer outFile.Close() //nolint: gosec

	_, err = inFile.WriteString(input)
	require.NoError(t, err)

	err = ConvertFile(inFile.Name(), outFile.Name(), true, true, true, true)
	if err != nil {
		t.Fatal(err)
	}

	buf := bytes.NewBuffer(nil)
	_, err = io.Copy(buf, outFile)
	require.NoError(t, err)

	assert.Equal(t, expected, buf.String())
}
<commit_msg>Replace calls to deprecated ioutil functions<commit_after>package convert

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"strings"
	"testing"

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

func TestCIDR(t *testing.T) {
	checkHeader(
		t,
		cidrHeader,
		[]string{"network"},
	)

	v4net := "1.1.1.0/24"
	checkLine(
		t,
		cidrLine,
		v4net,
		[]string{v4net},
	)

	v6net := "2001:db8:85a3:42::/64"
	checkLine(
		t,
		cidrLine,
		v6net,
		[]string{v6net},
	)
}

func TestRange(t *testing.T) {
	checkHeader(
		t,
		rangeHeader,
		[]string{"network_start_ip", "network_last_ip"},
	)

	checkLine(
		t,
		rangeLine,
		"1.1.1.0/24",
		[]string{"1.1.1.0", "1.1.1.255"},
	)

	checkLine(
		t,
		rangeLine,
		"2001:0db8:85a3:0042::/64",
		[]string{"2001:db8:85a3:42::", "2001:db8:85a3:42:ffff:ffff:ffff:ffff"},
	)
}

func TestIntRange(t *testing.T) {
	checkHeader(
		t,
		intRangeHeader,
		[]string{"network_start_integer", "network_last_integer"},
	)

	checkLine(
		t,
		intRangeLine,
		"1.1.1.0/24",
		[]string{"16843008", "16843263"},
	)

	checkLine(
		t,
		intRangeLine,
		"2001:0db8:85a3:0042::/64",
		[]string{
			"42540766452641155289225172512357220352",
			"42540766452641155307671916586066771967",
		},
	)
}

func TestHexRange(t *testing.T) {
	checkHeader(
		t,
		hexRangeHeader,
		[]string{"network_start_hex", "network_last_hex"},
	)

	checkLine(
		t,
		hexRangeLine,
		"1.1.1.0/24",
		[]string{"1010100", "10101ff"},
	)

	checkLine(
		t,
		hexRangeLine,
		"2001:0db8:85a3:0042::/64",
		[]string{
			"20010db885a300420000000000000000",
			"20010db885a30042ffffffffffffffff",
		},
	)
}

func checkHeader(
	t *testing.T,
	makeHeader headerFunc,
	expected []string,
) {
	suffix := []string{"city", "country"}
	assert.Equal(
		t,
		append(expected, suffix...),
		makeHeader(suffix),
	)
}

func checkLine(
	t *testing.T,
	makeLine lineFunc,
	network string,
	expected []string,
) {
	p, err := makePrefix(network)
	if err != nil {
		t.Fatal(err)
	}

	suffix := []string{"1", "2"}
	assert.Equal(
		t,
		append(expected, suffix...),
		makeLine(p, suffix),
	)
}

func TestCIDROutput(t *testing.T) {
	checkOutput(
		t,
		"CIDR only",
		true,
		false,
		false,
		false,
		[]interface{}{
			"network",
			"1.0.0.0/24",
			"4.69.140.16/29",
			"5.61.192.0/21",
			"2001:4220::/32",
			"2402:d000::/32",
			"2406:4000::/32",
		},
	)
}

func TestRangeOutput(t *testing.T) {
	checkOutput(
		t,
		"range only",
		false,
		true,
		false,
		false,
		[]interface{}{
			"network_start_ip,network_last_ip",
			"1.0.0.0,1.0.0.255",
			"4.69.140.16,4.69.140.23",
			"5.61.192.0,5.61.199.255",
			"2001:4220::,2001:4220:ffff:ffff:ffff:ffff:ffff:ffff",
			"2402:d000::,2402:d000:ffff:ffff:ffff:ffff:ffff:ffff",
			"2406:4000::,2406:4000:ffff:ffff:ffff:ffff:ffff:ffff",
		},
	)
}

func TestIntRangeOutput(t *testing.T) {
	checkOutput(
		t,
		"integer range only",
		false,
		false,
		true,
		false,
		[]interface{}{
			"network_start_integer,network_last_integer",
			"16777216,16777471",
			"71666704,71666711",
			"87932928,87934975",
			"42541829336310884227257139937291534336,42541829415539046741521477530835484671",
			"47866811183171600627242296191018336256,47866811262399763141506633784562286591",
			"47884659703622814097215369772150030336,47884659782850976611479707365693980671",
		},
	)
}

func TestHexRangeOutput(t *testing.T) {
	checkOutput(
		t,
		"hex range only",
		false,
		false,
		false,
		true,
		[]interface{}{
			"network_start_hex,network_last_hex",
			"1000000,10000ff",
			"4458c10,4458c17",
			"53dc000,53dc7ff",
			"20014220000000000000000000000000,20014220ffffffffffffffffffffffff",
			"2402d000000000000000000000000000,2402d000ffffffffffffffffffffffff",
			"24064000000000000000000000000000,24064000ffffffffffffffffffffffff",
		},
	)
}

func TestAllOutput(t *testing.T) {
	checkOutput(
		t,
		"all output options",
		true,
		true,
		true,
		true,
		[]interface{}{
			//nolint: lll
			"network,network_start_ip,network_last_ip,network_start_integer,network_last_integer,network_start_hex,network_last_hex",
			"1.0.0.0/24,1.0.0.0,1.0.0.255,16777216,16777471,1000000,10000ff",
			"4.69.140.16/29,4.69.140.16,4.69.140.23,71666704,71666711,4458c10,4458c17",
			"5.61.192.0/21,5.61.192.0,5.61.199.255,87932928,87934975,53dc000,53dc7ff",
			//nolint: lll
			"2001:4220::/32,2001:4220::,2001:4220:ffff:ffff:ffff:ffff:ffff:ffff,42541829336310884227257139937291534336,42541829415539046741521477530835484671,20014220000000000000000000000000,20014220ffffffffffffffffffffffff",
			//nolint: lll
			"2402:d000::/32,2402:d000::,2402:d000:ffff:ffff:ffff:ffff:ffff:ffff,47866811183171600627242296191018336256,47866811262399763141506633784562286591,2402d000000000000000000000000000,2402d000ffffffffffffffffffffffff",
			//nolint: lll
			"2406:4000::/32,2406:4000::,2406:4000:ffff:ffff:ffff:ffff:ffff:ffff,47884659703622814097215369772150030336,47884659782850976611479707365693980671,24064000000000000000000000000000,24064000ffffffffffffffffffffffff",
		},
	)
}

func checkOutput(
	t *testing.T,
	name string,
	cidr bool,
	ipRange bool,
	intRange bool,
	hexRange bool,
	expected []interface{},
) {
	//nolint: lll
	input := `network,geoname_id,registered_country_geoname_id,represented_country_geoname_id,is_anonymous_proxy,is_satellite_provider
1.0.0.0/24,2077456,2077456,,0,0
4.69.140.16/29,6252001,6252001,,0,0
5.61.192.0/21,2635167,2635167,,0,0
2001:4220::/32,357994,357994,,0,0
2402:d000::/32,1227603,1227603,,0,0
2406:4000::/32,1835841,1835841,,0,0
`
	var outbuf bytes.Buffer

	err := Convert(strings.NewReader(input), &outbuf, cidr, ipRange, intRange, hexRange)
	if err != nil {
		t.Fatal(err)
	}

	// This is a regexp as Go 1.4 does not quote empty fields while earlier
	// versions do
	//nolint: lll
	outTMPL := `%s,geoname_id,registered_country_geoname_id,represented_country_geoname_id,is_anonymous_proxy,is_satellite_provider
%s,2077456,2077456,(?:"")?,0,0
%s,6252001,6252001,(?:"")?,0,0
%s,2635167,2635167,(?:"")?,0,0
%s,357994,357994,(?:"")?,0,0
%s,1227603,1227603,(?:"")?,0,0
%s,1835841,1835841,(?:"")?,0,0
`

	assert.Regexp(
		t,
		fmt.Sprintf(outTMPL, expected...),
		outbuf.String(),
		name,
	)
}

func TestFileWriting(t *testing.T) {
	input := `network,something
1.0.0.0/24,"some more"
`

	//nolint: lll
	expected := `network,network_start_ip,network_last_ip,network_start_integer,network_last_integer,network_start_hex,network_last_hex,something
1.0.0.0/24,1.0.0.0,1.0.0.255,16777216,16777471,1000000,10000ff,some more
`

	inFile, err := os.CreateTemp("", "input")
	if err != nil {
		t.Fatal(err)
	}
	defer inFile.Close() //nolint: gosec

	outFile, err := os.CreateTemp("", "output")
	if err != nil {
		t.Fatal(err)
	}
	defer outFile.Close() //nolint: gosec

	_, err = inFile.WriteString(input)
	require.NoError(t, err)

	err = ConvertFile(inFile.Name(), outFile.Name(), true, true, true, true)
	if err != nil {
		t.Fatal(err)
	}

	buf := bytes.NewBuffer(nil)
	_, err = io.Copy(buf, outFile)
	require.NoError(t, err)

	assert.Equal(t, expected, buf.String())
}
<|endoftext|>


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

package build

import (
	"appengine"
	"appengine/datastore"
	"appengine/delay"
	"appengine/mail"
	"bytes"
	"encoding/gob"
	"fmt"
	"text/template"
)

const (
	mailFrom   = "builder@golang.org" // use this for sending any mail
	failMailTo = "golang-dev@googlegroups.com"
	domain     = "build.golang.org"
)

// notifyOnFailure checks whether the supplied Commit or the subsequent
// Commit (if present) breaks the build for this builder.
// If either of those commits break the build an email notification is sent
// from a delayed task. (We use a task because this way the mail won't be
// sent if the enclosing datastore transaction fails.)
//
// This must be run in a datastore transaction, and the provided *Commit must
// have been retrieved from the datastore within that transaction.
func notifyOnFailure(c appengine.Context, com *Commit, builder string) error {
	// TODO(adg): implement notifications for packages
	if com.PackagePath != "" {
		return nil
	}

	p := &Package{Path: com.PackagePath}
	var broken *Commit
	cr := com.Result(builder, "")
	if cr == nil {
		return fmt.Errorf("no result for %s/%s", com.Hash, builder)
	}
	q := datastore.NewQuery("Commit").Ancestor(p.Key(c))
	if cr.OK {
		// This commit is OK. Notify if next Commit is broken.
		next := new(Commit)
		q.Filter("ParentHash=", com.Hash)
		if err := firstMatch(c, q, next); err != nil {
			if err == datastore.ErrNoSuchEntity {
				// OK at tip, no notification necessary.
				return nil
			}
			return err
		}
		if nr := next.Result(builder, ""); nr != nil && !nr.OK {
			c.Debugf("commit ok: %#v\nresult: %#v", com, cr)
			c.Debugf("next commit broken: %#v\nnext result:%#v", next, nr)
			broken = next
		}
	} else {
		// This commit is broken. Notify if the previous Commit is OK.
		prev := new(Commit)
		q.Filter("Hash=", com.ParentHash)
		if err := firstMatch(c, q, prev); err != nil {
			if err == datastore.ErrNoSuchEntity {
				// No previous result, let the backfill of
				// this result trigger the notification.
				return nil
			}
			return err
		}
		if pr := prev.Result(builder, ""); pr != nil && pr.OK {
			c.Debugf("commit broken: %#v\nresult: %#v", com, cr)
			c.Debugf("previous commit ok: %#v\nprevious result:%#v", prev, pr)
			broken = com
		}
	}
	var err error
	if broken != nil && !broken.FailNotificationSent {
		c.Infof("%s is broken commit; notifying", broken.Hash)
		sendFailMailLater.Call(c, broken, builder) // add task to queue
		broken.FailNotificationSent = true
		_, err = datastore.Put(c, broken.Key(c), broken)
	}
	return err
}

// firstMatch executes the query q and loads the first entity into v.
func firstMatch(c appengine.Context, q *datastore.Query, v interface{}) error {
	t := q.Limit(1).Run(c)
	_, err := t.Next(v)
	if err == datastore.Done {
		err = datastore.ErrNoSuchEntity
	}
	return err
}

var (
	sendFailMailLater = delay.Func("sendFailMail", sendFailMail)
	sendFailMailTmpl  = template.Must(
		template.New("notify.txt").
			Funcs(template.FuncMap(tmplFuncs)).
			ParseFiles("build/notify.txt"),
	)
)

func init() {
	gob.Register(&Commit{}) // for delay
}

// sendFailMail sends a mail notification that the build failed on the
// provided commit and builder.
func sendFailMail(c appengine.Context, com *Commit, builder string) {
	// TODO(adg): handle packages

	// get Result
	r := com.Result(builder, "")
	if r == nil {
		c.Errorf("finding result for %q: %+v", builder, com)
		return
	}

	// get Log
	k := datastore.NewKey(c, "Log", r.LogHash, 0, nil)
	l := new(Log)
	if err := datastore.Get(c, k, l); err != nil {
		c.Errorf("finding Log record %v: %v", r.LogHash, err)
		return
	}

	// prepare mail message
	var body bytes.Buffer
	err := sendFailMailTmpl.Execute(&body, map[string]interface{}{
		"Builder": builder, "Commit": com, "Result": r, "Log": l,
		"Hostname": domain,
	})
	if err != nil {
		c.Errorf("rendering mail template: %v", err)
		return
	}
	subject := fmt.Sprintf("%s broken by %s", builder, shortDesc(com.Desc))
	msg := &mail.Message{
		Sender:  mailFrom,
		To:      []string{failMailTo},
		ReplyTo: failMailTo,
		Subject: subject,
		Body:    body.String(),
	}

	// send mail
	if err := mail.Send(c, msg); err != nil {
		c.Errorf("sending mail: %v", err)
	}
}
<commit_msg>      misc/dashboard/app: fix build failure notifications<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package build

import (
	"appengine"
	"appengine/datastore"
	"appengine/delay"
	"appengine/mail"
	"bytes"
	"encoding/gob"
	"fmt"
	"text/template"
)

const (
	mailFrom   = "builder@golang.org" // use this for sending any mail
	failMailTo = "golang-dev@googlegroups.com"
	domain     = "build.golang.org"
)

// notifyOnFailure checks whether the supplied Commit or the subsequent
// Commit (if present) breaks the build for this builder.
// If either of those commits break the build an email notification is sent
// from a delayed task. (We use a task because this way the mail won't be
// sent if the enclosing datastore transaction fails.)
//
// This must be run in a datastore transaction, and the provided *Commit must
// have been retrieved from the datastore within that transaction.
func notifyOnFailure(c appengine.Context, com *Commit, builder string) error {
	// TODO(adg): implement notifications for packages
	if com.PackagePath != "" {
		return nil
	}

	p := &Package{Path: com.PackagePath}
	var broken *Commit
	cr := com.Result(builder, "")
	if cr == nil {
		return fmt.Errorf("no result for %s/%s", com.Hash, builder)
	}
	q := datastore.NewQuery("Commit").Ancestor(p.Key(c))
	if cr.OK {
		// This commit is OK. Notify if next Commit is broken.
		next := new(Commit)
		q = q.Filter("ParentHash=", com.Hash)
		if err := firstMatch(c, q, next); err != nil {
			if err == datastore.ErrNoSuchEntity {
				// OK at tip, no notification necessary.
				return nil
			}
			return err
		}
		if nr := next.Result(builder, ""); nr != nil && !nr.OK {
			c.Debugf("commit ok: %#v\nresult: %#v", com, cr)
			c.Debugf("next commit broken: %#v\nnext result:%#v", next, nr)
			broken = next
		}
	} else {
		// This commit is broken. Notify if the previous Commit is OK.
		prev := new(Commit)
		q = q.Filter("Hash=", com.ParentHash)
		if err := firstMatch(c, q, prev); err != nil {
			if err == datastore.ErrNoSuchEntity {
				// No previous result, let the backfill of
				// this result trigger the notification.
				return nil
			}
			return err
		}
		if pr := prev.Result(builder, ""); pr != nil && pr.OK {
			c.Debugf("commit broken: %#v\nresult: %#v", com, cr)
			c.Debugf("previous commit ok: %#v\nprevious result:%#v", prev, pr)
			broken = com
		}
	}
	var err error
	if broken != nil && !broken.FailNotificationSent {
		c.Infof("%s is broken commit; notifying", broken.Hash)
		sendFailMailLater.Call(c, broken, builder) // add task to queue
		broken.FailNotificationSent = true
		_, err = datastore.Put(c, broken.Key(c), broken)
	}
	return err
}

// firstMatch executes the query q and loads the first entity into v.
func firstMatch(c appengine.Context, q *datastore.Query, v interface{}) error {
	t := q.Limit(1).Run(c)
	_, err := t.Next(v)
	if err == datastore.Done {
		err = datastore.ErrNoSuchEntity
	}
	return err
}

var (
	sendFailMailLater = delay.Func("sendFailMail", sendFailMail)
	sendFailMailTmpl  = template.Must(
		template.New("notify.txt").
			Funcs(template.FuncMap(tmplFuncs)).
			ParseFiles("build/notify.txt"),
	)
)

func init() {
	gob.Register(&Commit{}) // for delay
}

// sendFailMail sends a mail notification that the build failed on the
// provided commit and builder.
func sendFailMail(c appengine.Context, com *Commit, builder string) {
	// TODO(adg): handle packages

	// get Result
	r := com.Result(builder, "")
	if r == nil {
		c.Errorf("finding result for %q: %+v", builder, com)
		return
	}

	// get Log
	k := datastore.NewKey(c, "Log", r.LogHash, 0, nil)
	l := new(Log)
	if err := datastore.Get(c, k, l); err != nil {
		c.Errorf("finding Log record %v: %v", r.LogHash, err)
		return
	}

	// prepare mail message
	var body bytes.Buffer
	err := sendFailMailTmpl.Execute(&body, map[string]interface{}{
		"Builder": builder, "Commit": com, "Result": r, "Log": l,
		"Hostname": domain,
	})
	if err != nil {
		c.Errorf("rendering mail template: %v", err)
		return
	}
	subject := fmt.Sprintf("%s broken by %s", builder, shortDesc(com.Desc))
	msg := &mail.Message{
		Sender:  mailFrom,
		To:      []string{failMailTo},
		ReplyTo: failMailTo,
		Subject: subject,
		Body:    body.String(),
	}

	// send mail
	if err := mail.Send(c, msg); err != nil {
		c.Errorf("sending mail: %v", err)
	}
}
<|endoftext|>


<commit_before>package tree

import "github.com/catorpilor/leetcode/utils"

func buildTree(preorder, inorder []int) *utils.TreeNode {
	return nil
}
<commit_msg>solve 105 using dfs<commit_after>package tree

import "github.com/catorpilor/leetcode/utils"

func buildTree(preorder, inorder []int) *utils.TreeNode {
	return useDFS(preorder, inorder)
}

// useDFS time complexity O(N) space complexity  O(1)
func useDFS(preorder, inorder []int) *utils.TreeNode {
	np, ni := len(preorder), len(inorder)
	if np < 1 && ni < 1 {
		return nil
	}
	val := preorder[0] // root val
	root := &utils.TreeNode{Val: val}
	if np == 1 && ni == 1 {
		return root
	}
	var pos int // find root's pos in inorder array
	for pos < ni {
		if inorder[pos] == val {
			break
		}
		pos++
	}
	root.Left = useDFS(preorder[1:1+pos], inorder[:pos])
	root.Right = useDFS(preorder[1+pos:], inorder[pos+1:])
	return root
}
<|endoftext|>