<commit_before>package main

import (
	"errors"
	"fmt"
	"net/url"
	"sync"
	"sync/atomic"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/go-ini/ini"
)

const CACHE_INTERVAL = 1 * time.Hour

type Album struct {
	site *Site

	Path         string
	BucketPrefix string

	AuthUser string
	AuthPass string

	MetaTitle  string
	AlbumTitle string

	InIndex bool

	KeyCache        atomic.Value
	LastCacheUpdate time.Time

	CacheUpdateMutex sync.Mutex
}

type GetFromCacheResult struct {
	keys []string
	err  error
}

func NewAlbumFromConfig(section *ini.Section, s *Site) (*Album, error) {
	album := &Album{site: s, InIndex: true}
	if err := section.MapTo(album); err != nil {
		return nil, err
	}

	if err := album.IsValid(); err != nil {
		return nil, err
	}

	return album, nil
}

func NewAlbum(s *Site, path string, bucketPrefix string, authUser string, authPass string, metaTitle string, albumTitle string) (*Album, error) {
	album := &Album{
		site:         s,
		Path:         path,
		BucketPrefix: bucketPrefix,
		AuthUser:     authUser,
		AuthPass:     authPass,
		MetaTitle:    metaTitle,
		AlbumTitle:   albumTitle,
		InIndex:      true,
	}

	if err := album.IsValid(); err != nil {
		return nil, err
	}

	return album, nil
}

func (a *Album) IsValid() error {
	if a.Path == "" {
		return errors.New("'Path' is a required parameters that must have a valid value.")
	}

	if a.InIndex && a.HasOwnAuth() {
		return errors.New("An album that requires authentication can't be shown in the index. If you need authentication please add it to the site.")
	}
	return nil
}

func (a *Album) HasOwnAuth() bool {
	return a.AuthUser != "" && a.AuthPass != ""
}

// An album inherits it's sites auth settings if the album config doesn't override them. If both the site and album have
// auth enabled, the album auth takes precedence
func (a *Album) HasAuth() bool {
	return a.site.HasAuth() || a.HasOwnAuth()
}

func (a *Album) GetAuthUser() string {
	if a.AuthUser != "" {
		return a.AuthUser
	} else {
		return a.site.AuthUser
	}
}

func (a *Album) GetAuthPass() string {
	if a.AuthPass != "" {
		return a.AuthPass
	} else {
		return a.site.AuthPass
	}
}

func (a *Album) GetCanonicalUrl() *url.URL {
	u := a.site.GetCanonicalUrl()
	u.Path = a.Path
	return u
}

func (a *Album) GetCoverPhoto() (Renderable, error) {
	if photos, err := a.GetAllPhotos(); err != nil {
		return nil, err
	} else {
		if len(photos) > 0 {
			return photos[0], nil
		}
	}

	return &ErrorPhoto{}, nil
}

func (a *Album) GetCoverPhotoForTemplate() Renderable {
	if photo, err := a.GetCoverPhoto(); err != nil {
		fmt.Printf("Unable to get cover photo. Error: %s\n", err.Error())
		return &ErrorPhoto{}
	} else {
		return photo
	}
}

func (a *Album) GetThumbnailPhotosForTemplate() []Renderable {
	if photos, err := a.GetAllPhotos(); err != nil {
		fmt.Printf("Unable to get thumbnail photos. Error: %s\n", err.Error())
		return nil
	} else {
		if len(photos) > 6 {
			return photos[1:6]
		} else {
			return photos[1:]
		}
	}
}

func (a *Album) GetAllObjects() ([]*s3.Object, error) {
	svc, err := a.site.GetS3Service()
	if err != nil {
		return nil, err
	}

	objects, err := svc.ListObjects(&s3.ListObjectsInput{
		Bucket:    aws.String(a.site.BucketName),
		Prefix:    aws.String(a.BucketPrefix),
		Delimiter: aws.String("/"),
	})
	if err != nil {
		return nil, err
	}

	return objects.Contents, nil
}

func (a *Album) GetAllImageKeysFromBucket() ([]string, error) {
	objects, err := a.GetAllObjects()
	if err != nil {
		return nil, err
	}

	var imageKeys []string
	for _, obj := range objects {
		key := *obj.Key
		if key[len(*obj.Key)-1] != '/' {
			imageKeys = append(imageKeys, key)
		}
	}

	return imageKeys, nil
}

func (a *Album) GetAllPhotos() ([]Renderable, error) {
	var imageUrls []Renderable

	imageKeys, err := a.GetAllImageKeys()
	if err != nil {
		fmt.Printf("Unable to get image keys from S3. Error: %s\n", err.Error())
		return imageUrls, err
	}

	for _, v := range imageKeys {
		imageUrl := a.site.GetPhotoForKey(v)
		imageUrls = append(imageUrls, imageUrl)
	}

	return imageUrls, nil
}

func (a *Album) GetAllImageKeys() ([]string, error) {
	c := make(chan *GetFromCacheResult)
	go func() {
		var keys []string
		var err error

		if a.KeyCache.Load() != nil {
			c <- &GetFromCacheResult{a.KeyCache.Load().([]string), nil}

			a.CacheUpdateMutex.Lock()
			if a.NeedsUpdate() {
				keys, err = a.GetAllImageKeysFromBucket()
				if err == nil {
					a.KeyCache.Store(keys)
					a.LastCacheUpdate = time.Now()
				}
			}

			a.CacheUpdateMutex.Unlock()
		} else {
			a.CacheUpdateMutex.Lock()

			keys, err = a.GetAllImageKeysFromBucket()
			if err == nil {
				a.KeyCache.Store(keys)
				a.LastCacheUpdate = time.Now()
			}
			c <- &GetFromCacheResult{keys, err}

			a.CacheUpdateMutex.Unlock()
		}
	}()

	result := <-c
	if result.err != nil {
		return nil, result.err
	} else {
		return result.keys, result.err
	}
}

func (a *Album) NeedsUpdate() bool {
	return time.Now().Sub(a.LastCacheUpdate) > CACHE_INTERVAL
}
<commit_msg>Return nil when getting thumbnails for empty album<commit_after>package main

import (
	"errors"
	"fmt"
	"net/url"
	"sync"
	"sync/atomic"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/go-ini/ini"
)

const CACHE_INTERVAL = 1 * time.Hour

type Album struct {
	site *Site

	Path         string
	BucketPrefix string

	AuthUser string
	AuthPass string

	MetaTitle  string
	AlbumTitle string

	InIndex bool

	KeyCache        atomic.Value
	LastCacheUpdate time.Time

	CacheUpdateMutex sync.Mutex
}

type GetFromCacheResult struct {
	keys []string
	err  error
}

func NewAlbumFromConfig(section *ini.Section, s *Site) (*Album, error) {
	album := &Album{site: s, InIndex: true}
	if err := section.MapTo(album); err != nil {
		return nil, err
	}

	if err := album.IsValid(); err != nil {
		return nil, err
	}

	return album, nil
}

func NewAlbum(s *Site, path string, bucketPrefix string, authUser string, authPass string, metaTitle string, albumTitle string) (*Album, error) {
	album := &Album{
		site:         s,
		Path:         path,
		BucketPrefix: bucketPrefix,
		AuthUser:     authUser,
		AuthPass:     authPass,
		MetaTitle:    metaTitle,
		AlbumTitle:   albumTitle,
		InIndex:      true,
	}

	if err := album.IsValid(); err != nil {
		return nil, err
	}

	return album, nil
}

func (a *Album) IsValid() error {
	if a.Path == "" {
		return errors.New("'Path' is a required parameters that must have a valid value.")
	}

	if a.InIndex && a.HasOwnAuth() {
		return errors.New("An album that requires authentication can't be shown in the index. If you need authentication please add it to the site.")
	}
	return nil
}

func (a *Album) HasOwnAuth() bool {
	return a.AuthUser != "" && a.AuthPass != ""
}

// An album inherits it's sites auth settings if the album config doesn't override them. If both the site and album have
// auth enabled, the album auth takes precedence
func (a *Album) HasAuth() bool {
	return a.site.HasAuth() || a.HasOwnAuth()
}

func (a *Album) GetAuthUser() string {
	if a.AuthUser != "" {
		return a.AuthUser
	} else {
		return a.site.AuthUser
	}
}

func (a *Album) GetAuthPass() string {
	if a.AuthPass != "" {
		return a.AuthPass
	} else {
		return a.site.AuthPass
	}
}

func (a *Album) GetCanonicalUrl() *url.URL {
	u := a.site.GetCanonicalUrl()
	u.Path = a.Path
	return u
}

func (a *Album) GetCoverPhoto() (Renderable, error) {
	if photos, err := a.GetAllPhotos(); err != nil {
		return nil, err
	} else {
		if len(photos) > 0 {
			return photos[0], nil
		}
	}

	return &ErrorPhoto{}, nil
}

func (a *Album) GetCoverPhotoForTemplate() Renderable {
	if photo, err := a.GetCoverPhoto(); err != nil {
		fmt.Printf("Unable to get cover photo. Error: %s\n", err.Error())
		return &ErrorPhoto{}
	} else {
		return photo
	}
}

func (a *Album) GetThumbnailPhotosForTemplate() []Renderable {
	if photos, err := a.GetAllPhotos(); err != nil {
		fmt.Printf("Unable to get thumbnail photos. Error: %s\n", err.Error())
		return nil
	} else {
		if len(photos) > 6 {
			return photos[1:6]
		} else if len(photos) > 0 {
			return photos[1:]
		} else {
			return nil
		}
	}
}

func (a *Album) GetAllObjects() ([]*s3.Object, error) {
	svc, err := a.site.GetS3Service()
	if err != nil {
		return nil, err
	}

	objects, err := svc.ListObjects(&s3.ListObjectsInput{
		Bucket:    aws.String(a.site.BucketName),
		Prefix:    aws.String(a.BucketPrefix),
		Delimiter: aws.String("/"),
	})
	if err != nil {
		return nil, err
	}

	return objects.Contents, nil
}

func (a *Album) GetAllImageKeysFromBucket() ([]string, error) {
	objects, err := a.GetAllObjects()
	if err != nil {
		return nil, err
	}

	var imageKeys []string
	for _, obj := range objects {
		key := *obj.Key
		if key[len(*obj.Key)-1] != '/' {
			imageKeys = append(imageKeys, key)
		}
	}

	return imageKeys, nil
}

func (a *Album) GetAllPhotos() ([]Renderable, error) {
	var imageUrls []Renderable

	imageKeys, err := a.GetAllImageKeys()
	if err != nil {
		fmt.Printf("Unable to get image keys from S3. Error: %s\n", err.Error())
		return imageUrls, err
	}

	for _, v := range imageKeys {
		imageUrl := a.site.GetPhotoForKey(v)
		imageUrls = append(imageUrls, imageUrl)
	}

	return imageUrls, nil
}

func (a *Album) GetAllImageKeys() ([]string, error) {
	c := make(chan *GetFromCacheResult)
	go func() {
		var keys []string
		var err error

		if a.KeyCache.Load() != nil {
			c <- &GetFromCacheResult{a.KeyCache.Load().([]string), nil}

			a.CacheUpdateMutex.Lock()
			if a.NeedsUpdate() {
				keys, err = a.GetAllImageKeysFromBucket()
				if err == nil {
					a.KeyCache.Store(keys)
					a.LastCacheUpdate = time.Now()
				}
			}

			a.CacheUpdateMutex.Unlock()
		} else {
			a.CacheUpdateMutex.Lock()

			keys, err = a.GetAllImageKeysFromBucket()
			if err == nil {
				a.KeyCache.Store(keys)
				a.LastCacheUpdate = time.Now()
			}
			c <- &GetFromCacheResult{keys, err}

			a.CacheUpdateMutex.Unlock()
		}
	}()

	result := <-c
	if result.err != nil {
		return nil, result.err
	} else {
		return result.keys, result.err
	}
}

func (a *Album) NeedsUpdate() bool {
	return time.Now().Sub(a.LastCacheUpdate) > CACHE_INTERVAL
}
<|endoftext|>


<commit_before>//
// Use and distribution licensed under the Apache license version 2.
//
// See the COPYING file in the root project directory for full text.
//

package ghw

import (
	"github.com/jaypipes/ghw/pkg/baseboard"
	"github.com/jaypipes/ghw/pkg/bios"
	"github.com/jaypipes/ghw/pkg/block"
	"github.com/jaypipes/ghw/pkg/chassis"
	"github.com/jaypipes/ghw/pkg/cpu"
	"github.com/jaypipes/ghw/pkg/gpu"
	"github.com/jaypipes/ghw/pkg/memory"
	"github.com/jaypipes/ghw/pkg/net"
	"github.com/jaypipes/ghw/pkg/option"
	"github.com/jaypipes/ghw/pkg/pci"
	pciaddress "github.com/jaypipes/ghw/pkg/pci/address"
	"github.com/jaypipes/ghw/pkg/product"
	"github.com/jaypipes/ghw/pkg/topology"
)

type WithOption = option.Option

var (
	WithChroot       = option.WithChroot
	WithSnapshot     = option.WithSnapshot
	WithAlerter      = option.WithAlerter
	WithNullAlerter  = option.WithNullAlerter
	// match the existing environ variable to minimize surprises
	WithDisableWarnings = option.WithNullAlerter
	WithDisableTools    = option.WithDisableTools
	WithPathOverrides   = option.WithPathOverrides
)

type SnapshotOptions = option.SnapshotOptions

type PathOverrides = option.PathOverrides

type CPUInfo = cpu.Info

var (
	CPU = cpu.New
)

type MemoryArea = memory.Area
type MemoryInfo = memory.Info
type MemoryCacheType = memory.CacheType
type MemoryModule = memory.Module

const (
	MEMORY_CACHE_TYPE_UNIFIED     = memory.CACHE_TYPE_UNIFIED
	MEMORY_CACHE_TYPE_INSTRUCTION = memory.CACHE_TYPE_INSTRUCTION
	MEMORY_CACHE_TYPE_DATA        = memory.CACHE_TYPE_DATA
)

var (
	Memory = memory.New
)

type BlockInfo = block.Info
type Disk = block.Disk
type Partition = block.Partition

var (
	Block = block.New
)

type DriveType = block.DriveType

const (
	DRIVE_TYPE_UNKNOWN = block.DRIVE_TYPE_UNKNOWN
	DRIVE_TYPE_HDD     = block.DRIVE_TYPE_HDD
	DRIVE_TYPE_FDD     = block.DRIVE_TYPE_FDD
	DRIVE_TYPE_ODD     = block.DRIVE_TYPE_ODD
	DRIVE_TYPE_SSD     = block.DRIVE_TYPE_SSD
)

type StorageController = block.StorageController

const (
	STORAGE_CONTROLLER_UNKNOWN = block.STORAGE_CONTROLLER_UNKNOWN
	STORAGE_CONTROLLER_IDE     = block.STORAGE_CONTROLLER_IDE
	STORAGE_CONTROLLER_SCSI    = block.STORAGE_CONTROLLER_SCSI
	STORAGE_CONTROLLER_NVME    = block.STORAGE_CONTROLLER_NVME
	STORAGE_CONTROLLER_VIRTIO  = block.STORAGE_CONTROLLER_VIRTIO
	STORAGE_CONTROLLER_MMC     = block.STORAGE_CONTROLLER_MMC
)

type NetworkInfo = net.Info
type NIC = net.NIC
type NICCapability = net.NICCapability

var (
	Network = net.New
)

type BIOSInfo = bios.Info

var (
	BIOS = bios.New
)

type ChassisInfo = chassis.Info

var (
	Chassis = chassis.New
)

type BaseboardInfo = baseboard.Info

var (
	Baseboard = baseboard.New
)

type TopologyInfo = topology.Info
type TopologyNode = topology.Node

var (
	Topology = topology.New
)

type Architecture = topology.Architecture

const (
	ARCHITECTURE_SMP  = topology.ARCHITECTURE_SMP
	ARCHITECTURE_NUMA = topology.ARCHITECTURE_NUMA
)

type PCIInfo = pci.Info
type PCIAddress = pciaddress.Address
type PCIDevice = pci.Device

var (
	PCI                  = pci.New
	PCIAddressFromString = pciaddress.FromString
)

type ProductInfo = product.Info

var (
	Product = product.New
)

type GPUInfo = gpu.Info
type GraphicsCard = gpu.GraphicsCard

var (
	GPU = gpu.New
)
<commit_msg>alias: trivial style fix<commit_after>//
// Use and distribution licensed under the Apache license version 2.
//
// See the COPYING file in the root project directory for full text.
//

package ghw

import (
	"github.com/jaypipes/ghw/pkg/baseboard"
	"github.com/jaypipes/ghw/pkg/bios"
	"github.com/jaypipes/ghw/pkg/block"
	"github.com/jaypipes/ghw/pkg/chassis"
	"github.com/jaypipes/ghw/pkg/cpu"
	"github.com/jaypipes/ghw/pkg/gpu"
	"github.com/jaypipes/ghw/pkg/memory"
	"github.com/jaypipes/ghw/pkg/net"
	"github.com/jaypipes/ghw/pkg/option"
	"github.com/jaypipes/ghw/pkg/pci"
	pciaddress "github.com/jaypipes/ghw/pkg/pci/address"
	"github.com/jaypipes/ghw/pkg/product"
	"github.com/jaypipes/ghw/pkg/topology"
)

type WithOption = option.Option

var (
	WithChroot      = option.WithChroot
	WithSnapshot    = option.WithSnapshot
	WithAlerter     = option.WithAlerter
	WithNullAlerter = option.WithNullAlerter
	// match the existing environ variable to minimize surprises
	WithDisableWarnings = option.WithNullAlerter
	WithDisableTools    = option.WithDisableTools
	WithPathOverrides   = option.WithPathOverrides
)

type SnapshotOptions = option.SnapshotOptions

type PathOverrides = option.PathOverrides

type CPUInfo = cpu.Info

var (
	CPU = cpu.New
)

type MemoryArea = memory.Area
type MemoryInfo = memory.Info
type MemoryCacheType = memory.CacheType
type MemoryModule = memory.Module

const (
	MEMORY_CACHE_TYPE_UNIFIED     = memory.CACHE_TYPE_UNIFIED
	MEMORY_CACHE_TYPE_INSTRUCTION = memory.CACHE_TYPE_INSTRUCTION
	MEMORY_CACHE_TYPE_DATA        = memory.CACHE_TYPE_DATA
)

var (
	Memory = memory.New
)

type BlockInfo = block.Info
type Disk = block.Disk
type Partition = block.Partition

var (
	Block = block.New
)

type DriveType = block.DriveType

const (
	DRIVE_TYPE_UNKNOWN = block.DRIVE_TYPE_UNKNOWN
	DRIVE_TYPE_HDD     = block.DRIVE_TYPE_HDD
	DRIVE_TYPE_FDD     = block.DRIVE_TYPE_FDD
	DRIVE_TYPE_ODD     = block.DRIVE_TYPE_ODD
	DRIVE_TYPE_SSD     = block.DRIVE_TYPE_SSD
)

type StorageController = block.StorageController

const (
	STORAGE_CONTROLLER_UNKNOWN = block.STORAGE_CONTROLLER_UNKNOWN
	STORAGE_CONTROLLER_IDE     = block.STORAGE_CONTROLLER_IDE
	STORAGE_CONTROLLER_SCSI    = block.STORAGE_CONTROLLER_SCSI
	STORAGE_CONTROLLER_NVME    = block.STORAGE_CONTROLLER_NVME
	STORAGE_CONTROLLER_VIRTIO  = block.STORAGE_CONTROLLER_VIRTIO
	STORAGE_CONTROLLER_MMC     = block.STORAGE_CONTROLLER_MMC
)

type NetworkInfo = net.Info
type NIC = net.NIC
type NICCapability = net.NICCapability

var (
	Network = net.New
)

type BIOSInfo = bios.Info

var (
	BIOS = bios.New
)

type ChassisInfo = chassis.Info

var (
	Chassis = chassis.New
)

type BaseboardInfo = baseboard.Info

var (
	Baseboard = baseboard.New
)

type TopologyInfo = topology.Info
type TopologyNode = topology.Node

var (
	Topology = topology.New
)

type Architecture = topology.Architecture

const (
	ARCHITECTURE_SMP  = topology.ARCHITECTURE_SMP
	ARCHITECTURE_NUMA = topology.ARCHITECTURE_NUMA
)

type PCIInfo = pci.Info
type PCIAddress = pciaddress.Address
type PCIDevice = pci.Device

var (
	PCI                  = pci.New
	PCIAddressFromString = pciaddress.FromString
)

type ProductInfo = product.Info

var (
	Product = product.New
)

type GPUInfo = gpu.Info
type GraphicsCard = gpu.GraphicsCard

var (
	GPU = gpu.New
)
<|endoftext|>


<commit_before>package kubernetes

import (
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"text/template"

	"github.com/jsdir/deployer/pkg/resources"

	"github.com/mitchellh/mapstructure"
)

type KubernetesConfig struct {
	ManifestGlob string
	Cmd          string
}

type Kubernetes struct{}

func (k *Kubernetes) Deploy(deploy *resources.Deploy) error {
	// Get environment config.
	config := KubernetesConfig{
		ManifestGlob: "./manifests/*.json",
		Cmd:          "kubectl",
	}
	err := mapstructure.Decode(deploy.EnvConfig, &config)
	if err != nil {
		return err
	}

	log.Println(config)

	// Iterate through and parse templates.
	templates, err := filepath.Glob(config.ManifestGlob)
	if err != nil {
		return err
	}

	// Execute commands in parallel.
	count := len(templates)
	if count == 0 {
		log.Println("Info: No templates found")
		return nil
	}

	sem := make(chan error, count)
	for _, filename := range templates {
		go func(filename string) {
			sem <- updateManifest(filename, deploy, &config)
			return
		}(filename)
	}

	for i := 0; i < count; i++ {
		err := <-sem
		if err != nil {
			log.Println(err)
			return errors.New("Failed to run command")
		}
	}

	return nil
}

func updateManifest(filename string, deploy *resources.Deploy, config *KubernetesConfig) error {
	log.Printf("Uploading %s", filename)
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}

	tmpl, err := template.New("").Parse(string(data))
	if err != nil {
		return err
	}

	runCmd := func(action string) ([]byte, error) {
		log.Println("Running command:", config.Cmd, action)
		args := append(strings.Split(config.Cmd, " "), action, "-f", "-")
		cmd := exec.Command(args[0], args[1:]...)

		// Attach pipes.
		cmd.Stdout = os.Stdout
		stdin, err := cmd.StdinPipe()
		if err != nil {
			return nil, err
		}
		stderr, err := cmd.StderrPipe()
		if err != nil {
			return nil, err
		}

		// Start command.
		err = cmd.Start()
		if err != nil {
			return nil, err
		}

		err = tmpl.Execute(stdin, deploy)
		if err != nil {
			return nil, err
		}

		stdin.Close()
		stderrData, err := ioutil.ReadAll(stderr)
		if err != nil {
			return nil, err
		}

		return stderrData, cmd.Wait()
	}

	// Run commands.
	stderr, err := runCmd("create")

	// Try updating if the resource already exists.
	if err != nil {
		matched, matchErr := regexp.Match("already exists", stderr)
		if matchErr == nil && matched {
			updateStderr, updateErr := runCmd("update")
			if updateErr != nil {
				fmt.Println(string(updateStderr[:]))
				return updateErr
			}
			return nil
		}

		fmt.Println(string(stderr[:]))
		return err
	}

	return nil
}
<commit_msg>Delete before create<commit_after>package kubernetes

import (
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"text/template"

	"github.com/jsdir/deployer/pkg/resources"

	"github.com/mitchellh/mapstructure"
)

type KubernetesConfig struct {
	ManifestGlob string
	Cmd          string
}

type Kubernetes struct{}

func (k *Kubernetes) Deploy(deploy *resources.Deploy) error {
	// Get environment config.
	config := KubernetesConfig{
		ManifestGlob: "./manifests/*.json",
		Cmd:          "kubectl",
	}
	err := mapstructure.Decode(deploy.EnvConfig, &config)
	if err != nil {
		return err
	}

	log.Println(config)

	// Iterate through and parse templates.
	templates, err := filepath.Glob(config.ManifestGlob)
	if err != nil {
		return err
	}

	// Execute commands in parallel.
	count := len(templates)
	if count == 0 {
		log.Println("Info: No templates found")
		return nil
	}

	sem := make(chan error, count)
	for _, filename := range templates {
		go func(filename string) {
			sem <- updateManifest(filename, deploy, &config)
			return
		}(filename)
	}

	for i := 0; i < count; i++ {
		err := <-sem
		if err != nil {
			log.Println(err)
			return errors.New("Failed to run command")
		}
	}

	return nil
}

func updateManifest(filename string, deploy *resources.Deploy, config *KubernetesConfig) error {
	log.Printf("Uploading %s", filename)
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}

	tmpl, err := template.New("").Parse(string(data))
	if err != nil {
		return err
	}

	runCmd := func(action string) ([]byte, error) {
		log.Println("Running command:", config.Cmd, action)
		args := append(strings.Split(config.Cmd, " "), action, "-f", "-")
		cmd := exec.Command(args[0], args[1:]...)

		// Attach pipes.
		cmd.Stdout = os.Stdout
		stdin, err := cmd.StdinPipe()
		if err != nil {
			return nil, err
		}
		stderr, err := cmd.StderrPipe()
		if err != nil {
			return nil, err
		}

		// Start command.
		err = cmd.Start()
		if err != nil {
			return nil, err
		}

		err = tmpl.Execute(stdin, deploy)
		if err != nil {
			return nil, err
		}

		stdin.Close()
		stderrData, err := ioutil.ReadAll(stderr)
		if err != nil {
			return nil, err
		}

		return stderrData, cmd.Wait()
	}

	// Run commands.
	stderr, err := runCmd("create")

	// Try updating if the resource already exists.
	if err != nil {
		matched, matchErr := regexp.Match("already exists", stderr)
		if matchErr == nil && matched {
			// Temporarily delete before create until ReplicationControllers are supported.
			deleteStderr, deleteErr := runCmd("delete")
			if deleteErr != nil {
				fmt.Println(string(deleteStderr[:]))
				return deleteErr
			}
			createStderr, createErr := runCmd("create")
			if createErr != nil {
				fmt.Println(string(createStderr[:]))
				return createErr
			}
			return nil
		}

		fmt.Println(string(stderr[:]))
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
)

func main() {
	fmt.Println("Hello")
}
<commit_msg>endret tekst<commit_after>package main

import (
	"fmt"
)

func main() {
	fmt.Println("Hello, din tulling")
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"strings"
)

func helpHandler(inst *Instance) {
	inst.Println("Help:")
	for _, c := range inst.cmds {
		inst.Printf("  %s: %s\n", c.name, c.synopsis)
	}
	inst.Print("  exit, help: exit program\n")
}

func executeCmdline(inst *Instance, line []byte) int {
	ret := 0
	cmdline := strings.Fields(string(line))
	if len(cmdline) == 0 {
		inst.Log("parse input line failed: %s", string(line))
		return ret
	}
	inst.Log("[%v]\n", cmdline)

	switch cmdline[0] {
	case "help":
		helpHandler(inst)
	case "exit", "quit":
		return 1
	default:
		var cmd *Cmd
		for _, c := range inst.cmds {
			if cmdline[0] == c.name {
				cmd = c
			}
		}
		if cmd != nil {
			cmd.handler(cmdline)
		} else {
			helpHandler(inst)
		}
	}

	return ret
}

func handleTab(inst *Instance, line []byte) {
	inst.Log(" autocomplete \n")
	inst.Printf("%s%s", inst.prompt, string(line))
}

func inputLoop(inst *Instance) {
	inst.printPrompt()
	end := false
	for !end {
		c, err := inst.r.ReadByte()
		if err != nil {
			if err == io.EOF {
				inst.Printf("got EOF\n")
			} else {
				inst.Printf("error: %v", err)
			}
			end = true
		}

		//inst.Log("[%d]", c)
		switch c {
		case CharInterrupt:
			inst.Printf("\ngot Interrupt(Ctrl+C)\n")
			inst.line = inst.line[0:0]
			inst.Printf("\n")
			inst.printPrompt()
		case CharEOF:
			if len(inst.line) == 0 {
				inst.Printf("\ngot EOF(Ctrl+D)\n")
				end = true
			} else {
				inst.line = inst.line[0:0]
				inst.Printf("\n")
				inst.printPrompt()
			}
		case CharEnter:
			ret := executeCmdline(inst, inst.line)
			if ret != 0 {
				end = true
				break
			}
			inst.line = inst.line[0:0]
			inst.printPrompt()
		case CharTab:
			handleTab(inst, inst.line)
		case CharBackspace:
			inst.Print("\b \b")
			inst.line = inst.line[0 : len(inst.line)-1]
		default:
			inst.line = append(inst.line, c)
			inst.Printf("%c", c)
		}
	}
}
<commit_msg>use map to handle input charactors<commit_after>package main

import (
	"io"
	"strings"
)

type inputHandler func(*Instance) bool

var inputMap = map[byte]inputHandler{
	CharEOF:       eofHandler,
	CharTab:       tabHandler,
	CharEnter:     enterHandler,
	CharBackspace: backspaceHandler,
	CharInterrupt: interruptHandler,
}

func interruptHandler(inst *Instance) bool {
	inst.Printf("\ngot Interrupt(Ctrl+C)\n")
	inst.line = inst.line[0:0]
	inst.Printf("\n")
	inst.printPrompt()
	return false
}

func backspaceHandler(inst *Instance) bool {
	inst.Print("\b \b")
	inst.line = inst.line[0 : len(inst.line)-1]
	return false
}

func enterHandler(inst *Instance) bool {
	if executeCmdline(inst, inst.line) != 0 {
		return true
	}
	inst.line = inst.line[0:0]
	inst.printPrompt()
	return false
}

func tabHandler(inst *Instance) bool {
	inst.Log(" autocomplete \n")
	inst.Printf("%s%s", inst.prompt, string(inst.line))
	return false
}

func eofHandler(inst *Instance) bool {
	if len(inst.line) == 0 {
		inst.Printf("\ngot EOF(Ctrl+D)\n")
		return true
	}
	inst.line = inst.line[0:0]
	inst.Printf("\n")
	inst.printPrompt()
	return false
}

func helpHandler(inst *Instance) {
	inst.Println("Help:")
	for _, c := range inst.cmds {
		inst.Printf("  %s: %s\n", c.name, c.synopsis)
	}
	inst.Print("  exit, help: exit program\n")
}

func executeCmdline(inst *Instance, line []byte) int {
	ret := 0
	cmdline := strings.Fields(string(line))
	if len(cmdline) == 0 {
		inst.Log("parse input line failed: %s", string(line))
		return ret
	}
	inst.Log("[%v]\n", cmdline)

	switch cmdline[0] {
	case "help":
		helpHandler(inst)
	case "exit", "quit":
		return 1
	default:
		var cmd *Cmd
		for _, c := range inst.cmds {
			if cmdline[0] == c.name {
				cmd = c
			}
		}
		if cmd != nil {
			cmd.handler(cmdline)
		} else {
			helpHandler(inst)
		}
	}

	return ret
}

func inputLoop(inst *Instance) {
	inst.printPrompt()
	end := false
	for !end {
		c, err := inst.r.ReadByte()
		if err != nil {
			if err == io.EOF {
				inst.Printf("got EOF\n")
			} else {
				inst.Printf("error: %v", err)
			}
			end = true
		}

		//inst.Log("[%d]", c)
		handler, ok := inputMap[c]
		if ok {
			end = handler(inst)
		} else {
			inst.line = append(inst.line, c)
			inst.Printf("%c", c)
		}
	}
}
<|endoftext|>


<commit_before>package readline

import (
	"bufio"
	"io"
	"os"
)

type inputTerm struct {
	r        *bufio.Reader // for input
	termFd   int           // for setting the terminal input
	oldState *State        // old state of terminal
}

func (it *inputTerm) init() error {
	it.termFd = int(os.Stdin.Fd())
	oldState, err := MakeRaw(it.termFd)
	if err != nil {
		panic(err)
		return err
	}
	it.oldState = oldState

	it.r = bufio.NewReader(os.Stdin)

	return nil
}

func (it *inputTerm) deinit() {
	restoreTerm(it.termFd, it.oldState)
}

func (it *inputTerm) readByte() (byte, error) {
	return it.r.ReadByte()
}

type inputHandler func(*Instance) (byte, bool)

var inputMap = map[byte]inputHandler{
	CharEOF:       eofHandler,
	CharTab:       tabHandler,
	CharEnter:     enterHandler,
	CharBackspace: backspaceHandler,
	CharInterrupt: interruptHandler,
}

func eofHandler(inst *Instance) (byte, bool) {
	if inst.line.Len() == 0 {
		inst.Printf("\ngot EOF(Ctrl+D)\n")
		return CharEOF, true
	}
	inst.Print("\n")
	inst.resetCmdline()
	return CharEOF, false
}

func interruptHandler(inst *Instance) (byte, bool) {
	inst.Printf("\ngot Interrupt(Ctrl+C)\n")
	inst.resetCmdline()
	return CharInterrupt, false
}

func backspaceHandler(inst *Instance) (byte, bool) {
	inst.line.backspace()
	return CharBackspace, false
}

func enterHandler(inst *Instance) (byte, bool) {
	inst.Print("\n")
	end := inst.execute(inst.line.String(), inst.data)
	if !end {
		inst.resetCmdline()
	}
	return CharEnter, end
}

func tabHandler(inst *Instance) (byte, bool) {
	key := byte(CharTab)
	if inst.lastKey != CharTab { // First tab
		_, candidates, end, err := getCandidates(inst)
		if err != nil {
			inst.Log("1st tab error: %v\n", err)
			return key, false
		}
		switch len(candidates) {
		case 0:
			inst.Log("TODO: can not happen\n")
		case 1:
			completeWhole(inst, candidates[0])
			if end {
				inst.lineAdd(' ')
				key = ' '
			}
		default:
			completePartial(inst, candidates)
		}
	} else { // Second Tab
		cp, candidates, _, err := getCandidates(inst)
		if err != nil {
			inst.Log("2nd tab error: %v\n", err)
			return key, false
		}
		switch len(candidates) {
		case 0, 1:
			inst.Log("TODO: can not happen\n")
		default:
			inst.Log("multi candidates\n")
			printCandidates(inst, cp, candidates)
			inst.Printf("%s%s", inst.view.prompt, inst.line.String())
		}
	}

	return key, false
}

func InputLoop(inst *Instance) {
	inst.line.reset()
	inst.view.printPrompt()
	for {
		c, err := inst.input.readByte()
		if err != nil {
			if err == io.EOF {
				inst.Printf("got EOF\n")
			} else {
				inst.Printf("error: %v\n", err)
			}
			break
		}

		//inst.Log("[%d]", c)
		handler, ok := inputMap[c]
		if ok {
			key, end := handler(inst)
			if end {
				break
			}
			inst.lastKey = key
		} else {
			inst.line.insert(c)
			inst.lastKey = c
		}

		inst.view.clearLine()
		inst.view.Print(inst.view.prompt + inst.line.String())
		inst.view.resetCursor(false)
		inst.view.setCursor(inst.line.curPos)
		inst.view.flush()
	}
}
<commit_msg>modify the layout of code<commit_after>package readline

import (
	"bufio"
	"io"
	"os"
)

type inputTerm struct {
	r        *bufio.Reader // for input
	termFd   int           // for setting the terminal input
	oldState *State        // old state of terminal
}

func (it *inputTerm) init() error {
	it.termFd = int(os.Stdin.Fd())
	oldState, err := MakeRaw(it.termFd)
	if err != nil {
		panic(err)
		return err
	}
	it.oldState = oldState

	it.r = bufio.NewReader(os.Stdin)

	return nil
}

func (it *inputTerm) deinit() {
	restoreTerm(it.termFd, it.oldState)
}

func (it *inputTerm) readByte() (byte, error) {
	return it.r.ReadByte()
}

type inputHandler func(*Instance) (byte, bool)

var inputMap = map[byte]inputHandler{
	CharEOF:       eofHandler,
	CharTab:       tabHandler,
	CharEnter:     enterHandler,
	CharBackspace: backspaceHandler,
	CharInterrupt: interruptHandler,
}

func eofHandler(inst *Instance) (byte, bool) {
	if inst.line.Len() == 0 {
		inst.Printf("\ngot EOF(Ctrl+D)\n")
		return CharEOF, true
	}
	inst.Print("\n")
	inst.resetCmdline()
	return CharEOF, false
}

func tabHandler(inst *Instance) (byte, bool) {
	key := byte(CharTab)
	if inst.lastKey != CharTab { // First tab
		_, candidates, end, err := getCandidates(inst)
		if err != nil {
			inst.Log("1st tab error: %v\n", err)
			return key, false
		}
		switch len(candidates) {
		case 0:
			inst.Log("TODO: can not happen\n")
		case 1:
			completeWhole(inst, candidates[0])
			if end {
				inst.lineAdd(' ')
				key = ' '
			}
		default:
			completePartial(inst, candidates)
		}
	} else { // Second Tab
		cp, candidates, _, err := getCandidates(inst)
		if err != nil {
			inst.Log("2nd tab error: %v\n", err)
			return key, false
		}
		switch len(candidates) {
		case 0, 1:
			inst.Log("TODO: can not happen\n")
		default:
			inst.Log("multi candidates\n")
			printCandidates(inst, cp, candidates)
			inst.Printf("%s%s", inst.view.prompt, inst.line.String())
		}
	}

	return key, false
}

func enterHandler(inst *Instance) (byte, bool) {
	inst.Print("\n")
	end := inst.execute(inst.line.String(), inst.data)
	if !end {
		inst.resetCmdline()
	}
	return CharEnter, end
}

func backspaceHandler(inst *Instance) (byte, bool) {
	inst.line.backspace()
	return CharBackspace, false
}

func interruptHandler(inst *Instance) (byte, bool) {
	inst.Printf("\ngot Interrupt(Ctrl+C)\n")
	inst.resetCmdline()
	return CharInterrupt, false
}

func InputLoop(inst *Instance) {
	inst.line.reset()
	inst.view.printPrompt()
	for {
		c, err := inst.input.readByte()
		if err != nil {
			if err == io.EOF {
				inst.Printf("got EOF\n")
			} else {
				inst.Printf("error: %v\n", err)
			}
			break
		}

		//inst.Log("[%d]", c)
		handler, ok := inputMap[c]
		if ok {
			key, end := handler(inst)
			if end {
				break
			}
			inst.lastKey = key
		} else {
			inst.line.insert(c)
			inst.lastKey = c
		}

		inst.view.clearLine()
		inst.view.Print(inst.view.prompt + inst.line.String())
		inst.view.resetCursor(false)
		inst.view.setCursor(inst.line.curPos)
		inst.view.flush()
	}
}
<|endoftext|>


<commit_before>package husky

import (
	"net/http"
)

type Input struct {
	gets    map[string]string
	posts   map[string]string
	cookies map[string]string

	req *http.Request
}

func NewInput(req *http.Request) *Input {
	i := &Input{
		req: req,
	}

	i.initialize()

	return i
}

func (i *Input) initialize() {

}

func (i *Input) Get(key string) string {
	var val string

	if value, ok := i.gets[key]; ok {
		val = value
	}

	return val
}
<commit_msg>Added native http.Request getter<commit_after>package husky

import (
	"net/http"
)

type Input struct {
	gets    map[string]string
	posts   map[string]string
	cookies map[string]string

	req *http.Request
}

func NewInput(req *http.Request) *Input {
	i := &Input{
		req: req,
	}

	i.initialize()

	return i
}

func (i *Input) initialize() {

}

func (i *input) GetRequest() *http.Request {
	return i.req
}

func (i *Input) Get(key string) string {
	var val string

	if value, ok := i.gets[key]; ok {
		val = value
	}

	return val
}
<|endoftext|>


<commit_before>package hyper

import (
	"github.com/samuelngs/hyper/engine"
	"github.com/samuelngs/hyper/websocket"
)

// New creates a hyper server
func New(opts ...Option) *Hyper {
	o := newOptions(opts...)
	w := websocket.New(
		websocket.ID(o.ID),
		websocket.Sync(o.Sync),
		websocket.Cache(o.Cache),
		websocket.Message(o.Message),
		websocket.Router(o.Router),
	)
	e := engine.New(
		engine.ID(o.ID),
		engine.Addr(o.Addr),
		engine.Proto(o.Protocol),
		engine.Cache(o.Cache),
		engine.Message(o.Message),
		engine.Router(o.Router),
		engine.Websocket(w),
	)
	return &Hyper{
		id:        o.ID,
		addr:      o.Addr,
		cache:     o.Cache,
		message:   o.Message,
		sync:      o.Sync,
		router:    o.Router,
		engine:    e,
		websocket: w,
	}
}
<commit_msg>Enable compression by default<commit_after>package hyper

import (
	"github.com/samuelngs/hyper/engine"
	"github.com/samuelngs/hyper/websocket"
)

// New creates a hyper server
func New(opts ...Option) *Hyper {
	o := newOptions(opts...)
	w := websocket.New(
		websocket.ID(o.ID),
		websocket.Sync(o.Sync),
		websocket.Cache(o.Cache),
		websocket.Message(o.Message),
		websocket.Router(o.Router),
		websocket.EnableCompression(true),
	)
	e := engine.New(
		engine.ID(o.ID),
		engine.Addr(o.Addr),
		engine.Proto(o.Protocol),
		engine.Cache(o.Cache),
		engine.Message(o.Message),
		engine.Router(o.Router),
		engine.Websocket(w),
	)
	return &Hyper{
		id:        o.ID,
		addr:      o.Addr,
		cache:     o.Cache,
		message:   o.Message,
		sync:      o.Sync,
		router:    o.Router,
		engine:    e,
		websocket: w,
	}
}
<|endoftext|>


<commit_before>package jq

import (
	"bytes"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"

	"github.com/jingweno/jqpipe-go"
)

var Path, Version string

func init() {
	var err error

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

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

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

	jqPath := filepath.Join(pwd, "bin", fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH))
	os.Setenv("PATH", fmt.Sprintf("%s%c%s", jqPath, os.PathListSeparator, os.Getenv("PATH")))

	return filepath.Join(jqPath, "jq"), nil
}

func jqVersion() (string, error) {
	out, err := exec.Command("jq", "--version").Output()
	if err != nil {
		return "", err
	}

	out = bytes.TrimSpace(out)
	r := regexp.MustCompile(`^jq-(.+)$`)
	if r.Match(out) {
		m := r.FindSubmatch(out)[1]
		return string(m), nil
	}

	r = regexp.MustCompile(`^jq version (.+)$`)
	if r.Match(out) {
		m := r.FindSubmatch(out)[1]
		return string(m), nil
	}

	return "", fmt.Errorf("can't find jq version: %s", out)
}

type JQ struct {
	J string `json:"j"`
	Q string `json:"q"`
}

func (j *JQ) Eval() (string, error) {
	seq, err := jq.Eval(j.J, j.Q)
	if err != nil {
		return "", err
	}

	result := []string{}
	for _, s := range seq {
		ss := string(s)
		if ss != "" && ss != "null" {
			result = append(result, ss)
		}
	}

	return strings.Join(result, "\n"), nil
}

func (j *JQ) Valid() bool {
	return j.J != "" && j.Q != ""
}

func (j JQ) String() string {
	return fmt.Sprintf("j=%s, q=%s", j.J, j.Q)
}
<commit_msg>Add debug line<commit_after>package jq

import (
	"bytes"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"

	"github.com/jingweno/jqpipe-go"
)

var Path, Version string

func init() {
	var err error

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

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

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

	jqPath := filepath.Join(pwd, "bin", fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH))
	os.Setenv("PATH", fmt.Sprintf("%s%c%s", jqPath, os.PathListSeparator, os.Getenv("PATH")))

	return filepath.Join(jqPath, "jq"), nil
}

func jqVersion() (string, error) {
	out, err := exec.Command("jq", "--version").Output()
	if err != nil {
		return "", err
	}

	fmt.Println(out)

	out = bytes.TrimSpace(out)
	r := regexp.MustCompile(`^jq-(.+)$`)
	if r.Match(out) {
		m := r.FindSubmatch(out)[1]
		return string(m), nil
	}

	r = regexp.MustCompile(`^jq version (.+)$`)
	if r.Match(out) {
		m := r.FindSubmatch(out)[1]
		return string(m), nil
	}

	return "", fmt.Errorf("can't find jq version: %s", out)
}

type JQ struct {
	J string `json:"j"`
	Q string `json:"q"`
}

func (j *JQ) Eval() (string, error) {
	seq, err := jq.Eval(j.J, j.Q)
	if err != nil {
		return "", err
	}

	result := []string{}
	for _, s := range seq {
		ss := string(s)
		if ss != "" && ss != "null" {
			result = append(result, ss)
		}
	}

	return strings.Join(result, "\n"), nil
}

func (j *JQ) Valid() bool {
	return j.J != "" && j.Q != ""
}

func (j JQ) String() string {
	return fmt.Sprintf("j=%s, q=%s", j.J, j.Q)
}
<|endoftext|>


<commit_before>package xkcd

import (
	"image"
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"
	"io"
	"net/http"
)

// Image represents an xkcd comic image.
type Image struct {
	image.Image

	sourceURL    string
	sourceFormat string
}

// NewImage takes an io.Reader and returns an Image struct.
func NewImage(r io.Reader) (*Image, error) {
	var img Image
	var err error

	img.Image, img.sourceFormat, err = image.Decode(r)

	return &img, err
}

// GetImage is a convenience function to download a comic's metadata and
// then download the comic's image. If you already have the comic
// metadata, use Comic's Image() method.
func GetImage(n int) (*Image, error) {
	c, err := Get(n)
	if err != nil {
		return nil, err
	}
	return c.Image()
}

func getImageFromURL(url string) (*Image, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	return NewImage(resp.Body)
}

// SourceURL is URL from which the comic image was retrieved. If image
// wasn't retrieved from a URL (e.g. when it is created by calling
// NewImage directly) a blank string will be returned.
func (img *Image) SourceURL() string {
	return img.sourceURL
}

// SourceFormat is the file format that the image was decoded from.
func (img *Image) SourceFormat() string {
	return img.sourceFormat
}
<commit_msg>Set sourceURL for images retrieved from URL.<commit_after>package xkcd

import (
	"image"
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"
	"io"
	"net/http"
)

// Image represents an xkcd comic image.
type Image struct {
	image.Image

	sourceURL    string
	sourceFormat string
}

// NewImage takes an io.Reader and returns an Image struct.
func NewImage(r io.Reader) (*Image, error) {
	var img Image
	var err error

	img.Image, img.sourceFormat, err = image.Decode(r)

	return &img, err
}

// GetImage is a convenience function to download a comic's metadata and
// then download the comic's image. If you already have the comic
// metadata, use Comic's Image() method.
func GetImage(n int) (*Image, error) {
	c, err := Get(n)
	if err != nil {
		return nil, err
	}
	return c.Image()
}

func getImageFromURL(url string) (*Image, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	img, err := NewImage(resp.Body)
	if err != nil {
		return nil, err
	}

	img.sourceURL = url

	return img, nil
}

// SourceURL is URL from which the comic image was retrieved. If image
// wasn't retrieved from a URL (e.g. when it is created by calling
// NewImage directly) a blank string will be returned.
func (img *Image) SourceURL() string {
	return img.sourceURL
}

// SourceFormat is the file format that the image was decoded from.
func (img *Image) SourceFormat() string {
	return img.sourceFormat
}
<|endoftext|>


<commit_before>package cl11

import (
	clw "github.com/rdwilliamson/clw11"
)

// A 2D or 3D image (Depth and SlicePitch are 0 for 2D images).
type Image struct {
	id clw.Mem

	// The context the buffer was created on.
	Context *Context

	// The image format, the channel order and data type.
	Format ImageFormat

	// The width in pixels.
	Width int

	// The height in pixels.
	Height int

	// The depth in pixels. Zero for a 2D image.
	Depth int

	// Scan line width in bytes. Only valid if Host is not nil. If Host is not
	// nil then valid values are 0 for Width * size of element in bytes or
	// greater than or equal to Width * size of element in bytes.
	RowPitch int

	// The size in bytes of each 2D image in bytes. Only valid if Host is not
	// nil; valid values are 0 for RowPitch * Height or greater than or equal to
	// RowPitch * Height.
	SlicePitch int

	// Usage information for the buffer from the device's point of view.
	Flags MemFlags

	// The host backed memory for the buffer, if applicable.
	Host interface{}
}

type (
	MemObjectType clw.MemObjectType
	ChannelOrder  clw.ChannelOrder
	ChannelType   clw.ChannelType
)

type ImageFormat struct {
	ChannelOrder ChannelOrder
	ChannelType  ChannelType
}

const (
	MemObjectImage2D = MemObjectType(clw.MemObjectImage2D)
	MemObjectImage3D = MemObjectType(clw.MemObjectImage3D)
)

const (
	R         = ChannelOrder(clw.R)
	A         = ChannelOrder(clw.A)
	RG        = ChannelOrder(clw.RG)
	RA        = ChannelOrder(clw.RA)
	RGB       = ChannelOrder(clw.RGB)
	RGBA      = ChannelOrder(clw.RGBA)
	BGRA      = ChannelOrder(clw.BGRA)
	ARGB      = ChannelOrder(clw.ARGB)
	Intensity = ChannelOrder(clw.Intensity)
	Luminance = ChannelOrder(clw.Luminance)
	Rx        = ChannelOrder(clw.Rx)
	RGx       = ChannelOrder(clw.RGx)
	RGBx      = ChannelOrder(clw.RGBx)
)

const (
	SnormInt8      = ChannelType(clw.SnormInt8)
	SnormInt16     = ChannelType(clw.SnormInt16)
	UnormInt8      = ChannelType(clw.UnormInt8)
	UnormInt16     = ChannelType(clw.UnormInt16)
	UnormShort565  = ChannelType(clw.UnormShort565)
	UnormShort555  = ChannelType(clw.UnormShort555)
	UnormInt101010 = ChannelType(clw.UnormInt101010)
	SignedInt8     = ChannelType(clw.SignedInt8)
	SignedInt16    = ChannelType(clw.SignedInt16)
	SignedInt32    = ChannelType(clw.SignedInt32)
	UnsignedInt8   = ChannelType(clw.UnsignedInt8)
	UnsignedInt16  = ChannelType(clw.UnsignedInt16)
	UnsignedInt32  = ChannelType(clw.UnsignedInt32)
	HalfFloat      = ChannelType(clw.HalfFloat)
	Float          = ChannelType(clw.Float)
)

func (c *Context) GetSupportedImageFormats(mf MemFlags, t MemObjectType) ([]ImageFormat, error) {

	var count clw.Uint
	err := clw.GetSupportedImageFormats(c.id, clw.MemFlags(mf), clw.MemObjectType(t), 0, nil, &count)
	if err != nil {
		return nil, err
	}

	formats := make([]clw.ImageFormat, int(count))

	err = clw.GetSupportedImageFormats(c.id, clw.MemFlags(mf), clw.MemObjectType(t), count, &formats[0], nil)
	if err != nil {
		return nil, err
	}

	results := make([]ImageFormat, int(count))

	for i := range formats {
		results[i].ChannelOrder = ChannelOrder(formats[i].ChannelOrder())
		results[i].ChannelType = ChannelType(formats[i].ChannelType())
	}

	return results, nil
}

func (c *Context) CreateImage2D(mf MemFlags, fmt ImageFormat, width, height, rowPitch int,
	src interface{}) (*Image, error) {

	fmt2 := clw.CreateImageFormat(clw.ChannelOrder(fmt.ChannelOrder), clw.ChannelType(fmt.ChannelType))

	mem, err := clw.CreateImage2D(c.id, clw.MemFlags(mf), fmt2, clw.Size(width), clw.Size(height), clw.Size(rowPitch),
		nil)
	if err != nil {
		return nil, err
	}

	return &Image{id: mem, Context: c, Format: fmt, Width: width, Height: height, RowPitch: rowPitch, Flags: mf}, nil
}
<commit_msg>Renamed variable to avoid conflict with standard packages.<commit_after>package cl11

import (
	clw "github.com/rdwilliamson/clw11"
)

// A 2D or 3D image (Depth and SlicePitch are 0 for 2D images).
type Image struct {
	id clw.Mem

	// The context the buffer was created on.
	Context *Context

	// The image format, the channel order and data type.
	Format ImageFormat

	// The width in pixels.
	Width int

	// The height in pixels.
	Height int

	// The depth in pixels. Zero for a 2D image.
	Depth int

	// Scan line width in bytes. Only valid if Host is not nil. If Host is not
	// nil then valid values are 0 for Width * size of element in bytes or
	// greater than or equal to Width * size of element in bytes.
	RowPitch int

	// The size in bytes of each 2D image in bytes. Only valid if Host is not
	// nil; valid values are 0 for RowPitch * Height or greater than or equal to
	// RowPitch * Height.
	SlicePitch int

	// Usage information for the buffer from the device's point of view.
	Flags MemFlags

	// The host backed memory for the buffer, if applicable.
	Host interface{}
}

type (
	MemObjectType clw.MemObjectType
	ChannelOrder  clw.ChannelOrder
	ChannelType   clw.ChannelType
)

type ImageFormat struct {
	ChannelOrder ChannelOrder
	ChannelType  ChannelType
}

const (
	MemObjectImage2D = MemObjectType(clw.MemObjectImage2D)
	MemObjectImage3D = MemObjectType(clw.MemObjectImage3D)
)

const (
	R         = ChannelOrder(clw.R)
	A         = ChannelOrder(clw.A)
	RG        = ChannelOrder(clw.RG)
	RA        = ChannelOrder(clw.RA)
	RGB       = ChannelOrder(clw.RGB)
	RGBA      = ChannelOrder(clw.RGBA)
	BGRA      = ChannelOrder(clw.BGRA)
	ARGB      = ChannelOrder(clw.ARGB)
	Intensity = ChannelOrder(clw.Intensity)
	Luminance = ChannelOrder(clw.Luminance)
	Rx        = ChannelOrder(clw.Rx)
	RGx       = ChannelOrder(clw.RGx)
	RGBx      = ChannelOrder(clw.RGBx)
)

const (
	SnormInt8      = ChannelType(clw.SnormInt8)
	SnormInt16     = ChannelType(clw.SnormInt16)
	UnormInt8      = ChannelType(clw.UnormInt8)
	UnormInt16     = ChannelType(clw.UnormInt16)
	UnormShort565  = ChannelType(clw.UnormShort565)
	UnormShort555  = ChannelType(clw.UnormShort555)
	UnormInt101010 = ChannelType(clw.UnormInt101010)
	SignedInt8     = ChannelType(clw.SignedInt8)
	SignedInt16    = ChannelType(clw.SignedInt16)
	SignedInt32    = ChannelType(clw.SignedInt32)
	UnsignedInt8   = ChannelType(clw.UnsignedInt8)
	UnsignedInt16  = ChannelType(clw.UnsignedInt16)
	UnsignedInt32  = ChannelType(clw.UnsignedInt32)
	HalfFloat      = ChannelType(clw.HalfFloat)
	Float          = ChannelType(clw.Float)
)

func (c *Context) GetSupportedImageFormats(mf MemFlags, t MemObjectType) ([]ImageFormat, error) {

	var count clw.Uint
	err := clw.GetSupportedImageFormats(c.id, clw.MemFlags(mf), clw.MemObjectType(t), 0, nil, &count)
	if err != nil {
		return nil, err
	}

	formats := make([]clw.ImageFormat, int(count))

	err = clw.GetSupportedImageFormats(c.id, clw.MemFlags(mf), clw.MemObjectType(t), count, &formats[0], nil)
	if err != nil {
		return nil, err
	}

	results := make([]ImageFormat, int(count))

	for i := range formats {
		results[i].ChannelOrder = ChannelOrder(formats[i].ChannelOrder())
		results[i].ChannelType = ChannelType(formats[i].ChannelType())
	}

	return results, nil
}

func (c *Context) CreateImage2D(mf MemFlags, format ImageFormat, width, height, rowPitch int,
	src interface{}) (*Image, error) {

	cFormat := clw.CreateImageFormat(clw.ChannelOrder(format.ChannelOrder), clw.ChannelType(format.ChannelType))

	mem, err := clw.CreateImage2D(c.id, clw.MemFlags(mf), cFormat, clw.Size(width), clw.Size(height),
		clw.Size(rowPitch), nil)
	if err != nil {
		return nil, err
	}

	return &Image{id: mem, Context: c, Format: format, Width: width, Height: height, RowPitch: rowPitch, Flags: mf}, nil
}
<|endoftext|>


<commit_before>package main

import "os"
import "github.com/docker/engine-api/client"
import "math/rand"
import "os/exec"
import "strconv"
import "github.com/seehuhn/mt19937"
import "time"
import "os/user"

var cli *client.Client

type ExecRequest struct {
	Image string
	Cmd []string
	SourceFileName string
}

type Judge struct {
	Code string
	Compile *ExecRequest
	Exec ExecRequest
	Time int64
	Mem  int64
	TCCount int // The number of test cases
}

type JudgeResult int

const (
	Accepted            JudgeResult = 0
	WrongAnswer         JudgeResult = 1
	CompileError        JudgeResult = 2
	TimeLimitExceeded   JudgeResult = 3
	MemoryLimitExceeded JudgeResult = 4
	RuntimeError        JudgeResult = 5
	InternalError       JudgeResult = 6
	Judging             JudgeResult = 7
	CompileTimeLimitExceeded JudgeResult = 8
	CompileMemoryLimitExceeded JudgeResult = 9
)

type JudgeStatus struct {
	Case     *string
	JR       JudgeResult
	Mem      int64
	Time     int64
	Msg      *string
}

func CreateInternalError(msg string) JudgeStatus {
	return JudgeStatus{nil, InternalError, 0, 0, &msg}
}

const BASE_RAND_STRING = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

func RandomName() string {
	rng := rand.New(mt19937.New())
	rng.Seed(time.Now().UnixNano())

	res := make([]byte, 0, 32)
	for i := 0; i < 32; i++ {
		res = append(res, BASE_RAND_STRING[rng.Intn(len(BASE_RAND_STRING))])
	}

	return string(res)
}

func (j *Judge) Run(ch chan<- JudgeStatus, tests <-chan struct {
	Name string
	In  string
	Out string
}) {
	// Close a channel to send results of judging
	defer close(ch)

	// Identity
	id := RandomName()

	// User
	_, err := exec.Command("useradd", "--no-create-home", id).Output()

	if err != nil {
		ch <- CreateInternalError("Failed to create a directory to build your code. " + err.Error())

		return
	}

	uid, err := user.Lookup(id)

	if err != nil {
		ch <- CreateInternalError("Failed to look up a user. " + err.Error())

		return
	}

	uidInt, err := strconv.ParseInt(uid.Uid, 10, 64)

	if err != nil {
		ch <- CreateInternalError("Failed to parseInt uid. " + err.Error())

		return
	}
	gidInt, err := strconv.ParseInt(uid.Gid, 10, 64)
	if err != nil {
		ch <- CreateInternalError("Failed to parseInt gid. " + err.Error())

		return
	}

	defer exec.Command("userdel", id)

	// Working Directory
	path := workingDirectory + "/" + id

	err = os.Mkdir(path, 0664)

	if err != nil {
		ch <- CreateInternalError("Failed to create a directory. " + err.Error())

		return
	}

	defer os.RemoveAll(path)

	uidInt = uidInt * gidInt
	err = nil//os.Chown(path, int(uidInt), int(gidInt))

	if err != nil {
		ch <- CreateInternalError("Failed to chown the directory. " + err.Error())

		return
	}

	// Source File
	fp, err := os.Create(path + "/" + j.Compile.SourceFileName)

	if err != nil {
		ch <- CreateInternalError("Failed to create source file." + err.Error())

		return
	}

	l, err := fp.Write([]byte(j.Code))

	if err != nil {
		ch <- CreateInternalError("Failed to write your code on your file. " + err.Error())

		return
	}

	if l != len(j.Code) {
		ch <- CreateInternalError("Failed to write your code on your file.")

		return
	}

	fp.Close()

	err = os.Chmod(path + "/" + j.Compile.SourceFileName, 0644)

	if err != nil {
		ch <- CreateInternalError("Failed to chmod the source file. " + err.Error())

		return
	}

	// Compile
	if j.Compile != nil {
		exe, err := NewExecutor(id, 512 * 1024 * 1024, []string{"ls", "-la", "/work"}, j.Compile.Image, []string{path + ":" + "/work"}, uid.Uid)

		if err != nil {
			ch <- CreateInternalError("Failed to create a Docker container to compile your code." + err.Error())

			return
		}

		res := exe.Run(10000, "")

		exe.Delete()
		if res.Status != ExecFinished {
			switch res.Status {
			case ExecError:
				ch <- CreateInternalError("Failed to execute a compiler." + res.Stderr)

				return
			case ExecMemoryLimitExceeded:
				ch <- JudgeStatus{JR: CompileMemoryLimitExceeded}

				return
			case ExecTimeLimitExceeded:
				ch <- JudgeStatus{JR: CompileTimeLimitExceeded}

				return
			}
		}

		if res.ExitCode != 0 || true { // Debug
			msg := res.Stdout + res.Stderr
			ch <- JudgeStatus{JR: CompileError, Msg: &msg}

			return
		}
	}
	return

	exe, err := NewExecutor(id, j.Mem, j.Exec.Cmd, j.Exec.Image, []string{path + ":" + "/work:ro"}, uid.Uid)

	if err != nil {
		ch <- CreateInternalError("Failed to create a Docker container to judge." + err.Error())

		return
	}

	defer exe.Delete()

	tcCounter := 0
	for tc, res := <-tests; res; tc, res = <-tests {
		res := exe.Run(j.Time, tc.In)

		if res.Status != ExecFinished {
			switch res.Status {
			case ExecError:
				msg := "Failed to execute your code." + res.Stderr
				ch <- JudgeStatus{Case: &tc.Name, JR: InternalError, Msg: &msg}
			case ExecMemoryLimitExceeded:
				ch <- JudgeStatus{Case: &tc.Name, JR: MemoryLimitExceeded}
			case ExecTimeLimitExceeded:
				ch <- JudgeStatus{Case: &tc.Name, JR: TimeLimitExceeded}
			}
		}else {
			if res.ExitCode != 0 {
				ch <- JudgeStatus{Case: &tc.Name, JR: RuntimeError}
			}else {
				if res.Stdout == tc.Out {
					ch <- JudgeStatus{Case: &tc.Name, JR: Accepted}
				}else {
					ch <- JudgeStatus{Case: &tc.Name, JR: WrongAnswer}
				}
			}
		}

		tcCounter++

		msg := strconv.FormatInt(int64(tcCounter), 10) + "/" + strconv.FormatInt(int64(j.TCCount), 10)
		ch <- JudgeStatus{JR: Judging, Msg: &msg}
	}

}
<commit_msg>Sun May 22 19:22:30 JST 2016<commit_after>package main

import "os"
import "github.com/docker/engine-api/client"
import "math/rand"
import "os/exec"
import "strconv"
import "github.com/seehuhn/mt19937"
import "time"
import "os/user"

var cli *client.Client

type ExecRequest struct {
	Image string
	Cmd []string
	SourceFileName string
}

type Judge struct {
	Code string
	Compile *ExecRequest
	Exec ExecRequest
	Time int64
	Mem  int64
	TCCount int // The number of test cases
}

type JudgeResult int

const (
	Accepted            JudgeResult = 0
	WrongAnswer         JudgeResult = 1
	CompileError        JudgeResult = 2
	TimeLimitExceeded   JudgeResult = 3
	MemoryLimitExceeded JudgeResult = 4
	RuntimeError        JudgeResult = 5
	InternalError       JudgeResult = 6
	Judging             JudgeResult = 7
	CompileTimeLimitExceeded JudgeResult = 8
	CompileMemoryLimitExceeded JudgeResult = 9
)

type JudgeStatus struct {
	Case     *string
	JR       JudgeResult
	Mem      int64
	Time     int64
	Msg      *string
}

func CreateInternalError(msg string) JudgeStatus {
	return JudgeStatus{nil, InternalError, 0, 0, &msg}
}

const BASE_RAND_STRING = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

func RandomName() string {
	rng := rand.New(mt19937.New())
	rng.Seed(time.Now().UnixNano())

	res := make([]byte, 0, 32)
	for i := 0; i < 32; i++ {
		res = append(res, BASE_RAND_STRING[rng.Intn(len(BASE_RAND_STRING))])
	}

	return string(res)
}

func (j *Judge) Run(ch chan<- JudgeStatus, tests <-chan struct {
	Name string
	In  string
	Out string
}) {
	// Close a channel to send results of judging
	defer close(ch)

	// Identity
	id := RandomName()

	// User
	_, err := exec.Command("useradd", "--no-create-home", id).Output()

	if err != nil {
		ch <- CreateInternalError("Failed to create a directory to build your code. " + err.Error())

		return
	}

	uid, err := user.Lookup(id)

	if err != nil {
		ch <- CreateInternalError("Failed to look up a user. " + err.Error())

		return
	}

	uidInt, err := strconv.ParseInt(uid.Uid, 10, 64)

	if err != nil {
		ch <- CreateInternalError("Failed to parseInt uid. " + err.Error())

		return
	}
	gidInt, err := strconv.ParseInt(uid.Gid, 10, 64)
	if err != nil {
		ch <- CreateInternalError("Failed to parseInt gid. " + err.Error())

		return
	}

	defer exec.Command("userdel", id)

	// Working Directory
	path := workingDirectory + "/" + id

	err = os.Mkdir(path, 0664)

	if err != nil {
		ch <- CreateInternalError("Failed to create a directory. " + err.Error())

		return
	}

	defer os.RemoveAll(path)

	uidInt = uidInt * gidInt
	err = os.Chown(path, int(uidInt), int(gidInt))

	if err != nil {
		ch <- CreateInternalError("Failed to chown the directory. " + err.Error())

		return
	}
	err = os.Chmod(path, int(uidInt), int(gidInt))

	if err != nil {
		ch <- CreateInternalError("Failed to chmod the directory. " + err.Error())

		return
	}
	// Source File
	fp, err := os.Create(path + "/" + j.Compile.SourceFileName)

	if err != nil {
		ch <- CreateInternalError("Failed to create source file." + err.Error())

		return
	}

	l, err := fp.Write([]byte(j.Code))

	if err != nil {
		ch <- CreateInternalError("Failed to write your code on your file. " + err.Error())

		return
	}

	if l != len(j.Code) {
		ch <- CreateInternalError("Failed to write your code on your file.")

		return
	}

	fp.Close()

	err = os.Chmod(path + "/" + j.Compile.SourceFileName, 0644)

	if err != nil {
		ch <- CreateInternalError("Failed to chmod the source file. " + err.Error())

		return
	}

	// Compile
	if j.Compile != nil {
		exe, err := NewExecutor(id, 512 * 1024 * 1024, []string{"ls", "-la", "/work"}, j.Compile.Image, []string{path + ":" + "/work"}, uid.Uid)

		if err != nil {
			ch <- CreateInternalError("Failed to create a Docker container to compile your code." + err.Error())

			return
		}

		res := exe.Run(10000, "")

		exe.Delete()
		if res.Status != ExecFinished {
			switch res.Status {
			case ExecError:
				ch <- CreateInternalError("Failed to execute a compiler." + res.Stderr)

				return
			case ExecMemoryLimitExceeded:
				ch <- JudgeStatus{JR: CompileMemoryLimitExceeded}

				return
			case ExecTimeLimitExceeded:
				ch <- JudgeStatus{JR: CompileTimeLimitExceeded}

				return
			}
		}

		if res.ExitCode != 0 || true { // Debug
			msg := res.Stdout + res.Stderr
			ch <- JudgeStatus{JR: CompileError, Msg: &msg}

			return
		}
	}
	return

	exe, err := NewExecutor(id, j.Mem, j.Exec.Cmd, j.Exec.Image, []string{path + ":" + "/work:ro"}, uid.Uid)

	if err != nil {
		ch <- CreateInternalError("Failed to create a Docker container to judge." + err.Error())

		return
	}

	defer exe.Delete()

	tcCounter := 0
	for tc, res := <-tests; res; tc, res = <-tests {
		res := exe.Run(j.Time, tc.In)

		if res.Status != ExecFinished {
			switch res.Status {
			case ExecError:
				msg := "Failed to execute your code." + res.Stderr
				ch <- JudgeStatus{Case: &tc.Name, JR: InternalError, Msg: &msg}
			case ExecMemoryLimitExceeded:
				ch <- JudgeStatus{Case: &tc.Name, JR: MemoryLimitExceeded}
			case ExecTimeLimitExceeded:
				ch <- JudgeStatus{Case: &tc.Name, JR: TimeLimitExceeded}
			}
		}else {
			if res.ExitCode != 0 {
				ch <- JudgeStatus{Case: &tc.Name, JR: RuntimeError}
			}else {
				if res.Stdout == tc.Out {
					ch <- JudgeStatus{Case: &tc.Name, JR: Accepted}
				}else {
					ch <- JudgeStatus{Case: &tc.Name, JR: WrongAnswer}
				}
			}
		}

		tcCounter++

		msg := strconv.FormatInt(int64(tcCounter), 10) + "/" + strconv.FormatInt(int64(j.TCCount), 10)
		ch <- JudgeStatus{JR: Judging, Msg: &msg}
	}

}
<|endoftext|>


<commit_before>package mutagen

// LegalNotice provides license notices for Mutagen itself and any third-party
// dependencies.
const LegalNotice = `Mutagen

Copyright (c) 2016 Jacob Howard. All rights reserved.

Released under the terms of the MIT License.

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Mutagen makes use of the following third-party software:

Go, the Go standard library, and the Go net subrepository (https://golang.org/)

Copyright (c) 2009 The Go Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

* Neither the name of Google Inc. nor the names of its contributors may be used
  to endorse or promote products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Additional IP Rights Grant (Patents)

"This implementation" means the copyrightable works distributed by Google as
part of the Go project.

Google hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
royalty-free, irrevocable (except as stated in this section) patent license to
make, have made, use, offer to sell, sell, import, transfer and otherwise run,
modify and propagate the contents of this implementation of Go, where such
license applies only to those patent claims, both currently owned or controlled
by Google and acquired in the future, licensable by Google that are necessarily
infringed by this implementation of Go. This grant does not include claims that
would be infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or order or
agree to the institution of patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that this implementation of
Go or any code incorporated within this implementation of Go constitutes direct
or contributory patent infringement, or inducement of patent infringement, then
any patent rights granted to you under this License for this implementation of
Go shall terminate as of the date such litigation is filed.

errors (https://github.com/pkg/errors)

Copyright (c) 2015, Dave Cheney <dave@cheney.net>
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
  list of conditions and the following disclaimer in the documentation and/or
  other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

pflag (https://github.com/ogier/pflag)

Copyright (c) 2012 Alex Ogier. All rights reserved.
Copyright (c) 2012 The Go Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
  list of conditions and the following disclaimer in the documentation and/or
  other materials provided with the distribution.

* Neither the name of Google Inc. nor the names of its contributors may be used
  to endorse or promote products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

golang-levenshtein (https://github.com/texttheater/golang-levenshtein)

The MIT License (MIT)

Copyright (c) 2013 Kilian Evang and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

protobuf (https://github.com/golang/protobuf)

Go support for Protocol Buffers - Google's data interchange format

Copyright 2010 The Go Authors.  All rights reserved.
https://github.com/golang/protobuf

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
  list of conditions and the following disclaimer in the documentation and/or
  other materials provided with the distribution.

* Neither the name of Google Inc. nor the names of its contributors may be used
  to endorse or promote products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

grpc-go (https://github.com/grpc/grpc-go)

Copyright 2014, Google Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
  list of conditions and the following disclaimer in the documentation and/or
  other materials provided with the distribution.

* Neither the name of Google Inc. nor the names of its contributors may be used
  to endorse or promote products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
`
<commit_msg>Added license information for the gogo/protobuf package.<commit_after>package mutagen

// LegalNotice provides license notices for Mutagen itself and any third-party
// dependencies.
const LegalNotice = `Mutagen

Copyright (c) 2016 Jacob Howard. All rights reserved.

Released under the terms of the MIT License.

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Mutagen makes use of the following third-party software:

Go, the Go standard library, and the Go net subrepository (https://golang.org/)

Copyright (c) 2009 The Go Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

* Neither the name of Google Inc. nor the names of its contributors may be used
  to endorse or promote products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Additional IP Rights Grant (Patents)

"This implementation" means the copyrightable works distributed by Google as
part of the Go project.

Google hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
royalty-free, irrevocable (except as stated in this section) patent license to
make, have made, use, offer to sell, sell, import, transfer and otherwise run,
modify and propagate the contents of this implementation of Go, where such
license applies only to those patent claims, both currently owned or controlled
by Google and acquired in the future, licensable by Google that are necessarily
infringed by this implementation of Go. This grant does not include claims that
would be infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or order or
agree to the institution of patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that this implementation of
Go or any code incorporated within this implementation of Go constitutes direct
or contributory patent infringement, or inducement of patent infringement, then
any patent rights granted to you under this License for this implementation of
Go shall terminate as of the date such litigation is filed.

errors (https://github.com/pkg/errors)

Copyright (c) 2015, Dave Cheney <dave@cheney.net>
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
  list of conditions and the following disclaimer in the documentation and/or
  other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

pflag (https://github.com/ogier/pflag)

Copyright (c) 2012 Alex Ogier. All rights reserved.
Copyright (c) 2012 The Go Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
  list of conditions and the following disclaimer in the documentation and/or
  other materials provided with the distribution.

* Neither the name of Google Inc. nor the names of its contributors may be used
  to endorse or promote products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

golang-levenshtein (https://github.com/texttheater/golang-levenshtein)

The MIT License (MIT)

Copyright (c) 2013 Kilian Evang and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

protobuf (https://github.com/golang/protobuf)

Go support for Protocol Buffers - Google's data interchange format

Copyright 2010 The Go Authors.  All rights reserved.
https://github.com/golang/protobuf

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
  list of conditions and the following disclaimer in the documentation and/or
  other materials provided with the distribution.

* Neither the name of Google Inc. nor the names of its contributors may be used
  to endorse or promote products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

gogo/protobuf (https://github.com/gogo/protobuf)

Protocol Buffers for Go with Gadgets

Copyright (c) 2013, The GoGo Authors. All rights reserved.
http://github.com/gogo/protobuf

Go support for Protocol Buffers - Google's data interchange format

Copyright 2010 The Go Authors.  All rights reserved.
https://github.com/golang/protobuf

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
  list of conditions and the following disclaimer in the documentation and/or
  other materials provided with the distribution.

* Neither the name of Google Inc. nor the names of its contributors may be used
  to endorse or promote products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

grpc-go (https://github.com/grpc/grpc-go)

Copyright 2014, Google Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
  list of conditions and the following disclaimer in the documentation and/or
  other materials provided with the distribution.

* Neither the name of Google Inc. nor the names of its contributors may be used
  to endorse or promote products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
`
<|endoftext|>


<commit_before>package algebra

import (
	"fmt"
	"unicode"
)

const (
	NumberToken         = "Number"
	SkipToken           = "Skip"
	LeftBracketToken    = "LeftBracket"
	RightBracketToken   = "RightBracket"
	AdditionToken       = "Addition"
	SubtractionToken    = "Subtraction"
	MultiplicationToken = "Multiplication"
)

type Token struct {
	Name     string
	Contents string
}

func (t Token) Type(n string) bool {
	if n == t.Name {
		return true
	}

	return false
}

type Lexer struct {
	source   string
	location int
}

func (lex *Lexer) Lex() []Token {
	return lex.lex()
}

func (lex *Lexer) lex() []Token {
	var stream []Token
	for !lex.End() {
		c := lex.source[lex.location]

		if lex.isNumber(c) {
			stream = append(stream, lex.number())
			continue
		}

		if lex.isBrackets(c) {
			stream = append(stream, lex.brackets())
			continue
		}

		if lex.isAddition(c) {
			stream = append(stream, lex.addition())
			continue
		}

		if lex.isSubtraction(c) {
			stream = append(stream, lex.subtraction())
			continue
		}

		if lex.isMultiplication(c) {
			stream = append(stream, lex.multiplication())
			continue
		}

		if lex.isWhitespace(c) {
			stream = append(stream, lex.whitespace())
			continue
		}

		fmt.Println("Invalid token!")
		lex.Next()
	}

	return stream
}

func (lex *Lexer) addition() Token {
	lex.Next()

	return Token{AdditionToken, "+"}
}

func (lex *Lexer) subtraction() Token {
	lex.Next()

	return Token{SubtractionToken, "-"}
}

func (lex *Lexer) multiplication() Token {
	lex.Next()

	return Token{MultiplicationToken, "*"}
}

func (lex *Lexer) whitespace() Token {
	var content string
	for !lex.End() && lex.isWhitespace(lex.source[lex.location]) {
		content += string(lex.source[lex.location])
		lex.Next()
	}

	return Token{SkipToken, content}
}

func (lex *Lexer) brackets() Token {
	c := lex.source[lex.location]

	lex.Next()
	if c == '(' {
		return Token{RightBracketToken, "("}
	}

	return Token{LeftBracketToken, ")"}
}

func (lex *Lexer) number() Token {
	var content string

	for !lex.End() && lex.isNumber(lex.source[lex.location]) {
		content += string(lex.source[lex.location])
		lex.Next()
	}

	return Token{NumberToken, content}
}

func (lex *Lexer) isSubtraction(c uint8) bool {
	if c == '-' {
		return true
	}

	return false
}

func (lex *Lexer) isAddition(c uint8) bool {
	if c == '+' {
		return true
	}

	return false
}

func (lex *Lexer) isMultiplication(c uint8) bool {
	if c == '*' {
		return true
	}

	return false
}

func (lex *Lexer) isWhitespace(c uint8) bool {
	return unicode.IsSpace(rune(c))
}

func (lex *Lexer) isBrackets(c uint8) bool {
	if c == '(' || c == ')' {
		return true
	}

	return false
}

func (lex *Lexer) isNumber(c uint8) bool {
	if c == '-' && unicode.IsNumber(rune(lex.source[lex.location+1])) {
		lex.Next()
		c = lex.source[lex.location+1]
	}

	if unicode.IsNumber(rune(c)) {
		return true
	}

	return false
}

func (lex *Lexer) End() bool {
	if lex.location >= len(lex.source) {
		return true
	}

	return false
}

func (lex *Lexer) Next() {
	lex.location += 1
}
<commit_msg>lexer: fix negative number detection<commit_after>package algebra

import (
	"fmt"
	"unicode"
)

const (
	NumberToken         = "Number"
	SkipToken           = "Skip"
	LeftBracketToken    = "LeftBracket"
	RightBracketToken   = "RightBracket"
	AdditionToken       = "Addition"
	SubtractionToken    = "Subtraction"
	MultiplicationToken = "Multiplication"
)

type Token struct {
	Name     string
	Contents string
}

func (t Token) Type(n string) bool {
	if n == t.Name {
		return true
	}

	return false
}

type Lexer struct {
	source   string
	location int
}

func (lex *Lexer) Lex() []Token {
	return lex.lex()
}

func (lex *Lexer) lex() []Token {
	var stream []Token
	for !lex.End() {
		c := lex.source[lex.location]

		if lex.isNumber(c) {
			stream = append(stream, lex.number())
			continue
		}

		if lex.isBrackets(c) {
			stream = append(stream, lex.brackets())
			continue
		}

		if lex.isAddition(c) {
			stream = append(stream, lex.addition())
			continue
		}

		if lex.isSubtraction(c) {
			stream = append(stream, lex.subtraction())
			continue
		}

		if lex.isMultiplication(c) {
			stream = append(stream, lex.multiplication())
			continue
		}

		if lex.isWhitespace(c) {
			stream = append(stream, lex.whitespace())
			continue
		}

		fmt.Println("Invalid token!")
		lex.Next()
	}

	return stream
}

func (lex *Lexer) addition() Token {
	lex.Next()

	return Token{AdditionToken, "+"}
}

func (lex *Lexer) subtraction() Token {
	lex.Next()

	return Token{SubtractionToken, "-"}
}

func (lex *Lexer) multiplication() Token {
	lex.Next()

	return Token{MultiplicationToken, "*"}
}

func (lex *Lexer) whitespace() Token {
	var content string
	for !lex.End() && lex.isWhitespace(lex.source[lex.location]) {
		content += string(lex.source[lex.location])
		lex.Next()
	}

	return Token{SkipToken, content}
}

func (lex *Lexer) brackets() Token {
	c := lex.source[lex.location]

	lex.Next()
	if c == '(' {
		return Token{RightBracketToken, "("}
	}

	return Token{LeftBracketToken, ")"}
}

func (lex *Lexer) number() Token {
	var content string

	for !lex.End() && lex.isNumber(lex.source[lex.location]) {
		content += string(lex.source[lex.location])
		lex.Next()
	}

	return Token{NumberToken, content}
}

func (lex *Lexer) isSubtraction(c uint8) bool {
	if c == '-' {
		return true
	}

	return false
}

func (lex *Lexer) isAddition(c uint8) bool {
	if c == '+' {
		return true
	}

	return false
}

func (lex *Lexer) isMultiplication(c uint8) bool {
	if c == '*' {
		return true
	}

	return false
}

func (lex *Lexer) isWhitespace(c uint8) bool {
	return unicode.IsSpace(rune(c))
}

func (lex *Lexer) isBrackets(c uint8) bool {
	if c == '(' || c == ')' {
		return true
	}

	return false
}

func (lex *Lexer) isNumber(c uint8) bool {
	if c == '-' && unicode.IsNumber(rune(lex.source[lex.location+1])) {
		return true
	}

	if unicode.IsNumber(rune(c)) {
		return true
	}

	return false
}

func (lex *Lexer) End() bool {
	if lex.location >= len(lex.source) {
		return true
	}

	return false
}

func (lex *Lexer) Next() {
	lex.location += 1
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/ymotongpoo/goltsv"
	"regexp"
	"strings"
)

var KEYS_LIST = regexp.MustCompile(`(?:[^,\\]|\\.)*`)

func ParseKeysList(list string) []string {
	keys := KEYS_LIST.FindAllString(list, -1)
	for i := 0; i < len(keys); i++ {
		keys[i] = strings.Replace(keys[i], `\,`, `,`, -1)
		keys[i] = strings.Replace(keys[i], `\\`, `\`, -1)
	}
	return keys
}

type LTSVScanner struct {
	keys   []string
	line   string
	err    error
	reader *goltsv.LTSVReader
}
<commit_msg>Implement NewLTSVScanner<commit_after>package main

import (
	"io"
	"regexp"
	"strings"

	"github.com/ymotongpoo/goltsv"
)

var KEYS_LIST = regexp.MustCompile(`(?:[^,\\]|\\.)*`)

func ParseKeysList(list string) []string {
	keys := KEYS_LIST.FindAllString(list, -1)
	for i := 0; i < len(keys); i++ {
		keys[i] = strings.Replace(keys[i], `\,`, `,`, -1)
		keys[i] = strings.Replace(keys[i], `\\`, `\`, -1)
	}
	return keys
}

type LTSVScanner struct {
	keys   []string
	line   string
	err    error
	reader *goltsv.LTSVReader
}

func NewLTSVScanner(keys []string, r io.Reader) *LTSVScanner {
	return &LTSVScanner{
		keys:   keys,
		reader: goltsv.NewReader(r),
	}
}
<|endoftext|>