<commit_before>// Copyright 2018 Google LLC
//
// 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.

// This program ensures source code files have copyright license headers.
// See usage with "addlicence -h".
package main

import (
	"bytes"
	"flag"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"
)

const helpText = `Usage: addlicense [flags] pattern [pattern ...]

The program ensures source code files have copyright license headers
by scanning directory patterns recursively.

It modifies all source files in place and avoids adding a license header
to any file that already has one.

The pattern argument can be provided multiple times, and may also refer
to single files.

Flags:
`

var (
	holder   = flag.String("c", "Google LLC", "copyright holder")
	license  = flag.String("l", "apache", "license type: apache, bsd, mit")
	licensef = flag.String("f", "", "license file")
	year     = flag.String("y", fmt.Sprint(time.Now().Year()), "copyright year(s)")
)

func main() {
	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, helpText)
		flag.PrintDefaults()
	}
	flag.Parse()
	if flag.NArg() == 0 {
		flag.Usage()
		os.Exit(1)
	}

	data := &copyrightData{
		Year:   *year,
		Holder: *holder,
	}

	var t *template.Template
	if *licensef != "" {
		d, err := ioutil.ReadFile(*licensef)
		if err != nil {
			log.Printf("license file: %v", err)
			os.Exit(1)
		}
		t, err = template.New("").Parse(string(d))
		if err != nil {
			log.Printf("license file: %v", err)
			os.Exit(1)
		}
	} else {
		t = licenseTemplate[*license]
		if t == nil {
			log.Printf("unknown license: %s", *license)
			os.Exit(1)
		}
	}

	// process at most 1000 files in parallel
	ch := make(chan *file, 1000)
	done := make(chan struct{})
	go func() {
		var wg sync.WaitGroup
		for f := range ch {
			wg.Add(1)
			go func(f *file) {
				err := addLicense(f.path, f.mode, t, data)
				if err != nil {
					log.Printf("%s: %v", f.path, err)
				}
				wg.Done()
			}(f)
		}
		wg.Wait()
		close(done)
	}()

	for _, d := range flag.Args() {
		walk(ch, d)
	}
	close(ch)
	<-done
}

type file struct {
	path string
	mode os.FileMode
}

func walk(ch chan<- *file, start string) {
	filepath.Walk(start, func(path string, fi os.FileInfo, err error) error {
		if err != nil {
			log.Printf("%s error: %v", path, err)
			return nil
		}
		if fi.IsDir() {
			return nil
		}
		ch <- &file{path, fi.Mode()}
		return nil
	})
}

func addLicense(path string, fmode os.FileMode, tmpl *template.Template, data *copyrightData) error {
	var lic []byte
	var err error
	switch fileExtension(path) {
	default:
		return nil
	case ".c", ".h":
		lic, err = prefix(tmpl, data, "/*", " * ", " */")
	case ".js", ".jsx", ".tsx", ".css", ".tf":
		lic, err = prefix(tmpl, data, "/**", " * ", " */")
	case ".cc", ".cpp", ".cs", ".go", ".hh", ".hpp", ".java", ".m", ".mm", ".proto", ".rs", ".scala", ".swift", ".dart", ".groovy":
		lic, err = prefix(tmpl, data, "", "// ", "")
	case ".py", ".sh", ".yaml", ".yml", ".dockerfile", "dockerfile", ".rb", "gemfile":
		lic, err = prefix(tmpl, data, "", "# ", "")
	case ".el", ".lisp":
		lic, err = prefix(tmpl, data, "", ";; ", "")
	case ".erl":
		lic, err = prefix(tmpl, data, "", "% ", "")
	case ".hs", ".sql":
		lic, err = prefix(tmpl, data, "", "-- ", "")
	case ".html", ".xml":
		lic, err = prefix(tmpl, data, "<!--", " ", "-->")
	case ".php":
		lic, err = prefix(tmpl, data, "<?php", "// ", "?>")
	}
	if err != nil || lic == nil {
		return err
	}

	b, err := ioutil.ReadFile(path)
	if err != nil || hasLicense(b) {
		return err
	}

	line := hashBang(b)
	if len(line) > 0 {
		b = b[len(line):]
		if line[len(line)-1] != '\n' {
			line = append(line, '\n')
		}
		lic = append(line, lic...)
	}
	b = append(lic, b...)
	return ioutil.WriteFile(path, b, fmode)
}

func fileExtension(name string) string {
	if v := filepath.Ext(name); v != "" {
		return strings.ToLower(v)
	}
	return strings.ToLower(filepath.Base(name))
}

var head = []string{
	"#!",                       // shell script
	"<?xml",                    // XML declaratioon
	"<!doctype",                // HTML doctype
	"# encoding:",              // Ruby encoding
	"# frozen_string_literal:", // Ruby interpreter instruction
}

func hashBang(b []byte) []byte {
	var line []byte
	for _, c := range b {
		line = append(line, c)
		if c == '\n' {
			break
		}
	}
	first := strings.ToLower(string(line))
	for _, h := range head {
		if strings.HasPrefix(first, h) {
			return line
		}
	}
	return nil
}

func hasLicense(b []byte) bool {
	n := 1000
	if len(b) < 1000 {
		n = len(b)
	}
	return bytes.Contains(bytes.ToLower(b[:n]), []byte("copyright"))
}
<commit_msg>Add kotlin files to list of accepted extensions<commit_after>// Copyright 2018 Google LLC
//
// 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.

// This program ensures source code files have copyright license headers.
// See usage with "addlicence -h".
package main

import (
	"bytes"
	"flag"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"
)

const helpText = `Usage: addlicense [flags] pattern [pattern ...]

The program ensures source code files have copyright license headers
by scanning directory patterns recursively.

It modifies all source files in place and avoids adding a license header
to any file that already has one.

The pattern argument can be provided multiple times, and may also refer
to single files.

Flags:
`

var (
	holder   = flag.String("c", "Google LLC", "copyright holder")
	license  = flag.String("l", "apache", "license type: apache, bsd, mit")
	licensef = flag.String("f", "", "license file")
	year     = flag.String("y", fmt.Sprint(time.Now().Year()), "copyright year(s)")
)

func main() {
	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, helpText)
		flag.PrintDefaults()
	}
	flag.Parse()
	if flag.NArg() == 0 {
		flag.Usage()
		os.Exit(1)
	}

	data := &copyrightData{
		Year:   *year,
		Holder: *holder,
	}

	var t *template.Template
	if *licensef != "" {
		d, err := ioutil.ReadFile(*licensef)
		if err != nil {
			log.Printf("license file: %v", err)
			os.Exit(1)
		}
		t, err = template.New("").Parse(string(d))
		if err != nil {
			log.Printf("license file: %v", err)
			os.Exit(1)
		}
	} else {
		t = licenseTemplate[*license]
		if t == nil {
			log.Printf("unknown license: %s", *license)
			os.Exit(1)
		}
	}

	// process at most 1000 files in parallel
	ch := make(chan *file, 1000)
	done := make(chan struct{})
	go func() {
		var wg sync.WaitGroup
		for f := range ch {
			wg.Add(1)
			go func(f *file) {
				err := addLicense(f.path, f.mode, t, data)
				if err != nil {
					log.Printf("%s: %v", f.path, err)
				}
				wg.Done()
			}(f)
		}
		wg.Wait()
		close(done)
	}()

	for _, d := range flag.Args() {
		walk(ch, d)
	}
	close(ch)
	<-done
}

type file struct {
	path string
	mode os.FileMode
}

func walk(ch chan<- *file, start string) {
	filepath.Walk(start, func(path string, fi os.FileInfo, err error) error {
		if err != nil {
			log.Printf("%s error: %v", path, err)
			return nil
		}
		if fi.IsDir() {
			return nil
		}
		ch <- &file{path, fi.Mode()}
		return nil
	})
}

func addLicense(path string, fmode os.FileMode, tmpl *template.Template, data *copyrightData) error {
	var lic []byte
	var err error
	switch fileExtension(path) {
	default:
		return nil
	case ".c", ".h":
		lic, err = prefix(tmpl, data, "/*", " * ", " */")
	case ".js", ".jsx", ".tsx", ".css", ".tf":
		lic, err = prefix(tmpl, data, "/**", " * ", " */")
	case ".cc", ".cpp", ".cs", ".go", ".hh", ".hpp", ".java", ".m", ".mm", ".proto", ".rs", ".scala", ".swift", ".dart", ".groovy", ".kt", ".kts":
		lic, err = prefix(tmpl, data, "", "// ", "")
	case ".py", ".sh", ".yaml", ".yml", ".dockerfile", "dockerfile", ".rb", "gemfile":
		lic, err = prefix(tmpl, data, "", "# ", "")
	case ".el", ".lisp":
		lic, err = prefix(tmpl, data, "", ";; ", "")
	case ".erl":
		lic, err = prefix(tmpl, data, "", "% ", "")
	case ".hs", ".sql":
		lic, err = prefix(tmpl, data, "", "-- ", "")
	case ".html", ".xml":
		lic, err = prefix(tmpl, data, "<!--", " ", "-->")
	case ".php":
		lic, err = prefix(tmpl, data, "<?php", "// ", "?>")
	}
	if err != nil || lic == nil {
		return err
	}

	b, err := ioutil.ReadFile(path)
	if err != nil || hasLicense(b) {
		return err
	}

	line := hashBang(b)
	if len(line) > 0 {
		b = b[len(line):]
		if line[len(line)-1] != '\n' {
			line = append(line, '\n')
		}
		lic = append(line, lic...)
	}
	b = append(lic, b...)
	return ioutil.WriteFile(path, b, fmode)
}

func fileExtension(name string) string {
	if v := filepath.Ext(name); v != "" {
		return strings.ToLower(v)
	}
	return strings.ToLower(filepath.Base(name))
}

var head = []string{
	"#!",                       // shell script
	"<?xml",                    // XML declaratioon
	"<!doctype",                // HTML doctype
	"# encoding:",              // Ruby encoding
	"# frozen_string_literal:", // Ruby interpreter instruction
}

func hashBang(b []byte) []byte {
	var line []byte
	for _, c := range b {
		line = append(line, c)
		if c == '\n' {
			break
		}
	}
	first := strings.ToLower(string(line))
	for _, h := range head {
		if strings.HasPrefix(first, h) {
			return line
		}
	}
	return nil
}

func hasLicense(b []byte) bool {
	n := 1000
	if len(b) < 1000 {
		n = len(b)
	}
	return bytes.Contains(bytes.ToLower(b[:n]), []byte("copyright"))
}
<|endoftext|>


<commit_before>package llog

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

type LogLevel int8
type LogType int8

var logger *log.Logger
var filelog *log.Logger
var minLevel LogLevel

const (
	TRACE LogLevel = iota
	DEBUG
	INFO
	WARN
	ERROR
	FATAL
	PANIC
)

const (
	CONSOLE LogType = iota + 1
	FILE
)

// Call Initialize after setting (or not setting) SyslogHost and SyslogPort when
// they're read from configuration source.
func init() {
	minLevel = TRACE
	logger = log.New(os.Stdout, "\r\n", log.Ldate|log.Ltime|log.Lshortfile)
}

func SetLogLevel(level LogLevel) {
	minLevel = level
}

func GetLogLevel() LogLevel {
	return minLevel
}

func ResetLogger() {
	logger = nil
	filelog = nil
}

func AddLogger(logtype LogType) {
	if logtype == CONSOLE {
		logger = log.New(os.Stdout, "\r\n", log.Ldate|log.Ltime|log.Lshortfile)
	} else if logtype == FILE {
		filename := fmt.Sprintf("./%s.llog", time.Now().String())
		fmt.Printf("Log initialize:%s\n", filename)
		logfile, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0600)
		if err != nil {
			Panic(err)
		}
		filelog = log.New(logfile, "\r\n", log.Ldate|log.Ltime|log.Lshortfile)
	}
}

func DelLogger(logtype LogType) {
	if logtype == CONSOLE {
		logger = nil
	} else if logtype == FILE {
		filelog = nil
	}
}

func _log(s string) {
	if logger != nil {
		logger.Output(4, s)
	}
	if filelog != nil {
		filelog.Output(4, s)
	}
}

func Panic(messages ...interface{}) {
	panic_(messages...)
}

func Panicf(format string, messages ...interface{}) {
	panicf(format, messages...)
}

func Fatal(messages ...interface{}) {
	if minLevel <= FATAL {
		fatal(messages...)
	}
}

func Fatalf(format string, messages ...interface{}) {
	if minLevel <= FATAL {
		fatalf(format, messages...)
	}
}

func Error(messages ...interface{}) {
	if minLevel <= ERROR {
		print(messages...)
	}
}

func Errorf(format string, messages ...interface{}) {
	if minLevel <= ERROR {
		printf(format, messages...)
	}
}

func Warn(messages ...interface{}) {
	if minLevel <= WARN {
		print(messages...)
	}
}

func Warnf(format string, messages ...interface{}) {
	if minLevel <= WARN {
		printf(format, messages...)
	}
}

func Info(messages ...interface{}) {
	if minLevel <= INFO {
		print(messages...)
	}
}

func Infof(format string, messages ...interface{}) {
	if minLevel <= INFO {
		printf(format, messages...)
	}
}

func Debug(messages ...interface{}) {
	if minLevel <= DEBUG {
		print(messages...)
	}
}

func Debugf(format string, messages ...interface{}) {
	if minLevel <= DEBUG {
		printf(format, messages...)
	}
}

func Trace(messages ...interface{}) {
	if minLevel <= TRACE {
		print(messages...)
	}
}

func Tracef(format string, messages ...interface{}) {
	if minLevel <= TRACE {
		printf(format, messages...)
	}
}

// Printf calls l.Output to print to the logger.
// Arguments are handled in the manner of fmt.Printf.
func printf(format string, v ...interface{}) {
	_log(fmt.Sprintf(format, v...))
}

// Print calls l.Output to print to the logger.
// Arguments are handled in the manner of fmt.Print.
func print(v ...interface{}) { _log(fmt.Sprint(v...)) }

// Println calls l.Output to print to the logger.
// Arguments are handled in the manner of fmt.Println.
func println(v ...interface{}) { _log(fmt.Sprintln(v...)) }

// Fatal is equivalent to l.Print() followed by a call to os.Exit(1).
func fatal(v ...interface{}) {
	_log(fmt.Sprint(v...))
	os.Exit(1)
}

// Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1).
func fatalf(format string, v ...interface{}) {
	_log(fmt.Sprintf(format, v...))
	os.Exit(1)
}

// Fatalln is equivalent to l.Println() followed by a call to os.Exit(1).
func fatalln(v ...interface{}) {
	_log(fmt.Sprintln(v...))
	os.Exit(1)
}

// Panic is equivalent to l.Print() followed by a call to panic().
func panic_(v ...interface{}) {
	s := fmt.Sprint(v...)
	_log(s)
	panic(s)
}

// Panicf is equivalent to l.Printf() followed by a call to panic().
func panicf(format string, v ...interface{}) {
	s := fmt.Sprintf(format, v...)
	_log(s)
	panic(s)
}

// Panicln is equivalent to l.Println() followed by a call to panic().
func panicln(v ...interface{}) {
	s := fmt.Sprintln(v...)
	_log(s)
	panic(s)
}

func Println(level LogLevel, messages ...interface{}) {

	switch level {
	case DEBUG:
		Debugf("%v", messages)
	case TRACE:
		Tracef("%v", messages)
	case INFO:
		Infof("%v", messages)
	case WARN:
		Warnf("%v", messages)
	case ERROR:
		Errorf("%v", messages)
	case FATAL:
		Fatalf("%v", messages)
	case PANIC:
		Panicf("%v", messages)
	}

	return
}

func Printf(level LogLevel, format string, messages ...interface{}) {

	switch level {
	case DEBUG:
		Debugf(format, messages)
	case TRACE:
		Tracef(format, messages)
	case INFO:
		Infof(format, messages)
	case WARN:
		Warnf(format, messages)
	case ERROR:
		Errorf(format, messages)
	case FATAL:
		Fatalf(format, messages)
	case PANIC:
		Panicf(format, messages)
	}

	return
}

func fromMulti(messages ...interface{}) string {
	var r string
	for x := 0; x < len(messages); x++ {
		r = r + messages[x].(string)
		if x < len(messages) {
			r = r + "  "
		}
	}
	return r
}

func LevelFromString(l string) (level LogLevel) {
	switch l {
	case "DEBUG":
		level = DEBUG
	case "TRACE":
		level = TRACE
	case "INFO":
		level = INFO
	case "WARN":
		level = WARN
	case "ERROR":
		level = ERROR
	case "FATAL":
		level = FATAL
	case "PANIC":
		level = PANIC
	}

	return
}
<commit_msg>change log filename to have a prefix.<commit_after>package llog

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

type LogLevel int8
type LogType int8

var logger *log.Logger
var filelog *log.Logger
var minLevel LogLevel
var fileTag string

const (
	TRACE LogLevel = iota
	DEBUG
	INFO
	WARN
	ERROR
	FATAL
	PANIC
)

const (
	CONSOLE LogType = iota + 1
	FILE
)

const (
	CALLDEPTH = 2
)

// Call Initialize after setting (or not setting) SyslogHost and SyslogPort when
// they're read from configuration source.
func init() {
	minLevel = TRACE
	logger = log.New(os.Stdout, "\r\n", log.Ldate|log.Ltime|log.Lshortfile)
}

func SetLogLevel(level LogLevel) {
	minLevel = level
}

func GetLogLevel() LogLevel {
	return minLevel
}

func SetFileTag(filetag string) {
	fileTag = filetag
}

func ResetLogger() {
	logger = nil
	filelog = nil
}

func AddLogger(logtype LogType) {
	if logtype == CONSOLE {
		logger = log.New(os.Stdout, "\r\n", log.Ldate|log.Ltime|log.Lshortfile)
	} else if logtype == FILE {
		filename := fmt.Sprintf("./%s%s.llog",fileTag, time.Now().String())
		fmt.Printf("Log initialize:%s\n", filename)
		logfile, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0600)
		if err != nil {
			Panic(err)
		}
		filelog = log.New(logfile, "\r\n", log.Ldate|log.Ltime|log.Lshortfile)
	}
}

func DelLogger(logtype LogType) {
	if logtype == CONSOLE {
		logger = nil
	} else if logtype == FILE {
		filelog = nil
	}
}

func _log(calldepth int, s string) {
	if logger != nil {
		logger.Output(calldepth + 1, s)
	}
	if filelog != nil {
		filelog.Output(calldepth + 1, s)
	}
}

func Panic(messages ...interface{}) {
	_panic(CALLDEPTH, messages...)
}

func Panicf(format string, messages ...interface{}) {
	panicf(CALLDEPTH, format, messages...)
}

func Fatal(messages ...interface{}) {
	if minLevel <= FATAL {
		fatalln(CALLDEPTH, messages...)
	}
}

func Fatalf(format string, messages ...interface{}) {
	if minLevel <= FATAL {
		fatalf(CALLDEPTH, format, messages...)
	}
}

func Error(messages ...interface{}) {
	if minLevel <= ERROR {
		println(CALLDEPTH, messages...)
	}
}

func Errorf(format string, messages ...interface{}) {
	if minLevel <= ERROR {
		printf(CALLDEPTH, format, messages...)
	}
}

func Warn(messages ...interface{}) {
	if minLevel <= WARN {
		println(CALLDEPTH, messages...)
	}
}

func Warnf(format string, messages ...interface{}) {
	if minLevel <= WARN {
		printf(CALLDEPTH, format, messages...)
	}
}

func Info(messages ...interface{}) {
	if minLevel <= INFO {
		println(CALLDEPTH, messages...)
	}
}

func Infof(format string, messages ...interface{}) {
	if minLevel <= INFO {
		printf(CALLDEPTH, format, messages...)
	}
}

func Debug(messages ...interface{}) {
	if minLevel <= DEBUG {
		println(CALLDEPTH, messages...)
	}
}

func Debugf(format string, messages ...interface{}) {
	if minLevel <= DEBUG {
		printf(CALLDEPTH, format, messages...)
	}
}

func Trace(messages ...interface{}) {
	if minLevel <= TRACE {
		println(CALLDEPTH, messages...)
	}
}

func Tracef(format string, messages ...interface{}) {
	if minLevel <= TRACE {
		printf(CALLDEPTH, format, messages...)
	}
}

// Printf calls l.Output to print to the logger.
// Arguments are handled in the manner of fmt.Printf.
func printf(calldepth int,format string, v ...interface{}) {
	_log(calldepth + 1, fmt.Sprintf(format, v...))
}

// Print calls l.Output to print to the logger.
// Arguments are handled in the manner of fmt.Print.
func print(calldepth int, v ...interface{}) { _log(calldepth + 1,fmt.Sprint(v...)) }

// Println calls l.Output to print to the logger.
// Arguments are handled in the manner of fmt.Println.
func println(calldepth int, v ...interface{}) { _log(calldepth + 1, fmt.Sprintln(v...)) }

// Fatal is equivalent to l.Print() followed by a call to os.Exit(1).
func fatal(calldepth int, v ...interface{}) {
	_log(calldepth + 1, fmt.Sprint(v...))
	os.Exit(1)
}

// Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1).
func fatalf(calldepth int, format string, v ...interface{}) {
	_log(calldepth + 1, fmt.Sprintf(format, v...))
	os.Exit(1)
}

// Fatalln is equivalent to l.Println() followed by a call to os.Exit(1).
func fatalln(calldepth int, v ...interface{}) {
	_log(calldepth + 1, fmt.Sprintln(v...))
	os.Exit(1)
}

// Panic is equivalent to l.Print() followed by a call to panic().
func _panic(calldepth int, v ...interface{}) {
	s := fmt.Sprint(v...)
	_log(calldepth + 1, s)
	panic(s)
}

// Panicf is equivalent to l.Printf() followed by a call to panic().
func panicf(calldepth int, format string, v ...interface{}) {
	s := fmt.Sprintf(format, v...)
	_log(calldepth + 1, s)
	panic(s)
}

// Panicln is equivalent to l.Println() followed by a call to panic().
func panicln(calldepth int, v ...interface{}) {
	s := fmt.Sprintln(v...)
	_log(calldepth + 1, s)
	panic(s)
}

func Println(level LogLevel, messages ...interface{}) {

	switch level {
	case DEBUG:
		Debugf("%v", messages)
	case TRACE:
		Tracef("%v", messages)
	case INFO:
		Infof("%v", messages)
	case WARN:
		Warnf("%v", messages)
	case ERROR:
		Errorf("%v", messages)
	case FATAL:
		Fatalf("%v", messages)
	case PANIC:
		Panicf("%v", messages)
	}

	return
}

func Printf(level LogLevel, format string, messages ...interface{}) {

	switch level {
	case DEBUG:
		Debugf(format, messages)
	case TRACE:
		Tracef(format, messages)
	case INFO:
		Infof(format, messages)
	case WARN:
		Warnf(format, messages)
	case ERROR:
		Errorf(format, messages)
	case FATAL:
		Fatalf(format, messages)
	case PANIC:
		Panicf(format, messages)
	}

	return
}

func fromMulti(messages ...interface{}) string {
	var r string
	for x := 0; x < len(messages); x++ {
		r = r + messages[x].(string)
		if x < len(messages) {
			r = r + "  "
		}
	}
	return r
}

func LevelFromString(l string) (level LogLevel) {
	switch l {
	case "DEBUG":
		level = DEBUG
	case "TRACE":
		level = TRACE
	case "INFO":
		level = INFO
	case "WARN":
		level = WARN
	case "ERROR":
		level = ERROR
	case "FATAL":
		level = FATAL
	case "PANIC":
		level = PANIC
	}

	return
}
<|endoftext|>


<commit_before>// 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 main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"

	"github.com/line/line-bot-sdk-go/linebot"
)

var bot *linebot.Client

type GeoContent struct {
	LatLong string `json:"latLon"`
	Utm     string `json:"utm"`
	Mgrs    string `json:"mgrs"`
}

type ResultGeoLoc struct {
	Results GeoContent `json:"result"`
}

func getGeoLoc(body []byte) (*ResultGeoLoc, error) {
	var s = new(ResultGeoLoc)
	err := json.Unmarshal(body, &s)
	if err != nil {
		fmt.Println("whoops:", err)
	}
	return s, err
}

func main() {
	getAllUser()
	addNewUser()
	// line bot
	strID := os.Getenv("ChannelID")
	numID, err := strconv.ParseInt(strID, 10, 64)
	if err != nil {
		log.Fatal("Wrong environment setting about ChannelID")
	}

	bot, err = linebot.NewClient(numID, os.Getenv("ChannelSecret"), os.Getenv("MID"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
}
func callbackHandler(w http.ResponseWriter, r *http.Request) {

	received, err := bot.ParseRequest(r)
	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}
	for _, result := range received.Results {
		content := result.Content()
		log.Println("-->", content)

		//Log detail receive content
		if content != nil {
			log.Println("RECEIVE Msg:", content.IsMessage, " OP:", content.IsOperation, " type:", content.ContentType, " from:", content.From, "to:", content.To, " ID:", content.ID)
		}
		// user add friend
		if content != nil && content.IsOperation && content.OpType == linebot.OpTypeAddedAsFriend {
			out := fmt.Sprintf("Bot แปลงพิกัด Eggyo\nวิธีใช้\nเพียงแค่กดแชร์ Location ที่ต้องการ ระบบจะทำการแปลง Location เป็นพิกัดระบบต่างๆ และหาความสูงจากระดับน้ำทะเลให้\nกด #help เพื่อดูวิธีใช้อื่นๆ :))")
			//result.RawContent.Params[0] is who send your bot friend added operation, otherwise you cannot get in content or operation content.
			_, err = bot.SendText([]string{result.RawContent.Params[0]}, out)
			if err != nil {
				log.Println(err)
			}
		}

		if content != nil && content.IsMessage && content.ContentType == linebot.ContentTypeText {
			text, err := content.TextContent()
			var processedText = messageCheck(text.Text)
			_, err = bot.SendText([]string{content.From}, processedText)

			if err != nil {
				log.Println(err)
			}
		}
		if content != nil && content.ContentType == linebot.ContentTypeLocation {
			_, err = bot.SendText([]string{content.From}, "ระบบกำลังประมวลผล...")

			loc, err := content.LocationContent()

			// add eggyo geo test
			resp, err := http.Get("http://eggyo-geo-node.herokuapp.com/geo/" + FloatToString(loc.Latitude) + "/" + FloatToString(loc.Longitude))
			if err != nil {
				println(err.Error())
				return
			}
			defer resp.Body.Close()
			body, err := ioutil.ReadAll(resp.Body)
			log.Println(string(body))

			var elev = callGoogleElev(loc.Latitude, loc.Longitude)
			geo, err := getGeoLoc([]byte(body))
			_, err = bot.SendText([]string{content.From}, "LatLong :"+geo.Results.LatLong)
			_, err = bot.SendText([]string{content.From}, "Utm :"+geo.Results.Utm+"\n\nMgrs :"+geo.Results.Mgrs+"\n\nAltitude :"+elev)
			if err != nil {
				log.Println(err)
			}
		}
	}
}
<commit_msg>v.3.6.5<commit_after>// 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 main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"

	"github.com/line/line-bot-sdk-go/linebot"
)

var bot *linebot.Client

type GeoContent struct {
	LatLong string `json:"latLon"`
	Utm     string `json:"utm"`
	Mgrs    string `json:"mgrs"`
}

type ResultGeoLoc struct {
	Results GeoContent `json:"result"`
}

func getGeoLoc(body []byte) (*ResultGeoLoc, error) {
	var s = new(ResultGeoLoc)
	err := json.Unmarshal(body, &s)
	if err != nil {
		fmt.Println("whoops:", err)
	}
	return s, err
}

func main() {
	getAllUser()
	addNewUser()
	// line bot
	strID := os.Getenv("ChannelID")
	numID, err := strconv.ParseInt(strID, 10, 64)
	if err != nil {
		log.Fatal("Wrong environment setting about ChannelID")
	}

	bot, err = linebot.NewClient(numID, os.Getenv("ChannelSecret"), os.Getenv("MID"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
	//test
	_, err = bot.SendText([]string{"ufa92a3a52f197e19bfddeb5ca0595e93"}, "deploy done!")

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

	received, err := bot.ParseRequest(r)
	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}
	for _, result := range received.Results {
		content := result.Content()
		log.Println("-->", content)

		//Log detail receive content
		if content != nil {
			log.Println("RECEIVE Msg:", content.IsMessage, " OP:", content.IsOperation, " type:", content.ContentType, " from:", content.From, "to:", content.To, " ID:", content.ID)
		}
		// user add friend
		if content != nil && content.IsOperation && content.OpType == linebot.OpTypeAddedAsFriend {
			out := fmt.Sprintf("Bot แปลงพิกัด Eggyo\nวิธีใช้\nเพียงแค่กดแชร์ Location ที่ต้องการ ระบบจะทำการแปลง Location เป็นพิกัดระบบต่างๆ และหาความสูงจากระดับน้ำทะเลให้\nกด #help เพื่อดูวิธีใช้อื่นๆ \nติดต่อผู้พัฒนา LINE ID : eggyo")
			//result.RawContent.Params[0] is who send your bot friend added operation, otherwise you cannot get in content or operation content.
			_, err = bot.SendText([]string{result.RawContent.Params[0]}, out)
			if err != nil {
				log.Println(err)
			}
		}

		if content != nil && content.IsMessage && content.ContentType == linebot.ContentTypeText {

			text, err := content.TextContent()
			var processedText = messageCheck(text.Text)
			_, err = bot.SendText([]string{content.From}, processedText)

			if err != nil {
				log.Println(err)
			}
		}
		if content != nil && content.ContentType == linebot.ContentTypeLocation {
			_, err = bot.SendText([]string{content.From}, "ระบบกำลังประมวลผล...")

			loc, err := content.LocationContent()

			// add eggyo geo test
			resp, err := http.Get("http://eggyo-geo-node.herokuapp.com/geo/" + FloatToString(loc.Latitude) + "/" + FloatToString(loc.Longitude))
			if err != nil {
				println(err.Error())
				return
			}
			defer resp.Body.Close()
			body, err := ioutil.ReadAll(resp.Body)
			log.Println(string(body))

			var elev = callGoogleElev(loc.Latitude, loc.Longitude)
			geo, err := getGeoLoc([]byte(body))
			_, err = bot.SendText([]string{content.From}, "LatLong :"+geo.Results.LatLong)
			_, err = bot.SendText([]string{content.From}, "Utm :"+geo.Results.Utm+"\n\nMgrs :"+geo.Results.Mgrs+"\n\nAltitude :"+elev)
			if err != nil {
				log.Println(err)
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"

	"code.google.com/p/go.net/websocket"
)

func main() {
	port := flag.Int("p", 8000, "port to listen on")
	dir := flag.String("d", ".", "directory to serve")
	flag.Parse()

	s := NewServer(http.Dir(*dir))

	http.Handle("/", s)
	http.Handle("/_srv/api", websocket.Handler(s.wsHandler))
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", *port), nil))
}
<commit_msg>Add "listening on ..." message<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"

	"code.google.com/p/go.net/websocket"
)

func main() {
	port := flag.Int("p", 8000, "port to listen on")
	dir := flag.String("d", ".", "directory to serve")
	flag.Parse()

	s := NewServer(http.Dir(*dir))

	http.Handle("/", s)
	http.Handle("/_srv/api", websocket.Handler(s.wsHandler))

	fmt.Fprintf(os.Stderr, "Listening on 0.0.0.0:%d\n", *port)

	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", *port), nil))
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"runtime"
	"time"

	"github.com/rs/zerolog"
	"github.com/rs/zerolog/log"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
	version   string
	branch    string
	revision  string
	buildDate string
	goVersion = runtime.Version()
)

var (
	prometheusAddress     = flag.String("metrics-listen-address", ":9001", "The address to listen on for Prometheus metrics requests.")
	prometheusMetricsPath = flag.String("metrics-path", "/metrics", "The path to listen for Prometheus metrics requests.")
	apiAddress            = flag.String("api-listen-address", ":5000", "The address to listen on for api HTTP requests.")

	// seed random number
	r = rand.New(rand.NewSource(time.Now().UnixNano()))

	// define prometheus counter
	webhookTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "estafette_ci_api_webhook_totals",
			Help: "Total of received webhooks.",
		},
		[]string{"event", "source"},
	)
)

func init() {
	// Metrics have to be registered to be exposed:
	prometheus.MustRegister(webhookTotal)
}

func main() {

	// set some default fields added to all logs
	log := zerolog.New(os.Stdout).With().
		Timestamp().
		Str("app", "estafette-ci-api").
		Str("version", version).
		Logger()

	// log startup message
	log.Info().
		Str("branch", branch).
		Str("revision", revision).
		Str("buildDate", buildDate).
		Str("goVersion", goVersion).
		Msg("Starting estafette-ci-api...")

	// start prometheus
	go func() {
		log.Info().
			Str("port", *prometheusAddress).
			Str("path", *prometheusMetricsPath).
			Msg("Serving Prometheus metrics...")

		http.Handle(*prometheusMetricsPath, promhttp.Handler())

		if err := http.ListenAndServe(*prometheusAddress, nil); err != nil {
			log.Fatal().Err(err).Msg("Starting Prometheus listener failed")
		}
	}()

	log.Info().
		Str("port", *apiAddress).
		Msg("Serving api calls...")

	http.HandleFunc("/webhook/github", githubWebhookHandler)
	http.HandleFunc("/webhook/bitbucket", bitbucketWebhookHandler)
	http.HandleFunc("/liveness", livenessHandler)
	http.HandleFunc("/readiness", readinessHandler)

	if err := http.ListenAndServe(*apiAddress, nil); err != nil {
		log.Fatal().Err(err).Msg("Starting api listener failed")
	}
}

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

	// https://developer.github.com/webhooks/
	eventType := r.Header.Get("X-GitHub-Event")
	webhookTotal.With(prometheus.Labels{"event": eventType, "source": "github"}).Inc()

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Error().Err(err).Msg("Reading body from Github webhook failed")
		http.Error(w, "Reading body from Github webhook failed", 500)
		return
	}

	// unmarshal json body
	var b interface{}
	err = json.Unmarshal(body, &b)
	if err != nil {
		log.Error().Err(err).Str("body", string(body)).Msg("Deserializing body from Github webhook failed")
		http.Error(w, "Deserializing body from Github webhook failed", 500)
		return
	}

	log.Info().
		Str("method", r.Method).
		Str("url", r.URL.String()).
		Interface("headers", r.Header).
		Interface("body", b).
		Msgf("Received webhook event '%v' from GitHub...", eventType)

	switch eventType {
	case "push":
		handleGithubPush(body)
	default:
		log.Warn().Str("event", eventType).Msgf("Unsupported Github event %v", eventType)
	}

	fmt.Fprintf(w, "Aye aye!")
}

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

	// https://confluence.atlassian.com/bitbucket/manage-webhooks-735643732.html

	eventType := r.Header.Get("X-Event-Key")
	webhookTotal.With(prometheus.Labels{"event": eventType, "source": "bitbucket"}).Inc()

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Error().Err(err).Msg("Reading body from Bitbucket webhook failed")
		http.Error(w, "Reading body from Bitbucket webhook failed", 500)
		return
	}

	// unmarshal json body
	var b interface{}
	err = json.Unmarshal(body, &b)
	if err != nil {
		log.Error().Err(err).Str("body", string(body)).Msg("Deserializing body from Bitbucket webhook failed")
		http.Error(w, "Deserializing body from Bitbucket webhook failed", 500)
		return
	}

	log.Info().
		Str("method", r.Method).
		Str("url", r.URL.String()).
		Interface("headers", r.Header).
		Interface("body", string(body)).
		Msgf("Received webhook event '%v' from Bitbucket", eventType)

	switch eventType {
	case "repo:push":
		handleBitbucketPush(body)
	default:
		log.Warn().Str("event", eventType).Msgf("Unsupported Bitbucket event %v", eventType)
	}

	fmt.Fprintf(w, "Aye aye!")
}

// GithubPushEvent represents a Github webhook push event
type GithubPushEvent struct {
	After      string           `json:"after"`
	Commits    []GithubCommit   `json:"commits"`
	HeadCommit GithubCommit     `json:"head_commit"`
	Pusher     GithubPusher     `json:"pusher"`
	Repository GithubRepository `json:"repository"`
}

// GithubCommit represents a Github commit
type GithubCommit struct {
	Author  GithubAuthor `json:"author"`
	Message string       `json:"message"`
	ID      string       `json:"id"`
}

// GithubAuthor represents a Github author
type GithubAuthor struct {
	Email    string `json:"email"`
	Name     string `json:"name"`
	UserName string `json:"username"`
}

// GithubPusher represents a Github pusher
type GithubPusher struct {
	Email string `json:"email"`
	Name  string `json:"name"`
}

// GithubRepository represents a Github repository
type GithubRepository struct {
	GitURL   string `json:"git_url"`
	HTMLURL  string `json:"html_url"`
	Name     string `json:"name"`
	FullName string `json:"full_name"`
}

func handleGithubPush(body []byte) {

	// unmarshal json body
	var pushEvent GithubPushEvent
	err := json.Unmarshal(body, &pushEvent)
	if err != nil {
		log.Error().Err(err).Str("body", string(body)).Msg("Deserializing body to GithubPushEvent failed")
		return
	}

	log.Info().Interface("pushEvent", pushEvent).Msg("Deserialized GitHub push event")
}

func handleBitbucketPush(body []byte) {

}

func livenessHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "I'm alive!")
}

func readinessHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "I'm ready!")
}
<commit_msg>more update log messages<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"runtime"
	"time"

	"github.com/rs/zerolog"
	"github.com/rs/zerolog/log"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
	version   string
	branch    string
	revision  string
	buildDate string
	goVersion = runtime.Version()
)

var (
	prometheusAddress     = flag.String("metrics-listen-address", ":9001", "The address to listen on for Prometheus metrics requests.")
	prometheusMetricsPath = flag.String("metrics-path", "/metrics", "The path to listen for Prometheus metrics requests.")
	apiAddress            = flag.String("api-listen-address", ":5000", "The address to listen on for api HTTP requests.")

	// seed random number
	r = rand.New(rand.NewSource(time.Now().UnixNano()))

	// define prometheus counter
	webhookTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "estafette_ci_api_webhook_totals",
			Help: "Total of received webhooks.",
		},
		[]string{"event", "source"},
	)
)

func init() {
	// Metrics have to be registered to be exposed:
	prometheus.MustRegister(webhookTotal)
}

func main() {

	// set some default fields added to all logs
	log := zerolog.New(os.Stdout).With().
		Timestamp().
		Str("app", "estafette-ci-api").
		Str("version", version).
		Logger()

	// log startup message
	log.Info().
		Str("branch", branch).
		Str("revision", revision).
		Str("buildDate", buildDate).
		Str("goVersion", goVersion).
		Msg("Starting estafette-ci-api...")

	// start prometheus
	go func() {
		log.Info().
			Str("port", *prometheusAddress).
			Str("path", *prometheusMetricsPath).
			Msg("Serving Prometheus metrics...")

		http.Handle(*prometheusMetricsPath, promhttp.Handler())

		if err := http.ListenAndServe(*prometheusAddress, nil); err != nil {
			log.Fatal().Err(err).Msg("Starting Prometheus listener failed")
		}
	}()

	log.Info().
		Str("port", *apiAddress).
		Msg("Serving api calls...")

	http.HandleFunc("/webhook/github", githubWebhookHandler)
	http.HandleFunc("/webhook/bitbucket", bitbucketWebhookHandler)
	http.HandleFunc("/liveness", livenessHandler)
	http.HandleFunc("/readiness", readinessHandler)

	if err := http.ListenAndServe(*apiAddress, nil); err != nil {
		log.Fatal().Err(err).Msg("Starting api listener failed")
	}
}

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

	// https://developer.github.com/webhooks/
	eventType := r.Header.Get("X-GitHub-Event")
	webhookTotal.With(prometheus.Labels{"event": eventType, "source": "github"}).Inc()

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Error().Err(err).Msg("Reading body from Github webhook failed")
		http.Error(w, "Reading body from Github webhook failed", 500)
		return
	}

	// unmarshal json body
	var b interface{}
	err = json.Unmarshal(body, &b)
	if err != nil {
		log.Error().Err(err).Str("body", string(body)).Msg("Deserializing body from Github webhook failed")
		http.Error(w, "Deserializing body from Github webhook failed", 500)
		return
	}

	log.Info().
		Str("method", r.Method).
		Str("url", r.URL.String()).
		Interface("headers", r.Header).
		Interface("body", b).
		Msgf("Received webhook event '%v' from GitHub...", eventType)

	switch eventType {
	case "push":
		handleGithubPush(body)
	default:
		log.Warn().Str("event", eventType).Msgf("Unsupported Github webhook event '%v'", eventType)
	}

	fmt.Fprintf(w, "Aye aye!")
}

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

	// https://confluence.atlassian.com/bitbucket/manage-webhooks-735643732.html

	eventType := r.Header.Get("X-Event-Key")
	webhookTotal.With(prometheus.Labels{"event": eventType, "source": "bitbucket"}).Inc()

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Error().Err(err).Msg("Reading body from Bitbucket webhook failed")
		http.Error(w, "Reading body from Bitbucket webhook failed", 500)
		return
	}

	// unmarshal json body
	var b interface{}
	err = json.Unmarshal(body, &b)
	if err != nil {
		log.Error().Err(err).Str("body", string(body)).Msg("Deserializing body from Bitbucket webhook failed")
		http.Error(w, "Deserializing body from Bitbucket webhook failed", 500)
		return
	}

	log.Info().
		Str("method", r.Method).
		Str("url", r.URL.String()).
		Interface("headers", r.Header).
		Interface("body", string(body)).
		Msgf("Received webhook event '%v' from Bitbucket", eventType)

	switch eventType {
	case "repo:push":
		handleBitbucketPush(body)
	default:
		log.Warn().Str("event", eventType).Msgf("Unsupported Bitbucket webhook event '%v'", eventType)
	}

	fmt.Fprintf(w, "Aye aye!")
}

// GithubPushEvent represents a Github webhook push event
type GithubPushEvent struct {
	After      string           `json:"after"`
	Commits    []GithubCommit   `json:"commits"`
	HeadCommit GithubCommit     `json:"head_commit"`
	Pusher     GithubPusher     `json:"pusher"`
	Repository GithubRepository `json:"repository"`
}

// GithubCommit represents a Github commit
type GithubCommit struct {
	Author  GithubAuthor `json:"author"`
	Message string       `json:"message"`
	ID      string       `json:"id"`
}

// GithubAuthor represents a Github author
type GithubAuthor struct {
	Email    string `json:"email"`
	Name     string `json:"name"`
	UserName string `json:"username"`
}

// GithubPusher represents a Github pusher
type GithubPusher struct {
	Email string `json:"email"`
	Name  string `json:"name"`
}

// GithubRepository represents a Github repository
type GithubRepository struct {
	GitURL   string `json:"git_url"`
	HTMLURL  string `json:"html_url"`
	Name     string `json:"name"`
	FullName string `json:"full_name"`
}

func handleGithubPush(body []byte) {

	// unmarshal json body
	var pushEvent GithubPushEvent
	err := json.Unmarshal(body, &pushEvent)
	if err != nil {
		log.Error().Err(err).Str("body", string(body)).Msg("Deserializing body to GithubPushEvent failed")
		return
	}

	log.Info().Interface("pushEvent", pushEvent).Msg("Deserialized GitHub push event")
}

func handleBitbucketPush(body []byte) {

}

func livenessHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "I'm alive!")
}

func readinessHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "I'm ready!")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net"
	"net/http"
	"strings"
	"net/url"
	"errors"
	"os"
	"io"
	"io/ioutil"
	"log"
)

const userAgent = "docker-multi-tenancy"

var (
	// ErrInvalidEndpoint is returned when the endpoint is not a valid HTTP URL.
	ErrInvalidEndpoint = errors.New("invalid endpoint")

	ErrConnectionRefused = errors.New("Connection refused")
)

type Client struct{
	endpoint            string
	endpointURL         *url.URL
	unixHTTPClient      *http.Client
	dialer              func(string, string) (net.Conn, error)
}

// Error represents failures in the API. It represents a failure from the API.
type Error struct {
	Status  int
	Message string
}

func (e *Error) Error() string {
	return fmt.Sprintf("API error (%d): %s", e.Status, e.Message)
}

var (
	localAddrString  = "localhost:9000"
	unixDockerSocket = "unix:///var/run/docker.sock"

)
func main(){

	fmt.Println("Starting multi-tenancy proxy")

	// Setup localListener (type net.Listener)
	localListener, err := net.Listen("tcp", localAddrString)

	if err != nil {
		log.Fatalf("net.Listen failed: %v", err)
	}

	for {
		// Setup localConn (type net.Conn)
		localConn, err := localListener.Accept()
		if err != nil {
			log.Fatalf("listen.Accept failed: %v", err)
		}
		go forward(localConn)
	}

}

func forward(localConn net.Conn) {
	c, err := newClient(unixDockerSocket)

	sockerCon, err := c.dialer("unix", c.endpointURL.Path)

	if err != nil {
		fmt.Println("Error dialing")
		os.Exit(-1)
	}

	// Copy localConn.Reader to sshConn.Writer
	go func() {
		_, err = io.Copy(sockerCon, localConn)
		if err != nil {
			log.Fatalf("io.Copy failed: %v", err)
		}
	}()

	// Copy sshConn.Reader to localConn.Writer
	go func() {
		_, err = io.Copy(localConn, sockerCon)
		if err != nil {
			log.Fatalf("io.Copy failed: %v", err)
		}
	}()
}

// NewVersionedClient returns a Client instance ready for communication with
// the given server endpoint
func newClient(endpoint string) (*Client, error) {
	u, err := url.Parse(endpoint)

	if err != nil {
		return nil, ErrInvalidEndpoint
	}

	d := net.Dialer{}
	dialFunc := func(network, addr string) (net.Conn, error) {
		return d.Dial("unix", u.Path)
	}
	unixHTTPClient := &http.Client{
		Transport: &http.Transport{
			Dial: dialFunc,
		},
	}

	return &Client{
		unixHTTPClient:      unixHTTPClient,
		endpoint:            endpoint,
		endpointURL:         u,
		dialer:				 dialFunc,
	}, nil
}

// getFakeUnixURL returns the URL needed to make an HTTP request over a UNIX
// domain socket to the given path.
func (c *Client) getFakeUnixURL(path string) string {
	u := *c.endpointURL // Copy.

	// Override URL so that net/http will not complain.
	u.Scheme = "http"
	u.Host = "unix.sock" // Doesn't matter what this is - it's not used.
	u.Path = ""

	urlStr := strings.TrimRight(u.String(), "/")

	return fmt.Sprintf("%s%s", urlStr, path)
}

func (c *Client) do(method, path string) (*http.Response, error) {
	var params io.Reader
	var u string

	httpClient := c.unixHTTPClient
	u = c.getFakeUnixURL(path)

	req, err := http.NewRequest(method, u, params)
	if err != nil {
		return nil, err
	}
	req.Header.Set("User-Agent", userAgent)

	if method == "POST" {
		req.Header.Set("Content-Type", "plain/text")
	}

	resp, err := httpClient.Do(req)
	if err != nil {
		if strings.Contains(err.Error(), "connection refused") {
			return nil, ErrConnectionRefused
		}
		return nil, err
	}

	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
		return nil, newError(resp)
	}
	return resp, nil
}

func newError(resp *http.Response) *Error {
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return &Error{Status: resp.StatusCode, Message: fmt.Sprintf("cannot read body, err: %v", err)}
	}
	return &Error{Status: resp.StatusCode, Message: string(data)}
}
<commit_msg>Introduce handlers to modify the request given a url match<commit_after>package main

import (
	"fmt"
	"net"
	"net/http"
	"strings"
	"net/url"
	"errors"
	"os"
	"io"
	"io/ioutil"
	"log"
)

const userAgent = "docker-multi-tenancy"

var (
	// ErrInvalidEndpoint is returned when the endpoint is not a valid HTTP URL.
	ErrInvalidEndpoint = errors.New("invalid endpoint")

	ErrConnectionRefused = errors.New("Connection refused")
)

type Client struct{
	endpoint            string
	endpointURL         *url.URL
	unixHTTPClient      *http.Client
	dialer              func(string, string) (net.Conn, error)
}

// Error represents failures in the API. It represents a failure from the API.
type Error struct {
	Status  int
	Message string
}

func (e *Error) Error() string {
	return fmt.Sprintf("API error (%d): %s", e.Status, e.Message)
}

var (
	localAddrString  = ":9000"
	unixDockerSocket = "unix:///var/run/docker.sock"

)

func dockerRequestHandler(transformers map[string]func(r *http.Request)) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("Recieved methos ", r.Method, " url", r.URL)
		c, err := newClient(unixDockerSocket)

		if err != nil {
			w.Write([]byte("Error"))
			return
		}

		for k, f := range transformers{
			fmt.Println("Applixing expresion ", k)
			f(r)
		}

		// TODO needs to accept POST content
		resp, err := c.do( r.Method,  r.URL.String())

		if err != nil {
			w.Write([]byte("Error"))
			return
		}

		defer resp.Body.Close()

		content, _ := ioutil.ReadAll(resp.Body)

		w.Write(content)
	}
	return http.HandlerFunc(fn)
}

func main(){

	fmt.Println("Starting multi-tenancy proxy")

	f := func(r *http.Request){
		fmt.Println("Modifiy somehow the request")
	}

	transformers := make(map[string]func(r *http.Request))

	transformers["*"] = f

	http.ListenAndServe(localAddrString, dockerRequestHandler(transformers))

}

func forward(localConn net.Conn) {
	c, err := newClient(unixDockerSocket)

	sockerCon, err := c.dialer("unix", c.endpointURL.Path)

	if err != nil {
		fmt.Println("Error dialing")
		os.Exit(-1)
	}

	// Copy localConn.Reader to sshConn.Writer
	go func() {
		_, err = io.Copy(sockerCon, localConn)
		if err != nil {
			log.Fatalf("io.Copy failed: %v", err)
		}
	}()

	// Copy sshConn.Reader to localConn.Writer
	go func() {
		_, err = io.Copy(localConn, sockerCon)
		if err != nil {
			log.Fatalf("io.Copy failed: %v", err)
		}
	}()
}

// NewVersionedClient returns a Client instance ready for communication with
// the given server endpoint
func newClient(endpoint string) (*Client, error) {
	u, err := url.Parse(endpoint)

	if err != nil {
		return nil, ErrInvalidEndpoint
	}

	d := net.Dialer{}
	dialFunc := func(network, addr string) (net.Conn, error) {
		return d.Dial("unix", u.Path)
	}
	unixHTTPClient := &http.Client{
		Transport: &http.Transport{
			Dial: dialFunc,
		},
	}

	return &Client{
		unixHTTPClient:      unixHTTPClient,
		endpoint:            endpoint,
		endpointURL:         u,
		dialer:				 dialFunc,
	}, nil
}

// getFakeUnixURL returns the URL needed to make an HTTP request over a UNIX
// domain socket to the given path.
func (c *Client) getFakeUnixURL(path string) string {
	u := *c.endpointURL // Copy.

	// Override URL so that net/http will not complain.
	u.Scheme = "http"
	u.Host = "unix.sock" // Doesn't matter what this is - it's not used.
	u.Path = ""

	urlStr := strings.TrimRight(u.String(), "/")

	return fmt.Sprintf("%s%s", urlStr, path)
}

func (c *Client) do(method, path string) (*http.Response, error) {
	var params io.Reader
	var u string

	httpClient := c.unixHTTPClient
	u = c.getFakeUnixURL(path)

	req, err := http.NewRequest(method, u, params)
	if err != nil {
		return nil, err
	}
	req.Header.Set("User-Agent", userAgent)

	if method == "POST" {
		req.Header.Set("Content-Type", "plain/text")
	}

	resp, err := httpClient.Do(req)
	if err != nil {
		if strings.Contains(err.Error(), "connection refused") {
			return nil, ErrConnectionRefused
		}
		return nil, err
	}

	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
		return nil, newError(resp)
	}
	return resp, nil
}

func newError(resp *http.Response) *Error {
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return &Error{Status: resp.StatusCode, Message: fmt.Sprintf("cannot read body, err: %v", err)}
	}
	return &Error{Status: resp.StatusCode, Message: string(data)}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"regexp"
	"strings"

	"github.com/phayes/checkstyle"
)

var (
	regexGithub    = regexp.MustCompile("^g")
	regexBitbucket = regexp.MustCompile("^b")
	regexGitURI    = regexp.MustCompile("((git|ssh|http(s)?)|(git@[\\w\\.]+))(:(//)?)([\\w\\.@\\:/\\-~]+)(\\.git)(/)?")
)

var (
	cstyle                                                   = checkstyle.New()
	homeEnv                                                  = os.Getenv("HOME")
	gopathEnv                                                = os.Getenv("GOPATH")
	scrutinizerProjectEnv                                    = os.Getenv("SCRUTINIZER_PROJECT")
	projectFull, projectDomain, projectOwner, projectProject string
)

func main() {
	// Set up environment variables
	if gopathEnv == "" {
		gopathEnv = homeEnv + "/go"
	}

	// Set up project
	if len(scrutinizerProjectEnv) == 0 {
		log.Fatal("Not running without scrutinizer environemnt. SCRUTINIZER_PROJECT environment variable not found")
	}

	projectFull = regexGithub.ReplaceAllString(scrutinizerProjectEnv, "github.com")
	projectFull = regexBitbucket.ReplaceAllString(projectFull, "bitbucket.com")

	projectParts := strings.Split(projectFull, "/")
	if len(projectParts) != 3 {
		log.Fatal("Malformed SCRUTINIZER_PROJECT environment variable.")
	}
	projectDomain = projectParts[0]
	projectOwner = projectParts[1]
	projectProject = projectParts[2]

	// Install all dependancies
	cmd := exec.Command("go", "get", "-t", "./...")
	_, err := cmd.Output()
	if err != nil {
		exitErr, ok := err.(*exec.ExitError)
		if ok && len(exitErr.Stderr) != 0 {
			log.Println(string(exitErr.Stderr))
		}
		log.Fatal("go get -t ./...", err)
	}

	// Run metalinter
	metalinter()

	// Run tests and coverage
	testAndCoverage()
}

func metalinter() {
	goMetaLinterCmd := gopathEnv + "/bin/gometalinter"

	// Install gometalinter -- no-op if already installed
	cmd := exec.Command("go", "get", "github.com/alecthomas/gometalinter")
	_, err := cmd.Output()
	if err != nil {
		exitErr, ok := err.(*exec.ExitError)
		if ok && len(exitErr.Stderr) != 0 {
			log.Println(string(exitErr.Stderr))
		}
		log.Fatal("go get github.com/alecthomas/gometalinter", err)
	}

	// Install all gometalinter dependancies -- no-op if already installed
	cmd = exec.Command(goMetaLinterCmd, "install")
	_, err = cmd.Output()
	if err != nil {
		exitErr, ok := err.(*exec.ExitError)
		if ok && len(exitErr.Stderr) != 0 {
			log.Println(string(exitErr.Stderr))
		}
		log.Fatal(goMetaLinterCmd, "install", err)
	}

	// Configure the metalinter
	if _, err := os.Stat("go-scrutinize.config"); os.IsNotExist(err) {
		cmd = exec.Command(goMetaLinterCmd, "--checkstyle")
	} else {
		cmd = exec.Command(goMetaLinterCmd, "--checkstyle", "--config=go-scrutinize.config")
	}

	// Run the metalinter
	out, err := cmd.Output()
	if err != nil {
		exitErr := err.(*exec.ExitError)
		if len(exitErr.Stderr) != 0 {
			log.Println(string(exitErr.Stderr))
		}
		log.Fatal(goMetaLinterCmd, "install", err)
	}

	// Write the output from the metalinter
	ioutil.WriteFile("checkstyle_report.xml", out, os.ModePerm)
}

func testAndCoverage() {
	goConvCmd := gopathEnv + "/bin/gocov"
	goConvXMLCmd := gopathEnv + "/bin/gocov-xml"

	// Install the coverage tools
	cmd := exec.Command("go", "get", "github.com/axw/gocov/...")
	err := cmd.Run()
	if err != nil {
		log.Fatal("go get github.com/axw/gocov/...", err)
	}

	cmd = exec.Command("go", "get", "github.com/AlekSi/gocov-xml")
	err = cmd.Run()
	if err != nil {
		log.Fatal("go get github.com/AlekSi/gocov-xml", err)
	}

	// Run tests with coverage
	cmd = exec.Command(goConvCmd, "test", "./...", "-race")
	gocovout, err := cmd.Output()
	if err != nil {
		exitErr := err.(*exec.ExitError)
		if len(exitErr.Stderr) != 0 {
			log.Fatal(string(exitErr.Stderr))
		}
	}

	// Convert to clover format
	cmd = exec.Command(goConvXMLCmd)
	cmd.Stdin = bytes.NewReader(gocovout)
	xmlout, err := cmd.Output()
	if err != nil {
		exitErr := err.(*exec.ExitError)
		if len(exitErr.Stderr) != 0 {
			log.Fatal(string(exitErr.Stderr))
		}
	}

	// Rewrite all filenames to use /home/scrutinizer/build paths
	coveragexml := strings.Replace(string(xmlout), gopathEnv+"/src/"+projectFull, "/home/scrutinizer/build", 0)

	// Write the output from the metalinter
	ioutil.WriteFile("coverage.xml", []byte(coveragexml), os.ModePerm)

}
<commit_msg>Adding better error reporting<commit_after>package main

import (
	"bytes"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"regexp"
	"strings"

	"github.com/phayes/checkstyle"
)

var (
	regexGithub    = regexp.MustCompile("^g")
	regexBitbucket = regexp.MustCompile("^b")
	regexGitURI    = regexp.MustCompile("((git|ssh|http(s)?)|(git@[\\w\\.]+))(:(//)?)([\\w\\.@\\:/\\-~]+)(\\.git)(/)?")
)

var (
	cstyle                                                   = checkstyle.New()
	homeEnv                                                  = os.Getenv("HOME")
	gopathEnv                                                = os.Getenv("GOPATH")
	scrutinizerProjectEnv                                    = os.Getenv("SCRUTINIZER_PROJECT")
	projectFull, projectDomain, projectOwner, projectProject string
)

func main() {
	// Set up environment variables
	if gopathEnv == "" {
		gopathEnv = homeEnv + "/go"
	}

	// Set up project
	if len(scrutinizerProjectEnv) == 0 {
		log.Fatal("Not running without scrutinizer environemnt. SCRUTINIZER_PROJECT environment variable not found")
	}

	projectFull = regexGithub.ReplaceAllString(scrutinizerProjectEnv, "github.com")
	projectFull = regexBitbucket.ReplaceAllString(projectFull, "bitbucket.com")

	projectParts := strings.Split(projectFull, "/")
	if len(projectParts) != 3 {
		log.Fatal("Malformed SCRUTINIZER_PROJECT environment variable.")
	}
	projectDomain = projectParts[0]
	projectOwner = projectParts[1]
	projectProject = projectParts[2]

	// Install all dependancies
	cmd := exec.Command("go", "get", "-t", "./...")
	_, err := cmd.Output()
	if err != nil {
		exitErr, ok := err.(*exec.ExitError)
		if ok && len(exitErr.Stderr) != 0 {
			log.Println(string(exitErr.Stderr))
		}
		log.Fatal("go get -t ./...", err)
	}

	// Run metalinter
	metalinter()

	// Run tests and coverage
	testAndCoverage()
}

func metalinter() {
	goMetaLinterCmd := gopathEnv + "/bin/gometalinter"

	// Install gometalinter -- no-op if already installed
	cmd := exec.Command("go", "get", "github.com/alecthomas/gometalinter")
	_, err := cmd.Output()
	if err != nil {
		exitErr, ok := err.(*exec.ExitError)
		if ok && len(exitErr.Stderr) != 0 {
			log.Println(string(exitErr.Stderr))
		}
		log.Fatal("go get github.com/alecthomas/gometalinter", err)
	}

	// Install all gometalinter dependancies -- no-op if already installed
	cmd = exec.Command(goMetaLinterCmd, "install")
	_, err = cmd.Output()
	if err != nil {
		exitErr, ok := err.(*exec.ExitError)
		if ok && len(exitErr.Stderr) != 0 {
			log.Println(string(exitErr.Stderr))
		}
		log.Fatal(goMetaLinterCmd, "install", err)
	}

	// Configure the metalinter
	if _, err := os.Stat("go-scrutinize.config"); os.IsNotExist(err) {
		cmd = exec.Command(goMetaLinterCmd, "--checkstyle")
	} else {
		cmd = exec.Command(goMetaLinterCmd, "--checkstyle", "--config=go-scrutinize.config")
	}

	// Run the metalinter
	out, err := cmd.Output()
	if err != nil {
		exitErr := err.(*exec.ExitError)
		if len(exitErr.Stderr) != 0 {
			log.Println(string(exitErr.Stderr))
		}
		log.Fatal(goMetaLinterCmd, "install", err)
	}

	// Write the output from the metalinter
	ioutil.WriteFile("checkstyle_report.xml", out, os.ModePerm)
}

func testAndCoverage() {
	goConvCmd := gopathEnv + "/bin/gocov"
	goConvXMLCmd := gopathEnv + "/bin/gocov-xml"

	// Install the coverage tools
	cmd := exec.Command("go", "get", "github.com/axw/gocov/...")
	_, err := cmd.Output()
	if err != nil {
		exitErr := err.(*exec.ExitError)
		if len(exitErr.Stderr) != 0 {
			log.Println(string(exitErr.Stderr))
		}
		log.Fatal("go", "get", "github.com/axw/gocov/...", err)
	}

	cmd = exec.Command("go", "get", "github.com/AlekSi/gocov-xml")
	_, err = cmd.Output()
	if err != nil {
		exitErr := err.(*exec.ExitError)
		if len(exitErr.Stderr) != 0 {
			log.Println(string(exitErr.Stderr))
		}
		log.Fatal("go", "get", "github.com/AlekSi/gocov-xml", err)
	}

	// Run tests with coverage
	cmd = exec.Command(goConvCmd, "test", "./...", "-race")
	gocovout, err := cmd.Output()
	if err != nil {
		exitErr := err.(*exec.ExitError)
		if len(exitErr.Stderr) != 0 {
			log.Println(string(exitErr.Stderr))
		}
		log.Fatal(goConvCmd, "test", "./...", "-race", err)
	}

	// Convert to clover format
	cmd = exec.Command(goConvXMLCmd)
	cmd.Stdin = bytes.NewReader(gocovout)
	xmlout, err := cmd.Output()
	if err != nil {
		exitErr := err.(*exec.ExitError)
		if len(exitErr.Stderr) != 0 {
			log.Println(string(exitErr.Stderr))
		}
		log.Fatal(goConvXMLCmd, err)
	}

	// Rewrite all filenames to use /home/scrutinizer/build paths
	coveragexml := strings.Replace(string(xmlout), gopathEnv+"/src/"+projectFull, "/home/scrutinizer/build", 0)

	// Write the output from the metalinter
	ioutil.WriteFile("coverage.xml", []byte(coveragexml), os.ModePerm)

}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/boltdb/bolt"
	"github.com/chzyer/readline"
)

var db *bolt.DB

type command struct {
	name string
	info *commandInfo
}

// commandInfo struct is stored as the value to commands
type commandInfo struct {
	time  time.Time
	count int
}

func (ci *commandInfo) String() string {
	// Store the time in RFC3339 format for easy parsing
	return fmt.Sprintf("%s%s%d", ci.time.Format(time.RFC3339), ",", ci.count)
}

func (ci *commandInfo) Update(ciString string) {
	info := strings.Split(ciString, ",")

	count, err := strconv.Atoi(info[1])
	if err != nil {
		count = 0
	}

	ci.time = time.Now()
	ci.count = count + 1
}

func (ci *commandInfo) NewFromString(ciString string) *commandInfo {
	info := strings.Split(ciString, ",")

	// Parse the time as RFC3339 format
	date, err := time.Parse(time.RFC3339, info[0])
	if err != nil {
		date = time.Now()
	}

	count, err := strconv.Atoi(info[1])
	if err != nil {
		count = 0
	}

	ci.time = date
	ci.count = count

	return ci
}

type byTime []*command

func (s byTime) Len() int {
	return len(s)
}

func (s byTime) Less(i, j int) bool {
	return s[i].info.time.After(s[j].info.time)
}

func (s byTime) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func main() {
	// Setup flags
	// statsPtr := flag.Bool("stats", false, "show stats and usage of `r`")
	// completePtr := flag.String("complete", "", "show all results for `r`")
	commandPtr := flag.Bool("command", false, "show last command selected from `r`")
	addPtr := flag.String("add", "", "show stats and usage of `r`")
	flag.Parse()

	// Setup bolt db
	usr, err := user.Current()
	if err != nil {
		log.Fatal(err)
	}
	boltPath := filepath.Join(usr.HomeDir, ".r.db")
	// It will be created if it doesn't exist.
	db, err = bolt.Open(boltPath, 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// Check if `results` flag is passed
	// if *completePtr != "" {
	// 	results := showResults(*completePtr)
	// 	for _, result := range results {
	// 		fmt.Println(result)
	// 	}
	// 	os.Exit(0)
	// }

	if *commandPtr {
		printLastCommand()
		os.Exit(0)
	}

	// Check if `add` flag is passed
	if *addPtr != "" {
		args := strings.Split(*addPtr, ":")
		err := add(args[0], args[1])
		if err != nil {
			log.Fatal(err)
		}

		os.Exit(0)
	}

	// reset last command to blank
	// set line as stored command
	err = db.Update(func(tx *bolt.Tx) error {
		b, err := tx.CreateBucketIfNotExists([]byte("command"))
		if err != nil {
			return err
		}

		err = b.Put([]byte("command"), []byte(""))
		if err != nil {
			return err
		}
		return nil
	})

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

	readLine()
}

// readLine used the readline library create a prompt to
// show the command history
func readLine() {
	// create completer from results
	results, err := results()
	if err != nil {
		log.Panic(err)
	}

	var pcItems []*readline.PrefixCompleter
	for _, result := range results {
		pcItems = append(pcItems, readline.PcItem(result.name))
	}
	var completer = readline.NewPrefixCompleter(pcItems...)

	rl, err := readline.NewEx(&readline.Config{
		Prompt:       "> ",
		AutoComplete: completer,
	})
	if err != nil {
		log.Panic(err)
	}
	defer rl.Close()

	for {
		line, err := rl.Readline()
		if err != nil { // io.EOF
			break
		}

		line = strings.TrimSpace(line)

		cmdNames := namesOfCmds(results)

		// Only execute if the command typed is in the list of results
		if !containsCmd(line, cmdNames) {
			fmt.Println("Command not found in `r` history.")
			os.Exit(0)
		}

		// The command was found and will be executed so add it to the DB to update
		wd, err := os.Getwd()
		if err != nil {
			fmt.Println("Error executing command.")
			os.Exit(1)
		}
		add(wd, line)

		// set line as stored command
		err = db.Update(func(tx *bolt.Tx) error {
			b, err := tx.CreateBucketIfNotExists([]byte("command"))
			if err != nil {
				return err
			}

			err = b.Put([]byte("command"), []byte(line))
			if err != nil {
				return err
			}
			return nil
		})

		if err != nil {
			fmt.Println("Error storing command.")
			os.Exit(1)
		}

		os.Exit(0)
	}
}

// printLastCommand is used with the --command flag
// it shows the last command selected from the readline prompt
func printLastCommand() {
	var val string
	db.Update(func(tx *bolt.Tx) error {
		b, err := tx.CreateBucketIfNotExists([]byte("command"))
		if err != nil {
			return err
		}

		val = string(b.Get([]byte("command")))
		return nil
	})

	fmt.Println(val)
}

// showResults reads the boltdb and returns the command history
// based on your current working directory
func results() ([]*command, error) {
	wd, err := os.Getwd()
	if err != nil {
		return nil, err
	}

	// results := []string{"git status", "git clone", "go install", "cd /Users/jesse/", "cd /Users/jesse/gocode/src/github.com/jesselucas", "ls -Glah"}
	var results []*command
	err = db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("DirectoryBucket"))
		pathBucket := b.Bucket([]byte(wd))
		return pathBucket.ForEach(func(k, v []byte) error {
			cmd := new(command)
			ci := new(commandInfo)
			cmd.name = string(k)
			cmd.info = ci.NewFromString(string(v))

			results = append(results, cmd)
			return nil
		})
	})

	if err != nil {
		return nil, err
	}

	// Sorty by last command first
	sort.Sort(byTime(results))
	// for _, cmd := range results {
	// 	fmt.Printf("%s: %s \n", cmd.name, cmd.info.time)
	// }

	return results, nil

	// filter
	// var filtered []string
	// for _, result := range results {
	// 	if strings.HasPrefix(result, input) {
	// 		filtered = append(filtered, result)
	// 	}
	// }
	//
	// return filtered

}

// add checks if command being passed is in the listCommands
// then stores the command and workding directory
func add(path string, promptCmd string) error {
	// get the first command in the promptCmd string
	cmd := strings.Split(promptCmd, " ")[0]

	commands, err := listCommands()
	if err != nil {
		return err
	}

	// check if the command is valid
	if !containsCmd(cmd, commands) {
		return nil
	}

	// Add command to db
	// fmt.Printf("adding. cmd: %s, path: %s \n", promptCmd, path)
	return db.Update(func(tx *bolt.Tx) error {
		directoryBucket, err := tx.CreateBucketIfNotExists([]byte("DirectoryBucket"))
		if err != nil {
			return err
		}

		pathBucket, err := directoryBucket.CreateBucketIfNotExists([]byte(path))
		if err != nil {
			return err
		}

		// Store path and command for contextual path sorting
		cmdBucket, err := tx.CreateBucketIfNotExists([]byte("CommandBucket"))
		if err != nil {
			return err
		}

		// Don't store if the command is r
		if cmd == "r" {
			return nil
		}

		// Create commandInfo struct
		ci := new(commandInfo)
		ci.time = time.Now()
		ci.count = 1

		// Check if there is a command info value already
		v := cmdBucket.Get([]byte(promptCmd))
		if v != nil {
			// There is a previous command info value
			// Let's update the count and time
			ci.Update(string(v))
		}

		err = cmdBucket.Put([]byte(promptCmd), []byte(ci.String()))
		if err != nil {
			return err
		}

		// Now let's do the same thing for the pathBucket
		v = pathBucket.Get([]byte(promptCmd))
		if v != nil {
			// There is a previous command info value
			// Let's update the count and time
			ci.Update(string(v))
		}

		err = pathBucket.Put([]byte(promptCmd), []byte(ci.String()))
		if err != nil {
			return err
		}

		return nil
	})
}

func namesOfCmds(cmds []*command) []string {
	var names []string
	for _, cmd := range cmds {
		names = append(names, cmd.name)
	}

	return names
}

// containsCmd checks if a command string is is in a slice of strings
func containsCmd(cmd string, commands []string) bool {
	for _, c := range commands {
		// check first command against list of commands
		if c == cmd {
			return true
		}
	}
	return false
}

// listCommands use $PATH to find directories
// Then reads each directory and looks for executables
func listCommands() ([]string, error) {
	// Split $PATH directories into slice
	paths := strings.Split(os.Getenv("PATH"), ":")
	var commands []string

	// created buffered error chan
	errc := make(chan error, 1)

	// sync go routines
	var wg sync.WaitGroup

	// find commands appends results to commands slice
	findCommands := func(p string) {
		defer wg.Done()

		files, err := ioutil.ReadDir(p)
		if err != nil {
			errc <- err // write err into error chan
			return
		}

		for _, f := range files {
			m := f.Mode()

			// Check if file is executable
			if m&0111 != 0 {
				commands = append(commands, f.Name())
			}
		}

		errc <- nil // write nil into error chan
	}

	// Check each path for commands
	for _, p := range paths {
		wg.Add(1)
		go findCommands(p)

		// read any error that is in error chan
		if err := <-errc; err != nil {
			return nil, err
		}
	}

	wg.Wait() // Wait for the paths to be checked

	return commands, nil
}

// stats TODO print stats and usage of r
func stats() {
	fmt.Println("stats")
}
<commit_msg>Pruning commands after one is added to the directory and global commands buckets<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/boltdb/bolt"
	"github.com/chzyer/readline"
)

var db *bolt.DB

type command struct {
	name string
	info *commandInfo
}

// commandInfo struct is stored as the value to commands
type commandInfo struct {
	time  time.Time
	count int
}

func (ci *commandInfo) String() string {
	// Store the time in RFC3339 format for easy parsing
	return fmt.Sprintf("%s%s%d", ci.time.Format(time.RFC3339), ",", ci.count)
}

func (ci *commandInfo) Update(ciString string) {
	info := strings.Split(ciString, ",")

	count, err := strconv.Atoi(info[1])
	if err != nil {
		count = 0
	}

	ci.time = time.Now()
	ci.count = count + 1
}

func (ci *commandInfo) NewFromString(ciString string) *commandInfo {
	info := strings.Split(ciString, ",")

	// Parse the time as RFC3339 format
	date, err := time.Parse(time.RFC3339, info[0])
	if err != nil {
		date = time.Now()
	}

	count, err := strconv.Atoi(info[1])
	if err != nil {
		count = 0
	}

	ci.time = date
	ci.count = count

	return ci
}

type byTime []*command

func (s byTime) Len() int {
	return len(s)
}

func (s byTime) Less(i, j int) bool {
	return s[i].info.time.After(s[j].info.time)
}

func (s byTime) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func main() {
	// Setup flags
	// statsPtr := flag.Bool("stats", false, "show stats and usage of `r`")
	// completePtr := flag.String("complete", "", "show all results for `r`")
	commandPtr := flag.Bool("command", false, "show last command selected from `r`")
	addPtr := flag.String("add", "", "show stats and usage of `r`")
	flag.Parse()

	// Setup bolt db
	usr, err := user.Current()
	if err != nil {
		log.Fatal(err)
	}
	boltPath := filepath.Join(usr.HomeDir, ".r.db")
	// It will be created if it doesn't exist.
	db, err = bolt.Open(boltPath, 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// Check if `results` flag is passed
	// if *completePtr != "" {
	// 	results := showResults(*completePtr)
	// 	for _, result := range results {
	// 		fmt.Println(result)
	// 	}
	// 	os.Exit(0)
	// }

	if *commandPtr {
		printLastCommand()
		os.Exit(0)
	}

	// Check if `add` flag is passed
	if *addPtr != "" {
		args := strings.Split(*addPtr, ":")
		err := add(args[0], args[1])
		if err != nil {
			log.Fatal(err)
		}

		os.Exit(0)
	}

	// reset last command to blank
	// set line as stored command
	err = db.Update(func(tx *bolt.Tx) error {
		b, err := tx.CreateBucketIfNotExists([]byte("command"))
		if err != nil {
			return err
		}

		err = b.Put([]byte("command"), []byte(""))
		if err != nil {
			return err
		}
		return nil
	})

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

	readLine()
}

// readLine used the readline library create a prompt to
// show the command history
func readLine() {
	// create completer from results
	wd, err := os.Getwd()
	if err != nil {
		log.Panic(err)
	}

	results, err := results(wd)
	if err != nil {
		log.Panic(err)
	}

	var pcItems []*readline.PrefixCompleter
	for _, result := range results {
		pcItems = append(pcItems, readline.PcItem(result.name))
	}
	var completer = readline.NewPrefixCompleter(pcItems...)

	rl, err := readline.NewEx(&readline.Config{
		Prompt:       "r> ",
		AutoComplete: completer,
	})
	if err != nil {
		log.Panic(err)
	}
	defer rl.Close()

	for {
		line, err := rl.Readline()
		if err != nil { // io.EOF
			break
		}

		line = strings.TrimSpace(line)

		cmdNames := namesOfCmds(results)

		// Only execute if the command typed is in the list of results
		if !containsCmd(line, cmdNames) {
			fmt.Println("Command not found in `r` history.")
			os.Exit(0)
		}

		// The command was found and will be executed so add it to the DB to update
		wd, err := os.Getwd()
		if err != nil {
			fmt.Println("Error executing command.")
			os.Exit(1)
		}
		add(wd, line)

		// set line as stored command
		err = db.Update(func(tx *bolt.Tx) error {
			b, err := tx.CreateBucketIfNotExists([]byte("command"))
			if err != nil {
				return err
			}

			err = b.Put([]byte("command"), []byte(line))
			if err != nil {
				return err
			}
			return nil
		})

		if err != nil {
			fmt.Println("Error storing command.")
			os.Exit(1)
		}

		os.Exit(0)
	}
}

// printLastCommand is used with the --command flag
// it shows the last command selected from the readline prompt
func printLastCommand() {
	var val string
	db.Update(func(tx *bolt.Tx) error {
		b, err := tx.CreateBucketIfNotExists([]byte("command"))
		if err != nil {
			return err
		}

		val = string(b.Get([]byte("command")))
		return nil
	})

	fmt.Println(val)
}

// showResults reads the boltdb and returns the command history
// based on your current working directory
func results(path string) ([]*command, error) {
	// dir := filepath.Dir(path)

	// results := []string{"git status", "git clone", "go install", "cd /Users/jesse/", "cd /Users/jesse/gocode/src/github.com/jesselucas", "ls -Glah"}
	var results []*command
	err := db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("DirectoryBucket"))
		pathBucket := b.Bucket([]byte(path))
		return pathBucket.ForEach(func(k, v []byte) error {
			cmd := new(command)
			ci := new(commandInfo)
			cmd.name = string(k)
			cmd.info = ci.NewFromString(string(v))

			results = append(results, cmd)
			return nil
		})
	})

	if err != nil {
		return nil, err
	}

	// Sorty by last command first
	sort.Sort(byTime(results))
	// for _, cmd := range results {
	// 	fmt.Printf("%s: %s \n", cmd.name, cmd.info.time)
	// }

	return results, nil

	// filter
	// var filtered []string
	// for _, result := range results {
	// 	if strings.HasPrefix(result, input) {
	// 		filtered = append(filtered, result)
	// 	}
	// }
	//
	// return filtered

}

func globalResults() ([]*command, error) {
	// Now get all the commands stored
	var results []*command
	err := db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("CommandBucket"))
		err := b.ForEach(func(k, v []byte) error {
			command := new(command)
			ci := new(commandInfo)
			command.name = string(k)
			command.info = ci.NewFromString(string(v))
			results = append(results, command)

			return nil
		})
		if err != nil {
			return err
		}

		return nil
	})

	if err != nil {
		return nil, err
	}

	// Sorty by last command first
	sort.Sort(byTime(results))
	// for _, cmd := range results {
	// 	fmt.Printf("%s: %s \n", cmd.name, cmd.info.time)
	// }

	return results, nil
}

// add checks if command being passed is in the listCommands
// then stores the command and workding directory
func add(path string, promptCmd string) error {
	// get the first command in the promptCmd string
	cmd := strings.Split(promptCmd, " ")[0]

	// Don't store if the command is r
	if cmd == "r" {
		return nil
	}

	commands, err := listCommands()
	if err != nil {
		return err
	}

	// check if the command is valid
	if !containsCmd(cmd, commands) {
		return nil
	}

	// Add command to db
	err = db.Update(func(tx *bolt.Tx) error {
		directoryBucket, err := tx.CreateBucketIfNotExists([]byte("DirectoryBucket"))
		if err != nil {
			return err
		}

		pathBucket, err := directoryBucket.CreateBucketIfNotExists([]byte(path))
		if err != nil {
			return err
		}

		// Store path and command for contextual path sorting
		cmdBucket, err := tx.CreateBucketIfNotExists([]byte("CommandBucket"))
		if err != nil {
			return err
		}

		// Create commandInfo struct
		ci := new(commandInfo)
		ci.time = time.Now()
		ci.count = 1

		// Check if there is a command info value already
		v := cmdBucket.Get([]byte(promptCmd))
		if v != nil {
			// There is a previous command info value
			// Let's update the count and time
			ci.Update(string(v))
		}

		err = cmdBucket.Put([]byte(promptCmd), []byte(ci.String()))
		if err != nil {
			return err
		}

		// Now let's do the same thing for the pathBucket
		v = pathBucket.Get([]byte(promptCmd))
		if v != nil {
			// There is a previous command info value
			// Let's update the count and time
			ci.Update(string(v))
		}

		err = pathBucket.Put([]byte(promptCmd), []byte(ci.String()))
		if err != nil {
			return err
		}

		return nil
	})

	if err != nil {
		return err
	}

	// now prune the older commands
	err = prune(path)
	if err != nil {
		return err
	}

	return nil
}

// prune deletes commands from a directory bucket and overall bucket
func prune(path string) error {
	// TODO move this to an environment variable
	numberToPruneDir := 20
	numberToPruneGlobal := 100
	pruneGlobal := true
	prunePath := true

	results, err := results(path)
	if err != nil {
		return err
	}

	if len(results) <= numberToPruneDir {
		prunePath = false
	}

	// List the global commands
	globalResults, err := globalResults()
	if err != nil {
		return err
	}

	// set pruneGlobal to true if there isn't enough
	if len(globalResults) <= numberToPruneGlobal {
		pruneGlobal = false
	}

	err = db.Update(func(tx *bolt.Tx) error {
		if prunePath {
			directoryBucket, err := tx.CreateBucketIfNotExists([]byte("DirectoryBucket"))
			if err != nil {
				return err
			}

			pathBucket, err := directoryBucket.CreateBucketIfNotExists([]byte(path))
			if err != nil {
				return err
			}

			pruneDirResults := results[numberToPruneDir:]
			for _, cmd := range pruneDirResults {
				pathBucket.Delete([]byte(cmd.name))
			}
		}
		// Prune stored global commands
		if pruneGlobal {
			// Store path and command for contextual path sorting
			cmdBucket, err := tx.CreateBucketIfNotExists([]byte("CommandBucket"))
			if err != nil {
				return err
			}

			pruneGlobalResults := globalResults[numberToPruneGlobal:]
			for _, cmd := range pruneGlobalResults {
				cmdBucket.Delete([]byte(cmd.name))
			}
		}

		return nil
	})

	if err != nil {
		return err
	}

	return nil
}

// namesOfCmds takes a slice of command structs and return
// a slice with just their names
func namesOfCmds(cmds []*command) []string {
	var names []string
	for _, cmd := range cmds {
		names = append(names, cmd.name)
	}

	return names
}

// containsCmd checks if a command string is is in a slice of strings
func containsCmd(cmd string, commands []string) bool {
	for _, c := range commands {
		// check first command against list of commands
		if c == cmd {
			return true
		}
	}
	return false
}

// listCommands use $PATH to find directories
// Then reads each directory and looks for executables
func listCommands() ([]string, error) {
	// Split $PATH directories into slice
	paths := strings.Split(os.Getenv("PATH"), ":")
	var commands []string

	// created buffered error chan
	errc := make(chan error, 1)

	// sync go routines
	var wg sync.WaitGroup

	// find commands appends results to commands slice
	findCommands := func(p string) {
		defer wg.Done()

		files, err := ioutil.ReadDir(p)
		if err != nil {
			errc <- err // write err into error chan
			return
		}

		for _, f := range files {
			m := f.Mode()

			// Check if file is executable
			if m&0111 != 0 {
				commands = append(commands, f.Name())
			}
		}

		errc <- nil // write nil into error chan
	}

	// Check each path for commands
	for _, p := range paths {
		wg.Add(1)
		go findCommands(p)

		// read any error that is in error chan
		if err := <-errc; err != nil {
			return nil, err
		}
	}

	wg.Wait() // Wait for the paths to be checked

	return commands, nil
}

// stats TODO print stats and usage of r
func stats() {
	fmt.Println("stats")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"runtime"
	"syscall"
	"time"

	sdees "github.com/schollz/gitsdees/src"
	"github.com/urfave/cli"
)

var (
	Version, BuildTime, Build   string
	Debug                       bool
	DontEncrypt, Clean          bool
	DeleteDocument, DeleteEntry string
	ResetConfig                 bool
	ImportOldFile, ImportFile   string
)

func main() {
	// Delete temp files upon exit
	defer sdees.CleanUp()

	// Handle Ctl+C for cleanUp
	// from http://stackoverflow.com/questions/11268943/golang-is-it-possible-to-capture-a-ctrlc-signal-and-run-a-cleanup-function-in
	c := make(chan os.Signal, 2)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		<-c
		sdees.CleanUp()
		os.Exit(1)
	}()

	// App information
	app := cli.NewApp()
	app.Name = "sdees"
	if len(Build) == 0 {
		Build = "dev"
		out, err := exec.Command("git", []string{"rev-parse", "HEAD"}...).Output()
		if err != nil {
			log.Fatal(err)
		}
		bString := string(out)
		Build = bString[0:7]
		Version = "dev"
		BuildTime = time.Now().String()
	} else {
		Build = Build[0:7]
	}
	app.Version = Version + " " + Build + " " + BuildTime
	app.Usage = `SDEES Does Editing, Encryption, and Synchronization

	 https://github.com/schollz/sdees

EXAMPLE USAGE:
   sdees new.txt # edit a new document, new.txt
   sdees --summary -n 5 # list a summary of last five entries
   sdees --search "dogs cats" # find entries that mention 'dogs' or 'cats'`

	app.Action = func(c *cli.Context) error {
		// Set the log level
		if Debug {
			sdees.DebugMode()
		}

		workingFile := c.Args().Get(0)
		if len(workingFile) > 0 {
			sdees.InputDocument = workingFile
		}

		// Check if its Windows
		if runtime.GOOS == "windows" {
			sdees.Extension = ".exe"
		} else {
			sdees.Extension = ""
		}

		sdees.Encrypt = !DontEncrypt

		// Load configuration
		sdees.LoadConfiguration()

		// Process some flags
		if ResetConfig {
			sdees.SetupConfig()
		} else if len(ImportOldFile) > 0 {
			fmt.Printf("Importing %s using deprecated import file\n", ImportOldFile)
			sdees.CurrentDocument = ImportOldFile
			sdees.ImportOld(ImportOldFile)
		} else if len(ImportFile) > 0 {
			fmt.Printf("Importing %s\n", ImportFile)
			sdees.CurrentDocument = ImportFile
			sdees.Import(ImportFile)
		} else if Clean {
			sdees.CleanAll()
		} else {
			sdees.Run()
		}
		return nil
	}
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:        "debug",
			Usage:       "Turn on debug mode",
			Destination: &Debug,
		},
		cli.BoolFlag{
			Name:        "clean",
			Usage:       "Deletes all gitsdees files",
			Destination: &Clean,
		},
		cli.StringFlag{
			Name:        "search",
			Usage:       "Search for `word`",
			Destination: &sdees.Search,
		},
		cli.StringFlag{
			Name:        "importold",
			Usage:       "Import `document` (JRNL-format)",
			Destination: &ImportOldFile,
		},
		cli.StringFlag{
			Name:        "import",
			Usage:       "Import `document`",
			Destination: &ImportFile,
		},
		cli.BoolFlag{
			Name:        "export",
			Usage:       "Export `document`",
			Destination: &sdees.Export,
		},
		cli.BoolFlag{
			Name:        "config",
			Usage:       "Configure",
			Destination: &ResetConfig,
		},
		cli.BoolFlag{
			Name:        "all, a",
			Usage:       "Edit all of the document",
			Destination: &sdees.All,
		},
		cli.StringFlag{
			Name:        "delete",
			Usage:       "Delete `entry`",
			Destination: &sdees.DeleteEntry,
		},
		cli.BoolFlag{
			Name:        "ddelete",
			Usage:       "Delete `document`",
			Destination: &sdees.DeleteDocument,
		},
		cli.BoolFlag{
			Name:        "plaintext",
			Usage:       "Turns off encryption",
			Destination: &DontEncrypt,
		},
		cli.BoolFlag{
			Name:        "summary",
			Usage:       "Gets summary",
			Destination: &sdees.Summarize,
		},
	}
	app.Run(os.Args)
}
<commit_msg>gitsdees -> sdees<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"runtime"
	"syscall"
	"time"

	sdees "github.com/schollz/sdees/src"
	"github.com/urfave/cli"
)

var (
	Version, BuildTime, Build   string
	Debug                       bool
	DontEncrypt, Clean          bool
	DeleteDocument, DeleteEntry string
	ResetConfig                 bool
	ImportOldFile, ImportFile   string
)

func main() {
	// Delete temp files upon exit
	defer sdees.CleanUp()

	// Handle Ctl+C for cleanUp
	// from http://stackoverflow.com/questions/11268943/golang-is-it-possible-to-capture-a-ctrlc-signal-and-run-a-cleanup-function-in
	c := make(chan os.Signal, 2)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		<-c
		sdees.CleanUp()
		os.Exit(1)
	}()

	// App information
	app := cli.NewApp()
	app.Name = "sdees"
	if len(Build) == 0 {
		Build = "dev"
		out, err := exec.Command("git", []string{"rev-parse", "HEAD"}...).Output()
		if err != nil {
			log.Fatal(err)
		}
		bString := string(out)
		Build = bString[0:7]
		Version = "dev"
		BuildTime = time.Now().String()
	} else {
		Build = Build[0:7]
	}
	app.Version = Version + " " + Build + " " + BuildTime
	app.Usage = `SDEES Does Editing, Encryption, and Synchronization

	 https://github.com/schollz/sdees

EXAMPLE USAGE:
   sdees new.txt # edit a new document, new.txt
   sdees --summary -n 5 # list a summary of last five entries
   sdees --search "dogs cats" # find entries that mention 'dogs' or 'cats'`

	app.Action = func(c *cli.Context) error {
		// Set the log level
		if Debug {
			sdees.DebugMode()
		}

		workingFile := c.Args().Get(0)
		if len(workingFile) > 0 {
			sdees.InputDocument = workingFile
		}

		// Check if its Windows
		if runtime.GOOS == "windows" {
			sdees.Extension = ".exe"
		} else {
			sdees.Extension = ""
		}

		sdees.Encrypt = !DontEncrypt

		// Load configuration
		sdees.LoadConfiguration()

		// Process some flags
		if ResetConfig {
			sdees.SetupConfig()
		} else if len(ImportOldFile) > 0 {
			fmt.Printf("Importing %s using deprecated import file\n", ImportOldFile)
			sdees.CurrentDocument = ImportOldFile
			sdees.ImportOld(ImportOldFile)
		} else if len(ImportFile) > 0 {
			fmt.Printf("Importing %s\n", ImportFile)
			sdees.CurrentDocument = ImportFile
			sdees.Import(ImportFile)
		} else if Clean {
			sdees.CleanAll()
		} else {
			sdees.Run()
		}
		return nil
	}
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:        "debug",
			Usage:       "Turn on debug mode",
			Destination: &Debug,
		},
		cli.BoolFlag{
			Name:        "clean",
			Usage:       "Deletes all sdees files",
			Destination: &Clean,
		},
		cli.StringFlag{
			Name:        "search",
			Usage:       "Search for `word`",
			Destination: &sdees.Search,
		},
		cli.StringFlag{
			Name:        "importold",
			Usage:       "Import `document` (JRNL-format)",
			Destination: &ImportOldFile,
		},
		cli.StringFlag{
			Name:        "import",
			Usage:       "Import `document`",
			Destination: &ImportFile,
		},
		cli.BoolFlag{
			Name:        "export",
			Usage:       "Export `document`",
			Destination: &sdees.Export,
		},
		cli.BoolFlag{
			Name:        "config",
			Usage:       "Configure",
			Destination: &ResetConfig,
		},
		cli.BoolFlag{
			Name:        "all, a",
			Usage:       "Edit all of the document",
			Destination: &sdees.All,
		},
		cli.StringFlag{
			Name:        "delete",
			Usage:       "Delete `entry`",
			Destination: &sdees.DeleteEntry,
		},
		cli.BoolFlag{
			Name:        "ddelete",
			Usage:       "Delete `document`",
			Destination: &sdees.DeleteDocument,
		},
		cli.BoolFlag{
			Name:        "plaintext",
			Usage:       "Turns off encryption",
			Destination: &DontEncrypt,
		},
		cli.BoolFlag{
			Name:        "summary",
			Usage:       "Gets summary",
			Destination: &sdees.Summarize,
		},
	}
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"sync"
	"time"

	"github.com/gorilla/websocket"
)

func main() {
	var (
		listen   = flag.String("listen", ":8080", "HTTP listen")
		interval = flag.Duration("interval", 1*time.Second, "broadcast interval")
	)
	flag.Parse()
	http.HandleFunc("/", handleSocket(newNumberStation(*interval)))
	log.Printf("listening on %s", *listen)
	log.Fatal(http.ListenAndServe(*listen, nil))
}

func handleSocket(s station) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "GET" {
			http.Error(w, "Method not allowed", 405)
			return
		}
		conn, err := websocket.Upgrade(w, r, nil, 1024, 1024)
		if _, ok := err.(websocket.HandshakeError); ok {
			http.Error(w, "Not a websocket handshake", 400)
			return
		} else if err != nil {
			log.Println(err)
			return
		}
		s.Subscribe(conn)
		wait(conn)
	}
}

type station interface {
	Subscribe(*websocket.Conn)
}

type numberStation struct {
	sync.RWMutex
	sub   chan *websocket.Conn
	unsub chan *websocket.Conn
}

func newNumberStation(interval time.Duration) *numberStation {
	s := &numberStation{
		sub:   make(chan *websocket.Conn),
		unsub: make(chan *websocket.Conn),
	}
	go s.loop(interval)
	return s
}

func (s *numberStation) loop(interval time.Duration) {
	m := map[*websocket.Conn]struct{}{}
	tick := time.Tick(interval)
	for {
		select {
		case <-tick:
			if len(m) <= 0 {
				continue
			}
			log.Printf("broadcasting to %d", len(m))
			number := rand.Intn(255)
			for conn := range m {
				go send(conn, number, s.unsub)
			}
		case conn := <-s.sub:
			log.Printf("%s: subscribed", conn.RemoteAddr())
			m[conn] = struct{}{}
		case conn := <-s.unsub:
			log.Printf("%s: unsubscribed", conn.RemoteAddr())
			delete(m, conn)
		}
	}
}

func (s *numberStation) Subscribe(conn *websocket.Conn) {
	s.sub <- conn
}

func send(conn *websocket.Conn, number int, unsub chan<- *websocket.Conn) {
	if err := conn.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf("%02x", number))); err != nil {
		log.Printf("%s: %s", conn.RemoteAddr(), err)
		unsub <- conn
	}
}

func wait(conn *websocket.Conn) {
	defer conn.Close()
	for {
		if _, _, err := conn.ReadMessage(); err != nil {
			break
		}
	}
}
<commit_msg>Remove unnecessary (old) sync.RWMutex<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"time"

	"github.com/gorilla/websocket"
)

func main() {
	var (
		listen   = flag.String("listen", ":8080", "HTTP listen")
		interval = flag.Duration("interval", 1*time.Second, "broadcast interval")
	)
	flag.Parse()
	http.HandleFunc("/", handleSocket(newNumberStation(*interval)))
	log.Printf("listening on %s", *listen)
	log.Fatal(http.ListenAndServe(*listen, nil))
}

func handleSocket(s station) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "GET" {
			http.Error(w, "Method not allowed", 405)
			return
		}
		conn, err := websocket.Upgrade(w, r, nil, 1024, 1024)
		if _, ok := err.(websocket.HandshakeError); ok {
			http.Error(w, "Not a websocket handshake", 400)
			return
		} else if err != nil {
			log.Println(err)
			return
		}
		s.Subscribe(conn)
		wait(conn)
	}
}

type station interface {
	Subscribe(*websocket.Conn)
}

type numberStation struct {
	sub   chan *websocket.Conn
	unsub chan *websocket.Conn
}

func newNumberStation(interval time.Duration) *numberStation {
	s := &numberStation{
		sub:   make(chan *websocket.Conn),
		unsub: make(chan *websocket.Conn),
	}
	go s.loop(interval)
	return s
}

func (s *numberStation) loop(interval time.Duration) {
	m := map[*websocket.Conn]struct{}{}
	tick := time.Tick(interval)
	for {
		select {
		case <-tick:
			if len(m) <= 0 {
				continue
			}
			log.Printf("broadcasting to %d", len(m))
			number := rand.Intn(255)
			for conn := range m {
				go send(conn, number, s.unsub)
			}
		case conn := <-s.sub:
			log.Printf("%s: subscribed", conn.RemoteAddr())
			m[conn] = struct{}{}
		case conn := <-s.unsub:
			log.Printf("%s: unsubscribed", conn.RemoteAddr())
			delete(m, conn)
		}
	}
}

func (s *numberStation) Subscribe(conn *websocket.Conn) {
	s.sub <- conn
}

func send(conn *websocket.Conn, number int, unsub chan<- *websocket.Conn) {
	if err := conn.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf("%02x", number))); err != nil {
		log.Printf("%s: %s", conn.RemoteAddr(), err)
		unsub <- conn
	}
}

func wait(conn *websocket.Conn) {
	defer conn.Close()
	for {
		if _, _, err := conn.ReadMessage(); err != nil {
			break
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/http"
	"net/url"
	"strings"

	"github.com/julienschmidt/httprouter"
)

func main() {
	router := httprouter.New()
	router.GET("/:size/*source", handleResize)
	log.Fatal(http.ListenAndServe(":8888", router))
}

func handleResize(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
	log.Printf(req.Method + " " + req.URL.Path)
	sourceURL, err := url.Parse(strings.TrimPrefix(params.ByName("source"), "/"))
	if err != nil || !(sourceURL.Scheme == "http" || sourceURL.Scheme == "https") {
		http.Error(w, "invalid source URL", 400)
		return
	}
	w.Write([]byte("ok\n"))
}
<commit_msg>basic fetching + resizing of images<commit_after>package main

import (
	"fmt"
	"image"
	"image/jpeg"
	"io"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	"github.com/julienschmidt/httprouter"
	"github.com/nfnt/resize"
)

func main() {
	router := httprouter.New()
	router.GET("/:size/*source", handleResize)
	log.Fatal(http.ListenAndServe(":8888", router))
}

func handleResize(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
	log.Printf(req.Method + " " + req.URL.Path)
	sourceURL, err := url.Parse(strings.TrimPrefix(params.ByName("source"), "/"))
	if err != nil || !(sourceURL.Scheme == "http" || sourceURL.Scheme == "https") {
		http.Error(w, "invalid source URL", 400)
		return
	}

	sizeParts := strings.Split(params.ByName("size"), "x")
	if len(sizeParts) != 2 {
		http.Error(w, "invalid width requested", 400)
		return
	}
	width, err := strconv.ParseUint(sizeParts[0], 10, 64)
	if err != nil {
		http.Error(w, "invalid width requested", 400)
		return
	}
	height, err := strconv.ParseUint(sizeParts[1], 10, 64)
	if err != nil {
		http.Error(w, "invalid height requested", 400)
		return
	}

	resp, err := http.Get(sourceURL.String())
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	if resp.StatusCode != 200 {
		copyHeader(w.Header(), resp.Header)
		io.Copy(w, resp.Body)
		return
	}

	contentType := resp.Header.Get("Content-Type")
	if !strings.HasPrefix(contentType, "image/") {
		http.Error(w, fmt.Sprintf("invalid content type %q", contentType), 500)
		return
	}

	img, _, err := image.Decode(resp.Body)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	imgResized := resize.Resize(uint(width), uint(height), img, resize.Bicubic)
	w.Header().Set("Content-Type", "image/jpeg")
	// TODO(bgentry) set other headers
	jpeg.Encode(w, imgResized, nil)
}

func copyHeader(dst, src http.Header) {
	for k, vv := range src {
		for _, v := range vv {
			dst.Add(k, v)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"fmt"
	"strconv"
	"Jira__backend/tools"
	"Jira__backend/router"
)

func main() {
	port, err := tools.GetPort("configs/server.json")

	if err != nil {
		panic("bad config: ")
	}

	router.NewRouter()

	fmt.Printf("Server started on port %d...\n", port)
	http.ListenAndServe(":" + strconv.Itoa(port), nil)
}
<commit_msg>add config<commit_after>package main

import (
	"net/http"
	"fmt"
	"strconv"
	"Jira__backend/tools"
	"Jira__backend/router"
)

func main() {
	port, err := tools.GetPort("configs/server.json")

	if err != nil {
		panic("bad config")
	}

	router.NewRouter()

	fmt.Printf("Server started on port %d...\n", port)
	http.ListenAndServe(":" + strconv.Itoa(port), nil)
}
<|endoftext|>