<commit_before>package peco

import "sync"

type Hub struct {
	isSync      bool
	mutex       *sync.Mutex
	loopCh      chan struct{}
	queryCh     chan HubReq
	drawCh      chan HubReq
	statusMsgCh chan HubReq
	pagingCh    chan HubReq
}

type HubReq struct {
	data    interface{}
	replyCh chan struct{}
}

func (hr HubReq) DataInterface() interface{} {
	return hr.data
}

func (hr HubReq) DataString() string {
	return hr.data.(string)
}

func (hr HubReq) Done() {
	if hr.replyCh != nil {
		hr.replyCh <- struct{}{}
	}
}

func NewHub() *Hub {
	return &Hub{
		false,
		&sync.Mutex{},
		make(chan struct{}),  // loopCh. You never send messages to this. no point in buffering
		make(chan HubReq, 5), // queryCh.
		make(chan HubReq, 5), // drawCh.
		make(chan HubReq, 5), // statusMsgCh
		make(chan HubReq, 5), // pagingCh
	}
}

// Batch allows you to synchronously send messages during the
// scope of f() being executed.
func (h *Hub) Batch(f func()) {
	// lock during this operation
	h.mutex.Lock()
	defer h.mutex.Unlock()

	// temporarily set isSync = true
	o := h.isSync
	h.isSync = true
	defer func() { h.isSync = o }()

	// ignore panics
	defer func() { recover() }()

	f()
}

// low-level utility
func send(ch chan HubReq, r HubReq, needReply bool) {
	if needReply {
		r.replyCh = make(chan struct{})
		defer func() { <-r.replyCh }()
	}

	ch <- r
}

func (h *Hub) QueryCh() chan HubReq {
	return h.queryCh
}

func (h *Hub) SendQuery(q string) {
	send(h.QueryCh(), HubReq{q, nil}, h.isSync)
}

func (h *Hub) LoopCh() chan struct{} {
	return h.loopCh
}

func (h *Hub) DrawCh() chan HubReq {
	return h.drawCh
}

func (h *Hub) SendDraw(matches []Match) {
	send(h.DrawCh(), HubReq{matches, nil}, h.isSync)
}

func (h *Hub) StatusMsgCh() chan HubReq {
	return h.statusMsgCh
}

func (h *Hub) SendStatusMsg(q string) {
	send(h.StatusMsgCh(), HubReq{q, nil}, h.isSync)
}

func (h *Hub) PagingCh() chan HubReq {
	return h.pagingCh
}

func (h *Hub) SendPaging(x PagingRequest) {
	send(h.PagingCh(), HubReq{x, nil}, h.isSync)
}

func (h *Hub) Stop() {
	close(h.LoopCh())
}
<commit_msg>golint<commit_after>package peco

import "sync"

// Hub acts as the messaging hub between components -- that is,
// it controls how the communication that goes through channels
// are handled.
type Hub struct {
	isSync      bool
	mutex       *sync.Mutex
	loopCh      chan struct{}
	queryCh     chan HubReq
	drawCh      chan HubReq
	statusMsgCh chan HubReq
	pagingCh    chan HubReq
}

// HubReq is a wrapper around the actual requst value that needs
// to be passed. It contains an optional channel field which can
// be filled to force synchronous communication between the
// sender and receiver
type HubReq struct {
	data    interface{}
	replyCh chan struct{}
}

// DataInterface returns the underlying data as interface{}
func (hr HubReq) DataInterface() interface{} {
	return hr.data
}

// DataString returns the underlying data as a string. Panics
// if type conversion fails.
func (hr HubReq) DataString() string {
	return hr.data.(string)
}

// Done marks the request as done. If Hub is operating in
// asynchronous mode (default), it's a no op. Otherwise it
// sends a message back the reply channel to finish up the
// synchronous communication
func (hr HubReq) Done() {
	if hr.replyCh == nil {
		return
	}
	hr.replyCh <- struct{}{}
}

// NewHub creates a new Hub struct
func NewHub() *Hub {
	return &Hub{
		false,
		&sync.Mutex{},
		make(chan struct{}),  // loopCh. You never send messages to this. no point in buffering
		make(chan HubReq, 5), // queryCh.
		make(chan HubReq, 5), // drawCh.
		make(chan HubReq, 5), // statusMsgCh
		make(chan HubReq, 5), // pagingCh
	}
}

// Batch allows you to synchronously send messages during the
// scope of f() being executed.
func (h *Hub) Batch(f func()) {
	// lock during this operation
	h.mutex.Lock()
	defer h.mutex.Unlock()

	// temporarily set isSync = true
	o := h.isSync
	h.isSync = true
	defer func() { h.isSync = o }()

	// ignore panics
	defer func() { recover() }()

	f()
}

// low-level utility
func send(ch chan HubReq, r HubReq, needReply bool) {
	if needReply {
		r.replyCh = make(chan struct{})
		defer func() { <-r.replyCh }()
	}

	ch <- r
}

// QueryCh returns the underlying channel for queries
func (h *Hub) QueryCh() chan HubReq {
	return h.queryCh
}

// SendQuery sends the query string to be processed by the Filter
func (h *Hub) SendQuery(q string) {
	send(h.QueryCh(), HubReq{q, nil}, h.isSync)
}

// LoopCh returns the channel to control the main execution loop.
// Nothing should ever be sent through this channel. The only way
// the channel communicates anything to its receivers is when
// it is closed -- which is when peco is done.
func (h *Hub) LoopCh() chan struct{} {
	return h.loopCh
}

// DrawCh returns the channel to redraw the terminal display
func (h *Hub) DrawCh() chan HubReq {
	return h.drawCh
}

// SendDraw sends a request to redraw the terminal display
func (h *Hub) SendDraw(matches []Match) {
	send(h.DrawCh(), HubReq{matches, nil}, h.isSync)
}

// StatusMsgCh returns the channel to update the status message
func (h *Hub) StatusMsgCh() chan HubReq {
	return h.statusMsgCh
}

// SendStatusMsg sends a string to be displayed in the status message
func (h *Hub) SendStatusMsg(q string) {
	send(h.StatusMsgCh(), HubReq{q, nil}, h.isSync)
}

// PagingCh returns the channel to page through the results
func (h *Hub) PagingCh() chan HubReq {
	return h.pagingCh
}

// SendPaging sends a request to move the cursor around
func (h *Hub) SendPaging(x PagingRequest) {
	send(h.PagingCh(), HubReq{x, nil}, h.isSync)
}

// Stop closes the LoopCh so that peco shutsdown
func (h *Hub) Stop() {
	close(h.LoopCh())
}
<|endoftext|>


<commit_before>package core

import "github.com/Comcast/sheens/match"

type Bindings match.Bindings

var (
	matcher                = match.DefaultMatcher
	AllowPropertyVariables = matcher.AllowPropertyVariables
)

func Match(ctx *Context, pattern, fact interface{}, bs Bindings) ([]Bindings, error) {
	bssExt, err := matcher.Match(pattern, fact, match.Bindings(bs))
	bss := make([]Bindings, len(bssExt))
	for i := range bssExt {
		bss[i] = Bindings(bssExt[i])
	}
	return bss, err
}

func Matches(ctx *Context, pattern, fact interface{}) ([]Bindings, error) {
	return Match(ctx, pattern, fact, map[string]interface{}{})
}

func IsVariable(s string) bool {
	return matcher.IsVariable(s)
}
<commit_msg>feat(core): perform casting around matcher<commit_after>package core

import "github.com/Comcast/sheens/match"

type Bindings match.Bindings

var (
	Matcher                = match.DefaultMatcher
	AllowPropertyVariables = Matcher.AllowPropertyVariables
)

func Match(ctx *Context, pattern, fact interface{}, bs Bindings) ([]Bindings, error) {
	return castBss(Matcher.Match(castMap(pattern), castMap(fact), match.Bindings(bs)))
}

func Matches(ctx *Context, pattern, fact interface{}) ([]Bindings, error) {
	return Match(ctx, pattern, fact, map[string]interface{}{})
}

func IsVariable(s string) bool {
	return Matcher.IsVariable(s)
}

func castBss(bssExt []match.Bindings, err error) ([]Bindings, error) {
	bss := make([]Bindings, len(bssExt))
	for i := range bssExt {
		bss[i] = Bindings(bssExt[i])
	}
	return bss, err
}

func castMap(iface interface{}) interface{} {
	switch v := iface.(type) {
	case Map, map[string]interface{}:
		m, ok := v.(map[string]interface{})
		if !ok {
			m = map[string]interface{}(v.(Map))
		}
		for k, v := range m {
			m[k] = castMap(v)
		}
		iface = m
	case []interface{}:
		for i := range v {
			v[i] = castMap(v[i])
		}
		iface = v
	default:
		if v, ok := ISlice(v); ok {
			iface = v
		}
	}

	return iface
}
<|endoftext|>


<commit_before>package zwo

import (
	"fmt"
	"github.com/dynport/gologger"
	"github.com/dynport/zwo/host"
	"runtime/debug"
)

// Provision the given host with the given packages. This is where zwo's secret leprechauns sit and do their work!
func ProvisionHost(host *host.Host, packages ...Compiler) (e error) {
	return newSSHClient(host).provisionHost(packages...)
}

func ProvisionHostDryrun(host *host.Host, packages ...Compiler) (e error) {
	logger.PushPrefix(gologger.Colorize(226, "DRYRUN"))
	defer logger.PopPrefix()
	sc := newSSHClient(host)
	sc.dryrun = true
	return sc.provisionHost(packages...)
}

// Provision the given packages into a docker container image tagged with the given tag (the according registry will be
// added automatically). The build will happen on the given host, that must be a docker host with build capability.
func ProvisionImage(host *host.Host, tag string, packages ...Compiler) (imageId string, e error) {
	if !host.IsDockerHost() {
		return "", fmt.Errorf("host %s is not a docker host", host.Hostname())
	}
	dc, e := newDockerClient(host)
	if e != nil {
		return "", e
	}
	return dc.provisionImage(tag, packages...)
}

// Precompile the given packages for the given host.
func precompileRunlists(host *host.Host, packages ...Compiler) (runLists []*Runlist, e error) {
	defer func() {
		if r := recover(); r != nil {
			var ok bool
			e, ok = r.(error)
			if !ok {
				e = fmt.Errorf("failed to precompile package: %v", r)
			}
			logger.Info(e.Error())
			logger.Debug(string(debug.Stack()))
		}
	}()

	runLists = make([]*Runlist, 0, len(packages))

	runlistNames := map[string]bool{}

	for _, pkg := range packages { // Precompile runlists.
		pkgName := packageName(pkg)

		if pkgName == "" {
			return nil, fmt.Errorf("package name empty")
		}

		if runlistNames[pkgName] {
			return nil, fmt.Errorf("package %q used twice", pkgName)
		}
		runlistNames[pkgName] = true

		rl := &Runlist{host: host}
		rl.setConfig(pkg)
		rl.setName(pkgName)
		pkg.Compile(rl)

		runLists = append(runLists, rl)
		logger.Debugf("Precompiled package %s", pkgName)
	}

	return runLists, nil
}

// Provision the given list of runlists.
func provisionRunlists(runLists []*Runlist, provisionFunc func(*Runlist) error) (e error) {
	for i := range runLists {
		rl := runLists[i]

		logger.PushPrefix(padToFixedLength(rl.getName(), 15))

		if e = provisionFunc(runLists[i]); e != nil {
			logger.Errorf("failed to provision: %s", e.Error())
			return e
		}

		logger.PopPrefix()
	}
	return nil
}
<commit_msg>make dryrun an option of ProvisionHost function<commit_after>package zwo

import (
	"fmt"
	"github.com/dynport/gologger"
	"github.com/dynport/zwo/host"
	"runtime/debug"
)

// Provision the given host with the given packages. This is where zwo's secret leprechauns sit and do their work!
func ProvisionHost(host *host.Host, dryrun bool, packages ...Compiler) (e error) {
	sc := newSSHClient(host)
	if dryrun {
		sc.dryrun = true
		logger.PushPrefix(gologger.Colorize(226, "DRYRUN"))
		defer logger.PopPrefix()
	}

	return sc.provisionHost(packages...)
}

// Provision the given packages into a docker container image tagged with the given tag (the according registry will be
// added automatically). The build will happen on the given host, that must be a docker host with build capability.
func ProvisionImage(host *host.Host, tag string, packages ...Compiler) (imageId string, e error) {
	if !host.IsDockerHost() {
		return "", fmt.Errorf("host %s is not a docker host", host.Hostname())
	}
	dc, e := newDockerClient(host)
	if e != nil {
		return "", e
	}
	return dc.provisionImage(tag, packages...)
}

// Precompile the given packages for the given host.
func precompileRunlists(host *host.Host, packages ...Compiler) (runLists []*Runlist, e error) {
	defer func() {
		if r := recover(); r != nil {
			var ok bool
			e, ok = r.(error)
			if !ok {
				e = fmt.Errorf("failed to precompile package: %v", r)
			}
			logger.Info(e.Error())
			logger.Debug(string(debug.Stack()))
		}
	}()

	runLists = make([]*Runlist, 0, len(packages))

	runlistNames := map[string]bool{}

	for _, pkg := range packages { // Precompile runlists.
		pkgName := packageName(pkg)

		if pkgName == "" {
			return nil, fmt.Errorf("package name empty")
		}

		if runlistNames[pkgName] {
			return nil, fmt.Errorf("package %q used twice", pkgName)
		}
		runlistNames[pkgName] = true

		rl := &Runlist{host: host}
		rl.setConfig(pkg)
		rl.setName(pkgName)
		pkg.Compile(rl)

		runLists = append(runLists, rl)
		logger.Debugf("Precompiled package %s", pkgName)
	}

	return runLists, nil
}

// Provision the given list of runlists.
func provisionRunlists(runLists []*Runlist, provisionFunc func(*Runlist) error) (e error) {
	for i := range runLists {
		rl := runLists[i]

		logger.PushPrefix(padToFixedLength(rl.getName(), 15))

		if e = provisionFunc(runLists[i]); e != nil {
			logger.Errorf("failed to provision: %s", e.Error())
			return e
		}

		logger.PopPrefix()
	}
	return nil
}
<|endoftext|>


<commit_before><commit_msg>Change dir path<commit_after><|endoftext|>


<commit_before>/*
 Copyright 2016 Padduck, LLC

 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 templates

const SRCDS = `{
  "pufferd": {
    "type": "srcds",
    "install": {
      "commands": [
        {
          "files": "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz",
          "type": "download"
        },
        {
          "commands": [
            "mkdir steamcmd",
            "tar --no-same-owner -xzvf steamcmd_linux.tar.gz -C steamcmd",
            "steamcmd/steamcmd.sh +login anonymous +force_install_dir ${rootdir} +app_update ${appid} +quit",
            "mkdir -p .steam/sdk32",
            "cp steamcmd/linux32/steamclient.so .steam/sdk32/steamclient.so"
          ],
          "type": "command"
        }
      ]
    },
    "run": {
      "stop": "exit",
      "pre": [],
      "post": [],
      "arguments": [
      	"-game ${gametype}",
      	"-console",
        "+map ${map}",
      	"-norestart"
      ],
      "program": "./srcds_run"
    },
    "data": {
      "appid": {
        "value": "232250",
        "required": true,
        "desc": "App ID",
        "display": "Application ID",
        "internal": false
    }
     "gametype": {
      "value": "tf",
      "required": true,
      "desc": "Game Type",
      "display": "tf, csgo, etc.",
      "internal": false
    }
      "map": {
      	"value": "ctf_2fort",
      	"required": false,
      	"desc": "Map",
      	"display": "Map to load",
      	"internal": false
      }
    }
  }
}`

const TF2 = `{
  "pufferd": {
    "type": "srcds",
    "install": {
      "commands": [
        {
          "files": "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz",
          "type": "download"
        },
        {
          "commands": [
            "mkdir steamcmd",
            "tar --no-same-owner -xzvf steamcmd_linux.tar.gz -C steamcmd",
            "steamcmd/steamcmd.sh +login anonymous +force_install_dir ${rootdir} +app_update 232250 +quit",
            "mkdir -p .steam/sdk32",
            "cp steamcmd/linux32/steamclient.so .steam/sdk32/steamclient.so"
          ],
          "type": "command"
        }
      ]
    },
    "run": {
      "stop": "exit",
      "pre": [],
      "post": [],
      "arguments": [
      	"-game tf",
      	"-console",
        "+map ${map}",
      	"-norestart"
      ],
      "program": "./srcds_run"
    },
    "data": {
      "map": {
      	"value": "ctf_2fort",
      	"required": true,
      	"desc": "TF2 Map",
      	"display": "Team Fortess 2 Map to load",
      	"internal": false
      }
    }
  }
}`
<commit_msg>Fix SRCDS JSON<commit_after>/*
 Copyright 2016 Padduck, LLC

 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 templates

const SRCDS = `{
  "pufferd": {
    "type": "srcds",
    "install": {
      "commands": [
        {
          "files": "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz",
          "type": "download"
        },
        {
          "commands": [
            "mkdir steamcmd",
            "tar --no-same-owner -xzvf steamcmd_linux.tar.gz -C steamcmd",
            "steamcmd/steamcmd.sh +login anonymous +force_install_dir ${rootdir} +app_update ${appid} +quit",
            "mkdir -p .steam/sdk32",
            "cp steamcmd/linux32/steamclient.so .steam/sdk32/steamclient.so"
          ],
          "type": "command"
        }
      ]
    },
    "run": {
      "stop": "exit",
      "pre": [],
      "post": [],
      "arguments": [
      	"-game ${gametype}",
      	"-console",
        "+map ${map}",
      	"-norestart"
      ],
      "program": "./srcds_run"
    },
    "data": {
      "appid": {
        "value": "232250",
        "required": true,
        "desc": "App ID",
        "display": "Application ID",
        "internal": false
    },
     "gametype": {
      "value": "tf",
      "required": true,
      "desc": "Game Type",
      "display": "tf, csgo, etc.",
      "internal": false
   },
      "map": {
      	"value": "ctf_2fort",
      	"required": false,
      	"desc": "Map",
      	"display": "Map to load",
      	"internal": false
      }
    }
  }
}`

const TF2 = `{
  "pufferd": {
    "type": "srcds",
    "install": {
      "commands": [
        {
          "files": "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz",
          "type": "download"
        },
        {
          "commands": [
            "mkdir steamcmd",
            "tar --no-same-owner -xzvf steamcmd_linux.tar.gz -C steamcmd",
            "steamcmd/steamcmd.sh +login anonymous +force_install_dir ${rootdir} +app_update 232250 +quit",
            "mkdir -p .steam/sdk32",
            "cp steamcmd/linux32/steamclient.so .steam/sdk32/steamclient.so"
          ],
          "type": "command"
        }
      ]
    },
    "run": {
      "stop": "exit",
      "pre": [],
      "post": [],
      "arguments": [
      	"-game tf",
      	"-console",
        "+map ${map}",
      	"-norestart"
      ],
      "program": "./srcds_run"
    },
    "data": {
      "map": {
      	"value": "ctf_2fort",
      	"required": true,
      	"desc": "TF2 Map",
      	"display": "Team Fortess 2 Map to load",
      	"internal": false
      }
    }
  }
}`
<|endoftext|>


<commit_before>package air

import (
	"net/http"
	"net/http/httptest"
	"testing"

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

func TestGroup(t *testing.T) {
	a := New()
	g := a.Group("/foo")

	g.GET("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [GET /foo/bar]")
	})

	g.HEAD("/bar", func(req *Request, res *Response) error {
		return res.Write(nil)
	})

	g.POST("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [POST /foo/bar]")
	})

	g.PUT("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [PUT /foo/bar]")
	})

	g.PATCH("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [PATCH /foo/bar]")
	})

	g.DELETE("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [DELETE /foo/bar]")
	})

	g.CONNECT("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [CONNECT /foo/bar]")
	})

	g.OPTIONS("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [OPTIONS /foo/bar]")
	})

	g.TRACE("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [TRACE /foo/bar]")
	})

	g.BATCH(nil, "/bar2", func(req *Request, res *Response) error {
		return res.WriteString("Matched [* /foo/bar2]")
	})

	g.FILE("/bar3", "/foo.bar")
	g.FILES("/bar4", "/foobar")
	g.Group("/bar5")

	req := httptest.NewRequest(http.MethodGet, "/foo/bar", nil)
	rec := httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [GET /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodHead, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Empty(t, rec.Body.String())

	req = httptest.NewRequest(http.MethodPost, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [POST /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodPut, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [PUT /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodPatch, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [PATCH /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodDelete, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [DELETE /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodConnect, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [CONNECT /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodOptions, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [OPTIONS /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodTrace, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [TRACE /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodGet, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodHead, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Empty(t, rec.Body.String())

	req = httptest.NewRequest(http.MethodPost, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodPut, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodPatch, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodDelete, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodConnect, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodOptions, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodTrace, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodGet, "/foo/bar4", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusNotFound, rec.Code)
	assert.Equal(t, "Not Found", rec.Body.String())

	req = httptest.NewRequest(http.MethodHead, "/foo/bar4", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusNotFound, rec.Code)
	assert.Empty(t, rec.Body.String())

	req = httptest.NewRequest(http.MethodGet, "/foo/bar5", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusNotFound, rec.Code)
	assert.Equal(t, "Not Found", rec.Body.String())

	req = httptest.NewRequest(http.MethodHead, "/foo/bar5", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusNotFound, rec.Code)
	assert.Empty(t, rec.Body.String())
}
<commit_msg>test: update group_test.go<commit_after>package air

import (
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"path"
	"path/filepath"
	"testing"

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

func TestGroup(t *testing.T) {
	a := New()
	g := a.Group("/foo")

	assert.NotNil(t, g)
	assert.Equal(t, a, g.Air)
	assert.Equal(t, "/foo", g.Prefix)
	assert.Nil(t, g.Gases)

	g.GET("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [GET /foo/bar]")
	})

	g.HEAD("/bar", func(req *Request, res *Response) error {
		return res.Write(nil)
	})

	g.POST("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [POST /foo/bar]")
	})

	g.PUT("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [PUT /foo/bar]")
	})

	g.PATCH("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [PATCH /foo/bar]")
	})

	g.DELETE("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [DELETE /foo/bar]")
	})

	g.CONNECT("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [CONNECT /foo/bar]")
	})

	g.OPTIONS("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [OPTIONS /foo/bar]")
	})

	g.TRACE("/bar", func(req *Request, res *Response) error {
		return res.WriteString("Matched [TRACE /foo/bar]")
	})

	g.BATCH(nil, "/bar2", func(req *Request, res *Response) error {
		return res.WriteString("Matched [* /foo/bar2]")
	})

	dir, err := ioutil.TempDir("", "air.TestGroup")
	assert.NoError(t, err)
	assert.NotEmpty(t, dir)
	defer os.RemoveAll(dir)

	f, err := ioutil.TempFile(dir, "")
	assert.NoError(t, err)
	assert.NotNil(t, f)

	_, err = f.Write([]byte("Foobar"))
	assert.NoError(t, err)
	assert.NoError(t, f.Close())

	f2, err := ioutil.TempFile(dir, "")
	assert.NoError(t, err)
	assert.NotNil(t, f2)

	_, err = f2.Write([]byte("Foobar2"))
	assert.NoError(t, err)
	assert.NoError(t, f2.Close())

	g.FILE("/bar3", f.Name())
	g.FILES("/bar4", dir)

	g2 := g.Group("/bar5")
	assert.NotNil(t, g2)
	assert.Equal(t, a, g2.Air)
	assert.Equal(t, "/foo/bar5", g2.Prefix)
	assert.Nil(t, g2.Gases)

	req := httptest.NewRequest(http.MethodGet, "/foo/bar", nil)
	rec := httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [GET /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodHead, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Empty(t, rec.Body.String())

	req = httptest.NewRequest(http.MethodPost, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [POST /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodPut, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [PUT /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodPatch, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [PATCH /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodDelete, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [DELETE /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodConnect, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [CONNECT /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodOptions, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [OPTIONS /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodTrace, "/foo/bar", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [TRACE /foo/bar]", rec.Body.String())

	req = httptest.NewRequest(http.MethodGet, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodHead, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Empty(t, rec.Body.String())

	req = httptest.NewRequest(http.MethodPost, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodPut, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodPatch, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodDelete, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodConnect, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodOptions, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodTrace, "/foo/bar2", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Matched [* /foo/bar2]", rec.Body.String())

	req = httptest.NewRequest(http.MethodGet, "/foo/bar4", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusNotFound, rec.Code)
	assert.Equal(t, "Not Found", rec.Body.String())

	req = httptest.NewRequest(http.MethodHead, "/foo/bar4", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusNotFound, rec.Code)
	assert.Empty(t, rec.Body.String())

	req = httptest.NewRequest(http.MethodGet, "/foo/bar5", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusNotFound, rec.Code)
	assert.Equal(t, "Not Found", rec.Body.String())

	req = httptest.NewRequest(http.MethodHead, "/foo/bar5", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusNotFound, rec.Code)
	assert.Empty(t, rec.Body.String())

	req = httptest.NewRequest(http.MethodGet, "/foo/bar3", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Foobar", rec.Body.String())

	req = httptest.NewRequest(http.MethodHead, "/foo/bar3", nil)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Empty(t, rec.Body.String())

	req = httptest.NewRequest(
		http.MethodGet,
		path.Join("/foo/bar4", filepath.Base(f2.Name())),
		nil,
	)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Equal(t, "Foobar2", rec.Body.String())

	req = httptest.NewRequest(
		http.MethodHead,
		path.Join("/foo/bar4/", filepath.Base(f2.Name())),
		nil,
	)
	rec = httptest.NewRecorder()
	a.server.ServeHTTP(rec, req)
	assert.Equal(t, http.StatusOK, rec.Code)
	assert.Empty(t, rec.Body.String())
}
<|endoftext|>


<commit_before>package driver

import (
	"fmt"
	"io"
	"regexp"
	"strconv"
	"strings"

	"github.com/docker/distribution/context"
)

// Version is a string representing the storage driver version, of the form
// Major.Minor.
// The registry must accept storage drivers with equal major version and greater
// minor version, but may not be compatible with older storage driver versions.
type Version string

// Major returns the major (primary) component of a version.
func (version Version) Major() uint {
	majorPart := strings.Split(string(version), ".")[0]
	major, _ := strconv.ParseUint(majorPart, 10, 0)
	return uint(major)
}

// Minor returns the minor (secondary) component of a version.
func (version Version) Minor() uint {
	minorPart := strings.Split(string(version), ".")[1]
	minor, _ := strconv.ParseUint(minorPart, 10, 0)
	return uint(minor)
}

// CurrentVersion is the current storage driver Version.
const CurrentVersion Version = "0.1"

// StorageDriver defines methods that a Storage Driver must implement for a
// filesystem-like key/value object storage.
type StorageDriver interface {
	// Name returns the human-readable "name" of the driver, useful in error
	// messages and logging. By convention, this will just be the registration
	// name, but drivers may provide other information here.
	Name() string

	// GetContent retrieves the content stored at "path" as a []byte.
	// This should primarily be used for small objects.
	GetContent(ctx context.Context, path string) ([]byte, error)

	// PutContent stores the []byte content at a location designated by "path".
	// This should primarily be used for small objects.
	PutContent(ctx context.Context, path string, content []byte) error

	// ReadStream retrieves an io.ReadCloser for the content stored at "path"
	// with a given byte offset.
	// May be used to resume reading a stream by providing a nonzero offset.
	ReadStream(ctx context.Context, path string, offset int64) (io.ReadCloser, error)

	// WriteStream stores the contents of the provided io.ReadCloser at a
	// location designated by the given path.
	// May be used to resume writing a stream by providing a nonzero offset.
	// The offset must be no larger than the CurrentSize for this path.
	WriteStream(ctx context.Context, path string, offset int64, reader io.Reader) (nn int64, err error)

	// Stat retrieves the FileInfo for the given path, including the current
	// size in bytes and the creation time.
	Stat(ctx context.Context, path string) (FileInfo, error)

	// List returns a list of the objects that are direct descendants of the
	//given path.
	List(ctx context.Context, path string) ([]string, error)

	// Move moves an object stored at sourcePath to destPath, removing the
	// original object.
	// Note: This may be no more efficient than a copy followed by a delete for
	// many implementations.
	Move(ctx context.Context, sourcePath string, destPath string) error

	// Delete recursively deletes all objects stored at "path" and its subpaths.
	Delete(ctx context.Context, path string) error

	// URLFor returns a URL which may be used to retrieve the content stored at
	// the given path, possibly using the given options.
	// May return an ErrUnsupportedMethod in certain StorageDriver
	// implementations.
	URLFor(ctx context.Context, path string, options map[string]interface{}) (string, error)
}

// PathRegexp is the regular expression which each file path must match. A
// file path is absolute, beginning with a slash and containing a positive
// number of path components separated by slashes, where each component is
// restricted to lowercase alphanumeric characters or a period, underscore, or
// hyphen.
var PathRegexp = regexp.MustCompile(`^(/[A-Za-z0-9._-]+)+$`)

// ErrUnsupportedMethod may be returned in the case where a StorageDriver implementation does not support an optional method.
type ErrUnsupportedMethod struct {
	DriverName string
}

func (err ErrUnsupportedMethod) Error() string {
	return fmt.Sprintf("[%s] unsupported method", err.DriverName)
}

// PathNotFoundError is returned when operating on a nonexistent path.
type PathNotFoundError struct {
	Path       string
	DriverName string
}

func (err PathNotFoundError) Error() string {
	return fmt.Sprintf("[%s] Path not found: %s", err.DriverName, err.Path)
}

// InvalidPathError is returned when the provided path is malformed.
type InvalidPathError struct {
	Path       string
	DriverName string
}

func (err InvalidPathError) Error() string {
	return fmt.Sprintf("[%s] Invalid path: %s", err.DriverName, err.Path)
}

// InvalidOffsetError is returned when attempting to read or write from an
// invalid offset.
type InvalidOffsetError struct {
	Path       string
	Offset     int64
	DriverName string
}

func (err InvalidOffsetError) Error() string {
	return fmt.Sprintf("[%s] Invalid offset: %d for path: %s", err.DriverName, err.Offset, err.Path)
}

// Error is a catch-all error type which captures an error string and
// the driver type on which it occured.
type Error struct {
	DriverName string
	Enclosed   error
}

func (err Error) Error() string {
	return fmt.Sprintf("[%s] %s", err.DriverName, err.Enclosed)
}
<commit_msg>Fix comment for PathRegexp<commit_after>package driver

import (
	"fmt"
	"io"
	"regexp"
	"strconv"
	"strings"

	"github.com/docker/distribution/context"
)

// Version is a string representing the storage driver version, of the form
// Major.Minor.
// The registry must accept storage drivers with equal major version and greater
// minor version, but may not be compatible with older storage driver versions.
type Version string

// Major returns the major (primary) component of a version.
func (version Version) Major() uint {
	majorPart := strings.Split(string(version), ".")[0]
	major, _ := strconv.ParseUint(majorPart, 10, 0)
	return uint(major)
}

// Minor returns the minor (secondary) component of a version.
func (version Version) Minor() uint {
	minorPart := strings.Split(string(version), ".")[1]
	minor, _ := strconv.ParseUint(minorPart, 10, 0)
	return uint(minor)
}

// CurrentVersion is the current storage driver Version.
const CurrentVersion Version = "0.1"

// StorageDriver defines methods that a Storage Driver must implement for a
// filesystem-like key/value object storage.
type StorageDriver interface {
	// Name returns the human-readable "name" of the driver, useful in error
	// messages and logging. By convention, this will just be the registration
	// name, but drivers may provide other information here.
	Name() string

	// GetContent retrieves the content stored at "path" as a []byte.
	// This should primarily be used for small objects.
	GetContent(ctx context.Context, path string) ([]byte, error)

	// PutContent stores the []byte content at a location designated by "path".
	// This should primarily be used for small objects.
	PutContent(ctx context.Context, path string, content []byte) error

	// ReadStream retrieves an io.ReadCloser for the content stored at "path"
	// with a given byte offset.
	// May be used to resume reading a stream by providing a nonzero offset.
	ReadStream(ctx context.Context, path string, offset int64) (io.ReadCloser, error)

	// WriteStream stores the contents of the provided io.ReadCloser at a
	// location designated by the given path.
	// May be used to resume writing a stream by providing a nonzero offset.
	// The offset must be no larger than the CurrentSize for this path.
	WriteStream(ctx context.Context, path string, offset int64, reader io.Reader) (nn int64, err error)

	// Stat retrieves the FileInfo for the given path, including the current
	// size in bytes and the creation time.
	Stat(ctx context.Context, path string) (FileInfo, error)

	// List returns a list of the objects that are direct descendants of the
	//given path.
	List(ctx context.Context, path string) ([]string, error)

	// Move moves an object stored at sourcePath to destPath, removing the
	// original object.
	// Note: This may be no more efficient than a copy followed by a delete for
	// many implementations.
	Move(ctx context.Context, sourcePath string, destPath string) error

	// Delete recursively deletes all objects stored at "path" and its subpaths.
	Delete(ctx context.Context, path string) error

	// URLFor returns a URL which may be used to retrieve the content stored at
	// the given path, possibly using the given options.
	// May return an ErrUnsupportedMethod in certain StorageDriver
	// implementations.
	URLFor(ctx context.Context, path string, options map[string]interface{}) (string, error)
}

// PathRegexp is the regular expression which each file path must match. A
// file path is absolute, beginning with a slash and containing a positive
// number of path components separated by slashes, where each component is
// restricted to alphanumeric characters or a period, underscore, or
// hyphen.
var PathRegexp = regexp.MustCompile(`^(/[A-Za-z0-9._-]+)+$`)

// ErrUnsupportedMethod may be returned in the case where a StorageDriver implementation does not support an optional method.
type ErrUnsupportedMethod struct {
	DriverName string
}

func (err ErrUnsupportedMethod) Error() string {
	return fmt.Sprintf("[%s] unsupported method", err.DriverName)
}

// PathNotFoundError is returned when operating on a nonexistent path.
type PathNotFoundError struct {
	Path       string
	DriverName string
}

func (err PathNotFoundError) Error() string {
	return fmt.Sprintf("[%s] Path not found: %s", err.DriverName, err.Path)
}

// InvalidPathError is returned when the provided path is malformed.
type InvalidPathError struct {
	Path       string
	DriverName string
}

func (err InvalidPathError) Error() string {
	return fmt.Sprintf("[%s] Invalid path: %s", err.DriverName, err.Path)
}

// InvalidOffsetError is returned when attempting to read or write from an
// invalid offset.
type InvalidOffsetError struct {
	Path       string
	Offset     int64
	DriverName string
}

func (err InvalidOffsetError) Error() string {
	return fmt.Sprintf("[%s] Invalid offset: %d for path: %s", err.DriverName, err.Offset, err.Path)
}

// Error is a catch-all error type which captures an error string and
// the driver type on which it occured.
type Error struct {
	DriverName string
	Enclosed   error
}

func (err Error) Error() string {
	return fmt.Sprintf("[%s] %s", err.DriverName, err.Enclosed)
}
<|endoftext|>


<commit_before>package delmo

import (
	"bytes"
	"io"
	"log"
	"os"
	"os/exec"
)

type DockerCompose struct {
	rawCmd      string
	composeFile string
	handle      *dockerComposeHandle
}

type dockerComposeHandle struct {
	cmd    *exec.Cmd
	Output *bytes.Buffer
	stopCh chan int
}

func NewDockerCompose(composeFile string) (*DockerCompose, error) {
	cmd, err := exec.LookPath("docker-compose")
	if err != nil {
		return nil, err
	}
	dc := &DockerCompose{
		rawCmd:      cmd,
		composeFile: composeFile,
	}
	return dc, nil
}

func (d *DockerCompose) Start() {
	args := []string{
		"-f", d.composeFile, "up",
	}
	cmd := exec.Command(d.rawCmd, args...)
	buf := new(bytes.Buffer)
	d.handle = &dockerComposeHandle{
		cmd:    cmd,
		stopCh: make(chan int),
		Output: buf,
	}
	go d.handle.run()
}

func (d *DockerCompose) Stop() {
	d.handle.stop()
}
func (d *DockerCompose) Output() io.Reader {
	return d.handle.Output
}

func (h *dockerComposeHandle) run() {
	h.cmd.Stdout = h.Output
	// h.cmd.Stderr = h.Output

	if err := h.cmd.Start(); err != nil {
		log.Fatal(err)
	}

	select {
	case <-h.stopCh:
		os.Stdout.Write([]byte("recieved stop signal"))
	}

	h.cmd.Process.Signal(os.Interrupt)
}

func (h *dockerComposeHandle) stop() {
	h.stopCh <- 1
}
<commit_msg>Private output<commit_after>package delmo

import (
	"bytes"
	"io"
	"log"
	"os"
	"os/exec"
)

type DockerCompose struct {
	rawCmd      string
	composeFile string
	handle      *dockerComposeHandle
}

type dockerComposeHandle struct {
	cmd    *exec.Cmd
	output *bytes.Buffer
	stopCh chan int
}

func NewDockerCompose(composeFile string) (*DockerCompose, error) {
	cmd, err := exec.LookPath("docker-compose")
	if err != nil {
		return nil, err
	}
	dc := &DockerCompose{
		rawCmd:      cmd,
		composeFile: composeFile,
	}
	return dc, nil
}

func (d *DockerCompose) Start() {
	args := []string{
		"-f", d.composeFile, "up",
	}
	cmd := exec.Command(d.rawCmd, args...)
	buf := new(bytes.Buffer)
	d.handle = &dockerComposeHandle{
		cmd:    cmd,
		stopCh: make(chan int),
		output: buf,
	}
	go d.handle.run()
}

func (d *DockerCompose) Stop() {
	d.handle.stop()
}
func (d *DockerCompose) Output() io.Reader {
	return d.handle.output
}

func (h *dockerComposeHandle) run() {
	h.cmd.Stdout = h.output
	// h.cmd.Stderr = h.Output

	if err := h.cmd.Start(); err != nil {
		log.Fatal(err)
	}

	select {
	case <-h.stopCh:
		os.Stdout.Write([]byte("recieved stop signal"))
	}

	h.cmd.Process.Signal(os.Interrupt)
}

func (h *dockerComposeHandle) stop() {
	h.stopCh <- 1
}
<|endoftext|>


<commit_before>package integration

import (
	"testing"

	"github.com/openshift/origin/pkg/cmd/server/api"
	"github.com/openshift/origin/pkg/cmd/server/bootstrappolicy"
	overrideapi "github.com/openshift/origin/pkg/quota/admission/clusterresourceoverride/api"
	testutil "github.com/openshift/origin/test/util"
	testserver "github.com/openshift/origin/test/util/server"
	kapi "k8s.io/kubernetes/pkg/api"
	apierrors "k8s.io/kubernetes/pkg/api/errors"
	"k8s.io/kubernetes/pkg/api/resource"
	kclient "k8s.io/kubernetes/pkg/client/unversioned"

	_ "github.com/openshift/origin/pkg/quota/admission/clusterresourceoverride/api/install"
)

func TestClusterResourceOverridePluginWithNoLimits(t *testing.T) {
	config := &overrideapi.ClusterResourceOverrideConfig{
		LimitCPUToMemoryPercent:     100,
		CPURequestToLimitPercent:    50,
		MemoryRequestToLimitPercent: 50,
	}
	kubeClient := setupClusterResourceOverrideTest(t, config)
	podHandler := kubeClient.Pods(testutil.Namespace())

	// test with no limits object present

	podCreated, err := podHandler.Create(testClusterResourceOverridePod("limitless", "2Gi", "1"))
	if err != nil {
		t.Fatal(err)
	}
	if memory := podCreated.Spec.Containers[0].Resources.Requests.Memory(); memory.Cmp(resource.MustParse("1Gi")) != 0 {
		t.Errorf("limitlesspod: Memory did not match expected 1Gi: %#v", memory)
	}
	if cpu := podCreated.Spec.Containers[0].Resources.Limits.Cpu(); cpu.Cmp(resource.MustParse("2")) != 0 {
		t.Errorf("limitlesspod: CPU limit did not match expected 2 core: %#v", cpu)
	}
	if cpu := podCreated.Spec.Containers[0].Resources.Requests.Cpu(); cpu.Cmp(resource.MustParse("1")) != 0 {
		t.Errorf("limitlesspod: CPU req did not match expected 1 core: %#v", cpu)
	}
}

func TestClusterResourceOverridePluginWithLimits(t *testing.T) {
	config := &overrideapi.ClusterResourceOverrideConfig{
		LimitCPUToMemoryPercent:     100,
		CPURequestToLimitPercent:    50,
		MemoryRequestToLimitPercent: 50,
	}
	kubeClient := setupClusterResourceOverrideTest(t, config)
	podHandler := kubeClient.Pods(testutil.Namespace())
	limitHandler := kubeClient.LimitRanges(testutil.Namespace())

	// test with limits object with defaults;
	// I wanted to test with a limits object without defaults to see limits forbid an empty resource spec,
	// but found that if defaults aren't set in the limit object, something still fills them in.
	// note: defaults are only used when quantities are *missing*, not when they are 0
	limitItem := kapi.LimitRangeItem{
		Type:                 kapi.LimitTypeContainer,
		Max:                  testResourceList("2Gi", "2"),
		Min:                  testResourceList("128Mi", "200m"),
		Default:              testResourceList("512Mi", "500m"), // note: auto-filled from max if we set that;
		DefaultRequest:       testResourceList("128Mi", "200m"), // filled from max if set, or min if that is set
		MaxLimitRequestRatio: kapi.ResourceList{},
	}
	limit := &kapi.LimitRange{
		ObjectMeta: kapi.ObjectMeta{Name: "limit"},
		Spec:       kapi.LimitRangeSpec{Limits: []kapi.LimitRangeItem{limitItem}},
	}
	_, err := limitHandler.Create(limit)
	if err != nil {
		t.Fatal(err)
	}
	podCreated, err := podHandler.Create(testClusterResourceOverridePod("limit-with-default", "", "1"))
	if err != nil {
		t.Fatal(err)
	}
	if memory := podCreated.Spec.Containers[0].Resources.Limits.Memory(); memory.Cmp(resource.MustParse("512Mi")) != 0 {
		t.Errorf("limit-with-default: Memory limit did not match default 512Mi: %v", memory)
	}
	if memory := podCreated.Spec.Containers[0].Resources.Requests.Memory(); memory.Cmp(resource.MustParse("256Mi")) != 0 {
		t.Errorf("limit-with-default: Memory req did not match expected 256Mi: %v", memory)
	}
	if cpu := podCreated.Spec.Containers[0].Resources.Limits.Cpu(); cpu.Cmp(resource.MustParse("500m")) != 0 {
		t.Errorf("limit-with-default: CPU limit did not match expected 500 mcore: %v", cpu)
	}
	if cpu := podCreated.Spec.Containers[0].Resources.Requests.Cpu(); cpu.Cmp(resource.MustParse("250m")) != 0 {
		t.Errorf("limit-with-default: CPU req did not match expected 250 mcore: %v", cpu)
	}

	// set it up so that the overrides create resources that fail validation
	_, err = podHandler.Create(testClusterResourceOverridePod("limit-with-default-fail", "128Mi", "1"))
	if err == nil {
		t.Errorf("limit-with-default-fail: expected to be forbidden")
	} else if !apierrors.IsForbidden(err) {
		t.Errorf("limit-with-default-fail: unexpected error: %v", err)
	}
}

func setupClusterResourceOverrideTest(t *testing.T, pluginConfig *overrideapi.ClusterResourceOverrideConfig) kclient.Interface {
	masterConfig, err := testserver.DefaultMasterOptions()
	if err != nil {
		t.Fatal(err)
	}
	// fill in possibly-empty config values
	if masterConfig.KubernetesMasterConfig == nil {
		masterConfig.KubernetesMasterConfig = &api.KubernetesMasterConfig{}
	}
	kubeMaster := masterConfig.KubernetesMasterConfig
	if kubeMaster.AdmissionConfig.PluginConfig == nil {
		kubeMaster.AdmissionConfig.PluginConfig = map[string]api.AdmissionPluginConfig{}
	}
	// set our config as desired
	kubeMaster.AdmissionConfig.PluginConfig[overrideapi.PluginName] =
		api.AdmissionPluginConfig{Configuration: pluginConfig}

	// start up a server and return useful clients to that server
	clusterAdminKubeConfig, err := testserver.StartConfiguredMaster(masterConfig)
	if err != nil {
		t.Fatal(err)
	}
	clusterAdminKubeClient, err := testutil.GetClusterAdminKubeClient(clusterAdminKubeConfig)
	if err != nil {
		t.Fatal(err)
	}
	clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig)
	if err != nil {
		t.Fatal(err)
	}
	// need to create a project and return client for project admin
	clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig)
	if err != nil {
		t.Fatal(err)
	}
	_, err = testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, testutil.Namespace(), "peon")
	if err != nil {
		t.Fatal(err)
	}
	if err := testserver.WaitForServiceAccounts(clusterAdminKubeClient, testutil.Namespace(), []string{bootstrappolicy.DefaultServiceAccountName}); err != nil {
		t.Fatal(err)
	}
	return clusterAdminKubeClient
}

func testClusterResourceOverridePod(name string, memory string, cpu string) *kapi.Pod {
	resources := kapi.ResourceRequirements{
		Limits:   testResourceList(memory, cpu),
		Requests: kapi.ResourceList{},
	}
	container := kapi.Container{Name: name, Image: "scratch", Resources: resources}
	pod := &kapi.Pod{
		ObjectMeta: kapi.ObjectMeta{Name: name},
		Spec:       kapi.PodSpec{Containers: []kapi.Container{container}},
	}
	return pod
}

func testResourceList(memory string, cpu string) kapi.ResourceList {
	list := kapi.ResourceList{}
	if memory != "" {
		list[kapi.ResourceMemory] = resource.MustParse(memory)
	}
	if cpu != "" {
		list[kapi.ResourceCPU] = resource.MustParse(cpu)
	}
	return list
}
<commit_msg>Test must set RequireEtcd<commit_after>package integration

import (
	"testing"

	"github.com/openshift/origin/pkg/cmd/server/api"
	"github.com/openshift/origin/pkg/cmd/server/bootstrappolicy"
	overrideapi "github.com/openshift/origin/pkg/quota/admission/clusterresourceoverride/api"
	testutil "github.com/openshift/origin/test/util"
	testserver "github.com/openshift/origin/test/util/server"
	kapi "k8s.io/kubernetes/pkg/api"
	apierrors "k8s.io/kubernetes/pkg/api/errors"
	"k8s.io/kubernetes/pkg/api/resource"
	kclient "k8s.io/kubernetes/pkg/client/unversioned"

	_ "github.com/openshift/origin/pkg/quota/admission/clusterresourceoverride/api/install"
)

func TestClusterResourceOverridePluginWithNoLimits(t *testing.T) {
	config := &overrideapi.ClusterResourceOverrideConfig{
		LimitCPUToMemoryPercent:     100,
		CPURequestToLimitPercent:    50,
		MemoryRequestToLimitPercent: 50,
	}
	kubeClient := setupClusterResourceOverrideTest(t, config)
	podHandler := kubeClient.Pods(testutil.Namespace())

	// test with no limits object present

	podCreated, err := podHandler.Create(testClusterResourceOverridePod("limitless", "2Gi", "1"))
	if err != nil {
		t.Fatal(err)
	}
	if memory := podCreated.Spec.Containers[0].Resources.Requests.Memory(); memory.Cmp(resource.MustParse("1Gi")) != 0 {
		t.Errorf("limitlesspod: Memory did not match expected 1Gi: %#v", memory)
	}
	if cpu := podCreated.Spec.Containers[0].Resources.Limits.Cpu(); cpu.Cmp(resource.MustParse("2")) != 0 {
		t.Errorf("limitlesspod: CPU limit did not match expected 2 core: %#v", cpu)
	}
	if cpu := podCreated.Spec.Containers[0].Resources.Requests.Cpu(); cpu.Cmp(resource.MustParse("1")) != 0 {
		t.Errorf("limitlesspod: CPU req did not match expected 1 core: %#v", cpu)
	}
}

func TestClusterResourceOverridePluginWithLimits(t *testing.T) {
	config := &overrideapi.ClusterResourceOverrideConfig{
		LimitCPUToMemoryPercent:     100,
		CPURequestToLimitPercent:    50,
		MemoryRequestToLimitPercent: 50,
	}
	kubeClient := setupClusterResourceOverrideTest(t, config)
	podHandler := kubeClient.Pods(testutil.Namespace())
	limitHandler := kubeClient.LimitRanges(testutil.Namespace())

	// test with limits object with defaults;
	// I wanted to test with a limits object without defaults to see limits forbid an empty resource spec,
	// but found that if defaults aren't set in the limit object, something still fills them in.
	// note: defaults are only used when quantities are *missing*, not when they are 0
	limitItem := kapi.LimitRangeItem{
		Type:                 kapi.LimitTypeContainer,
		Max:                  testResourceList("2Gi", "2"),
		Min:                  testResourceList("128Mi", "200m"),
		Default:              testResourceList("512Mi", "500m"), // note: auto-filled from max if we set that;
		DefaultRequest:       testResourceList("128Mi", "200m"), // filled from max if set, or min if that is set
		MaxLimitRequestRatio: kapi.ResourceList{},
	}
	limit := &kapi.LimitRange{
		ObjectMeta: kapi.ObjectMeta{Name: "limit"},
		Spec:       kapi.LimitRangeSpec{Limits: []kapi.LimitRangeItem{limitItem}},
	}
	_, err := limitHandler.Create(limit)
	if err != nil {
		t.Fatal(err)
	}
	podCreated, err := podHandler.Create(testClusterResourceOverridePod("limit-with-default", "", "1"))
	if err != nil {
		t.Fatal(err)
	}
	if memory := podCreated.Spec.Containers[0].Resources.Limits.Memory(); memory.Cmp(resource.MustParse("512Mi")) != 0 {
		t.Errorf("limit-with-default: Memory limit did not match default 512Mi: %v", memory)
	}
	if memory := podCreated.Spec.Containers[0].Resources.Requests.Memory(); memory.Cmp(resource.MustParse("256Mi")) != 0 {
		t.Errorf("limit-with-default: Memory req did not match expected 256Mi: %v", memory)
	}
	if cpu := podCreated.Spec.Containers[0].Resources.Limits.Cpu(); cpu.Cmp(resource.MustParse("500m")) != 0 {
		t.Errorf("limit-with-default: CPU limit did not match expected 500 mcore: %v", cpu)
	}
	if cpu := podCreated.Spec.Containers[0].Resources.Requests.Cpu(); cpu.Cmp(resource.MustParse("250m")) != 0 {
		t.Errorf("limit-with-default: CPU req did not match expected 250 mcore: %v", cpu)
	}

	// set it up so that the overrides create resources that fail validation
	_, err = podHandler.Create(testClusterResourceOverridePod("limit-with-default-fail", "128Mi", "1"))
	if err == nil {
		t.Errorf("limit-with-default-fail: expected to be forbidden")
	} else if !apierrors.IsForbidden(err) {
		t.Errorf("limit-with-default-fail: unexpected error: %v", err)
	}
}

func setupClusterResourceOverrideTest(t *testing.T, pluginConfig *overrideapi.ClusterResourceOverrideConfig) kclient.Interface {
	testutil.RequireEtcd(t)
	masterConfig, err := testserver.DefaultMasterOptions()
	if err != nil {
		t.Fatal(err)
	}
	// fill in possibly-empty config values
	if masterConfig.KubernetesMasterConfig == nil {
		masterConfig.KubernetesMasterConfig = &api.KubernetesMasterConfig{}
	}
	kubeMaster := masterConfig.KubernetesMasterConfig
	if kubeMaster.AdmissionConfig.PluginConfig == nil {
		kubeMaster.AdmissionConfig.PluginConfig = map[string]api.AdmissionPluginConfig{}
	}
	// set our config as desired
	kubeMaster.AdmissionConfig.PluginConfig[overrideapi.PluginName] =
		api.AdmissionPluginConfig{Configuration: pluginConfig}

	// start up a server and return useful clients to that server
	clusterAdminKubeConfig, err := testserver.StartConfiguredMaster(masterConfig)
	if err != nil {
		t.Fatal(err)
	}
	clusterAdminKubeClient, err := testutil.GetClusterAdminKubeClient(clusterAdminKubeConfig)
	if err != nil {
		t.Fatal(err)
	}
	clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig)
	if err != nil {
		t.Fatal(err)
	}
	// need to create a project and return client for project admin
	clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig)
	if err != nil {
		t.Fatal(err)
	}
	_, err = testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, testutil.Namespace(), "peon")
	if err != nil {
		t.Fatal(err)
	}
	if err := testserver.WaitForServiceAccounts(clusterAdminKubeClient, testutil.Namespace(), []string{bootstrappolicy.DefaultServiceAccountName}); err != nil {
		t.Fatal(err)
	}
	return clusterAdminKubeClient
}

func testClusterResourceOverridePod(name string, memory string, cpu string) *kapi.Pod {
	resources := kapi.ResourceRequirements{
		Limits:   testResourceList(memory, cpu),
		Requests: kapi.ResourceList{},
	}
	container := kapi.Container{Name: name, Image: "scratch", Resources: resources}
	pod := &kapi.Pod{
		ObjectMeta: kapi.ObjectMeta{Name: name},
		Spec:       kapi.PodSpec{Containers: []kapi.Container{container}},
	}
	return pod
}

func testResourceList(memory string, cpu string) kapi.ResourceList {
	list := kapi.ResourceList{}
	if memory != "" {
		list[kapi.ResourceMemory] = resource.MustParse(memory)
	}
	if cpu != "" {
		list[kapi.ResourceCPU] = resource.MustParse(cpu)
	}
	return list
}
<|endoftext|>


<commit_before><commit_msg>v0.9.6<commit_after><|endoftext|>


<commit_before>// The igo command starts a Go kernel for IPython.
package main

import (
    "flag"
    "io"
    "log"
    "os"
    igo "github.com/takluyver/igo/igopkg"
)

func main() {
    debug := flag.Bool("debug", false, "Log extra info to stderr")
    flag.Parse()
    if flag.NArg() < 1 {
        log.Fatalln("Need a command line argument for the connection file.")
    }
    var logwriter io.Writer = os.Stderr
    var err error
    if !*debug {
        logwriter, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0666)
        if err != nil {
            log.Fatalln(err)
        }
    }
    igo.RunKernel(flag.Arg(0), logwriter)
}

<commit_msg>Use ioutil.Discard instead of opening /dev/null<commit_after>// The igo command starts a Go kernel for IPython.
package main

import (
    "flag"
    "io"
    "io/ioutil"
    "log"
    "os"
    igo "github.com/takluyver/igo/igopkg"
)

func main() {
    debug := flag.Bool("debug", false, "Log extra info to stderr")
    flag.Parse()
    if flag.NArg() < 1 {
        log.Fatalln("Need a command line argument for the connection file.")
    }
    var logwriter io.Writer = os.Stderr
    if !*debug {
        logwriter = ioutil.Discard
    }
    igo.RunKernel(flag.Arg(0), logwriter)
}

<|endoftext|>


<commit_before>// Package graphemes provides a scanner for Unicode text segmentation grapheme cluster boundaries: https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
package graphemes

import (
	"bufio"
	"fmt"
	"io"
	"unicode/utf8"
)

// NewScanner tokenizes a reader into a stream of grapheme clusters according to Unicode Text Segmentation boundaries https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
// Iterate through the stream by calling Scan() until false.
//	text := "Good dog! 👍🏼🐶"
//	reader := strings.NewReader(text)
//
//	scanner := graphemes.NewScanner(reader)
//	for scanner.Scan() {
//		fmt.Printf("%s\n", scanner.Text())
//	}
//	if err := scanner.Err(); err != nil {
//		log.Fatal(err)
//	}
func NewScanner(r io.Reader) *bufio.Scanner {
	scanner := bufio.NewScanner(r)
	scanner.Split(SplitFunc)
	return scanner
}

var trie = newGraphemesTrie(0)

// is tests if the first rune of s is in categories
func is(categories uint16, s []byte) bool {
	lookup, _ := trie.lookup(s)
	return (lookup & categories) != 0
}

var _Ignore = _Extend

// SplitFunc is a bufio.SplitFunc implementation of grapheme cluster segmentation, for use with bufio.Scanner
func SplitFunc(data []byte, atEOF bool) (advance int, token []byte, err error) {
	if atEOF && len(data) == 0 {
		return 0, nil, nil
	}

	current := 0

	for {
		if current == len(data) && !atEOF {
			// Request more data
			return 0, nil, nil
		}

		sot := current == 0 // "start of text"
		eof := len(data) == current

		// https://unicode.org/reports/tr29/#SB1
		if sot && !eof {
			_, w := utf8.DecodeRune(data[current:])
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#SB2
		if eof {
			break
		}

		// Rules are usually of the form Cat1 × Cat2; "current" refers to the first category
		// to the right of the ×, from which we look back or forward

		// Decoding runes is a bit redundant, it happens in other places too
		// We do it here for clarity and to pick up errors early

		r, w := utf8.DecodeRune(data[current:])
		if r == utf8.RuneError {
			return 0, nil, fmt.Errorf("error decoding rune at byte 0x%x", data[current])
		}

		_, pw := utf8.DecodeLastRune(data[:current])
		last := current - pw

		// https://unicode.org/reports/tr29/#GB3
		if is(_LF, data[current:]) && is(_CR, data[last:]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB4
		if is(_Control|_CR|_LF, data[last:]) {
			break
		}

		// https://unicode.org/reports/tr29/#GB5
		if is(_Control|_CR|_LF, data[current:]) {
			break
		}

		// https://unicode.org/reports/tr29/#GB6
		if is(_L|_V|_LV|_LVT, data[current:]) && is(_L, data[last:]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB7
		if is(_V|_T, data[current:]) && is(_LV|_V, data[last:]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB8
		if is(_T, data[current:]) && is(_LVT|_T, data[last:]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB9
		if is(_Extend|_ZWJ, data[current:]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB9a
		if is(_SpacingMark, data[current:]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB9b
		if is(_Prepend, data[last:]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB11
		if is(_Extended_Pictographic, data[current:]) && is(_ZWJ, data[last:]) && previous(_Extended_Pictographic, data[:last]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB12
		if is(_Regional_Indicator, data[current:]) {
			allRI := true

			// Buffer comprised entirely of an odd number of RI, ignoring Extend|Format|ZWJ
			i := current
			count := 0
			for i > 0 {
				_, w := utf8.DecodeLastRune(data[:i])
				i -= w
				if !is(_Regional_Indicator, data[i:]) {
					allRI = false
					break
				}
				count++
			}

			if allRI {
				odd := count > 0 && count%2 == 1
				if odd {
					current += w
					continue
				}
			}
		}

		// https://unicode.org/reports/tr29/#GB13
		if is(_Regional_Indicator, data[current:]) {
			odd := false
			// Last n runes represent an odd number of RI, ignoring Extend|Format|ZWJ
			i := current
			count := 0
			for i > 0 {
				_, w := utf8.DecodeLastRune(data[:i])
				i -= w
				if !is(_Regional_Indicator, data[i:]) {
					odd = count > 0 && count%2 == 1
					break
				}
				count++
			}

			if odd {
				current += w
				continue
			}
		}

		// If we fall through all the above rules, it's a grapheme cluster break
		break
	}

	// Return token
	return current, data[:current], nil
}
<commit_msg>Comments<commit_after>// Package graphemes provides a scanner for Unicode text segmentation grapheme cluster boundaries: https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
package graphemes

import (
	"bufio"
	"fmt"
	"io"
	"unicode/utf8"
)

// NewScanner tokenizes a reader into a stream of grapheme clusters according to Unicode Text Segmentation boundaries https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
// Iterate through the stream by calling Scan() until false.
//	text := "Good dog! 👍🏼🐶"
//	reader := strings.NewReader(text)
//
//	scanner := graphemes.NewScanner(reader)
//	for scanner.Scan() {
//		fmt.Printf("%s\n", scanner.Text())
//	}
//	if err := scanner.Err(); err != nil {
//		log.Fatal(err)
//	}
func NewScanner(r io.Reader) *bufio.Scanner {
	scanner := bufio.NewScanner(r)
	scanner.Split(SplitFunc)
	return scanner
}

var trie = newGraphemesTrie(0)

// is tests if the first rune of s is in categories
func is(categories uint16, s []byte) bool {
	lookup, _ := trie.lookup(s)
	return (lookup & categories) != 0
}

var _Ignore = _Extend

// SplitFunc is a bufio.SplitFunc implementation of grapheme cluster segmentation, for use with bufio.Scanner
func SplitFunc(data []byte, atEOF bool) (advance int, token []byte, err error) {
	if atEOF && len(data) == 0 {
		return 0, nil, nil
	}

	current := 0

	for {
		if current == len(data) && !atEOF {
			// Request more data
			return 0, nil, nil
		}

		sot := current == 0 // "start of text"
		eof := len(data) == current

		// https://unicode.org/reports/tr29/#SB1
		if sot && !eof {
			_, w := utf8.DecodeRune(data[current:])
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#SB2
		if eof {
			break
		}

		// Rules are usually of the form Cat1 × Cat2; "current" refers to the first category
		// to the right of the ×, from which we look back or forward

		// Decoding runes is a bit redundant, it happens in other places too
		// We do it here for clarity and to pick up errors early

		r, w := utf8.DecodeRune(data[current:])
		if r == utf8.RuneError {
			return 0, nil, fmt.Errorf("error decoding rune at byte 0x%x", data[current])
		}

		_, pw := utf8.DecodeLastRune(data[:current])
		last := current - pw

		// https://unicode.org/reports/tr29/#GB3
		if is(_LF, data[current:]) && is(_CR, data[last:]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB4
		if is(_Control|_CR|_LF, data[last:]) {
			break
		}

		// https://unicode.org/reports/tr29/#GB5
		if is(_Control|_CR|_LF, data[current:]) {
			break
		}

		// https://unicode.org/reports/tr29/#GB6
		if is(_L|_V|_LV|_LVT, data[current:]) && is(_L, data[last:]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB7
		if is(_V|_T, data[current:]) && is(_LV|_V, data[last:]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB8
		if is(_T, data[current:]) && is(_LVT|_T, data[last:]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB9
		if is(_Extend|_ZWJ, data[current:]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB9a
		if is(_SpacingMark, data[current:]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB9b
		if is(_Prepend, data[last:]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB11
		if is(_Extended_Pictographic, data[current:]) && is(_ZWJ, data[last:]) && previous(_Extended_Pictographic, data[:last]) {
			current += w
			continue
		}

		// https://unicode.org/reports/tr29/#GB12
		if is(_Regional_Indicator, data[current:]) {
			allRI := true

			// Buffer comprised entirely of an odd number of RI
			i := current
			count := 0
			for i > 0 {
				_, w := utf8.DecodeLastRune(data[:i])
				i -= w
				if !is(_Regional_Indicator, data[i:]) {
					allRI = false
					break
				}
				count++
			}

			if allRI {
				odd := count > 0 && count%2 == 1
				if odd {
					current += w
					continue
				}
			}
		}

		// https://unicode.org/reports/tr29/#GB13
		if is(_Regional_Indicator, data[current:]) {
			odd := false
			// Last n runes represent an odd number of RI
			i := current
			count := 0
			for i > 0 {
				_, w := utf8.DecodeLastRune(data[:i])
				i -= w
				if !is(_Regional_Indicator, data[i:]) {
					odd = count > 0 && count%2 == 1
					break
				}
				count++
			}

			if odd {
				current += w
				continue
			}
		}

		// If we fall through all the above rules, it's a grapheme cluster break
		break
	}

	// Return token
	return current, data[:current], nil
}
<|endoftext|>


<commit_before>/*
Copyright 2017 Google 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 errdiff makes it easy to compare Error by code, substring or exact
// match in tests.
//
// Similar in intended usage to messagediff.Diff and pretty.Compare,
// particularly in table-driven tests.
//
// Example usage:
//
//	testCases := []struct {
//		...
//		wantSubstring string
//	}{
//		// Success
//		{...},
//		// Failures
//		{..., wantSubstring: "failed"},
//		{..., wantSubstring: "too many users"},
//	}
//	for _, c := range testCases {
//		got, err := fn(...)
//		if diff := errdiff.Substring(err, c.wantSubstring); diff != "" {
//			t.Errorf("fn() %v", diff)
//			continue
//		}
//		...
//	}
//
// The generic function Check may be used in place of Code or
// Substring or when comparing against another error or for simple
// existance of an error:
//
//	testCases := []struct {
//		...
//		err interface{}
//	}{
//		// Success
//		{...},
//		// Failures
//		{..., err: io.EOF},  // An explicit error
//		{..., err: "my expected error string"},  // contains text
//		{..., err: true}, // expect an error, don't care what
//	}
//	for _, c := range testCases {
//		got, err := fn(...)
//		if diff := errdiff.Check(err, c.err); diff != "" {
//			t.Errorf("fn() %v", diff)
//			continue
//		}
//		...
package errdiff

import (
	"fmt"
	"strings"

	"google.golang.org/grpc/codes"
	"google.golang.org/grpc"
)

// Text returns a message describing the difference between the
// error text and the desired input. want="" indicates that no error is
// expected.
func Text(got error, want string) string {
	if want == "" {
		if got == nil {
			return ""
		}
		return fmt.Sprintf("got err=%v, want err=nil", got)
	}
	if got == nil {
		return fmt.Sprintf("got err=nil, want err with exact text %v", want)
	}
	if got.Error() != want {
		return fmt.Sprintf("got err=%v, want err with exact text %v", got, want)
	}
	return ""
}

// ExactTextCompare is deprecated. Please use Text.
func ExactTextCompare(got error, want string) string {
	return Text(got, want)
}

// Substring returns a message describing the difference between the
// error text and the desired input. want="" indicates that no error is
// expected.
func Substring(got error, want string) string {
	if want == "" {
		if got == nil {
			return ""
		}
		return fmt.Sprintf("got err=%v, want err=nil", got)
	}
	if got == nil {
		return fmt.Sprintf("got err=nil, want err containing %v", want)
	}
	if !strings.Contains(got.Error(), want) {
		return fmt.Sprintf("got err=%v, want err containing %v", got, want)
	}
	return ""
}

// Code returns a message describing the difference between the error's
// code and the desired codes. want=codes.OK indicates that no error is
// expected.
func Code(got error, want codes.Code) string {
	if want == codes.OK {
		if got == nil {
			return ""
		}
		return fmt.Sprintf("got err=%v, want OK", got)
	}
	if got == nil {
		return fmt.Sprintf("got err=nil, want code %v", want)
	}
	if grpc.Code(got) != want {
		return fmt.Sprintf("got err=%v, want code %v", got, want)
	}
	return ""
}

// CodeCompare is deprecated, please use Code.
func CodeCompare(got error, want codes.Code) string {
	return Code(got, want)
}

// StatusCompare is deprecated, please use Code.
func StatusCompare(got error, want codes.Code) string {
	return Code(got, want)
}

// Check returns a message describing the difference between the error err and
// want.  If want is a codes.Code, this function is the same as Code.
// If want is a string, this function is the same as Substring.  If
// want is an error, this is essentially the same as ExactTextCompare(got,
// w.Error()).  If want is a bool, err is simply tested for existance (want of
// true means an error is wanted).
func Check(got error, want interface{}) string {
	switch w := want.(type) {
	case nil:
		if got == nil {
			return ""
		}
		return fmt.Sprintf("got err=%v, want err=nil", got)
	case bool:
		switch {
		case w && got == nil:
			return "did not get expected error"
		case !w && got != nil:
			return fmt.Sprintf("got err=%v, want err=nil", got)
		}
		return ""
	case codes.Code:
		return CodeCompare(got, w)
	case string:
		return Substring(got, w)
	case error:
		switch {
		case got == w:
			return ""
		case got == nil:
			return fmt.Sprintf("got err=nil, want err=%v", w)
		case w == nil:
			return fmt.Sprintf("got err=%v, want err=nil", got)
		case got.Error() == w.Error():
			return ""
		default:
			return fmt.Sprintf("got err=%v, want err=%v", got, w)
		}
	default:
		return fmt.Sprintf("unsupported type in Check: %T", want)
	}
}
<commit_msg>Remove all deprecated functions from errdiff.<commit_after>/*
Copyright 2017 Google 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 errdiff makes it easy to compare Error by code, substring or exact
// match in tests.
//
// Similar in intended usage to messagediff.Diff and pretty.Compare,
// particularly in table-driven tests.
//
// Example usage:
//
//	testCases := []struct {
//		...
//		wantSubstring string
//	}{
//		// Success
//		{...},
//		// Failures
//		{..., wantSubstring: "failed"},
//		{..., wantSubstring: "too many users"},
//	}
//	for _, c := range testCases {
//		got, err := fn(...)
//		if diff := errdiff.Substring(err, c.wantSubstring); diff != "" {
//			t.Errorf("fn() %v", diff)
//			continue
//		}
//		...
//	}
//
// The generic function Check may be used in place of Code or
// Substring or when comparing against another error or for simple
// existance of an error:
//
//	testCases := []struct {
//		...
//		err interface{}
//	}{
//		// Success
//		{...},
//		// Failures
//		{..., err: io.EOF},  // An explicit error
//		{..., err: "my expected error string"},  // contains text
//		{..., err: true}, // expect an error, don't care what
//	}
//	for _, c := range testCases {
//		got, err := fn(...)
//		if diff := errdiff.Check(err, c.err); diff != "" {
//			t.Errorf("fn() %v", diff)
//			continue
//		}
//		...
package errdiff

import (
	"fmt"
	"strings"

	"google.golang.org/grpc/codes"
	"google.golang.org/grpc"
)

// Text returns a message describing the difference between the
// error text and the desired input. want="" indicates that no error is
// expected.
func Text(got error, want string) string {
	if want == "" {
		if got == nil {
			return ""
		}
		return fmt.Sprintf("got err=%v, want err=nil", got)
	}
	if got == nil {
		return fmt.Sprintf("got err=nil, want err with exact text %v", want)
	}
	if got.Error() != want {
		return fmt.Sprintf("got err=%v, want err with exact text %v", got, want)
	}
	return ""
}

// Substring returns a message describing the difference between the
// error text and the desired input. want="" indicates that no error is
// expected.
func Substring(got error, want string) string {
	if want == "" {
		if got == nil {
			return ""
		}
		return fmt.Sprintf("got err=%v, want err=nil", got)
	}
	if got == nil {
		return fmt.Sprintf("got err=nil, want err containing %v", want)
	}
	if !strings.Contains(got.Error(), want) {
		return fmt.Sprintf("got err=%v, want err containing %v", got, want)
	}
	return ""
}

// Code returns a message describing the difference between the error's
// code and the desired codes. want=codes.OK indicates that no error is
// expected.
func Code(got error, want codes.Code) string {
	if want == codes.OK {
		if got == nil {
			return ""
		}
		return fmt.Sprintf("got err=%v, want OK", got)
	}
	if got == nil {
		return fmt.Sprintf("got err=nil, want code %v", want)
	}
	if grpc.Code(got) != want {
		return fmt.Sprintf("got err=%v, want code %v", got, want)
	}
	return ""
}

// Check returns a message describing the difference between the error err and
// want.  If want is a codes.Code, this function is the same as Code.
// If want is a string, this function is the same as Substring.  If
// want is an error, this is essentially the same as ExactTextCompare(got,
// w.Error()).  If want is a bool, err is simply tested for existance (want of
// true means an error is wanted).
func Check(got error, want interface{}) string {
	switch w := want.(type) {
	case nil:
		if got == nil {
			return ""
		}
		return fmt.Sprintf("got err=%v, want err=nil", got)
	case bool:
		switch {
		case w && got == nil:
			return "did not get expected error"
		case !w && got != nil:
			return fmt.Sprintf("got err=%v, want err=nil", got)
		}
		return ""
	case codes.Code:
		return Code(got, w)
	case string:
		return Substring(got, w)
	case error:
		switch {
		case got == w:
			return ""
		case got == nil:
			return fmt.Sprintf("got err=nil, want err=%v", w)
		case w == nil:
			return fmt.Sprintf("got err=%v, want err=nil", got)
		case got.Error() == w.Error():
			return ""
		default:
			return fmt.Sprintf("got err=%v, want err=%v", got, w)
		}
	default:
		return fmt.Sprintf("unsupported type in Check: %T", want)
	}
}
<|endoftext|>


<commit_before>package models

import (
	"log"
	"time"
)

type Counter struct {
	Created    time.Time `db:"created"`
	Username   string    `db:"username"`
	Media      int64     `db:"media"`
	Follows    int64     `db:"follows"`
	FollowedBy int64     `db:"followed_by"`
}

func (db *DB) CountersCreate(c *Counter) error {
	countersCollection := db.Collection("counters")
	counterID, err := countersCollection.Insert(Counter{
		Created:    time.Now(),
		Username:   c.Username,
		Media:      c.Media,
		Follows:    c.Follows,
		FollowedBy: c.FollowedBy,
	})

	if err != nil {
		log.Fatal("Inserting counters error: ", err)
		return err
	}
	log.Printf("Add new counters with ID: %d", counterID)
	return nil
}

func (db *DB) LastCounters() (*Counter, error) {
	var counter *Counter
	q := db.SelectFrom("counters").OrderBy("created DESC").Limit(1)
	err := q.One(&counter)
	if err != nil {
		return nil, err
	}
	return counter, nil
}

func (db *DB) CountersForLastMonth() ([]*Counter, error) {
	var counters []*Counter
	q := db.SelectFrom("counters").Where("created > datetime('created', '-1 month')")
	err := q.All(&counters)
	if err != nil {
		log.Fatal("Err getCounterForLastMonth", err)
		return counters, err
	}
	log.Println("CountersForLastMonth: ", counters)
	return counters, nil
}
<commit_msg>Add json meta<commit_after>package models

import (
	"log"
	"time"
)

type Counter struct {
	Created    time.Time `db:"created" json:"created"`
	Username   string    `db:"username" json:"username"`
	Media      int64     `db:"media" json:"media"`
	Follows    int64     `db:"follows" json:"follows"`
	FollowedBy int64     `db:"followed_by" json:"followed_by"`
}

func (db *DB) CountersCreate(c *Counter) error {
	countersCollection := db.Collection("counters")
	counterID, err := countersCollection.Insert(Counter{
		Created:    time.Now(),
		Username:   c.Username,
		Media:      c.Media,
		Follows:    c.Follows,
		FollowedBy: c.FollowedBy,
	})

	if err != nil {
		log.Fatal("Inserting counters error: ", err)
		return err
	}
	log.Printf("Add new counters with ID: %d", counterID)
	return nil
}

func (db *DB) LastCounters() (*Counter, error) {
	var counter *Counter
	q := db.SelectFrom("counters").OrderBy("created DESC").Limit(1)
	err := q.One(&counter)
	if err != nil {
		return nil, err
	}
	return counter, nil
}

func (db *DB) CountersForLastMonth() ([]*Counter, error) {
	var counters []*Counter
	q := db.SelectFrom("counters").Where("created > datetime('created', '-1 month')")
	err := q.All(&counters)
	if err != nil {
		log.Fatal("Err getCounterForLastMonth", err)
		return counters, err
	}
	log.Println("CountersForLastMonth: ", counters)
	return counters, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
	"time"

	c "github.com/flynn/flynn/Godeps/_workspace/src/github.com/flynn/go-check"
	"github.com/flynn/flynn/pkg/attempt"
)

type GitDeploySuite struct {
	Helper
}

var _ = c.ConcurrentSuite(&GitDeploySuite{})

func (s *GitDeploySuite) SetUpSuite(t *c.C) {
	t.Assert(flynn(t, "/", "key", "add", s.sshKeys(t).Pub), Succeeds)
}

var Attempts = attempt.Strategy{
	Total: 60 * time.Second,
	Delay: 500 * time.Millisecond,
}

func (s *GitDeploySuite) TestEnvDir(t *c.C) {
	r := s.newGitRepo(t, "env-dir")
	t.Assert(r.flynn("create"), Succeeds)
	t.Assert(r.flynn("env", "set", "FOO=bar", "BUILDPACK_URL=https://github.com/kr/heroku-buildpack-inline"), Succeeds)

	push := r.git("push", "flynn", "master")
	t.Assert(push, Succeeds)
	t.Assert(push, OutputContains, "bar")
}

func (s *GitDeploySuite) TestBuildCaching(t *c.C) {
	r := s.newGitRepo(t, "build-cache")
	t.Assert(r.flynn("create"), Succeeds)
	t.Assert(r.flynn("env", "set", "BUILDPACK_URL=https://github.com/kr/heroku-buildpack-inline"), Succeeds)

	r.git("commit", "-m", "bump", "--allow-empty")
	push := r.git("push", "flynn", "master")
	t.Assert(push, Succeeds)
	t.Assert(push, c.Not(OutputContains), "cached")

	r.git("commit", "-m", "bump", "--allow-empty")
	push = r.git("push", "flynn", "master")
	t.Assert(push, Succeeds)
	t.Assert(push, OutputContains, "cached: 0")

	r.git("commit", "-m", "bump", "--allow-empty")
	push = r.git("push", "flynn", "master")
	t.Assert(push, Succeeds)
	t.Assert(push, OutputContains, "cached: 1")
}

func (s *GitDeploySuite) TestAppRecreation(t *c.C) {
	r := s.newGitRepo(t, "empty")
	t.Assert(r.flynn("create", "-y", "app-recreation"), Succeeds)
	r.git("commit", "-m", "bump", "--allow-empty")
	t.Assert(r.git("push", "flynn", "master"), Succeeds)
	t.Assert(r.flynn("delete", "-y"), Succeeds)

	// recreate app and push again, it should work
	t.Assert(r.flynn("create", "-y", "app-recreation"), Succeeds)
	t.Assert(r.git("push", "flynn", "master"), Succeeds)
	t.Assert(r.flynn("delete", "-y"), Succeeds)
}

func (s *GitDeploySuite) TestGoBuildpack(t *c.C) {
	s.runBuildpackTest(t, "go-flynn-example", []string{"postgres"})
}

func (s *GitDeploySuite) TestNodejsBuildpack(t *c.C) {
	s.runBuildpackTest(t, "nodejs-flynn-example", nil)
}

func (s *GitDeploySuite) TestPhpBuildpack(t *c.C) {
	s.runBuildpackTest(t, "php-flynn-example", nil)
}

func (s *GitDeploySuite) TestRubyBuildpack(t *c.C) {
	s.runBuildpackTest(t, "ruby-flynn-example", nil)
}

func (s *GitDeploySuite) TestJavaBuildpack(t *c.C) {
	s.runBuildpackTest(t, "java-flynn-example", nil)
}

func (s *GitDeploySuite) TestClojureBuildpack(t *c.C) {
	s.runBuildpackTest(t, "clojure-flynn-example", nil)
}

func (s *GitDeploySuite) TestGradleBuildpack(t *c.C) {
	s.runBuildpackTest(t, "gradle-flynn-example", nil)
}

func (s *GitDeploySuite) TestPlayBuildpack(t *c.C) {
	s.runBuildpackTest(t, "play-flynn-example", nil)
}

func (s *GitDeploySuite) TestPythonBuildpack(t *c.C) {
	s.runBuildpackTest(t, "python-flynn-example", nil)
}

func (s *GitDeploySuite) runBuildpackTest(t *c.C, name string, resources []string) {
	r := s.newGitRepo(t, "https://github.com/flynn-examples/"+name)

	t.Assert(r.flynn("create", name), Outputs, fmt.Sprintf("Created %s\n", name))

	for _, resource := range resources {
		t.Assert(r.flynn("resource", "add", resource), Succeeds)
	}

	push := r.git("push", "flynn", "master")
	t.Assert(push, Succeeds)
	t.Assert(push, OutputContains, "Creating release")
	t.Assert(push, OutputContains, "Application deployed")
	t.Assert(push, OutputContains, "Added default web=1 formation")
	t.Assert(push, OutputContains, "* [new branch]      master -> master")

	route := name + ".dev"
	newRoute := r.flynn("route", "add", "http", route)
	t.Assert(newRoute, Succeeds)

	err := Attempts.Run(func() error {
		// Make HTTP requests
		client := &http.Client{}
		req, err := http.NewRequest("GET", "http://"+routerIP, nil)
		if err != nil {
			return err
		}
		req.Host = route
		res, err := client.Do(req)
		if err != nil {
			return err
		}
		defer res.Body.Close()
		contents, err := ioutil.ReadAll(res.Body)
		if err != nil {
			return err
		}
		if res.StatusCode != 200 {
			return fmt.Errorf("Expected status 200, got %v", res.StatusCode)
		}
		m, err := regexp.MatchString(`Hello from Flynn on port \d+`, string(contents))
		if err != nil {
			return err
		}
		if !m {
			return fmt.Errorf("Expected `Hello from Flynn on port \\d+`, got `%v`", string(contents))
		}
		return nil
	})
	t.Assert(err, c.IsNil)

	t.Assert(r.flynn("scale", "web=0"), Succeeds)
}
<commit_msg>test: Add resources after git push<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
	"time"

	c "github.com/flynn/flynn/Godeps/_workspace/src/github.com/flynn/go-check"
	"github.com/flynn/flynn/pkg/attempt"
)

type GitDeploySuite struct {
	Helper
}

var _ = c.ConcurrentSuite(&GitDeploySuite{})

func (s *GitDeploySuite) SetUpSuite(t *c.C) {
	t.Assert(flynn(t, "/", "key", "add", s.sshKeys(t).Pub), Succeeds)
}

var Attempts = attempt.Strategy{
	Total: 60 * time.Second,
	Delay: 500 * time.Millisecond,
}

func (s *GitDeploySuite) TestEnvDir(t *c.C) {
	r := s.newGitRepo(t, "env-dir")
	t.Assert(r.flynn("create"), Succeeds)
	t.Assert(r.flynn("env", "set", "FOO=bar", "BUILDPACK_URL=https://github.com/kr/heroku-buildpack-inline"), Succeeds)

	push := r.git("push", "flynn", "master")
	t.Assert(push, Succeeds)
	t.Assert(push, OutputContains, "bar")
}

func (s *GitDeploySuite) TestBuildCaching(t *c.C) {
	r := s.newGitRepo(t, "build-cache")
	t.Assert(r.flynn("create"), Succeeds)
	t.Assert(r.flynn("env", "set", "BUILDPACK_URL=https://github.com/kr/heroku-buildpack-inline"), Succeeds)

	r.git("commit", "-m", "bump", "--allow-empty")
	push := r.git("push", "flynn", "master")
	t.Assert(push, Succeeds)
	t.Assert(push, c.Not(OutputContains), "cached")

	r.git("commit", "-m", "bump", "--allow-empty")
	push = r.git("push", "flynn", "master")
	t.Assert(push, Succeeds)
	t.Assert(push, OutputContains, "cached: 0")

	r.git("commit", "-m", "bump", "--allow-empty")
	push = r.git("push", "flynn", "master")
	t.Assert(push, Succeeds)
	t.Assert(push, OutputContains, "cached: 1")
}

func (s *GitDeploySuite) TestAppRecreation(t *c.C) {
	r := s.newGitRepo(t, "empty")
	t.Assert(r.flynn("create", "-y", "app-recreation"), Succeeds)
	r.git("commit", "-m", "bump", "--allow-empty")
	t.Assert(r.git("push", "flynn", "master"), Succeeds)
	t.Assert(r.flynn("delete", "-y"), Succeeds)

	// recreate app and push again, it should work
	t.Assert(r.flynn("create", "-y", "app-recreation"), Succeeds)
	t.Assert(r.git("push", "flynn", "master"), Succeeds)
	t.Assert(r.flynn("delete", "-y"), Succeeds)
}

func (s *GitDeploySuite) TestGoBuildpack(t *c.C) {
	s.runBuildpackTest(t, "go-flynn-example", []string{"postgres"})
}

func (s *GitDeploySuite) TestNodejsBuildpack(t *c.C) {
	s.runBuildpackTest(t, "nodejs-flynn-example", nil)
}

func (s *GitDeploySuite) TestPhpBuildpack(t *c.C) {
	s.runBuildpackTest(t, "php-flynn-example", nil)
}

func (s *GitDeploySuite) TestRubyBuildpack(t *c.C) {
	s.runBuildpackTest(t, "ruby-flynn-example", nil)
}

func (s *GitDeploySuite) TestJavaBuildpack(t *c.C) {
	s.runBuildpackTest(t, "java-flynn-example", nil)
}

func (s *GitDeploySuite) TestClojureBuildpack(t *c.C) {
	s.runBuildpackTest(t, "clojure-flynn-example", nil)
}

func (s *GitDeploySuite) TestGradleBuildpack(t *c.C) {
	s.runBuildpackTest(t, "gradle-flynn-example", nil)
}

func (s *GitDeploySuite) TestPlayBuildpack(t *c.C) {
	s.runBuildpackTest(t, "play-flynn-example", nil)
}

func (s *GitDeploySuite) TestPythonBuildpack(t *c.C) {
	s.runBuildpackTest(t, "python-flynn-example", nil)
}

func (s *GitDeploySuite) runBuildpackTest(t *c.C, name string, resources []string) {
	r := s.newGitRepo(t, "https://github.com/flynn-examples/"+name)

	t.Assert(r.flynn("create", name), Outputs, fmt.Sprintf("Created %s\n", name))

	push := r.git("push", "flynn", "master")
	t.Assert(push, Succeeds)
	t.Assert(push, OutputContains, "Creating release")
	t.Assert(push, OutputContains, "Application deployed")
	t.Assert(push, OutputContains, "Added default web=1 formation")
	t.Assert(push, OutputContains, "* [new branch]      master -> master")

	// Although not adding the resource before the deploy will result in an
	// initially crashing release, add it after the git push so that the
	// initial release gets a default web=1 formation from the receiver.
	for _, resource := range resources {
		t.Assert(r.flynn("resource", "add", resource), Succeeds)
	}

	route := name + ".dev"
	newRoute := r.flynn("route", "add", "http", route)
	t.Assert(newRoute, Succeeds)

	err := Attempts.Run(func() error {
		// Make HTTP requests
		client := &http.Client{}
		req, err := http.NewRequest("GET", "http://"+routerIP, nil)
		if err != nil {
			return err
		}
		req.Host = route
		res, err := client.Do(req)
		if err != nil {
			return err
		}
		defer res.Body.Close()
		contents, err := ioutil.ReadAll(res.Body)
		if err != nil {
			return err
		}
		if res.StatusCode != 200 {
			return fmt.Errorf("Expected status 200, got %v", res.StatusCode)
		}
		m, err := regexp.MatchString(`Hello from Flynn on port \d+`, string(contents))
		if err != nil {
			return err
		}
		if !m {
			return fmt.Errorf("Expected `Hello from Flynn on port \\d+`, got `%v`", string(contents))
		}
		return nil
	})
	t.Assert(err, c.IsNil)

	t.Assert(r.flynn("scale", "web=0"), Succeeds)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"github.com/jessevdk/go-flags"
	"github.com/takumakanari/cronv"
	"os"
)

const (
	VERSION = "0.2.1"
	NAME    = "Cronv"
)

func main() {
	opts := cronv.NewCronvCommand()

	parser := flags.NewParser(opts, flags.Default)
	parser.Name = fmt.Sprintf("%s v%s", NAME, VERSION)
	if _, err := parser.Parse(); err != nil {
		os.Exit(1)
	}

	ctx, err := cronv.NewCtx(opts)
	if err != nil {
		panic(err)
	}

	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		line := scanner.Text()
		if len(line) > 0 && string(line[0]) != "#" {
			if err := ctx.AppendNewLine(line); err != nil {
				panic(err)
			}
		}
	}
	if err := scanner.Err(); err != nil {
		panic(err)
	}

	path, err := ctx.Dump()
	if err != nil {
		panic(err)
	}

	fmt.Printf("%s: '%s' generated successfully.\n", opts.Title, path)
}
<commit_msg>dump version<commit_after>package main

import (
	"bufio"
	"fmt"
	"github.com/jessevdk/go-flags"
	"github.com/takumakanari/cronv"
	"os"
)

const (
	VERSION = "0.2.2"
	NAME    = "Cronv"
)

func main() {
	opts := cronv.NewCronvCommand()

	parser := flags.NewParser(opts, flags.Default)
	parser.Name = fmt.Sprintf("%s v%s", NAME, VERSION)
	if _, err := parser.Parse(); err != nil {
		os.Exit(1)
	}

	ctx, err := cronv.NewCtx(opts)
	if err != nil {
		panic(err)
	}

	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		line := scanner.Text()
		if len(line) > 0 && string(line[0]) != "#" {
			if err := ctx.AppendNewLine(line); err != nil {
				panic(err)
			}
		}
	}
	if err := scanner.Err(); err != nil {
		panic(err)
	}

	path, err := ctx.Dump()
	if err != nil {
		panic(err)
	}

	fmt.Printf("%s: '%s' generated successfully.\n", opts.Title, path)
}
<|endoftext|>