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

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"sort"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)

// pathf is fmt.Sprintf for generating paths
// (on windows it turns / into \ after the printf).
func pathf(format string, args ...interface{}) string {
	return filepath.Clean(fmt.Sprintf(format, args...))
}

// filter returns a slice containing the elements x from list for which f(x) == true.
func filter(list []string, f func(string) bool) []string {
	var out []string
	for _, x := range list {
		if f(x) {
			out = append(out, x)
		}
	}
	return out
}

// uniq returns a sorted slice containing the unique elements of list.
func uniq(list []string) []string {
	out := make([]string, len(list))
	copy(out, list)
	sort.Strings(out)
	keep := out[:0]
	for _, x := range out {
		if len(keep) == 0 || keep[len(keep)-1] != x {
			keep = append(keep, x)
		}
	}
	return keep
}

// splitlines returns a slice with the result of splitting
// the input p after each \n.
func splitlines(p string) []string {
	return strings.SplitAfter(p, "\n")
}

// splitfields replaces the vector v with the result of splitting
// the input p into non-empty fields containing no spaces.
func splitfields(p string) []string {
	return strings.Fields(p)
}

const (
	CheckExit = 1 << iota
	ShowOutput
	Background
)

var outputLock sync.Mutex

// run runs the command line cmd in dir.
// If mode has ShowOutput set, run collects cmd's output and returns it as a string;
// otherwise, run prints cmd's output to standard output after the command finishes.
// If mode has CheckExit set and the command fails, run calls fatal.
// If mode has Background set, this command is being run as a
// Background job. Only bgrun should use the Background mode,
// not other callers.
func run(dir string, mode int, cmd ...string) string {
	if vflag > 1 {
		errprintf("run: %s\n", strings.Join(cmd, " "))
	}

	xcmd := exec.Command(cmd[0], cmd[1:]...)
	xcmd.Dir = dir
	var err error
	data, err := xcmd.CombinedOutput()
	if err != nil && mode&CheckExit != 0 {
		outputLock.Lock()
		if len(data) > 0 {
			xprintf("%s\n", data)
		}
		outputLock.Unlock()
		atomic.AddInt32(&ndone, +1)
		die := func() {
			time.Sleep(100 * time.Millisecond)
			fatal("FAILED: %v", strings.Join(cmd, " "))
		}
		if mode&Background != 0 {
			// This is a background run, and fatal will
			// wait for it to finish before exiting.
			// If we call fatal directly, that's a deadlock.
			// Instead, call fatal in a background goroutine
			// and let this run return normally, so that
			// fatal can wait for it to finish.
			go die()
		} else {
			die()
		}
	}
	if mode&ShowOutput != 0 {
		os.Stdout.Write(data)
	}
	return string(data)
}

var maxbg = 4 /* maximum number of jobs to run at once */

var (
	bgwork = make(chan func())
	bgdone = make(chan struct{}, 1e6)
	nwork  int32
	ndone  int32
)

func bginit() {
	for i := 0; i < maxbg; i++ {
		go bghelper()
	}
}

func bghelper() {
	for {
		(<-bgwork)()
	}
}

// bgrun is like run but runs the command in the background.
// CheckExit|ShowOutput mode is implied (since output cannot be returned).
func bgrun(dir string, cmd ...string) {
	bgwork <- func() {
		run(dir, CheckExit|ShowOutput|Background, cmd...)
	}
}

// bgwait waits for pending bgruns to finish.
func bgwait() {
	var wg sync.WaitGroup
	wg.Add(maxbg)
	for i := 0; i < maxbg; i++ {
		bgwork <- func() {
			wg.Done()
			wg.Wait()
		}
	}
	wg.Wait()
}

// xgetwd returns the current directory.
func xgetwd() string {
	wd, err := os.Getwd()
	if err != nil {
		fatal("%s", err)
	}
	return wd
}

// xrealwd returns the 'real' name for the given path.
// real is defined as what xgetwd returns in that directory.
func xrealwd(path string) string {
	old := xgetwd()
	if err := os.Chdir(path); err != nil {
		fatal("chdir %s: %v", path, err)
	}
	real := xgetwd()
	if err := os.Chdir(old); err != nil {
		fatal("chdir %s: %v", old, err)
	}
	return real
}

// isdir reports whether p names an existing directory.
func isdir(p string) bool {
	fi, err := os.Stat(p)
	return err == nil && fi.IsDir()
}

// isfile reports whether p names an existing file.
func isfile(p string) bool {
	fi, err := os.Stat(p)
	return err == nil && fi.Mode().IsRegular()
}

// mtime returns the modification time of the file p.
func mtime(p string) time.Time {
	fi, err := os.Stat(p)
	if err != nil {
		return time.Time{}
	}
	return fi.ModTime()
}

// isabs reports whether p is an absolute path.
func isabs(p string) bool {
	return filepath.IsAbs(p)
}

// readfile returns the content of the named file.
func readfile(file string) string {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		fatal("%v", err)
	}
	return string(data)
}

// writefile writes b to the named file, creating it if needed.  if
// exec is non-zero, marks the file as executable.
func writefile(b, file string, exec int) {
	mode := os.FileMode(0666)
	if exec != 0 {
		mode = 0777
	}
	err := ioutil.WriteFile(file, []byte(b), mode)
	if err != nil {
		fatal("%v", err)
	}
}

// xmkdir creates the directory p.
func xmkdir(p string) {
	err := os.Mkdir(p, 0777)
	if err != nil {
		fatal("%v", err)
	}
}

// xmkdirall creates the directory p and its parents, as needed.
func xmkdirall(p string) {
	err := os.MkdirAll(p, 0777)
	if err != nil {
		fatal("%v", err)
	}
}

// xremove removes the file p.
func xremove(p string) {
	if vflag > 2 {
		errprintf("rm %s\n", p)
	}
	os.Remove(p)
}

// xremoveall removes the file or directory tree rooted at p.
func xremoveall(p string) {
	if vflag > 2 {
		errprintf("rm -r %s\n", p)
	}
	os.RemoveAll(p)
}

// xreaddir replaces dst with a list of the names of the files in dir.
// The names are relative to dir; they are not full paths.
func xreaddir(dir string) []string {
	f, err := os.Open(dir)
	if err != nil {
		fatal("%v", err)
	}
	defer f.Close()
	names, err := f.Readdirnames(-1)
	if err != nil {
		fatal("reading %s: %v", dir, err)
	}
	return names
}

// xworkdir creates a new temporary directory to hold object files
// and returns the name of that directory.
func xworkdir() string {
	name, err := ioutil.TempDir("", "go-tool-dist-")
	if err != nil {
		fatal("%v", err)
	}
	return name
}

// fatal prints an error message to standard error and exits.
func fatal(format string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, "go tool dist: %s\n", fmt.Sprintf(format, args...))
	bgwait()
	xexit(2)
}

var atexits []func()

// xexit exits the process with return code n.
func xexit(n int) {
	for i := len(atexits) - 1; i >= 0; i-- {
		atexits[i]()
	}
	os.Exit(n)
}

// xatexit schedules the exit-handler f to be run when the program exits.
func xatexit(f func()) {
	atexits = append(atexits, f)
}

// xprintf prints a message to standard output.
func xprintf(format string, args ...interface{}) {
	fmt.Printf(format, args...)
}

// errprintf prints a message to standard output.
func errprintf(format string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, format, args...)
}

// main takes care of OS-specific startup and dispatches to xmain.
func main() {
	os.Setenv("TERM", "dumb") // disable escape codes in clang errors

	slash = string(filepath.Separator)

	gohostos = runtime.GOOS
	switch gohostos {
	case "darwin":
		// Even on 64-bit platform, darwin uname -m prints i386.
		if strings.Contains(run("", CheckExit, "sysctl", "machdep.cpu.extfeatures"), "EM64T") {
			gohostarch = "amd64"
		}
	case "solaris":
		// Even on 64-bit platform, solaris uname -m prints i86pc.
		out := run("", CheckExit, "isainfo", "-n")
		if strings.Contains(out, "amd64") {
			gohostarch = "amd64"
		}
		if strings.Contains(out, "i386") {
			gohostarch = "386"
		}
	case "plan9":
		gohostarch = os.Getenv("objtype")
		if gohostarch == "" {
			fatal("$objtype is unset")
		}
	}

	sysinit()

	if gohostarch == "" {
		// Default Unix system.
		out := run("", CheckExit, "uname", "-m")
		switch {
		case strings.Contains(out, "x86_64"), strings.Contains(out, "amd64"):
			gohostarch = "amd64"
		case strings.Contains(out, "86"):
			gohostarch = "386"
		case strings.Contains(out, "arm"):
			gohostarch = "arm"
		case strings.Contains(out, "ppc64le"):
			gohostarch = "ppc64le"
		case strings.Contains(out, "ppc64"):
			gohostarch = "ppc64"
		default:
			fatal("unknown architecture: %s", out)
		}
	}

	if gohostarch == "arm" {
		maxbg = 1
	}
	bginit()

	// The OS X 10.6 linker does not support external linking mode.
	// See golang.org/issue/5130.
	//
	// OS X 10.6 does not work with clang either, but OS X 10.9 requires it.
	// It seems to work with OS X 10.8, so we default to clang for 10.8 and later.
	// See golang.org/issue/5822.
	//
	// Roughly, OS X 10.N shows up as uname release (N+4),
	// so OS X 10.6 is uname version 10 and OS X 10.8 is uname version 12.
	if gohostos == "darwin" {
		rel := run("", CheckExit, "uname", "-r")
		if i := strings.Index(rel, "."); i >= 0 {
			rel = rel[:i]
		}
		osx, _ := strconv.Atoi(rel)
		if osx <= 6+4 {
			goextlinkenabled = "0"
		}
		if osx >= 8+4 {
			defaultclang = true
		}
	}

	xinit()
	xmain()
}

// xsamefile reports whether f1 and f2 are the same file (or dir)
func xsamefile(f1, f2 string) bool {
	fi1, err1 := os.Stat(f1)
	fi2, err2 := os.Stat(f2)
	if err1 != nil || err2 != nil {
		return f1 == f2
	}
	return os.SameFile(fi1, fi2)
}

func cpuid(info *[4]uint32, ax uint32)

func cansse2() bool {
	if gohostarch != "386" && gohostarch != "amd64" {
		return false
	}

	var info [4]uint32
	cpuid(&info, 1)
	return info[3]&(1<<26) != 0 // SSE2
}

func xgetgoarm() string {
	if goos == "nacl" {
		// NaCl guarantees VFPv3 and is always cross-compiled.
		return "7"
	}
	if gohostarch != "arm" || goos != gohostos {
		// Conservative default for cross-compilation.
		return "5"
	}
	if goos == "freebsd" {
		// FreeBSD has broken VFP support.
		return "5"
	}
	if xtryexecfunc(useVFPv3) {
		return "7"
	}
	if xtryexecfunc(useVFPv1) {
		return "6"
	}
	return "5"
}

func xtryexecfunc(f func()) bool {
	// TODO(rsc): Implement.
	// The C cmd/dist used this to test whether certain assembly
	// sequences could be executed properly. It used signals and
	// timers and sigsetjmp, which is basically not possible in Go.
	// We probably have to invoke ourselves as a subprocess instead,
	// to contain the fault/timeout.
	return false
}

func useVFPv1()
func useVFPv3()
<commit_msg>cmd/dist: do not leave go-tool-dist-* temporary directories behind<commit_after>// Copyright 2012 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"sort"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)

// pathf is fmt.Sprintf for generating paths
// (on windows it turns / into \ after the printf).
func pathf(format string, args ...interface{}) string {
	return filepath.Clean(fmt.Sprintf(format, args...))
}

// filter returns a slice containing the elements x from list for which f(x) == true.
func filter(list []string, f func(string) bool) []string {
	var out []string
	for _, x := range list {
		if f(x) {
			out = append(out, x)
		}
	}
	return out
}

// uniq returns a sorted slice containing the unique elements of list.
func uniq(list []string) []string {
	out := make([]string, len(list))
	copy(out, list)
	sort.Strings(out)
	keep := out[:0]
	for _, x := range out {
		if len(keep) == 0 || keep[len(keep)-1] != x {
			keep = append(keep, x)
		}
	}
	return keep
}

// splitlines returns a slice with the result of splitting
// the input p after each \n.
func splitlines(p string) []string {
	return strings.SplitAfter(p, "\n")
}

// splitfields replaces the vector v with the result of splitting
// the input p into non-empty fields containing no spaces.
func splitfields(p string) []string {
	return strings.Fields(p)
}

const (
	CheckExit = 1 << iota
	ShowOutput
	Background
)

var outputLock sync.Mutex

// run runs the command line cmd in dir.
// If mode has ShowOutput set, run collects cmd's output and returns it as a string;
// otherwise, run prints cmd's output to standard output after the command finishes.
// If mode has CheckExit set and the command fails, run calls fatal.
// If mode has Background set, this command is being run as a
// Background job. Only bgrun should use the Background mode,
// not other callers.
func run(dir string, mode int, cmd ...string) string {
	if vflag > 1 {
		errprintf("run: %s\n", strings.Join(cmd, " "))
	}

	xcmd := exec.Command(cmd[0], cmd[1:]...)
	xcmd.Dir = dir
	var err error
	data, err := xcmd.CombinedOutput()
	if err != nil && mode&CheckExit != 0 {
		outputLock.Lock()
		if len(data) > 0 {
			xprintf("%s\n", data)
		}
		outputLock.Unlock()
		atomic.AddInt32(&ndone, +1)
		die := func() {
			time.Sleep(100 * time.Millisecond)
			fatal("FAILED: %v", strings.Join(cmd, " "))
		}
		if mode&Background != 0 {
			// This is a background run, and fatal will
			// wait for it to finish before exiting.
			// If we call fatal directly, that's a deadlock.
			// Instead, call fatal in a background goroutine
			// and let this run return normally, so that
			// fatal can wait for it to finish.
			go die()
		} else {
			die()
		}
	}
	if mode&ShowOutput != 0 {
		os.Stdout.Write(data)
	}
	return string(data)
}

var maxbg = 4 /* maximum number of jobs to run at once */

var (
	bgwork = make(chan func())
	bgdone = make(chan struct{}, 1e6)
	nwork  int32
	ndone  int32
)

func bginit() {
	for i := 0; i < maxbg; i++ {
		go bghelper()
	}
}

func bghelper() {
	for {
		(<-bgwork)()
	}
}

// bgrun is like run but runs the command in the background.
// CheckExit|ShowOutput mode is implied (since output cannot be returned).
func bgrun(dir string, cmd ...string) {
	bgwork <- func() {
		run(dir, CheckExit|ShowOutput|Background, cmd...)
	}
}

// bgwait waits for pending bgruns to finish.
func bgwait() {
	var wg sync.WaitGroup
	wg.Add(maxbg)
	for i := 0; i < maxbg; i++ {
		bgwork <- func() {
			wg.Done()
			wg.Wait()
		}
	}
	wg.Wait()
}

// xgetwd returns the current directory.
func xgetwd() string {
	wd, err := os.Getwd()
	if err != nil {
		fatal("%s", err)
	}
	return wd
}

// xrealwd returns the 'real' name for the given path.
// real is defined as what xgetwd returns in that directory.
func xrealwd(path string) string {
	old := xgetwd()
	if err := os.Chdir(path); err != nil {
		fatal("chdir %s: %v", path, err)
	}
	real := xgetwd()
	if err := os.Chdir(old); err != nil {
		fatal("chdir %s: %v", old, err)
	}
	return real
}

// isdir reports whether p names an existing directory.
func isdir(p string) bool {
	fi, err := os.Stat(p)
	return err == nil && fi.IsDir()
}

// isfile reports whether p names an existing file.
func isfile(p string) bool {
	fi, err := os.Stat(p)
	return err == nil && fi.Mode().IsRegular()
}

// mtime returns the modification time of the file p.
func mtime(p string) time.Time {
	fi, err := os.Stat(p)
	if err != nil {
		return time.Time{}
	}
	return fi.ModTime()
}

// isabs reports whether p is an absolute path.
func isabs(p string) bool {
	return filepath.IsAbs(p)
}

// readfile returns the content of the named file.
func readfile(file string) string {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		fatal("%v", err)
	}
	return string(data)
}

// writefile writes b to the named file, creating it if needed.  if
// exec is non-zero, marks the file as executable.
func writefile(b, file string, exec int) {
	mode := os.FileMode(0666)
	if exec != 0 {
		mode = 0777
	}
	err := ioutil.WriteFile(file, []byte(b), mode)
	if err != nil {
		fatal("%v", err)
	}
}

// xmkdir creates the directory p.
func xmkdir(p string) {
	err := os.Mkdir(p, 0777)
	if err != nil {
		fatal("%v", err)
	}
}

// xmkdirall creates the directory p and its parents, as needed.
func xmkdirall(p string) {
	err := os.MkdirAll(p, 0777)
	if err != nil {
		fatal("%v", err)
	}
}

// xremove removes the file p.
func xremove(p string) {
	if vflag > 2 {
		errprintf("rm %s\n", p)
	}
	os.Remove(p)
}

// xremoveall removes the file or directory tree rooted at p.
func xremoveall(p string) {
	if vflag > 2 {
		errprintf("rm -r %s\n", p)
	}
	os.RemoveAll(p)
}

// xreaddir replaces dst with a list of the names of the files in dir.
// The names are relative to dir; they are not full paths.
func xreaddir(dir string) []string {
	f, err := os.Open(dir)
	if err != nil {
		fatal("%v", err)
	}
	defer f.Close()
	names, err := f.Readdirnames(-1)
	if err != nil {
		fatal("reading %s: %v", dir, err)
	}
	return names
}

// xworkdir creates a new temporary directory to hold object files
// and returns the name of that directory.
func xworkdir() string {
	name, err := ioutil.TempDir("", "go-tool-dist-")
	if err != nil {
		fatal("%v", err)
	}
	return name
}

// fatal prints an error message to standard error and exits.
func fatal(format string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, "go tool dist: %s\n", fmt.Sprintf(format, args...))
	bgwait()
	xexit(2)
}

var atexits []func()

// xexit exits the process with return code n.
func xexit(n int) {
	for i := len(atexits) - 1; i >= 0; i-- {
		atexits[i]()
	}
	os.Exit(n)
}

// xatexit schedules the exit-handler f to be run when the program exits.
func xatexit(f func()) {
	atexits = append(atexits, f)
}

// xprintf prints a message to standard output.
func xprintf(format string, args ...interface{}) {
	fmt.Printf(format, args...)
}

// errprintf prints a message to standard output.
func errprintf(format string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, format, args...)
}

// main takes care of OS-specific startup and dispatches to xmain.
func main() {
	os.Setenv("TERM", "dumb") // disable escape codes in clang errors

	slash = string(filepath.Separator)

	gohostos = runtime.GOOS
	switch gohostos {
	case "darwin":
		// Even on 64-bit platform, darwin uname -m prints i386.
		if strings.Contains(run("", CheckExit, "sysctl", "machdep.cpu.extfeatures"), "EM64T") {
			gohostarch = "amd64"
		}
	case "solaris":
		// Even on 64-bit platform, solaris uname -m prints i86pc.
		out := run("", CheckExit, "isainfo", "-n")
		if strings.Contains(out, "amd64") {
			gohostarch = "amd64"
		}
		if strings.Contains(out, "i386") {
			gohostarch = "386"
		}
	case "plan9":
		gohostarch = os.Getenv("objtype")
		if gohostarch == "" {
			fatal("$objtype is unset")
		}
	}

	sysinit()

	if gohostarch == "" {
		// Default Unix system.
		out := run("", CheckExit, "uname", "-m")
		switch {
		case strings.Contains(out, "x86_64"), strings.Contains(out, "amd64"):
			gohostarch = "amd64"
		case strings.Contains(out, "86"):
			gohostarch = "386"
		case strings.Contains(out, "arm"):
			gohostarch = "arm"
		case strings.Contains(out, "ppc64le"):
			gohostarch = "ppc64le"
		case strings.Contains(out, "ppc64"):
			gohostarch = "ppc64"
		default:
			fatal("unknown architecture: %s", out)
		}
	}

	if gohostarch == "arm" {
		maxbg = 1
	}
	bginit()

	// The OS X 10.6 linker does not support external linking mode.
	// See golang.org/issue/5130.
	//
	// OS X 10.6 does not work with clang either, but OS X 10.9 requires it.
	// It seems to work with OS X 10.8, so we default to clang for 10.8 and later.
	// See golang.org/issue/5822.
	//
	// Roughly, OS X 10.N shows up as uname release (N+4),
	// so OS X 10.6 is uname version 10 and OS X 10.8 is uname version 12.
	if gohostos == "darwin" {
		rel := run("", CheckExit, "uname", "-r")
		if i := strings.Index(rel, "."); i >= 0 {
			rel = rel[:i]
		}
		osx, _ := strconv.Atoi(rel)
		if osx <= 6+4 {
			goextlinkenabled = "0"
		}
		if osx >= 8+4 {
			defaultclang = true
		}
	}

	xinit()
	xmain()
	xexit(0)
}

// xsamefile reports whether f1 and f2 are the same file (or dir)
func xsamefile(f1, f2 string) bool {
	fi1, err1 := os.Stat(f1)
	fi2, err2 := os.Stat(f2)
	if err1 != nil || err2 != nil {
		return f1 == f2
	}
	return os.SameFile(fi1, fi2)
}

func cpuid(info *[4]uint32, ax uint32)

func cansse2() bool {
	if gohostarch != "386" && gohostarch != "amd64" {
		return false
	}

	var info [4]uint32
	cpuid(&info, 1)
	return info[3]&(1<<26) != 0 // SSE2
}

func xgetgoarm() string {
	if goos == "nacl" {
		// NaCl guarantees VFPv3 and is always cross-compiled.
		return "7"
	}
	if gohostarch != "arm" || goos != gohostos {
		// Conservative default for cross-compilation.
		return "5"
	}
	if goos == "freebsd" {
		// FreeBSD has broken VFP support.
		return "5"
	}
	if xtryexecfunc(useVFPv3) {
		return "7"
	}
	if xtryexecfunc(useVFPv1) {
		return "6"
	}
	return "5"
}

func xtryexecfunc(f func()) bool {
	// TODO(rsc): Implement.
	// The C cmd/dist used this to test whether certain assembly
	// sequences could be executed properly. It used signals and
	// timers and sigsetjmp, which is basically not possible in Go.
	// We probably have to invoke ourselves as a subprocess instead,
	// to contain the fault/timeout.
	return false
}

func useVFPv1()
func useVFPv3()
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"

	"config"
	"site"

	flags "github.com/jessevdk/go-flags"
	fsnotify "gopkg.in/fsnotify.v1"
)

var opts struct {
	StartDaemon bool   `short:"d" long:"daemon" description:"start a simple HTTP server watching for markdown changes."`
	Config      string `short:"c" long:"config" default:"config.json" description:"the settings file."`
	ServerPort  int    `short:"p" long:"port" default:"8080" description:"port where to run the server."`
}

func getAllSubdirectories(parentPath string) (paths []string, err error) {
	walkFn := func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			paths = append(paths, path)
		}
		return nil
	}
	err = filepath.Walk(parentPath, walkFn)
	return paths, err
}

func writeSite(config config.Config, sourcedir string, outdir string) error {
	s := site.New(config, outdir)
	if err := s.Populate(sourcedir); err != nil {
		return err
	}
	if err := s.Write(); err != nil {
		return err
	}
	return nil
}

func main() {
	parser := flags.NewParser(&opts, flags.Default)
	parser.Usage = "[OPTIONS] sourcedir outputdir" + parser.Usage

	args, err := parser.Parse()
	if err != nil {
		panic(err)
	}

	if len(args) != 2 {
		parser.WriteHelp(os.Stderr)
		os.Exit(1)
	}

	sourcedir := args[0]
	outdir := args[1]

	config, err := config.New(opts.Config)
	if err != nil {
		log.Panic(err)
	}
	if err := writeSite(*config, sourcedir, outdir); err != nil {
		log.Fatal(err)
	}

	if opts.StartDaemon {
		watcher, err := fsnotify.NewWatcher()
		if err != nil {
			log.Fatal(err)
		}
		defer watcher.Close()

		go func() {
			for {
				select {
				case event := <-watcher.Events:
					if event.Op != fsnotify.Chmod {
						log.Println("Rewriting the site")
						if err := writeSite(*config, sourcedir, outdir); err != nil {
							log.Fatal(err)
						}
					}
				case err := <-watcher.Errors:
					log.Fatal(err)
				}
			}
		}()

		paths, err := getAllSubdirectories(sourcedir)
		if err != nil {
			log.Fatal(err)
		}
		for _, path := range paths {
			watcher.Add(path)
		}

		addr := fmt.Sprintf(":%d", opts.ServerPort)
		log.Printf("Static server created on address %s\n", addr)
		log.Fatal(
			http.ListenAndServe(addr, http.FileServer(http.Dir(outdir))))
	}
}
<commit_msg>Check if the paths exists before using them<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"time"

	"config"
	"site"

	flags "github.com/jessevdk/go-flags"
	fsnotify "gopkg.in/fsnotify.v1"
)

var opts struct {
	StartDaemon bool   `short:"d" long:"daemon" description:"start a simple HTTP server watching for markdown changes."`
	Config      string `short:"c" long:"config" default:"config.json" description:"the settings file."`
	ServerPort  int    `short:"p" long:"port" default:"8080" description:"port where to run the server."`
}

func getAllSubdirectories(parentPath string) (paths []string, err error) {
	walkFn := func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			paths = append(paths, path)
		}
		return nil
	}
	err = filepath.Walk(parentPath, walkFn)
	return paths, err
}

func writeSite(config config.Config, sourcedir string, outdir string) error {
	s := site.New(config, outdir)
	if err := s.Populate(sourcedir); err != nil {
		return err
	}
	if err := s.Write(); err != nil {
		return err
	}
	return nil
}

func main() {
	parser := flags.NewParser(&opts, flags.Default)
	parser.Usage = "[OPTIONS] sourcedir outputdir" + parser.Usage

	args, err := parser.Parse()
	if err != nil {
		panic(err)
	}

	if len(args) != 2 {
		parser.WriteHelp(os.Stderr)
		os.Exit(1)
	}

	// TODO: this need to be clean up
	directoryExists := func(dir string) bool {
		if fi, err := os.Stat(dir); err == nil {
			return fi.IsDir()
		}
		return false
	}
	sourcedir := args[0]
	if !directoryExists(sourcedir) {
		fmt.Fprintf(os.Stderr, "The sourcedir must be an existent directory!")
		os.Exit(1)
	}
	outdir := args[1]
	if !directoryExists(outdir) {
		if err := os.Mkdir(outdir, os.ModePerm); err != nil {
			fmt.Fprintf(os.Stderr, "The outdir didn't exists and couldn't be created!")
		}
		time.Sleep(1 * time.Second) // Ugliest thing ever but it doesn't create the dir at time?
	}

	config, err := config.New(opts.Config)
	if err != nil {
		log.Panic(err)
	}
	if err := writeSite(*config, sourcedir, outdir); err != nil {
		log.Fatal(err)
	}

	if opts.StartDaemon {
		watcher, err := fsnotify.NewWatcher()
		if err != nil {
			log.Fatal(err)
		}
		defer watcher.Close()

		go func() {
			for {
				select {
				case event := <-watcher.Events:
					if event.Op != fsnotify.Chmod {
						log.Println("Rewriting the site")
						if err := writeSite(*config, sourcedir, outdir); err != nil {
							log.Fatal(err)
						}
					}
				case err := <-watcher.Errors:
					log.Fatal(err)
				}
			}
		}()

		paths, err := getAllSubdirectories(sourcedir)
		if err != nil {
			log.Fatal(err)
		}
		for _, path := range paths {
			watcher.Add(path)
		}

		addr := fmt.Sprintf(":%d", opts.ServerPort)
		log.Printf("Static server created on address %s\n", addr)
		log.Fatal(
			http.ListenAndServe(addr, http.FileServer(http.Dir(outdir))))
	}
}
<|endoftext|>


<commit_before>package log

import (
	. "github.com/divtxt/raft"
	"github.com/divtxt/raft/testdata"
	"strconv"
)

// Make an InMemoryLog with 10 entries with terms as shown in Figure 7, leader line.
// Commands will be Command("c1"), Command("c2"), etc.
func TestUtil_NewInMemoryLog_WithFigure7LeaderLine(maxEntriesPerAppendEntry uint64) *InMemoryLog {
	figure7LeaderLine := testdata.TestUtil_MakeFigure7LeaderLineTerms()
	return TestUtil_NewInMemoryLog_WithTerms(figure7LeaderLine, maxEntriesPerAppendEntry)
}

// Make an InMemoryLog with entries with given terms.
// Commands will be Command("c1"), Command("c2"), etc.
func TestUtil_NewInMemoryLog_WithTerms(
	logTerms []TermNo,
	maxEntriesPerAppendEntry uint64,
) *InMemoryLog {
	inmem_log := NewInMemoryLog(maxEntriesPerAppendEntry)

	for i, term := range logTerms {
		command := Command("c" + strconv.Itoa(i+1))
		inmem_log.AppendEntry(term, command)
	}

	return inmem_log
}

// Test Helper
func TestHelper_GetLogEntryAtIndex(log LogReadOnly, li LogIndex) LogEntry {
	if li == 0 {
		panic("oops!")
	}
	entries, err := log.GetEntriesAfterIndex(li - 1)
	if err != nil {
		panic(err)
	}
	return entries[0]
}
<commit_msg>Add missing err check<commit_after>package log

import (
	. "github.com/divtxt/raft"
	"github.com/divtxt/raft/testdata"
	"strconv"
)

// Make an InMemoryLog with 10 entries with terms as shown in Figure 7, leader line.
// Commands will be Command("c1"), Command("c2"), etc.
func TestUtil_NewInMemoryLog_WithFigure7LeaderLine(maxEntriesPerAppendEntry uint64) *InMemoryLog {
	figure7LeaderLine := testdata.TestUtil_MakeFigure7LeaderLineTerms()
	return TestUtil_NewInMemoryLog_WithTerms(figure7LeaderLine, maxEntriesPerAppendEntry)
}

// Make an InMemoryLog with entries with given terms.
// Commands will be Command("c1"), Command("c2"), etc.
func TestUtil_NewInMemoryLog_WithTerms(
	logTerms []TermNo,
	maxEntriesPerAppendEntry uint64,
) *InMemoryLog {
	inmem_log := NewInMemoryLog(maxEntriesPerAppendEntry)

	for i, term := range logTerms {
		command := Command("c" + strconv.Itoa(i+1))
		err := inmem_log.AppendEntry(term, command)
		if err != nil {
			panic(err)
		}
	}

	return inmem_log
}

// Test Helper
func TestHelper_GetLogEntryAtIndex(log LogReadOnly, li LogIndex) LogEntry {
	if li == 0 {
		panic("oops!")
	}
	entries, err := log.GetEntriesAfterIndex(li - 1)
	if err != nil {
		panic(err)
	}
	return entries[0]
}
<|endoftext|>


<commit_before>package facebook

type News struct {
	ID string
	From Object
	To []Object
	Message string
	Actions []Link
	Type string
	CreatedTime string
	UpdatedTime string
	Likes string
	Comments []Comment
}

type Comment struct {
	ID string
	From Object
	Message string
	CreatedTime string

}
<commit_msg>Parse functions for home.go<commit_after>package facebook

type News struct {
	ID          string
	From        Object
	To          []Object
	Message     string
	Actions     []Link
	Type        string
	CreatedTime string
	UpdatedTime string
	Likes       string
	Comments    []Comment
}

func parseHome(value []interface{}) (news []News) {
	news = make([]News, len(value))
	for i, v := range value {
		wp := v.(map[string]interface{})
		for key, val := range wp {
			switch key {
			case "id":
				news[i].ID = val.(string)
			case "from":
				news[i].From = parseObject(val.(map[string]interface{}))
			case "to":
				data := val.(map[string]interface{})
				news[i].To = parseObjects(data["data"].([]interface{}))
			case "message":
				news[i].Message = val.(string)
			case "actions":
				news[i].Actions = parseLinks(val.([]interface{}))
			case "type":
				news[i].Type = val.(string)
			case "created_time":
				news[i].CreatedTime = val.(string)
			case "updated_time":
				news[i].UpdatedTime = val.(string)
			case "likes":
				news[i].Likes = val.(string)
			case "comments":
				data := val.(map[string]interface{})
				news[i].Comments = parseComments(data["data"].([]interface{}))
			}
		}
	}
	return
}

type Comment struct {
	ID          string
	From        Object
	Message     string
	CreatedTime string
}

func parseComment(value map[string]interface{}) (comment Comment) {
	comment.ID = value["id"].(string)
	comment.From = parseObject(value["from"].(map[string]interface{}))
	comment.Message = value["message"].(string)
	comment.CreatedTime = value["created_time"].(string)
	return
}

func parseComments(value []interface{}) (comments []Comment) {
	for i, v := range value {
		comments[i] = parseComment(v.(map[string]interface{}))
	}
	return
}
<|endoftext|>


<commit_before>// The joystick Package handles any joystick or gamepad events on the gl context,
// it can be used for feedback and input.
package joystick

import (
	"math"

	"github.com/veandco/go-sdl2/sdl"
)

// vibration is a struct that keeps track of vibration patterns and lengths for
// communication with sdl
type vibration struct {
	Left, Right float32
	Effect      sdl.HapticEffect
	Data        [4]uint16
	ID          int
	Endtime     uint32
}

// Joystick is an instance of any joystick or gamepad that is connected to the
// program.
type Joystick struct {
	id         int
	stick      *sdl.Joystick
	controller *sdl.GameController
	haptic     *sdl.Haptic
	vibration  *vibration
}

// open connects the joystick to the sdl instance, it will return true if successful
// and false if it could not get the joystick.
func (joystick *Joystick) open() bool {
	joystick.close()

	joystick.stick = sdl.JoystickOpen(joystick.id)

	if joystick.stick != nil && sdl.IsGameController(joystick.id) {
		joystick.controller = sdl.GameControllerOpen(joystick.id)
	}

	return joystick.IsConnected()
}

// IsGamepad gets whether the Joystick is recognized as a gamepad.
func (joystick *Joystick) IsGamepad() bool {
	return joystick.controller != nil
}

// GetID Gets the joystick's unique identifier.
func (joystick *Joystick) GetID() int {
	return joystick.id
}

// GetName the name of the joystick as it is identified on the os.
func (joystick *Joystick) GetName() string {
	// Prefer the Joystick name for consistency.
	name := joystick.stick.Name()
	if name == "" && joystick.controller != nil {
		name = joystick.controller.Name()
	}

	return name
}

// IsConnected gets whether the Joystick is connected.
func (joystick *Joystick) IsConnected() bool {
	return joystick.stick != nil && joystick.stick.GetAttached()
}

// GetGUID gets a stable GUID unique to the type of the physical joystick.
func (joystick *Joystick) GetGUID() string {
	return sdl.JoystickGetGUIDString(joystick.stick.GetGUID())
}

// getHandle gets the sdl instance id for this joystick
func (joystick *Joystick) getHandle() *sdl.Joystick {
	return joystick.stick
}

// close disconnects this joystick from the sdl instance.
func (joystick *Joystick) close() {
	if joystick.controller != nil {
		joystick.controller.Close()
	}
	if joystick.stick != nil {
		joystick.stick.Close()
	}
	joystick.stick = nil
	joystick.controller = nil
}

// IsDown checks if a button on the Joystick is pressed.
func (joystick *Joystick) IsDown(button int) bool {
	if joystick.IsConnected() == false {
		return false
	}
	return joystick.stick.GetButton(button) == 1
}

// GetAxisCount gets the number of axes on the joystick.
func (joystick *Joystick) GetAxisCount() int {
	if joystick.IsConnected() == false {
		return 0
	}
	return joystick.stick.NumAxes()
}

// GetButtonCount gets the number of buttons on the joystick.
func (joystick *Joystick) GetButtonCount() int {
	if joystick.IsConnected() == false {
		return 0
	}
	return joystick.stick.NumButtons()
}

// GetHatCount gets the number of hats on the joystick.
func (joystick *Joystick) GetHatCount() int {
	if joystick.IsConnected() == false {
		return 0
	}
	return joystick.stick.NumHats()
}

// GetAxis gets the direction of an axis. Values are clamped.
func (joystick *Joystick) GetAxis(axisindex int) float32 {
	if joystick.IsConnected() == false || axisindex < 0 || axisindex >= joystick.GetAxisCount() {
		return 0.0
	}

	return clampval(float32(joystick.stick.GetAxis(axisindex)) / 32768.0)
}

// GetAxes gets the direction of each axis. Values are clamped.
func (joystick *Joystick) GetAxes() []float32 {
	count := joystick.GetAxisCount()
	axes := []float32{}

	if joystick.IsConnected() == false || count <= 0 {
		return axes
	}

	for i := 0; i < count; i++ {
		axes = append(axes, clampval(float32(joystick.stick.GetAxis(i))/32768.0))
	}

	return axes
}

// GetHat gets the direction of a hat.
func (joystick *Joystick) GetHat(hatindex int) byte {
	if joystick.IsConnected() == false || hatindex < 0 || hatindex >= joystick.GetHatCount() {
		return 0
	}

	return joystick.stick.GetHat(hatindex)
}

// GetGamepadAxis gets the direction of a virtual gamepad axis. Values are clamped.
func (joystick *Joystick) GetGamepadAxis(axis GameControllerAxis) float32 {
	if joystick.IsConnected() == false || joystick.IsGamepad() == false {
		return 0.0
	}

	value := joystick.controller.GetAxis(sdl.GameControllerAxis(axis))

	return clampval(float32(value) / 32768.0)
}

// IsGamePadDown checks if a virtual gamepad button on the Joystick is pressed.
func (joystick *Joystick) IsGamepadDown(button GameControllerButton) bool {
	if joystick.IsConnected() == false || joystick.IsGamepad() == false {
		return false
	}

	return joystick.controller.GetButton(sdl.GameControllerButton(button)) == 1
}

// IsVibrationSupported gets whether the Joystick supports vibration.
func (joystick *Joystick) IsVibrationSupported() bool {
	if joystick.checkCreateHaptic() == false {
		return false
	}

	features := joystick.haptic.Query()

	if (features & sdl.HAPTIC_LEFTRIGHT) != 0 {
		return true
	}

	// Some gamepad drivers only support left/right motors via a custom effect.
	if joystick.IsGamepad() && (features&sdl.HAPTIC_CUSTOM) != 0 {
		return true
	}

	// Test for simple sine wave support as a last resort.
	if (features & sdl.HAPTIC_SINE) != 0 {
		return true
	}

	return false
}

// checkCreateHaptic will check the controller and the system if it supports
// haptic feedback and will enable it if it is able to do so. It will return
// if it was successful or not
func (joystick *Joystick) checkCreateHaptic() bool {
	if joystick.IsConnected() == false {
		return false
	}

	if sdl.WasInit(sdl.INIT_HAPTIC) == 0 && sdl.InitSubSystem(sdl.INIT_HAPTIC) != nil {
		return false
	}

	if joystick.haptic != nil && sdl.HapticIndex(joystick.haptic) != -1 {
		return true
	}

	if joystick.haptic != nil {
		joystick.haptic.Close()
	}

	joystick.haptic = sdl.HapticOpenFromJoystick(joystick.stick)
	joystick.vibration = &vibration{
		ID:      -1,
		Left:    0.0,
		Right:   0.0,
		Endtime: sdl.HAPTIC_INFINITY,
		Effect:  sdl.HapticEffect{},
	}

	return joystick.haptic != nil
}

// runVibrationEffect will initiate the joysticks haptic vibration and will return
// if it was successful in running the vibration.
func (joystick *Joystick) runVibrationEffect() bool {
	if joystick.vibration.ID != -1 {
		if joystick.haptic.UpdateEffect(joystick.vibration.ID, &joystick.vibration.Effect) == 0 {
			if joystick.haptic.RunEffect(joystick.vibration.ID, 1) == 0 {
				return true
			}
		}

		// If the effect fails to update, we should destroy and re-create it.
		joystick.haptic.DestroyEffect(joystick.vibration.ID)
		joystick.vibration.ID = -1
	}

	joystick.vibration.ID = joystick.haptic.NewEffect(&joystick.vibration.Effect)

	if joystick.vibration.ID != -1 && joystick.haptic.RunEffect(joystick.vibration.ID, 1) == 0 {
		return true
	}

	return false
}

// SetVibration sets the vibration motor speeds on a Joystick with rumble support.
// if passed no arguments it will stop the vibration. If passed one value it will
// set the vibration for both left and right with a duration of INFINITY. If passed
// two parameters it will set left and right intensities with a duration of INFINITY.
// If passed 3 parameters it will set both intensities and the diration as the third
// parameter, all other parameters will be ignored.
func (joystick *Joystick) SetVibration(args ...float32) bool {
	if !joystick.checkCreateHaptic() {
		return false
	}

	// no arguments given means stop the vibration
	if len(args) == 0 {
		return joystick.stopVibration()
	}

	left := float32(math.Min(math.Max(float64(args[0]), 0.0), 1.0))
	right := left

	if len(args) > 1 {
		right = float32(math.Min(math.Max(float64(right), 0.0), 1.0))
	}

	if left == 0.0 && right == 0.0 {
		return joystick.stopVibration()
	}

	length := sdl.HAPTIC_INFINITY
	if len(args) > 2 && args[2] >= 0.0 {
		maxduration := math.MaxUint32 / 1000.0
		length = int(math.Min(float64(args[2]), float64(maxduration)) * 1000)
	}

	success := false
	features := joystick.haptic.Query()
	axes := joystick.haptic.NumAxes()

	if (features & sdl.HAPTIC_LEFTRIGHT) != 0 {
		joystick.vibration.Effect.SetType(sdl.HAPTIC_LEFTRIGHT)
		lr := joystick.vibration.Effect.LeftRight()
		lr.Length = uint32(length)
		lr.LargeMagnitude = uint16(left * math.MaxUint16)
		lr.SmallMagnitude = uint16(right * math.MaxUint16)
		success = joystick.runVibrationEffect()
	}

	// Some gamepad drivers only give support for controlling individual motors
	// through a custom FF effect.
	if !success && joystick.IsGamepad() && (features&sdl.HAPTIC_CUSTOM) != 0 && axes == 2 {
		// NOTE: this may cause issues with drivers which support custom effects
		// but aren't similar to https://github.com/d235j/360Controller .

		// Custom effect data is clamped to 0x7FFF in SDL.
		joystick.vibration.Data[0] = uint16(left * 0x7FFF)
		joystick.vibration.Data[2] = uint16(left * 0x7FFF)
		joystick.vibration.Data[1] = uint16(right * 0x7FFF)
		joystick.vibration.Data[3] = uint16(right * 0x7FFF)

		joystick.vibration.Effect.SetType(sdl.HAPTIC_CUSTOM)
		custom := joystick.vibration.Effect.Custom()
		custom.Length = uint32(length)
		custom.Channels = 2
		custom.Period = 10
		custom.Samples = 2
		custom.Data = &joystick.vibration.Data[0]

		success = joystick.runVibrationEffect()
	}

	//// Fall back to a simple sine wave if all else fails. This only supports a
	//// single strength value.
	if !success && (features&sdl.HAPTIC_SINE) != 0 {
		joystick.vibration.Effect.SetType(sdl.HAPTIC_SINE)
		periodic := joystick.vibration.Effect.Periodic()
		periodic.Length = uint32(length)
		periodic.Period = 10
		strength := math.Max(float64(left), float64(right))
		periodic.Magnitude = int16(strength * 0x7FFF)
		success = joystick.runVibrationEffect()
	}

	if success {
		joystick.vibration.Left = left
		joystick.vibration.Right = right
		if length == sdl.HAPTIC_INFINITY {
			joystick.vibration.Endtime = sdl.HAPTIC_INFINITY
		} else {
			joystick.vibration.Endtime = sdl.GetTicks() + uint32(length)
		}
	} else {
		joystick.vibration.Left = 0.0
		joystick.vibration.Right = 0.0
		joystick.vibration.Endtime = sdl.HAPTIC_INFINITY
	}

	return success
}

// stopVibration will pause the vibration in the controller.
func (joystick *Joystick) stopVibration() bool {
	success := true

	if sdl.WasInit(sdl.INIT_HAPTIC) == 0 && joystick.haptic != nil && sdl.HapticIndex(joystick.haptic) != -1 {
		success = (joystick.haptic.StopEffect(joystick.vibration.ID) == 0)
	}

	if success {
		joystick.vibration.Left = 0.0
		joystick.vibration.Right = 0.0
	}

	return success
}

// GetVibration will return the current intensity of both the left and right motors
// currently vibrating. It will return 0s if they are not vibrating.
func (joystick *Joystick) GetVibration() (float32, float32) {
	if joystick.vibration.Endtime != sdl.HAPTIC_INFINITY {
		// With some drivers, the effect physically stops at the right time, but
		// SDL_HapticGetEffectStatus still thinks it's playing. So we explicitly
		// stop it once it's done, just to be sure.
		if joystick.vibration.Endtime-sdl.GetTicks() <= 0 {
			joystick.stopVibration()
			joystick.vibration.Endtime = sdl.HAPTIC_INFINITY
		}
	}

	// Check if the haptic effect has stopped playing.
	if joystick.haptic == nil || joystick.vibration.ID == -1 || joystick.haptic.GetEffectStatus(joystick.vibration.ID) != 1 {
		joystick.vibration.Left = 0.0
		joystick.vibration.Right = 0.0
	}

	return joystick.vibration.Left, joystick.vibration.Right
}
<commit_msg>fixing the joystick id change in the joystickopen sdl call. this closes #2<commit_after>// The joystick Package handles any joystick or gamepad events on the gl context,
// it can be used for feedback and input.
package joystick

import (
	"math"

	"github.com/veandco/go-sdl2/sdl"
)

// vibration is a struct that keeps track of vibration patterns and lengths for
// communication with sdl
type vibration struct {
	Left, Right float32
	Effect      sdl.HapticEffect
	Data        [4]uint16
	ID          int
	Endtime     uint32
}

// Joystick is an instance of any joystick or gamepad that is connected to the
// program.
type Joystick struct {
	id         int
	stick      *sdl.Joystick
	controller *sdl.GameController
	haptic     *sdl.Haptic
	vibration  *vibration
}

// open connects the joystick to the sdl instance, it will return true if successful
// and false if it could not get the joystick.
func (joystick *Joystick) open() bool {
	joystick.close()

	joystick.stick = sdl.JoystickOpen(sdl.JoystickID(joystick.id))

	if joystick.stick != nil && sdl.IsGameController(joystick.id) {
		joystick.controller = sdl.GameControllerOpen(joystick.id)
	}

	return joystick.IsConnected()
}

// IsGamepad gets whether the Joystick is recognized as a gamepad.
func (joystick *Joystick) IsGamepad() bool {
	return joystick.controller != nil
}

// GetID Gets the joystick's unique identifier.
func (joystick *Joystick) GetID() int {
	return joystick.id
}

// GetName the name of the joystick as it is identified on the os.
func (joystick *Joystick) GetName() string {
	// Prefer the Joystick name for consistency.
	name := joystick.stick.Name()
	if name == "" && joystick.controller != nil {
		name = joystick.controller.Name()
	}

	return name
}

// IsConnected gets whether the Joystick is connected.
func (joystick *Joystick) IsConnected() bool {
	return joystick.stick != nil && joystick.stick.GetAttached()
}

// GetGUID gets a stable GUID unique to the type of the physical joystick.
func (joystick *Joystick) GetGUID() string {
	return sdl.JoystickGetGUIDString(joystick.stick.GetGUID())
}

// getHandle gets the sdl instance id for this joystick
func (joystick *Joystick) getHandle() *sdl.Joystick {
	return joystick.stick
}

// close disconnects this joystick from the sdl instance.
func (joystick *Joystick) close() {
	if joystick.controller != nil {
		joystick.controller.Close()
	}
	if joystick.stick != nil {
		joystick.stick.Close()
	}
	joystick.stick = nil
	joystick.controller = nil
}

// IsDown checks if a button on the Joystick is pressed.
func (joystick *Joystick) IsDown(button int) bool {
	if joystick.IsConnected() == false {
		return false
	}
	return joystick.stick.GetButton(button) == 1
}

// GetAxisCount gets the number of axes on the joystick.
func (joystick *Joystick) GetAxisCount() int {
	if joystick.IsConnected() == false {
		return 0
	}
	return joystick.stick.NumAxes()
}

// GetButtonCount gets the number of buttons on the joystick.
func (joystick *Joystick) GetButtonCount() int {
	if joystick.IsConnected() == false {
		return 0
	}
	return joystick.stick.NumButtons()
}

// GetHatCount gets the number of hats on the joystick.
func (joystick *Joystick) GetHatCount() int {
	if joystick.IsConnected() == false {
		return 0
	}
	return joystick.stick.NumHats()
}

// GetAxis gets the direction of an axis. Values are clamped.
func (joystick *Joystick) GetAxis(axisindex int) float32 {
	if joystick.IsConnected() == false || axisindex < 0 || axisindex >= joystick.GetAxisCount() {
		return 0.0
	}

	return clampval(float32(joystick.stick.GetAxis(axisindex)) / 32768.0)
}

// GetAxes gets the direction of each axis. Values are clamped.
func (joystick *Joystick) GetAxes() []float32 {
	count := joystick.GetAxisCount()
	axes := []float32{}

	if joystick.IsConnected() == false || count <= 0 {
		return axes
	}

	for i := 0; i < count; i++ {
		axes = append(axes, clampval(float32(joystick.stick.GetAxis(i))/32768.0))
	}

	return axes
}

// GetHat gets the direction of a hat.
func (joystick *Joystick) GetHat(hatindex int) byte {
	if joystick.IsConnected() == false || hatindex < 0 || hatindex >= joystick.GetHatCount() {
		return 0
	}

	return joystick.stick.GetHat(hatindex)
}

// GetGamepadAxis gets the direction of a virtual gamepad axis. Values are clamped.
func (joystick *Joystick) GetGamepadAxis(axis GameControllerAxis) float32 {
	if joystick.IsConnected() == false || joystick.IsGamepad() == false {
		return 0.0
	}

	value := joystick.controller.GetAxis(sdl.GameControllerAxis(axis))

	return clampval(float32(value) / 32768.0)
}

// IsGamePadDown checks if a virtual gamepad button on the Joystick is pressed.
func (joystick *Joystick) IsGamepadDown(button GameControllerButton) bool {
	if joystick.IsConnected() == false || joystick.IsGamepad() == false {
		return false
	}

	return joystick.controller.GetButton(sdl.GameControllerButton(button)) == 1
}

// IsVibrationSupported gets whether the Joystick supports vibration.
func (joystick *Joystick) IsVibrationSupported() bool {
	if joystick.checkCreateHaptic() == false {
		return false
	}

	features := joystick.haptic.Query()

	if (features & sdl.HAPTIC_LEFTRIGHT) != 0 {
		return true
	}

	// Some gamepad drivers only support left/right motors via a custom effect.
	if joystick.IsGamepad() && (features&sdl.HAPTIC_CUSTOM) != 0 {
		return true
	}

	// Test for simple sine wave support as a last resort.
	if (features & sdl.HAPTIC_SINE) != 0 {
		return true
	}

	return false
}

// checkCreateHaptic will check the controller and the system if it supports
// haptic feedback and will enable it if it is able to do so. It will return
// if it was successful or not
func (joystick *Joystick) checkCreateHaptic() bool {
	if joystick.IsConnected() == false {
		return false
	}

	if sdl.WasInit(sdl.INIT_HAPTIC) == 0 && sdl.InitSubSystem(sdl.INIT_HAPTIC) != nil {
		return false
	}

	if joystick.haptic != nil && sdl.HapticIndex(joystick.haptic) != -1 {
		return true
	}

	if joystick.haptic != nil {
		joystick.haptic.Close()
	}

	joystick.haptic = sdl.HapticOpenFromJoystick(joystick.stick)
	joystick.vibration = &vibration{
		ID:      -1,
		Left:    0.0,
		Right:   0.0,
		Endtime: sdl.HAPTIC_INFINITY,
		Effect:  sdl.HapticEffect{},
	}

	return joystick.haptic != nil
}

// runVibrationEffect will initiate the joysticks haptic vibration and will return
// if it was successful in running the vibration.
func (joystick *Joystick) runVibrationEffect() bool {
	if joystick.vibration.ID != -1 {
		if joystick.haptic.UpdateEffect(joystick.vibration.ID, &joystick.vibration.Effect) == 0 {
			if joystick.haptic.RunEffect(joystick.vibration.ID, 1) == 0 {
				return true
			}
		}

		// If the effect fails to update, we should destroy and re-create it.
		joystick.haptic.DestroyEffect(joystick.vibration.ID)
		joystick.vibration.ID = -1
	}

	joystick.vibration.ID = joystick.haptic.NewEffect(&joystick.vibration.Effect)

	if joystick.vibration.ID != -1 && joystick.haptic.RunEffect(joystick.vibration.ID, 1) == 0 {
		return true
	}

	return false
}

// SetVibration sets the vibration motor speeds on a Joystick with rumble support.
// if passed no arguments it will stop the vibration. If passed one value it will
// set the vibration for both left and right with a duration of INFINITY. If passed
// two parameters it will set left and right intensities with a duration of INFINITY.
// If passed 3 parameters it will set both intensities and the diration as the third
// parameter, all other parameters will be ignored.
func (joystick *Joystick) SetVibration(args ...float32) bool {
	if !joystick.checkCreateHaptic() {
		return false
	}

	// no arguments given means stop the vibration
	if len(args) == 0 {
		return joystick.stopVibration()
	}

	left := float32(math.Min(math.Max(float64(args[0]), 0.0), 1.0))
	right := left

	if len(args) > 1 {
		right = float32(math.Min(math.Max(float64(right), 0.0), 1.0))
	}

	if left == 0.0 && right == 0.0 {
		return joystick.stopVibration()
	}

	length := sdl.HAPTIC_INFINITY
	if len(args) > 2 && args[2] >= 0.0 {
		maxduration := math.MaxUint32 / 1000.0
		length = int(math.Min(float64(args[2]), float64(maxduration)) * 1000)
	}

	success := false
	features := joystick.haptic.Query()
	axes := joystick.haptic.NumAxes()

	if (features & sdl.HAPTIC_LEFTRIGHT) != 0 {
		joystick.vibration.Effect.SetType(sdl.HAPTIC_LEFTRIGHT)
		lr := joystick.vibration.Effect.LeftRight()
		lr.Length = uint32(length)
		lr.LargeMagnitude = uint16(left * math.MaxUint16)
		lr.SmallMagnitude = uint16(right * math.MaxUint16)
		success = joystick.runVibrationEffect()
	}

	// Some gamepad drivers only give support for controlling individual motors
	// through a custom FF effect.
	if !success && joystick.IsGamepad() && (features&sdl.HAPTIC_CUSTOM) != 0 && axes == 2 {
		// NOTE: this may cause issues with drivers which support custom effects
		// but aren't similar to https://github.com/d235j/360Controller .

		// Custom effect data is clamped to 0x7FFF in SDL.
		joystick.vibration.Data[0] = uint16(left * 0x7FFF)
		joystick.vibration.Data[2] = uint16(left * 0x7FFF)
		joystick.vibration.Data[1] = uint16(right * 0x7FFF)
		joystick.vibration.Data[3] = uint16(right * 0x7FFF)

		joystick.vibration.Effect.SetType(sdl.HAPTIC_CUSTOM)
		custom := joystick.vibration.Effect.Custom()
		custom.Length = uint32(length)
		custom.Channels = 2
		custom.Period = 10
		custom.Samples = 2
		custom.Data = &joystick.vibration.Data[0]

		success = joystick.runVibrationEffect()
	}

	//// Fall back to a simple sine wave if all else fails. This only supports a
	//// single strength value.
	if !success && (features&sdl.HAPTIC_SINE) != 0 {
		joystick.vibration.Effect.SetType(sdl.HAPTIC_SINE)
		periodic := joystick.vibration.Effect.Periodic()
		periodic.Length = uint32(length)
		periodic.Period = 10
		strength := math.Max(float64(left), float64(right))
		periodic.Magnitude = int16(strength * 0x7FFF)
		success = joystick.runVibrationEffect()
	}

	if success {
		joystick.vibration.Left = left
		joystick.vibration.Right = right
		if length == sdl.HAPTIC_INFINITY {
			joystick.vibration.Endtime = sdl.HAPTIC_INFINITY
		} else {
			joystick.vibration.Endtime = sdl.GetTicks() + uint32(length)
		}
	} else {
		joystick.vibration.Left = 0.0
		joystick.vibration.Right = 0.0
		joystick.vibration.Endtime = sdl.HAPTIC_INFINITY
	}

	return success
}

// stopVibration will pause the vibration in the controller.
func (joystick *Joystick) stopVibration() bool {
	success := true

	if sdl.WasInit(sdl.INIT_HAPTIC) == 0 && joystick.haptic != nil && sdl.HapticIndex(joystick.haptic) != -1 {
		success = (joystick.haptic.StopEffect(joystick.vibration.ID) == 0)
	}

	if success {
		joystick.vibration.Left = 0.0
		joystick.vibration.Right = 0.0
	}

	return success
}

// GetVibration will return the current intensity of both the left and right motors
// currently vibrating. It will return 0s if they are not vibrating.
func (joystick *Joystick) GetVibration() (float32, float32) {
	if joystick.vibration.Endtime != sdl.HAPTIC_INFINITY {
		// With some drivers, the effect physically stops at the right time, but
		// SDL_HapticGetEffectStatus still thinks it's playing. So we explicitly
		// stop it once it's done, just to be sure.
		if joystick.vibration.Endtime-sdl.GetTicks() <= 0 {
			joystick.stopVibration()
			joystick.vibration.Endtime = sdl.HAPTIC_INFINITY
		}
	}

	// Check if the haptic effect has stopped playing.
	if joystick.haptic == nil || joystick.vibration.ID == -1 || joystick.haptic.GetEffectStatus(joystick.vibration.ID) != 1 {
		joystick.vibration.Left = 0.0
		joystick.vibration.Right = 0.0
	}

	return joystick.vibration.Left, joystick.vibration.Right
}
<|endoftext|>


<commit_before>package postgres

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"unicode"

	// Used pg drive on sqlx
	"github.com/jmoiron/sqlx"
	_ "github.com/lib/pq"

	"database/sql"

	"github.com/nuveo/prest/api"
	"github.com/nuveo/prest/config"
)

const (
	pageNumberKey   = "_page"
	pageSizeKey     = "_page_size"
	defaultPageSize = 10
)

var db *sqlx.DB

func init() {
	cfg := config.Prest{}
	config.Parse(&cfg)
	var err error
	dbUri := fmt.Sprintf("user=%s dbname=%s host=%s port=%v sslmode=disable", cfg.PGUser, cfg.PGDatabase, cfg.PGHost, cfg.PGPort)
	if cfg.PGPass != "" {
		dbUri += " password=" + cfg.PGPass
	}
	db, err = sqlx.Connect("postgres", dbUri)
	if err != nil {
		panic(fmt.Sprintf("Unable to connection to database: %v\n", err))
	}
	db.SetMaxIdleConns(cfg.PGMaxIdleConn)
	db.SetMaxOpenConns(cfg.PGMAxOpenConn)
}

// chkInvaidIdentifier return true if identifier is invalid
func chkInvaidIdentifier(identifer string) bool {
	if len(identifer) > 63 ||
		unicode.IsDigit([]rune(identifer)[0]) {
		return true
	}

	for _, v := range identifer {
		if !unicode.IsLetter(v) &&
			!unicode.IsDigit(v) &&
			v != '_' &&
			v != '.' {
			return true
		}
	}
	return false
}

// WhereByRequest create interface for queries + where
func WhereByRequest(r *http.Request, initialPlaceholderID int) (whereSyntax string, values []interface{}, err error) {
	whereKey := []string{}
	whereValues := []string{}

	u, _ := url.Parse(r.URL.String())
	pid := initialPlaceholderID
	for key, val := range u.Query() {
		if !strings.HasPrefix(key, "_") {
			keyInfo := strings.Split(key, ":")
			if len(keyInfo) > 1 {
				switch keyInfo[1] {
				case "jsonb":
					jsonField := strings.Split(keyInfo[0], "->>")
					if chkInvaidIdentifier(jsonField[0]) ||
						chkInvaidIdentifier(jsonField[1]) {
						err = errors.New("Invalid identifier")
						return
					}
					whereKey = append(whereKey, fmt.Sprintf("%s->>'%s'=$%d", jsonField[0], jsonField[1], pid))
					whereValues = append(whereValues, val[0])
				default:
					if chkInvaidIdentifier(keyInfo[0]) {
						err = errors.New("Invalid identifier")
						return
					}
					whereKey = append(whereKey, fmt.Sprintf("%s=$%d", keyInfo[0], pid))
					whereValues = append(whereValues, val[0])
				}
				continue
			}
			if chkInvaidIdentifier(key) {
				err = errors.New("Invalid identifier")
				return
			}

			whereKey = append(whereKey, fmt.Sprintf("%s=$%d", key, pid))
			whereValues = append(whereValues, val[0])

			pid++
		}
	}

	for i := 0; i < len(whereKey); i++ {
		if whereSyntax == "" {
			whereSyntax += whereKey[i]
		} else {
			whereSyntax += " AND " + whereKey[i]
		}

		values = append(values, whereValues[i])
	}

	return
}

// Query process queries
func Query(SQL string, params ...interface{}) (jsonData []byte, err error) {
	// db := connection.Conn()

	prepare, err := db.Prepare(SQL)

	if err != nil {
		return
	}

	rows, err := prepare.Query(params...)
	if err != nil {
		return
	}
	defer rows.Close()

	columns, err := rows.Columns()
	if err != nil {
		return
	}

	count := len(columns)
	tableData := make([]map[string]interface{}, 0)
	values := make([]interface{}, count)
	valuePtrs := make([]interface{}, count)
	for rows.Next() {
		for i := 0; i < count; i++ {
			valuePtrs[i] = &values[i]
		}
		rows.Scan(valuePtrs...)
		entry := make(map[string]interface{})
		for i, col := range columns {
			var v interface{}
			val := values[i]
			b, ok := val.([]byte)
			if ok {
				v = string(b)
			} else {
				v = val
			}
			entry[col] = v
		}
		tableData = append(tableData, entry)
	}
	jsonData, err = json.Marshal(tableData)

	return
}

// PaginateIfPossible func
func PaginateIfPossible(r *http.Request) (paginatedQuery string, err error) {
	u, _ := url.Parse(r.URL.String())
	values := u.Query()
	if _, ok := values[pageNumberKey]; !ok {
		paginatedQuery = ""
		return
	}
	pageNumber, err := strconv.Atoi(values[pageNumberKey][0])
	if err != nil {
		return
	}
	pageSize := defaultPageSize
	if size, ok := values[pageSizeKey]; ok {
		pageSize, err = strconv.Atoi(size[0])
		if err != nil {
			return
		}
	}
	paginatedQuery = fmt.Sprintf("LIMIT %d OFFSET(%d - 1) * %d", pageSize, pageNumber, pageSize)
	return
}

// Insert execute insert sql into a table
func Insert(database, schema, table string, body api.Request) (jsonData []byte, err error) {

	if chkInvaidIdentifier(database) ||
		chkInvaidIdentifier(schema) ||
		chkInvaidIdentifier(table) {
		err = errors.New("Insert: Invalid identifier")
		return
	}

	var result sql.Result
	var rowsAffected int64

	fields := make([]string, 0)
	values := make([]interface{}, 0)
	for key, value := range body.Data {
		if chkInvaidIdentifier(key) {
			err = errors.New("Insert: Invalid identifier")
			return
		}
		fields = append(fields, key)
		values = append(values, value)
	}

	colsName := strings.Join(fields, ", ")
	colPlaceholder := ""
	for i := 1; i < len(values)+1; i++ {
		if colPlaceholder != "" {
			colPlaceholder += ","
		}
		colPlaceholder += fmt.Sprintf("$%d", i)
	}

	sql := fmt.Sprintf("INSERT INTO %s.%s.%s (%s) VALUES (%s)", database, schema, table, colsName, colPlaceholder)

	// db := connection.Conn()
	stmt, err := db.Prepare(sql)
	if err != nil {
		return
	}

	valuesAux := make([]interface{}, 0, len(values))

	for i := 0; i < len(values); i++ {
		valuesAux = append(valuesAux, values[i])
	}

	result, err = stmt.Exec(valuesAux...)
	if err != nil {
		return
	}

	rowsAffected, err = result.RowsAffected()
	if err != nil {
		return
	}

	data := make(map[string]interface{})
	data["rows_affected"] = rowsAffected
	jsonData, err = json.Marshal(data)
	return
}

// Delete execute delete sql into a table
func Delete(database, schema, table, where string, whereValues []interface{}) (jsonData []byte, err error) {
	var result sql.Result
	var rowsAffected int64

	if chkInvaidIdentifier(database) ||
		chkInvaidIdentifier(schema) ||
		chkInvaidIdentifier(table) {
		err = errors.New("Delete: Invalid identifier")
		return
	}

	sql := fmt.Sprintf("DELETE FROM %s.%s.%s", database, schema, table)
	if where != "" {
		sql = fmt.Sprint(
			sql,
			" WHERE ",
			where)
	}

	// db := connection.Conn()
	result, err = db.Exec(sql, whereValues...)
	if err != nil {
		return
	}
	rowsAffected, err = result.RowsAffected()
	if err != nil {
		return
	}

	data := make(map[string]interface{})
	data["rows_affected"] = rowsAffected
	jsonData, err = json.Marshal(data)
	return
}

// Update execute update sql into a table
func Update(database, schema, table, where string, whereValues []interface{}, body api.Request) (jsonData []byte, err error) {

	if chkInvaidIdentifier(database) ||
		chkInvaidIdentifier(schema) ||
		chkInvaidIdentifier(table) {
		err = errors.New("Update: Invalid identifier")
		return
	}

	var result sql.Result
	var rowsAffected int64

	fields := []string{}
	values := make([]interface{}, 0)
	pid := len(whereValues) + 1 // placeholder id
	for key, value := range body.Data {
		fields = append(fields, fmt.Sprintf("%s=$%d", key, pid))
		values = append(values, value)
		pid++
	}
	setSyntax := strings.Join(fields, ", ")

	sql := fmt.Sprintf("UPDATE %s.%s.%s SET %s", database, schema, table, setSyntax)

	if where != "" {
		sql = fmt.Sprint(
			sql,
			" WHERE ",
			where)
		values = append(whereValues, values...)
	}

	// db := connection.Conn()
	stmt, err := db.Prepare(sql)
	if err != nil {
		return
	}

	valuesAux := make([]interface{}, 0, len(values))

	for i := 0; i < len(values); i++ {
		valuesAux = append(valuesAux, values[i])
	}

	result, err = stmt.Exec(valuesAux...)
	if err != nil {
		return
	}

	rowsAffected, err = result.RowsAffected()
	if err != nil {
		return
	}

	data := make(map[string]interface{})
	data["rows_affected"] = rowsAffected
	jsonData, err = json.Marshal(data)
	return
}
<commit_msg>fix lint<commit_after>package postgres

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"unicode"

	"github.com/jmoiron/sqlx"

	// Used pg drive on sqlx
	_ "github.com/lib/pq"

	"database/sql"

	"github.com/nuveo/prest/api"
	"github.com/nuveo/prest/config"
)

const (
	pageNumberKey   = "_page"
	pageSizeKey     = "_page_size"
	defaultPageSize = 10
)

var db *sqlx.DB

func init() {
	cfg := config.Prest{}
	config.Parse(&cfg)
	var err error
	dbURI := fmt.Sprintf("user=%s dbname=%s host=%s port=%v sslmode=disable", cfg.PGUser, cfg.PGDatabase, cfg.PGHost, cfg.PGPort)
	if cfg.PGPass != "" {
		dbURI += " password=" + cfg.PGPass
	}
	db, err = sqlx.Connect("postgres", dbURI)
	if err != nil {
		panic(fmt.Sprintf("Unable to connection to database: %v\n", err))
	}
	db.SetMaxIdleConns(cfg.PGMaxIdleConn)
	db.SetMaxOpenConns(cfg.PGMAxOpenConn)
}

// chkInvaidIdentifier return true if identifier is invalid
func chkInvaidIdentifier(identifer string) bool {
	if len(identifer) > 63 ||
		unicode.IsDigit([]rune(identifer)[0]) {
		return true
	}

	for _, v := range identifer {
		if !unicode.IsLetter(v) &&
			!unicode.IsDigit(v) &&
			v != '_' &&
			v != '.' {
			return true
		}
	}
	return false
}

// WhereByRequest create interface for queries + where
func WhereByRequest(r *http.Request, initialPlaceholderID int) (whereSyntax string, values []interface{}, err error) {
	whereKey := []string{}
	whereValues := []string{}

	u, _ := url.Parse(r.URL.String())
	pid := initialPlaceholderID
	for key, val := range u.Query() {
		if !strings.HasPrefix(key, "_") {
			keyInfo := strings.Split(key, ":")
			if len(keyInfo) > 1 {
				switch keyInfo[1] {
				case "jsonb":
					jsonField := strings.Split(keyInfo[0], "->>")
					if chkInvaidIdentifier(jsonField[0]) ||
						chkInvaidIdentifier(jsonField[1]) {
						err = errors.New("Invalid identifier")
						return
					}
					whereKey = append(whereKey, fmt.Sprintf("%s->>'%s'=$%d", jsonField[0], jsonField[1], pid))
					whereValues = append(whereValues, val[0])
				default:
					if chkInvaidIdentifier(keyInfo[0]) {
						err = errors.New("Invalid identifier")
						return
					}
					whereKey = append(whereKey, fmt.Sprintf("%s=$%d", keyInfo[0], pid))
					whereValues = append(whereValues, val[0])
				}
				continue
			}
			if chkInvaidIdentifier(key) {
				err = errors.New("Invalid identifier")
				return
			}

			whereKey = append(whereKey, fmt.Sprintf("%s=$%d", key, pid))
			whereValues = append(whereValues, val[0])

			pid++
		}
	}

	for i := 0; i < len(whereKey); i++ {
		if whereSyntax == "" {
			whereSyntax += whereKey[i]
		} else {
			whereSyntax += " AND " + whereKey[i]
		}

		values = append(values, whereValues[i])
	}

	return
}

// Query process queries
func Query(SQL string, params ...interface{}) (jsonData []byte, err error) {
	// db := connection.Conn()

	prepare, err := db.Prepare(SQL)

	if err != nil {
		return
	}

	rows, err := prepare.Query(params...)
	if err != nil {
		return
	}
	defer rows.Close()

	columns, err := rows.Columns()
	if err != nil {
		return
	}

	count := len(columns)
	tableData := make([]map[string]interface{}, 0)
	values := make([]interface{}, count)
	valuePtrs := make([]interface{}, count)
	for rows.Next() {
		for i := 0; i < count; i++ {
			valuePtrs[i] = &values[i]
		}
		rows.Scan(valuePtrs...)
		entry := make(map[string]interface{})
		for i, col := range columns {
			var v interface{}
			val := values[i]
			b, ok := val.([]byte)
			if ok {
				v = string(b)
			} else {
				v = val
			}
			entry[col] = v
		}
		tableData = append(tableData, entry)
	}
	jsonData, err = json.Marshal(tableData)

	return
}

// PaginateIfPossible func
func PaginateIfPossible(r *http.Request) (paginatedQuery string, err error) {
	u, _ := url.Parse(r.URL.String())
	values := u.Query()
	if _, ok := values[pageNumberKey]; !ok {
		paginatedQuery = ""
		return
	}
	pageNumber, err := strconv.Atoi(values[pageNumberKey][0])
	if err != nil {
		return
	}
	pageSize := defaultPageSize
	if size, ok := values[pageSizeKey]; ok {
		pageSize, err = strconv.Atoi(size[0])
		if err != nil {
			return
		}
	}
	paginatedQuery = fmt.Sprintf("LIMIT %d OFFSET(%d - 1) * %d", pageSize, pageNumber, pageSize)
	return
}

// Insert execute insert sql into a table
func Insert(database, schema, table string, body api.Request) (jsonData []byte, err error) {

	if chkInvaidIdentifier(database) ||
		chkInvaidIdentifier(schema) ||
		chkInvaidIdentifier(table) {
		err = errors.New("Insert: Invalid identifier")
		return
	}

	var result sql.Result
	var rowsAffected int64

	fields := make([]string, 0)
	values := make([]interface{}, 0)
	for key, value := range body.Data {
		if chkInvaidIdentifier(key) {
			err = errors.New("Insert: Invalid identifier")
			return
		}
		fields = append(fields, key)
		values = append(values, value)
	}

	colsName := strings.Join(fields, ", ")
	colPlaceholder := ""
	for i := 1; i < len(values)+1; i++ {
		if colPlaceholder != "" {
			colPlaceholder += ","
		}
		colPlaceholder += fmt.Sprintf("$%d", i)
	}

	sql := fmt.Sprintf("INSERT INTO %s.%s.%s (%s) VALUES (%s)", database, schema, table, colsName, colPlaceholder)

	// db := connection.Conn()
	stmt, err := db.Prepare(sql)
	if err != nil {
		return
	}

	valuesAux := make([]interface{}, 0, len(values))

	for i := 0; i < len(values); i++ {
		valuesAux = append(valuesAux, values[i])
	}

	result, err = stmt.Exec(valuesAux...)
	if err != nil {
		return
	}

	rowsAffected, err = result.RowsAffected()
	if err != nil {
		return
	}

	data := make(map[string]interface{})
	data["rows_affected"] = rowsAffected
	jsonData, err = json.Marshal(data)
	return
}

// Delete execute delete sql into a table
func Delete(database, schema, table, where string, whereValues []interface{}) (jsonData []byte, err error) {
	var result sql.Result
	var rowsAffected int64

	if chkInvaidIdentifier(database) ||
		chkInvaidIdentifier(schema) ||
		chkInvaidIdentifier(table) {
		err = errors.New("Delete: Invalid identifier")
		return
	}

	sql := fmt.Sprintf("DELETE FROM %s.%s.%s", database, schema, table)
	if where != "" {
		sql = fmt.Sprint(
			sql,
			" WHERE ",
			where)
	}

	// db := connection.Conn()
	result, err = db.Exec(sql, whereValues...)
	if err != nil {
		return
	}
	rowsAffected, err = result.RowsAffected()
	if err != nil {
		return
	}

	data := make(map[string]interface{})
	data["rows_affected"] = rowsAffected
	jsonData, err = json.Marshal(data)
	return
}

// Update execute update sql into a table
func Update(database, schema, table, where string, whereValues []interface{}, body api.Request) (jsonData []byte, err error) {

	if chkInvaidIdentifier(database) ||
		chkInvaidIdentifier(schema) ||
		chkInvaidIdentifier(table) {
		err = errors.New("Update: Invalid identifier")
		return
	}

	var result sql.Result
	var rowsAffected int64

	fields := []string{}
	values := make([]interface{}, 0)
	pid := len(whereValues) + 1 // placeholder id
	for key, value := range body.Data {
		fields = append(fields, fmt.Sprintf("%s=$%d", key, pid))
		values = append(values, value)
		pid++
	}
	setSyntax := strings.Join(fields, ", ")

	sql := fmt.Sprintf("UPDATE %s.%s.%s SET %s", database, schema, table, setSyntax)

	if where != "" {
		sql = fmt.Sprint(
			sql,
			" WHERE ",
			where)
		values = append(whereValues, values...)
	}

	// db := connection.Conn()
	stmt, err := db.Prepare(sql)
	if err != nil {
		return
	}

	valuesAux := make([]interface{}, 0, len(values))

	for i := 0; i < len(values); i++ {
		valuesAux = append(valuesAux, values[i])
	}

	result, err = stmt.Exec(valuesAux...)
	if err != nil {
		return
	}

	rowsAffected, err = result.RowsAffected()
	if err != nil {
		return
	}

	data := make(map[string]interface{})
	data["rows_affected"] = rowsAffected
	jsonData, err = json.Marshal(data)
	return
}
<|endoftext|>


<commit_before>package digitalocean

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"
)

var (
	mux    *http.ServeMux
	server *httptest.Server
)

func setup() {
	mux = http.NewServeMux()
	server = httptest.NewServer(mux)
	os.Setenv("DIGITALOCEAN_API_URL", server.URL)
	os.Setenv("DIGITALOCEAN_API_KEY", "api-key")
}

func teardown() {
	server.Close()
}

func TestAuth(t *testing.T) {
	for _, test := range []struct {
		apiKEY   string
		apiURL   string
		baseURL  string
		errIsNil bool
	}{
		{"", "", "", false},
		{"apikey", "", "https://api.digitalocean.com/", true},
		{"apikey", "http://127.0.0.1:3000", "http://127.0.0.1:3000", true},
		{"apikey", "://localhost", "", false},
	} {
		do := &Digitalocean{}
		os.Setenv("DIGITALOCEAN_API_KEY", test.apiKEY)
		os.Setenv("DIGITALOCEAN_API_URL", test.apiURL)
		errBool := do.Auth() == nil
		if errBool != test.errIsNil {
			t.Errorf("%+v Expected %+v but found %+v", test, test.errIsNil, errBool)
		}
		if errBool && (do.client.BaseURL.String() != test.baseURL) {
			t.Errorf("Expected %q but found %q", test.baseURL, do.client.BaseURL)
		}
	}
}

func TestCreateMachine(t *testing.T) {
	setup()
	defer teardown()
	mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			t.Fatalf("Expected method POST but request method is %s", r.Method)
		}
		droplet := `{"droplet": {
						"id": 1,
						"name": "gofn",
						"region": {"slug": "nyc3"},
						"status": "new",
						"image": {"slug": "ubuntu-16-10-x64"},
						"networks": {
							"v4":[
								{
									"ip_address": "104.131.186.241",
									"type": "public"
								}
							]
						}
					}
				}`
		w.Header().Set("Content-Type", "application/json; charset=utf8")
		fmt.Fprintln(w, droplet)
	})
	mux.HandleFunc("/v2/account/keys", func(w http.ResponseWriter, r *http.Request) {
		if r.Method == http.MethodPost {
			w.WriteHeader(201)
			key := `{
				"ssh_key": {
					"id": 512189,
					"fingerprint": "3b:16:bf:e4:8b:00:8b:b8:59:8c:a9:d3:f0:19:45:fa",
					"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDDHr/jh2Jy4yALcK4JyWbVkPRaWmhck3IgCoeOO3z1e2dBowLh64QAM+Qb72pxekALga2oi4GvT+TlWNhzPH4V example",
					"name": "Gofn"
				}
			}`
			fmt.Fprintln(w, key)
		}
		if r.Method == http.MethodGet {
			w.WriteHeader(200)
		}
		keys := `{
			"ssh_keys": [
				{
				"id": 512189,
				"fingerprint": "3b:16:bf:e4:8b:00:8b:b8:59:8c:a9:d3:f0:19:45:fa",
				"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDDHr/jh2Jy4yALcK4JyWbVkPRaWmhck3IgCoeOO3z1e2dBowLh64QAM+Qb72pxekALga2oi4GvT+TlWNhzPH4V example",
				"name": "Gofn"
				}
			]
		}`
		fmt.Fprintln(w, keys)
	})
	do := &Digitalocean{}
	m, err := do.CreateMachine()
	if err != nil {
		t.Fatalf("Expected run without errors but has %q", err)
	}
	if m.ID != "1" {
		t.Errorf("Expected id = 1 but found %s", m.ID)
	}
	if m.IP != "104.131.186.241" {
		t.Errorf("Expected id = 104.131.186.241 but found %s", m.IP)
	}
	if m.Name != "gofn" {
		t.Errorf("Expected name = \"gofn\" but found %q", m.Name)
	}
	if m.Status != "new" {
		t.Errorf("Expected status = \"new\" but found %q", m.Status)
	}
	if m.SSHKeysID[0] != 512189 {
		t.Errorf("Expected SSHKeysID = 512189 but found %q", m.SSHKeysID[0])
	}
}

func TestCreateMachineWrongAuth(t *testing.T) {
	os.Setenv("DIGITALOCEAN_API_URL", "://localhost")
	do := &Digitalocean{}
	m, err := do.CreateMachine()
	if err == nil || m != nil {
		t.Errorf("expected erros but run without errors")
	}
}

func TestCreateMachineWrongIP(t *testing.T) {
	setup()
	defer teardown()
	mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			t.Fatalf("Expected method POST but request method is %s", r.Method)
		}
		droplet := `{"droplet": {
						"id": 1,
						"name": "gofn",
						"region": {"slug": "nyc3"},
						"status": "new",
						"image": {"slug": "ubuntu-16-10-x64"}
					}
				}`
		w.Header().Set("Content-Type", "application/json; charset=utf8")
		fmt.Fprintln(w, droplet)
	})
	do := &Digitalocean{}
	_, err := do.CreateMachine()
	if err == nil {
		t.Errorf("expected errors but run without errors")
	}
}

func TestCreateMachineRequestError(t *testing.T) {
	setup()
	defer teardown()
	mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			t.Fatalf("Expected method POST but request method is %s", r.Method)
		}
		droplet := `{"droplet": {
						"id": 1,
						"name": "gofn",
						"region": {"slug": "nyc3"},
						"status": "new",
						"image": {"slug": "ubuntu-16-10-x64"},
					}
				}`
		w.Header().Set("Content-Type", "application/json; charset=utf8")
		fmt.Fprintln(w, droplet)
	})
	do := &Digitalocean{}
	_, err := do.CreateMachine()
	if err == nil {
		t.Errorf("expected errors but run without errors")
	}
}

func TestCreateMachineWithNewSSHKey(t *testing.T) {
	setup()
	defer teardown()
	mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			t.Fatalf("Expected method POST but request method is %s", r.Method)
		}
		droplet := `{"droplet": {
						"id": 1,
						"name": "gofn",
						"region": {"slug": "nyc3"},
						"status": "new",
						"image": {"slug": "ubuntu-16-10-x64"},
						"networks": {
							"v4":[
								{
									"ip_address": "104.131.186.241",
									"type": "public"
								}
							]
						}
					}
				}`
		w.Header().Set("Content-Type", "application/json; charset=utf8")
		fmt.Fprintln(w, droplet)
	})
	mux.HandleFunc("/v2/account/keys", func(w http.ResponseWriter, r *http.Request) {
		if r.Method == http.MethodPost {
			w.WriteHeader(201)
			key := `{
				"ssh_key": {
					"id": 512189,
					"fingerprint": "3b:16:bf:e4:8b:00:8b:b8:59:8c:a9:d3:f0:19:45:fa",
					"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDDHr/jh2Jy4yALcK4JyWbVkPRaWmhck3IgCoeOO3z1e2dBowLh64QAM+Qb72pxekALga2oi4GvT+TlWNhzPH4V example",
					"name": "my key"
				}
			}`
			fmt.Fprintln(w, key)
		}
		if r.Method == http.MethodGet {
			w.WriteHeader(200)
		}
		keys := `{
			"ssh_keys": [
				{
				"id": 512189,
				"fingerprint": "3b:16:bf:e4:8b:00:8b:b8:59:8c:a9:d3:f0:19:45:fa",
				"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDDHr/jh2Jy4yALcK4JyWbVkPRaWmhck3IgCoeOO3z1e2dBowLh64QAM+Qb72pxekALga2oi4GvT+TlWNhzPH4V example",
				"name": "Gofn"
				}
			]
		}`
		fmt.Fprintln(w, keys)
	})
	do := &Digitalocean{}
	m, err := do.CreateMachine()
	if err != nil {
		t.Fatalf("Expected run without errors but has %q", err)
	}
	if m.ID != "1" {
		t.Errorf("Expected id = 1 but found %s", m.ID)
	}
	if m.IP != "104.131.186.241" {
		t.Errorf("Expected id = 104.131.186.241 but found %s", m.IP)
	}
	if m.Name != "gofn" {
		t.Errorf("Expected name = \"gofn\" but found %q", m.Name)
	}
	if m.Status != "new" {
		t.Errorf("Expected status = \"new\" but found %q", m.Status)
	}
	if m.SSHKeysID[0] != 512189 {
		t.Errorf("Expected SSHKeysID = 512189 but found %q", m.SSHKeysID[0])
	}
}
<commit_msg>fix tests<commit_after>package digitalocean

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"
)

var (
	mux    *http.ServeMux
	server *httptest.Server
)

func setup() {
	mux = http.NewServeMux()
	server = httptest.NewServer(mux)
	os.Setenv("DIGITALOCEAN_API_URL", server.URL)
	os.Setenv("DIGITALOCEAN_API_KEY", "api-key")
}

func teardown() {
	server.Close()
}

func TestAuth(t *testing.T) {
	for _, test := range []struct {
		apiKEY   string
		apiURL   string
		baseURL  string
		errIsNil bool
	}{
		{"", "", "", false},
		{"apikey", "", "https://api.digitalocean.com/", true},
		{"apikey", "http://127.0.0.1:3000", "http://127.0.0.1:3000", true},
		{"apikey", "://localhost", "", false},
	} {
		do := &Digitalocean{}
		os.Setenv("DIGITALOCEAN_API_KEY", test.apiKEY)
		os.Setenv("DIGITALOCEAN_API_URL", test.apiURL)
		errBool := do.Auth() == nil
		if errBool != test.errIsNil {
			t.Errorf("%+v Expected %+v but found %+v", test, test.errIsNil, errBool)
		}
		if errBool && (do.client.BaseURL.String() != test.baseURL) {
			t.Errorf("Expected %q but found %q", test.baseURL, do.client.BaseURL)
		}
	}
}

func TestCreateMachine(t *testing.T) {
	setup()
	defer teardown()
	mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			t.Fatalf("Expected method POST but request method is %s", r.Method)
		}
		droplet := `{"droplet": {
						"id": 1,
						"name": "gofn",
						"region": {"slug": "nyc3"},
						"status": "new",
						"image": {"slug": "ubuntu-16-10-x64"},
						"networks": {
							"v4":[
								{
									"ip_address": "104.131.186.241",
									"type": "public"
								}
							]
						}
					}
				}`
		w.Header().Set("Content-Type", "application/json; charset=utf8")
		fmt.Fprintln(w, droplet)
	})
	mux.HandleFunc("/v2/account/keys", func(w http.ResponseWriter, r *http.Request) {
		if r.Method == http.MethodPost {
			w.WriteHeader(201)
			key := `{
				"ssh_key": {
					"id": 512189,
					"fingerprint": "3b:16:bf:e4:8b:00:8b:b8:59:8c:a9:d3:f0:19:45:fa",
					"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDDHr/jh2Jy4yALcK4JyWbVkPRaWmhck3IgCoeOO3z1e2dBowLh64QAM+Qb72pxekALga2oi4GvT+TlWNhzPH4V example",
					"name": "Gofn"
				}
			}`
			fmt.Fprintln(w, key)
		}
		if r.Method == http.MethodGet {
			w.WriteHeader(200)
		}
		keys := `{
			"ssh_keys": [
				{
				"id": 512189,
				"fingerprint": "3b:16:bf:e4:8b:00:8b:b8:59:8c:a9:d3:f0:19:45:fa",
				"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDDHr/jh2Jy4yALcK4JyWbVkPRaWmhck3IgCoeOO3z1e2dBowLh64QAM+Qb72pxekALga2oi4GvT+TlWNhzPH4V example",
				"name": "Gofn"
				}
			]
		}`
		fmt.Fprintln(w, keys)
	})
	do := &Digitalocean{}
	m, err := do.CreateMachine()
	if err != nil {
		t.Fatalf("Expected run without errors but has %q", err)
	}
	if m.ID != "1" {
		t.Errorf("Expected id = 1 but found %s", m.ID)
	}
	if m.IP != "104.131.186.241" {
		t.Errorf("Expected id = 104.131.186.241 but found %s", m.IP)
	}
	if m.Name != "gofn" {
		t.Errorf("Expected name = \"gofn\" but found %q", m.Name)
	}
	if m.Status != "new" {
		t.Errorf("Expected status = \"new\" but found %q", m.Status)
	}
	if m.SSHKeysID[0] != 512189 {
		t.Errorf("Expected SSHKeysID = 512189 but found %q", m.SSHKeysID[0])
	}
}

func TestCreateMachineWrongAuth(t *testing.T) {
	os.Setenv("DIGITALOCEAN_API_URL", "://localhost")
	do := &Digitalocean{}
	m, err := do.CreateMachine()
	if err == nil || m != nil {
		t.Errorf("expected erros but run without errors")
	}
}

func TestCreateMachineWrongIP(t *testing.T) {
	setup()
	defer teardown()
	mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			t.Fatalf("Expected method POST but request method is %s", r.Method)
		}
		droplet := `{"droplet": {
						"id": 1,
						"name": "gofn",
						"region": {"slug": "nyc3"},
						"status": "new",
						"image": {"slug": "ubuntu-16-10-x64"}
					}
				}`
		w.Header().Set("Content-Type", "application/json; charset=utf8")
		fmt.Fprintln(w, droplet)
	})
	do := &Digitalocean{}
	_, err := do.CreateMachine()
	if err == nil {
		t.Errorf("expected errors but run without errors")
	}
}

func TestCreateMachineRequestError(t *testing.T) {
	setup()
	defer teardown()
	mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			t.Fatalf("Expected method POST but request method is %s", r.Method)
		}
		droplet := `{"droplet": {
						"id": 1,
						"name": "gofn",
						"region": {"slug": "nyc3"},
						"status": "new",
						"image": {"slug": "ubuntu-16-10-x64"},
					}
				}`
		w.Header().Set("Content-Type", "application/json; charset=utf8")
		fmt.Fprintln(w, droplet)
	})
	do := &Digitalocean{}
	_, err := do.CreateMachine()
	if err == nil {
		t.Errorf("expected errors but run without errors")
	}
}

func TestCreateMachineWithNewSSHKey(t *testing.T) {
	setup()
	defer teardown()
	mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			t.Fatalf("Expected method POST but request method is %s", r.Method)
		}
		droplet := `{"droplet": {
						"id": 1,
						"name": "gofn",
						"region": {"slug": "nyc3"},
						"status": "new",
						"image": {"slug": "ubuntu-16-10-x64"},
						"networks": {
							"v4":[
								{
									"ip_address": "104.131.186.241",
									"type": "public"
								}
							]
						}
					}
				}`
		w.Header().Set("Content-Type", "application/json; charset=utf8")
		fmt.Fprintln(w, droplet)
	})
	mux.HandleFunc("/v2/account/keys", func(w http.ResponseWriter, r *http.Request) {
		if r.Method == http.MethodPost {
			w.WriteHeader(201)
			key := `{
				"ssh_key": {
					"id": 512189,
					"fingerprint": "3b:16:bf:e4:8b:00:8b:b8:59:8c:a9:d3:f0:19:45:fa",
					"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDDHr/jh2Jy4yALcK4JyWbVkPRaWmhck3IgCoeOO3z1e2dBowLh64QAM+Qb72pxekALga2oi4GvT+TlWNhzPH4V example",
					"name": "my key"
				}
			}`
			fmt.Fprintln(w, key)
		}
		if r.Method == http.MethodGet {
			w.WriteHeader(200)

			keys := `{
			"ssh_keys": [
				{
				"id": 512189,
				"fingerprint": "3b:16:bf:e4:8b:00:8b:b8:59:8c:a9:d3:f0:19:45:fa",
				"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDDHr/jh2Jy4yALcK4JyWbVkPRaWmhck3IgCoeOO3z1e2dBowLh64QAM+Qb72pxekALga2oi4GvT+TlWNhzPH4V example",
				"name": "Gofn"
				}
			]
		}`
			fmt.Fprintln(w, keys)
		}
	})
	do := &Digitalocean{}
	m, err := do.CreateMachine()
	if err != nil {
		t.Fatalf("Expected run without errors but has %q", err)
	}
	if m.ID != "1" {
		t.Errorf("Expected id = 1 but found %s", m.ID)
	}
	if m.IP != "104.131.186.241" {
		t.Errorf("Expected id = 104.131.186.241 but found %s", m.IP)
	}
	if m.Name != "gofn" {
		t.Errorf("Expected name = \"gofn\" but found %q", m.Name)
	}
	if m.Status != "new" {
		t.Errorf("Expected status = \"new\" but found %q", m.Status)
	}
	if m.SSHKeysID[0] != 512189 {
		t.Errorf("Expected SSHKeysID = 512189 but found %q", m.SSHKeysID[0])
	}
}
<|endoftext|>