<commit_before>// Package base provides a base implementation of the storage driver that can
// be used to implement common checks. The goal is to increase the amount of
// code sharing.
//
// The canonical approach to use this class is to embed in the exported driver
// struct such that calls are proxied through this implementation. First,
// declare the internal driver, as follows:
//
// 	type driver struct { ... internal ...}
//
// The resulting type should implement StorageDriver such that it can be the
// target of a Base struct. The exported type can then be declared as follows:
//
// 	type Driver struct {
// 		Base
// 	}
//
// Because Driver embeds Base, it effectively implements Base. If the driver
// needs to intercept a call, before going to base, Driver should implement
// that method. Effectively, Driver can intercept calls before coming in and
// driver implements the actual logic.
//
// To further shield the embed from other packages, it is recommended to
// employ a private embed struct:
//
// 	type baseEmbed struct {
// 		base.Base
// 	}
//
// Then, declare driver to embed baseEmbed, rather than Base directly:
//
// 	type Driver struct {
// 		baseEmbed
// 	}
//
// The type now implements StorageDriver, proxying through Base, without
// exporting an unnessecary field.
package base

import (
	"io"

	"github.com/docker/distribution/context"
	storagedriver "github.com/docker/distribution/registry/storage/driver"
)

// Base provides a wrapper around a storagedriver implementation that provides
// common path and bounds checking.
type Base struct {
	storagedriver.StorageDriver
}

// GetContent wraps GetContent of underlying storage driver.
func (base *Base) GetContent(path string) ([]byte, error) {
	_, done := context.WithTrace(context.Background())
	defer done("Base.GetContent")

	if !storagedriver.PathRegexp.MatchString(path) {
		return nil, storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.GetContent(path)
}

// PutContent wraps PutContent of underlying storage driver.
func (base *Base) PutContent(path string, content []byte) error {
	_, done := context.WithTrace(context.Background())
	defer done("Base.PutContent")

	if !storagedriver.PathRegexp.MatchString(path) {
		return storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.PutContent(path, content)
}

// ReadStream wraps ReadStream of underlying storage driver.
func (base *Base) ReadStream(path string, offset int64) (io.ReadCloser, error) {
	_, done := context.WithTrace(context.Background())
	defer done("Base.ReadStream")

	if offset < 0 {
		return nil, storagedriver.InvalidOffsetError{Path: path, Offset: offset}
	}

	if !storagedriver.PathRegexp.MatchString(path) {
		return nil, storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.ReadStream(path, offset)
}

// WriteStream wraps WriteStream of underlying storage driver.
func (base *Base) WriteStream(path string, offset int64, reader io.Reader) (nn int64, err error) {
	_, done := context.WithTrace(context.Background())
	defer done("Base.WriteStream")

	if offset < 0 {
		return 0, storagedriver.InvalidOffsetError{Path: path, Offset: offset}
	}

	if !storagedriver.PathRegexp.MatchString(path) {
		return 0, storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.WriteStream(path, offset, reader)
}

// Stat wraps Stat of underlying storage driver.
func (base *Base) Stat(path string) (storagedriver.FileInfo, error) {
	_, done := context.WithTrace(context.Background())
	defer done("Base.Stat")

	if !storagedriver.PathRegexp.MatchString(path) {
		return nil, storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.Stat(path)
}

// List wraps List of underlying storage driver.
func (base *Base) List(path string) ([]string, error) {
	_, done := context.WithTrace(context.Background())
	defer done("Base.List")

	if !storagedriver.PathRegexp.MatchString(path) && path != "/" {
		return nil, storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.List(path)
}

// Move wraps Move of underlying storage driver.
func (base *Base) Move(sourcePath string, destPath string) error {
	_, done := context.WithTrace(context.Background())
	defer done("Base.Move")

	if !storagedriver.PathRegexp.MatchString(sourcePath) {
		return storagedriver.InvalidPathError{Path: sourcePath}
	} else if !storagedriver.PathRegexp.MatchString(destPath) {
		return storagedriver.InvalidPathError{Path: destPath}
	}

	return base.StorageDriver.Move(sourcePath, destPath)
}

// Delete wraps Delete of underlying storage driver.
func (base *Base) Delete(path string) error {
	_, done := context.WithTrace(context.Background())
	defer done("Base.Move")

	if !storagedriver.PathRegexp.MatchString(path) {
		return storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.Delete(path)
}

// URLFor wraps URLFor of underlying storage driver.
func (base *Base) URLFor(path string, options map[string]interface{}) (string, error) {
	_, done := context.WithTrace(context.Background())
	defer done("Base.URLFor")

	if !storagedriver.PathRegexp.MatchString(path) {
		return "", storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.URLFor(path, options)
}
<commit_msg>Add path and other info to filesytem trace methods.<commit_after>// Package base provides a base implementation of the storage driver that can
// be used to implement common checks. The goal is to increase the amount of
// code sharing.
//
// The canonical approach to use this class is to embed in the exported driver
// struct such that calls are proxied through this implementation. First,
// declare the internal driver, as follows:
//
// 	type driver struct { ... internal ...}
//
// The resulting type should implement StorageDriver such that it can be the
// target of a Base struct. The exported type can then be declared as follows:
//
// 	type Driver struct {
// 		Base
// 	}
//
// Because Driver embeds Base, it effectively implements Base. If the driver
// needs to intercept a call, before going to base, Driver should implement
// that method. Effectively, Driver can intercept calls before coming in and
// driver implements the actual logic.
//
// To further shield the embed from other packages, it is recommended to
// employ a private embed struct:
//
// 	type baseEmbed struct {
// 		base.Base
// 	}
//
// Then, declare driver to embed baseEmbed, rather than Base directly:
//
// 	type Driver struct {
// 		baseEmbed
// 	}
//
// The type now implements StorageDriver, proxying through Base, without
// exporting an unnecessary field.
package base

import (
	"io"

	"github.com/docker/distribution/context"
	storagedriver "github.com/docker/distribution/registry/storage/driver"
)

// Base provides a wrapper around a storagedriver implementation that provides
// common path and bounds checking.
type Base struct {
	storagedriver.StorageDriver
}

// GetContent wraps GetContent of underlying storage driver.
func (base *Base) GetContent(path string) ([]byte, error) {
	_, done := context.WithTrace(context.Background())
	defer done("Base.GetContent(\"%s\")", path)

	if !storagedriver.PathRegexp.MatchString(path) {
		return nil, storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.GetContent(path)
}

// PutContent wraps PutContent of underlying storage driver.
func (base *Base) PutContent(path string, content []byte) error {
	_, done := context.WithTrace(context.Background())
	defer done("Base.PutContent(\"%s\")", path)

	if !storagedriver.PathRegexp.MatchString(path) {
		return storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.PutContent(path, content)
}

// ReadStream wraps ReadStream of underlying storage driver.
func (base *Base) ReadStream(path string, offset int64) (io.ReadCloser, error) {
	_, done := context.WithTrace(context.Background())
	defer done("Base.ReadStream(\"%s\", %d)", path, offset)

	if offset < 0 {
		return nil, storagedriver.InvalidOffsetError{Path: path, Offset: offset}
	}

	if !storagedriver.PathRegexp.MatchString(path) {
		return nil, storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.ReadStream(path, offset)
}

// WriteStream wraps WriteStream of underlying storage driver.
func (base *Base) WriteStream(path string, offset int64, reader io.Reader) (nn int64, err error) {
	_, done := context.WithTrace(context.Background())
	defer done("Base.WriteStream(\"%s\", %d)", path, offset)

	if offset < 0 {
		return 0, storagedriver.InvalidOffsetError{Path: path, Offset: offset}
	}

	if !storagedriver.PathRegexp.MatchString(path) {
		return 0, storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.WriteStream(path, offset, reader)
}

// Stat wraps Stat of underlying storage driver.
func (base *Base) Stat(path string) (storagedriver.FileInfo, error) {
	_, done := context.WithTrace(context.Background())
	defer done("Base.Stat(\"%s\")", path)

	if !storagedriver.PathRegexp.MatchString(path) {
		return nil, storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.Stat(path)
}

// List wraps List of underlying storage driver.
func (base *Base) List(path string) ([]string, error) {
	_, done := context.WithTrace(context.Background())
	defer done("Base.List(\"%s\")", path)

	if !storagedriver.PathRegexp.MatchString(path) && path != "/" {
		return nil, storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.List(path)
}

// Move wraps Move of underlying storage driver.
func (base *Base) Move(sourcePath string, destPath string) error {
	_, done := context.WithTrace(context.Background())
	defer done("Base.Move(\"%s\", \"%s\"", sourcePath, destPath)

	if !storagedriver.PathRegexp.MatchString(sourcePath) {
		return storagedriver.InvalidPathError{Path: sourcePath}
	} else if !storagedriver.PathRegexp.MatchString(destPath) {
		return storagedriver.InvalidPathError{Path: destPath}
	}

	return base.StorageDriver.Move(sourcePath, destPath)
}

// Delete wraps Delete of underlying storage driver.
func (base *Base) Delete(path string) error {
	_, done := context.WithTrace(context.Background())
	defer done("Base.Delete(\"%s\")", path)

	if !storagedriver.PathRegexp.MatchString(path) {
		return storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.Delete(path)
}

// URLFor wraps URLFor of underlying storage driver.
func (base *Base) URLFor(path string, options map[string]interface{}) (string, error) {
	_, done := context.WithTrace(context.Background())
	defer done("Base.URLFor(\"%s\")", path)

	if !storagedriver.PathRegexp.MatchString(path) {
		return "", storagedriver.InvalidPathError{Path: path}
	}

	return base.StorageDriver.URLFor(path, options)
}
<|endoftext|>


<commit_before>package cmap

import (
	"sort"
	"strconv"
	"testing"
)

type Animal struct {
	name string
}

func TestMapCreation(t *testing.T) {
	m := NewConcurretMap()
	if m == nil {
		t.Error("map is null.")
	}

	if m.Count() != 0 {
		t.Error("new map should be empty.")
	}
}

func TestInsert(t *testing.T) {
	m := NewConcurretMap()
	elephant := Animal{"elephant"}
	monkey := Animal{"monkey"}

	m.Add("elephant", elephant)
	m.Add("monkey", monkey)

	if m.Count() != 2 {
		t.Error("map should contain exactly two elements.")
	}
}

func TestGet(t *testing.T) {
	m := NewConcurretMap()

	// Get a missing element.
	val, ok := m.Get("Money")

	if ok == true {
		t.Error("ok should be false when item is missing from map.")
	}

	if val != nil {
		t.Error("Missing values should return as null.")
	}

	elephant := Animal{"elephant"}
	m.Add("elephant", elephant)

	// Retrieve inserted element.

	tmp, ok := m.Get("elephant")
	elephant = tmp.(Animal) // Type assertion.

	if ok == false {
		t.Error("ok should be true for item stored within the map.")
	}

	if &elephant == nil {
		t.Error("expecting an element, not null.")
	}

	if elephant.name != "elephant" {
		t.Error("item was modified.")
	}
}

func TestHas(t *testing.T) {
	m := NewConcurretMap()

	// Get a missing element.
	if m.Has("Money") == true {
		t.Error("element shouldn't exists")
	}

	elephant := Animal{"elephant"}
	m.Add("elephant", elephant)

	if m.Has("elephant") == false {
		t.Error("element exists, expecting Has to return True.")
	}
}

func TestRemove(t *testing.T) {
	m := NewConcurretMap()

	monkey := Animal{"monkey"}
	m.Add("monkey", monkey)

	m.Remove("monkey")

	if m.Count() != 0 {
		t.Error("Expecting count to be zero once item was removed.")
	}

	temp, ok := m.Get("monkey")

	if ok != false {
		t.Error("Expecting ok to be false for missing items.")
	}

	if temp != nil {
		t.Error("Expecting item to be nil after its removal.")
	}

	// Remove a none existing element.
	m.Remove("noone")
}

func TestCount(t *testing.T) {
	m := NewConcurretMap()
	for i := 0; i < 100; i++ {
		m.Add(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}

	if m.Count() != 100 {
		t.Error("Expecting 100 element within map.")
	}
}

func TestClear(t *testing.T) {
	m := NewConcurretMap()

	m.Clear()
	if m.Count() != 0 {
		t.Error("Expecting an empty map")
	}

	monkey := Animal{"monkey"}

	m.Add("monkey", monkey)

	m.Clear()
	if m.Count() != 0 {
		t.Error("Expecting an empty map")
	}

	if &monkey == nil {
		t.Error("Element should still exits")
	}
}

func TestIsEmpty(t *testing.T) {
	m := NewConcurretMap()

	if m.IsEmpty() == false {
		t.Error("new map should be empty")
	}

	m.Add("elephant", Animal{"elephant"})

	if m.IsEmpty() != false {
		t.Error("map shouldn't be empty.")
	}
}

func TestRange(t *testing.T) {
	m := NewConcurretMap()

	// Insert 100 elements.
	for i := 0; i < 100; i++ {
		m.Add(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}

	counter := 0
	// Iterate over elements.
	for item := range m.Iter() {
		val := item.val

		if val == nil {
			t.Error("Expecting an object.")
		}
		counter++
	}

	if counter != 100 {
		t.Error("We should have counted 100 elements.")
	}
}

func TestConcurrent(t *testing.T) {
	m := NewConcurretMap()
	ch := make(chan int)
	var a [10000]int

	// Using go routines insert 10000 ints into our map.
	for i := 0; i < 10000; i++ {
		go func(j int) {
			// Add item to map.
			m.Add(strconv.Itoa(j), j)

			// Retrieve item from map.
			val, _ := m.Get(strconv.Itoa(j))

			// Write to channel inserted value.
			ch <- val.(int)
		}(i) // Call go routine with current index.
	}

	// Wait for all go routines to finish.
	counter := 0
	for elem := range ch {
		a[counter] = elem
		counter++
		if counter == 10000 {
			break
		}
	}

	// Sorts array, will make is simpler to verify all inserted values we're returned.
	sort.Ints(a[0:10000])

	// Make sure map contains 10000 elements.
	if m.Count() != 10000 {
		t.Error("Expecting 10000 elements.")
	}

	// Make sure all inserted values we're fetched from map.
	for i := 0; i < 10000; i++ {
		if i != a[i] {
			t.Error("missing value", i)
		}
	}
}
<commit_msg>decrese goroutines<commit_after>package cmap

import (
	"sort"
	"strconv"
	"testing"
)

type Animal struct {
	name string
}

func TestMapCreation(t *testing.T) {
	m := NewConcurretMap()
	if m == nil {
		t.Error("map is null.")
	}

	if m.Count() != 0 {
		t.Error("new map should be empty.")
	}
}

func TestInsert(t *testing.T) {
	m := NewConcurretMap()
	elephant := Animal{"elephant"}
	monkey := Animal{"monkey"}

	m.Add("elephant", elephant)
	m.Add("monkey", monkey)

	if m.Count() != 2 {
		t.Error("map should contain exactly two elements.")
	}
}

func TestGet(t *testing.T) {
	m := NewConcurretMap()

	// Get a missing element.
	val, ok := m.Get("Money")

	if ok == true {
		t.Error("ok should be false when item is missing from map.")
	}

	if val != nil {
		t.Error("Missing values should return as null.")
	}

	elephant := Animal{"elephant"}
	m.Add("elephant", elephant)

	// Retrieve inserted element.

	tmp, ok := m.Get("elephant")
	elephant = tmp.(Animal) // Type assertion.

	if ok == false {
		t.Error("ok should be true for item stored within the map.")
	}

	if &elephant == nil {
		t.Error("expecting an element, not null.")
	}

	if elephant.name != "elephant" {
		t.Error("item was modified.")
	}
}

func TestHas(t *testing.T) {
	m := NewConcurretMap()

	// Get a missing element.
	if m.Has("Money") == true {
		t.Error("element shouldn't exists")
	}

	elephant := Animal{"elephant"}
	m.Add("elephant", elephant)

	if m.Has("elephant") == false {
		t.Error("element exists, expecting Has to return True.")
	}
}

func TestRemove(t *testing.T) {
	m := NewConcurretMap()

	monkey := Animal{"monkey"}
	m.Add("monkey", monkey)

	m.Remove("monkey")

	if m.Count() != 0 {
		t.Error("Expecting count to be zero once item was removed.")
	}

	temp, ok := m.Get("monkey")

	if ok != false {
		t.Error("Expecting ok to be false for missing items.")
	}

	if temp != nil {
		t.Error("Expecting item to be nil after its removal.")
	}

	// Remove a none existing element.
	m.Remove("noone")
}

func TestCount(t *testing.T) {
	m := NewConcurretMap()
	for i := 0; i < 100; i++ {
		m.Add(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}

	if m.Count() != 100 {
		t.Error("Expecting 100 element within map.")
	}
}

func TestClear(t *testing.T) {
	m := NewConcurretMap()

	m.Clear()
	if m.Count() != 0 {
		t.Error("Expecting an empty map")
	}

	monkey := Animal{"monkey"}

	m.Add("monkey", monkey)

	m.Clear()
	if m.Count() != 0 {
		t.Error("Expecting an empty map")
	}

	if &monkey == nil {
		t.Error("Element should still exits")
	}
}

func TestIsEmpty(t *testing.T) {
	m := NewConcurretMap()

	if m.IsEmpty() == false {
		t.Error("new map should be empty")
	}

	m.Add("elephant", Animal{"elephant"})

	if m.IsEmpty() != false {
		t.Error("map shouldn't be empty.")
	}
}

func TestRange(t *testing.T) {
	m := NewConcurretMap()

	// Insert 100 elements.
	for i := 0; i < 100; i++ {
		m.Add(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}

	counter := 0
	// Iterate over elements.
	for item := range m.Iter() {
		val := item.val

		if val == nil {
			t.Error("Expecting an object.")
		}
		counter++
	}

	if counter != 100 {
		t.Error("We should have counted 100 elements.")
	}
}

func TestConcurrent(t *testing.T) {
	m := NewConcurretMap()
	ch := make(chan int)
	var a [1000]int

	// Using go routines insert 1000 ints into our map.
	for i := 0; i < 1000; i++ {
		go func(j int) {
			// Add item to map.
			m.Add(strconv.Itoa(j), j)

			// Retrieve item from map.
			val, _ := m.Get(strconv.Itoa(j))

			// Write to channel inserted value.
			ch <- val.(int)
		}(i) // Call go routine with current index.
	}

	// Wait for all go routines to finish.
	counter := 0
	for elem := range ch {
		a[counter] = elem
		counter++
		if counter == 1000 {
			break
		}
	}

	// Sorts array, will make is simpler to verify all inserted values we're returned.
	sort.Ints(a[0:1000])

	// Make sure map contains 1000 elements.
	if m.Count() != 1000 {
		t.Error("Expecting 1000 elements.")
	}

	// Make sure all inserted values we're fetched from map.
	for i := 0; i < 1000; i++ {
		if i != a[i] {
			t.Error("missing value", i)
		}
	}
}
<|endoftext|>


<commit_before>package dynamodb

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbiface"
	"github.com/dtan4/valec/secret"
	"github.com/pkg/errors"
)

// Client represents the wrapper of DynamoDB API client
type Client struct {
	api dynamodbiface.DynamoDBAPI
}

// NewClient creates new Client object
func NewClient(api dynamodbiface.DynamoDBAPI) *Client {
	return &Client{
		api: api,
	}
}

// CreateTable creates new table for Valec
func (c *Client) CreateTable(table string) error {
	_, err := c.api.CreateTable(&dynamodb.CreateTableInput{
		AttributeDefinitions: []*dynamodb.AttributeDefinition{
			&dynamodb.AttributeDefinition{
				AttributeName: aws.String("namespace"),
				AttributeType: aws.String("S"),
			},
			&dynamodb.AttributeDefinition{
				AttributeName: aws.String("key"),
				AttributeType: aws.String("S"),
			},
		},
		KeySchema: []*dynamodb.KeySchemaElement{
			&dynamodb.KeySchemaElement{
				AttributeName: aws.String("namespace"),
				KeyType:       aws.String("HASH"),
			},
			&dynamodb.KeySchemaElement{
				AttributeName: aws.String("key"),
				KeyType:       aws.String("RANGE"),
			},
		},
		ProvisionedThroughput: &dynamodb.ProvisionedThroughput{
			ReadCapacityUnits:  aws.Int64(1),
			WriteCapacityUnits: aws.Int64(1),
		},
		TableName: aws.String(table),
	})
	if err != nil {
		return errors.Wrapf(err, "Failed to create DynamoDB table. table=%s", table)
	}

	return nil
}

// Delete deletes records from DynamoDB table
func (c *Client) Delete(table, namespace string, secrets []*secret.Secret) error {
	if len(secrets) == 0 {
		return nil
	}

	writeRequests := []*dynamodb.WriteRequest{}

	var writeRequest *dynamodb.WriteRequest

	for _, secret := range secrets {
		writeRequest = &dynamodb.WriteRequest{
			DeleteRequest: &dynamodb.DeleteRequest{
				Key: map[string]*dynamodb.AttributeValue{
					"namespace": &dynamodb.AttributeValue{
						S: aws.String(namespace),
					},
					"key": &dynamodb.AttributeValue{
						S: aws.String(secret.Key),
					},
				},
			},
		}
		writeRequests = append(writeRequests, writeRequest)
	}

	requestItems := make(map[string][]*dynamodb.WriteRequest)
	requestItems[table] = writeRequests

	_, err := c.api.BatchWriteItem(&dynamodb.BatchWriteItemInput{
		RequestItems: requestItems,
	})
	if err != nil {
		return errors.Wrap(err, "Failed to delete items.")
	}

	return nil
}

// Insert creates / updates records of secrets in DynamoDB table
func (c *Client) Insert(table, namespace string, secrets []*secret.Secret) error {
	if len(secrets) == 0 {
		return nil
	}

	writeRequests := []*dynamodb.WriteRequest{}

	var writeRequest *dynamodb.WriteRequest

	for _, secret := range secrets {
		writeRequest = &dynamodb.WriteRequest{
			PutRequest: &dynamodb.PutRequest{
				Item: map[string]*dynamodb.AttributeValue{
					"namespace": &dynamodb.AttributeValue{
						S: aws.String(namespace),
					},
					"key": &dynamodb.AttributeValue{
						S: aws.String(secret.Key),
					},
					"value": &dynamodb.AttributeValue{
						S: aws.String(secret.Value),
					},
				},
			},
		}
		writeRequests = append(writeRequests, writeRequest)
	}

	requestItems := make(map[string][]*dynamodb.WriteRequest)
	requestItems[table] = writeRequests

	_, err := c.api.BatchWriteItem(&dynamodb.BatchWriteItemInput{
		RequestItems: requestItems,
	})
	if err != nil {
		return errors.Wrap(err, "Failed to insert items.")
	}

	return nil
}

// ListSecrets returns all secrets in the given table and namespace
func (c *Client) ListSecrets(table, namespace string) ([]*secret.Secret, error) {
	keyConditions := map[string]*dynamodb.Condition{
		"namespace": &dynamodb.Condition{
			ComparisonOperator: aws.String(dynamodb.ComparisonOperatorEq),
			AttributeValueList: []*dynamodb.AttributeValue{
				&dynamodb.AttributeValue{
					S: aws.String(namespace),
				},
			},
		},
	}
	params := &dynamodb.QueryInput{
		TableName:     aws.String(table),
		KeyConditions: keyConditions,
	}

	resp, err := c.api.Query(params)
	if err != nil {
		return []*secret.Secret{}, errors.Wrapf(err, "Failed to list up secrets. namespace=%s", namespace)
	}

	secrets := []*secret.Secret{}

	for _, item := range resp.Items {
		secret := &secret.Secret{
			Key:   *item["key"].S,
			Value: *item["value"].S,
		}

		secrets = append(secrets, secret)
	}

	return secrets, nil
}

// ListNamespaces returns all namespaces
func (c *Client) ListNamespaces(table string) ([]string, error) {
	resp, err := c.api.Scan(&dynamodb.ScanInput{
		TableName: aws.String(table),
	})
	if err != nil {
		return []string{}, errors.Wrapf(err, "Failed to retrieve items from DynamoDB table. table=%s", table)
	}

	nsmap := map[string]bool{}

	for _, item := range resp.Items {
		nsmap[*item["namespace"].S] = true
	}

	namespaces := []string{}

	for k := range nsmap {
		namespaces = append(namespaces, k)
	}

	return namespaces, nil
}

// TableExists check whether the given table exists or not
func (c *Client) TableExists(table string) (bool, error) {
	resp, err := c.api.ListTables(&dynamodb.ListTablesInput{})
	if err != nil {
		return false, errors.Wrap(err, "Failed to retrieve DynamoDB tables.")
	}

	for _, tableName := range resp.TableNames {
		if *tableName == table {
			return true, nil
		}
	}

	return false, nil
}
<commit_msg>Sort namespace in alphabetical order<commit_after>package dynamodb

import (
	"sort"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbiface"
	"github.com/dtan4/valec/secret"
	"github.com/pkg/errors"
)

// Client represents the wrapper of DynamoDB API client
type Client struct {
	api dynamodbiface.DynamoDBAPI
}

// NewClient creates new Client object
func NewClient(api dynamodbiface.DynamoDBAPI) *Client {
	return &Client{
		api: api,
	}
}

// CreateTable creates new table for Valec
func (c *Client) CreateTable(table string) error {
	_, err := c.api.CreateTable(&dynamodb.CreateTableInput{
		AttributeDefinitions: []*dynamodb.AttributeDefinition{
			&dynamodb.AttributeDefinition{
				AttributeName: aws.String("namespace"),
				AttributeType: aws.String("S"),
			},
			&dynamodb.AttributeDefinition{
				AttributeName: aws.String("key"),
				AttributeType: aws.String("S"),
			},
		},
		KeySchema: []*dynamodb.KeySchemaElement{
			&dynamodb.KeySchemaElement{
				AttributeName: aws.String("namespace"),
				KeyType:       aws.String("HASH"),
			},
			&dynamodb.KeySchemaElement{
				AttributeName: aws.String("key"),
				KeyType:       aws.String("RANGE"),
			},
		},
		ProvisionedThroughput: &dynamodb.ProvisionedThroughput{
			ReadCapacityUnits:  aws.Int64(1),
			WriteCapacityUnits: aws.Int64(1),
		},
		TableName: aws.String(table),
	})
	if err != nil {
		return errors.Wrapf(err, "Failed to create DynamoDB table. table=%s", table)
	}

	return nil
}

// Delete deletes records from DynamoDB table
func (c *Client) Delete(table, namespace string, secrets []*secret.Secret) error {
	if len(secrets) == 0 {
		return nil
	}

	writeRequests := []*dynamodb.WriteRequest{}

	var writeRequest *dynamodb.WriteRequest

	for _, secret := range secrets {
		writeRequest = &dynamodb.WriteRequest{
			DeleteRequest: &dynamodb.DeleteRequest{
				Key: map[string]*dynamodb.AttributeValue{
					"namespace": &dynamodb.AttributeValue{
						S: aws.String(namespace),
					},
					"key": &dynamodb.AttributeValue{
						S: aws.String(secret.Key),
					},
				},
			},
		}
		writeRequests = append(writeRequests, writeRequest)
	}

	requestItems := make(map[string][]*dynamodb.WriteRequest)
	requestItems[table] = writeRequests

	_, err := c.api.BatchWriteItem(&dynamodb.BatchWriteItemInput{
		RequestItems: requestItems,
	})
	if err != nil {
		return errors.Wrap(err, "Failed to delete items.")
	}

	return nil
}

// Insert creates / updates records of secrets in DynamoDB table
func (c *Client) Insert(table, namespace string, secrets []*secret.Secret) error {
	if len(secrets) == 0 {
		return nil
	}

	writeRequests := []*dynamodb.WriteRequest{}

	var writeRequest *dynamodb.WriteRequest

	for _, secret := range secrets {
		writeRequest = &dynamodb.WriteRequest{
			PutRequest: &dynamodb.PutRequest{
				Item: map[string]*dynamodb.AttributeValue{
					"namespace": &dynamodb.AttributeValue{
						S: aws.String(namespace),
					},
					"key": &dynamodb.AttributeValue{
						S: aws.String(secret.Key),
					},
					"value": &dynamodb.AttributeValue{
						S: aws.String(secret.Value),
					},
				},
			},
		}
		writeRequests = append(writeRequests, writeRequest)
	}

	requestItems := make(map[string][]*dynamodb.WriteRequest)
	requestItems[table] = writeRequests

	_, err := c.api.BatchWriteItem(&dynamodb.BatchWriteItemInput{
		RequestItems: requestItems,
	})
	if err != nil {
		return errors.Wrap(err, "Failed to insert items.")
	}

	return nil
}

// ListSecrets returns all secrets in the given table and namespace
func (c *Client) ListSecrets(table, namespace string) ([]*secret.Secret, error) {
	keyConditions := map[string]*dynamodb.Condition{
		"namespace": &dynamodb.Condition{
			ComparisonOperator: aws.String(dynamodb.ComparisonOperatorEq),
			AttributeValueList: []*dynamodb.AttributeValue{
				&dynamodb.AttributeValue{
					S: aws.String(namespace),
				},
			},
		},
	}
	params := &dynamodb.QueryInput{
		TableName:     aws.String(table),
		KeyConditions: keyConditions,
	}

	resp, err := c.api.Query(params)
	if err != nil {
		return []*secret.Secret{}, errors.Wrapf(err, "Failed to list up secrets. namespace=%s", namespace)
	}

	secrets := []*secret.Secret{}

	for _, item := range resp.Items {
		secret := &secret.Secret{
			Key:   *item["key"].S,
			Value: *item["value"].S,
		}

		secrets = append(secrets, secret)
	}

	return secrets, nil
}

// ListNamespaces returns all namespaces
func (c *Client) ListNamespaces(table string) ([]string, error) {
	resp, err := c.api.Scan(&dynamodb.ScanInput{
		TableName: aws.String(table),
	})
	if err != nil {
		return []string{}, errors.Wrapf(err, "Failed to retrieve items from DynamoDB table. table=%s", table)
	}

	nsmap := map[string]bool{}

	for _, item := range resp.Items {
		nsmap[*item["namespace"].S] = true
	}

	namespaces := []string{}

	for k := range nsmap {
		namespaces = append(namespaces, k)
	}

	sort.Strings(namespaces)

	return namespaces, nil
}

// TableExists check whether the given table exists or not
func (c *Client) TableExists(table string) (bool, error) {
	resp, err := c.api.ListTables(&dynamodb.ListTablesInput{})
	if err != nil {
		return false, errors.Wrap(err, "Failed to retrieve DynamoDB tables.")
	}

	for _, tableName := range resp.TableNames {
		if *tableName == table {
			return true, nil
		}
	}

	return false, nil
}
<|endoftext|>


<commit_before>package github

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"testing"

	"github.com/moovweb/gokogiri"
	. "github.com/smartystreets/goconvey/convey"
)

var logger = log.New(os.Stderr, "", 0)

type item struct {
	Type    string
	Name    string
	Payload []*payloadItem
}

const (
	stateBegin = iota
	stateEventName
	statePayload
	stateHookName
)

const (
	idxKey = iota
	idxType
	idxDescription
)

type payloadItem struct {
	Key         string
	Type        string
	Description string
}

func parseEventTypes(b []byte) ([]*item, error) {
	doc, e := gokogiri.ParseHtml(b)
	if e != nil {
		return nil, e
	}
	nodes, e := doc.Search("//div[@class='content']")
	if e != nil {
		return nil, e
	}
	if len(nodes) != 1 {
		return nil, fmt.Errorf("expected 1 content, found %d", len(nodes))
	}

	c := nodes[0]

	nodes, e = c.Search(".//*")
	if e != nil {
		return nil, e
	}
	i := &item{}
	items := []*item{}
	state := stateBegin
	for _, n := range nodes {
		switch n.Name() {
		case "h2":
			if i.Type != "" {
				items = append(items, i)
			}
			i = &item{Type: n.Content()}
		case "h3":
			switch id := n.Attr("id"); {
			case strings.HasPrefix(id, "event-name"):
				state = stateEventName
			case strings.HasPrefix(id, "payload"):
				state = statePayload
			case strings.HasPrefix(id, "hook-name"):
				state = stateHookName
			}
		case "table":
			if state == statePayload {
				trs, e := n.Search(".//tr")
				if e != nil {
					return nil, e
				}
				if len(trs) > 1 {
					payload := []*payloadItem{}
					for _, tr := range trs[1:] {
						tds, e := tr.Search(".//td")
						if e != nil {
							return nil, e
						}

						p := &payloadItem{}

						for i, td := range tds {
							c := strings.TrimSpace(td.Content())
							switch i {
							case idxKey:
								p.Key = c
							case idxType:
								p.Type = c
							case idxDescription:
								p.Description = c
							}

						}
						payload = append(payload, p)
					}
					if i != nil {
						i.Payload = payload
					}
				}
			}
		case "p":
			switch state {
			case stateEventName:
				i.Name = n.Content()
				state = stateBegin
			}
		}
	}
	return items, nil
}

func TestParse(t *testing.T) {
	Convey("Parsing", t, func() {
		b := mustRead(t, "event_types.html")
		So(b, ShouldNotBeNil)

		items, e := parseEventTypes(b)
		So(e, ShouldBeNil)
		So(items, ShouldNotBeNil)
		So(len(items), ShouldEqual, 22)

		item := items[0]
		So(item.Type, ShouldEqual, "CommitCommentEvent")
		So(item.Name, ShouldEqual, "commit_comment")

		So(item.Payload, ShouldNotBeNil)
		So(len(item.Payload), ShouldEqual, 1)

		So(item.Payload[0].Key, ShouldEqual, "comment")
		So(item.Payload[0].Type, ShouldEqual, "object")
		So(item.Payload[0].Description, ShouldEqual, "The comment itself.")

		item = items[10]
		So(item.Type, ShouldEqual, "GollumEvent")
		So(item.Name, ShouldEqual, "gollum")

		payload := item.Payload
		So(payload, ShouldNotBeNil)
		So(len(payload), ShouldEqual, 6)

		So(payload[1].Key, ShouldEqual, "pages[][page_name]")
		So(payload[1].Type, ShouldEqual, "string")
		So(payload[1].Description, ShouldEqual, "The name of the page.")

		types := map[string]int{}
		objects := map[string]int{}

		for _, i := range items {
			for _, p := range i.Payload {
				types[p.Type]++
				if p.Type == "object" {
					objects[p.Key]++
				}
			}
		}
		logger.Printf("types=%#v", types)
		logger.Printf("objects=%#v", objects)

	})
}

func mustRead(t *testing.T, name string) []byte {
	b, e := ioutil.ReadFile("fixtures/" + name)
	if e != nil {
		t.Fatal(e)
	}
	return b
}
<commit_msg>remove debug output<commit_after>package github

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"testing"

	"github.com/moovweb/gokogiri"
	. "github.com/smartystreets/goconvey/convey"
)

var logger = log.New(os.Stderr, "", 0)

type item struct {
	Type    string
	Name    string
	Payload []*payloadItem
}

const (
	stateBegin = iota
	stateEventName
	statePayload
	stateHookName
)

const (
	idxKey = iota
	idxType
	idxDescription
)

type payloadItem struct {
	Key         string
	Type        string
	Description string
}

func parseEventTypes(b []byte) ([]*item, error) {
	doc, e := gokogiri.ParseHtml(b)
	if e != nil {
		return nil, e
	}
	nodes, e := doc.Search("//div[@class='content']")
	if e != nil {
		return nil, e
	}
	if len(nodes) != 1 {
		return nil, fmt.Errorf("expected 1 content, found %d", len(nodes))
	}

	c := nodes[0]

	nodes, e = c.Search(".//*")
	if e != nil {
		return nil, e
	}
	i := &item{}
	items := []*item{}
	state := stateBegin
	for _, n := range nodes {
		switch n.Name() {
		case "h2":
			if i.Type != "" {
				items = append(items, i)
			}
			i = &item{Type: n.Content()}
		case "h3":
			switch id := n.Attr("id"); {
			case strings.HasPrefix(id, "event-name"):
				state = stateEventName
			case strings.HasPrefix(id, "payload"):
				state = statePayload
			case strings.HasPrefix(id, "hook-name"):
				state = stateHookName
			}
		case "table":
			if state == statePayload {
				trs, e := n.Search(".//tr")
				if e != nil {
					return nil, e
				}
				if len(trs) > 1 {
					payload := []*payloadItem{}
					for _, tr := range trs[1:] {
						tds, e := tr.Search(".//td")
						if e != nil {
							return nil, e
						}

						p := &payloadItem{}

						for i, td := range tds {
							c := strings.TrimSpace(td.Content())
							switch i {
							case idxKey:
								p.Key = c
							case idxType:
								p.Type = c
							case idxDescription:
								p.Description = c
							}

						}
						payload = append(payload, p)
					}
					if i != nil {
						i.Payload = payload
					}
				}
			}
		case "p":
			switch state {
			case stateEventName:
				i.Name = n.Content()
				state = stateBegin
			}
		}
	}
	return items, nil
}

func TestParse(t *testing.T) {
	Convey("Parsing", t, func() {
		b := mustRead(t, "event_types.html")
		So(b, ShouldNotBeNil)

		items, e := parseEventTypes(b)
		So(e, ShouldBeNil)
		So(items, ShouldNotBeNil)
		So(len(items), ShouldEqual, 22)

		item := items[0]
		So(item.Type, ShouldEqual, "CommitCommentEvent")
		So(item.Name, ShouldEqual, "commit_comment")

		So(item.Payload, ShouldNotBeNil)
		So(len(item.Payload), ShouldEqual, 1)

		So(item.Payload[0].Key, ShouldEqual, "comment")
		So(item.Payload[0].Type, ShouldEqual, "object")
		So(item.Payload[0].Description, ShouldEqual, "The comment itself.")

		item = items[10]
		So(item.Type, ShouldEqual, "GollumEvent")
		So(item.Name, ShouldEqual, "gollum")

		payload := item.Payload
		So(payload, ShouldNotBeNil)
		So(len(payload), ShouldEqual, 6)

		So(payload[1].Key, ShouldEqual, "pages[][page_name]")
		So(payload[1].Type, ShouldEqual, "string")
		So(payload[1].Description, ShouldEqual, "The name of the page.")

		types := map[string]int{}
		objects := map[string]int{}

		for _, i := range items {
			for _, p := range i.Payload {
				types[p.Type]++
				if p.Type == "object" {
					objects[p.Key]++
				}
			}
		}
	})
}

func mustRead(t *testing.T, name string) []byte {
	b, e := ioutil.ReadFile("fixtures/" + name)
	if e != nil {
		t.Fatal(e)
	}
	return b
}
<|endoftext|>


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

// MockGen generates mock implementations of Go interfaces.
package main

// TODO: This does not support recursive embedded interfaces.
// TODO: This does not support embedding package-local interfaces in a separate file.

import (
	"bytes"
	"flag"
	"fmt"
	"go/format"
	"go/token"
	"io"
	"log"
	"os"
	"path"
	"strconv"
	"strings"
	"unicode"

	"github.com/golang/mock/mockgen/model"
)

const (
	gomockImportPath = "github.com/golang/mock/gomock"
)

var (
	source      = flag.String("source", "", "(source mode) Input Go source file; enables source mode.")
	destination = flag.String("destination", "", "Output file; defaults to stdout.")
	packageOut  = flag.String("package", "", "Package of the generated code; defaults to the package of the input with a 'mock_' prefix.")
	selfPackage = flag.String("self_package", "", "If set, the package this mock will be part of.")

	debugParser = flag.Bool("debug_parser", false, "Print out parser results only.")
)

func main() {
	flag.Usage = usage
	flag.Parse()

	var pkg *model.Package
	var err error
	if *source != "" {
		pkg, err = ParseFile(*source)
	} else {
		if flag.NArg() != 2 {
			log.Fatal("Expected exactly two arguments")
		}
		pkg, err = Reflect(flag.Arg(0), strings.Split(flag.Arg(1), ","))
	}
	if err != nil {
		log.Fatalf("Loading input failed: %v", err)
	}

	if *debugParser {
		pkg.Print(os.Stdout)
		return
	}

	dst := os.Stdout
	if len(*destination) > 0 {
		f, err := os.Create(*destination)
		if err != nil {
			log.Fatalf("Failed opening destination file: %v", err)
		}
		defer f.Close()
		dst = f
	}

	packageName := *packageOut
	if packageName == "" {
		// pkg.Name in reflect mode is the base name of the import path,
		// which might have characters that are illegal to have in package names.
		packageName = "mock_" + sanitize(pkg.Name)
	}

	g := new(generator)
	if *source != "" {
		g.filename = *source
	} else {
		g.srcPackage = flag.Arg(0)
		g.srcInterfaces = flag.Arg(1)
	}
	if err := g.Generate(pkg, packageName); err != nil {
		log.Fatalf("Failed generating mock: %v", err)
	}
	if _, err := dst.Write(g.Output()); err != nil {
		log.Fatalf("Failed writing to destination: %v", err)
	}
}

func usage() {
	io.WriteString(os.Stderr, usageText)
	flag.PrintDefaults()
}

const usageText = `mockgen has two modes of operation: source and reflect.

Source mode generates mock interfaces from a source file.
It is enabled by using the -source flag. Other flags that
may be useful in this mode are -imports and -aux_files.
Example:
	mockgen -source=foo.go [other options]

Reflect mode generates mock interfaces by building a program
that uses reflection to understand interfaces. It is enabled
by passing two non-flag arguments: an import path, and a
comma-separated list of symbols.
Example:
	mockgen database/sql/driver Conn,Driver

`

type generator struct {
	buf    bytes.Buffer
	indent string

	filename                  string // may be empty
	srcPackage, srcInterfaces string // may be empty

	packageMap map[string]string // map from import path to package name
}

func (g *generator) p(format string, args ...interface{}) {
	fmt.Fprintf(&g.buf, g.indent+format+"\n", args...)
}

func (g *generator) in() {
	g.indent += "\t"
}

func (g *generator) out() {
	if len(g.indent) > 0 {
		g.indent = g.indent[0 : len(g.indent)-1]
	}
}

func removeDot(s string) string {
	if len(s) > 0 && s[len(s)-1] == '.' {
		return s[0 : len(s)-1]
	}
	return s
}

// sanitize cleans up a string to make a suitable package name.
func sanitize(s string) string {
	t := ""
	for _, r := range s {
		if t == "" {
			if unicode.IsLetter(r) || r == '_' {
				t += string(r)
				continue
			}
		} else {
			if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' {
				t += string(r)
				continue
			}
		}
		t += "_"
	}
	if t == "_" {
		t = "x"
	}
	return t
}

func (g *generator) Generate(pkg *model.Package, pkgName string) error {
	g.p("// Automatically generated by MockGen. DO NOT EDIT!")
	if g.filename != "" {
		g.p("// Source: %v", g.filename)
	} else {
		g.p("// Source: %v (interfaces: %v)", g.srcPackage, g.srcInterfaces)
	}
	g.p("")

	// Get all required imports, and generate unique names for them all.
	im := pkg.Imports()
	im[gomockImportPath] = true
	g.packageMap = make(map[string]string, len(im))
	localNames := make(map[string]bool, len(im))
	for pth := range im {
		base := sanitize(path.Base(pth))

		// Local names for an imported package can usually be the basename of the import path.
		// A couple of situations don't permit that, such as duplicate local names
		// (e.g. importing "html/template" and "text/template"), or where the basename is
		// a keyword (e.g. "foo/case").
		// try base0, base1, ...
		pkgName := base
		i := 0
		for localNames[pkgName] || token.Lookup(pkgName).IsKeyword() {
			pkgName = base + strconv.Itoa(i)
			i++
		}

		g.packageMap[pth] = pkgName
		localNames[pkgName] = true
	}

	g.p("package %v", pkgName)
	g.p("")
	g.p("import (")
	g.in()
	for path, pkg := range g.packageMap {
		if path == *selfPackage {
			continue
		}
		g.p("%v %q", pkg, path)
	}
	for _, path := range pkg.DotImports {
		g.p(". %q", path)
	}
	g.out()
	g.p(")")

	for _, intf := range pkg.Interfaces {
		if err := g.GenerateMockInterface(intf); err != nil {
			return err
		}
	}

	return nil
}

// The name of the mock type to use for the given interface identifier.
func mockName(typeName string) string {
	return "Mock" + typeName
}

func (g *generator) GenerateMockInterface(intf *model.Interface) error {
	mockType := mockName(intf.Name)

	g.p("")
	g.p("// Mock of %v interface", intf.Name)
	g.p("type %v struct {", mockType)
	g.in()
	g.p("ctrl     *gomock.Controller")
	g.p("recorder *_%vRecorder", mockType)
	g.out()
	g.p("}")
	g.p("")

	g.p("// Recorder for %v (not exported)", mockType)
	g.p("type _%vRecorder struct {", mockType)
	g.in()
	g.p("mock *%v", mockType)
	g.out()
	g.p("}")
	g.p("")

	// TODO: Re-enable this if we can import the interface reliably.
	//g.p("// Verify that the mock satisfies the interface at compile time.")
	//g.p("var _ %v = (*%v)(nil)", typeName, mockType)
	//g.p("")

	g.p("func New%v(ctrl *gomock.Controller) *%v {", mockType, mockType)
	g.in()
	g.p("mock := &%v{ctrl: ctrl}", mockType)
	g.p("mock.recorder = &_%vRecorder{mock}", mockType)
	g.p("return mock")
	g.out()
	g.p("}")
	g.p("")

	// XXX: possible name collision here if someone has EXPECT in their interface.
	g.p("func (_m *%v) EXPECT() *_%vRecorder {", mockType, mockType)
	g.in()
	g.p("return _m.recorder")
	g.out()
	g.p("}")

	g.GenerateMockMethods(mockType, intf, *selfPackage)

	return nil
}

func (g *generator) GenerateMockMethods(mockType string, intf *model.Interface, pkgOverride string) {
	for _, m := range intf.Methods {
		g.p("")
		g.GenerateMockMethod(mockType, m, pkgOverride)
		g.p("")
		g.GenerateMockRecorderMethod(mockType, m)
	}
}

// GenerateMockMethod generates a mock method implementation.
// If non-empty, pkgOverride is the package in which unqualified types reside.
func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOverride string) error {
	args := make([]string, len(m.In))
	argNames := make([]string, len(m.In))
	for i, p := range m.In {
		name := p.Name
		if name == "" {
			name = fmt.Sprintf("_param%d", i)
		}
		ts := p.Type.String(g.packageMap, pkgOverride)
		args[i] = name + " " + ts
		argNames[i] = name
	}
	if m.Variadic != nil {
		name := m.Variadic.Name
		if name == "" {
			name = fmt.Sprintf("_param%d", len(m.In))
		}
		ts := m.Variadic.Type.String(g.packageMap, pkgOverride)
		args = append(args, name+" ..."+ts)
		argNames = append(argNames, name)
	}
	argString := strings.Join(args, ", ")

	rets := make([]string, len(m.Out))
	for i, p := range m.Out {
		rets[i] = p.Type.String(g.packageMap, pkgOverride)
	}
	retString := strings.Join(rets, ", ")
	if len(rets) > 1 {
		retString = "(" + retString + ")"
	}
	if retString != "" {
		retString = " " + retString
	}

	g.p("func (_m *%v) %v(%v)%v {", mockType, m.Name, argString, retString)
	g.in()

	callArgs := strings.Join(argNames, ", ")
	if callArgs != "" {
		callArgs = ", " + callArgs
	}
	if m.Variadic != nil {
		// Non-trivial. The generated code must build a []interface{},
		// but the variadic argument may be any type.
		g.p("_s := []interface{}{%s}", strings.Join(argNames[:len(argNames)-1], ", "))
		g.p("for _, _x := range %s {", argNames[len(argNames)-1])
		g.in()
		g.p("_s = append(_s, _x)")
		g.out()
		g.p("}")
		callArgs = ", _s..."
	}
	if len(m.Out) == 0 {
		g.p(`_m.ctrl.Call(_m, "%v"%v)`, m.Name, callArgs)
	} else {
		g.p(`ret := _m.ctrl.Call(_m, "%v"%v)`, m.Name, callArgs)

		// Go does not allow "naked" type assertions on nil values, so we use the two-value form here.
		// The value of that is either (x.(T), true) or (Z, false), where Z is the zero value for T.
		// Happily, this coincides with the semantics we want here.
		retNames := make([]string, len(rets))
		for i, t := range rets {
			retNames[i] = fmt.Sprintf("ret%d", i)
			g.p("%s, _ := ret[%d].(%s)", retNames[i], i, t)
		}
		g.p("return " + strings.Join(retNames, ", "))
	}

	g.out()
	g.p("}")
	return nil
}

func (g *generator) GenerateMockRecorderMethod(mockType string, m *model.Method) error {
	nargs := len(m.In)
	args := make([]string, nargs)
	for i := 0; i < nargs; i++ {
		args[i] = "arg" + strconv.Itoa(i)
	}
	argString := strings.Join(args, ", ")
	if nargs > 0 {
		argString += " interface{}"
	}
	if m.Variadic != nil {
		if nargs > 0 {
			argString += ", "
		}
		argString += fmt.Sprintf("arg%d ...interface{}", nargs)
	}

	g.p("func (_mr *_%vRecorder) %v(%v) *gomock.Call {", mockType, m.Name, argString)
	g.in()

	callArgs := strings.Join(args, ", ")
	if nargs > 0 {
		callArgs = ", " + callArgs
	}
	if m.Variadic != nil {
		if nargs == 0 {
			// Easy: just use ... to push the arguments through.
			callArgs = ", arg0..."
		} else {
			// Hard: create a temporary slice.
			g.p("_s := append([]interface{}{%s}, arg%d...)", strings.Join(args, ", "), nargs)
			callArgs = ", _s..."
		}
	}
	g.p(`return _mr.mock.ctrl.RecordCall(_mr.mock, "%v"%v)`, m.Name, callArgs)

	g.out()
	g.p("}")
	return nil
}

// Output returns the generator's output, formatted in the standard Go style.
func (g *generator) Output() []byte {
	src, err := format.Source(g.buf.Bytes())
	if err != nil {
		log.Fatalf("Failed to format generated source code: %s\n%s", err, g.buf.String())
	}
	return src
}
<commit_msg>Add mock_prefix flag to specify custom mocked function names<commit_after>// Copyright 2010 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// MockGen generates mock implementations of Go interfaces.
package main

// TODO: This does not support recursive embedded interfaces.
// TODO: This does not support embedding package-local interfaces in a separate file.

import (
	"bytes"
	"flag"
	"fmt"
	"go/format"
	"go/token"
	"io"
	"log"
	"os"
	"path"
	"strconv"
	"strings"
	"unicode"

	"github.com/golang/mock/mockgen/model"
)

const (
	gomockImportPath = "github.com/golang/mock/gomock"
)

var (
	source      = flag.String("source", "", "(source mode) Input Go source file; enables source mode.")
	destination = flag.String("destination", "", "Output file; defaults to stdout.")
	packageOut  = flag.String("package", "", "Package of the generated code; defaults to the package of the input with a 'mock_' prefix.")
	selfPackage = flag.String("self_package", "", "If set, the package this mock will be part of.")
	mockPrefix  = flag.String("mock_prefix", "", "If set, adds prefix to the mocked function names.")

	debugParser = flag.Bool("debug_parser", false, "Print out parser results only.")
)

func main() {
	flag.Usage = usage
	flag.Parse()

	var pkg *model.Package
	var err error
	if *source != "" {
		pkg, err = ParseFile(*source)
	} else {
		if flag.NArg() != 2 {
			log.Fatal("Expected exactly two arguments")
		}
		pkg, err = Reflect(flag.Arg(0), strings.Split(flag.Arg(1), ","))
	}
	if err != nil {
		log.Fatalf("Loading input failed: %v", err)
	}

	if *debugParser {
		pkg.Print(os.Stdout)
		return
	}

	dst := os.Stdout
	if len(*destination) > 0 {
		f, err := os.Create(*destination)
		if err != nil {
			log.Fatalf("Failed opening destination file: %v", err)
		}
		defer f.Close()
		dst = f
	}

	packageName := *packageOut
	if packageName == "" {
		// pkg.Name in reflect mode is the base name of the import path,
		// which might have characters that are illegal to have in package names.
		packageName = "mock_" + sanitize(pkg.Name)
	}

	g := new(generator)
	if *source != "" {
		g.filename = *source
	} else {
		g.srcPackage = flag.Arg(0)
		g.srcInterfaces = flag.Arg(1)
	}
	if err := g.Generate(pkg, packageName); err != nil {
		log.Fatalf("Failed generating mock: %v", err)
	}
	if _, err := dst.Write(g.Output()); err != nil {
		log.Fatalf("Failed writing to destination: %v", err)
	}
}

func usage() {
	io.WriteString(os.Stderr, usageText)
	flag.PrintDefaults()
}

const usageText = `mockgen has two modes of operation: source and reflect.

Source mode generates mock interfaces from a source file.
It is enabled by using the -source flag. Other flags that
may be useful in this mode are -imports and -aux_files.
Example:
	mockgen -source=foo.go [other options]

Reflect mode generates mock interfaces by building a program
that uses reflection to understand interfaces. It is enabled
by passing two non-flag arguments: an import path, and a
comma-separated list of symbols.
Example:
	mockgen database/sql/driver Conn,Driver

`

type generator struct {
	buf    bytes.Buffer
	indent string

	filename                  string // may be empty
	srcPackage, srcInterfaces string // may be empty

	packageMap map[string]string // map from import path to package name
}

func (g *generator) p(format string, args ...interface{}) {
	fmt.Fprintf(&g.buf, g.indent+format+"\n", args...)
}

func (g *generator) in() {
	g.indent += "\t"
}

func (g *generator) out() {
	if len(g.indent) > 0 {
		g.indent = g.indent[0 : len(g.indent)-1]
	}
}

func removeDot(s string) string {
	if len(s) > 0 && s[len(s)-1] == '.' {
		return s[0 : len(s)-1]
	}
	return s
}

// sanitize cleans up a string to make a suitable package name.
func sanitize(s string) string {
	t := ""
	for _, r := range s {
		if t == "" {
			if unicode.IsLetter(r) || r == '_' {
				t += string(r)
				continue
			}
		} else {
			if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' {
				t += string(r)
				continue
			}
		}
		t += "_"
	}
	if t == "_" {
		t = "x"
	}
	return t
}

func (g *generator) Generate(pkg *model.Package, pkgName string) error {
	g.p("// Automatically generated by MockGen. DO NOT EDIT!")
	if g.filename != "" {
		g.p("// Source: %v", g.filename)
	} else {
		g.p("// Source: %v (interfaces: %v)", g.srcPackage, g.srcInterfaces)
	}
	g.p("")

	// Get all required imports, and generate unique names for them all.
	im := pkg.Imports()
	im[gomockImportPath] = true
	g.packageMap = make(map[string]string, len(im))
	localNames := make(map[string]bool, len(im))
	for pth := range im {
		base := sanitize(path.Base(pth))

		// Local names for an imported package can usually be the basename of the import path.
		// A couple of situations don't permit that, such as duplicate local names
		// (e.g. importing "html/template" and "text/template"), or where the basename is
		// a keyword (e.g. "foo/case").
		// try base0, base1, ...
		pkgName := base
		i := 0
		for localNames[pkgName] || token.Lookup(pkgName).IsKeyword() {
			pkgName = base + strconv.Itoa(i)
			i++
		}

		g.packageMap[pth] = pkgName
		localNames[pkgName] = true
	}

	g.p("package %v", pkgName)
	g.p("")
	g.p("import (")
	g.in()
	for path, pkg := range g.packageMap {
		if path == *selfPackage {
			continue
		}
		g.p("%v %q", pkg, path)
	}
	for _, path := range pkg.DotImports {
		g.p(". %q", path)
	}
	g.out()
	g.p(")")

	for _, intf := range pkg.Interfaces {
		if err := g.GenerateMockInterface(intf); err != nil {
			return err
		}
	}

	return nil
}

// The name of the mock type to use for the given interface identifier.
func mockName(typeName string) string {
	return "Mock" + *mockPrefix + typeName
}

func (g *generator) GenerateMockInterface(intf *model.Interface) error {
	mockType := mockName(intf.Name)

	g.p("")
	g.p("// Mock of %v interface", intf.Name)
	g.p("type %v struct {", mockType)
	g.in()
	g.p("ctrl     *gomock.Controller")
	g.p("recorder *_%vRecorder", mockType)
	g.out()
	g.p("}")
	g.p("")

	g.p("// Recorder for %v (not exported)", mockType)
	g.p("type _%vRecorder struct {", mockType)
	g.in()
	g.p("mock *%v", mockType)
	g.out()
	g.p("}")
	g.p("")

	// TODO: Re-enable this if we can import the interface reliably.
	//g.p("// Verify that the mock satisfies the interface at compile time.")
	//g.p("var _ %v = (*%v)(nil)", typeName, mockType)
	//g.p("")

	g.p("func New%v(ctrl *gomock.Controller) *%v {", mockType, mockType)
	g.in()
	g.p("mock := &%v{ctrl: ctrl}", mockType)
	g.p("mock.recorder = &_%vRecorder{mock}", mockType)
	g.p("return mock")
	g.out()
	g.p("}")
	g.p("")

	// XXX: possible name collision here if someone has EXPECT in their interface.
	g.p("func (_m *%v) EXPECT() *_%vRecorder {", mockType, mockType)
	g.in()
	g.p("return _m.recorder")
	g.out()
	g.p("}")

	g.GenerateMockMethods(mockType, intf, *selfPackage)

	return nil
}

func (g *generator) GenerateMockMethods(mockType string, intf *model.Interface, pkgOverride string) {
	for _, m := range intf.Methods {
		g.p("")
		g.GenerateMockMethod(mockType, m, pkgOverride)
		g.p("")
		g.GenerateMockRecorderMethod(mockType, m)
	}
}

// GenerateMockMethod generates a mock method implementation.
// If non-empty, pkgOverride is the package in which unqualified types reside.
func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOverride string) error {
	args := make([]string, len(m.In))
	argNames := make([]string, len(m.In))
	for i, p := range m.In {
		name := p.Name
		if name == "" {
			name = fmt.Sprintf("_param%d", i)
		}
		ts := p.Type.String(g.packageMap, pkgOverride)
		args[i] = name + " " + ts
		argNames[i] = name
	}
	if m.Variadic != nil {
		name := m.Variadic.Name
		if name == "" {
			name = fmt.Sprintf("_param%d", len(m.In))
		}
		ts := m.Variadic.Type.String(g.packageMap, pkgOverride)
		args = append(args, name+" ..."+ts)
		argNames = append(argNames, name)
	}
	argString := strings.Join(args, ", ")

	rets := make([]string, len(m.Out))
	for i, p := range m.Out {
		rets[i] = p.Type.String(g.packageMap, pkgOverride)
	}
	retString := strings.Join(rets, ", ")
	if len(rets) > 1 {
		retString = "(" + retString + ")"
	}
	if retString != "" {
		retString = " " + retString
	}

	g.p("func (_m *%v) %v(%v)%v {", mockType, m.Name, argString, retString)
	g.in()

	callArgs := strings.Join(argNames, ", ")
	if callArgs != "" {
		callArgs = ", " + callArgs
	}
	if m.Variadic != nil {
		// Non-trivial. The generated code must build a []interface{},
		// but the variadic argument may be any type.
		g.p("_s := []interface{}{%s}", strings.Join(argNames[:len(argNames)-1], ", "))
		g.p("for _, _x := range %s {", argNames[len(argNames)-1])
		g.in()
		g.p("_s = append(_s, _x)")
		g.out()
		g.p("}")
		callArgs = ", _s..."
	}
	if len(m.Out) == 0 {
		g.p(`_m.ctrl.Call(_m, "%v"%v)`, m.Name, callArgs)
	} else {
		g.p(`ret := _m.ctrl.Call(_m, "%v"%v)`, m.Name, callArgs)

		// Go does not allow "naked" type assertions on nil values, so we use the two-value form here.
		// The value of that is either (x.(T), true) or (Z, false), where Z is the zero value for T.
		// Happily, this coincides with the semantics we want here.
		retNames := make([]string, len(rets))
		for i, t := range rets {
			retNames[i] = fmt.Sprintf("ret%d", i)
			g.p("%s, _ := ret[%d].(%s)", retNames[i], i, t)
		}
		g.p("return " + strings.Join(retNames, ", "))
	}

	g.out()
	g.p("}")
	return nil
}

func (g *generator) GenerateMockRecorderMethod(mockType string, m *model.Method) error {
	nargs := len(m.In)
	args := make([]string, nargs)
	for i := 0; i < nargs; i++ {
		args[i] = "arg" + strconv.Itoa(i)
	}
	argString := strings.Join(args, ", ")
	if nargs > 0 {
		argString += " interface{}"
	}
	if m.Variadic != nil {
		if nargs > 0 {
			argString += ", "
		}
		argString += fmt.Sprintf("arg%d ...interface{}", nargs)
	}

	g.p("func (_mr *_%vRecorder) %v(%v) *gomock.Call {", mockType, m.Name, argString)
	g.in()

	callArgs := strings.Join(args, ", ")
	if nargs > 0 {
		callArgs = ", " + callArgs
	}
	if m.Variadic != nil {
		if nargs == 0 {
			// Easy: just use ... to push the arguments through.
			callArgs = ", arg0..."
		} else {
			// Hard: create a temporary slice.
			g.p("_s := append([]interface{}{%s}, arg%d...)", strings.Join(args, ", "), nargs)
			callArgs = ", _s..."
		}
	}
	g.p(`return _mr.mock.ctrl.RecordCall(_mr.mock, "%v"%v)`, m.Name, callArgs)

	g.out()
	g.p("}")
	return nil
}

// Output returns the generator's output, formatted in the standard Go style.
func (g *generator) Output() []byte {
	src, err := format.Source(g.buf.Bytes())
	if err != nil {
		log.Fatalf("Failed to format generated source code: %s\n%s", err, g.buf.String())
	}
	return src
}
<|endoftext|>


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

package backend

import (
	"fmt"
	"html/template"
	"net/http"
	"path"
	"strconv"
	"time"
)

const (
	AMP_LIVE_LIST_COOKIE_NAME = "ABE_AMP_LIVE_LIST_STATUS"
	MAX_AGE_IN_SECONDS        = 1
	DIST_FOLDER               = "dist"
	SAMPLE_AMPS_FOLDER        = "sample_amps"
	COMPONENTS_FOLDER         = "components"
	MINUS_FIFTEEN_SECONDS     = -15
)

type BlogItem struct {
	Text              string
	Image             string
	Timestamp         string
	Date              string
	ID                string
	Heading           string
	MetadataTimestamp string
}

func (blogItem BlogItem) cloneWith(id int, timestamp time.Time) BlogItem {
	return createBlogEntry(blogItem.Heading, blogItem.Text, blogItem.Image, timestamp, id)
}

type Score struct {
	Timestamp  string
	ScoreTeam1 int
	ScoreTeam2 int
}

type Page struct {
	BlogItems     []BlogItem
	FootballScore Score
}

var blogs []BlogItem

func InitAmpLiveList() {
	blogs = make([]BlogItem, 0)
	blogs = append(blogs,
		createBlogEntryWithTimeNow("Green landscape", "A green landscape with a house and trees.", "/img/landscape_hills_1280x853.jpg", 1),
		createBlogEntryWithTimeNow("Mountains", "Mountains reflecting on a lake.", "/img/landscape_mountains_1280x853.jpg", 2),
		createBlogEntryWithTimeNow("Road leading to a lake", "A road leading to a lake with mountains on the back.", "/img/landscape_lake_1280x853.jpg", 3),
		createBlogEntryWithTimeNow("Forested hills", "Forested hills with a blue sky in the background.", "/img/landscape_trees_1280x823.jpg", 4),
		createBlogEntryWithTimeNow("Scattered houses", "Scattered houses in a mountain village.", "/img/landscape_village_1280x720.jpg", 5),
		createBlogEntryWithTimeNow("Canyon", "A deep canyon at sunset.", "/img/landscape_canyon_1280x853.jpg", 6),
		createBlogEntryWithTimeNow("Desert", "A desert with mountains in the background.", "/img/landscape_desert_1280x606.jpg", 7),
		createBlogEntryWithTimeNow("Houses", "Colorful one floor houses on a street.", "/img/landscape_houses_1280x858.jpg", 8),
		createBlogEntryWithTimeNow("Blue sea", "Blue sea surrounding a cave.", "/img/landscape_sea_1280_853.jpg", 9),
		createBlogEntryWithTimeNow("Sailing ship", "A ship sailing the sea at sunset.", "/img/landscape_ship_1280_853.jpg", 10))

	registerHandler(SAMPLE_AMPS_FOLDER, "live_blog")
	registerHandler(SAMPLE_AMPS_FOLDER, "live_blog/preview")
	registerHandler(COMPONENTS_FOLDER, "amp-live-list")

}

func registerHandler(sampleType string, sampleName string) {

	url := path.Join("/", sampleType, sampleName) + "/"
	filePath := path.Join(DIST_FOLDER, sampleType, sampleName, "index.html")

	http.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
		renderSample(w, r, filePath)
	})
}

func createBlogEntryWithTimeNow(heading string, text string, imagePath string, id int) BlogItem {
	var now = time.Now()
	return createBlogEntry(heading, text, imagePath, now, id)
}

func createBlogEntry(heading string, text string, imagePath string, time time.Time, id int) BlogItem {
	return BlogItem{Text: text,
		Image:             imagePath,
		Timestamp:         time.Format("20060102150405"),
		Date:              time.Format("15:04:05"),
		ID:                "post" + strconv.Itoa(id),
		Heading:           heading,
		MetadataTimestamp: time.Format("2006-01-02T15:04:05.999999-07:00")}
}

func updateStatus(w http.ResponseWriter, r *http.Request) int {
	newStatus := readStatus(r) + 1
	writeStatus(w, newStatus)
	return newStatus
}

func readStatus(r *http.Request) int {
	cookie, err := r.Cookie(AMP_LIVE_LIST_COOKIE_NAME)
	if err != nil {
		return 0
	}
	result, _ := strconv.Atoi(cookie.Value)
	return result
}

func createPage(newStatus int, timestamp time.Time) Page {
	if newStatus > len(blogs) {
		newStatus = len(blogs)
	}
	blogItems := getBlogEntries(newStatus, timestamp)
	score := createScore(newStatus, 0)
	return Page{BlogItems: blogItems, FootballScore: score}
}

func renderSample(w http.ResponseWriter, r *http.Request, filePath string) {
	t, _ := template.ParseFiles(filePath)
	w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%d, public, must-revalidate", MAX_AGE_IN_SECONDS))
	newStatus := updateStatus(w, r)
	t.Execute(w, createPage(newStatus, time.Now()))
}

func getBlogEntries(size int, timestamp time.Time) []BlogItem {
	result := make([]BlogItem, 0)
	for i := 0; i < size; i++ {
		result = append(result, blogs[i].cloneWith(i+1, timestamp.Add(time.Duration(MINUS_FIFTEEN_SECONDS*(size-i))*time.Second)))
	}
	return result
}

func createScore(scoreTeam1 int, scoreTeam2 int) Score {
	return Score{Timestamp: currentTimestamp(), ScoreTeam1: scoreTeam1, ScoreTeam2: scoreTeam2}
}

func currentTimestamp() string {
	return time.Now().Format("20060102150405")
}

func writeStatus(w http.ResponseWriter, newValue int) {
	expireInOneDay := time.Now().AddDate(0, 0, 1)
	cookie := &http.Cookie{
		Name:    AMP_LIVE_LIST_COOKIE_NAME,
		Expires: expireInOneDay,
		Value:   strconv.Itoa(newValue),
	}
	http.SetCookie(w, cookie)
}
<commit_msg>fix live blog category<commit_after>// Copyright Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package backend

import (
	"fmt"
	"html/template"
	"net/http"
	"path"
	"strconv"
	"time"
)

const (
	AMP_LIVE_LIST_COOKIE_NAME = "ABE_AMP_LIVE_LIST_STATUS"
	MAX_AGE_IN_SECONDS        = 1
	DIST_FOLDER               = "dist"
	SAMPLE_AMPS_FOLDER        = "samples_templates"
	COMPONENTS_FOLDER         = "components"
	MINUS_FIFTEEN_SECONDS     = -15
)

type BlogItem struct {
	Text              string
	Image             string
	Timestamp         string
	Date              string
	ID                string
	Heading           string
	MetadataTimestamp string
}

func (blogItem BlogItem) cloneWith(id int, timestamp time.Time) BlogItem {
	return createBlogEntry(blogItem.Heading, blogItem.Text, blogItem.Image, timestamp, id)
}

type Score struct {
	Timestamp  string
	ScoreTeam1 int
	ScoreTeam2 int
}

type Page struct {
	BlogItems     []BlogItem
	FootballScore Score
}

var blogs []BlogItem

func InitAmpLiveList() {
	blogs = make([]BlogItem, 0)
	blogs = append(blogs,
		createBlogEntryWithTimeNow("Green landscape", "A green landscape with a house and trees.", "/img/landscape_hills_1280x853.jpg", 1),
		createBlogEntryWithTimeNow("Mountains", "Mountains reflecting on a lake.", "/img/landscape_mountains_1280x853.jpg", 2),
		createBlogEntryWithTimeNow("Road leading to a lake", "A road leading to a lake with mountains on the back.", "/img/landscape_lake_1280x853.jpg", 3),
		createBlogEntryWithTimeNow("Forested hills", "Forested hills with a blue sky in the background.", "/img/landscape_trees_1280x823.jpg", 4),
		createBlogEntryWithTimeNow("Scattered houses", "Scattered houses in a mountain village.", "/img/landscape_village_1280x720.jpg", 5),
		createBlogEntryWithTimeNow("Canyon", "A deep canyon at sunset.", "/img/landscape_canyon_1280x853.jpg", 6),
		createBlogEntryWithTimeNow("Desert", "A desert with mountains in the background.", "/img/landscape_desert_1280x606.jpg", 7),
		createBlogEntryWithTimeNow("Houses", "Colorful one floor houses on a street.", "/img/landscape_houses_1280x858.jpg", 8),
		createBlogEntryWithTimeNow("Blue sea", "Blue sea surrounding a cave.", "/img/landscape_sea_1280_853.jpg", 9),
		createBlogEntryWithTimeNow("Sailing ship", "A ship sailing the sea at sunset.", "/img/landscape_ship_1280_853.jpg", 10))

	registerHandler(SAMPLE_AMPS_FOLDER, "live_blog")
	registerHandler(SAMPLE_AMPS_FOLDER, "live_blog/preview")
	registerHandler(COMPONENTS_FOLDER, "amp-live-list")

}

func registerHandler(sampleType string, sampleName string) {

	url := path.Join("/", sampleType, sampleName) + "/"
	filePath := path.Join(DIST_FOLDER, sampleType, sampleName, "index.html")

	http.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
		renderSample(w, r, filePath)
	})
}

func createBlogEntryWithTimeNow(heading string, text string, imagePath string, id int) BlogItem {
	var now = time.Now()
	return createBlogEntry(heading, text, imagePath, now, id)
}

func createBlogEntry(heading string, text string, imagePath string, time time.Time, id int) BlogItem {
	return BlogItem{Text: text,
		Image:             imagePath,
		Timestamp:         time.Format("20060102150405"),
		Date:              time.Format("15:04:05"),
		ID:                "post" + strconv.Itoa(id),
		Heading:           heading,
		MetadataTimestamp: time.Format("2006-01-02T15:04:05.999999-07:00")}
}

func updateStatus(w http.ResponseWriter, r *http.Request) int {
	newStatus := readStatus(r) + 1
	writeStatus(w, newStatus)
	return newStatus
}

func readStatus(r *http.Request) int {
	cookie, err := r.Cookie(AMP_LIVE_LIST_COOKIE_NAME)
	if err != nil {
		return 0
	}
	result, _ := strconv.Atoi(cookie.Value)
	return result
}

func createPage(newStatus int, timestamp time.Time) Page {
	if newStatus > len(blogs) {
		newStatus = len(blogs)
	}
	blogItems := getBlogEntries(newStatus, timestamp)
	score := createScore(newStatus, 0)
	return Page{BlogItems: blogItems, FootballScore: score}
}

func renderSample(w http.ResponseWriter, r *http.Request, filePath string) {
	t, _ := template.ParseFiles(filePath)
	w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%d, public, must-revalidate", MAX_AGE_IN_SECONDS))
	newStatus := updateStatus(w, r)
	t.Execute(w, createPage(newStatus, time.Now()))
}

func getBlogEntries(size int, timestamp time.Time) []BlogItem {
	result := make([]BlogItem, 0)
	for i := 0; i < size; i++ {
		result = append(result, blogs[i].cloneWith(i+1, timestamp.Add(time.Duration(MINUS_FIFTEEN_SECONDS*(size-i))*time.Second)))
	}
	return result
}

func createScore(scoreTeam1 int, scoreTeam2 int) Score {
	return Score{Timestamp: currentTimestamp(), ScoreTeam1: scoreTeam1, ScoreTeam2: scoreTeam2}
}

func currentTimestamp() string {
	return time.Now().Format("20060102150405")
}

func writeStatus(w http.ResponseWriter, newValue int) {
	expireInOneDay := time.Now().AddDate(0, 0, 1)
	cookie := &http.Cookie{
		Name:    AMP_LIVE_LIST_COOKIE_NAME,
		Expires: expireInOneDay,
		Value:   strconv.Itoa(newValue),
	}
	http.SetCookie(w, cookie)
}
<|endoftext|>


<commit_before>// Copyright 2016 Red Hat, Inc. and/or its affiliates
// and other contributors.
//
// 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 backend
package memory

import (
	"net/url"
	"regexp"

	"github.com/yaacov/mohawk/backend"
)

type TimeValuePair struct {
	timeStamp int64
	value     float64
}

type TimeSeries struct {
	tags map[string]string
	data []TimeValuePair
}

type Tenant struct {
	ts map[string]*TimeSeries
}

type Backend struct {
	timeGranularitySec int64
	timeRetentionSec   int64
	timeLastSec        int64

	tenant map[string]*Tenant
}

// Backend functions
// Required by backend interface

func (r Backend) Name() string {
	return "Backend-Memory"
}

func (r *Backend) Open(options url.Values) {
	// set last entry time
	r.timeLastSec = 0
	// set time granularity to 30 sec
	r.timeGranularitySec = 30
	// set time retention to 7 days
	r.timeRetentionSec = 7 * 24 * 60 * 60

	// open db connection
	r.tenant = make(map[string]*Tenant, 0)
}

func (r Backend) GetTenants() []backend.Tenant {
	res := make([]backend.Tenant, 0)

	// return a list of tenants
	for key, _ := range r.tenant {
		res = append(res, backend.Tenant{Id: key})
	}

	return res
}

func (r Backend) GetItemList(tenant string, tags map[string]string) []backend.Item {
	res := make([]backend.Item, 0)
	t, ok := r.tenant[tenant]

	// check tenant
	if !ok {
		return res
	}

	for key, ts := range t.ts {
		if hasMatchingTag(tags, ts.tags) {
			res = append(res, backend.Item{
				Id:   key,
				Type: "gauge",
				Tags: ts.tags,
			})
		}
	}

	// filter using tags
	// 	if we have a list of _all_ items, we need to filter them by tags
	// 	if the list is already filtered, we do not need to re-filter it
	if len(tags) > 0 {
		for key, value := range tags {
			res = backend.FilterItems(res, func(i backend.Item) bool {
				r, _ := regexp.Compile("^" + value + "$")
				return r.MatchString(i.Tags[key])
			})
		}
	}

	return res
}

func (r *Backend) GetRawData(tenant string, id string, end int64, start int64, limit int64, order string) []backend.DataItem {
	res := make([]backend.DataItem, 0)
	memFirstTime := (r.timeLastSec - r.timeRetentionSec) * 1000
	memLastTime := r.timeLastSec * 1000

	arraySize := r.timeRetentionSec / r.timeGranularitySec
	pStart := r.getPosForTimestamp(start)
	pEnd := r.getPosForTimestamp(end)

	// make sure start and end times is in the retention time
	if start < memFirstTime {
		start = memFirstTime
	}
	if end > memLastTime {
		end = memLastTime + 1
	}

	// sanity check pEnd
	if pEnd <= pStart {
		pEnd += arraySize
	}

	// check if tenant and id exists, create them if necessary
	r.checkID(tenant, id)

	// fill data out array
	count := int64(0)
	for i := pEnd; count < limit && i > pStart; i-- {
		d := r.tenant[tenant].ts[id].data[i%arraySize]

		// if this is a valid point
		if d.timeStamp < end && d.timeStamp >= start {
			count++
			res = append(res, backend.DataItem{
				Timestamp: d.timeStamp,
				Value:     d.value,
			})
		}
	}

	// order
	if order == "ASC" {
		for i := 0; i < len(res)/2; i++ {
			j := len(res) - i - 1
			res[i], res[j] = res[j], res[i]
		}
	}

	return res
}

func (r Backend) GetStatData(tenant string, id string, end int64, start int64, limit int64, order string, bucketDuration int64) []backend.StatItem {
	res := make([]backend.StatItem, 0)
	memFirstTime := (r.timeLastSec - r.timeRetentionSec) * 1000
	memLastTime := r.timeLastSec * 1000

	// make sure start and end times is in the retention time
	if start < memFirstTime {
		start = memFirstTime
	}
	if end > memLastTime {
		end = memLastTime + 1
	}

	// make sure start, end and backetDuration is a multiple of granularity
	bucketDuration = r.timeGranularitySec * (1 + bucketDuration/r.timeGranularitySec)
	start = r.timeGranularitySec * (1 + start/1000/r.timeGranularitySec) * 1000
	end = r.timeGranularitySec * (1 + end/1000/r.timeGranularitySec) * 1000

	arraySize := r.timeRetentionSec / r.timeGranularitySec
	pStep := bucketDuration / r.timeGranularitySec
	pStart := r.getPosForTimestamp(start)
	pEnd := r.getPosForTimestamp(end)

	// sanity check pEnd
	if pEnd <= pStart {
		pEnd += arraySize
	}

	// sanity check step
	if pStep < 1 {
		pStep = 1
	}
	if pStep > (pEnd - pStart) {
		pStep = pEnd - pStart
	}

	startTimestamp := end
	stepMillisec := pStep * r.timeGranularitySec * 1000

	// check if tenant and id exists, create them if necessary
	r.checkID(tenant, id)

	// fill data out array
	count := int64(0)
	for b := pEnd; count < limit && b > pStart && startTimestamp > stepMillisec; b -= pStep {
		samples := int64(0)
		sum := float64(0)
		last := float64(0)

		// loop on all points in bucket
		for i := (b - pStep); i < b; i++ {
			d := r.tenant[tenant].ts[id].data[i%arraySize]
			if d.timeStamp <= end && d.timeStamp > start {
				samples++
				last = d.value
				sum += d.value
			}
		}

		// all points are valid
		startTimestamp -= stepMillisec
		count++

		// all points are valid
		if samples > 0 {
			res = append(res, backend.StatItem{
				Start:   startTimestamp,
				End:     startTimestamp + stepMillisec,
				Empty:   false,
				Samples: samples,
				Min:     0,
				Max:     last,
				Avg:     sum / float64(samples),
				Median:  0,
				Sum:     sum,
			})
		} else {
			count++
			res = append(res, backend.StatItem{
				Start:   startTimestamp,
				End:     startTimestamp + stepMillisec,
				Empty:   true,
				Samples: 0,
				Min:     0,
				Max:     0,
				Avg:     0,
				Median:  0,
				Sum:     0,
			})
		}
	}

	// order
	if order == "ASC" {
		for i := 0; i < len(res)/2; i++ {
			j := len(res) - i - 1
			res[i], res[j] = res[j], res[i]
		}
	}

	return res
}

func (r *Backend) PostRawData(tenant string, id string, t int64, v float64) bool {
	// check if tenant and id exists, create them if necessary
	r.checkID(tenant, id)

	// update time value pair to the time serias
	p := r.getPosForTimestamp(t)
	r.tenant[tenant].ts[id].data[p] = TimeValuePair{timeStamp: t, value: v}

	// update last
	tSec := t / 1000
	if tSec > r.timeLastSec {
		r.timeLastSec = tSec
	}

	return true
}

func (r *Backend) PutTags(tenant string, id string, tags map[string]string) bool {
	// check if tenant and id exists, create them if necessary
	r.checkID(tenant, id)

	// update time serias tags
	if len(tags) > 0 {
		for key, value := range tags {
			r.tenant[tenant].ts[id].tags[key] = value
		}
	}

	return true
}

func (r *Backend) DeleteData(tenant string, id string, end int64, start int64) bool {
	return true
}

func (r *Backend) DeleteTags(tenant string, id string, tags []string) bool {
	return true
}

// Helper functions
// Not required by backend interface

func (r *Backend) getPosForTimestamp(timestamp int64) int64 {
	arraySize := r.timeRetentionSec / r.timeGranularitySec
	arrayPos := timestamp / 1000 / r.timeGranularitySec

	return arrayPos % arraySize
}

func (r *Backend) checkID(tenant string, id string) {
	var ok bool

	// check for tenant
	if _, ok = r.tenant[tenant]; !ok {
		r.tenant[tenant] = &Tenant{ts: make(map[string]*TimeSeries)}
	}

	// check for TimeSeries
	if _, ok = r.tenant[tenant].ts[id]; !ok {
		r.tenant[tenant].ts[id] = &TimeSeries{
			tags: make(map[string]string),
			data: make([]TimeValuePair, r.timeRetentionSec/r.timeGranularitySec),
		}
	}
}

func hasMatchingTag(tags map[string]string, itemTags map[string]string) bool {
	out := true

	// if no tags, all items match
	if len(tags) == 0 {
		return true
	}

	// if item has no tags, item is invalid
	if len(itemTags) == 0 {
		return false
	}

	// loop on all the tags, we need _all_ query tags to match tags on item
	for key, value := range tags {
		r, _ := regexp.Compile("^" + value + "$")
		out = out && r.MatchString(itemTags[key])
	}

	return out
}
<commit_msg>update readme<commit_after>// Copyright 2016 Red Hat, Inc. and/or its affiliates
// and other contributors.
//
// 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 backend
package memory

import (
	"net/url"
	"regexp"

	"github.com/yaacov/mohawk/backend"
)

type TimeValuePair struct {
	timeStamp int64
	value     float64
}

type TimeSeries struct {
	tags map[string]string
	data []TimeValuePair
}

type Tenant struct {
	ts map[string]*TimeSeries
}

type Backend struct {
	timeGranularitySec int64
	timeRetentionSec   int64
	timeLastSec        int64

	tenant map[string]*Tenant
}

// Backend functions
// Required by backend interface

func (r Backend) Name() string {
	return "Backend-Memory"
}

func (r *Backend) Open(options url.Values) {
	// set last entry time
	r.timeLastSec = 0
	// set time granularity to 30 sec
	r.timeGranularitySec = 30
	// set time retention to 7 days
	r.timeRetentionSec = 7 * 24 * 60 * 60

	// open db connection
	r.tenant = make(map[string]*Tenant, 0)
}

func (r Backend) GetTenants() []backend.Tenant {
	res := make([]backend.Tenant, 0)

	// return a list of tenants
	for key := range r.tenant {
		res = append(res, backend.Tenant{Id: key})
	}

	return res
}

func (r Backend) GetItemList(tenant string, tags map[string]string) []backend.Item {
	res := make([]backend.Item, 0)
	t, ok := r.tenant[tenant]

	// check tenant
	if !ok {
		return res
	}

	for key, ts := range t.ts {
		if hasMatchingTag(tags, ts.tags) {
			res = append(res, backend.Item{
				Id:   key,
				Type: "gauge",
				Tags: ts.tags,
			})
		}
	}

	// filter using tags
	// 	if we have a list of _all_ items, we need to filter them by tags
	// 	if the list is already filtered, we do not need to re-filter it
	if len(tags) > 0 {
		for key, value := range tags {
			res = backend.FilterItems(res, func(i backend.Item) bool {
				r, _ := regexp.Compile("^" + value + "$")
				return r.MatchString(i.Tags[key])
			})
		}
	}

	return res
}

func (r *Backend) GetRawData(tenant string, id string, end int64, start int64, limit int64, order string) []backend.DataItem {
	res := make([]backend.DataItem, 0)
	memFirstTime := (r.timeLastSec - r.timeRetentionSec) * 1000
	memLastTime := r.timeLastSec * 1000

	arraySize := r.timeRetentionSec / r.timeGranularitySec
	pStart := r.getPosForTimestamp(start)
	pEnd := r.getPosForTimestamp(end)

	// make sure start and end times is in the retention time
	if start < memFirstTime {
		start = memFirstTime
	}
	if end > memLastTime {
		end = memLastTime + 1
	}

	// sanity check pEnd
	if pEnd <= pStart {
		pEnd += arraySize
	}

	// check if tenant and id exists, create them if necessary
	r.checkID(tenant, id)

	// fill data out array
	count := int64(0)
	for i := pEnd; count < limit && i > pStart; i-- {
		d := r.tenant[tenant].ts[id].data[i%arraySize]

		// if this is a valid point
		if d.timeStamp < end && d.timeStamp >= start {
			count++
			res = append(res, backend.DataItem{
				Timestamp: d.timeStamp,
				Value:     d.value,
			})
		}
	}

	// order
	if order == "ASC" {
		for i := 0; i < len(res)/2; i++ {
			j := len(res) - i - 1
			res[i], res[j] = res[j], res[i]
		}
	}

	return res
}

func (r Backend) GetStatData(tenant string, id string, end int64, start int64, limit int64, order string, bucketDuration int64) []backend.StatItem {
	res := make([]backend.StatItem, 0)
	memFirstTime := (r.timeLastSec - r.timeRetentionSec) * 1000
	memLastTime := r.timeLastSec * 1000

	// make sure start and end times is in the retention time
	if start < memFirstTime {
		start = memFirstTime
	}
	if end > memLastTime {
		end = memLastTime + 1
	}

	// make sure start, end and backetDuration is a multiple of granularity
	bucketDuration = r.timeGranularitySec * (1 + bucketDuration/r.timeGranularitySec)
	start = r.timeGranularitySec * (1 + start/1000/r.timeGranularitySec) * 1000
	end = r.timeGranularitySec * (1 + end/1000/r.timeGranularitySec) * 1000

	arraySize := r.timeRetentionSec / r.timeGranularitySec
	pStep := bucketDuration / r.timeGranularitySec
	pStart := r.getPosForTimestamp(start)
	pEnd := r.getPosForTimestamp(end)

	// sanity check pEnd
	if pEnd <= pStart {
		pEnd += arraySize
	}

	// sanity check step
	if pStep < 1 {
		pStep = 1
	}
	if pStep > (pEnd - pStart) {
		pStep = pEnd - pStart
	}

	startTimestamp := end
	stepMillisec := pStep * r.timeGranularitySec * 1000

	// check if tenant and id exists, create them if necessary
	r.checkID(tenant, id)

	// fill data out array
	count := int64(0)
	for b := pEnd; count < limit && b > pStart && startTimestamp > stepMillisec; b -= pStep {
		samples := int64(0)
		sum := float64(0)
		last := float64(0)

		// loop on all points in bucket
		for i := (b - pStep); i < b; i++ {
			d := r.tenant[tenant].ts[id].data[i%arraySize]
			if d.timeStamp <= end && d.timeStamp > start {
				samples++
				last = d.value
				sum += d.value
			}
		}

		// all points are valid
		startTimestamp -= stepMillisec
		count++

		// all points are valid
		if samples > 0 {
			res = append(res, backend.StatItem{
				Start:   startTimestamp,
				End:     startTimestamp + stepMillisec,
				Empty:   false,
				Samples: samples,
				Min:     0,
				Max:     last,
				Avg:     sum / float64(samples),
				Median:  0,
				Sum:     sum,
			})
		} else {
			count++
			res = append(res, backend.StatItem{
				Start:   startTimestamp,
				End:     startTimestamp + stepMillisec,
				Empty:   true,
				Samples: 0,
				Min:     0,
				Max:     0,
				Avg:     0,
				Median:  0,
				Sum:     0,
			})
		}
	}

	// order
	if order == "ASC" {
		for i := 0; i < len(res)/2; i++ {
			j := len(res) - i - 1
			res[i], res[j] = res[j], res[i]
		}
	}

	return res
}

func (r *Backend) PostRawData(tenant string, id string, t int64, v float64) bool {
	// check if tenant and id exists, create them if necessary
	r.checkID(tenant, id)

	// update time value pair to the time serias
	p := r.getPosForTimestamp(t)
	r.tenant[tenant].ts[id].data[p] = TimeValuePair{timeStamp: t, value: v}

	// update last
	tSec := t / 1000
	if tSec > r.timeLastSec {
		r.timeLastSec = tSec
	}

	return true
}

func (r *Backend) PutTags(tenant string, id string, tags map[string]string) bool {
	// check if tenant and id exists, create them if necessary
	r.checkID(tenant, id)

	// update time serias tags
	if len(tags) > 0 {
		for key, value := range tags {
			r.tenant[tenant].ts[id].tags[key] = value
		}
	}

	return true
}

func (r *Backend) DeleteData(tenant string, id string, end int64, start int64) bool {
	return true
}

func (r *Backend) DeleteTags(tenant string, id string, tags []string) bool {
	return true
}

// Helper functions
// Not required by backend interface

func (r *Backend) getPosForTimestamp(timestamp int64) int64 {
	arraySize := r.timeRetentionSec / r.timeGranularitySec
	arrayPos := timestamp / 1000 / r.timeGranularitySec

	return arrayPos % arraySize
}

func (r *Backend) checkID(tenant string, id string) {
	var ok bool

	// check for tenant
	if _, ok = r.tenant[tenant]; !ok {
		r.tenant[tenant] = &Tenant{ts: make(map[string]*TimeSeries)}
	}

	// check for TimeSeries
	if _, ok = r.tenant[tenant].ts[id]; !ok {
		r.tenant[tenant].ts[id] = &TimeSeries{
			tags: make(map[string]string),
			data: make([]TimeValuePair, r.timeRetentionSec/r.timeGranularitySec),
		}
	}
}

func hasMatchingTag(tags map[string]string, itemTags map[string]string) bool {
	out := true

	// if no tags, all items match
	if len(tags) == 0 {
		return true
	}

	// if item has no tags, item is invalid
	if len(itemTags) == 0 {
		return false
	}

	// loop on all the tags, we need _all_ query tags to match tags on item
	for key, value := range tags {
		r, _ := regexp.Compile("^" + value + "$")
		out = out && r.MatchString(itemTags[key])
	}

	return out
}
<|endoftext|>


<commit_before>package gitmedia

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

const Version = "0.0.1"

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "git-media")
	LocalWorkingDir    string
	LocalGitDir        string
	LocalMediaDir      string
	LocalLogDir        string
)

func TempFile() (*os.File, error) {
	return ioutil.TempFile(TempDir, "")
}

func LocalMediaPath(sha string) string {
	path := filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
	if err := os.MkdirAll(path, 0744); err != nil {
		panic(fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err))
	}

	return filepath.Join(path, sha)
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 4, len(osEnviron)+4)
	env[0] = fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir)
	env[1] = fmt.Sprintf("LocalGitDir=%s", LocalGitDir)
	env[2] = fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir)
	env[3] = fmt.Sprintf("TempDir=%s", TempDir)

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

func init() {
	var err error
	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalMediaDir = filepath.Join(LocalGitDir, "media")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		queueDir = setupQueueDir()

		if err := os.MkdirAll(TempDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}
	}
}

func resolveGitDir() (string, string, error) {
	wd, err := os.Getwd()
	if err != nil {
		panic(fmt.Errorf("Error reading working directory: %s", err))
	}

	return recursiveResolveGitDir(wd)
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	if len(dir) == 1 && dir[0] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		return filepath.Dir(dir), dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	if info, err := os.Stat(gitDir); err == nil {
		if info.IsDir() {
			return dir, gitDir, nil
		}
	}

	return recursiveResolveGitDir(filepath.Dir(dir))
}

const gitExt = ".git"
<commit_msg>ララララー ラララー ララ<commit_after>package gitmedia

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

const Version = "0.0.1"

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "git-media")
	LocalWorkingDir    string
	LocalGitDir        string
	LocalMediaDir      string
	LocalLogDir        string
)

func TempFile() (*os.File, error) {
	return ioutil.TempFile(TempDir, "")
}

func LocalMediaPath(sha string) string {
	path := filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
	if err := os.MkdirAll(path, 0744); err != nil {
		panic(fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err))
	}

	return filepath.Join(path, sha)
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 4, len(osEnviron)+4)
	env[0] = fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir)
	env[1] = fmt.Sprintf("LocalGitDir=%s", LocalGitDir)
	env[2] = fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir)
	env[3] = fmt.Sprintf("TempDir=%s", TempDir)

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

func init() {
	var err error
	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalMediaDir = filepath.Join(LocalGitDir, "media")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		queueDir = setupQueueDir()

		if err := os.MkdirAll(TempDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}
	}
}

func resolveGitDir() (string, string, error) {
	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	return recursiveResolveGitDir(wd)
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	if len(dir) == 1 && dir[0] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		return filepath.Dir(dir), dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	if info, err := os.Stat(gitDir); err == nil {
		if info.IsDir() {
			return dir, gitDir, nil
		}
	}

	return recursiveResolveGitDir(filepath.Dir(dir))
}

const gitExt = ".git"
<|endoftext|>


<commit_before>package main

import (
	"github.com/wikena/zlmgo"
	"log"
	"os"
)

func main() {
	l := zlmgo.LicenseNew()
	if err := l.Get("My Product", "1.0", os.Args[0], ".", ""); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>goimports<commit_after>package main

import (
	"log"
	"os"

	"github.com/wikena/zlmgo"
)

func main() {
	l := zlmgo.LicenseNew()
	if err := l.Get("My Product", "1.0", os.Args[0], ".", ""); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package mux

import (
	"testing"
)

func helloHandler(ctx *Context) {
	ctx.Write([]byte("Hello world"))
}

func testReverse(t *testing.T, expected string, m *Mux, name string, args ...interface{}) {
	rev, err := m.Reverse(name, args...)
	if expected != "" {
		if err != nil {
			t.Error(err)
		}
	} else {
		if err == nil {
			t.Errorf("Expecting error while reversing %s with arguments %v", name, args)
		}
	}
	if rev != expected {
		t.Errorf("Error reversing %q with arguments %v, expected %q, got %q", name, args, expected, rev)
	} else {
		t.Logf("Reversed %q with %v to %q", name, args, rev)
	}
}

func TestReverse(t *testing.T) {
	m := New()
	m.HandleNamedFunc("^/program/(\\d+)/$", helloHandler, "program")
	m.HandleNamedFunc("^/program/(\\d+)/version/(\\d+)/$", helloHandler, "programversion")
	m.HandleNamedFunc("^/program/(?P<pid>\\d+)/version/(?P<vers>\\d+)/$", helloHandler, "programversionnamed")
	m.HandleNamedFunc("^/program/(\\d+)/(?:version/(\\d+)/)?$", helloHandler, "programoptversion")
	m.HandleNamedFunc("^/program/(\\d+)/(?:version/(\\d+)/)?(?:revision/(\\d+)/)?$", helloHandler, "programrevision")
	m.HandleNamedFunc("^/archive/(\\d+)?$", helloHandler, "archive")
	m.HandleNamedFunc("^/image/(\\w+)\\.(\\w+)$", helloHandler, "image")
	m.HandleNamedFunc("^/image/(\\w+)\\-(\\w+)$", helloHandler, "imagedash")
	m.HandleNamedFunc("^/image/(\\w+)\\\\(\\w+)$", helloHandler, "imageslash")

	testReverse(t, "/program/1/", m, "program", 1)
	testReverse(t, "/program/1/version/2/", m, "programversion", 1, 2)
	testReverse(t, "/program/1/version/2/", m, "programversionnamed", 1, 2)
	testReverse(t, "/program/1/", m, "programoptversion", 1)
	testReverse(t, "/program/1/version/2/", m, "programoptversion", 1, 2)
	testReverse(t, "/program/1/", m, "programrevision", 1)
	testReverse(t, "/program/1/version/2/", m, "programrevision", 1, 2)
	testReverse(t, "/program/1/version/2/revision/3/", m, "programrevision", 1, 2, 3)

	testReverse(t, "/archive/19700101", m, "archive", "19700101")
	testReverse(t, "/archive/", m, "archive")

	// Test invalid reverses
	testReverse(t, "", m, "program")
	testReverse(t, "", m, "program", "foo")
	testReverse(t, "", m, "program", 1, 2)
	testReverse(t, "", m, "programrevision", 1, 2, 3, 4)

	// Dot, dash and slash
	testReverse(t, "/image/test.png", m, "image", "test", "png")
	testReverse(t, "/image/test-png", m, "imagedash", "test", "png")
	testReverse(t, "/image/test\\png", m, "imageslash", "test", "png")
}
<commit_msg>Add some test cases that still not work with the current code<commit_after>package mux

import (
	"testing"
)

func helloHandler(ctx *Context) {
	ctx.Write([]byte("Hello world"))
}

func testReverse(t *testing.T, expected string, m *Mux, name string, args ...interface{}) {
	rev, err := m.Reverse(name, args...)
	if expected != "" {
		if err != nil {
			t.Error(err)
		}
	} else {
		if err == nil {
			t.Errorf("Expecting error while reversing %s with arguments %v", name, args)
		}
	}
	if rev != expected {
		t.Errorf("Error reversing %q with arguments %v, expected %q, got %q", name, args, expected, rev)
	} else {
		t.Logf("Reversed %q with %v to %q", name, args, rev)
	}
}

func TestReverse(t *testing.T) {
	m := New()
	m.HandleNamedFunc("^/program/(\\d+)/$", helloHandler, "program")
	m.HandleNamedFunc("^/program/(\\d+)/version/(\\d+)/$", helloHandler, "programversion")
	m.HandleNamedFunc("^/program/(?P<pid>\\d+)/version/(?P<vers>\\d+)/$", helloHandler, "programversionnamed")
	m.HandleNamedFunc("^/program/(\\d+)/(?:version/(\\d+)/)?$", helloHandler, "programoptversion")
	m.HandleNamedFunc("^/program/(\\d+)/(?:version/(\\d+)/)?(?:revision/(\\d+)/)?$", helloHandler, "programrevision")
	m.HandleNamedFunc("^/archive/(\\d+)?$", helloHandler, "archive")
	m.HandleNamedFunc("^/image/(\\w+)\\.(\\w+)$", helloHandler, "image")
	m.HandleNamedFunc("^/image/(\\w+)\\-(\\w+)$", helloHandler, "imagedash")
	m.HandleNamedFunc("^/image/(\\w+)\\\\(\\w+)$", helloHandler, "imageslash")

	testReverse(t, "/program/1/", m, "program", 1)
	testReverse(t, "/program/1/version/2/", m, "programversion", 1, 2)
	testReverse(t, "/program/1/version/2/", m, "programversionnamed", 1, 2)
	testReverse(t, "/program/1/", m, "programoptversion", 1)
	testReverse(t, "/program/1/version/2/", m, "programoptversion", 1, 2)
	testReverse(t, "/program/1/", m, "programrevision", 1)
	testReverse(t, "/program/1/version/2/", m, "programrevision", 1, 2)
	testReverse(t, "/program/1/version/2/revision/3/", m, "programrevision", 1, 2, 3)

	testReverse(t, "/archive/19700101", m, "archive", "19700101")
	testReverse(t, "/archive/", m, "archive")

	// TODO: These don't work
	/*
		m.HandleNamedFunc("^/section/(sub/(\\d+)/subsub(\\d+))?$", helloHandler, "section")
		testReverse(t, "/section/", m, "section")
		testReverse(t, "/section/sub/1/subsub/2", m, "section", 1, 2)
		testReverse(t, "/section/sub/1", m, "section", 1)
	*/

	// Test invalid reverses
	testReverse(t, "", m, "program")
	testReverse(t, "", m, "program", "foo")
	testReverse(t, "", m, "program", 1, 2)
	testReverse(t, "", m, "programrevision", 1, 2, 3, 4)

	// Dot, dash and slash
	testReverse(t, "/image/test.png", m, "image", "test", "png")
	testReverse(t, "/image/test-png", m, "imagedash", "test", "png")
	testReverse(t, "/image/test\\png", m, "imageslash", "test", "png")
}
<|endoftext|>