<commit_before>package codegen

import (
	"strconv"

	"github.com/llir/llvm/ir"
	"github.com/llir/llvm/ir/value"
)

type ResultType int

const (
	VOID    ResultType = iota // fragment will not produce a value
	VALUE                     // fragment will produce a value
	POINTER                   // fragment will produce a pointer value
)

type FragmentType int

const (
	MODULE FragmentType = iota
	FUNCTIONS
	BLOCKS
	INSTRUCTIONS
)

// Fragment represents a fragment of instructions in asm
type Fragment interface {
	Append(fragment Fragment)
	AppendWithResultPropogation(fragment Fragment)
	GetResultType() ResultType
	GetResult() value.Value
}

type ModuleFragment struct {
	Module *ir.Module
}

func NewModuleFragment(module *ir.Module) *ModuleFragment {
	if module == nil {
		module = ir.NewModule()
	}

	return &ModuleFragment{Module: module}
}

func (moduleFragment *ModuleFragment) Append(fragment Fragment) {
	switch f := fragment.(type) {
	case *ModuleFragment:
		panic("Cannot append module to module")
	case *FunctionsFragment:
		moduleFragment.Module.Funcs = append(moduleFragment.Module.Funcs, f.Functions...)

		for _, function := range f.Functions {
			function.Parent = moduleFragment.Module
		}
	case *BlocksFragment:
		panic("Cannot append blocks to module")
	case *InstructionsFragment:
		panic("Cannot append instructions to module")
	}
}

func (moduleFragment *ModuleFragment) AppendWithResultPropogation(fragment Fragment) {
	moduleFragment.Append(fragment)
}

func (moduleFragment *ModuleFragment) GetResultType() ResultType {
	return VOID
}

func (moduleFragment *ModuleFragment) GetResult() value.Value {
	return nil
}

type FunctionsFragment struct {
	Functions       []*ir.Func
	currentFunction *ir.Func
}

func NewFunctionsFragment() *FunctionsFragment {
	functions := make([]*ir.Func, 0)

	return &FunctionsFragment{Functions: functions, currentFunction: nil}
}

func (functionsFragment *FunctionsFragment) AddFunc(function *ir.Func) {
	if function == nil {
		panic("Cannot add nil function")
	}

	functionsFragment.Functions = append(functionsFragment.Functions, function)
	functionsFragment.currentFunction = function
}

func (functionsFragment *FunctionsFragment) Append(fragment Fragment) {
	switch f := fragment.(type) {
	case *ModuleFragment:
		panic("Cannot append module to function")
	case *FunctionsFragment:
		if f.Functions != nil && len(f.Functions) > 0 {
			functionsFragment.Functions = append(functionsFragment.Functions, f.Functions...)

			functionsFragment.currentFunction = f.currentFunction
		}
	case *BlocksFragment:
		blocks := functionsFragment.currentFunction.Blocks

		// Chain new blocks to existing blocks
		numberOfBlocks := len(blocks)
		if numberOfBlocks > 0 && blocks[numberOfBlocks-1].Term == nil && len(f.Blocks) > 0 {
			blocks[numberOfBlocks-1].NewBr(f.Blocks[0])
		}

		functionsFragment.currentFunction.Blocks = append(blocks, f.Blocks...)

		for _, block := range f.Blocks {
			block.Parent = functionsFragment.currentFunction
		}
	case *InstructionsFragment:
		blockLength := len(functionsFragment.currentFunction.Blocks)
		lastBlock := functionsFragment.currentFunction.Blocks[blockLength-1]
		instructions := lastBlock.Insts

		lastBlock.Insts = append(instructions, f.Instructions...)
	}
}

func (functionsFragment *FunctionsFragment) AppendWithResultPropogation(fragment Fragment) {
	functionsFragment.Append(fragment)
}

func (functionsFragment *FunctionsFragment) GetResultType() ResultType {
	return VOID
}

func (functionsFragment *FunctionsFragment) GetResult() value.Value {
	return nil
}

type BlocksFragment struct {
	Blocks       []*ir.Block
	CurrentBlock *ir.Block
	resultType   ResultType
	resultValue  value.Value
}

func NewBlocksFragment(resultType ResultType) *BlocksFragment {
	blocks := make([]*ir.Block, 0)

	return &BlocksFragment{Blocks: blocks, CurrentBlock: nil, resultType: resultType, resultValue: nil}
}

func (blocksFragment *BlocksFragment) Append(fragment Fragment) {
	switch f := fragment.(type) {
	case *ModuleFragment:
		panic("Cannot append blocks to module")
	case *FunctionsFragment:
		panic("Cannot append blocks to functions")
	case *BlocksFragment:
		if len(f.Blocks) > 0 {
			blocksFragment.ChainBlocks(f.Blocks...)
			blocksFragment.Blocks = append(blocksFragment.Blocks, f.Blocks...)
			blocksFragment.CurrentBlock = f.CurrentBlock
		}

	case *InstructionsFragment:
		blocksFragment.CurrentBlock.Insts = append(blocksFragment.CurrentBlock.Insts, f.Instructions...)
	}
}

func (blocksFragment *BlocksFragment) AppendWithResultPropogation(fragment Fragment) {
	switch f := fragment.(type) {
	case *ModuleFragment:
		panic("Cannot append blocks to module")
	case *FunctionsFragment:
		panic("Cannot append blocks to functions")
	case *BlocksFragment:
		if len(f.Blocks) > 0 {
			blocksFragment.ChainBlocks(f.Blocks...)
			blocksFragment.Blocks = append(blocksFragment.Blocks, f.Blocks...)
			blocksFragment.CurrentBlock = f.CurrentBlock

			blocksFragment.resultType = f.resultType
			blocksFragment.resultValue = f.resultValue
		}

	case *InstructionsFragment:
		blocksFragment.CurrentBlock.Insts = append(blocksFragment.CurrentBlock.Insts, f.Instructions...)
	}
}

func (blocksFragment *BlocksFragment) GetResultType() ResultType {
	return blocksFragment.resultType
}

func (blocksFragment *BlocksFragment) GetResult() value.Value {
	switch blocksFragment.resultType {
	case VOID:
		return nil
	case VALUE, POINTER:
		return blocksFragment.resultValue
	default:
		panic("does not support other result type" + strconv.Itoa((int)(blocksFragment.resultType)))
	}
}

func (blocksFragment *BlocksFragment) NewBlock(name string) {
	newBlock := ir.NewBlock(name)

	blocksFragment.ChainBlocks(newBlock)
	blocksFragment.Blocks = append(blocksFragment.Blocks, newBlock)
	blocksFragment.CurrentBlock = newBlock
}

func (blocksFragment *BlocksFragment) AddBlock(block *ir.Block) {
	if block != nil {
		blocksFragment.ChainBlocks(block)
		blocksFragment.Blocks = append(blocksFragment.Blocks, block)
		blocksFragment.CurrentBlock = block
	}
}

func (blocksFragment *BlocksFragment) ChainBlocks(blocks ...*ir.Block) {
	if blocksFragment.CurrentBlock != nil && blocksFragment.CurrentBlock.Term == nil &&
		blocks != nil && len(blocks) > 0 {
		blocksFragment.CurrentBlock.NewBr(blocks[0])
	}
}

type InstructionsFragment struct {
	Instructions       []ir.Instruction
	currentInstruction *ir.Instruction
	resultType         ResultType
	resultValue        value.Value
}

func NewInstructionsFragment(resultType ResultType) *InstructionsFragment {
	instructions := make([]ir.Instruction, 0)

	return &InstructionsFragment{Instructions: instructions, currentInstruction: nil, resultType: resultType, resultValue: nil}
}

func (instructionsFragment *InstructionsFragment) Append(fragment Fragment) {
	switch f := fragment.(type) {
	case *ModuleFragment:
		panic("Cannot append instructions to module")
	case *FunctionsFragment:
		panic("Cannot append instructions to functions")
	case *BlocksFragment:
		panic("Cannot append instructions to blocks")
	case *InstructionsFragment:
		instructionsFragment.Instructions = append(instructionsFragment.Instructions, f.Instructions...)
		instructionsFragment.currentInstruction = f.currentInstruction
	}
}

func (instructionsFragment *InstructionsFragment) AppendWithResultPropogation(fragment Fragment) {

}

func (instructionsFragment *InstructionsFragment) GetResultType() ResultType {
	return instructionsFragment.resultType
}

func (instructionsFragment *InstructionsFragment) GetResult() value.Value {
	switch instructionsFragment.resultType {
	case VOID:
		return nil
	case VALUE:
		return instructionsFragment.resultValue
	default:
		panic("does not support other result type" + strconv.Itoa((int)(instructionsFragment.resultType)))
	}
}

func (instructionsFragment *InstructionsFragment) AddInstruction(instr ir.Instruction) {
	instructionsFragment.Instructions = append(instructionsFragment.Instructions, instr)
}
<commit_msg>panic when appending blocks to empty functionsFragment<commit_after>package codegen

import (
	"strconv"

	"github.com/llir/llvm/ir"
	"github.com/llir/llvm/ir/value"
)

type ResultType int

const (
	VOID    ResultType = iota // fragment will not produce a value
	VALUE                     // fragment will produce a value
	POINTER                   // fragment will produce a pointer value
)

type FragmentType int

const (
	MODULE FragmentType = iota
	FUNCTIONS
	BLOCKS
	INSTRUCTIONS
)

// Fragment represents a fragment of instructions in asm
type Fragment interface {
	Append(fragment Fragment)
	AppendWithResultPropogation(fragment Fragment)
	GetResultType() ResultType
	GetResult() value.Value
}

type ModuleFragment struct {
	Module *ir.Module
}

func NewModuleFragment(module *ir.Module) *ModuleFragment {
	if module == nil {
		module = ir.NewModule()
	}

	return &ModuleFragment{Module: module}
}

func (moduleFragment *ModuleFragment) Append(fragment Fragment) {
	switch f := fragment.(type) {
	case *ModuleFragment:
		panic("Cannot append module to module")
	case *FunctionsFragment:
		moduleFragment.Module.Funcs = append(moduleFragment.Module.Funcs, f.Functions...)

		for _, function := range f.Functions {
			function.Parent = moduleFragment.Module
		}
	case *BlocksFragment:
		panic("Cannot append blocks to module")
	case *InstructionsFragment:
		panic("Cannot append instructions to module")
	}
}

func (moduleFragment *ModuleFragment) AppendWithResultPropogation(fragment Fragment) {
	moduleFragment.Append(fragment)
}

func (moduleFragment *ModuleFragment) GetResultType() ResultType {
	return VOID
}

func (moduleFragment *ModuleFragment) GetResult() value.Value {
	return nil
}

type FunctionsFragment struct {
	Functions       []*ir.Func
	currentFunction *ir.Func
}

func NewFunctionsFragment() *FunctionsFragment {
	functions := make([]*ir.Func, 0)

	return &FunctionsFragment{Functions: functions, currentFunction: nil}
}

func (functionsFragment *FunctionsFragment) AddFunc(function *ir.Func) {
	if function == nil {
		panic("Cannot add nil function")
	}

	functionsFragment.Functions = append(functionsFragment.Functions, function)
	functionsFragment.currentFunction = function
}

func (functionsFragment *FunctionsFragment) Append(fragment Fragment) {
	switch f := fragment.(type) {
	case *ModuleFragment:
		panic("Cannot append module to function")
	case *FunctionsFragment:
		if f.Functions != nil && len(f.Functions) > 0 {
			functionsFragment.Functions = append(functionsFragment.Functions, f.Functions...)

			functionsFragment.currentFunction = f.currentFunction
		}
	case *BlocksFragment:
		if functionsFragment.currentFunction == nil {
			panic("FunctionsFragment does not contain any function")
		}
		blocks := functionsFragment.currentFunction.Blocks

		// Chain new blocks to existing blocks
		numberOfBlocks := len(blocks)
		if numberOfBlocks > 0 && blocks[numberOfBlocks-1].Term == nil && len(f.Blocks) > 0 {
			blocks[numberOfBlocks-1].NewBr(f.Blocks[0])
		}

		functionsFragment.currentFunction.Blocks = append(blocks, f.Blocks...)

		for _, block := range f.Blocks {
			block.Parent = functionsFragment.currentFunction
		}
	case *InstructionsFragment:
		blockLength := len(functionsFragment.currentFunction.Blocks)
		lastBlock := functionsFragment.currentFunction.Blocks[blockLength-1]
		instructions := lastBlock.Insts

		lastBlock.Insts = append(instructions, f.Instructions...)
	}
}

func (functionsFragment *FunctionsFragment) AppendWithResultPropogation(fragment Fragment) {
	functionsFragment.Append(fragment)
}

func (functionsFragment *FunctionsFragment) GetResultType() ResultType {
	return VOID
}

func (functionsFragment *FunctionsFragment) GetResult() value.Value {
	return nil
}

type BlocksFragment struct {
	Blocks       []*ir.Block
	CurrentBlock *ir.Block
	resultType   ResultType
	resultValue  value.Value
}

func NewBlocksFragment(resultType ResultType) *BlocksFragment {
	blocks := make([]*ir.Block, 0)

	return &BlocksFragment{Blocks: blocks, CurrentBlock: nil, resultType: resultType, resultValue: nil}
}

func (blocksFragment *BlocksFragment) Append(fragment Fragment) {
	switch f := fragment.(type) {
	case *ModuleFragment:
		panic("Cannot append blocks to module")
	case *FunctionsFragment:
		panic("Cannot append blocks to functions")
	case *BlocksFragment:
		if len(f.Blocks) > 0 {
			blocksFragment.ChainBlocks(f.Blocks...)
			blocksFragment.Blocks = append(blocksFragment.Blocks, f.Blocks...)
			blocksFragment.CurrentBlock = f.CurrentBlock
		}

	case *InstructionsFragment:
		blocksFragment.CurrentBlock.Insts = append(blocksFragment.CurrentBlock.Insts, f.Instructions...)
	}
}

func (blocksFragment *BlocksFragment) AppendWithResultPropogation(fragment Fragment) {
	switch f := fragment.(type) {
	case *ModuleFragment:
		panic("Cannot append blocks to module")
	case *FunctionsFragment:
		panic("Cannot append blocks to functions")
	case *BlocksFragment:
		if len(f.Blocks) > 0 {
			blocksFragment.ChainBlocks(f.Blocks...)
			blocksFragment.Blocks = append(blocksFragment.Blocks, f.Blocks...)
			blocksFragment.CurrentBlock = f.CurrentBlock

			blocksFragment.resultType = f.resultType
			blocksFragment.resultValue = f.resultValue
		}

	case *InstructionsFragment:
		blocksFragment.CurrentBlock.Insts = append(blocksFragment.CurrentBlock.Insts, f.Instructions...)
	}
}

func (blocksFragment *BlocksFragment) GetResultType() ResultType {
	return blocksFragment.resultType
}

func (blocksFragment *BlocksFragment) GetResult() value.Value {
	switch blocksFragment.resultType {
	case VOID:
		return nil
	case VALUE, POINTER:
		return blocksFragment.resultValue
	default:
		panic("does not support other result type" + strconv.Itoa((int)(blocksFragment.resultType)))
	}
}

func (blocksFragment *BlocksFragment) NewBlock(name string) {
	newBlock := ir.NewBlock(name)

	blocksFragment.ChainBlocks(newBlock)
	blocksFragment.Blocks = append(blocksFragment.Blocks, newBlock)
	blocksFragment.CurrentBlock = newBlock
}

func (blocksFragment *BlocksFragment) AddBlock(block *ir.Block) {
	if block != nil {
		blocksFragment.ChainBlocks(block)
		blocksFragment.Blocks = append(blocksFragment.Blocks, block)
		blocksFragment.CurrentBlock = block
	}
}

func (blocksFragment *BlocksFragment) ChainBlocks(blocks ...*ir.Block) {
	if blocksFragment.CurrentBlock != nil && blocksFragment.CurrentBlock.Term == nil &&
		blocks != nil && len(blocks) > 0 {
		blocksFragment.CurrentBlock.NewBr(blocks[0])
	}
}

type InstructionsFragment struct {
	Instructions       []ir.Instruction
	currentInstruction *ir.Instruction
	resultType         ResultType
	resultValue        value.Value
}

func NewInstructionsFragment(resultType ResultType) *InstructionsFragment {
	instructions := make([]ir.Instruction, 0)

	return &InstructionsFragment{Instructions: instructions, currentInstruction: nil, resultType: resultType, resultValue: nil}
}

func (instructionsFragment *InstructionsFragment) Append(fragment Fragment) {
	switch f := fragment.(type) {
	case *ModuleFragment:
		panic("Cannot append instructions to module")
	case *FunctionsFragment:
		panic("Cannot append instructions to functions")
	case *BlocksFragment:
		panic("Cannot append instructions to blocks")
	case *InstructionsFragment:
		instructionsFragment.Instructions = append(instructionsFragment.Instructions, f.Instructions...)
		instructionsFragment.currentInstruction = f.currentInstruction
	}
}

func (instructionsFragment *InstructionsFragment) AppendWithResultPropogation(fragment Fragment) {

}

func (instructionsFragment *InstructionsFragment) GetResultType() ResultType {
	return instructionsFragment.resultType
}

func (instructionsFragment *InstructionsFragment) GetResult() value.Value {
	switch instructionsFragment.resultType {
	case VOID:
		return nil
	case VALUE:
		return instructionsFragment.resultValue
	default:
		panic("does not support other result type" + strconv.Itoa((int)(instructionsFragment.resultType)))
	}
}

func (instructionsFragment *InstructionsFragment) AddInstruction(instr ir.Instruction) {
	instructionsFragment.Instructions = append(instructionsFragment.Instructions, instr)
}
<|endoftext|>


<commit_before>package vnetpeering

import (
	"context"
	"fmt"

	"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network"
	"github.com/giantswarm/microerror"
	"github.com/giantswarm/operatorkit/controller/context/resourcecanceledcontext"

	"github.com/giantswarm/azure-operator/client"
	"github.com/giantswarm/azure-operator/service/controller/v2/key"
)

// GetCurrentState retrieve the current host cluster virtual network peering
// resource from azure.
func (r *Resource) GetCurrentState(ctx context.Context, obj interface{}) (interface{}, error) {
	customObject, err := key.ToCustomObject(obj)
	if err != nil {
		return network.VirtualNetworkPeering{}, microerror.Mask(err)
	}

	// In order to make vnet peering work we need a virtual network which we can
	// use to peer. In case there is no virtual network yet we cancel the resource
	// and try again on the next resync period. This is a classical scenario on
	// guest cluster creation. If we would not check for the virtual network
	// existence the client calls of CreateOrUpdate would fail with not found
	// errors.
	{
		c, err := r.getVirtualNetworksClient()
		if err != nil {
			return network.VirtualNetworkPeering{}, microerror.Mask(err)
		}

		g := key.ResourceGroupName(customObject)
		n := key.VnetName(customObject)
		e := ""
		v, err := c.Get(ctx, g, n, e)
		if IsVirtualNetworkNotFound(err) {
			r.logger.LogCtx(ctx, "level", "debug", "message", "did not find the virtual network in the Azure API")
			resourcecanceledcontext.SetCanceled(ctx)
			r.logger.LogCtx(ctx, "level", "debug", "message", "canceling resource for custom object")

			return network.VirtualNetworkPeering{}, nil
		} else if err != nil {
			return network.VirtualNetworkPeering{}, microerror.Mask(err)
		} else {
			s := *v.ProvisioningState

			if !key.IsFinalProvisioningState(s) {
				r.logger.LogCtx(ctx, "level", "debug", "message", fmt.Sprintf("virtual network is in state '%s'", s))
				resourcecanceledcontext.SetCanceled(ctx)
				r.logger.LogCtx(ctx, "level", "debug", "message", "canceling resource for custom object")

				return network.VirtualNetworkPeering{}, nil
			}
		}
	}

	// Look for the current state of the vnet peering. It is a valid operation to
	// not find any state. This indicates we want to create the vnet peering in
	// the following steps.
	var vnetPeering network.VirtualNetworkPeering
	{
		r.logger.LogCtx(ctx, "level", "debug", "message", "looking for the vnet peerings in the Azure API")

		c, err := r.getVnetPeeringClient()
		if err != nil {
			return network.VirtualNetworkPeering{}, microerror.Mask(err)
		}

		g := r.azure.HostCluster.ResourceGroup
		n := key.ResourceGroupName(customObject)
		vnetPeering, err = c.Get(ctx, g, g, n)
		if client.ResponseWasNotFound(vnetPeering.Response) {
			r.logger.LogCtx(ctx, "level", "debug", "message", "did not find the vnet peerings in the Azure API")

			return network.VirtualNetworkPeering{}, nil
		} else if err != nil {
			return network.VirtualNetworkPeering{}, microerror.Mask(err)
		}

		r.logger.LogCtx(ctx, "level", "debug", "message", "found the vnet peerings in the Azure API")
	}

	return vnetPeering, nil
}
<commit_msg>does not cancel resource on deletion when resources should be removed (#219)<commit_after>package vnetpeering

import (
	"context"
	"fmt"

	"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network"
	"github.com/giantswarm/microerror"
	"github.com/giantswarm/operatorkit/controller/context/resourcecanceledcontext"

	"github.com/giantswarm/azure-operator/client"
	"github.com/giantswarm/azure-operator/service/controller/v2/key"
)

// GetCurrentState retrieve the current host cluster virtual network peering
// resource from azure.
func (r *Resource) GetCurrentState(ctx context.Context, obj interface{}) (interface{}, error) {
	customObject, err := key.ToCustomObject(obj)
	if err != nil {
		return network.VirtualNetworkPeering{}, microerror.Mask(err)
	}

	// In order to make vnet peering work we need a virtual network which we can
	// use to peer. In case there is no virtual network yet we cancel the resource
	// and try again on the next resync period. This is a classical scenario on
	// guest cluster creation. If we would not check for the virtual network
	// existence the client calls of CreateOrUpdate would fail with not found
	// errors.
	if !key.IsDeleted(customObject) {
		c, err := r.getVirtualNetworksClient()
		if err != nil {
			return network.VirtualNetworkPeering{}, microerror.Mask(err)
		}

		g := key.ResourceGroupName(customObject)
		n := key.VnetName(customObject)
		e := ""
		v, err := c.Get(ctx, g, n, e)
		if IsVirtualNetworkNotFound(err) {
			r.logger.LogCtx(ctx, "level", "debug", "message", "did not find the virtual network in the Azure API")
			resourcecanceledcontext.SetCanceled(ctx)
			r.logger.LogCtx(ctx, "level", "debug", "message", "canceling resource for custom object")

			return network.VirtualNetworkPeering{}, nil
		} else if err != nil {
			return network.VirtualNetworkPeering{}, microerror.Mask(err)
		} else {
			s := *v.ProvisioningState

			if !key.IsFinalProvisioningState(s) {
				r.logger.LogCtx(ctx, "level", "debug", "message", fmt.Sprintf("virtual network is in state '%s'", s))
				resourcecanceledcontext.SetCanceled(ctx)
				r.logger.LogCtx(ctx, "level", "debug", "message", "canceling resource for custom object")

				return network.VirtualNetworkPeering{}, nil
			}
		}
	}

	// Look for the current state of the vnet peering. It is a valid operation to
	// not find any state. This indicates we want to create the vnet peering in
	// the following steps.
	var vnetPeering network.VirtualNetworkPeering
	{
		r.logger.LogCtx(ctx, "level", "debug", "message", "looking for the vnet peerings in the Azure API")

		c, err := r.getVnetPeeringClient()
		if err != nil {
			return network.VirtualNetworkPeering{}, microerror.Mask(err)
		}

		g := r.azure.HostCluster.ResourceGroup
		n := key.ResourceGroupName(customObject)
		vnetPeering, err = c.Get(ctx, g, g, n)
		if client.ResponseWasNotFound(vnetPeering.Response) {
			r.logger.LogCtx(ctx, "level", "debug", "message", "did not find the vnet peerings in the Azure API")

			return network.VirtualNetworkPeering{}, nil
		} else if err != nil {
			return network.VirtualNetworkPeering{}, microerror.Mask(err)
		}

		r.logger.LogCtx(ctx, "level", "debug", "message", "found the vnet peerings in the Azure API")
	}

	return vnetPeering, nil
}
<|endoftext|>


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

// This binary simulates the report origins sending requests to helpers for aggregating partial reports.
package main

import (
	"context"
	"flag"

	log "github.com/golang/glog"
	"google.golang.org/grpc"
	"github.com/google/privacy-sandbox-aggregation-service/service/query"

	pb "github.com/google/privacy-sandbox-aggregation-service/pipeline/crypto_go_proto"
	grpcpb "github.com/google/privacy-sandbox-aggregation-service/service/service_go_grpc_proto"
)

var (
	helperAddr1 = flag.String("helper_addr1", "", "Address of helper 1.")
	helperAddr2 = flag.String("helper_addr2", "", "Address of helper 2.")

	partialReportFile1        = flag.String("partial_report_file1", "", "Input partial report for helper 1.")
	partialReportFile2        = flag.String("partial_report_file2", "", "Input partial report for helper 2.")
	hierarchicalHistogramFile = flag.String("hierarchical_histogram_file", "", "Output file for the hierarchical aggregation results.")
	expansionConfigFile       = flag.String("expansion_config_file", "", "Input file for the expansion configurations that defines the query hierarchy.")
	paramsDir                 = flag.String("params_dir", "", "Input directory that stores the parameter files.")
	partialAggregationDir     = flag.String("partial_aggregation_dir", "", "Output directory for the partial aggregation files.")
)

func main() {
	flag.Parse()

	ctx := context.Background()
	expansionConfig, err := query.ReadExpansionConfigFile(ctx, *expansionConfigFile)
	if err != nil {
		log.Exit(err)
	}

	conn1, err := grpc.Dial(*helperAddr1, nil)
	if err != nil {
		log.Exit(err)
	}
	defer conn1.Close()

	conn2, err := grpc.Dial(*helperAddr2, nil)
	if err != nil {
		log.Exit(err)
	}
	defer conn2.Close()

	params := &query.PrefixHistogramParams{
		Prefixes:              &pb.HierarchicalPrefixes{Prefixes: []*pb.DomainPrefixes{{}}},
		SumParams:             &pb.IncrementalDpfParameters{},
		PartialReportFile1:    *partialReportFile1,
		PartialReportFile2:    *partialReportFile2,
		PartialAggregationDir: *partialAggregationDir,
		ParamsDir:             *paramsDir,
		Helper1:               grpcpb.NewAggregatorClient(conn1),
		Helper2:               grpcpb.NewAggregatorClient(conn2),
	}

	results, err := query.HierarchicalAggregation(ctx, params, expansionConfig)
	if err != nil {
		log.Exit(err)
	}
	if err := query.WriteHierarchicalResultsFile(ctx, results, *hierarchicalHistogramFile); err != nil {
		log.Exit(err)
	}
}
<commit_msg>Use grpc.WithInsecure() for the required DialOption. There are lots of other options, and grpc.WithInsecure() is used for simplicity.<commit_after>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// This binary simulates the report origins sending requests to helpers for aggregating partial reports.
package main

import (
	"context"
	"flag"

	log "github.com/golang/glog"
	"google.golang.org/grpc"
	"github.com/google/privacy-sandbox-aggregation-service/service/query"

	pb "github.com/google/privacy-sandbox-aggregation-service/pipeline/crypto_go_proto"
	grpcpb "github.com/google/privacy-sandbox-aggregation-service/service/service_go_grpc_proto"
)

var (
	helperAddr1 = flag.String("helper_addr1", "", "Address of helper 1.")
	helperAddr2 = flag.String("helper_addr2", "", "Address of helper 2.")

	partialReportFile1        = flag.String("partial_report_file1", "", "Input partial report for helper 1.")
	partialReportFile2        = flag.String("partial_report_file2", "", "Input partial report for helper 2.")
	hierarchicalHistogramFile = flag.String("hierarchical_histogram_file", "", "Output file for the hierarchical aggregation results.")
	expansionConfigFile       = flag.String("expansion_config_file", "", "Input file for the expansion configurations that defines the query hierarchy.")
	paramsDir                 = flag.String("params_dir", "", "Input directory that stores the parameter files.")
	partialAggregationDir     = flag.String("partial_aggregation_dir", "", "Output directory for the partial aggregation files.")
)

func main() {
	flag.Parse()

	ctx := context.Background()
	expansionConfig, err := query.ReadExpansionConfigFile(ctx, *expansionConfigFile)
	if err != nil {
		log.Exit(err)
	}

	// grpc.WithInsecure() is used for demonstration, and for real instances we should use more secure options.
	conn1, err := grpc.Dial(*helperAddr1, grpc.WithInsecure())
	if err != nil {
		log.Exit(err)
	}
	defer conn1.Close()

	conn2, err := grpc.Dial(*helperAddr2, grpc.WithInsecure())
	if err != nil {
		log.Exit(err)
	}
	defer conn2.Close()

	params := &query.PrefixHistogramParams{
		Prefixes:              &pb.HierarchicalPrefixes{Prefixes: []*pb.DomainPrefixes{{}}},
		SumParams:             &pb.IncrementalDpfParameters{},
		PartialReportFile1:    *partialReportFile1,
		PartialReportFile2:    *partialReportFile2,
		PartialAggregationDir: *partialAggregationDir,
		ParamsDir:             *paramsDir,
		Helper1:               grpcpb.NewAggregatorClient(conn1),
		Helper2:               grpcpb.NewAggregatorClient(conn2),
	}

	results, err := query.HierarchicalAggregation(ctx, params, expansionConfig)
	if err != nil {
		log.Exit(err)
	}
	if err := query.WriteHierarchicalResultsFile(ctx, results, *hierarchicalHistogramFile); err != nil {
		log.Exit(err)
	}
}
<|endoftext|>


<commit_before>package db

/*
Simple CASE Expression
----------------------

The syntax for a simple CASE expression is:

SELECT CASE ("column_name")
  WHEN "value1" THEN "result1"
  WHEN "value2" THEN "result2"
  ...
  [ELSE "resultN"]
  END
FROM "table_name";

Searched CASE Expression
------------------------

The syntax for a searched CASE expression is:

SELECT CASE
  WHEN "condition1" THEN "result1"
  WHEN "condition2" THEN "result2"
  ...
  [ELSE "resultN"]
  END
FROM "table_name";
*/

type SearchedWhen struct {
	parent   *SearchedCase
	criteria *Criteria
	result   interface{}
}

type SearchedCase struct {
	whens []*SearchedWhen
	other interface{}
	alias string
}

func NewSearchedCase() *SearchedCase {
	this := new(SearchedCase)
	this.whens = make([]*SearchedWhen, 0)
	return this
}

func (this *SearchedCase) If(criteria *Criteria) *SearchedWhen {
	when := new(SearchedWhen)
	when.parent = this
	when.criteria = criteria
	this.whens = append(this.whens, when)
	return when
}

func (this *SearchedWhen) Then(value interface{}) *SearchedCase {
	this.result = value
	return this.parent
}

func (this *SearchedCase) Else(value interface{}) *SearchedCase {
	this.other = value
	return this
}

func (this *SearchedCase) End() *Token {
	vals := make([]interface{}, 0)
	for _, v := range this.whens {
		vals = append(vals, NewToken(TOKEN_CASE_WHEN, v.criteria, v.result))
	}
	if this.other != nil {
		vals = append(vals, NewToken(TOKEN_CASE_ELSE, this.other))
	}
	return NewToken(TOKEN_CASE, vals...)
}

type SimpleWhen struct {
	parent     *SimpleCase
	expression interface{}
	result     interface{}
}

type SimpleCase struct {
	expression interface{}
	whens      []*SimpleWhen
	other      interface{}
	alias      string
}

func NewSimpleCase(expression interface{}) *SimpleCase {
	this := new(SimpleCase)
	this.expression = expression
	return this
}

func (this *SimpleCase) When(expression interface{}) *SimpleWhen {
	when := new(SimpleWhen)
	when.parent = this
	when.expression = expression
	this.whens = append(this.whens, when)
	return when
}

func (this *SimpleWhen) Then(value interface{}) *SimpleCase {
	this.result = value
	return this.parent
}

func (this *SimpleCase) Else(value interface{}) *SimpleCase {
	this.other = value
	return this
}

func (this *SimpleCase) End() *Token {
	vals := make([]interface{}, 0)
	if this.expression != nil {
		vals = append(vals, this.expression)
	}
	for _, v := range this.whens {
		vals = append(vals, NewToken(TOKEN_CASE_WHEN, v.expression, v.result))
	}
	if this.other != nil {
		vals = append(vals, NewToken(TOKEN_CASE_ELSE, this.other))
	}
	return NewToken(TOKEN_CASE, vals...)
}
<commit_msg>forgot to instantiate whens<commit_after>package db

/*
Simple CASE Expression
----------------------

The syntax for a simple CASE expression is:

SELECT CASE ("column_name")
  WHEN "value1" THEN "result1"
  WHEN "value2" THEN "result2"
  ...
  [ELSE "resultN"]
  END
FROM "table_name";

Searched CASE Expression
------------------------

The syntax for a searched CASE expression is:

SELECT CASE
  WHEN "condition1" THEN "result1"
  WHEN "condition2" THEN "result2"
  ...
  [ELSE "resultN"]
  END
FROM "table_name";
*/

type SearchedWhen struct {
	parent   *SearchedCase
	criteria *Criteria
	result   interface{}
}

type SearchedCase struct {
	whens []*SearchedWhen
	other interface{}
	alias string
}

func NewSearchedCase() *SearchedCase {
	this := new(SearchedCase)
	this.whens = make([]*SearchedWhen, 0)
	return this
}

func (this *SearchedCase) If(criteria *Criteria) *SearchedWhen {
	when := new(SearchedWhen)
	when.parent = this
	when.criteria = criteria
	this.whens = append(this.whens, when)
	return when
}

func (this *SearchedWhen) Then(value interface{}) *SearchedCase {
	this.result = value
	return this.parent
}

func (this *SearchedCase) Else(value interface{}) *SearchedCase {
	this.other = value
	return this
}

func (this *SearchedCase) End() *Token {
	vals := make([]interface{}, 0)
	for _, v := range this.whens {
		vals = append(vals, NewToken(TOKEN_CASE_WHEN, v.criteria, v.result))
	}
	if this.other != nil {
		vals = append(vals, NewToken(TOKEN_CASE_ELSE, this.other))
	}
	return NewToken(TOKEN_CASE, vals...)
}

type SimpleWhen struct {
	parent     *SimpleCase
	expression interface{}
	result     interface{}
}

type SimpleCase struct {
	expression interface{}
	whens      []*SimpleWhen
	other      interface{}
	alias      string
}

func NewSimpleCase(expression interface{}) *SimpleCase {
	this := new(SimpleCase)
	this.expression = expression
	this.whens = make([]*SimpleWhen, 0)
	return this
}

func (this *SimpleCase) When(expression interface{}) *SimpleWhen {
	when := new(SimpleWhen)
	when.parent = this
	when.expression = expression
	this.whens = append(this.whens, when)
	return when
}

func (this *SimpleWhen) Then(value interface{}) *SimpleCase {
	this.result = value
	return this.parent
}

func (this *SimpleCase) Else(value interface{}) *SimpleCase {
	this.other = value
	return this
}

func (this *SimpleCase) End() *Token {
	vals := make([]interface{}, 0)
	if this.expression != nil {
		vals = append(vals, this.expression)
	}
	for _, v := range this.whens {
		vals = append(vals, NewToken(TOKEN_CASE_WHEN, v.expression, v.result))
	}
	if this.other != nil {
		vals = append(vals, NewToken(TOKEN_CASE_ELSE, this.other))
	}
	return NewToken(TOKEN_CASE, vals...)
}
<|endoftext|>


<commit_before>// Copyright 2017 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.

// Command git-p prints the status of pending commits on all branches.
//
// git-p summarizes the status of each commit, including its review
// state in Gerrit and whether or not there are any comments or TryBot
// failures.
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"regexp"
	"strings"
	"unicode/utf8"
)

// TODO: Provide a way to exclude branches (like archive/, etc)

// TODO: Do the right thing if the terminal is dumb.

const (
	// TODO: Support other repos.
	remoteUrl = "https://go.googlesource.com/go"
	project   = "go"
	gerritUrl = "https://go-review.googlesource.com"
)

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [branches...]\n\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "With no arguments, list branches from newest to oldest.\n")
		flag.PrintDefaults()
	}
	flag.Parse()
	branches := flag.Args()

	// Check the branch names.
	for _, b := range branches {
		if out, err := tryGit("rev-parse", b, "--"); err != nil {
			fmt.Printf("%s\n", out)
			os.Exit(1)
		}
	}

	setupPager()

	// Find the Gerrit remote name.
	remote, err := getRemote(remoteUrl)
	if err != nil {
		log.Fatal(err)
	}

	// Get commits that are available from the Gerrit remote.
	upstreams := lines(git("for-each-ref", "--format", "%(objectname)", "refs/remotes/"+remote+"/"))
	if len(upstreams) == 0 {
		log.Fatalf("no refs for remote %s", remote)
	}

	gerrit := NewGerrit(gerritUrl)

	// Pass a token through each showBranch so we can pipeline
	// fetching branch information, while displaying it in order.
	token := make(chan struct{}, 1)
	token <- struct{}{}
	// But if the output of showBranch is blocked (e.g., by
	// back-pressure from a pager), don't start new showBranches.
	// This avoids making lots of ultimately ignored requests to
	// Gerrit.
	limit := make(chan struct{}, 3)

	var head string
	if len(branches) == 0 {
		// Resolve HEAD and show it first regardless of age.
		head, _ = tryGit("symbolic-ref", "HEAD")
		if head != "" {
			token = showBranch(gerrit, head, "HEAD", remote, upstreams, token, limit)
		}

		// Get all local branches, sorted by most recent commit date.
		branches = lines(git("for-each-ref", "--format", "%(refname)", "--sort", "-committerdate", "refs/heads/"))
	}

	// Show all branches.
	for _, branch := range branches {
		if branch == head {
			continue
		}
		token = showBranch(gerrit, branch, "", remote, upstreams, token, limit)
	}

	<-token
}

func showBranch(gerrit *Gerrit, branch, extra string, remote string, upstreams []string, token, limit chan struct{}) chan struct{} {
	// Don't start too many showBranches.
	limit <- struct{}{}

	// Get the Gerrit upstream name so we can construct full
	// Change-IDs.
	upstream := upstreamOf(branch)
	if upstream == "" {
		upstream = "refs/" + remote + "/master"
	}

	// Get commits from the branch to any upstream.
	args := []string{"rev-list", branch}
	for _, u := range upstreams {
		args = append(args, "^"+u)
	}
	args = append(args, "--")
	commits := lines(git(args...))

	// Get Change-Ids from these commits.
	cids := changeIds(project, upstream, commits)

	// Fetch information on all of these changes.
	//
	// We need DETAILED_LABELS to get numeric values of labels.
	changes := make([]*GerritChanges, len(cids))
	for i, cid := range cids {
		// TODO: Would this be simpler with a single big OR query?
		if cid != "" {
			changes[i] = gerrit.QueryChanges("change:"+cid, printChangeOptions...)
		}
	}

	if len(changes) == 0 {
		<-limit
		return token
	}

	done := make(chan struct{})
	go func() {
		<-token
		// Print changes.
		fmt.Printf("\x1b[1;32m%s\x1b[0m", strings.TrimPrefix(branch, "refs/heads/"))
		if extra != "" {
			fmt.Printf(" (\x1b[1;36m%s\x1b[0m)", extra)
		}
		fmt.Printf("\n")
		for i, change := range changes {
			printChange(commits[i], change)
		}
		fmt.Println()
		<-limit
		done <- struct{}{}
	}()
	return done
}

var labelMsg = regexp.MustCompile(`^Patch Set [0-9]+: [-a-zA-Z]+\+[0-9]$`)

func changeStatus(commit string, info *GerritChange) (status string, warnings []string) {
	switch info.Status {
	default:
		return fmt.Sprintf("Unknown status %q", info.Status), nil
	case "MERGED":
		return "Submitted", nil
	case "ABANDONED":
		return "Abandoned", nil
	case "DRAFT":
		return "Draft", nil
	case "NEW":
	}

	// Check for warnings on current PS. (Requires
	// CURRENT_REVISION or ALL_REVISIONS option.)
	curPatchSet := info.Revisions[info.CurrentRevision].Number
	// Are there unmailed changes?
	if info.CurrentRevision != commit {
		// How serious are the differences with the mailed changes?
		pid1, err1 := gitPatchID(info.CurrentRevision)
		pid2, err2 := gitPatchID(commit)
		if !(err1 == nil && err2 == nil && pid1 == pid2) {
			// The patches are different.
			warnings = append(warnings, "Local commit differs from mailed commit")
		} else {
			msg1, err1 := gitCommitMessage(info.CurrentRevision)
			msg2, err2 := gitCommitMessage(commit)
			if !(err1 == nil && err2 == nil && msg1 == msg2) {
				// Patches are the same, but the
				// commit message has changed.
				warnings = append(warnings, "Local commit message differs")
			}
		}
	}
	// Are there rejections?
	rejected := false
	for labelName, label := range info.Labels {
		if !label.Optional && label.Rejected != nil {
			if labelName == "Do-Not-Submit" {
				warnings = append(warnings, "Marked \"Do not submit\"")
			} else {
				warnings = append(warnings, fmt.Sprintf("Rejected by %s", label.Rejected.Name))
				rejected = true
			}
		}
	}
	// Are there comments on the latest PS? (Requires
	// MESSAGES option.)
	nComments := 0
	commentUsers, commentUsersSet := []string{}, map[string]bool{}
	for _, msg := range info.Messages {
		if msg.PatchSet != curPatchSet {
			continue
		}
		// Ignore automated comments.
		if strings.HasPrefix(msg.Tag, "autogenerated:gerrit:") {
			continue
		}
		// Ignore label-only messages (ugh, why aren't these
		// better marked?)
		if labelMsg.MatchString(msg.Message) {
			continue
		}
		// Ignore TryBot comments (Requires
		// DETAILED_ACCOUNTS option.)
		if msg.Author.Email == "gobot@golang.org" {
			continue
		}
		nComments++
		if !commentUsersSet[msg.Author.Name] {
			commentUsersSet[msg.Author.Name] = true
			commentUsers = append(commentUsers, msg.Author.Name)
		}
	}
	if nComments > 0 {
		msg := "1 comment"
		if nComments > 1 {
			msg = fmt.Sprintf("%d comments", nComments)
		}
		msg += " on latest PS from " + strings.Join(commentUsers, ", ")
		warnings = append(warnings, msg)
	}
	// Are the trybots unhappy? (Requires LABELS option.)
	if tbr := info.Labels["TryBot-Result"]; tbr != nil && tbr.Rejected != nil {
		// TODO: List failed configs
		warnings = append(warnings, "TryBots are unhappy")
	} else if tbr == nil || tbr.Approved == nil {
		warnings = append(warnings, "TryBots not run")
	}

	// Submittable? (Requires SUBMITTABLE option.)
	status = "Pending"
	if rejected {
		status = "Rejected"
	} else if info.Submittable {
		status = "Ready"
	}

	return status, warnings
}

var printChangeOptions = []string{"SUBMITTABLE", "LABELS", "CURRENT_REVISION", "MESSAGES", "DETAILED_ACCOUNTS"}

var display = map[string]string{
	"Not mailed": "\x1b[35m", // Magenta

	"Pending warn":  "\x1b[33m",   // Yellow
	"Ready warn":    "\x1b[33m",   // Yellow
	"Rejected warn": "\x1b[1;31m", // Bright red

	"Ready": "\x1b[32m", // Green

	"Submitted": "\x1b[37m",   // Gray
	"Abandoned": "\x1b[9;37m", // Gray, strike-through
	"Draft":     "\x1b[37m",   // Gray
}

// printChange prints a summary of change's status and warnings.
//
// change must be retrieved with options printChangeOptions.
func printChange(commit string, change *GerritChanges) {
	logMsg := git("log", "-n1", "--oneline", commit)

	status, warnings, link := "Not mailed", []string(nil), ""
	if change != nil {
		results, err := change.Wait()
		if err != nil {
			log.Fatal(err)
		}
		if len(results) > 1 {
			log.Fatal("multiple changes found for commit %s", commit)
		}
		if len(results) == 1 {
			status, warnings = changeStatus(commit, results[0])
			//link = fmt.Sprintf("[%s/c/%d]", gerritUrl, results[0].Number)
			link = fmt.Sprintf(" [golang.org/cl/%d]", results[0].Number)
		}
	}

	var control, eControl string
	if len(warnings) != 0 {
		if c, ok := display[status+" warn"]; ok {
			control = c
		}
	}
	if control == "" {
		if c, ok := display[status]; ok {
			control = c
		}
	}
	if control != "" {
		eControl = "\x1b[0m"
	}

	hdr := fmt.Sprintf("%-10s %s", status, logMsg)
	hdrMax := 80 - len(link) - 2
	if utf8.RuneCountInString(hdr) > hdrMax {
		hdr = fmt.Sprintf("%*.*s…", hdrMax-1, hdrMax-1, hdr)
	}
	fmt.Printf("  %s%-*s%s%s\n", control, hdrMax, hdr, eControl, link)
	for _, w := range warnings {
		fmt.Printf("    %s\n", w)
	}
}
<commit_msg>git-p: print which TryBot configs failed<commit_after>// Copyright 2017 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.

// Command git-p prints the status of pending commits on all branches.
//
// git-p summarizes the status of each commit, including its review
// state in Gerrit and whether or not there are any comments or TryBot
// failures.
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"regexp"
	"strings"
	"unicode/utf8"
)

// TODO: Provide a way to exclude branches (like archive/, etc)

// TODO: Do the right thing if the terminal is dumb.

const (
	// TODO: Support other repos.
	remoteUrl = "https://go.googlesource.com/go"
	project   = "go"
	gerritUrl = "https://go-review.googlesource.com"
)

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [branches...]\n\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "With no arguments, list branches from newest to oldest.\n")
		flag.PrintDefaults()
	}
	flag.Parse()
	branches := flag.Args()

	// Check the branch names.
	for _, b := range branches {
		if out, err := tryGit("rev-parse", b, "--"); err != nil {
			fmt.Printf("%s\n", out)
			os.Exit(1)
		}
	}

	setupPager()

	// Find the Gerrit remote name.
	remote, err := getRemote(remoteUrl)
	if err != nil {
		log.Fatal(err)
	}

	// Get commits that are available from the Gerrit remote.
	upstreams := lines(git("for-each-ref", "--format", "%(objectname)", "refs/remotes/"+remote+"/"))
	if len(upstreams) == 0 {
		log.Fatalf("no refs for remote %s", remote)
	}

	gerrit := NewGerrit(gerritUrl)

	// Pass a token through each showBranch so we can pipeline
	// fetching branch information, while displaying it in order.
	token := make(chan struct{}, 1)
	token <- struct{}{}
	// But if the output of showBranch is blocked (e.g., by
	// back-pressure from a pager), don't start new showBranches.
	// This avoids making lots of ultimately ignored requests to
	// Gerrit.
	limit := make(chan struct{}, 3)

	var head string
	if len(branches) == 0 {
		// Resolve HEAD and show it first regardless of age.
		head, _ = tryGit("symbolic-ref", "HEAD")
		if head != "" {
			token = showBranch(gerrit, head, "HEAD", remote, upstreams, token, limit)
		}

		// Get all local branches, sorted by most recent commit date.
		branches = lines(git("for-each-ref", "--format", "%(refname)", "--sort", "-committerdate", "refs/heads/"))
	}

	// Show all branches.
	for _, branch := range branches {
		if branch == head {
			continue
		}
		token = showBranch(gerrit, branch, "", remote, upstreams, token, limit)
	}

	<-token
}

func showBranch(gerrit *Gerrit, branch, extra string, remote string, upstreams []string, token, limit chan struct{}) chan struct{} {
	// Don't start too many showBranches.
	limit <- struct{}{}

	// Get the Gerrit upstream name so we can construct full
	// Change-IDs.
	upstream := upstreamOf(branch)
	if upstream == "" {
		upstream = "refs/" + remote + "/master"
	}

	// Get commits from the branch to any upstream.
	args := []string{"rev-list", branch}
	for _, u := range upstreams {
		args = append(args, "^"+u)
	}
	args = append(args, "--")
	commits := lines(git(args...))

	// Get Change-Ids from these commits.
	cids := changeIds(project, upstream, commits)

	// Fetch information on all of these changes.
	//
	// We need DETAILED_LABELS to get numeric values of labels.
	changes := make([]*GerritChanges, len(cids))
	for i, cid := range cids {
		// TODO: Would this be simpler with a single big OR query?
		if cid != "" {
			changes[i] = gerrit.QueryChanges("change:"+cid, printChangeOptions...)
		}
	}

	if len(changes) == 0 {
		<-limit
		return token
	}

	done := make(chan struct{})
	go func() {
		<-token
		// Print changes.
		fmt.Printf("\x1b[1;32m%s\x1b[0m", strings.TrimPrefix(branch, "refs/heads/"))
		if extra != "" {
			fmt.Printf(" (\x1b[1;36m%s\x1b[0m)", extra)
		}
		fmt.Printf("\n")
		for i, change := range changes {
			printChange(commits[i], change)
		}
		fmt.Println()
		<-limit
		done <- struct{}{}
	}()
	return done
}

var labelMsg = regexp.MustCompile(`^Patch Set [0-9]+: [-a-zA-Z]+\+[0-9]$`)
var trybotFailures = regexp.MustCompile(`(?m)^Failed on ([^:]+):`)

func changeStatus(commit string, info *GerritChange) (status string, warnings []string) {
	switch info.Status {
	default:
		return fmt.Sprintf("Unknown status %q", info.Status), nil
	case "MERGED":
		return "Submitted", nil
	case "ABANDONED":
		return "Abandoned", nil
	case "DRAFT":
		return "Draft", nil
	case "NEW":
	}

	// Check for warnings on current PS. (Requires
	// CURRENT_REVISION or ALL_REVISIONS option.)
	curPatchSet := info.Revisions[info.CurrentRevision].Number
	// Are there unmailed changes?
	if info.CurrentRevision != commit {
		// How serious are the differences with the mailed changes?
		pid1, err1 := gitPatchID(info.CurrentRevision)
		pid2, err2 := gitPatchID(commit)
		if !(err1 == nil && err2 == nil && pid1 == pid2) {
			// The patches are different.
			warnings = append(warnings, "Local commit differs from mailed commit")
		} else {
			msg1, err1 := gitCommitMessage(info.CurrentRevision)
			msg2, err2 := gitCommitMessage(commit)
			if !(err1 == nil && err2 == nil && msg1 == msg2) {
				// Patches are the same, but the
				// commit message has changed.
				warnings = append(warnings, "Local commit message differs")
			}
		}
	}
	// Are there rejections?
	rejected := false
	for labelName, label := range info.Labels {
		if !label.Optional && label.Rejected != nil {
			if labelName == "Do-Not-Submit" {
				warnings = append(warnings, "Marked \"Do not submit\"")
			} else {
				warnings = append(warnings, fmt.Sprintf("Rejected by %s", label.Rejected.Name))
				rejected = true
			}
		}
	}
	// Are there comments on the latest PS? (Requires
	// MESSAGES option.)
	nComments := 0
	commentUsers, commentUsersSet := []string{}, map[string]bool{}
	for _, msg := range info.Messages {
		if msg.PatchSet != curPatchSet {
			continue
		}
		// Ignore automated comments.
		if strings.HasPrefix(msg.Tag, "autogenerated:gerrit:") {
			continue
		}
		// Ignore label-only messages (ugh, why aren't these
		// better marked?)
		if labelMsg.MatchString(msg.Message) {
			continue
		}
		// Ignore TryBot comments (Requires
		// DETAILED_ACCOUNTS option.)
		if msg.Author.Email == "gobot@golang.org" {
			continue
		}
		nComments++
		if !commentUsersSet[msg.Author.Name] {
			commentUsersSet[msg.Author.Name] = true
			commentUsers = append(commentUsers, msg.Author.Name)
		}
	}
	if nComments > 0 {
		msg := "1 comment"
		if nComments > 1 {
			msg = fmt.Sprintf("%d comments", nComments)
		}
		msg += " on latest PS from " + strings.Join(commentUsers, ", ")
		warnings = append(warnings, msg)
	}
	// Are the trybots unhappy? (Requires LABELS option.)
	if tbr := info.Labels["TryBot-Result"]; tbr != nil && tbr.Rejected != nil {
		// Get the failed configs. (Requires MESSAGES option.)
		configs := []string{}
		for _, msg := range info.Messages {
			// Requires DETAILED_ACCOUNTS option.
			if msg.PatchSet != curPatchSet || msg.Author.Email != "gobot@golang.org" {
				continue
			}
			for _, f := range trybotFailures.FindAllStringSubmatch(msg.Message, -1) {
				configs = append(configs, f[1])
			}
		}
		if len(configs) == 0 {
			warnings = append(warnings, "TryBots failed")
		} else {
			warnings = append(warnings, "TryBots failed on "+strings.Join(configs, ", "))
		}
	} else if tbr == nil || tbr.Approved == nil {
		warnings = append(warnings, "TryBots not run")
	}

	// Submittable? (Requires SUBMITTABLE option.)
	status = "Pending"
	if rejected {
		status = "Rejected"
	} else if info.Submittable {
		status = "Ready"
	}

	return status, warnings
}

var printChangeOptions = []string{"SUBMITTABLE", "LABELS", "CURRENT_REVISION", "MESSAGES", "DETAILED_ACCOUNTS"}

var display = map[string]string{
	"Not mailed": "\x1b[35m", // Magenta

	"Pending warn":  "\x1b[33m",   // Yellow
	"Ready warn":    "\x1b[33m",   // Yellow
	"Rejected warn": "\x1b[1;31m", // Bright red

	"Ready": "\x1b[32m", // Green

	"Submitted": "\x1b[37m",   // Gray
	"Abandoned": "\x1b[9;37m", // Gray, strike-through
	"Draft":     "\x1b[37m",   // Gray
}

// printChange prints a summary of change's status and warnings.
//
// change must be retrieved with options printChangeOptions.
func printChange(commit string, change *GerritChanges) {
	logMsg := git("log", "-n1", "--oneline", commit)

	status, warnings, link := "Not mailed", []string(nil), ""
	if change != nil {
		results, err := change.Wait()
		if err != nil {
			log.Fatal(err)
		}
		if len(results) > 1 {
			log.Fatal("multiple changes found for commit %s", commit)
		}
		if len(results) == 1 {
			status, warnings = changeStatus(commit, results[0])
			//link = fmt.Sprintf("[%s/c/%d]", gerritUrl, results[0].Number)
			link = fmt.Sprintf(" [golang.org/cl/%d]", results[0].Number)
		}
	}

	var control, eControl string
	if len(warnings) != 0 {
		if c, ok := display[status+" warn"]; ok {
			control = c
		}
	}
	if control == "" {
		if c, ok := display[status]; ok {
			control = c
		}
	}
	if control != "" {
		eControl = "\x1b[0m"
	}

	hdr := fmt.Sprintf("%-10s %s", status, logMsg)
	hdrMax := 80 - len(link) - 2
	if utf8.RuneCountInString(hdr) > hdrMax {
		hdr = fmt.Sprintf("%*.*s…", hdrMax-1, hdrMax-1, hdr)
	}
	fmt.Printf("  %s%-*s%s%s\n", control, hdrMax, hdr, eControl, link)
	for _, w := range warnings {
		fmt.Printf("    %s\n", w)
	}
}
<|endoftext|>


<commit_before>//
// repos.go
// Copyright (C) 2016 datawolf <datawolf@datawolf-Lenovo-G460>
//
// Distributed under terms of the MIT license.
//

package index

import (
	"fmt"
)

// RepositoriesService handles communication with the repository related
// methods of the rnd-dockerhub API
type RepositoriesService struct {
	client *Client
}

// Repository represents a rmd-dockerhub repository
type Repository struct {
	Description *string `json:"description,omitempty"`
	IsOfficial  *bool   `json:"is_official,omitempty"`
	IsTrusted   *bool   `json:"is_trusted,omitempty"`
	Name        *string `json:"name,omitempty"`
	StarCount   *int    `json:"star_count,omitempty"`
}

func (r Repository) String() string {
	return Stringify(r)
}

type Image struct {
	Tag  *string `json:"tag,omitempty"`
	Size *int    `json:"size,omitempty"`
}

func (i Image) String() string {
	return Stringify(i)
}

// Property represents a rund-dockerhub repo's property
type Property struct {
	NumberDL    *int    `json:"download_num,omitempty"`
	ImageList   []Image `json:"image_list,omitempty"`
	NumberImage *int    `json:"image_num,omitempty"`
	Property    *string `json:"property,omitempty"`
	RepoName    *string `json:"repo,omitempty"`
	Size        *int    `json:"size,omitempty"`
}

func (s *RepositoriesService) Get(repo string) (*Property, *Response, error) {
	result := new(Property)
	u := fmt.Sprintf("/index/repositories/%s/properties", repo)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return result, nil, err
	}
	resp, err := s.client.Do(req, result)
	return result, resp, err
}

func (s *RepositoriesService) Set(repo string, property *Property) (string, *Response, error) {
	u := fmt.Sprintf("/index/repositories/%s/properties", repo)
	req, err := s.client.NewRequest("PUT", u, property)
	if err != nil {
		return "", nil, err
	}
	req.Header.Add("Content-Type", "application/json")

	resp, err := s.client.Do(req, nil)
	if err != nil {
		return "", nil, err
	}

	return "SUCCESS", resp, nil
}
<commit_msg>add delete tag and repo, set and get repo desc API lib<commit_after>//
// repos.go
// Copyright (C) 2016 datawolf <datawolf@datawolf-Lenovo-G460>
//
// Distributed under terms of the MIT license.
//

package index

import (
	"bytes"
	"fmt"

	qs "github.com/google/go-querystring/query"
)

// RepositoriesService handles communication with the repository related
// methods of the rnd-dockerhub API
type RepositoriesService struct {
	client *Client
}

// Repository represents a rmd-dockerhub repository
type Repository struct {
	Description *string `json:"description,omitempty"`
	IsOfficial  *bool   `json:"is_official,omitempty"`
	IsTrusted   *bool   `json:"is_trusted,omitempty"`
	Name        *string `json:"name,omitempty"`
	StarCount   *int    `json:"star_count,omitempty"`
}

func (r Repository) String() string {
	return Stringify(r)
}

type Image struct {
	Tag  *string `json:"tag,omitempty"`
	Size *int    `json:"size,omitempty"`
}

func (i Image) String() string {
	return Stringify(i)
}

// Property represents a rund-dockerhub repo's property
type Property struct {
	NumberDL    *int    `json:"download_num,omitempty"`
	ImageList   []Image `json:"image_list,omitempty"`
	NumberImage *int    `json:"image_num,omitempty"`
	Property    *string `json:"property,omitempty"`
	RepoName    *string `json:"repo,omitempty"`
	Size        *int    `json:"size,omitempty"`
}

func (s *RepositoriesService) Get(repo string) (*Property, *Response, error) {
	result := new(Property)
	u := fmt.Sprintf("/index/repositories/%s/properties", repo)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return result, nil, err
	}
	resp, err := s.client.Do(req, result)
	return result, resp, err
}

func (s *RepositoriesService) Set(repo string, property *Property) (string, *Response, error) {
	u := fmt.Sprintf("/index/repositories/%s/properties", repo)
	req, err := s.client.NewRequest("PUT", u, property)
	if err != nil {
		return "", nil, err
	}
	req.Header.Add("Content-Type", "application/json")

	resp, err := s.client.Do(req, nil)
	if err != nil {
		return "", nil, err
	}

	return "SUCCESS", resp, nil
}

type RepoDesc struct {
	Description string `json:"description,omitempty"`
}

func (s *RepositoriesService) GetRepoDesc(repo string) (*RepoDesc, *Response, error) {
	result := new(RepoDesc)
	u := fmt.Sprintf("/index/repositories/%s/description", repo)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return result, nil, err
	}
	resp, err := s.client.Do(req, result)
	return result, resp, err
}

func (s *RepositoriesService) SetRepoDesc(repo string, repoDesc *RepoDesc) (string, *Response, error) {
	u := fmt.Sprintf("/index/repositories/%s/description", repo)
	req, err := s.client.NewRequest("PUT", u, property)
	if err != nil {
		return "", nil, err
	}
	req.Header.Add("Content-Type", "application/json")

	resp, err := s.client.Do(req, nil)
	if err != nil {
		return "", nil, err
	}

	return "SUCCESS", resp, nil
}

func (s *RepositoriesService) DeleteRepo(repo string) (string, *Response, error) {
	u := fmt.Sprintf("/index/repositories/%s/entirety", repo)
	req, err := s.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return "", nil, err
	}

	buf := new(bytes.Buffer)
	resp, err := s.client.Do(req, buf)
	if err != nil {
		return "", err
	}

	return buf.String(), resp, nil
}

func (s *RepositoriesService) DeleteTag(repo string, tag string) (string, *Response, error) {
	params, err := qs.Values(nil)
	if err != nil {
		return nil, err
	}
	params.Add("tag", tag)
	u := fmt.Sprintf("/index/repositories/%s/tag?%s", repo, params.Encode())
	req, err := s.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return "", nil, err
	}

	buf := new(bytes.Buffer)
	resp, err := s.client.Do(req, buf)
	if err != nil {
		return "", err
	}

	return buf.String(), resp, nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"os"
	"path/filepath"
	"strings"
)

var (
	root            string
	dontRecurseFlag = flag.Bool("n", false, "don't recursively check paths")
)

func main() {
	flag.Parse()
	if len(flag.Args()) != 1 {
		fmt.Println("missing argument: filepath")
		return
	}

	var err error
	root, err = filepath.Abs(flag.Arg(0))
	if err != nil {
		fmt.Printf("Error finding absolute path :%s", err)
		return
	}

	errors := 0
	filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
		if err != nil {
			fmt.Printf("Error during filesystem walk: %v\n", err)
			return nil
		}
		if fi.IsDir() {
			if *dontRecurseFlag && path != root {
				return filepath.SkipDir
			}
			return nil
		}
		if !strings.HasSuffix(path, ".go") {
			return nil
		}
		errors += checkPath(path)
		return nil
	})
	if errors > 0 {
		os.Exit(1)
	}
}

func checkPath(path string) (errors int) {
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, path, nil, 0)
	if err != nil {
		return errors
	}

	chk := &checker{map[*ast.Object]*ast.Ident{}, map[*ast.Object]bool{}, 0, 0}
	for _, d := range f.Decls {
		if d, ok := d.(*ast.GenDecl); ok && d.Tok == token.VAR {
			for _, s := range d.Specs {
				for _, i := range s.(*ast.ValueSpec).Names {
					chk.escapes[i.Obj] = true
				}
			}
		}
	}
	ast.Walk(chk, f)
	for _, i := range chk.assignedNotUsed {
		if !chk.escapes[i.Obj] {
			fmt.Println(fset.Position(i.Pos()), i.Name)
			errors++
		}
	}
	return errors
}

type checker struct {
	assignedNotUsed map[*ast.Object]*ast.Ident
	escapes         map[*ast.Object]bool
	loops, funcLits int
}

// TODO: Be less conservative: Take variable scope into consideration in loops and func literals.
func (chk *checker) Visit(n ast.Node) ast.Visitor {
	switch n := n.(type) {
	case *ast.AssignStmt:
		for _, x := range append(n.Rhs, n.Lhs...) {
			ast.Walk(chk, x)
		}
		if n.Tok == token.ASSIGN {
			for _, x := range n.Lhs {
				if i, ok := unparen(x).(*ast.Ident); ok {
					// Conservatively ignore assignments inside loops.
					if chk.loops == 0 && i.Obj != nil {
						chk.assignedNotUsed[i.Obj] = i
					}
				}
			}
		}
		return nil
	case *ast.BranchStmt:
		// A goto may act as a loop.  Conservatively ignore any assignments occurring before it.
		if n.Tok == token.GOTO {
			chk.assignedNotUsed = map[*ast.Object]*ast.Ident{}
		}
	case *ast.FuncType:
		if n.Results != nil {
			for _, f := range n.Results.List {
				for _, i := range f.Names {
					chk.escapes[i.Obj] = true
				}
			}
		}
	case *ast.Ident:
		delete(chk.assignedNotUsed, n.Obj)
		// Conservatively mark any variable mentioned in a func literal as escaping.
		if chk.funcLits > 0 {
			chk.escapes[n.Obj] = true
		}
	case *ast.UnaryExpr:
		if i, ok := unparen(n.X).(*ast.Ident); n.Op == token.AND && ok {
			chk.escapes[i.Obj] = true
		}
	case *ast.CallExpr:
		// A method call might implicitly take the address of its receiver, causing it to escape.
		// We can't do any better here without knowing the variable's type.
		if s, ok := unparen(n.Fun).(*ast.SelectorExpr); ok {
			if i, ok := unparen(s.X).(*ast.Ident); ok {
				chk.escapes[i.Obj] = true
			}
		}
	case *ast.ForStmt:
		walk(chk, n.Init)
		chk.loops++
		walk(chk, n.Cond)
		walk(chk, n.Post)
		walk(chk, n.Body)
		chk.loops--
		return nil
	case *ast.RangeStmt:
		walk(chk, n.X)
		chk.loops++
		walk(chk, n.Key)
		walk(chk, n.Value)
		walk(chk, n.Body)
		chk.loops--
		return nil
	case *ast.FuncLit:
		walk(chk, n.Type)
		chk.funcLits++
		walk(chk, n.Body)
		chk.funcLits--
		return nil
	}
	return chk
}

func walk(v ast.Visitor, n ast.Node) {
	if n != nil {
		ast.Walk(v, n)
	}
}

func unparen(x ast.Expr) ast.Expr {
	if p, ok := x.(*ast.ParenExpr); ok {
		return unparen(p.X)
	}
	return x
}
<commit_msg>Make error message more explicit<commit_after>package main

import (
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"os"
	"path/filepath"
	"strings"
)

var (
	root            string
	dontRecurseFlag = flag.Bool("n", false, "don't recursively check paths")
)

func main() {
	flag.Parse()
	if len(flag.Args()) != 1 {
		fmt.Println("missing argument: filepath")
		return
	}

	var err error
	root, err = filepath.Abs(flag.Arg(0))
	if err != nil {
		fmt.Printf("Error finding absolute path :%s", err)
		return
	}

	errors := 0
	filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
		if err != nil {
			fmt.Printf("Error during filesystem walk: %v\n", err)
			return nil
		}
		if fi.IsDir() {
			if *dontRecurseFlag && path != root {
				return filepath.SkipDir
			}
			return nil
		}
		if !strings.HasSuffix(path, ".go") {
			return nil
		}
		errors += checkPath(path)
		return nil
	})
	if errors > 0 {
		os.Exit(1)
	}
}

func checkPath(path string) (errors int) {
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, path, nil, 0)
	if err != nil {
		return errors
	}

	chk := &checker{map[*ast.Object]*ast.Ident{}, map[*ast.Object]bool{}, 0, 0}
	for _, d := range f.Decls {
		if d, ok := d.(*ast.GenDecl); ok && d.Tok == token.VAR {
			for _, s := range d.Specs {
				for _, i := range s.(*ast.ValueSpec).Names {
					chk.escapes[i.Obj] = true
				}
			}
		}
	}
	ast.Walk(chk, f)
	for _, i := range chk.assignedNotUsed {
		if !chk.escapes[i.Obj] {
			fmt.Printf("%s: %s is assigned but not used\n",
				fset.Position(i.Pos()), i.Name)
			errors++
		}
	}
	return errors
}

type checker struct {
	assignedNotUsed map[*ast.Object]*ast.Ident
	escapes         map[*ast.Object]bool
	loops, funcLits int
}

// TODO: Be less conservative: Take variable scope into consideration in loops and func literals.
func (chk *checker) Visit(n ast.Node) ast.Visitor {
	switch n := n.(type) {
	case *ast.AssignStmt:
		for _, x := range append(n.Rhs, n.Lhs...) {
			ast.Walk(chk, x)
		}
		if n.Tok == token.ASSIGN {
			for _, x := range n.Lhs {
				if i, ok := unparen(x).(*ast.Ident); ok {
					// Conservatively ignore assignments inside loops.
					if chk.loops == 0 && i.Obj != nil {
						chk.assignedNotUsed[i.Obj] = i
					}
				}
			}
		}
		return nil
	case *ast.BranchStmt:
		// A goto may act as a loop.  Conservatively ignore any assignments occurring before it.
		if n.Tok == token.GOTO {
			chk.assignedNotUsed = map[*ast.Object]*ast.Ident{}
		}
	case *ast.FuncType:
		if n.Results != nil {
			for _, f := range n.Results.List {
				for _, i := range f.Names {
					chk.escapes[i.Obj] = true
				}
			}
		}
	case *ast.Ident:
		delete(chk.assignedNotUsed, n.Obj)
		// Conservatively mark any variable mentioned in a func literal as escaping.
		if chk.funcLits > 0 {
			chk.escapes[n.Obj] = true
		}
	case *ast.UnaryExpr:
		if i, ok := unparen(n.X).(*ast.Ident); n.Op == token.AND && ok {
			chk.escapes[i.Obj] = true
		}
	case *ast.CallExpr:
		// A method call might implicitly take the address of its receiver, causing it to escape.
		// We can't do any better here without knowing the variable's type.
		if s, ok := unparen(n.Fun).(*ast.SelectorExpr); ok {
			if i, ok := unparen(s.X).(*ast.Ident); ok {
				chk.escapes[i.Obj] = true
			}
		}
	case *ast.ForStmt:
		walk(chk, n.Init)
		chk.loops++
		walk(chk, n.Cond)
		walk(chk, n.Post)
		walk(chk, n.Body)
		chk.loops--
		return nil
	case *ast.RangeStmt:
		walk(chk, n.X)
		chk.loops++
		walk(chk, n.Key)
		walk(chk, n.Value)
		walk(chk, n.Body)
		chk.loops--
		return nil
	case *ast.FuncLit:
		walk(chk, n.Type)
		chk.funcLits++
		walk(chk, n.Body)
		chk.funcLits--
		return nil
	}
	return chk
}

func walk(v ast.Visitor, n ast.Node) {
	if n != nil {
		ast.Walk(v, n)
	}
}

func unparen(x ast.Expr) ast.Expr {
	if p, ok := x.(*ast.ParenExpr); ok {
		return unparen(p.X)
	}
	return x
}
<|endoftext|>


<commit_before>// Package gjsfs implements an http.FileSystem for gopherjs compiled files
package gjsfs // import "merovius.de/go-misc/gjsfs"

import (
	"bytes"
	"io"
	"net/http"
	"os"
	"path"

	"github.com/shurcooL/gopherjslib"
)

// New returns a http.FileSystem that wraps fs. All .js files opened are
// rewritten to .go names and - if existent in fs - compiled when read. All
// other files are passed through verbatim.
func New(fs http.FileSystem) http.FileSystem {
	return fileSystem{fs}
}

type file struct {
	r    io.ReadSeeker
	size int64
	f    http.File
}

func (f *file) compile() error {
	if f.r != nil {
		return nil
	}

	buf := new(bytes.Buffer)
	err := gopherjslib.Build(f.f, buf, &gopherjslib.Options{Minify: true})
	if err != nil {
		return err
	}
	f.r = bytes.NewReader(buf.Bytes())
	f.size = int64(len(buf.Bytes()))
	return nil
}

func (f *file) Read(buf []byte) (n int, err error) {
	if f.r == nil {
		if err := f.compile(); err != nil {
			return 0, err
		}
	}
	return f.r.Read(buf)
}

func (f *file) Close() error {
	if c, ok := f.r.(io.Closer); ok {
		return c.Close()
	}
	return nil
}

func (f *file) Readdir(count int) ([]os.FileInfo, error) {
	return f.f.Readdir(count)
}

func (f *file) Seek(offset int64, whence int) (int64, error) {
	if f.r == nil {
		if err := f.compile(); err != nil {
			return 0, err
		}
	}
	return f.r.Seek(offset, whence)
}

type rewriteInfo struct {
	os.FileInfo
	size func() int64
}

func (i rewriteInfo) Name() string {
	n := i.FileInfo.Name()
	return n[:len(n)-2] + "js"
}

func (i rewriteInfo) Size() int64 {
	return i.size()
}

func (f *file) Stat() (os.FileInfo, error) {
	i, err := f.f.Stat()
	if err != nil {
		return nil, err
	}
	return rewriteInfo{
		FileInfo: i,
		size: func() int64 {
			// TODO
			_ = f.compile()
			return f.size
		},
	}, nil
}

type fileSystem struct {
	fs http.FileSystem
}

func (fs fileSystem) Open(name string) (http.File, error) {
	if path.Ext(name) != ".js" {
		return fs.fs.Open(name)
	}
	name = name[:len(name)-2] + "go"

	f, err := fs.fs.Open(name)
	if err != nil {
		return nil, err
	}

	fi, err := f.Stat()
	if err != nil {
		return f, nil
	}

	if fi.IsDir() {
		return f, nil
	}

	return &file{f: f}, nil
}
<commit_msg>gjsfs: Add logging<commit_after>// Package gjsfs implements an http.FileSystem for gopherjs compiled files
package gjsfs // import "merovius.de/go-misc/gjsfs"

import (
	"bytes"
	"io"
	"log"
	"net/http"
	"os"
	"path"

	"github.com/shurcooL/gopherjslib"
)

var Log = log.New(os.Stderr, "[gjsfs]", log.LstdFlags)

// New returns a http.FileSystem that wraps fs. All .js files opened are
// rewritten to .go names and - if existent in fs - compiled when read. All
// other files are passed through verbatim.
func New(fs http.FileSystem) http.FileSystem {
	return fileSystem{fs}
}

type file struct {
	r    io.ReadSeeker
	size int64
	f    http.File
}

func (f *file) compile() error {
	if f.r != nil {
		return nil
	}

	Log.Println("Compiling…")
	defer Log.Println("Compilation finished")

	buf := new(bytes.Buffer)
	err := gopherjslib.Build(f.f, buf, &gopherjslib.Options{Minify: true})
	if err != nil {
		Log.Printf("Compilation failed: %v", err)
		return err
	}
	f.r = bytes.NewReader(buf.Bytes())
	f.size = int64(len(buf.Bytes()))
	return nil
}

func (f *file) Read(buf []byte) (n int, err error) {
	if f.r == nil {
		if err := f.compile(); err != nil {
			return 0, err
		}
	}
	return f.r.Read(buf)
}

func (f *file) Close() error {
	if c, ok := f.r.(io.Closer); ok {
		return c.Close()
	}
	return nil
}

func (f *file) Readdir(count int) ([]os.FileInfo, error) {
	return f.f.Readdir(count)
}

func (f *file) Seek(offset int64, whence int) (int64, error) {
	if f.r == nil {
		if err := f.compile(); err != nil {
			return 0, err
		}
	}
	return f.r.Seek(offset, whence)
}

type rewriteInfo struct {
	os.FileInfo
	size func() int64
}

func (i rewriteInfo) Name() string {
	n := i.FileInfo.Name()
	return n[:len(n)-2] + "js"
}

func (i rewriteInfo) Size() int64 {
	return i.size()
}

func (f *file) Stat() (os.FileInfo, error) {
	i, err := f.f.Stat()
	if err != nil {
		return nil, err
	}
	return rewriteInfo{
		FileInfo: i,
		size: func() int64 {
			// TODO
			_ = f.compile()
			return f.size
		},
	}, nil
}

type fileSystem struct {
	fs http.FileSystem
}

func (fs fileSystem) Open(name string) (http.File, error) {
	Log.Printf("Open(%q)", name)
	if path.Ext(name) != ".js" {
		Log.Println("Not a javascript file, passing through")
		return fs.fs.Open(name)
	}
	name = name[:len(name)-2] + "go"

	f, err := fs.fs.Open(name)
	if err != nil {
		Log.Println("Could not open: %v", err)
		return nil, err
	}

	fi, err := f.Stat()
	if err != nil {
		Log.Println("Could not stat: %v", err)
		return f, nil
	}

	if fi.IsDir() {
		Log.Println("Is directory, skipping")
		return f, nil
	}

	return &file{f: f}, nil
}
<|endoftext|>


<commit_before>// Copyright 2014 Mathias Fiedler
//
// 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 gl

// #include <GLES2/gl2.h>
import "C"

import (
	"image"
	"unsafe"
)

type TextureFormat C.GLenum
type TextureUnit C.GLenum
type Texture C.GLuint
type TextureTarget C.GLenum
type TextureParameter C.GLenum
type TextureParameterValue C.GLint

const (
	DEPTH_COMPONENT TextureFormat = C.GL_DEPTH_COMPONENT
	ALPHA                         = C.GL_ALPHA
	RGB                           = C.GL_RGB
	RGBA                          = C.GL_RGBA
	LUMINANCE                     = C.GL_LUMINANCE
	LUMINANCE_ALPHA               = C.GL_LUMINANCE_ALPHA

	TEXTURE_MAG_FILTER TextureParameter = C.GL_TEXTURE_MAG_FILTER
	TEXTURE_MIN_FILTER                  = C.GL_TEXTURE_MIN_FILTER
	TEXTURE_WRAP_S                      = C.GL_TEXTURE_WRAP_S
	TEXTURE_WRAP_T                      = C.GL_TEXTURE_WRAP_T

	TEXTURE_2D                  TextureTarget = C.GL_TEXTURE_2D
	TEXTURE_CUBE_MAP                          = C.GL_TEXTURE_CUBE_MAP
	TEXTURE_CUBE_MAP_POSITIVE_X               = C.GL_TEXTURE_CUBE_MAP_POSITIVE_X
	TEXTURE_CUBE_MAP_NEGATIVE_X               = C.GL_TEXTURE_CUBE_MAP_NEGATIVE_X
	TEXTURE_CUBE_MAP_POSITIVE_Y               = C.GL_TEXTURE_CUBE_MAP_POSITIVE_Y
	TEXTURE_CUBE_MAP_NEGATIVE_Y               = C.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
	TEXTURE_CUBE_MAP_POSITIVE_Z               = C.GL_TEXTURE_CUBE_MAP_POSITIVE_Z
	TEXTURE_CUBE_MAP_NEGATIVE_Z               = C.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
	MAX_CUBE_MAP_TEXTURE_SIZE                 = C.GL_MAX_CUBE_MAP_TEXTURE_SIZE

	TEXTURE0  TextureUnit = C.GL_TEXTURE0
	TEXTURE1              = C.GL_TEXTURE1
	TEXTURE2              = C.GL_TEXTURE2
	TEXTURE3              = C.GL_TEXTURE3
	TEXTURE4              = C.GL_TEXTURE4
	TEXTURE5              = C.GL_TEXTURE5
	TEXTURE6              = C.GL_TEXTURE6
	TEXTURE7              = C.GL_TEXTURE7
	TEXTURE8              = C.GL_TEXTURE8
	TEXTURE9              = C.GL_TEXTURE9
	TEXTURE10             = C.GL_TEXTURE10
	TEXTURE11             = C.GL_TEXTURE11
	TEXTURE12             = C.GL_TEXTURE12
	TEXTURE13             = C.GL_TEXTURE13
	TEXTURE14             = C.GL_TEXTURE14
	TEXTURE15             = C.GL_TEXTURE15
	TEXTURE16             = C.GL_TEXTURE16
	TEXTURE17             = C.GL_TEXTURE17
	TEXTURE18             = C.GL_TEXTURE18
	TEXTURE19             = C.GL_TEXTURE19
	TEXTURE20             = C.GL_TEXTURE20
	TEXTURE21             = C.GL_TEXTURE21
	TEXTURE22             = C.GL_TEXTURE22
	TEXTURE23             = C.GL_TEXTURE23
	TEXTURE24             = C.GL_TEXTURE24
	TEXTURE25             = C.GL_TEXTURE25
	TEXTURE26             = C.GL_TEXTURE26
	TEXTURE27             = C.GL_TEXTURE27
	TEXTURE28             = C.GL_TEXTURE28
	TEXTURE29             = C.GL_TEXTURE29
	TEXTURE30             = C.GL_TEXTURE30
	TEXTURE31             = C.GL_TEXTURE31

	NEAREST                TextureParameterValue = C.GL_NEAREST
	LINEAR                                       = C.GL_LINEAR
	NEAREST_MIPMAP_NEAREST                       = C.GL_NEAREST_MIPMAP_NEAREST
	LINEAR_MIPMAP_NEAREST                        = C.GL_LINEAR_MIPMAP_NEAREST
	NEAREST_MIPMAP_LINEAR                        = C.GL_NEAREST_MIPMAP_LINEAR
	LINEAR_MIPMAP_LINEAR                         = C.GL_LINEAR_MIPMAP_LINEAR
	REPEAT                                       = C.GL_REPEAT
	CLAMP_TO_EDGE                                = C.GL_CLAMP_TO_EDGE
	MIRRORED_REPEAT                              = C.GL_MIRRORED_REPEAT
)

func ActiveTexture(texture TextureUnit) {
	C.glActiveTexture(C.GLenum(texture))
}

func GetActiveTexture() TextureUnit {
	texture := C.GLint(0)
	C.glGetIntegerv(C.GL_ACTIVE_TEXTURE, &texture)
	return TextureUnit(texture)
}

func BindTexture(target TextureTarget, texture Texture) {
	C.glBindTexture(C.GLenum(target), C.GLuint(texture))
}

// TODO:
// func CompressedTexImage2D(target TextureTarget, level int, internalformat TextureFormat, width, height int, data []interface{}) {
// 	C.glCompressedTexImage2D(C.GLenum(target), C.GLint(level), C.GLenum(internalformat), C.GLsizei(width), C.GLsizei(height), 0, unsafe.Sizeof(data[0])*len(data), data)
// }

// func CompressedTexSubImage2D(target TextureTarget, level, xoffset, yoffset, width, height, format TextureFormat, data []interface{}) {
// 	C.glCompressedTexSubImage2D(C.GLenum(target), C.GLint(level), C.GLint(xoffset), C.GLint(yoffset), C.GLsizei(width), C.GLsizei(height), C.GLenum(format), unsafe.Sizeof(data[0])*len(data), data)
// }

func CopyTexImage2D(target TextureTarget, level int, internalformat TextureFormat, x, y, width, height int) {
	C.glCopyTexImage2D(C.GLenum(target), C.GLint(level), C.GLenum(internalformat), C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height), 0)
}

func CopyTexSubImage2D(target TextureTarget, level, xoffset, yoffset, x, y, width, height int) {
	C.glCopyTexSubImage2D(C.GLenum(target), C.GLint(level), C.GLint(xoffset), C.GLint(yoffset), C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
}

func DeleteTextures(textures []Texture) {
	C.glDeleteTextures(C.GLsizei(len(textures)), (*C.GLuint)(&textures[0]))
}

func (t Texture) Delete() {
	C.glDeleteTextures(1, (*C.GLuint)(&t))
}

func CreateTexture() Texture {
	texture := Texture(0)
	C.glGenTextures(1, (*C.GLuint)(&texture))
	return texture
}

func GenTextures(textures []Texture) {
	C.glGenTextures(C.GLsizei(len(textures)), (*C.GLuint)(&textures[0]))
}

func GenerateMipmap(target TextureTarget) {
	C.glGenerateMipmap(C.GLenum(target))
}

func GetTexParameterf(target TextureTarget, pname TextureParameter) float32 {
	param := float32(0)
	C.glGetTexParameterfv(C.GLenum(target), C.GLenum(pname), (*C.GLfloat)(&param))
	return param
}

func GetTexParameteri(target TextureTarget, pname TextureParameter) int {
	param := C.GLint(0)
	C.glGetTexParameteriv(C.GLenum(target), C.GLenum(pname), &param)
	return int(param)
}

func TexImage2D(target TextureTarget, level int, internalformat TextureFormat, width, height int, datatype DataType, pixels []uint8) {
	C.glTexImage2D(C.GLenum(target), C.GLint(level), C.GLint(internalformat), C.GLsizei(width), C.GLsizei(height), 0, C.GLenum(internalformat), C.GLenum(datatype), unsafe.Pointer(&pixels[0]))
}

func TexImageRGBA(target TextureTarget, level int, img *image.NRGBA) {
	C.glTexImage2D(C.GLenum(target), C.GLint(level), C.GL_RGBA, C.GLsizei(img.Rect.Dx()), C.GLsizei(img.Rect.Dy()), 0, C.GL_RGBA, C.GL_UNSIGNED_BYTE, unsafe.Pointer(&img.Pix[0]))
}

func TexImageAlpha(target TextureTarget, level int, img *image.Alpha) {
	C.glTexImage2D(C.GLenum(target), C.GLint(level), C.GL_ALPHA, C.GLsizei(img.Rect.Dx()), C.GLsizei(img.Rect.Dy()), 0, C.GL_ALPHA, C.GL_UNSIGNED_BYTE, unsafe.Pointer(&img.Pix[0]))
}

func TexImageLuminance(target TextureTarget, level int, img *image.Gray) {
	C.glTexImage2D(C.GLenum(target), C.GLint(level), C.GL_LUMINANCE, C.GLsizei(img.Rect.Dx()), C.GLsizei(img.Rect.Dy()), 0, C.GL_LUMINANCE, C.GL_UNSIGNED_BYTE, unsafe.Pointer(&img.Pix[0]))
}

func TexParameter(target TextureTarget, pname TextureParameter, param TextureParameterValue) {
	C.glTexParameteri(C.GLenum(target), C.GLenum(pname), C.GLint(param))
}

func TexSubImage2D(target TextureTarget, level, xoffset, yoffset, width, height int, format TextureFormat, datatype DataType, pixels []uint8) {
	C.glTexSubImage2D(C.GLenum(target), C.GLint(level), C.GLint(xoffset), C.GLint(yoffset), C.GLsizei(width), C.GLsizei(height), C.GLenum(format), C.GLenum(datatype), unsafe.Pointer(&pixels[0]))
}

func TexSubImageRGBA(target TextureTarget, level int, img *image.NRGBA) {
	C.glTexSubImage2D(C.GLenum(target), C.GLint(level), C.GLint(img.Rect.Min.X), C.GLint(img.Rect.Min.Y), C.GLsizei(img.Rect.Dx()), C.GLsizei(img.Rect.Dy()), C.GL_RGBA, C.GL_UNSIGNED_BYTE, unsafe.Pointer(&img.Pix[0]))
}

func TexSubImageAlpha(target TextureTarget, level int, img *image.Alpha) {
	C.glTexSubImage2D(C.GLenum(target), C.GLint(level), C.GLint(img.Rect.Min.X), C.GLint(img.Rect.Min.Y), C.GLsizei(img.Rect.Dx()), C.GLsizei(img.Rect.Dy()), C.GL_ALPHA, C.GL_UNSIGNED_BYTE, unsafe.Pointer(&img.Pix[0]))
}

func TexSubImageLuminance(target TextureTarget, level int, img *image.Gray) {
	C.glTexSubImage2D(C.GLenum(target), C.GLint(level), C.GLint(img.Rect.Min.X), C.GLint(img.Rect.Min.Y), C.GLsizei(img.Rect.Dx()), C.GLsizei(img.Rect.Dy()), C.GL_LUMINANCE, C.GL_UNSIGNED_BYTE, unsafe.Pointer(&img.Pix[0]))
}
<commit_msg>ensure correct unpack alignment for uploading texture data<commit_after>// Copyright 2014 Mathias Fiedler
//
// 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 gl

// #include <GLES2/gl2.h>
import "C"

import (
	"image"
	"unsafe"
)

type TextureFormat C.GLenum
type TextureUnit C.GLenum
type Texture C.GLuint
type TextureTarget C.GLenum
type TextureParameter C.GLenum
type TextureParameterValue C.GLint

const (
	DEPTH_COMPONENT TextureFormat = C.GL_DEPTH_COMPONENT
	ALPHA                         = C.GL_ALPHA
	RGB                           = C.GL_RGB
	RGBA                          = C.GL_RGBA
	LUMINANCE                     = C.GL_LUMINANCE
	LUMINANCE_ALPHA               = C.GL_LUMINANCE_ALPHA

	TEXTURE_MAG_FILTER TextureParameter = C.GL_TEXTURE_MAG_FILTER
	TEXTURE_MIN_FILTER                  = C.GL_TEXTURE_MIN_FILTER
	TEXTURE_WRAP_S                      = C.GL_TEXTURE_WRAP_S
	TEXTURE_WRAP_T                      = C.GL_TEXTURE_WRAP_T

	TEXTURE_2D                  TextureTarget = C.GL_TEXTURE_2D
	TEXTURE_CUBE_MAP                          = C.GL_TEXTURE_CUBE_MAP
	TEXTURE_CUBE_MAP_POSITIVE_X               = C.GL_TEXTURE_CUBE_MAP_POSITIVE_X
	TEXTURE_CUBE_MAP_NEGATIVE_X               = C.GL_TEXTURE_CUBE_MAP_NEGATIVE_X
	TEXTURE_CUBE_MAP_POSITIVE_Y               = C.GL_TEXTURE_CUBE_MAP_POSITIVE_Y
	TEXTURE_CUBE_MAP_NEGATIVE_Y               = C.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
	TEXTURE_CUBE_MAP_POSITIVE_Z               = C.GL_TEXTURE_CUBE_MAP_POSITIVE_Z
	TEXTURE_CUBE_MAP_NEGATIVE_Z               = C.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
	MAX_CUBE_MAP_TEXTURE_SIZE                 = C.GL_MAX_CUBE_MAP_TEXTURE_SIZE

	TEXTURE0  TextureUnit = C.GL_TEXTURE0
	TEXTURE1              = C.GL_TEXTURE1
	TEXTURE2              = C.GL_TEXTURE2
	TEXTURE3              = C.GL_TEXTURE3
	TEXTURE4              = C.GL_TEXTURE4
	TEXTURE5              = C.GL_TEXTURE5
	TEXTURE6              = C.GL_TEXTURE6
	TEXTURE7              = C.GL_TEXTURE7
	TEXTURE8              = C.GL_TEXTURE8
	TEXTURE9              = C.GL_TEXTURE9
	TEXTURE10             = C.GL_TEXTURE10
	TEXTURE11             = C.GL_TEXTURE11
	TEXTURE12             = C.GL_TEXTURE12
	TEXTURE13             = C.GL_TEXTURE13
	TEXTURE14             = C.GL_TEXTURE14
	TEXTURE15             = C.GL_TEXTURE15
	TEXTURE16             = C.GL_TEXTURE16
	TEXTURE17             = C.GL_TEXTURE17
	TEXTURE18             = C.GL_TEXTURE18
	TEXTURE19             = C.GL_TEXTURE19
	TEXTURE20             = C.GL_TEXTURE20
	TEXTURE21             = C.GL_TEXTURE21
	TEXTURE22             = C.GL_TEXTURE22
	TEXTURE23             = C.GL_TEXTURE23
	TEXTURE24             = C.GL_TEXTURE24
	TEXTURE25             = C.GL_TEXTURE25
	TEXTURE26             = C.GL_TEXTURE26
	TEXTURE27             = C.GL_TEXTURE27
	TEXTURE28             = C.GL_TEXTURE28
	TEXTURE29             = C.GL_TEXTURE29
	TEXTURE30             = C.GL_TEXTURE30
	TEXTURE31             = C.GL_TEXTURE31

	NEAREST                TextureParameterValue = C.GL_NEAREST
	LINEAR                                       = C.GL_LINEAR
	NEAREST_MIPMAP_NEAREST                       = C.GL_NEAREST_MIPMAP_NEAREST
	LINEAR_MIPMAP_NEAREST                        = C.GL_LINEAR_MIPMAP_NEAREST
	NEAREST_MIPMAP_LINEAR                        = C.GL_NEAREST_MIPMAP_LINEAR
	LINEAR_MIPMAP_LINEAR                         = C.GL_LINEAR_MIPMAP_LINEAR
	REPEAT                                       = C.GL_REPEAT
	CLAMP_TO_EDGE                                = C.GL_CLAMP_TO_EDGE
	MIRRORED_REPEAT                              = C.GL_MIRRORED_REPEAT
)

func ActiveTexture(texture TextureUnit) {
	C.glActiveTexture(C.GLenum(texture))
}

func GetActiveTexture() TextureUnit {
	texture := C.GLint(0)
	C.glGetIntegerv(C.GL_ACTIVE_TEXTURE, &texture)
	return TextureUnit(texture)
}

func BindTexture(target TextureTarget, texture Texture) {
	C.glBindTexture(C.GLenum(target), C.GLuint(texture))
}

// TODO:
// func CompressedTexImage2D(target TextureTarget, level int, internalformat TextureFormat, width, height int, data []interface{}) {
// 	C.glCompressedTexImage2D(C.GLenum(target), C.GLint(level), C.GLenum(internalformat), C.GLsizei(width), C.GLsizei(height), 0, unsafe.Sizeof(data[0])*len(data), data)
// }

// func CompressedTexSubImage2D(target TextureTarget, level, xoffset, yoffset, width, height, format TextureFormat, data []interface{}) {
// 	C.glCompressedTexSubImage2D(C.GLenum(target), C.GLint(level), C.GLint(xoffset), C.GLint(yoffset), C.GLsizei(width), C.GLsizei(height), C.GLenum(format), unsafe.Sizeof(data[0])*len(data), data)
// }

func CopyTexImage2D(target TextureTarget, level int, internalformat TextureFormat, x, y, width, height int) {
	C.glCopyTexImage2D(C.GLenum(target), C.GLint(level), C.GLenum(internalformat), C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height), 0)
}

func CopyTexSubImage2D(target TextureTarget, level, xoffset, yoffset, x, y, width, height int) {
	C.glCopyTexSubImage2D(C.GLenum(target), C.GLint(level), C.GLint(xoffset), C.GLint(yoffset), C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
}

func DeleteTextures(textures []Texture) {
	C.glDeleteTextures(C.GLsizei(len(textures)), (*C.GLuint)(&textures[0]))
}

func (t Texture) Delete() {
	C.glDeleteTextures(1, (*C.GLuint)(&t))
}

func CreateTexture() Texture {
	texture := Texture(0)
	C.glGenTextures(1, (*C.GLuint)(&texture))
	return texture
}

func GenTextures(textures []Texture) {
	C.glGenTextures(C.GLsizei(len(textures)), (*C.GLuint)(&textures[0]))
}

func GenerateMipmap(target TextureTarget) {
	C.glGenerateMipmap(C.GLenum(target))
}

func GetTexParameterf(target TextureTarget, pname TextureParameter) float32 {
	param := float32(0)
	C.glGetTexParameterfv(C.GLenum(target), C.GLenum(pname), (*C.GLfloat)(&param))
	return param
}

func GetTexParameteri(target TextureTarget, pname TextureParameter) int {
	param := C.GLint(0)
	C.glGetTexParameteriv(C.GLenum(target), C.GLenum(pname), &param)
	return int(param)
}

func TexImage2D(target TextureTarget, level int, internalformat TextureFormat, width, height int, datatype DataType, pixels []uint8) {
	C.glTexImage2D(C.GLenum(target), C.GLint(level), C.GLint(internalformat), C.GLsizei(width), C.GLsizei(height), 0, C.GLenum(internalformat), C.GLenum(datatype), unsafe.Pointer(&pixels[0]))
}

func adjustUnpackAlignment(stride int) C.GLint {

	alignment := C.GLint(0)
	C.glGetIntegerv(C.GL_UNPACK_ALIGNMENT, &alignment)

	align := C.GLint(1)

	for align < alignment && stride%(int(align)*2) == 0 {
		align *= 2
	}

	// need smaller alignment
	if align < alignment {
		C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, align)
		// return old alignment
		return alignment
	} else {
		return 0
	}
}

func restoreAlignment(alignment C.GLint) {
	if alignment > 0 {
		C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, alignment)
	}
}

func TexImageRGBA(target TextureTarget, level int, img *image.NRGBA) {
	a := adjustUnpackAlignment(img.Stride)
	C.glTexImage2D(C.GLenum(target), C.GLint(level), C.GL_RGBA, C.GLsizei(img.Rect.Dx()), C.GLsizei(img.Rect.Dy()), 0, C.GL_RGBA, C.GL_UNSIGNED_BYTE, unsafe.Pointer(&img.Pix[0]))
	restoreAlignment(a)
}

func TexImageAlpha(target TextureTarget, level int, img *image.Alpha) {
	a := adjustUnpackAlignment(img.Stride)
	C.glTexImage2D(C.GLenum(target), C.GLint(level), C.GL_ALPHA, C.GLsizei(img.Rect.Dx()), C.GLsizei(img.Rect.Dy()), 0, C.GL_ALPHA, C.GL_UNSIGNED_BYTE, unsafe.Pointer(&img.Pix[0]))
	restoreAlignment(a)
}

func TexImageLuminance(target TextureTarget, level int, img *image.Gray) {
	a := adjustUnpackAlignment(img.Stride)
	C.glTexImage2D(C.GLenum(target), C.GLint(level), C.GL_LUMINANCE, C.GLsizei(img.Rect.Dx()), C.GLsizei(img.Rect.Dy()), 0, C.GL_LUMINANCE, C.GL_UNSIGNED_BYTE, unsafe.Pointer(&img.Pix[0]))
	restoreAlignment(a)
}

func TexParameter(target TextureTarget, pname TextureParameter, param TextureParameterValue) {
	C.glTexParameteri(C.GLenum(target), C.GLenum(pname), C.GLint(param))
}

func TexSubImage2D(target TextureTarget, level, xoffset, yoffset, width, height int, format TextureFormat, datatype DataType, pixels []uint8) {
	C.glTexSubImage2D(C.GLenum(target), C.GLint(level), C.GLint(xoffset), C.GLint(yoffset), C.GLsizei(width), C.GLsizei(height), C.GLenum(format), C.GLenum(datatype), unsafe.Pointer(&pixels[0]))
}

func TexSubImageRGBA(target TextureTarget, level int, img *image.NRGBA) {
	a := adjustUnpackAlignment(img.Stride)
	C.glTexSubImage2D(C.GLenum(target), C.GLint(level), C.GLint(img.Rect.Min.X), C.GLint(img.Rect.Min.Y), C.GLsizei(img.Rect.Dx()), C.GLsizei(img.Rect.Dy()), C.GL_RGBA, C.GL_UNSIGNED_BYTE, unsafe.Pointer(&img.Pix[0]))
	restoreAlignment(a)
}

func TexSubImageAlpha(target TextureTarget, level int, img *image.Alpha) {
	a := adjustUnpackAlignment(img.Stride)
	C.glTexSubImage2D(C.GLenum(target), C.GLint(level), C.GLint(img.Rect.Min.X), C.GLint(img.Rect.Min.Y), C.GLsizei(img.Rect.Dx()), C.GLsizei(img.Rect.Dy()), C.GL_ALPHA, C.GL_UNSIGNED_BYTE, unsafe.Pointer(&img.Pix[0]))
	restoreAlignment(a)
}

func TexSubImageLuminance(target TextureTarget, level int, img *image.Gray) {
	a := adjustUnpackAlignment(img.Stride)
	C.glTexSubImage2D(C.GLenum(target), C.GLint(level), C.GLint(img.Rect.Min.X), C.GLint(img.Rect.Min.Y), C.GLsizei(img.Rect.Dx()), C.GLsizei(img.Rect.Dy()), C.GL_LUMINANCE, C.GL_UNSIGNED_BYTE, unsafe.Pointer(&img.Pix[0]))
	restoreAlignment(a)
}
<|endoftext|>


<commit_before>// Copyright 2014 Brian J. Downs
//
// 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 openweathermap

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

// CurrentWeatherData struct contains an aggregate view of the structs
// defined above for JSON to be unmarshaled into.
type CurrentWeatherData struct {
	GeoPos  Coordinates `json:"coord"`
	Sys     Sys         `json:"sys"`
	Base    string      `json:"base"`
	Weather []Weather   `json:"weather"`
	Main    Main        `json:"main"`
	Wind    Wind        `json:"wind"`
	Clouds  Clouds      `json:"clouds"`
	Dt      int         `json:"dt"`
	ID      int         `json:"id"`
	Name    string      `json:"name"`
	Cod     int         `json:"cod"`
	Units   string
}

// NewCurrent returns a new WeatherData pointer with the supplied.
func NewCurrent(unit string) (*CurrentWeatherData, error) {
	unitChoice := strings.ToLower(unit)
	if ValidDataUnit(unitChoice) {
		return &CurrentWeatherData{Units: unitChoice}, nil
	}
	return nil, errors.New("ERROR: unit of measure not available")
}

// CurrentByName will provide the current weather with the
// provided location name.
func (w *CurrentWeatherData) CurrentByName(location string) error {
	response, err := http.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "q=%s&units=%s"), location, w.Units))
	if err != nil {
		return err
	}
	defer response.Body.Close()

	result, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(result, &w)
	if err != nil {
		return err
	}
	return nil
}

// CurrentByCoordinates will provide the current weather with the
// provided location coordinates.
func (w *CurrentWeatherData) CurrentByCoordinates(location *Coordinates) error {
	response, err := http.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "lat=%f&lon=%f&units=%s"), location.Latitude, location.Longitude, w.Units))
	if err != nil {
		return err
	}
	defer response.Body.Close()

	result, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(result, &w)
	if err != nil {
		return err
	}
	return nil
}

// CurrentByID will provide the current weather with the
// provided location ID.
func (w *CurrentWeatherData) CurrentByID(id int) error {
	response, err := http.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "id=%d&units=%s"), id, w.Units))
	if err != nil {
		return err
	}
	defer response.Body.Close()

	result, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(result, &w)
	if err != nil {
		return err
	}
	return nil
}

// CurrentByArea will provide the current weather for the
// provided area.
func (w *CurrentWeatherData) CurrentByArea() {}
<commit_msg>removed unused import<commit_after>// Copyright 2014 Brian J. Downs
//
// 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 openweathermap

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
)

// CurrentWeatherData struct contains an aggregate view of the structs
// defined above for JSON to be unmarshaled into.
type CurrentWeatherData struct {
	GeoPos  Coordinates `json:"coord"`
	Sys     Sys         `json:"sys"`
	Base    string      `json:"base"`
	Weather []Weather   `json:"weather"`
	Main    Main        `json:"main"`
	Wind    Wind        `json:"wind"`
	Clouds  Clouds      `json:"clouds"`
	Dt      int         `json:"dt"`
	ID      int         `json:"id"`
	Name    string      `json:"name"`
	Cod     int         `json:"cod"`
	Units   string
}

// NewCurrent returns a new WeatherData pointer with the supplied.
func NewCurrent(unit string) (*CurrentWeatherData, error) {
	unitChoice := strings.ToLower(unit)
	if ValidDataUnit(unitChoice) {
		return &CurrentWeatherData{Units: unitChoice}, nil
	}
	return nil, errors.New("ERROR: unit of measure not available")
}

// CurrentByName will provide the current weather with the
// provided location name.
func (w *CurrentWeatherData) CurrentByName(location string) error {
	response, err := http.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "q=%s&units=%s"), location, w.Units))
	if err != nil {
		return err
	}
	defer response.Body.Close()

	result, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(result, &w)
	if err != nil {
		return err
	}
	return nil
}

// CurrentByCoordinates will provide the current weather with the
// provided location coordinates.
func (w *CurrentWeatherData) CurrentByCoordinates(location *Coordinates) error {
	response, err := http.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "lat=%f&lon=%f&units=%s"), location.Latitude, location.Longitude, w.Units))
	if err != nil {
		return err
	}
	defer response.Body.Close()

	result, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(result, &w)
	if err != nil {
		return err
	}
	return nil
}

// CurrentByID will provide the current weather with the
// provided location ID.
func (w *CurrentWeatherData) CurrentByID(id int) error {
	response, err := http.Get(fmt.Sprintf(fmt.Sprintf(baseURL, "id=%d&units=%s"), id, w.Units))
	if err != nil {
		return err
	}
	defer response.Body.Close()

	result, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(result, &w)
	if err != nil {
		return err
	}
	return nil
}

// CurrentByArea will provide the current weather for the
// provided area.
func (w *CurrentWeatherData) CurrentByArea() {}
<|endoftext|>