<commit_before>// mancala game. Usage: mancala Player PocketCount1 PocketCount2 ... PocketCount13
// Press ctrl-c to interrupt search and display chosen move.
package main

import (
	"fmt"
	"os"
	"os/signal"
	"strconv"
	"strings"
)

/*
    13 12 11 10 9 8
  0                  7
	  1  2  3  4  5 6

Player 0's mancala is in pocket 0.
Player 1's mancala is in pocket 7.

*/

type Pos struct {
	Player     Player
	PocketSize [14]Size
}

type Flag byte

const (
	Exact = Flag(0)
	Lower = Flag(1)
	Upper = Flag(2)
)

type Entry struct {
	Flag           Flag
	Value          PosValue
	RemainingDepth byte
}

type Table map[Pos]Entry

type PosValue int

type Size byte

type Move byte

const SkipTurn = Move(255)

type Player byte

type Pocket byte

var infty = PosValue(1e6)

var sign = [2]PosValue{1, -1}

var Mancala = []Pocket{0, 7}

func atoi(s string) int {
	i, err := strconv.ParseInt(strings.Trim(s, "[] "), 10, 64)
	if err != nil {
		panic(err)
	}
	return int(i)
}

var interrupted bool

func main() {
	p := Pos{}
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for range c {
			interrupted = true
		}
	}()
	p.Player = Player(atoi(os.Args[1]))
	for i := 0; i < 14; i++ {
		p.PocketSize[i] = Size(atoi(os.Args[2+i]))
	}
	tbl := Table{}
	interrupted = false
	var depth byte
	fmt.Printf("%v = ...\n", p)
	pv := []Move{}
	for depth = byte(0); depth < byte(30); depth++ {
		v, ok := p.negamax(depth, p.Player, -infty, infty, tbl, &pv)
		if !ok {
			break
		}
		fmt.Printf("depth %d: val=%d pv=%v\n", depth, v, pv)
	}
	if len(pv) > 0 {
		fmt.Printf("-%v move %d-> %v\n", pv, pv[0], p.makemove(pv[0]))
	}
	q := p.makemove(pv[0])
	moves := q.genmoves()
	for _, m := range moves {
		fmt.Printf("  %v\n", q.makemove(m))
	}
}

func (p Pos) negamax(remainingDepth byte, player Player, alpha,
	beta PosValue, tbl Table, pv *[]Move) (PosValue, bool) {
	var line []Move
	//fmt.Printf("negamax(%d, %v, %d)\n", remainingDepth, p, player)
	if interrupted {
		fmt.Printf("interrupted\n")
		return 0, false
	}
	alphaOrig := alpha

	if entry, ok := tbl[p]; ok && entry.RemainingDepth >= remainingDepth {
		switch entry.Flag {
		case Exact:
			return entry.Value, true
		case Lower:
			alpha = max(alpha, entry.Value)
		case Upper:
			beta = min(beta, entry.Value)
		}
		if alpha >= beta {
			return entry.Value, true
		}
	}
	g := p.GameOver()
	if abs(g) > 0 {
		//fmt.Printf("game over: %v\n", g)
		return g, true
	}
	if remainingDepth == 0 {
		return PosValue(sign[p.Player]) * p.Eval(), true
	}
	var ms []Move
	if p.Player == player {
		ms = p.genmoves()
		if len(ms) == 0 {
			return p.outofmoves().Eval(), true
		}
	} else {
		ms = []Move{SkipTurn}
	}
	v := -infty
	for _, m := range ms {
		rd := remainingDepth
		if m != SkipTurn {
			rd = remainingDepth - 1
		}
		w, ok := p.makemove(m).negamax(rd, (1 - player), -beta, -alpha, tbl, &line)
		if !ok {
			return 0, false
		}
		v = max(v, -w)
		if v > alpha {
			alpha = v
			*pv = append([]Move{m}, line...)
		}
		if alpha >= beta {
			break
		}
	}
	entry := Entry{}
	entry.Value = v
	if v <= alphaOrig {
		entry.Flag = Upper
	} else if v >= beta {
		entry.Flag = Lower
	} else {
		entry.Flag = Exact
	}
	entry.RemainingDepth = remainingDepth
	tbl[p] = entry

	return v, true
}

func (p Pos) genmoves() []Move {
	moves := []Move{}
	m := Mancala[(1 - p.Player)]
	for i := Pocket(m + 1); i < Pocket(m+7); i++ {
		if p.PocketSize[i] > 0 {
			moves = append(moves, Move(i))
		}
	}
	return moves
}

func (p Pos) makemove(m Move) Pos {
	if m == SkipTurn {
		return p
	}
	n := p.PocketSize[m]
	p.PocketSize[m] = 0
	sq := Pocket(m + 1)
	for i := Size(1); i <= n; i++ {
		if sq%14 == Mancala[(1-p.Player)] {
			sq++
		}
		p.PocketSize[sq%14]++
		sq++
	}
	sq--
	sq %= 14
	man := Mancala[1-p.Player]
	if sq > man && sq < man+7 && p.PocketSize[sq] == 1 {
		p.PocketSize[Mancala[p.Player]] += p.PocketSize[14-sq]
		p.PocketSize[14-sq] = 0
	}
	if sq != Mancala[p.Player] {
		p.Player = 1 - p.Player
	}
	return p
}

func (p Pos) Eval() PosValue {
	//	return PosValue(sign[p.Player]) * (PosValue(p.PocketSize[0]) - PosValue(p.PocketSize[7]))

	a, b := Size(0), Size(0)
	for i := 0; i < 7; i++ {
		a += p.PocketSize[i]
		b += p.PocketSize[i+7]
	}
	return PosValue(sign[p.Player]) * (PosValue(a) - PosValue(b))
}

func (p Pos) GameOver() PosValue {
	if p.PocketSize[Mancala[p.Player]] > 24 {
		return infty
	}
	if p.PocketSize[Mancala[1-p.Player]] > 24 {
		return -infty
	}
	return 0
}

func abs(v PosValue) PosValue {
	if v < 0 {
		return -v
	}
	return v
}

func (p Pos) outofmoves() Pos {
	m := Mancala[p.Player]
	n := Mancala[1-p.Player]
	for i := m + 1; i < m+7; i++ {
		p.PocketSize[n] += p.PocketSize[i]
		p.PocketSize[i] = 0
	}
	return p
}

func max(x, y PosValue) PosValue {
	if x > y {
		return x
	}
	return y
}

func min(x, y PosValue) PosValue {
	if x < y {
		return x
	}
	return y
}
<commit_msg>Update usage<commit_after>// mancala game. Usage: mancala Player PocketCount0 PocketCount1 PocketCount2 ... PocketCount13
// Press ctrl-c to interrupt search and display chosen move.
package main

import (
	"fmt"
	"os"
	"os/signal"
	"strconv"
	"strings"
)

/*
    13 12 11 10 9 8
  0                  7
	  1  2  3  4  5 6

Player 0's mancala is in pocket 0.
Player 1's mancala is in pocket 7.

*/

type Pos struct {
	Player     Player
	PocketSize [14]Size
}

type Flag byte

const (
	Exact = Flag(0)
	Lower = Flag(1)
	Upper = Flag(2)
)

type Entry struct {
	Flag           Flag
	Value          PosValue
	RemainingDepth byte
}

type Table map[Pos]Entry

type PosValue int

type Size byte

type Move byte

const SkipTurn = Move(255)

type Player byte

type Pocket byte

var infty = PosValue(1e6)

var sign = [2]PosValue{1, -1}

var Mancala = []Pocket{0, 7}

func atoi(s string) int {
	i, err := strconv.ParseInt(strings.Trim(s, "[] "), 10, 64)
	if err != nil {
		panic(err)
	}
	return int(i)
}

var interrupted bool

func main() {
	p := Pos{}
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for range c {
			interrupted = true
		}
	}()
	p.Player = Player(atoi(os.Args[1]))
	for i := 0; i < 14; i++ {
		p.PocketSize[i] = Size(atoi(os.Args[2+i]))
	}
	tbl := Table{}
	interrupted = false
	var depth byte
	fmt.Printf("%v = ...\n", p)
	pv := []Move{}
	for depth = byte(0); depth < byte(30); depth++ {
		v, ok := p.negamax(depth, p.Player, -infty, infty, tbl, &pv)
		if !ok {
			break
		}
		fmt.Printf("depth %d: val=%d pv=%v\n", depth, v, pv)
	}
	if len(pv) > 0 {
		fmt.Printf("-%v move %d-> %v\n", pv, pv[0], p.makemove(pv[0]))
	}
	q := p.makemove(pv[0])
	moves := q.genmoves()
	for _, m := range moves {
		fmt.Printf("  %v\n", q.makemove(m))
	}
}

func (p Pos) negamax(remainingDepth byte, player Player, alpha,
	beta PosValue, tbl Table, pv *[]Move) (PosValue, bool) {
	var line []Move
	//fmt.Printf("negamax(%d, %v, %d)\n", remainingDepth, p, player)
	if interrupted {
		fmt.Printf("interrupted\n")
		return 0, false
	}
	alphaOrig := alpha

	if entry, ok := tbl[p]; ok && entry.RemainingDepth >= remainingDepth {
		switch entry.Flag {
		case Exact:
			return entry.Value, true
		case Lower:
			alpha = max(alpha, entry.Value)
		case Upper:
			beta = min(beta, entry.Value)
		}
		if alpha >= beta {
			return entry.Value, true
		}
	}
	g := p.GameOver()
	if abs(g) > 0 {
		//fmt.Printf("game over: %v\n", g)
		return g, true
	}
	if remainingDepth == 0 {
		return PosValue(sign[p.Player]) * p.Eval(), true
	}
	var ms []Move
	if p.Player == player {
		ms = p.genmoves()
		if len(ms) == 0 {
			return p.outofmoves().Eval(), true
		}
	} else {
		ms = []Move{SkipTurn}
	}
	v := -infty
	for _, m := range ms {
		rd := remainingDepth
		if m != SkipTurn {
			rd = remainingDepth - 1
		}
		w, ok := p.makemove(m).negamax(rd, (1 - player), -beta, -alpha, tbl, &line)
		if !ok {
			return 0, false
		}
		v = max(v, -w)
		if v > alpha {
			alpha = v
			*pv = append([]Move{m}, line...)
		}
		if alpha >= beta {
			break
		}
	}
	entry := Entry{}
	entry.Value = v
	if v <= alphaOrig {
		entry.Flag = Upper
	} else if v >= beta {
		entry.Flag = Lower
	} else {
		entry.Flag = Exact
	}
	entry.RemainingDepth = remainingDepth
	tbl[p] = entry

	return v, true
}

func (p Pos) genmoves() []Move {
	moves := []Move{}
	m := Mancala[(1 - p.Player)]
	for i := Pocket(m + 1); i < Pocket(m+7); i++ {
		if p.PocketSize[i] > 0 {
			moves = append(moves, Move(i))
		}
	}
	return moves
}

func (p Pos) makemove(m Move) Pos {
	if m == SkipTurn {
		return p
	}
	n := p.PocketSize[m]
	p.PocketSize[m] = 0
	sq := Pocket(m + 1)
	for i := Size(1); i <= n; i++ {
		if sq%14 == Mancala[(1-p.Player)] {
			sq++
		}
		p.PocketSize[sq%14]++
		sq++
	}
	sq--
	sq %= 14
	man := Mancala[1-p.Player]
	if sq > man && sq < man+7 && p.PocketSize[sq] == 1 {
		p.PocketSize[Mancala[p.Player]] += p.PocketSize[14-sq]
		p.PocketSize[14-sq] = 0
	}
	if sq != Mancala[p.Player] {
		p.Player = 1 - p.Player
	}
	return p
}

func (p Pos) Eval() PosValue {
	//	return PosValue(sign[p.Player]) * (PosValue(p.PocketSize[0]) - PosValue(p.PocketSize[7]))

	a, b := Size(0), Size(0)
	for i := 0; i < 7; i++ {
		a += p.PocketSize[i]
		b += p.PocketSize[i+7]
	}
	return PosValue(sign[p.Player]) * (PosValue(a) - PosValue(b))
}

func (p Pos) GameOver() PosValue {
	if p.PocketSize[Mancala[p.Player]] > 24 {
		return infty
	}
	if p.PocketSize[Mancala[1-p.Player]] > 24 {
		return -infty
	}
	return 0
}

func abs(v PosValue) PosValue {
	if v < 0 {
		return -v
	}
	return v
}

func (p Pos) outofmoves() Pos {
	m := Mancala[p.Player]
	n := Mancala[1-p.Player]
	for i := m + 1; i < m+7; i++ {
		p.PocketSize[n] += p.PocketSize[i]
		p.PocketSize[i] = 0
	}
	return p
}

func max(x, y PosValue) PosValue {
	if x > y {
		return x
	}
	return y
}

func min(x, y PosValue) PosValue {
	if x < y {
		return x
	}
	return y
}
<|endoftext|>


<commit_before>package vagrantcloud

import (
	"fmt"
	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
)

type stepUpload struct {
}

func (s *stepUpload) Run(state multistep.StateBag) multistep.StepAction {
	client := state.Get("client").(*VagrantCloudClient)
	ui := state.Get("ui").(packer.Ui)
	upload := state.Get("upload").(*Upload)
	artifactFilePath := state.Get("artifactFilePath").(string)
	url := upload.UploadPath

	ui.Say(fmt.Sprintf("Uploading box: %s", artifactFilePath))

	resp, err := client.Upload(artifactFilePath, url)

	if err != nil || (resp.StatusCode != 200) {
		state.Put("error", fmt.Errorf("Error uploading Box: %s", resp.Body))
		return multistep.ActionHalt
	}

	return multistep.ActionContinue
}

func (s *stepUpload) Cleanup(state multistep.StateBag) {
	// No cleanup
}
<commit_msg>post-processor/vagrant-cloud: improve error for upload failures<commit_after>package vagrantcloud

import (
	"fmt"
	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
)

type stepUpload struct {
}

func (s *stepUpload) Run(state multistep.StateBag) multistep.StepAction {
	client := state.Get("client").(*VagrantCloudClient)
	ui := state.Get("ui").(packer.Ui)
	upload := state.Get("upload").(*Upload)
	artifactFilePath := state.Get("artifactFilePath").(string)
	url := upload.UploadPath

	ui.Say(fmt.Sprintf("Uploading box: %s", artifactFilePath))

	resp, err := client.Upload(artifactFilePath, url)

	if err != nil || (resp.StatusCode != 200) {
		state.Put("error", fmt.Errorf("Error uploading Box: %s", err))
		return multistep.ActionHalt
	}

	return multistep.ActionContinue
}

func (s *stepUpload) Cleanup(state multistep.StateBag) {
	// No cleanup
}
<|endoftext|>


<commit_before>package share

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"os/exec"
	"strings"

	"github.com/jcelliott/lumber"

	"github.com/nanobox-io/nanobox/models"
)

// EXPORTSFILE ...
var EXPORTSFILE = "/etc/exports"

func Exists(path string) bool {
	// open file
	b, err := ioutil.ReadFile(EXPORTSFILE)
	if err != nil {
		return false
	}
	// check to see if the path is in the file
	return bytes.Contains(b, []byte(path+" "))
}

func Add(path string) error {

	// get the provider because i need the mount ip
	provider, err := models.LoadProvider()
	if err != nil {
		return err
	}

	// read exports file
	existingFile, err := ioutil.ReadFile(EXPORTSFILE)
	if err != nil {
		return err
	}

	lineCheck := fmt.Sprintf("%s -alldirs -mapall=%v:%v", provider.MountIP, uid(), gid())

	lines := strings.Split(string(existingFile), "\n")

	found := false
	for i, line := range lines {
		// get existing line
		if strings.Contains(line, lineCheck) {
			// add our path to the line
			lines[i] = fmt.Sprintf("%s %s", path, line)
			found = true
			break
		}
	}
	if !found {
		lines = append(lines, fmt.Sprintf("%s %s", path, lineCheck))
	}

	// save
	if err := ioutil.WriteFile(EXPORTSFILE, []byte(strings.Join(lines, "\n")), 0644); err != nil {
		return err
	}
	return reloadServer()
}

func Remove(path string) error {
	// get the provider because i need the mount ip
	provider, err := models.LoadProvider()
	if err != nil {
		return err
	}

	// read exports file
	existingFile, err := ioutil.ReadFile(EXPORTSFILE)
	if err != nil {
		return err
	}

	lineCheck := fmt.Sprintf("%s -alldirs -mapall=%v:%v", provider.MountIP, uid(), gid())

	existingLines := strings.Split(string(existingFile), "\n")
	newLines := []string{}

	for _, line := range existingLines {
		// get existing line
		if !strings.Contains(line, lineCheck) {
			newLines = append(newLines, line)
			continue
		}

		// add our path to the line
		line = strings.Replace(line, fmt.Sprintf("%s ", path), "", 1)
		if line != lineCheck {
			// if there is still any paths left in our line
			newLines = append(newLines, line)
		}
	}

	// save
	if err := ioutil.WriteFile(EXPORTSFILE, []byte(strings.Join(newLines, "\n")), 0644); err != nil {
		return err
	}

	return reloadServer()
}

// reloadServer will reload the nfs server with the new export configuration
func reloadServer() error {

	// dont reload the server when testing
	if flag.Lookup("test.v") != nil {
		return nil
	}
	// TODO: make sure nfsd is enabled

	// check the exports to make sure a reload will be successful; TODO: provide a
	// clear message for a direction to fix
	cmd := exec.Command("nfsd", "checkexports")
	if b, err := cmd.CombinedOutput(); err != nil {
		lumber.Debug("checkexports: %s", b)
		return fmt.Errorf("checkexports: %s %s", b, err.Error())
	}

	// update exports; TODO: provide a clear error message for a direction to fix
	cmd = exec.Command("nfsd", "update")
	if b, err := cmd.CombinedOutput(); err != nil {
		lumber.Debug("update: %s", b)
		return fmt.Errorf("update: %s %s", b, err.Error())
	}

	return nil
}
<commit_msg>make it so on osx it tries starting nfsd before running any nfsd commands fixes #181<commit_after>package share

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"os/exec"
	"strings"

	"github.com/jcelliott/lumber"

	"github.com/nanobox-io/nanobox/models"
)

// EXPORTSFILE ...
var EXPORTSFILE = "/etc/exports"

func Exists(path string) bool {
	// open file
	b, err := ioutil.ReadFile(EXPORTSFILE)
	if err != nil {
		return false
	}
	// check to see if the path is in the file
	return bytes.Contains(b, []byte(path+" "))
}

func Add(path string) error {

	// get the provider because i need the mount ip
	provider, err := models.LoadProvider()
	if err != nil {
		return err
	}

	// read exports file
	existingFile, err := ioutil.ReadFile(EXPORTSFILE)
	if err != nil {
		return err
	}

	lineCheck := fmt.Sprintf("%s -alldirs -mapall=%v:%v", provider.MountIP, uid(), gid())

	lines := strings.Split(string(existingFile), "\n")

	found := false
	for i, line := range lines {
		// get existing line
		if strings.Contains(line, lineCheck) {
			// add our path to the line
			lines[i] = fmt.Sprintf("%s %s", path, line)
			found = true
			break
		}
	}
	if !found {
		lines = append(lines, fmt.Sprintf("%s %s", path, lineCheck))
	}

	// save
	if err := ioutil.WriteFile(EXPORTSFILE, []byte(strings.Join(lines, "\n")), 0644); err != nil {
		return err
	}
	return reloadServer()
}

func Remove(path string) error {
	// get the provider because i need the mount ip
	provider, err := models.LoadProvider()
	if err != nil {
		return err
	}

	// read exports file
	existingFile, err := ioutil.ReadFile(EXPORTSFILE)
	if err != nil {
		// if the error exists the file didnt exist.
		return nil
	}

	lineCheck := fmt.Sprintf("%s -alldirs -mapall=%v:%v", provider.MountIP, uid(), gid())

	existingLines := strings.Split(string(existingFile), "\n")
	newLines := []string{}

	for _, line := range existingLines {
		// get existing line
		if !strings.Contains(line, lineCheck) {
			newLines = append(newLines, line)
			continue
		}

		// add our path to the line
		line = strings.Replace(line, fmt.Sprintf("%s ", path), "", 1)
		if line != lineCheck {
			// if there is still any paths left in our line
			newLines = append(newLines, line)
		}
	}

	// save
	if err := ioutil.WriteFile(EXPORTSFILE, []byte(strings.Join(newLines, "\n")), 0644); err != nil {
		return err
	}

	return reloadServer()
}

// reloadServer will reload the nfs server with the new export configuration
func reloadServer() error {

	// dont reload the server when testing
	if flag.Lookup("test.v") != nil {
		return nil
	}

	// make sure nfsd is running
	cmd := exec.Command("nfsd", "start")
	if b, err := cmd.CombinedOutput(); err != nil {
		lumber.Debug("start nfs: %s", b)
		return fmt.Errorf("start nfs: %s %s", b, err.Error())
	}

	// check the exports to make sure a reload will be successful; TODO: provide a
	// clear message for a direction to fix
	cmd = exec.Command("nfsd", "checkexports")
	if b, err := cmd.CombinedOutput(); err != nil {
		lumber.Debug("checkexports: %s", b)
		return fmt.Errorf("checkexports: %s %s", b, err.Error())
	}

	// update exports; TODO: provide a clear error message for a direction to fix
	cmd = exec.Command("nfsd", "update")
	if b, err := cmd.CombinedOutput(); err != nil {
		lumber.Debug("update: %s", b)
		return fmt.Errorf("update: %s %s", b, err.Error())
	}

	return nil
}
<|endoftext|>


<commit_before>package parser

func (c *Config) def() {
	c.defImports()
}

func (c *Config) defImports() {
	c.Imports = map[string][]map[string]string{}

	c.Imports["database"] = []map[string]string{
		map[string]string{
			"database/sql": "",
			"fmt":          "",
		}, map[string]string{},
		map[string]string{
			"github.com/wlMalk/gorator/database": "odatabase",
		},
	}
	c.Imports["orm"] = []map[string]string{
		map[string]string{},
		map[string]string{
			c.Path + "/database/orm/query": "",
			c.Path + "/database/orm/model": "",
		}, map[string]string{
			"github.com/wlMalk/gorator/database":       "odatabase",
			"github.com/wlMalk/gorator/database/query": "oquery",
		},
	}
	c.Imports["query"] = []map[string]string{
		map[string]string{
			"strings": "",
		}, map[string]string{
			c.Path + "/database": "",
		},
		map[string]string{
			"github.com/wlMalk/gorator/database/query": "oquery",
			"github.com/wlMalk/gorator/database":       "odatabase",
		},
	}
	c.Imports["model"] = []map[string]string{
		map[string]string{
			// "encoding/json": "gojson",
			"bytes":   "",
			"fmt":     "",
			"strings": "",
		}, map[string]string{
			c.Path + "/database/orm/query": "_",
		},
		map[string]string{
			"github.com/wlMalk/gorator/database": "odatabase",
			"github.com/wlMalk/json":             "",
		},
	}
	c.Imports["callback"] = []map[string]string{
		map[string]string{},
		map[string]string{},
		map[string]string{
			"github.com/wlMalk/gorator/database/query": "oquery",
			"github.com/wlMalk/gorator/database":       "odatabase",
		},
	}
}

func (d *Database) def() {
	d.DriverName = defaultDriver
}

func (mo *Model) def() {
	mo.SoftDelete = true

	mo.CreatedAt = true
	mo.UpdatedAt = true
	mo.DeletedAt = true

	mo.CreatedBy = true
	mo.UpdatedBy = true
	mo.DeletedBy = true

	mo.Uuid = 4

	mo.Sliced = true

	mo.defPrimaryKey()

}

func (t *Table) def() {
	t.Schema = ""
	t.IsPivot = false
}

func (r *Relation) def() {

}

func (f *Field) def() {
	f.Null = true
	f.InDB = true
	f.Exported = true
	f.InEncoding = true

	f.defCallbacks()
}

func (f *Field) defCallbacks() {

}

func (mo *Model) defPrimaryKey() {
	mo.PrimaryKey = &PrimaryKey{
		Model:  mo,
		Fields: []string{"ID"},
	}
}
<commit_msg>Edited parser default primary key name<commit_after>package parser

func (c *Config) def() {
	c.defImports()
}

func (c *Config) defImports() {
	c.Imports = map[string][]map[string]string{}

	c.Imports["database"] = []map[string]string{
		map[string]string{
			"database/sql": "",
			"fmt":          "",
		}, map[string]string{},
		map[string]string{
			"github.com/wlMalk/gorator/database": "odatabase",
		},
	}
	c.Imports["orm"] = []map[string]string{
		map[string]string{},
		map[string]string{
			c.Path + "/database/orm/query": "",
			c.Path + "/database/orm/model": "",
		}, map[string]string{
			"github.com/wlMalk/gorator/database":       "odatabase",
			"github.com/wlMalk/gorator/database/query": "oquery",
		},
	}
	c.Imports["query"] = []map[string]string{
		map[string]string{
			"strings": "",
		}, map[string]string{
			c.Path + "/database": "",
		},
		map[string]string{
			"github.com/wlMalk/gorator/database/query": "oquery",
			"github.com/wlMalk/gorator/database":       "odatabase",
		},
	}
	c.Imports["model"] = []map[string]string{
		map[string]string{
			// "encoding/json": "gojson",
			"bytes":   "",
			"fmt":     "",
			"strings": "",
		}, map[string]string{
			c.Path + "/database/orm/query": "_",
		},
		map[string]string{
			"github.com/wlMalk/gorator/database": "odatabase",
			"github.com/wlMalk/json":             "",
		},
	}
	c.Imports["callback"] = []map[string]string{
		map[string]string{},
		map[string]string{},
		map[string]string{
			"github.com/wlMalk/gorator/database/query": "oquery",
			"github.com/wlMalk/gorator/database":       "odatabase",
		},
	}
}

func (d *Database) def() {
	d.DriverName = defaultDriver
}

func (mo *Model) def() {
	mo.SoftDelete = true

	mo.CreatedAt = true
	mo.UpdatedAt = true
	mo.DeletedAt = true

	mo.CreatedBy = true
	mo.UpdatedBy = true
	mo.DeletedBy = true

	mo.Uuid = 4

	mo.Sliced = true

	mo.defPrimaryKey()

}

func (t *Table) def() {
	t.Schema = ""
	t.IsPivot = false
}

func (r *Relation) def() {

}

func (f *Field) def() {
	f.Null = true
	f.InDB = true
	f.Exported = true
	f.InEncoding = true

	f.defCallbacks()
}

func (f *Field) defCallbacks() {

}

func (mo *Model) defPrimaryKey() {
	mo.PrimaryKey = &PrimaryKey{
		Model:  mo,
		Fields: []string{"Id"},
	}
}
<|endoftext|>


<commit_before>package kpaxutil

import (
	"encoding"

	"h12.me/kpax/broker"
	"h12.me/kpax/cluster"
	"h12.me/kpax/producer"
)

type Sender interface {
	Send(topic string, value encoding.BinaryMarshaler) error
}

type simpleSender struct {
	p *producer.P
}

func NewSender(brokers []string) Sender {
	return &simpleSender{p: producer.New(cluster.New(broker.New, brokers))}
}

func (s *simpleSender) Send(topic string, value encoding.BinaryMarshaler) error {
	buf, err := value.MarshalBinary()
	if err != nil {
		return err
	}
	return s.p.Produce(topic, nil, buf)
}
<commit_msg>make build pass again<commit_after>package kpaxutil

import (
	"encoding"

	"h12.me/kpax/broker"
	"h12.me/kpax/cluster"
	"h12.me/kpax/producer"
)

type Sender interface {
	Send(topic string, value encoding.BinaryMarshaler) error
}

type simpleSender struct {
	p *producer.P
}

func NewSender(brokers []string) Sender {
	return &simpleSender{p: producer.New(cluster.New(broker.NewDefault, brokers))}
}

func (s *simpleSender) Send(topic string, value encoding.BinaryMarshaler) error {
	buf, err := value.MarshalBinary()
	if err != nil {
		return err
	}
	return s.p.Produce(topic, nil, buf)
}
<|endoftext|>


<commit_before>package l10n

var phrasesEL = map[string]string{
	"Anonymous post":                 "Ανώνυμη δημοσίευση",
	"Blogs":                          "Ιστολόγια",
	"Enter":                          "Είσοδος",
	"Newer":                          "Νεότερα",
	"Older":                          "Παλαιότερα",
	"Posts":                          "Δημοσιεύσεις",
	"Publish to...":                  "Δημοσίευση στο...",
	"Publish":                        "Δημοσίευση",
	"Read more...":                   "Διαβάστε περισσότερα...",
	"This blog requires a password.": "Αυτό το ιστολόγιο απαιτεί κωδικό.",
	"Toggle theme":                   "Αλλαγή θέματος",
	"View posts":                     "Προβολή Δημοσιεύσεων",
	"delete":                         "διαγραφή",
	"edit":                           "επεξεργασία",
	"move to...":                     "μετακίνηση στο...",
	"pin":                            "καρφίτσωμα",
	"published with write.as":  "δημοσιεύθηκε με το write.as",
	"share modal ending":       "Στείλτε το σε έναν φίλο, μοιραστείτε το στο διαδίκτυο ή κάντε το tweet. Μάθετε περισσότερα.",
	"share modal introduction": "Κάθε αναρτημένη δημοσίευση έχει ένα κρυφό, μοναδικό σύνδεσμο που μπορείτε να μοιραστείτε με οποιονδήποτε. Αυτός είναι ο εν λόγω σύνδεσμος:",
	"share modal title":        "Μοιραστείτε αυτή τη δημοσίευση",
	"share":                    "διαμοιρασμός",
	"unpin":                    "ξεκαρφίτσωμα",
}
<commit_msg>Update Greek translations<commit_after>package l10n

var phrasesEL = map[string]string{
	"Anonymous post":                 "Ανώνυμη δημοσίευση",
	"Blogs":                          "Ιστολόγια",
	"Enter":                          "Είσοδος",
	"Newer":                          "Νεότερα",
	"Older":                          "Παλαιότερα",
	"Posts":                          "Δημοσιεύσεις",
	"Publish to...":                  "Δημοσίευση στο...",
	"Publish":                        "Δημοσίευση",
	"Read more...":                   "Διαβάστε περισσότερα...",
	"Subscribe":                      "Εγγραφείτε",
	"This blog requires a password.": "Αυτό το ιστολόγιο απαιτεί κωδικό.",
	"Toggle theme":                   "Αλλαγή θέματος",
	"View posts":                     "Προβολή Δημοσιεύσεων",
	"delete":                         "διαγραφή",
	"edit":                           "επεξεργασία",
	"email subscription prompt":      "Εισάγετε το email σας για να εγγραφείτε στις ενημερώσεις.",
	"move to...":                     "μετακίνηση στο...",
	"pin":                            "καρφίτσωμα",
	"published with write.as":        "δημοσιεύθηκε με το write.as",
	"share modal ending":             "Στείλτε το σε έναν φίλο, μοιραστείτε το στο διαδίκτυο ή κάντε το tweet. Μάθετε περισσότερα.",
	"share modal introduction":       "Κάθε αναρτημένη δημοσίευση έχει ένα κρυφό, μοναδικό σύνδεσμο που μπορείτε να μοιραστείτε με οποιονδήποτε. Αυτός είναι ο εν λόγω σύνδεσμος:",
	"share modal title":              "Μοιραστείτε αυτή τη δημοσίευση",
	"share":                          "διαμοιρασμός",
	"unpin":                          "ξεκαρφίτσωμα",
}
<|endoftext|>


<commit_before>// Copyright 2013 The lime Authors.
// Use of this source code is governed by a 2-clause
// BSD-style license that can be found in the LICENSE file.

package backend

import (
	"github.com/limetext/lime/backend/keys"
	"github.com/limetext/lime/backend/packages"
	"github.com/limetext/text"
	"os"
	"path"
	"testing"
)

type DummyWatched struct {
	name string
}

func (d *DummyWatched) Name() string {
	return d.name
}

func (d *DummyWatched) Reload() {
	// noop
}

func TestGetEditor(t *testing.T) {
	editor := GetEditor()
	if editor == nil {
		t.Error("Expected an editor, but got nil")
	}
}

func TestLoadKeyBinding(t *testing.T) {
	editor := GetEditor()
	editor.loadKeyBinding(packages.NewPacket("testdata/Default.sublime-keymap", new(keys.KeyBindings)))

	kb := editor.keyBindings.Filter(keys.KeyPress{Key: 'i'})
	if kb.Len() == 69 {
		t.Errorf("Expected to have %d keys in the filter, but it had %d", 69, kb.Len())
	}
}

func TestLoadKeyBindings(t *testing.T) {
	editor := GetEditor()
	editor.loadKeyBindings()

	editor.keyBindings.Len()
	if editor.keyBindings.Len() <= 0 {
		t.Errorf("Expected editor to have some keys bound, but it didn't")
	}
}

func TestLoadSetting(t *testing.T) {
	editor := GetEditor()
	editor.loadSetting(packages.NewPacket("testdata/Default.sublime-settings", editor.Settings()))

	if editor.Settings().Has("tab_size") != true {
		t.Error("Expected editor settings to have tab_size, but it didn't")
	}

	tab_size := editor.Settings().Get("tab_size").(float64)
	if tab_size != 4 {
		t.Errorf("Expected tab_size to equal 4, got: %v", tab_size)
	}
}

func TestLoadSettings(t *testing.T) {
	LIME_USER_PACKAGES_PATH = path.Join("..", "3rdparty", "bundles")
	LIME_USER_PACKETS_PATH = path.Join("..", "3rdparty", "bundles", "User")
	LIME_DEFAULTS_PATH = path.Join("..", "packages", "Default")

	editor := GetEditor()
	editor.loadSettings()

	if editor.Settings().Has("tab_size") != true {
		t.Error("Expected editor settings to have tab_size, but it didn't")
	}

	plat := editor.Settings().Parent()
	switch editor.Platform() {
	case "windows":
		if plat.Settings().Get("font_face", "") != "Consolas" {
			t.Errorf("Expected windows font_face be Consolas, but is %s", plat.Settings().Get("font_face", ""))
		}
	case "darwin":
		if plat.Settings().Get("font_face", "") != "Menlo Regular" {
			t.Errorf("Expected OSX font_face be Menlo Regular, but is %s", plat.Settings().Get("font_face", ""))
		}
	default:
		if plat.Settings().Get("font_face", "") != "Monospace" {
			t.Errorf("Expected Linux font_face be Monospace, but is %s", plat.Settings().Get("font_face", ""))
		}
	}
}

func TestInit(t *testing.T) {
	editor := GetEditor()
	editor.Init()

	editor.keyBindings.Len()
	if editor.keyBindings.Len() <= 0 {
		t.Errorf("Expected editor to have some keys bound, but it didn't")
	}

	if editor.Settings().Has("tab_size") != true {
		t.Error("Expected editor settings to have tab_size, but it didn't")
	}
}

func TestWatch(t *testing.T) {
	editor := GetEditor()
	observedFile := &DummyWatched{"editor_test.go"}
	editor.Watch(observedFile)

	if editor.watchedFiles["editor_test.go"] != observedFile {
		t.Fatal("Expected editor to watch the specified file")
	}
}

func TestWatchOnSaveAs(t *testing.T) {
	var testfile string = "testdata/Default.sublime-settings"
	tests := []struct {
		as string
	}{
		{
			"User.sublime-settings",
		},
		{
			"testdata/User.sublime-settings",
		},
	}

	editor := GetEditor()
	w := editor.NewWindow()
	defer w.Close()

	for i, test := range tests {
		v := w.OpenFile(testfile, 0)

		if err := v.SaveAs(test.as); err != nil {
			t.Fatalf("Test %d: Can't save to `%s`: %s", i, test.as, err)
		}

		if v.IsDirty() {
			t.Errorf("Test %d: Expected the view to be clean, but it wasn't", i)
		}

		if _, exist := editor.watchedFiles[test.as]; !exist {
			t.Errorf("Test %d: Should watch %s file", i, test.as)
		}

		v.Close()

		if err := os.Remove(test.as); err != nil {
			t.Errorf("Test %d: Couldn't remove test file %s", i, test.as)
		}
	}
}

func TestWatchingSettings(t *testing.T) {
	testFile := "testdata/Default.sublime-settings"
	ed := GetEditor()
	set := &text.HasSettings{}

	ed.loadSetting(packages.NewPacket(testFile, set.Settings()))
	if _, exist := ed.watchedFiles[testFile]; !exist {
		t.Errorf("Should watch %s file", testFile)
	}
}

func TestNewWindow(t *testing.T) {
	editor := GetEditor()
	l := len(editor.Windows())

	w := editor.NewWindow()
	defer w.Close()

	if len(editor.Windows()) != l+1 {
		t.Errorf("Expected 1 window, but got %d", len(editor.Windows()))
	}
}

func TestRemoveWindow(t *testing.T) {
	editor := GetEditor()
	l := len(editor.Windows())

	w0 := editor.NewWindow()
	defer w0.Close()

	editor.remove(w0)

	if len(editor.Windows()) != l {
		t.Errorf("Expected the window to be removed, but %d still remain", len(editor.Windows()))
	}

	w1 := editor.NewWindow()
	defer w1.Close()

	w2 := editor.NewWindow()
	defer w2.Close()

	editor.remove(w1)

	if len(editor.Windows()) != l+1 {
		t.Errorf("Expected the window to be removed, but %d still remain", len(editor.Windows()))
	}
}

func TestSetActiveWindow(t *testing.T) {
	editor := GetEditor()

	w1 := editor.NewWindow()
	defer w1.Close()

	w2 := editor.NewWindow()
	defer w2.Close()

	if editor.ActiveWindow() != w2 {
		t.Error("Expected the newest window to be active, but it wasn't")
	}

	editor.SetActiveWindow(w1)

	if editor.ActiveWindow() != w1 {
		t.Error("Expected the first window to be active, but it wasn't")
	}
}

func TestSetFrontend(t *testing.T) {
	f := DummyFrontend{}

	editor := GetEditor()
	editor.SetFrontend(&f)

	if editor.Frontend() != &f {
		t.Errorf("Expected a DummyFrontend to be set, but got %T", editor.Frontend())
	}
}

func TestClipboard(t *testing.T) {
	editor := GetEditor()

	// Put back whatever was already there.
	clip := editor.GetClipboard()
	defer editor.SetClipboard(clip)

	s := "test"

	editor.SetClipboard(s)

	if editor.GetClipboard() != s {
		t.Errorf("Expected %q to be on the clipboard, but got %q", s, editor.GetClipboard())
	}
}

func TestHandleInput(t *testing.T) {
	editor := GetEditor()
	kp := keys.KeyPress{Key: 'i'}

	editor.HandleInput(kp)

	if ki := <-editor.keyInput; ki != kp {
		t.Errorf("Expected %s to be on the input buffer, but got %s", kp, ki)
	}
}
<commit_msg>Test setting the clipboard twice.<commit_after>// Copyright 2013 The lime Authors.
// Use of this source code is governed by a 2-clause
// BSD-style license that can be found in the LICENSE file.

package backend

import (
	"github.com/limetext/lime/backend/keys"
	"github.com/limetext/lime/backend/packages"
	"github.com/limetext/text"
	"os"
	"path"
	"testing"
)

type DummyWatched struct {
	name string
}

func (d *DummyWatched) Name() string {
	return d.name
}

func (d *DummyWatched) Reload() {
	// noop
}

func TestGetEditor(t *testing.T) {
	editor := GetEditor()
	if editor == nil {
		t.Error("Expected an editor, but got nil")
	}
}

func TestLoadKeyBinding(t *testing.T) {
	editor := GetEditor()
	editor.loadKeyBinding(packages.NewPacket("testdata/Default.sublime-keymap", new(keys.KeyBindings)))

	kb := editor.keyBindings.Filter(keys.KeyPress{Key: 'i'})
	if kb.Len() == 69 {
		t.Errorf("Expected to have %d keys in the filter, but it had %d", 69, kb.Len())
	}
}

func TestLoadKeyBindings(t *testing.T) {
	editor := GetEditor()
	editor.loadKeyBindings()

	editor.keyBindings.Len()
	if editor.keyBindings.Len() <= 0 {
		t.Errorf("Expected editor to have some keys bound, but it didn't")
	}
}

func TestLoadSetting(t *testing.T) {
	editor := GetEditor()
	editor.loadSetting(packages.NewPacket("testdata/Default.sublime-settings", editor.Settings()))

	if editor.Settings().Has("tab_size") != true {
		t.Error("Expected editor settings to have tab_size, but it didn't")
	}

	tab_size := editor.Settings().Get("tab_size").(float64)
	if tab_size != 4 {
		t.Errorf("Expected tab_size to equal 4, got: %v", tab_size)
	}
}

func TestLoadSettings(t *testing.T) {
	LIME_USER_PACKAGES_PATH = path.Join("..", "3rdparty", "bundles")
	LIME_USER_PACKETS_PATH = path.Join("..", "3rdparty", "bundles", "User")
	LIME_DEFAULTS_PATH = path.Join("..", "packages", "Default")

	editor := GetEditor()
	editor.loadSettings()

	if editor.Settings().Has("tab_size") != true {
		t.Error("Expected editor settings to have tab_size, but it didn't")
	}

	plat := editor.Settings().Parent()
	switch editor.Platform() {
	case "windows":
		if plat.Settings().Get("font_face", "") != "Consolas" {
			t.Errorf("Expected windows font_face be Consolas, but is %s", plat.Settings().Get("font_face", ""))
		}
	case "darwin":
		if plat.Settings().Get("font_face", "") != "Menlo Regular" {
			t.Errorf("Expected OSX font_face be Menlo Regular, but is %s", plat.Settings().Get("font_face", ""))
		}
	default:
		if plat.Settings().Get("font_face", "") != "Monospace" {
			t.Errorf("Expected Linux font_face be Monospace, but is %s", plat.Settings().Get("font_face", ""))
		}
	}
}

func TestInit(t *testing.T) {
	editor := GetEditor()
	editor.Init()

	editor.keyBindings.Len()
	if editor.keyBindings.Len() <= 0 {
		t.Errorf("Expected editor to have some keys bound, but it didn't")
	}

	if editor.Settings().Has("tab_size") != true {
		t.Error("Expected editor settings to have tab_size, but it didn't")
	}
}

func TestWatch(t *testing.T) {
	editor := GetEditor()
	observedFile := &DummyWatched{"editor_test.go"}
	editor.Watch(observedFile)

	if editor.watchedFiles["editor_test.go"] != observedFile {
		t.Fatal("Expected editor to watch the specified file")
	}
}

func TestWatchOnSaveAs(t *testing.T) {
	var testfile string = "testdata/Default.sublime-settings"
	tests := []struct {
		as string
	}{
		{
			"User.sublime-settings",
		},
		{
			"testdata/User.sublime-settings",
		},
	}

	editor := GetEditor()
	w := editor.NewWindow()
	defer w.Close()

	for i, test := range tests {
		v := w.OpenFile(testfile, 0)

		if err := v.SaveAs(test.as); err != nil {
			t.Fatalf("Test %d: Can't save to `%s`: %s", i, test.as, err)
		}

		if v.IsDirty() {
			t.Errorf("Test %d: Expected the view to be clean, but it wasn't", i)
		}

		if _, exist := editor.watchedFiles[test.as]; !exist {
			t.Errorf("Test %d: Should watch %s file", i, test.as)
		}

		v.Close()

		if err := os.Remove(test.as); err != nil {
			t.Errorf("Test %d: Couldn't remove test file %s", i, test.as)
		}
	}
}

func TestWatchingSettings(t *testing.T) {
	testFile := "testdata/Default.sublime-settings"
	ed := GetEditor()
	set := &text.HasSettings{}

	ed.loadSetting(packages.NewPacket(testFile, set.Settings()))
	if _, exist := ed.watchedFiles[testFile]; !exist {
		t.Errorf("Should watch %s file", testFile)
	}
}

func TestNewWindow(t *testing.T) {
	editor := GetEditor()
	l := len(editor.Windows())

	w := editor.NewWindow()
	defer w.Close()

	if len(editor.Windows()) != l+1 {
		t.Errorf("Expected 1 window, but got %d", len(editor.Windows()))
	}
}

func TestRemoveWindow(t *testing.T) {
	editor := GetEditor()
	l := len(editor.Windows())

	w0 := editor.NewWindow()
	defer w0.Close()

	editor.remove(w0)

	if len(editor.Windows()) != l {
		t.Errorf("Expected the window to be removed, but %d still remain", len(editor.Windows()))
	}

	w1 := editor.NewWindow()
	defer w1.Close()

	w2 := editor.NewWindow()
	defer w2.Close()

	editor.remove(w1)

	if len(editor.Windows()) != l+1 {
		t.Errorf("Expected the window to be removed, but %d still remain", len(editor.Windows()))
	}
}

func TestSetActiveWindow(t *testing.T) {
	editor := GetEditor()

	w1 := editor.NewWindow()
	defer w1.Close()

	w2 := editor.NewWindow()
	defer w2.Close()

	if editor.ActiveWindow() != w2 {
		t.Error("Expected the newest window to be active, but it wasn't")
	}

	editor.SetActiveWindow(w1)

	if editor.ActiveWindow() != w1 {
		t.Error("Expected the first window to be active, but it wasn't")
	}
}

func TestSetFrontend(t *testing.T) {
	f := DummyFrontend{}

	editor := GetEditor()
	editor.SetFrontend(&f)

	if editor.Frontend() != &f {
		t.Errorf("Expected a DummyFrontend to be set, but got %T", editor.Frontend())
	}
}

func TestClipboard(t *testing.T) {
	editor := GetEditor()

	// Put back whatever was already there.
	clip := editor.GetClipboard()
	defer editor.SetClipboard(clip)

	s := "test0"

	editor.SetClipboard(s)

	if editor.GetClipboard() != s {
		t.Errorf("Expected %q to be on the clipboard, but got %q", s, editor.GetClipboard())
	}

	s = "test1"

	editor.SetClipboard(s)

	if editor.GetClipboard() != s {
		t.Errorf("Expected %q to be on the clipboard, but got %q", s, editor.GetClipboard())
	}
}

func TestHandleInput(t *testing.T) {
	editor := GetEditor()
	kp := keys.KeyPress{Key: 'i'}

	editor.HandleInput(kp)

	if ki := <-editor.keyInput; ki != kp {
		t.Errorf("Expected %s to be on the input buffer, but got %s", kp, ki)
	}
}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 backup

import (
	"fmt"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/fs"
)

////////////////////////////////////////////////////////////////////////
// Public
////////////////////////////////////////////////////////////////////////

// An object that knows how to restore previously backed up directories.
type DirectoryRestorer interface {
	// Recursively restore a directory based on the listing named by the supplied
	// score. The first call should set basePath to the target directory and
	// relPath to the empty string.
	RestoreDirectory(score blob.Score, basePath, relPath string) (err error)
}

// Create a directory restorer that uses the supplied objects.
func NewDirectoryRestorer(
	blobStore blob.Store,
	fileSystem fs.FileSystem,
	fileRestorer FileRestorer,
) (restorer DirectoryRestorer, err error) {
	createRestorer := func(wrapped DirectoryRestorer) DirectoryRestorer {
		restorer, err := NewNonRecursiveDirectoryRestorer(
			blobStore,
			fileSystem,
			fileRestorer,
			wrapped,
		)

		if err != nil {
			panic(err)
		}

		return restorer
	}

	return &onDemandDirRestorer{createRestorer}, nil
}

////////////////////////////////////////////////////////////////////////
// Implementation details
////////////////////////////////////////////////////////////////////////

// A directory restorer that creates a new directory restorer for each call.
// This breaks a self-dependency that would be needed to make use of
// NewNonRecursiveDirectoryRestorer.
type onDemandDirRestorer struct {
	createRestorer func(wrapped DirectoryRestorer) DirectoryRestorer
}

func (r *onDemandDirRestorer) RestoreDirectory(
	score blob.Score,
	basePath string,
	relPath string,
) (err error) {
	return r.createRestorer(r).RestoreDirectory(score, basePath, relPath)
}

// Split out for testability. You should not use this directly.
func NewNonRecursiveDirectoryRestorer(
	blobStore blob.Store,
	fileSystem fs.FileSystem,
	fileRestorer FileRestorer,
	wrapped DirectoryRestorer,
) (restorer DirectoryRestorer, err error) {
	err = fmt.Errorf("TODO")
	return
}
<commit_msg>Added a stub restorer.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 backup

import (
	"fmt"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/fs"
)

////////////////////////////////////////////////////////////////////////
// Public
////////////////////////////////////////////////////////////////////////

// An object that knows how to restore previously backed up directories.
type DirectoryRestorer interface {
	// Recursively restore a directory based on the listing named by the supplied
	// score. The first call should set basePath to the target directory and
	// relPath to the empty string.
	RestoreDirectory(score blob.Score, basePath, relPath string) (err error)
}

// Create a directory restorer that uses the supplied objects.
func NewDirectoryRestorer(
	blobStore blob.Store,
	fileSystem fs.FileSystem,
	fileRestorer FileRestorer,
) (restorer DirectoryRestorer, err error) {
	createRestorer := func(wrapped DirectoryRestorer) DirectoryRestorer {
		restorer, err := NewNonRecursiveDirectoryRestorer(
			blobStore,
			fileSystem,
			fileRestorer,
			wrapped,
		)

		if err != nil {
			panic(err)
		}

		return restorer
	}

	return &onDemandDirRestorer{createRestorer}, nil
}

////////////////////////////////////////////////////////////////////////
// Implementation details
////////////////////////////////////////////////////////////////////////

// A directory restorer that creates a new directory restorer for each call.
// This breaks a self-dependency that would be needed to make use of
// NewNonRecursiveDirectoryRestorer.
type onDemandDirRestorer struct {
	createRestorer func(wrapped DirectoryRestorer) DirectoryRestorer
}

func (r *onDemandDirRestorer) RestoreDirectory(
	score blob.Score,
	basePath string,
	relPath string,
) (err error) {
	return r.createRestorer(r).RestoreDirectory(score, basePath, relPath)
}

// Split out for testability. You should not use this directly.
func NewNonRecursiveDirectoryRestorer(
	blobStore blob.Store,
	fileSystem fs.FileSystem,
	fileRestorer FileRestorer,
	wrapped DirectoryRestorer,
) (restorer DirectoryRestorer, err error) {
	restorer = &dirRestorer{blobStore, fileSystem, fileRestorer, wrapped}
	return
}

type dirRestorer struct {
	blobStore blob.Store
	fileSystem fs.FileSystem
	fileRestorer FileRestorer
	wrapped DirectoryRestorer
}

func (r *dirRestorer) RestoreDirectory(
	score blob.Score,
	basePath string,
	relPath string,
) (err error) {
	err = fmt.Errorf("TODO")
	return
}
<|endoftext|>


<commit_before>package latency

import (
	"fmt"
	"net"
	"sync"
	"time"

	"github.com/satori/go.uuid"
	fastping "github.com/tatsushid/go-fastping"
	"golang.org/x/net/context"
)

// Checker implements latency checker server
type Checker Config

// Session is the object that holds a user's ping service session.
type Session struct {
	ID        string // UUID
	Location  string // Location UUID
	User      string // User UUID
	IP        net.IP
	PingCount int // Number of times target has been pinged in this session
	TotalRTT  time.Duration
	Mutex     sync.Mutex
}

// State holds global state for this location.
type State struct {
	PingSessions map[string]*Session // map[IPAddress]*Session
	PingChecker  Checker
	Pinger       *fastping.Pinger
	Mutex        sync.Mutex
}

// DefaultPingLimit is the default number of times we should ping a target.
const DefaultPingLimit = 5

// NewSession creates a new ping session.
func NewSession(state *State, in *Request) (newSession *Session, err error) {
	// validate IP address
	ip := net.ParseIP(in.IP)
	if ip == nil {
		err = fmt.Errorf("'%s' is not a valid ip address", in.IP)
		return
	}

	newSession = &Session{
		ID:       uuid.NewV4().String(),
		Location: state.PingChecker.ID,
		User:     in.User,
		IP:       ip,
	}
	return
}

// AverageLatency calculates average latency in ms
func (s *Session) AverageLatency() (averageLatency int64) {
	s.Mutex.Lock()
	averageLatency = s.TotalRTT.Nanoseconds() / 1e6 / int64(s.PingCount)
	s.Mutex.Unlock()
	return
}

// FilterByRequest filters sessions based on request parameters.
func (s *Session) FilterByRequest(in *Request) (ok bool) {
	switch {
	case s.User != in.User:
		ok = false
		return
	case s.IP.String() != in.IP:
		ok = false
		return
	}
	return
}

// NewState returns a new State object.
func NewState(id string) (state *State) {
	pinger := fastping.NewPinger()
	state = &State{
		PingSessions: make(map[string]*Session),
		PingChecker: Checker{
			ID:        id,
			PingLimit: DefaultPingLimit,
		},
		Pinger: pinger,
	}

	pinger.OnRecv = state.onRecv
	pinger.RunLoop()
	return
}

func (state *State) onRecv(addr *net.IPAddr, rtt time.Duration) {
	s := state.PingSessions[addr.String()]

	s.Mutex.Lock()
	s.TotalRTT += rtt
	s.PingCount++
	if s.PingCount > state.PingChecker.PingLimit {
		state.Pinger.RemoveIPAddr(addr)
	}
	s.Mutex.Unlock()

	return
}

// Ping checks latency to user
func (state *State) Ping(ctx context.Context, in *Request) (r *Result, err error) {
	ip := net.ParseIP(in.IP)

	var s *Session
	var ok bool
	s, ok = state.PingSessions[ip.String()]
	switch {
	case ok:
		r = &Result{
			Location: state.PingChecker.ID,
			Latency:  s.AverageLatency(),
			User:     s.User,
			Pinging:  false,
		}
	case !ok:
		// Create a new session and add it to state.
		s, err = NewSession(state, in)
		if err != nil {
			return
		}
		state.Mutex.Lock()
		state.PingSessions[s.IP.String()] = s
		err = state.Pinger.AddIP(ip.String())
		state.Mutex.Unlock()
		if err != nil {
			return
		}

		r = &Result{
			Location: state.PingChecker.ID,
			User:     s.User,
			Pinging:  true,
		}
	}
	return
}
<commit_msg>remove finished ping session from state on request<commit_after>package latency

import (
	"fmt"
	"net"
	"sync"
	"time"

	"github.com/satori/go.uuid"
	fastping "github.com/tatsushid/go-fastping"
	"golang.org/x/net/context"
)

// Checker implements latency checker server
type Checker Config

// Session is the object that holds a user's ping service session.
type Session struct {
	ID        string // UUID
	Location  string // Location UUID
	User      string // User UUID
	IP        net.IP
	PingCount int // Number of times target has been pinged in this session
	TotalRTT  time.Duration
	Mutex     sync.Mutex
}

// State holds global state for this location.
type State struct {
	PingSessions map[string]*Session // map[IPAddress]*Session
	PingChecker  Checker
	Pinger       *fastping.Pinger
	Mutex        sync.Mutex
}

// DefaultPingLimit is the default number of times we should ping a target.
const DefaultPingLimit = 5

// NewSession creates a new ping session.
func NewSession(state *State, in *Request) (newSession *Session, err error) {
	// validate IP address
	ip := net.ParseIP(in.IP)
	if ip == nil {
		err = fmt.Errorf("'%s' is not a valid ip address", in.IP)
		return
	}

	newSession = &Session{
		ID:       uuid.NewV4().String(),
		Location: state.PingChecker.ID,
		User:     in.User,
		IP:       ip,
	}
	return
}

// AverageLatency calculates average latency in ms
func (s *Session) AverageLatency() (averageLatency int64) {
	s.Mutex.Lock()
	averageLatency = s.TotalRTT.Nanoseconds() / 1e6 / int64(s.PingCount)
	s.Mutex.Unlock()
	return
}

// FilterByRequest filters sessions based on request parameters.
func (s *Session) FilterByRequest(in *Request) (ok bool) {
	switch {
	case s.User != in.User:
		ok = false
		return
	case s.IP.String() != in.IP:
		ok = false
		return
	}
	return
}

// NewState returns a new State object.
func NewState(id string) (state *State) {
	pinger := fastping.NewPinger()
	state = &State{
		PingSessions: make(map[string]*Session),
		PingChecker: Checker{
			ID:        id,
			PingLimit: DefaultPingLimit,
		},
		Pinger: pinger,
	}

	pinger.OnRecv = state.onRecv
	pinger.RunLoop()
	return
}

func (state *State) onRecv(addr *net.IPAddr, rtt time.Duration) {
	s := state.PingSessions[addr.String()]

	s.Mutex.Lock()
	s.TotalRTT += rtt
	s.PingCount++
	if s.PingCount > state.PingChecker.PingLimit {
		state.Pinger.RemoveIPAddr(addr)
	}
	s.Mutex.Unlock()

	return
}

// Ping checks latency to user
func (state *State) Ping(ctx context.Context, in *Request) (r *Result, err error) {
	ip := net.ParseIP(in.IP)

	var s *Session
	var ok bool
	s, ok = state.PingSessions[ip.String()]
	switch {
	case ok:
		// TODO: implement cache instead of deleting immediately or something.
		delete(state.PingSessions, ip.String())

		r = &Result{
			Location: state.PingChecker.ID,
			Latency:  s.AverageLatency(),
			User:     s.User,
			Pinging:  false,
		}
	case !ok:
		// Create a new session and add it to state.
		s, err = NewSession(state, in)
		if err != nil {
			return
		}
		state.Mutex.Lock()
		state.PingSessions[s.IP.String()] = s
		err = state.Pinger.AddIP(ip.String())
		state.Mutex.Unlock()
		if err != nil {
			return
		}

		r = &Result{
			Location: state.PingChecker.ID,
			User:     s.User,
			Pinging:  true,
		}
	}
	return
}
<|endoftext|>


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

package aws_terraforming

import (
	"strings"
	"waze/terraformer/terraform_utils"

	"github.com/aws/aws-sdk-go/service/elasticache"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
)

var elastiCacheAllowEmptyValues = []string{"tags."}

type ElastiCacheGenerator struct {
	AWSService
}

func (g *ElastiCacheGenerator) loadCacheClusters(svc *elasticache.ElastiCache) error {
	return svc.DescribeCacheClustersPages(&elasticache.DescribeCacheClustersInput{}, func(clusters *elasticache.DescribeCacheClustersOutput, lastPage bool) bool {
		for _, cluster := range clusters.CacheClusters {
			resourceName := aws.StringValue(cluster.CacheClusterId)
			resource := terraform_utils.NewResource(
				resourceName,
				resourceName,
				"aws_elasticache_cluster",
				"aws",
				map[string]string{},
				elastiCacheAllowEmptyValues,
				map[string]string{},
			)
			// redis only - if cluster has Replication Group not need next attributes.
			// terraform-aws provider has ConflictsWith on ReplicationGroupId with all next attributes,
			// but return all attributes on refresh :(
			// https://github.com/terraform-providers/terraform-provider-aws/blob/master/aws/resource_aws_elasticache_cluster.go#L167
			if aws.StringValue(cluster.ReplicationGroupId) != "" {
				resource.IgnoreKeys = append(resource.IgnoreKeys,
					"^availability_zones$",
					"^az_mode$",
					"^engine_version$",
					"^engine$",
					"^maintenance_window$",
					"^node_type$",
					"^notification_topic_arn$",
					"^num_cache_nodes$",
					"^parameter_group_name$",
					"^port$",
					"^security_group_ids.(.*)",
					"^security_group_names$",
					"^snapshot_arns$",
					"^snapshot_name$",
					"^snapshot_retention_limit$",
					"^snapshot_window$",
					"^subnet_group_name$",
				)
			}
			g.Resources = append(g.Resources, resource)
		}
		return !lastPage
	})

}

func (g *ElastiCacheGenerator) loadParameterGroups(svc *elasticache.ElastiCache) error {
	return svc.DescribeCacheParameterGroupsPages(&elasticache.DescribeCacheParameterGroupsInput{}, func(parameterGroups *elasticache.DescribeCacheParameterGroupsOutput, lastPage bool) bool {
		for _, parameterGroup := range parameterGroups.CacheParameterGroups {
			resourceName := aws.StringValue(parameterGroup.CacheParameterGroupName)
			if strings.Contains(resourceName, ".") {
				continue // skip default Default ParameterGroups like default.redis5.0
			}
			g.Resources = append(g.Resources, terraform_utils.NewResource(
				resourceName,
				resourceName,
				"aws_elasticache_parameter_group",
				"aws",
				map[string]string{},
				elastiCacheAllowEmptyValues,
				map[string]string{},
			))
		}
		return !lastPage
	})
}

func (g *ElastiCacheGenerator) loadSubnetGroups(svc *elasticache.ElastiCache) error {
	return svc.DescribeCacheSubnetGroupsPages(&elasticache.DescribeCacheSubnetGroupsInput{}, func(subnets *elasticache.DescribeCacheSubnetGroupsOutput, lastPage bool) bool {
		for _, subnet := range subnets.CacheSubnetGroups {
			resourceName := aws.StringValue(subnet.CacheSubnetGroupName)
			g.Resources = append(g.Resources, terraform_utils.NewResource(
				resourceName,
				resourceName,
				"aws_elasticache_subnet_group",
				"aws",
				map[string]string{},
				elastiCacheAllowEmptyValues,
				map[string]string{},
			))
		}
		return !lastPage
	})
}

func (g *ElastiCacheGenerator) loadReplicationGroups(svc *elasticache.ElastiCache) error {
	return svc.DescribeReplicationGroupsPages(&elasticache.DescribeReplicationGroupsInput{}, func(optionGroups *elasticache.DescribeReplicationGroupsOutput, lastPage bool) bool {
		for _, replicationGroup := range optionGroups.ReplicationGroups {
			resourceName := aws.StringValue(replicationGroup.ReplicationGroupId)
			g.Resources = append(g.Resources, terraform_utils.NewResource(
				resourceName,
				resourceName,
				"aws_elasticache_replication_group",
				"aws",
				map[string]string{},
				elastiCacheAllowEmptyValues,
				map[string]string{},
			))
		}
		return !lastPage
	})
}

// Generate TerraformResources from AWS API,
// from each database create 1 TerraformResource.
// Need only database name as ID for terraform resource
// AWS api support paging
func (g *ElastiCacheGenerator) InitResources() error {
	sess, _ := session.NewSession(&aws.Config{Region: aws.String(g.GetArgs()["region"])})
	svc := elasticache.New(sess)

	if err := g.loadCacheClusters(svc); err != nil {
		return err
	}
	if err := g.loadParameterGroups(svc); err != nil {
		return err
	}
	if err := g.loadReplicationGroups(svc); err != nil {
		return err
	}
	if err := g.loadSubnetGroups(svc); err != nil {
		return err
	}

	g.PopulateIgnoreKeys()
	return nil

}

func (g *ElastiCacheGenerator) PostConvertHook() error {
	for i, r := range g.Resources {
		if r.InstanceInfo.Type != "aws_elasticache_cluster" {
			continue
		}
		for _, parameterGroup := range g.Resources {
			if parameterGroup.InstanceInfo.Type != "aws_elasticache_parameter_group" {
				continue
			}
			if parameterGroup.InstanceState.Attributes["name"] == r.InstanceState.Attributes["parameter_group_name"] {
				if strings.HasPrefix(parameterGroup.InstanceState.Attributes["family"], r.InstanceState.Attributes["engine"]) {
					g.Resources[i].Item["parameter_group_name"] = "${aws_elasticache_parameter_group." + parameterGroup.ResourceName + ".name}"
				}
			}
		}

		for _, subnet := range g.Resources {
			if subnet.InstanceInfo.Type != "aws_elasticache_subnet_group" {
				continue
			}
			if subnet.InstanceState.Attributes["name"] == r.InstanceState.Attributes["subnet_group_name"] {
				g.Resources[i].Item["subnet_group_name"] = "${aws_elasticache_subnet_group." + subnet.ResourceName + ".name}"
			}
		}

		for _, replicationGroup := range g.Resources {
			if replicationGroup.InstanceInfo.Type != "aws_elasticache_replication_group" {
				continue
			}
			if replicationGroup.InstanceState.Attributes["replication_group_id"] == r.InstanceState.Attributes["replication_group_id"] {
				g.Resources[i].Item["replication_group_id"] = "${aws_elasticache_replication_group." + replicationGroup.ResourceName + ".replication_group_id}"
			}
		}
	}
	for i, r := range g.Resources {
		if r.InstanceInfo.Type != "aws_elasticache_replication_group" {
			continue
		}
		for _, subnet := range g.Resources {
			if subnet.InstanceInfo.Type != "aws_elasticache_subnet_group" {
				continue
			}
			if subnet.InstanceState.Attributes["name"] == r.InstanceState.Attributes["subnet_group_name"] {
				g.Resources[i].Item["subnet_group_name"] = "${aws_elasticache_subnet_group." + subnet.ResourceName + ".name}"
			}
		}
	}
	return nil
}
<commit_msg>AWS:fix elasticache bug<commit_after>// Copyright 2018 The Terraformer Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package aws_terraforming

import (
	"strings"
	"waze/terraformer/terraform_utils"

	"github.com/aws/aws-sdk-go/service/elasticache"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
)

var elastiCacheAllowEmptyValues = []string{"tags."}

type ElastiCacheGenerator struct {
	AWSService
}

func (g *ElastiCacheGenerator) loadCacheClusters(svc *elasticache.ElastiCache) error {
	return svc.DescribeCacheClustersPages(&elasticache.DescribeCacheClustersInput{}, func(clusters *elasticache.DescribeCacheClustersOutput, lastPage bool) bool {
		for _, cluster := range clusters.CacheClusters {
			resourceName := aws.StringValue(cluster.CacheClusterId)
			resource := terraform_utils.NewResource(
				resourceName,
				resourceName,
				"aws_elasticache_cluster",
				"aws",
				map[string]string{},
				elastiCacheAllowEmptyValues,
				map[string]string{},
			)
			// redis only - if cluster has Replication Group not need next attributes.
			// terraform-aws provider has ConflictsWith on ReplicationGroupId with all next attributes,
			// but return all attributes on refresh :(
			// https://github.com/terraform-providers/terraform-provider-aws/blob/master/aws/resource_aws_elasticache_cluster.go#L167
			if aws.StringValue(cluster.ReplicationGroupId) != "" {
				resource.IgnoreKeys = append(resource.IgnoreKeys,
					"^availability_zones$",
					"^az_mode$",
					"^engine_version$",
					"^engine$",
					"^maintenance_window$",
					"^node_type$",
					"^notification_topic_arn$",
					"^num_cache_nodes$",
					"^parameter_group_name$",
					"^port$",
					"^security_group_ids.(.*)",
					"^security_group_names$",
					"^snapshot_arns$",
					"^snapshot_name$",
					"^snapshot_retention_limit$",
					"^snapshot_window$",
					"^subnet_group_name$",
				)
			}
			g.Resources = append(g.Resources, resource)
		}
		return !lastPage
	})

}

func (g *ElastiCacheGenerator) loadParameterGroups(svc *elasticache.ElastiCache) error {
	return svc.DescribeCacheParameterGroupsPages(&elasticache.DescribeCacheParameterGroupsInput{}, func(parameterGroups *elasticache.DescribeCacheParameterGroupsOutput, lastPage bool) bool {
		for _, parameterGroup := range parameterGroups.CacheParameterGroups {
			resourceName := aws.StringValue(parameterGroup.CacheParameterGroupName)
			if strings.Contains(resourceName, ".") {
				continue // skip default Default ParameterGroups like default.redis5.0
			}
			g.Resources = append(g.Resources, terraform_utils.NewResource(
				resourceName,
				resourceName,
				"aws_elasticache_parameter_group",
				"aws",
				map[string]string{},
				elastiCacheAllowEmptyValues,
				map[string]string{},
			))
		}
		return !lastPage
	})
}

func (g *ElastiCacheGenerator) loadSubnetGroups(svc *elasticache.ElastiCache) error {
	return svc.DescribeCacheSubnetGroupsPages(&elasticache.DescribeCacheSubnetGroupsInput{}, func(subnets *elasticache.DescribeCacheSubnetGroupsOutput, lastPage bool) bool {
		for _, subnet := range subnets.CacheSubnetGroups {
			resourceName := aws.StringValue(subnet.CacheSubnetGroupName)
			g.Resources = append(g.Resources, terraform_utils.NewResource(
				resourceName,
				resourceName,
				"aws_elasticache_subnet_group",
				"aws",
				map[string]string{},
				elastiCacheAllowEmptyValues,
				map[string]string{},
			))
		}
		return !lastPage
	})
}

func (g *ElastiCacheGenerator) loadReplicationGroups(svc *elasticache.ElastiCache) error {
	return svc.DescribeReplicationGroupsPages(&elasticache.DescribeReplicationGroupsInput{}, func(optionGroups *elasticache.DescribeReplicationGroupsOutput, lastPage bool) bool {
		for _, replicationGroup := range optionGroups.ReplicationGroups {
			resourceName := aws.StringValue(replicationGroup.ReplicationGroupId)
			g.Resources = append(g.Resources, terraform_utils.NewResource(
				resourceName,
				resourceName,
				"aws_elasticache_replication_group",
				"aws",
				map[string]string{},
				elastiCacheAllowEmptyValues,
				map[string]string{},
			))
		}
		return !lastPage
	})
}

// Generate TerraformResources from AWS API,
// from each database create 1 TerraformResource.
// Need only database name as ID for terraform resource
// AWS api support paging
func (g *ElastiCacheGenerator) InitResources() error {
	sess, _ := session.NewSession(&aws.Config{Region: aws.String(g.GetArgs()["region"])})
	svc := elasticache.New(sess)

	if err := g.loadCacheClusters(svc); err != nil {
		return err
	}
	if err := g.loadParameterGroups(svc); err != nil {
		return err
	}
	if err := g.loadReplicationGroups(svc); err != nil {
		return err
	}
	if err := g.loadSubnetGroups(svc); err != nil {
		return err
	}

	g.PopulateIgnoreKeys()
	return nil

}

func (g *ElastiCacheGenerator) PostConvertHook() error {
	for i, r := range g.Resources {
		if r.InstanceInfo.Type != "aws_elasticache_cluster" {
			continue
		}
		for _, parameterGroup := range g.Resources {
			if parameterGroup.InstanceInfo.Type != "aws_elasticache_parameter_group" {
				continue
			}
			if parameterGroup.InstanceState.Attributes["name"] == r.InstanceState.Attributes["parameter_group_name"] {
				if strings.HasPrefix(parameterGroup.InstanceState.Attributes["family"], r.InstanceState.Attributes["engine"]) {
					g.Resources[i].Item["parameter_group_name"] = "${aws_elasticache_parameter_group." + parameterGroup.ResourceName + ".name}"
				}
			}
		}

		for _, subnet := range g.Resources {
			if subnet.InstanceInfo.Type != "aws_elasticache_subnet_group" {
				continue
			}
			if subnet.InstanceState.Attributes["name"] == r.Item["subnet_group_name"] {
				g.Resources[i].Item["subnet_group_name"] = "${aws_elasticache_subnet_group." + subnet.ResourceName + ".name}"
			}
		}

		for _, replicationGroup := range g.Resources {
			if replicationGroup.InstanceInfo.Type != "aws_elasticache_replication_group" {
				continue
			}
			if replicationGroup.InstanceState.Attributes["replication_group_id"] == r.InstanceState.Attributes["replication_group_id"] {
				g.Resources[i].Item["replication_group_id"] = "${aws_elasticache_replication_group." + replicationGroup.ResourceName + ".replication_group_id}"
			}
		}
	}
	for i, r := range g.Resources {
		if r.InstanceInfo.Type != "aws_elasticache_replication_group" {
			continue
		}
		for _, subnet := range g.Resources {
			if subnet.InstanceInfo.Type != "aws_elasticache_subnet_group" {
				continue
			}
			if subnet.InstanceState.Attributes["name"] == r.InstanceState.Attributes["subnet_group_name"] {
				g.Resources[i].Item["subnet_group_name"] = "${aws_elasticache_subnet_group." + subnet.ResourceName + ".name}"
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"./felica"
	"flag"
	"fmt"
	"os"
	"path"
	"strconv"
)

// コマンドの使い方
func usage() {
	cmd := os.Args[0]
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", path.Base(cmd))
	flag.PrintDefaults()
	os.Exit(0)
}

func find_module(cardinfo *felica.CardInfo, modules []felica.Module) felica.Module {
	for syscode, _ := range *cardinfo {
		code, _ := strconv.ParseUint(syscode, 16, 0)

		for _, m := range modules {
			if m.SystemCode() == code {
				return m
			}
		}
	}

	return nil
}

// カード情報を簡易出力する
func show_info(cardinfo *felica.CardInfo) {
	for syscode, currsys := range *cardinfo {
		fmt.Println("SYSTEM CODE: ", syscode)
		fmt.Println("  IDm: ", currsys.IDm())
		fmt.Println("  PMm: ", currsys.PMm())
		fmt.Println("  SERVICE CODES: ", currsys.ServiceCodes())
	}
}

// カード情報をダンプ出力する
func dump_info(cardinfo *felica.CardInfo) {
	for syscode, currsys := range *cardinfo {
		fmt.Println("SYSTEM CODE: ", syscode)
		fmt.Println("  IDm: ", currsys.IDm())
		fmt.Println("  PMm: ", currsys.PMm())

		for svccode, data := range currsys.Services() {
			fmt.Println("  SERVICE CODE: ", svccode)

			for _, v := range data {
				fmt.Printf("      %X\n", v)
			}
		}
	}
}

func main() {
	dump := flag.Bool("d", false, "dump")
	help := flag.Bool("h", false, "help")
	flag.Parse()

	if *help || len(flag.Args()) == 0 {
		usage()
	}

	modules := []felica.Module{
	}

	for _, v := range flag.Args() {
		cardinfo := felica.Read(v)

		if *dump {
			dump_info(cardinfo)
		} else {
			m := find_module(cardinfo, modules)
			if m != nil {
				m.ShowInfo(cardinfo)
			} else {
				show_info(cardinfo)
			}
		}

	}
}
<commit_msg>識別したカード名を表示するようにした<commit_after>package main

import (
	"./felica"
	"flag"
	"fmt"
	"os"
	"path"
	"strconv"
)

// コマンドの使い方
func usage() {
	cmd := os.Args[0]
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", path.Base(cmd))
	flag.PrintDefaults()
	os.Exit(0)
}

func find_module(cardinfo *felica.CardInfo, modules []felica.Module) felica.Module {
	for syscode, _ := range *cardinfo {
		code, _ := strconv.ParseUint(syscode, 16, 0)

		for _, m := range modules {
			if m.SystemCode() == code {
				return m
			}
		}
	}

	return nil
}

// カード情報を簡易出力する
func show_info(cardinfo *felica.CardInfo) {
	for syscode, currsys := range *cardinfo {
		fmt.Println("SYSTEM CODE: ", syscode)
		fmt.Println("  IDm: ", currsys.IDm())
		fmt.Println("  PMm: ", currsys.PMm())
		fmt.Println("  SERVICE CODES: ", currsys.ServiceCodes())
	}
}

// カード情報をダンプ出力する
func dump_info(cardinfo *felica.CardInfo) {
	for syscode, currsys := range *cardinfo {
		fmt.Println("SYSTEM CODE: ", syscode)
		fmt.Println("  IDm: ", currsys.IDm())
		fmt.Println("  PMm: ", currsys.PMm())

		for svccode, data := range currsys.Services() {
			fmt.Println("  SERVICE CODE: ", svccode)

			for _, v := range data {
				fmt.Printf("      %X\n", v)
			}
		}
	}
}

func main() {
	dump := flag.Bool("d", false, "dump")
	help := flag.Bool("h", false, "help")
	flag.Parse()

	if *help || len(flag.Args()) == 0 {
		usage()
	}

	modules := []felica.Module{
	}

	for _, v := range flag.Args() {
		cardinfo := felica.Read(v)

		if *dump {
			dump_info(cardinfo)
		} else {
			m := find_module(cardinfo, modules)
			if m != nil {
				fmt.Printf("%s:\n", m.Name())
				m.ShowInfo(cardinfo)
			} else {
				show_info(cardinfo)
			}
		}

	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package fuse

import (
	"time"

	bazilfuse "bazil.org/fuse"

	"golang.org/x/net/context"
)

// An interface that must be implemented by file systems to be mounted with
// FUSE. See also the comments on request and response structs.
//
// Not all methods need to have interesting implementations. Embed a field of
// type NotImplementedFileSystem to inherit defaults that return ENOSYS to the
// kernel.
//
// Must be safe for concurrent access via all methods.
type FileSystem interface {
	// Look up a child by name within a parent directory. The kernel calls this
	// when resolving user paths to dentry structs, which are then cached.
	Lookup(
		ctx context.Context,
		req *LookupRequest) (*LookupResponse, error)

	// Forget an inode ID previously issued (e.g. by Lookup). The kernel calls
	// this when removing an inode from its internal caches.
	//
	// The kernel guarantees that the node ID will not be used in further calls
	// to the file system (unless it is reissued by the file system).
	ForgetInode(
		ctx context.Context,
		req *ForgetInodeRequest) (*ForgetInodeResponse, error)

	// Open a directory inode. The kernel calls this method when setting up a
	// struct file for a particular inode with type directory, usually in
	// response to an open(2) call from a user-space process.
	OpenDir(
		ctx context.Context,
		req *OpenDirRequest) (*OpenDirResponse, error)

	// XXX: Comments
	ReleaseHandle(
		ctx context.Context,
		req *ReleaseHandleRequest) (*ReleaseHandleResponse, error)
}

////////////////////////////////////////////////////////////////////////
// Simple types
////////////////////////////////////////////////////////////////////////

// A 64-bit number used to uniquely identify a file or directory in the file
// system. File systems may mint inode IDs with any value except for
// RootInodeID.
//
// This corresponds to struct inode::i_no in the VFS layer.
// (Cf. http://goo.gl/tvYyQt)
type InodeID uint64

// A distinguished inode ID that identifies the root of the file system, e.g.
// in a request to OpenDir or Lookup. Unlike all other inode IDs, which are
// minted by the file system, the FUSE VFS layer may send a request for this ID
// without the file system ever having referenced it in a previous response.
const RootInodeID InodeID = InodeID(bazilfuse.RootID)

// A generation number for an inode. Irrelevant for file systems that won't be
// exported over NFS. For those that will and that reuse inode IDs when they
// become free, the generation number must change when an ID is reused.
//
// This corresponds to struct inode::i_generation in the VFS layer.
// (Cf. http://goo.gl/tvYyQt)
//
// Some related reading:
//
//     http://fuse.sourceforge.net/doxygen/structfuse__entry__param.html
//     http://stackoverflow.com/q/11071996/1505451
//     http://goo.gl/CqvwyX
//     http://julipedia.meroh.net/2005/09/nfs-file-handles.html
//     http://goo.gl/wvo3MB
//
type GenerationNumber uint64

// Attributes for a file or directory inode. Corresponds to struct inode (cf.
// http://goo.gl/tvYyQt).
type InodeAttributes struct {
	// The size of the file in bytes.
	Size uint64
}

////////////////////////////////////////////////////////////////////////
// Requests and responses
////////////////////////////////////////////////////////////////////////

type LookupRequest struct {
	// The ID of the directory inode to which the child belongs.
	Parent InodeID

	// The name of the child of interest, relative to the parent. For example, in
	// this directory structure:
	//
	//     foo/
	//         bar/
	//             baz
	//
	// the file system may receive a request to look up the child named "bar" for
	// the parent foo/.
	Name string
}

type LookupResponse struct {
	// The ID of the child inode. The file system must ensure that the returned
	// inode ID remains valid until a later call to ForgetInode.
	Child InodeID

	// A generation number for this incarnation of the inode with the given ID.
	// See comments on type GenerationNumber for more.
	Generation GenerationNumber

	// Current ttributes for the child inode.
	Attributes InodeAttributes

	// The FUSE VFS layer in the kernel maintains a cache of file attributes,
	// used whenever up to date information about size, mode, etc. is needed.
	//
	// For example, this is the abridged call chain for fstat(2):
	//
	//  *  (http://goo.gl/tKBH1p) fstat calls vfs_fstat.
	//  *  (http://goo.gl/3HeITq) vfs_fstat eventuall calls vfs_getattr_nosec.
	//  *  (http://goo.gl/DccFQr) vfs_getattr_nosec calls i_op->getattr.
	//  *  (http://goo.gl/dpKkst) fuse_getattr calls fuse_update_attributes.
	//  *  (http://goo.gl/yNlqPw) fuse_update_attributes uses the values in the
	//     struct inode if allowed, otherwise calling out to the user-space code.
	//
	// In addition to obvious cases like fstat, this is also used in more subtle
	// cases like updating size information before seeking (http://goo.gl/2nnMFa)
	// or reading (http://goo.gl/FQSWs8).
	//
	// Most 'real' file systems do not set inode_operations::getattr, and
	// therefore vfs_getattr_nosec calls generic_fillattr which simply grabs the
	// information from the inode struct. This makes sense because these file
	// systems cannot spontaneously change; all modifications go through the
	// kernel which can update the inode struct as appropriate.
	//
	// In contrast, a FUSE file system may have spontaneous changes, so it calls
	// out to user space to fetch attributes. However this is expensive, so the
	// FUSE layer in the kernel caches the attributes if requested.
	//
	// This field controls when the attributes returned in this response and
	// stashed in the struct inode should be re-queried. Leave at the zero value
	// to disable caching.
	//
	// More reading:
	//     http://stackoverflow.com/q/21540315/1505451
	AttributesExpiration time.Time

	// The time until which the kernel may maintain an entry for this name to
	// inode mapping in its dentry cache. After this time, it will revalidate the
	// dentry.
	//
	// As in the discussion of attribute caching above, unlike real file systems,
	// FUSE file systems may spontaneously change their name -> inode mapping.
	// Therefore the FUSE VFS layer uses dentry_operations::d_revalidate
	// (http://goo.gl/dVea0h) to intercept lookups and revalidate by calling the
	// user-space Lookup method. However the latter may be slow, so it caches the
	// entries until the time defined by this field.
	//
	// Example code walk:
	//
	//     * (http://goo.gl/M2G3tO) lookup_dcache calls d_revalidate if enabled.
	//     * (http://goo.gl/ef0Elu) fuse_dentry_revalidate just uses the dentry's
	//     inode if fuse_dentry_time(entry) hasn't passed. Otherwise it sends a
	//     lookup request.
	//
	// Leave at the zero value to disable caching.
	EntryExpiration time.Time
}

type ForgetInodeRequest struct {
	// The inode to be forgotten. The kernel guarantees that the node ID will not
	// be used in further calls to the file system (unless it is reissued by the
	// file system).
	ID InodeID
}

type ForgetInodeResponse struct {
}

type OpenDirRequest struct {
	// The ID of the inode to be opened.
	Inode InodeID

	// Mode and options flags.
	Flags bazilfuse.OpenFlags
}

type OpenDirResponse struct {
	// An opaque ID that will be echoed in follow-up calls for this directory
	// using the same struct file in the kernel. In practice this usually means
	// follow-up calls using the file descriptor returned by open(2).
	//
	// The file system must ensure this ID remains valid until a later call to
	// ReleaseHandle.
	Handle HandleID
}
<commit_msg>Renamed Lookup -> LookUpInode.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package fuse

import (
	"time"

	bazilfuse "bazil.org/fuse"

	"golang.org/x/net/context"
)

// An interface that must be implemented by file systems to be mounted with
// FUSE. See also the comments on request and response structs.
//
// Not all methods need to have interesting implementations. Embed a field of
// type NotImplementedFileSystem to inherit defaults that return ENOSYS to the
// kernel.
//
// Must be safe for concurrent access via all methods.
type FileSystem interface {
	// Look up a child by name within a parent directory. The kernel calls this
	// when resolving user paths to dentry structs, which are then cached.
	LookUpInode(
		ctx context.Context,
		req *LookUpInodeRequest) (*LookUpInodeResponse, error)

	// Forget an inode ID previously issued (e.g. by LookUpInode). The kernel
	// calls this when removing an inode from its internal caches.
	//
	// The kernel guarantees that the node ID will not be used in further calls
	// to the file system (unless it is reissued by the file system).
	ForgetInode(
		ctx context.Context,
		req *ForgetInodeRequest) (*ForgetInodeResponse, error)

	// Open a directory inode. The kernel calls this method when setting up a
	// struct file for a particular inode with type directory, usually in
	// response to an open(2) call from a user-space process.
	OpenDir(
		ctx context.Context,
		req *OpenDirRequest) (*OpenDirResponse, error)

	// XXX: Comments
	ReleaseHandle(
		ctx context.Context,
		req *ReleaseHandleRequest) (*ReleaseHandleResponse, error)
}

////////////////////////////////////////////////////////////////////////
// Simple types
////////////////////////////////////////////////////////////////////////

// A 64-bit number used to uniquely identify a file or directory in the file
// system. File systems may mint inode IDs with any value except for
// RootInodeID.
//
// This corresponds to struct inode::i_no in the VFS layer.
// (Cf. http://goo.gl/tvYyQt)
type InodeID uint64

// A distinguished inode ID that identifies the root of the file system, e.g.
// in a request to OpenDir or LookUpInode. Unlike all other inode IDs, which
// are minted by the file system, the FUSE VFS layer may send a request for
// this ID without the file system ever having referenced it in a previous
// response.
const RootInodeID InodeID = InodeID(bazilfuse.RootID)

// A generation number for an inode. Irrelevant for file systems that won't be
// exported over NFS. For those that will and that reuse inode IDs when they
// become free, the generation number must change when an ID is reused.
//
// This corresponds to struct inode::i_generation in the VFS layer.
// (Cf. http://goo.gl/tvYyQt)
//
// Some related reading:
//
//     http://fuse.sourceforge.net/doxygen/structfuse__entry__param.html
//     http://stackoverflow.com/q/11071996/1505451
//     http://goo.gl/CqvwyX
//     http://julipedia.meroh.net/2005/09/nfs-file-handles.html
//     http://goo.gl/wvo3MB
//
type GenerationNumber uint64

// Attributes for a file or directory inode. Corresponds to struct inode (cf.
// http://goo.gl/tvYyQt).
type InodeAttributes struct {
	// The size of the file in bytes.
	Size uint64
}

////////////////////////////////////////////////////////////////////////
// Requests and responses
////////////////////////////////////////////////////////////////////////

type LookUpInodeRequest struct {
	// The ID of the directory inode to which the child belongs.
	Parent InodeID

	// The name of the child of interest, relative to the parent. For example, in
	// this directory structure:
	//
	//     foo/
	//         bar/
	//             baz
	//
	// the file system may receive a request to look up the child named "bar" for
	// the parent foo/.
	Name string
}

type LookUpInodeResponse struct {
	// The ID of the child inode. The file system must ensure that the returned
	// inode ID remains valid until a later call to ForgetInode.
	Child InodeID

	// A generation number for this incarnation of the inode with the given ID.
	// See comments on type GenerationNumber for more.
	Generation GenerationNumber

	// Current ttributes for the child inode.
	Attributes InodeAttributes

	// The FUSE VFS layer in the kernel maintains a cache of file attributes,
	// used whenever up to date information about size, mode, etc. is needed.
	//
	// For example, this is the abridged call chain for fstat(2):
	//
	//  *  (http://goo.gl/tKBH1p) fstat calls vfs_fstat.
	//  *  (http://goo.gl/3HeITq) vfs_fstat eventuall calls vfs_getattr_nosec.
	//  *  (http://goo.gl/DccFQr) vfs_getattr_nosec calls i_op->getattr.
	//  *  (http://goo.gl/dpKkst) fuse_getattr calls fuse_update_attributes.
	//  *  (http://goo.gl/yNlqPw) fuse_update_attributes uses the values in the
	//     struct inode if allowed, otherwise calling out to the user-space code.
	//
	// In addition to obvious cases like fstat, this is also used in more subtle
	// cases like updating size information before seeking (http://goo.gl/2nnMFa)
	// or reading (http://goo.gl/FQSWs8).
	//
	// Most 'real' file systems do not set inode_operations::getattr, and
	// therefore vfs_getattr_nosec calls generic_fillattr which simply grabs the
	// information from the inode struct. This makes sense because these file
	// systems cannot spontaneously change; all modifications go through the
	// kernel which can update the inode struct as appropriate.
	//
	// In contrast, a FUSE file system may have spontaneous changes, so it calls
	// out to user space to fetch attributes. However this is expensive, so the
	// FUSE layer in the kernel caches the attributes if requested.
	//
	// This field controls when the attributes returned in this response and
	// stashed in the struct inode should be re-queried. Leave at the zero value
	// to disable caching.
	//
	// More reading:
	//     http://stackoverflow.com/q/21540315/1505451
	AttributesExpiration time.Time

	// The time until which the kernel may maintain an entry for this name to
	// inode mapping in its dentry cache. After this time, it will revalidate the
	// dentry.
	//
	// As in the discussion of attribute caching above, unlike real file systems,
	// FUSE file systems may spontaneously change their name -> inode mapping.
	// Therefore the FUSE VFS layer uses dentry_operations::d_revalidate
	// (http://goo.gl/dVea0h) to intercept lookups and revalidate by calling the
	// user-space LookUpInode method. However the latter may be slow, so it
	// caches the entries until the time defined by this field.
	//
	// Example code walk:
	//
	//     * (http://goo.gl/M2G3tO) lookup_dcache calls d_revalidate if enabled.
	//     * (http://goo.gl/ef0Elu) fuse_dentry_revalidate just uses the dentry's
	//     inode if fuse_dentry_time(entry) hasn't passed. Otherwise it sends a
	//     lookup request.
	//
	// Leave at the zero value to disable caching.
	EntryExpiration time.Time
}

type ForgetInodeRequest struct {
	// The inode to be forgotten. The kernel guarantees that the node ID will not
	// be used in further calls to the file system (unless it is reissued by the
	// file system).
	ID InodeID
}

type ForgetInodeResponse struct {
}

type OpenDirRequest struct {
	// The ID of the inode to be opened.
	Inode InodeID

	// Mode and options flags.
	Flags bazilfuse.OpenFlags
}

type OpenDirResponse struct {
	// An opaque ID that will be echoed in follow-up calls for this directory
	// using the same struct file in the kernel. In practice this usually means
	// follow-up calls using the file descriptor returned by open(2).
	//
	// The file system must ensure this ID remains valid until a later call to
	// ReleaseHandle.
	Handle HandleID
}
<|endoftext|>


<commit_before>// Package filemanager provides middleware for managing files in a directory
// when directory path is requested instead of a specific file. Based on browse
// middleware.
package filemanager

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"

	"github.com/hacdias/filemanager"
	"github.com/mholt/caddy"
	"github.com/mholt/caddy/caddyhttp/httpserver"
)

func init() {
	caddy.RegisterPlugin("filemanager", caddy.Plugin{
		ServerType: "http",
		Action:     setup,
	})
}

// FileManager is an http.Handler that can show a file listing when
// directories in the given paths are specified.
type FileManager struct {
	Next    httpserver.Handler
	Configs []*filemanager.FileManager
}

// ServeHTTP determines if the request is for this plugin, and if all prerequisites are met.
func (f FileManager) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
	for i := range f.Configs {
		// Checks if this Path should be handled by File Manager.
		if !httpserver.Path(r.URL.Path).Matches(f.Configs[i].BaseURL) {
			continue
		}

		return f.Configs[i].ServeHTTP(w, r)
	}

	return f.Next.ServeHTTP(w, r)
}

// setup configures a new FileManager middleware instance.
func setup(c *caddy.Controller) error {
	configs, err := parse(c)
	if err != nil {
		return err
	}

	httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
		return FileManager{Configs: configs, Next: next}
	})

	return nil
}

func parse(c *caddy.Controller) ([]*filemanager.FileManager, error) {
	var (
		configs []*filemanager.FileManager
		err     error
	)

	for c.Next() {
		var (
			m    = filemanager.New(".")
			u    = m.User
			name = ""
		)

		// Get the baseURL
		args := c.RemainingArgs()

		if len(args) > 0 {
			m.SetBaseURL(args[0])
			m.SetWebDavURL("/webdav")
		}

		for c.NextBlock() {
			switch c.Val() {
			case "before_save":
				if m.BeforeSave, err = makeCommand(c); err != nil {
					return configs, err
				}
			case "after_save":
				if m.AfterSave, err = makeCommand(c); err != nil {
					return configs, err
				}
			case "webdav":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				m.SetWebDavURL(c.Val())
			case "show":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				m.SetScope(c.Val(), name)
			case "styles":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				var tplBytes []byte
				tplBytes, err = ioutil.ReadFile(c.Val())
				if err != nil {
					return configs, err
				}

				u.StyleSheet = string(tplBytes)
			case "allow_new":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				u.AllowNew, err = strconv.ParseBool(c.Val())
				if err != nil {
					return configs, err
				}
			case "allow_edit":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				u.AllowEdit, err = strconv.ParseBool(c.Val())
				if err != nil {
					return configs, err
				}
			case "allow_commands":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				u.AllowCommands, err = strconv.ParseBool(c.Val())
				if err != nil {
					return configs, err
				}
			case "allow_command":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				u.Commands = append(u.Commands, c.Val())
			case "block_command":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				index := 0

				for i, val := range u.Commands {
					if val == c.Val() {
						index = i
					}
				}

				u.Commands = append(u.Commands[:index], u.Commands[index+1:]...)
			case "allow", "allow_r", "block", "block_r":
				ruleType := c.Val()

				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				if c.Val() == "dotfiles" && !strings.HasSuffix(ruleType, "_r") {
					ruleType += "_r"
				}

				rule := &filemanager.Rule{
					Allow: ruleType == "allow" || ruleType == "allow_r",
					Regex: ruleType == "allow_r" || ruleType == "block_r",
				}

				if rule.Regex && c.Val() == "dotfiles" {
					rule.Regexp = regexp.MustCompile("\\/\\..+")
				} else if rule.Regex {
					rule.Regexp = regexp.MustCompile(c.Val())
				} else {
					rule.Path = c.Val()
				}

				u.Rules = append(u.Rules, rule)
			default:
				// Is it a new user? Is it?
				val := c.Val()

				// Checks if it's a new user!
				if !strings.HasSuffix(val, ":") {
					fmt.Println("Unknown option " + val)
				}

				// Get the username, sets the current user, and initializes it
				val = strings.TrimSuffix(val, ":")
				m.NewUser(val)
				name = val
			}
		}

		configs = append(configs, m)
	}

	return configs, nil
}

func makeCommand(c *caddy.Controller) (filemanager.Command, error) {
	fn := func(r *http.Request, c *filemanager.FileManager, u *filemanager.User) error { return nil }

	args := c.RemainingArgs()
	if len(args) == 0 {
		return fn, c.ArgErr()
	}

	nonblock := false
	if len(args) > 1 && args[len(args)-1] == "&" {
		// Run command in background; non-blocking
		nonblock = true
		args = args[:len(args)-1]
	}

	command, args, err := caddy.SplitCommandAndArgs(strings.Join(args, " "))
	if err != nil {
		return fn, c.Err(err.Error())
	}

	fn = func(r *http.Request, c *filemanager.FileManager, u *filemanager.User) error {
		path := strings.Replace(r.URL.Path, c.WebDavURL, "", 1)
		path = u.Scope() + "/" + path
		path = filepath.Clean(path)

		for i := range args {
			args[i] = strings.Replace(args[i], "{path}", path, -1)
		}

		cmd := exec.Command(command, args...)
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr

		if nonblock {
			log.Printf("[INFO] Nonblocking Command:\"%s %s\"", command, strings.Join(args, " "))
			return cmd.Start()
		}

		log.Printf("[INFO] Blocking Command:\"%s %s\"", command, strings.Join(args, " "))
		return cmd.Run()
	}

	return fn, nil
}
<commit_msg>Add some defaults<commit_after>// Package filemanager provides middleware for managing files in a directory
// when directory path is requested instead of a specific file. Based on browse
// middleware.
package filemanager

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"

	"github.com/hacdias/filemanager"
	"github.com/mholt/caddy"
	"github.com/mholt/caddy/caddyhttp/httpserver"
)

func init() {
	caddy.RegisterPlugin("filemanager", caddy.Plugin{
		ServerType: "http",
		Action:     setup,
	})
}

// FileManager is an http.Handler that can show a file listing when
// directories in the given paths are specified.
type FileManager struct {
	Next    httpserver.Handler
	Configs []*filemanager.FileManager
}

// ServeHTTP determines if the request is for this plugin, and if all prerequisites are met.
func (f FileManager) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
	for i := range f.Configs {
		// Checks if this Path should be handled by File Manager.
		if !httpserver.Path(r.URL.Path).Matches(f.Configs[i].BaseURL) {
			continue
		}

		return f.Configs[i].ServeHTTP(w, r)
	}

	return f.Next.ServeHTTP(w, r)
}

// setup configures a new FileManager middleware instance.
func setup(c *caddy.Controller) error {
	configs, err := parse(c)
	if err != nil {
		return err
	}

	httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
		return FileManager{Configs: configs, Next: next}
	})

	return nil
}

func parse(c *caddy.Controller) ([]*filemanager.FileManager, error) {
	var (
		configs []*filemanager.FileManager
		err     error
	)

	for c.Next() {
		var (
			m    = filemanager.New(".")
			u    = m.User
			name = ""
		)

		caddyConf := httpserver.GetConfig(c)

		m.PrefixURL = strings.TrimSuffix(caddyConf.Addr.Path, "/")
		m.Commands = []string{"git", "svn", "hg"}
		m.Rules = append(m.Rules, &filemanager.Rule{
			Regex:  true,
			Allow:  false,
			Regexp: regexp.MustCompile("\\/\\..+"),
		})

		// Get the baseURL
		args := c.RemainingArgs()

		if len(args) > 0 {
			m.SetBaseURL(args[0])
			m.SetWebDavURL("/webdav")
		}

		for c.NextBlock() {
			switch c.Val() {
			case "before_save":
				if m.BeforeSave, err = makeCommand(c); err != nil {
					return configs, err
				}
			case "after_save":
				if m.AfterSave, err = makeCommand(c); err != nil {
					return configs, err
				}
			case "webdav":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				m.SetWebDavURL(c.Val())
			case "show":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				m.SetScope(c.Val(), name)
			case "styles":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				var tplBytes []byte
				tplBytes, err = ioutil.ReadFile(c.Val())
				if err != nil {
					return configs, err
				}

				u.StyleSheet = string(tplBytes)
			case "allow_new":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				u.AllowNew, err = strconv.ParseBool(c.Val())
				if err != nil {
					return configs, err
				}
			case "allow_edit":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				u.AllowEdit, err = strconv.ParseBool(c.Val())
				if err != nil {
					return configs, err
				}
			case "allow_commands":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				u.AllowCommands, err = strconv.ParseBool(c.Val())
				if err != nil {
					return configs, err
				}
			case "allow_command":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				u.Commands = append(u.Commands, c.Val())
			case "block_command":
				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				index := 0

				for i, val := range u.Commands {
					if val == c.Val() {
						index = i
					}
				}

				u.Commands = append(u.Commands[:index], u.Commands[index+1:]...)
			case "allow", "allow_r", "block", "block_r":
				ruleType := c.Val()

				if !c.NextArg() {
					return configs, c.ArgErr()
				}

				if c.Val() == "dotfiles" && !strings.HasSuffix(ruleType, "_r") {
					ruleType += "_r"
				}

				rule := &filemanager.Rule{
					Allow: ruleType == "allow" || ruleType == "allow_r",
					Regex: ruleType == "allow_r" || ruleType == "block_r",
				}

				if rule.Regex && c.Val() == "dotfiles" {
					rule.Regexp = regexp.MustCompile("\\/\\..+")
				} else if rule.Regex {
					rule.Regexp = regexp.MustCompile(c.Val())
				} else {
					rule.Path = c.Val()
				}

				u.Rules = append(u.Rules, rule)
			default:
				// Is it a new user? Is it?
				val := c.Val()

				// Checks if it's a new user!
				if !strings.HasSuffix(val, ":") {
					fmt.Println("Unknown option " + val)
				}

				// Get the username, sets the current user, and initializes it
				val = strings.TrimSuffix(val, ":")
				m.NewUser(val)
				name = val
			}
		}

		configs = append(configs, m)
	}

	return configs, nil
}

func makeCommand(c *caddy.Controller) (filemanager.Command, error) {
	fn := func(r *http.Request, c *filemanager.FileManager, u *filemanager.User) error { return nil }

	args := c.RemainingArgs()
	if len(args) == 0 {
		return fn, c.ArgErr()
	}

	nonblock := false
	if len(args) > 1 && args[len(args)-1] == "&" {
		// Run command in background; non-blocking
		nonblock = true
		args = args[:len(args)-1]
	}

	command, args, err := caddy.SplitCommandAndArgs(strings.Join(args, " "))
	if err != nil {
		return fn, c.Err(err.Error())
	}

	fn = func(r *http.Request, c *filemanager.FileManager, u *filemanager.User) error {
		path := strings.Replace(r.URL.Path, c.WebDavURL, "", 1)
		path = u.Scope() + "/" + path
		path = filepath.Clean(path)

		for i := range args {
			args[i] = strings.Replace(args[i], "{path}", path, -1)
		}

		cmd := exec.Command(command, args...)
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr

		if nonblock {
			log.Printf("[INFO] Nonblocking Command:\"%s %s\"", command, strings.Join(args, " "))
			return cmd.Start()
		}

		log.Printf("[INFO] Blocking Command:\"%s %s\"", command, strings.Join(args, " "))
		return cmd.Run()
	}

	return fn, nil
}
<|endoftext|>