<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"time"
)

var colors = map[string]string{
	"header": "\033[95m",
	"blue":   "\033[94m",
	"green":  "\033[92m",
	"yellow": "\033[93m",
	"red":    "\033[91m",
	"bold":   "\033[1m",
	"end":    "\033[0m",
}

func color(color string, s string) string {
	return fmt.Sprintf("%s%s%s", colors[color], s, colors["end"])
}

var rexes = map[string]*regexp.Regexp{
	"pep8":      regexp.MustCompile(`\w+:(\d+):(\d+):\s(\w+)\s(.+)(?m)$`),
	"pylint":    regexp.MustCompile(`(?m)^(\w):\s+(\d+),\s*(\d+):\s(.+)$`),
	"blameName": regexp.MustCompile(`\(([\w\s]+)\d{4}`),
    "goBuild": regexp.MustCompile(`\w+:(\d+):\s(.+)(?m)$`),
}

var config = map[string]string{
	"workingDir": "",
}

type Environment struct {
	gitPath string
	gitName string
}

func (c *Environment) GitPath() string {
	if len(c.gitPath) == 0 {
		cmd := exec.Command("git", "rev-parse", "--show-toplevel")
		out, err := cmd.Output()
		if err != nil {
			log.Fatal("Failed to find git parent path.")
		}
		c.gitPath = strings.TrimSpace(string(out))
	}
	return c.gitPath
}

func (c *Environment) GitName() string {
	if len(c.gitName) == 0 {
		cmd := exec.Command("git", "config", "user.name")
		out, err := cmd.Output()
		if err != nil {
			c.gitName = "None"
		} else {
			c.gitName = strings.TrimSpace(string(out))
		}
	}
	return c.gitName
}

func (c Environment) CurrentGitBranch() string {
	cmd := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD")
	out, err := cmd.Output()
	if err != nil {
		log.Fatal("Failed to get git branch")
	}
	return strings.TrimSpace(string(out))
}

var env = Environment{}

type ModifiedTimes struct {
	times map[string]time.Time
}

func NewModifiedTimes() *ModifiedTimes {
	return &ModifiedTimes{times: make(map[string]time.Time, 9)}
}

func (m *ModifiedTimes) CheckTime(path string) bool {
	hasChanged := false

	fileInfo, err := os.Stat(path)
	if err != nil {
		log.Println("Couldn't access ", path, ". Skipping it.")
	} else {
		if fileInfo != nil {
			mt := fileInfo.ModTime()
			if storedTime, ok := m.times[path]; ok {
				if !storedTime.Equal(mt) {
					hasChanged = true
				}
			} else {
				hasChanged = true
			}
			if hasChanged {
				m.times[path] = mt
			}
		}
	}
	return hasChanged
}

func (m ModifiedTimes) MostRecent() string {
	var returnPath string
	var mostRecentTime time.Time
	for path, time := range m.times {
		if mostRecentTime.Before(time) {
			returnPath = path
			mostRecentTime = time
		}
	}
	return returnPath
}

type Wart struct {
	Reporter  string
	Line      int
	Column    int
	IssueCode string
	Message   string
}

func (w Wart) String() string {
	return fmt.Sprintf("%d: [%s %s] %s", w.Line, w.Reporter, w.IssueCode, w.Message)
}

type TargetFile struct {
	Path         string
	ContentLines []string
	BlameLines   []string
	Warts        map[int][]Wart
}

func (tf *TargetFile) Blame() {
	os.Chdir(config["workingDir"])
	cmd := exec.Command("git", "blame", tf.Path)
	results, err := cmd.Output()
	if err != nil {
		tf.BlameLines = make([]string, 0)
	} else {
    	tf.BlameLines = strings.Split(string(results), "\n")
    }
}

func NewWart(reporter string, line string, column string, issueCode string, message string) Wart {

	line64, err := strconv.ParseInt(line, 10, 0)
	if err != nil {
		log.Fatal("Failed parsing line number %s", line)
	}
	col64, err := strconv.ParseInt(column, 10, 0)
	if err != nil {
		log.Fatal("Failed parsing column number %s", column)
	}
	w := Wart{
		Reporter:  reporter,
		Line:      int(line64),
		Column:    int(col64),
		IssueCode: issueCode,
		Message:   message,
	}
	return w
}

func (tf TargetFile) ExtEquals(ext string) bool {
    return filepath.Ext(tf.Path) == ext
}

func (tf *TargetFile) AddWart(wart Wart) {
    if _, ok := tf.Warts[wart.Line]; !ok {
        tf.Warts[wart.Line] = make([]Wart, 0)
    }
    tf.Warts[wart.Line] = append(tf.Warts[wart.Line], wart)
}

func (tf *TargetFile) Pep8() {
	if filepath.Ext(tf.Path) != ".py" {
		return
	}
	cmd := exec.Command("pep8", tf.Path)
	results, _ := cmd.Output()
	parsed := rexes["pep8"].FindAllStringSubmatch(string(results), -1)
	for _, group := range parsed {
		wart := NewWart("PEP8", group[1], group[2], group[3], group[4])
        tf.AddWart(wart)
	}
}

func (tf *TargetFile) GoBuild() {
    if !tf.ExtEquals(".go") { return }
    os.Chdir(config["workingDir"])
    _, file := filepath.Split(tf.Path)
    cmd := exec.Command("go", "build", file)
    results, _ := cmd.CombinedOutput()
    parsed := rexes["goBuild"].FindAllStringSubmatch(string(results), -1)
    for _, group := range parsed {
        wart := NewWart("gobuild", group[1], "0", "-", group[2])
        tf.AddWart(wart)
    }
}

func (tf *TargetFile) PyLint() {
	if filepath.Ext(tf.Path) != ".py" {
		return
	}
	cmd := exec.Command("pylint", "--output-format=text", tf.Path)
	results, _ := cmd.Output()
	parsed := rexes["pylint"].FindAllStringSubmatch(string(results), -1)
    for _, group := range parsed {
        wart := NewWart("Pylint", group[2], group[3], group[1], group[4])
        tf.AddWart(wart)
    }
}

func (tf TargetFile) BlameName(line int) string {
    if len(tf.BlameLines) == 0 {
        return "-"
    }
	match := rexes["blameName"].FindStringSubmatch(tf.BlameLines[line - 1])
	return strings.TrimSpace(match[1])
}

func NewTargetFile(path string) *TargetFile {
	tf := TargetFile{
		Path:  path,
		Warts: make(map[int][]Wart),
	}
	bytes, err := ioutil.ReadFile(path)
	if err != nil {
		log.Fatal("Unable to read file ", path)
	}
	tf.ContentLines = strings.Split(string(bytes), "\n")
	tf.Blame()
	tf.Pep8()
    tf.PyLint()
    tf.GoBuild()
	return &tf
}

func getDirFiles(dir string) []string {
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		log.Fatal("Could not read directory", dir)
	}
	filepaths := make([]string, len(files))
	for i, fileInfo := range files {
		filepaths[i] = path.Join(dir, fileInfo.Name())
	}
	return filterFiles(filepaths)
}

func gitBranchFiles() []string {
	dirtyFilesCmd := exec.Command("git", "diff", "--name-only")
	dirtyFiles, err := dirtyFilesCmd.Output()
	if err != nil {
		log.Fatal("Failed to list dirty files")
	}

	branchFilesCmd := exec.Command("git", "diff", "--name-only", "master..HEAD")
	branchFiles, err := branchFilesCmd.Output()
	if err != nil {
		log.Print("branchFiles: ", branchFiles)
		log.Fatal("Failed to list branch files:", err)
	}

	allFiles := append(
		strings.Split(string(dirtyFiles), "\n"),
		strings.Split(string(branchFiles), "\n")...,
	)
	return filterFiles(allFiles)
}

func filterFiles(filepaths []string) []string {
	goodstuffs := make([]string, 0)
	for _, path := range filepaths {
		if len(path) > 0 {
			match, err := regexp.MatchString(".py|.go", filepath.Ext(path))
			if err != nil {
				log.Fatalf("Failed checking %s's extension", path)
			}
			if match == true {
				goodstuffs = append(goodstuffs, path)
			}
		}
	}
	return goodstuffs
}

func printWarts(targetFile *TargetFile) {
	fmt.Println(color("green", targetFile.Path))
	if len(targetFile.Warts) == 0 {
		fmt.Println(color("bold", "- All clean!"))
	}
	for line, warts := range targetFile.Warts {
		blameName := targetFile.BlameName(line)
		nameColor := "blue"
		if blameName == env.GitName() {
			nameColor = "yellow"
		}
		fmt.Printf(
			"%s: (%s) %s\n",
			color("bold", fmt.Sprintf("%d", line)),
			color(nameColor, blameName),
			strings.TrimSpace(targetFile.ContentLines[line-1]),
		)
		for _, wart := range warts {
			fmt.Printf(
				"    [%s %s] %s\n",
				wart.Reporter,
				wart.IssueCode,
				color("bold", wart.Message),
			)
		}
	}
}

func clear() {
	cmd := exec.Command("clear")
	cmd.Stdout = os.Stdout
	cmd.Run()
    fmt.Println(color("header", "--- LintBlame ---"))
}

func makeTargetFile(filepath string, c chan *TargetFile) {
	tf := NewTargetFile(filepath)
	c <- tf
}

func update(filepaths []string) {
	c := make(chan *TargetFile)
	for _, path := range filepaths {
		go makeTargetFile(path, c)
	}
	cleared := false
	for i := 0; i < len(filepaths); i++ {
		if !cleared {
			clear()
			cleared = true
		}
		tf := <-c
		printWarts(tf)
        fmt.Println("")
	}
}

func main() {
	var branch bool
	var dir string
	flag.BoolVar(&branch, "b", false, "Run against current branch")
	flag.StringVar(&dir, "d", "", "Run against a directory")
	flag.Parse()

	var filepaths []string
	if len(dir) > 0 {
        path, err := filepath.Abs(dir)
        if err != nil {
            log.Fatal("Unable to get absolute path of ", dir)
        }
		config["workingDir"] = path
		filepaths = getDirFiles(dir)
	} else if branch {
		config["workingDir"] = env.GitPath()
		filepaths = gitBranchFiles()
	}

	modTimes := NewModifiedTimes()

	for _, file := range filepaths {
		modTimes.CheckTime(file)
	}
	update(filepaths)
	for {
		runUpdate := false
		for _, file := range filepaths {
			if modTimes.CheckTime(file) {
				runUpdate = true
				break
			}
		}
		if runUpdate {
			update(filepaths)
		}

		time.Sleep(1 * time.Second)
	}
}
<commit_msg>Simplified command line args<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
    "time"
	"sort"
)

var colors = map[string]string{
	"header": "\033[95m",
	"blue":   "\033[94m",
	"green":  "\033[92m",
	"yellow": "\033[93m",
	"red":    "\033[91m",
	"bold":   "\033[1m",
	"end":    "\033[0m",
}

func color(color string, s string) string {
	return fmt.Sprintf("%s%s%s", colors[color], s, colors["end"])
}

var rexes = map[string]*regexp.Regexp{
	"pep8":      regexp.MustCompile(`\w+:(\d+):(\d+):\s(\w+)\s(.+)(?m)$`),
	"pylint":    regexp.MustCompile(`(?m)^(\w):\s+(\d+),\s*(\d+):\s(.+)$`),
	"blameName": regexp.MustCompile(`\(([\w\s]+)\d{4}`),
    "goBuild": regexp.MustCompile(`\w+:(\d+):\s(.+)(?m)$`),
}

var config = map[string]string{
	"workingDir": "",
}

type Environment struct {
	gitPath string
	gitName string
}

func (c *Environment) GitPath() string {
	if len(c.gitPath) == 0 {
		cmd := exec.Command("git", "rev-parse", "--show-toplevel")
		out, err := cmd.Output()
		if err != nil {
			log.Fatal("Failed to find git parent path.")
		}
		c.gitPath = strings.TrimSpace(string(out))
	}
	return c.gitPath
}

func (c *Environment) GitName() string {
	if len(c.gitName) == 0 {
		cmd := exec.Command("git", "config", "user.name")
		out, err := cmd.Output()
		if err != nil {
			c.gitName = "None"
		} else {
			c.gitName = strings.TrimSpace(string(out))
		}
	}
	return c.gitName
}

func (c Environment) CurrentGitBranch() string {
	cmd := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD")
	out, err := cmd.Output()
	if err != nil {
		log.Fatal("Failed to get git branch")
	}
	return strings.TrimSpace(string(out))
}

var env = Environment{}

type Times []*time.Time
func (s Times) Len() int { return len(s) }
func (s Times) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

type ByTime struct{ Times }
func (s ByTime) Less(i, j int) bool { return s.Times[i].Before(*s.Times[j]) }

type ModifiedTimes struct {
	timeMap map[string]time.Time
}

func (m *ModifiedTimes) CheckTime(path string) bool {
	hasChanged := false

	fileInfo, err := os.Stat(path)
	if err != nil {
		log.Println("Couldn't access ", path, ". Skipping it.")
	} else {
		if fileInfo != nil {
			mt := fileInfo.ModTime()
			if storedTime, ok := m.timeMap[path]; ok {
				if !storedTime.Equal(mt) {
					hasChanged = true
				}
			} else {
				hasChanged = true
			}
			if hasChanged {
				m.timeMap[path] = mt
			}
		}
	}
	return hasChanged
}

func (m ModifiedTimes) MostRecent() string {
	var returnPath string
	var mostRecentTime time.Time
	for path, time := range m.timeMap {
		if mostRecentTime.Before(time) {
			returnPath = path
			mostRecentTime = time
		}
	}
	return returnPath
}

func (m ModifiedTimes) PathsByModTime() []string {
    size := len(m.timeMap)
    times := make(Times, size)
    timesToPaths := make(map[time.Time]string, size)
    returnSlice := make([]string, size)
    i := 0
    for path, time_ := range m.timeMap {
        times[i] = &time_
        timesToPaths[time_] = path
        i += 1
    }
    sort.Sort(ByTime{times})

    for i, time_ := range times {
        log.Print("time_: ", time_)
        returnSlice[i] = timesToPaths[*time_]
    }
    return returnSlice
}

func NewModifiedTimes() *ModifiedTimes {
    return &ModifiedTimes{timeMap: make(map[string]time.Time, 9)}
}

type Wart struct {
	Reporter  string
	Line      int
	Column    int
	IssueCode string
	Message   string
}

func (w Wart) String() string {
	return fmt.Sprintf("%d: [%s %s] %s", w.Line, w.Reporter, w.IssueCode, w.Message)
}

type TargetFile struct {
	Path         string
	ContentLines []string
	BlameLines   []string
	Warts        map[int][]Wart
}

func (tf *TargetFile) Blame() {
	os.Chdir(config["workingDir"])
	cmd := exec.Command("git", "blame", tf.Path)
	results, err := cmd.Output()
	if err != nil {
		tf.BlameLines = make([]string, 0)
	} else {
    	tf.BlameLines = strings.Split(string(results), "\n")
    }
}

func NewWart(reporter string, line string, column string, issueCode string, message string) Wart {

	line64, err := strconv.ParseInt(line, 10, 0)
	if err != nil {
		log.Fatal("Failed parsing line number %s", line)
	}
	col64, err := strconv.ParseInt(column, 10, 0)
	if err != nil {
		log.Fatal("Failed parsing column number %s", column)
	}
	w := Wart{
		Reporter:  reporter,
		Line:      int(line64),
		Column:    int(col64),
		IssueCode: issueCode,
		Message:   message,
	}
	return w
}

func (tf TargetFile) ExtEquals(ext string) bool {
    return filepath.Ext(tf.Path) == ext
}

func (tf *TargetFile) AddWart(wart Wart) {
    if _, ok := tf.Warts[wart.Line]; !ok {
        tf.Warts[wart.Line] = make([]Wart, 0)
    }
    tf.Warts[wart.Line] = append(tf.Warts[wart.Line], wart)
}

func (tf *TargetFile) Pep8() {
	if filepath.Ext(tf.Path) != ".py" {
		return
	}
	cmd := exec.Command("pep8", tf.Path)
	results, _ := cmd.Output()
	parsed := rexes["pep8"].FindAllStringSubmatch(string(results), -1)
	for _, group := range parsed {
		wart := NewWart("PEP8", group[1], group[2], group[3], group[4])
        tf.AddWart(wart)
	}
}

func (tf *TargetFile) GoBuild() {
    if !tf.ExtEquals(".go") { return }
    os.Chdir(config["workingDir"])
    _, file := filepath.Split(tf.Path)
    cmd := exec.Command("go", "build", file)
    results, _ := cmd.CombinedOutput()
    parsed := rexes["goBuild"].FindAllStringSubmatch(string(results), -1)
    for _, group := range parsed {
        wart := NewWart("gobuild", group[1], "0", "-", group[2])
        tf.AddWart(wart)
    }
}

func (tf *TargetFile) PyLint() {
	if filepath.Ext(tf.Path) != ".py" {
		return
	}
	cmd := exec.Command("pylint", "--output-format=text", tf.Path)
	results, _ := cmd.Output()
	parsed := rexes["pylint"].FindAllStringSubmatch(string(results), -1)
    for _, group := range parsed {
        wart := NewWart("Pylint", group[2], group[3], group[1], group[4])
        tf.AddWart(wart)
    }
}

func (tf TargetFile) BlameName(line int) string {
    if len(tf.BlameLines) == 0 {
        return "-"
    }
	match := rexes["blameName"].FindStringSubmatch(tf.BlameLines[line - 1])
	return strings.TrimSpace(match[1])
}

func NewTargetFile(path string) *TargetFile {
	tf := TargetFile{
		Path:  path,
		Warts: make(map[int][]Wart),
	}
	bytes, err := ioutil.ReadFile(path)
	if err != nil {
		log.Fatal("Unable to read file ", path)
	}
	tf.ContentLines = strings.Split(string(bytes), "\n")
	tf.Blame()
	tf.Pep8()
    tf.PyLint()
    tf.GoBuild()
	return &tf
}

func getDirFiles(dirPath string) []string {
	files, err := ioutil.ReadDir(dirPath)
	if err != nil {
		log.Fatal("Could not read directory", dirPath)
	}
	filepaths := make([]string, len(files))
	for i, fileInfo := range files {
		filepaths[i] = path.Join(dirPath, fileInfo.Name())
	}
	return filterFiles(filepaths)
}

func gitBranchFiles() []string {
	dirtyFilesCmd := exec.Command("git", "diff", "--name-only")
	dirtyFiles, err := dirtyFilesCmd.Output()
	if err != nil {
		log.Fatal("Failed to list dirty files")
	}

	branchFilesCmd := exec.Command("git", "diff", "--name-only", "master..HEAD")
	branchFiles, err := branchFilesCmd.Output()
	if err != nil {
		log.Print("branchFiles: ", branchFiles)
		log.Fatal("Failed to list branch files:", err)
	}

	allFiles := append(
		strings.Split(string(dirtyFiles), "\n"),
		strings.Split(string(branchFiles), "\n")...,
	)
	return filterFiles(allFiles)
}

func filterFiles(filepaths []string) []string {
	goodstuffs := make([]string, 0)
	for _, filepath := range filepaths {
		if len(filepath) > 0 {
			match, err := regexp.MatchString(".py|.go", path.Ext(filepath))
			if err != nil {
				log.Fatalf("Failed checking %s's extension", filepath)
			}
            if match == true {
                if !strings.HasPrefix(filepath, "/") {
                    filepath = path.Join(config["workingDir"], filepath)
                }
				goodstuffs = append(goodstuffs, filepath)
			}
		}
	}
	return goodstuffs
}

func printWarts(targetFile *TargetFile) {
	fmt.Println(color("green", targetFile.Path))
	if len(targetFile.Warts) == 0 {
		fmt.Println(color("bold", "- All clean!"))
	}
	for line, warts := range targetFile.Warts {
		blameName := targetFile.BlameName(line)
		nameColor := "blue"
		if blameName == env.GitName() {
			nameColor = "yellow"
		}
		fmt.Printf(
			"%s: (%s) %s\n",
			color("bold", fmt.Sprintf("%d", line)),
			color(nameColor, blameName),
			strings.TrimSpace(targetFile.ContentLines[line-1]),
		)
		for _, wart := range warts {
			fmt.Printf(
				"    [%s %s] %s\n",
				wart.Reporter,
				wart.IssueCode,
				color("bold", wart.Message),
			)
		}
	}
}

func clear() {
	cmd := exec.Command("clear")
	cmd.Stdout = os.Stdout
	cmd.Run()
    fmt.Println(color("header", "--- LintBlame ---"))
}

func makeTargetFile(filepath string, c chan *TargetFile) {
	tf := NewTargetFile(filepath)
	c <- tf
}

func update(filepaths []string) {
	c := make(chan *TargetFile)
	for _, path := range filepaths {
		go makeTargetFile(path, c)
	}
	cleared := false
	for i := 0; i < len(filepaths); i++ {
		if !cleared {
			clear()
			cleared = true
		}
		tf := <-c
		printWarts(tf)
        fmt.Println("")
	}
}

func initialPaths() []string {
    var branch bool
    flag.BoolVar(&branch, "b", false, "Run against current branch")
    flag.Parse()

    var filepaths []string
    if branch {
        config["workingDir"] = env.GitPath()
        filepaths = gitBranchFiles()
    } else {
        args := flag.Args()
        if len(args) > 0 {
            target := args[0]
            stat, err := os.Stat(target)
            if err != nil {
                log.Fatal("Unable to process argument: ", target)
            }
            absPath, err := filepath.Abs(target)
            if err != nil {
                log.Fatal("Unable to get absolute path of ", target)
            }
            if stat.IsDir() {
                config["workingDir"] = absPath
                filepaths = getDirFiles(absPath)
            } else {
                dir, _ := filepath.Split(absPath)
                config["workingDir"] = dir
                filepaths = filterFiles([]string{absPath})
            }
        }
    }
    return filepaths
}

func main() {
    filepaths := initialPaths()
	modTimes := NewModifiedTimes()

	for _, file := range filepaths {
		modTimes.CheckTime(file)
	}
	update(modTimes.PathsByModTime())
	for {
		runUpdate := false
		for _, file := range filepaths {
			if modTimes.CheckTime(file) {
				runUpdate = true
				break
			}
		}
		if runUpdate {
			update(modTimes.PathsByModTime())
		}
		time.Sleep(1 * time.Second)
	}
}
<|endoftext|>


<commit_before>package controllers

import (
	"crypto/tls"
	"crypto/x509"
	"io/ioutil"
	"net/url"
	"os"

	"github.com/go-libs/quest"
)

type DockerOptions struct {
	Url             *url.URL
	CertPath        string
	TLSClientConfig *tls.Config
}

const UNIX_SOCKET = "unix:///var/run/docker.sock"

var dockerOptions = &DockerOptions{}

func NewRequest(method quest.Method, endpoint string) (q *quest.Requester, err error) {
	q, err = quest.Request(method, dockerOptions.Url.String()+endpoint)
	if err != nil {
		return
	}
	q.TLSConfig(dockerOptions.TLSClientConfig)
	return
}

func NewContainers() *ContainersController {
	return &ContainersController{}
}

func NewImages() *ImagesController {
	return &ImagesController{}
}

func NewApps() *AppsController {
	return &AppsController{}
}

func GetTLSConfig(path string, insecure bool) (t *tls.Config, err error) {
	certPool := x509.NewCertPool()
	if !insecure {
		var file []byte
		file, err = ioutil.ReadFile(path + "/ca.pem")
		if err != nil {
			return
		}
		certPool.AppendCertsFromPEM(file)
	}
	cert, err := tls.LoadX509KeyPair(path+"/cert.pem", path+"/key.pem")
	if err != nil {
		return
	}
	t = &tls.Config{
		RootCAs:            certPool,
		Certificates:       []tls.Certificate{cert},
		InsecureSkipVerify: insecure,
	}
	return
}

func init() {
	host := os.Getenv("DOCKER_HOST")
	certPath := os.Getenv("DOCKER_CERT_PATH")
	tlsVerify := os.Getenv("DOCKER_TLS_VERIFY")

	if host == "" {
		host = UNIX_SOCKET
	}

	u, err := url.Parse(host)
	if err == nil {
		dockerOptions.Url = u
		if u.Scheme == "tcp" {
			u.Scheme = "http"
		}
		if certPath != "" {
			u.Scheme = "https"
			dockerOptions.CertPath = certPath
			TLSClientConfig, _ := GetTLSConfig(certPath, tlsVerify == "1")
			if TLSClientConfig != nil {
				dockerOptions.TLSClientConfig = TLSClientConfig
			}
		}
	}
}
<commit_msg>improve tls insecure<commit_after>package controllers

import (
	"crypto/tls"
	"crypto/x509"
	"io/ioutil"
	"net/url"
	"os"

	"github.com/go-libs/quest"
)

type DockerOptions struct {
	Url             *url.URL
	CertPath        string
	TLSClientConfig *tls.Config
}

const UNIX_SOCKET = "unix:///var/run/docker.sock"

var dockerOptions = &DockerOptions{}

func NewRequest(method quest.Method, endpoint string) (q *quest.Requester, err error) {
	q, err = quest.Request(method, dockerOptions.Url.String()+endpoint)
	if err != nil {
		return
	}
	q.TLSConfig(dockerOptions.TLSClientConfig)
	return
}

func NewContainers() *ContainersController {
	return &ContainersController{}
}

func NewImages() *ImagesController {
	return &ImagesController{}
}

func NewApps() *AppsController {
	return &AppsController{}
}

func GetTLSConfig(path string, insecure bool) (t *tls.Config, err error) {
	t = &tls.Config{}
	if !insecure {
		var file []byte
		file, err = ioutil.ReadFile(path + "/ca.pem")
		if err != nil {
			return
		}
		certPool := x509.NewCertPool()
		certPool.AppendCertsFromPEM(file)
		t.RootCAs = certPool
	}
	cert, err := tls.LoadX509KeyPair(path+"/cert.pem", path+"/key.pem")
	if err != nil {
		return
	}
	t.Certificates = []tls.Certificate{cert}
	t.InsecureSkipVerify = insecure
	return
}

func init() {
	host := os.Getenv("DOCKER_HOST")
	certPath := os.Getenv("DOCKER_CERT_PATH")
	tlsVerify := os.Getenv("DOCKER_TLS_VERIFY")

	if host == "" {
		host = UNIX_SOCKET
	}

	u, err := url.Parse(host)
	if err == nil {
		dockerOptions.Url = u
		if u.Scheme == "tcp" {
			u.Scheme = "http"
		}
		if certPath != "" {
			u.Scheme = "https"
			dockerOptions.CertPath = certPath
			if TLSClientConfig, err := GetTLSConfig(certPath, tlsVerify == "1"); err == nil {
				dockerOptions.TLSClientConfig = TLSClientConfig
			}
		}
	}
}
<|endoftext|>


<commit_before>package middleware

import (
	"fmt"
	. "github.com/mickael-kerjean/filestash/server/common"
	"net/http"
	"path/filepath"
)

func ApiHeaders(fn func(App, http.ResponseWriter, *http.Request)) func(ctx App, res http.ResponseWriter, req *http.Request) {
	return func(ctx App, res http.ResponseWriter, req *http.Request) {
		header := res.Header()
		header.Set("Content-Type", "application/json")
		header.Set("Cache-Control", "no-cache")
		fn(ctx, res, req)
	}
}

func SecureAjax(fn func(App, http.ResponseWriter, *http.Request)) func(ctx App, res http.ResponseWriter, req *http.Request) {
	return func(ctx App, res http.ResponseWriter, req *http.Request) {
		if req.Header.Get("X-Requested-With") != "XmlHttpRequest" {
			Log.Warning("Intrusion detection: %s - %s", req.RemoteAddr, req.URL.String())
			SendErrorResult(res, ErrNotAllowed)
			return
		}
		fn(ctx, res, req)
	}
}

func StaticHeaders(fn func(App, http.ResponseWriter, *http.Request)) func(ctx App, res http.ResponseWriter, req *http.Request) {
	return func(ctx App, res http.ResponseWriter, req *http.Request) {
		header := res.Header()
		header.Set("Content-Type", GetMimeType(filepath.Ext(req.URL.Path)))
		header.Set("Cache-Control", "max-age=2592000")
		fn(ctx, res, req)
	}
}

func IndexHeaders(fn func(App, http.ResponseWriter, *http.Request)) func(ctx App, res http.ResponseWriter, req *http.Request) {
	return func(ctx App, res http.ResponseWriter, req *http.Request) {
		header := res.Header()
		header.Set("Content-Type", "text/html")
		header.Set("Cache-Control", "no-cache")
		header.Set("Referrer-Policy", "same-origin")
		header.Set("X-Powered-By", fmt.Sprintf("Filestash/%s <https://filestash.app>", APP_VERSION + "." + BUILD_NUMBER))
		fn(ctx, res, req)
	}
}

func SecureHeaders(fn func(App, http.ResponseWriter, *http.Request)) func(ctx App, res http.ResponseWriter, req *http.Request) {
	return func(ctx App, res http.ResponseWriter, req *http.Request) {
		if host := Config.Get("general.host").String(); host != "" {
			if req.Host != host && req.Host != fmt.Sprintf("%s:443", host) {
				Log.Error("Invalid access from host: %s", req.Host)
				SendErrorResult(res, ErrNotAllowed)
				return
			}
		}
		header := res.Header()
		if Config.Get("general.force_ssl").Bool() {
			header.Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload")
		}
		header.Set("X-Content-Type-Options", "nosniff")
		header.Set("X-XSS-Protection", "1; mode=block")
		header.Set("X-Frame-Options", "DENY")
		fn(ctx, res, req)
	}
}
<commit_msg>improve (http): Mozilla observatory tips<commit_after>package middleware

import (
	"fmt"
	. "github.com/mickael-kerjean/filestash/server/common"
	"net/http"
	"path/filepath"
)

func ApiHeaders(fn func(App, http.ResponseWriter, *http.Request)) func(ctx App, res http.ResponseWriter, req *http.Request) {
	return func(ctx App, res http.ResponseWriter, req *http.Request) {
		header := res.Header()
		header.Set("Content-Type", "application/json")
		header.Set("Cache-Control", "no-cache")
		fn(ctx, res, req)
	}
}

func SecureAjax(fn func(App, http.ResponseWriter, *http.Request)) func(ctx App, res http.ResponseWriter, req *http.Request) {
	return func(ctx App, res http.ResponseWriter, req *http.Request) {
		if req.Header.Get("X-Requested-With") != "XmlHttpRequest" {
			Log.Warning("Intrusion detection: %s - %s", req.RemoteAddr, req.URL.String())
			SendErrorResult(res, ErrNotAllowed)
			return
		}
		fn(ctx, res, req)
	}
}

func StaticHeaders(fn func(App, http.ResponseWriter, *http.Request)) func(ctx App, res http.ResponseWriter, req *http.Request) {
	return func(ctx App, res http.ResponseWriter, req *http.Request) {
		header := res.Header()
		header.Set("Content-Type", GetMimeType(filepath.Ext(req.URL.Path)))
		header.Set("Cache-Control", "max-age=2592000")
		fn(ctx, res, req)
	}
}

func IndexHeaders(fn func(App, http.ResponseWriter, *http.Request)) func(ctx App, res http.ResponseWriter, req *http.Request) {
	return func(ctx App, res http.ResponseWriter, req *http.Request) {
		header := res.Header()
		header.Set("Content-Type", "text/html")
		header.Set("Cache-Control", "no-cache")
		header.Set("Referrer-Policy", "same-origin")
		header.Set("X-Content-Type-Options", "nosniff")
		header.Set("X-XSS-Protection", "1; mode=block")
		header.Set("X-Frame-Options", "DENY")
		header.Set("X-Powered-By", fmt.Sprintf("Filestash/%s <https://filestash.app>", APP_VERSION + "." + BUILD_NUMBER))
		fn(ctx, res, req)
	}
}

func SecureHeaders(fn func(App, http.ResponseWriter, *http.Request)) func(ctx App, res http.ResponseWriter, req *http.Request) {
	return func(ctx App, res http.ResponseWriter, req *http.Request) {
		if host := Config.Get("general.host").String(); host != "" {
			if req.Host != host && req.Host != fmt.Sprintf("%s:443", host) {
				Log.Error("Invalid access from host: %s", req.Host)
				SendErrorResult(res, ErrNotAllowed)
				return
			}
		}
		header := res.Header()
		if Config.Get("general.force_ssl").Bool() {
			header.Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload")
		}
		header.Set("X-Content-Type-Options", "nosniff")
		header.Set("X-XSS-Protection", "1; mode=block")
		header.Set("X-Frame-Options", "DENY")
		fn(ctx, res, req)
	}
}
<|endoftext|>


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

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file runs lisp based tests.

package golisp

import (
	. "gopkg.in/check.v1"
	"path/filepath"
	"time"
)

type LispSuite struct {
}

var _ = Suite(&LispSuite{})

func (s *LispSuite) TestLisp(c *C) {
	files, err := filepath.Glob("tests/*.lsp")
	if err != nil {
		c.Fail()
	}
	VerboseTests = false
	startTime := time.Now()
	for _, f := range files {
		c.Logf("Loading %s\n", f)
		_, err := ProcessFile(f)
		if err != nil {
			c.Logf("Error: %s\n", err)
		}
	}
	PrintTestResults(time.Since(startTime))
}
<commit_msg>Fix for new lisp test runner<commit_after>// Copyright 2014 SteelSeries ApS.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file runs lisp based tests.

package golisp

import (
	. "gopkg.in/check.v1"
)

type LispSuite struct {
}

var _ = Suite(&LispSuite{})

func (s *LispSuite) TestLisp(c *C) {
	testCommand := "(run-all-tests \"tests\")"
	ProcessFile("testing.lsp")
	ParseAndEval(testCommand)
}
<|endoftext|>


<commit_before>package storage

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/user"
	"regexp"
	"strings"
	"sync"
	"time"

	"github.com/satori/go.uuid"

	"code.tobolaski.com/brendan/ejrnl"
	"code.tobolaski.com/brendan/ejrnl/crypto"
)

type Driver struct {
	directory string
	key       []byte
	indexLock *sync.RWMutex
}

// NewDriver creates a new storage driver from the specified config and password.
func NewDriver(conf ejrnl.Config, password string) (*Driver, error) {
	salt, err := base64.StdEncoding.DecodeString(conf.Salt)
	if err != nil {
		return &Driver{}, fmt.Errorf("Failed to decode salt because %s", err)
	}

	key, err := crypto.GenerateKey([]byte(password), salt, conf.Pow)
	if err != nil {
		return &Driver{}, err
	}

	driver := &Driver{
		directory: conf.StorageDirectory,
		key:       key,
		indexLock: &sync.RWMutex{},
	}

	err = driver.checkExists()
	if err != nil {
		return driver, err
	}

	return driver, nil
}

// checkExists checks whether the journal already exists
func (d *Driver) checkExists() error {
	current, err := user.Current()
	if err != nil {
		return fmt.Errorf("Can't retrieve the current user's information because %s", err)
	}

	path := strings.Replace(d.directory, "~", current.HomeDir, -1)
	d.directory = path

	if _, err := os.Stat(fmt.Sprintf("%s/index.cpt", path)); os.IsNotExist(err) {
		return &NeedsInit{msg: "the index doesn't exist"}
	}

	return nil
}

func (d *Driver) Write(entry ejrnl.Entry) error {
	if entry.Date == nil {
		now := time.Now()
		entry.Date = &now
	}
	if entry.Id == "" {
		entry.Id = fmt.Sprintf("%s", uuid.NewV4())
	}
	plaintext, err := json.Marshal(entry)
	if err != nil {
		return err
	}
	cyphertext, err := crypto.Encrypt(plaintext, d.key)
	if err != nil {
		return err
	}

	var previousDate time.Time

	if _, err = os.Stat(fmt.Sprintf("%s/%s.cpt", d.directory, entry.Id)); err == nil {
		old, err := d.Read(entry.Id)
		if err != nil {
			log.Printf("Failed to read previous entry because %s", err)
		} else {
			previousDate = *old.Date
		}
	}

	err = ioutil.WriteFile(fmt.Sprintf("%s/%s.cpt", d.directory, entry.Id), cyphertext, 0600)
	if err != nil {
		return err
	}

	d.indexLock.Lock()
	defer d.indexLock.Unlock()
	index, err := d.readIndex()
	if err != nil {
		return err
	}
	delete(index, previousDate)
	index[*entry.Date] = entry.Id
	err = d.writeIndex(index)
	return err
}

func (d *Driver) Read(id string) (ejrnl.Entry, error) {
	bytes, err := ioutil.ReadFile(fmt.Sprintf("%s/%s.cpt", d.directory, id))
	if err != nil {
		return ejrnl.Entry{}, err
	}

	plaintext, err := crypto.Decrypt(bytes, d.key)
	if err != nil {
		return ejrnl.Entry{}, err
	}

	entry := &ejrnl.Entry{}
	err = json.Unmarshal(plaintext, entry)
	return *entry, err
}

// List returns the index of all the entries stored in the journal
func (d *Driver) List() (map[time.Time]string, error) {
	d.indexLock.RLock()
	defer d.indexLock.RUnlock()
	return d.readIndex()
}

// readIndex reads the index from the disk. The caller must have at least a read lock on d.indexLock
func (d *Driver) readIndex() (map[time.Time]string, error) {
	index := make(map[time.Time]string)
	cyphertext, err := ioutil.ReadFile(fmt.Sprintf("%s/index.cpt", d.directory))
	if err != nil {
		return index, err
	}

	plaintext, err := crypto.Decrypt(cyphertext, d.key)
	if err != nil {
		return index, err
	}

	p := &index
	err = json.Unmarshal(plaintext, p)
	return *p, err
}

// writeIndex writes an updated index file. Note that the caller must have the a lock on d.indexLock
func (d *Driver) writeIndex(index map[time.Time]string) error {
	plaintext, err := json.Marshal(index)
	if err != nil {
		return err
	}

	cyphertext, err := crypto.Encrypt(plaintext, d.key)
	if err != nil {
		return err
	}

	err = ioutil.WriteFile(fmt.Sprintf("%s/index.cpt", d.directory), cyphertext, 0600)
	return err
}

// Init creates the new journal
func (d *Driver) Init() error {
	d.indexLock.Lock()
	defer d.indexLock.Unlock()
	if _, err := os.Stat(d.directory); os.IsNotExist(err) {
		os.MkdirAll(d.directory, 0700)
	}

	files, err := ioutil.ReadDir(d.directory)
	if err != nil {
		return fmt.Errorf("Failed to read directory for journal because %s")
	}
	previousEntries := []os.FileInfo{}
	for _, file := range files {
		if match, _ := regexp.MatchString("\\.cpt$", file.Name()); match {
			previousEntries = append(previousEntries, file)
		}
	}

	emptyIndex := make(map[time.Time]string)

	if len(previousEntries) > 0 {
		entryReader := make(chan *ejrnl.Entry, len(previousEntries))
		reader := func(f os.FileInfo) {
			id := strings.Replace(f.Name(), ".cpt", "", 1)
			entry, err := d.Read(id)
			if err != nil {
				log.Printf("Failed to recover %s because %s", f.Name(), err)
				entryReader <- nil
			} else {
				entryReader <- &entry
			}
		}
		for _, file := range previousEntries {
			go reader(file)
		}

		complete := 0
		failed := 0
		timer := time.NewTimer(30 * time.Second)

		for complete < len(previousEntries) {
			select {
			case entry := <-entryReader:
				complete++
				if entry == nil {
					failed++
				} else {
					emptyIndex[*entry.Date] = entry.Id
				}
			case <-timer.C:
				return errors.New("Timed out waiting for recovery to finish")
			}
		}
		if failed > 0 {
			return errors.New("Failed to recover one or more entries. See previous messages")
		}
	}

	return d.writeIndex(emptyIndex)
}
<commit_msg>Verify that the provided password actually decrypts the journal<commit_after>package storage

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/user"
	"regexp"
	"strings"
	"sync"
	"time"

	"github.com/satori/go.uuid"

	"code.tobolaski.com/brendan/ejrnl"
	"code.tobolaski.com/brendan/ejrnl/crypto"
)

type Driver struct {
	directory string
	key       []byte
	indexLock *sync.RWMutex
}

// NewDriver creates a new storage driver from the specified config and password.
func NewDriver(conf ejrnl.Config, password string) (*Driver, error) {
	salt, err := base64.StdEncoding.DecodeString(conf.Salt)
	if err != nil {
		return &Driver{}, fmt.Errorf("Failed to decode salt because %s", err)
	}

	key, err := crypto.GenerateKey([]byte(password), salt, conf.Pow)
	if err != nil {
		return &Driver{}, err
	}

	driver := &Driver{
		directory: conf.StorageDirectory,
		key:       key,
		indexLock: &sync.RWMutex{},
	}

	err = driver.checkExists()
	if err != nil {
		return driver, err
	}

	return driver, nil
}

// checkExists checks whether the journal already exists
func (d *Driver) checkExists() error {
	current, err := user.Current()
	if err != nil {
		return fmt.Errorf("Can't retrieve the current user's information because %s", err)
	}

	path := strings.Replace(d.directory, "~", current.HomeDir, -1)
	d.directory = path

	if _, err := os.Stat(fmt.Sprintf("%s/index.cpt", path)); os.IsNotExist(err) {
		return &NeedsInit{msg: "the index doesn't exist"}
	}

	d.indexLock.RLock()
	defer d.indexLock.RUnlock()

	_, err = d.readIndex()

	return err
}

func (d *Driver) Write(entry ejrnl.Entry) error {
	if entry.Date == nil {
		now := time.Now()
		entry.Date = &now
	}
	if entry.Id == "" {
		entry.Id = fmt.Sprintf("%s", uuid.NewV4())
	}
	plaintext, err := json.Marshal(entry)
	if err != nil {
		return err
	}
	cyphertext, err := crypto.Encrypt(plaintext, d.key)
	if err != nil {
		return err
	}

	var previousDate time.Time

	if _, err = os.Stat(fmt.Sprintf("%s/%s.cpt", d.directory, entry.Id)); err == nil {
		old, err := d.Read(entry.Id)
		if err != nil {
			log.Printf("Failed to read previous entry because %s", err)
		} else {
			previousDate = *old.Date
		}
	}

	err = ioutil.WriteFile(fmt.Sprintf("%s/%s.cpt", d.directory, entry.Id), cyphertext, 0600)
	if err != nil {
		return err
	}

	d.indexLock.Lock()
	defer d.indexLock.Unlock()
	index, err := d.readIndex()
	if err != nil {
		return err
	}
	delete(index, previousDate)
	index[*entry.Date] = entry.Id
	err = d.writeIndex(index)
	return err
}

func (d *Driver) Read(id string) (ejrnl.Entry, error) {
	bytes, err := ioutil.ReadFile(fmt.Sprintf("%s/%s.cpt", d.directory, id))
	if err != nil {
		return ejrnl.Entry{}, err
	}

	plaintext, err := crypto.Decrypt(bytes, d.key)
	if err != nil {
		return ejrnl.Entry{}, err
	}

	entry := &ejrnl.Entry{}
	err = json.Unmarshal(plaintext, entry)
	return *entry, err
}

// List returns the index of all the entries stored in the journal
func (d *Driver) List() (map[time.Time]string, error) {
	d.indexLock.RLock()
	defer d.indexLock.RUnlock()
	return d.readIndex()
}

// readIndex reads the index from the disk. The caller must have at least a read lock on d.indexLock
func (d *Driver) readIndex() (map[time.Time]string, error) {
	index := make(map[time.Time]string)
	cyphertext, err := ioutil.ReadFile(fmt.Sprintf("%s/index.cpt", d.directory))
	if err != nil {
		return index, err
	}

	plaintext, err := crypto.Decrypt(cyphertext, d.key)
	if err != nil {
		return index, err
	}

	p := &index
	err = json.Unmarshal(plaintext, p)
	return *p, err
}

// writeIndex writes an updated index file. Note that the caller must have the a lock on d.indexLock
func (d *Driver) writeIndex(index map[time.Time]string) error {
	plaintext, err := json.Marshal(index)
	if err != nil {
		return err
	}

	cyphertext, err := crypto.Encrypt(plaintext, d.key)
	if err != nil {
		return err
	}

	err = ioutil.WriteFile(fmt.Sprintf("%s/index.cpt", d.directory), cyphertext, 0600)
	return err
}

// Init creates the new journal
func (d *Driver) Init() error {
	d.indexLock.Lock()
	defer d.indexLock.Unlock()
	if _, err := os.Stat(d.directory); os.IsNotExist(err) {
		os.MkdirAll(d.directory, 0700)
	}

	files, err := ioutil.ReadDir(d.directory)
	if err != nil {
		return fmt.Errorf("Failed to read directory for journal because %s")
	}
	previousEntries := []os.FileInfo{}
	for _, file := range files {
		if match, _ := regexp.MatchString("\\.cpt$", file.Name()); match {
			previousEntries = append(previousEntries, file)
		}
	}

	emptyIndex := make(map[time.Time]string)

	if len(previousEntries) > 0 {
		entryReader := make(chan *ejrnl.Entry, len(previousEntries))
		reader := func(f os.FileInfo) {
			id := strings.Replace(f.Name(), ".cpt", "", 1)
			entry, err := d.Read(id)
			if err != nil {
				log.Printf("Failed to recover %s because %s", f.Name(), err)
				entryReader <- nil
			} else {
				entryReader <- &entry
			}
		}
		for _, file := range previousEntries {
			go reader(file)
		}

		complete := 0
		failed := 0
		timer := time.NewTimer(30 * time.Second)

		for complete < len(previousEntries) {
			select {
			case entry := <-entryReader:
				complete++
				if entry == nil {
					failed++
				} else {
					emptyIndex[*entry.Date] = entry.Id
				}
			case <-timer.C:
				return errors.New("Timed out waiting for recovery to finish")
			}
		}
		if failed > 0 {
			return errors.New("Failed to recover one or more entries. See previous messages")
		}
	}

	return d.writeIndex(emptyIndex)
}
<|endoftext|>


<commit_before>// This file definse the logOuter interface and several types of logOuter.
//
// emptyOuter = logOuter where both Out and Outf are noops
// lineOuter = logOuter where a newline is inserted after every call to
//			   Out and Outf
// fatalLineOuter = logOuter that logs message with inserted newline then
//					exits with call to os.EXIT(1)

package golog

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"strconv"
	"time"
)

// The location in the source of a log message. Any fields set to their zero
// values will be assumed to be absent. (The empty string is not a valid
// package/function/file, and 0 is not a valid line number).
type LogLocation struct {
	Package  string
	Function string
	File     string
	Line     int
}

type LogMessage struct {
	Level       int
	Nanoseconds int64
	Message     string
	Location    *LogLocation
}

type LogOuter interface {
	// Output a LogMessage (to a file, to stderr, to a tester, etc). Output
	// must be safe to call from multiple threads.
	Output(*LogMessage)
}

// Render a formatted LogLocation to the buffer. If all present, format is
// "{pack}.{func}/{file}:{line}". If some fields omitted, intelligently
// delimits the remaining fields.
func renderLogLocation(buf *bytes.Buffer, l *LogLocation) {
	if l == nil {
		return
	}
	packPresent := len(l.Package) > 0
	funcPresent := len(l.Function) > 0
	filePresent := len(l.Function) > 0
	linePresent := l.Line > 0

	// TODO(awreece) This logic is terrifying.
	if packPresent {
		buf.WriteString(l.Package)
	}
	if funcPresent {
		if packPresent {
			buf.WriteString(".")
		}
		buf.WriteString(l.Function)
	}
	if (packPresent || funcPresent) && (filePresent || linePresent) {
		buf.WriteString("/")
	}
	if filePresent {
		buf.WriteString(l.File)
	}
	if linePresent {
		if filePresent {
			buf.WriteString(":")
		}
		buf.WriteString(strconv.Itoa(l.Line))
	}
}

// Format the message as a string, optionally inserting a newline.
// Format is: "L{level} {time} {pack}.{func}/{file}:{line}] {message}"
func formatLogMessage(m *LogMessage, insertNewline bool) string {
	var buf bytes.Buffer
	buf.WriteString(fmt.Sprintf("L%d", m.Level))
	t := time.NanosecondsToLocalTime(m.Nanoseconds)
	buf.WriteString(t.Format(" 15:04:05.000000"))
	if m.Location != nil {
		buf.WriteString(" ")
		renderLogLocation(&buf, m.Location)
	}
	buf.WriteString("] ")
	buf.WriteString(m.Message)
	if insertNewline {
		buf.WriteString("\n")
	}
	return buf.String()
}

type writerLogOuter struct {
	// TODO(awreece) Insert mutex?
	io.Writer
}

func (f *writerLogOuter) Output(m *LogMessage) {
	// TODO(awreece) Grab mutex?
	// TODO(awreece) Keep writing until all bytes written!
	// Make sure to insert a newline.
	f.Write([]byte(formatLogMessage(m, true)))
}

// Returns a LogOuter wrapping the io.Writer.
func NewWriterLogOuter(f io.Writer) LogOuter {
	return &writerLogOuter{f}
}

// Returns a LogOuter wrapping the file, or an error if the file cannot be
// opened.
func NewFileLogOuter(filename string) (LogOuter, os.Error) {
	if file, err := os.Create(filename); err != nil {
		return nil, err
	} else {
		return NewWriterLogOuter(file), nil
	}

	panic("Code never reaches here, this mollifies the compiler.")
}

// We want to allow an abitrary testing framework.
type TestController interface {
	// We will assume that testers insert newlines in manner similar to
	// the FEATURE of testing.T where it inserts extra newlines. >.<
	Log(...interface{})
	FailNow()
}

type testLogOuter struct {
	TestController
}

func (t *testLogOuter) Output(m *LogMessage) {
	// Don't insert an additional log message since the tester inserts them
	// for us.
	t.Log(formatLogMessage(m, false))
}

// Return a LogOuter wrapping the TestControlller.
func NewTestLogOuter(t TestController) LogOuter {
	return &testLogOuter{t}
}
<commit_msg>Comment nil Location expectation<commit_after>// This file definse the logOuter interface and several types of logOuter.
//
// emptyOuter = logOuter where both Out and Outf are noops
// lineOuter = logOuter where a newline is inserted after every call to
//			   Out and Outf
// fatalLineOuter = logOuter that logs message with inserted newline then
//					exits with call to os.EXIT(1)

package golog

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"strconv"
	"time"
)

// The location in the source of a log message. Any fields set to their zero
// values will be assumed to be absent. (The empty string is not a valid
// package/function/file, and 0 is not a valid line number).
type LogLocation struct {
	Package  string
	Function string
	File     string
	Line     int
}

type LogMessage struct {
	Level       int
	Nanoseconds int64
	Message     string
	// Indicate no location provided with a nil Location.
	Location    *LogLocation
}

type LogOuter interface {
	// Output a LogMessage (to a file, to stderr, to a tester, etc). Output
	// must be safe to call from multiple threads.
	Output(*LogMessage)
}

// Render a formatted LogLocation to the buffer. If all present, format is
// "{pack}.{func}/{file}:{line}". If some fields omitted, intelligently
// delimits the remaining fields.
func renderLogLocation(buf *bytes.Buffer, l *LogLocation) {
	if l == nil {
		return
	}
	packPresent := len(l.Package) > 0
	funcPresent := len(l.Function) > 0
	filePresent := len(l.Function) > 0
	linePresent := l.Line > 0

	// TODO(awreece) This logic is terrifying.
	if packPresent {
		buf.WriteString(l.Package)
	}
	if funcPresent {
		if packPresent {
			buf.WriteString(".")
		}
		buf.WriteString(l.Function)
	}
	if (packPresent || funcPresent) && (filePresent || linePresent) {
		buf.WriteString("/")
	}
	if filePresent {
		buf.WriteString(l.File)
	}
	if linePresent {
		if filePresent {
			buf.WriteString(":")
		}
		buf.WriteString(strconv.Itoa(l.Line))
	}
}

// Format the message as a string, optionally inserting a newline.
// Format is: "L{level} {time} {pack}.{func}/{file}:{line}] {message}"
func formatLogMessage(m *LogMessage, insertNewline bool) string {
	var buf bytes.Buffer
	buf.WriteString(fmt.Sprintf("L%d", m.Level))
	t := time.NanosecondsToLocalTime(m.Nanoseconds)
	buf.WriteString(t.Format(" 15:04:05.000000"))
	if m.Location != nil {
		buf.WriteString(" ")
		renderLogLocation(&buf, m.Location)
	}
	buf.WriteString("] ")
	buf.WriteString(m.Message)
	if insertNewline {
		buf.WriteString("\n")
	}
	return buf.String()
}

type writerLogOuter struct {
	// TODO(awreece) Insert mutex?
	io.Writer
}

func (f *writerLogOuter) Output(m *LogMessage) {
	// TODO(awreece) Grab mutex?
	// TODO(awreece) Keep writing until all bytes written!
	// Make sure to insert a newline.
	f.Write([]byte(formatLogMessage(m, true)))
}

// Returns a LogOuter wrapping the io.Writer.
func NewWriterLogOuter(f io.Writer) LogOuter {
	return &writerLogOuter{f}
}

// Returns a LogOuter wrapping the file, or an error if the file cannot be
// opened.
func NewFileLogOuter(filename string) (LogOuter, os.Error) {
	if file, err := os.Create(filename); err != nil {
		return nil, err
	} else {
		return NewWriterLogOuter(file), nil
	}

	panic("Code never reaches here, this mollifies the compiler.")
}

// We want to allow an abitrary testing framework.
type TestController interface {
	// We will assume that testers insert newlines in manner similar to
	// the FEATURE of testing.T where it inserts extra newlines. >.<
	Log(...interface{})
	FailNow()
}

type testLogOuter struct {
	TestController
}

func (t *testLogOuter) Output(m *LogMessage) {
	// Don't insert an additional log message since the tester inserts them
	// for us.
	t.Log(formatLogMessage(m, false))
}

// Return a LogOuter wrapping the TestControlller.
func NewTestLogOuter(t TestController) LogOuter {
	return &testLogOuter{t}
}
<|endoftext|>


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

// Package logf can control log file.
package logf

import (
	"log"
	"os"
	"os/signal"
	"sync"
	"syscall"
)

var (
	locker sync.Mutex
	logS   string
	logF   *os.File
)

func SetOutput(path string) error {
	file, err := os.OpenFile(path,
		os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}

	log.SetOutput(file)

	locker.Lock()
	defer locker.Unlock()

	if logF != nil {
		logF.Close()
	}

	logS = path
	logF = file

	return nil
}

func init() {
	go logSig()
}

func logSig() {
	defer func() { recover() }()

	// SIGUSR1 to reload log.
	rC := make(chan os.Signal, 1)
	signal.Notify(rC, syscall.SIGUSR1)

	for {
		select {
		case <-rC:
			locker.Lock()
			path := logS
			locker.Unlock()
			if len(path) > 0 {
				SetOutput(path)
			}
		}
	}
}
<commit_msg>remove logf<commit_after><|endoftext|>


<commit_before>package controllers

import (
	"fmt"
	"github.com/astaxie/beego"
	"github.com/dyzdyz010/Blog/models"
	"github.com/qiniu/api/rs"
)

type AdminController struct {
	beego.Controller
}

func checkLogin(ac *AdminController) {
	name := ac.GetSession("user")
	if name == nil {
		ac.Redirect("/admin/login", 302)
	}
}

func (this *AdminController) Dashboard() {
	checkLogin(this)

	this.TplNames = "admin/dashboard.tpl"

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["DashboardActive"] = true

	renderTemplate(this.Ctx, "views/admin/dashboard.amber", this.Data)
}

// Login

func (this *AdminController) Login() {
	this.TplNames = "admin/login.tpl"

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"

	renderTemplate(this.Ctx, "views/admin/login.amber", this.Data)
}

func (this *AdminController) PostLogin() {
	this.TplNames = "admin/login.tpl"

	author := models.Author{}
	err := this.ParseForm(&author)
	if err != nil {
		panic(err)
	}

	a, err := models.AuthorByName(author.Name)
	if err != nil {
		this.Data["Message"] = err.Error()
	} else if models.Hash(author.Password) != a.Password {
		this.Data["Message"] = "Wrong password."
	} else {
		this.SetSession("user", author.Name)
		this.Redirect("/admin", 302)
	}
	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"

	renderTemplate(this.Ctx, "views/admin/login.amber", this.Data)
}

// Entry Operations

func (this *AdminController) Entries() {
	checkLogin(this)
	this.TplNames = "admin/entry-list.tpl"

	// fmt.Println(this.GetSession("user").(string))
	entries, err := models.EntriesByUser(this.GetSession("user").(string))
	if err != nil {
		panic(err)
	}

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["EntryActive"] = true
	this.Data["Entries"] = entries

	renderTemplate(this.Ctx, "views/admin/entry-list.amber", this.Data)
}

func (this *AdminController) Entry() {
	checkLogin(this)
	this.TplNames = "admin/entry.tpl"

	eid := this.Ctx.Input.Param(":id")
	fmt.Println(eid)
	if eid != "new" {
		entry, _ := models.EntryById(eid)
		if entry == nil {
			this.Abort("404")
			return
		} else {
			this.Data["Entry"] = entry
			this.Data["PostId"] = "update/" + entry.Id
		}
	}

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["EntryActive"] = true
	this.Data["MarkdownEnabled"] = true

	collections, err := models.CollectionsByUser(this.GetSession("user").(string))
	if err != nil {
		panic(err)
	}
	this.Data["Collections"] = collections
	fmt.Println(this.Data["Entry"])

	renderTemplate(this.Ctx, "views/admin/entry.amber", this.Data)
}

func (this *AdminController) UpdateEntry() {
	entry := models.Entry{}
	err := this.ParseForm(&entry)
	if err != nil {
		panic(err)
	}

	entry.Id = this.Ctx.Input.Param(":id")
	entry.Author = this.GetSession("user").(string)
	entry.Collection = this.Input().Get("collection")
	err = models.UpdateEntry(entry)
	if err != nil {
		panic(err)
	}

	this.TplNames = "admin/entry.tpl"
	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["EntryActive"] = true
	this.Data["PostId"] = "update/" + entry.Id
	this.Data["Entry"] = entry
	this.Data["MarkdownEnabled"] = true
	collections, err := models.CollectionsByUser(this.GetSession("user").(string))
	if err != nil {
		panic(err)
	}
	this.Data["Collections"] = collections
	this.Data["Message"] = "Update Successful"

	renderTemplate(this.Ctx, "views/admin/entry.amber", this.Data)
}

func (this *AdminController) DeleteEntry() {
	this.TplNames = "admin/entry-list.tpl"

	id := this.GetString("id")
	fmt.Println("Entry Id: ", id)
	err := models.DeleteEntry(id)
	if err != nil {
		panic(err)
	}

	this.Redirect("/admin/entries", 302)
}

func (this *AdminController) NewEntry() {
	checkLogin(this)
	this.TplNames = "admin/entry.tpl"

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["PostId"] = "new"
	this.Data["EntryActive"] = true
	this.Data["MarkdownEnabled"] = true
	collections, err := models.CollectionsByUser(this.GetSession("user").(string))
	if err != nil {
		panic(err)
	}
	this.Data["Collections"] = collections

	renderTemplate(this.Ctx, "views/admin/entry.amber", this.Data)
}

func (this *AdminController) PostNewEntry() {
	entry := models.Entry{}
	err := this.ParseForm(&entry)
	if err != nil {
		panic(err)
	}
	entry.Author = this.GetSession("user").(string)
	entry.Collection = this.Input().Get("collection")
	nid, err := models.AddEntry(entry)
	this.TplNames = "admin/entry.tpl"
	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["EntryActive"] = true
	if err != nil {
		this.Data["PostId"] = "new"
		this.Data["Message"] = err.Error()
	} else {
		this.Data["PostId"] = "update/" + nid
		this.Data["Message"] = "Post Successful"

		collections, err := models.CollectionsByUser(this.GetSession("user").(string))
		if err != nil {
			panic(err)
		}
		this.Data["Collections"] = collections
	}
	this.Data["Entry"] = entry
	this.Data["MarkdownEnabled"] = true

	renderTemplate(this.Ctx, "views/admin/entry.amber", this.Data)
}

// Collection Operations

func (this *AdminController) Collections() {
	checkLogin(this)
	this.TplNames = "admin/collection-list.tpl"

	collections, err := models.CollectionsByUser(this.GetSession("user").(string))
	if err != nil {
		panic(err)
	}

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["CollectionActive"] = true
	this.Data["Collections"] = collections

	renderTemplate(this.Ctx, "views/admin/collection-list.amber", this.Data)
}

func (this *AdminController) Collection() {
	fmt.Println("Collection")
	checkLogin(this)
	this.TplNames = "admin/collection.tpl"

	id := this.Ctx.Input.Param(":id")
	collection, err := models.CollectionById(id)
	if err != nil {
		panic(err)
	}

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["CollectionActive"] = true
	this.Data["Collection"] = collection
	this.Data["PostId"] = "update/" + id

	renderTemplate(this.Ctx, "views/admin/collection.amber", this.Data)
}

func (this *AdminController) UpdateCollection() {
	this.TplNames = "admin/collection.tpl"

	collection := models.Collection{}
	err := this.ParseForm(&collection)
	if err != nil {
		panic(err)
	}

	collection.Id = this.Ctx.Input.Param(":id")
	collection.Author = this.GetSession("user").(string)
	nid, err := models.UpdateCollection(collection)
	if err != nil {
		this.Data["PostId"] = "update/" + collection.Id
		this.Data["Message"] = err.Error()
	} else {
		this.Data["PostId"] = "update/" + nid
		this.Data["Message"] = "Update Successful"
	}
	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["Collection"] = collection
	this.Data["CollectionActive"] = true

	renderTemplate(this.Ctx, "views/admin/collection.amber", this.Data)
}

func (this *AdminController) NewCollection() {
	fmt.Println("New Collection")
	checkLogin(this)
	this.TplNames = "admin/collection.tpl"

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["CollectionActive"] = true
	this.Data["PostId"] = "new"

	renderTemplate(this.Ctx, "views/admin/collection.amber", this.Data)
}

func (this *AdminController) DeleteCollection() {
	fmt.Println("Delete Collection")
	this.TplNames = "admin/collection-list.tpl"

	id := this.GetString("id")
	err := models.DeleteCollection(id)
	if err != nil {
		panic(err)
	}

	this.Redirect("/admin/collections", 302)
}

func (this *AdminController) CreateCollection() {
	this.TplNames = "admin/collection.tpl"

	collection := models.Collection{}
	err := this.ParseForm(&collection)
	if err != nil {
		panic(err)
	}
	fmt.Println(this.GetSession("user"))
	collection.Author = this.GetSession("user").(string)
	cid, err := models.CreateCollection(collection)
	if err != nil {
		this.Data["PostId"] = "new"
		this.Data["Message"] = err.Error()
	} else {
		this.Data["PostId"] = "update/" + cid
		this.Data["Message"] = "Post Successful"
	}
	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["Collection"] = collection
	this.Data["CollectionActive"] = true

	renderTemplate(this.Ctx, "views/admin/collection.amber", this.Data)
}

func (this *AdminController) QiniuTokens() {
	bucket := models.Appconf.String("qiniu::bucket")
	putPolicy := rs.PutPolicy{
		Scope:     bucket,
		MimeLimit: "image/*",
	}

	this.Data["json"] = putPolicy.Token(nil)
	this.ServeJson()
}
<commit_msg>small fix<commit_after>package controllers

import (
	"fmt"
	"github.com/astaxie/beego"
	"github.com/dyzdyz010/Blog/models"
	"github.com/qiniu/api/rs"
)

type AdminController struct {
	beego.Controller
}

func checkLogin(ac *AdminController) {
	name := ac.GetSession("user")
	if name == nil {
		ac.Redirect("/admin/login", 302)
	}
}

func (this *AdminController) Dashboard() {
	checkLogin(this)

	this.TplNames = "admin/dashboard.tpl"

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["DashboardActive"] = true

	renderTemplate(this.Ctx, "views/admin/dashboard.amber", this.Data)
}

// Login

func (this *AdminController) Login() {
	this.TplNames = "admin/login.tpl"

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"

	renderTemplate(this.Ctx, "views/admin/login.amber", this.Data)
}

func (this *AdminController) PostLogin() {
	this.TplNames = "admin/login.tpl"

	author := models.Author{}
	err := this.ParseForm(&author)
	if err != nil {
		panic(err)
	}

	a, err := models.AuthorByName(author.Name)
	if err != nil {
		this.Data["Message"] = err.Error()
	} else if models.Hash(author.Password) != a.Password {
		this.Data["Message"] = "Wrong password."
	} else {
		this.SetSession("user", author.Name)
		this.Redirect("/admin", 302)
	}
	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"

	renderTemplate(this.Ctx, "views/admin/login.amber", this.Data)
}

// Entry Operations

func (this *AdminController) Entries() {
	checkLogin(this)
	this.TplNames = "admin/entry-list.tpl"

	// fmt.Println(this.GetSession("user").(string))
	entries, err := models.EntriesByUser(this.GetSession("user").(string))
	if err != nil {
		panic(err)
	}

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["EntryActive"] = true
	this.Data["Entries"] = entries

	renderTemplate(this.Ctx, "views/admin/entry-list.amber", this.Data)
}

func (this *AdminController) Entry() {
	checkLogin(this)
	this.TplNames = "admin/entry.tpl"

	eid := this.Ctx.Input.Param(":id")
	fmt.Println(eid)
	if eid != "new" {
		entry, _ := models.EntryById(eid)
		if entry == nil {
			this.Abort("404")
			return
		} else {
			this.Data["Entry"] = entry
			this.Data["PostId"] = "update/" + entry.Id
		}
	}

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["EntryActive"] = true
	this.Data["MarkdownEnabled"] = true

	collections, err := models.CollectionsByUser(this.GetSession("user").(string))
	if err != nil {
		panic(err)
	}
	this.Data["Collections"] = collections
	fmt.Println(this.Data["Entry"])

	renderTemplate(this.Ctx, "views/admin/entry.amber", this.Data)
}

func (this *AdminController) UpdateEntry() {
	entry := models.Entry{}
	err := this.ParseForm(&entry)
	if err != nil {
		panic(err)
	}

	entry.Id = this.Ctx.Input.Param(":id")
	entry.Author = this.GetSession("user").(string)
	entry.Collection = this.Input().Get("collection")
	err = models.UpdateEntry(entry)
	if err != nil {
		panic(err)
	}

	this.TplNames = "admin/entry.tpl"
	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["EntryActive"] = true
	this.Data["PostId"] = "update/" + entry.Id
	this.Data["Entry"] = entry
	this.Data["MarkdownEnabled"] = true
	collections, err := models.CollectionsByUser(this.GetSession("user").(string))
	if err != nil {
		panic(err)
	}
	this.Data["Collections"] = collections
	this.Data["Message"] = "Update Successful"

	renderTemplate(this.Ctx, "views/admin/entry.amber", this.Data)
}

func (this *AdminController) DeleteEntry() {
	this.TplNames = "admin/entry-list.tpl"

	id := this.GetString("id")
	fmt.Println("Entry Id: ", id)
	err := models.DeleteEntry(id)
	if err != nil {
		panic(err)
	}

	this.Redirect("/admin/entries", 302)
}

func (this *AdminController) NewEntry() {
	checkLogin(this)
	this.TplNames = "admin/entry.tpl"

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["PostId"] = "new"
	this.Data["EntryActive"] = true
	this.Data["MarkdownEnabled"] = true
	collections, err := models.CollectionsByUser(this.GetSession("user").(string))
	if err != nil {
		panic(err)
	}
	this.Data["Collections"] = collections

	renderTemplate(this.Ctx, "views/admin/entry.amber", this.Data)
}

func (this *AdminController) PostNewEntry() {
	entry := models.Entry{}
	err := this.ParseForm(&entry)
	if err != nil {
		panic(err)
	}
	entry.Author = this.GetSession("user").(string)
	entry.Collection = this.Input().Get("collection")
	nid, err := models.AddEntry(entry)
	this.TplNames = "admin/entry.tpl"
	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["EntryActive"] = true
	if err != nil {
		this.Data["PostId"] = "new"
		this.Data["Message"] = err.Error()
	} else {
		this.Data["PostId"] = "update/" + nid
		this.Data["Message"] = "Post Successful"

		collections, err := models.CollectionsByUser(this.GetSession("user").(string))
		if err != nil {
			panic(err)
		}
		this.Data["Collections"] = collections
	}
	this.Data["Entry"] = entry
	this.Data["MarkdownEnabled"] = true

	renderTemplate(this.Ctx, "views/admin/entry.amber", this.Data)
}

// Collection Operations

func (this *AdminController) Collections() {
	checkLogin(this)
	this.TplNames = "admin/collection-list.tpl"

	collections, err := models.CollectionsByUser(this.GetSession("user").(string))
	if err != nil {
		panic(err)
	}

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["CollectionActive"] = true
	this.Data["Collections"] = collections

	renderTemplate(this.Ctx, "views/admin/collection-list.amber", this.Data)
}

func (this *AdminController) Collection() {
	fmt.Println("Collection")
	checkLogin(this)
	this.TplNames = "admin/collection.tpl"

	id := this.Ctx.Input.Param(":id")
	collection, err := models.CollectionById(id)
	if err != nil {
		panic(err)
	}

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["CollectionActive"] = true
	this.Data["Collection"] = collection
	this.Data["PostId"] = "update/" + id

	renderTemplate(this.Ctx, "views/admin/collection.amber", this.Data)
}

func (this *AdminController) UpdateCollection() {
	this.TplNames = "admin/collection.tpl"

	collection := models.Collection{}
	err := this.ParseForm(&collection)
	if err != nil {
		panic(err)
	}

	collection.Id = this.Ctx.Input.Param(":id")
	collection.Author = this.GetSession("user").(string)
	nid, err := models.UpdateCollection(collection)
	if err != nil {
		this.Data["PostId"] = "update/" + collection.Id
		this.Data["Message"] = err.Error()
	} else {
		this.Data["PostId"] = "update/" + nid
		this.Data["Message"] = "Update Successful"
	}
	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["Collection"] = collection
	this.Data["CollectionActive"] = true

	renderTemplate(this.Ctx, "views/admin/collection.amber", this.Data)
}

func (this *AdminController) NewCollection() {
	fmt.Println("New Collection")
	checkLogin(this)
	this.TplNames = "admin/collection.tpl"

	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["CollectionActive"] = true
	this.Data["PostId"] = "new"

	renderTemplate(this.Ctx, "views/admin/collection.amber", this.Data)
}

func (this *AdminController) DeleteCollection() {
	fmt.Println("Delete Collection")
	this.TplNames = "admin/collection-list.tpl"

	id := this.GetString("id")
	err := models.DeleteCollection(id)
	if err != nil {
		panic(err)
	}

	this.Redirect("/admin/collections", 302)
}

func (this *AdminController) CreateCollection() {
	this.TplNames = "admin/collection.tpl"

	collection := models.Collection{}
	err := this.ParseForm(&collection)
	if err != nil {
		panic(err)
	}
	fmt.Println(this.GetSession("user"))
	collection.Author = this.GetSession("user").(string)
	cid, err := models.CreateCollection(collection)
	if err != nil {
		this.Data["PostId"] = "new"
		this.Data["Message"] = err.Error()
	} else {
		this.Data["PostId"] = "update/" + cid
		this.Data["Message"] = "Post Successful"
	}
	this.Data["Title"] = "Moonlightter"
	this.Data["Subtitle"] = "My Programming Life"
	this.Data["Collection"] = collection
	this.Data["CollectionActive"] = true

	renderTemplate(this.Ctx, "views/admin/collection.amber", this.Data)
}

func (this *AdminController) QiniuTokens() {
	bucket := models.Appconf.String("qiniu::bucket")
	putPolicy := rs.PutPolicy{
		Scope: bucket,
	}

	this.Data["json"] = putPolicy.Token(nil)
	this.ServeJson()
}
<|endoftext|>


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

package rbtree

import (
	"testing"
)

func TestDeleteReturnValue(t *testing.T) {
	rbt := New()

	rbt.Insert(String("go"))
	rbt.Insert(String("lang"))

	if rbt.Len() != 2 {
		t.Errorf("tree.Len() = %d, expect %d", rbt.Len(), 2)
	}

	// go should be in the rbtree
	deletedGo := rbt.Delete(String("go"))
	if deletedGo != String("go") {
		t.Errorf("expect %v, got %v", "go", deletedGo)
	}

	// C should not be in the rbtree
	deletedC := rbt.Delete(String("C"))
	if deletedC != nil {
		t.Errorf("expect %v, got %v", nil, deletedC)
	}
}
<commit_msg>Test: add test for function Min<commit_after>// Copyright 2015, Hu Keping. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rbtree

import (
	"testing"
)

func TestDeleteReturnValue(t *testing.T) {
	rbt := New()

	rbt.Insert(String("go"))
	rbt.Insert(String("lang"))

	if rbt.Len() != 2 {
		t.Errorf("tree.Len() = %d, expect %d", rbt.Len(), 2)
	}

	// go should be in the rbtree
	deletedGo := rbt.Delete(String("go"))
	if deletedGo != String("go") {
		t.Errorf("expect %v, got %v", "go", deletedGo)
	}

	// C should not be in the rbtree
	deletedC := rbt.Delete(String("C"))
	if deletedC != nil {
		t.Errorf("expect %v, got %v", nil, deletedC)
	}
}

func TestMin(t *testing.T) {
	rbt := New()

	m := 0
	n := 1000
	for m < n {
		rbt.Insert(Int(m))
		m++
	}
	if rbt.Len() != uint(n) {
		t.Errorf("tree.Len() = %d, expect %d", rbt.Len(), n)
	}

	for m >= 0 {
		rbt.Delete(rbt.Min())
		m--
	}

	if rbt.Len() != 0 {
		t.Errorf("tree.Len() = %d, expect %d", rbt.Len(), 0)
	}
}
<|endoftext|>


<commit_before>package structs

import (
        "bytes"
        "fmt"
        "io/ioutil"
        "net/http"
        "os"
        "time"
        "text/template"

        "gopkg.in/mgo.v2/bson"
        "github.com/owm-inc/weatherchecker-go/db"
        "github.com/owm-inc/weatherchecker-go/adapters"
        )

type HistoryDataEntry struct {
    Id bson.ObjectId `bson:"_id,omitempty" json:"objectid"`
    Location LocationEntry
    Source SourceEntry
    Measurements adapters.MeasurementArray
    WType string
    Url string
}

func NewHistoryDataEntry (location LocationEntry, source SourceEntry, measurements adapters.MeasurementArray, wtype string, url string) HistoryDataEntry {
    entry := HistoryDataEntry {Location:location, Source:source, Measurements:measurements, WType:wtype, Url:url}
    entry.Id = bson.NewObjectId()

    return entry
}

func GetDataEntry (location LocationEntry, source SourceEntry, wtype string) HistoryDataEntry {
    url := makeUrl (source.Urls[wtype], UrlData {Source:source, Location:location})
    raw := download (url)
    measurements := adapters.AdaptWeather(source.Name, wtype, raw)
    data := NewHistoryDataEntry(location, source, measurements, wtype, url)

    return data
}

type HistoryEntry struct {
    Id bson.ObjectId `bson:"_id,omitempty"`
    EntryTime time.Time
    WType string
    Data []HistoryDataEntry
}

func NewHistoryEntry (dataset []HistoryDataEntry, entryTime time.Time, wType string) HistoryEntry {
    var historyEntry = HistoryEntry {Data:dataset, EntryTime: entryTime, WType:wType}

    return historyEntry
}

type WeatherHistory struct {
    Database *db.MongoDb
    Collection string
}

func (this *WeatherHistory) AddHistoryEntry (locations []LocationEntry, sources []SourceEntry, wtypes []string) HistoryEntry {
    var dataset []HistoryDataEntry

    for _, location := range locations {
        for _, source := range sources {
            for _, wtype := range wtypes {
                data := GetDataEntry(location, source, wtype)

                dataset = append(dataset, data)
            }
        }
    }

    newHistoryEntry := NewHistoryEntry(dataset, time.Now(), "current")
    this.Database.Insert(this.Collection, newHistoryEntry)

    return newHistoryEntry
}

func (this *WeatherHistory) ShowFullHistory () []HistoryEntry {
    var result []HistoryEntry
    this.Database.FindAll(this.Collection, &result)
    return result
}

func NewWeatherHistory (db_instance *db.MongoDb) WeatherHistory {
    var history = WeatherHistory {Database:db_instance, Collection:"WeatherHistory"}

    return history
}

type Keyring struct {
    Key string
    Uref string
}

type SourceEntry struct {
    Name string `json:"name"`
    Urls map[string]string `json:"urls"`
    Keys Keyring
}

func CreateSources() []SourceEntry {
    var sources []SourceEntry
    var keys Keyring
    var urls map[string]string
    var entry SourceEntry

    keys = Keyring{Key:os.Getenv("OWM_KEY")}
    urls = map[string]string {"current":`http://api.openweathermap.org/data/2.5/weather?appid={{.Source.Keys.Key}}&lat={{.Location.Latitude}}&lon={{.Location.Longitude}}&units=metric`,
                              "forecast":``}
    entry = SourceEntry{Name:"OpenWeatherMap", Urls:urls, Keys:keys}
    sources = append(sources, entry)

    keys = Keyring{Key:os.Getenv("WUNDERGROUND_KEY")}
    urls = map[string]string {"current": `http://api.wunderground.com/api/{{.Source.Keys.Key}}/conditions/q/{{.Location.Latitude}},{{.Location.Longitude}}.json`,
                              "forecast": ``}
    entry = SourceEntry{Name:"Weather Underground", Urls:urls, Keys:keys}
    sources = append(sources, entry)

    keys = Keyring{Key:os.Getenv("MYWEATHER2_KEY"), Uref:os.Getenv("MYWEATHER2_UREF")}
    urls = map[string]string {"current": `http://www.myweather2.com/developer/forecast.ashx?uac={{.Source.Keys.Key}}&query={{.Location.Latitude}},{{.Location.Longitude}}&temp_unit=c&output=json&ws_unit=kph`,
                              "forecast": ``}
    entry = SourceEntry{Name:"MyWeather2", Urls:urls, Keys:keys}
    sources = append(sources, entry)

    keys = Keyring{}
    urls = map[string]string {"current": `http://www.accuweather.com/ru/{{.Location.Iso_country}}/{{.Location.Accuweather_city_name}}/{{.Location.Accuweather_id}}/hourly-weather-forecast/{{.Location.Accuweather_id}}`,
                              "forecast": ``}
    entry = SourceEntry{Name:"AccuWeather", Urls:urls, Keys:keys}
    sources = append(sources, entry)

    return sources
}

type UrlData struct {
    Source SourceEntry
    Location LocationEntry
}

func makeUrl(url_template string, data UrlData) string {
    var urlBuf = new(bytes.Buffer)

    var t = template.New("URL template")
    t, _ = t.Parse(url_template)
    t.Execute(urlBuf, data)

    urlString := urlBuf.String()
    return urlString
}

func download(url string) string {
    resp, err := http.Get(url)
    var data string
    if err != nil {
        fmt.Println(`Request finished with error`, err)
        data = ``
    } else {
        defer resp.Body.Close()
        readallContents, _ := ioutil.ReadAll(resp.Body)
        data = string(readallContents)
    }
    return data
}
<commit_msg>Исправлена json-выдача истории<commit_after>package structs

import (
        "bytes"
        "fmt"
        "io/ioutil"
        "net/http"
        "os"
        "time"
        "text/template"

        "gopkg.in/mgo.v2/bson"
        "github.com/owm-inc/weatherchecker-go/db"
        "github.com/owm-inc/weatherchecker-go/adapters"
        )

type HistoryDataEntry struct {
    Id bson.ObjectId `bson:"_id,omitempty" json:"objectid"`
    Location LocationEntry `json:"location"`
    Source SourceEntry `json:"source"`
    Measurements adapters.MeasurementArray `json:"measurements"`
    WType string `json:"wtype"`
    Url string `json:"url"`
}

func NewHistoryDataEntry (location LocationEntry, source SourceEntry, measurements adapters.MeasurementArray, wtype string, url string) HistoryDataEntry {
    entry := HistoryDataEntry {Location:location, Source:source, Measurements:measurements, WType:wtype, Url:url}
    entry.Id = bson.NewObjectId()

    return entry
}

func GetDataEntry (location LocationEntry, source SourceEntry, wtype string) HistoryDataEntry {
    url := makeUrl (source.Urls[wtype], UrlData {Source:source, Location:location})
    raw := download (url)
    measurements := adapters.AdaptWeather(source.Name, wtype, raw)
    data := NewHistoryDataEntry(location, source, measurements, wtype, url)

    return data
}

type HistoryEntry struct {
    Id bson.ObjectId `bson:"_id,omitempty" json:"objectid"`
    EntryTime time.Time `json:"entry_time"`
    WType string `json:"wtype"`
    Data []HistoryDataEntry `json:"data"`
}

func NewHistoryEntry (dataset []HistoryDataEntry, entryTime time.Time, wType string) HistoryEntry {
    entry := HistoryEntry {Data:dataset, EntryTime: entryTime, WType:wType}
    entry.Id = bson.NewObjectId()

    return entry
}

type WeatherHistory struct {
    Database *db.MongoDb
    Collection string
}

func (this *WeatherHistory) AddHistoryEntry (locations []LocationEntry, sources []SourceEntry, wtypes []string) HistoryEntry {
    var dataset []HistoryDataEntry

    for _, location := range locations {
        for _, source := range sources {
            for _, wtype := range wtypes {
                data := GetDataEntry(location, source, wtype)

                dataset = append(dataset, data)
            }
        }
    }

    newHistoryEntry := NewHistoryEntry(dataset, time.Now(), "current")
    this.Database.Insert(this.Collection, newHistoryEntry)

    return newHistoryEntry
}

func (this *WeatherHistory) ShowFullHistory () []HistoryEntry {
    var result []HistoryEntry
    this.Database.FindAll(this.Collection, &result)
    return result
}

func NewWeatherHistory (db_instance *db.MongoDb) WeatherHistory {
    var history = WeatherHistory {Database:db_instance, Collection:"WeatherHistory"}

    return history
}

type Keyring struct {
    Key string
    Uref string
}

type SourceEntry struct {
    Name string `json:"name"`
    Urls map[string]string `json:"urls"`
    Keys Keyring
}

func CreateSources() []SourceEntry {
    var sources []SourceEntry
    var keys Keyring
    var urls map[string]string
    var entry SourceEntry

    keys = Keyring{Key:os.Getenv("OWM_KEY")}
    urls = map[string]string {"current":`http://api.openweathermap.org/data/2.5/weather?appid={{.Source.Keys.Key}}&lat={{.Location.Latitude}}&lon={{.Location.Longitude}}&units=metric`,
                              "forecast":``}
    entry = SourceEntry{Name:"OpenWeatherMap", Urls:urls, Keys:keys}
    sources = append(sources, entry)

    keys = Keyring{Key:os.Getenv("WUNDERGROUND_KEY")}
    urls = map[string]string {"current": `http://api.wunderground.com/api/{{.Source.Keys.Key}}/conditions/q/{{.Location.Latitude}},{{.Location.Longitude}}.json`,
                              "forecast": ``}
    entry = SourceEntry{Name:"Weather Underground", Urls:urls, Keys:keys}
    sources = append(sources, entry)

    keys = Keyring{Key:os.Getenv("MYWEATHER2_KEY"), Uref:os.Getenv("MYWEATHER2_UREF")}
    urls = map[string]string {"current": `http://www.myweather2.com/developer/forecast.ashx?uac={{.Source.Keys.Key}}&query={{.Location.Latitude}},{{.Location.Longitude}}&temp_unit=c&output=json&ws_unit=kph`,
                              "forecast": ``}
    entry = SourceEntry{Name:"MyWeather2", Urls:urls, Keys:keys}
    sources = append(sources, entry)

    keys = Keyring{}
    urls = map[string]string {"current": `http://www.accuweather.com/ru/{{.Location.Iso_country}}/{{.Location.Accuweather_city_name}}/{{.Location.Accuweather_id}}/hourly-weather-forecast/{{.Location.Accuweather_id}}`,
                              "forecast": ``}
    entry = SourceEntry{Name:"AccuWeather", Urls:urls, Keys:keys}
    sources = append(sources, entry)

    return sources
}

type UrlData struct {
    Source SourceEntry
    Location LocationEntry
}

func makeUrl(url_template string, data UrlData) string {
    var urlBuf = new(bytes.Buffer)

    var t = template.New("URL template")
    t, _ = t.Parse(url_template)
    t.Execute(urlBuf, data)

    urlString := urlBuf.String()
    return urlString
}

func download(url string) string {
    resp, err := http.Get(url)
    var data string
    if err != nil {
        fmt.Println(`Request finished with error`, err)
        data = ``
    } else {
        defer resp.Body.Close()
        readallContents, _ := ioutil.ReadAll(resp.Body)
        data = string(readallContents)
    }
    return data
}
<|endoftext|>


<commit_before>/*
 * Copyright 2019 Dgraph Labs, Inc. and Contributors
 *
 * 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 ristretto

import (
	"testing"
)

func BenchmarkStoreLockedMap(b *testing.B) {
	GenerateBench(func() store { return newLockedMap() })(b)
}

func GenerateBench(create func() store) func(*testing.B) {
	return func(b *testing.B) {
		b.Run("get  ", func(b *testing.B) {
			m := create()
			m.Set(1, 1)
			b.SetBytes(1)
			b.ResetTimer()
			b.RunParallel(func(pb *testing.PB) {
				for pb.Next() {
					m.Get(1)
				}
			})
		})
	}
}

func TestStore(t *testing.T) {
	GenerateTest(func() store { return newStore() })(t)
}

func TestStoreLockedMap(t *testing.T) {
	GenerateTest(func() store { return newLockedMap() })(t)
}

func GenerateTest(create func() store) func(*testing.T) {
	return func(t *testing.T) {
		t.Run("set/get", func(t *testing.T) {
			m := create()
			m.Set(1, 1)
			if val, _ := m.Get(1); val != nil && val.(int) != 1 {
				t.Fatal("set-get error")
			}
		})
		t.Run("set", func(t *testing.T) {
			m := create()
			m.Set(1, 1)
			// overwrite
			m.Set(1, 2)
			if val, _ := m.Get(1); val != nil && val.(int) != 2 {
				t.Fatal("set update error")
			}
		})
		t.Run("del", func(t *testing.T) {
			m := create()
			m.Set(1, 1)
			// delete item
			m.Del(1)
			if val, found := m.Get(1); val != nil || found {
				t.Fatal("del error")
			}
		})
		t.Run("clear", func(t *testing.T) {
			m := create()
			// set a lot of values
			for i := uint64(0); i < 1000; i++ {
				m.Set(i, i)
			}
			// clear
			m.Clear()
			// check if any of the values exist
			for i := uint64(0); i < 1000; i++ {
				if _, ok := m.Get(i); ok {
					t.Fatal("clear operation failed")
				}
      }
    })
		t.Run("update", func(t *testing.T) {
			m := create()
			m.Set(1, 1)
			if updated := m.Update(1, 2); !updated {
				t.Fatal("value should have been updated")
			}
			if val, _ := m.Get(1); val.(int) != 2 {
				t.Fatal("value wasn't updated")
			}
			if updated := m.Update(2, 2); updated {
				t.Fatal("value should not have been updated")
			}
			if val, found := m.Get(2); val != nil || found {
				t.Fatal("value should not have been updated")
			}
		})
	}
}
<commit_msg>Fix formatting (#79)<commit_after>/*
 * Copyright 2019 Dgraph Labs, Inc. and Contributors
 *
 * 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 ristretto

import (
	"testing"
)

func BenchmarkStoreLockedMap(b *testing.B) {
	GenerateBench(func() store { return newLockedMap() })(b)
}

func GenerateBench(create func() store) func(*testing.B) {
	return func(b *testing.B) {
		b.Run("get  ", func(b *testing.B) {
			m := create()
			m.Set(1, 1)
			b.SetBytes(1)
			b.ResetTimer()
			b.RunParallel(func(pb *testing.PB) {
				for pb.Next() {
					m.Get(1)
				}
			})
		})
	}
}

func TestStore(t *testing.T) {
	GenerateTest(func() store { return newStore() })(t)
}

func TestStoreLockedMap(t *testing.T) {
	GenerateTest(func() store { return newLockedMap() })(t)
}

func GenerateTest(create func() store) func(*testing.T) {
	return func(t *testing.T) {
		t.Run("set/get", func(t *testing.T) {
			m := create()
			m.Set(1, 1)
			if val, _ := m.Get(1); val != nil && val.(int) != 1 {
				t.Fatal("set-get error")
			}
		})
		t.Run("set", func(t *testing.T) {
			m := create()
			m.Set(1, 1)
			// overwrite
			m.Set(1, 2)
			if val, _ := m.Get(1); val != nil && val.(int) != 2 {
				t.Fatal("set update error")
			}
		})
		t.Run("del", func(t *testing.T) {
			m := create()
			m.Set(1, 1)
			// delete item
			m.Del(1)
			if val, found := m.Get(1); val != nil || found {
				t.Fatal("del error")
			}
		})
		t.Run("clear", func(t *testing.T) {
			m := create()
			// set a lot of values
			for i := uint64(0); i < 1000; i++ {
				m.Set(i, i)
			}
			// clear
			m.Clear()
			// check if any of the values exist
			for i := uint64(0); i < 1000; i++ {
				if _, ok := m.Get(i); ok {
					t.Fatal("clear operation failed")
				}
			}
		})
		t.Run("update", func(t *testing.T) {
			m := create()
			m.Set(1, 1)
			if updated := m.Update(1, 2); !updated {
				t.Fatal("value should have been updated")
			}
			if val, _ := m.Get(1); val.(int) != 2 {
				t.Fatal("value wasn't updated")
			}
			if updated := m.Update(2, 2); updated {
				t.Fatal("value should not have been updated")
			}
			if val, found := m.Get(2); val != nil || found {
				t.Fatal("value should not have been updated")
			}
		})
	}
}
<|endoftext|>