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

// TODO(adg): accept -a flag on 'create' and 'commit' (like git commit -a)
// TODO(adg): accept -r flag on 'upload' to nominate reviewer
// TODO(adg): support 'create' from non-master branches
// TODO(adg): check style of commit message
// TODO(adg): write doc comment
// TOOD(adg): print gerrit votes on 'pending'
// TODO(adg): add gofmt commit hook
// TODO(adg): 'upload' warn about uncommitted changes (maybe commit/create too?)

package main // import "golang.org/x/review"

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
)

var (
	hookFile = filepath.FromSlash(".git/hooks/commit-msg")
	verbose  = flag.Bool("v", false, "verbose output")
	noRun    = flag.Bool("n", false, "print but do not run commands")
)

const usage = `Usage: %s [-n] [-v] <command>
Type "%s help" for more information.
`

const help = `Usage: %s [-n] [-v] <command>

The review command is a wrapper for the git command that provides a simple
interface to the "single-commit feature branch" development model.

Available comands:

	create <name>
		Create a local branch with the provided name
		and commit the staged changes to it.

	commit
		Amend local branch HEAD commit with the staged changes.

	diff
		View differences between remote branch HEAD and
		the local branch HEAD.
		(The differences introduced by this change.)

	upload
		Upload HEAD commit to the code review server.

	sync
		Fetch changes from the remote repository and merge them to the
		current branch, rebasing the HEAD commit (if any) on top of
		them. If the HEAD commit has been submitted, switch back to the
		master branch and delete the feature branch.

	pending
		Show local branches and their head commits.

`

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, usage, os.Args[0], os.Args[0])
		os.Exit(2)
	}
	flag.Parse()

	goToRepoRoot()
	installHook()

	command, args := flag.Arg(0), flag.Args()[1:]

	switch command {
	case "help":
		fmt.Fprintf(os.Stdout, help, os.Args[0])
	case "create", "cr":
		create(args)
	case "commit", "co":
		commit(args)
	case "diff", "d":
		diff(args)
	case "upload", "u":
		upload(args)
	case "sync", "s":
		doSync(args)
	case "pending", "p":
		pending(args)
	default:
		flag.Usage()
	}
}

func create(args []string) {
	if len(args) != 1 || args[0] == "" {
		flag.Usage()
	}
	name := args[0]
	if !hasStagedChanges() {
		dief("no staged changes.\nDid you forget to 'git add'?")
	}
	if b := currentBranch(); b != "master" {
		dief("must run 'create' from the master branch (now on %q).\n"+
			"(Try 'review sync' or 'git checkout master' first.)",
			b)
	}
	run("git", "checkout", "-q", "-b", name)
	if err := runErr("git", "commit", "-q"); err != nil {
		verbosef("Commit failed: %v\nSwitching back to master.\n", err)
		run("git", "checkout", "-q", "master")
		run("git", "branch", "-q", "-d", name)
	}
}

func commit(args []string) {
	if len(args) != 0 {
		flag.Usage()
	}
	if !hasStagedChanges() {
		dief("no staged changes. Did you forget to 'git add'?")
	}
	if currentBranch() == "master" {
		dief("can't commit to master branch.")
	}
	run("git", "commit", "-q", "--amend", "-C", "HEAD")
}

func diff(args []string) {
	if len(args) != 0 {
		flag.Usage()
	}
	run("git", "diff", "HEAD^", "HEAD")
}

func upload(args []string) {
	if len(args) != 0 {
		flag.Usage()
	}
	if currentBranch() == "master" {
		dief("can't upload from master branch.")
	}
	run("git", "push", "-q", "origin", "HEAD:refs/for/master")
}

func doSync(args []string) {
	if len(args) != 0 {
		flag.Usage()
	}
	run("git", "fetch", "-q")

	// If we're on master, just fast-forward.
	branch := currentBranch()
	if branch == "master" {
		run("git", "merge", "-q", "--ff-only", "origin/master")
		return
	}

	// Check that exactly this commit was submitted to master. If so,
	// switch back to master, fast-forward, delete the feature branch.
	if branchContains("origin/master", "HEAD") {
		run("git", "checkout", "-q", "master")
		run("git", "merge", "-q", "--ff-only", "origin/master")
		run("git", "branch", "-q", "-d", branch)
		fmt.Printf("Change on %q submitted; branch deleted.\n"+
			"On master branch.\n", branch)
		return
	}

	// Check whether a rebased version of this commit was submitted to
	// master. If so, switch back to master, fast-forward, and
	// provide instructions for deleting the feature branch.
	// (We're not 100% sure that the feature branch HEAD was submitted,
	// so be cautious.)
	if headSubmitted(branch) {
		run("git", "checkout", "-q", "master")
		run("git", "merge", "-q", "--ff-only", "origin/master")
		fmt.Fprintf(os.Stderr,
			"I think the change on %q has been submitted.\n"+
				"If you agree, and no longer need branch %q, "+
				"run:\n\tgit branch -D %v\n"+
				"On master branch.\n",
			branch, branch, branch)
		return
	}

	// Bump master HEAD to that of origin/master, just in case the user
	// switches back to master with "git checkout master" later.
	// TODO(adg): maybe we shouldn't do this at all?
	if !branchContains("origin/master", "master") {
		run("git", "branch", "-f", "master", "origin/master")
	}

	// We have un-submitted changes on this feature branch; rebase.
	run("git", "rebase", "-q", "origin/master")
}

func pending(args []string) {
	if len(args) != 0 {
		flag.Usage()
	}
	var (
		wg      sync.WaitGroup
		origin  = originURL()
		current = currentBranch()
	)
	if current == "master" {
		fmt.Println("On master branch.")
	}
	for _, branch := range localBranches() {
		if branch == "master" {
			continue
		}
		wg.Add(1)
		go func(branch string) {
			defer wg.Done()
			p := ""
			if branch == current {
				p = "* "
			}
			id := headChangeId(branch)
			c, err := getChange(origin, id)
			switch err {
			case notFound:
				// TODO(adg): read local commit msg
				var msg string
				fmt.Printf("%v%v:\n\t%v\n\t(not uploaded)\n",
					p, branch, msg)
			case nil:
				status := ""
				switch c.Status {
				case "MERGED":
					status += " [submitted]"
				case "ABANDONED":
					status += " [abandoned]"
				}
				fmt.Printf("%v%v%v:\n\t%v\n\t%v\n",
					p, branch, status, c.Subject, c.URL)
			default:
				fmt.Fprintf(os.Stderr, "fetching change for %q: %v\n", branch, err)
			}
		}(branch)
	}
	wg.Wait()
}

func originURL() string {
	out, err := exec.Command("git", "config", "remote.origin.url").CombinedOutput()
	if err != nil {
		dief("could not find URL for 'origin' remote.\n"+
			"Did you check out from the right place?\n"+
			"git config remote.origin.url: %v\n"+
			"%s", err, out)
	}
	return string(out)
}

func localBranches() (branches []string) {
	for _, s := range runLines("git", "branch", "-l", "-q") {
		branches = append(branches, strings.TrimPrefix(s, "* "))
	}
	return branches
}

func branchContains(branch, rev string) bool {
	for _, s := range runLines("git", "branch", "-r", "--contains", rev) {
		if s == branch {
			return true
		}
	}
	return false
}

var stagedRe = regexp.MustCompile(`^[ACDMR]  `)

func hasStagedChanges() bool {
	for _, s := range runLines("git", "status", "-b", "--porcelain") {
		if stagedRe.MatchString(s) {
			return true
		}
	}
	return false
}

func currentBranch() string {
	return strings.TrimSpace(runOutput("git", "rev-parse", "--abbrev-ref", "HEAD"))
}

func headSubmitted(branch string) bool {
	s := "Change-Id: " + headChangeId(branch)
	return len(runOutput("git", "log", "--grep", s, "origin/master")) > 0
}

func headChangeId(branch string) string {
	const (
		p = "Change-Id: "
		f = "--format=format:%b"
	)
	for _, s := range runLines("git", "log", "-n", "1", f, branch, "--") {
		if strings.HasPrefix(s, p) {
			return strings.TrimSpace(strings.TrimPrefix(s, p))
		}
	}
	dief("no Change-Id line found in HEAD commit on branch %s.", branch)
	panic("unreachable")
}

func goToRepoRoot() {
	prevDir, err := os.Getwd()
	if err != nil {
		dief("could not get current directory: %v", err)
	}
	for {
		if _, err := os.Stat(".git"); err == nil {
			return
		}
		if err := os.Chdir(".."); err != nil {
			dief("could not chdir: %v", err)
		}
		currentDir, err := os.Getwd()
		if err != nil {
			dief("could not get current directory: %v", err)
		}
		if currentDir == prevDir {
			dief("git root not found.\n" +
				"Run from within the Git tree please.")
		}
		prevDir = currentDir
	}
}

func installHook() {
	_, err := os.Stat(hookFile)
	if err == nil {
		return
	}
	if !os.IsNotExist(err) {
		dief("error checking for hook file: %v", err)
	}
	verbosef("Presubmit hook to add Change-Id to commit messages is missing.\n"+
		"Automatically creating it at %v.\n", hookFile)
	hookContent := []byte(commitMsgHook)
	if err := ioutil.WriteFile(hookFile, hookContent, 0700); err != nil {
		dief("error writing hook file: %v", err)
	}
}

func run(command string, args ...string) {
	if err := runErr(command, args...); err != nil {
		if !*verbose {
			// If we're not in verbose mode, print the command
			// before dying to give context to the failure.
			fmt.Fprintln(os.Stderr, commandString(command, args))
		}
		dief("%v", err)
	}
}

func runErr(command string, args ...string) error {
	if *verbose || *noRun {
		fmt.Fprintln(os.Stderr, commandString(command, args))
	}
	if *noRun {
		return nil
	}
	cmd := exec.Command(command, args...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func runOutput(command string, args ...string) string {
	b, err := exec.Command(command, args...).CombinedOutput()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n%s\n", commandString(command, args), b)
		dief("%v", err)
	}
	return string(b)
}

func runLines(command string, args ...string) []string {
	var s []string
	for _, l := range strings.Split(runOutput(command, args...), "\n") {
		l = strings.TrimSpace(l)
		if l != "" {
			s = append(s, l)
		}
	}
	return s
}

func commandString(command string, args []string) string {
	return strings.Join(append([]string{command}, args...), " ")
}

func dief(format string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, "review: "+format+"\n", args...)
	os.Exit(1)
}

func verbosef(format string, args ...interface{}) {
	if *verbose {
		fmt.Fprintf(os.Stderr, format, args...)
	}
}
<commit_msg>review: document the idempotence of runOutput and runLines<commit_after>// Copyright 2014 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.

// TODO(adg): accept -a flag on 'create' and 'commit' (like git commit -a)
// TODO(adg): accept -r flag on 'upload' to nominate reviewer
// TODO(adg): support 'create' from non-master branches
// TODO(adg): check style of commit message
// TODO(adg): write doc comment
// TOOD(adg): print gerrit votes on 'pending'
// TODO(adg): add gofmt commit hook
// TODO(adg): 'upload' warn about uncommitted changes (maybe commit/create too?)

package main // import "golang.org/x/review"

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
)

var (
	hookFile = filepath.FromSlash(".git/hooks/commit-msg")
	verbose  = flag.Bool("v", false, "verbose output")
	noRun    = flag.Bool("n", false, "print but do not run commands")
)

const usage = `Usage: %s [-n] [-v] <command>
Type "%s help" for more information.
`

const help = `Usage: %s [-n] [-v] <command>

The review command is a wrapper for the git command that provides a simple
interface to the "single-commit feature branch" development model.

Available comands:

	create <name>
		Create a local branch with the provided name
		and commit the staged changes to it.

	commit
		Amend local branch HEAD commit with the staged changes.

	diff
		View differences between remote branch HEAD and
		the local branch HEAD.
		(The differences introduced by this change.)

	upload
		Upload HEAD commit to the code review server.

	sync
		Fetch changes from the remote repository and merge them to the
		current branch, rebasing the HEAD commit (if any) on top of
		them. If the HEAD commit has been submitted, switch back to the
		master branch and delete the feature branch.

	pending
		Show local branches and their head commits.

`

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, usage, os.Args[0], os.Args[0])
		os.Exit(2)
	}
	flag.Parse()

	goToRepoRoot()
	installHook()

	command, args := flag.Arg(0), flag.Args()[1:]

	switch command {
	case "help":
		fmt.Fprintf(os.Stdout, help, os.Args[0])
	case "create", "cr":
		create(args)
	case "commit", "co":
		commit(args)
	case "diff", "d":
		diff(args)
	case "upload", "u":
		upload(args)
	case "sync", "s":
		doSync(args)
	case "pending", "p":
		pending(args)
	default:
		flag.Usage()
	}
}

func create(args []string) {
	if len(args) != 1 || args[0] == "" {
		flag.Usage()
	}
	name := args[0]
	if !hasStagedChanges() {
		dief("no staged changes.\nDid you forget to 'git add'?")
	}
	if b := currentBranch(); b != "master" {
		dief("must run 'create' from the master branch (now on %q).\n"+
			"(Try 'review sync' or 'git checkout master' first.)",
			b)
	}
	run("git", "checkout", "-q", "-b", name)
	if err := runErr("git", "commit", "-q"); err != nil {
		verbosef("Commit failed: %v\nSwitching back to master.\n", err)
		run("git", "checkout", "-q", "master")
		run("git", "branch", "-q", "-d", name)
	}
}

func commit(args []string) {
	if len(args) != 0 {
		flag.Usage()
	}
	if !hasStagedChanges() {
		dief("no staged changes. Did you forget to 'git add'?")
	}
	if currentBranch() == "master" {
		dief("can't commit to master branch.")
	}
	run("git", "commit", "-q", "--amend", "-C", "HEAD")
}

func diff(args []string) {
	if len(args) != 0 {
		flag.Usage()
	}
	run("git", "diff", "HEAD^", "HEAD")
}

func upload(args []string) {
	if len(args) != 0 {
		flag.Usage()
	}
	if currentBranch() == "master" {
		dief("can't upload from master branch.")
	}
	run("git", "push", "-q", "origin", "HEAD:refs/for/master")
}

func doSync(args []string) {
	if len(args) != 0 {
		flag.Usage()
	}
	run("git", "fetch", "-q")

	// If we're on master, just fast-forward.
	branch := currentBranch()
	if branch == "master" {
		run("git", "merge", "-q", "--ff-only", "origin/master")
		return
	}

	// Check that exactly this commit was submitted to master. If so,
	// switch back to master, fast-forward, delete the feature branch.
	if branchContains("origin/master", "HEAD") {
		run("git", "checkout", "-q", "master")
		run("git", "merge", "-q", "--ff-only", "origin/master")
		run("git", "branch", "-q", "-d", branch)
		fmt.Printf("Change on %q submitted; branch deleted.\n"+
			"On master branch.\n", branch)
		return
	}

	// Check whether a rebased version of this commit was submitted to
	// master. If so, switch back to master, fast-forward, and
	// provide instructions for deleting the feature branch.
	// (We're not 100% sure that the feature branch HEAD was submitted,
	// so be cautious.)
	if headSubmitted(branch) {
		run("git", "checkout", "-q", "master")
		run("git", "merge", "-q", "--ff-only", "origin/master")
		fmt.Fprintf(os.Stderr,
			"I think the change on %q has been submitted.\n"+
				"If you agree, and no longer need branch %q, "+
				"run:\n\tgit branch -D %v\n"+
				"On master branch.\n",
			branch, branch, branch)
		return
	}

	// Bump master HEAD to that of origin/master, just in case the user
	// switches back to master with "git checkout master" later.
	// TODO(adg): maybe we shouldn't do this at all?
	if !branchContains("origin/master", "master") {
		run("git", "branch", "-f", "master", "origin/master")
	}

	// We have un-submitted changes on this feature branch; rebase.
	run("git", "rebase", "-q", "origin/master")
}

func pending(args []string) {
	if len(args) != 0 {
		flag.Usage()
	}
	var (
		wg      sync.WaitGroup
		origin  = originURL()
		current = currentBranch()
	)
	if current == "master" {
		fmt.Println("On master branch.")
	}
	for _, branch := range localBranches() {
		if branch == "master" {
			continue
		}
		wg.Add(1)
		go func(branch string) {
			defer wg.Done()
			p := ""
			if branch == current {
				p = "* "
			}
			id := headChangeId(branch)
			c, err := getChange(origin, id)
			switch err {
			case notFound:
				// TODO(adg): read local commit msg
				var msg string
				fmt.Printf("%v%v:\n\t%v\n\t(not uploaded)\n",
					p, branch, msg)
			case nil:
				status := ""
				switch c.Status {
				case "MERGED":
					status += " [submitted]"
				case "ABANDONED":
					status += " [abandoned]"
				}
				fmt.Printf("%v%v%v:\n\t%v\n\t%v\n",
					p, branch, status, c.Subject, c.URL)
			default:
				fmt.Fprintf(os.Stderr, "fetching change for %q: %v\n", branch, err)
			}
		}(branch)
	}
	wg.Wait()
}

func originURL() string {
	out, err := exec.Command("git", "config", "remote.origin.url").CombinedOutput()
	if err != nil {
		dief("could not find URL for 'origin' remote.\n"+
			"Did you check out from the right place?\n"+
			"git config remote.origin.url: %v\n"+
			"%s", err, out)
	}
	return string(out)
}

func localBranches() (branches []string) {
	for _, s := range getLines("git", "branch", "-l", "-q") {
		branches = append(branches, strings.TrimPrefix(s, "* "))
	}
	return branches
}

func branchContains(branch, rev string) bool {
	for _, s := range getLines("git", "branch", "-r", "--contains", rev) {
		if s == branch {
			return true
		}
	}
	return false
}

var stagedRe = regexp.MustCompile(`^[ACDMR]  `)

func hasStagedChanges() bool {
	for _, s := range getLines("git", "status", "-b", "--porcelain") {
		if stagedRe.MatchString(s) {
			return true
		}
	}
	return false
}

func currentBranch() string {
	return strings.TrimSpace(getOutput("git", "rev-parse", "--abbrev-ref", "HEAD"))
}

func headSubmitted(branch string) bool {
	s := "Change-Id: " + headChangeId(branch)
	return len(getOutput("git", "log", "--grep", s, "origin/master")) > 0
}

func headChangeId(branch string) string {
	const (
		p = "Change-Id: "
		f = "--format=format:%b"
	)
	for _, s := range getLines("git", "log", "-n", "1", f, branch, "--") {
		if strings.HasPrefix(s, p) {
			return strings.TrimSpace(strings.TrimPrefix(s, p))
		}
	}
	dief("no Change-Id line found in HEAD commit on branch %s.", branch)
	panic("unreachable")
}

func goToRepoRoot() {
	prevDir, err := os.Getwd()
	if err != nil {
		dief("could not get current directory: %v", err)
	}
	for {
		if _, err := os.Stat(".git"); err == nil {
			return
		}
		if err := os.Chdir(".."); err != nil {
			dief("could not chdir: %v", err)
		}
		currentDir, err := os.Getwd()
		if err != nil {
			dief("could not get current directory: %v", err)
		}
		if currentDir == prevDir {
			dief("git root not found.\n" +
				"Run from within the Git tree please.")
		}
		prevDir = currentDir
	}
}

func installHook() {
	_, err := os.Stat(hookFile)
	if err == nil {
		return
	}
	if !os.IsNotExist(err) {
		dief("error checking for hook file: %v", err)
	}
	verbosef("Presubmit hook to add Change-Id to commit messages is missing.\n"+
		"Automatically creating it at %v.\n", hookFile)
	hookContent := []byte(commitMsgHook)
	if err := ioutil.WriteFile(hookFile, hookContent, 0700); err != nil {
		dief("error writing hook file: %v", err)
	}
}

func run(command string, args ...string) {
	if err := runErr(command, args...); err != nil {
		if !*verbose {
			// If we're not in verbose mode, print the command
			// before dying to give context to the failure.
			fmt.Fprintln(os.Stderr, commandString(command, args))
		}
		dief("%v", err)
	}
}

func runErr(command string, args ...string) error {
	if *verbose || *noRun {
		fmt.Fprintln(os.Stderr, commandString(command, args))
	}
	if *noRun {
		return nil
	}
	cmd := exec.Command(command, args...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

// getOutput runs the specified command and returns its combined standard
// output and standard error outputs.
// NOTE: It should only be used to run commands that return information,
// **not** commands that make any actual changes.
func getOutput(command string, args ...string) string {
	b, err := exec.Command(command, args...).CombinedOutput()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n%s\n", commandString(command, args), b)
		dief("%v", err)
	}
	return string(b)
}

// getLines is like getOutput but it returns non-empty output lines.
// NOTE: It should only be used to run commands that return information,
// **not** commands that make any actual changes.
func getLines(command string, args ...string) []string {
	var s []string
	for _, l := range strings.Split(getOutput(command, args...), "\n") {
		l = strings.TrimSpace(l)
		if l != "" {
			s = append(s, l)
		}
	}
	return s
}

func commandString(command string, args []string) string {
	return strings.Join(append([]string{command}, args...), " ")
}

func dief(format string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, "review: "+format+"\n", args...)
	os.Exit(1)
}

func verbosef(format string, args ...interface{}) {
	if *verbose {
		fmt.Fprintf(os.Stderr, format, args...)
	}
}
<|endoftext|>


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

package server

import (
	"context"
	"fmt"
	"sync"
	"time"

	"github.com/golang/glog"
	"github.com/golang/protobuf/ptypes"
	"github.com/google/trillian"
	"github.com/google/trillian/extension"
	"github.com/google/trillian/log"
	"github.com/google/trillian/merkle/hashers"
	"github.com/google/trillian/trees"

	tcrypto "github.com/google/trillian/crypto"
)

// SequencerManager provides sequencing operations for a collection of Logs.
type SequencerManager struct {
	guardWindow  time.Duration
	registry     extension.Registry
	signers      map[int64]*tcrypto.Signer
	signersMutex sync.Mutex
}

var seqOpts = trees.NewGetOpts(trees.SequenceLog, trillian.TreeType_LOG, trillian.TreeType_PREORDERED_LOG)

// NewSequencerManager creates a new SequencerManager instance based on the provided KeyManager instance
// and guard window.
func NewSequencerManager(registry extension.Registry, gw time.Duration) *SequencerManager {
	return &SequencerManager{
		guardWindow: gw,
		registry:    registry,
		signers:     make(map[int64]*tcrypto.Signer),
	}
}

// Name returns the name of the object.
func (s *SequencerManager) Name() string {
	return "Sequencer"
}

// ExecutePass performs sequencing for the specified Log.
func (s *SequencerManager) ExecutePass(ctx context.Context, logID int64, info *LogOperationInfo) (int, error) {
	// TODO(Martin2112): Honor the sequencing enabled in log parameters, needs an API change
	// so deferring it

	tree, err := trees.GetTree(ctx, s.registry.AdminStorage, logID, seqOpts)
	if err != nil {
		return 0, fmt.Errorf("error retrieving log %v: %v", logID, err)
	}
	ctx = trees.NewContext(ctx, tree)

	hasher, err := hashers.NewLogHasher(tree.HashStrategy)
	if err != nil {
		return 0, fmt.Errorf("error getting hasher for log %v: %v", logID, err)
	}

	signer, err := s.getSigner(ctx, tree)
	if err != nil {
		return 0, fmt.Errorf("error getting signer for log %v: %v", logID, err)
	}

	sequencer := log.NewSequencer(hasher, info.TimeSource, s.registry.LogStorage, signer, s.registry.MetricFactory, s.registry.QuotaManager)

	maxRootDuration, err := ptypes.Duration(tree.MaxRootDuration)
	if err != nil {
		glog.Warning("failed to parse tree.MaxRootDuration, using zero")
		maxRootDuration = 0
	}
	leaves, err := sequencer.IntegrateBatch(ctx, tree, info.BatchSize, s.guardWindow, maxRootDuration)
	if err != nil {
		return 0, fmt.Errorf("failed to integrate batch for %v: %v", logID, err)
	}
	return leaves, nil
}

// getSigner returns a signer for the given tree.
// Signers are cached, so only one will be created per tree.
func (s *SequencerManager) getSigner(ctx context.Context, tree *trillian.Tree) (*tcrypto.Signer, error) {
	s.signersMutex.Lock()
	defer s.signersMutex.Unlock()

	if signer, ok := s.signers[tree.GetTreeId()]; ok {
		return signer, nil
	}

	signer, err := trees.Signer(ctx, tree)
	if err != nil {
		return nil, err
	}

	s.signers[tree.GetTreeId()] = signer
	return signer, nil
}
<commit_msg>Pass the error from ExecutePass back directly so we don't lose the status code. The extra log id was also just duplicating what the caller logs.<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package server

import (
	"context"
	"fmt"
	"sync"
	"time"

	"github.com/golang/glog"
	"github.com/golang/protobuf/ptypes"
	"github.com/google/trillian"
	"github.com/google/trillian/extension"
	"github.com/google/trillian/log"
	"github.com/google/trillian/merkle/hashers"
	"github.com/google/trillian/trees"

	tcrypto "github.com/google/trillian/crypto"
)

// SequencerManager provides sequencing operations for a collection of Logs.
type SequencerManager struct {
	guardWindow  time.Duration
	registry     extension.Registry
	signers      map[int64]*tcrypto.Signer
	signersMutex sync.Mutex
}

var seqOpts = trees.NewGetOpts(trees.SequenceLog, trillian.TreeType_LOG, trillian.TreeType_PREORDERED_LOG)

// NewSequencerManager creates a new SequencerManager instance based on the provided KeyManager instance
// and guard window.
func NewSequencerManager(registry extension.Registry, gw time.Duration) *SequencerManager {
	return &SequencerManager{
		guardWindow: gw,
		registry:    registry,
		signers:     make(map[int64]*tcrypto.Signer),
	}
}

// Name returns the name of the object.
func (s *SequencerManager) Name() string {
	return "Sequencer"
}

// ExecutePass performs sequencing for the specified Log.
func (s *SequencerManager) ExecutePass(ctx context.Context, logID int64, info *LogOperationInfo) (int, error) {
	// TODO(Martin2112): Honor the sequencing enabled in log parameters, needs an API change
	// so deferring it

	tree, err := trees.GetTree(ctx, s.registry.AdminStorage, logID, seqOpts)
	if err != nil {
		return 0, err
	}
	ctx = trees.NewContext(ctx, tree)

	hasher, err := hashers.NewLogHasher(tree.HashStrategy)
	if err != nil {
		return 0, fmt.Errorf("error getting hasher for log %v: %v", logID, err)
	}

	signer, err := s.getSigner(ctx, tree)
	if err != nil {
		return 0, fmt.Errorf("error getting signer for log %v: %v", logID, err)
	}

	sequencer := log.NewSequencer(hasher, info.TimeSource, s.registry.LogStorage, signer, s.registry.MetricFactory, s.registry.QuotaManager)

	maxRootDuration, err := ptypes.Duration(tree.MaxRootDuration)
	if err != nil {
		glog.Warning("failed to parse tree.MaxRootDuration, using zero")
		maxRootDuration = 0
	}
	leaves, err := sequencer.IntegrateBatch(ctx, tree, info.BatchSize, s.guardWindow, maxRootDuration)
	if err != nil {
		return 0, fmt.Errorf("failed to integrate batch for %v: %v", logID, err)
	}
	return leaves, nil
}

// getSigner returns a signer for the given tree.
// Signers are cached, so only one will be created per tree.
func (s *SequencerManager) getSigner(ctx context.Context, tree *trillian.Tree) (*tcrypto.Signer, error) {
	s.signersMutex.Lock()
	defer s.signersMutex.Unlock()

	if signer, ok := s.signers[tree.GetTreeId()]; ok {
		return signer, nil
	}

	signer, err := trees.Signer(ctx, tree)
	if err != nil {
		return nil, err
	}

	s.signers[tree.GetTreeId()] = signer
	return signer, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	//"github.com/udhos/gowut/gwu"
	"github.com/icza/gowut/gwu"
	//"log"
	//"math/rand"
	//"os"
	//"strconv"
)

const hardUser = "a"
const hardPass = "a"

func newAccPanel(user string) gwu.Panel {
	ap := gwu.NewHorizontalPanel()
	ap.Style().AddClass("account_panel")

	ap.Add(gwu.NewLabel(fmt.Sprintf("%s %s", appName, appVersion)))

	if user == "" {
		// guest user

		// create login button
		b := gwu.NewButton("Login")
		b.AddEHandlerFunc(func(e gwu.Event) {
			e.ReloadWin("login")
		}, gwu.ETypeClick)
		ap.Add(b)

	} else {

		// logged user
		l := gwu.NewLabel(fmt.Sprintf("username=[%s]", user))
		ap.Add(l)
	}
	return ap
}

func accountPanelUpdate(jaz *app, user string) {

	if jaz.winHome != nil {
		if jaz.apHome != nil {
			home := jaz.winHome.ById(jaz.apHome.Id())
			jaz.winHome.Remove(home)
		}
		jaz.apHome = newAccPanel(user)
		if !jaz.winHome.Insert(jaz.apHome, 0) {
			jaz.logf("home win insert accPanel failed")
		}
	}

	if jaz.winAdmin != nil {
		if jaz.apAdmin != nil {
			admin := jaz.winAdmin.ById(jaz.apAdmin.Id())
			jaz.winAdmin.Remove(admin)
		}
		jaz.apAdmin = newAccPanel(user)
		if !jaz.winAdmin.Insert(jaz.apAdmin, 0) {
			jaz.logf("admin win insert accPanel failed")
		}
	}

	if jaz.winLogout != nil {
		if jaz.apLogout != nil {
			logout := jaz.winLogout.ById(jaz.apLogout.Id())
			jaz.winLogout.Remove(logout)
		}
		jaz.apLogout = newAccPanel(user)
		if !jaz.winLogout.Insert(jaz.apLogout, 0) {
			jaz.logf("logout win insert accPanel failed")
		}
	}

}

func accountPanelUpdateEvent(jaz *app, user string, e gwu.Event) {
	accountPanelUpdate(jaz, user)

	if jaz.winHome != nil {
		e.MarkDirty(jaz.winHome)
	}

	if jaz.winAdmin != nil {
		e.MarkDirty(jaz.winAdmin)
	}

	if jaz.winLogout != nil {
		e.MarkDirty(jaz.winLogout)
	}
}

func newWin(jaz *app, path, name string) gwu.Window {
	win := gwu.NewWindow(path, name)
	cssLink := fmt.Sprintf(`<link rel="stylesheet" type="text/css" href="%s">`, jaz.cssPath)
	win.AddHeadHtml(cssLink)
	jaz.logf("window=[%s] attached CSS=[%s]", path, cssLink)
	return win
}

func buildHomeWin(jaz *app, s gwu.Session) {

	winName := fmt.Sprintf("%s home", appName)
	win := newWin(jaz, "home", winName)

	win.Add(jaz.apHome)

	l := gwu.NewLabel(winName)
	l.Style().SetFontWeight(gwu.FontWeightBold).SetFontSize("130%")
	win.Add(l)

	/*
		win.Add(gwu.NewLabel("Click on the button to login:"))
		b := gwu.NewButton("Login")
		b.AddEHandlerFunc(func(e gwu.Event) {
			e.ReloadWin("login")
		}, gwu.ETypeClick)
		win.Add(b)
	*/

	s.AddWin(win)

	jaz.winHome = win
}

func buildLoginWin(jaz *app, s gwu.Session) {

	winName := fmt.Sprintf("%s login", appName)
	win := newWin(jaz, "login", winName)

	win.Style().SetFullSize()
	win.SetAlign(gwu.HACenter, gwu.VAMiddle)

	p := gwu.NewPanel()
	p.SetHAlign(gwu.HACenter)
	p.SetCellPadding(2)

	l := gwu.NewLabel(winName)
	l.Style().SetFontWeight(gwu.FontWeightBold).SetFontSize("150%")
	p.Add(l)
	l = gwu.NewLabel("Login")
	l.Style().SetFontWeight(gwu.FontWeightBold).SetFontSize("130%")
	p.Add(l)
	p.CellFmt(l).Style().SetBorder2(1, gwu.BrdStyleDashed, gwu.ClrNavy)
	l = gwu.NewLabel(fmt.Sprintf("user/pass: %s/%s", hardUser, hardPass))
	l.Style().SetFontSize("80%").SetFontStyle(gwu.FontStyleItalic)
	p.Add(l)

	errL := gwu.NewLabel("")
	errL.Style().SetColor(gwu.ClrRed)
	p.Add(errL)

	table := gwu.NewTable()
	table.SetCellPadding(2)
	table.EnsureSize(2, 2)
	table.Add(gwu.NewLabel("Username:"), 0, 0)
	tb := gwu.NewTextBox("")
	tb.AddSyncOnETypes(gwu.ETypeKeyUp) // synchronize values during editing (while you type in characters)

	tb.Style().SetWidthPx(160)
	table.Add(tb, 0, 1)
	table.Add(gwu.NewLabel("Password:"), 1, 0)
	pb := gwu.NewPasswBox("")
	pb.AddSyncOnETypes(gwu.ETypeKeyUp) // synchronize values during editing (while you type in characters)

	pb.Style().SetWidthPx(160)
	table.Add(pb, 1, 1)
	p.Add(table)
	b := gwu.NewButton("OK")

	p.Add(b)
	l = gwu.NewLabel("")
	p.Add(l)
	p.CellFmt(l).Style().SetHeightPx(200)

	loginHandler := func(e gwu.Event) {

		user := tb.Text()
		pass := pb.Text()
		auth := loginAuth(user, pass)

		//jaz.logf("debug login user=[%s] pass=[%s] result=[%v]", user, pass, auth)

		if auth {

			// Clear username/password fields
			tb.SetText("")
			pb.SetText("")

			// Clear error message
			errL.SetText("")
			e.MarkDirty(errL)

			newSession := e.NewSession()
			newSession.SetAttr("username", user)

			remoteAddr := "(remoteAddr?)"
			if hrr, ok := e.(gwu.HasRequestResponse); ok {
				req := hrr.Request()
				remoteAddr = req.RemoteAddr
			}

			buildPrivateWins(jaz, newSession, remoteAddr)

			accountPanelUpdateEvent(jaz, user, e)

			e.ReloadWin("admin")
		} else {
			//e.SetFocusedComp(tb)
			errL.SetText("Invalid user name or password!")
			e.MarkDirty(errL)
		}
	}

	enterHandler := func(e gwu.Event) {
		if e.Type() == gwu.ETypeKeyPress && e.KeyCode() == gwu.KeyEnter {
			// enter key was pressed
			loginHandler(e)
		}
	}

	tb.AddEHandlerFunc(enterHandler, gwu.ETypeKeyPress)
	pb.AddEHandlerFunc(enterHandler, gwu.ETypeKeyPress)
	b.AddEHandlerFunc(loginHandler, gwu.ETypeClick)

	win.Add(p)
	win.SetFocusedCompId(tb.Id())

	s.AddWin(win)
}

func loginAuth(user, pass string) bool {
	return user == hardUser && pass == hardPass
}

func buildPrivateWins(jaz *app, s gwu.Session, remoteAddr string) {
	user := s.Attr("username").(string)

	buildLogoutWin(jaz, s, user, remoteAddr)
	buildAdminWin(jaz, s, user, remoteAddr)
}

func buildLogoutWin(jaz *app, s gwu.Session, user, remoteAddr string) {
	winName := fmt.Sprintf("%s logout", appName)
	winHeader := fmt.Sprintf("%s - user=%s - address=%s", winName, user, remoteAddr)

	win := newWin(jaz, "logout", winName)

	win.Style().SetFullWidth()
	win.SetCellPadding(2)

	win.Add(jaz.apLogout)

	title := gwu.NewLabel(winHeader)
	win.Add(title)

	p := gwu.NewPanel()
	p.SetCellPadding(2)

	logoutButton := gwu.NewButton("Logout")

	p.Add(logoutButton)

	win.Add(p)
	s.AddWin(win)

	jaz.winLogout = win
}

func buildAdminWin(jaz *app, s gwu.Session, user, remoteAddr string) {
	winName := fmt.Sprintf("%s admin", appName)
	winHeader := fmt.Sprintf("%s - user=%s - address=%s", winName, user, remoteAddr)

	win := newWin(jaz, "admin", winName)

	win.Style().SetFullWidth()
	win.SetCellPadding(2)

	win.Add(jaz.apAdmin)

	title := gwu.NewLabel(winHeader)
	win.Add(title)

	win.Add(gwu.NewLabel("click on this window to see updates"))

	win.AddEHandlerFunc(func(e gwu.Event) {

		if hrr, ok := e.(gwu.HasRequestResponse); ok {
			req := hrr.Request()
			remoteAddr = req.RemoteAddr
		}

		win.Add(gwu.NewLabel(fmt.Sprintf("click - addr=%v", remoteAddr)))
		e.MarkDirty(win)
	}, gwu.ETypeClick)

	s.AddWin(win)

	jaz.winAdmin = win
}
<commit_msg>Clean-up.<commit_after>package main

import (
	"fmt"
	//"github.com/udhos/gowut/gwu"
	"github.com/icza/gowut/gwu"
	//"log"
	//"math/rand"
	//"os"
	//"strconv"
)

func newAccPanel(user string) gwu.Panel {
	ap := gwu.NewHorizontalPanel()
	ap.Style().AddClass("account_panel")

	ap.Add(gwu.NewLabel(fmt.Sprintf("%s %s", appName, appVersion)))

	if user == "" {
		// guest user

		// create login button
		b := gwu.NewButton("Login")
		b.AddEHandlerFunc(func(e gwu.Event) {
			e.ReloadWin("login")
		}, gwu.ETypeClick)
		ap.Add(b)

	} else {

		// logged user
		l := gwu.NewLabel(fmt.Sprintf("username=[%s]", user))
		ap.Add(l)
	}
	return ap
}

func accountPanelUpdate(jaz *app, user string) {

	if jaz.winHome != nil {
		if jaz.apHome != nil {
			home := jaz.winHome.ById(jaz.apHome.Id())
			jaz.winHome.Remove(home)
		}
		jaz.apHome = newAccPanel(user)
		if !jaz.winHome.Insert(jaz.apHome, 0) {
			jaz.logf("home win insert accPanel failed")
		}
	}

	if jaz.winAdmin != nil {
		if jaz.apAdmin != nil {
			admin := jaz.winAdmin.ById(jaz.apAdmin.Id())
			jaz.winAdmin.Remove(admin)
		}
		jaz.apAdmin = newAccPanel(user)
		if !jaz.winAdmin.Insert(jaz.apAdmin, 0) {
			jaz.logf("admin win insert accPanel failed")
		}
	}

	if jaz.winLogout != nil {
		if jaz.apLogout != nil {
			logout := jaz.winLogout.ById(jaz.apLogout.Id())
			jaz.winLogout.Remove(logout)
		}
		jaz.apLogout = newAccPanel(user)
		if !jaz.winLogout.Insert(jaz.apLogout, 0) {
			jaz.logf("logout win insert accPanel failed")
		}
	}

}

func accountPanelUpdateEvent(jaz *app, user string, e gwu.Event) {
	accountPanelUpdate(jaz, user)

	if jaz.winHome != nil {
		e.MarkDirty(jaz.winHome)
	}

	if jaz.winAdmin != nil {
		e.MarkDirty(jaz.winAdmin)
	}

	if jaz.winLogout != nil {
		e.MarkDirty(jaz.winLogout)
	}
}

func newWin(jaz *app, path, name string) gwu.Window {
	win := gwu.NewWindow(path, name)
	cssLink := fmt.Sprintf(`<link rel="stylesheet" type="text/css" href="%s">`, jaz.cssPath)
	win.AddHeadHtml(cssLink)
	jaz.logf("window=[%s] attached CSS=[%s]", path, cssLink)
	return win
}

func buildHomeWin(jaz *app, s gwu.Session) {

	winName := fmt.Sprintf("%s home", appName)
	win := newWin(jaz, "home", winName)

	win.Add(jaz.apHome)

	l := gwu.NewLabel(winName)
	l.Style().SetFontWeight(gwu.FontWeightBold).SetFontSize("130%")
	win.Add(l)

	/*
		win.Add(gwu.NewLabel("Click on the button to login:"))
		b := gwu.NewButton("Login")
		b.AddEHandlerFunc(func(e gwu.Event) {
			e.ReloadWin("login")
		}, gwu.ETypeClick)
		win.Add(b)
	*/

	s.AddWin(win)

	jaz.winHome = win
}

func buildLoginWin(jaz *app, s gwu.Session) {

	winName := fmt.Sprintf("%s login", appName)
	win := newWin(jaz, "login", winName)

	win.Style().SetFullSize()
	win.SetAlign(gwu.HACenter, gwu.VAMiddle)

	p := gwu.NewPanel()
	p.SetHAlign(gwu.HACenter)
	p.SetCellPadding(2)

	l := gwu.NewLabel(winName)
	l.Style().SetFontWeight(gwu.FontWeightBold).SetFontSize("150%")
	p.Add(l)
	l = gwu.NewLabel("Login")
	l.Style().SetFontWeight(gwu.FontWeightBold).SetFontSize("130%")
	p.Add(l)
	p.CellFmt(l).Style().SetBorder2(1, gwu.BrdStyleDashed, gwu.ClrNavy)
	l = gwu.NewLabel("FIXME: username must be equal to password")
	l.Style().SetFontSize("80%").SetFontStyle(gwu.FontStyleItalic)
	p.Add(l)

	errL := gwu.NewLabel("")
	errL.Style().SetColor(gwu.ClrRed)
	p.Add(errL)

	table := gwu.NewTable()
	table.SetCellPadding(2)
	table.EnsureSize(2, 2)
	table.Add(gwu.NewLabel("Username:"), 0, 0)
	tb := gwu.NewTextBox("")
	tb.AddSyncOnETypes(gwu.ETypeKeyUp) // synchronize values during editing (while you type in characters)

	tb.Style().SetWidthPx(160)
	table.Add(tb, 0, 1)
	table.Add(gwu.NewLabel("Password:"), 1, 0)
	pb := gwu.NewPasswBox("")
	pb.AddSyncOnETypes(gwu.ETypeKeyUp) // synchronize values during editing (while you type in characters)

	pb.Style().SetWidthPx(160)
	table.Add(pb, 1, 1)
	p.Add(table)
	b := gwu.NewButton("OK")

	p.Add(b)
	l = gwu.NewLabel("")
	p.Add(l)
	p.CellFmt(l).Style().SetHeightPx(200)

	loginHandler := func(e gwu.Event) {

		user := tb.Text()
		pass := pb.Text()
		auth := loginAuth(user, pass)

		//jaz.logf("debug login user=[%s] pass=[%s] result=[%v]", user, pass, auth)

		if auth {

			// Clear username/password fields
			tb.SetText("")
			pb.SetText("")

			// Clear error message
			errL.SetText("")
			e.MarkDirty(errL)

			newSession := e.NewSession()
			newSession.SetAttr("username", user)

			remoteAddr := "(remoteAddr?)"
			if hrr, ok := e.(gwu.HasRequestResponse); ok {
				req := hrr.Request()
				remoteAddr = req.RemoteAddr
			}

			buildPrivateWins(jaz, newSession, remoteAddr)

			accountPanelUpdateEvent(jaz, user, e)

			e.ReloadWin("admin")
		} else {
			//e.SetFocusedComp(tb)
			errL.SetText("Invalid user name or password!")
			e.MarkDirty(errL)
		}
	}

	enterHandler := func(e gwu.Event) {
		if e.Type() == gwu.ETypeKeyPress && e.KeyCode() == gwu.KeyEnter {
			// enter key was pressed
			loginHandler(e)
		}
	}

	tb.AddEHandlerFunc(enterHandler, gwu.ETypeKeyPress)
	pb.AddEHandlerFunc(enterHandler, gwu.ETypeKeyPress)
	b.AddEHandlerFunc(loginHandler, gwu.ETypeClick)

	win.Add(p)
	win.SetFocusedCompId(tb.Id())

	s.AddWin(win)
}

func loginAuth(user, pass string) bool {
	return user == pass // loginAuth: FIXME WRITEME
}

func buildPrivateWins(jaz *app, s gwu.Session, remoteAddr string) {
	user := s.Attr("username").(string)

	buildLogoutWin(jaz, s, user, remoteAddr)
	buildAdminWin(jaz, s, user, remoteAddr)
}

func buildLogoutWin(jaz *app, s gwu.Session, user, remoteAddr string) {
	winName := fmt.Sprintf("%s logout", appName)
	winHeader := fmt.Sprintf("%s - user=%s - address=%s", winName, user, remoteAddr)

	win := newWin(jaz, "logout", winName)

	win.Style().SetFullWidth()
	win.SetCellPadding(2)

	win.Add(jaz.apLogout)

	title := gwu.NewLabel(winHeader)
	win.Add(title)

	p := gwu.NewPanel()
	p.SetCellPadding(2)

	logoutButton := gwu.NewButton("Logout")

	p.Add(logoutButton)

	win.Add(p)
	s.AddWin(win)

	jaz.winLogout = win
}

func buildAdminWin(jaz *app, s gwu.Session, user, remoteAddr string) {
	winName := fmt.Sprintf("%s admin", appName)
	winHeader := fmt.Sprintf("%s - user=%s - address=%s", winName, user, remoteAddr)

	win := newWin(jaz, "admin", winName)

	win.Style().SetFullWidth()
	win.SetCellPadding(2)

	win.Add(jaz.apAdmin)

	title := gwu.NewLabel(winHeader)
	win.Add(title)

	win.Add(gwu.NewLabel("click on this window to see updates"))

	win.AddEHandlerFunc(func(e gwu.Event) {

		if hrr, ok := e.(gwu.HasRequestResponse); ok {
			req := hrr.Request()
			remoteAddr = req.RemoteAddr
		}

		win.Add(gwu.NewLabel(fmt.Sprintf("click - addr=%v", remoteAddr)))
		e.MarkDirty(win)
	}, gwu.ETypeClick)

	s.AddWin(win)

	jaz.winAdmin = win
}
<|endoftext|>


<commit_before>package markdown

import (
	"bytes"
	"io/ioutil"
	"text/template"

	"github.com/mholt/caddy/caddyhttp/httpserver"
	"github.com/mholt/caddy/caddyhttp/markdown/metadata"
)

// Data represents a markdown document.
type Data struct {
	httpserver.Context
	Doc     map[string]interface{}
	Styles  []string
	Scripts []string
	Meta    map[string]string
	Files   []FileInfo
}

// Include "overrides" the embedded httpserver.Context's Include()
// method so that included files have access to d's fields.
// Note: using {{template 'template-name' .}} instead might be better.
func (d Data) Include(filename string) (string, error) {
	return httpserver.ContextInclude(filename, d, d.Root)
}

// execTemplate executes a template given a requestPath, template, and metadata
func execTemplate(c *Config, mdata metadata.Metadata, meta map[string]string, files []FileInfo, ctx httpserver.Context) ([]byte, error) {
	mdData := Data{
		Context: ctx,
		Doc:     mdata.Variables,
		Styles:  c.Styles,
		Scripts: c.Scripts,
		Meta:    meta,
		Files:   files,
	}

	b := new(bytes.Buffer)
	if err := c.Template.ExecuteTemplate(b, mdata.Template, mdData); err != nil {
		return nil, err
	}

	return b.Bytes(), nil
}

// SetTemplate reads in the template with the filename provided. If the file does not exist or is not parsable, it will return an error.
func SetTemplate(t *template.Template, name, filename string) error {

	// Read template
	buf, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}

	// Update if exists
	if tt := t.Lookup(name); tt != nil {
		_, err = tt.Parse(string(buf))
		return err
	}

	// Allocate new name if not
	_, err = t.New(name).Parse(string(buf))
	return err
}

// GetDefaultTemplate returns the default template.
func GetDefaultTemplate() *template.Template {
	return template.Must(template.New("").Parse(defaultTemplate))
}

const (
	defaultTemplate = `<!DOCTYPE html>
<html>
	<head>
		<title>{{.Doc.title}}</title>
		<meta charset="utf-8">
		{{range $key, $val := .Meta}}
		<meta name="{{$key}}" content="{{$val}}">
		{{end}}
		{{- range .Styles}}
		<link rel="stylesheet" href="{{.}}">
		{{- end}}
		{{- range .Scripts}}
		<script src="{{.}}"></script>
		{{- end}}
	</head>
	<body>
		{{.Doc.body}}
	</body>
</html>`
)
<commit_msg>markdown: Support Include arguments for Markdown. (#1653)<commit_after>package markdown

import (
	"bytes"
	"io/ioutil"
	"text/template"

	"github.com/mholt/caddy/caddyhttp/httpserver"
	"github.com/mholt/caddy/caddyhttp/markdown/metadata"
)

// Data represents a markdown document.
type Data struct {
	httpserver.Context
	Doc     map[string]interface{}
	Styles  []string
	Scripts []string
	Meta    map[string]string
	Files   []FileInfo
}

// Include "overrides" the embedded httpserver.Context's Include()
// method so that included files have access to d's fields.
// Note: using {{template 'template-name' .}} instead might be better.
func (d Data) Include(filename string, args ...interface{}) (string, error) {
	d.Args = args
	return httpserver.ContextInclude(filename, d, d.Root)
}

// execTemplate executes a template given a requestPath, template, and metadata
func execTemplate(c *Config, mdata metadata.Metadata, meta map[string]string, files []FileInfo, ctx httpserver.Context) ([]byte, error) {
	mdData := Data{
		Context: ctx,
		Doc:     mdata.Variables,
		Styles:  c.Styles,
		Scripts: c.Scripts,
		Meta:    meta,
		Files:   files,
	}

	b := new(bytes.Buffer)
	if err := c.Template.ExecuteTemplate(b, mdata.Template, mdData); err != nil {
		return nil, err
	}

	return b.Bytes(), nil
}

// SetTemplate reads in the template with the filename provided. If the file does not exist or is not parsable, it will return an error.
func SetTemplate(t *template.Template, name, filename string) error {

	// Read template
	buf, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}

	// Update if exists
	if tt := t.Lookup(name); tt != nil {
		_, err = tt.Parse(string(buf))
		return err
	}

	// Allocate new name if not
	_, err = t.New(name).Parse(string(buf))
	return err
}

// GetDefaultTemplate returns the default template.
func GetDefaultTemplate() *template.Template {
	return template.Must(template.New("").Parse(defaultTemplate))
}

const (
	defaultTemplate = `<!DOCTYPE html>
<html>
	<head>
		<title>{{.Doc.title}}</title>
		<meta charset="utf-8">
		{{range $key, $val := .Meta}}
		<meta name="{{$key}}" content="{{$val}}">
		{{end}}
		{{- range .Styles}}
		<link rel="stylesheet" href="{{.}}">
		{{- end}}
		{{- range .Scripts}}
		<script src="{{.}}"></script>
		{{- end}}
	</head>
	<body>
		{{.Doc.body}}
	</body>
</html>`
)
<|endoftext|>


<commit_before>// Library for working with webcams and other video capturing devices.
// It depends entirely on v4l2 framework, thus will compile and work
// only on Linux machine
package webcam

import (
	"errors"
	"golang.org/x/sys/unix"
	"os"
	"reflect"
	"unsafe"
)

// Webcam object
type Webcam struct {
	file    *os.File
	fd      uintptr
	buffers [][]byte
}

// Open a webcam with a given path
// Checks if device is a v4l2 device and if it is
// capable to stream video
func Open(path string) (*Webcam, error) {

	file, err := os.OpenFile(path, unix.O_RDWR|unix.O_NONBLOCK, 0666)
	fd := file.Fd()

	if fd < 0 || err != nil {
		return nil, err
	}

	supportsVideoCapture, supportsVideoStreaming, err := checkCapabilities(fd)

	if err != nil {
		return nil, err
	}

	if !supportsVideoCapture {
		return nil, errors.New("Not a video capture device")
	}

	if !supportsVideoStreaming {
		return nil, errors.New("Device does not support the streaming I/O method")
	}

	w := new(Webcam)
	w.fd = fd
	w.file = file
	return w, nil
}

// Returns image formats supported by the device alongside with
// their text description
// Not that this function is somewhat experimental. Frames are not ordered in
// any meaning, also duplicates can occur so it's up to developer to clean it up.
// See http://linuxtv.org/downloads/v4l-dvb-apis/vidioc-enum-framesizes.html
// for more information
func (w *Webcam) GetSupportedFormats() map[PixelFormat]string {

	result := make(map[PixelFormat]string)
	var err error
	var code uint32
	var desc string
	var index uint32

	for index = 0; err == nil; index++ {
		code, desc, err = getPixelFormat(w.fd, index)

		if err != nil {
			break
		}

		result[PixelFormat(code)] = desc
	}

	return result
}

// Returns supported frame sizes for a given image format
func (w *Webcam) GetSupportedFrameSizes(f PixelFormat) []FrameSize {
	result := make([]FrameSize, 0)

	var index uint32
	var err error

	for index = 0; err == nil; index++ {
		s, err := getFrameSize(w.fd, index, uint32(f))

		if err != nil {
			break
		}

		result = append(result, s)
	}

	return result
}

// Sets desired image format and frame size
// Note, that device driver can change that values.
// Resulting values are returned by a function
// alongside with an error if any
func (w *Webcam) SetImageFormat(f PixelFormat, width, height uint32) (PixelFormat, uint32, uint32, error) {

	code := uint32(f)
	cw := width
	ch := height

	err := setImageFormat(w.fd, &code, &width, &height)

	if err != nil {
		return 0, 0, 0, err
	} else {
		return PixelFormat(code), cw, ch, nil
	}
}

// Start streaming process
func (w *Webcam) StartStreaming() error {

	var buf_count uint32 = 256

	err := mmapRequestBuffers(w.fd, &buf_count)

	if err != nil {
		return errors.New("Failed to map request buffers: " + string(err.Error()))
	}

	if buf_count < 2 {
		return errors.New("Insufficient buffer memory")
	}

	w.buffers = make([][]byte, buf_count, buf_count)
	for index, _ := range w.buffers {
		var length uint32

		buffer, err := mmapQueryBuffer(w.fd, uint32(index), &length)

		if err != nil {
			return errors.New("Failed to map memory: " + string(err.Error()))
		}

		w.buffers[index] = buffer
	}

	for index, _ := range w.buffers {

		err := mmapEnqueueBuffer(w.fd, uint32(index))

		if err != nil {
			return errors.New("Failed to enqueue buffer: " + string(err.Error()))
		}

	}

	err = startStreaming(w.fd)

	if err != nil {
		return errors.New("Failed to start streaming: " + string(err.Error()))
	}

	return nil
}

// Read a single frame from the webcam
// If frame cannot be read at the moment
// function will return empty slice
func (w *Webcam) ReadFrame() ([]byte, error) {
	var index uint32
	var length uint32

	err := mmapDequeueBuffer(w.fd, &index, &length)

	if err != nil {
		return nil, err
	}

	result := w.buffers[int(index)][:length]

	err = mmapEnqueueBuffer(w.fd, index)

	return result, err

}

// Wait until frame could be read
func (w *Webcam) WaitForFrame(timeout uint32) error {

	count, err := waitForFrame(w.fd, timeout)

	if count < 0 || err != nil {
		return err
	} else if count == 0 {
		return new(Timeout)
	} else {
		return nil
	}
}

func (w *Webcam) StopStreaming() error {
	for _, buffer := range w.buffers {
		err := mmapReleaseBuffer(buffer)
		if err != nil {
			return err
		}
	}

	return stopStreaming(w.fd)
}

// Close the device
func (w *Webcam) Close() error {
	for _, buffer := range w.buffers {
		err := mmapReleaseBuffer(buffer)
		if err != nil {
			return err
		}
	}

	err := w.file.Close()

	return err
}

// Sets automatic white balance correction
func (w *Webcam) SetAutoWhiteBalance(val bool) error {
	v := int32(0)
	if val {
		v = 1
	}
	return setControl(w.fd, V4L2_CID_AUTO_WHITE_BALANCE, v)
}

func gobytes(p unsafe.Pointer, n int) []byte {

	h := reflect.SliceHeader{uintptr(p), n, n}
	s := *(*[]byte)(unsafe.Pointer(&h))

	return s
}
<commit_msg>Replace os.OpenFile with unix.Open to avoid blocking write operations (#15)<commit_after>// Library for working with webcams and other video capturing devices.
// It depends entirely on v4l2 framework, thus will compile and work
// only on Linux machine
package webcam

import (
	"errors"
	"golang.org/x/sys/unix"
	"reflect"
	"unsafe"
)

// Webcam object
type Webcam struct {
	fd      uintptr
	buffers [][]byte
}

// Open a webcam with a given path
// Checks if device is a v4l2 device and if it is
// capable to stream video
func Open(path string) (*Webcam, error) {

	handle, err := unix.Open(path, unix.O_RDWR|unix.O_NONBLOCK, 0666)
	fd := uintptr(handle)

	if fd < 0 || err != nil {
		return nil, err
	}

	supportsVideoCapture, supportsVideoStreaming, err := checkCapabilities(fd)

	if err != nil {
		return nil, err
	}

	if !supportsVideoCapture {
		return nil, errors.New("Not a video capture device")
	}

	if !supportsVideoStreaming {
		return nil, errors.New("Device does not support the streaming I/O method")
	}

	w := new(Webcam)
	w.fd = uintptr(fd)
	return w, nil
}

// Returns image formats supported by the device alongside with
// their text description
// Not that this function is somewhat experimental. Frames are not ordered in
// any meaning, also duplicates can occur so it's up to developer to clean it up.
// See http://linuxtv.org/downloads/v4l-dvb-apis/vidioc-enum-framesizes.html
// for more information
func (w *Webcam) GetSupportedFormats() map[PixelFormat]string {

	result := make(map[PixelFormat]string)
	var err error
	var code uint32
	var desc string
	var index uint32

	for index = 0; err == nil; index++ {
		code, desc, err = getPixelFormat(w.fd, index)

		if err != nil {
			break
		}

		result[PixelFormat(code)] = desc
	}

	return result
}

// Returns supported frame sizes for a given image format
func (w *Webcam) GetSupportedFrameSizes(f PixelFormat) []FrameSize {
	result := make([]FrameSize, 0)

	var index uint32
	var err error

	for index = 0; err == nil; index++ {
		s, err := getFrameSize(w.fd, index, uint32(f))

		if err != nil {
			break
		}

		result = append(result, s)
	}

	return result
}

// Sets desired image format and frame size
// Note, that device driver can change that values.
// Resulting values are returned by a function
// alongside with an error if any
func (w *Webcam) SetImageFormat(f PixelFormat, width, height uint32) (PixelFormat, uint32, uint32, error) {

	code := uint32(f)
	cw := width
	ch := height

	err := setImageFormat(w.fd, &code, &width, &height)

	if err != nil {
		return 0, 0, 0, err
	} else {
		return PixelFormat(code), cw, ch, nil
	}
}

// Start streaming process
func (w *Webcam) StartStreaming() error {

	var buf_count uint32 = 256

	err := mmapRequestBuffers(w.fd, &buf_count)

	if err != nil {
		return errors.New("Failed to map request buffers: " + string(err.Error()))
	}

	if buf_count < 2 {
		return errors.New("Insufficient buffer memory")
	}

	w.buffers = make([][]byte, buf_count, buf_count)
	for index, _ := range w.buffers {
		var length uint32

		buffer, err := mmapQueryBuffer(w.fd, uint32(index), &length)

		if err != nil {
			return errors.New("Failed to map memory: " + string(err.Error()))
		}

		w.buffers[index] = buffer
	}

	for index, _ := range w.buffers {

		err := mmapEnqueueBuffer(w.fd, uint32(index))

		if err != nil {
			return errors.New("Failed to enqueue buffer: " + string(err.Error()))
		}

	}

	err = startStreaming(w.fd)

	if err != nil {
		return errors.New("Failed to start streaming: " + string(err.Error()))
	}

	return nil
}

// Read a single frame from the webcam
// If frame cannot be read at the moment
// function will return empty slice
func (w *Webcam) ReadFrame() ([]byte, error) {
	var index uint32
	var length uint32

	err := mmapDequeueBuffer(w.fd, &index, &length)

	if err != nil {
		return nil, err
	}

	result := w.buffers[int(index)][:length]

	err = mmapEnqueueBuffer(w.fd, index)

	return result, err

}

// Wait until frame could be read
func (w *Webcam) WaitForFrame(timeout uint32) error {

	count, err := waitForFrame(w.fd, timeout)

	if count < 0 || err != nil {
		return err
	} else if count == 0 {
		return new(Timeout)
	} else {
		return nil
	}
}

func (w *Webcam) StopStreaming() error {
	for _, buffer := range w.buffers {
		err := mmapReleaseBuffer(buffer)
		if err != nil {
			return err
		}
	}

	return stopStreaming(w.fd)
}

// Close the device
func (w *Webcam) Close() error {
	for _, buffer := range w.buffers {
		err := mmapReleaseBuffer(buffer)
		if err != nil {
			return err
		}
	}

	err := unix.Close(int(w.fd))

	return err
}

// Sets automatic white balance correction
func (w *Webcam) SetAutoWhiteBalance(val bool) error {
	v := int32(0)
	if val {
		v = 1
	}
	return setControl(w.fd, V4L2_CID_AUTO_WHITE_BALANCE, v)
}

func gobytes(p unsafe.Pointer, n int) []byte {

	h := reflect.SliceHeader{uintptr(p), n, n}
	s := *(*[]byte)(unsafe.Pointer(&h))

	return s
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/go-martini/martini"
	"github.com/johnernaut/webhog/webhog"
	"github.com/martini-contrib/binding"
	"github.com/martini-contrib/render"
	"net/http"
	"runtime"
)

type Url struct {
	Url  string `json:"url"`
	UUID string `json:"uuid"`
}

func main() {
	// All the parallelism are belong to us!
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Load configuration file.
	webhog.LoadConfig()

	// Load DB instance.
	webhog.LoadDB()

	// Start the server.
	m := martini.Classic()

	m.Use(render.Renderer())

	// Middleware to make sure each request has a specified API key
	m.Use(func(res http.ResponseWriter, req *http.Request, r render.Render) {
		if req.Header.Get("X-API-KEY") != webhog.Config.ApiKey {
			r.JSON(401, map[string]interface{}{"error": "Invalid API key."})
		}
	})

	m.Post("/scrape", binding.Json(Url{}), func(url Url, r render.Render) {
		entity, err := webhog.NewScraper(url.Url)
		if err != nil {
			r.JSON(400, map[string]interface{}{"errors": err.Error()})
		} else {
			r.JSON(200, entity)
		}
	})

	m.Run()
}
<commit_msg>add GET path to retrieve persisted entities<commit_after>package main

import (
	"github.com/go-martini/martini"
	"github.com/johnernaut/webhog/webhog"
	"github.com/martini-contrib/binding"
	"github.com/martini-contrib/render"
	"labix.org/v2/mgo/bson"
	"net/http"
	"runtime"
)

type Url struct {
	Url  string `json:"url"`
	UUID string `json:"uuid"`
}

func main() {
	// All the parallelism are belong to us!
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Load configuration file.
	webhog.LoadConfig()

	// Load DB instance.
	webhog.LoadDB()

	// Start the server.
	m := martini.Classic()

	m.Use(render.Renderer())

	// Middleware to make sure each request has a specified API key
	m.Use(func(res http.ResponseWriter, req *http.Request, r render.Render) {
		if req.Header.Get("X-API-KEY") != webhog.Config.ApiKey {
			r.JSON(401, map[string]interface{}{"error": "Invalid API key."})
		}
	})

	m.Post("/scrape", binding.Json(Url{}), func(url Url, r render.Render) {
		entity, err := webhog.NewScraper(url.Url)
		if err != nil {
			r.JSON(400, map[string]interface{}{"errors": err.Error()})
		} else {
			r.JSON(200, entity)
		}
	})

	m.Get("/entity/:uuid", func(params martini.Params, r render.Render) {
		entity := new(webhog.Entity)
		err := entity.Find(bson.M{"uuid": params["uuid"]})

		if err != nil {
			r.JSON(400, map[string]interface{}{"errors": "Entity not found."})
		} else {
			r.JSON(200, entity)
		}
	})

	m.Run()
}
<|endoftext|>


<commit_before>package helm

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

const (
	get     = "GET"
	head    = "HEAD"
	post    = "POST"
	put     = "PUT"
	patch   = "PATCH"
	deleteh = "DELETE"
)

// Handle is just like "net/http" Handlers, only takes params.
type Handle func(http.ResponseWriter, *http.Request, url.Values)

// Middleware is just like the Handle type, but has a boolean return. True
// means to keep processing the rest of the middleware chain, false means end.
// If you return false to end the request-response cycle you MUST
// write something back to the client, otherwise it will be left hanging.
type Middleware func(http.ResponseWriter, *http.Request, url.Values) bool

// Router name says it all.
type Router struct {
	tree           *node
	rootHandler    Handle
	middleware     []Middleware
	l              *log.Logger
	LoggingEnabled bool
}

type Param struct {
	Name     string
	Required bool
}

// New creates a new router. Take the root/fall through route
// like how the default mux works. Only difference is in this case,
// you have to specific one.
func New(rootHandler Handle) *Router {
	node := node{component: "/", isNamedParam: false, methods: make(map[string]*route)}
	return &Router{tree: &node, rootHandler: rootHandler}
}

// EnableLogging sets logging to supplied writer.
func (r *Router) EnableLogging(w io.Writer) {
	r.l = log.New(w, "[helm] ", 0)
	r.LoggingEnabled = true
}

// Handle takes an http handler, method and pattern for a route.
func (r *Router) Handle(method, path string, handler Handle, middleware ...Middleware) {
	if path[0] != '/' {
		panic("Path has to start with a /.")
	}
	r.tree.addNode(method, path, handler, middleware...)
}

// GET same as Handle only the method is already implied.
func (r *Router) GET(path string, handler Handle, middleware ...Middleware) {
	r.Handle(get, path, handler, middleware...)
}

// HEAD same as Handle only the method is already implied.
func (r *Router) HEAD(path string, handler Handle, middleware ...Middleware) {
	r.Handle(head, path, handler, middleware...)
}

// POST same as Handle only the method is already implied.
func (r *Router) POST(path string, handler Handle, middleware ...Middleware) {
	r.Handle(post, path, handler, middleware...)
}

// PUT same as Handle only the method is already implied.
func (r *Router) PUT(path string, handler Handle, middleware ...Middleware) {
	r.Handle(put, path, handler, middleware...)
}

// PATCH same as Handle only the method is already implied.
func (r *Router) PATCH(path string, handler Handle, middleware ...Middleware) { // might make this and put one.
	r.Handle(patch, path, handler, middleware...)
}

// DELETE same as Handle only the method is already implied.
func (r *Router) DELETE(path string, handler Handle, middleware ...Middleware) {
	r.Handle(deleteh, path, handler, middleware...)
}

// Use adds middleware to all of the routes.
func (r *Router) Use(middleware ...Middleware) {
	r.middleware = append(r.middleware, middleware...)
}

// Run is a simple wrapper around http.ListenAndServe.
func (r *Router) Run(address string) {
	if r.LoggingEnabled {
		r.l.Println("Running on", address)
	}
	http.ListenAndServe(address, r)
}

// runMiddleware loops over the slice of middleware and call to each of the middleware handlers.
func runMiddleware(w http.ResponseWriter, req *http.Request, params url.Values, middleware ...Middleware) bool {
	for _, m := range middleware {
		if !m(w, req, params) {
			return false // the middleware returned false, so end processing the chain.
		}
	}
	return true
}

// Needed by "net/http" to handle http requests and be a mux to http.ListenAndServe.
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	defer clear(req)
	cw := w
	if r.LoggingEnabled {
		r.l.Printf("Started %s %s", req.Method, req.URL.Path)
		cw = &responseWriter{w, 200}
		start := time.Now()
		defer func(time.Time) {
			status := cw.(*responseWriter).status
			r.l.Printf("Completed %d %s in %v", status, http.StatusText(status), time.Since(start))
		}(start)
	}

	req.ParseMultipartForm(10 * 1024 * 1024) // 10MB. Should probably make this configurable...
	params := req.Form
	if !runMiddleware(cw, req, params, r.middleware...) {
		return // end the chain.
	}
	node, _ := r.tree.traverse(strings.Split(req.URL.Path, "/")[1:], params)
	if handler := node.methods[req.Method]; handler != nil {
		if !runMiddleware(cw, req, params, handler.middleware...) {
			return
		}
		handler.handler(cw, req, params)
	} else {
		r.rootHandler(cw, req, params)
	}
}

// ValidateParams is used for validating and sanizating params. Since HTTP params can have
// same name for multiple params, if this happens it will just use the first one.
func ValidateParams(params url.Values, desiredParams []Param) (map[string]string, error) {
	paramValues := make(map[string]string)
	for _, param := range desiredParams {
		p, ok := params[param.Name]
		if !ok && param.Required && p[0] != "" {
			return nil, errors.New(fmt.Sprintf("Required parameter (%s) not valid", param.Name))
		} else if ok {
			paramValues[param.Name] = p[0]
		}
	}
	return paramValues, nil
}
<commit_msg>Improving the logic.<commit_after>package helm

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

const (
	get     = "GET"
	head    = "HEAD"
	post    = "POST"
	put     = "PUT"
	patch   = "PATCH"
	deleteh = "DELETE"
)

// Handle is just like "net/http" Handlers, only takes params.
type Handle func(http.ResponseWriter, *http.Request, url.Values)

// Middleware is just like the Handle type, but has a boolean return. True
// means to keep processing the rest of the middleware chain, false means end.
// If you return false to end the request-response cycle you MUST
// write something back to the client, otherwise it will be left hanging.
type Middleware func(http.ResponseWriter, *http.Request, url.Values) bool

// Router name says it all.
type Router struct {
	tree           *node
	rootHandler    Handle
	middleware     []Middleware
	l              *log.Logger
	LoggingEnabled bool
}

type Param struct {
	Name     string
	Required bool
}

// New creates a new router. Take the root/fall through route
// like how the default mux works. Only difference is in this case,
// you have to specific one.
func New(rootHandler Handle) *Router {
	node := node{component: "/", isNamedParam: false, methods: make(map[string]*route)}
	return &Router{tree: &node, rootHandler: rootHandler}
}

// EnableLogging sets logging to supplied writer.
func (r *Router) EnableLogging(w io.Writer) {
	r.l = log.New(w, "[helm] ", 0)
	r.LoggingEnabled = true
}

// Handle takes an http handler, method and pattern for a route.
func (r *Router) Handle(method, path string, handler Handle, middleware ...Middleware) {
	if path[0] != '/' {
		panic("Path has to start with a /.")
	}
	r.tree.addNode(method, path, handler, middleware...)
}

// GET same as Handle only the method is already implied.
func (r *Router) GET(path string, handler Handle, middleware ...Middleware) {
	r.Handle(get, path, handler, middleware...)
}

// HEAD same as Handle only the method is already implied.
func (r *Router) HEAD(path string, handler Handle, middleware ...Middleware) {
	r.Handle(head, path, handler, middleware...)
}

// POST same as Handle only the method is already implied.
func (r *Router) POST(path string, handler Handle, middleware ...Middleware) {
	r.Handle(post, path, handler, middleware...)
}

// PUT same as Handle only the method is already implied.
func (r *Router) PUT(path string, handler Handle, middleware ...Middleware) {
	r.Handle(put, path, handler, middleware...)
}

// PATCH same as Handle only the method is already implied.
func (r *Router) PATCH(path string, handler Handle, middleware ...Middleware) { // might make this and put one.
	r.Handle(patch, path, handler, middleware...)
}

// DELETE same as Handle only the method is already implied.
func (r *Router) DELETE(path string, handler Handle, middleware ...Middleware) {
	r.Handle(deleteh, path, handler, middleware...)
}

// Use adds middleware to all of the routes.
func (r *Router) Use(middleware ...Middleware) {
	r.middleware = append(r.middleware, middleware...)
}

// Run is a simple wrapper around http.ListenAndServe.
func (r *Router) Run(address string) {
	if r.LoggingEnabled {
		r.l.Println("Running on", address)
	}
	http.ListenAndServe(address, r)
}

// runMiddleware loops over the slice of middleware and call to each of the middleware handlers.
func runMiddleware(w http.ResponseWriter, req *http.Request, params url.Values, middleware ...Middleware) bool {
	for _, m := range middleware {
		if !m(w, req, params) {
			return false // the middleware returned false, so end processing the chain.
		}
	}
	return true
}

// Needed by "net/http" to handle http requests and be a mux to http.ListenAndServe.
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	defer clear(req)
	cw := w
	if r.LoggingEnabled {
		r.l.Printf("Started %s %s", req.Method, req.URL.Path)
		cw = &responseWriter{w, 200}
		start := time.Now()
		defer func(time.Time) {
			status := cw.(*responseWriter).status
			r.l.Printf("Completed %d %s in %v", status, http.StatusText(status), time.Since(start))
		}(start)
	}

	req.ParseMultipartForm(10 * 1024 * 1024) // 10MB. Should probably make this configurable...
	params := req.Form
	if !runMiddleware(cw, req, params, r.middleware...) {
		return // end the chain.
	}
	node, _ := r.tree.traverse(strings.Split(req.URL.Path, "/")[1:], params)
	if handler := node.methods[req.Method]; handler != nil {
		if !runMiddleware(cw, req, params, handler.middleware...) {
			return
		}
		handler.handler(cw, req, params)
	} else {
		r.rootHandler(cw, req, params)
	}
}

// ValidateParams is used for validating and sanizating params. Since HTTP params can have
// same name for multiple params, if this happens it will just use the first one.
func ValidateParams(params url.Values, desiredParams []Param) (map[string]string, error) {
	paramValues := make(map[string]string)
	for _, param := range desiredParams {
		p, ok := params[param.Name]
		if !ok && param.Required || p[0] == "" && param.Required {
			return nil, errors.New(fmt.Sprintf("Required parameter (%s) not valid", param.Name))
		} else if ok && p[0] != "" {
			paramValues[param.Name] = p[0]
		}
	}
	return paramValues, nil
}
<|endoftext|>


<commit_before>/**
 * This file is for providing to get web page from weblio.jp
 */

package main

import (
	"fmt"
	"strings"

	"github.com/PuerkitoBio/goquery"
	"github.com/fatih/color"
)

// getWeblioDict function prints dictionary in weblio.jp.
// Top of discription block and wikipedia-jp discription will be print.
func getWeblioDict(word string) {
	var str string
	yellow := color.New(color.Bold, color.FgYellow).SprintFunc()

	// get page from weblio.jp
	url := "http://www.weblio.jp/content/" + word
	doc, _ := goquery.NewDocument(url)

	// trim elemets
	doc.Find(".NetDicHead .midashigo > span").Empty()

	// print Midashigo
	str = doc.Find(".NetDicHead .midashigo").Text()
	if str != "" {
		fmt.Println(yellow(str))
	} else {
		str = word
		fmt.Println(yellow(str))
	}

	// print dictionary bodies
	doc.Find("#cont .kiji .NetDicBody > div > div > div > div").Each(func(_ int, s *goquery.Selection) {
		str = strings.TrimSpace(s.Text())
		if str != "" {
			fmt.Println(str)
		}
	})
	// print Wikipedia-ja text
	str = strings.TrimSpace(doc.Find(".kiji .Wkpja .WkpjaTs").Next().Text())
	if str != "" {
		fmt.Println(str)
	}
}

// getWeblioEijiDict function prints dictionary in ejje.weblio.jp.
// summary and example writing will be print.
func getWeblioEijiDict(word string) {
	var str string
	green := color.New(color.Bold, color.FgGreen).SprintFunc()
	yellow := color.New(color.FgYellow).SprintFunc()
	bold := color.New(color.Bold).SprintFunc()

	// get page from ejje.weblio.jp
	url := "http://ejje.weblio.jp/content/" + word
	doc, _ := goquery.NewDocument(url)

	// print query
	str = doc.Find("#h1Query").Text()
	if str != "" {
		fmt.Println(green(str))
	} else {
		str = word
		fmt.Println(green(str))
	}

	// print summary
	summary := doc.Find(".summaryM table tbody tr td.content-explanation").Text()
	fmt.Println(summary)

	// print example documents
	fmt.Print(bold("\n[Examples]\n"))
	doc.Find(".qotC").Each(func(_ int, s *goquery.Selection) {
		s.Find(".qotCE > span").Empty()
		s.Find(".qotCJE > span").Empty()
		s.Find(".qotCJJ > span").Empty()
		exampleHead := s.Find(".qotCE").Text()
		exampleTail := s.Find(".qotCJ").Text()
		if exampleHead == "" {
			exampleHead = s.Find(".qotCJE").Text()
			exampleTail = s.Find(".qotCJJ").Text()
		}
		if exampleHead != "" {
			fmt.Println(yellow(exampleHead))
			fmt.Println(exampleTail)
		}
	})

	// print more link
	moreExample, _ := doc.Find(".hlt_SNTCE .kiji > a").Attr("href")
	ul := color.New(color.Underline).SprintFunc()
	fmt.Println("\n", ul(moreExample))
	fmt.Println("")
}
<commit_msg>add small error handling codes.<commit_after>/**
 * This file is for providing to get web page from weblio.jp
 */

package main

import (
	"fmt"
	"log"
	"strings"

	"github.com/PuerkitoBio/goquery"
	"github.com/fatih/color"
)

// getWeblioDict function prints dictionary in weblio.jp.
// Top of discription block and wikipedia-jp discription will be print.
func getWeblioDict(word string) {
	var str string
	yellow := color.New(color.Bold, color.FgYellow).SprintFunc()

	// get page from weblio.jp
	url := "http://www.weblio.jp/content/" + word
	doc, err := goquery.NewDocument(url)

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

	// trim elemets
	doc.Find(".NetDicHead .midashigo > span").Empty()

	// print midashigo
	str = doc.Find(".NetDicHead .midashigo").Text()
	if str != "" {
		fmt.Println(yellow(str))
	} else {
		str = word
		fmt.Println(yellow(str))
	}

	// print dictionary bodies
	doc.Find("#cont .kiji .NetDicBody > div > div > div > div").Each(func(_ int, s *goquery.Selection) {
		str = strings.TrimSpace(s.Text())
		if str != "" {
			fmt.Println(str)
		}
	})
	// print Wikipedia-ja text
	str = strings.TrimSpace(doc.Find(".kiji .Wkpja .WkpjaTs").Next().Text())
	if str != "" {
		fmt.Println(str)
	}
}

// getWeblioEijiDict function prints dictionary in ejje.weblio.jp.
// summary and example writing will be print.
func getWeblioEijiDict(word string) {
	var str string
	green := color.New(color.Bold, color.FgGreen).SprintFunc()
	yellow := color.New(color.FgYellow).SprintFunc()
	bold := color.New(color.Bold).SprintFunc()

	// get page from ejje.weblio.jp
	url := "http://ejje.weblio.jp/content/" + word
	doc, _ := goquery.NewDocument(url)

	// print query
	str = doc.Find("#h1Query").Text()
	if str != "" {
		fmt.Println(green(str))
	} else {
		str = word
		fmt.Println(green(str))
	}

	// print summary
	summary := doc.Find(".summaryM table tbody tr td.content-explanation").Text()
	fmt.Println(summary)

	// print example documents
	fmt.Print(bold("\n[Examples]\n"))
	doc.Find(".qotC").Each(func(_ int, s *goquery.Selection) {
		s.Find(".qotCE > span").Empty()
		s.Find(".qotCJE > span").Empty()
		s.Find(".qotCJJ > span").Empty()
		exampleHead := s.Find(".qotCE").Text()
		exampleTail := s.Find(".qotCJ").Text()
		if exampleHead == "" {
			exampleHead = s.Find(".qotCJE").Text()
			exampleTail = s.Find(".qotCJJ").Text()
		}
		if exampleHead != "" {
			fmt.Println(yellow(exampleHead))
			fmt.Println(exampleTail)
		}
	})

	// print more link
	moreExample, _ := doc.Find(".hlt_SNTCE .kiji > a").Attr("href")
	ul := color.New(color.Underline).SprintFunc()
	fmt.Println("\n", ul(moreExample))
	fmt.Println("")
}
<|endoftext|>


<commit_before>package zaiuz

import "net/http"
import "github.com/gorilla/mux"

// Router is a wrapper over Gorrila web toolkit's mux router
// (http://www.gorillatoolkit.org/pkg/mux) that provides helpers that work with standard
// zaiuz Action function signature as well as Filters.
type Router struct {
	parent  *Router
	router  *mux.Router
	filters []Filter
}

var _ http.Handler = &Router{}

func NewRouter() *Router {
	filters := make([]Filter, 0, InitialContextCapacity)
	return &Router{nil, mux.NewRouter(), filters}
}

// Parent() method returns the parent router if this is a child router, or nil otherwise.
func (router *Router) Parent() *Router {
	return router.parent
}

// Router() method returns the internal mux.Router from gorilla web toolkit for direct
// access. This method is not recommended unless you want to access specifici
// functionality provided by the gorilla web toolkit that does not yet have an equivalent
// in zaiuz.
func (router *Router) Router() *mux.Router {
	return router.router
}

// Retreive all modules included into this router so far. Also resolve parent's list of
// modules if called from a subrouter.
func (router *Router) Filters() []Filter {
	if router.parent == nil {
		return router.filters
	} else {
		return append(router.parent.filters, router.filters...)
	}
}

// Creates a child router. Analogous to calling mux's Router.Subrouter function but also
// carry over all the Filters included so far as well. Filters added in the subrouter only
// run inside the subrouter.
func (router *Router) Subrouter(path string) *Router {
	var subrouter *mux.Router
	if path == "" {
		// PathPrefix with empty string causes routing to not match so we need to sepcial case
		// here.
		subrouter = router.router.NewRoute().Subrouter()
	} else {
		subrouter = router.router.PathPrefix(path).Subrouter()
	}

	return &Router{router, subrouter, []Filter{}}
}

func (router *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	router.router.ServeHTTP(w, r)
}

// Include a Filter in the current router for all mapped (and future) actions.
func (router *Router) Include(filters ...Filter) {
	router.filters = append(router.filters, filters...)
}

// Maps an Action to the specified URL Path and HTTP GET method.
func (router *Router) Get(path string, action Action) *Router {
	handler := router.actionShim(action)
	router.router.Path(path).Methods("GET").HandlerFunc(handler)
	return router
}

// Maps an Action to the specified URL Path and HTTP POST method.
func (router *Router) Post(path string, action Action) *Router {
	handler := router.actionShim(action)
	router.router.Path(path).Methods("POST").HandlerFunc(handler)
	return router
}

// Maps an Action to the specified URL Path and HTTP GET _and_ POST method.
func (router *Router) GetPost(path string, action Action) *Router {
	handler := router.actionShim(action)
	router.router.Path(path).Methods("GET", "POST").HandlerFunc(handler)
	return router
}

func (router *Router) Static(urlPath, filePath string) *Router {
	// TODO: Allow action shim to still be applied
	fs := http.StripPrefix(urlPath, http.FileServer(http.Dir(filePath)))
	router.router.PathPrefix(urlPath).Methods("GET").Handler(fs)
	return router
}

func (router *Router) actionShim(action Action) func(http.ResponseWriter, *http.Request) {
	// apply innermost filter first
	filters := router.Filters()
	for i := range filters {
		// TODO: Detect nil
		action = filters[len(filters)-1-i](action)
	}

	return func(w http.ResponseWriter, r *http.Request) {
		context := NewContext(w, r)

		vars := mux.Vars(r)
		for key, value := range vars {
			context.Set(key, value)
		}

		result := action(context)
		result.Render(context)
	}
}
<commit_msg>Panic on result rendering error.<commit_after>package zaiuz

import "net/http"
import "github.com/gorilla/mux"

// Router is a wrapper over Gorrila web toolkit's mux router
// (http://www.gorillatoolkit.org/pkg/mux) that provides helpers that work with standard
// zaiuz Action function signature as well as Filters.
type Router struct {
	parent  *Router
	router  *mux.Router
	filters []Filter
}

var _ http.Handler = &Router{}

func NewRouter() *Router {
	filters := make([]Filter, 0, InitialContextCapacity)
	return &Router{nil, mux.NewRouter(), filters}
}

// Parent() method returns the parent router if this is a child router, or nil otherwise.
func (router *Router) Parent() *Router {
	return router.parent
}

// Router() method returns the internal mux.Router from gorilla web toolkit for direct
// access. This method is not recommended unless you want to access specifici
// functionality provided by the gorilla web toolkit that does not yet have an equivalent
// in zaiuz.
func (router *Router) Router() *mux.Router {
	return router.router
}

// Retreive all modules included into this router so far. Also resolve parent's list of
// modules if called from a subrouter.
func (router *Router) Filters() []Filter {
	if router.parent == nil {
		return router.filters
	} else {
		return append(router.parent.filters, router.filters...)
	}
}

// Creates a child router. Analogous to calling mux's Router.Subrouter function but also
// carry over all the Filters included so far as well. Filters added in the subrouter only
// run inside the subrouter.
func (router *Router) Subrouter(path string) *Router {
	var subrouter *mux.Router
	if path == "" {
		// PathPrefix with empty string causes routing to not match so we need to sepcial case
		// here.
		subrouter = router.router.NewRoute().Subrouter()
	} else {
		subrouter = router.router.PathPrefix(path).Subrouter()
	}

	return &Router{router, subrouter, []Filter{}}
}

func (router *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	router.router.ServeHTTP(w, r)
}

// Include a Filter in the current router for all mapped (and future) actions.
func (router *Router) Include(filters ...Filter) {
	router.filters = append(router.filters, filters...)
}

// Maps an Action to the specified URL Path and HTTP GET method.
func (router *Router) Get(path string, action Action) *Router {
	handler := router.actionShim(action)
	router.router.Path(path).Methods("GET").HandlerFunc(handler)
	return router
}

// Maps an Action to the specified URL Path and HTTP POST method.
func (router *Router) Post(path string, action Action) *Router {
	handler := router.actionShim(action)
	router.router.Path(path).Methods("POST").HandlerFunc(handler)
	return router
}

// Maps an Action to the specified URL Path and HTTP GET _and_ POST method.
func (router *Router) GetPost(path string, action Action) *Router {
	handler := router.actionShim(action)
	router.router.Path(path).Methods("GET", "POST").HandlerFunc(handler)
	return router
}

func (router *Router) Static(urlPath, filePath string) *Router {
	// TODO: Allow action shim to still be applied
	fs := http.StripPrefix(urlPath, http.FileServer(http.Dir(filePath)))
	router.router.PathPrefix(urlPath).Methods("GET").Handler(fs)
	return router
}

func (router *Router) actionShim(action Action) func(http.ResponseWriter, *http.Request) {
	// apply innermost filter first
	filters := router.Filters()
	for i := range filters {
		// TODO: Detect nil
		action = filters[len(filters)-1-i](action)
	}

	return func(w http.ResponseWriter, r *http.Request) {
		context := NewContext(w, r)

		vars := mux.Vars(r)
		for key, value := range vars {
			context.Set(key, value)
		}

		result := action(context)
		// TODO: panic filter or better gracefully handle?
		e := result.Render(context)
		if e != nil {
			panic(e)
		}
	}
}
<|endoftext|>


<commit_before>package webpay

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	simplejson "github.com/bitly/go-simplejson"
)

type WebPayClient struct {
	header    map[string]string
	options   map[string]string
	authToken string
	Charge    Charge
	Customer  Customer
	Recursion Recursion
	Token     Token
	Event     Event
	Account   Account
	mode      string
}

func NewWebPayClient(auth_token string) WebPayClient {
	cli := WebPayClient{
		authToken: auth_token,
		header: map[string]string{
			"Content-Type":    "application/x-www-form-urlencoded",
			"Accept":          "application/json",
			"User-Agent":      "webpay/2.1.1 golang",
			"Accept-Language": "en",
			"Authorization":   "Bearer " + auth_token,
		},
		options: map[string]string{
			"api_base": "https://api.webpay.jp/v1",
		},
	}

	cli.Charge = NewCharge(&cli)
	cli.Customer = NewCustomer(&cli)
	cli.Recursion = NewRecursion(&cli)
	cli.Token = NewToken(&cli)
	cli.Event = NewEvent(&cli)
	cli.Account = NewAccount(&cli)
	cli.mode = "real"

	return cli
}

func (cli WebPayClient) SetAcceptLanguage(lang string) {
	cli.header["Accept-Language"] = lang
}

func (cli WebPayClient) Post(path string, params url.Values) (*simplejson.Json, error) {
	return cli.Request("POST", path, params)
}
func (cli WebPayClient) Delete(path string, params url.Values) (*simplejson.Json, error) {
	return cli.Request("DELETE", path, params)
}
func (cli WebPayClient) Get(path string, params url.Values) (*simplejson.Json, error) {
	return cli.Request("GET", path, params)
}

func (cli WebPayClient) Request(method, path string, params url.Values) (*simplejson.Json, error) {
	if cli.mode != "real" {
		return cli.returnMockJson(method, path, params)
	}

	client := &http.Client{}

	u := cli.options["api_base"] + "/" + path
	req, _ := http.NewRequest(
		method,
		u,
		strings.NewReader(params.Encode()),
	)
	for k, v := range cli.header {
		req.Header.Add(k, v)
	}
	req.SetBasicAuth(cli.authToken, "")
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}

	body, err := ioutil.ReadAll(resp.Body)
	defer resp.Body.Close()
	if err != nil {
		return nil, err
	}

	// fmt.Println(string(body))

	js, err := simplejson.NewJson(body)
	if err != nil {
		return nil, err
	}

	return js, nil
}

// GetId returns 'id' of the JSON.
func GetId(json *simplejson.Json) (string, error) {
	return json.Get("id").String()
}

// getAllPathWithQuery creates path with query from map args.
func getAllPathWithQuery(path string, args map[string]int) string {
	query := url.Values{}
	if count, exists := args["count"]; exists {
		query.Add("count", strconv.Itoa(count))
	}
	if offset, exists := args["offset"]; exists {
		query.Add("offset", strconv.Itoa(offset))
	}

	if created, exists := args["created"]; exists {
		query.Add("created", strconv.Itoa(created))
	}
	if gt, exists := args["gt"]; exists {
		query.Add("gt", strconv.Itoa(gt))
	}
	if gte, exists := args["gte"]; exists {
		query.Add("gte", strconv.Itoa(gte))
	}
	if lt, exists := args["lt"]; exists {
		query.Add("lt", strconv.Itoa(lt))
	}
	if lte, exists := args["lte"]; exists {
		query.Add("lte", strconv.Itoa(lte))
	}

	return fmt.Sprintf("%s?%s", path, query.Encode())
}

// returnMockJson return JSON which is read from under test_data dir for testing.
func (cli WebPayClient) returnMockJson(method, path string, params url.Values) (*simplejson.Json, error) {
	path = strings.Replace(path, "?", "_", -1)
	path = strings.Replace(path, "=", "_", -1)
	path = strings.Replace(path, "&", "_", -1)
	path = strings.Replace(path, "/", "_", -1)

	if method == "DELETE" {
		path = "delete_" + path
	}

	// 	fmt.Println(path)

	dat, err := ioutil.ReadFile("test_data/" + path)
	if err != nil {
		js, _ := simplejson.NewJson([]byte("{}"))
		return js, nil
	}

	js, err := simplejson.NewJson(dat)
	if err != nil {
		return nil, err
	}

	return js, nil
}
<commit_msg>HTTP connect even if cert is invalid.<commit_after>package webpay

import (
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	simplejson "github.com/bitly/go-simplejson"
)

type WebPayClient struct {
	header    map[string]string
	options   map[string]string
	authToken string
	Charge    Charge
	Customer  Customer
	Recursion Recursion
	Token     Token
	Event     Event
	Account   Account
	mode      string
}

func NewWebPayClient(auth_token string) WebPayClient {
	cli := WebPayClient{
		authToken: auth_token,
		header: map[string]string{
			"Content-Type":    "application/x-www-form-urlencoded",
			"Accept":          "application/json",
			"User-Agent":      "webpay/2.1.1 golang",
			"Accept-Language": "en",
			"Authorization":   "Bearer " + auth_token,
		},
		options: map[string]string{
			"api_base": "https://api.webpay.jp/v1",
		},
	}

	cli.Charge = NewCharge(&cli)
	cli.Customer = NewCustomer(&cli)
	cli.Recursion = NewRecursion(&cli)
	cli.Token = NewToken(&cli)
	cli.Event = NewEvent(&cli)
	cli.Account = NewAccount(&cli)
	cli.mode = "real"

	return cli
}

func (cli WebPayClient) SetAcceptLanguage(lang string) {
	cli.header["Accept-Language"] = lang
}

func (cli WebPayClient) Post(path string, params url.Values) (*simplejson.Json, error) {
	return cli.Request("POST", path, params)
}
func (cli WebPayClient) Delete(path string, params url.Values) (*simplejson.Json, error) {
	return cli.Request("DELETE", path, params)
}
func (cli WebPayClient) Get(path string, params url.Values) (*simplejson.Json, error) {
	return cli.Request("GET", path, params)
}

func (cli WebPayClient) Request(method, path string, params url.Values) (*simplejson.Json, error) {
	if cli.mode != "real" {
		return cli.returnMockJson(method, path, params)
	}

	u := cli.options["api_base"] + "/" + path

	var client *http.Client
	if strings.HasPrefix(u, "https://") {
		tr := &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		}
		client = &http.Client{Transport: tr}
	} else {
		client = &http.Client{}
	}

	req, _ := http.NewRequest(
		method,
		u,
		strings.NewReader(params.Encode()),
	)
	for k, v := range cli.header {
		req.Header.Add(k, v)
	}
	req.SetBasicAuth(cli.authToken, "")
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}

	body, err := ioutil.ReadAll(resp.Body)
	defer resp.Body.Close()
	if err != nil {
		return nil, err
	}

	// fmt.Println(string(body))

	js, err := simplejson.NewJson(body)
	if err != nil {
		return nil, err
	}

	return js, nil
}

// GetId returns 'id' of the JSON.
func GetId(json *simplejson.Json) (string, error) {
	return json.Get("id").String()
}

// getAllPathWithQuery creates path with query from map args.
func getAllPathWithQuery(path string, args map[string]int) string {
	query := url.Values{}
	if count, exists := args["count"]; exists {
		query.Add("count", strconv.Itoa(count))
	}
	if offset, exists := args["offset"]; exists {
		query.Add("offset", strconv.Itoa(offset))
	}

	if created, exists := args["created"]; exists {
		query.Add("created", strconv.Itoa(created))
	}
	if gt, exists := args["gt"]; exists {
		query.Add("gt", strconv.Itoa(gt))
	}
	if gte, exists := args["gte"]; exists {
		query.Add("gte", strconv.Itoa(gte))
	}
	if lt, exists := args["lt"]; exists {
		query.Add("lt", strconv.Itoa(lt))
	}
	if lte, exists := args["lte"]; exists {
		query.Add("lte", strconv.Itoa(lte))
	}

	return fmt.Sprintf("%s?%s", path, query.Encode())
}

// returnMockJson return JSON which is read from under test_data dir for testing.
func (cli WebPayClient) returnMockJson(method, path string, params url.Values) (*simplejson.Json, error) {
	path = strings.Replace(path, "?", "_", -1)
	path = strings.Replace(path, "=", "_", -1)
	path = strings.Replace(path, "&", "_", -1)
	path = strings.Replace(path, "/", "_", -1)

	if method == "DELETE" {
		path = "delete_" + path
	}

	// 	fmt.Println(path)

	dat, err := ioutil.ReadFile("test_data/" + path)
	if err != nil {
		js, _ := simplejson.NewJson([]byte("{}"))
		return js, nil
	}

	js, err := simplejson.NewJson(dat)
	if err != nil {
		return nil, err
	}

	return js, nil
}
<|endoftext|>


<commit_before>package route

import (
	"net/http"
	"regexp"
)

// inspired by the following sources with some small changes:
// http://stackoverflow.com/questions/6564558/wildcards-in-the-pattern-for-http-handlefunc
// https://github.com/raymi/quickerreference
type route struct {
	pattern *regexp.Regexp
	handler http.Handler
}

type Router struct {
	routes          []*route  // array of routes with a tuple (pattern, handler)
	staticResources []*string // array of static resources
}

// Handle registers the handler for the given pattern in the router.
func (r *Router) Handle(strPattern string, handler http.Handler) {
	// encapsulate string pattern with start and end constraints.
	pattern := regexp.MustCompile("^" + strPattern + "$")
	r.routes = append(r.routes, &route{pattern, handler})
}

// HandleFunc registers the handler function for the given pattern in the router.
func (r *Router) HandleFunc(strPattern string, handler func(http.ResponseWriter, *http.Request)) {
	r.Handle(strPattern, http.HandlerFunc(handler))
}

// ServeHTTP looks for a matching route among the routes. Returns 404 if no match is found.
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {

	for _, route := range r.routes {
		if route.pattern.MatchString(req.URL.Path) {
			route.handler.ServeHTTP(w, req)
			return
		}
	}

	// route not found. check if it is a static ressource.
	for _, sr := range r.staticResources {
		dir := http.Dir(*sr)
		if _, err := dir.Open(req.URL.Path); err == nil {
			// Could open file, set static resource and call ServeHTTP again.
			r.Handle(req.URL.Path, http.FileServer(dir))
			r.ServeHTTP(w, req)
			return
		}
	}

	// no pattern matched; send 404 response
	http.NotFound(w, req)
}

// AddStaticResource adds a resource value to an array of static resources.
// Use this if you want to serve a static directory and it's sub directories.
func (r *Router) AddStaticResource(resource *string) {
	r.staticResources = append(r.staticResources, resource)
}
<commit_msg>Handle routes with variables<commit_after>package route

import (
	"net/http"
	"regexp"
	"strings"
	)

	// inspired by the following sources with some small changes:
	// http://stackoverflow.com/questions/6564558/wildcards-in-the-pattern-for-http-handlefunc
	// https://github.com/raymi/quickerreference
	type route struct {
		pattern string
		vars map[string]string
		handler http.Handler
	}

	type Router struct {
		routes          []*route  // array of routes with a tuple (pattern, handler)
		staticResources []*string // array of static resources
	}

	// Handle registers the handler for the given pattern in the router.
	func (r *Router) Handle(pattern string, handler http.Handler) {
		vars := make(map[string]string)
		r.routes = append(r.routes, &route{pattern, vars, handler})
	}

	// HandleFunc registers the handler function for the given pattern in the router.
	func (r *Router) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) {
		r.Handle(pattern, http.HandlerFunc(handler))
	}

	// ServeHTTP looks for a matching route among the routes. Returns 404 if no match is found.
	func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {

		for _, route := range r.routes {
			if route.match(req.URL.Path) {
				route.handler.ServeHTTP(w, req)
				return
			}
		}

		// route not found. check if it is a static ressource.
		for _, sr := range r.staticResources {
			dir := http.Dir(*sr)
			if _, err := dir.Open(req.URL.Path); err == nil {
				// Could open file, set static resource and call ServeHTTP again.
				r.Handle(req.URL.Path, http.FileServer(dir))
				r.ServeHTTP(w, req)
					return
				}
			}

			// no pattern matched; send 404 response
			http.NotFound(w, req)
		}

		// AddStaticResource adds a resource value to an array of static resources.
		// Use this if you want to serve a static directory and it's sub directories.
		func (r *Router) AddStaticResource(resource *string) {
			r.staticResources = append(r.staticResources, resource)
		}

		// Determine if the path matches the pattern of the route.
		// Fill the vars map with variables found in the path.
		func (r *route) match(path string) bool {
			splitPattern := strings.Split(strings.TrimSuffix(r.pattern, "/"), "/")
			splitPath := strings.Split(strings.TrimSuffix(path, "/"), "/")

			if len(splitPattern) != len(splitPath) {
				return false
			}

			for idx, val := range splitPattern {
				if val != splitPath[idx] {
					if !strings.HasPrefix(val, ":") {
						return false
					}

					variable := strings.TrimPrefix(val, ":")
					if matched, _ := regexp.MatchString("^[a-zA-Z0-9_-]+$", variable); !matched {
						return false
					}

					r.vars[variable] = splitPath[idx]
				}
			}

			return true
		}
<|endoftext|>