<commit_before>package log

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path"
	"runtime"
	"strconv"
	"sync"
	"time"

	"github.com/mattn/go-isatty"
	"github.com/valyala/fasttemplate"

	"github.com/labstack/gommon/color"
)

type (
	Logger struct {
		prefix     string
		level      Lvl
		output     io.Writer
		template   *fasttemplate.Template
		levels     []string
		color      *color.Color
		bufferPool sync.Pool
		mutex      sync.Mutex
	}

	Lvl uint8

	JSON map[string]interface{}
)

const (
	DEBUG Lvl = iota + 1
	INFO
	WARN
	ERROR
	OFF
)

var (
	global        = New("-")
	defaultHeader = `{"time":"${time_rfc3339_nano}","level":"${level}","prefix":"${prefix}",` +
		`"file":"${short_file}","line":"${line}"}`
)

func New(prefix string) (l *Logger) {
	l = &Logger{
		level:    INFO,
		prefix:   prefix,
		template: l.newTemplate(defaultHeader),
		color:    color.New(),
		bufferPool: sync.Pool{
			New: func() interface{} {
				return bytes.NewBuffer(make([]byte, 256))
			},
		},
	}
	l.initLevels()
	l.SetOutput(output())
	return
}

func (l *Logger) initLevels() {
	l.levels = []string{
		"-",
		l.color.Blue("DEBUG"),
		l.color.Green("INFO"),
		l.color.Yellow("WARN"),
		l.color.Red("ERROR"),
	}
}

func (l *Logger) newTemplate(format string) *fasttemplate.Template {
	return fasttemplate.New(format, "${", "}")
}

func (l *Logger) DisableColor() {
	l.color.Disable()
	l.initLevels()
}

func (l *Logger) EnableColor() {
	l.color.Enable()
	l.initLevels()
}

func (l *Logger) Prefix() string {
	return l.prefix
}

func (l *Logger) SetPrefix(p string) {
	l.prefix = p
}

func (l *Logger) Level() Lvl {
	return l.level
}

func (l *Logger) SetLevel(v Lvl) {
	l.level = v
}

func (l *Logger) Output() io.Writer {
	return l.output
}

func (l *Logger) SetOutput(w io.Writer) {
	l.output = w
	if w, ok := w.(*os.File); !ok || !isatty.IsTerminal(w.Fd()) {
		l.DisableColor()
	}
}

func (l *Logger) Color() *color.Color {
	return l.color
}

func (l *Logger) SetHeader(h string) {
	l.template = l.newTemplate(h)
}

func (l *Logger) Print(i ...interface{}) {
	l.log(0, "", i...)
	// fmt.Fprintln(l.output, i...)
}

func (l *Logger) Printf(format string, args ...interface{}) {
	l.log(0, format, args...)
}

func (l *Logger) Printj(j JSON) {
	l.log(0, "json", j)
}

func (l *Logger) Debug(i ...interface{}) {
	l.log(DEBUG, "", i...)
}

func (l *Logger) Debugf(format string, args ...interface{}) {
	l.log(DEBUG, format, args...)
}

func (l *Logger) Debugj(j JSON) {
	l.log(DEBUG, "json", j)
}

func (l *Logger) Info(i ...interface{}) {
	l.log(INFO, "", i...)
}

func (l *Logger) Infof(format string, args ...interface{}) {
	l.log(INFO, format, args...)
}

func (l *Logger) Infoj(j JSON) {
	l.log(INFO, "json", j)
}

func (l *Logger) Warn(i ...interface{}) {
	l.log(WARN, "", i...)
}

func (l *Logger) Warnf(format string, args ...interface{}) {
	l.log(WARN, format, args...)
}

func (l *Logger) Warnj(j JSON) {
	l.log(WARN, "json", j)
}

func (l *Logger) Error(i ...interface{}) {
	l.log(ERROR, "", i...)
}

func (l *Logger) Errorf(format string, args ...interface{}) {
	l.log(ERROR, format, args...)
}

func (l *Logger) Errorj(j JSON) {
	l.log(ERROR, "json", j)
}

func (l *Logger) Fatal(i ...interface{}) {
	l.Print(i...)
	os.Exit(1)
}

func (l *Logger) Fatalf(format string, args ...interface{}) {
	l.Printf(format, args...)
	os.Exit(1)
}

func (l *Logger) Fatalj(j JSON) {
	l.Printj(j)
	os.Exit(1)
}

func (l *Logger) Panic(i ...interface{}) {
	l.Print(i...)
	panic(fmt.Sprint(i...))
}

func (l *Logger) Panicf(format string, args ...interface{}) {
	l.Printf(format, args...)
	panic(fmt.Sprintf(format, args))
}

func (l *Logger) Panicj(j JSON) {
	l.Printj(j)
	panic(j)
}

func DisableColor() {
	global.DisableColor()
}

func EnableColor() {
	global.EnableColor()
}

func Prefix() string {
	return global.Prefix()
}

func SetPrefix(p string) {
	global.SetPrefix(p)
}

func Level() Lvl {
	return global.Level()
}

func SetLevel(v Lvl) {
	global.SetLevel(v)
}

func Output() io.Writer {
	return global.Output()
}

func SetOutput(w io.Writer) {
	global.SetOutput(w)
}

func SetHeader(h string) {
	global.SetHeader(h)
}

func Print(i ...interface{}) {
	global.Print(i...)
}

func Printf(format string, args ...interface{}) {
	global.Printf(format, args...)
}

func Printj(j JSON) {
	global.Printj(j)
}

func Debug(i ...interface{}) {
	global.Debug(i...)
}

func Debugf(format string, args ...interface{}) {
	global.Debugf(format, args...)
}

func Debugj(j JSON) {
	global.Debugj(j)
}

func Info(i ...interface{}) {
	global.Info(i...)
}

func Infof(format string, args ...interface{}) {
	global.Infof(format, args...)
}

func Infoj(j JSON) {
	global.Infoj(j)
}

func Warn(i ...interface{}) {
	global.Warn(i...)
}

func Warnf(format string, args ...interface{}) {
	global.Warnf(format, args...)
}

func Warnj(j JSON) {
	global.Warnj(j)
}

func Error(i ...interface{}) {
	global.Error(i...)
}

func Errorf(format string, args ...interface{}) {
	global.Errorf(format, args...)
}

func Errorj(j JSON) {
	global.Errorj(j)
}

func Fatal(i ...interface{}) {
	global.Fatal(i...)
}

func Fatalf(format string, args ...interface{}) {
	global.Fatalf(format, args...)
}

func Fatalj(j JSON) {
	global.Fatalj(j)
}

func Panic(i ...interface{}) {
	global.Panic(i...)
}

func Panicf(format string, args ...interface{}) {
	global.Panicf(format, args...)
}

func Panicj(j JSON) {
	global.Panicj(j)
}

func (l *Logger) log(v Lvl, format string, args ...interface{}) {
	l.mutex.Lock()
	defer l.mutex.Unlock()
	buf := l.bufferPool.Get().(*bytes.Buffer)
	buf.Reset()
	defer l.bufferPool.Put(buf)
	_, file, line, _ := runtime.Caller(2)

	if v >= l.level || v == 0 {
		message := ""
		if format == "" {
			message = fmt.Sprint(args...)
		} else if format == "json" {
			b, err := json.Marshal(args[0])
			if err != nil {
				panic(err)
			}
			message = string(b)
		} else {
			message = fmt.Sprintf(format, args...)
		}

		_, err := l.template.ExecuteFunc(buf, func(w io.Writer, tag string) (int, error) {
			switch tag {
			case "time_rfc3339":
				return w.Write([]byte(time.Now().Format(time.RFC3339)))
			case "time_rfc3339_nano":
				return w.Write([]byte(time.Now().Format(time.RFC3339Nano)))
			case "level":
				return w.Write([]byte(l.levels[v]))
			case "prefix":
				return w.Write([]byte(l.prefix))
			case "long_file":
				return w.Write([]byte(file))
			case "short_file":
				return w.Write([]byte(path.Base(file)))
			case "line":
				return w.Write([]byte(strconv.Itoa(line)))
			}
			return 0, nil
		})

		if err == nil {
			s := buf.String()
			i := buf.Len() - 1
			if s[i] == '}' {
				// JSON header
				buf.Truncate(i)
				buf.WriteByte(',')
				if format == "json" {
					buf.WriteString(message[1:])
				} else {
					buf.WriteString(`"message":`)
					buf.WriteString(strconv.Quote(message))
					buf.WriteString(`}`)
				}
			} else {
				// Text header
				buf.WriteByte(' ')
				buf.WriteString(message)
			}
			buf.WriteByte('\n')
			l.output.Write(buf.Bytes())
		}
	}
}
<commit_msg>Make the Panic and the Fatal functions behave similar to the rest (#19)<commit_after>package log

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path"
	"runtime"
	"strconv"
	"sync"
	"time"

	"github.com/mattn/go-isatty"
	"github.com/valyala/fasttemplate"

	"github.com/labstack/gommon/color"
)

type (
	Logger struct {
		prefix     string
		level      Lvl
		output     io.Writer
		template   *fasttemplate.Template
		levels     []string
		color      *color.Color
		bufferPool sync.Pool
		mutex      sync.Mutex
	}

	Lvl uint8

	JSON map[string]interface{}
)

const (
	DEBUG Lvl = iota + 1
	INFO
	WARN
	ERROR
	OFF
	panicLevel
	fatalLevel
)

var (
	global        = New("-")
	defaultHeader = `{"time":"${time_rfc3339_nano}","level":"${level}","prefix":"${prefix}",` +
		`"file":"${short_file}","line":"${line}"}`
)

func New(prefix string) (l *Logger) {
	l = &Logger{
		level:    INFO,
		prefix:   prefix,
		template: l.newTemplate(defaultHeader),
		color:    color.New(),
		bufferPool: sync.Pool{
			New: func() interface{} {
				return bytes.NewBuffer(make([]byte, 256))
			},
		},
	}
	l.initLevels()
	l.SetOutput(output())
	return
}

func (l *Logger) initLevels() {
	l.levels = []string{
		"-",
		l.color.Blue("DEBUG"),
		l.color.Green("INFO"),
		l.color.Yellow("WARN"),
		l.color.Red("ERROR"),
		"",
		l.color.Yellow("PANIC", color.U),
		l.color.Red("FATAL", color.U),
	}
}

func (l *Logger) newTemplate(format string) *fasttemplate.Template {
	return fasttemplate.New(format, "${", "}")
}

func (l *Logger) DisableColor() {
	l.color.Disable()
	l.initLevels()
}

func (l *Logger) EnableColor() {
	l.color.Enable()
	l.initLevels()
}

func (l *Logger) Prefix() string {
	return l.prefix
}

func (l *Logger) SetPrefix(p string) {
	l.prefix = p
}

func (l *Logger) Level() Lvl {
	return l.level
}

func (l *Logger) SetLevel(v Lvl) {
	l.level = v
}

func (l *Logger) Output() io.Writer {
	return l.output
}

func (l *Logger) SetOutput(w io.Writer) {
	l.output = w
	if w, ok := w.(*os.File); !ok || !isatty.IsTerminal(w.Fd()) {
		l.DisableColor()
	}
}

func (l *Logger) Color() *color.Color {
	return l.color
}

func (l *Logger) SetHeader(h string) {
	l.template = l.newTemplate(h)
}

func (l *Logger) Print(i ...interface{}) {
	l.log(0, "", i...)
	// fmt.Fprintln(l.output, i...)
}

func (l *Logger) Printf(format string, args ...interface{}) {
	l.log(0, format, args...)
}

func (l *Logger) Printj(j JSON) {
	l.log(0, "json", j)
}

func (l *Logger) Debug(i ...interface{}) {
	l.log(DEBUG, "", i...)
}

func (l *Logger) Debugf(format string, args ...interface{}) {
	l.log(DEBUG, format, args...)
}

func (l *Logger) Debugj(j JSON) {
	l.log(DEBUG, "json", j)
}

func (l *Logger) Info(i ...interface{}) {
	l.log(INFO, "", i...)
}

func (l *Logger) Infof(format string, args ...interface{}) {
	l.log(INFO, format, args...)
}

func (l *Logger) Infoj(j JSON) {
	l.log(INFO, "json", j)
}

func (l *Logger) Warn(i ...interface{}) {
	l.log(WARN, "", i...)
}

func (l *Logger) Warnf(format string, args ...interface{}) {
	l.log(WARN, format, args...)
}

func (l *Logger) Warnj(j JSON) {
	l.log(WARN, "json", j)
}

func (l *Logger) Error(i ...interface{}) {
	l.log(ERROR, "", i...)
}

func (l *Logger) Errorf(format string, args ...interface{}) {
	l.log(ERROR, format, args...)
}

func (l *Logger) Errorj(j JSON) {
	l.log(ERROR, "json", j)
}

func (l *Logger) Fatal(i ...interface{}) {
	l.log(fatalLevel, "", i...)
	os.Exit(1)
}

func (l *Logger) Fatalf(format string, args ...interface{}) {
	l.log(fatalLevel, format, args...)
	os.Exit(1)
}

func (l *Logger) Fatalj(j JSON) {
	l.log(fatalLevel, "json", j)
	os.Exit(1)
}

func (l *Logger) Panic(i ...interface{}) {
	l.log(panicLevel, "", i...)
	panic(fmt.Sprint(i...))
}

func (l *Logger) Panicf(format string, args ...interface{}) {
	l.log(panicLevel, format, args...)
	panic(fmt.Sprintf(format, args))
}

func (l *Logger) Panicj(j JSON) {
	l.log(panicLevel, "json", j)
	panic(j)
}

func DisableColor() {
	global.DisableColor()
}

func EnableColor() {
	global.EnableColor()
}

func Prefix() string {
	return global.Prefix()
}

func SetPrefix(p string) {
	global.SetPrefix(p)
}

func Level() Lvl {
	return global.Level()
}

func SetLevel(v Lvl) {
	global.SetLevel(v)
}

func Output() io.Writer {
	return global.Output()
}

func SetOutput(w io.Writer) {
	global.SetOutput(w)
}

func SetHeader(h string) {
	global.SetHeader(h)
}

func Print(i ...interface{}) {
	global.Print(i...)
}

func Printf(format string, args ...interface{}) {
	global.Printf(format, args...)
}

func Printj(j JSON) {
	global.Printj(j)
}

func Debug(i ...interface{}) {
	global.Debug(i...)
}

func Debugf(format string, args ...interface{}) {
	global.Debugf(format, args...)
}

func Debugj(j JSON) {
	global.Debugj(j)
}

func Info(i ...interface{}) {
	global.Info(i...)
}

func Infof(format string, args ...interface{}) {
	global.Infof(format, args...)
}

func Infoj(j JSON) {
	global.Infoj(j)
}

func Warn(i ...interface{}) {
	global.Warn(i...)
}

func Warnf(format string, args ...interface{}) {
	global.Warnf(format, args...)
}

func Warnj(j JSON) {
	global.Warnj(j)
}

func Error(i ...interface{}) {
	global.Error(i...)
}

func Errorf(format string, args ...interface{}) {
	global.Errorf(format, args...)
}

func Errorj(j JSON) {
	global.Errorj(j)
}

func Fatal(i ...interface{}) {
	global.Fatal(i...)
}

func Fatalf(format string, args ...interface{}) {
	global.Fatalf(format, args...)
}

func Fatalj(j JSON) {
	global.Fatalj(j)
}

func Panic(i ...interface{}) {
	global.Panic(i...)
}

func Panicf(format string, args ...interface{}) {
	global.Panicf(format, args...)
}

func Panicj(j JSON) {
	global.Panicj(j)
}

func (l *Logger) log(v Lvl, format string, args ...interface{}) {
	l.mutex.Lock()
	defer l.mutex.Unlock()
	buf := l.bufferPool.Get().(*bytes.Buffer)
	buf.Reset()
	defer l.bufferPool.Put(buf)
	_, file, line, _ := runtime.Caller(2)

	if v >= l.level || v == 0 {
		message := ""
		if format == "" {
			message = fmt.Sprint(args...)
		} else if format == "json" {
			b, err := json.Marshal(args[0])
			if err != nil {
				panic(err)
			}
			message = string(b)
		} else {
			message = fmt.Sprintf(format, args...)
		}

		_, err := l.template.ExecuteFunc(buf, func(w io.Writer, tag string) (int, error) {
			switch tag {
			case "time_rfc3339":
				return w.Write([]byte(time.Now().Format(time.RFC3339)))
			case "time_rfc3339_nano":
				return w.Write([]byte(time.Now().Format(time.RFC3339Nano)))
			case "level":
				return w.Write([]byte(l.levels[v]))
			case "prefix":
				return w.Write([]byte(l.prefix))
			case "long_file":
				return w.Write([]byte(file))
			case "short_file":
				return w.Write([]byte(path.Base(file)))
			case "line":
				return w.Write([]byte(strconv.Itoa(line)))
			}
			return 0, nil
		})

		if err == nil {
			s := buf.String()
			i := buf.Len() - 1
			if s[i] == '}' {
				// JSON header
				buf.Truncate(i)
				buf.WriteByte(',')
				if format == "json" {
					buf.WriteString(message[1:])
				} else {
					buf.WriteString(`"message":`)
					buf.WriteString(strconv.Quote(message))
					buf.WriteString(`}`)
				}
			} else {
				// Text header
				buf.WriteByte(' ')
				buf.WriteString(message)
			}
			buf.WriteByte('\n')
			l.output.Write(buf.Bytes())
		}
	}
}
<|endoftext|>


<commit_before>package log

import (
	"os"
	"strings"
	"sync"

	"github.com/zimmski/logrus"
)

var log = logrus.New()
var logIndentation int
var logIndentationLock sync.RWMutex

func init() {
	log.Formatter = &TextFormatter{}
	log.Out = os.Stderr
}

// setting functions

// Level sets the current log level
func Level(level logrus.Level) {
	log.Level = level
}

// LevelDebug sets the current log level to Debug
func LevelDebug() {
	Level(logrus.DebugLevel)
}

// LevelInfo sets the current log level to Info
func LevelInfo() {
	Level(logrus.InfoLevel)
}

// LevelWarn sets the current log level to Warn
func LevelWarn() {
	Level(logrus.WarnLevel)
}

// LevelError sets the current log level to Error
func LevelError() {
	Level(logrus.ErrorLevel)
}

// indentation functions

func indentation() string {
	logIndentationLock.RLock()
	defer logIndentationLock.RUnlock()

	return strings.Repeat("  ", logIndentation)
}

func IncreaseIndentation() {
	logIndentationLock.Lock()
	defer logIndentationLock.Unlock()

	logIndentation++

}

func DecreaseIndentation() {
	logIndentationLock.Lock()
	defer logIndentationLock.Unlock()

	logIndentation--

	if logIndentation < 0 {
		panic("Log indentation is negative")
	}
}

// logging functions

// Debugf logs a message at level Debug on the standard logger.
func Debugf(format string, args ...interface{}) {
	log.Debugf(indentation()+format, args...)
}

// Infof logs a message at level Info on the standard logger.
func Infof(format string, args ...interface{}) {
	log.Infof(indentation()+format, args...)
}

// Printf logs a message at level Info on the standard logger.
func Printf(format string, args ...interface{}) {
	log.Printf(indentation()+format, args...)
}

// Warnf logs a message at level Warn on the standard logger.
func Warnf(format string, args ...interface{}) {
	log.Warnf(indentation()+format, args...)
}

// Warningf logs a message at level Warn on the standard logger.
func Warningf(format string, args ...interface{}) {
	log.Warnf(indentation()+format, args...)
}

// Errorf logs a message at level Error on the standard logger.
func Errorf(format string, args ...interface{}) {
	log.Errorf(indentation()+format, args...)
}

// Fatalf logs a message at level Fatal on the standard logger.
func Fatalf(format string, args ...interface{}) {
	log.Fatalf(indentation()+format, args...)
}

// Panicf logs a message at level Panic on the standard logger.
func Panicf(format string, args ...interface{}) {
	log.Panicf(indentation()+format, args...)
}

// Debug logs a message at level Debug on the standard logger.
func Debug(args ...interface{}) {
	log.Debug(append([]interface{}{indentation()}, args...)...)
}

// Info logs a message at level Info on the standard logger.
func Info(args ...interface{}) {
	log.Info(append([]interface{}{indentation()}, args...)...)
}

// Print logs a message at level Info on the standard logger.
func Print(args ...interface{}) {
	log.Info(append([]interface{}{indentation()}, args...)...)
}

// Warn logs a message at level Warn on the standard logger.
func Warn(args ...interface{}) {
	log.Warn(append([]interface{}{indentation()}, args...)...)
}

// Warning logs a message at level Warn on the standard logger.
func Warning(args ...interface{}) {
	log.Warn(append([]interface{}{indentation()}, args...)...)
}

// Error logs a message at level Error on the standard logger.
func Error(args ...interface{}) {
	log.Error(append([]interface{}{indentation()}, args...)...)
}

// Fatal logs a message at level Fatal on the standard logger.
func Fatal(args ...interface{}) {
	log.Fatal(append([]interface{}{indentation()}, args...)...)
}

// Panic logs a message at level Panic on the standard logger.
func Panic(args ...interface{}) {
	log.Panic(append([]interface{}{indentation()}, args...)...)
}

// Debugln logs a message at level Debug on the standard logger.
func Debugln(args ...interface{}) {
	log.Debugln(append([]interface{}{indentation()}, args...)...)
}

// Infoln logs a message at level Info on the standard logger.
func Infoln(args ...interface{}) {
	log.Infoln(append([]interface{}{indentation()}, args...)...)
}

// Println logs a message at level Info on the standard logger.
func Println(args ...interface{}) {
	log.Println(append([]interface{}{indentation()}, args...)...)
}

// Warnln logs a message at level Warn on the standard logger.
func Warnln(args ...interface{}) {
	log.Warnln(append([]interface{}{indentation()}, args...)...)
}

// Warningln logs a message at level Warn on the standard logger.
func Warningln(args ...interface{}) {
	log.Warnln(append([]interface{}{indentation()}, args...)...)
}

// Errorln logs a message at level Error on the standard logger.
func Errorln(args ...interface{}) {
	log.Errorln(append([]interface{}{indentation()}, args...)...)
}

// Fatalln logs a message at level Fatal on the standard logger.
func Fatalln(args ...interface{}) {
	log.Fatalln(append([]interface{}{indentation()}, args...)...)
}

// Panicln logs a message at level Panic on the standard logger.
func Panicln(args ...interface{}) {
	log.Panicln(append([]interface{}{indentation()}, args...)...)
}
<commit_msg>Document the new IncreaseIndentation and DecreaseIndentation functions<commit_after>package log

import (
	"os"
	"strings"
	"sync"

	"github.com/zimmski/logrus"
)

var log = logrus.New()
var logIndentation int
var logIndentationLock sync.RWMutex

func init() {
	log.Formatter = &TextFormatter{}
	log.Out = os.Stderr
}

// setting functions

// Level sets the current log level
func Level(level logrus.Level) {
	log.Level = level
}

// LevelDebug sets the current log level to Debug
func LevelDebug() {
	Level(logrus.DebugLevel)
}

// LevelInfo sets the current log level to Info
func LevelInfo() {
	Level(logrus.InfoLevel)
}

// LevelWarn sets the current log level to Warn
func LevelWarn() {
	Level(logrus.WarnLevel)
}

// LevelError sets the current log level to Error
func LevelError() {
	Level(logrus.ErrorLevel)
}

// indentation functions

func indentation() string {
	logIndentationLock.RLock()
	defer logIndentationLock.RUnlock()

	return strings.Repeat("  ", logIndentation)
}

// IncreaseIndentation increase the log indentation.
func IncreaseIndentation() {
	logIndentationLock.Lock()
	defer logIndentationLock.Unlock()

	logIndentation++

}

// DecreaseIndentation decrease the log indentation.
func DecreaseIndentation() {
	logIndentationLock.Lock()
	defer logIndentationLock.Unlock()

	logIndentation--

	if logIndentation < 0 {
		panic("Log indentation is negative")
	}
}

// logging functions

// Debugf logs a message at level Debug on the standard logger.
func Debugf(format string, args ...interface{}) {
	log.Debugf(indentation()+format, args...)
}

// Infof logs a message at level Info on the standard logger.
func Infof(format string, args ...interface{}) {
	log.Infof(indentation()+format, args...)
}

// Printf logs a message at level Info on the standard logger.
func Printf(format string, args ...interface{}) {
	log.Printf(indentation()+format, args...)
}

// Warnf logs a message at level Warn on the standard logger.
func Warnf(format string, args ...interface{}) {
	log.Warnf(indentation()+format, args...)
}

// Warningf logs a message at level Warn on the standard logger.
func Warningf(format string, args ...interface{}) {
	log.Warnf(indentation()+format, args...)
}

// Errorf logs a message at level Error on the standard logger.
func Errorf(format string, args ...interface{}) {
	log.Errorf(indentation()+format, args...)
}

// Fatalf logs a message at level Fatal on the standard logger.
func Fatalf(format string, args ...interface{}) {
	log.Fatalf(indentation()+format, args...)
}

// Panicf logs a message at level Panic on the standard logger.
func Panicf(format string, args ...interface{}) {
	log.Panicf(indentation()+format, args...)
}

// Debug logs a message at level Debug on the standard logger.
func Debug(args ...interface{}) {
	log.Debug(append([]interface{}{indentation()}, args...)...)
}

// Info logs a message at level Info on the standard logger.
func Info(args ...interface{}) {
	log.Info(append([]interface{}{indentation()}, args...)...)
}

// Print logs a message at level Info on the standard logger.
func Print(args ...interface{}) {
	log.Info(append([]interface{}{indentation()}, args...)...)
}

// Warn logs a message at level Warn on the standard logger.
func Warn(args ...interface{}) {
	log.Warn(append([]interface{}{indentation()}, args...)...)
}

// Warning logs a message at level Warn on the standard logger.
func Warning(args ...interface{}) {
	log.Warn(append([]interface{}{indentation()}, args...)...)
}

// Error logs a message at level Error on the standard logger.
func Error(args ...interface{}) {
	log.Error(append([]interface{}{indentation()}, args...)...)
}

// Fatal logs a message at level Fatal on the standard logger.
func Fatal(args ...interface{}) {
	log.Fatal(append([]interface{}{indentation()}, args...)...)
}

// Panic logs a message at level Panic on the standard logger.
func Panic(args ...interface{}) {
	log.Panic(append([]interface{}{indentation()}, args...)...)
}

// Debugln logs a message at level Debug on the standard logger.
func Debugln(args ...interface{}) {
	log.Debugln(append([]interface{}{indentation()}, args...)...)
}

// Infoln logs a message at level Info on the standard logger.
func Infoln(args ...interface{}) {
	log.Infoln(append([]interface{}{indentation()}, args...)...)
}

// Println logs a message at level Info on the standard logger.
func Println(args ...interface{}) {
	log.Println(append([]interface{}{indentation()}, args...)...)
}

// Warnln logs a message at level Warn on the standard logger.
func Warnln(args ...interface{}) {
	log.Warnln(append([]interface{}{indentation()}, args...)...)
}

// Warningln logs a message at level Warn on the standard logger.
func Warningln(args ...interface{}) {
	log.Warnln(append([]interface{}{indentation()}, args...)...)
}

// Errorln logs a message at level Error on the standard logger.
func Errorln(args ...interface{}) {
	log.Errorln(append([]interface{}{indentation()}, args...)...)
}

// Fatalln logs a message at level Fatal on the standard logger.
func Fatalln(args ...interface{}) {
	log.Fatalln(append([]interface{}{indentation()}, args...)...)
}

// Panicln logs a message at level Panic on the standard logger.
func Panicln(args ...interface{}) {
	log.Panicln(append([]interface{}{indentation()}, args...)...)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"regexp"
	"time"

	"github.com/fsnotify/fsnotify"
	"github.com/logplex/logplexc"
)

var redisPrefix = regexp.MustCompile(`([-*#] .*)`)

func lineWorker(die dieCh, f *os.File, cfg logplexc.Config, sr *serveRecord) {
	cfg.Logplex = sr.u

	target, err := logplexc.NewClient(&cfg)
	if err != nil {
		log.Fatalf("could not create logging client: %v", err)
	}

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Printf("can't create watcher: %v", err)
	}
	defer watcher.Close()

	r := bufio.NewReader(f)

	go func() {
		for {
			select {
			case <-die:
				return
			case event := <-watcher.Events:
				if event.Op&fsnotify.Write == fsnotify.Write {
					for {
						l, err := r.ReadBytes('\n')
						// Allow service specific changes
						l = parseLog(sr, l)

						// Don't emit empty lines
						l = bytes.TrimSpace(l)
						if len(l) == 0 {
							continue
						}

						// Append log prefix
						l = append([]byte(fmt.Sprintf("%s ", sr.Prefix)), l...)

						// Send the log line
						target.BufferMessage(134, time.Now(), sr.Service,
							sr.Service, l)

						if err != nil {
							if err == io.EOF {
								break
							}
							log.Printf("unexpected read error: %v", err)
						}
					}
				}
			case err := <-watcher.Errors:
				log.Printf("unexpected fs watch error %v:", err)
			}
		}
	}()

	if err := watcher.Add(f.Name()); err != nil {
		log.Printf("can't add watcher: %v", err)
	}

	<-die
}

func parseLog(sr *serveRecord, l []byte) []byte {
	switch sr.Service {
	case "redis":
		m := redisPrefix.Find(l)
		if len(m) > 1 {
			return m
		}
	}
	return l
}
<commit_msg>Empty lines are a signal that you should stop reading<commit_after>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"regexp"
	"time"

	"github.com/fsnotify/fsnotify"
	"github.com/logplex/logplexc"
)

var redisPrefix = regexp.MustCompile(`([-*#] .*)`)

func lineWorker(die dieCh, f *os.File, cfg logplexc.Config, sr *serveRecord) {
	cfg.Logplex = sr.u

	target, err := logplexc.NewClient(&cfg)
	if err != nil {
		log.Fatalf("could not create logging client: %v", err)
	}

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Printf("can't create watcher: %v", err)
	}
	defer watcher.Close()

	r := bufio.NewReader(f)

	go func() {
		for {
			select {
			case <-die:
				return
			case event := <-watcher.Events:
				if event.Op&fsnotify.Write == fsnotify.Write {
					for {
						l, err := r.ReadBytes('\n')
						// Allow service specific changes
						l = parseLog(sr, l)

						// Don't emit empty lines
						l = bytes.TrimSpace(l)
						if len(l) == 0 {
							break
						}

						// Append log prefix
						l = append([]byte(fmt.Sprintf("%s ", sr.Prefix)), l...)

						// Send the log line
						target.BufferMessage(134, time.Now(), sr.Service,
							sr.Service, l)

						if err != nil {
							if err == io.EOF {
								break
							}
							log.Printf("unexpected read error: %v", err)
						}
					}
				}
			case err := <-watcher.Errors:
				log.Printf("unexpected fs watch error %v:", err)
			}
		}
	}()

	if err := watcher.Add(f.Name()); err != nil {
		log.Printf("can't add watcher: %v", err)
	}

	<-die
}

func parseLog(sr *serveRecord, l []byte) []byte {
	switch sr.Service {
	case "redis":
		m := redisPrefix.Find(l)
		if len(m) > 1 {
			return m
		}
	}
	return l
}
<|endoftext|>


<commit_before>package logging

import (
	"errors"
	"log"
)

var (
	Default *Logger
	loggers map[string]*Logger
)

// errors
var (
	ErrLoggerNotFounded = errors.New("Logger name is not in loggers")
)

func init() {
	loggers = map[string]*Logger{}
	Default = &Logger{
		Name:   "default",
		Level:  DEBUG,
		Logger: GetDefaultLogger(),
	}
}

func GetLogger(name string) *Logger {
	logger, ok := loggers[name]
	if !ok {
		Default.Warn("cannot find logger \"" + name + "\" - return to default logger")
		return Default
	}

	return logger
}

func SetLogger(name string, level Level, logger *log.Logger) {
	l, ok := loggers[name]
	if ok {
		l.Level = level
		l.Logger = logger
	} else {
		l = &Logger{
			Name:   name,
			Level:  level,
			Logger: logger,
		}
	}

	loggers[l.Name] = l
}

func SetLevel(name string, level Level) error {
	logger, ok := loggers[name]
	if !ok {
		Default.Error("cannot find logger " + name)
		return ErrLoggerNotFounded
	}

	logger.Level = level
	return nil
}
<commit_msg>gelogger name이 default면 로깅 찍지 않게 수정<commit_after>package logging

import (
	"errors"
	"log"
)

var (
	Default *Logger
	loggers map[string]*Logger
)

// errors
var (
	ErrLoggerNotFounded = errors.New("Logger name is not in loggers")
)

func init() {
	loggers = map[string]*Logger{}
	Default = &Logger{
		Name:   "default",
		Level:  DEBUG,
		Logger: GetDefaultLogger(),
	}
}

func GetLogger(name string) *Logger {
	logger, ok := loggers[name]
	if !ok {
		if name != "default" {
			Default.Warn("cannot find logger \"" + name + "\" - return to default logger")
		}
		return Default
	}

	return logger
}

func SetLogger(name string, level Level, logger *log.Logger) {
	l, ok := loggers[name]
	if ok {
		l.Level = level
		l.Logger = logger
	} else {
		l = &Logger{
			Name:   name,
			Level:  level,
			Logger: logger,
		}
	}

	loggers[l.Name] = l
}

func SetLevel(name string, level Level) error {
	logger, ok := loggers[name]
	if !ok {
		Default.Error("cannot find logger " + name)
		return ErrLoggerNotFounded
	}

	logger.Level = level
	return nil
}
<|endoftext|>


<commit_before>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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 main

import (
	"bytes"
	"encoding/json"
	"fmt"

	"github.com/hyperledger/fabric/core/chaincode/shim"
	pb "github.com/hyperledger/fabric/protos/peer"
)

// ============================================================================================================================
// Read - read a generic variable from ledger
//
// Shows Off GetState() - reading a key/value from the ledger
//
// Inputs - Array of strings
//  0
//  key
//  "abc"
//
// Returns - string
// ============================================================================================================================
func read(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	var key, jsonResp string
	var err error
	fmt.Println("starting read")

	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting key of the var to query")
	}

	// input sanitation
	err = sanitize_arguments(args)
	if err != nil {
		return shim.Error(err.Error())
	}

	key = args[0]
	valAsbytes, err := stub.GetState(key)           //get the var from ledger
	if err != nil {
		jsonResp = "{\"Error\":\"Failed to get state for " + key + "\"}"
		return shim.Error(jsonResp)
	}

	fmt.Println("- end read")
	return shim.Success(valAsbytes)                  //send it onward
}

// ============================================================================================================================
// Get everything we need (owners + marbles + companies)
//
// Inputs - none
//
// Returns:
// {
//	"owners": [{
//			"id": "o99999999",
//			"company": "United Marbles"
//			"username": "alice"
//	}],
//	"marbles": [{
//		"id": "m1490898165086",
//		"color": "white",
//		"docType" :"marble",
//		"owner": {
//			"company": "United Marbles"
//			"username": "alice"
//		},
//		"size" : 35
//	}]
// }
// ============================================================================================================================
func read_everything(stub shim.ChaincodeStubInterface) pb.Response {
	type Everything struct {
		Owners   []Owner   `json:"owners"`
		Marbles  []Marble  `json:"marbles"`
	}
	var everything Everything

	// ---- Get All Marbles ---- //
	resultsIterator, err := stub.GetStateByRange("m0", "m9999999999999999999")
	if err != nil {
		return shim.Error(err.Error())
	}
	defer resultsIterator.Close()

	for resultsIterator.HasNext() {
		queryKeyAsStr, queryValAsBytes, err := resultsIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}

		fmt.Println("on marble id - ", queryKeyAsStr)
		var marble Marble
		json.Unmarshal(queryValAsBytes, &marble)                  //un stringify it aka JSON.parse()
		everything.Marbles = append(everything.Marbles, marble)   //add this marble to the list
	}
	fmt.Println("marble array - ", everything.Marbles)

	// ---- Get All Owners ---- //
	ownersIterator, err := stub.GetStateByRange("o0", "o9999999999999999999")
	if err != nil {
		return shim.Error(err.Error())
	}
	defer ownersIterator.Close()

	for ownersIterator.HasNext() {
		queryKeyAsStr, queryValAsBytes, err := ownersIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}

		fmt.Println("on owner id - ", queryKeyAsStr)
		var owner Owner
		json.Unmarshal(queryValAsBytes, &owner)                  //un stringify it aka JSON.parse()
		everything.Owners = append(everything.Owners, owner)     //add this marble to the list
	}
	fmt.Println("owner array - ", everything.Owners)

	//change to array of bytes
	everythingAsBytes, _ := json.Marshal(everything)             //convert to array of bytes
	return shim.Success(everythingAsBytes)
}

// ============================================================================================================================
// Get history of asset
//
// Shows Off GetHistoryForKey() - reading complete history of a key/value
//
// Inputs - Array of strings
//  0
//  id
//  "m01490985296352SjAyM"
// ============================================================================================================================
func getHistory(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	type AuditHistory struct {
		TxId    string   `json:"txId"`
		Value   Marble   `json:"value"`
	}
	var history []AuditHistory;
	var marble Marble

	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}

	marbleId := args[0]
	fmt.Printf("- start getHistoryForMarble: %s\n", marbleId)

	// Get History
	resultsIterator, err := stub.GetHistoryForKey(marbleId)
	if err != nil {
		return shim.Error(err.Error())
	}
	defer resultsIterator.Close()

	for resultsIterator.HasNext() {
		txID, historicValue, err := resultsIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}

		var tx AuditHistory
		tx.TxId = txID                             //copy transaction id over
		json.Unmarshal(historicValue, &marble)     //un stringify it aka JSON.parse()
		if historicValue == nil {                  //marble has been deleted
			var emptyMarble Marble
			emptyMarble.Color="red"
			emptyMarble.Size=16
			tx.Value = emptyMarble                 //copy nil marble
		} else {
			json.Unmarshal(historicValue, &marble) //un stringify it aka JSON.parse()
			marble.Color="red"
			marble.Size=16
			tx.Value = marble                      //copy marble over
		}
		history = append(history, tx)              //add this tx to the list
	}
	fmt.Printf("- getHistoryForMarble returning:\n%s", history)

	//change to array of bytes
	historyAsBytes, _ := json.Marshal(history)     //convert to array of bytes
	return shim.Success(historyAsBytes)
}

// ============================================================================================================================
// Get history of asset - performs a range query based on the start and end keys provided.
//
// Shows Off GetStateByRange() - reading a multiple key/values from the ledger
//
// Inputs - Array of strings
//       0     ,    1
//   startKey  ,  endKey
//  "marbles1" , "marbles5"
// ============================================================================================================================
func getMarblesByRange(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 2 {
		return shim.Error("Incorrect number of arguments. Expecting 2")
	}

	startKey := args[0]
	endKey := args[1]

	resultsIterator, err := stub.GetStateByRange(startKey, endKey)
	if err != nil {
		return shim.Error(err.Error())
	}
	defer resultsIterator.Close()

	// buffer is a JSON array containing QueryResults
	var buffer bytes.Buffer
	buffer.WriteString("[")

	bArrayMemberAlreadyWritten := false
	for resultsIterator.HasNext() {
		queryResultKey, queryResultValue, err := resultsIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}
		// Add a comma before array members, suppress it for the first array member
		if bArrayMemberAlreadyWritten == true {
			buffer.WriteString(",")
		}
		buffer.WriteString("{\"Key\":")
		buffer.WriteString("\"")
		buffer.WriteString(queryResultKey)
		buffer.WriteString("\"")

		buffer.WriteString(", \"Record\":")
		// Record is a JSON object, so we write as-is
		buffer.WriteString(string(queryResultValue))
		buffer.WriteString("}")
		bArrayMemberAlreadyWritten = true
	}
	buffer.WriteString("]")

	fmt.Printf("- getMarblesByRange queryResult:\n%s\n", buffer.String())

	return shim.Success(buffer.Bytes())
}
<commit_msg>First<commit_after>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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 main

import (
	"bytes"
	"encoding/json"
	"fmt"

	"github.com/hyperledger/fabric/core/chaincode/shim"
	pb "github.com/hyperledger/fabric/protos/peer"
)

// ============================================================================================================================
// Read - read a generic variable from ledger
//
// Shows Off GetState() - reading a key/value from the ledger
//
// Inputs - Array of strings
//  0
//  key
//  "abc"
//
// Returns - string
// ============================================================================================================================
func read(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	var key, jsonResp string
	var err error
	fmt.Println("starting read")

	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting key of the var to query")
	}

	// input sanitation
	err = sanitize_arguments(args)
	if err != nil {
		return shim.Error(err.Error())
	}

	key = args[0]
	valAsbytes, err := stub.GetState(key)           //get the var from ledger
	if err != nil {
		jsonResp = "{\"Error\":\"Failed to get state for " + key + "\"}"
		return shim.Error(jsonResp)
	}

	fmt.Println("- end read")
	return shim.Success(valAsbytes)                  //send it onward
}

// ============================================================================================================================
// Get everything we need (owners + marbles + companies)
//
// Inputs - none
//
// Returns:
// {
//	"owners": [{
//			"id": "o99999999",
//			"company": "United Marbles"
//			"username": "alice"
//	}],
//	"marbles": [{
//		"id": "m1490898165086",
//		"color": "white",
//		"docType" :"marble",
//		"owner": {
//			"company": "United Marbles"
//			"username": "alice"
//		},
//		"size" : 35
//	}]
// }
// ============================================================================================================================
func read_everything(stub shim.ChaincodeStubInterface) pb.Response {
	type Everything struct {
		Owners   []Owner   `json:"owners"`
		Marbles  []Marble  `json:"marbles"`
	}
	var everything Everything

	// ---- Get All Marbles ---- //
	resultsIterator, err := stub.GetStateByRange("m0", "m9999999999999999999")
	if err != nil {
		return shim.Error(err.Error())
	}
	defer resultsIterator.Close()

	for resultsIterator.HasNext() {
		queryKeyAsStr, queryValAsBytes, err := resultsIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}

		fmt.Println("on marble id - ", queryKeyAsStr)
		var marble Marble
		json.Unmarshal(queryValAsBytes, &marble)                  //un stringify it aka JSON.parse()
		everything.Marbles = append(everything.Marbles, marble)   //add this marble to the list
	}
	fmt.Println("marble array - ", everything.Marbles)

	// ---- Get All Owners ---- //
	ownersIterator, err := stub.GetStateByRange("o0", "o9999999999999999999")
	if err != nil {
		return shim.Error(err.Error())
	}
	defer ownersIterator.Close()

	for ownersIterator.HasNext() {
		queryKeyAsStr, queryValAsBytes, err := ownersIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}

		fmt.Println("on owner id - ", queryKeyAsStr)
		var owner Owner
		json.Unmarshal(queryValAsBytes, &owner)                  //un stringify it aka JSON.parse()
		everything.Owners = append(everything.Owners, owner)     //add this marble to the list
	}
	fmt.Println("owner array - ", everything.Owners)

	//change to array of bytes
	everythingAsBytes, _ := json.Marshal(everything)             //convert to array of bytes
	return shim.Success(everythingAsBytes)
}

// ============================================================================================================================
// Get history of asset
//
// Shows Off GetHistoryForKey() - reading complete history of a key/value
//
// Inputs - Array of strings
//  0
//  id
//  "m01490985296352SjAyM"
// ============================================================================================================================
func getHistory(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	type AuditHistory struct {
		TxId    string   `json:"txId"`
		Value   Marble   `json:"value"`
	}
	var history []AuditHistory;
	var marble Marble

	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}

	marbleId := args[0]
	fmt.Printf("- start getHistoryForMarble: %s\n", marbleId)

	// Get History
	resultsIterator, err := stub.GetHistoryForKey(marbleId)
	if err != nil {
		return shim.Error(err.Error())
	}
	defer resultsIterator.Close()

	for resultsIterator.HasNext() {
		txID, historicValue, err := resultsIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}

		var tx AuditHistory
		tx.TxId = txID                             //copy transaction id over
		json.Unmarshal(historicValue, &marble)     //un stringify it aka JSON.parse()
		if historicValue == nil {                  //marble has been deleted
			var emptyMarble Marble
			emptyMarble.Color="black"
			emptyMarble.Size=16
			tx.Value = emptyMarble                 //copy nil marble
		} else {
			json.Unmarshal(historicValue, &marble) //un stringify it aka JSON.parse()
			marble.Color="black"
			marble.Size=16
			tx.Value = marble                      //copy marble over
		}
		history = append(history, tx)              //add this tx to the list
	}
	fmt.Printf("- getHistoryForMarble returning:\n%s", history)

	//change to array of bytes
	historyAsBytes, _ := json.Marshal(history)     //convert to array of bytes
	return shim.Success(historyAsBytes)
}

// ============================================================================================================================
// Get history of asset - performs a range query based on the start and end keys provided.
//
// Shows Off GetStateByRange() - reading a multiple key/values from the ledger
//
// Inputs - Array of strings
//       0     ,    1
//   startKey  ,  endKey
//  "marbles1" , "marbles5"
// ============================================================================================================================
func getMarblesByRange(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 2 {
		return shim.Error("Incorrect number of arguments. Expecting 2")
	}

	startKey := args[0]
	endKey := args[1]

	resultsIterator, err := stub.GetStateByRange(startKey, endKey)
	if err != nil {
		return shim.Error(err.Error())
	}
	defer resultsIterator.Close()

	// buffer is a JSON array containing QueryResults
	var buffer bytes.Buffer
	buffer.WriteString("[")

	bArrayMemberAlreadyWritten := false
	for resultsIterator.HasNext() {
		queryResultKey, queryResultValue, err := resultsIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}
		// Add a comma before array members, suppress it for the first array member
		if bArrayMemberAlreadyWritten == true {
			buffer.WriteString(",")
		}
		buffer.WriteString("{\"Key\":")
		buffer.WriteString("\"")
		buffer.WriteString(queryResultKey)
		buffer.WriteString("\"")

		buffer.WriteString(", \"Record\":")
		// Record is a JSON object, so we write as-is
		buffer.WriteString(string(queryResultValue))
		buffer.WriteString("}")
		bArrayMemberAlreadyWritten = true
	}
	buffer.WriteString("]")

	fmt.Printf("- getMarblesByRange queryResult:\n%s\n", buffer.String())

	return shim.Success(buffer.Bytes())
}
<|endoftext|>


<commit_before>package ogdat

import (
	"encoding/csv"
	"io"
	"log"
	"os"
	"strconv"
)

/*	Version10 = "OGD Austria Metadata 1.0" // Version 1.0: 24.10.2011
	Version11 = "OGD Austria Metadata 1.1" // Version 1.1: 12.03.2012
	Version20 = "OGD Austria Metadata 2.0" // Version 2.0: 10.10.2012
	Version21 = "OGD Austria Metadata 2.1" // Version 2.1: 15.10.2012
*/
var specification = make(map[string]*OGDSet)

type Occurrence int

const (
	OccUndef Occurrence = iota
	OccRequired
	OccOptional
)

type Beschreibung struct {
	ID            int
	Bezeichner    string
	OGD_Kurzname  string
	CKAN_Feld     string
	Anzahl        string
	Definition_DE string
	Erlauterung   string
	Beispiel      string
	ONA2270       string
	ISO19115      string
	RDFProperty   string
	Definition_EN string
	occurrence    Occurrence
	version       string
}

func NewBeschreibung(ID int, occur Occurrence, ver string) *Beschreibung {
	return &Beschreibung{ID: ID, occurrence: occur, version: ver}
}

func (desc *Beschreibung) Version() string {
	return desc.version
}

func (desc *Beschreibung) Occurrence() Occurrence {
	return desc.occurrence
}

func (desc *Beschreibung) IsRequired() bool {
	return desc.occurrence == OccRequired
}

type OGDSet struct {
	Label        []string
	Beschreibung []*Beschreibung
}

func (set *OGDSet) GetBeschreibungForID(id int) (*Beschreibung, string) {
	if set != nil {
		for idx, elm := range set.Beschreibung {
			if elm.ID == id {
				return set.Beschreibung[idx], set.Label[idx]
			}
		}
	}
	return nil, ""
}

func Register(version, specfile string) *OGDSet {
	specmap, _ := Loadogdatspec(version, specfile)
	specification[version] = specmap
	return specmap
}

func GetOGDSetForVersion(version string) *OGDSet {
	return specification[version]
}
}

func Loadogdatspec(version, filename string) (*OGDSet, error) {
	reader, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer reader.Close()

	csvreader := csv.NewReader(reader)
	csvreader.Comma = '|'
	csvreader.LazyQuotes = true

	// Read the first line and use it as the labels for the items to load
	record, err := csvreader.Read()
	if err != nil {
		return nil, err
	}

	set := &OGDSet{}
	set.Label = record

	spec := make([]*Beschreibung, 0)
	for record, err = csvreader.Read(); err != io.EOF; record, err = csvreader.Read() {
		id, _ := strconv.Atoi(record[0])
		var occ Occurrence
		switch record[12][0] {
		case 'R':
			occ = OccRequired
		case 'O':
			occ = OccOptional
		}
		descrecord := NewBeschreibung(id, occ, version)

		descrecord.Bezeichner = record[1]
		descrecord.OGD_Kurzname = record[2]
		descrecord.CKAN_Feld = record[3]
		descrecord.Anzahl = record[4]
		descrecord.Definition_DE = record[5]
		descrecord.Erlauterung = record[6]
		descrecord.Beispiel = record[7]
		descrecord.ONA2270 = record[8]
		descrecord.ISO19115 = record[9]
		descrecord.RDFProperty = record[10]
		descrecord.Definition_EN = record[11]

		spec = append(spec, descrecord)
	}
	set.Beschreibung = spec
	log.Printf("Info: Read %d %s specifiaction records", len(spec), version)

	return set, nil
}
<commit_msg>add helper function which extracts an OGD-ID from a string<commit_after>package ogdat

import (
	"encoding/csv"
	"io"
	"log"
	"os"
	"strconv"
	"strings"
)

/*	Version10 = "OGD Austria Metadata 1.0" // Version 1.0: 24.10.2011
	Version11 = "OGD Austria Metadata 1.1" // Version 1.1: 12.03.2012
	Version20 = "OGD Austria Metadata 2.0" // Version 2.0: 10.10.2012
	Version21 = "OGD Austria Metadata 2.1" // Version 2.1: 15.10.2012
*/
var specification = make(map[string]*OGDSet)

type Occurrence int

const (
	OccUndef Occurrence = iota
	OccRequired
	OccOptional
)

type Beschreibung struct {
	ID            int
	Bezeichner    string
	OGD_Kurzname  string
	CKAN_Feld     string
	Anzahl        string
	Definition_DE string
	Erlauterung   string
	Beispiel      string
	ONA2270       string
	ISO19115      string
	RDFProperty   string
	Definition_EN string
	occurrence    Occurrence
	version       string
}

func NewBeschreibung(ID int, occur Occurrence, ver string) *Beschreibung {
	return &Beschreibung{ID: ID, occurrence: occur, version: ver}
}

func (desc *Beschreibung) Version() string {
	return desc.version
}

func (desc *Beschreibung) Occurrence() Occurrence {
	return desc.occurrence
}

func (desc *Beschreibung) IsRequired() bool {
	return desc.occurrence == OccRequired
}

type OGDSet struct {
	Label        []string
	Beschreibung []*Beschreibung
}

func (set *OGDSet) GetBeschreibungForID(id int) (*Beschreibung, string) {
	if set != nil {
		for idx, elm := range set.Beschreibung {
			if elm.ID == id {
				return set.Beschreibung[idx], set.Label[idx]
			}
		}
	}
	return nil, ""
}

func Register(version, specfile string) *OGDSet {
	specmap, _ := Loadogdatspec(version, specfile)
	specification[version] = specmap
	return specmap
}

func GetOGDSetForVersion(version string) *OGDSet {
	return specification[version]
}

func GetOGDIDFromString(ids string) int {
	if idx := strings.Index(ids, "ID"); idx > -1 {
		ids = ids[idx+1:]
		if idx = strings.IndexRune(ids, ' '); idx > -1 {
			ids = ids[:idx]
		}
		if i, err := strconv.Atoi(ids); err == nil {
			return i
		}
	}
	return -1
}

func Loadogdatspec(version, filename string) (*OGDSet, error) {
	reader, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer reader.Close()

	csvreader := csv.NewReader(reader)
	csvreader.Comma = '|'
	csvreader.LazyQuotes = true

	// Read the first line and use it as the labels for the items to load
	record, err := csvreader.Read()
	if err != nil {
		return nil, err
	}

	set := &OGDSet{}
	set.Label = record

	spec := make([]*Beschreibung, 0)
	for record, err = csvreader.Read(); err != io.EOF; record, err = csvreader.Read() {
		id, _ := strconv.Atoi(record[0])
		var occ Occurrence
		switch record[12][0] {
		case 'R':
			occ = OccRequired
		case 'O':
			occ = OccOptional
		}
		descrecord := NewBeschreibung(id, occ, version)

		descrecord.Bezeichner = record[1]
		descrecord.OGD_Kurzname = record[2]
		descrecord.CKAN_Feld = record[3]
		descrecord.Anzahl = record[4]
		descrecord.Definition_DE = record[5]
		descrecord.Erlauterung = record[6]
		descrecord.Beispiel = record[7]
		descrecord.ONA2270 = record[8]
		descrecord.ISO19115 = record[9]
		descrecord.RDFProperty = record[10]
		descrecord.Definition_EN = record[11]

		spec = append(spec, descrecord)
	}
	set.Beschreibung = spec
	log.Printf("Info: Read %d %s specifiaction records", len(spec), version)

	return set, nil
}
<|endoftext|>


<commit_before>package dns

import (
	"io"
	"hash"
	"strings"
	"crypto/sha1"
)

type saltWireFmt struct {
	Salt string "size-hex"
}

// HashName hashes a string or label according to RFC5155. It returns
// the hashed string.
func HashName(label string, ha int, iterations int, salt string) string {
	saltwire := new(saltWireFmt)
	saltwire.Salt = salt
	wire := make([]byte, DefaultMsgSize)
	n, ok := packStruct(saltwire, wire, 0)
	if !ok {
		return ""
	}
	wire = wire[:n]
	name := make([]byte, 255)
	off, ok1 := packDomainName(strings.ToLower(label), name, 0)
	if !ok1 {
		return ""
	}
	name = name[:off]
	var s hash.Hash
	switch ha {
	case SHA1:
		s = sha1.New()
	default:
		return ""
	}

	// k = 0
	name = append(name, wire...)
	io.WriteString(s, string(name))
	nsec3 := s.Sum()
	// k > 0
	for k := 0; k < iterations; k++ {
		s.Reset()
		nsec3 = append(nsec3, wire...)
		io.WriteString(s, string(nsec3))
		nsec3 = s.Sum()
	}
	return unpackBase32(nsec3)
}

// Hash the ownername and the next owner name in an NSEC3 record according
// to RFC 5155.
// Use the parameters from the NSEC3 itself.
func (nsec3 *RR_NSEC3) HashNames() {
	nsec3.Header().Name = hashName(nsec3.Header().Name, int(nsec3.Hash), int(nsec3.Iterations), nsec3.Salt)
	nsec3.NextDomain = hashName(nsec3.NextDomain, int(nsec3.Hash), int(nsec3.Iterations), nsec3.Salt)
}
<commit_msg>Make nsec3.go compile<commit_after>package dns

import (
	"io"
	"hash"
	"strings"
	"crypto/sha1"
)

type saltWireFmt struct {
	Salt string "size-hex"
}

// HashName hashes a string or label according to RFC5155. It returns
// the hashed string.
func HashName(label string, ha int, iterations int, salt string) string {
	saltwire := new(saltWireFmt)
	saltwire.Salt = salt
	wire := make([]byte, DefaultMsgSize)
	n, ok := packStruct(saltwire, wire, 0)
	if !ok {
		return ""
	}
	wire = wire[:n]
	name := make([]byte, 255)
	off, ok1 := packDomainName(strings.ToLower(label), name, 0)
	if !ok1 {
		return ""
	}
	name = name[:off]
	var s hash.Hash
	switch ha {
	case SHA1:
		s = sha1.New()
	default:
		return ""
	}

	// k = 0
	name = append(name, wire...)
	io.WriteString(s, string(name))
	nsec3 := s.Sum()
	// k > 0
	for k := 0; k < iterations; k++ {
		s.Reset()
		nsec3 = append(nsec3, wire...)
		io.WriteString(s, string(nsec3))
		nsec3 = s.Sum()
	}
	return unpackBase32(nsec3)
}

// Hash the ownername and the next owner name in an NSEC3 record according
// to RFC 5155.
// Use the parameters from the NSEC3 itself.
func (nsec3 *RR_NSEC3) HashNames() {
	nsec3.Header().Name = HashName(nsec3.Header().Name, int(nsec3.Hash), int(nsec3.Iterations), nsec3.Salt)
	nsec3.NextDomain = HashName(nsec3.NextDomain, int(nsec3.Hash), int(nsec3.Iterations), nsec3.Salt)
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 vppcalls

import (
	"fmt"

	govppapi "git.fd.io/govpp.git/api"
	"github.com/ligato/cn-infra/logging"
	"github.com/ligato/cn-infra/logging/logroot"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/ifplugin/bin_api/interfaces"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/ifplugin/bin_api/ip"
)

/*
// VppUnsetAllInterfacesFromVRF removes all interfaces from VRF (set them to default VRF 0)
func VppUnsetAllInterfacesFromVRF(vrfIndex uint32, log logging.Logger,
	vppChan *govppapi.Channel) error {
	log.Debugf("Unsetting all interfaces from VRF %v", vrfIndex)

	return nil
}*/

// GetInterfaceVRF assigns VRF table to interface
func GetInterfaceVRF(ifaceIndex uint32, log logging.Logger,
	vppChan *govppapi.Channel) (uint32, error) {
	log.Debugf("Getting VRF for interface %v", ifaceIndex)

	req := &interfaces.SwInterfaceGetTable{
		SwIfIndex: ifaceIndex,
	}
	/*if table.IsIPv6 {
		req.IsIpv6 = 1
	} else {
		req.IsIpv6 = 0
	}*/

	// Send message
	reply := new(interfaces.SwInterfaceGetTableReply)
	if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil {
		return 0, err
	}
	if reply.Retval != 0 {
		return 0, fmt.Errorf("SwInterfaceGetTableReply returned %d", reply.Retval)
	}

	return reply.VrfID, nil
}

// SetInterfaceVRF retrieves VRF table from interface
func SetInterfaceVRF(ifaceIndex, vrfIndex uint32, log logging.Logger,
	vppChan *govppapi.Channel) error {
	log.Debugf("Setting interface %v to VRF %v", ifaceIndex, vrfIndex)

	req := &interfaces.SwInterfaceSetTable{
		VrfID:     vrfIndex,
		SwIfIndex: ifaceIndex,
	}
	/*if table.IsIPv6 {
		req.IsIpv6 = 1
	} else {
		req.IsIpv6 = 0
	}*/

	// Send message
	reply := new(interfaces.SwInterfaceSetTableReply)
	if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil {
		return err
	}
	if reply.Retval != 0 {
		return fmt.Errorf("SwInterfaceSetTableReply returned %d", reply.Retval)
	}

	return nil
}

func dumpVrfTables(vppChan *govppapi.Channel) (map[uint32][]*ip.IPFibDetails, error) {
	fibs := map[uint32][]*ip.IPFibDetails{}

	reqCtx := vppChan.SendMultiRequest(&ip.IPFibDump{})
	for {
		fibDetails := &ip.IPFibDetails{}
		stop, err := reqCtx.ReceiveReply(fibDetails)
		if stop {
			break // break out of the loop
		}
		if err != nil {
			return nil, err
		}

		tableID := fibDetails.TableID
		fibs[tableID] = append(fibs[tableID], fibDetails)
	}

	return fibs, nil
}

func vppAddDelIPTable(tableID uint32, vppChan *govppapi.Channel, delete bool) error {
	req := &ip.IPTableAddDel{
		TableID: tableID,
	}
	if delete {
		req.IsAdd = 0
	} else {
		req.IsAdd = 1
	}

	// Send message
	reply := new(ip.IPTableAddDelReply)
	if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil {
		return err
	}
	if reply.Retval != 0 {
		return fmt.Errorf("IPTableAddDel returned %d", reply.Retval)
	}

	return nil
}

func createVrfIfNeeded(vrf uint32, vppChan *govppapi.Channel) error {
	tables, err := dumpVrfTables(vppChan)
	if err != nil {
		return err
	}
	if _, ok := tables[vrf]; !ok {
		logroot.StandardLogger().Warnf("VXLAN: VRF table %v does not exists, creating it", vrf)
		return vppAddDelIPTable(vrf, vppChan, false)
	}
	return nil
}
<commit_msg>Skip creating VRF table for default VRF 0<commit_after>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 vppcalls

import (
	"fmt"

	govppapi "git.fd.io/govpp.git/api"
	"github.com/ligato/cn-infra/logging"
	"github.com/ligato/cn-infra/logging/logroot"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/ifplugin/bin_api/interfaces"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/ifplugin/bin_api/ip"
)

/*
// VppUnsetAllInterfacesFromVRF removes all interfaces from VRF (set them to default VRF 0)
func VppUnsetAllInterfacesFromVRF(vrfIndex uint32, log logging.Logger,
	vppChan *govppapi.Channel) error {
	log.Debugf("Unsetting all interfaces from VRF %v", vrfIndex)

	return nil
}*/

// GetInterfaceVRF assigns VRF table to interface
func GetInterfaceVRF(ifaceIndex uint32, log logging.Logger,
	vppChan *govppapi.Channel) (uint32, error) {
	log.Debugf("Getting VRF for interface %v", ifaceIndex)

	req := &interfaces.SwInterfaceGetTable{
		SwIfIndex: ifaceIndex,
	}
	/*if table.IsIPv6 {
		req.IsIpv6 = 1
	} else {
		req.IsIpv6 = 0
	}*/

	// Send message
	reply := new(interfaces.SwInterfaceGetTableReply)
	if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil {
		return 0, err
	}
	if reply.Retval != 0 {
		return 0, fmt.Errorf("SwInterfaceGetTableReply returned %d", reply.Retval)
	}

	return reply.VrfID, nil
}

// SetInterfaceVRF retrieves VRF table from interface
func SetInterfaceVRF(ifaceIndex, vrfIndex uint32, log logging.Logger,
	vppChan *govppapi.Channel) error {
	log.Debugf("Setting interface %v to VRF %v", ifaceIndex, vrfIndex)

	req := &interfaces.SwInterfaceSetTable{
		VrfID:     vrfIndex,
		SwIfIndex: ifaceIndex,
	}
	/*if table.IsIPv6 {
		req.IsIpv6 = 1
	} else {
		req.IsIpv6 = 0
	}*/

	// Send message
	reply := new(interfaces.SwInterfaceSetTableReply)
	if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil {
		return err
	}
	if reply.Retval != 0 {
		return fmt.Errorf("SwInterfaceSetTableReply returned %d", reply.Retval)
	}

	return nil
}

func dumpVrfTables(vppChan *govppapi.Channel) (map[uint32][]*ip.IPFibDetails, error) {
	fibs := map[uint32][]*ip.IPFibDetails{}

	reqCtx := vppChan.SendMultiRequest(&ip.IPFibDump{})
	for {
		fibDetails := &ip.IPFibDetails{}
		stop, err := reqCtx.ReceiveReply(fibDetails)
		if stop {
			break // break out of the loop
		}
		if err != nil {
			return nil, err
		}

		tableID := fibDetails.TableID
		fibs[tableID] = append(fibs[tableID], fibDetails)
	}

	return fibs, nil
}

func vppAddDelIPTable(tableID uint32, vppChan *govppapi.Channel, delete bool) error {
	req := &ip.IPTableAddDel{
		TableID: tableID,
	}
	if delete {
		req.IsAdd = 0
	} else {
		req.IsAdd = 1
	}

	// Send message
	reply := new(ip.IPTableAddDelReply)
	if err := vppChan.SendRequest(req).ReceiveReply(reply); err != nil {
		return err
	}
	if reply.Retval != 0 {
		return fmt.Errorf("IPTableAddDel returned %d", reply.Retval)
	}

	return nil
}

func createVrfIfNeeded(vrf uint32, vppChan *govppapi.Channel) error {
	if vrf == 0 {
		return nil
	}
	tables, err := dumpVrfTables(vppChan)
	if err != nil {
		return err
	}
	if _, ok := tables[vrf]; !ok {
		logroot.StandardLogger().Warnf("VXLAN: VRF table %v does not exists, creating it", vrf)
		return vppAddDelIPTable(vrf, vppChan, false)
	}
	return nil
}
<|endoftext|>


<commit_before>//go:build !windows
// +build !windows

package port_name

func servicesPath() string {
	return "/etc/services"
}
<commit_msg>fix: search services file in /etc/services and fall back to /usr/etc/services (#11179)<commit_after>//go:build !windows
// +build !windows

package port_name

import (
	"os"
)

// servicesPath tries to find the `services` file at the common
// place(s) on most systems and returns its path. If it can't
// find anything, it returns the common default `/etc/services`
func servicesPath() string {
	var files = []string{
		"/etc/services",
		"/usr/etc/services", // fallback on OpenSuSE
	}

	for i := range files {
		if _, err := os.Stat(files[i]); err == nil {
			return files[i]
		}
	}
	return files[0]
}
<|endoftext|>


<commit_before>package email

import (
	"github.com/nathan-osman/go-cannon/queue"
	"github.com/nathan-osman/go-cannon/util"

	"bytes"
	"fmt"
	"io"
	"mime/multipart"
	"net/textproto"
	"strings"
	"time"
)

// Abstract representation of an email.
type Email struct {
	From        string       `json:"from"`
	To          []string     `json:"to"`
	Cc          []string     `json:"cc"`
	Bcc         []string     `json:"bcc"`
	Subject     string       `json:"subject"`
	Text        string       `json:"text"`
	Html        string       `json:"html"`
	Attachments []Attachment `json:"attachments"`
}

// Create a multipart body with the specified text and HTML and write it to the
// specified writer. A temporary buffer is used to work around a cyclical
// dependency with respect to the writer, header, and part.
func writeMultipartBody(w *multipart.Writer, text, html string) error {
	var (
		buff      = &bytes.Buffer{}
		altWriter = multipart.NewWriter(buff)
		headers   = textproto.MIMEHeader{
			"Content-Type": []string{
				fmt.Sprintf("multipart/alternative; boundary=\"%s\"", altWriter.Boundary()),
			},
		}
		textPart = &Attachment{
			ContentType: "text/plain; charset=\"utf-8\"",
			Content:     text,
		}
		htmlPart = &Attachment{
			ContentType: "text/html; charset=\"utf-8\"",
			Content:     html,
		}
	)
	part, err := w.CreatePart(headers)
	if err != nil {
		return err
	}
	if err := textPart.Write(altWriter); err != nil {
		return err
	}
	if err := htmlPart.Write(altWriter); err != nil {
		return err
	}
	if err := altWriter.Close(); err != nil {
		return err
	}
	_, err = io.Copy(part, buff)
	return err
}

// Convert the email into an array of messages grouped by host suitable for
// delivery to the mail queue.
func (e *Email) Messages(s *queue.Storage) ([]*queue.Message, error) {
	if w, body, err := s.NewBody(); err == nil {
		var (
			m       = multipart.NewWriter(w)
			headers = EmailHeaders{
				"Message-Id":   fmt.Sprintf("<%s@go-cannon>", body),
				"From":         e.From,
				"To":           strings.Join(e.To, ", "),
				"Subject":      e.Subject,
				"Date":         time.Now().Format("Mon, 02 Jan 2006 15:04:05 -0700"),
				"MIME-Version": "1.0",
				"Content-Type": fmt.Sprintf("multipart/mixed; boundary=%s", m.Boundary()),
			}
			addresses = append(append(e.To, e.Cc...), e.Bcc...)
		)
		if len(e.Cc) > 0 {
			headers["Cc"] = strings.Join(e.Cc, ",")
		}
		if err := headers.Write(w); err != nil {
			return nil, err
		}
		if err := writeMultipartBody(m, e.Text, e.Html); err != nil {
			return nil, err
		}
		for _, a := range e.Attachments {
			if err := a.Write(m); err != nil {
				return nil, err
			}
		}
		if err := m.Close(); err != nil {
			return nil, err
		}
		if err := w.Close(); err != nil {
			return nil, err
		}
		if addrMap, err := util.GroupAddressesByHost(addresses); err == nil {
			messages := make([]*queue.Message, 0, 1)
			for h, to := range addrMap {
				msg := &queue.Message{
					Host: h,
					From: e.From,
					To:   to,
				}
				if err := s.SaveMessage(msg, body); err != nil {
					return nil, err
				}
				messages = append(messages, msg)
			}
			return messages, nil
		} else {
			return nil, err
		}
	} else {
		return nil, err
	}
}
<commit_msg>Reorganized Email processing methods.<commit_after>package email

import (
	"github.com/nathan-osman/go-cannon/queue"
	"github.com/nathan-osman/go-cannon/util"

	"bytes"
	"fmt"
	"io"
	"mime/multipart"
	"net/mail"
	"net/textproto"
	"strings"
	"time"
)

// Abstract representation of an email.
type Email struct {
	From        string       `json:"from"`
	To          []string     `json:"to"`
	Cc          []string     `json:"cc"`
	Bcc         []string     `json:"bcc"`
	Subject     string       `json:"subject"`
	Text        string       `json:"text"`
	Html        string       `json:"html"`
	Attachments []Attachment `json:"attachments"`
}

// Write the headers for the email to the specified writer.
func (e *Email) writeHeaders(w io.Writer, id, boundary string) error {
	headers := EmailHeaders{
		"Message-Id":   fmt.Sprintf("<%s@go-cannon>", id),
		"From":         e.From,
		"To":           strings.Join(e.To, ", "),
		"Subject":      e.Subject,
		"Date":         time.Now().Format("Mon, 02 Jan 2006 15:04:05 -0700"),
		"MIME-Version": "1.0",
		"Content-Type": fmt.Sprintf("multipart/mixed; boundary=%s", boundary),
	}
	if len(e.Cc) > 0 {
		headers["Cc"] = strings.Join(e.Cc, ", ")
	}
	return headers.Write(w)
}

// Write the body of the email to the specified writer.
func (e *Email) writeBody(w *multipart.Writer) error {
	var (
		buff      = &bytes.Buffer{}
		altWriter = multipart.NewWriter(buff)
		header    = textproto.MIMEHeader{
			"Content-Type": []string{
				fmt.Sprintf("multipart/alternative; boundary=%s", altWriter.Boundary()),
			},
		}
	)
	if p, err := w.CreatePart(header); err == nil {
		if err := (Attachment{
			ContentType: "text/plain; charset=utf-8",
			Content:     e.Text,
		}.Write(w)); err != nil {
			return err
		}
		if err := (Attachment{
			ContentType: "text/html; charset=utf-8",
			Content:     e.Html,
		}.Write(w)); err != nil {
			return err
		}
		if err := altWriter.Close(); err != nil {
			return err
		}
		if _, err := io.Copy(p, buff); err != nil {
			return err
		}
		return nil
	} else {
		return err
	}
}

// Create an array of messages with the specified body.
func (e *Email) newMessages(s *queue.Storage, from, body string) ([]*queue.Message, error) {
	addresses := append(append(e.To, e.Cc...), e.Bcc...)
	if m, err := util.GroupAddressesByHost(addresses); err == nil {
		messages := make([]*queue.Message, 0, 1)
		for h, to := range m {
			msg := &queue.Message{
				Host: h,
				From: from,
				To:   to,
			}
			if err := s.SaveMessage(msg, body); err != nil {
				return nil, err
			}
			messages = append(messages, msg)
		}
		return messages, nil
	} else {
		return nil, err
	}
}

// Convert the email into an array of messages grouped by host suitable for
// delivery to the mail queue.
func (e *Email) Messages(s *queue.Storage) ([]*queue.Message, error) {
	if from, err := mail.ParseAddress(e.From); err == nil {
		if w, body, err := s.NewBody(); err == nil {
			mpWriter := multipart.NewWriter(w)
			if err := e.writeHeaders(w, body, mpWriter.Boundary()); err != nil {
				return nil, err
			}
			if err := e.writeBody(mpWriter); err != nil {
				return nil, err
			}
			for _, a := range e.Attachments {
				if err := a.Write(mpWriter); err != nil {
					return nil, err
				}
			}
			if err := mpWriter.Close(); err != nil {
				return nil, err
			}
			if err := w.Close(); err != nil {
				return nil, err
			}
			return e.newMessages(s, from.Address, body)
		} else {
			return nil, err
		}
	} else {
		return nil, err
	}
}
<|endoftext|>


<commit_before>package models

import (
	"time"

	envmanModels "github.com/bitrise-io/envman/models"
)

// StepSourceModel ...
type StepSourceModel struct {
	Git    string `json:"git,omitempty" yaml:"git,omitempty"`
	Commit string `json:"commit,omitempty" yaml:"commit,omitempty"`
}

// DependencyModel ...
type DependencyModel struct {
	Manager string `json:"manager,omitempty" yaml:"manager,omitempty"`
	Name    string `json:"name,omitempty" yaml:"name,omitempty"`
}

// BrewDepModel ...
type BrewDepModel struct {
	Name string `json:"name,omitempty" yaml:"name,omitempty"`
	Tap  string `json:"tap,omitempty" yaml:"tap,omitempty"`
}

// BrewCaskDepModel ...
type BrewCaskDepModel struct {
	Name string `json:"name,omitempty" yaml:"name,omitempty"`
}

// AptGetDepModel ...
type AptGetDepModel struct {
	Name string `json:"name,omitempty" yaml:"name,omitempty"`
}

// DepsModel ...
type DepsModel struct {
	Brew     []BrewDepModel     `json:"brew,omitempty" yaml:"brew,omitempty"`
	BrewCask []BrewCaskDepModel `json:"brew_cask,omitempty" yaml:"brew_cask,omitempty"`
	AptGet   []AptGetDepModel   `json:"apt_get,omitempty" yaml:"apt_get,omitempty"`
}

// StepModel ...
type StepModel struct {
	Title       *string `json:"title,omitempty" yaml:"title,omitempty"`
	Summary     *string `json:"summary,omitempty" yaml:"summary,omitempty"`
	Description *string `json:"description,omitempty" yaml:"description,omitempty"`
	//
	Website       *string `json:"website,omitempty" yaml:"website,omitempty"`
	SourceCodeURL *string `json:"source_code_url,omitempty" yaml:"source_code_url,omitempty"`
	SupportURL    *string `json:"support_url,omitempty" yaml:"support_url,omitempty"`
	// auto-generated at share
	PublishedAt *time.Time        `json:"published_at,omitempty" yaml:"published_at,omitempty"`
	Source      StepSourceModel   `json:"source,omitempty" yaml:"source,omitempty"`
	AssetURLs   map[string]string `json:"asset_urls,omitempty" yaml:"asset_urls,omitempty"`
	//
	HostOsTags          []string          `json:"host_os_tags,omitempty" yaml:"host_os_tags,omitempty"`
	ProjectTypeTags     []string          `json:"project_type_tags,omitempty" yaml:"project_type_tags,omitempty"`
	TypeTags            []string          `json:"type_tags,omitempty" yaml:"type_tags,omitempty"`
	Dependencies        []DependencyModel `json:"dependencies,omitempty" yaml:"dependencies,omitempty"`
	Deps                DepsModel         `json:"deps,omitempty" yaml:"deps,omitempty"`
	IsRequiresAdminUser *bool             `json:"is_requires_admin_user,omitempty" yaml:"is_requires_admin_user,omitempty"`
	// IsAlwaysRun : if true then this step will always run,
	//  even if a previous step fails.
	IsAlwaysRun *bool `json:"is_always_run,omitempty" yaml:"is_always_run,omitempty"`
	// IsSkippable : if true and this step fails the build will still continue.
	//  If false then the build will be marked as failed and only those
	//  steps will run which are marked with IsAlwaysRun.
	IsSkippable *bool `json:"is_skippable,omitempty" yaml:"is_skippable,omitempty"`
	// RunIf : only run the step if the template example evaluates to true
	RunIf *string `json:"run_if,omitempty" yaml:"run_if,omitempty"`
	//
	Inputs  []envmanModels.EnvironmentItemModel `json:"inputs,omitempty" yaml:"inputs,omitempty"`
	Outputs []envmanModels.EnvironmentItemModel `json:"outputs,omitempty" yaml:"outputs,omitempty"`
}

// StepGroupModel ...
type StepGroupModel struct {
	LatestVersionNumber string               `json:"latest_version_number"`
	Versions            map[string]StepModel `json:"versions"`
}

// StepHash ...
type StepHash map[string]StepGroupModel

// DownloadLocationModel ...
type DownloadLocationModel struct {
	Type string `json:"type"`
	Src  string `json:"src"`
}

// StepCollectionModel ...
type StepCollectionModel struct {
	FormatVersion         string                  `json:"format_version" yaml:"format_version"`
	GeneratedAtTimeStamp  int64                   `json:"generated_at_timestamp" yaml:"generated_at_timestamp"`
	SteplibSource         string                  `json:"steplib_source" yaml:"steplib_source"`
	DownloadLocations     []DownloadLocationModel `json:"download_locations" yaml:"download_locations"`
	AssetsDownloadBaseURI string                  `json:"assets_download_base_uri" yaml:"assets_download_base_uri"`
	Steps                 StepHash                `json:"steps" yaml:"steps"`
}

// EnvInfoModel ...
type EnvInfoModel struct {
	Key          string   `json:"key,omitempty" yaml:"key,omitempty"`
	Title        string   `json:"title,omitempty" yaml:"title,omitempty"`
	Description  string   `json:"description,omitempty" yaml:"description,omitempty"`
	ValueOptions []string `json:"value_options,omitempty" yaml:"value_options,omitempty"`
	DefaultValue string   `json:"default_value,omitempty" yaml:"default_value,omitempty"`
	IsExpand     bool     `json:"is_expand" yaml:"is_expand"`
}

// StepInfoModel ...
type StepInfoModel struct {
	ID          string         `json:"step_id,omitempty" yaml:"step_id,omitempty"`
	Version     string         `json:"step_version,omitempty" yaml:"step_version,omitempty"`
	Latest      string         `json:"latest_version,omitempty" yaml:"latest_version,omitempty"`
	Description string         `json:"description,omitempty" yaml:"description,omitempty"`
	Source      string         `json:"source,omitempty" yaml:"source,omitempty"`
	StepLib     string         `json:"steplib,omitempty" yaml:"steplib,omitempty"`
	Inputs      []EnvInfoModel `json:"inputs,omitempty" yaml:"inputs,omitempty"`
	Outputs     []EnvInfoModel `json:"outputs,omitempty" yaml:"outputs,omitempty"`
}

// StepListModel ...
type StepListModel struct {
	StepLib string   `json:"steplib,omitempty" yaml:"steplib,omitempty"`
	Steps   []string `json:"steps,omitempty" yaml:"steps,omitempty"`
}
<commit_msg>new deps model<commit_after>package models

import (
	"time"

	envmanModels "github.com/bitrise-io/envman/models"
)

// StepSourceModel ...
type StepSourceModel struct {
	Git    string `json:"git,omitempty" yaml:"git,omitempty"`
	Commit string `json:"commit,omitempty" yaml:"commit,omitempty"`
}

// DependencyModel ...
type DependencyModel struct {
	Manager string `json:"manager,omitempty" yaml:"manager,omitempty"`
	Name    string `json:"name,omitempty" yaml:"name,omitempty"`
}

// BrewDepModel ...
type BrewDepModel struct {
	Name string `json:"name,omitempty" yaml:"name,omitempty"`
}

// AptGetDepModel ...
type AptGetDepModel struct {
	Name string `json:"name,omitempty" yaml:"name,omitempty"`
}

// DepsModel ...
type DepsModel struct {
	Brew   []BrewDepModel   `json:"brew,omitempty" yaml:"brew,omitempty"`
	AptGet []AptGetDepModel `json:"apt_get,omitempty" yaml:"apt_get,omitempty"`
}

// StepModel ...
type StepModel struct {
	Title       *string `json:"title,omitempty" yaml:"title,omitempty"`
	Summary     *string `json:"summary,omitempty" yaml:"summary,omitempty"`
	Description *string `json:"description,omitempty" yaml:"description,omitempty"`
	//
	Website       *string `json:"website,omitempty" yaml:"website,omitempty"`
	SourceCodeURL *string `json:"source_code_url,omitempty" yaml:"source_code_url,omitempty"`
	SupportURL    *string `json:"support_url,omitempty" yaml:"support_url,omitempty"`
	// auto-generated at share
	PublishedAt *time.Time        `json:"published_at,omitempty" yaml:"published_at,omitempty"`
	Source      StepSourceModel   `json:"source,omitempty" yaml:"source,omitempty"`
	AssetURLs   map[string]string `json:"asset_urls,omitempty" yaml:"asset_urls,omitempty"`
	//
	HostOsTags          []string          `json:"host_os_tags,omitempty" yaml:"host_os_tags,omitempty"`
	ProjectTypeTags     []string          `json:"project_type_tags,omitempty" yaml:"project_type_tags,omitempty"`
	TypeTags            []string          `json:"type_tags,omitempty" yaml:"type_tags,omitempty"`
	Dependencies        []DependencyModel `json:"dependencies,omitempty" yaml:"dependencies,omitempty"`
	Deps                DepsModel         `json:"deps,omitempty" yaml:"deps,omitempty"`
	IsRequiresAdminUser *bool             `json:"is_requires_admin_user,omitempty" yaml:"is_requires_admin_user,omitempty"`
	// IsAlwaysRun : if true then this step will always run,
	//  even if a previous step fails.
	IsAlwaysRun *bool `json:"is_always_run,omitempty" yaml:"is_always_run,omitempty"`
	// IsSkippable : if true and this step fails the build will still continue.
	//  If false then the build will be marked as failed and only those
	//  steps will run which are marked with IsAlwaysRun.
	IsSkippable *bool `json:"is_skippable,omitempty" yaml:"is_skippable,omitempty"`
	// RunIf : only run the step if the template example evaluates to true
	RunIf *string `json:"run_if,omitempty" yaml:"run_if,omitempty"`
	//
	Inputs  []envmanModels.EnvironmentItemModel `json:"inputs,omitempty" yaml:"inputs,omitempty"`
	Outputs []envmanModels.EnvironmentItemModel `json:"outputs,omitempty" yaml:"outputs,omitempty"`
}

// StepGroupModel ...
type StepGroupModel struct {
	LatestVersionNumber string               `json:"latest_version_number"`
	Versions            map[string]StepModel `json:"versions"`
}

// StepHash ...
type StepHash map[string]StepGroupModel

// DownloadLocationModel ...
type DownloadLocationModel struct {
	Type string `json:"type"`
	Src  string `json:"src"`
}

// StepCollectionModel ...
type StepCollectionModel struct {
	FormatVersion         string                  `json:"format_version" yaml:"format_version"`
	GeneratedAtTimeStamp  int64                   `json:"generated_at_timestamp" yaml:"generated_at_timestamp"`
	SteplibSource         string                  `json:"steplib_source" yaml:"steplib_source"`
	DownloadLocations     []DownloadLocationModel `json:"download_locations" yaml:"download_locations"`
	AssetsDownloadBaseURI string                  `json:"assets_download_base_uri" yaml:"assets_download_base_uri"`
	Steps                 StepHash                `json:"steps" yaml:"steps"`
}

// EnvInfoModel ...
type EnvInfoModel struct {
	Key          string   `json:"key,omitempty" yaml:"key,omitempty"`
	Title        string   `json:"title,omitempty" yaml:"title,omitempty"`
	Description  string   `json:"description,omitempty" yaml:"description,omitempty"`
	ValueOptions []string `json:"value_options,omitempty" yaml:"value_options,omitempty"`
	DefaultValue string   `json:"default_value,omitempty" yaml:"default_value,omitempty"`
	IsExpand     bool     `json:"is_expand" yaml:"is_expand"`
}

// StepInfoModel ...
type StepInfoModel struct {
	ID          string         `json:"step_id,omitempty" yaml:"step_id,omitempty"`
	Version     string         `json:"step_version,omitempty" yaml:"step_version,omitempty"`
	Latest      string         `json:"latest_version,omitempty" yaml:"latest_version,omitempty"`
	Description string         `json:"description,omitempty" yaml:"description,omitempty"`
	Source      string         `json:"source,omitempty" yaml:"source,omitempty"`
	StepLib     string         `json:"steplib,omitempty" yaml:"steplib,omitempty"`
	Inputs      []EnvInfoModel `json:"inputs,omitempty" yaml:"inputs,omitempty"`
	Outputs     []EnvInfoModel `json:"outputs,omitempty" yaml:"outputs,omitempty"`
}

// StepListModel ...
type StepListModel struct {
	StepLib string   `json:"steplib,omitempty" yaml:"steplib,omitempty"`
	Steps   []string `json:"steps,omitempty" yaml:"steps,omitempty"`
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, Mitchell Cooper
package transport

import (
	"bufio"
	"errors"
	"github.com/cooper/quiki/wikiclient"
	"io"
	"log"
	"time"
)

type jsonTransport struct {
	*transport
	incoming chan []byte
	err      chan error
	writer   io.Writer
	reader   *bufio.Reader
}

// create json transport base
func createJson() *jsonTransport {
	return &jsonTransport{
		createTransport(),
		make(chan []byte),
		make(chan error),
		nil,
		nil,
	}
}

// start the loop
func (jsonTr *jsonTransport) startLoops() {
	go jsonTr.readLoop()
	go jsonTr.mainLoop()
}

func (jsonTr *jsonTransport) readLoop() {
	log.Println("readLoop")
	for {

		// not ready
		if jsonTr.reader == nil {
			jsonTr.err <- errors.New("reader is not available")
			return
		}

		// read a full line
		data, err := jsonTr.reader.ReadBytes('\n')

		// some error occurred
		if err != nil {
			jsonTr.err <- err
			return
		}

		jsonTr.incoming <- data
	}
}

func (jsonTr *jsonTransport) mainLoop() {
	for {
		select {

		// read error
		case err := <-jsonTr.err:
			log.Println("error reading!", err)
			go func() {
				time.Sleep(5 * time.Second)
				jsonTr.readLoop()
			}()

			// outgoing messages
		case msg := <-jsonTr.writeMessages:
			log.Println("found a message to write:", msg)
			data := append(msg.ToJson(), '\n')
			if _, err := jsonTr.writer.Write(data); err != nil {
				log.Println("error writing!", err)
			}

			// incoming json data
		case json := <-jsonTr.incoming:
			log.Println("found some data to handle:", string(json))
			msg, err := wikiclient.MessageFromJson(json)
			if err != nil {
				log.Println("error creating message:", err)
				continue
			}
			jsonTr.readMessages <- msg
		}
	}
}
<commit_msg>use baseTransport errors<commit_after>// Copyright (c) 2017, Mitchell Cooper
package transport

import (
	"bufio"
	"errors"
	"github.com/cooper/quiki/wikiclient"
	"io"
)

type jsonTransport struct {
	*transport
	incoming chan []byte
	writer   io.Writer
	reader   *bufio.Reader
}

// create json transport base
func createJson() *jsonTransport {
	return &jsonTransport{
		createTransport(),
		make(chan []byte),
		nil,
		nil,
	}
}

// start the loop
func (jsonTr *jsonTransport) startLoops() {
	go jsonTr.readLoop()
	go jsonTr.mainLoop()
}

func (jsonTr *jsonTransport) readLoop() {
	for {

		// not ready
		if jsonTr.reader == nil {
			jsonTr.errors <- errors.New("reader is not available")
			return
		}

		// read a full line
		data, err := jsonTr.reader.ReadBytes('\n')

		// some error occurred
		if err != nil {
			jsonTr.errors <- err
			return
		}

		jsonTr.incoming <- data
	}
}

func (jsonTr *jsonTransport) mainLoop() {
	for {
		select {

		// outgoing messages
		case msg := <-jsonTr.writeMessages:
			data := append(msg.ToJson(), '\n')
			if _, err := jsonTr.writer.Write(data); err != nil {
				jsonTr.errors <- err
			}

		// incoming json data
		case json := <-jsonTr.incoming:
			msg, err := wikiclient.MessageFromJson(json)
			if err != nil {
				jsonTr.errors <- errors.New("error creating message: " + err.Error())
				break
			}
			jsonTr.readMessages <- msg

		}
	}
}
<|endoftext|>