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

package oauth2

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

	"github.com/go-martini/martini"
	"github.com/martini-contrib/sessions"
)

func Test_LoginRedirect(t *testing.T) {
	recorder := httptest.NewRecorder()
	m := martini.New()
	m.Use(sessions.Sessions("my_session", sessions.NewCookieStore([]byte("secret123"))))
	m.Use(Google(&Options{
		ClientId:     "client_id",
		ClientSecret: "client_secret",
		RedirectURL:  "refresh_url",
		Scopes:       []string{"x", "y"},
	}))

	r, _ := http.NewRequest("GET", "/login", nil)
	m.ServeHTTP(recorder, r)

	location := recorder.HeaderMap["Location"][0]
	if recorder.Code != 302 {
		t.Errorf("Not being redirected to the auth page.")
	}
	if location != "https://accounts.google.com/o/oauth2/auth?access_type=&approval_prompt=&client_id=client_id&redirect_uri=refresh_url&response_type=code&scope=x+y&state=" {
		t.Errorf("Not being redirected to the right page, %v found", location)
	}
}

func Test_LoginRedirectAfterLoginRequired(t *testing.T) {
	recorder := httptest.NewRecorder()
	m := martini.Classic()
	m.Use(sessions.Sessions("my_session", sessions.NewCookieStore([]byte("secret123"))))
	m.Use(Google(&Options{
		ClientId:     "client_id",
		ClientSecret: "client_secret",
		RedirectURL:  "refresh_url",
		Scopes:       []string{"x", "y"},
	}))

	m.Get("/login-required", LoginRequired, func(tokens Tokens) (int, string) {
		return 200, tokens.Access()
	})

	r, _ := http.NewRequest("GET", "/login-required?key=value", nil)
	m.ServeHTTP(recorder, r)

	location := recorder.HeaderMap["Location"][0]
	if recorder.Code != 302 {
		t.Errorf("Not being redirected to the auth page.")
	}
	if location != "/login?next=%2Flogin-required%3Fkey%3Dvalue" {
		t.Errorf("Not being redirected to the right page, %v found", location)
	}
}

func Test_Logout(t *testing.T) {
	recorder := httptest.NewRecorder()
	s := sessions.NewCookieStore([]byte("secret123"))

	m := martini.Classic()
	m.Use(sessions.Sessions("my_session", s))
	m.Use(Google(&Options{
	// no need to configure
	}))

	m.Get("/", func(s sessions.Session) {
		s.Set(keyToken, "dummy token")
	})

	m.Get("/get", func(s sessions.Session) {
		if s.Get(keyToken) != nil {
			t.Errorf("User credentials are still kept in the session.")
		}
	})

	logout, _ := http.NewRequest("GET", "/logout", nil)
	index, _ := http.NewRequest("GET", "/", nil)

	m.ServeHTTP(httptest.NewRecorder(), index)
	m.ServeHTTP(recorder, logout)

	if recorder.Code != 302 {
		t.Errorf("Not being redirected to the next page.")
	}
}

func Test_LogoutOnAccessTokenExpiration(t *testing.T) {
	recorder := httptest.NewRecorder()
	s := sessions.NewCookieStore([]byte("secret123"))

	m := martini.Classic()
	m.Use(sessions.Sessions("my_session", s))
	m.Use(Google(&Options{
	// no need to configure
	}))

	m.Get("/addtoken", func(s sessions.Session) {
		s.Set(keyToken, "dummy token")
	})

	m.Get("/", func(s sessions.Session) {
		if s.Get(keyToken) != nil {
			t.Errorf("User not logged out although access token is expired.")
		}
	})

	addtoken, _ := http.NewRequest("GET", "/addtoken", nil)
	index, _ := http.NewRequest("GET", "/", nil)
	m.ServeHTTP(recorder, addtoken)
	m.ServeHTTP(recorder, index)
}

func Test_InjectedTokens(t *testing.T) {
	recorder := httptest.NewRecorder()
	m := martini.Classic()
	m.Use(sessions.Sessions("my_session", sessions.NewCookieStore([]byte("secret123"))))
	m.Use(Google(&Options{
	// no need to configure
	}))
	m.Get("/", func(tokens Tokens) string {
		return "Hello world!"
	})
	r, _ := http.NewRequest("GET", "/", nil)
	m.ServeHTTP(recorder, r)
}

func Test_LoginRequired(t *testing.T) {
	recorder := httptest.NewRecorder()
	m := martini.Classic()
	m.Use(sessions.Sessions("my_session", sessions.NewCookieStore([]byte("secret123"))))
	m.Use(Google(&Options{
	// no need to configure
	}))
	m.Get("/", LoginRequired, func(tokens Tokens) string {
		return "Hello world!"
	})
	r, _ := http.NewRequest("GET", "/", nil)
	m.ServeHTTP(recorder, r)
	if recorder.Code != 302 {
		t.Errorf("Not being redirected to the auth page although user is not logged in.")
	}
}
<commit_msg>Updated so test passes<commit_after>// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package oauth2

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

	"github.com/go-martini/martini"
	"github.com/martini-contrib/sessions"
)

func Test_LoginRedirect(t *testing.T) {
	recorder := httptest.NewRecorder()
	m := martini.New()
	m.Use(sessions.Sessions("my_session", sessions.NewCookieStore([]byte("secret123"))))
	m.Use(Google(&Options{
		ClientId:     "client_id",
		ClientSecret: "client_secret",
		RedirectURL:  "refresh_url",
		Scopes:       []string{"x", "y"},
	}))

	r, _ := http.NewRequest("GET", "/login", nil)
	m.ServeHTTP(recorder, r)

	location := recorder.HeaderMap["Location"][0]
	if recorder.Code != 302 {
		t.Errorf("Not being redirected to the auth page.")
	}
	if location != "https://accounts.google.com/o/oauth2/auth?access_type=&approval_prompt=&client_id=client_id&redirect_uri=refresh_url&response_type=code&scope=x+y&state=%2F" {
		t.Errorf("Not being redirected to the right page, %v found", location)
	}
}

func Test_LoginRedirectAfterLoginRequired(t *testing.T) {
	recorder := httptest.NewRecorder()
	m := martini.Classic()
	m.Use(sessions.Sessions("my_session", sessions.NewCookieStore([]byte("secret123"))))
	m.Use(Google(&Options{
		ClientId:     "client_id",
		ClientSecret: "client_secret",
		RedirectURL:  "refresh_url",
		Scopes:       []string{"x", "y"},
	}))

	m.Get("/login-required", LoginRequired, func(tokens Tokens) (int, string) {
		return 200, tokens.Access()
	})

	r, _ := http.NewRequest("GET", "/login-required?key=value", nil)
	m.ServeHTTP(recorder, r)

	location := recorder.HeaderMap["Location"][0]
	if recorder.Code != 302 {
		t.Errorf("Not being redirected to the auth page.")
	}
	if location != "/login?next=%2Flogin-required%3Fkey%3Dvalue" {
		t.Errorf("Not being redirected to the right page, %v found", location)
	}
}

func Test_Logout(t *testing.T) {
	recorder := httptest.NewRecorder()
	s := sessions.NewCookieStore([]byte("secret123"))

	m := martini.Classic()
	m.Use(sessions.Sessions("my_session", s))
	m.Use(Google(&Options{
	// no need to configure
	}))

	m.Get("/", func(s sessions.Session) {
		s.Set(keyToken, "dummy token")
	})

	m.Get("/get", func(s sessions.Session) {
		if s.Get(keyToken) != nil {
			t.Errorf("User credentials are still kept in the session.")
		}
	})

	logout, _ := http.NewRequest("GET", "/logout", nil)
	index, _ := http.NewRequest("GET", "/", nil)

	m.ServeHTTP(httptest.NewRecorder(), index)
	m.ServeHTTP(recorder, logout)

	if recorder.Code != 302 {
		t.Errorf("Not being redirected to the next page.")
	}
}

func Test_LogoutOnAccessTokenExpiration(t *testing.T) {
	recorder := httptest.NewRecorder()
	s := sessions.NewCookieStore([]byte("secret123"))

	m := martini.Classic()
	m.Use(sessions.Sessions("my_session", s))
	m.Use(Google(&Options{
	// no need to configure
	}))

	m.Get("/addtoken", func(s sessions.Session) {
		s.Set(keyToken, "dummy token")
	})

	m.Get("/", func(s sessions.Session) {
		if s.Get(keyToken) != nil {
			t.Errorf("User not logged out although access token is expired.")
		}
	})

	addtoken, _ := http.NewRequest("GET", "/addtoken", nil)
	index, _ := http.NewRequest("GET", "/", nil)
	m.ServeHTTP(recorder, addtoken)
	m.ServeHTTP(recorder, index)
}

func Test_InjectedTokens(t *testing.T) {
	recorder := httptest.NewRecorder()
	m := martini.Classic()
	m.Use(sessions.Sessions("my_session", sessions.NewCookieStore([]byte("secret123"))))
	m.Use(Google(&Options{
	// no need to configure
	}))
	m.Get("/", func(tokens Tokens) string {
		return "Hello world!"
	})
	r, _ := http.NewRequest("GET", "/", nil)
	m.ServeHTTP(recorder, r)
}

func Test_LoginRequired(t *testing.T) {
	recorder := httptest.NewRecorder()
	m := martini.Classic()
	m.Use(sessions.Sessions("my_session", sessions.NewCookieStore([]byte("secret123"))))
	m.Use(Google(&Options{
	// no need to configure
	}))
	m.Get("/", LoginRequired, func(tokens Tokens) string {
		return "Hello world!"
	})
	r, _ := http.NewRequest("GET", "/", nil)
	m.ServeHTTP(recorder, r)
	if recorder.Code != 302 {
		t.Errorf("Not being redirected to the auth page although user is not logged in.")
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.

package provider

import (
	"log"
)

const Version = "3.14.0"

func PrintVersion() {
	log.Printf("[INFO] terraform-provider-oci %s\n", Version)
}
<commit_msg>Finalize changelog and release version v3.14.1<commit_after>// Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.

package provider

import (
	"log"
)

const Version = "3.14.1"

func PrintVersion() {
	log.Printf("[INFO] terraform-provider-oci %s\n", Version)
}
<|endoftext|>


<commit_before>package of10

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"
)

var (
	errUnsupportedAction = errors.New("Unsupported action type")
)

type ActionType uint16

const actionHeaderLength = 4

type Action interface {
	GetType() ActionType
	FillBody(buf *bytes.Buffer) error
}

func readAction(buf *bytes.Reader) (Action, error) {
	// read action header
	var header ActionHeader
	if err := binary.Read(buf, binary.BigEndian, &header); err != nil {
		return nil, err
	}

	// make an empty action
	action := newAction(&header)
	if action == nil {
		return nil, errUnsupportedAction
	}

	// read remaining body
	body := make([]byte, header.Length-actionHeaderLength)
	if _, err := io.ReadFull(buf, body); err != nil {
		return nil, err
	}

	// parse action body
	bodyBuf := bytes.NewBuffer(body)
	if err := action.FillBody(bodyBuf); err != nil {
		return nil, err
	}
	return action, nil
}

func readActions(buf *bytes.Reader, length int) []Action {
	actions := make([]Action, 0, 8)
	end := buf.Len() - length
	for buf.Len() > end {
		action, err := readAction(buf)
		if err != nil {
			break
		}
		actions = append(actions, action)
	}
	return actions
}

func newAction(h *ActionHeader) Action {
	switch h.Type {
	case ActionTypes.Output:
		return &SendOutPort{ActionHeader: *h}
	case ActionTypes.SetVlanId:
		return &SetVlanVid{ActionHeader: *h}
	case ActionTypes.SetVlanPcp:
		return &SetVlanPcp{ActionHeader: *h}
	case ActionTypes.StripVlan:
		return &StripVlan{ActionHeader: *h}
	case ActionTypes.SetEtherSrc:
		return &SetEtherSrc{ActionHeader: *h}
	case ActionTypes.SetEtherDst:
		return &SetEtherDst{ActionHeader: *h}
	case ActionTypes.SetIpSrc:
		return &SetIpSrc{ActionHeader: *h}
	case ActionTypes.SetIpDst:
		return &SetIpDst{ActionHeader: *h}
	case ActionTypes.SetIpTos:
		return &SetIpTos{ActionHeader: *h}
	case ActionTypes.SetNetworkSrc:
		return &SetTransportSrc{ActionHeader: *h}
	case ActionTypes.SetNetworkDst:
		return &SetTransportDst{ActionHeader: *h}
	case ActionTypes.Enqueue:
		return &Enqueue{ActionHeader: *h}
	case ActionTypes.Vendor:
		return &VendorActionHeader{ActionHeader: *h}
	default:
		return nil
	}
}

type ActionHeader struct {
	Type   ActionType
	Length uint16
}

func (header *ActionHeader) GetType() ActionType {
	return header.Type
}

type SendOutPort struct {
	ActionHeader
	Port      PortNumber
	MaxLength uint16
}

func (a *SendOutPort) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Port); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.MaxLength); err != nil {
		return err
	}
	return nil
}

type Enqueue struct {
	ActionHeader
	Port    PortNumber
	pad     [6]uint8
	QueueId uint32
}

func (a *Enqueue) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Port); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.QueueId); err != nil {
		return err
	}
	return nil
}

type SetVlanVid struct {
	ActionHeader
	Id  VlanId
	pad [2]uint32
}

func (a *SetVlanVid) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Id); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	return nil
}

type SetVlanPcp struct {
	ActionHeader
	Priority VlanPriority
	pad      [3]uint8
}

func (a *SetVlanPcp) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Priority); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	return nil
}

type StripVlan struct {
	ActionHeader
}

func (a *StripVlan) FillBody(buf *bytes.Buffer) error {
	return nil
}

type SetEtherSrc struct {
	ActionHeader
	Address [EthernetAddressLength]uint8
	pad     [6]uint8
}

func (a *SetEtherSrc) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Address); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	return nil
}

type SetEtherDst struct {
	ActionHeader
	Address [EthernetAddressLength]uint8
	pad     [6]uint8
}

func (a *SetEtherDst) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Address); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	return nil
}

type SetIpSrc struct {
	ActionHeader
	Address [4]uint8
}

func (a *SetIpSrc) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Address); err != nil {
		return err
	}
	return nil
}

type SetIpDst struct {
	ActionHeader
	Address [4]uint8
}

func (a *SetIpDst) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Address); err != nil {
		return err
	}
	return nil
}

type SetIpTos struct {
	ActionHeader
	Tos Dscp
	pad [3]uint8
}

func (a *SetIpTos) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Tos); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	return nil
}

type SetTransportSrc struct {
	ActionHeader
	Port TransportPort
	pad  [2]uint8
}

func (a *SetTransportSrc) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Port); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	return nil
}

type SetTransportDst struct {
	ActionHeader
	Port TransportPort
	pad  [2]uint8
}

func (a *SetTransportDst) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Port); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	return nil
}

type VendorActionHeader struct {
	ActionHeader
	Vendor VendorId
}

func (a *VendorActionHeader) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Vendor); err != nil {
		return err
	}
	return nil
}

type VendorId uint32
<commit_msg>Implement new deserialization methods of actions<commit_after>package of10

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"
)

var (
	errUnsupportedAction = errors.New("Unsupported action type")
)

type ActionType uint16

const actionHeaderLength = 4

type Action interface {
	GetType() ActionType
	FillBody(buf *bytes.Buffer) error
}

func readAction(buf *bytes.Reader) (Action, error) {
	// read action header
	var header ActionHeader
	if err := binary.Read(buf, binary.BigEndian, &header); err != nil {
		return nil, err
	}

	// make an empty action
	action := newAction(&header)
	if action == nil {
		return nil, errUnsupportedAction
	}

	// read remaining body
	body := make([]byte, header.Length-actionHeaderLength)
	if _, err := io.ReadFull(buf, body); err != nil {
		return nil, err
	}

	// parse action body
	bodyBuf := bytes.NewBuffer(body)
	if err := action.FillBody(bodyBuf); err != nil {
		return nil, err
	}
	return action, nil
}

func readActions(buf *bytes.Reader, length int) []Action {
	actions := make([]Action, 0, 8)
	end := buf.Len() - length
	for buf.Len() > end {
		action, err := readAction(buf)
		if err != nil {
			break
		}
		actions = append(actions, action)
	}
	return actions
}

func newAction(h *ActionHeader) Action {
	switch h.Type {
	case ActionTypes.Output:
		return &SendOutPort{ActionHeader: *h}
	case ActionTypes.SetVlanId:
		return &SetVlanVid{ActionHeader: *h}
	case ActionTypes.SetVlanPcp:
		return &SetVlanPcp{ActionHeader: *h}
	case ActionTypes.StripVlan:
		return &StripVlan{ActionHeader: *h}
	case ActionTypes.SetEtherSrc:
		return &SetEtherSrc{ActionHeader: *h}
	case ActionTypes.SetEtherDst:
		return &SetEtherDst{ActionHeader: *h}
	case ActionTypes.SetIpSrc:
		return &SetIpSrc{ActionHeader: *h}
	case ActionTypes.SetIpDst:
		return &SetIpDst{ActionHeader: *h}
	case ActionTypes.SetIpTos:
		return &SetIpTos{ActionHeader: *h}
	case ActionTypes.SetNetworkSrc:
		return &SetTransportSrc{ActionHeader: *h}
	case ActionTypes.SetNetworkDst:
		return &SetTransportDst{ActionHeader: *h}
	case ActionTypes.Enqueue:
		return &Enqueue{ActionHeader: *h}
	case ActionTypes.Vendor:
		return &VendorActionHeader{ActionHeader: *h}
	default:
		return nil
	}
}

type ActionHeader struct {
	Type   ActionType
	Length uint16
}

func (header *ActionHeader) GetType() ActionType {
	return header.Type
}

type SendOutPort struct {
	ActionHeader
	Port      PortNumber
	MaxLength uint16
}

func (a *SendOutPort) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Port); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.MaxLength); err != nil {
		return err
	}
	return nil
}

type Enqueue struct {
	ActionHeader
	Port    PortNumber
	pad     [6]uint8
	QueueId uint32
}

func (a *Enqueue) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Port); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.QueueId); err != nil {
		return err
	}
	return nil
}

type SetVlanVid struct {
	ActionHeader
	Id  VlanId
	pad [2]uint32
}

func (a *SetVlanVid) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Id); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	return nil
}

type SetVlanPcp struct {
	ActionHeader
	Priority VlanPriority
	pad      [3]uint8
}

func (a *SetVlanPcp) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Priority); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	return nil
}

type StripVlan struct {
	ActionHeader
}

func (a *StripVlan) FillBody(buf *bytes.Buffer) error {
	return nil
}

type SetEtherSrc struct {
	ActionHeader
	Address [EthernetAddressLength]uint8
	pad     [6]uint8
}

func (a *SetEtherSrc) UnmarshalBinary(data []byte) error {
	return unmarshalFields(bytes.NewReader(data), a)
}

func (a *SetEtherSrc) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Address); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	return nil
}

type SetEtherDst struct {
	ActionHeader
	Address [EthernetAddressLength]uint8
	pad     [6]uint8
}

func (a *SetEtherDst) UnmarshalBinary(data []byte) error {
	return unmarshalFields(bytes.NewReader(data), a)
}

func (a *SetEtherDst) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Address); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	return nil
}

type SetIpSrc struct {
	ActionHeader
	Address [4]uint8
}

func (a *SetIpSrc) UnmarshalBinary(data []byte) error {
	return unmarshalFields(bytes.NewReader(data), a)
}

func (a *SetIpSrc) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Address); err != nil {
		return err
	}
	return nil
}

type SetIpDst struct {
	ActionHeader
	Address [4]uint8
}

func (a *SetIpDst) UnmarshalBinary(data []byte) error {
	return unmarshalFields(bytes.NewReader(data), a)
}

func (a *SetIpDst) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Address); err != nil {
		return err
	}
	return nil
}

type SetIpTos struct {
	ActionHeader
	Tos Dscp
	pad [3]uint8
}

func (a *SetIpTos) UnmarshalBinary(data []byte) error {
	return unmarshalFields(bytes.NewReader(data), a)
}

func (a *SetIpTos) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Tos); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	return nil
}

type SetTransportSrc struct {
	ActionHeader
	Port TransportPort
	pad  [2]uint8
}

func (a *SetTransportSrc) UnmarshalBinary(data []byte) error {
	return unmarshalFields(bytes.NewReader(data), a)
}

func (a *SetTransportSrc) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Port); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	return nil
}

type SetTransportDst struct {
	ActionHeader
	Port TransportPort
	pad  [2]uint8
}

func (a *SetTransportDst) UnmarshalBinary(data []byte) error {
	return unmarshalFields(bytes.NewReader(data), a)
}

func (a *SetTransportDst) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Port); err != nil {
		return err
	}
	if err := binary.Read(buf, binary.BigEndian, &a.pad); err != nil {
		return err
	}
	return nil
}

type VendorActionHeader struct {
	ActionHeader
	Vendor VendorId
}

func (a *VendorActionHeader) UnmarshalBinary(data []byte) error {
	return unmarshalFields(bytes.NewReader(data), a)
}

func (a *VendorActionHeader) FillBody(buf *bytes.Buffer) error {
	if err := binary.Read(buf, binary.BigEndian, &a.Vendor); err != nil {
		return err
	}
	return nil
}

type VendorId uint32
<|endoftext|>


<commit_before>/*
   Implements the Google omaha protocol.

   Omaha is a request/response protocol using XML. Requests are made by
   clients and responses are given by the Omaha server.
   http://code.google.com/p/omaha/wiki/ServerProtocol
*/
package omaha

import (
	"encoding/xml"
)

type Request struct {
	XMLName        xml.Name `xml:"request" datastore:"-"`
	Os             Os       `xml:"os"`
	Apps           []*App   `xml:"app"`
	Protocol       string   `xml:"protocol,attr"`
	Version        string   `xml:"version,attr,omitempty"`
	IsMachine      string   `xml:"ismachine,attr,omitempty"`
	SessionId      string   `xml:"sessionid,attr,omitempty"`
	UserId         string   `xml:"userid,attr,omitempty"`
	InstallSource  string   `xml:"installsource,attr,omitempty"`
	TestSource     string   `xml:"testsource,attr,omitempty"`
	RequestId      string   `xml:"requestid,attr,omitempty"`
	UpdaterVersion string   `xml:"updaterversion,attr,omitempty"`
}

func NewRequest(version string, platform string, sp string, arch string) *Request {
	r := new(Request)
	r.Protocol = "3.0"
	r.Os = Os{Version: version, Platform: platform, Sp: sp, Arch: arch}
	return r
}

func (r *Request) AddApp(id string, version string) *App {
	a := NewApp(id)
	a.Version = version
	r.Apps = append(r.Apps, a)
	return a
}

/* Response
 */
type Response struct {
	XMLName  xml.Name `xml:"response" datastore:"-" json:"-"`
	DayStart DayStart `xml:"daystart"`
	Apps     []*App   `xml:"app"`
	Protocol string   `xml:"protocol,attr"`
	Server   string   `xml:"server,attr"`
}

func NewResponse(server string) *Response {
	r := &Response{Server: server, Protocol: "3.0"}
	r.DayStart.ElapsedSeconds = "0"
	return r
}

type DayStart struct {
	ElapsedSeconds string `xml:"elapsed_seconds,attr"`
}

func (r *Response) AddApp(id string) *App {
	a := NewApp(id)
	r.Apps = append(r.Apps, a)
	return a
}

type App struct {
	XMLName     xml.Name     `xml:"app" datastore"-" json:"-"`
	Ping        *Ping        `xml:"ping"`
	UpdateCheck *UpdateCheck `xml:"updatecheck"`
	Events      []*Event     `xml:"event" json:",omitempty"`
	Id          string       `xml:"appid,attr,omitempty"`
	Version     string       `xml:"version,attr,omitempty"`
	NextVersion string       `xml:"nextversion,attr,omitempty"`
	Lang        string       `xml:"lang,attr,omitempty"`
	Client      string       `xml:"client,attr,omitempty"`
	InstallAge  string       `xml:"installage,attr,omitempty"`
	Status      string       `xml:"status,attr,omitempty"`

	// update engine extensions
	Track     string `xml:"track,attr,omitempty"`
	FromTrack string `xml:"from_track,attr,omitempty"`

	// coreos update engine extensions
	BootId    string `xml:"bootid,attr,omitempty"`
	MachineID string `xml:"machineid,attr,omitempty"`
	OEM       string `xml:"oem,attr,omitempty"`
}

func NewApp(id string) *App {
	a := &App{Id: id}
	return a
}

func (a *App) AddUpdateCheck() *UpdateCheck {
	a.UpdateCheck = new(UpdateCheck)
	return a.UpdateCheck
}

func (a *App) AddPing() *Ping {
	a.Ping = new(Ping)
	return a.Ping
}

func (a *App) AddEvent() *Event {
	event := new(Event)
	a.Events = append(a.Events, event)
	return event
}

type UpdateCheck struct {
	XMLName             xml.Name  `xml:"updatecheck" datastore:"-" json:"-"`
	Urls                *Urls     `xml:"urls"`
	Manifest            *Manifest `xml:"manifest"`
	TargetVersionPrefix string    `xml:"targetversionprefix,attr,omitempty"`
	Status              string    `xml:"status,attr,omitempty"`
}

func (u *UpdateCheck) AddUrl(codebase string) *Url {
	if u.Urls == nil {
		u.Urls = new(Urls)
	}
	url := new(Url)
	url.CodeBase = codebase
	u.Urls.Urls = append(u.Urls.Urls, *url)
	return url
}

func (u *UpdateCheck) AddManifest(version string) *Manifest {
	u.Manifest = &Manifest{Version: version}
	return u.Manifest
}

type Ping struct {
	XMLName        xml.Name `xml:"ping" datastore:"-" json:"-"`
	LastReportDays string   `xml:"r,attr,omitempty"`
	Status         string   `xml:"status,attr,omitempty"`
}

type Os struct {
	XMLName  xml.Name `xml:"os" datastore:"-" json:"-"`
	Platform string   `xml:"platform,attr,omitempty"`
	Version  string   `xml:"version,attr,omitempty"`
	Sp       string   `xml:"sp,attr,omitempty"`
	Arch     string   `xml:"arch,attr,omitempty"`
}

func NewOs(platform string, version string, sp string, arch string) *Os {
	o := &Os{Version: version, Platform: platform, Sp: sp, Arch: arch}
	return o
}

type Event struct {
	XMLName         xml.Name `xml:"event" datastore:"-" json:"-"`
	Type            string   `xml:"eventtype,attr,omitempty"`
	Result          string   `xml:"eventresult,attr,omitempty"`
	PreviousVersion string   `xml:"previousversion,attr,omitempty"`
	ErrorCode       string   `xml:"errorcode,attr,omitempty"`
}

type Urls struct {
	XMLName xml.Name `xml:"urls" datastore:"-" json:"-"`
	Urls    []Url    `xml:"url" json:",omitempty"`
}

type Url struct {
	XMLName  xml.Name `xml:"url" datastore:"-" json:"-"`
	CodeBase string   `xml:"codebase,attr"`
}

type Manifest struct {
	XMLName  xml.Name `xml:"manifest" datastore:"-" json:"-"`
	Packages Packages `xml:"packages"`
	Actions  Actions  `xml:"actions"`
	Version  string   `xml:"version,attr"`
}

type Packages struct {
	XMLName  xml.Name  `xml:"packages" datastore:"-" json:"-"`
	Packages []Package `xml:"package" json:",omitempty"`
}

type Package struct {
	XMLName  xml.Name `xml:"package" datastore:"-" json:"-"`
	Hash     string   `xml:"hash,attr"`
	Name     string   `xml:"name,attr"`
	Size     string   `xml:"size,attr"`
	Required bool     `xml:"required,attr"`
}

func (m *Manifest) AddPackage(hash string, name string, size string, required bool) *Package {
	p := &Package{Hash: hash, Name: name, Size: size, Required: required}
	m.Packages.Packages = append(m.Packages.Packages, *p)
	return p
}

type Actions struct {
	XMLName xml.Name  `xml:"actions" datastore:"-" json:"-"`
	Actions []*Action `xml:"action" json:",omitempty"`
}

type Action struct {
	XMLName xml.Name `xml:"action" datastore:"-" json:"-"`
	Event   string   `xml:"event,attr"`

	// Extensions added by update_engine
	ChromeOSVersion       string `xml:"ChromeOSVersion,attr"`
	Sha256                string `xml:"sha256,attr"`
	NeedsAdmin            bool   `xml:"needsadmin,attr"`
	IsDelta               bool   `xml:"IsDelta,attr"`
	DisablePayloadBackoff bool   `xml:"DisablePayloadBackoff,attr,omitempty"`
	MetadataSignatureRsa  string `xml:"MetadataSignatureRsa,attr,omitempty"`
	MetadataSize          string `xml:"MetadataSize,attr,omitempty"`
	Deadline              string `xml:"deadline,attr,omitempty"`
}

func (m *Manifest) AddAction(event string) *Action {
	a := &Action{Event: event}
	m.Actions.Actions = append(m.Actions.Actions, a)
	return a
}

var EventTypes = map[int]string{
	0:   "unknown",
	1:   "download complete",
	2:   "install complete",
	3:   "update complete",
	4:   "uninstall",
	5:   "download started",
	6:   "install started",
	9:   "new application install started",
	10:  "setup started",
	11:  "setup finished",
	12:  "update application started",
	13:  "update download started",
	14:  "update download finished",
	15:  "update installer started",
	16:  "setup update begin",
	17:  "setup update complete",
	20:  "register product complete",
	30:  "OEM install first check",
	40:  "app-specific command started",
	41:  "app-specific command ended",
	100: "setup failure",
	102: "COM server failure",
	103: "setup update failure",
	800: "ping",
}

var EventResults = map[int]string{
	0:  "error",
	1:  "success",
	2:  "success reboot",
	3:  "success restart browser",
	4:  "cancelled",
	5:  "error installer MSI",
	6:  "error installer other",
	7:  "noupdate",
	8:  "error installer system",
	9:  "update deferred",
	10: "handoff error",
}
<commit_msg>Added Status to Event type to response in Event response<commit_after>/*
   Implements the Google omaha protocol.

   Omaha is a request/response protocol using XML. Requests are made by
   clients and responses are given by the Omaha server.
   http://code.google.com/p/omaha/wiki/ServerProtocol
*/
package omaha

import (
	"encoding/xml"
)

type Request struct {
	XMLName        xml.Name `xml:"request" datastore:"-"`
	Os             Os       `xml:"os"`
	Apps           []*App   `xml:"app"`
	Protocol       string   `xml:"protocol,attr"`
	Version        string   `xml:"version,attr,omitempty"`
	IsMachine      string   `xml:"ismachine,attr,omitempty"`
	SessionId      string   `xml:"sessionid,attr,omitempty"`
	UserId         string   `xml:"userid,attr,omitempty"`
	InstallSource  string   `xml:"installsource,attr,omitempty"`
	TestSource     string   `xml:"testsource,attr,omitempty"`
	RequestId      string   `xml:"requestid,attr,omitempty"`
	UpdaterVersion string   `xml:"updaterversion,attr,omitempty"`
}

func NewRequest(version string, platform string, sp string, arch string) *Request {
	r := new(Request)
	r.Protocol = "3.0"
	r.Os = Os{Version: version, Platform: platform, Sp: sp, Arch: arch}
	return r
}

func (r *Request) AddApp(id string, version string) *App {
	a := NewApp(id)
	a.Version = version
	r.Apps = append(r.Apps, a)
	return a
}

/* Response
 */
type Response struct {
	XMLName  xml.Name `xml:"response" datastore:"-" json:"-"`
	DayStart DayStart `xml:"daystart"`
	Apps     []*App   `xml:"app"`
	Protocol string   `xml:"protocol,attr"`
	Server   string   `xml:"server,attr"`
}

func NewResponse(server string) *Response {
	r := &Response{Server: server, Protocol: "3.0"}
	r.DayStart.ElapsedSeconds = "0"
	return r
}

type DayStart struct {
	ElapsedSeconds string `xml:"elapsed_seconds,attr"`
}

func (r *Response) AddApp(id string) *App {
	a := NewApp(id)
	r.Apps = append(r.Apps, a)
	return a
}

type App struct {
	XMLName     xml.Name     `xml:"app" datastore"-" json:"-"`
	Ping        *Ping        `xml:"ping"`
	UpdateCheck *UpdateCheck `xml:"updatecheck"`
	Events      []*Event     `xml:"event" json:",omitempty"`
	Id          string       `xml:"appid,attr,omitempty"`
	Version     string       `xml:"version,attr,omitempty"`
	NextVersion string       `xml:"nextversion,attr,omitempty"`
	Lang        string       `xml:"lang,attr,omitempty"`
	Client      string       `xml:"client,attr,omitempty"`
	InstallAge  string       `xml:"installage,attr,omitempty"`
	Status      string       `xml:"status,attr,omitempty"`

	// update engine extensions
	Track     string `xml:"track,attr,omitempty"`
	FromTrack string `xml:"from_track,attr,omitempty"`

	// coreos update engine extensions
	BootId    string `xml:"bootid,attr,omitempty"`
	MachineID string `xml:"machineid,attr,omitempty"`
	OEM       string `xml:"oem,attr,omitempty"`
}

func NewApp(id string) *App {
	a := &App{Id: id}
	return a
}

func (a *App) AddUpdateCheck() *UpdateCheck {
	a.UpdateCheck = new(UpdateCheck)
	return a.UpdateCheck
}

func (a *App) AddPing() *Ping {
	a.Ping = new(Ping)
	return a.Ping
}

func (a *App) AddEvent() *Event {
	event := new(Event)
	a.Events = append(a.Events, event)
	return event
}

type UpdateCheck struct {
	XMLName             xml.Name  `xml:"updatecheck" datastore:"-" json:"-"`
	Urls                *Urls     `xml:"urls"`
	Manifest            *Manifest `xml:"manifest"`
	TargetVersionPrefix string    `xml:"targetversionprefix,attr,omitempty"`
	Status              string    `xml:"status,attr,omitempty"`
}

func (u *UpdateCheck) AddUrl(codebase string) *Url {
	if u.Urls == nil {
		u.Urls = new(Urls)
	}
	url := new(Url)
	url.CodeBase = codebase
	u.Urls.Urls = append(u.Urls.Urls, *url)
	return url
}

func (u *UpdateCheck) AddManifest(version string) *Manifest {
	u.Manifest = &Manifest{Version: version}
	return u.Manifest
}

type Ping struct {
	XMLName        xml.Name `xml:"ping" datastore:"-" json:"-"`
	LastReportDays string   `xml:"r,attr,omitempty"`
	Status         string   `xml:"status,attr,omitempty"`
}

type Os struct {
	XMLName  xml.Name `xml:"os" datastore:"-" json:"-"`
	Platform string   `xml:"platform,attr,omitempty"`
	Version  string   `xml:"version,attr,omitempty"`
	Sp       string   `xml:"sp,attr,omitempty"`
	Arch     string   `xml:"arch,attr,omitempty"`
}

func NewOs(platform string, version string, sp string, arch string) *Os {
	o := &Os{Version: version, Platform: platform, Sp: sp, Arch: arch}
	return o
}

type Event struct {
	XMLName         xml.Name `xml:"event" datastore:"-" json:"-"`
	Type            string   `xml:"eventtype,attr,omitempty"`
	Result          string   `xml:"eventresult,attr,omitempty"`
	PreviousVersion string   `xml:"previousversion,attr,omitempty"`
	ErrorCode       string   `xml:"errorcode,attr,omitempty"`
	Status          string   `xml:"status,attr,omitempty"`
}

type Urls struct {
	XMLName xml.Name `xml:"urls" datastore:"-" json:"-"`
	Urls    []Url    `xml:"url" json:",omitempty"`
}

type Url struct {
	XMLName  xml.Name `xml:"url" datastore:"-" json:"-"`
	CodeBase string   `xml:"codebase,attr"`
}

type Manifest struct {
	XMLName  xml.Name `xml:"manifest" datastore:"-" json:"-"`
	Packages Packages `xml:"packages"`
	Actions  Actions  `xml:"actions"`
	Version  string   `xml:"version,attr"`
}

type Packages struct {
	XMLName  xml.Name  `xml:"packages" datastore:"-" json:"-"`
	Packages []Package `xml:"package" json:",omitempty"`
}

type Package struct {
	XMLName  xml.Name `xml:"package" datastore:"-" json:"-"`
	Hash     string   `xml:"hash,attr"`
	Name     string   `xml:"name,attr"`
	Size     string   `xml:"size,attr"`
	Required bool     `xml:"required,attr"`
}

func (m *Manifest) AddPackage(hash string, name string, size string, required bool) *Package {
	p := &Package{Hash: hash, Name: name, Size: size, Required: required}
	m.Packages.Packages = append(m.Packages.Packages, *p)
	return p
}

type Actions struct {
	XMLName xml.Name  `xml:"actions" datastore:"-" json:"-"`
	Actions []*Action `xml:"action" json:",omitempty"`
}

type Action struct {
	XMLName xml.Name `xml:"action" datastore:"-" json:"-"`
	Event   string   `xml:"event,attr"`

	// Extensions added by update_engine
	ChromeOSVersion       string `xml:"ChromeOSVersion,attr"`
	Sha256                string `xml:"sha256,attr"`
	NeedsAdmin            bool   `xml:"needsadmin,attr"`
	IsDelta               bool   `xml:"IsDelta,attr"`
	DisablePayloadBackoff bool   `xml:"DisablePayloadBackoff,attr,omitempty"`
	MetadataSignatureRsa  string `xml:"MetadataSignatureRsa,attr,omitempty"`
	MetadataSize          string `xml:"MetadataSize,attr,omitempty"`
	Deadline              string `xml:"deadline,attr,omitempty"`
}

func (m *Manifest) AddAction(event string) *Action {
	a := &Action{Event: event}
	m.Actions.Actions = append(m.Actions.Actions, a)
	return a
}

var EventTypes = map[int]string{
	0:   "unknown",
	1:   "download complete",
	2:   "install complete",
	3:   "update complete",
	4:   "uninstall",
	5:   "download started",
	6:   "install started",
	9:   "new application install started",
	10:  "setup started",
	11:  "setup finished",
	12:  "update application started",
	13:  "update download started",
	14:  "update download finished",
	15:  "update installer started",
	16:  "setup update begin",
	17:  "setup update complete",
	20:  "register product complete",
	30:  "OEM install first check",
	40:  "app-specific command started",
	41:  "app-specific command ended",
	100: "setup failure",
	102: "COM server failure",
	103: "setup update failure",
	800: "ping",
}

var EventResults = map[int]string{
	0:  "error",
	1:  "success",
	2:  "success reboot",
	3:  "success restart browser",
	4:  "cancelled",
	5:  "error installer MSI",
	6:  "error installer other",
	7:  "noupdate",
	8:  "error installer system",
	9:  "update deferred",
	10: "handoff error",
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"syscall"

	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/daemon/graphdriver/devmapper"
	"github.com/docker/docker/pkg/archive"
	"github.com/docker/docker/pkg/ioutils"
)

type devicemapper struct {
	root    string
	devices *devmapper.DeviceSet
}

func NewDevicemapperChecksums(root string) Mounter {
	devices, err := devmapper.NewDeviceSet(root, false, nil, nil, nil)
	if err != nil {
		logrus.Errorf("Can't initialize device mapper: %q", err)
		os.Exit(1)
	}

	return &devicemapper{root, devices}
}

func (c *devicemapper) Mount(id string) (string, func(), error) {
	tmpdir, err := ioutil.TempDir("", "migrate-devicemapper")
	if err != nil {
		return "", nil, err
	}

	err = c.devices.MountDevice(id, tmpdir, "")
	if err != nil {
		fmt.Println("Can't create snap device: ", err)
		os.Exit(1)
	}
	return filepath.Join(tmpdir, "rootfs"), func() {
		syscall.Unmount(tmpdir, 0)
		os.RemoveAll(tmpdir)
	}, nil
}

func (c *devicemapper) TarStream(id, parent string) (io.ReadCloser, error) {
	mainPath, releaseMain, err := c.Mount(id)
	if err != nil {
		return nil, err
	}

	if parent == "" {
		tar, err := archive.Tar(mainPath, archive.Uncompressed)
		if err != nil {
			return nil, err
		}
		return ioutils.NewReadCloserWrapper(tar, func() error {
			releaseMain()
			return tar.Close()
		}), nil
	}

	parentPath, releaseParent, err := c.Mount(parent)
	if err != nil {
		releaseMain()
		return nil, err
	}
	tar, err := Diff(mainPath, parentPath)
	if err != nil {
		releaseParent()
		releaseMain()
		return nil, err
	}
	return ioutils.NewReadCloserWrapper(tar, func() error {
		releaseParent()
		releaseMain()
		return tar.Close()
	}), nil
}
<commit_msg>Allow multiple mounts for device mapper<commit_after>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"

	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/daemon/graphdriver/devmapper"
	"github.com/docker/docker/pkg/archive"
	"github.com/docker/docker/pkg/ioutils"
)

type mount struct {
	activity int
	path     string
}

type devicemapper struct {
	sync.Mutex
	mounts  map[string]*mount
	root    string
	devices *devmapper.DeviceSet
}

func NewDevicemapperChecksums(root string) Mounter {
	devices, err := devmapper.NewDeviceSet(root, false, nil, nil, nil)
	if err != nil {
		logrus.Errorf("Can't initialize device mapper: %q", err)
		os.Exit(1)
	}

	return &devicemapper{root: root, devices: devices, mounts: make(map[string]*mount)}
}

func (c *devicemapper) Mount(id string) (string, func(), error) {
	c.Lock()
	defer c.Unlock()

	mounts, ok := c.mounts[id]
	if !ok {
		tmpdir, err := ioutil.TempDir("", "migrate-devicemapper")
		if err != nil {
			return "", nil, err
		}
		mounts = &mount{0, tmpdir}
		c.mounts[id] = mounts
	}

	if mounts.activity == 0 {
		err := c.devices.MountDevice(id, mounts.path, "")
		if err != nil {
			return "", nil, fmt.Errorf("Can't create snap device: %v", err)
		}
	}
	mounts.activity++

	path := filepath.Join(mounts.path, "rootfs")
	// sometimes rootfs does not exist. return empty dir then
	if _, err := os.Lstat(path); err != nil {
		tmpdir, err := ioutil.TempDir("", "migrate-devicemapper")
		if err != nil {
			return "", nil, err
		}
		path = tmpdir
	}

	return path, func() {
		c.umount(id)
	}, nil
}

func (c *devicemapper) umount(id string) {
	c.Lock()
	defer c.Unlock()
	c.mounts[id].activity--
	if c.mounts[id].activity == 0 {
		err := c.devices.UnmountDevice(id)
		if err != nil {
			logrus.Errorf("Can't umount %s: %v", id, err)
		}
		os.RemoveAll(c.mounts[id].path)
		delete(c.mounts, id)
	}
}

func (c *devicemapper) TarStream(id, parent string) (io.ReadCloser, error) {
	mainPath, releaseMain, err := c.Mount(id)
	if err != nil {
		return nil, err
	}

	if parent == "" {
		tar, err := archive.Tar(mainPath, archive.Uncompressed)
		if err != nil {
			return nil, err
		}
		return ioutils.NewReadCloserWrapper(tar, func() error {
			releaseMain()
			return tar.Close()
		}), nil
	}

	parentPath, releaseParent, err := c.Mount(parent)
	if err != nil {
		releaseMain()
		return nil, err
	}
	tar, err := Diff(mainPath, parentPath)
	if err != nil {
		releaseParent()
		releaseMain()
		return nil, err
	}
	return ioutils.NewReadCloserWrapper(tar, func() error {
		releaseParent()
		releaseMain()
		return tar.Close()
	}), nil
}
<|endoftext|>


<commit_before>package mantle

import (
	"github.com/garyburd/redigo/redis"
	"github.com/vireshas/minimal_vitess_pool/pools"
	"strconv"
	"strings"
	"time"
)

//cant make these guys const as []string is not allowed in consts

//default pool size
var RedisPoolSize = 10

//default host:port to connect
var DefaultRedisConfig = []string{"localhost:6379"}

/*
 * This method creates a redis connection
   Connect is passed as a callback to pools
   Params:
     Instance: This is a reference to a struct redis instance
               Connect needs some params like db, hostAndPorts
               These params are read from this instance rederence
*/
func Connect(Instance interface{}) (pools.Resource, error) {
	//converting interface Redis struct type
	redisInstance := Instance.(*Redis)
	//this is a string of type "localhost:6379"
	hostNPorts := redisInstance.Settings.HostAndPorts
	//select db after dialing
	db := redisInstance.db

	//panic is more than 1 ip is given
	if len(hostNPorts) > 1 {
		panic("we can only connect to 1 server at the moment")
	}

	hostNPort := strings.Split(hostNPorts[0], ":")
	//dial host and port
	cli, err := redis.Dial("tcp", hostNPort[0]+":"+hostNPort[1])
	if err != nil {
		panic(err)
	}

	//select a redis db
	_, err = cli.Do("SELECT", db)
	if err != nil {
		panic(err)
	}

	//typecast to RedisConn
	return &RedisConn{cli}, nil
}

/*
 * Wrapping redigo redis connection
   Pool expects a Object which defines
   Close() and doesn't return anything, but
   redigo.Redis#Close() returns error, hence this wrapper
   around redis.Conn
*/
type RedisConn struct {
	redis.Conn
}

//Close a redis connection
func (r *RedisConn) Close() {
	_ = r.Conn.Close()
}

//Gets a connection from pool and converts to RedisConn type
//If all the connections are in use, timeout the present request after a minute
func (r *Redis) GetClient() (*RedisConn, error) {
	connection, err := r.pool.GetConn(r.Settings.Timeout)
	if err != nil {
		return nil, err
	}
	return connection.(*RedisConn), nil
}

//Puts a connection back to pool
func (r *Redis) PutClient(c *RedisConn) {
	r.pool.PutConn(c)
}

type Redis struct {
	Settings PoolSettings
	pool     *ResourcePool
	db       int
}

//Add default settings if they are missing
func (r *Redis) SetDefaults() {
	if len(r.Settings.HostAndPorts) == 0 {
		r.Settings.HostAndPorts = DefaultRedisConfig
	}
	//this is poolsize
	if r.Settings.Capacity == 0 {
		r.Settings.Capacity = RedisPoolSize
	}
	//maxcapacity of the pool
	if r.Settings.MaxCapacity == 0 {
		r.Settings.MaxCapacity = RedisPoolSize
	}
	//pool timeout
	r.Settings.Timeout = time.Minute

	//select a particular db in redis
	db, ok := r.Settings.Options["db"]
	if !ok {
		db = "0"
	}
	select_db, err := strconv.Atoi(db)
	if err != nil {
		panic("From Redis: select db is not a valid string")
	}
	r.db = select_db

	//create a pool finally
	r.pool = NewPool(Connect, r, r.Settings)
}

func (r *Redis) Configure(settings PoolSettings) {
	r.Settings = settings
	r.SetDefaults()
}

//Generic method to execute any redis call
//Gets a client from pool, executes a cmd, puts conn back in pool
func (r *Redis) Execute(cmd string, args ...interface{}) (interface{}, error) {
	client, err := r.GetClient()
	if err != nil {
		return nil, err
	}
	defer r.PutClient(client)
	return client.Do(cmd, args...)
}

func (r *Redis) Delete(keys ...interface{}) int {
	value, err := redis.Int(r.Execute("DEL", keys...))
	if err != nil {
		return -1
	}
	return value
}

func (r *Redis) Get(key string) string {
	value, err := redis.String(r.Execute("GET", key))
	if err != nil {
		return ""
	}
	return value
}

func (r *Redis) Set(key string, value interface{}) bool {
	_, err := r.Execute("SET", key, value)
	if err != nil {
		return false
	}
	return true
}

func (r *Redis) MGet(keys ...interface{}) []string {
	values, err := redis.Strings(r.Execute("MGET", keys...))
	if err != nil {
		return []string{}
	}
	return values
}

func (r *Redis) MSet(mapOfKeyVal map[string]interface{}) bool {
	_, err := r.Execute("MSET", redis.Args{}.AddFlat(mapOfKeyVal)...)
	if err != nil {
		return false
	}
	return true
}

func (r *Redis) Expire(key string, duration int) bool {
	_, err := r.Execute("EXPIRE", key, duration)
	if err != nil {
		return false
	}
	return true
}

func (r *Redis) Setex(key string, duration int, val interface{}) bool {
	_, err := r.Execute("SETEX", key, duration, val)
	if err != nil {
		return false
	}
	return true
}
<commit_msg>Connect collides with other backend<commit_after>package mantle

import (
	"github.com/garyburd/redigo/redis"
	"github.com/vireshas/minimal_vitess_pool/pools"
	"strconv"
	"strings"
	"time"
)

//cant make these guys const as []string is not allowed in consts

//default pool size
var RedisPoolSize = 10

//default host:port to connect
var DefaultRedisConfig = []string{"localhost:6379"}

/*
 * This method creates a redis connection
   Connect is passed as a callback to pools
   Params:
     Instance: This is a reference to a struct redis instance
               Connect needs some params like db, hostAndPorts
               These params are read from this instance rederence
*/
func CreateRedisConnection(Instance interface{}) (pools.Resource, error) {
	//converting interface Redis struct type
	redisInstance := Instance.(*Redis)
	//this is a string of type "localhost:6379"
	hostNPorts := redisInstance.Settings.HostAndPorts
	//select db after dialing
	db := redisInstance.db

	//panic is more than 1 ip is given
	if len(hostNPorts) > 1 {
		panic("we can only connect to 1 server at the moment")
	}

	hostNPort := strings.Split(hostNPorts[0], ":")
	//dial host and port
	cli, err := redis.Dial("tcp", hostNPort[0]+":"+hostNPort[1])
	if err != nil {
		panic(err)
	}

	//select a redis db
	_, err = cli.Do("SELECT", db)
	if err != nil {
		panic(err)
	}

	//typecast to RedisConn
	return &RedisConn{cli}, nil
}

/*
 * Wrapping redigo redis connection
   Pool expects a Object which defines
   Close() and doesn't return anything, but
   redigo.Redis#Close() returns error, hence this wrapper
   around redis.Conn
*/
type RedisConn struct {
	redis.Conn
}

//Close a redis connection
func (r *RedisConn) Close() {
	_ = r.Conn.Close()
}

//Gets a connection from pool and converts to RedisConn type
//If all the connections are in use, timeout the present request after a minute
func (r *Redis) GetClient() (*RedisConn, error) {
	connection, err := r.pool.GetConn(r.Settings.Timeout)
	if err != nil {
		return nil, err
	}
	return connection.(*RedisConn), nil
}

//Puts a connection back to pool
func (r *Redis) PutClient(c *RedisConn) {
	r.pool.PutConn(c)
}

type Redis struct {
	Settings PoolSettings
	pool     *ResourcePool
	db       int
}

//Add default settings if they are missing
func (r *Redis) SetDefaults() {
	if len(r.Settings.HostAndPorts) == 0 {
		r.Settings.HostAndPorts = DefaultRedisConfig
	}
	//this is poolsize
	if r.Settings.Capacity == 0 {
		r.Settings.Capacity = RedisPoolSize
	}
	//maxcapacity of the pool
	if r.Settings.MaxCapacity == 0 {
		r.Settings.MaxCapacity = RedisPoolSize
	}
	//pool timeout
	r.Settings.Timeout = time.Minute

	//select a particular db in redis
	db, ok := r.Settings.Options["db"]
	if !ok {
		db = "0"
	}
	select_db, err := strconv.Atoi(db)
	if err != nil {
		panic("From Redis: select db is not a valid string")
	}
	r.db = select_db

	//create a pool finally
	r.pool = NewPool(CreateRedisConnection, r, r.Settings)
}

func (r *Redis) Configure(settings PoolSettings) {
	r.Settings = settings
	r.SetDefaults()
}

//Generic method to execute any redis call
//Gets a client from pool, executes a cmd, puts conn back in pool
func (r *Redis) Execute(cmd string, args ...interface{}) (interface{}, error) {
	client, err := r.GetClient()
	if err != nil {
		return nil, err
	}
	defer r.PutClient(client)
	return client.Do(cmd, args...)
}

func (r *Redis) Delete(keys ...interface{}) int {
	value, err := redis.Int(r.Execute("DEL", keys...))
	if err != nil {
		return -1
	}
	return value
}

func (r *Redis) Get(key string) string {
	value, err := redis.String(r.Execute("GET", key))
	if err != nil {
		return ""
	}
	return value
}

func (r *Redis) Set(key string, value interface{}) bool {
	_, err := r.Execute("SET", key, value)
	if err != nil {
		return false
	}
	return true
}

func (r *Redis) MGet(keys ...interface{}) []string {
	values, err := redis.Strings(r.Execute("MGET", keys...))
	if err != nil {
		return []string{}
	}
	return values
}

func (r *Redis) MSet(mapOfKeyVal map[string]interface{}) bool {
	_, err := r.Execute("MSET", redis.Args{}.AddFlat(mapOfKeyVal)...)
	if err != nil {
		return false
	}
	return true
}

func (r *Redis) Expire(key string, duration int) bool {
	_, err := r.Execute("EXPIRE", key, duration)
	if err != nil {
		return false
	}
	return true
}

func (r *Redis) Setex(key string, duration int, val interface{}) bool {
	_, err := r.Execute("SETEX", key, duration, val)
	if err != nil {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>package banner

import (
	"log"
	"io"
	"net"
	"time"
	"strings"
	"strconv"
	"../zcrypto/ztls"
)

type Result struct {
	Addr string
	FirstData []byte
	Err error
	TlsHandshakeLog TlsLog
	Data []byte
}

type GrabConfig struct {
	Udp, Tls, SendMessage, StartTls, ReadFirst, Heartbleed bool
	Port uint16
	Timeout int
	Message string
	ErrorLog *log.Logger
	LocalAddr net.Addr
}

func makeDialer(config *GrabConfig) ( func(rhost string) (net.Conn, []byte, TlsLog, error) ) {
	var network string
	if config.Udp {
		network = "udp"
	} else {
		network = "tcp"
	}

	timeout := time.Duration(config.Timeout) * time.Second

	b := make([]byte, 65536)
	if config.Tls {
		tlsConfig := new(ztls.Config)
		tlsConfig.InsecureSkipVerify = true
		tlsConfig.MinVersion = ztls.VersionSSL30
		return func(rhost string) (net.Conn, []byte, TlsLog, error) {
			now := time.Now()
			deadline := now.Add(timeout)
			dialer := net.Dialer{Timeout:timeout, Deadline:deadline, LocalAddr:config.LocalAddr, DualStack:false}
			var conn *ztls.Conn
			firstRead := []byte{}
			if nconn, err := dialer.Dial(network, rhost); err != nil {
				return nconn, firstRead, nil, err
			} else {
				nconn.SetDeadline(deadline)
				if config.ReadFirst {
					res := make([]byte, 1024)
					// TODO add logging
					if firstReadBytes, err := nconn.Read(res); err != nil {
						log.Print("failed first read")
						return nconn, firstRead, nil, err
					} else {
						firstRead = make([]byte, firstReadBytes)
						copy(firstRead, res)
					}
				}
				if config.StartTls {
					res := make([]byte, 1024)
					if _, err := nconn.Write([]byte("EHLO eecs.umich.edu\r\n")); err != nil {
						log.Print("failed EHLO")
						return nconn, firstRead, nil, err
					}
					if _, err := nconn.Read(res); err != nil {
						// TODO Validate server likes it
						log.Print("failed EHLO read")
					}
					if _, err := nconn.Write([]byte("STARTTLS\r\n")); err != nil {
						log.Print("failed starttls");
					}
					if _, err := nconn.Read(res); err != nil {
						log.Print("failed starttls read")
					}
				}
				conn = ztls.Client(nconn, tlsConfig)
				conn.SetDeadline(deadline)
				err = conn.Handshake()
				if err == nil && config.Heartbleed {
					conn.CheckHeartbleed(b)
				}
				return conn, firstRead, conn.ConnectionLog(), err
			}
		}
	} else {
		return func(rhost string) (net.Conn, []byte, TlsLog, error) {
			now := time.Now()
			deadline := now.Add(timeout)
			dialer := net.Dialer{Timeout:timeout, Deadline:deadline, LocalAddr:config.LocalAddr}
			conn, err := dialer.Dial(network, rhost);
			if err == nil {
				conn.SetDeadline(deadline)
			}
			return conn, []byte{}, nil, err
		}
	}
}

func GrabBanner(addrChan chan net.IP, resultChan chan Result, doneChan chan int, config *GrabConfig) {
	dial := makeDialer(config)
	port := strconv.FormatUint(uint64(config.Port), 10)
	for ip := range addrChan {
		addr := ip.String()
		rhost := net.JoinHostPort(addr, port)
		conn, firstData, tlsLog, err := dial(rhost)
		if err != nil {
			config.ErrorLog.Print("Could not connect to host ", addr, " - ", err)
			resultChan <- Result{addr, firstData, err, tlsLog, nil}
			continue
		}
		if config.SendMessage {
			s := strings.Replace(config.Message, "%s", addr, -1)
			if _, err := conn.Write([]byte(s)); err != nil {
				conn.Close()
				config.ErrorLog.Print("Could not write message to host ", addr, " - ", err)
				resultChan <- Result{addr, firstData, err, tlsLog, nil}
				continue
			}
		}
		var buf [1024]byte
		n, err := conn.Read(buf[:])
		conn.Close()
		if err != nil && (err != io.EOF || n == 0) {
			config.ErrorLog.Print("Could not read from host ", addr, " - ", err)
			res := Result{addr, firstData, err, tlsLog, nil}
			resultChan <- res
			continue
		}
		res := Result{addr, firstData, nil, tlsLog, buf[0:n]}
		resultChan <- res
	}
	doneChan <- 1
}
<commit_msg>Respect error log with STARTTLS and --read-first<commit_after>package banner

import (
	"log"
	"io"
	"net"
	"time"
	"strings"
	"strconv"
	"../zcrypto/ztls"
)

type Result struct {
	Addr string
	FirstData []byte
	Err error
	TlsHandshakeLog TlsLog
	Data []byte
}

type GrabConfig struct {
	Udp, Tls, SendMessage, StartTls, ReadFirst, Heartbleed bool
	Port uint16
	Timeout int
	Message string
	ErrorLog *log.Logger
	LocalAddr net.Addr
}

func makeDialer(config *GrabConfig) ( func(rhost string) (net.Conn, []byte, TlsLog, error) ) {
	var network string
	if config.Udp {
		network = "udp"
	} else {
		network = "tcp"
	}

	timeout := time.Duration(config.Timeout) * time.Second

	b := make([]byte, 65536)
	if config.Tls {
		tlsConfig := new(ztls.Config)
		tlsConfig.InsecureSkipVerify = true
		tlsConfig.MinVersion = ztls.VersionSSL30
		return func(rhost string) (net.Conn, []byte, TlsLog, error) {
			now := time.Now()
			deadline := now.Add(timeout)
			dialer := net.Dialer{Timeout:timeout, Deadline:deadline, LocalAddr:config.LocalAddr, DualStack:false}
			var conn *ztls.Conn
			firstRead := []byte{}
			if nconn, err := dialer.Dial(network, rhost); err != nil {
				return nconn, firstRead, nil, err
			} else {
				nconn.SetDeadline(deadline)
				if config.ReadFirst {
					res := make([]byte, 1024)
					// TODO add logging
					if firstReadBytes, err := nconn.Read(res); err != nil {
						config.ErrorLog.Print("failed first read")
						return nconn, firstRead, nil, err
					} else {
						firstRead = make([]byte, firstReadBytes)
						copy(firstRead, res)
					}
				}
				if config.StartTls {
					res := make([]byte, 1024)
					if _, err := nconn.Write([]byte("EHLO eecs.umich.edu\r\n")); err != nil {
						config.ErrorLog.Print("failed EHLO")
						return nconn, firstRead, nil, err
					}
					if _, err := nconn.Read(res); err != nil {
						// TODO Validate server likes it
						config.ErrorLog.Print("failed EHLO read")
					}
					if _, err := nconn.Write([]byte("STARTTLS\r\n")); err != nil {
						config.ErrorLog.Print("failed starttls");
					}
					if _, err := nconn.Read(res); err != nil {
						config.ErrorLog.Print("failed starttls read")
					}
				}
				conn = ztls.Client(nconn, tlsConfig)
				conn.SetDeadline(deadline)
				err = conn.Handshake()
				if err == nil && config.Heartbleed {
					conn.CheckHeartbleed(b)
				}
				return conn, firstRead, conn.ConnectionLog(), err
			}
		}
	} else {
		return func(rhost string) (net.Conn, []byte, TlsLog, error) {
			now := time.Now()
			deadline := now.Add(timeout)
			dialer := net.Dialer{Timeout:timeout, Deadline:deadline, LocalAddr:config.LocalAddr}
			conn, err := dialer.Dial(network, rhost);
			if err == nil {
				conn.SetDeadline(deadline)
			}
			return conn, []byte{}, nil, err
		}
	}
}

func GrabBanner(addrChan chan net.IP, resultChan chan Result, doneChan chan int, config *GrabConfig) {
	dial := makeDialer(config)
	port := strconv.FormatUint(uint64(config.Port), 10)
	for ip := range addrChan {
		addr := ip.String()
		rhost := net.JoinHostPort(addr, port)
		conn, firstData, tlsLog, err := dial(rhost)
		if err != nil {
			config.ErrorLog.Print("Could not connect to host ", addr, " - ", err)
			resultChan <- Result{addr, firstData, err, tlsLog, nil}
			continue
		}
		if config.SendMessage {
			s := strings.Replace(config.Message, "%s", addr, -1)
			if _, err := conn.Write([]byte(s)); err != nil {
				conn.Close()
				config.ErrorLog.Print("Could not write message to host ", addr, " - ", err)
				resultChan <- Result{addr, firstData, err, tlsLog, nil}
				continue
			}
		}
		var buf [1024]byte
		n, err := conn.Read(buf[:])
		conn.Close()
		if err != nil && (err != io.EOF || n == 0) {
			config.ErrorLog.Print("Could not read from host ", addr, " - ", err)
			res := Result{addr, firstData, err, tlsLog, nil}
			resultChan <- res
			continue
		}
		res := Result{addr, firstData, nil, tlsLog, buf[0:n]}
		resultChan <- res
	}
	doneChan <- 1
}
<|endoftext|>


<commit_before>package main

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
  "github.com/hoisie/mustache"
)

func onRun(c *cli.Context) error {
  template := c.Args().Get(0)
  name := c.Args().Get(1)
  fmt.Printf("%s, %s", template, name)
  return nil
}

func main() {
  app := cli.NewApp()
  app.Name = "thaum"
  app.Usage = "Generate micro-boilerplates"
  app.Action = onRun

  app.Run(os.Args)
}
<commit_msg>Add validation of path<commit_after>package main

import (
  "fmt"
  "os"
  "errors"
  "log"

  "github.com/urfave/cli"
  "github.com/hoisie/mustache"
  "github.com/spf13/afero"
)

const THAUM_FILES = "thaum_files"

var (
  ErrNoTemplateFolder = errors.New("Thaum can't find your thaum_files!")
  ErrNoTemplate = errors.New("Thaum can't that template in your folder.")
)

// Global Afero Filesystem variable
var AppFs afero.Fs = afero.NewOsFs()

func exists(path string) (bool) {
  exists, err := afero.Exists(AppFs, path)
  if err != nil { log.Fatal(err) }
  return exists
}

func findTemplate(template string) (string, error) {

  // Check if thaum_files folder exists
  path := fmt.Sprintf("./%s", THAUM_FILES)
  if !exists(path) {
    return "", ErrNoTemplateFolder
  }

  // Check if this template exists
  path = fmt.Sprintf("%s/%s", path, template)
  if !exists(path) {
    return "", ErrNoTemplate
  }

  return path, nil // Success!
}

func render(template string, name string) (string) {
  return mustache.Render(template, map[string]string{"name":name})
}

func onRun(c *cli.Context) error {
  template := c.Args().Get(0)
  // name := c.Args().Get(1)

  path, err := findTemplate(template)
  if err != nil { log.Fatal(err) }

  fmt.Printf("%s", path)
  return nil
}

func main() {
  app := cli.NewApp()
  app.Name = "thaum"
  app.Usage = "Generate micro-boilerplates"
  app.Action = onRun

  app.Run(os.Args)
}
<|endoftext|>


<commit_before>package mnemosyne

import (
	"bytes"
	"database/sql/driver"
	"encoding/hex"
	"errors"

	"golang.org/x/crypto/sha3"
	"golang.org/x/net/context"
)

// NewAccessTokenContext returns a new Context that carries Token value.
func NewAccessTokenContext(ctx context.Context, at AccessToken) context.Context {
	return context.WithValue(ctx, AccessTokenContextKey, at)
}

// AccessTokenFromContext returns the Token value stored in context, if any.
func AccessTokenFromContext(ctx context.Context) (AccessToken, bool) {
	at, ok := ctx.Value(AccessTokenContextKey).(AccessToken)

	return at, ok
}

// Encode ...
func (at *AccessToken) Encode() string {
	return string(at.Bytes())
}

// Bytes ...
func (at *AccessToken) Bytes() []byte {
	if len(at.Key) < 10 {
		return at.Hash
	}

	return append(at.Key[:10], at.Hash...)
}

// DecodeAccessToken parse string and allocates new token instance if ok. Expected token has format <key(10)><hash(n)>.
func DecodeAccessToken(s []byte) (at AccessToken) {
	if len(s) < 10 {
		return
	}

	return AccessToken{
		Key:  bytes.TrimSpace(s[:10]),
		Hash: bytes.TrimSpace(s[10:]),
	}
}

// DecodeAccessTokenString works like DecodeToken but accepts string.
func DecodeAccessTokenString(s string) AccessToken {
	return DecodeAccessToken([]byte(s))
}

// NewAccessToken ...
func NewAccessToken(key, hash []byte) AccessToken {
	if len(key) < 10 {
		return AccessToken{
			Key:  append([]byte("0000000000")[:10-len(key)], key...),
			Hash: hash,
		}
	}
	return AccessToken{
		Key:  key[:10],
		Hash: hash,
	}
}

// RandomAccessToken ...
func RandomAccessToken(generator RandomBytesGenerator, key []byte) (at AccessToken, err error) {
	var buf []byte
	buf, err = generator.GenerateRandomBytes(128)
	if err != nil {
		return
	}

	// A hash needs to be 64 bytes long to have 256-bit collision resistance.
	hash := make([]byte, 64)
	// Compute a 64-byte hash of buf and put it in h.
	sha3.ShakeSum256(hash, buf)
	hash2 := make([]byte, hex.EncodedLen(len(hash)))
	hex.Encode(hash2, hash)
	return NewAccessToken(key, hash2), nil
}

// Value implements driver.Valuer interface.
func (at AccessToken) Value() (driver.Value, error) {
	return string(at.Bytes()), nil
}

// Scan implements sql.Scanner interface.
func (at *AccessToken) Scan(src interface{}) error {
	var (
		token AccessToken
	)

	switch s := src.(type) {
	case []byte:
		token = DecodeAccessToken(s)
	case string:
		token = DecodeAccessTokenString(s)
	default:
		return errors.New("mnemosyne: token supports scan only from slice of bytes and string")
	}

	*at = token

	return nil
}

// IsEmpty ...
func (at *AccessToken) IsEmpty() bool {
	if at == nil {
		return true
	}
	return len(at.Hash) == 0
}
<commit_msg>comment line break<commit_after>package mnemosyne

import (
	"bytes"
	"database/sql/driver"
	"encoding/hex"
	"errors"

	"golang.org/x/crypto/sha3"
	"golang.org/x/net/context"
)

// NewAccessTokenContext returns a new Context that carries Token value.
func NewAccessTokenContext(ctx context.Context, at AccessToken) context.Context {
	return context.WithValue(ctx, AccessTokenContextKey, at)
}

// AccessTokenFromContext returns the Token value stored in context, if any.
func AccessTokenFromContext(ctx context.Context) (AccessToken, bool) {
	at, ok := ctx.Value(AccessTokenContextKey).(AccessToken)

	return at, ok
}

// Encode ...
func (at *AccessToken) Encode() string {
	return string(at.Bytes())
}

// Bytes ...
func (at *AccessToken) Bytes() []byte {
	if len(at.Key) < 10 {
		return at.Hash
	}

	return append(at.Key[:10], at.Hash...)
}

// DecodeAccessToken parse string and allocates new token instance if ok.
// Expected token has format <key(10)><hash(n)>.
func DecodeAccessToken(s []byte) (at AccessToken) {
	if len(s) < 10 {
		return
	}

	return AccessToken{
		Key:  bytes.TrimSpace(s[:10]),
		Hash: bytes.TrimSpace(s[10:]),
	}
}

// DecodeAccessTokenString works like DecodeToken but accepts string.
func DecodeAccessTokenString(s string) AccessToken {
	return DecodeAccessToken([]byte(s))
}

// NewAccessToken ...
func NewAccessToken(key, hash []byte) AccessToken {
	if len(key) < 10 {
		return AccessToken{
			Key:  append([]byte("0000000000")[:10-len(key)], key...),
			Hash: hash,
		}
	}
	return AccessToken{
		Key:  key[:10],
		Hash: hash,
	}
}

// RandomAccessToken ...
func RandomAccessToken(generator RandomBytesGenerator, key []byte) (at AccessToken, err error) {
	var buf []byte
	buf, err = generator.GenerateRandomBytes(128)
	if err != nil {
		return
	}

	// A hash needs to be 64 bytes long to have 256-bit collision resistance.
	hash := make([]byte, 64)
	// Compute a 64-byte hash of buf and put it in h.
	sha3.ShakeSum256(hash, buf)
	hash2 := make([]byte, hex.EncodedLen(len(hash)))
	hex.Encode(hash2, hash)
	return NewAccessToken(key, hash2), nil
}

// Value implements driver.Valuer interface.
func (at AccessToken) Value() (driver.Value, error) {
	return string(at.Bytes()), nil
}

// Scan implements sql.Scanner interface.
func (at *AccessToken) Scan(src interface{}) error {
	var (
		token AccessToken
	)

	switch s := src.(type) {
	case []byte:
		token = DecodeAccessToken(s)
	case string:
		token = DecodeAccessTokenString(s)
	default:
		return errors.New("mnemosyne: token supports scan only from slice of bytes and string")
	}

	*at = token

	return nil
}

// IsEmpty ...
func (at *AccessToken) IsEmpty() bool {
	if at == nil {
		return true
	}
	return len(at.Hash) == 0
}
<|endoftext|>


<commit_before>// Copyright 2016 The OPA Authors.  All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

package topdown_test

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"

	"strings"

	"github.com/open-policy-agent/opa/ast"
	"github.com/open-policy-agent/opa/storage/inmem"
	"github.com/open-policy-agent/opa/topdown"
	"github.com/open-policy-agent/opa/topdown/builtins"
	"github.com/open-policy-agent/opa/types"
)

func ExampleQuery_Iter() {
	// Initialize context for the example. Normally the caller would obtain the
	// context from an input parameter or instantiate their own.
	ctx := context.Background()

	compiler := ast.NewCompiler()

	// Define a dummy query and some data that the query will execute against.
	query, err := compiler.QueryCompiler().Compile(ast.MustParseBody(`data.a[_] = x; x >= 2`))
	if err != nil {
		// Handle error.
	}

	var data map[string]interface{}

	// OPA uses Go's standard JSON library but assumes that numbers have been
	// decoded as json.Number instead of float64. You MUST decode with UseNumber
	// enabled.
	decoder := json.NewDecoder(bytes.NewBufferString(`{"a": [1,2,3,4]}`))
	decoder.UseNumber()

	if err := decoder.Decode(&data); err != nil {
		// Handle error.
	}

	// Instantiate the policy engine's storage layer.
	store := inmem.NewFromObject(data)

	// Create a new transaction. Transactions allow the policy engine to
	// evaluate the query over a consistent snapshot fo the storage layer.
	txn, err := store.NewTransaction(ctx)
	if err != nil {
		// Handle error.
	}

	defer store.Abort(ctx, txn)

	// Prepare the evaluation parameters. Evaluation executes against the policy
	// engine's storage. In this case, we seed the storage with a single array
	// of number. Other parameters such as the input, tracing configuration,
	// etc. can be set on the query object.
	q := topdown.NewQuery(query).
		WithCompiler(compiler).
		WithStore(store).
		WithTransaction(txn)

	result := []interface{}{}

	// Execute the query and provide a callback function to accumulate the results.
	err = q.Iter(ctx, func(qr topdown.QueryResult) error {

		// Each variable in the query will have an associated binding.
		x := qr[ast.Var("x")]

		// The bindings are ast.Value types so we will convert to a native Go value here.
		v, err := ast.JSON(x.Value)
		if err != nil {
			return err
		}

		result = append(result, v)
		return nil
	})

	// Inspect the query result.
	fmt.Println("result:", result)
	fmt.Println("err:", err)

	// Output:
	// result: [2 3 4]
	// err: <nil>
}

func ExampleRegisterFunctionalBuiltin1() {

	// Rego includes a number of built-in functions ("built-ins") for performing
	// standard operations like string manipulation, regular expression
	// matching, and computing aggregates.
	//
	// This test shows how to add a new built-in to Rego and OPA.

	// Initialize context for the example. Normally the caller would obtain the
	// context from an input parameter or instantiate their own.
	ctx := context.Background()

	// The ast package contains a registry that enumerates the built-ins
	// included in Rego. When adding a new built-in, you must update the
	// registry to include your built-in. Otherwise, the compiler will complain
	// when it encounters your built-in.
	builtin := &ast.Builtin{
		Name: "mybuiltins.upper",
		Decl: types.NewFunction(
			types.Args(types.S),
			types.S,
		),
	}

	ast.RegisterBuiltin(builtin)

	// This is the implementation of the built-in that will be called during
	// query evaluation.
	builtinImpl := func(a ast.Value) (ast.Value, error) {

		str, err := builtins.StringOperand(a, 1)

		if err != nil {
			return nil, err
		}

		if str.Equal(ast.String("magic")) {
			// topdown.BuiltinEmpty indicates to the evaluation engine that the
			// expression is false/not defined.
			return nil, topdown.BuiltinEmpty{}
		}

		return ast.String(strings.ToUpper(string(str))), nil
	}

	// See documentation for registering functions that take different numbers
	// of arguments.
	topdown.RegisterFunctionalBuiltin1(builtin.Name, builtinImpl)

	// At this point, the new built-in has been registered and can be used in
	// queries. Our custom built-in converts strings to upper case but is not
	// defined for the input "magic".
	compiler := ast.NewCompiler()
	query, err := compiler.QueryCompiler().Compile(ast.MustParseBody(`mybuiltins.upper("custom", x); not mybuiltins.upper("magic", "MAGIC")`))
	if err != nil {
		// Handle error.
	}

	// Evaluate the query.
	q := topdown.NewQuery(query).WithCompiler(compiler)

	q.Iter(ctx, func(qr topdown.QueryResult) error {
		fmt.Println("x:", qr[ast.Var("x")])
		return nil
	})

	// If you add a new built-in function to OPA, you should:
	//
	// 1. Update the Language Reference: http://www.openpolicyagent.org/docs/language-reference.html.
	// 2. Add an integration test to the topdown package.

	// Output:
	//
	// x: "CUSTOM"
}
<commit_msg>Add topdown.Query#Run example<commit_after>// Copyright 2016 The OPA Authors.  All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

package topdown_test

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"

	"strings"

	"github.com/open-policy-agent/opa/ast"
	"github.com/open-policy-agent/opa/storage/inmem"
	"github.com/open-policy-agent/opa/topdown"
	"github.com/open-policy-agent/opa/topdown/builtins"
	"github.com/open-policy-agent/opa/types"
)

func ExampleQuery_Iter() {
	// Initialize context for the example. Normally the caller would obtain the
	// context from an input parameter or instantiate their own.
	ctx := context.Background()

	compiler := ast.NewCompiler()

	// Define a dummy query and some data that the query will execute against.
	query, err := compiler.QueryCompiler().Compile(ast.MustParseBody(`data.a[_] = x; x >= 2`))
	if err != nil {
		// Handle error.
	}

	var data map[string]interface{}

	// OPA uses Go's standard JSON library but assumes that numbers have been
	// decoded as json.Number instead of float64. You MUST decode with UseNumber
	// enabled.
	decoder := json.NewDecoder(bytes.NewBufferString(`{"a": [1,2,3,4]}`))
	decoder.UseNumber()

	if err := decoder.Decode(&data); err != nil {
		// Handle error.
	}

	// Instantiate the policy engine's storage layer.
	store := inmem.NewFromObject(data)

	// Create a new transaction. Transactions allow the policy engine to
	// evaluate the query over a consistent snapshot fo the storage layer.
	txn, err := store.NewTransaction(ctx)
	if err != nil {
		// Handle error.
	}

	defer store.Abort(ctx, txn)

	// Prepare the evaluation parameters. Evaluation executes against the policy
	// engine's storage. In this case, we seed the storage with a single array
	// of number. Other parameters such as the input, tracing configuration,
	// etc. can be set on the query object.
	q := topdown.NewQuery(query).
		WithCompiler(compiler).
		WithStore(store).
		WithTransaction(txn)

	result := []interface{}{}

	// Execute the query and provide a callback function to accumulate the results.
	err = q.Iter(ctx, func(qr topdown.QueryResult) error {

		// Each variable in the query will have an associated binding.
		x := qr[ast.Var("x")]

		// The bindings are ast.Value types so we will convert to a native Go value here.
		v, err := ast.JSON(x.Value)
		if err != nil {
			return err
		}

		result = append(result, v)
		return nil
	})

	// Inspect the query result.
	fmt.Println("result:", result)
	fmt.Println("err:", err)

	// Output:
	// result: [2 3 4]
	// err: <nil>
}

func ExampleQuery_Run() {
	// Initialize context for the example. Normally the caller would obtain the
	// context from an input parameter or instantiate their own.
	ctx := context.Background()

	compiler := ast.NewCompiler()

	// Define a dummy query and some data that the query will execute against.
	query, err := compiler.QueryCompiler().Compile(ast.MustParseBody(`data.a[_] = x; x >= 2`))
	if err != nil {
		// Handle error.
	}

	var data map[string]interface{}

	// OPA uses Go's standard JSON library but assumes that numbers have been
	// decoded as json.Number instead of float64. You MUST decode with UseNumber
	// enabled.
	decoder := json.NewDecoder(bytes.NewBufferString(`{"a": [1,2,3,4]}`))
	decoder.UseNumber()

	if err := decoder.Decode(&data); err != nil {
		// Handle error.
	}

	// Instantiate the policy engine's storage layer.
	store := inmem.NewFromObject(data)

	// Create a new transaction. Transactions allow the policy engine to
	// evaluate the query over a consistent snapshot fo the storage layer.
	txn, err := store.NewTransaction(ctx)
	if err != nil {
		// Handle error.
	}

	defer store.Abort(ctx, txn)

	// Prepare the evaluation parameters. Evaluation executes against the policy
	// engine's storage. In this case, we seed the storage with a single array
	// of number. Other parameters such as the input, tracing configuration,
	// etc. can be set on the query object.
	q := topdown.NewQuery(query).
		WithCompiler(compiler).
		WithStore(store).
		WithTransaction(txn)

	rs, err := q.Run(ctx)

	// Inspect the query result set.
	fmt.Println("len:", len(rs))
	for i := range rs {
		fmt.Printf("rs[%d][\"x\"]: %v\n", i, rs[i]["x"])
	}
	fmt.Println("err:", err)

	// Output:
	// len: 3
	// rs[0]["x"]: 2
	// rs[1]["x"]: 3
	// rs[2]["x"]: 4
	// err: <nil>
}

func ExampleRegisterFunctionalBuiltin1() {

	// Rego includes a number of built-in functions ("built-ins") for performing
	// standard operations like string manipulation, regular expression
	// matching, and computing aggregates.
	//
	// This test shows how to add a new built-in to Rego and OPA.

	// Initialize context for the example. Normally the caller would obtain the
	// context from an input parameter or instantiate their own.
	ctx := context.Background()

	// The ast package contains a registry that enumerates the built-ins
	// included in Rego. When adding a new built-in, you must update the
	// registry to include your built-in. Otherwise, the compiler will complain
	// when it encounters your built-in.
	builtin := &ast.Builtin{
		Name: "mybuiltins.upper",
		Decl: types.NewFunction(
			types.Args(types.S),
			types.S,
		),
	}

	ast.RegisterBuiltin(builtin)

	// This is the implementation of the built-in that will be called during
	// query evaluation.
	builtinImpl := func(a ast.Value) (ast.Value, error) {

		str, err := builtins.StringOperand(a, 1)

		if err != nil {
			return nil, err
		}

		if str.Equal(ast.String("magic")) {
			// topdown.BuiltinEmpty indicates to the evaluation engine that the
			// expression is false/not defined.
			return nil, topdown.BuiltinEmpty{}
		}

		return ast.String(strings.ToUpper(string(str))), nil
	}

	// See documentation for registering functions that take different numbers
	// of arguments.
	topdown.RegisterFunctionalBuiltin1(builtin.Name, builtinImpl)

	// At this point, the new built-in has been registered and can be used in
	// queries. Our custom built-in converts strings to upper case but is not
	// defined for the input "magic".
	compiler := ast.NewCompiler()
	query, err := compiler.QueryCompiler().Compile(ast.MustParseBody(`mybuiltins.upper("custom", x); not mybuiltins.upper("magic", "MAGIC")`))
	if err != nil {
		// Handle error.
	}

	// Evaluate the query.
	q := topdown.NewQuery(query).WithCompiler(compiler)

	q.Iter(ctx, func(qr topdown.QueryResult) error {
		fmt.Println("x:", qr[ast.Var("x")])
		return nil
	})

	// If you add a new built-in function to OPA, you should:
	//
	// 1. Update the Language Reference: http://www.openpolicyagent.org/docs/language-reference.html.
	// 2. Add an integration test to the topdown package.

	// Output:
	//
	// x: "CUSTOM"
}
<|endoftext|>


<commit_before>// "chloe" is a cli binary which serves as a companion to "bower". Its
// single purpose is to list and delete any files not required as part of
// the "bower_dependencies".
//
// "chloe" will scan your "bower.json" file for ignore and must-preserve
// files and directories, and cull any extra junk fetched by "bower".
// Do remember that if you delete even the "README.md" file from a bower
// package - it will prompt bower to re-fetch it on the next update.
package main

import (
    "log"
    "os"
    "strings"
    "bufio"
    "io/ioutil"
    "path/filepath"

    "github.com/sabhiram/go-colorize"
    "github.com/sabhiram/go-git-ignore"

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

// Define application constants
const (
    ENABLE_DEBUG_MODE = false

    // Set "debugLoggingEnabled" to "true" if you want debug spew
    debugLoggingEnabled = ENABLE_DEBUG_MODE

    // Set "traceLoggingEnabled" to "true" if you want function entry spew
    traceLoggingEnabled = ENABLE_DEBUG_MODE

    // Set "timestampEnable" to "true" if you want timestamp output w/ all logs (except the Output logger)
    timestampEnabled    = ENABLE_DEBUG_MODE
)

// Define application globals
var (
    // Trace is used for function enter exit logging
    Trace *log.Logger

    // Debug is enabled for arbitrary logging
    Debug *log.Logger

    // Warning and error speak for themselves
    Warn  *log.Logger
    Error *log.Logger

    // Output is any stuff we wish to print to the screen
    Output *log.Logger

    // Define holders for the cli arguments we wish to parse
    Options struct {
        Version     bool   `short:"v" long:"version"`
        Help        bool   `short:"h" long:"help"`
        File        string `short:"i" long:"input" default:"bower.json"`
        ForceDelete bool   `short:"f" long:"force"`
    }
)

// Sets up any application logging, and any other startup-y
// things we might need to do when this package is used (first-time)
func init() {
    var timestamp   = 0
    var debugWriter = ioutil.Discard
    var traceWriter = ioutil.Discard

    if timestampEnabled    { timestamp = log.Ldate | log.Ltime }
    if debugLoggingEnabled { debugWriter = os.Stdout }
    if traceLoggingEnabled { traceWriter = os.Stdout }

    Trace  = log.New(traceWriter, colorize.ColorString("TRACE: ", "magenta"), timestamp)
    Debug  = log.New(debugWriter, colorize.ColorString("DEBUG: ", "green"),   timestamp)
    Warn   = log.New(os.Stdout,   colorize.ColorString("WARN:  ", "yellow"),  timestamp)
    Error  = log.New(os.Stderr,   colorize.ColorString("ERROR: ", "red"),     timestamp)
    Output = log.New(os.Stdout,   "",                                         0)
}

// Executes the "chloe dispatch" command and its subset ("chloe list")
func chloeDispatch(command string) int {
    Trace.Printf("chloeDispatch(%s)\n", command)

    var workingDir   string
    var files        []string
    var err          error
    var ignoreObject *ignore.GitIgnore

    // Build an ignore object from the input file
    if err == nil {
        ignoreObject, err = getIgnoreObjectFromJSONFile(Options.File)
    }

    // Fetch the current working dir where "chloe" was run from
    if err == nil {
        workingDir, err = os.Getwd()
    }

    // Fetch files we might want to delete using the "workingDir" as the base
    if err == nil {
        // Define function to aggregate matched paths into the "files" slice
        aggregateMatchedFilesFn := func(path string, fileInfo os.FileInfo, err error) error {
            relPath, _ := filepath.Rel(workingDir, path)
            if ignoreObject.MatchesPath(relPath) {
                files = append(files, relPath)
            }
            return nil
        }
        err = filepath.Walk(workingDir, aggregateMatchedFilesFn)
    }

    // List and delete files
    if err == nil && len(files) > 0 {
        Output.Printf("Found %d extra files:\n", len(files))
        for _, file := range files {
            Output.Printf(" - %s\n", file)
        }

        // Only attempt to delete if we are running a dispatch command
        if command == "dispatch" {
            deletePaths := Options.ForceDelete
            if !Options.ForceDelete {
                var input string
                reader := bufio.NewReader(os.Stdin)

                Output.Printf("Purge %d files? [ Yes | No ]: ", len(files))
                input, err = reader.ReadString('\n')
                input = strings.ToLower(strings.Trim(input, "\n"))

                deletePaths = false
                if containsString([]string{"t", "y", "true", "yes", "1"}, input) {
                    deletePaths = true
                }
            }

            // Actually walk and delete files
            if deletePaths {
                for idx := len(files) - 1; idx >= 0; idx-- {
                    file := files[idx]
                    fullPath, _ := filepath.Abs(file)
                    err = os.Remove(fullPath)

                    if err != nil { break }
                }

                if err == nil {
                    Output.Printf("Deleted %d files!\n", len(files))
                }
            }
        }
    } else if err == nil {
        Output.Printf("Found no files to cleanup\n")
    }

    // Handle error condition
    if err != nil {
        Error.Printf("%s\n", err.Error())
        return 1
    }
    return 0
}

// Runs the appropriate chloe command
func runCommand(command string) int {
    Trace.Printf("runCommand(%s)\n", command)

    switch {
    case command == "list" || command == "dispatch":
        return chloeDispatch(command)
    }
    panic(command + " is not a valid command, this code should not be hit!")
    return 1
}

// Application entry-point for "chloe". Responsible for parsing
// the cli arguments and invoking the appropriate action
func main() {
    Trace.Printf("main()\n")

    // Parse arguments which might get passed to "chloe"
    parser := flags.NewParser(&Options, flags.Default & ^flags.HelpFlag)
    args, error := parser.Parse()
    command := strings.ToLower(strings.Join(args, " "))

    exitCode := 0
    switch {

    // Parse Error, print usage
    case error != nil:
        Output.Printf(getAppUsageString())
        exitCode = 1

    // No arguments, or help requested, print usage
    case len(os.Args) == 1 || Options.Help:
        Output.Printf(getAppUsageString())

    // "--version" requested
    case Options.Version:
        Output.Printf("%s\n", getAppVersionString())

    // "list" command invoked
    case isValidCommand(command):
        exitCode = runCommand(command)

    // All other cases go here!
    case true:
        Output.Printf("Unknown command %s, see usage:\n", colorize.ColorString(command, "red"))
        Output.Printf(getAppUsageString())
        exitCode = 1
    }
    os.Exit(exitCode)
}
<commit_msg>Error handle rel path call<commit_after>// "chloe" is a cli binary which serves as a companion to "bower". Its
// single purpose is to list and delete any files not required as part of
// the "bower_dependencies".
//
// "chloe" will scan your "bower.json" file for ignore and must-preserve
// files and directories, and cull any extra junk fetched by "bower".
// Do remember that if you delete even the "README.md" file from a bower
// package - it will prompt bower to re-fetch it on the next update.
package main

import (
    "log"
    "os"
    "strings"
    "bufio"
    "io/ioutil"
    "path/filepath"

    "github.com/sabhiram/go-colorize"
    "github.com/sabhiram/go-git-ignore"

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

// Define application constants
const (
    ENABLE_DEBUG_MODE = false

    // Set "debugLoggingEnabled" to "true" if you want debug spew
    debugLoggingEnabled = ENABLE_DEBUG_MODE

    // Set "traceLoggingEnabled" to "true" if you want function entry spew
    traceLoggingEnabled = ENABLE_DEBUG_MODE

    // Set "timestampEnable" to "true" if you want timestamp output w/ all logs (except the Output logger)
    timestampEnabled    = ENABLE_DEBUG_MODE
)

// Define application globals
var (
    // Trace is used for function enter exit logging
    Trace *log.Logger

    // Debug is enabled for arbitrary logging
    Debug *log.Logger

    // Warning and error speak for themselves
    Warn  *log.Logger
    Error *log.Logger

    // Output is any stuff we wish to print to the screen
    Output *log.Logger

    // Define holders for the cli arguments we wish to parse
    Options struct {
        Version     bool   `short:"v" long:"version"`
        Help        bool   `short:"h" long:"help"`
        File        string `short:"i" long:"input" default:"bower.json"`
        ForceDelete bool   `short:"f" long:"force"`
    }
)

// Sets up any application logging, and any other startup-y
// things we might need to do when this package is used (first-time)
func init() {
    var timestamp   = 0
    var debugWriter = ioutil.Discard
    var traceWriter = ioutil.Discard

    if timestampEnabled    { timestamp = log.Ldate | log.Ltime }
    if debugLoggingEnabled { debugWriter = os.Stdout }
    if traceLoggingEnabled { traceWriter = os.Stdout }

    Trace  = log.New(traceWriter, colorize.ColorString("TRACE: ", "magenta"), timestamp)
    Debug  = log.New(debugWriter, colorize.ColorString("DEBUG: ", "green"),   timestamp)
    Warn   = log.New(os.Stdout,   colorize.ColorString("WARN:  ", "yellow"),  timestamp)
    Error  = log.New(os.Stderr,   colorize.ColorString("ERROR: ", "red"),     timestamp)
    Output = log.New(os.Stdout,   "",                                         0)
}

// Executes the "chloe dispatch" command and its subset ("chloe list")
func chloeDispatch(command string) int {
    Trace.Printf("chloeDispatch(%s)\n", command)

    var workingDir   string
    var files        []string
    var err          error
    var ignoreObject *ignore.GitIgnore

    // Build an ignore object from the input file
    if err == nil {
        ignoreObject, err = getIgnoreObjectFromJSONFile(Options.File)
    }

    // Fetch the current working dir where "chloe" was run from
    if err == nil {
        workingDir, err = os.Getwd()
    }

    // Fetch files we might want to delete using the "workingDir" as the base
    if err == nil {
        // Define function to aggregate matched paths into the "files" slice
        aggregateMatchedFilesFn := func(path string, fileInfo os.FileInfo, err error) error {
            relPath, err := filepath.Rel(workingDir, path)
            if err != nil {
                return err
            }
            if ignoreObject.MatchesPath(relPath) {
                files = append(files, relPath)
            }
            return nil
        }
        err = filepath.Walk(workingDir, aggregateMatchedFilesFn)
    }

    // List and delete files
    if err == nil && len(files) > 0 {
        Output.Printf("Found %d extra files:\n", len(files))
        for _, file := range files {
            Output.Printf(" - %s\n", file)
        }

        // Only attempt to delete if we are running a dispatch command
        if command == "dispatch" {
            deletePaths := Options.ForceDelete
            if !Options.ForceDelete {
                var input string
                reader := bufio.NewReader(os.Stdin)

                Output.Printf("Purge %d files? [ Yes | No ]: ", len(files))
                input, err = reader.ReadString('\n')
                input = strings.ToLower(strings.Trim(input, "\n"))

                deletePaths = false
                if containsString([]string{"t", "y", "true", "yes", "1"}, input) {
                    deletePaths = true
                }
            }

            // Actually walk and delete files
            if deletePaths {
                for idx := len(files) - 1; idx >= 0; idx-- {
                    file := files[idx]
                    fullPath, _ := filepath.Abs(file)
                    err = os.Remove(fullPath)

                    if err != nil { break }
                }

                if err == nil {
                    Output.Printf("Deleted %d files!\n", len(files))
                }
            }
        }
    } else if err == nil {
        Output.Printf("Found no files to cleanup\n")
    }

    // Handle error condition
    if err != nil {
        Error.Printf("%s\n", err.Error())
        return 1
    }
    return 0
}

// Runs the appropriate chloe command
func runCommand(command string) int {
    Trace.Printf("runCommand(%s)\n", command)

    switch {
    case command == "list" || command == "dispatch":
        return chloeDispatch(command)
    }
    panic(command + " is not a valid command, this code should not be hit!")
    return 1
}

// Application entry-point for "chloe". Responsible for parsing
// the cli arguments and invoking the appropriate action
func main() {
    Trace.Printf("main()\n")

    // Parse arguments which might get passed to "chloe"
    parser := flags.NewParser(&Options, flags.Default & ^flags.HelpFlag)
    args, error := parser.Parse()
    command := strings.ToLower(strings.Join(args, " "))

    exitCode := 0
    switch {

    // Parse Error, print usage
    case error != nil:
        Output.Printf(getAppUsageString())
        exitCode = 1

    // No arguments, or help requested, print usage
    case len(os.Args) == 1 || Options.Help:
        Output.Printf(getAppUsageString())

    // "--version" requested
    case Options.Version:
        Output.Printf("%s\n", getAppVersionString())

    // "list" command invoked
    case isValidCommand(command):
        exitCode = runCommand(command)

    // All other cases go here!
    case true:
        Output.Printf("Unknown command %s, see usage:\n", colorize.ColorString(command, "red"))
        Output.Printf(getAppUsageString())
        exitCode = 1
    }
    os.Exit(exitCode)
}
<|endoftext|>