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

/*
Package template (html/template) implements data-driven templates for
generating HTML output safe against code injection. It provides the
same interface as package text/template and should be used instead of
text/template whenever the output is HTML.

The documentation here focuses on the security features of the package.
For information about how to program the templates themselves, see the
documentation for text/template.

Introduction

This package wraps package text/template so you can share its template API
to parse and execute HTML templates safely.

  tmpl, err := template.New("name").Parse(...)
  // Error checking elided
  err = tmpl.Execute(out, "Foo", data)

If successful, tmpl will now be injection-safe. Otherwise, err is an error
defined in the docs for ErrorCode.

HTML templates treat data values as plain text which should be encoded so they
can be safely embedded in an HTML document. The escaping is contextual, so
actions can appear within JavaScript, CSS, and URI contexts.

The security model used by this package assumes that template authors are
trusted, while text/template Execute's data parameter is not. More details are
provided below.

Example

  import "text/template"
  ...
  t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
  err = t.ExecuteTemplate(out, "T", "")

produces

  Hello, !

but the contextual autoescaping in html/template

  import "html/template"
  ...
  t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
  err = t.ExecuteTemplate(out, "T", "")

produces safe, escaped HTML output

  Hello, <script>alert('you have been pwned')</script>!

Contexts

This package understands HTML, CSS, JavaScript, and URIs. It adds sanitizing
functions to each simple action pipeline, so given the excerpt

  {{.}}

At parse time each {{.}} is overwritten to add escaping functions as necessary.
In this case it becomes

  {{. | html}}

Errors

See the documentation of ErrorCode for details.

A fuller picture

The rest of this package comment may be skipped on first reading; it includes
details necessary to understand escaping contexts and error messages. Most users
will not need to understand these details.

Contexts

Assuming {{.}} is `O'Reilly: How are <i>you</i>?`, the table below shows
how {{.}} appears when used in the context to the left.

  Context                          {{.}} After
  {{.}}                            O'Reilly: How are <i>you</i>?
                  O'Reilly: How are you?
                  O'Reilly: How are %3ci%3eyou%3c/i%3e?
                O'Reilly%3a%20How%20are%3ci%3e...%3f
               O\x27Reilly: How are \x3ci\x3eyou...?
                 "O\x27Reilly: How are \x3ci\x3eyou...?"
       O\x27Reilly: How are \x3ci\x3eyou...\x3f

If used in an unsafe context, then the value might be filtered out:

  Context                          {{.}} After
                   #ZgotmplZ

since "O'Reilly:" is not an allowed protocol like "http:".

If {{.}} is the innocuous word, `left`, then it can appear more widely,

  Context                              {{.}} After
  {{.}}                                left
                      left
                       left
                      left
                  left
          left
               left
         left
    left
     left

Non-string values can be used in JavaScript contexts.
If {{.}} is

  []struct{A,B string}{ "foo", "bar" }

in the escaped template

then the template output is

See package json to understand how non-string content is marshalled for
embedding in JavaScript contexts.

Typed Strings

By default, this package assumes that all pipelines produce a plain text string.
It adds escaping pipeline stages necessary to correctly and safely embed that
plain text string in the appropriate context.

When a data value is not plain text, you can make sure it is not over-escaped
by marking it with its type.

Types HTML, JS, URL, and others from content.go can carry safe content that is
exempted from escaping.

The template

  Hello, {{.}}!

can be invoked with

  tmpl.Execute(out, HTML(`<b>World</b>`))

to produce

  Hello, World!

instead of the

  Hello, <b>World<b>!

that would have been produced if {{.}} was a regular string.

Security Model

http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/safetemplate.html#problem_definition defines "safe" as used by this package.

This package assumes that template authors are trusted, that Execute's data
parameter is not, and seeks to preserve the properties below in the face
of untrusted data:

Structure Preservation Property:
"... when a template author writes an HTML tag in a safe templating language,
the browser will interpret the corresponding portion of the output as a tag
regardless of the values of untrusted data, and similarly for other structures
such as attribute boundaries and JS and CSS string boundaries."

Code Effect Property:
"... only code specified by the template author should run as a result of
injecting the template output into a page and all code specified by the
template author should run as a result of the same."

Least Surprise Property:
"A developer (or code reviewer) familiar with HTML, CSS, and JavaScript, who
knows that contextual autoescaping happens should be able to look at a {{.}}
and correctly infer what sanitization happens."
*/
package template
<commit_msg>html/template: use correct method signature, in introduction example.<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Package template (html/template) implements data-driven templates for
generating HTML output safe against code injection. It provides the
same interface as package text/template and should be used instead of
text/template whenever the output is HTML.

The documentation here focuses on the security features of the package.
For information about how to program the templates themselves, see the
documentation for text/template.

Introduction

This package wraps package text/template so you can share its template API
to parse and execute HTML templates safely.

  tmpl, err := template.New("name").Parse(...)
  // Error checking elided
  err = tmpl.Execute(out, data)

If successful, tmpl will now be injection-safe. Otherwise, err is an error
defined in the docs for ErrorCode.

HTML templates treat data values as plain text which should be encoded so they
can be safely embedded in an HTML document. The escaping is contextual, so
actions can appear within JavaScript, CSS, and URI contexts.

The security model used by this package assumes that template authors are
trusted, while text/template Execute's data parameter is not. More details are
provided below.

Example

  import "text/template"
  ...
  t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
  err = t.ExecuteTemplate(out, "T", "")

produces

  Hello, !

but the contextual autoescaping in html/template

  import "html/template"
  ...
  t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
  err = t.ExecuteTemplate(out, "T", "")

produces safe, escaped HTML output

  Hello, <script>alert('you have been pwned')</script>!

Contexts

This package understands HTML, CSS, JavaScript, and URIs. It adds sanitizing
functions to each simple action pipeline, so given the excerpt

  {{.}}

At parse time each {{.}} is overwritten to add escaping functions as necessary.
In this case it becomes

  {{. | html}}

Errors

See the documentation of ErrorCode for details.

A fuller picture

The rest of this package comment may be skipped on first reading; it includes
details necessary to understand escaping contexts and error messages. Most users
will not need to understand these details.

Contexts

Assuming {{.}} is `O'Reilly: How are <i>you</i>?`, the table below shows
how {{.}} appears when used in the context to the left.

  Context                          {{.}} After
  {{.}}                            O'Reilly: How are <i>you</i>?
                  O'Reilly: How are you?
                  O'Reilly: How are %3ci%3eyou%3c/i%3e?
                O'Reilly%3a%20How%20are%3ci%3e...%3f
               O\x27Reilly: How are \x3ci\x3eyou...?
                 "O\x27Reilly: How are \x3ci\x3eyou...?"
       O\x27Reilly: How are \x3ci\x3eyou...\x3f

If used in an unsafe context, then the value might be filtered out:

  Context                          {{.}} After
                   #ZgotmplZ

since "O'Reilly:" is not an allowed protocol like "http:".

If {{.}} is the innocuous word, `left`, then it can appear more widely,

  Context                              {{.}} After
  {{.}}                                left
                      left
                       left
                      left
                  left
          left
               left
         left
    left
     left

Non-string values can be used in JavaScript contexts.
If {{.}} is

  []struct{A,B string}{ "foo", "bar" }

in the escaped template

then the template output is

See package json to understand how non-string content is marshalled for
embedding in JavaScript contexts.

Typed Strings

By default, this package assumes that all pipelines produce a plain text string.
It adds escaping pipeline stages necessary to correctly and safely embed that
plain text string in the appropriate context.

When a data value is not plain text, you can make sure it is not over-escaped
by marking it with its type.

Types HTML, JS, URL, and others from content.go can carry safe content that is
exempted from escaping.

The template

  Hello, {{.}}!

can be invoked with

  tmpl.Execute(out, HTML(`<b>World</b>`))

to produce

  Hello, World!

instead of the

  Hello, <b>World<b>!

that would have been produced if {{.}} was a regular string.

Security Model

http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/safetemplate.html#problem_definition defines "safe" as used by this package.

This package assumes that template authors are trusted, that Execute's data
parameter is not, and seeks to preserve the properties below in the face
of untrusted data:

Structure Preservation Property:
"... when a template author writes an HTML tag in a safe templating language,
the browser will interpret the corresponding portion of the output as a tag
regardless of the values of untrusted data, and similarly for other structures
such as attribute boundaries and JS and CSS string boundaries."

Code Effect Property:
"... only code specified by the template author should run as a result of
injecting the template output into a page and all code specified by the
template author should run as a result of the same."

Least Surprise Property:
"A developer (or code reviewer) familiar with HTML, CSS, and JavaScript, who
knows that contextual autoescaping happens should be able to look at a {{.}}
and correctly infer what sanitization happens."
*/
package template
<|endoftext|>


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

// Plan 9 environment variables.

package syscall

import "errors"

func Getenv(key string) (value string, found bool) {
	if len(key) == 0 {
		return "", false
	}
	f, e := Open("/env/"+key, O_RDONLY)
	if e != nil {
		return "", false
	}
	defer Close(f)

	l, _ := Seek(f, 0, 2)
	Seek(f, 0, 0)
	buf := make([]byte, l)
	n, e := Read(f, buf)
	if e != nil {
		return "", false
	}

	if n > 0 && buf[n-1] == 0 {
		buf = buf[:n-1]
	}
	return string(buf), true
}

func Setenv(key, value string) error {
	if len(key) == 0 {
		return errors.New("bad arg in system call")
	}

	f, e := Create("/env/"+key, O_RDWR, 0666)
	if e != nil {
		return e
	}
	defer Close(f)

	_, e = Write(f, []byte(value))
	return nil
}

func Clearenv() {
	RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
}

func Environ() []string {
	env := make([]string, 0, 100)

	f, e := Open("/env", O_RDONLY)
	if e != nil {
		panic(e)
	}
	defer Close(f)

	names, e := readdirnames(f)
	if e != nil {
		panic(e)
	}

	for _, k := range names {
		if v, ok := Getenv(k); ok {
			env = append(env, k+"="+v)
		}
	}
	return env[0:len(env)]
}
<commit_msg>syscall: cache environment variables on Plan 9.<commit_after>// Copyright 2011 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.

// Plan 9 environment variables.

package syscall

import (
	"errors"
	"sync"
)

var (
	// envOnce guards initialization by copyenv, which populates env.
	envOnce sync.Once

	// envLock guards env.
	envLock sync.RWMutex

	// env maps from an environment variable to its value.
	env map[string]string
)

func readenv(key string) (string, error) {
	fd, err := Open("/env/"+key, O_RDONLY)
	if err != nil {
		return "", err
	}
	defer Close(fd)
	l, _ := Seek(fd, 0, 2)
	Seek(fd, 0, 0)
	buf := make([]byte, l)
	n, err := Read(fd, buf)
	if err != nil {
		return "", err
	}
	if n > 0 && buf[n-1] == 0 {
		buf = buf[:n-1]
	}
	return string(buf), nil
}

func writeenv(key, value string) error {
	fd, err := Create("/env/"+key, O_RDWR, 0666)
	if err != nil {
		return err
	}
	defer Close(fd)
	_, err = Write(fd, []byte(value))
	return err
}

func copyenv() {
	env = make(map[string]string)
	fd, err := Open("/env", O_RDONLY)
	if err != nil {
		return
	}
	defer Close(fd)
	files, err := readdirnames(fd)
	if err != nil {
		return
	}
	for _, key := range files {
		v, err := readenv(key)
		if err != nil {
			continue
		}
		env[key] = v
	}
}

func Getenv(key string) (value string, found bool) {
	envOnce.Do(copyenv)
	if len(key) == 0 {
		return "", false
	}

	envLock.RLock()
	defer envLock.RUnlock()

	v, ok := env[key]
	if !ok {
		return "", false
	}
	return v, true
}

func Setenv(key, value string) error {
	envOnce.Do(copyenv)
	if len(key) == 0 {
		return errors.New("zero length key")
	}

	envLock.Lock()
	defer envLock.Unlock()

	err := writeenv(key, value)
	if err != nil {
		return err
	}
	env[key] = value
	return nil
}

func Clearenv() {
	envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv

	envLock.Lock()
	defer envLock.Unlock()

	env = make(map[string]string)
	RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
}

func Environ() []string {
	envOnce.Do(copyenv)
	envLock.RLock()
	defer envLock.RUnlock()
	a := make([]string, len(env))
	i := 0
	for k, v := range env {
		a[i] = k + "=" + v
		i++
	}
	return a
}
<|endoftext|>


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

// Package dwarf provides access to DWARF debugging information loaded from
// executable files, as defined in the DWARF 2.0 Standard at
// http://dwarfstd.org/doc/dwarf-2.0.0.pdf
package dwarf

import "encoding/binary"

// Data represents the DWARF debugging information
// loaded from an executable file (for example, an ELF or Mach-O executable).
type Data struct {
	// raw data
	abbrev   []byte
	aranges  []byte
	frame    []byte
	info     []byte
	line     []byte
	pubnames []byte
	ranges   []byte
	str      []byte

	// parsed data
	abbrevCache map[uint32]abbrevTable
	addrsize    int
	order       binary.ByteOrder
	typeCache   map[Offset]Type
	unit        []unit
}

// New returns a new Data object initialized from the given parameters.
// Rather than calling this function directly, clients should typically use
// the DWARF method of the File type of the appropriate package debug/elf,
// debug/macho, or debug/pe.
//
// The []byte arguments are the data from the corresponding debug section
// in the object file; for example, for an ELF object, abbrev is the contents of
// the ".debug_abbrev" section.
func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Data, error) {
	d := &Data{
		abbrev:      abbrev,
		aranges:     aranges,
		frame:       frame,
		info:        info,
		line:        line,
		pubnames:    pubnames,
		ranges:      ranges,
		str:         str,
		abbrevCache: make(map[uint32]abbrevTable),
		typeCache:   make(map[Offset]Type),
	}

	// Sniff .debug_info to figure out byte order.
	// bytes 4:6 are the version, a tiny 16-bit number (1, 2, 3).
	if len(d.info) < 6 {
		return nil, DecodeError{"info", Offset(len(d.info)), "too short"}
	}
	x, y := d.info[4], d.info[5]
	switch {
	case x == 0 && y == 0:
		return nil, DecodeError{"info", 4, "unsupported version 0"}
	case x == 0:
		d.order = binary.BigEndian
	case y == 0:
		d.order = binary.LittleEndian
	default:
		return nil, DecodeError{"info", 4, "cannot determine byte order"}
	}

	u, err := d.parseUnits()
	if err != nil {
		return nil, err
	}
	d.unit = u
	return d, nil
}
<commit_msg>debug/dwarf: remove unused field addrsize from Data<commit_after>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package dwarf provides access to DWARF debugging information loaded from
// executable files, as defined in the DWARF 2.0 Standard at
// http://dwarfstd.org/doc/dwarf-2.0.0.pdf
package dwarf

import "encoding/binary"

// Data represents the DWARF debugging information
// loaded from an executable file (for example, an ELF or Mach-O executable).
type Data struct {
	// raw data
	abbrev   []byte
	aranges  []byte
	frame    []byte
	info     []byte
	line     []byte
	pubnames []byte
	ranges   []byte
	str      []byte

	// parsed data
	abbrevCache map[uint32]abbrevTable
	order       binary.ByteOrder
	typeCache   map[Offset]Type
	unit        []unit
}

// New returns a new Data object initialized from the given parameters.
// Rather than calling this function directly, clients should typically use
// the DWARF method of the File type of the appropriate package debug/elf,
// debug/macho, or debug/pe.
//
// The []byte arguments are the data from the corresponding debug section
// in the object file; for example, for an ELF object, abbrev is the contents of
// the ".debug_abbrev" section.
func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Data, error) {
	d := &Data{
		abbrev:      abbrev,
		aranges:     aranges,
		frame:       frame,
		info:        info,
		line:        line,
		pubnames:    pubnames,
		ranges:      ranges,
		str:         str,
		abbrevCache: make(map[uint32]abbrevTable),
		typeCache:   make(map[Offset]Type),
	}

	// Sniff .debug_info to figure out byte order.
	// bytes 4:6 are the version, a tiny 16-bit number (1, 2, 3).
	if len(d.info) < 6 {
		return nil, DecodeError{"info", Offset(len(d.info)), "too short"}
	}
	x, y := d.info[4], d.info[5]
	switch {
	case x == 0 && y == 0:
		return nil, DecodeError{"info", 4, "unsupported version 0"}
	case x == 0:
		d.order = binary.BigEndian
	case y == 0:
		d.order = binary.LittleEndian
	default:
		return nil, DecodeError{"info", 4, "cannot determine byte order"}
	}

	u, err := d.parseUnits()
	if err != nil {
		return nil, err
	}
	d.unit = u
	return d, nil
}
<|endoftext|>


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

package net

import (
	"fmt"
	"runtime"
	"testing"
	"time"
)

func testTimeout(t *testing.T, net, addr string, readFrom bool) {
	c, err := Dial(net, addr)
	if err != nil {
		t.Errorf("Dial(%q, %q) failed: %v", net, addr, err)
		return
	}
	defer c.Close()
	what := "Read"
	if readFrom {
		what = "ReadFrom"
	}

	errc := make(chan error, 1)
	go func() {
		t0 := time.Now()
		c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
		var b [100]byte
		var n int
		var err error
		if readFrom {
			n, _, err = c.(PacketConn).ReadFrom(b[0:])
		} else {
			n, err = c.Read(b[0:])
		}
		t1 := time.Now()
		if n != 0 || err == nil || !err.(Error).Timeout() {
			errc <- fmt.Errorf("%s(%q, %q) did not return 0, timeout: %v, %v", what, net, addr, n, err)
			return
		}
		if dt := t1.Sub(t0); dt < 50*time.Millisecond || !testing.Short() && dt > 250*time.Millisecond {
			errc <- fmt.Errorf("%s(%q, %q) took %s, expected 0.1s", what, net, addr, dt)
			return
		}
		errc <- nil
	}()
	select {
	case err := <-errc:
		if err != nil {
			t.Error(err)
		}
	case <-time.After(1 * time.Second):
		t.Errorf("%s(%q, %q) took over 1 second, expected 0.1s", what, net, addr)
	}
}

func TestTimeoutUDP(t *testing.T) {
	switch runtime.GOOS {
	case "plan9":
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}

	// set up a listener that won't talk back
	listening := make(chan string)
	done := make(chan int)
	go runDatagramPacketConnServer(t, "udp", "127.0.0.1:0", listening, done)
	addr := <-listening

	testTimeout(t, "udp", addr, false)
	testTimeout(t, "udp", addr, true)
	<-done
}

func TestTimeoutTCP(t *testing.T) {
	switch runtime.GOOS {
	case "plan9":
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}

	// set up a listener that won't talk back
	listening := make(chan string)
	done := make(chan int)
	go runStreamConnServer(t, "tcp", "127.0.0.1:0", listening, done)
	addr := <-listening

	testTimeout(t, "tcp", addr, false)
	<-done
}

func TestDeadlineReset(t *testing.T) {
	switch runtime.GOOS {
	case "plan9":
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer ln.Close()
	tl := ln.(*TCPListener)
	tl.SetDeadline(time.Now().Add(1 * time.Minute))
	tl.SetDeadline(time.Time{}) // reset it
	errc := make(chan error, 1)
	go func() {
		_, err := ln.Accept()
		errc <- err
	}()
	select {
	case <-time.After(50 * time.Millisecond):
		// Pass.
	case err := <-errc:
		// Accept should never return; we never
		// connected to it.
		t.Errorf("unexpected return from Accept; err=%v", err)
	}
}

func TestTimeoutAccept(t *testing.T) {
	switch runtime.GOOS {
	case "plan9":
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer ln.Close()
	tl := ln.(*TCPListener)
	tl.SetDeadline(time.Now().Add(100 * time.Millisecond))
	errc := make(chan error, 1)
	go func() {
		_, err := ln.Accept()
		errc <- err
	}()
	select {
	case <-time.After(1 * time.Second):
		// Accept shouldn't block indefinitely
		t.Errorf("Accept didn't return in an expected time")
	case <-errc:
		// Pass.
	}
}

func TestReadWriteDeadline(t *testing.T) {
	if !canCancelIO {
		t.Logf("skipping test on this system")
		return
	}
	const (
		readTimeout  = 100 * time.Millisecond
		writeTimeout = 200 * time.Millisecond
		delta        = 40 * time.Millisecond
	)
	checkTimeout := func(command string, start time.Time, should time.Duration) {
		is := time.Now().Sub(start)
		d := should - is
		if d < -delta || delta < d {
			t.Errorf("%s timeout test failed: is=%v should=%v\n", command, is, should)
		}
	}

	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("ListenTCP on :0: %v", err)
	}

	lnquit := make(chan bool)

	go func() {
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("Accept: %v", err)
		}
		defer c.Close()
		lnquit <- true
	}()

	c, err := Dial("tcp", ln.Addr().String())
	if err != nil {
		t.Fatalf("Dial: %v", err)
	}
	defer c.Close()

	start := time.Now()
	err = c.SetReadDeadline(start.Add(readTimeout))
	if err != nil {
		t.Fatalf("SetReadDeadline: %v", err)
	}
	err = c.SetWriteDeadline(start.Add(writeTimeout))
	if err != nil {
		t.Fatalf("SetWriteDeadline: %v", err)
	}

	quit := make(chan bool)

	go func() {
		var buf [10]byte
		_, err = c.Read(buf[:])
		if err == nil {
			t.Errorf("Read should not succeed")
		}
		checkTimeout("Read", start, readTimeout)
		quit <- true
	}()

	go func() {
		var buf [10000]byte
		for {
			_, err = c.Write(buf[:])
			if err != nil {
				break
			}
		}
		checkTimeout("Write", start, writeTimeout)
		quit <- true
	}()

	<-quit
	<-quit
	<-lnquit
}
<commit_msg>net: fix race in TestReadWriteDeadline.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package net

import (
	"fmt"
	"runtime"
	"testing"
	"time"
)

func testTimeout(t *testing.T, net, addr string, readFrom bool) {
	c, err := Dial(net, addr)
	if err != nil {
		t.Errorf("Dial(%q, %q) failed: %v", net, addr, err)
		return
	}
	defer c.Close()
	what := "Read"
	if readFrom {
		what = "ReadFrom"
	}

	errc := make(chan error, 1)
	go func() {
		t0 := time.Now()
		c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
		var b [100]byte
		var n int
		var err error
		if readFrom {
			n, _, err = c.(PacketConn).ReadFrom(b[0:])
		} else {
			n, err = c.Read(b[0:])
		}
		t1 := time.Now()
		if n != 0 || err == nil || !err.(Error).Timeout() {
			errc <- fmt.Errorf("%s(%q, %q) did not return 0, timeout: %v, %v", what, net, addr, n, err)
			return
		}
		if dt := t1.Sub(t0); dt < 50*time.Millisecond || !testing.Short() && dt > 250*time.Millisecond {
			errc <- fmt.Errorf("%s(%q, %q) took %s, expected 0.1s", what, net, addr, dt)
			return
		}
		errc <- nil
	}()
	select {
	case err := <-errc:
		if err != nil {
			t.Error(err)
		}
	case <-time.After(1 * time.Second):
		t.Errorf("%s(%q, %q) took over 1 second, expected 0.1s", what, net, addr)
	}
}

func TestTimeoutUDP(t *testing.T) {
	switch runtime.GOOS {
	case "plan9":
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}

	// set up a listener that won't talk back
	listening := make(chan string)
	done := make(chan int)
	go runDatagramPacketConnServer(t, "udp", "127.0.0.1:0", listening, done)
	addr := <-listening

	testTimeout(t, "udp", addr, false)
	testTimeout(t, "udp", addr, true)
	<-done
}

func TestTimeoutTCP(t *testing.T) {
	switch runtime.GOOS {
	case "plan9":
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}

	// set up a listener that won't talk back
	listening := make(chan string)
	done := make(chan int)
	go runStreamConnServer(t, "tcp", "127.0.0.1:0", listening, done)
	addr := <-listening

	testTimeout(t, "tcp", addr, false)
	<-done
}

func TestDeadlineReset(t *testing.T) {
	switch runtime.GOOS {
	case "plan9":
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer ln.Close()
	tl := ln.(*TCPListener)
	tl.SetDeadline(time.Now().Add(1 * time.Minute))
	tl.SetDeadline(time.Time{}) // reset it
	errc := make(chan error, 1)
	go func() {
		_, err := ln.Accept()
		errc <- err
	}()
	select {
	case <-time.After(50 * time.Millisecond):
		// Pass.
	case err := <-errc:
		// Accept should never return; we never
		// connected to it.
		t.Errorf("unexpected return from Accept; err=%v", err)
	}
}

func TestTimeoutAccept(t *testing.T) {
	switch runtime.GOOS {
	case "plan9":
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer ln.Close()
	tl := ln.(*TCPListener)
	tl.SetDeadline(time.Now().Add(100 * time.Millisecond))
	errc := make(chan error, 1)
	go func() {
		_, err := ln.Accept()
		errc <- err
	}()
	select {
	case <-time.After(1 * time.Second):
		// Accept shouldn't block indefinitely
		t.Errorf("Accept didn't return in an expected time")
	case <-errc:
		// Pass.
	}
}

func TestReadWriteDeadline(t *testing.T) {
	if !canCancelIO {
		t.Logf("skipping test on this system")
		return
	}
	const (
		readTimeout  = 100 * time.Millisecond
		writeTimeout = 200 * time.Millisecond
		delta        = 40 * time.Millisecond
	)
	checkTimeout := func(command string, start time.Time, should time.Duration) {
		is := time.Now().Sub(start)
		d := should - is
		if d < -delta || delta < d {
			t.Errorf("%s timeout test failed: is=%v should=%v\n", command, is, should)
		}
	}

	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("ListenTCP on :0: %v", err)
	}

	lnquit := make(chan bool)

	go func() {
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("Accept: %v", err)
		}
		defer c.Close()
		lnquit <- true
	}()

	c, err := Dial("tcp", ln.Addr().String())
	if err != nil {
		t.Fatalf("Dial: %v", err)
	}
	defer c.Close()

	start := time.Now()
	err = c.SetReadDeadline(start.Add(readTimeout))
	if err != nil {
		t.Fatalf("SetReadDeadline: %v", err)
	}
	err = c.SetWriteDeadline(start.Add(writeTimeout))
	if err != nil {
		t.Fatalf("SetWriteDeadline: %v", err)
	}

	quit := make(chan bool)

	go func() {
		var buf [10]byte
		_, err := c.Read(buf[:])
		if err == nil {
			t.Errorf("Read should not succeed")
		}
		checkTimeout("Read", start, readTimeout)
		quit <- true
	}()

	go func() {
		var buf [10000]byte
		for {
			_, err := c.Write(buf[:])
			if err != nil {
				break
			}
		}
		checkTimeout("Write", start, writeTimeout)
		quit <- true
	}()

	<-quit
	<-quit
	<-lnquit
}
<|endoftext|>


<commit_before>package scene

import (
	objects "de/vorlesung/projekt/raytracer/SceneObjects"
	"testing"
)

func TestNewScene(t *testing.T) {
	defer func() {
		e := recover()
		if e == nil {
			t.Errorf("TestNewScene error is nil")
		}
	}()
	g := NewGrid(objects.NewVector(1.0, 2.0, 3.0), objects.NewVector(1.0, 5.0, 6.0))
	s := NewScene(objects.NewVector(7.0, 8.0, 9.0), g)

	if *s.eye != *objects.NewVector(7.0, 8.0, 9.0) || *s.grid.top_left != *objects.NewVector(1.0, 2.0, 3.0) || *s.grid.bottom_right != *objects.NewVector(1.0, 5.0, 6.0) || s.elements == nil || *s.ambient != *objects.NewVector(0.0, 0.0, 0.0) || *s.skyColor != *objects.NewVector(0.0, 0.0, 0.0) || s.light == nil {
		t.Errorf("TestNewScene %v %v %v %v %v %v %v", s.eye, s.grid.top_left, s.grid.bottom_right, s.elements, s.ambient, s.skyColor, s.light)
	}

	g = NewGrid(objects.NewVector(1.0, 2.0, 3.0), objects.NewVector(2.0, 5.0, 6.0))
	s = NewScene(objects.NewVector(7.0, 8.0, 9.0), g)
}

func TestSceneGetSet(t *testing.T) {
	g := NewGrid(objects.NewVector(1.0, 2.0, 3.0), objects.NewVector(1.0, 5.0, 6.0))
	s := NewScene(objects.NewVector(7.0, 8.0, 9.0), g)

	if *s.Eye() != *objects.NewVector(7.0, 8.0, 9.0) || *s.Grid().top_left != *objects.NewVector(1.0, 2.0, 3.0) || *s.Grid().bottom_right != *objects.NewVector(1.0, 5.0, 6.0) || s.Elements() == nil || *s.Ambient() != *objects.NewVector(0.0, 0.0, 0.0) || *s.SkyColor() != *objects.NewVector(0.0, 0.0, 0.0) || s.light == nil {
		t.Errorf("TestSceneGetSet 1 %v %v %v %v %v %v %v", s.Eye(), s.Grid().top_left, s.Grid().bottom_right, s.Elements(), s.Ambient(), s.SkyColor(), s.Light())
	}

	g = NewGrid(objects.NewVector(10.0, 11.0, 12.0), objects.NewVector(10.0, 14.0, 15.0))
	s.SetGrid(g)
	s.SetEye(objects.NewVector(16.0, 17.0, 18.0))
	//objects := make([]SceneObject)
	//objects = append(objects, element)
	s.SetAmbient(objects.NewVector(19.0, 20.0, 21.0))
	s.SetSkyColor(objects.NewVector(22.0, 23.0, 24.0))

	if *s.Eye() != *objects.NewVector(16.0, 17.0, 18.0) || *s.Grid().top_left != *objects.NewVector(10.0, 11.0, 12.0) || *s.Grid().bottom_right != *objects.NewVector(10.0, 14.0, 15.0) || s.Elements() == nil || *s.Ambient() != *objects.NewVector(19.0, 20.0, 21.0) || *s.SkyColor() != *objects.NewVector(22.0, 23.0, 24.0) {
		t.Errorf("TestSceneGetSet 2 %v %v %v %v %v %v %v", s.Eye(), s.Grid().top_left, s.Grid().bottom_right, s.Elements(), s.Ambient(), s.SkyColor(), s.Light())
	}
}
<commit_msg>Scene test update<commit_after>package scene

import (
	objects "de/vorlesung/projekt/raytracer/SceneObjects"
	"testing"
)

func TestNewScene(t *testing.T) {
	defer func() {
		e := recover()
		if e == nil {
			t.Errorf("TestNewScene error is nil")
		}
	}()
	g := NewGrid(objects.NewVector(1.0, 2.0, 3.0), objects.NewVector(1.0, 5.0, 6.0))
	s := NewScene(objects.NewVector(7.0, 8.0, 9.0), g)

	if *s.View() != *objects.NewVector(7.0, 8.0, 9.0) || *s.Grid().TopLeft() != *objects.NewVector(1.0, 2.0, 3.0) || *s.Grid().BottomRight() != *objects.NewVector(1.0, 5.0, 6.0) || s.Elements() == nil || *s.Ambient() != *objects.NewVector(0.0, 0.0, 0.0) || *s.SkyColor() != *objects.NewVector(0.0, 0.0, 0.0) || s.Light() == nil {
		t.Errorf("TestNewScene %v %v %v %v %v %v %v", s.View(), s.Grid().TopLeft(), s.Grid().BottomRight(), s.Elements(), s.Ambient(), s.SkyColor(), s.Light())
	}

	g = NewGrid(objects.NewVector(1.0, 2.0, 3.0), objects.NewVector(2.0, 5.0, 6.0))
	s = NewScene(objects.NewVector(7.0, 8.0, 9.0), g)
}

func TestSceneGetSet(t *testing.T) {
	g := NewGrid(objects.NewVector(1.0, 2.0, 3.0), objects.NewVector(1.0, 5.0, 6.0))
	s := NewScene(objects.NewVector(7.0, 8.0, 9.0), g)

	if *s.View() != *objects.NewVector(7.0, 8.0, 9.0) || *s.Grid().TopLeft() != *objects.NewVector(1.0, 2.0, 3.0) || *s.Grid().BottomRight() != *objects.NewVector(1.0, 5.0, 6.0) || s.Elements() == nil || *s.Ambient() != *objects.NewVector(0.0, 0.0, 0.0) || *s.SkyColor() != *objects.NewVector(0.0, 0.0, 0.0) || s.Light() == nil {
		t.Errorf("TestSceneGetSet 1 %v %v %v %v %v %v %v", s.View(), s.Grid().TopLeft(), s.Grid().BottomRight(), s.Elements(), s.Ambient(), s.SkyColor(), s.Light())
	}

	g = NewGrid(objects.NewVector(10.0, 11.0, 12.0), objects.NewVector(10.0, 14.0, 15.0))
	s.SetGrid(g)
	s.SetView(objects.NewVector(16.0, 17.0, 18.0))
	//objects := make([]SceneObject)
	//objects = append(objects, element)
	s.SetAmbient(objects.NewVector(19.0, 20.0, 21.0))
	s.SetSkyColor(objects.NewVector(22.0, 23.0, 24.0))

	if *s.View() != *objects.NewVector(16.0, 17.0, 18.0) || *s.Grid().TopLeft() != *objects.NewVector(10.0, 11.0, 12.0) || *s.Grid().BottomRight() != *objects.NewVector(10.0, 14.0, 15.0) || s.Elements() == nil || *s.Ambient() != *objects.NewVector(19.0, 20.0, 21.0) || *s.SkyColor() != *objects.NewVector(22.0, 23.0, 24.0) {
		t.Errorf("TestSceneGetSet 2 %v %v %v %v %v %v %v", s.View(), s.Grid().TopLeft(), s.Grid().BottomRight(), s.Elements(), s.Ambient(), s.SkyColor(), s.Light())
	}
}
<|endoftext|>


<commit_before>package parse

import (
	"fmt"
	"testing"

	"github.com/stretchr/testify/require"
)

func TestBasic(t *testing.T) {
	pipeline, err := ParsePipeline("testdata/basic")
	require.NoError(t, err)
	fmt.Printf("%+v\n", pipeline)
}

func TestGetAllFilePaths(t *testing.T) {
	files, err := getAllFilePaths("testdata/basic", []string{}, []string{"other", "root/ignore", "ignore-me.yml"})
	require.NoError(t, err)
	require.Equal(
		t,
		[]string{
			"root/foo-node.yml",
			"root/foo-service.yml",
			"root/include/bar-node.yml",
			"root/include/bar-service.yml",
			"root/include/bat-node.yml",
			"root/include/baz-node.yml",
			"root/include/baz-service.yml",
		},
		files,
	)
}
<commit_msg>remove printf from test<commit_after>package parse

import (
	"testing"

	"github.com/stretchr/testify/require"
)

func TestBasic(t *testing.T) {
	_, err := ParsePipeline("testdata/basic")
	require.NoError(t, err)
}

func TestGetAllFilePaths(t *testing.T) {
	files, err := getAllFilePaths("testdata/basic", []string{}, []string{"other", "root/ignore", "ignore-me.yml"})
	require.NoError(t, err)
	require.Equal(
		t,
		[]string{
			"root/foo-node.yml",
			"root/foo-service.yml",
			"root/include/bar-node.yml",
			"root/include/bar-service.yml",
			"root/include/bat-node.yml",
			"root/include/baz-node.yml",
			"root/include/baz-service.yml",
		},
		files,
	)
}
<|endoftext|>


<commit_before>package baa

import (
	"log"
	"net/http"
	"os"
	"strings"
	"sync"
)

const (
	// DEV mode
	DEV = "development"
	// PROD mode
	PROD = "production"
	// TEST mode
	TEST = "test"
)

// Baa provlider an application
type Baa struct {
	debug           bool
	name            string
	di              *DI
	router          *Router
	pool            sync.Pool
	errorHandler    ErrorHandleFunc
	notFoundHandler HandlerFunc
	middleware      []HandlerFunc
}

// Middleware middleware handler
type Middleware interface{}

// HandlerFunc context handler
type HandlerFunc func(*Context)

// ErrorHandleFunc HTTP error handleFunc
type ErrorHandleFunc func(error, *Context)

// New create a baa application without any config.
func New() *Baa {
	b := new(Baa)
	b.middleware = make([]HandlerFunc, 0)
	b.pool = sync.Pool{
		New: func() interface{} {
			return newContext(nil, nil, b)
		},
	}
	if os.Getenv("Baa.Env") != PROD {
		b.debug = true
	}
	b.di = newDI()
	b.router = newRouter()
	b.errorHandler = b.DefaultErrorHandler
	b.notFoundHandler = b.DefaultNotFoundHandler
	b.SetDI("logger", log.New(os.Stderr, "[Baa] ", log.LstdFlags))
	b.SetDI("render", newRender())
	return b
}

// Server returns the internal *http.Server.
func (b *Baa) Server(addr string) *http.Server {
	s := &http.Server{Addr: addr}
	return s
}

// Run runs a server.
func (b *Baa) Run(addr string) {
	b.run(b.Server(addr))
}

// RunTLS runs a server with TLS configuration.
func (b *Baa) RunTLS(addr, certfile, keyfile string) {
	b.run(b.Server(addr), certfile, keyfile)
}

// RunServer runs a custom server.
func (b *Baa) RunServer(s *http.Server) {
	b.run(s)
}

// RunTLSServer runs a custom server with TLS configuration.
func (b *Baa) RunTLSServer(s *http.Server, crtFile, keyFile string) {
	b.run(s, crtFile, keyFile)
}

func (b *Baa) run(s *http.Server, files ...string) {
	s.Handler = b
	if len(files) == 0 {
		b.Logger().Printf("Listen %s", s.Addr)
		b.Logger().Fatal(s.ListenAndServe())
	} else if len(files) == 2 {
		b.Logger().Printf("Listen %s with TLS", s.Addr)
		b.Logger().Fatal(s.ListenAndServeTLS(files[0], files[1]))
	} else {
		b.Logger().Fatal("invalid TLS configuration")
	}
}

func (b *Baa) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	c := b.pool.Get().(*Context)
	c.reset(w, r)

	// build handler chain
	route := b.router.match(r.Method, r.URL.Path, c)
	// notFound
	if route == nil || route.handlers == nil {
		c.handlers = append(c.handlers, b.notFoundHandler)
	} else {
		c.handlers = append(c.handlers, route.handlers...)
	}

	c.Next()

	b.pool.Put(c)
}

// SetDebug set baa debug
func (b *Baa) SetDebug(v bool) {
	b.debug = v
}

// Logger return baa logger
func (b *Baa) Logger() Logger {
	return b.GetDI("logger").(Logger)
}

// Render return baa render
func (b *Baa) Render() Renderer {
	return b.GetDI("render").(Renderer)
}

// SetErrorHandler registers a custom Baa.ErrorHandleFunc.
func (b *Baa) SetErrorHandler(h ErrorHandleFunc) {
	b.errorHandler = h
}

// Use registers a middleware
func (b *Baa) Use(m ...Middleware) {
	for i := range m {
		b.middleware = append(b.middleware, wrapMiddleware(m[i]))
	}
}

// SetDI registers a dependency injection
func (b *Baa) SetDI(name string, h interface{}) {
	b.di.set(name, h)
}

// GetDI fetch a registered dependency injection
func (b *Baa) GetDI(name string) interface{} {
	return b.di.get(name)
}

// Static set static file route
// h used for set Expries ...
func (b *Baa) Static(prefix string, dir string, index bool, h HandlerFunc) {
	if prefix == "" {
		panic("baa.Static prefix can not be empty")
	}
	if dir == "" {
		panic("baa.Static dir can not be empty")
	}
	staticHandler := newStatic(prefix, dir, index, h)
	b.Get(prefix, staticHandler)
	b.Get(prefix+":file", staticHandler)
}

// SetAutoHead sets the value who determines whether add HEAD method automatically
// when GET method is added. Combo router will not be affected by this value.
func (b *Baa) SetAutoHead(v bool) {
	b.router.autoHead = v
}

// Route is a shortcut for same handlers but different HTTP methods.
//
// Example:
// 		baa.route("/", "GET,POST", h)
func (b *Baa) Route(pattern, methods string, h ...HandlerFunc) *Route {
	var ru *Route
	for _, m := range strings.Split(methods, ",") {
		ru = b.router.add(strings.TrimSpace(m), pattern, h)
	}
	return ru
}

// Group registers a list of same prefix route
func (b *Baa) Group(pattern string, f func(), h ...HandlerFunc) {
	b.router.groupAdd(pattern, f, h)
}

// Get is a shortcut for b.router.handle("GET", pattern, handlers)
func (b *Baa) Get(pattern string, h ...HandlerFunc) *Route {
	rs := b.router.add("GET", pattern, h)
	if b.router.autoHead {
		b.Head(pattern, h...)
	}
	return rs
}

// Patch is a shortcut for b.router.handle("PATCH", pattern, handlers)
func (b *Baa) Patch(pattern string, h ...HandlerFunc) *Route {
	return b.router.add("PATCH", pattern, h)
}

// Post is a shortcut for b.router.handle("POST", pattern, handlers)
func (b *Baa) Post(pattern string, h ...HandlerFunc) *Route {
	return b.router.add("POST", pattern, h)
}

// Put is a shortcut for b.router.handle("PUT", pattern, handlers)
func (b *Baa) Put(pattern string, h ...HandlerFunc) *Route {
	return b.router.add("PUT", pattern, h)
}

// Delete is a shortcut for b.router.handle("DELETE", pattern, handlers)
func (b *Baa) Delete(pattern string, h ...HandlerFunc) *Route {
	return b.router.add("DELETE", pattern, h)
}

// Options is a shortcut for b.router.handle("OPTIONS", pattern, handlers)
func (b *Baa) Options(pattern string, h ...HandlerFunc) *Route {
	return b.router.add("OPTIONS", pattern, h)
}

// Head is a shortcut for b.router.handle("HEAD", pattern, handlers)
func (b *Baa) Head(pattern string, h ...HandlerFunc) *Route {
	return b.router.add("HEAD", pattern, h)
}

// Any is a shortcut for b.router.handle("*", pattern, handlers)
func (b *Baa) Any(pattern string, h ...HandlerFunc) *Route {
	var ru *Route
	for m := range methods {
		ru = b.router.add(m, pattern, h)
	}
	return ru
}

// NotFound set not found route handler
func (b *Baa) NotFound(h HandlerFunc) {
	b.notFoundHandler = h
}

// Error execute internal error handler
func (b *Baa) Error(err error, c *Context) {
	if b.errorHandler != nil {
		b.errorHandler(err, c)
		return
	}
	http.Error(c.Resp, err.Error(), 500)
	if b.debug {
		b.Logger().Println("Error " + err.Error())
	}
}

// DefaultErrorHandler invokes the default HTTP error handler.
func (b *Baa) DefaultErrorHandler(err error, c *Context) {
	code := http.StatusInternalServerError
	msg := http.StatusText(code)
	if b.debug {
		msg = err.Error()
	}
	http.Error(c.Resp, msg, code)
}

// DefaultNotFoundHandler invokes the default HTTP error handler.
func (b *Baa) DefaultNotFoundHandler(c *Context) {
	code := http.StatusNotFound
	msg := http.StatusText(code)
	http.Error(c.Resp, msg, code)
}

// URLFor use named route return format url
func (b *Baa) URLFor(name string, args ...interface{}) string {
	return b.router.urlFor(name, args...)
}

// wrapMiddleware wraps middleware.
func wrapMiddleware(m Middleware) HandlerFunc {
	switch m := m.(type) {
	case HandlerFunc:
		return m
	case func(*Context):
		return m
	case http.Handler:
		return wrapHandlerFunc(func(c *Context) {
			m.ServeHTTP(c.Resp, c.Req)
		})
	case http.HandlerFunc:
		return wrapHandlerFunc(func(c *Context) {
			m(c.Resp, c.Req)
		})
	case func(http.ResponseWriter, *http.Request):
		return wrapHandlerFunc(func(c *Context) {
			m(c.Resp, c.Req)
		})
	default:
		panic("unknown middleware")
	}
}
<commit_msg>optimize router<commit_after>package baa

import (
	"log"
	"net/http"
	"os"
	"strings"
	"sync"
)

const (
	// DEV mode
	DEV = "development"
	// PROD mode
	PROD = "production"
	// TEST mode
	TEST = "test"
)

// Baa provlider an application
type Baa struct {
	debug           bool
	name            string
	di              *DI
	router          *Router
	pool            sync.Pool
	errorHandler    ErrorHandleFunc
	notFoundHandler HandlerFunc
	middleware      []HandlerFunc
}

// Middleware middleware handler
type Middleware interface{}

// Handler context handler
type Handler interface{}

// HandlerFunc context handler func
type HandlerFunc func(*Context)

// ErrorHandleFunc HTTP error handleFunc
type ErrorHandleFunc func(error, *Context)

// New create a baa application without any config.
func New() *Baa {
	b := new(Baa)
	b.middleware = make([]HandlerFunc, 0)
	b.pool = sync.Pool{
		New: func() interface{} {
			return newContext(nil, nil, b)
		},
	}
	if os.Getenv("Baa.Env") != PROD {
		b.debug = true
	}
	b.di = newDI()
	b.router = newRouter()
	b.errorHandler = b.DefaultErrorHandler
	b.notFoundHandler = b.DefaultNotFoundHandler
	b.SetDI("logger", log.New(os.Stderr, "[Baa] ", log.LstdFlags))
	b.SetDI("render", newRender())
	return b
}

// Server returns the internal *http.Server.
func (b *Baa) Server(addr string) *http.Server {
	s := &http.Server{Addr: addr}
	return s
}

// Run runs a server.
func (b *Baa) Run(addr string) {
	b.run(b.Server(addr))
}

// RunTLS runs a server with TLS configuration.
func (b *Baa) RunTLS(addr, certfile, keyfile string) {
	b.run(b.Server(addr), certfile, keyfile)
}

// RunServer runs a custom server.
func (b *Baa) RunServer(s *http.Server) {
	b.run(s)
}

// RunTLSServer runs a custom server with TLS configuration.
func (b *Baa) RunTLSServer(s *http.Server, crtFile, keyFile string) {
	b.run(s, crtFile, keyFile)
}

func (b *Baa) run(s *http.Server, files ...string) {
	s.Handler = b
	if len(files) == 0 {
		b.Logger().Printf("Listen %s", s.Addr)
		b.Logger().Fatal(s.ListenAndServe())
	} else if len(files) == 2 {
		b.Logger().Printf("Listen %s with TLS", s.Addr)
		b.Logger().Fatal(s.ListenAndServeTLS(files[0], files[1]))
	} else {
		b.Logger().Fatal("invalid TLS configuration")
	}
}

func (b *Baa) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	c := b.pool.Get().(*Context)
	c.reset(w, r)

	// build handler chain
	route := b.router.match(r.Method, r.URL.Path, c)
	// notFound
	if route == nil || route.handlers == nil {
		c.handlers = append(c.handlers, b.notFoundHandler)
	} else {
		c.handlers = append(c.handlers, route.handlers...)
	}

	c.Next()

	b.pool.Put(c)
}

// SetDebug set baa debug
func (b *Baa) SetDebug(v bool) {
	b.debug = v
}

// Logger return baa logger
func (b *Baa) Logger() Logger {
	return b.GetDI("logger").(Logger)
}

// Render return baa render
func (b *Baa) Render() Renderer {
	return b.GetDI("render").(Renderer)
}

// SetErrorHandler registers a custom Baa.ErrorHandleFunc.
func (b *Baa) SetErrorHandler(h ErrorHandleFunc) {
	b.errorHandler = h
}

// Use registers a middleware
func (b *Baa) Use(m ...Middleware) {
	for i := range m {
		b.middleware = append(b.middleware, wrapMiddleware(m[i]))
	}
}

// SetDI registers a dependency injection
func (b *Baa) SetDI(name string, h interface{}) {
	b.di.set(name, h)
}

// GetDI fetch a registered dependency injection
func (b *Baa) GetDI(name string) interface{} {
	return b.di.get(name)
}

// Static set static file route
// h used for set Expries ...
func (b *Baa) Static(prefix string, dir string, index bool, h HandlerFunc) {
	if prefix == "" {
		panic("baa.Static prefix can not be empty")
	}
	if dir == "" {
		panic("baa.Static dir can not be empty")
	}
	staticHandler := newStatic(prefix, dir, index, h)
	b.Get(prefix, staticHandler)
	b.Get(prefix+":file", staticHandler)
}

// SetAutoHead sets the value who determines whether add HEAD method automatically
// when GET method is added. Combo router will not be affected by this value.
func (b *Baa) SetAutoHead(v bool) {
	b.router.autoHead = v
}

// Route is a shortcut for same handlers but different HTTP methods.
//
// Example:
// 		baa.route("/", "GET,POST", h)
func (b *Baa) Route(pattern, methods string, h ...HandlerFunc) *Route {
	var ru *Route
	for _, m := range strings.Split(methods, ",") {
		ru = b.router.add(strings.TrimSpace(m), pattern, h)
	}
	return ru
}

// Group registers a list of same prefix route
func (b *Baa) Group(pattern string, f func(), h ...HandlerFunc) {
	b.router.groupAdd(pattern, f, h)
}

// Get is a shortcut for b.router.handle("GET", pattern, handlers)
func (b *Baa) Get(pattern string, h ...HandlerFunc) *Route {
	rs := b.router.add("GET", pattern, h)
	if b.router.autoHead {
		b.Head(pattern, h...)
	}
	return rs
}

// Patch is a shortcut for b.router.handle("PATCH", pattern, handlers)
func (b *Baa) Patch(pattern string, h ...HandlerFunc) *Route {
	return b.router.add("PATCH", pattern, h)
}

// Post is a shortcut for b.router.handle("POST", pattern, handlers)
func (b *Baa) Post(pattern string, h ...HandlerFunc) *Route {
	return b.router.add("POST", pattern, h)
}

// Put is a shortcut for b.router.handle("PUT", pattern, handlers)
func (b *Baa) Put(pattern string, h ...HandlerFunc) *Route {
	return b.router.add("PUT", pattern, h)
}

// Delete is a shortcut for b.router.handle("DELETE", pattern, handlers)
func (b *Baa) Delete(pattern string, h ...HandlerFunc) *Route {
	return b.router.add("DELETE", pattern, h)
}

// Options is a shortcut for b.router.handle("OPTIONS", pattern, handlers)
func (b *Baa) Options(pattern string, h ...HandlerFunc) *Route {
	return b.router.add("OPTIONS", pattern, h)
}

// Head is a shortcut for b.router.handle("HEAD", pattern, handlers)
func (b *Baa) Head(pattern string, h ...HandlerFunc) *Route {
	return b.router.add("HEAD", pattern, h)
}

// Any is a shortcut for b.router.handle("*", pattern, handlers)
func (b *Baa) Any(pattern string, h ...HandlerFunc) *Route {
	var ru *Route
	for m := range methods {
		ru = b.router.add(m, pattern, h)
	}
	return ru
}

// NotFound set not found route handler
func (b *Baa) NotFound(h HandlerFunc) {
	b.notFoundHandler = h
}

// Error execute internal error handler
func (b *Baa) Error(err error, c *Context) {
	if b.errorHandler != nil {
		b.errorHandler(err, c)
		return
	}
	http.Error(c.Resp, err.Error(), 500)
	if b.debug {
		b.Logger().Println("Error " + err.Error())
	}
}

// DefaultErrorHandler invokes the default HTTP error handler.
func (b *Baa) DefaultErrorHandler(err error, c *Context) {
	code := http.StatusInternalServerError
	msg := http.StatusText(code)
	if b.debug {
		msg = err.Error()
	}
	http.Error(c.Resp, msg, code)
}

// DefaultNotFoundHandler invokes the default HTTP error handler.
func (b *Baa) DefaultNotFoundHandler(c *Context) {
	code := http.StatusNotFound
	msg := http.StatusText(code)
	http.Error(c.Resp, msg, code)
}

// URLFor use named route return format url
func (b *Baa) URLFor(name string, args ...interface{}) string {
	return b.router.urlFor(name, args...)
}

// wrapMiddleware wraps middleware.
func wrapMiddleware(m Middleware) HandlerFunc {
	switch m := m.(type) {
	case HandlerFunc:
		return m
	case func(*Context):
		return m
	case http.Handler:
		return wrapHandlerFunc(func(c *Context) {
			m.ServeHTTP(c.Resp, c.Req)
		})
	case http.HandlerFunc:
		return wrapHandlerFunc(func(c *Context) {
			m(c.Resp, c.Req)
		})
	case func(http.ResponseWriter, *http.Request):
		return wrapHandlerFunc(func(c *Context) {
			m(c.Resp, c.Req)
		})
	default:
		panic("unknown middleware")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/v4run/bob/bLogger"
	"github.com/v4run/bob/watcher"
	"os"
	"path/filepath"
	"flag"
	"fmt"
	"github.com/v4run/bob/graceful"
)

const (
	VERSION = "1.0.0"
)

var (
	path string
	version bool
	help bool
	l = bLogger.Logger()
)

func init() {
	flag.StringVar(&path, "d", "", "-d <directory to watch>")
	flag.StringVar(&path, "dir", "", "-dir <directory to watch>")
	flag.BoolVar(&version, "v", false, "-v <directory to watch>")
	flag.BoolVar(&version, "version", false, "-version <directory to watch>")
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: bob [options]\n")
		fmt.Fprintf(os.Stderr, "options:\n")
		fmt.Fprintf(os.Stderr, "\t-d, -directory Directory   The directory to watch.\n")
		fmt.Fprintf(os.Stderr, "\t-v, -version   Version     Prints the version.\n")
		fmt.Fprintf(os.Stderr, "\t-h, -help      Help        Show this help.\n")
	}
}

func parseFlags() {
	flag.Parse()

	if version {
		fmt.Printf("bob v%s\n", VERSION)
		os.Exit(0)
	}

	if help {
		flag.Usage()
		os.Exit(0)
	}

	if path == "" {
		dir, _ := filepath.Abs(filepath.Dir(os.Args[0]))
		path = dir
	}
}

func main() {
	go graceful.ActivateGracefulShutdown()
	parseFlags()
	dir, _ := filepath.Abs(filepath.Dir(os.Args[0]))
	w := watcher.NewWatcher(dir)
	if err := w.Watch(); err != nil {
		l.Error(err.Error())
		os.Exit(1)
	}
}
<commit_msg>typo fix<commit_after>package main

import (
	"github.com/v4run/bob/bLogger"
	"github.com/v4run/bob/watcher"
	"os"
	"path/filepath"
	"flag"
	"fmt"
	"github.com/v4run/bob/graceful"
)

const (
	VERSION = "1.0.0"
)

var (
	path string
	version bool
	help bool
	l = bLogger.Logger()
)

func init() {
	flag.StringVar(&path, "d", "", "-d <directory to watch>")
	flag.StringVar(&path, "dir", "", "-dir <directory to watch>")
	flag.BoolVar(&version, "v", false, "-v <directory to watch>")
	flag.BoolVar(&version, "version", false, "-version <directory to watch>")
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: bob [options]\n")
		fmt.Fprintf(os.Stderr, "options:\n")
		fmt.Fprintf(os.Stderr, "\t-d, -dir Directory   The directory to watch.\n")
		fmt.Fprintf(os.Stderr, "\t-v, -version   Version     Prints the version.\n")
		fmt.Fprintf(os.Stderr, "\t-h, -help      Help        Show this help.\n")
	}
}

func parseFlags() {
	flag.Parse()

	if version {
		fmt.Printf("bob v%s\n", VERSION)
		os.Exit(0)
	}

	if help {
		flag.Usage()
		os.Exit(0)
	}

	if path == "" {
		dir, _ := filepath.Abs(filepath.Dir(os.Args[0]))
		path = dir
	}
}

func main() {
	go graceful.ActivateGracefulShutdown()
	parseFlags()
	dir, _ := filepath.Abs(filepath.Dir(os.Args[0]))
	w := watcher.NewWatcher(dir)
	if err := w.Watch(); err != nil {
		l.Error(err.Error())
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package bob

import (
	"github.com/rafecolton/bob/dclient"
	"github.com/rafecolton/bob/log"
	"github.com/rafecolton/bob/parser"
)

import (
	"github.com/hishboy/gocommons/lang"
	"github.com/onsi/gocleanup"
	"github.com/wsxiaoys/terminal/color"
)

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
)

/*
A Builder is the struct that actually does the work of moving files around and
executing the commands that do the docker build.
*/
type Builder struct {
	dockerClient dclient.DockerClient
	log.Logger
	workdir         string
	isRegular       bool
	nextSubSequence *parser.SubSequence
	Stderr          io.Writer
	Stdout          io.Writer
	Builderfile     string
}

/*
SetNextSubSequence sets the next subsequence within bob to be processed. This
function is exported because it is used explicitly in tests, but in Build(), it
is intended to be used as a helper function.
*/
func (bob *Builder) SetNextSubSequence(subSeq *parser.SubSequence) {
	bob.nextSubSequence = subSeq
}

/*
NewBuilder returns an instance of a Builder struct.  The function exists in
case we want to initialize our Builders with something.
*/
func NewBuilder(logger log.Logger, shouldBeRegular bool) *Builder {
	if logger == nil {
		logger = &log.NullLogger{}
	}

	client, err := dclient.NewDockerClient(logger, shouldBeRegular)

	if err != nil {
		return nil
	}

	return &Builder{
		dockerClient: client,
		Logger:       logger,
		isRegular:    shouldBeRegular,
		Stdout:       log.NewOutWriter(logger, "         @{g}%s@{|}"),
		Stderr:       log.NewOutWriter(logger, "         @{r}%s@{|}"),
	}
}

/*
Build is currently a placeholder function but will eventually be used to do the
actual work of building.
*/
func (bob *Builder) Build(commandSequence *parser.CommandSequence) error {
	for _, seq := range commandSequence.Commands {
		bob.CleanWorkdir()
		bob.SetNextSubSequence(seq)
		bob.Setup()

		workdir := bob.Workdir()

		bob.Println(color.Sprintf("@{w!}  ----->  Running commands for %q @{|}", seq.Metadata.Name))

		var imageID string
		var err error

		for _, cmd := range seq.SubCommand {
			cmd.Stdout = bob.Stdout
			cmd.Stderr = bob.Stderr
			cmd.Dir = workdir

			if cmd.Path == "docker" {
				path, err := exec.LookPath("docker")
				if err != nil {
					return err
				}

				cmd.Path = path
			}

			switch cmd.Args[1] {
			case "build":
				bob.Println(color.Sprintf("@{w!}  ----->  Running command %s @{|}", cmd.Args))
				if err := cmd.Run(); err != nil {
					return err
				}

				imageID, err = bob.LatestImageTaggedWithUUID(seq.Metadata.UUID)
				if err != nil {
					return err
				}
			case "tag":
				cmd.Args[2] = imageID
				bob.Println(color.Sprintf("@{w!}  ----->  Running command %s @{|}", cmd.Args))

				if err := cmd.Run(); err != nil {
					return err
				}
			case "push":
				bob.Println(color.Sprintf("@{w!}  ----->  Running command %s @{|}", cmd.Args))

				if err := cmd.Run(); err != nil {
					return err
				}
			default:
				return errors.New(
					color.Sprintf(
						"@{r!}oops, looks like the command you're asking me to run is improperly formed:@{|} %s\n",
						cmd.Args,
					),
				)
			}
		}
	}

	return nil
}

/*
Setup moves all of the correct files into place in the temporary directory in
order to perform the docker build.
*/
func (bob *Builder) Setup() error {
	if bob.nextSubSequence == nil {
		return errors.New("no command sub sequence set, cannot perform setup")
	}

	meta := bob.nextSubSequence.Metadata
	fileSet := lang.NewHashSet()

	if len(meta.Included) == 0 {
		files, err := ioutil.ReadDir(bob.Repodir())
		if err != nil {
			return err
		}

		for _, v := range files {
			fileSet.Add(v.Name())
		}
	} else {
		for _, v := range meta.Included {
			fileSet.Add(v)
		}
	}

	// subtract any excludes from fileSet
	for _, exclude := range meta.Excluded {
		if fileSet.Contains(exclude) {
			fileSet.Remove(exclude)
		}
	}

	if fileSet.Contains("Dockerfile") {
		fileSet.Remove("Dockerfile")
	}

	// add the Dockerfile
	fileSet.Add(meta.Dockerfile)

	workdir := bob.Workdir()
	repodir := bob.Repodir()

	// copy the actual files over
	for _, file := range fileSet.ToSlice() {
		src := fmt.Sprintf("%s/%s", repodir, file)
		dest := fmt.Sprintf("%s/%s", workdir, file)

		if file == meta.Dockerfile {
			dest = fmt.Sprintf("%s/%s", workdir, "Dockerfile")
		}

		fileInfo, err := os.Stat(src)
		if err != nil {
			return err
		}

		if fileInfo.IsDir() {
			err = CopyDir(src, dest)
		} else {
			err = CopyFile(src, dest)
		}
		if err != nil {
			return err
		}
	}

	return nil
}

/*
Repodir is the dir from which we are using files for our docker builds.
*/
func (bob *Builder) Repodir() string {
	if !bob.isRegular {
		repoDir := "spec/fixtures/repodir"
		return fmt.Sprintf("%s/%s", os.Getenv("PWD"), repoDir)
	}
	return filepath.Dir(bob.Builderfile)
}

/*
Workdir returns bob's working directory.
*/
func (bob *Builder) Workdir() string {
	return bob.workdir
}

func (bob *Builder) generateWorkDir() string {
	if !bob.isRegular {
		specWorkdir := "spec/fixtures/workdir"
		return fmt.Sprintf("%s/%s", os.Getenv("PWD"), specWorkdir)
	}

	tmp, err := ioutil.TempDir("", "bob")
	if err != nil {
		return ""
	}

	gocleanup.Register(func() {
		os.RemoveAll(tmp)
	})

	return tmp
}

/*
CleanWorkdir effectively does a rm -rf and mkdir -p on bob's workdir.  Intended
to be used before using the workdir (i.e. before new command groups).
*/
func (bob *Builder) CleanWorkdir() error {
	workdir := bob.generateWorkDir()
	bob.workdir = workdir

	if !bob.isRegular {
		readme := fmt.Sprintf("%s/README.txt", workdir)
		os.RemoveAll(workdir)
		err := os.MkdirAll(workdir, 0755)
		if err != nil {
			return err
		}

		file, err := os.Create(readme)
		if err != nil {
			return err
		}
		defer file.Close()

		bytes := []byte("This directory tree is used for specs - please do not modify.\n")
		if _, err := file.Write(bytes); err != nil {
			return err
		}

		return nil
	}

	os.RemoveAll(workdir)
	err := os.MkdirAll(workdir, 0755)
	if err != nil {
		return err
	}

	return nil
}

/*
LatestImageTaggedWithUUID accepts a uuid and invokes the underlying utility
DockerClient to determine the id of the most recently created image tagged with
the provided uuid.
*/
func (bob *Builder) LatestImageTaggedWithUUID(uuid string) (string, error) {
	id, err := bob.dockerClient.LatestImageTaggedWithUUID(uuid)
	if err != nil {
		bob.Println(err)
		return "", err
	}

	return id, nil
}
<commit_msg>Not trying to use a special workdir for specs<commit_after>package bob

import (
	"github.com/rafecolton/bob/dclient"
	"github.com/rafecolton/bob/log"
	"github.com/rafecolton/bob/parser"
)

import (
	"github.com/hishboy/gocommons/lang"
	"github.com/onsi/gocleanup"
	"github.com/wsxiaoys/terminal/color"
)

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
)

/*
A Builder is the struct that actually does the work of moving files around and
executing the commands that do the docker build.
*/
type Builder struct {
	dockerClient dclient.DockerClient
	log.Logger
	workdir         string
	isRegular       bool
	nextSubSequence *parser.SubSequence
	Stderr          io.Writer
	Stdout          io.Writer
	Builderfile     string
}

/*
SetNextSubSequence sets the next subsequence within bob to be processed. This
function is exported because it is used explicitly in tests, but in Build(), it
is intended to be used as a helper function.
*/
func (bob *Builder) SetNextSubSequence(subSeq *parser.SubSequence) {
	bob.nextSubSequence = subSeq
}

/*
NewBuilder returns an instance of a Builder struct.  The function exists in
case we want to initialize our Builders with something.
*/
func NewBuilder(logger log.Logger, shouldBeRegular bool) *Builder {
	if logger == nil {
		logger = &log.NullLogger{}
	}

	client, err := dclient.NewDockerClient(logger, shouldBeRegular)

	if err != nil {
		return nil
	}

	return &Builder{
		dockerClient: client,
		Logger:       logger,
		isRegular:    shouldBeRegular,
		Stdout:       log.NewOutWriter(logger, "         @{g}%s@{|}"),
		Stderr:       log.NewOutWriter(logger, "         @{r}%s@{|}"),
	}
}

/*
Build is currently a placeholder function but will eventually be used to do the
actual work of building.
*/
func (bob *Builder) Build(commandSequence *parser.CommandSequence) error {
	for _, seq := range commandSequence.Commands {
		bob.CleanWorkdir()
		bob.SetNextSubSequence(seq)
		bob.Setup()

		workdir := bob.Workdir()

		bob.Println(color.Sprintf("@{w!}  ----->  Running commands for %q @{|}", seq.Metadata.Name))

		var imageID string
		var err error

		for _, cmd := range seq.SubCommand {
			cmd.Stdout = bob.Stdout
			cmd.Stderr = bob.Stderr
			cmd.Dir = workdir

			if cmd.Path == "docker" {
				path, err := exec.LookPath("docker")
				if err != nil {
					return err
				}

				cmd.Path = path
			}

			switch cmd.Args[1] {
			case "build":
				bob.Println(color.Sprintf("@{w!}  ----->  Running command %s @{|}", cmd.Args))
				if err := cmd.Run(); err != nil {
					return err
				}

				imageID, err = bob.LatestImageTaggedWithUUID(seq.Metadata.UUID)
				if err != nil {
					return err
				}
			case "tag":
				cmd.Args[2] = imageID
				bob.Println(color.Sprintf("@{w!}  ----->  Running command %s @{|}", cmd.Args))

				if err := cmd.Run(); err != nil {
					return err
				}
			case "push":
				bob.Println(color.Sprintf("@{w!}  ----->  Running command %s @{|}", cmd.Args))

				if err := cmd.Run(); err != nil {
					return err
				}
			default:
				return errors.New(
					color.Sprintf(
						"@{r!}oops, looks like the command you're asking me to run is improperly formed:@{|} %s\n",
						cmd.Args,
					),
				)
			}
		}
	}

	return nil
}

/*
Setup moves all of the correct files into place in the temporary directory in
order to perform the docker build.
*/
func (bob *Builder) Setup() error {
	if bob.nextSubSequence == nil {
		return errors.New("no command sub sequence set, cannot perform setup")
	}

	meta := bob.nextSubSequence.Metadata
	fileSet := lang.NewHashSet()

	if len(meta.Included) == 0 {
		files, err := ioutil.ReadDir(bob.Repodir())
		if err != nil {
			return err
		}

		for _, v := range files {
			fileSet.Add(v.Name())
		}
	} else {
		for _, v := range meta.Included {
			fileSet.Add(v)
		}
	}

	// subtract any excludes from fileSet
	for _, exclude := range meta.Excluded {
		if fileSet.Contains(exclude) {
			fileSet.Remove(exclude)
		}
	}

	if fileSet.Contains("Dockerfile") {
		fileSet.Remove("Dockerfile")
	}

	// add the Dockerfile
	fileSet.Add(meta.Dockerfile)

	workdir := bob.Workdir()
	repodir := bob.Repodir()

	// copy the actual files over
	for _, file := range fileSet.ToSlice() {
		src := fmt.Sprintf("%s/%s", repodir, file)
		dest := fmt.Sprintf("%s/%s", workdir, file)

		if file == meta.Dockerfile {
			dest = fmt.Sprintf("%s/%s", workdir, "Dockerfile")
		}

		fileInfo, err := os.Stat(src)
		if err != nil {
			return err
		}

		if fileInfo.IsDir() {
			err = CopyDir(src, dest)
		} else {
			err = CopyFile(src, dest)
		}
		if err != nil {
			return err
		}
	}

	return nil
}

/*
Repodir is the dir from which we are using files for our docker builds.
*/
func (bob *Builder) Repodir() string {
	if !bob.isRegular {
		repoDir := "spec/fixtures/repodir"
		return fmt.Sprintf("%s/%s", os.Getenv("PWD"), repoDir)
	}
	return filepath.Dir(bob.Builderfile)
}

/*
Workdir returns bob's working directory.
*/
func (bob *Builder) Workdir() string {
	return bob.workdir
}

func (bob *Builder) generateWorkDir() string {
	tmp, err := ioutil.TempDir("", "bob")
	if err != nil {
		return ""
	}

	gocleanup.Register(func() {
		os.RemoveAll(tmp)
	})

	return tmp
}

/*
CleanWorkdir effectively does a rm -rf and mkdir -p on bob's workdir.  Intended
to be used before using the workdir (i.e. before new command groups).
*/
func (bob *Builder) CleanWorkdir() error {
	workdir := bob.generateWorkDir()
	bob.workdir = workdir

	if err := os.RemoveAll(workdir); err != nil {
		return err
	}

	if err := os.MkdirAll(workdir, 0755); err != nil {
		return err
	}

	return nil
}

/*
LatestImageTaggedWithUUID accepts a uuid and invokes the underlying utility
DockerClient to determine the id of the most recently created image tagged with
the provided uuid.
*/
func (bob *Builder) LatestImageTaggedWithUUID(uuid string) (string, error) {
	id, err := bob.dockerClient.LatestImageTaggedWithUUID(uuid)
	if err != nil {
		bob.Println(err)
		return "", err
	}

	return id, nil
}
<|endoftext|>


<commit_before>package main

import (
	"./twitch"
	"./wisdom"
	"fmt"
	"github.com/thoj/go-ircevent"
	"strings"
)

func main() {
	channel := "#r/test"
	con := irc.IRC("Tresdin", "Tresdin")
	err := con.Connect("irc.quakenet.org:6667")
	if err != nil {
		fmt.Println("Failed connecting")
		return
	}
	con.AddCallback("001", func(e *irc.Event) {
		con.Join(channel)
	})
	con.AddCallback("PRIVMSG", func(e *irc.Event) {
		switch e.Message() {
		case "!matches", "!m", "!t", "!tournament":
			s := strings.Join(twitch.TournamentStreams(), " - ")
			if len(s) == 0 {
				con.Privmsg(channel, "No tournaments live.")
			} else {
				con.Privmsg(channel, s)
			}
		case "!all", "!a":
			con.Privmsg(channel, strings.Join(twitch.Dota2Streams(), " - "))
		case "!help", "!h":
			con.Privmsg(channel, "Use !s for filtered streams, !a for all streams.")
		case "!scores":
			con.Privmsg(channel, "no scores")
		case "!favorites", "!f":
			con.Privmsg(channel, strings.Join(twitch.FavoriteDota2Streams(), " - "))
		case "!streams", "!s":
			con.Privmsg(channel, strings.Join(twitch.FilteredDota2Streams(), " - "))
		}
	})

	go twitch.WatchFavorites(func(m string) {
		con.Privmsg(channel, m)
	})
	go twitch.WatchTournaments(func(m string) {
		con.Privmsg(channel, m)
	})

	con.Loop()
}
<commit_msg>removed test channel<commit_after>package main

import (
	"./twitch"
	"fmt"
	"github.com/thoj/go-ircevent"
	"strings"
)

func main() {
	channel := "#r/dota2"
	con := irc.IRC("Tresdin", "Tresdin")
	err := con.Connect("irc.quakenet.org:6667")
	if err != nil {
		fmt.Println("Failed connecting")
		return
	}
	con.AddCallback("001", func(e *irc.Event) {
		con.Join(channel)
	})
	con.AddCallback("PRIVMSG", func(e *irc.Event) {
		switch e.Message() {
		case "!matches", "!m", "!t", "!tournament":
			s := strings.Join(twitch.TournamentStreams(), " - ")
			if len(s) == 0 {
				con.Privmsg(channel, "No tournaments live.")
			} else {
				con.Privmsg(channel, s)
			}
		case "!all", "!a":
			con.Privmsg(channel, strings.Join(twitch.Dota2Streams(), " - "))
		case "!help", "!h":
			con.Privmsg(channel, "Use !s for filtered streams, !a for all streams.")
		case "!scores":
			con.Privmsg(channel, "no scores")
		case "!favorites", "!f":
			con.Privmsg(channel, strings.Join(twitch.FavoriteDota2Streams(), " - "))
		case "!streams", "!s":
			con.Privmsg(channel, strings.Join(twitch.FilteredDota2Streams(), " - "))
		}
	})

	go twitch.WatchFavorites(func(m string) {
		con.Privmsg(channel, m)
	})
	go twitch.WatchTournaments(func(m string) {
		con.Privmsg(channel, m)
	})

	con.Loop()
}
<|endoftext|>


<commit_before>// Brief: Bot logic
// Primary responsibility: Top level logic layer for bot

package main

import (
	"log"

	bmul "github.com/julwrites/BotMultiplexer"
)

func HelpMessage(env *bmul.SessionData) {
	env.Res.Message = "Hi, this message comes from the bot"
}

func RunCommands(env *bmul.SessionData) {
	switch env.Msg.Command {
	default:
		GetBiblePassage(env)
	}
}

func HandleBotLogic(env *bmul.SessionData) {
	RunCommands(env)

	log.Printf("Commands run, resulting message: %s", env.Res.Message)
	if len(env.Res.Message) == 0 {
		log.Printf("This message was not handled by bot")
		HelpMessage(env)
	}
}
<commit_msg>Copying over help message from Release 1<commit_after>// Brief: Bot logic
// Primary responsibility: Top level logic layer for bot

package main

import (
	"log"

	bmul "github.com/julwrites/BotMultiplexer"
)

func HelpMessage(env *bmul.SessionData) {
	env.Res.Message = "Hello %s! Give me a Bible reference and I'll give you the passage!" //\nHere are some other things I can do:\n/tms - Get a card from the Navigators' Topical Memory System\n/version - Choose your preferred Bible version\n/dailydevo - Get reading material right now\n/subscribe - Subscribe to / Unsubscribe from daily reading material\n/search - Search for a passage, lexicon entry, word or phrase\n"
}

func RunCommands(env *bmul.SessionData) {
	switch env.Msg.Command {
	default:
		GetBiblePassage(env)
	}
}

func HandleBotLogic(env *bmul.SessionData) {
	RunCommands(env)

	log.Printf("Commands run, resulting message: %s", env.Res.Message)
	if len(env.Res.Message) == 0 {
		log.Printf("This message was not handled by bot")
		HelpMessage(env)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/aws/aws-lambda-go/lambda"
	"github.com/gocolly/colly"
	"io"
	"log"
	"net/http"
	"os"
	"strconv"
	"time"

	"github.com/go-telegram-bot-api/telegram-bot-api"
)

type post struct {
	URL       string
	Timestamp int64
	Author    string
	Comment   string
	Images    []string
}

var (
	TOKEN = os.Getenv("token")
	URL   = "https://www.kaffee-netz.de"
)

var topics = map[string]string{
	"Wie sieht eure Kaffee-Ecke aus?":                     "/threads/wie-sieht-eure-kaffee-ecke-aus.13966",
	"Der \"Ich habe gerade Kaffeekram gekauft\" Thread":   "/threads/der-ich-habe-gerade-kaffeekram-gekauft-thread.62180",
	"Und plötzlich war da Latte Art":                      "/threads/und-ploetzlich-war-da-latte-art.7785",
	"Ich trinke gerade diesen Filterkaffee/Brühkaffee...": "/threads/ich-trinke-gerade-diesen-espresso.19308",
	"3rd Wave Röster und Röstungen":                       "/threads/3rd-wave-roester-und-roestungen.79568",
}

func HandleRequest() {
	bot, err := tgbotapi.NewBotAPI(TOKEN)
	if err != nil {
		log.Panic(err)
	}

	posts := make([]*post, 0)

	c := colly.NewCollector(
		colly.UserAgent("Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"),
	)

	c.OnRequest(func(r *colly.Request) {
		r.Ctx.Put("url", r.URL.String())
	})

	c.OnHTML(".mainContent", func(e *colly.HTMLElement) {
		lastPage := e.ChildAttr(`.PageNav`, "data-last")
		currentUrl := e.Response.Ctx.Get("url")
		_ = e.Request.Visit(currentUrl + "/page-" + lastPage)

		e.ForEach("ol.messageList li", func(i int, element *colly.HTMLElement) {
			// Only last posts have timestamps
			timestamp, err := strconv.Atoi(element.ChildAttr(".DateTime", "data-time"))
			if err == nil {
				// If images are found, put it to the array
				images := element.ChildAttrs(".LbImage", "src")
				if images != nil {
					p := &post{
						URL:       URL + "/" + element.ChildAttr("a.hashPermalink", "href"),
						Timestamp: int64(timestamp * 1000), // To milliseconds
						Author:    element.Attr("data-author"),
						Comment:   element.ChildText(".messageText"),
						Images:    images,
					}
					posts = append(posts, p)
				}
			}
		})
	})

	for _, topic := range topics {
		_ = c.Visit(URL + topic)
	}

	enc := json.NewEncoder(os.Stdout)
	enc.SetIndent("", "  ")

	for _, post := range posts {
		_ = enc.Encode(post)
		if post.Timestamp+3600000 >= Now() {
			SendPost(bot, *post)
		}
	}
}

func SendPost(bot *tgbotapi.BotAPI, p post) {
	chatId := int64(405001)

	msg := fmt.Sprintf("%s: %s", p.Author, p.Comment)
	msg += "\n" + p.URL
	textMsg := tgbotapi.NewMessage(chatId, msg)
	bot.Send(textMsg)

	for _, image := range p.Images {
		data, _ := DownloadFile(image)
		file := tgbotapi.FileBytes{Name: p.URL, Bytes: data}
		msg := tgbotapi.NewPhotoUpload(chatId, file)
		bot.Send(msg)
	}
}

func DownloadFile(url string) ([]byte, error) {

	// Get the data
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// Write the body to file
	buf := new(bytes.Buffer)
	_, err = io.Copy(buf, resp.Body)
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

func Now() int64 {
	return time.Now().UnixNano()/int64(time.Millisecond) - 3600000 // Locale: Europe/Berlin
}

func main() {
	lambda.Start(HandleRequest)
}
<commit_msg>minor update<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/aws/aws-lambda-go/lambda"
	"github.com/gocolly/colly"
	"io"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/go-telegram-bot-api/telegram-bot-api"
)

type post struct {
	URL       string
	Timestamp int64
	Author    string
	Comment   string
	Images    []string
}

var (
	TOKEN = os.Getenv("TOKEN")
	URL   = "https://www.kaffee-netz.de"
)

var topics = map[string]string{
	"Wie sieht eure Kaffee-Ecke aus?":                     "/threads/wie-sieht-eure-kaffee-ecke-aus.13966",
	"Der \"Ich habe gerade Kaffeekram gekauft\" Thread":   "/threads/der-ich-habe-gerade-kaffeekram-gekauft-thread.62180",
	"Und plötzlich war da Latte Art":                      "/threads/und-ploetzlich-war-da-latte-art.7785",
	"Ich trinke gerade diesen Filterkaffee/Brühkaffee...": "/threads/ich-trinke-gerade-diesen-espresso.19308",
	"3rd Wave Röster und Röstungen":                       "/threads/3rd-wave-roester-und-roestungen.79568",
}

func HandleRequest() {
	bot, err := tgbotapi.NewBotAPI(TOKEN)
	if err != nil {
		log.Panic(err)
	}

	posts := make([]*post, 0)

	c := colly.NewCollector(
		colly.UserAgent("Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"),
	)

	c.OnRequest(func(r *colly.Request) {
		r.Ctx.Put("url", r.URL.String())
	})

	c.OnHTML(".mainContent", func(e *colly.HTMLElement) {
		lastPage := e.ChildAttr(`.PageNav`, "data-last")
		currentUrl := e.Response.Ctx.Get("url")
		_ = e.Request.Visit(currentUrl + "/page-" + lastPage)

		e.ForEach("ol.messageList li", func(i int, element *colly.HTMLElement) {
			// Only last posts have timestamps
			timestamp, err := strconv.Atoi(element.ChildAttr(".DateTime", "data-time"))
			if err == nil {
				// If images are found, put it to the array
				images := element.ChildAttrs(".LbImage", "src")
				if images != nil {
					p := &post{
						URL:       URL + "/" + element.ChildAttr("a.hashPermalink", "href"),
						Timestamp: int64(timestamp * 1000), // To milliseconds
						Author:    element.Attr("data-author"),
						Comment:   element.ChildText(".messageText"),
						Images:    images,
					}
					posts = append(posts, p)
				}
			}
		})
	})

	for _, topic := range topics {
		_ = c.Visit(URL + topic)
	}

	enc := json.NewEncoder(os.Stdout)
	enc.SetIndent("", "  ")

	for _, post := range posts {
		_ = enc.Encode(post)
		if post.Timestamp+3600000 >= Now() {
			SendPost(bot, *post)
		}
	}
}

func SendPost(bot *tgbotapi.BotAPI, p post) {
	chatId := int64(405001)

	msg := fmt.Sprintf("%s: %s", p.Author, p.Comment)
	msg += "\n" + p.URL
	textMsg := tgbotapi.NewMessage(chatId, msg)
	bot.Send(textMsg)

	for _, image := range p.Images {
		if !strings.HasPrefix(image, URL) {
			image = URL + "/" + image
		}
		data, _ := DownloadFile(image)
		file := tgbotapi.FileBytes{Name: p.URL, Bytes: data}
		msg := tgbotapi.NewPhotoUpload(chatId, file)
		bot.Send(msg)
	}
}

func DownloadFile(url string) ([]byte, error) {

	// Get the data
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// Write the body to file
	buf := new(bytes.Buffer)
	_, err = io.Copy(buf, resp.Body)
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

func Now() int64 {
	return time.Now().UnixNano()/int64(time.Millisecond) - 3600000 // Locale: Europe/Berlin
}

func main() {
	lambda.Start(HandleRequest)
}
<|endoftext|>


<commit_before>package box

import (
	"context"
	"fmt"
	"io"
	"regexp"
	"strings"

	"github.com/mattn/go-runewidth"
)

var ansiCutter = regexp.MustCompile("\x1B[^a-zA-Z]*[A-Za-z]")

func Print(ctx context.Context, nodes []string, out io.Writer) bool {
	b := New()
	b.Height = 0
	value, _, _ := b.Print(ctx, nodes, 0, out)
	return value
}

func (b *box_t) Print(ctx context.Context,
	nodes []string,
	offset int,
	out io.Writer) (bool, int, int) {
	maxLen := 1
	for _, finfo := range nodes {
		length := runewidth.StringWidth(ansiCutter.ReplaceAllString(finfo, ""))
		if length > maxLen {
			maxLen = length
		}
	}
	nodePerLine := (b.Width - 1) / (maxLen + 1)
	if nodePerLine <= 0 {
		nodePerLine = 1
	}
	nlines := (len(nodes) + nodePerLine - 1) / nodePerLine

	lines := make([][]byte, nlines)
	row := 0
	for _, finfo := range nodes {
		lines[row] = append(lines[row], finfo...)
		w := runewidth.StringWidth(ansiCutter.ReplaceAllString(finfo, ""))
		if maxLen < b.Width {
			for i := maxLen + 1; i > w; i-- {
				lines[row] = append(lines[row], ' ')
			}
		}
		row++
		if row >= nlines {
			row = 0
		}
	}
	i_end := len(lines)
	if b.Height > 0 {
		if i_end >= offset+b.Height {
			i_end = offset + b.Height
		}
	}

	i := offset
	for {
		fmt.Fprint(out, string(lines[i]))
		fmt.Fprint(out, "\x1B[0K")
		if ctx != nil {
			select {
			case <-ctx.Done():
				return false, nodePerLine, nlines
			default:
			}
		}
		i++
		if i >= i_end {
			break
		}
		fmt.Fprintln(out)
	}
	return true, nodePerLine, nlines
}

const (
	CURSOR_OFF = "\x1B[?25l"
	CURSOR_ON  = "\x1B[?25h"
	BOLD_ON    = "\x1B[0;47;30m"
	BOLD_OFF   = "\x1B[0m"

	K_LEFT  = 0x25
	K_RIGHT = 0x27
	K_UP    = 0x26
	K_DOWN  = 0x28
)

func truncate(s string, w int) string {
	return runewidth.Truncate(strings.TrimSpace(s), w, "")
}

const (
	NONE  = 0
	LEFT  = 1
	DOWN  = 2
	UP    = 3
	RIGHT = 4
	ENTER = 5
	LEAVE = 6
)

func Choice(sources []string, out io.Writer) string {
	cursor := 0
	nodes := make([]string, 0, len(sources))
	draws := make([]string, 0, len(sources))
	b := New()
	defer b.Close()
	for _, text := range sources {
		val := truncate(text, b.Width-1)
		if val != "" {
			nodes = append(nodes, val)
			draws = append(draws, val)
		}
	}
	io.WriteString(out, CURSOR_OFF)
	defer io.WriteString(out, CURSOR_ON)

	if len(nodes) <= 0 {
		nodes = []string{""}
		draws = []string{""}
	}

	offset := 0
	for {
		draws[cursor] = BOLD_ON + truncate(nodes[cursor], b.Width-1) + BOLD_OFF
		status, _, h := b.Print(nil, draws, offset, out)
		if !status {
			return ""
		}
		draws[cursor] = truncate(nodes[cursor], b.Width-1)
		last := cursor
		for last == cursor {
			switch b.GetCmd() {
			case LEFT:
				cursor = (cursor + len(nodes) - h) % len(nodes)
			case RIGHT:
				cursor = (cursor + h) % len(nodes)
			case DOWN:
				cursor++
				if cursor >= len(nodes) {
					cursor = 0
				}
			case UP:
				cursor--
				if cursor < 0 {
					cursor = len(nodes) - 1
				}
			case ENTER:
				return nodes[cursor]
			case LEAVE:
				return ""
			}

			// x := cursor / h
			y := cursor % h
			if y < offset {
				offset = y
				// offset--
			} else if y >= offset+b.Height {
				offset = y - b.Height + 1
				// offset++
			}
		}
		if h < b.Height {
			fmt.Fprintf(out, "\x1B[%dA\r", h-1)
		} else {
			fmt.Fprintf(out, "\x1B[%dA\r", b.Height-1)
		}
	}
}
<commit_msg>Rename (*box_t){Print -> PrintNoLastLineFeed} and Make new Print which print last linefeed for compatible.<commit_after>package box

import (
	"context"
	"fmt"
	"io"
	"regexp"
	"strings"

	"github.com/mattn/go-runewidth"
)

var ansiCutter = regexp.MustCompile("\x1B[^a-zA-Z]*[A-Za-z]")

func Print(ctx context.Context, nodes []string, out io.Writer) bool {
	b := New()
	b.Height = 0
	value, _, _ := b.Print(ctx, nodes, 0, out)
	return value
}

func (b *box_t) Print(ctx context.Context,
	nodes []string,
	offset int,
	out io.Writer) (bool, int, int) {

	selected, columns, nlines := b.PrintNoLastLineFeed(ctx, nodes, offset, out)

	// append last linefeed.
	fmt.Fprintln(out)
	return selected, columns, nlines
}

func (b *box_t) PrintNoLastLineFeed(ctx context.Context,
	nodes []string,
	offset int,
	out io.Writer) (bool, int, int) {

	maxLen := 1
	for _, finfo := range nodes {
		length := runewidth.StringWidth(ansiCutter.ReplaceAllString(finfo, ""))
		if length > maxLen {
			maxLen = length
		}
	}
	nodePerLine := (b.Width - 1) / (maxLen + 1)
	if nodePerLine <= 0 {
		nodePerLine = 1
	}
	nlines := (len(nodes) + nodePerLine - 1) / nodePerLine

	lines := make([][]byte, nlines)
	row := 0
	for _, finfo := range nodes {
		lines[row] = append(lines[row], finfo...)
		w := runewidth.StringWidth(ansiCutter.ReplaceAllString(finfo, ""))
		if maxLen < b.Width {
			for i := maxLen + 1; i > w; i-- {
				lines[row] = append(lines[row], ' ')
			}
		}
		row++
		if row >= nlines {
			row = 0
		}
	}
	i_end := len(lines)
	if b.Height > 0 {
		if i_end >= offset+b.Height {
			i_end = offset + b.Height
		}
	}

	i := offset
	for {
		fmt.Fprint(out, string(lines[i]))
		fmt.Fprint(out, "\x1B[0K")
		if ctx != nil {
			select {
			case <-ctx.Done():
				return false, nodePerLine, nlines
			default:
			}
		}
		i++
		if i >= i_end {
			break
		}
		fmt.Fprintln(out)
	}
	return true, nodePerLine, nlines
}

const (
	CURSOR_OFF = "\x1B[?25l"
	CURSOR_ON  = "\x1B[?25h"
	BOLD_ON    = "\x1B[0;47;30m"
	BOLD_OFF   = "\x1B[0m"

	K_LEFT  = 0x25
	K_RIGHT = 0x27
	K_UP    = 0x26
	K_DOWN  = 0x28
)

func truncate(s string, w int) string {
	return runewidth.Truncate(strings.TrimSpace(s), w, "")
}

const (
	NONE  = 0
	LEFT  = 1
	DOWN  = 2
	UP    = 3
	RIGHT = 4
	ENTER = 5
	LEAVE = 6
)

func Choice(sources []string, out io.Writer) string {
	cursor := 0
	nodes := make([]string, 0, len(sources))
	draws := make([]string, 0, len(sources))
	b := New()
	defer b.Close()
	for _, text := range sources {
		val := truncate(text, b.Width-1)
		if val != "" {
			nodes = append(nodes, val)
			draws = append(draws, val)
		}
	}
	io.WriteString(out, CURSOR_OFF)
	defer io.WriteString(out, CURSOR_ON)

	if len(nodes) <= 0 {
		nodes = []string{""}
		draws = []string{""}
	}

	offset := 0
	for {
		draws[cursor] = BOLD_ON + truncate(nodes[cursor], b.Width-1) + BOLD_OFF
		status, _, h := b.PrintNoLastLineFeed(nil, draws, offset, out)
		if !status {
			return ""
		}
		draws[cursor] = truncate(nodes[cursor], b.Width-1)
		last := cursor
		for last == cursor {
			switch b.GetCmd() {
			case LEFT:
				cursor = (cursor + len(nodes) - h) % len(nodes)
			case RIGHT:
				cursor = (cursor + h) % len(nodes)
			case DOWN:
				cursor++
				if cursor >= len(nodes) {
					cursor = 0
				}
			case UP:
				cursor--
				if cursor < 0 {
					cursor = len(nodes) - 1
				}
			case ENTER:
				return nodes[cursor]
			case LEAVE:
				return ""
			}

			// x := cursor / h
			y := cursor % h
			if y < offset {
				offset = y
				// offset--
			} else if y >= offset+b.Height {
				offset = y - b.Height + 1
				// offset++
			}
		}
		if h < b.Height {
			fmt.Fprintf(out, "\x1B[%dA\r", h-1)
		} else {
			fmt.Fprintf(out, "\x1B[%dA\r", b.Height-1)
		}
	}
}
<|endoftext|>


<commit_before>//  Copyright (c) 2014 Couchbase, Inc.
//  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 main

type Cfg interface {
	// A zero cas means don't do a CAS match on Get().
	Get(key string, cas uint64) (val []byte, casSuccess uint64, err error)

	// A zero cas means must be a create.
	Set(key string, val []byte, cas uint64) (casSuccess uint64, err error)

	// A zero cas means don't match CAS on Del().
	Del(key string, cas uint64) error

	// Ephemeral subscriptions to changes to a key.
	Subscribe(key string, ch chan<- CfgEvent) error
}

type CfgCASError struct{}

func (e *CfgCASError) Error() string {
	return "CAS mismatch"
}

type CfgEvent struct {
	Key string
	CAS uint64
}
<commit_msg>comment on CfgEvent.CAS during deletion<commit_after>//  Copyright (c) 2014 Couchbase, Inc.
//  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 main

type Cfg interface {
	// A zero cas means don't do a CAS match on Get().
	Get(key string, cas uint64) (val []byte, casSuccess uint64, err error)

	// A zero cas means must be a create.
	Set(key string, val []byte, cas uint64) (casSuccess uint64, err error)

	// A zero cas means don't match CAS on Del().
	Del(key string, cas uint64) error

	// Ephemeral subscriptions to changes to a key.
	// During a deletion, the CfgEvent.CAS will be 0.
	Subscribe(key string, ch chan<- CfgEvent) error
}

type CfgCASError struct{}

func (e *CfgCASError) Error() string {
	return "CAS mismatch"
}

type CfgEvent struct {
	Key string
	CAS uint64
}
<|endoftext|>


<commit_before>package cli

type App struct {
	Name     string
	Summary  string
	Action   Action
	Commands []Command
}

type Command struct {
	Name        string
	Shortname   string
	Summary     string
	Description string
	Action      Action
}

type Action func(name string)

func (a App) Run(command string) {
	for _, c := range a.Commands {
		if c.Name == command {
			c.Action(command)
		}
	}
}
<commit_msg>More renaming. trying to keep consistent with Flags API<commit_after>package cli

type App struct {
	Name     string
	Usage    string
	Action   Action
	Commands []Command
}

type Command struct {
	Name        string
	ShortName   string
	Usage       string
	Description string
	Action      Action
}

type Action func(name string)

func (a App) Run(command string) {
	for _, c := range a.Commands {
		if c.Name == command {
			c.Action(command)
		}
	}
}
<|endoftext|>


<commit_before>package ghch

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"strings"
	"text/template"
	"time"

	"github.com/jessevdk/go-flags"
	"github.com/octokit/go-octokit/octokit"
)

type ghOpts struct {
	RepoPath    string `short:"r" long:"repo" default:"." description:"git repository path"`
	GitPath     string `short:"g" long:"git" default:"git" description:"git path"`
	From        string `short:"f" long:"from" description:"git commit revision range start from"`
	To          string `short:"t" long:"to" description:"git commit revision range end to"`
	Token       string `          long:"token" description:"github token"`
	Verbose     bool   `short:"v" long:"verbose"`
	Remote      string `          long:"remote" default:"origin" description:"default remote name"`
	Format      string `short:"F" long:"format" default:"json" description:"json or markdown"`
	All         bool   `short:"A" long:"all" description:"output all changes"`
	NextVersion string `short:"N" long:"next-version"`
	// Tmpl string
}

const (
	exitCodeOK = iota
	exitCodeParseFlagError
	exitCodeErr
)

// CLI is struct for command line tool
type CLI struct {
	OutStream, ErrStream io.Writer
}

// Run the ghch
func (cli *CLI) Run(argv []string) int {
	log.SetOutput(cli.ErrStream)
	p, opts, err := parseArgs(argv)
	if err != nil {
		if ferr, ok := err.(*flags.Error); !ok || ferr.Type != flags.ErrHelp {
			p.WriteHelp(cli.ErrStream)
		}
		return exitCodeParseFlagError
	}

	gh := (&ghch{
		remote:   opts.Remote,
		repoPath: opts.RepoPath,
		gitPath:  opts.GitPath,
		verbose:  opts.Verbose,
		token:    opts.Token,
	}).initialize()

	if opts.All {
		chlog := changelog{}
		vers := append(gh.versions(), "")
		prevRev := ""
		for _, rev := range vers {
			r := gh.getSection(rev, prevRev)
			if prevRev == "" && opts.NextVersion != "" {
				r.ToRevision = opts.NextVersion
			}
			chlog.Sections = append(chlog.Sections, r)
			prevRev = rev
		}

		if opts.Format == "markdown" {
			results := make([]string, len(chlog.Sections))
			for i, v := range chlog.Sections {
				results[i], _ = v.toMkdn()
			}
			fmt.Fprintln(cli.OutStream, strings.Join(results, "\n\n"))
		} else {
			jsn, _ := json.MarshalIndent(chlog, "", "  ")
			fmt.Fprintln(cli.OutStream, string(jsn))
		}
	} else {
		if opts.From == "" && opts.To == "" {
			opts.From = gh.getLatestSemverTag()
		}
		r := gh.getSection(opts.From, opts.To)
		if r.ToRevision == "" && opts.NextVersion != "" {
			r.ToRevision = opts.NextVersion
		}
		if opts.Format == "markdown" {
			str, err := r.toMkdn()
			if err != nil {
				log.Print(err)
			} else {
				fmt.Fprintln(cli.OutStream, str)
			}
		} else {
			jsn, _ := json.MarshalIndent(r, "", "  ")
			fmt.Fprintln(cli.OutStream, string(jsn))
		}
	}
	return exitCodeOK
}

func parseArgs(args []string) (*flags.Parser, *ghOpts, error) {
	opts := &ghOpts{}
	p := flags.NewParser(opts, flags.Default)
	p.Usage = "[OPTIONS]\n\nVersion: " + version
	_, err := p.ParseArgs(args)
	return p, opts, err
}

func (gh *ghch) getSection(from, to string) section {
	r := gh.mergedPRs(from, to)
	t, err := gh.getChangedAt(to)
	if err != nil {
		log.Print(err)
	}
	owner, repo := gh.ownerAndRepo()
	return section{
		PullRequests: r,
		FromRevision: from,
		ToRevision:   to,
		ChangedAt:    t,
		Owner:        owner,
		Repo:         repo,
	}
}

type changelog struct {
	Sections []section `json:"sections"`
}

type section struct {
	PullRequests []*octokit.PullRequest `json:"pull_requests"`
	FromRevision string                 `json:"from_revision"`
	ToRevision   string                 `json:"to_revision"`
	ChangedAt    time.Time              `json:"changed_at"`
	Owner        string                 `json:"owner"`
	Repo         string                 `json:"repo"`
}

var tmplStr = `{{$ret := . -}}
## [{{.ToRevision}}](https://github.com/{{.Owner}}/{{.Repo}}/releases/tag/{{.ToRevision}}) ({{.ChangedAt.Format "2006-01-02"}})
{{range .PullRequests}}
* {{.Title}} [#{{.Number}}](https://github.com/{{$ret.Owner}}/{{$ret.Repo}}/pull/{{.Number}}) ([{{.User.Login}}](https://github.com/{{.User.Login}}))
{{- end}}`

var mdTmpl *template.Template

func init() {
	var err error
	mdTmpl, err = template.New("md-changelog").Parse(tmplStr)
	if err != nil {
		log.Fatal(err)
	}
}

func (rs section) toMkdn() (string, error) {
	var b bytes.Buffer
	err := mdTmpl.Execute(&b, rs)
	if err != nil {
		return "", err
	}
	return b.String(), nil
}
<commit_msg>publicize Section and Changelog<commit_after>package ghch

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"strings"
	"text/template"
	"time"

	"github.com/jessevdk/go-flags"
	"github.com/octokit/go-octokit/octokit"
)

type ghOpts struct {
	RepoPath    string `short:"r" long:"repo" default:"." description:"git repository path"`
	GitPath     string `short:"g" long:"git" default:"git" description:"git path"`
	From        string `short:"f" long:"from" description:"git commit revision range start from"`
	To          string `short:"t" long:"to" description:"git commit revision range end to"`
	Token       string `          long:"token" description:"github token"`
	Verbose     bool   `short:"v" long:"verbose"`
	Remote      string `          long:"remote" default:"origin" description:"default remote name"`
	Format      string `short:"F" long:"format" default:"json" description:"json or markdown"`
	All         bool   `short:"A" long:"all" description:"output all changes"`
	NextVersion string `short:"N" long:"next-version"`
	// Tmpl string
}

const (
	exitCodeOK = iota
	exitCodeParseFlagError
	exitCodeErr
)

// CLI is struct for command line tool
type CLI struct {
	OutStream, ErrStream io.Writer
}

// Run the ghch
func (cli *CLI) Run(argv []string) int {
	log.SetOutput(cli.ErrStream)
	p, opts, err := parseArgs(argv)
	if err != nil {
		if ferr, ok := err.(*flags.Error); !ok || ferr.Type != flags.ErrHelp {
			p.WriteHelp(cli.ErrStream)
		}
		return exitCodeParseFlagError
	}

	gh := (&ghch{
		remote:   opts.Remote,
		repoPath: opts.RepoPath,
		gitPath:  opts.GitPath,
		verbose:  opts.Verbose,
		token:    opts.Token,
	}).initialize()

	if opts.All {
		chlog := Changelog{}
		vers := append(gh.versions(), "")
		prevRev := ""
		for _, rev := range vers {
			r := gh.getSection(rev, prevRev)
			if prevRev == "" && opts.NextVersion != "" {
				r.ToRevision = opts.NextVersion
			}
			chlog.Sections = append(chlog.Sections, r)
			prevRev = rev
		}

		if opts.Format == "markdown" {
			results := make([]string, len(chlog.Sections))
			for i, v := range chlog.Sections {
				results[i], _ = v.toMkdn()
			}
			fmt.Fprintln(cli.OutStream, strings.Join(results, "\n\n"))
		} else {
			jsn, _ := json.MarshalIndent(chlog, "", "  ")
			fmt.Fprintln(cli.OutStream, string(jsn))
		}
	} else {
		if opts.From == "" && opts.To == "" {
			opts.From = gh.getLatestSemverTag()
		}
		r := gh.getSection(opts.From, opts.To)
		if r.ToRevision == "" && opts.NextVersion != "" {
			r.ToRevision = opts.NextVersion
		}
		if opts.Format == "markdown" {
			str, err := r.toMkdn()
			if err != nil {
				log.Print(err)
			} else {
				fmt.Fprintln(cli.OutStream, str)
			}
		} else {
			jsn, _ := json.MarshalIndent(r, "", "  ")
			fmt.Fprintln(cli.OutStream, string(jsn))
		}
	}
	return exitCodeOK
}

func parseArgs(args []string) (*flags.Parser, *ghOpts, error) {
	opts := &ghOpts{}
	p := flags.NewParser(opts, flags.Default)
	p.Usage = "[OPTIONS]\n\nVersion: " + version
	_, err := p.ParseArgs(args)
	return p, opts, err
}

func (gh *ghch) getSection(from, to string) Section {
	r := gh.mergedPRs(from, to)
	t, err := gh.getChangedAt(to)
	if err != nil {
		log.Print(err)
	}
	owner, repo := gh.ownerAndRepo()
	return Section{
		PullRequests: r,
		FromRevision: from,
		ToRevision:   to,
		ChangedAt:    t,
		Owner:        owner,
		Repo:         repo,
	}
}

// Changelog contains Sectionst
type Changelog struct {
	Sections []Section `json:"Sections"`
}

// Section contains changes between two revisions
type Section struct {
	PullRequests []*octokit.PullRequest `json:"pull_requests"`
	FromRevision string                 `json:"from_revision"`
	ToRevision   string                 `json:"to_revision"`
	ChangedAt    time.Time              `json:"changed_at"`
	Owner        string                 `json:"owner"`
	Repo         string                 `json:"repo"`
}

var tmplStr = `{{$ret := . -}}
## [{{.ToRevision}}](https://github.com/{{.Owner}}/{{.Repo}}/releases/tag/{{.ToRevision}}) ({{.ChangedAt.Format "2006-01-02"}})
{{range .PullRequests}}
* {{.Title}} [#{{.Number}}](https://github.com/{{$ret.Owner}}/{{$ret.Repo}}/pull/{{.Number}}) ([{{.User.Login}}](https://github.com/{{.User.Login}}))
{{- end}}`

var mdTmpl *template.Template

func init() {
	var err error
	mdTmpl, err = template.New("md-changelog").Parse(tmplStr)
	if err != nil {
		log.Fatal(err)
	}
}

func (rs Section) toMkdn() (string, error) {
	var b bytes.Buffer
	err := mdTmpl.Execute(&b, rs)
	if err != nil {
		return "", err
	}
	return b.String(), nil
}
<|endoftext|>