<commit_before>/*
Copyright 2015 The ContainerOps Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package models

import (
	"time"
)

//
type DockerV2 struct {
	Id            int64      `json:"id" gorm:"primary_key"`
	Namespace     string     `json:"namespace" sql:"not null;type:varchar(255)"`
	Repository    string     `json:"repository" sql:"not null;type:varchar(255)"`
	SchemaVersion string     `json:"schemaversion" sql:"not null;type:varchar(255)"`
	Manifests     string     `json:"manifests" sql:"null;type:text"`
	Agent         string     `json:"agent" sql:"null;type:text"`
	Description   string     `json:"description" sql:"null;type:text"`
	Size          int64      `json:"size" sql:"default:0"`
	Locked        bool       `json:"locked" sql:"default:false"`
	CreatedAt     time.Time  `json:"created" sql:""`
	UpdatedAt     time.Time  `json:"updated" sql:""`
	DeletedAt     *time.Time `json:"deleted" sql:"index"`
}

//
func (*DockerV2) TableName() string {
	return "docker_V2"
}

//
type DockerImageV2 struct {
	Id              int64      `json:"id" gorm:"primary_key"`
	ImageId         string     `json:"imageid" sql:"unique;type:varchar(255)"`
	BlobSum         string     `json:"blobsum" sql:"null;unique;type:varchar(255)"`
	V1Compatibility string     `json:"v1compatibility" sql:"null;type:text"`
	Path            string     `json:"path" sql:"null;type:text"`
	OSS             string     `json:"oss" sql:"null;type:text"`
	Size            int64      `json:"size" sql:"default:0"`
	Locked          bool       `json:"locked" sql:"default:false"`
	CreatedAt       time.Time  `json:"created" sql:""`
	UpdatedAt       time.Time  `json:"updated" sql:""`
	DeletedAt       *time.Time `json:"deleted" sql:"index"`
}

//
func (*DockerImageV2) TableName() string {
	return "docker_image_v2"
}

//
type DockerTagV2 struct {
	Id        int64      `json:"id" gorm:"primary_key"`
	DockerV2  int64      `json:"dockerv2" sql:"not null"`
	Tag       string     `json:"tag" sql:"not null;type:varchar(255)"`
	ImageId   string     `json:"imageid" sql:"not null;type:varchar(255)"`
	Manifest  string     `json:"manifest" sql:"null;type:text"`
	Schema    int64      `json:"schema" sql:""`
	CreatedAt time.Time  `json:"created" sql:""`
	UpdatedAt time.Time  `json:"updated" sql:""`
	DeletedAt *time.Time `json:"deleted" sql:"index"`
}

//
func (*DockerTagV2) TableName() string {
	return "docker_tag_V2"
}
<commit_msg>Add index for namespace+repository in Docker Distribution V2 repository.<commit_after>/*
Copyright 2015 The ContainerOps Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package models

import (
	"time"
)

//Docker
type DockerV2 struct {
	Id            int64      `json:"id" gorm:"primary_key"`
	Namespace     string     `json:"namespace" sql:"not null;type:varchar(255)"  gorm:"unique_index:v2_repository"`
	Repository    string     `json:"repository" sql:"not null;type:varchar(255)"  gorm:"unique_index:v2_repository"`
	SchemaVersion string     `json:"schemaversion" sql:"not null;type:varchar(255)"`
	Manifests     string     `json:"manifests" sql:"null;type:text"`
	Agent         string     `json:"agent" sql:"null;type:text"`
	Description   string     `json:"description" sql:"null;type:text"`
	Size          int64      `json:"size" sql:"default:0"`
	Locked        bool       `json:"locked" sql:"default:false"`
	CreatedAt     time.Time  `json:"created" sql:""`
	UpdatedAt     time.Time  `json:"updated" sql:""`
	DeletedAt     *time.Time `json:"deleted" sql:"index"`
}

//
func (*DockerV2) TableName() string {
	return "docker_V2"
}

//
type DockerImageV2 struct {
	Id              int64      `json:"id" gorm:"primary_key"`
	ImageId         string     `json:"imageid" sql:"unique;type:varchar(255)"`
	BlobSum         string     `json:"blobsum" sql:"null;unique;type:varchar(255)"`
	V1Compatibility string     `json:"v1compatibility" sql:"null;type:text"`
	Path            string     `json:"path" sql:"null;type:text"`
	OSS             string     `json:"oss" sql:"null;type:text"`
	Size            int64      `json:"size" sql:"default:0"`
	Locked          bool       `json:"locked" sql:"default:false"`
	CreatedAt       time.Time  `json:"created" sql:""`
	UpdatedAt       time.Time  `json:"updated" sql:""`
	DeletedAt       *time.Time `json:"deleted" sql:"index"`
}

//
func (*DockerImageV2) TableName() string {
	return "docker_image_v2"
}

//
type DockerTagV2 struct {
	Id        int64      `json:"id" gorm:"primary_key"`
	DockerV2  int64      `json:"dockerv2" sql:"not null"`
	Tag       string     `json:"tag" sql:"not null;type:varchar(255)"`
	ImageId   string     `json:"imageid" sql:"not null;type:varchar(255)"`
	Manifest  string     `json:"manifest" sql:"null;type:text"`
	Schema    int64      `json:"schema" sql:""`
	CreatedAt time.Time  `json:"created" sql:""`
	UpdatedAt time.Time  `json:"updated" sql:""`
	DeletedAt *time.Time `json:"deleted" sql:"index"`
}

//
func (*DockerTagV2) TableName() string {
	return "docker_tag_V2"
}
<|endoftext|>


<commit_before>package gocb

import (
	"context"
	"time"

	gocbcore "github.com/couchbase/gocbcore/v8"
)

// BinaryCollection is a set of binary operations.
type BinaryCollection struct {
	*Collection
}

// AppendOptions are the options available to the Append operation.
type AppendOptions struct {
	Timeout         time.Duration
	Context         context.Context
	DurabilityLevel DurabilityLevel
	PersistTo       uint
	ReplicateTo     uint
}

// Append appends a byte value to a document.
func (c *BinaryCollection) Append(key string, val []byte, opts *AppendOptions) (mutOut *MutationResult, errOut error) {
	if opts == nil {
		opts = &AppendOptions{}
	}

	// Only update ctx if necessary, this means that the original ctx.Done() signal will be triggered as expected
	ctx, cancel := c.context(opts.Context, opts.Timeout)
	if cancel != nil {
		defer cancel()
	}

	err := c.verifyObserveOptions(opts.PersistTo, opts.ReplicateTo, opts.DurabilityLevel)
	if err != nil {
		return nil, err
	}

	res, err := c.append(ctx, key, val, *opts)
	if err != nil {
		return nil, err
	}

	if opts.PersistTo == 0 && opts.ReplicateTo == 0 {
		return res, nil
	}
	return res, c.durability(durabilitySettings{
		ctx:            opts.Context,
		key:            key,
		cas:            res.Cas(),
		mt:             res.MutationToken(),
		replicaTo:      opts.ReplicateTo,
		persistTo:      opts.PersistTo,
		forDelete:      true,
		scopeName:      c.scopeName(),
		collectionName: c.name(),
	})
}

func (c *BinaryCollection) append(ctx context.Context, key string, val []byte, opts AppendOptions) (mutOut *MutationResult, errOut error) {
	agent, err := c.getKvProvider()
	if err != nil {
		return nil, err
	}

	coerced, durabilityTimeout := c.durabilityTimeout(ctx, opts.DurabilityLevel)
	if coerced {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, time.Duration(durabilityTimeout)*time.Millisecond)
		defer cancel()
	}

	ctrl := c.newOpManager(ctx)
	err = ctrl.wait(agent.AppendEx(gocbcore.AdjoinOptions{
		Key:                    []byte(key),
		Value:                  val,
		CollectionName:         c.name(),
		ScopeName:              c.scopeName(),
		DurabilityLevel:        gocbcore.DurabilityLevel(opts.DurabilityLevel),
		DurabilityLevelTimeout: durabilityTimeout,
	}, func(res *gocbcore.AdjoinResult, err error) {
		if err != nil {
			errOut = err
			ctrl.resolve()
			return
		}

		mutTok := MutationToken{
			token:      res.MutationToken,
			bucketName: c.sb.BucketName,
		}
		mutOut = &MutationResult{
			mt: mutTok,
		}
		mutOut.cas = Cas(res.Cas)

		ctrl.resolve()
	}))
	if err != nil {
		errOut = err
	}

	return
}

// PrependOptions are the options available to the Prepend operation.
type PrependOptions struct {
	Timeout         time.Duration
	Context         context.Context
	DurabilityLevel DurabilityLevel
	PersistTo       uint
	ReplicateTo     uint
}

// Prepend prepends a byte value to a document.
func (c *BinaryCollection) Prepend(key string, val []byte, opts *PrependOptions) (mutOut *MutationResult, errOut error) {
	if opts == nil {
		opts = &PrependOptions{}
	}

	// Only update ctx if necessary, this means that the original ctx.Done() signal will be triggered as expected
	ctx, cancel := c.context(opts.Context, opts.Timeout)
	if cancel != nil {
		defer cancel()
	}

	err := c.verifyObserveOptions(opts.PersistTo, opts.ReplicateTo, opts.DurabilityLevel)
	if err != nil {
		return nil, err
	}

	res, err := c.prepend(ctx, key, val, *opts)
	if err != nil {
		return nil, err
	}

	if opts.PersistTo == 0 && opts.ReplicateTo == 0 {
		return res, nil
	}
	return res, c.durability(durabilitySettings{
		ctx:            opts.Context,
		key:            key,
		cas:            res.Cas(),
		mt:             res.MutationToken(),
		replicaTo:      opts.ReplicateTo,
		persistTo:      opts.PersistTo,
		forDelete:      true,
		scopeName:      c.scopeName(),
		collectionName: c.name(),
	})
}

func (c *BinaryCollection) prepend(ctx context.Context, key string, val []byte, opts PrependOptions) (mutOut *MutationResult, errOut error) {
	agent, err := c.getKvProvider()
	if err != nil {
		return nil, err
	}

	coerced, durabilityTimeout := c.durabilityTimeout(ctx, opts.DurabilityLevel)
	if coerced {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, time.Duration(durabilityTimeout)*time.Millisecond)
		defer cancel()
	}

	ctrl := c.newOpManager(ctx)
	err = ctrl.wait(agent.PrependEx(gocbcore.AdjoinOptions{
		Key:                    []byte(key),
		Value:                  val,
		CollectionName:         c.name(),
		ScopeName:              c.scopeName(),
		DurabilityLevel:        gocbcore.DurabilityLevel(opts.DurabilityLevel),
		DurabilityLevelTimeout: durabilityTimeout,
	}, func(res *gocbcore.AdjoinResult, err error) {
		if err != nil {
			errOut = err
			ctrl.resolve()
			return
		}

		mutTok := MutationToken{
			token:      res.MutationToken,
			bucketName: c.sb.BucketName,
		}
		mutOut = &MutationResult{
			mt: mutTok,
		}
		mutOut.cas = Cas(res.Cas)

		ctrl.resolve()
	}))
	if err != nil {
		errOut = err
	}

	return
}

// CounterOptions are the options available to the Counter operation.
type CounterOptions struct {
	Timeout time.Duration
	Context context.Context
	// Expiration is the length of time in seconds that the document will be stored in Couchbase.
	// A value of 0 will set the document to never expire.
	Expiration uint32
	// Initial, if non-negative, is the `initial` value to use for the document if it does not exist.
	// If present, this is the value that will be returned by a successful operation.
	Initial int64
	// Delta is the value to use for incrementing/decrementing if Initial is not present.
	Delta           uint64
	DurabilityLevel DurabilityLevel
	PersistTo       uint
	ReplicateTo     uint
}

// Increment performs an atomic addition for an integer document. Passing a
// non-negative `initial` value will cause the document to be created if it did not
// already exist.
func (c *BinaryCollection) Increment(key string, opts *CounterOptions) (countOut *CounterResult, errOut error) {
	if opts == nil {
		opts = &CounterOptions{}
	}

	// Only update ctx if necessary, this means that the original ctx.Done() signal will be triggered as expected
	ctx, cancel := c.context(opts.Context, opts.Timeout)
	if cancel != nil {
		defer cancel()
	}

	res, err := c.increment(ctx, key, *opts)
	if err != nil {
		return nil, err
	}

	if opts.PersistTo == 0 && opts.ReplicateTo == 0 {
		return res, nil
	}
	return res, c.durability(durabilitySettings{
		ctx:            opts.Context,
		key:            key,
		cas:            res.Cas(),
		mt:             res.MutationToken(),
		replicaTo:      opts.ReplicateTo,
		persistTo:      opts.PersistTo,
		forDelete:      true,
		scopeName:      c.scopeName(),
		collectionName: c.name(),
	})
}

func (c *BinaryCollection) increment(ctx context.Context, key string, opts CounterOptions) (countOut *CounterResult, errOut error) {
	realInitial := uint64(0xFFFFFFFFFFFFFFFF)
	if opts.Initial >= 0 {
		realInitial = uint64(opts.Initial)
	}

	agent, err := c.getKvProvider()
	if err != nil {
		return nil, err
	}

	coerced, durabilityTimeout := c.durabilityTimeout(ctx, opts.DurabilityLevel)
	if coerced {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, time.Duration(durabilityTimeout)*time.Millisecond)
		defer cancel()
	}

	ctrl := c.newOpManager(ctx)
	err = ctrl.wait(agent.IncrementEx(gocbcore.CounterOptions{
		Key:                    []byte(key),
		Delta:                  opts.Delta,
		Initial:                realInitial,
		Expiry:                 opts.Expiration,
		CollectionName:         c.name(),
		ScopeName:              c.scopeName(),
		DurabilityLevel:        gocbcore.DurabilityLevel(opts.DurabilityLevel),
		DurabilityLevelTimeout: durabilityTimeout,
	}, func(res *gocbcore.CounterResult, err error) {
		if err != nil {
			errOut = err
			ctrl.resolve()
			return
		}

		mutTok := MutationToken{
			token:      res.MutationToken,
			bucketName: c.sb.BucketName,
		}
		countOut = &CounterResult{
			MutationResult: MutationResult{
				mt: mutTok,
				Result: Result{
					cas: Cas(res.Cas),
				},
			},
			content: res.Value,
		}

		ctrl.resolve()
	}))
	if err != nil {
		errOut = err
	}

	return
}

// Decrement performs an atomic subtraction for an integer document. Passing a
// non-negative `initial` value will cause the document to be created if it did not
// already exist.
func (c *BinaryCollection) Decrement(key string, opts *CounterOptions) (countOut *CounterResult, errOut error) {
	if opts == nil {
		opts = &CounterOptions{}
	}

	// Only update ctx if necessary, this means that the original ctx.Done() signal will be triggered as expected
	ctx, cancel := c.context(opts.Context, opts.Timeout)
	if cancel != nil {
		defer cancel()
	}

	err := c.verifyObserveOptions(opts.PersistTo, opts.ReplicateTo, opts.DurabilityLevel)
	if err != nil {
		return nil, err
	}

	res, err := c.decrement(ctx, key, *opts)
	if err != nil {
		return nil, err
	}

	if opts.PersistTo == 0 && opts.ReplicateTo == 0 {
		return res, nil
	}
	return res, c.durability(durabilitySettings{
		ctx:            opts.Context,
		key:            key,
		cas:            res.Cas(),
		mt:             res.MutationToken(),
		replicaTo:      opts.ReplicateTo,
		persistTo:      opts.PersistTo,
		forDelete:      true,
		scopeName:      c.scopeName(),
		collectionName: c.name(),
	})
}

func (c *BinaryCollection) decrement(ctx context.Context, key string, opts CounterOptions) (countOut *CounterResult, errOut error) {
	agent, err := c.getKvProvider()
	if err != nil {
		return nil, err
	}

	realInitial := uint64(0xFFFFFFFFFFFFFFFF)
	if opts.Initial >= 0 {
		realInitial = uint64(opts.Initial)
	}

	coerced, durabilityTimeout := c.durabilityTimeout(ctx, opts.DurabilityLevel)
	if coerced {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, time.Duration(durabilityTimeout)*time.Millisecond)
		defer cancel()
	}

	ctrl := c.newOpManager(ctx)
	err = ctrl.wait(agent.DecrementEx(gocbcore.CounterOptions{
		Key:                    []byte(key),
		Delta:                  opts.Delta,
		Initial:                realInitial,
		Expiry:                 opts.Expiration,
		CollectionName:         c.name(),
		ScopeName:              c.scopeName(),
		DurabilityLevel:        gocbcore.DurabilityLevel(opts.DurabilityLevel),
		DurabilityLevelTimeout: durabilityTimeout,
	}, func(res *gocbcore.CounterResult, err error) {
		if err != nil {
			errOut = err
			ctrl.resolve()
			return
		}

		mutTok := MutationToken{
			token:      res.MutationToken,
			bucketName: c.sb.BucketName,
		}
		countOut = &CounterResult{
			MutationResult: MutationResult{
				mt: mutTok,
				Result: Result{
					cas: Cas(res.Cas),
				},
			},
			content: res.Value,
		}

		ctrl.resolve()
	}))
	if err != nil {
		errOut = err
	}

	return
}
<commit_msg>GOCBC-567: Add Cas to BinaryCollection operations<commit_after>package gocb

import (
	"context"
	"time"

	gocbcore "github.com/couchbase/gocbcore/v8"
)

// BinaryCollection is a set of binary operations.
type BinaryCollection struct {
	*Collection
}

// AppendOptions are the options available to the Append operation.
type AppendOptions struct {
	Timeout         time.Duration
	Context         context.Context
	DurabilityLevel DurabilityLevel
	PersistTo       uint
	ReplicateTo     uint
	Cas             Cas
}

// Append appends a byte value to a document.
func (c *BinaryCollection) Append(key string, val []byte, opts *AppendOptions) (mutOut *MutationResult, errOut error) {
	if opts == nil {
		opts = &AppendOptions{}
	}

	// Only update ctx if necessary, this means that the original ctx.Done() signal will be triggered as expected
	ctx, cancel := c.context(opts.Context, opts.Timeout)
	if cancel != nil {
		defer cancel()
	}

	err := c.verifyObserveOptions(opts.PersistTo, opts.ReplicateTo, opts.DurabilityLevel)
	if err != nil {
		return nil, err
	}

	res, err := c.append(ctx, key, val, *opts)
	if err != nil {
		return nil, err
	}

	if opts.PersistTo == 0 && opts.ReplicateTo == 0 {
		return res, nil
	}
	return res, c.durability(durabilitySettings{
		ctx:            opts.Context,
		key:            key,
		cas:            res.Cas(),
		mt:             res.MutationToken(),
		replicaTo:      opts.ReplicateTo,
		persistTo:      opts.PersistTo,
		forDelete:      true,
		scopeName:      c.scopeName(),
		collectionName: c.name(),
	})
}

func (c *BinaryCollection) append(ctx context.Context, key string, val []byte, opts AppendOptions) (mutOut *MutationResult, errOut error) {
	agent, err := c.getKvProvider()
	if err != nil {
		return nil, err
	}

	coerced, durabilityTimeout := c.durabilityTimeout(ctx, opts.DurabilityLevel)
	if coerced {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, time.Duration(durabilityTimeout)*time.Millisecond)
		defer cancel()
	}

	ctrl := c.newOpManager(ctx)
	err = ctrl.wait(agent.AppendEx(gocbcore.AdjoinOptions{
		Key:                    []byte(key),
		Value:                  val,
		CollectionName:         c.name(),
		ScopeName:              c.scopeName(),
		DurabilityLevel:        gocbcore.DurabilityLevel(opts.DurabilityLevel),
		DurabilityLevelTimeout: durabilityTimeout,
		Cas:                    gocbcore.Cas(opts.Cas),
	}, func(res *gocbcore.AdjoinResult, err error) {
		if err != nil {
			errOut = err
			ctrl.resolve()
			return
		}

		mutTok := MutationToken{
			token:      res.MutationToken,
			bucketName: c.sb.BucketName,
		}
		mutOut = &MutationResult{
			mt: mutTok,
		}
		mutOut.cas = Cas(res.Cas)

		ctrl.resolve()
	}))
	if err != nil {
		errOut = err
	}

	return
}

// PrependOptions are the options available to the Prepend operation.
type PrependOptions struct {
	Timeout         time.Duration
	Context         context.Context
	DurabilityLevel DurabilityLevel
	PersistTo       uint
	ReplicateTo     uint
	Cas             Cas
}

// Prepend prepends a byte value to a document.
func (c *BinaryCollection) Prepend(key string, val []byte, opts *PrependOptions) (mutOut *MutationResult, errOut error) {
	if opts == nil {
		opts = &PrependOptions{}
	}

	// Only update ctx if necessary, this means that the original ctx.Done() signal will be triggered as expected
	ctx, cancel := c.context(opts.Context, opts.Timeout)
	if cancel != nil {
		defer cancel()
	}

	err := c.verifyObserveOptions(opts.PersistTo, opts.ReplicateTo, opts.DurabilityLevel)
	if err != nil {
		return nil, err
	}

	res, err := c.prepend(ctx, key, val, *opts)
	if err != nil {
		return nil, err
	}

	if opts.PersistTo == 0 && opts.ReplicateTo == 0 {
		return res, nil
	}
	return res, c.durability(durabilitySettings{
		ctx:            opts.Context,
		key:            key,
		cas:            res.Cas(),
		mt:             res.MutationToken(),
		replicaTo:      opts.ReplicateTo,
		persistTo:      opts.PersistTo,
		forDelete:      true,
		scopeName:      c.scopeName(),
		collectionName: c.name(),
	})
}

func (c *BinaryCollection) prepend(ctx context.Context, key string, val []byte, opts PrependOptions) (mutOut *MutationResult, errOut error) {
	agent, err := c.getKvProvider()
	if err != nil {
		return nil, err
	}

	coerced, durabilityTimeout := c.durabilityTimeout(ctx, opts.DurabilityLevel)
	if coerced {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, time.Duration(durabilityTimeout)*time.Millisecond)
		defer cancel()
	}

	ctrl := c.newOpManager(ctx)
	err = ctrl.wait(agent.PrependEx(gocbcore.AdjoinOptions{
		Key:                    []byte(key),
		Value:                  val,
		CollectionName:         c.name(),
		ScopeName:              c.scopeName(),
		DurabilityLevel:        gocbcore.DurabilityLevel(opts.DurabilityLevel),
		DurabilityLevelTimeout: durabilityTimeout,
		Cas:                    gocbcore.Cas(opts.Cas),
	}, func(res *gocbcore.AdjoinResult, err error) {
		if err != nil {
			errOut = err
			ctrl.resolve()
			return
		}

		mutTok := MutationToken{
			token:      res.MutationToken,
			bucketName: c.sb.BucketName,
		}
		mutOut = &MutationResult{
			mt: mutTok,
		}
		mutOut.cas = Cas(res.Cas)

		ctrl.resolve()
	}))
	if err != nil {
		errOut = err
	}

	return
}

// CounterOptions are the options available to the Counter operation.
type CounterOptions struct {
	Timeout time.Duration
	Context context.Context
	// Expiration is the length of time in seconds that the document will be stored in Couchbase.
	// A value of 0 will set the document to never expire.
	Expiration uint32
	// Initial, if non-negative, is the `initial` value to use for the document if it does not exist.
	// If present, this is the value that will be returned by a successful operation.
	Initial int64
	// Delta is the value to use for incrementing/decrementing if Initial is not present.
	Delta           uint64
	DurabilityLevel DurabilityLevel
	PersistTo       uint
	ReplicateTo     uint
	Cas             Cas
}

// Increment performs an atomic addition for an integer document. Passing a
// non-negative `initial` value will cause the document to be created if it did not
// already exist.
func (c *BinaryCollection) Increment(key string, opts *CounterOptions) (countOut *CounterResult, errOut error) {
	if opts == nil {
		opts = &CounterOptions{}
	}

	// Only update ctx if necessary, this means that the original ctx.Done() signal will be triggered as expected
	ctx, cancel := c.context(opts.Context, opts.Timeout)
	if cancel != nil {
		defer cancel()
	}

	res, err := c.increment(ctx, key, *opts)
	if err != nil {
		return nil, err
	}

	if opts.PersistTo == 0 && opts.ReplicateTo == 0 {
		return res, nil
	}
	return res, c.durability(durabilitySettings{
		ctx:            opts.Context,
		key:            key,
		cas:            res.Cas(),
		mt:             res.MutationToken(),
		replicaTo:      opts.ReplicateTo,
		persistTo:      opts.PersistTo,
		forDelete:      true,
		scopeName:      c.scopeName(),
		collectionName: c.name(),
	})
}

func (c *BinaryCollection) increment(ctx context.Context, key string, opts CounterOptions) (countOut *CounterResult, errOut error) {
	realInitial := uint64(0xFFFFFFFFFFFFFFFF)
	if opts.Initial >= 0 {
		realInitial = uint64(opts.Initial)
	}

	agent, err := c.getKvProvider()
	if err != nil {
		return nil, err
	}

	coerced, durabilityTimeout := c.durabilityTimeout(ctx, opts.DurabilityLevel)
	if coerced {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, time.Duration(durabilityTimeout)*time.Millisecond)
		defer cancel()
	}

	ctrl := c.newOpManager(ctx)
	err = ctrl.wait(agent.IncrementEx(gocbcore.CounterOptions{
		Key:                    []byte(key),
		Delta:                  opts.Delta,
		Initial:                realInitial,
		Expiry:                 opts.Expiration,
		CollectionName:         c.name(),
		ScopeName:              c.scopeName(),
		DurabilityLevel:        gocbcore.DurabilityLevel(opts.DurabilityLevel),
		DurabilityLevelTimeout: durabilityTimeout,
		Cas:                    gocbcore.Cas(opts.Cas),
	}, func(res *gocbcore.CounterResult, err error) {
		if err != nil {
			errOut = err
			ctrl.resolve()
			return
		}

		mutTok := MutationToken{
			token:      res.MutationToken,
			bucketName: c.sb.BucketName,
		}
		countOut = &CounterResult{
			MutationResult: MutationResult{
				mt: mutTok,
				Result: Result{
					cas: Cas(res.Cas),
				},
			},
			content: res.Value,
		}

		ctrl.resolve()
	}))
	if err != nil {
		errOut = err
	}

	return
}

// Decrement performs an atomic subtraction for an integer document. Passing a
// non-negative `initial` value will cause the document to be created if it did not
// already exist.
func (c *BinaryCollection) Decrement(key string, opts *CounterOptions) (countOut *CounterResult, errOut error) {
	if opts == nil {
		opts = &CounterOptions{}
	}

	// Only update ctx if necessary, this means that the original ctx.Done() signal will be triggered as expected
	ctx, cancel := c.context(opts.Context, opts.Timeout)
	if cancel != nil {
		defer cancel()
	}

	err := c.verifyObserveOptions(opts.PersistTo, opts.ReplicateTo, opts.DurabilityLevel)
	if err != nil {
		return nil, err
	}

	res, err := c.decrement(ctx, key, *opts)
	if err != nil {
		return nil, err
	}

	if opts.PersistTo == 0 && opts.ReplicateTo == 0 {
		return res, nil
	}
	return res, c.durability(durabilitySettings{
		ctx:            opts.Context,
		key:            key,
		cas:            res.Cas(),
		mt:             res.MutationToken(),
		replicaTo:      opts.ReplicateTo,
		persistTo:      opts.PersistTo,
		forDelete:      true,
		scopeName:      c.scopeName(),
		collectionName: c.name(),
	})
}

func (c *BinaryCollection) decrement(ctx context.Context, key string, opts CounterOptions) (countOut *CounterResult, errOut error) {
	agent, err := c.getKvProvider()
	if err != nil {
		return nil, err
	}

	realInitial := uint64(0xFFFFFFFFFFFFFFFF)
	if opts.Initial >= 0 {
		realInitial = uint64(opts.Initial)
	}

	coerced, durabilityTimeout := c.durabilityTimeout(ctx, opts.DurabilityLevel)
	if coerced {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, time.Duration(durabilityTimeout)*time.Millisecond)
		defer cancel()
	}

	ctrl := c.newOpManager(ctx)
	err = ctrl.wait(agent.DecrementEx(gocbcore.CounterOptions{
		Key:                    []byte(key),
		Delta:                  opts.Delta,
		Initial:                realInitial,
		Expiry:                 opts.Expiration,
		CollectionName:         c.name(),
		ScopeName:              c.scopeName(),
		DurabilityLevel:        gocbcore.DurabilityLevel(opts.DurabilityLevel),
		DurabilityLevelTimeout: durabilityTimeout,
		Cas:                    gocbcore.Cas(opts.Cas),
	}, func(res *gocbcore.CounterResult, err error) {
		if err != nil {
			errOut = err
			ctrl.resolve()
			return
		}

		mutTok := MutationToken{
			token:      res.MutationToken,
			bucketName: c.sb.BucketName,
		}
		countOut = &CounterResult{
			MutationResult: MutationResult{
				mt: mutTok,
				Result: Result{
					cas: Cas(res.Cas),
				},
			},
			content: res.Value,
		}

		ctrl.resolve()
	}))
	if err != nil {
		errOut = err
	}

	return
}
<|endoftext|>


<commit_before>package termite

import (
	"fmt"
	"github.com/hanwen/go-fuse/fuse"
	"github.com/hanwen/termite/attr"
	"github.com/hanwen/termite/cba"
	"github.com/hanwen/termite/stats"
	"io"
	"log"
	"net/rpc"
	"sync"
	"time"
)

type RpcFs struct {
	fuse.DefaultFileSystem
	cache         *cba.Store
	client        *rpc.Client
	contentClient *cba.Client

	// Roots that we should try to fetch locally.
	localRoots []string
	timings    *stats.TimerStats
	attr       *attr.AttributeCache
	id         string

	// Below code is used to make sure we only fetch each hash
	// once.
	mutex    sync.Mutex
	cond     *sync.Cond
	fetching map[string]bool
}

func NewRpcFs(server *rpc.Client, cache *cba.Store, contentConn io.ReadWriteCloser) *RpcFs {
	me := &RpcFs{
		client:        server,
		contentClient: cache.NewClient(contentConn),
		timings:       stats.NewTimerStats(),
	}
	me.attr = attr.NewAttributeCache(
		func(n string) *attr.FileAttr {
			return me.fetchAttr(n)
		}, nil)
	me.cond = sync.NewCond(&me.mutex)
	me.fetching = map[string]bool{}
	me.cache = cache
	return me
}

func (me *RpcFs) Close() {
	me.client.Close()
	me.contentClient.Close()
}

func (me *RpcFs) FetchHash(a *attr.FileAttr) error {
	e := me.FetchHashOnce(a)
	if e == nil && a.Size < uint64(me.cache.Options.MemMaxSize) {
		me.cache.FaultIn(a.Hash)
	}
	return e
}

func (me *RpcFs) FetchHashOnce(a *attr.FileAttr) error {
	me.mutex.Lock()
	defer me.mutex.Unlock()
	h := a.Hash
	for !me.cache.HasHash(h) && me.fetching[h] {
		me.cond.Wait()
	}
	if me.cache.HasHash(h) {
		return nil
	}
	// TODO - necessary?  The contentClient already serializes.
	me.fetching[h] = true
	me.mutex.Unlock()

	log.Printf("Fetching contents for file %s: %x", a.Path, h)
	got, err := me.contentClient.Fetch(a.Hash, int64(a.Size))

	if !got && err == nil {
		log.Fatalf("RpcFs.FetchHashOnce: server did not have hash %x", a.Hash)
	}

	me.mutex.Lock()
	delete(me.fetching, h)
	me.cond.Broadcast()
	return err
}

func (me *RpcFs) Update(req *UpdateRequest, resp *UpdateResponse) error {
	me.updateFiles(req.Files)
	return nil
}

func (me *RpcFs) updateFiles(files []*attr.FileAttr) {
	me.attr.Update(files)
}

func (me *RpcFs) fetchAttr(n string) *attr.FileAttr {
	req := &AttrRequest{
		Name:   n,
		Origin: me.id,
	}
	start := time.Now()
	rep := &AttrResponse{}
	err := me.client.Call("FsServer.GetAttr", req, rep)
	dt := time.Now().Sub(start)
	me.timings.Log("FsServer.GetAttr", dt)
	if err != nil {
		// fatal?
		log.Println("GetAttr error:", err)
		return nil
	}

	var wanted *attr.FileAttr
	for _, attr := range rep.Attrs {
		if attr.Path == n {
			wanted = attr
		}
	}

	// TODO - if we got a deletion, we should refetch the parent.
	return wanted
}

////////////////////////////////////////////////////////////////
// FS API

func (me *RpcFs) String() string {
	return "RpcFs"
}

func (me *RpcFs) OpenDir(name string, context *fuse.Context) (chan fuse.DirEntry, fuse.Status) {
	r := me.attr.GetDir(name)
	if r.Deletion() {
		return nil, fuse.ENOENT
	}
	if !r.IsDir() {
		return nil, fuse.EINVAL
	}

	c := make(chan fuse.DirEntry, len(r.NameModeMap))
	for k, mode := range r.NameModeMap {
		c <- fuse.DirEntry{
			Name: k,
			Mode: uint32(mode),
		}
	}
	close(c)
	return c, fuse.OK
}

type rpcFsFile struct {
	fuse.File
	fuse.Attr
}

func (me *rpcFsFile) GetAttr() (*fuse.Attr, fuse.Status) {
	return &me.Attr, fuse.OK
}

func (me *rpcFsFile) String() string {
	return fmt.Sprintf("rpcFsFile(%s)", me.File.String())
}

func (me *RpcFs) Open(name string, flags uint32, context *fuse.Context) (fuse.File, fuse.Status) {
	if flags&fuse.O_ANYWRITE != 0 {
		return nil, fuse.EPERM
	}
	a := me.attr.Get(name)
	if a == nil {
		return nil, fuse.ENOENT
	}
	if a.Deletion() {
		return nil, fuse.ENOENT
	}

	if err := me.FetchHash(a); err != nil {
		log.Printf("Error fetching contents %v", err)
		return nil, fuse.EIO
	}

	if contents := me.cache.ContentsIfLoaded(a.Hash); contents != nil {
		fa := *a.Attr
		return &fuse.WithFlags{
			File: &rpcFsFile{
				fuse.NewDataFile(contents),
				fa,
			},
			FuseFlags: fuse.FOPEN_KEEP_CACHE,
		}, fuse.OK
	}
	fa := *a.Attr
	return &fuse.WithFlags{
		File: &rpcFsFile{
			&LazyLoopbackFile{Name: me.cache.Path(a.Hash)},
			fa,
		},
		FuseFlags: fuse.FOPEN_KEEP_CACHE,
	}, fuse.OK
}

func (me *RpcFs) Readlink(name string, context *fuse.Context) (string, fuse.Status) {
	a := me.attr.Get(name)
	if a == nil {
		return "", fuse.ENOENT
	}

	if a.Deletion() {
		return "", fuse.ENOENT
	}
	if !a.IsSymlink() {
		return "", fuse.EINVAL
	}

	// TODO - kick off getattr on destination.
	return a.Link, fuse.OK
}

func (me *RpcFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
	r := me.attr.Get(name)
	if r == nil {
		return nil, fuse.ENOENT
	}
	if r.Hash != "" {
		go me.FetchHash(r)
	}
	a := &fuse.Attr{}
	if !r.Deletion() {
		a = r.Attr
	} else {
		a = nil
	}
	return a, r.Status()
}

func (me *RpcFs) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
	if mode == fuse.F_OK {
		_, code := me.GetAttr(name, context)
		return code
	}
	if mode&fuse.W_OK != 0 {
		return fuse.EACCES
	}
	return fuse.OK
}
<commit_msg>Update for go-fuse changes.<commit_after>package termite

import (
	"fmt"
	"github.com/hanwen/go-fuse/fuse"
	"github.com/hanwen/go-fuse/raw"
	"github.com/hanwen/termite/attr"
	"github.com/hanwen/termite/cba"
	"github.com/hanwen/termite/stats"
	"io"
	"log"
	"net/rpc"
	"sync"
	"time"
)

type RpcFs struct {
	fuse.DefaultFileSystem
	cache         *cba.Store
	client        *rpc.Client
	contentClient *cba.Client

	// Roots that we should try to fetch locally.
	localRoots []string
	timings    *stats.TimerStats
	attr       *attr.AttributeCache
	id         string

	// Below code is used to make sure we only fetch each hash
	// once.
	mutex    sync.Mutex
	cond     *sync.Cond
	fetching map[string]bool
}

func NewRpcFs(server *rpc.Client, cache *cba.Store, contentConn io.ReadWriteCloser) *RpcFs {
	me := &RpcFs{
		client:        server,
		contentClient: cache.NewClient(contentConn),
		timings:       stats.NewTimerStats(),
	}
	me.attr = attr.NewAttributeCache(
		func(n string) *attr.FileAttr {
			return me.fetchAttr(n)
		}, nil)
	me.cond = sync.NewCond(&me.mutex)
	me.fetching = map[string]bool{}
	me.cache = cache
	return me
}

func (me *RpcFs) Close() {
	me.client.Close()
	me.contentClient.Close()
}

func (me *RpcFs) FetchHash(a *attr.FileAttr) error {
	e := me.FetchHashOnce(a)
	if e == nil && a.Size < uint64(me.cache.Options.MemMaxSize) {
		me.cache.FaultIn(a.Hash)
	}
	return e
}

func (me *RpcFs) FetchHashOnce(a *attr.FileAttr) error {
	me.mutex.Lock()
	defer me.mutex.Unlock()
	h := a.Hash
	for !me.cache.HasHash(h) && me.fetching[h] {
		me.cond.Wait()
	}
	if me.cache.HasHash(h) {
		return nil
	}
	// TODO - necessary?  The contentClient already serializes.
	me.fetching[h] = true
	me.mutex.Unlock()

	log.Printf("Fetching contents for file %s: %x", a.Path, h)
	got, err := me.contentClient.Fetch(a.Hash, int64(a.Size))

	if !got && err == nil {
		log.Fatalf("RpcFs.FetchHashOnce: server did not have hash %x", a.Hash)
	}

	me.mutex.Lock()
	delete(me.fetching, h)
	me.cond.Broadcast()
	return err
}

func (me *RpcFs) Update(req *UpdateRequest, resp *UpdateResponse) error {
	me.updateFiles(req.Files)
	return nil
}

func (me *RpcFs) updateFiles(files []*attr.FileAttr) {
	me.attr.Update(files)
}

func (me *RpcFs) fetchAttr(n string) *attr.FileAttr {
	req := &AttrRequest{
		Name:   n,
		Origin: me.id,
	}
	start := time.Now()
	rep := &AttrResponse{}
	err := me.client.Call("FsServer.GetAttr", req, rep)
	dt := time.Now().Sub(start)
	me.timings.Log("FsServer.GetAttr", dt)
	if err != nil {
		// fatal?
		log.Println("GetAttr error:", err)
		return nil
	}

	var wanted *attr.FileAttr
	for _, attr := range rep.Attrs {
		if attr.Path == n {
			wanted = attr
		}
	}

	// TODO - if we got a deletion, we should refetch the parent.
	return wanted
}

////////////////////////////////////////////////////////////////
// FS API

func (me *RpcFs) String() string {
	return "RpcFs"
}

func (me *RpcFs) OpenDir(name string, context *fuse.Context) (chan fuse.DirEntry, fuse.Status) {
	r := me.attr.GetDir(name)
	if r.Deletion() {
		return nil, fuse.ENOENT
	}
	if !r.IsDir() {
		return nil, fuse.EINVAL
	}

	c := make(chan fuse.DirEntry, len(r.NameModeMap))
	for k, mode := range r.NameModeMap {
		c <- fuse.DirEntry{
			Name: k,
			Mode: uint32(mode),
		}
	}
	close(c)
	return c, fuse.OK
}

type rpcFsFile struct {
	fuse.File
	fuse.Attr
}

func (me *rpcFsFile) GetAttr() (*fuse.Attr, fuse.Status) {
	return &me.Attr, fuse.OK
}

func (me *rpcFsFile) String() string {
	return fmt.Sprintf("rpcFsFile(%s)", me.File.String())
}

func (me *RpcFs) Open(name string, flags uint32, context *fuse.Context) (fuse.File, fuse.Status) {
	if flags&fuse.O_ANYWRITE != 0 {
		return nil, fuse.EPERM
	}
	a := me.attr.Get(name)
	if a == nil {
		return nil, fuse.ENOENT
	}
	if a.Deletion() {
		return nil, fuse.ENOENT
	}

	if err := me.FetchHash(a); err != nil {
		log.Printf("Error fetching contents %v", err)
		return nil, fuse.EIO
	}

	if contents := me.cache.ContentsIfLoaded(a.Hash); contents != nil {
		fa := *a.Attr
		return &fuse.WithFlags{
			File: &rpcFsFile{
				fuse.NewDataFile(contents),
				fa,
			},
			FuseFlags: raw.FOPEN_KEEP_CACHE,
		}, fuse.OK
	}
	fa := *a.Attr
	return &fuse.WithFlags{
		File: &rpcFsFile{
			&LazyLoopbackFile{Name: me.cache.Path(a.Hash)},
			fa,
		},
		FuseFlags: raw.FOPEN_KEEP_CACHE,
	}, fuse.OK
}

func (me *RpcFs) Readlink(name string, context *fuse.Context) (string, fuse.Status) {
	a := me.attr.Get(name)
	if a == nil {
		return "", fuse.ENOENT
	}

	if a.Deletion() {
		return "", fuse.ENOENT
	}
	if !a.IsSymlink() {
		return "", fuse.EINVAL
	}

	// TODO - kick off getattr on destination.
	return a.Link, fuse.OK
}

func (me *RpcFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
	r := me.attr.Get(name)
	if r == nil {
		return nil, fuse.ENOENT
	}
	if r.Hash != "" {
		go me.FetchHash(r)
	}
	a := &fuse.Attr{}
	if !r.Deletion() {
		a = r.Attr
	} else {
		a = nil
	}
	return a, r.Status()
}

func (me *RpcFs) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
	if mode == raw.F_OK {
		_, code := me.GetAttr(name, context)
		return code
	}
	if mode&raw.W_OK != 0 {
		return fuse.EACCES
	}
	return fuse.OK
}
<|endoftext|>


<commit_before>// +build !pro,!ent

package agent

import "net/http"

// registerEnterpriseHandlers is a no-op for the oss release
func (s *HTTPServer) registerEnterpriseHandlers() {
	s.mux.HandleFunc("/v1/namespaces", s.wrap(s.entOnly))
	s.mux.HandleFunc("/v1/namespace", s.wrap(s.entOnly))
	s.mux.HandleFunc("/v1/namespace/", s.wrap(s.entOnly))

	s.mux.HandleFunc("/v1/sentinel/policies", s.wrap(s.entOnly))
	s.mux.HandleFunc("/v1/sentinel/policy/", s.wrap(s.entOnly))

	s.mux.HandleFunc("/v1/quotas", s.wrap(s.entOnly))
	s.mux.HandleFunc("/v1/quota-usages", s.wrap(s.entOnly))
	s.mux.HandleFunc("/v1/quota/", s.wrap(s.entOnly))
	s.mux.HandleFunc("/v1/quota", s.wrap(s.entOnly))
}

func (s *HTTPServer) entOnly(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
	return nil, CodedError(501, ErrEntOnly)
}
<commit_msg>inlude pro in http_oss.go<commit_after>// +build !ent

package agent

import "net/http"

// registerEnterpriseHandlers is a no-op for the oss release
func (s *HTTPServer) registerEnterpriseHandlers() {
	s.mux.HandleFunc("/v1/namespaces", s.wrap(s.entOnly))
	s.mux.HandleFunc("/v1/namespace", s.wrap(s.entOnly))
	s.mux.HandleFunc("/v1/namespace/", s.wrap(s.entOnly))

	s.mux.HandleFunc("/v1/sentinel/policies", s.wrap(s.entOnly))
	s.mux.HandleFunc("/v1/sentinel/policy/", s.wrap(s.entOnly))

	s.mux.HandleFunc("/v1/quotas", s.wrap(s.entOnly))
	s.mux.HandleFunc("/v1/quota-usages", s.wrap(s.entOnly))
	s.mux.HandleFunc("/v1/quota/", s.wrap(s.entOnly))
	s.mux.HandleFunc("/v1/quota", s.wrap(s.entOnly))
}

func (s *HTTPServer) entOnly(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
	return nil, CodedError(501, ErrEntOnly)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/lawrencecraft/terrainmodel/drawer"
	"github.com/lawrencecraft/terrainmodel/generator"
	"net/http"
	"runtime"
)

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	g := generator.NewDiamondSquareGenerator(1.0, 1025, 1025)
	http.HandleFunc("/map", func(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Content-Type", "image/png")
		d := drawer.NewPngDrawer(w)
		t, _ := g.Generate()
		d.Draw(t)
	})

	err := http.ListenAndServe(":8822", nil)
	if err != nil {
		panic(err)
	}
}
<commit_msg>Slight upgrades<commit_after>package main

import (
	"flag"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/negroni"
	"github.com/jingweno/negroni-gorelic"
	"github.com/lawrencecraft/terrainmodel/drawer"
	"github.com/lawrencecraft/terrainmodel/generator"
	"net/http"
	"runtime"
)

func main() {
	port := flag.Int("p", 8822, "Port to listen for connections")
	nrkey := flag.String("nrkey", "", "NewRelic license key")
	flag.Parse()
	log.SetLevel(log.InfoLevel)
	runtime.GOMAXPROCS(runtime.NumCPU())
	log.Info("Setting max procs to", runtime.NumCPU())

	g := generator.NewDiamondSquareGenerator(1.0, 1025, 1025)

	r := http.NewServeMux()
	r.HandleFunc("/map", func(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Content-Type", "image/png")
		d := drawer.NewPngDrawer(w)
		t, _ := g.Generate()
		d.Draw(t)
	})

	n := negroni.New()

	if *nrkey != "" {
		log.Info("Using NewRelic")
		n.Use(negronigorelic.New(*nrkey, "terrainworker", true))
	}

	n.UseHandler(r)

	n.Run(fmt.Sprintf(":%d", *port))
}
<|endoftext|>


<commit_before>package commands

import (
	"bytes"
	"fmt"
	"os"
	"sync"

	"github.com/github/git-lfs/git"
	"github.com/github/git-lfs/lfs"
	"github.com/github/git-lfs/vendor/_nuts/github.com/spf13/cobra"
)

var (
	pruneCmd = &cobra.Command{
		Use:   "prune",
		Short: "Deletes old LFS files from the local store",
		Run:   pruneCommand,
	}
	pruneDryRunArg      bool
	pruneVerboseArg     bool
	pruneVerifyArg      bool
	pruneDoNotVerifyArg bool
)

func pruneCommand(cmd *cobra.Command, args []string) {

	// Guts of this must be re-usable from fetch --prune so just parse & dispatch
	if pruneVerifyArg && pruneDoNotVerifyArg {
		Exit("Cannot specify both --verify-remote and --no-verify-remote")
	}

	verify := !pruneDoNotVerifyArg &&
		(lfs.Config.FetchPruneConfig().PruneVerifyRemoteAlways || pruneVerifyArg)

	prune(verify, pruneDryRunArg, pruneVerboseArg)

}

type PruneProgressType int

const (
	PruneProgressTypeLocal  = PruneProgressType(iota)
	PruneProgressTypeRetain = PruneProgressType(iota)
	PruneProgressTypeVerify = PruneProgressType(iota)
)

// Progress from a sub-task of prune
type PruneProgress struct {
	Type  PruneProgressType
	Count int // Number of items done
}
type PruneProgressChan chan PruneProgress

func prune(verifyRemote, dryRun, verbose bool) {
	localObjects := make([]*lfs.Pointer, 0, 100)
	retainedObjects := lfs.NewStringSetWithCapacity(100)
	var reachableObjects lfs.StringSet
	var taskwait sync.WaitGroup

	// Add all the base funcs to the waitgroup before starting them, in case
	// one completes really fast & hits 0 unexpectedly
	// each main process can Add() to the wg itself if it subdivides the task
	taskwait.Add(5) // 1..5: localObjects, current checkout, recent refs, unpushed, worktree
	if verifyRemote {
		taskwait.Add(1) // 6
	}

	progressChan := make(PruneProgressChan, 100)

	// Collect errors
	errorChan := make(chan error, 10)
	var errorwait sync.WaitGroup
	errorwait.Add(1)
	var taskErrors []error
	go pruneTaskCollectErrors(&taskErrors, errorChan, &errorwait)

	// Populate the single list of local objects
	go pruneTaskGetLocalObjects(&localObjects, progressChan, &taskwait)

	// Now find files to be retained from many sources
	retainChan := make(chan string, 100)

	go pruneTaskGetRetainedCurrentCheckout(retainChan, errorChan, &taskwait)
	go pruneTaskGetRetainedRecentRefs(retainChan, errorChan, &taskwait)
	go pruneTaskGetRetainedUnpushed(retainChan, errorChan, &taskwait)
	go pruneTaskGetRetainedWorktree(retainChan, errorChan, &taskwait)
	if verifyRemote {
		reachableObjects = lfs.NewStringSetWithCapacity(100)
		go pruneTaskGetReachableObjects(&reachableObjects, errorChan, &taskwait)
	}

	// Now collect all the retained objects, on separate wait
	var retainwait sync.WaitGroup
	retainwait.Add(1)
	go pruneTaskCollectRetained(&retainedObjects, retainChan, progressChan, &retainwait)

	// Report progress
	var progresswait sync.WaitGroup
	progresswait.Add(1)
	go pruneTaskDisplayProgress(progressChan, &progresswait)

	taskwait.Wait()   // wait for subtasks
	close(retainChan) // triggers retain collector to end now all tasks have
	retainwait.Wait() // make sure all retained objects added

	close(errorChan) // triggers error collector to end now all tasks have
	errorwait.Wait() // make sure all errors have been processed
	pruneCheckErrors(taskErrors)

	prunableObjects := make([]string, 0, len(localObjects)/2)

	// Build list of prunables (also queue for verify at same time if applicable)
	var verifyQueue *lfs.TransferQueue
	var verifiedObjects lfs.StringSet
	var totalSize int64
	var verboseOutput bytes.Buffer
	if verifyRemote && !dryRun {
		lfs.Config.CurrentRemote = lfs.Config.FetchPruneConfig().PruneRemoteName
		// build queue now, no estimates or progress output
		verifyQueue = lfs.NewDownloadCheckQueue(0, 0, true)
		verifiedObjects = lfs.NewStringSetWithCapacity(len(localObjects) / 2)
	}
	for _, pointer := range localObjects {
		if !retainedObjects.Contains(pointer.Oid) {
			prunableObjects = append(prunableObjects, pointer.Oid)
			totalSize += pointer.Size
			if verbose {
				// Save up verbose output for the end, spinner still going
				verboseOutput.WriteString(fmt.Sprintf("Prune %v ,%v", pointer.Oid, humanizeBytes(pointer.Size)))
			}
			if verifyRemote && !dryRun {
				verifyQueue.Add(lfs.NewDownloadCheckable(&lfs.WrappedPointer{Pointer: pointer}))
			}
		}
	}
	if verifyRemote && !dryRun {
		// this channel is filled with oids for which Check() succeeded & Transfer() was called
		verifyc := verifyQueue.Watch()
		var verifywait sync.WaitGroup
		verifywait.Add(1)
		go func() {
			for oid := range verifyc {
				verifiedObjects.Add(oid)
				progressChan <- PruneProgress{PruneProgressTypeVerify, 1}
			}
			verifywait.Done()
		}()
		verifyQueue.Wait()
		verifywait.Wait()
		close(progressChan) // after verify (uses spinner) but before check
		progresswait.Wait()
		pruneCheckVerified(prunableObjects, reachableObjects, verifiedObjects)
	} else {
		close(progressChan)
		progresswait.Wait()
	}

	if dryRun {
		Print("%d files would be pruned, %v", len(prunableObjects), humanizeBytes(totalSize))
	} else {
		Print("Pruning %d files, %v", len(prunableObjects), humanizeBytes(totalSize))
		pruneDeleteFiles(prunableObjects)
	}

}

func pruneCheckVerified(prunableObjects []string, reachableObjects, verifiedObjects lfs.StringSet) {
	// There's no issue if an object is not reachable and misisng, only if reachable & missing
	var problems bytes.Buffer
	for _, oid := range prunableObjects {
		// Test verified first as most likely reachable
		if !verifiedObjects.Contains(oid) {
			if reachableObjects.Contains(oid) {
				problems.WriteString(fmt.Sprintf("%v\n", oid))
			}
		}
	}
	// technically we could still prune the other oids, but this indicates a
	// more serious issue because the local state implies that these can be
	// deleted but that's incorrect; bad state has occurred somehow, might need
	// push --all to resolve
	if problems.Len() > 0 {
		Exit("Failed to find prunable objects on remote, aborting:\n%v", problems.String())
	}
}

func pruneCheckErrors(taskErrors []error) {
	if len(taskErrors) > 0 {
		for _, err := range taskErrors {
			LoggedError(err, "Prune error: %v", err)
		}
		Exit("Prune sub-tasks failed, cannot continue")
	}
}

func pruneTaskDisplayProgress(progressChan PruneProgressChan, waitg *sync.WaitGroup) {
	defer waitg.Done()

	spinner := lfs.NewSpinner()
	localCount := 0
	retainCount := 0
	verifyCount := 0
	var msg string
	for p := range progressChan {
		switch p.Type {
		case PruneProgressTypeLocal:
			localCount++
		case PruneProgressTypeRetain:
			retainCount++
		case PruneProgressTypeVerify:
			verifyCount++
		}
		msg = fmt.Sprintf("%d local objects, %d retained", localCount, retainCount)
		if verifyCount > 0 {
			msg += fmt.Sprintf(", %d verified with remote", verifyCount)
		}
		spinner.Print(OutputWriter, msg)
	}
	spinner.Finish(OutputWriter, msg)
}

func pruneTaskCollectRetained(outRetainedObjects *lfs.StringSet, retainChan chan string,
	progressChan PruneProgressChan, retainwait *sync.WaitGroup) {

	defer retainwait.Done()

	for oid := range retainChan {
		outRetainedObjects.Add(oid)
		progressChan <- PruneProgress{PruneProgressTypeRetain, 1}
	}

}

func pruneTaskCollectErrors(outtaskErrors *[]error, errorChan chan error, errorwait *sync.WaitGroup) {
	defer errorwait.Done()

	for err := range errorChan {
		*outtaskErrors = append(*outtaskErrors, err)
	}
}

func pruneDeleteFiles(prunableObjects []string) {
	spinner := lfs.NewSpinner()
	var problems bytes.Buffer
	// In case we fail to delete some
	var deletedFiles int
	for i, oid := range prunableObjects {
		spinner.Print(OutputWriter, fmt.Sprintf("Deleting object %d/%d", i, len(prunableObjects)))
		mediaFile, err := lfs.LocalMediaPath(oid)
		if err != nil {
			problems.WriteString(fmt.Sprintf("Unable to find media path for %v: %v\n", oid, err))
			continue
		}
		err = os.Remove(mediaFile)
		if err != nil {
			problems.WriteString(fmt.Sprintf("Failed to remove file %v: %v\n", mediaFile, err))
			continue
		}
		deletedFiles++
	}
	spinner.Finish(OutputWriter, fmt.Sprintf("Deleted %d files", deletedFiles))
	if problems.Len() > 0 {
		LoggedError(fmt.Errorf("Failed to delete some files"), problems.String())
		Exit("Prune failed, see errors above")
	}
}

// Background task, must call waitg.Done() once at end
func pruneTaskGetLocalObjects(outLocalObjects *[]*lfs.Pointer, progChan PruneProgressChan, waitg *sync.WaitGroup) {
	defer waitg.Done()

	localObjectsChan := lfs.AllLocalObjectsChan()
	for p := range localObjectsChan {
		*outLocalObjects = append(*outLocalObjects, p)
		progChan <- PruneProgress{PruneProgressTypeLocal, 1}
	}
}

// Background task, must call waitg.Done() once at end
func pruneTaskGetRetainedCurrentCheckout(retainChan chan string, errorChan chan error, waitg *sync.WaitGroup) {
	defer waitg.Done()

	ref, err := git.CurrentRef()
	if err != nil {
		errorChan <- err
		return
	}
	// Only files AT ref, recent is checked in pruneTaskGetRetainedRecentRefs
	opts := &lfs.ScanRefsOptions{ScanMode: lfs.ScanRefsMode, SkipDeletedBlobs: true}
	refchan, err := lfs.ScanRefsToChan(ref.Sha, "", opts)
	if err != nil {
		errorChan <- err
		return
	}
	for wp := range refchan {
		retainChan <- wp.Pointer.Oid
	}
}

// Background task, must call waitg.Done() once at end
func pruneTaskGetRetainedRecentRefs(retainChan chan string, errorChan chan error, waitg *sync.WaitGroup) {
	defer waitg.Done()

	// TODO
}

// Background task, must call waitg.Done() once at end
func pruneTaskGetRetainedUnpushed(retainChan chan string, errorChan chan error, waitg *sync.WaitGroup) {
	defer waitg.Done()

	// TODO
}

// Background task, must call waitg.Done() once at end
func pruneTaskGetRetainedWorktree(retainChan chan string, errorChan chan error, waitg *sync.WaitGroup) {
	defer waitg.Done()

	// TODO
}

// Background task, must call waitg.Done() once at end
func pruneTaskGetReachableObjects(outObjectSet *lfs.StringSet, errorChan chan error, waitg *sync.WaitGroup) {
	defer waitg.Done()

	// TODO
}

func init() {
	pruneCmd.Flags().BoolVarP(&pruneDryRunArg, "dry-run", "d", false, "Don't delete anything, just report")
	pruneCmd.Flags().BoolVarP(&pruneDryRunArg, "verbose", "v", false, "Print full details of what is/would be deleted")
	pruneCmd.Flags().BoolVarP(&pruneDryRunArg, "verify-remote", "c", false, "Verify that remote has LFS files before deleting")
	pruneCmd.Flags().BoolVar(&pruneDryRunArg, "no-verify-remote", false, "Override lfs.pruneverifyremotealways and don't verify")
	RootCmd.AddCommand(pruneCmd)
}
<commit_msg>Implement retention of unpushed objects<commit_after>package commands

import (
	"bytes"
	"fmt"
	"os"
	"sync"

	"github.com/github/git-lfs/git"
	"github.com/github/git-lfs/lfs"
	"github.com/github/git-lfs/vendor/_nuts/github.com/spf13/cobra"
)

var (
	pruneCmd = &cobra.Command{
		Use:   "prune",
		Short: "Deletes old LFS files from the local store",
		Run:   pruneCommand,
	}
	pruneDryRunArg      bool
	pruneVerboseArg     bool
	pruneVerifyArg      bool
	pruneDoNotVerifyArg bool
)

func pruneCommand(cmd *cobra.Command, args []string) {

	// Guts of this must be re-usable from fetch --prune so just parse & dispatch
	if pruneVerifyArg && pruneDoNotVerifyArg {
		Exit("Cannot specify both --verify-remote and --no-verify-remote")
	}

	verify := !pruneDoNotVerifyArg &&
		(lfs.Config.FetchPruneConfig().PruneVerifyRemoteAlways || pruneVerifyArg)

	prune(verify, pruneDryRunArg, pruneVerboseArg)

}

type PruneProgressType int

const (
	PruneProgressTypeLocal  = PruneProgressType(iota)
	PruneProgressTypeRetain = PruneProgressType(iota)
	PruneProgressTypeVerify = PruneProgressType(iota)
)

// Progress from a sub-task of prune
type PruneProgress struct {
	Type  PruneProgressType
	Count int // Number of items done
}
type PruneProgressChan chan PruneProgress

func prune(verifyRemote, dryRun, verbose bool) {
	localObjects := make([]*lfs.Pointer, 0, 100)
	retainedObjects := lfs.NewStringSetWithCapacity(100)
	var reachableObjects lfs.StringSet
	var taskwait sync.WaitGroup

	// Add all the base funcs to the waitgroup before starting them, in case
	// one completes really fast & hits 0 unexpectedly
	// each main process can Add() to the wg itself if it subdivides the task
	taskwait.Add(5) // 1..5: localObjects, current checkout, recent refs, unpushed, worktree
	if verifyRemote {
		taskwait.Add(1) // 6
	}

	progressChan := make(PruneProgressChan, 100)

	// Collect errors
	errorChan := make(chan error, 10)
	var errorwait sync.WaitGroup
	errorwait.Add(1)
	var taskErrors []error
	go pruneTaskCollectErrors(&taskErrors, errorChan, &errorwait)

	// Populate the single list of local objects
	go pruneTaskGetLocalObjects(&localObjects, progressChan, &taskwait)

	// Now find files to be retained from many sources
	retainChan := make(chan string, 100)

	go pruneTaskGetRetainedCurrentCheckout(retainChan, errorChan, &taskwait)
	go pruneTaskGetRetainedRecentRefs(retainChan, errorChan, &taskwait)
	go pruneTaskGetRetainedUnpushed(retainChan, errorChan, &taskwait)
	go pruneTaskGetRetainedWorktree(retainChan, errorChan, &taskwait)
	if verifyRemote {
		reachableObjects = lfs.NewStringSetWithCapacity(100)
		go pruneTaskGetReachableObjects(&reachableObjects, errorChan, &taskwait)
	}

	// Now collect all the retained objects, on separate wait
	var retainwait sync.WaitGroup
	retainwait.Add(1)
	go pruneTaskCollectRetained(&retainedObjects, retainChan, progressChan, &retainwait)

	// Report progress
	var progresswait sync.WaitGroup
	progresswait.Add(1)
	go pruneTaskDisplayProgress(progressChan, &progresswait)

	taskwait.Wait()   // wait for subtasks
	close(retainChan) // triggers retain collector to end now all tasks have
	retainwait.Wait() // make sure all retained objects added

	close(errorChan) // triggers error collector to end now all tasks have
	errorwait.Wait() // make sure all errors have been processed
	pruneCheckErrors(taskErrors)

	prunableObjects := make([]string, 0, len(localObjects)/2)

	// Build list of prunables (also queue for verify at same time if applicable)
	var verifyQueue *lfs.TransferQueue
	var verifiedObjects lfs.StringSet
	var totalSize int64
	var verboseOutput bytes.Buffer
	if verifyRemote && !dryRun {
		lfs.Config.CurrentRemote = lfs.Config.FetchPruneConfig().PruneRemoteName
		// build queue now, no estimates or progress output
		verifyQueue = lfs.NewDownloadCheckQueue(0, 0, true)
		verifiedObjects = lfs.NewStringSetWithCapacity(len(localObjects) / 2)
	}
	for _, pointer := range localObjects {
		if !retainedObjects.Contains(pointer.Oid) {
			prunableObjects = append(prunableObjects, pointer.Oid)
			totalSize += pointer.Size
			if verbose {
				// Save up verbose output for the end, spinner still going
				verboseOutput.WriteString(fmt.Sprintf("Prune %v ,%v", pointer.Oid, humanizeBytes(pointer.Size)))
			}
			if verifyRemote && !dryRun {
				verifyQueue.Add(lfs.NewDownloadCheckable(&lfs.WrappedPointer{Pointer: pointer}))
			}
		}
	}
	if verifyRemote && !dryRun {
		// this channel is filled with oids for which Check() succeeded & Transfer() was called
		verifyc := verifyQueue.Watch()
		var verifywait sync.WaitGroup
		verifywait.Add(1)
		go func() {
			for oid := range verifyc {
				verifiedObjects.Add(oid)
				progressChan <- PruneProgress{PruneProgressTypeVerify, 1}
			}
			verifywait.Done()
		}()
		verifyQueue.Wait()
		verifywait.Wait()
		close(progressChan) // after verify (uses spinner) but before check
		progresswait.Wait()
		pruneCheckVerified(prunableObjects, reachableObjects, verifiedObjects)
	} else {
		close(progressChan)
		progresswait.Wait()
	}

	if dryRun {
		Print("%d files would be pruned, %v", len(prunableObjects), humanizeBytes(totalSize))
	} else {
		Print("Pruning %d files, %v", len(prunableObjects), humanizeBytes(totalSize))
		pruneDeleteFiles(prunableObjects)
	}

}

func pruneCheckVerified(prunableObjects []string, reachableObjects, verifiedObjects lfs.StringSet) {
	// There's no issue if an object is not reachable and misisng, only if reachable & missing
	var problems bytes.Buffer
	for _, oid := range prunableObjects {
		// Test verified first as most likely reachable
		if !verifiedObjects.Contains(oid) {
			if reachableObjects.Contains(oid) {
				problems.WriteString(fmt.Sprintf("%v\n", oid))
			}
		}
	}
	// technically we could still prune the other oids, but this indicates a
	// more serious issue because the local state implies that these can be
	// deleted but that's incorrect; bad state has occurred somehow, might need
	// push --all to resolve
	if problems.Len() > 0 {
		Exit("Failed to find prunable objects on remote, aborting:\n%v", problems.String())
	}
}

func pruneCheckErrors(taskErrors []error) {
	if len(taskErrors) > 0 {
		for _, err := range taskErrors {
			LoggedError(err, "Prune error: %v", err)
		}
		Exit("Prune sub-tasks failed, cannot continue")
	}
}

func pruneTaskDisplayProgress(progressChan PruneProgressChan, waitg *sync.WaitGroup) {
	defer waitg.Done()

	spinner := lfs.NewSpinner()
	localCount := 0
	retainCount := 0
	verifyCount := 0
	var msg string
	for p := range progressChan {
		switch p.Type {
		case PruneProgressTypeLocal:
			localCount++
		case PruneProgressTypeRetain:
			retainCount++
		case PruneProgressTypeVerify:
			verifyCount++
		}
		msg = fmt.Sprintf("%d local objects, %d retained", localCount, retainCount)
		if verifyCount > 0 {
			msg += fmt.Sprintf(", %d verified with remote", verifyCount)
		}
		spinner.Print(OutputWriter, msg)
	}
	spinner.Finish(OutputWriter, msg)
}

func pruneTaskCollectRetained(outRetainedObjects *lfs.StringSet, retainChan chan string,
	progressChan PruneProgressChan, retainwait *sync.WaitGroup) {

	defer retainwait.Done()

	for oid := range retainChan {
		outRetainedObjects.Add(oid)
		progressChan <- PruneProgress{PruneProgressTypeRetain, 1}
	}

}

func pruneTaskCollectErrors(outtaskErrors *[]error, errorChan chan error, errorwait *sync.WaitGroup) {
	defer errorwait.Done()

	for err := range errorChan {
		*outtaskErrors = append(*outtaskErrors, err)
	}
}

func pruneDeleteFiles(prunableObjects []string) {
	spinner := lfs.NewSpinner()
	var problems bytes.Buffer
	// In case we fail to delete some
	var deletedFiles int
	for i, oid := range prunableObjects {
		spinner.Print(OutputWriter, fmt.Sprintf("Deleting object %d/%d", i, len(prunableObjects)))
		mediaFile, err := lfs.LocalMediaPath(oid)
		if err != nil {
			problems.WriteString(fmt.Sprintf("Unable to find media path for %v: %v\n", oid, err))
			continue
		}
		err = os.Remove(mediaFile)
		if err != nil {
			problems.WriteString(fmt.Sprintf("Failed to remove file %v: %v\n", mediaFile, err))
			continue
		}
		deletedFiles++
	}
	spinner.Finish(OutputWriter, fmt.Sprintf("Deleted %d files", deletedFiles))
	if problems.Len() > 0 {
		LoggedError(fmt.Errorf("Failed to delete some files"), problems.String())
		Exit("Prune failed, see errors above")
	}
}

// Background task, must call waitg.Done() once at end
func pruneTaskGetLocalObjects(outLocalObjects *[]*lfs.Pointer, progChan PruneProgressChan, waitg *sync.WaitGroup) {
	defer waitg.Done()

	localObjectsChan := lfs.AllLocalObjectsChan()
	for p := range localObjectsChan {
		*outLocalObjects = append(*outLocalObjects, p)
		progChan <- PruneProgress{PruneProgressTypeLocal, 1}
	}
}

// Background task, must call waitg.Done() once at end
func pruneTaskGetRetainedCurrentCheckout(retainChan chan string, errorChan chan error, waitg *sync.WaitGroup) {
	defer waitg.Done()

	ref, err := git.CurrentRef()
	if err != nil {
		errorChan <- err
		return
	}
	// Only files AT ref, recent is checked in pruneTaskGetRetainedRecentRefs
	opts := &lfs.ScanRefsOptions{ScanMode: lfs.ScanRefsMode, SkipDeletedBlobs: true}
	refchan, err := lfs.ScanRefsToChan(ref.Sha, "", opts)
	if err != nil {
		errorChan <- err
		return
	}
	for wp := range refchan {
		retainChan <- wp.Pointer.Oid
	}
}

// Background task, must call waitg.Done() once at end
func pruneTaskGetRetainedRecentRefs(retainChan chan string, errorChan chan error, waitg *sync.WaitGroup) {
	defer waitg.Done()

	// TODO
}

// Background task, must call waitg.Done() once at end
func pruneTaskGetRetainedUnpushed(retainChan chan string, errorChan chan error, waitg *sync.WaitGroup) {
	defer waitg.Done()

	remoteName := lfs.Config.FetchPruneConfig().PruneRemoteName

	refchan, err := lfs.ScanUnpushedToChan(remoteName)
	if err != nil {
		errorChan <- err
		return
	}
	for wp := range refchan {
		retainChan <- wp.Pointer.Oid
	}
}

// Background task, must call waitg.Done() once at end
func pruneTaskGetRetainedWorktree(retainChan chan string, errorChan chan error, waitg *sync.WaitGroup) {
	defer waitg.Done()

	// TODO
}

// Background task, must call waitg.Done() once at end
func pruneTaskGetReachableObjects(outObjectSet *lfs.StringSet, errorChan chan error, waitg *sync.WaitGroup) {
	defer waitg.Done()

	// TODO
}

func init() {
	pruneCmd.Flags().BoolVarP(&pruneDryRunArg, "dry-run", "d", false, "Don't delete anything, just report")
	pruneCmd.Flags().BoolVarP(&pruneDryRunArg, "verbose", "v", false, "Print full details of what is/would be deleted")
	pruneCmd.Flags().BoolVarP(&pruneDryRunArg, "verify-remote", "c", false, "Verify that remote has LFS files before deleting")
	pruneCmd.Flags().BoolVar(&pruneDryRunArg, "no-verify-remote", false, "Override lfs.pruneverifyremotealways and don't verify")
	RootCmd.AddCommand(pruneCmd)
}
<|endoftext|>


<commit_before>package moves

var Start = [64]int16{
  B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK,
  B_PAWN, B_PAWN,   B_PAWN,   B_PAWN,  B_PAWN, B_PAWN,   B_PAWN,   B_PAWN,
  EMPTY,  EMPTY,    EMPTY,    EMPTY,   EMPTY,  EMPTY,    EMPTY,    EMPTY,
  EMPTY,  EMPTY,    EMPTY,    EMPTY,   EMPTY,  EMPTY,    EMPTY,    EMPTY,
  EMPTY,  EMPTY,    EMPTY,    EMPTY,   EMPTY,  EMPTY,    EMPTY,    EMPTY,
  EMPTY,  EMPTY,    EMPTY,    EMPTY,   EMPTY,  EMPTY,    EMPTY,    EMPTY,
  W_PAWN, W_PAWN,   W_PAWN,   W_PAWN,  W_PAWN, W_PAWN,   W_PAWN,   W_PAWN,
  W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK}

func Add(board [64]int16, move Move) [64]int16 {
  board[move.from] = EMPTY
  board[move.to] = move.piece
  return board
}

func Remove(board [64]int16, move Move) [64]int16 {
  board[move.to] = move.prev
  board[move.from] = move.piece
  return board
}
/*
func Load(fen string) [64]int16 {
  return []int16{}
}

func Save(board [64]int16) string {
  return ""
}
*/
func Perft(depth int) int {
  var board = Start
  var nodes int = 0

  var moves = Generate(board, COLOR_WHITE)

  if depth == 0 {
    return 1
  }

  if depth == 1 {
    return len(moves)
  }

  for _, move := range moves {
    Add(board, move)
    nodes += Perft(depth - 1)
    Remove(board, move)
  }

  return nodes
}
<commit_msg>feat: restore previous piece on undo move<commit_after>package moves

import "fmt"

var Start = [64]int16{
  B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK,
  B_PAWN, B_PAWN,   B_PAWN,   B_PAWN,  B_PAWN, B_PAWN,   B_PAWN,   B_PAWN,
  EMPTY,  EMPTY,    EMPTY,    EMPTY,   EMPTY,  EMPTY,    EMPTY,    EMPTY,
  EMPTY,  EMPTY,    EMPTY,    EMPTY,   EMPTY,  EMPTY,    EMPTY,    EMPTY,
  EMPTY,  EMPTY,    EMPTY,    EMPTY,   EMPTY,  EMPTY,    EMPTY,    EMPTY,
  EMPTY,  EMPTY,    EMPTY,    EMPTY,   EMPTY,  EMPTY,    EMPTY,    EMPTY,
  W_PAWN, W_PAWN,   W_PAWN,   W_PAWN,  W_PAWN, W_PAWN,   W_PAWN,   W_PAWN,
  W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK}

var Test = [64]int16{
  B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK,
  B_PAWN, B_PAWN,   B_PAWN,   B_PAWN,  B_PAWN, B_PAWN,   B_PAWN,   B_PAWN,
  EMPTY,  EMPTY,    EMPTY,    EMPTY,   EMPTY,  EMPTY,    EMPTY,    EMPTY,
  EMPTY,  EMPTY,    EMPTY,    EMPTY,   EMPTY,  EMPTY,    EMPTY,    EMPTY,
  EMPTY,  EMPTY,    EMPTY,    EMPTY,   EMPTY,  EMPTY,    EMPTY,    EMPTY,
  EMPTY,  EMPTY,    EMPTY,    W_PAWN,  EMPTY,  EMPTY,    EMPTY,    EMPTY,
  W_PAWN, W_PAWN,   W_PAWN,   EMPTY,   W_PAWN, W_PAWN,   W_PAWN,   W_PAWN,
  W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK}

func Add(board [64]int16, move Move) [64]int16 {
  board[move.From] = EMPTY
  board[move.To] = move.Piece
  return board
}

func Remove(board [64]int16, move Move) [64]int16 {
  board[move.To] = move.Prev
  board[move.From] = move.Piece
  return board
}
/*
func Load(fen string) [64]int16 {
  return []int16{}
}

func Save(board [64]int16) string {
  return ""
}
*/
func  Perft(board [64]int16, depth int, color int16) int {
  var nodes int = 0
  var captures int = 0

  var moves = Generate(board, color)

  // stats
  for _, move := range moves {
    if move.Capture {
      fmt.Println("capture", move.Capture)
      captures += 1
    }
  }

  if color == COLOR_WHITE {
    color = COLOR_BLACK
  } else {
    color = COLOR_WHITE
  }

  if depth == 1 {
    return len(moves)
  }

  for _, move := range moves {
    // make move
    Add(board, move)

    // look deeper
    nodes += Perft(board, depth - 1, color)

    // undo move
    Remove(board, move)
  }

  return nodes
}
<|endoftext|>


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

package commands

import (
	"bytes"
	"io"

	"github.com/gohugoio/hugo/transform"
	"github.com/gohugoio/hugo/transform/livereloadinject"
)

var buildErrorTemplate = `<!doctype html>

		<meta charset="utf-8">
		<title>Hugo Server: Error</title>

			{{ highlight .Error "apl" "noclasses=true,style=monokai" }}
			{{ with .File }}
			{{ $params := printf "noclasses=true,style=monokai,linenos=table,hl_lines=%d,linenostart=%d" (add .Pos 1) (sub .LineNumber .Pos) }}
			{{ $lexer := .ChromaLexer | default "go-html-template" }}
			{{  highlight (delimit .Lines "\n") $lexer $params }}
			{{ end }}
			{{ with .StackTrace }}
			{{ highlight . "apl" "noclasses=true,style=monokai" }}
			{{ end }}

{{ .Version }}

			Reload Page

`

func injectLiveReloadScript(src io.Reader, port int) string {
	var b bytes.Buffer
	chain := transform.Chain{livereloadinject.New(port)}
	chain.Apply(&b, src)

	return b.String()
}
<commit_msg>comamnds: Use overflow-x: auto; for browser errors<commit_after>// Copyright 2018 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package commands

import (
	"bytes"
	"io"

	"github.com/gohugoio/hugo/transform"
	"github.com/gohugoio/hugo/transform/livereloadinject"
)

var buildErrorTemplate = `<!doctype html>

		<meta charset="utf-8">
		<title>Hugo Server: Error</title>

			{{ highlight .Error "apl" "noclasses=true,style=monokai" }}
			{{ with .File }}
			{{ $params := printf "noclasses=true,style=monokai,linenos=table,hl_lines=%d,linenostart=%d" (add .Pos 1) (sub .LineNumber .Pos) }}
			{{ $lexer := .ChromaLexer | default "go-html-template" }}
			{{  highlight (delimit .Lines "\n") $lexer $params }}
			{{ end }}
			{{ with .StackTrace }}
			{{ highlight . "apl" "noclasses=true,style=monokai" }}
			{{ end }}

{{ .Version }}

			Reload Page

`

func injectLiveReloadScript(src io.Reader, port int) string {
	var b bytes.Buffer
	chain := transform.Chain{livereloadinject.New(port)}
	chain.Apply(&b, src)

	return b.String()
}
<|endoftext|>


<commit_before>package modules

import (
    "github.com/Seklfreak/Robyul2/modules/plugins"
    //"github.com/Seklfreak/Robyul2/modules/triggers"
    "github.com/Seklfreak/Robyul2/modules/triggers"
)

var (
    pluginCache         map[string]*Plugin
    triggerCache        map[string]*TriggerPlugin
    extendedPluginCache map[string]*ExtendedPlugin

    PluginList = []Plugin{
        &plugins.About{},
        &plugins.Stats{},
        //&plugins.Stone{},
        //&plugins.Support{},
        &plugins.Announcement{},
        //&plugins.Translator{},
        &plugins.Uptime{},
        &plugins.Music{},
        &plugins.Translator{},
        &plugins.Ping{},
        &plugins.UrbanDict{},
        &plugins.Weather{},
        &plugins.VLive{},
        &plugins.Twitter{},
        &plugins.Instagram{},
        &plugins.Facebook{},
        &plugins.WolframAlpha{},
        &plugins.LastFm{},
        &plugins.Twitch{},
        &plugins.Charts{},
        //&plugins.Avatar{},
        //&plugins.Calc{},
        //&plugins.Changelog{},
        &plugins.Choice{},
        //&plugins.FlipCoin{},
        //&plugins.Giphy{},
        //&plugins.Google{},
        //&plugins.Leet{},
        //&plugins.ListenDotMoe{},
        //&plugins.Minecraft{},
        &plugins.Osu{},
        &plugins.Reminders{},
        //&plugins.Roll{},
        //&plugins.Stone{},
        //&plugins.Support{},
        //&plugins.XKCD{},
        &plugins.Ratelimit{},
        &plugins.Gfycat{},
        &plugins.RandomPictures{},
        &plugins.YouTube{},
        &plugins.Spoiler{},
        &plugins.RandomCat{},
        &plugins.RPS{},
        &plugins.Nuke{},
        &plugins.Dig{},
        &plugins.Streamable{},
        &plugins.Troublemaker{},
    }

    // PluginList is the list of active plugins
    PluginExtendedList = []ExtendedPlugin{
        &plugins.Bias{},
        &plugins.GuildAnnouncements{},
        &plugins.Notifications{},
        &plugins.Levels{},
        &plugins.Gallery{},
        &plugins.Mirror{},
        &plugins.CustomCommands{},
        &plugins.ReactionPolls{},
        &plugins.Mod{},
    }

    // TriggerPluginList is the list of plugins that activate on normal chat
    TriggerPluginList = []TriggerPlugin{
        &triggers.Donators{},
        //&triggers.CSS{},
        //&triggers.Donate{},
        //&triggers.Git{},
        //&triggers.EightBall{},
        //&triggers.Hi{},
        //&triggers.HypeTrain{},
        //&triggers.Invite{},
        //&triggers.IPTables{},
        //&triggers.Lenny{},
        //&triggers.Nep{},
        //&triggers.ReZero{},
        //&triggers.Shrug{},
        //&triggers.TableFlip{},
        //&triggers.Triggered{},
    }
)
<commit_msg>enables 8ball<commit_after>package modules

import (
    "github.com/Seklfreak/Robyul2/modules/plugins"
    //"github.com/Seklfreak/Robyul2/modules/triggers"
    "github.com/Seklfreak/Robyul2/modules/triggers"
)

var (
    pluginCache         map[string]*Plugin
    triggerCache        map[string]*TriggerPlugin
    extendedPluginCache map[string]*ExtendedPlugin

    PluginList = []Plugin{
        &plugins.About{},
        &plugins.Stats{},
        //&plugins.Stone{},
        //&plugins.Support{},
        &plugins.Announcement{},
        //&plugins.Translator{},
        &plugins.Uptime{},
        &plugins.Music{},
        &plugins.Translator{},
        &plugins.Ping{},
        &plugins.UrbanDict{},
        &plugins.Weather{},
        &plugins.VLive{},
        &plugins.Twitter{},
        &plugins.Instagram{},
        &plugins.Facebook{},
        &plugins.WolframAlpha{},
        &plugins.LastFm{},
        &plugins.Twitch{},
        &plugins.Charts{},
        //&plugins.Avatar{},
        //&plugins.Calc{},
        //&plugins.Changelog{},
        &plugins.Choice{},
        //&plugins.FlipCoin{},
        //&plugins.Giphy{},
        //&plugins.Google{},
        //&plugins.Leet{},
        //&plugins.ListenDotMoe{},
        //&plugins.Minecraft{},
        &plugins.Osu{},
        &plugins.Reminders{},
        //&plugins.Roll{},
        //&plugins.Stone{},
        //&plugins.Support{},
        //&plugins.XKCD{},
        &plugins.Ratelimit{},
        &plugins.Gfycat{},
        &plugins.RandomPictures{},
        &plugins.YouTube{},
        &plugins.Spoiler{},
        &plugins.RandomCat{},
        &plugins.RPS{},
        &plugins.Nuke{},
        &plugins.Dig{},
        &plugins.Streamable{},
        &plugins.Troublemaker{},
    }

    // PluginList is the list of active plugins
    PluginExtendedList = []ExtendedPlugin{
        &plugins.Bias{},
        &plugins.GuildAnnouncements{},
        &plugins.Notifications{},
        &plugins.Levels{},
        &plugins.Gallery{},
        &plugins.Mirror{},
        &plugins.CustomCommands{},
        &plugins.ReactionPolls{},
        &plugins.Mod{},
    }

    // TriggerPluginList is the list of plugins that activate on normal chat
    TriggerPluginList = []TriggerPlugin{
        &triggers.Donators{},
        //&triggers.CSS{},
        //&triggers.Donate{},
        //&triggers.Git{},
        &triggers.EightBall{},
        //&triggers.Hi{},
        //&triggers.HypeTrain{},
        //&triggers.Invite{},
        //&triggers.IPTables{},
        //&triggers.Lenny{},
        //&triggers.Nep{},
        //&triggers.ReZero{},
        //&triggers.Shrug{},
        //&triggers.TableFlip{},
        //&triggers.Triggered{},
    }
)
<|endoftext|>


<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package libkb

// Version is the current version (should be MAJOR.MINOR.PATCH)
const Version = "1.0.26"
<commit_msg>Bump version after releases<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package libkb

// Version is the current version (should be MAJOR.MINOR.PATCH)
const Version = "1.0.27"
<|endoftext|>


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

package types

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/token"

	"code.google.com/p/go.tools/go/exact"
)

// TODO(gri) Document factory, accessor methods, and fields. General clean-up.

// An Object describes a named language entity such as a package,
// constant, type, variable, function (incl. methods), or label.
// All objects implement the Object interface.
//
type Object interface {
	Parent() *Scope   // scope in which this object is declared
	Pos() token.Pos   // position of object identifier in declaration
	Pkg() *Package    // nil for objects in the Universe scope and labels
	Name() string     // package local object name
	Type() Type       // object type
	IsExported() bool // reports whether the name starts with a capital letter
	Id() string       // object id (see Id below)

	// String returns a human-readable string of the object.
	String() string

	// isUsed reports whether the object was marked as 'used'.
	isUsed() bool

	// setParent sets the parent scope of the object.
	setParent(*Scope)

	// sameId reports whether obj.Id() and Id(pkg, name) are the same.
	sameId(pkg *Package, name string) bool
}

// Id returns name if it is exported, otherwise it
// returns the name qualified with the package path.
func Id(pkg *Package, name string) string {
	if ast.IsExported(name) {
		return name
	}
	// unexported names need the package path for differentiation
	path := ""
	// TODO(gri): shouldn't !ast.IsExported(name) => pkg != nil be an precondition?
	// if pkg == nil {
	// 	panic("nil package in lookup of unexported name")
	// }
	if pkg != nil {
		path = pkg.path
		if path == "" {
			path = "?"
		}
	}
	return path + "." + name
}

// An object implements the common parts of an Object.
type object struct {
	parent *Scope
	pos    token.Pos
	pkg    *Package
	name   string
	typ    Type
	used   bool
}

func (obj *object) Parent() *Scope   { return obj.parent }
func (obj *object) Pos() token.Pos   { return obj.pos }
func (obj *object) Pkg() *Package    { return obj.pkg }
func (obj *object) Name() string     { return obj.name }
func (obj *object) Type() Type       { return obj.typ }
func (obj *object) IsExported() bool { return ast.IsExported(obj.name) }
func (obj *object) Id() string       { return Id(obj.pkg, obj.name) }
func (obj *object) String() string   { panic("abstract") }

func (obj *object) isUsed() bool { return obj.used }

func (obj *object) toString(kind string, typ Type) string {
	var buf bytes.Buffer

	buf.WriteString(kind)
	buf.WriteByte(' ')
	// For package-level objects, package-qualify the name.
	if obj.pkg != nil && obj.pkg.scope.Lookup(obj.name) == obj {
		buf.WriteString(obj.pkg.name)
		buf.WriteByte('.')
	}
	buf.WriteString(obj.name)
	if typ != nil {
		buf.WriteByte(' ')
		writeType(&buf, typ)
	}

	return buf.String()
}

func (obj *object) setParent(parent *Scope) { obj.parent = parent }

func (obj *object) sameId(pkg *Package, name string) bool {
	// spec:
	// "Two identifiers are different if they are spelled differently,
	// or if they appear in different packages and are not exported.
	// Otherwise, they are the same."
	if name != obj.name {
		return false
	}
	// obj.Name == name
	if obj.IsExported() {
		return true
	}
	// not exported, so packages must be the same (pkg == nil for
	// fields in Universe scope; this can only happen for types
	// introduced via Eval)
	if pkg == nil || obj.pkg == nil {
		return pkg == obj.pkg
	}
	// pkg != nil && obj.pkg != nil
	return pkg.path == obj.pkg.path
}

// A PkgName represents an imported Go package.
type PkgName struct {
	object
}

func NewPkgName(pos token.Pos, pkg *Package, name string) *PkgName {
	return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], false}}
}

func (obj *PkgName) String() string { return obj.toString("package", nil) }

// A Const represents a declared constant.
type Const struct {
	object
	val exact.Value

	visited bool // for initialization cycle detection
}

func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val exact.Value) *Const {
	return &Const{object: object{nil, pos, pkg, name, typ, false}, val: val}
}

func (obj *Const) String() string   { return obj.toString("const", obj.typ) }
func (obj *Const) Val() exact.Value { return obj.val }

// A TypeName represents a declared type.
type TypeName struct {
	object
}

func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
	return &TypeName{object{nil, pos, pkg, name, typ, false}}
}

func (obj *TypeName) String() string { return obj.toString("type", obj.typ.Underlying()) }

// A Variable represents a declared variable (including function parameters and results, and struct fields).
type Var struct {
	object

	anonymous bool // if set, the variable is an anonymous struct field, and name is the type name
	visited   bool // for initialization cycle detection
}

func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var {
	return &Var{object: object{nil, pos, pkg, name, typ, false}}
}

func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var {
	return &Var{object: object{nil, pos, pkg, name, typ, true}} // parameters are always 'used'
}

func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool) *Var {
	return &Var{object: object{nil, pos, pkg, name, typ, false}, anonymous: anonymous}
}

func (obj *Var) Anonymous() bool { return obj.anonymous }
func (obj *Var) String() string  { return obj.toString("var", obj.typ) }

// A Func represents a declared function, concrete method, or abstract
// (interface) method.  Its Type() is always a *Signature.
// An abstract method may belong to many interfaces due to embedding.
type Func struct {
	object
}

func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
	// don't store a nil signature
	var typ Type
	if sig != nil {
		typ = sig
	}
	return &Func{object{nil, pos, pkg, name, typ, false}}
}

// FullName returns the package- or receiver-type-qualified name of
// function or method obj.
func (obj *Func) FullName() string {
	var buf bytes.Buffer
	obj.fullname(&buf)
	return buf.String()
}

func (obj *Func) fullname(buf *bytes.Buffer) {
	if obj.typ != nil {
		sig := obj.typ.(*Signature)
		if recv := sig.Recv(); recv != nil {
			buf.WriteByte('(')
			if _, ok := recv.Type().(*Interface); ok {
				// gcimporter creates abstract methods of
				// named interfaces using the interface type
				// (not the named type) as the receiver.
				// Don't print it in full.
				buf.WriteString("interface")
			} else {
				writeType(buf, recv.Type())
			}
			buf.WriteByte(')')
			buf.WriteByte('.')
		} else if obj.pkg != nil {
			buf.WriteString(obj.pkg.name)
			buf.WriteByte('.')
		}
	}
	buf.WriteString(obj.name)
}

func (obj *Func) String() string {
	var buf bytes.Buffer
	buf.WriteString("func ")
	obj.fullname(&buf)
	if obj.typ != nil {
		writeSignature(&buf, obj.typ.(*Signature))
	}
	return buf.String()
}

// A Label represents a declared label.
type Label struct {
	object
}

func NewLabel(pos token.Pos, name string) *Label {
	return &Label{object{pos: pos, name: name}}
}

func (obj *Label) String() string { return fmt.Sprintf("label %s", obj.Name()) }

// A Builtin represents a built-in function.
// Builtins don't have a valid type.
type Builtin struct {
	object

	id builtinId
}

func newBuiltin(id builtinId) *Builtin {
	return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid]}, id}
}

// Nil represents the predeclared value nil.
type Nil struct {
	object
}

func (*Nil) String() string { return "nil" }
<commit_msg>go.tools/go/types: return invalid type (rather than nil) for (*Label).Type()<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package types

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/token"

	"code.google.com/p/go.tools/go/exact"
)

// TODO(gri) Document factory, accessor methods, and fields. General clean-up.

// An Object describes a named language entity such as a package,
// constant, type, variable, function (incl. methods), or label.
// All objects implement the Object interface.
//
type Object interface {
	Parent() *Scope   // scope in which this object is declared
	Pos() token.Pos   // position of object identifier in declaration
	Pkg() *Package    // nil for objects in the Universe scope and labels
	Name() string     // package local object name
	Type() Type       // object type
	IsExported() bool // reports whether the name starts with a capital letter
	Id() string       // object id (see Id below)

	// String returns a human-readable string of the object.
	String() string

	// isUsed reports whether the object was marked as 'used'.
	isUsed() bool

	// setParent sets the parent scope of the object.
	setParent(*Scope)

	// sameId reports whether obj.Id() and Id(pkg, name) are the same.
	sameId(pkg *Package, name string) bool
}

// Id returns name if it is exported, otherwise it
// returns the name qualified with the package path.
func Id(pkg *Package, name string) string {
	if ast.IsExported(name) {
		return name
	}
	// unexported names need the package path for differentiation
	path := ""
	// TODO(gri): shouldn't !ast.IsExported(name) => pkg != nil be an precondition?
	// if pkg == nil {
	// 	panic("nil package in lookup of unexported name")
	// }
	if pkg != nil {
		path = pkg.path
		if path == "" {
			path = "?"
		}
	}
	return path + "." + name
}

// An object implements the common parts of an Object.
type object struct {
	parent *Scope
	pos    token.Pos
	pkg    *Package
	name   string
	typ    Type
	used   bool
}

func (obj *object) Parent() *Scope   { return obj.parent }
func (obj *object) Pos() token.Pos   { return obj.pos }
func (obj *object) Pkg() *Package    { return obj.pkg }
func (obj *object) Name() string     { return obj.name }
func (obj *object) Type() Type       { return obj.typ }
func (obj *object) IsExported() bool { return ast.IsExported(obj.name) }
func (obj *object) Id() string       { return Id(obj.pkg, obj.name) }
func (obj *object) String() string   { panic("abstract") }

func (obj *object) isUsed() bool { return obj.used }

func (obj *object) toString(kind string, typ Type) string {
	var buf bytes.Buffer

	buf.WriteString(kind)
	buf.WriteByte(' ')
	// For package-level objects, package-qualify the name.
	if obj.pkg != nil && obj.pkg.scope.Lookup(obj.name) == obj {
		buf.WriteString(obj.pkg.name)
		buf.WriteByte('.')
	}
	buf.WriteString(obj.name)
	if typ != nil {
		buf.WriteByte(' ')
		writeType(&buf, typ)
	}

	return buf.String()
}

func (obj *object) setParent(parent *Scope) { obj.parent = parent }

func (obj *object) sameId(pkg *Package, name string) bool {
	// spec:
	// "Two identifiers are different if they are spelled differently,
	// or if they appear in different packages and are not exported.
	// Otherwise, they are the same."
	if name != obj.name {
		return false
	}
	// obj.Name == name
	if obj.IsExported() {
		return true
	}
	// not exported, so packages must be the same (pkg == nil for
	// fields in Universe scope; this can only happen for types
	// introduced via Eval)
	if pkg == nil || obj.pkg == nil {
		return pkg == obj.pkg
	}
	// pkg != nil && obj.pkg != nil
	return pkg.path == obj.pkg.path
}

// A PkgName represents an imported Go package.
type PkgName struct {
	object
}

func NewPkgName(pos token.Pos, pkg *Package, name string) *PkgName {
	return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], false}}
}

func (obj *PkgName) String() string { return obj.toString("package", nil) }

// A Const represents a declared constant.
type Const struct {
	object
	val exact.Value

	visited bool // for initialization cycle detection
}

func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val exact.Value) *Const {
	return &Const{object: object{nil, pos, pkg, name, typ, false}, val: val}
}

func (obj *Const) String() string   { return obj.toString("const", obj.typ) }
func (obj *Const) Val() exact.Value { return obj.val }

// A TypeName represents a declared type.
type TypeName struct {
	object
}

func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
	return &TypeName{object{nil, pos, pkg, name, typ, false}}
}

func (obj *TypeName) String() string { return obj.toString("type", obj.typ.Underlying()) }

// A Variable represents a declared variable (including function parameters and results, and struct fields).
type Var struct {
	object

	anonymous bool // if set, the variable is an anonymous struct field, and name is the type name
	visited   bool // for initialization cycle detection
}

func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var {
	return &Var{object: object{nil, pos, pkg, name, typ, false}}
}

func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var {
	return &Var{object: object{nil, pos, pkg, name, typ, true}} // parameters are always 'used'
}

func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool) *Var {
	return &Var{object: object{nil, pos, pkg, name, typ, false}, anonymous: anonymous}
}

func (obj *Var) Anonymous() bool { return obj.anonymous }
func (obj *Var) String() string  { return obj.toString("var", obj.typ) }

// A Func represents a declared function, concrete method, or abstract
// (interface) method.  Its Type() is always a *Signature.
// An abstract method may belong to many interfaces due to embedding.
type Func struct {
	object
}

func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
	// don't store a nil signature
	var typ Type
	if sig != nil {
		typ = sig
	}
	return &Func{object{nil, pos, pkg, name, typ, false}}
}

// FullName returns the package- or receiver-type-qualified name of
// function or method obj.
func (obj *Func) FullName() string {
	var buf bytes.Buffer
	obj.fullname(&buf)
	return buf.String()
}

func (obj *Func) fullname(buf *bytes.Buffer) {
	if obj.typ != nil {
		sig := obj.typ.(*Signature)
		if recv := sig.Recv(); recv != nil {
			buf.WriteByte('(')
			if _, ok := recv.Type().(*Interface); ok {
				// gcimporter creates abstract methods of
				// named interfaces using the interface type
				// (not the named type) as the receiver.
				// Don't print it in full.
				buf.WriteString("interface")
			} else {
				writeType(buf, recv.Type())
			}
			buf.WriteByte(')')
			buf.WriteByte('.')
		} else if obj.pkg != nil {
			buf.WriteString(obj.pkg.name)
			buf.WriteByte('.')
		}
	}
	buf.WriteString(obj.name)
}

func (obj *Func) String() string {
	var buf bytes.Buffer
	buf.WriteString("func ")
	obj.fullname(&buf)
	if obj.typ != nil {
		writeSignature(&buf, obj.typ.(*Signature))
	}
	return buf.String()
}

// A Label represents a declared label.
type Label struct {
	object
}

func NewLabel(pos token.Pos, name string) *Label {
	return &Label{object{pos: pos, name: name, typ: Typ[Invalid]}}
}

func (obj *Label) String() string { return fmt.Sprintf("label %s", obj.Name()) }

// A Builtin represents a built-in function.
// Builtins don't have a valid type.
type Builtin struct {
	object

	id builtinId
}

func newBuiltin(id builtinId) *Builtin {
	return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid]}, id}
}

// Nil represents the predeclared value nil.
type Nil struct {
	object
}

func (*Nil) String() string { return "nil" }
<|endoftext|>


<commit_before>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package components

import (
	"github.com/thethingsnetwork/core"
	. "github.com/thethingsnetwork/core/utils/testing"
	"testing"
)

// ----- A new router instance can be created an obtained from a constuctor
func TestNewRouter(t *testing.T) {
	tests := []newRouterTest{
		{genBrokers(), nil},
		{[]core.BrokerAddress{}, core.ErrBadOptions},
	}

	for _, test := range tests {
		test.run(t)
	}
}

type newRouterTest struct {
	in   []core.BrokerAddress
	want error
}

func (test newRouterTest) run(t *testing.T) {
	Desc(t, "Create new router with params: %v", test.in)
	router, err := NewRouter(test.in...)
	checkErrors(t, test.want, err, router)
}

// ----- Build Utilities
func genBrokers() []core.BrokerAddress {
	return []core.BrokerAddress{
		core.BrokerAddress("0.0.0.0:3000"),
		core.BrokerAddress("0.0.0.0:3001"),
	}
}

// ----- Check Utilities
func checkErrors(t *testing.T, want error, got error, router core.Router) {
	if want != got {
		Ko(t, "Expected error {%v} but got {%v}", want, got)
		return
	}

	if want == nil && router == nil {
		Ko(t, "Expected no error but got a nil router")
		return
	}

	Ok(t)
}
<commit_msg>[router] Add backbone of HandleUplink() tests<commit_after>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package components

import (
	"github.com/thethingsnetwork/core"
	"github.com/thethingsnetwork/core/lorawan/semtech"
	"github.com/thethingsnetwork/core/testing/mock_adapters/gtw_rtr_mock"
	"github.com/thethingsnetwork/core/testing/mock_adapters/rtr_brk_mock"
	. "github.com/thethingsnetwork/core/utils/testing"
	"testing"
)

// ----- A new router instance can be created an obtained from a constuctor
func TestNewRouter(t *testing.T) {
	tests := []newRouterTest{
		{genBrokers(), nil},
		{[]core.BrokerAddress{}, core.ErrBadOptions},
	}

	for _, test := range tests {
		test.run(t)
	}
}

type newRouterTest struct {
	in   []core.BrokerAddress
	want error
}

func (test newRouterTest) run(t *testing.T) {
	Desc(t, "Create new router with params: %v", test.in)
	router, err := NewRouter(test.in...)
	checkErrors(t, test.want, err, router)
}

// ----- A router can handle uplink packets
func TestHandleUplink(t *testing.T) {
	tests := []handleUplinkTest{
		{genPULL_DATA(), core.GatewayAddress("a1"), 1, 0, 0},
	}

	for _, test := range tests {
		test.run(t)
	}
}

type handleUplinkTest struct {
	packet        semtech.Packet
	gateway       core.GatewayAddress
	wantAck       int
	wantForward   int
	wantBroadcast int
}

func (test handleUplinkTest) run(t *testing.T) {
	// Describe
	Desc(t, "Handle uplink packet %v from gateway %v", test.packet, test.gateway)

	// Build
	router, upAdapter, downAdapter := genAdaptersAndRouter(t)

	// Operate
	router.HandleUplink(test.packet, test.gateway)

	// Check
	checkUplink(t, upAdapter, downAdapter, test.wantAck, test.wantForward, test.wantBroadcast)
}

// ----- Build Utilities
func genBrokers() []core.BrokerAddress {
	return []core.BrokerAddress{
		core.BrokerAddress("0.0.0.0:3000"),
		core.BrokerAddress("0.0.0.0:3001"),
	}
}

func genAdaptersAndRouter(t *testing.T) (core.Router, core.GatewayRouterAdapter, core.RouterBrokerAdapter) {
	brokers := genBrokers()
	router, err := NewRouter(brokers...)
	if err != nil {
		panic(err)
	}

	upAdapter := gtw_rtr_mock.New()
	downAdapter := rtr_brk_mock.New()

	upAdapter.Listen(router, nil)
	downAdapter.Listen(router, brokers)
	router.Connect(upAdapter, downAdapter)

	return router, upAdapter, downAdapter
}

func genPULL_DATA() semtech.Packet {
	return semtech.Packet{
		Version:    semtech.VERSION,
		Identifier: semtech.PULL_DATA,
		Token:      []byte{0x14, 0xba},
		GatewayId:  []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
	}
}

// ----- Check Utilities
func checkErrors(t *testing.T, want error, got error, router core.Router) {
	if want != got {
		Ko(t, "Expected error {%v} but got {%v}", want, got)
		return
	}

	if want == nil && router == nil {
		Ko(t, "Expected no error but got a nil router")
		return
	}

	Ok(t)
}

func checkUplink(t *testing.T, upAdapter core.GatewayRouterAdapter, downAdapter core.RouterBrokerAdapter, wantAck int, wantForward int, wantBroadcast int) {
	mockUp := upAdapter.(*gtw_rtr_mock.Adapter)
	mockDown := downAdapter.(*rtr_brk_mock.Adapter)

	if len(mockDown.Broadcasts) != wantBroadcast {
		Ko(t, "Expected %d broadcast(s) but %d has/have been done", wantBroadcast, len(mockDown.Broadcasts))
		return
	}

	if len(mockDown.Forwards) != wantForward {
		Ko(t, "Expected %d forward(s) but %d has/have been done", wantForward, len(mockDown.Forwards))
	}

	if len(mockUp.Acks) != wantAck {
		Ko(t, "Expected %d ack(s) but got %d", wantAck, len(mockUp.Acks))
		return
	}

	Ok(t)
}
<|endoftext|>