<commit_before>// Copyright (c) 2015, Ben Morgan. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.

package repoctl

import (
	"os"
	"path"

	"github.com/goulash/errs"
	"github.com/goulash/osutil"
	pu "github.com/goulash/pacman/pkgutil"
)

// Link tries to hard link the file, and failing that, copies it over.
func (r *Repo) Link(h errs.Handler, pkgfiles ...string) error {
	return r.add(h, pkgfiles, linkFile, "linking")
}

// TODO: Get this in the osutil package.
func linkFile(src, dst string) error {
	err := os.Link(src, dst)
	if err != nil {
		// If we can't link it (not same filesystem, etc.), then try copying.
		return osutil.CopyFileLazy(src, dst)
	}
	return nil
}

// Copy copies the given files into the repository if they do not already
// exist there and adds them to the database.
func (r *Repo) Copy(h errs.Handler, pkgfiles ...string) error {
	return r.add(h, pkgfiles, osutil.CopyFileLazy, "copying")
}

// Move moves the given files into the repository if they do not already
// exist there and adds them to the database. If the files already exist
// there, then they are still deleted from where they were. Thus, the
// move always appears to have worked, even if no work was done.
//
// The exception is that when the source and destination files are the
// same; then no move or deletion is performed.
func (r *Repo) Move(h errs.Handler, pkgfiles ...string) error {
	return r.add(h, pkgfiles, osutil.MoveFileLazy, "moving")
}

// add does the hard work of Move and Copy.
func (r *Repo) add(h errs.Handler, pkgfiles []string, ar func(string, string) error, lbl string) error {
	errs.Init(&h)
	if len(pkgfiles) == 0 {
		return nil
	}

	added := make([]string, 0, len(pkgfiles))
	for _, f := range pkgfiles {
		pkg, err := NewSignedPkg(f)
		if err != nil {
			// This means that we are trying to add something that's
			// non-existant or corrupt.
			r.errorf("skipping %s: %s", f, err)
			continue
		}
		if r.RequireSignature && !pkg.HasSignature() {
			r.errorf("skipping %s: require signature but none available", f)
			continue
		}

		r.printf("%s and adding to repository: %s\n", lbl, pkg.PathSet())
		err = pkg.Apply(func(src string, _ bool) error {
			dst := path.Join(r.Directory, path.Base(src))
			return ar(src, dst)
		})
		if err != nil {
			err = h(err)
			if err != nil {
				return err
			}
			continue
		}
		added = append(added, path.Join(r.Directory, path.Base(f)))
	}

	err := r.DatabaseAdd(added...)
	if err != nil {
		return err
	}

	pkgs, err := r.FindSimilar(h, added...)
	return r.Dispatch(h, pu.Map(pkgs, pu.PkgFilename)...)
}

// Remove removes the given names from the database and dispatches
// the files.
func (r *Repo) Remove(h errs.Handler, pkgnames ...string) error {
	errs.Init(&h)
	if len(pkgnames) == 0 {
		return nil
	}

	pkgs, err := r.ReadNames(h, pkgnames...)
	if err != nil {
		return err
	}
	err = h(r.DatabaseRemove(pu.Map(pkgs, pu.PkgName)...))
	if err != nil {
		return err
	}
	return r.Dispatch(h, pu.Map(pkgs, pu.PkgFilename)...)
}

// Dispatch either removes the given files or it backs them up.
func (r *Repo) Dispatch(h errs.Handler, pkgfiles ...string) error {
	errs.Init(&h)
	if len(pkgfiles) == 0 {
		return nil
	}

	if r.Backup {
		return r.backup(h, pkgfiles)
	}
	return r.unlink(h, pkgfiles)
}

// IsObsoleteCached returns true when obsolete package files should
// be cached instead of backed-up or deleted.
//
// If the backup directory is the directory where all the
// packages are, then the idea is that we leave them in place.
func (r *Repo) IsObsoleteCached() bool {
	// TODO: this assumes that r.Directory is absolute and clean.
	return r.backupDirAbs() == r.Directory
}

// backupDirAbs returns the absolute path to the backup directory.
// If r.BackupDir is relative, then it is relative to the repository
// path, otherwise it is as is.
func (r *Repo) backupDirAbs() string {
	if path.IsAbs(r.BackupDir) {
		return path.Clean(r.BackupDir)
	}
	return path.Join(r.Directory, r.BackupDir)
}

func (r *Repo) backup(h errs.Handler, pkgfiles []string) error {
	if r.IsObsoleteCached() {
		for _, f := range pkgfiles {
			r.debugf("cached: %s\n", f)
		}
		return nil
	}

	backupDir := r.backupDirAbs()
	for _, f := range pkgfiles {
		pkg, err := NewSignedPkg(f)
		if err != nil {
			err = h(err)
			if err != nil {
				return err
			}
			if pkg == nil {
				continue
			}
		}

		r.printf("backing up: %s\n", pkg.NameSet())
		err = pkg.Apply(func(f string, _ bool) error {
			src := path.Base(f)
			dst := path.Join(backupDir, src)
			return osutil.MoveFileLazy(f, dst)
		})
		if err != nil {
			err = h(err)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func (r *Repo) unlink(h errs.Handler, pkgfiles []string) error {
	for _, f := range pkgfiles {
		pkg, err := NewSignedPkg(f)
		if err != nil {
			err = h(err)
			if err != nil {
				return err
			}
			if pkg == nil {
				continue
			}
		}

		r.printf("deleting: %s\n", pkg.NameSet())

		err = pkg.Apply(func(f string, _ bool) error {
			return os.Remove(f)
		})
		if err != nil {
			err = h(err)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// Update adds the newest package found for the given name to the
// database and dispatches the obsolete packages. Any obsolete entries
// in the database are removed.
//
// If pkgnames is empty, the entire repository is scanned.
//
// TODO: What happens when there are multiple files, and you delete
// the most recent one. Which file is deleted?
func (r *Repo) Update(h errs.Handler, pkgnames ...string) error {
	errs.Init(&h)

	pkgs, err := r.ReadMeta(h, pkgnames...)
	if err != nil {
		return err
	}

	var updates []string
	var obsolete []string
	var missing []string
	for _, p := range pkgs {
		if !p.HasFiles() {
			missing = append(missing, p.Name)
			continue
		}
		if p.HasObsolete() {
			obsolete = append(obsolete, pu.Map(p.Obsolete(), pu.PkgFilename)...)
		}
		if p.HasUpdate() || len(pkgnames) > 0 {
			f := p.Pkg().Filename
			if r.RequireSignature {
				spkg, err := NewSignedPkg(f)
				if err != nil {
					r.errorf("skipping %s: %s", f, err)
					continue
				} else if spkg.HasSignature() {
					r.errorf("skipping %s: require signature but none found", f)
					continue
				}
			}
			updates = append(updates, f)
		}
	}

	err = r.DatabaseRemove(missing...)
	if err != nil {
		return err
	}

	err = r.DatabaseAdd(updates...)
	if err != nil {
		return err
	}

	return r.Dispatch(h, obsolete...)
}

// Reset deletes the repository database and reads all the packages.
// This is the same as unlinking the database and then running Update.
func (r *Repo) Reset(h errs.Handler) error {
	errs.Init(&h)

	err := r.DeleteDatabase()
	if err != nil {
		return err
	}

	return r.Update(h)
}

// DeleteDatabase deletes the repository database (but not the files).
func (r *Repo) DeleteDatabase() error {
	db := path.Join(r.Directory, r.Database)
	r.printf("deleting database: %s\n", db)
	return os.Remove(db)
}
<commit_msg>Fix regression from handling signature files<commit_after>// Copyright (c) 2015, Ben Morgan. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.

package repoctl

import (
	"os"
	"path"

	"github.com/goulash/errs"
	"github.com/goulash/osutil"
	pu "github.com/goulash/pacman/pkgutil"
)

// Link tries to hard link the file, and failing that, copies it over.
func (r *Repo) Link(h errs.Handler, pkgfiles ...string) error {
	return r.add(h, pkgfiles, linkFile, "linking")
}

// TODO: Get this in the osutil package.
func linkFile(src, dst string) error {
	err := os.Link(src, dst)
	if err != nil {
		// If we can't link it (not same filesystem, etc.), then try copying.
		return osutil.CopyFileLazy(src, dst)
	}
	return nil
}

// Copy copies the given files into the repository if they do not already
// exist there and adds them to the database.
func (r *Repo) Copy(h errs.Handler, pkgfiles ...string) error {
	return r.add(h, pkgfiles, osutil.CopyFileLazy, "copying")
}

// Move moves the given files into the repository if they do not already
// exist there and adds them to the database. If the files already exist
// there, then they are still deleted from where they were. Thus, the
// move always appears to have worked, even if no work was done.
//
// The exception is that when the source and destination files are the
// same; then no move or deletion is performed.
func (r *Repo) Move(h errs.Handler, pkgfiles ...string) error {
	return r.add(h, pkgfiles, osutil.MoveFileLazy, "moving")
}

// add does the hard work of Move and Copy.
func (r *Repo) add(h errs.Handler, pkgfiles []string, ar func(string, string) error, lbl string) error {
	errs.Init(&h)
	if len(pkgfiles) == 0 {
		return nil
	}

	added := make([]string, 0, len(pkgfiles))
	for _, f := range pkgfiles {
		pkg, err := NewSignedPkg(f)
		if err != nil {
			// This means that we are trying to add something that's
			// non-existant or corrupt.
			r.errorf("skipping %s: %s", f, err)
			continue
		}
		if r.RequireSignature && !pkg.HasSignature() {
			r.errorf("skipping %s: require signature but none available", f)
			continue
		}

		r.printf("%s and adding to repository: %s\n", lbl, pkg.PathSet())
		err = pkg.Apply(func(src string, _ bool) error {
			dst := path.Join(r.Directory, path.Base(src))
			return ar(src, dst)
		})
		if err != nil {
			err = h(err)
			if err != nil {
				return err
			}
			continue
		}
		added = append(added, path.Join(r.Directory, path.Base(f)))
	}

	err := r.DatabaseAdd(added...)
	if err != nil {
		return err
	}

	pkgs, err := r.FindSimilar(h, added...)
	return r.Dispatch(h, pu.Map(pkgs, pu.PkgFilename)...)
}

// Remove removes the given names from the database and dispatches
// the files.
func (r *Repo) Remove(h errs.Handler, pkgnames ...string) error {
	errs.Init(&h)
	if len(pkgnames) == 0 {
		return nil
	}

	pkgs, err := r.ReadNames(h, pkgnames...)
	if err != nil {
		return err
	}
	err = h(r.DatabaseRemove(pu.Map(pkgs, pu.PkgName)...))
	if err != nil {
		return err
	}
	return r.Dispatch(h, pu.Map(pkgs, pu.PkgFilename)...)
}

// Dispatch either removes the given files or it backs them up.
func (r *Repo) Dispatch(h errs.Handler, pkgfiles ...string) error {
	errs.Init(&h)
	if len(pkgfiles) == 0 {
		return nil
	}

	if r.Backup {
		return r.backup(h, pkgfiles)
	}
	return r.unlink(h, pkgfiles)
}

// IsObsoleteCached returns true when obsolete package files should
// be cached instead of backed-up or deleted.
//
// If the backup directory is the directory where all the
// packages are, then the idea is that we leave them in place.
func (r *Repo) IsObsoleteCached() bool {
	// TODO: this assumes that r.Directory is absolute and clean.
	return r.backupDirAbs() == r.Directory
}

// backupDirAbs returns the absolute path to the backup directory.
// If r.BackupDir is relative, then it is relative to the repository
// path, otherwise it is as is.
func (r *Repo) backupDirAbs() string {
	if path.IsAbs(r.BackupDir) {
		return path.Clean(r.BackupDir)
	}
	return path.Join(r.Directory, r.BackupDir)
}

func (r *Repo) backup(h errs.Handler, pkgfiles []string) error {
	if r.IsObsoleteCached() {
		for _, f := range pkgfiles {
			r.debugf("cached: %s\n", f)
		}
		return nil
	}

	backupDir := r.backupDirAbs()
	for _, f := range pkgfiles {
		pkg, err := NewSignedPkg(f)
		if err != nil {
			err = h(err)
			if err != nil {
				return err
			}
			if pkg == nil {
				continue
			}
		}

		r.printf("backing up: %s\n", pkg.NameSet())
		err = pkg.Apply(func(f string, _ bool) error {
			src := path.Base(f)
			dst := path.Join(backupDir, src)
			return osutil.MoveFileLazy(f, dst)
		})
		if err != nil {
			err = h(err)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func (r *Repo) unlink(h errs.Handler, pkgfiles []string) error {
	for _, f := range pkgfiles {
		pkg, err := NewSignedPkg(f)
		if err != nil {
			err = h(err)
			if err != nil {
				return err
			}
			if pkg == nil {
				continue
			}
		}

		r.printf("deleting: %s\n", pkg.NameSet())

		err = pkg.Apply(func(f string, _ bool) error {
			return os.Remove(f)
		})
		if err != nil {
			err = h(err)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// Update adds the newest package found for the given name to the
// database and dispatches the obsolete packages. Any obsolete entries
// in the database are removed.
//
// If pkgnames is empty, the entire repository is scanned.
//
// TODO: What happens when there are multiple files, and you delete
// the most recent one. Which file is deleted?
func (r *Repo) Update(h errs.Handler, pkgnames ...string) error {
	errs.Init(&h)

	pkgs, err := r.ReadMeta(h, pkgnames...)
	if err != nil {
		return err
	}

	var updates []string
	var obsolete []string
	var missing []string
	for _, p := range pkgs {
		if !p.HasFiles() {
			missing = append(missing, p.Name)
			continue
		}
		if p.HasObsolete() {
			obsolete = append(obsolete, pu.Map(p.Obsolete(), pu.PkgFilename)...)
		}
		if p.HasUpdate() || len(pkgnames) > 0 {
			f := p.Pkg().Filename
			if r.RequireSignature {
				spkg, err := NewSignedPkg(f)
				if err != nil {
					r.errorf("skipping %s: %s", f, err)
					continue
				} else if !spkg.HasSignature() {
					r.errorf("skipping %s: require signature but none found", f)
					continue
				}
			}
			updates = append(updates, f)
		}
	}

	err = r.DatabaseRemove(missing...)
	if err != nil {
		return err
	}

	err = r.DatabaseAdd(updates...)
	if err != nil {
		return err
	}

	return r.Dispatch(h, obsolete...)
}

// Reset deletes the repository database and reads all the packages.
// This is the same as unlinking the database and then running Update.
func (r *Repo) Reset(h errs.Handler) error {
	errs.Init(&h)

	err := r.DeleteDatabase()
	if err != nil {
		return err
	}

	return r.Update(h)
}

// DeleteDatabase deletes the repository database (but not the files).
func (r *Repo) DeleteDatabase() error {
	db := path.Join(r.Directory, r.Database)
	r.printf("deleting database: %s\n", db)
	return os.Remove(db)
}
<|endoftext|>


<commit_before>// Copyright 2013 Andreas Koch. 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"
	"github.com/andreaskoch/allmark/config"
	"github.com/andreaskoch/allmark/renderer"
	"github.com/andreaskoch/allmark/server"
	"github.com/andreaskoch/allmark/util"
	"os"
	"strings"
)

const (
	CommandNameInit   = "init"
	CommandNameServe  = "serve"
	CommandNameRender = "render"
)

func main() {

	render := func(repositoryPath string) {
		config := config.GetConfig(repositoryPath)
		useTempDir := false
		renderer := renderer.New(repositoryPath, config, useTempDir)

		renderer.Execute()
	}

	serve := func(repositoryPath string) {

		config := config.GetConfig(repositoryPath)
		useTempDir := true
		server := server.New(repositoryPath, config, useTempDir)

		server.Serve()
	}

	init := func(repositoryPath string) {
		config.Initialize(repositoryPath)
	}

	parseCommandLineArguments(os.Args, func(commandName, repositoryPath string) (commandWasFound bool) {
		switch strings.ToLower(commandName) {
		case CommandNameInit:
			init(repositoryPath)

		case CommandNameRender:
			render(repositoryPath)

		case CommandNameServe:
			serve(repositoryPath)

		default:
			return false
		}

		return true
	})
}

func parseCommandLineArguments(args []string, commandHandler func(commandName, repositoryPath string) (commandWasFound bool)) {

	// check if the mandatory amount of
	// command line parameters has been
	// supplied. If not, print usage information.
	if len(args) < 2 {
		printUsageInformation(args)
		return
	}

	// Read the repository path parameters
	var repositoryPath string
	if len(args) > 2 {

		// use supplied repository path
		repositoryPath = args[2]

	} else {

		// use the current directory
		repositoryPath = util.GetWorkingDirectory()

	}

	// validate the supplied repository paths
	if !util.PathExists(repositoryPath) {
		fmt.Fprintf(os.Stderr, "The specified repository paths %q is does not exist.", repositoryPath)
		return
	}

	// Read the command parameter and execute the command handler
	commandName := strings.ToLower(args[1])
	if commandWasFound := commandHandler(commandName, repositoryPath); !commandWasFound {
		printUsageInformation(args)
	}
}

// Print usage information
func printUsageInformation(args []string) {
	executeableName := args[0]

	fmt.Fprintf(os.Stderr, "%s - %s\n", executeableName, "A markdown web server and renderer")
	fmt.Fprintf(os.Stderr, "\nUsage:\n%s %s %s\n", executeableName, "<command>", "<repository path>")
	fmt.Fprintf(os.Stderr, "\nAvailable commands:\n")
	fmt.Fprintf(os.Stderr, "  %7s  %s\n", CommandNameInit, "Initialize the configuration")
	fmt.Fprintf(os.Stderr, "  %7s  %s\n", CommandNameServe, "Start serving the supplied repository via HTTP")
	fmt.Fprintf(os.Stderr, "  %7s  %s\n", CommandNameRender, "Start rendering the items in the specified repository")
	fmt.Fprintf(os.Stderr, "\n")
	fmt.Fprintf(os.Stderr, "Fork me on GitHub %q", "https://github.com/andreaskoch/allmark")

	os.Exit(2)
}
<commit_msg>Continiously render<commit_after>// Copyright 2013 Andreas Koch. 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"
	"github.com/andreaskoch/allmark/config"
	"github.com/andreaskoch/allmark/renderer"
	"github.com/andreaskoch/allmark/server"
	"github.com/andreaskoch/allmark/util"
	"os"
	"strings"
	"time"
)

const (
	CommandNameInit   = "init"
	CommandNameServe  = "serve"
	CommandNameRender = "render"
)

func main() {

	render := func(repositoryPath string) {
		config := config.GetConfig(repositoryPath)
		useTempDir := false
		renderer := renderer.New(repositoryPath, config, useTempDir)

		renderer.Execute()

		for {
			time.Sleep(100 * time.Millisecond)
		}
	}

	serve := func(repositoryPath string) {

		config := config.GetConfig(repositoryPath)
		useTempDir := true
		server := server.New(repositoryPath, config, useTempDir)

		server.Serve()
	}

	init := func(repositoryPath string) {
		config.Initialize(repositoryPath)
	}

	parseCommandLineArguments(os.Args, func(commandName, repositoryPath string) (commandWasFound bool) {
		switch strings.ToLower(commandName) {
		case CommandNameInit:
			init(repositoryPath)

		case CommandNameRender:
			render(repositoryPath)

		case CommandNameServe:
			serve(repositoryPath)

		default:
			return false
		}

		return true
	})
}

func parseCommandLineArguments(args []string, commandHandler func(commandName, repositoryPath string) (commandWasFound bool)) {

	// check if the mandatory amount of
	// command line parameters has been
	// supplied. If not, print usage information.
	if len(args) < 2 {
		printUsageInformation(args)
		return
	}

	// Read the repository path parameters
	var repositoryPath string
	if len(args) > 2 {

		// use supplied repository path
		repositoryPath = args[2]

	} else {

		// use the current directory
		repositoryPath = util.GetWorkingDirectory()

	}

	// validate the supplied repository paths
	if !util.PathExists(repositoryPath) {
		fmt.Fprintf(os.Stderr, "The specified repository paths %q is does not exist.", repositoryPath)
		return
	}

	// Read the command parameter and execute the command handler
	commandName := strings.ToLower(args[1])
	if commandWasFound := commandHandler(commandName, repositoryPath); !commandWasFound {
		printUsageInformation(args)
	}
}

// Print usage information
func printUsageInformation(args []string) {
	executeableName := args[0]

	fmt.Fprintf(os.Stderr, "%s - %s\n", executeableName, "A markdown web server and renderer")
	fmt.Fprintf(os.Stderr, "\nUsage:\n%s %s %s\n", executeableName, "<command>", "<repository path>")
	fmt.Fprintf(os.Stderr, "\nAvailable commands:\n")
	fmt.Fprintf(os.Stderr, "  %7s  %s\n", CommandNameInit, "Initialize the configuration")
	fmt.Fprintf(os.Stderr, "  %7s  %s\n", CommandNameServe, "Start serving the supplied repository via HTTP")
	fmt.Fprintf(os.Stderr, "  %7s  %s\n", CommandNameRender, "Start rendering the items in the specified repository")
	fmt.Fprintf(os.Stderr, "\n")
	fmt.Fprintf(os.Stderr, "Fork me on GitHub %q", "https://github.com/andreaskoch/allmark")

	os.Exit(2)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"io"
	"log"
	"os"
	"time"

	"github.com/ecc1/medtronic"
	"github.com/ecc1/medtronic/packet"
)

const (
	verbose = false
)

type (
	SPILinkCommand struct {
		Command string
		Data    []byte // base64-encoded by json.Marshal
		Repeat  int
		Timeout int // microseconds
	}

	SPILinkResult struct {
		Data  []byte // base64-encoded by json.Marshal
		RSSI  int
		Error bool
	}
)

var (
	input  = json.NewDecoder(os.Stdin)
	output = json.NewEncoder(os.Stdout)

	radio = medtronic.Open().Radio
)

func main() {
	if radio.Error() != nil {
		log.Fatal(radio.Error())
	}
	for {
		cmd := readCommand()
		result := cmd.perform()
		err := output.Encode(result)
		radio.SetError(err)
		if radio.Error() != nil {
			log.Print(radio.Error())
			radio.SetError(nil)
		}
	}
}

func readCommand() SPILinkCommand {
	cmd := SPILinkCommand{}
	err := input.Decode(&cmd)
	if err == io.EOF {
		if verbose {
			log.Printf("EOF: exiting")
		}
		os.Exit(0)
	}
	if err != nil {
		log.Print(err)
	}
	return cmd
}

func (cmd SPILinkCommand) perform() SPILinkResult {
	if verbose {
		log.Printf("received %s command", cmd.Command)
	}
	timeout := time.Duration(cmd.Timeout) * time.Microsecond
	result := SPILinkResult{}
	switch cmd.Command {
	case "send_packet":
		result = send(cmd.Data, cmd.Repeat)
	case "get_packet":
		result = receive(timeout)
	case "send_and_listen":
		send(cmd.Data, cmd.Repeat)
		result = receive(timeout)
	default:
		log.Printf("unknown spilink command: %+v", cmd)
		result.Error = true
	}
	if verbose {
		log.Printf("returning %d-byte result", len(result.Data))
	}
	return result
}

func send(data []byte, repeat int) SPILinkResult {
	p := packet.Encode(data)
	if repeat == 0 {
		repeat = 1
	}
	if verbose {
		if repeat == 1 {
			log.Printf("sending %d-byte packet", len(p))
		} else {
			log.Printf("sending %d-byte packet %d times", len(p), repeat)
		}
	}
	for i := 0; i < repeat; i++ {
		radio.Send(p)
	}
	return SPILinkResult{}
}

func receive(timeout time.Duration) SPILinkResult {
	if verbose {
		log.Printf("receiving with timeout = %v", timeout)
	}
	result := SPILinkResult{}
	p, rssi := radio.Receive(timeout)
	data, err := packet.Decode6b4b(p)
	radio.SetError(err)
	result.Data = data
	if radio.Error() != nil {
		log.Print(radio.Error())
		radio.SetError(nil)
		result.Error = true
		return result
	}
	if verbose {
		log.Printf("received %d-byte packet (RSSI = %d)", len(p), rssi)
	}
	return result
}
<commit_msg>Fix warnings from gometalinter<commit_after>package main

import (
	"encoding/json"
	"io"
	"log"
	"os"
	"time"

	"github.com/ecc1/medtronic"
	"github.com/ecc1/medtronic/packet"
)

const (
	verbose = false
)

type (
	// SPILinkCommand represents a command sent by the client.
	SPILinkCommand struct {
		Command string
		Data    []byte // base64-encoded by json.Marshal
		Repeat  int
		Timeout int // microseconds
	}

	// SPILinkResult represents a result returned to the client.
	SPILinkResult struct {
		Data  []byte // base64-encoded by json.Marshal
		RSSI  int
		Error bool
	}
)

var (
	input  = json.NewDecoder(os.Stdin)
	output = json.NewEncoder(os.Stdout)

	radio = medtronic.Open().Radio
)

func main() {
	if radio.Error() != nil {
		log.Fatal(radio.Error())
	}
	for {
		cmd := readCommand()
		result := cmd.perform()
		err := output.Encode(result)
		radio.SetError(err)
		if radio.Error() != nil {
			log.Print(radio.Error())
			radio.SetError(nil)
		}
	}
}

func readCommand() SPILinkCommand {
	cmd := SPILinkCommand{}
	err := input.Decode(&cmd)
	if err == io.EOF {
		if verbose {
			log.Printf("EOF: exiting")
		}
		os.Exit(0)
	}
	if err != nil {
		log.Print(err)
	}
	return cmd
}

func (cmd SPILinkCommand) perform() SPILinkResult {
	if verbose {
		log.Printf("received %s command", cmd.Command)
	}
	timeout := time.Duration(cmd.Timeout) * time.Microsecond
	result := SPILinkResult{}
	switch cmd.Command {
	case "send_packet":
		result = send(cmd.Data, cmd.Repeat)
	case "get_packet":
		result = receive(timeout)
	case "send_and_listen":
		send(cmd.Data, cmd.Repeat)
		result = receive(timeout)
	default:
		log.Printf("unknown spilink command: %+v", cmd)
		result.Error = true
	}
	if verbose {
		log.Printf("returning %d-byte result", len(result.Data))
	}
	return result
}

func send(data []byte, repeat int) SPILinkResult {
	p := packet.Encode(data)
	if repeat == 0 {
		repeat = 1
	}
	if verbose {
		if repeat == 1 {
			log.Printf("sending %d-byte packet", len(p))
		} else {
			log.Printf("sending %d-byte packet %d times", len(p), repeat)
		}
	}
	for i := 0; i < repeat; i++ {
		radio.Send(p)
	}
	return SPILinkResult{}
}

func receive(timeout time.Duration) SPILinkResult {
	if verbose {
		log.Printf("receiving with timeout = %v", timeout)
	}
	result := SPILinkResult{}
	p, rssi := radio.Receive(timeout)
	data, err := packet.Decode6b4b(p)
	radio.SetError(err)
	result.Data = data
	if radio.Error() != nil {
		log.Print(radio.Error())
		radio.SetError(nil)
		result.Error = true
		return result
	}
	if verbose {
		log.Printf("received %d-byte packet (RSSI = %d)", len(p), rssi)
	}
	return result
}
<|endoftext|>


<commit_before>package main

import (
	"testing"
	"time"
)

func TestShouldFinishScraping(t *testing.T) {
	t.Parallel()

	makeChans := func() (chan time.Time, chan struct{}) {
		l := make(chan time.Time, 1)
		d := make(chan struct{}, 1)
		return l, d
	}

	tests := []struct {
		name   string
		fn     func() (chan time.Time, chan struct{})
		result bool
	}{
		{"LimiterBasic", func() (chan time.Time, chan struct{}) {
			l, d := makeChans()
			l <- time.Now()
			return l, d
		}, false},
		{"CloseBasic", func() (chan time.Time, chan struct{}) {
			l, d := makeChans()
			close(d)
			return l, d
		}, true},
		{"BothBasic", func() (chan time.Time, chan struct{}) {
			l, d := makeChans()
			l <- time.Now()
			close(d)
			return l, d
		}, true},
		{"CloseBeforeLimiter", func() (chan time.Time, chan struct{}) {
			l, d := makeChans()
			go func() {
				close(d)
				time.Sleep(time.Second)
				l <- time.Now()
			}()
			return l, d
		}, true},
		{"LimiterBeforeClose", func() (chan time.Time, chan struct{}) {
			l, d := makeChans()
			go func() {
				l <- time.Now()
				time.Sleep(time.Second)
				close(d)
			}()
			return l, d
		}, false},
		{"DelayedCloseBeforeLimiter", func() (chan time.Time, chan struct{}) {
			l, d := makeChans()
			go func() {
				time.Sleep(time.Second)
				close(d)
				time.Sleep(time.Second)
				l <- time.Now()
			}()
			return l, d
		}, true},
		{"DelayedLimiterBeforeClose", func() (chan time.Time, chan struct{}) {
			l, d := makeChans()
			go func() {
				time.Sleep(time.Second)
				l <- time.Now()
				time.Sleep(time.Second)
				close(d)
			}()
			return l, d
		}, false},
	}

	for i, test := range tests {
		l, d := test.fn()
		result := shouldFinishScraping(l, d)
		if result != test.result {
			t.Errorf("#%d: shouldFinishScraping(%s)=%t; want %t",
				i, test.name, result, test.result)
		}
	}
}

func TestParsePhotoPost(t *testing.T) {
	t.Parallel()
	t.Skip("Test not implemented")
}

func TestParseAnswerPost(t *testing.T) {
	t.Parallel()
	t.Skip("Test not implemented")
}

func TestParseRegularPost(t *testing.T) {
	t.Parallel()
	t.Skip("Test not implemented")
}

func TestParseVideoPost(t *testing.T) {
	t.Parallel()
	t.Skip("Test not implemented")
}

func TestParseAudioPost(t *testing.T) {
	t.Parallel()
	t.Skip("Feature not implemented")
}

// TestParseData tests parseDataForFiles. Aside from the other "Parse"
// tests above, it also checks if there is an invalid post type.
func TestParseData(t *testing.T) {
	t.Parallel()
	t.Skip("Test not implemented")
}

func TestMakeTumblrURL(t *testing.T) {
	t.Parallel()
	tests := []struct {
		u      *User
		page   int
		result string
	}{
		{
			&User{name: "InitialUser"},
			1, "http://InitialUser.tumblr.com/api/read/json?num=50&start=0",
		}, {
			&User{name: "OtherPageUser"},
			2, "http://OtherPageUser.tumblr.com/api/read/json?num=50&start=50",
		}, {
			&User{name: "TaggedInitialUser", tag: "test"},
			1, "http://TaggedInitialUser.tumblr.com/api/read/json?num=50&start=0&tagged=test",
		}, {
			&User{name: "TaggedOtherPageUser", tag: "test"},
			2, "http://TaggedOtherPageUser.tumblr.com/api/read/json?num=50&start=50&tagged=test",
		},
	}

	for i, test := range tests {
		result := makeTumblrURL(test.u, test.page).String()

		if result != test.result {
			t.Errorf("#%d: makeTumblrURL(%s)=%s; want %s",
				i, test.u.name, result, test.result)
		}
	}
}
<commit_msg>Update test cases to use the https scheme<commit_after>package main

import (
	"testing"
	"time"
)

func TestShouldFinishScraping(t *testing.T) {
	t.Parallel()

	makeChans := func() (chan time.Time, chan struct{}) {
		l := make(chan time.Time, 1)
		d := make(chan struct{}, 1)
		return l, d
	}

	tests := []struct {
		name   string
		fn     func() (chan time.Time, chan struct{})
		result bool
	}{
		{"LimiterBasic", func() (chan time.Time, chan struct{}) {
			l, d := makeChans()
			l <- time.Now()
			return l, d
		}, false},
		{"CloseBasic", func() (chan time.Time, chan struct{}) {
			l, d := makeChans()
			close(d)
			return l, d
		}, true},
		{"BothBasic", func() (chan time.Time, chan struct{}) {
			l, d := makeChans()
			l <- time.Now()
			close(d)
			return l, d
		}, true},
		{"CloseBeforeLimiter", func() (chan time.Time, chan struct{}) {
			l, d := makeChans()
			go func() {
				close(d)
				time.Sleep(time.Second)
				l <- time.Now()
			}()
			return l, d
		}, true},
		{"LimiterBeforeClose", func() (chan time.Time, chan struct{}) {
			l, d := makeChans()
			go func() {
				l <- time.Now()
				time.Sleep(time.Second)
				close(d)
			}()
			return l, d
		}, false},
		{"DelayedCloseBeforeLimiter", func() (chan time.Time, chan struct{}) {
			l, d := makeChans()
			go func() {
				time.Sleep(time.Second)
				close(d)
				time.Sleep(time.Second)
				l <- time.Now()
			}()
			return l, d
		}, true},
		{"DelayedLimiterBeforeClose", func() (chan time.Time, chan struct{}) {
			l, d := makeChans()
			go func() {
				time.Sleep(time.Second)
				l <- time.Now()
				time.Sleep(time.Second)
				close(d)
			}()
			return l, d
		}, false},
	}

	for i, test := range tests {
		l, d := test.fn()
		result := shouldFinishScraping(l, d)
		if result != test.result {
			t.Errorf("#%d: shouldFinishScraping(%s)=%t; want %t",
				i, test.name, result, test.result)
		}
	}
}

func TestParsePhotoPost(t *testing.T) {
	t.Parallel()
	t.Skip("Test not implemented")
}

func TestParseAnswerPost(t *testing.T) {
	t.Parallel()
	t.Skip("Test not implemented")
}

func TestParseRegularPost(t *testing.T) {
	t.Parallel()
	t.Skip("Test not implemented")
}

func TestParseVideoPost(t *testing.T) {
	t.Parallel()
	t.Skip("Test not implemented")
}

func TestParseAudioPost(t *testing.T) {
	t.Parallel()
	t.Skip("Feature not implemented")
}

// TestParseData tests parseDataForFiles. Aside from the other "Parse"
// tests above, it also checks if there is an invalid post type.
func TestParseData(t *testing.T) {
	t.Parallel()
	t.Skip("Test not implemented")
}

func TestMakeTumblrURL(t *testing.T) {
	t.Parallel()
	tests := []struct {
		u      *User
		page   int
		result string
	}{
		{
			&User{name: "InitialUser"},
			1, "https://InitialUser.tumblr.com/api/read/json?num=50&start=0",
		}, {
			&User{name: "OtherPageUser"},
			2, "https://OtherPageUser.tumblr.com/api/read/json?num=50&start=50",
		}, {
			&User{name: "TaggedInitialUser", tag: "test"},
			1, "https://TaggedInitialUser.tumblr.com/api/read/json?num=50&start=0&tagged=test",
		}, {
			&User{name: "TaggedOtherPageUser", tag: "test"},
			2, "https://TaggedOtherPageUser.tumblr.com/api/read/json?num=50&start=50&tagged=test",
		},
	}

	for i, test := range tests {
		result := makeTumblrURL(test.u, test.page).String()

		if result != test.result {
			t.Errorf("#%d: makeTumblrURL(%s)=%s; want %s",
				i, test.u.name, result, test.result)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"flag"
	"log"
	"os"

	_ "code.google.com/p/gosqlite/sqlite3"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/lib/pq"
	"github.com/modcloth-labs/schema_ensurer"
)

var (
	migrations = map[string][]string{
		"20131108000000": {`
	  CREATE TABLE IF NOT EXISTS messages(
		id serial PRIMARY KEY,

    content_type character varying(256),
    content_encoding character varying(256),
    delivery_mode smallint,
    priority smallint,
    correlation_id character varying(256),
    reply_to character varying(256),
    expiration character varying(256),
    timestamp timestamp with time zone,
    type character varying(256),
    user_id character varying(256),

		body text,

		created_at timestamp without time zone NOT NULL
	  );
	  `,
		},
	}
	logger             = log.New(os.Stderr, "[prism] ", log.LstdFlags)
	databaseDriverFlag string
	databaseUriFlag    string
)

func init() {
	flag.StringVar(&databaseDriverFlag, "database-driver", "sqlite3", "Database driver to use (possible values: sqlite3, mysql, postgres)")
	flag.StringVar(&databaseUriFlag, "database-uri", "messages.db", "Database uri")
  flag.Parse()
}

func main() {
	var (
		db            *sql.DB
		schemaEnsurer *sensurer.SchemaEnsurer
		err           error
	)

	if db, err = sql.Open(databaseDriverFlag, databaseUriFlag); err != nil {
		log.Printf("Could not connect to database: %s", err)
		os.Exit(1)
	}

	schemaEnsurer = sensurer.New(db, migrations, logger)
	if err = schemaEnsurer.EnsureSchema(); err != nil {
		log.Printf("Could not create schema: %s", err)
		os.Exit(1)
	}
}
<commit_msg>Expanding usage documentation<commit_after>package main

import (
	"database/sql"
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"

	_ "code.google.com/p/gosqlite/sqlite3"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/lib/pq"
	"github.com/modcloth-labs/schema_ensurer"
)

var (
	migrations = map[string][]string{
		"20131108000000": {`
	  CREATE TABLE IF NOT EXISTS messages(
		id serial PRIMARY KEY,

    content_type character varying(256),
    content_encoding character varying(256),
    delivery_mode smallint,
    priority smallint,
    correlation_id character varying(256),
    reply_to character varying(256),
    expiration character varying(256),
    timestamp timestamp with time zone,
    type character varying(256),
    user_id character varying(256),

		body text,

		created_at timestamp without time zone NOT NULL
	  );
	  `,
		},
	}
	logger             = log.New(os.Stderr, "[prism] ", log.LstdFlags)
	databaseDriverFlag string
	databaseUriFlag    string
)

func init() {
	usageString := `Usage: %s [options]
	Consumes messages from RabbitMQ and writes to database.
`
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, usageString, filepath.Base(os.Args[0]))
		flag.PrintDefaults()
	}
	flag.StringVar(&databaseDriverFlag, "database-driver", "sqlite3", "Database driver to use (possible values: sqlite3, mysql, postgres)")
	flag.StringVar(&databaseUriFlag, "database-uri", "messages.db", "Database uri")
  flag.Parse()
}

func main() {
	var (
		db            *sql.DB
		schemaEnsurer *sensurer.SchemaEnsurer
		err           error
	)

	if db, err = sql.Open(databaseDriverFlag, databaseUriFlag); err != nil {
		log.Printf("Could not connect to database: %s", err)
		os.Exit(1)
	}

	schemaEnsurer = sensurer.New(db, migrations, logger)
	if err = schemaEnsurer.EnsureSchema(); err != nil {
		log.Printf("Could not create schema: %s", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package bootstrap

import (
	"github.com/m3db/m3db/storage/bootstrap/result"
	"github.com/m3db/m3db/ts"
	xtime "github.com/m3db/m3x/time"
)

// Process represents the bootstrap process. Note that a bootstrap process can and will
// be resused so it is important to not rely on state stored in the bootstrap itself
// with the mindset that it will always be set to default values from the constructor.
type Process interface {
	// SetBootstrapper sets the bootstrapper to use when running the process.
	SetBootstrapper(bootstrapper Bootstrapper)

	// Bootstrapper returns the current bootstrapper to use when running the process.
	Bootstrapper() Bootstrapper

	// Run runs the bootstrap process, returning the bootstrap result and any error encountered.
	Run(
		namespace ts.ID,
		shards []uint32,
		targetRanges []TargetRange,
	) (result.BootstrapResult, error)
}

// TargetRange is a bootstrap target range.
type TargetRange struct {
	// Range is the time range to bootstrap for.
	Range xtime.Range

	// RunOptions is the bootstrap run options specific to the target range.
	RunOptions RunOptions
}

// RunOptions is a set of options for a bootstrap run.
type RunOptions interface {
	// SetIncremental sets whether this bootstrap should be an incremental
	// that saves intermediate results to durable storage or not.
	SetIncremental(value bool) RunOptions

	// Incremental returns whether this bootstrap should be an incremental
	// that saves intermediate results to durable storage or not.
	Incremental() bool
}

// Strategy describes a bootstrap strategy.
type Strategy int

const (
	// BootstrapSequential describes whether a bootstrap can use the sequential bootstrap strategy.
	BootstrapSequential Strategy = iota
	// BootstrapParallel describes whether a bootstrap can use the parallel bootstrap strategy.
	BootstrapParallel
)

// Bootstrapper is the interface for different bootstrapping mechanisms.  Note that a bootstrapper
// can and will be resused so it is important to not rely on state stored in the bootstrapper itself
// with the mindset that it will always be set to default values from the constructor.
type Bootstrapper interface {
	// String returns the name of the bootstrapper
	String() string

	// Can returns whether a specific bootstrapper strategy can be applied.
	Can(strategy Strategy) bool

	// Bootstrap performs bootstrapping for the given time ranges, returning the bootstrapped
	// series data and the time ranges it's unable to fulfill in parallel. A bootstrapper
	// should only return an error should it want to entirely cancel the bootstrapping of the
	// node, i.e. non-recoverable situation like not being able to read from the filesystem.
	Bootstrap(
		namespace ts.ID,
		shardsTimeRanges result.ShardTimeRanges,
		opts RunOptions,
	) (result.BootstrapResult, error)
}

// Source represents a bootstrap source. Note that a source can and will be resused so
// it is important to not rely on state stored in the source itself with the mindset
// that it will always be set to default values from the constructor.
type Source interface {
	// Can returns whether a specific bootstrapper strategy can be applied.
	Can(strategy Strategy) bool

	// Available returns what time ranges are available for a given set of shards.
	Available(
		namespace ts.ID,
		shardsTimeRanges result.ShardTimeRanges,
	) result.ShardTimeRanges

	// Read returns raw series for a given set of shards & specified time ranges and
	// the time ranges it's unable to fulfill. A bootstrapper source should only return
	// an error should it want to entirely cancel the bootstrapping of the node,
	// i.e. non-recoverable situation like not being able to read from the filesystem.
	Read(
		namespace ts.ID,
		shardsTimeRanges result.ShardTimeRanges,
		opts RunOptions,
	) (result.BootstrapResult, error)
}
<commit_msg>Fix typos in bootstrap types comments<commit_after>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package bootstrap

import (
	"github.com/m3db/m3db/storage/bootstrap/result"
	"github.com/m3db/m3db/ts"
	xtime "github.com/m3db/m3x/time"
)

// Process represents the bootstrap process. Note that a bootstrap process can and will
// be reused so it is important to not rely on state stored in the bootstrap itself
// with the mindset that it will always be set to default values from the constructor.
type Process interface {
	// SetBootstrapper sets the bootstrapper to use when running the process.
	SetBootstrapper(bootstrapper Bootstrapper)

	// Bootstrapper returns the current bootstrapper to use when running the process.
	Bootstrapper() Bootstrapper

	// Run runs the bootstrap process, returning the bootstrap result and any error encountered.
	Run(
		namespace ts.ID,
		shards []uint32,
		targetRanges []TargetRange,
	) (result.BootstrapResult, error)
}

// TargetRange is a bootstrap target range.
type TargetRange struct {
	// Range is the time range to bootstrap for.
	Range xtime.Range

	// RunOptions is the bootstrap run options specific to the target range.
	RunOptions RunOptions
}

// RunOptions is a set of options for a bootstrap run.
type RunOptions interface {
	// SetIncremental sets whether this bootstrap should be an incremental
	// that saves intermediate results to durable storage or not.
	SetIncremental(value bool) RunOptions

	// Incremental returns whether this bootstrap should be an incremental
	// that saves intermediate results to durable storage or not.
	Incremental() bool
}

// Strategy describes a bootstrap strategy.
type Strategy int

const (
	// BootstrapSequential describes whether a bootstrap can use the sequential bootstrap strategy.
	BootstrapSequential Strategy = iota
	// BootstrapParallel describes whether a bootstrap can use the parallel bootstrap strategy.
	BootstrapParallel
)

// Bootstrapper is the interface for different bootstrapping mechanisms.  Note that a bootstrapper
// can and will be reused so it is important to not rely on state stored in the bootstrapper itself
// with the mindset that it will always be set to default values from the constructor.
type Bootstrapper interface {
	// String returns the name of the bootstrapper
	String() string

	// Can returns whether a specific bootstrapper strategy can be applied.
	Can(strategy Strategy) bool

	// Bootstrap performs bootstrapping for the given time ranges, returning the bootstrapped
	// series data and the time ranges it's unable to fulfill in parallel. A bootstrapper
	// should only return an error should it want to entirely cancel the bootstrapping of the
	// node, i.e. non-recoverable situation like not being able to read from the filesystem.
	Bootstrap(
		namespace ts.ID,
		shardsTimeRanges result.ShardTimeRanges,
		opts RunOptions,
	) (result.BootstrapResult, error)
}

// Source represents a bootstrap source. Note that a source can and will be reused so
// it is important to not rely on state stored in the source itself with the mindset
// that it will always be set to default values from the constructor.
type Source interface {
	// Can returns whether a specific bootstrapper strategy can be applied.
	Can(strategy Strategy) bool

	// Available returns what time ranges are available for a given set of shards.
	Available(
		namespace ts.ID,
		shardsTimeRanges result.ShardTimeRanges,
	) result.ShardTimeRanges

	// Read returns raw series for a given set of shards & specified time ranges and
	// the time ranges it's unable to fulfill. A bootstrapper source should only return
	// an error should it want to entirely cancel the bootstrapping of the node,
	// i.e. non-recoverable situation like not being able to read from the filesystem.
	Read(
		namespace ts.ID,
		shardsTimeRanges result.ShardTimeRanges,
		opts RunOptions,
	) (result.BootstrapResult, error)
}
<|endoftext|>


<commit_before>package jsonpointer

import (
	"reflect"
	"testing"
)

var ptests = []struct {
	path string
	exp  interface{}
}{
	{"/foo", []interface{}{"bar", "baz"}},
	{"/foo/0", "bar"},
	{"/", 0.0},
	{"/a~1b", 1.0},
	{"/c%d", 2.0},
	{"/e^f", 3.0},
	{"/g|h", 4.0},
	{"/i\\j", 5.0},
	{"/k\"l", 6.0},
	{"/ ", 7.0},
	{"/m~0n", 8.0},
	{"/g~1n~1r", "has slash, will travel"},
	{"/g/n/r", "where's tito?"},
}

func TestPointerRoot(t *testing.T) {
	got, err := Find([]byte(objSrc), "")
	if err != nil {
		t.Fatalf("Error finding root: %v", err)
	}
	if !reflect.DeepEqual([]byte(objSrc), got) {
		t.Fatalf("Error finding root, found\n%s\n, wanted\n%s",
			got, objSrc)
	}
}

func TestManyPointers(t *testing.T) {
	pointers := []string{}
	exp := map[string]interface{}{}
	for _, test := range ptests {
		pointers = append(pointers, test.path)
		exp[test.path] = test.exp
	}

	rv, err := FindMany([]byte(objSrc), pointers)
	if err != nil {
		t.Fatalf("Error finding many: %v", err)
	}

	got := map[string]interface{}{}
	for k, v := range rv {
		var val interface{}
		err = Unmarshal(v, &val)
		if err != nil {
			t.Fatalf("Error unmarshaling %s: %v", v, err)
		}
		got[k] = val
	}

	if !reflect.DeepEqual(got, exp) {
		for k, v := range exp {
			if !reflect.DeepEqual(got[k], v) {
				t.Errorf("At %v, expected %#v, got %#v", k, v, got[k])
			}
		}
		t.Fail()
	}
}

func TestPointer(t *testing.T) {

	for _, test := range ptests {
		got, err := Find([]byte(objSrc), test.path)
		var val interface{}
		if err == nil {
			err = Unmarshal([]byte(got), &val)
		}
		if err != nil {
			t.Errorf("Got an error on key %v: %v", test.path, err)
			t.Fail()
		} else if !reflect.DeepEqual(val, test.exp) {
			t.Errorf("On %#v, expected %+v (%T), got %+v (%T)",
				test.path, test.exp, test.exp, val, val)
			t.Fail()
		} else {
			t.Logf("Success - got %s for %#v", got, test.path)
		}
	}
}

func TestPointerCoder(t *testing.T) {
	tests := map[string][]string{
		"/":        []string{""},
		"/a":       []string{"a"},
		"/a~1b":    []string{"a/b"},
		"/m~0n":    []string{"m~n"},
		"/ ":       []string{" "},
		"/g~1n~1r": []string{"g/n/r"},
		"/g/n/r":   []string{"g", "n", "r"},
	}

	for k, v := range tests {
		parsed := parsePointer(k)
		encoded := encodePointer(v)

		if k != encoded {
			t.Errorf("Expected to encode %#v as %#v, got %#v",
				v, k, encoded)
			t.Fail()
		}
		if !arreq(v, parsed) {
			t.Errorf("Expected to decode %#v as %#v, got %#v",
				k, v, parsed)
			t.Fail()
		}
	}
}

func BenchmarkPointer(b *testing.B) {
	obj := []byte(objSrc)
	for i := 0; i < b.N; i++ {
		for _, test := range tests {
			Find(obj, test.path)
		}
	}
}

func BenchmarkManyPointer(b *testing.B) {
	pointers := []string{}
	for _, test := range ptests {
		pointers = append(pointers, test.path)
	}
	obj := []byte(objSrc)

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		FindMany(obj, pointers)
	}
}
<commit_msg>Some benchmarks with the ~2MB testdata.<commit_after>package jsonpointer

import (
	"reflect"
	"testing"
)

var ptests = []struct {
	path string
	exp  interface{}
}{
	{"/foo", []interface{}{"bar", "baz"}},
	{"/foo/0", "bar"},
	{"/", 0.0},
	{"/a~1b", 1.0},
	{"/c%d", 2.0},
	{"/e^f", 3.0},
	{"/g|h", 4.0},
	{"/i\\j", 5.0},
	{"/k\"l", 6.0},
	{"/ ", 7.0},
	{"/m~0n", 8.0},
	{"/g~1n~1r", "has slash, will travel"},
	{"/g/n/r", "where's tito?"},
}

func TestPointerRoot(t *testing.T) {
	got, err := Find([]byte(objSrc), "")
	if err != nil {
		t.Fatalf("Error finding root: %v", err)
	}
	if !reflect.DeepEqual([]byte(objSrc), got) {
		t.Fatalf("Error finding root, found\n%s\n, wanted\n%s",
			got, objSrc)
	}
}

func TestManyPointers(t *testing.T) {
	pointers := []string{}
	exp := map[string]interface{}{}
	for _, test := range ptests {
		pointers = append(pointers, test.path)
		exp[test.path] = test.exp
	}

	rv, err := FindMany([]byte(objSrc), pointers)
	if err != nil {
		t.Fatalf("Error finding many: %v", err)
	}

	got := map[string]interface{}{}
	for k, v := range rv {
		var val interface{}
		err = Unmarshal(v, &val)
		if err != nil {
			t.Fatalf("Error unmarshaling %s: %v", v, err)
		}
		got[k] = val
	}

	if !reflect.DeepEqual(got, exp) {
		for k, v := range exp {
			if !reflect.DeepEqual(got[k], v) {
				t.Errorf("At %v, expected %#v, got %#v", k, v, got[k])
			}
		}
		t.Fail()
	}
}

func TestPointer(t *testing.T) {

	for _, test := range ptests {
		got, err := Find([]byte(objSrc), test.path)
		var val interface{}
		if err == nil {
			err = Unmarshal([]byte(got), &val)
		}
		if err != nil {
			t.Errorf("Got an error on key %v: %v", test.path, err)
			t.Fail()
		} else if !reflect.DeepEqual(val, test.exp) {
			t.Errorf("On %#v, expected %+v (%T), got %+v (%T)",
				test.path, test.exp, test.exp, val, val)
			t.Fail()
		} else {
			t.Logf("Success - got %s for %#v", got, test.path)
		}
	}
}

func TestPointerCoder(t *testing.T) {
	tests := map[string][]string{
		"/":        []string{""},
		"/a":       []string{"a"},
		"/a~1b":    []string{"a/b"},
		"/m~0n":    []string{"m~n"},
		"/ ":       []string{" "},
		"/g~1n~1r": []string{"g/n/r"},
		"/g/n/r":   []string{"g", "n", "r"},
	}

	for k, v := range tests {
		parsed := parsePointer(k)
		encoded := encodePointer(v)

		if k != encoded {
			t.Errorf("Expected to encode %#v as %#v, got %#v",
				v, k, encoded)
			t.Fail()
		}
		if !arreq(v, parsed) {
			t.Errorf("Expected to decode %#v as %#v, got %#v",
				k, v, parsed)
			t.Fail()
		}
	}
}

func BenchmarkPointer(b *testing.B) {
	obj := []byte(objSrc)
	for i := 0; i < b.N; i++ {
		for _, test := range tests {
			Find(obj, test.path)
		}
	}
}

func BenchmarkManyPointer(b *testing.B) {
	pointers := []string{}
	for _, test := range ptests {
		pointers = append(pointers, test.path)
	}
	obj := []byte(objSrc)

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		FindMany(obj, pointers)
	}
}

func BenchmarkPointerLarge(b *testing.B) {
	keys := []string{
		"/tree/kids/0/kids/0/name",
		"/tree/kids/0/name",
		"/tree/kids/0/kids/0/kids/0/kids/0/kids/0/name",
	}
	if codeJSON == nil {
		b.StopTimer()
		codeInit()
		b.StartTimer()
	}
	b.SetBytes(int64(len(codeJSON)))

	for i := 0; i < b.N; i++ {
		found, err := FindMany(codeJSON, keys)
		if err != nil || len(found) != 3 {
			b.Fatalf("Didn't find all the things from %v/%v",
				found, err)
		}
	}
}

func BenchmarkPointerLargeShallow(b *testing.B) {
	keys := []string{
		"/tree/kids/0/kids/0/kids/0/kids/0/kids/0/name",
	}
	if codeJSON == nil {
		b.StopTimer()
		codeInit()
		b.StartTimer()
	}
	b.SetBytes(int64(len(codeJSON)))

	for i := 0; i < b.N; i++ {
		found, err := FindMany(codeJSON, keys)
		if err != nil || len(found) != 1 {
			b.Fatalf("Didn't find all the things: %v/%v",
				found, err)
		}
	}
}

func BenchmarkPointerSlow(b *testing.B) {
	keys := []string{
		"/tree/kids/0/kids/0/kids/0/kids/0/kids/0/name",
	}
	if codeJSON == nil {
		b.StopTimer()
		codeInit()
		b.StartTimer()
	}
	b.SetBytes(int64(len(codeJSON)))

	for i := 0; i < b.N; i++ {
		m := map[string]interface{}{}
		err := Unmarshal(codeJSON, &m)
		if err != nil {
			b.Fatalf("Error parsing JSON: %v", err)
		}
		Get(m, keys[0])
	}
}
<|endoftext|>


<commit_before>// Copyright 2010 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.

// This file contains the printf-checker.

package main

import (
	"flag"
	"fmt"
	"go/ast"
	"go/token"
	"strings"
	"unicode/utf8"
)

var printfuncs = flag.String("printfuncs", "", "comma-separated list of print function names to check")

// printfList records the formatted-print functions. The value is the location
// of the format parameter. Names are lower-cased so the lookup is
// case insensitive.
var printfList = map[string]int{
	"errorf":  0,
	"fatalf":  0,
	"fprintf": 1,
	"panicf":  0,
	"printf":  0,
	"sprintf": 0,
}

// printList records the unformatted-print functions. The value is the location
// of the first parameter to be printed.  Names are lower-cased so the lookup is
// case insensitive.
var printList = map[string]int{
	"error":  0,
	"fatal":  0,
	"fprint": 1, "fprintln": 1,
	"panic": 0, "panicln": 0,
	"print": 0, "println": 0,
	"sprint": 0, "sprintln": 0,
}

// checkCall triggers the print-specific checks if the call invokes a print function.
func (f *File) checkFmtPrintfCall(call *ast.CallExpr, Name string) {
	name := strings.ToLower(Name)
	if skip, ok := printfList[name]; ok {
		f.checkPrintf(call, Name, skip)
		return
	}
	if skip, ok := printList[name]; ok {
		f.checkPrint(call, Name, skip)
		return
	}
}

// checkPrintf checks a call to a formatted print routine such as Printf.
// The skip argument records how many arguments to ignore; that is,
// call.Args[skip] is (well, should be) the format argument.
func (f *File) checkPrintf(call *ast.CallExpr, name string, skip int) {
	if len(call.Args) <= skip {
		return
	}
	// Common case: literal is first argument.
	arg := call.Args[skip]
	lit, ok := arg.(*ast.BasicLit)
	if !ok {
		// Too hard to check.
		if *verbose {
			f.Warn(call.Pos(), "can't check non-literal format in call to", name)
		}
		return
	}
	if lit.Kind == token.STRING {
		if !strings.Contains(lit.Value, "%") {
			if len(call.Args) > skip+1 {
				f.Badf(call.Pos(), "no formatting directive in %s call", name)
			}
			return
		}
	}
	// Hard part: check formats against args.
	// Trivial but useful test: count.
	numArgs := 0
	for i, w := 0, 0; i < len(lit.Value); i += w {
		w = 1
		if lit.Value[i] == '%' {
			nbytes, nargs := f.parsePrintfVerb(call, lit.Value[i:])
			w = nbytes
			numArgs += nargs
		}
	}
	expect := len(call.Args) - (skip + 1)
	if numArgs != expect {
		f.Badf(call.Pos(), "wrong number of args in %s call: %d needed but %d args", name, numArgs, expect)
	}
}

// parsePrintfVerb returns the number of bytes and number of arguments
// consumed by the Printf directive that begins s, including its percent sign
// and verb.
func (f *File) parsePrintfVerb(call *ast.CallExpr, s string) (nbytes, nargs int) {
	// There's guaranteed a percent sign.
	flags := make([]byte, 0, 5)
	nbytes = 1
	end := len(s)
	// There may be flags.
FlagLoop:
	for nbytes < end {
		switch s[nbytes] {
		case '#', '0', '+', '-', ' ':
			flags = append(flags, s[nbytes])
			nbytes++
		default:
			break FlagLoop
		}
	}
	getNum := func() {
		if nbytes < end && s[nbytes] == '*' {
			nbytes++
			nargs++
		} else {
			for nbytes < end && '0' <= s[nbytes] && s[nbytes] <= '9' {
				nbytes++
			}
		}
	}
	// There may be a width.
	getNum()
	// If there's a period, there may be a precision.
	if nbytes < end && s[nbytes] == '.' {
		flags = append(flags, '.') // Treat precision as a flag.
		nbytes++
		getNum()
	}
	// Now a verb.
	c, w := utf8.DecodeRuneInString(s[nbytes:])
	nbytes += w
	if c != '%' {
		nargs++
		f.checkPrintfVerb(call, c, flags)
	}
	return
}

type printVerb struct {
	verb  rune
	flags string // known flags are all ASCII
}

// Common flag sets for printf verbs.
const (
	numFlag      = " -+.0"
	sharpNumFlag = " -+.0#"
	allFlags     = " -+.0#"
)

// printVerbs identifies which flags are known to printf for each verb.
// TODO: A type that implements Formatter may do what it wants, and vet
// will complain incorrectly.
var printVerbs = []printVerb{
	// '-' is a width modifier, always valid.
	// '.' is a precision for float, max width for strings.
	// '+' is required sign for numbers, Go format for %v.
	// '#' is alternate format for several verbs.
	// ' ' is spacer for numbers
	{'b', numFlag},
	{'c', "-"},
	{'d', numFlag},
	{'e', "-."},
	{'E', numFlag},
	{'f', numFlag},
	{'F', numFlag},
	{'g', numFlag},
	{'G', numFlag},
	{'o', sharpNumFlag},
	{'p', "-#"},
	{'q', "-+#."},
	{'s', "-."},
	{'t', "-"},
	{'T', "-"},
	{'U', "-#"},
	{'v', allFlags},
	{'x', sharpNumFlag},
	{'X', sharpNumFlag},
}

const printfVerbs = "bcdeEfFgGopqstTvxUX"

func (f *File) checkPrintfVerb(call *ast.CallExpr, verb rune, flags []byte) {
	// Linear scan is fast enough for a small list.
	for _, v := range printVerbs {
		if v.verb == verb {
			for _, flag := range flags {
				if !strings.ContainsRune(v.flags, rune(flag)) {
					f.Badf(call.Pos(), "unrecognized printf flag for verb %q: %q", verb, flag)
				}
			}
			return
		}
	}
	f.Badf(call.Pos(), "unrecognized printf verb %q", verb)
}

// checkPrint checks a call to an unformatted print routine such as Println.
// The skip argument records how many arguments to ignore; that is,
// call.Args[skip] is the first argument to be printed.
func (f *File) checkPrint(call *ast.CallExpr, name string, skip int) {
	isLn := strings.HasSuffix(name, "ln")
	isF := strings.HasPrefix(name, "F")
	args := call.Args
	// check for Println(os.Stderr, ...)
	if skip == 0 && !isF && len(args) > 0 {
		if sel, ok := args[0].(*ast.SelectorExpr); ok {
			if x, ok := sel.X.(*ast.Ident); ok {
				if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") {
					f.Warnf(call.Pos(), "first argument to %s is %s.%s", name, x.Name, sel.Sel.Name)
				}
			}
		}
	}
	if len(args) <= skip {
		if *verbose && !isLn {
			f.Badf(call.Pos(), "no args in %s call", name)
		}
		return
	}
	arg := args[skip]
	if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
		if strings.Contains(lit.Value, "%") {
			f.Badf(call.Pos(), "possible formatting directive in %s call", name)
		}
	}
	if isLn {
		// The last item, if a string, should not have a newline.
		arg = args[len(call.Args)-1]
		if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
			if strings.HasSuffix(lit.Value, `\n"`) {
				f.Badf(call.Pos(), "%s call ends with newline", name)
			}
		}
	}
}

// This function never executes, but it serves as a simple test for the program.
// Test with make test.
func BadFunctionUsedInTests() {
	fmt.Println()                      // not an error
	fmt.Println("%s", "hi")            // ERROR "possible formatting directive in Println call"
	fmt.Printf("%s", "hi", 3)          // ERROR "wrong number of args in Printf call"
	fmt.Printf("%s%%%d", "hi", 3)      // correct
	fmt.Printf("%.*d", 3, 3)           // correct
	fmt.Printf("%.*d", 3, 3, 3)        // ERROR "wrong number of args in Printf call"
	printf("now is the time", "buddy") // ERROR "no formatting directive"
	Printf("now is the time", "buddy") // ERROR "no formatting directive"
	Printf("hi")                       // ok
	f := new(File)
	f.Warn(0, "%s", "hello", 3)  // ERROR "possible formatting directive in Warn call"
	f.Warnf(0, "%s", "hello", 3) // ERROR "wrong number of args in Warnf call"
	f.Warnf(0, "%r", "hello")    // ERROR "unrecognized printf verb"
	f.Warnf(0, "%#s", "hello")   // ERROR "unrecognized printf flag"
}

type BadTypeUsedInTests struct {
	X int "hello" // ERROR "struct field tag"
}

func (t *BadTypeUsedInTests) Scan(x fmt.ScanState, c byte) { // ERROR "method Scan[(]x fmt.ScanState, c byte[)] should have signature Scan[(]fmt.ScanState, rune[)] error"
}

type BadInterfaceUsedInTests interface {
	ReadByte() byte // ERROR "method ReadByte[(][)] byte should have signature ReadByte[(][)] [(]byte, error[)]"
}

// printf is used by the test.
func printf(format string, args ...interface{}) {
	panic("don't call - testing only")
}
<commit_msg>cmd/vet: don't give error for Printf("%+5.2e", x)<commit_after>// Copyright 2010 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.

// This file contains the printf-checker.

package main

import (
	"flag"
	"fmt"
	"go/ast"
	"go/token"
	"strings"
	"unicode/utf8"
)

var printfuncs = flag.String("printfuncs", "", "comma-separated list of print function names to check")

// printfList records the formatted-print functions. The value is the location
// of the format parameter. Names are lower-cased so the lookup is
// case insensitive.
var printfList = map[string]int{
	"errorf":  0,
	"fatalf":  0,
	"fprintf": 1,
	"panicf":  0,
	"printf":  0,
	"sprintf": 0,
}

// printList records the unformatted-print functions. The value is the location
// of the first parameter to be printed.  Names are lower-cased so the lookup is
// case insensitive.
var printList = map[string]int{
	"error":  0,
	"fatal":  0,
	"fprint": 1, "fprintln": 1,
	"panic": 0, "panicln": 0,
	"print": 0, "println": 0,
	"sprint": 0, "sprintln": 0,
}

// checkCall triggers the print-specific checks if the call invokes a print function.
func (f *File) checkFmtPrintfCall(call *ast.CallExpr, Name string) {
	name := strings.ToLower(Name)
	if skip, ok := printfList[name]; ok {
		f.checkPrintf(call, Name, skip)
		return
	}
	if skip, ok := printList[name]; ok {
		f.checkPrint(call, Name, skip)
		return
	}
}

// checkPrintf checks a call to a formatted print routine such as Printf.
// The skip argument records how many arguments to ignore; that is,
// call.Args[skip] is (well, should be) the format argument.
func (f *File) checkPrintf(call *ast.CallExpr, name string, skip int) {
	if len(call.Args) <= skip {
		return
	}
	// Common case: literal is first argument.
	arg := call.Args[skip]
	lit, ok := arg.(*ast.BasicLit)
	if !ok {
		// Too hard to check.
		if *verbose {
			f.Warn(call.Pos(), "can't check non-literal format in call to", name)
		}
		return
	}
	if lit.Kind == token.STRING {
		if !strings.Contains(lit.Value, "%") {
			if len(call.Args) > skip+1 {
				f.Badf(call.Pos(), "no formatting directive in %s call", name)
			}
			return
		}
	}
	// Hard part: check formats against args.
	// Trivial but useful test: count.
	numArgs := 0
	for i, w := 0, 0; i < len(lit.Value); i += w {
		w = 1
		if lit.Value[i] == '%' {
			nbytes, nargs := f.parsePrintfVerb(call, lit.Value[i:])
			w = nbytes
			numArgs += nargs
		}
	}
	expect := len(call.Args) - (skip + 1)
	if numArgs != expect {
		f.Badf(call.Pos(), "wrong number of args in %s call: %d needed but %d args", name, numArgs, expect)
	}
}

// parsePrintfVerb returns the number of bytes and number of arguments
// consumed by the Printf directive that begins s, including its percent sign
// and verb.
func (f *File) parsePrintfVerb(call *ast.CallExpr, s string) (nbytes, nargs int) {
	// There's guaranteed a percent sign.
	flags := make([]byte, 0, 5)
	nbytes = 1
	end := len(s)
	// There may be flags.
FlagLoop:
	for nbytes < end {
		switch s[nbytes] {
		case '#', '0', '+', '-', ' ':
			flags = append(flags, s[nbytes])
			nbytes++
		default:
			break FlagLoop
		}
	}
	getNum := func() {
		if nbytes < end && s[nbytes] == '*' {
			nbytes++
			nargs++
		} else {
			for nbytes < end && '0' <= s[nbytes] && s[nbytes] <= '9' {
				nbytes++
			}
		}
	}
	// There may be a width.
	getNum()
	// If there's a period, there may be a precision.
	if nbytes < end && s[nbytes] == '.' {
		flags = append(flags, '.') // Treat precision as a flag.
		nbytes++
		getNum()
	}
	// Now a verb.
	c, w := utf8.DecodeRuneInString(s[nbytes:])
	nbytes += w
	if c != '%' {
		nargs++
		f.checkPrintfVerb(call, c, flags)
	}
	return
}

type printVerb struct {
	verb  rune
	flags string // known flags are all ASCII
}

// Common flag sets for printf verbs.
const (
	numFlag      = " -+.0"
	sharpNumFlag = " -+.0#"
	allFlags     = " -+.0#"
)

// printVerbs identifies which flags are known to printf for each verb.
// TODO: A type that implements Formatter may do what it wants, and vet
// will complain incorrectly.
var printVerbs = []printVerb{
	// '-' is a width modifier, always valid.
	// '.' is a precision for float, max width for strings.
	// '+' is required sign for numbers, Go format for %v.
	// '#' is alternate format for several verbs.
	// ' ' is spacer for numbers
	{'b', numFlag},
	{'c', "-"},
	{'d', numFlag},
	{'e', numFlag},
	{'E', numFlag},
	{'f', numFlag},
	{'F', numFlag},
	{'g', numFlag},
	{'G', numFlag},
	{'o', sharpNumFlag},
	{'p', "-#"},
	{'q', "-+#."},
	{'s', "-."},
	{'t', "-"},
	{'T', "-"},
	{'U', "-#"},
	{'v', allFlags},
	{'x', sharpNumFlag},
	{'X', sharpNumFlag},
}

const printfVerbs = "bcdeEfFgGopqstTvxUX"

func (f *File) checkPrintfVerb(call *ast.CallExpr, verb rune, flags []byte) {
	// Linear scan is fast enough for a small list.
	for _, v := range printVerbs {
		if v.verb == verb {
			for _, flag := range flags {
				if !strings.ContainsRune(v.flags, rune(flag)) {
					f.Badf(call.Pos(), "unrecognized printf flag for verb %q: %q", verb, flag)
				}
			}
			return
		}
	}
	f.Badf(call.Pos(), "unrecognized printf verb %q", verb)
}

// checkPrint checks a call to an unformatted print routine such as Println.
// The skip argument records how many arguments to ignore; that is,
// call.Args[skip] is the first argument to be printed.
func (f *File) checkPrint(call *ast.CallExpr, name string, skip int) {
	isLn := strings.HasSuffix(name, "ln")
	isF := strings.HasPrefix(name, "F")
	args := call.Args
	// check for Println(os.Stderr, ...)
	if skip == 0 && !isF && len(args) > 0 {
		if sel, ok := args[0].(*ast.SelectorExpr); ok {
			if x, ok := sel.X.(*ast.Ident); ok {
				if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") {
					f.Warnf(call.Pos(), "first argument to %s is %s.%s", name, x.Name, sel.Sel.Name)
				}
			}
		}
	}
	if len(args) <= skip {
		if *verbose && !isLn {
			f.Badf(call.Pos(), "no args in %s call", name)
		}
		return
	}
	arg := args[skip]
	if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
		if strings.Contains(lit.Value, "%") {
			f.Badf(call.Pos(), "possible formatting directive in %s call", name)
		}
	}
	if isLn {
		// The last item, if a string, should not have a newline.
		arg = args[len(call.Args)-1]
		if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
			if strings.HasSuffix(lit.Value, `\n"`) {
				f.Badf(call.Pos(), "%s call ends with newline", name)
			}
		}
	}
}

// This function never executes, but it serves as a simple test for the program.
// Test with make test.
func BadFunctionUsedInTests() {
	fmt.Println()                      // not an error
	fmt.Println("%s", "hi")            // ERROR "possible formatting directive in Println call"
	fmt.Printf("%s", "hi", 3)          // ERROR "wrong number of args in Printf call"
	fmt.Printf("%s%%%d", "hi", 3)      // correct
	fmt.Printf("%.*d", 3, 3)           // correct
	fmt.Printf("%.*d", 3, 3, 3)        // ERROR "wrong number of args in Printf call"
	printf("now is the time", "buddy") // ERROR "no formatting directive"
	Printf("now is the time", "buddy") // ERROR "no formatting directive"
	Printf("hi")                       // ok
	f := new(File)
	f.Warn(0, "%s", "hello", 3)  // ERROR "possible formatting directive in Warn call"
	f.Warnf(0, "%s", "hello", 3) // ERROR "wrong number of args in Warnf call"
	f.Warnf(0, "%r", "hello")    // ERROR "unrecognized printf verb"
	f.Warnf(0, "%#s", "hello")   // ERROR "unrecognized printf flag"
}

type BadTypeUsedInTests struct {
	X int "hello" // ERROR "struct field tag"
}

func (t *BadTypeUsedInTests) Scan(x fmt.ScanState, c byte) { // ERROR "method Scan[(]x fmt.ScanState, c byte[)] should have signature Scan[(]fmt.ScanState, rune[)] error"
}

type BadInterfaceUsedInTests interface {
	ReadByte() byte // ERROR "method ReadByte[(][)] byte should have signature ReadByte[(][)] [(]byte, error[)]"
}

// printf is used by the test.
func printf(format string, args ...interface{}) {
	panic("don't call - testing only")
}
<|endoftext|>


<commit_before>// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

package robotgo

var mouseMap = Map{
	"left":       1,
	"right":      2,
	"center":     3,
	"wheelDown":  4,
	"wheelUp":    5,
	"wheelLeft":  6,
	"wheelRight": 7,
}

var keycode = Map{
	"`": 41,
	"1": 2,
	"2": 3,
	"3": 4,
	"4": 5,
	"5": 6,
	"6": 7,
	"7": 8,
	"8": 9,
	"9": 10,
	"0": 11,
	"-": 12,
	"+": 13,
	//
	"q":  16,
	"w":  17,
	"e":  18,
	"r":  19,
	"t":  20,
	"y":  21,
	"u":  22,
	"i":  23,
	"o":  24,
	"p":  25,
	"[":  26,
	"]":  27,
	"\\": 28,
	//
	"a": 30,
	"s": 31,
	"d": 32,
	"f": 33,
	"g": 34,
	"h": 35,
	"j": 36,
	"k": 37,
	"l": 38,
	";": 39,
	"'": 40,
	//
	"z": 44,
	"x": 45,
	"c": 46,
	"v": 47,
	"b": 48,
	"n": 49,
	"m": 50,
	",": 51,
	".": 52,
	"/": 53,
	//
	"f1":  59,
	"f2":  60,
	"f3":  61,
	"f4":  62,
	"f5":  63,
	"f6":  64,
	"f7":  65,
	"f8":  66,
	"f9":  67,
	"f10": 68,
	"f11": 69,
	"f12": 70,
	// more
	"esc":     1,
	"tab":     15,
	"ctrl":    29,
	"control": 29,
	"alt":     56,
	"space":   57,
	"shift":   42,
	"enter":   28,
	"cmd":     3675,
	"command": 3675,
}
<commit_msg>add keycode "delete" support and fixed "\\" error<commit_after>// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

package robotgo

var mouseMap = Map{
	"left":       1,
	"right":      2,
	"center":     3,
	"wheelDown":  4,
	"wheelUp":    5,
	"wheelLeft":  6,
	"wheelRight": 7,
}

var keycode = Map{
	"`": 41,
	"1": 2,
	"2": 3,
	"3": 4,
	"4": 5,
	"5": 6,
	"6": 7,
	"7": 8,
	"8": 9,
	"9": 10,
	"0": 11,
	"-": 12,
	"+": 13,
	//
	"q":  16,
	"w":  17,
	"e":  18,
	"r":  19,
	"t":  20,
	"y":  21,
	"u":  22,
	"i":  23,
	"o":  24,
	"p":  25,
	"[":  26,
	"]":  27,
	"\\": 43,
	//
	"a": 30,
	"s": 31,
	"d": 32,
	"f": 33,
	"g": 34,
	"h": 35,
	"j": 36,
	"k": 37,
	"l": 38,
	";": 39,
	"'": 40,
	//
	"z": 44,
	"x": 45,
	"c": 46,
	"v": 47,
	"b": 48,
	"n": 49,
	"m": 50,
	",": 51,
	".": 52,
	"/": 53,
	//
	"f1":  59,
	"f2":  60,
	"f3":  61,
	"f4":  62,
	"f5":  63,
	"f6":  64,
	"f7":  65,
	"f8":  66,
	"f9":  67,
	"f10": 68,
	"f11": 69,
	"f12": 70,
	// more
	"esc":     1,
	"delete":  14,
	"tab":     15,
	"ctrl":    29,
	"control": 29,
	"alt":     56,
	"space":   57,
	"shift":   42,
	"enter":   28,
	"cmd":     3675,
	"command": 3675,
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/tls"
	"flag"
	"fmt"
	"github.com/amahi/spdy"
	"io"
	"log"
	"net/http"
	"net/http/httputil"
	"time"
)

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

const HOST_PORT = "localhost:1444"

func main() {

	root := flag.String("r", "./testdata", "root of the directory to serve")
	spdy_debug := flag.Bool("s", false, "enable SPDY debug output")
	flag.Parse()

	if *spdy_debug {
		// enable spdy debug messages
		spdy.EnableDebug()
	}

	for {
		const SLEEP_RETRY = 5
		var conn *tls.Conn
		var err error
		for i := 0; i < 10; i++ {
			// connect to P.
			conn, err = tls.Dial("tcp", HOST_PORT, &tls.Config{InsecureSkipVerify: true})
			if err != nil {
				time.Sleep(100 * time.Millisecond)
			} else {
				break
			}
		}
		if conn == nil {
			log.Println("Failed to connect. Waiting", SLEEP_RETRY, "seconds.")
			time.Sleep(SLEEP_RETRY * time.Second)
			continue
		}

		// build the request
		buf := new(bytes.Buffer)
		_, err = buf.WriteString("Hello from C")
		handle(err)
		req, err := http.NewRequest("PUT", "https://"+HOST_PORT, buf)
		handle(err)

		// make the client connection
		client := httputil.NewClientConn(conn, nil)
		res, err := client.Do(req)
		if err != nil {
			log.Println("Error: Failed to make connection to P:", err)
			continue
		}
		buf.Reset()
		_, err = io.Copy(buf, res.Body)
		handle(err)
		fmt.Printf("%q from P: %q.\n", res.Status, buf.String())

		c, _ := client.Hijack()
		conn = c.(*tls.Conn)
		server := new(http.Server)
		server.Handler = http.FileServer(http.Dir(*root))
		session := spdy.NewServerSession(conn, server)
		session.Serve()
	}
}
<commit_msg>restore panic<commit_after>package main

import (
	"bytes"
	"crypto/tls"
	"flag"
	"fmt"
	"github.com/amahi/spdy"
	"io"
	"log"
	"net/http"
	"net/http/httputil"
	"time"
)

func handle(err error) {
	if err != nil {
		panic(err)
	}
}

const HOST_PORT = "localhost:1444"

func main() {

	root := flag.String("r", "./testdata", "root of the directory to serve")
	spdy_debug := flag.Bool("s", false, "enable SPDY debug output")
	flag.Parse()

	if *spdy_debug {
		// enable spdy debug messages
		spdy.EnableDebug()
	}

	for {
		const SLEEP_RETRY = 5
		var conn *tls.Conn
		var err error
		for i := 0; i < 10; i++ {
			// connect to P.
			conn, err = tls.Dial("tcp", HOST_PORT, &tls.Config{InsecureSkipVerify: true})
			if err != nil {
				time.Sleep(100 * time.Millisecond)
			} else {
				break
			}
		}
		if conn == nil {
			log.Println("Failed to connect. Waiting", SLEEP_RETRY, "seconds.")
			time.Sleep(SLEEP_RETRY * time.Second)
			continue
		}

		// build the request
		buf := new(bytes.Buffer)
		_, err = buf.WriteString("Hello from C")
		handle(err)
		req, err := http.NewRequest("PUT", "https://"+HOST_PORT, buf)
		handle(err)

		// make the client connection
		client := httputil.NewClientConn(conn, nil)
		res, err := client.Do(req)
		if err != nil {
			log.Println("Error: Failed to make connection to P:", err)
			continue
		}
		buf.Reset()
		_, err = io.Copy(buf, res.Body)
		handle(err)
		fmt.Printf("%q from P: %q.\n", res.Status, buf.String())

		c, _ := client.Hijack()
		conn = c.(*tls.Conn)
		server := new(http.Server)
		server.Handler = http.FileServer(http.Dir(*root))
		session := spdy.NewServerSession(conn, server)
		session.Serve()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/md5"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"os"
	"os/exec"
	"os/user"
	"strings"
	"time"

	"github.com/gtfierro/hod/config"
	hod "github.com/gtfierro/hod/db"
	"github.com/gtfierro/hod/goraptor"
	"github.com/gtfierro/hod/query"
	"github.com/gtfierro/hod/server"

	"github.com/chzyer/readline"
	"github.com/fatih/color"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
)

func benchLoad(c *cli.Context) error {
	if c.NArg() == 0 {
		return errors.New("Need to specify a turtle file to load")
	}
	filename := c.Args().Get(0)
	p := turtle.GetParser()
	ds, duration := p.Parse(filename)
	rate := float64((float64(ds.NumTriples()) / float64(duration.Nanoseconds())) * 1e9)
	fmt.Printf("Loaded %d triples, %d namespaces in %s (%.0f/sec)\n", ds.NumTriples(), ds.NumNamespaces(), duration, rate)
	return nil
}

func load(c *cli.Context) error {
	if c.NArg() == 0 {
		return errors.New("Need to specify a turtle file to load")
	}
	filename := c.Args().Get(0)
	cfg, err := config.ReadConfig(c.String("config"))
	if err != nil {
		return err
	}
	p := turtle.GetParser()
	ds, duration := p.Parse(filename)
	rate := float64((float64(ds.NumTriples()) / float64(duration.Nanoseconds())) * 1e9)
	log.Infof("Loaded %d triples, %d namespaces in %s (%.0f/sec)", ds.NumTriples(), ds.NumNamespaces(), duration, rate)

	cfg.ReloadBrick = true

	db, err := hod.NewDB(cfg)
	if err != nil {
		return err
	}
	err = db.LoadDataset(ds)
	if err != nil {
		return err
	}

	return nil
}

func loadLinks(c *cli.Context) error {
	if c.NArg() == 0 {
		return errors.New("Need to specify a JSON file to load")
	}
	filename := c.Args().Get(0)
	cfg, err := config.ReadConfig(c.String("config"))
	if err != nil {
		return err
	}
	cfg.ReloadBrick = false
	db, err := hod.NewDB(cfg)
	if err != nil {
		return err
	}
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	var updates = new(hod.LinkUpdates)
	decoder := json.NewDecoder(file)
	if err := decoder.Decode(updates); err != nil {
		return err
	}
	log.Noticef("Adding %d links, Removing %d links", len(updates.Adding), len(updates.Removing))
	return db.UpdateLinks(updates)
}

func startCLI(c *cli.Context) error {
	cfg, err := config.ReadConfig(c.String("config"))
	if err != nil {
		return err
	}
	cfg.ReloadBrick = false
	db, err := hod.NewDB(cfg)
	if err != nil {
		return err
	}
	return runInteractiveQuery(db)
}

func startHTTP(c *cli.Context) error {
	cfg, err := config.ReadConfig(c.String("config"))
	if err != nil {
		return err
	}
	cfg.ReloadBrick = false
	db, err := hod.NewDB(cfg)
	if err != nil {
		return err
	}
	server.StartHodServer(db, cfg)
	return nil
}

func dump(c *cli.Context) error {
	if c.NArg() == 0 {
		return errors.New("Need to specify a turtle file to load")
	}
	filename := c.Args().Get(0)
	p := turtle.GetParser()
	ds, _ := p.Parse(filename)
	for _, triple := range ds.Triples {
		var s = triple.Subject.Value
		var p = triple.Predicate.Value
		var o = triple.Object.Value
		for pfx, full := range ds.Namespaces {
			if triple.Subject.Namespace == full {
				s = pfx + ":" + s
			}
			if triple.Predicate.Namespace == full {
				p = pfx + ":" + p
			}
			if triple.Object.Namespace == full {
				o = pfx + ":" + o
			}
		}
		fmt.Printf("%s\t%s\t%s\n", s, p, o)
	}
	return nil
}

func classGraph(c *cli.Context) error {
	if c.NArg() == 0 {
		return errors.New("Need to specify a turtle file to load")
	}
	filename := c.Args().Get(0)
	p := turtle.GetParser()
	ds, _ := p.Parse(filename)

	name := gethash() + ".gv"
	f, err := os.Create(name)
	if err != nil {
		return err
	}

	nodes := make(map[string]struct{})
	edges := make(map[string]struct{})
	for _, triple := range ds.Triples {
		if triple.Predicate.String() == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" && triple.Object.String() == "http://www.w3.org/2002/07/owl#Class" {
			x := fmt.Sprintf("%s;\n", triple.Subject.Value)
			nodes[x] = struct{}{}
		} else if triple.Predicate.String() == "http://www.w3.org/2000/01/rdf-schema#subClassOf" {
			if strings.HasPrefix(triple.Object.Value, "genid") || strings.HasPrefix(triple.Subject.Value, "genid") {
				continue
			}
			x := fmt.Sprintf("%s -> %s [label=\"%s\"];\n", triple.Object.Value, triple.Subject.Value, "hasSubclass")
			edges[x] = struct{}{}
		}
	}

	fmt.Fprintln(f, "digraph G {")
	fmt.Fprintln(f, "ratio=\"auto\"")
	fmt.Fprintln(f, "rankdir=\"LR\"")
	fmt.Fprintln(f, "size=\"7.5,10\"")
	for node := range nodes {
		fmt.Fprintf(f, node)
	}
	for edge := range edges {
		fmt.Fprintf(f, edge)
	}
	fmt.Fprintln(f, "}")
	cmd := exec.Command("dot", "-Tpdf", name)
	pdf, err := cmd.Output()
	if err != nil {
		return err
	}
	f2, err := os.Create(filename + ".pdf")
	if err != nil {
		return err
	}
	_, err = f2.Write(pdf)
	if err != nil {
		return err
	}

	// remove DOT file
	os.Remove(name)
	return nil
}

func dumpGraph(c *cli.Context) error {
	if c.NArg() == 0 {
		return errors.New("Need to specify a turtle file to load")
	}
	filename := c.Args().Get(0)
	p := turtle.GetParser()
	ds, _ := p.Parse(filename)

	name := gethash() + ".gv"
	f, err := os.Create(name)
	if err != nil {
		return err
	}

	nodes := make(map[string]struct{})
	edges := make(map[string]struct{})
	for _, triple := range ds.Triples {
		x := fmt.Sprintf("%s;\n", triple.Subject.Value)
		nodes[x] = struct{}{}
		x = fmt.Sprintf("%s -> %s [label=\"%s\"];\n", triple.Subject.Value, triple.Object.Value, triple.Predicate.Value)
		edges[x] = struct{}{}
	}

	fmt.Fprintln(f, "digraph G {")
	fmt.Fprintln(f, "ratio=\"auto\"")
	fmt.Fprintln(f, "rankdir=\"LR\"")
	fmt.Fprintln(f, "size=\"7.5,10\"")
	for node := range nodes {
		fmt.Fprintf(f, node)
	}
	for edge := range edges {
		fmt.Fprintf(f, edge)
	}
	fmt.Fprintln(f, "}")
	cmd := exec.Command("sfdp", "-Tpdf", name)
	pdf, err := cmd.Output()
	if err != nil {
		// try graphviz dot then
		cmd = exec.Command("dot", "-Tpdf", name)
		pdf, err = cmd.Output()
		if err != nil {
			return err
		}
	}
	f2, err := os.Create(filename + ".pdf")
	if err != nil {
		return err
	}
	_, err = f2.Write(pdf)
	if err != nil {
		return err
	}

	// remove DOT file
	os.Remove(name)
	return nil
}

func gethash() string {
	h := md5.New()
	seed := make([]byte, 16)
	binary.PutVarint(seed, time.Now().UnixNano())
	h.Write(seed)
	return fmt.Sprintf("%x", h.Sum(nil))
}

func runInteractiveQuery(db *hod.DB) error {
	currentUser, err := user.Current()
	if err != nil {
		return err
	}
	fmt.Println("Successfully loaded dataset!")
	bufQuery := ""

	//setup color for prompt
	c := color.New(color.FgCyan)
	c.Add(color.Bold)
	cyan := c.SprintFunc()

	rl, err := readline.NewEx(&readline.Config{
		Prompt:                 cyan("(hod)> "),
		HistoryFile:            currentUser.HomeDir + "/.hod-query-history",
		DisableAutoSaveHistory: true,
	})
	for {
		line, err := rl.Readline()
		if err != nil {
			break
		}
		if len(line) == 0 {
			continue
		}
		bufQuery += line + " "
		if !strings.HasSuffix(strings.TrimSpace(line), ";") {
			rl.SetPrompt(">>> ...")
			continue
		}
		rl.SetPrompt(cyan("(hod)> "))
		rl.SaveHistory(bufQuery)
		q, err := query.Parse(strings.NewReader(bufQuery))
		if err != nil {
			log.Error(err)
		} else {
			res := db.RunQuery(q)
			res.Dump()
		}
		bufQuery = ""
	}
	return nil
}
<commit_msg>no panic message; fatal critical<commit_after>package main

import (
	"crypto/md5"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"os"
	"os/exec"
	"os/user"
	"strings"
	"time"

	"github.com/gtfierro/hod/config"
	hod "github.com/gtfierro/hod/db"
	"github.com/gtfierro/hod/goraptor"
	"github.com/gtfierro/hod/query"
	"github.com/gtfierro/hod/server"

	"github.com/chzyer/readline"
	"github.com/fatih/color"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
)

func benchLoad(c *cli.Context) error {
	if c.NArg() == 0 {
		log.Fatal("Need to specify a turtle file to load")
	}
	filename := c.Args().Get(0)
	p := turtle.GetParser()
	ds, duration := p.Parse(filename)
	rate := float64((float64(ds.NumTriples()) / float64(duration.Nanoseconds())) * 1e9)
	fmt.Printf("Loaded %d triples, %d namespaces in %s (%.0f/sec)\n", ds.NumTriples(), ds.NumNamespaces(), duration, rate)
	return nil
}

func load(c *cli.Context) error {
	if c.NArg() == 0 {
		log.Fatal("Need to specify a turtle file to load")
	}
	filename := c.Args().Get(0)
	cfg, err := config.ReadConfig(c.String("config"))
	if err != nil {
		return err
	}
	p := turtle.GetParser()
	ds, duration := p.Parse(filename)
	rate := float64((float64(ds.NumTriples()) / float64(duration.Nanoseconds())) * 1e9)
	log.Infof("Loaded %d triples, %d namespaces in %s (%.0f/sec)", ds.NumTriples(), ds.NumNamespaces(), duration, rate)

	cfg.ReloadBrick = true

	db, err := hod.NewDB(cfg)
	if err != nil {
		return err
	}
	err = db.LoadDataset(ds)
	if err != nil {
		return err
	}

	return nil
}

func loadLinks(c *cli.Context) error {
	if c.NArg() == 0 {
		return errors.New("Need to specify a JSON file to load")
	}
	filename := c.Args().Get(0)
	cfg, err := config.ReadConfig(c.String("config"))
	if err != nil {
		return err
	}
	cfg.ReloadBrick = false
	db, err := hod.NewDB(cfg)
	if err != nil {
		return err
	}
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	var updates = new(hod.LinkUpdates)
	decoder := json.NewDecoder(file)
	if err := decoder.Decode(updates); err != nil {
		return err
	}
	log.Noticef("Adding %d links, Removing %d links", len(updates.Adding), len(updates.Removing))
	return db.UpdateLinks(updates)
}

func startCLI(c *cli.Context) error {
	cfg, err := config.ReadConfig(c.String("config"))
	if err != nil {
		return err
	}
	cfg.ReloadBrick = false
	db, err := hod.NewDB(cfg)
	if err != nil {
		return err
	}
	return runInteractiveQuery(db)
}

func startHTTP(c *cli.Context) error {
	cfg, err := config.ReadConfig(c.String("config"))
	if err != nil {
		return err
	}
	cfg.ReloadBrick = false
	db, err := hod.NewDB(cfg)
	if err != nil {
		return err
	}
	server.StartHodServer(db, cfg)
	return nil
}

func dump(c *cli.Context) error {
	if c.NArg() == 0 {
		return errors.New("Need to specify a turtle file to load")
	}
	filename := c.Args().Get(0)
	p := turtle.GetParser()
	ds, _ := p.Parse(filename)
	for _, triple := range ds.Triples {
		var s = triple.Subject.Value
		var p = triple.Predicate.Value
		var o = triple.Object.Value
		for pfx, full := range ds.Namespaces {
			if triple.Subject.Namespace == full {
				s = pfx + ":" + s
			}
			if triple.Predicate.Namespace == full {
				p = pfx + ":" + p
			}
			if triple.Object.Namespace == full {
				o = pfx + ":" + o
			}
		}
		fmt.Printf("%s\t%s\t%s\n", s, p, o)
	}
	return nil
}

func classGraph(c *cli.Context) error {
	if c.NArg() == 0 {
		return errors.New("Need to specify a turtle file to load")
	}
	filename := c.Args().Get(0)
	p := turtle.GetParser()
	ds, _ := p.Parse(filename)

	name := gethash() + ".gv"
	f, err := os.Create(name)
	if err != nil {
		return err
	}

	nodes := make(map[string]struct{})
	edges := make(map[string]struct{})
	for _, triple := range ds.Triples {
		if triple.Predicate.String() == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" && triple.Object.String() == "http://www.w3.org/2002/07/owl#Class" {
			x := fmt.Sprintf("%s;\n", triple.Subject.Value)
			nodes[x] = struct{}{}
		} else if triple.Predicate.String() == "http://www.w3.org/2000/01/rdf-schema#subClassOf" {
			if strings.HasPrefix(triple.Object.Value, "genid") || strings.HasPrefix(triple.Subject.Value, "genid") {
				continue
			}
			x := fmt.Sprintf("%s -> %s [label=\"%s\"];\n", triple.Object.Value, triple.Subject.Value, "hasSubclass")
			edges[x] = struct{}{}
		}
	}

	fmt.Fprintln(f, "digraph G {")
	fmt.Fprintln(f, "ratio=\"auto\"")
	fmt.Fprintln(f, "rankdir=\"LR\"")
	fmt.Fprintln(f, "size=\"7.5,10\"")
	for node := range nodes {
		fmt.Fprintf(f, node)
	}
	for edge := range edges {
		fmt.Fprintf(f, edge)
	}
	fmt.Fprintln(f, "}")
	cmd := exec.Command("dot", "-Tpdf", name)
	pdf, err := cmd.Output()
	if err != nil {
		return err
	}
	f2, err := os.Create(filename + ".pdf")
	if err != nil {
		return err
	}
	_, err = f2.Write(pdf)
	if err != nil {
		return err
	}

	// remove DOT file
	os.Remove(name)
	return nil
}

func dumpGraph(c *cli.Context) error {
	if c.NArg() == 0 {
		return errors.New("Need to specify a turtle file to load")
	}
	filename := c.Args().Get(0)
	p := turtle.GetParser()
	ds, _ := p.Parse(filename)

	name := gethash() + ".gv"
	f, err := os.Create(name)
	if err != nil {
		return err
	}

	nodes := make(map[string]struct{})
	edges := make(map[string]struct{})
	for _, triple := range ds.Triples {
		x := fmt.Sprintf("%s;\n", triple.Subject.Value)
		nodes[x] = struct{}{}
		x = fmt.Sprintf("%s -> %s [label=\"%s\"];\n", triple.Subject.Value, triple.Object.Value, triple.Predicate.Value)
		edges[x] = struct{}{}
	}

	fmt.Fprintln(f, "digraph G {")
	fmt.Fprintln(f, "ratio=\"auto\"")
	fmt.Fprintln(f, "rankdir=\"LR\"")
	fmt.Fprintln(f, "size=\"7.5,10\"")
	for node := range nodes {
		fmt.Fprintf(f, node)
	}
	for edge := range edges {
		fmt.Fprintf(f, edge)
	}
	fmt.Fprintln(f, "}")
	cmd := exec.Command("sfdp", "-Tpdf", name)
	pdf, err := cmd.Output()
	if err != nil {
		// try graphviz dot then
		cmd = exec.Command("dot", "-Tpdf", name)
		pdf, err = cmd.Output()
		if err != nil {
			return err
		}
	}
	f2, err := os.Create(filename + ".pdf")
	if err != nil {
		return err
	}
	_, err = f2.Write(pdf)
	if err != nil {
		return err
	}

	// remove DOT file
	os.Remove(name)
	return nil
}

func gethash() string {
	h := md5.New()
	seed := make([]byte, 16)
	binary.PutVarint(seed, time.Now().UnixNano())
	h.Write(seed)
	return fmt.Sprintf("%x", h.Sum(nil))
}

func runInteractiveQuery(db *hod.DB) error {
	currentUser, err := user.Current()
	if err != nil {
		return err
	}
	fmt.Println("Successfully loaded dataset!")
	bufQuery := ""

	//setup color for prompt
	c := color.New(color.FgCyan)
	c.Add(color.Bold)
	cyan := c.SprintFunc()

	rl, err := readline.NewEx(&readline.Config{
		Prompt:                 cyan("(hod)> "),
		HistoryFile:            currentUser.HomeDir + "/.hod-query-history",
		DisableAutoSaveHistory: true,
	})
	for {
		line, err := rl.Readline()
		if err != nil {
			break
		}
		if len(line) == 0 {
			continue
		}
		bufQuery += line + " "
		if !strings.HasSuffix(strings.TrimSpace(line), ";") {
			rl.SetPrompt(">>> ...")
			continue
		}
		rl.SetPrompt(cyan("(hod)> "))
		rl.SaveHistory(bufQuery)
		q, err := query.Parse(strings.NewReader(bufQuery))
		if err != nil {
			log.Error(err)
		} else {
			res := db.RunQuery(q)
			res.Dump()
		}
		bufQuery = ""
	}
	return nil
}
<|endoftext|>


<commit_before>package api

import (
	"github.com/gin-gonic/gin"
	"github.com/magneticio/vamp-loadbalancer/haproxy"
	"github.com/magneticio/vamp-loadbalancer/metrics"
	gologger "github.com/op/go-logging"
	"strconv"
)

func CreateApi(port int, haConfig *haproxy.Config, haRuntime *haproxy.Runtime, log *gologger.Logger, SSEBroker *metrics.SSEBroker) {

	r := gin.New()
	r.Use(HaproxyMiddleware(haConfig, haRuntime))
	r.Use(LoggerMiddleware(log))
	r.Use(gin.Recovery())
	r.Static("/www", "./www")
	v1 := r.Group("/v1")

	{
		r.GET("/", func(c *gin.Context) {
			c.Redirect(301, "www/index.html")
		})

		/*
		   Backend
		*/
		v1.PUT("/backend/:name/server/:server", PutBackendWeight)

		/*
		   Frontend
		*/
		v1.POST("frontend/:name/acl/:acl/:pattern", PostAclPattern)
		v1.GET("/frontend/:name/acls", GetACLs)

		/*
		   Stats
		*/
		v1.GET("/stats", GetAllStats)
		v1.GET("/stats/backend", GetBackendStats)
		v1.GET("/stats/frontend", GetFrontendStats)
		v1.GET("/stats/server", GetServerStats)
		v1.GET("/stats/stream", SSEMiddleware(SSEBroker), GetSSEStream)

		/*
		   Full Config Actions
		*/
		v1.GET("/config", GetConfig)
		v1.POST("/config", PostConfig)

		/*
		   Info
		*/
		v1.GET("/info", GetInfo)
	}

	// Listen and server on port
	r.Run("0.0.0.0:" + strconv.Itoa(port))

}
<commit_msg>breaking change: resource endpoints now plural<commit_after>package api

import (
	"github.com/gin-gonic/gin"
	"github.com/magneticio/vamp-loadbalancer/haproxy"
	"github.com/magneticio/vamp-loadbalancer/metrics"
	gologger "github.com/op/go-logging"
	"strconv"
)

func CreateApi(port int, haConfig *haproxy.Config, haRuntime *haproxy.Runtime, log *gologger.Logger, SSEBroker *metrics.SSEBroker) {

	r := gin.New()
	r.Use(HaproxyMiddleware(haConfig, haRuntime))
	r.Use(LoggerMiddleware(log))
	r.Use(gin.Recovery())
	r.Static("/www", "./www")
	v1 := r.Group("/v1")

	{
		r.GET("/", func(c *gin.Context) {
			c.Redirect(301, "www/index.html")
		})

		/*
		   Frontend
		*/
		v1.POST("frontends/:name/acls", PostFrontendACL)
		v1.GET("/frontends/:name/acls", GetFrontendACLs)
		v1.GET("/frontends/:name", GetFrontend)
		v1.DELETE("/frontends/:name", DeleteFrontend)
		v1.POST("/frontends", PostFrontend)

		/*
		   Backend
		*/
		v1.PUT("/backends/:name/servers/:server", PutBackendWeight)
		v1.GET("/backends/:name", GetBackend)

		/*
		   Stats
		*/
		v1.GET("/stats", GetAllStats)
		v1.GET("/stats/backends", GetBackendStats)
		v1.GET("/stats/frontends", GetFrontendStats)
		v1.GET("/stats/servers", GetServerStats)
		v1.GET("/stats/stream", SSEMiddleware(SSEBroker), GetSSEStream)

		/*
		   Full Config Actions
		*/
		v1.GET("/config", GetConfig)
		v1.POST("/config", PostConfig)

		/*
		   Info
		*/
		v1.GET("/info", GetInfo)
	}

	// Listen and server on port
	r.Run("0.0.0.0:" + strconv.Itoa(port))

}
<|endoftext|>