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

package udp

import (
	"context"
	"net"
	"os"
	"sync"
	"testing"
	"time"

	"github.com/golang/protobuf/proto"
	"github.com/google/cloudprober/logger"
	"github.com/google/cloudprober/probes/options"
	"github.com/google/cloudprober/sysvars"
	"github.com/google/cloudprober/targets"
)

type serverConnStats struct {
	sync.Mutex
	msgCt map[string]int
}

func startUDPServer(ctx context.Context, t *testing.T, drop bool, delay time.Duration) (int, *serverConnStats) {
	conn, err := net.ListenUDP("udp", nil)
	if err != nil {
		t.Fatalf("Starting UDP server failed: %v", err)
	}
	t.Logf("Recv addr: %s", conn.LocalAddr().String())
	// Simple loop to ECHO data.
	scs := &serverConnStats{
		msgCt: make(map[string]int),
	}

	go func() {
		timeout := time.Millisecond * 100
		maxLen := 1500
		b := make([]byte, maxLen)
		for {
			select {
			case <-ctx.Done():
				conn.Close()
				return
			default:
			}

			conn.SetReadDeadline(time.Now().Add(timeout))
			msgLen, addr, err := conn.ReadFromUDP(b)
			if err != nil {
				if !isClientTimeout(err) {
					t.Logf("Error receiving message: %v", err)
				}
				continue
			}
			t.Logf("Message from %s, size: %d", addr.String(), msgLen)
			scs.Lock()
			scs.msgCt[addr.String()]++
			scs.Unlock()
			if drop {
				continue
			}
			go func(b []byte, addr *net.UDPAddr) {
				if delay != 0 {
					time.Sleep(delay)
				}
				conn.SetWriteDeadline(time.Now().Add(timeout))
				if _, err := conn.WriteToUDP(b, addr); err != nil {
					t.Logf("Error sending message %s: %v", b, err)
				}
				t.Logf("Sent message to %s", addr.String())
			}(append([]byte{}, b[:msgLen]...), addr)
		}
	}()

	return conn.LocalAddr().(*net.UDPAddr).Port, scs
}

func runProbe(ctx context.Context, t *testing.T, port int, interval, timeout time.Duration, pktsToSend int, scs *serverConnStats) *Probe {
	sysvars.Init(&logger.Logger{}, nil)
	p := &Probe{}
	ipVersion := int32(6)
	if _, ok := os.LookupEnv("TRAVIS"); ok {
		ipVersion = 4
	}
	opts := &options.Options{
		Targets:  targets.StaticTargets("localhost"),
		Interval: interval,
		Timeout:  timeout,
		ProbeConf: &ProbeConf{
			Port:       proto.Int32(int32(port)),
			NumTxPorts: proto.Int32(2),
			IpVersion:  proto.Int32(ipVersion),
		},
	}
	if err := p.Init("udp", opts); err != nil {
		t.Fatalf("Error initializing UDP probe: %v", err)
	}
	p.targets = p.opts.Targets.List()
	p.initProbeRunResults()

	for _, conn := range p.connList {
		go p.recvLoop(ctx, conn)
	}

	time.Sleep(time.Second)
	go func() {
		flushTicker := time.NewTicker(p.flushIntv)
		for {
			select {
			case <-ctx.Done():
				flushTicker.Stop()
				return
			case <-flushTicker.C:
				p.processPackets()
			}
		}
	}()

	time.Sleep(interval)
	for i := 0; i < pktsToSend; i++ {
		p.runProbe()
		time.Sleep(interval)
	}

	// Sleep for 2*statsExportIntv, to make sure that stats are updated and
	// exported.
	time.Sleep(2 * interval)
	time.Sleep(2 * timeout)

	scs.Lock()
	defer scs.Unlock()
	if len(scs.msgCt) != len(p.connList) {
		t.Errorf("Got packets over %d connections, required %d", len(scs.msgCt), p.connList)
	}
	t.Logf("Echo server stats: %v", scs.msgCt)

	return p
}

func TestSuccessMultipleCases(t *testing.T) {
	cases := []struct {
		name     string
		interval time.Duration
		timeout  time.Duration
		delay    time.Duration
		pktCount int64
	}{
		// 10 packets, at the interval of 100ms, with 50ms timeout and 40ms delay on server.
		{"success_normal", time.Second / 10, time.Second / 20, time.Second / 25, 10},
		// 20 packets, at the interval of 100ms, with 1000ms timeout and 50ms delay on server.
		{"success_timeout_larger_than_interval_1", time.Second / 10, time.Second, time.Second / 20, 20},
		// 20 packets, at the interval of 100ms, with 1000ms timeout and 200ms delay on server.
		{"success_timeout_larger_than_interval_2", time.Second / 10, time.Second, time.Second / 5, 20},
	}

	for _, c := range cases {
		ctx, cancelCtx := context.WithCancel(context.Background())
		port, scs := startUDPServer(ctx, t, false, c.delay)
		t.Logf("Case(%s): started server on port %d with delay %v", c.name, port, c.delay)
		p := runProbe(ctx, t, port, c.interval, c.timeout, int(c.pktCount), scs)
		cancelCtx()

		res := p.res["localhost"]
		if res.total != c.pktCount {
			t.Errorf("Case(%s): got total=%d, want %d", c.name, res.total, c.pktCount)
		}
		if res.success != c.pktCount {
			t.Errorf("Case(%s): got success=%d want %d", c.name, res.success, c.pktCount)
		}
		if res.delayed != 0 {
			t.Errorf("Case(%s): got delayed=%d, want 0", c.name, res.delayed)
		}
	}
}

func TestLossAndDelayed(t *testing.T) {
	var pktCount int64 = 10
	cases := []struct {
		name     string
		drop     bool
		interval time.Duration
		timeout  time.Duration
		delay    time.Duration
		delayCt  int64
	}{
		// 10 packets, at the interval of 100ms, with 50ms timeout and drop on server.
		{"loss", true, time.Second / 10, time.Second / 20, 0, 0},
		// 10 packets, at the interval of 100ms, with 50ms timeout and 67ms delay on server.
		{"delayed_1", false, time.Second / 10, time.Second / 20, time.Second / 15, pktCount},
		// 10 packets, at the interval of 100ms, with 250ms timeout and 333ms delay on server.
		{"delayed_2", false, time.Second / 10, time.Second / 4, time.Second / 3, pktCount},
	}

	for _, c := range cases {
		ctx, cancelCtx := context.WithCancel(context.Background())
		port, scs := startUDPServer(ctx, t, c.drop, c.delay)
		t.Logf("Case(%s): started server on port %d with loss %v delay %v", c.name, port, c.drop, c.delay)
		p := runProbe(ctx, t, port, c.interval, c.timeout, int(pktCount), scs)
		cancelCtx()

		res := p.res["localhost"]
		if res.total != pktCount {
			t.Errorf("Case(%s): got total=%d, want %d", c.name, res.total, pktCount)
		}
		if res.success != 0 {
			t.Errorf("Case(%s): got success=%d want 0", c.name, res.success)
		}
		if res.delayed != c.delayCt {
			t.Errorf("Case(%s): got delayed=%d, want %d", c.name, res.delayed, c.delayCt)
		}
	}
}
<commit_msg>Fix UDP tests for travis MacOS environment.<commit_after>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package udp

import (
	"context"
	"net"
	"os"
	"sync"
	"testing"
	"time"

	"github.com/golang/protobuf/proto"
	"github.com/google/cloudprober/logger"
	"github.com/google/cloudprober/probes/options"
	"github.com/google/cloudprober/sysvars"
	"github.com/google/cloudprober/targets"
)

type serverConnStats struct {
	sync.Mutex
	msgCt map[string]int
}

func startUDPServer(ctx context.Context, t *testing.T, drop bool, delay time.Duration) (int, *serverConnStats) {
	conn, err := net.ListenUDP("udp", nil)
	if err != nil {
		t.Fatalf("Starting UDP server failed: %v", err)
	}
	t.Logf("Recv addr: %s", conn.LocalAddr().String())
	// Simple loop to ECHO data.
	scs := &serverConnStats{
		msgCt: make(map[string]int),
	}

	go func() {
		timeout := time.Millisecond * 100
		maxLen := 1500
		b := make([]byte, maxLen)
		for {
			select {
			case <-ctx.Done():
				conn.Close()
				return
			default:
			}

			conn.SetReadDeadline(time.Now().Add(timeout))
			msgLen, addr, err := conn.ReadFromUDP(b)
			if err != nil {
				if !isClientTimeout(err) {
					t.Logf("Error receiving message: %v", err)
				}
				continue
			}
			t.Logf("Message from %s, size: %d", addr.String(), msgLen)
			scs.Lock()
			scs.msgCt[addr.String()]++
			scs.Unlock()
			if drop {
				continue
			}
			go func(b []byte, addr *net.UDPAddr) {
				if delay != 0 {
					time.Sleep(delay)
				}
				conn.SetWriteDeadline(time.Now().Add(timeout))
				if _, err := conn.WriteToUDP(b, addr); err != nil {
					t.Logf("Error sending message %s: %v", b, err)
				}
				t.Logf("Sent message to %s", addr.String())
			}(append([]byte{}, b[:msgLen]...), addr)
		}
	}()

	return conn.LocalAddr().(*net.UDPAddr).Port, scs
}

func runProbe(ctx context.Context, t *testing.T, port int, interval, timeout time.Duration, pktsToSend int, scs *serverConnStats) *Probe {
	sysvars.Init(&logger.Logger{}, nil)
	p := &Probe{}
	ipVersion := int32(6)
	if _, ok := os.LookupEnv("TRAVIS"); ok {
		ipVersion = 4
	}
	opts := &options.Options{
		Targets:  targets.StaticTargets("localhost"),
		Interval: interval,
		Timeout:  timeout,
		ProbeConf: &ProbeConf{
			Port:       proto.Int32(int32(port)),
			NumTxPorts: proto.Int32(2),
			IpVersion:  proto.Int32(ipVersion),
		},
	}
	if err := p.Init("udp", opts); err != nil {
		t.Fatalf("Error initializing UDP probe: %v", err)
	}
	p.targets = p.opts.Targets.List()
	p.initProbeRunResults()

	for _, conn := range p.connList {
		go p.recvLoop(ctx, conn)
	}

	time.Sleep(time.Second)
	go func() {
		flushTicker := time.NewTicker(p.flushIntv)
		for {
			select {
			case <-ctx.Done():
				flushTicker.Stop()
				return
			case <-flushTicker.C:
				p.processPackets()
			}
		}
	}()

	time.Sleep(interval)
	for i := 0; i < pktsToSend; i++ {
		p.runProbe()
		time.Sleep(interval)
	}

	// Sleep for 2*statsExportIntv, to make sure that stats are updated and
	// exported.
	time.Sleep(2 * interval)
	time.Sleep(2 * timeout)

	scs.Lock()
	defer scs.Unlock()
	if len(scs.msgCt) != len(p.connList) {
		t.Errorf("Got packets over %d connections, required %d", len(scs.msgCt), p.connList)
	}
	t.Logf("Echo server stats: %v", scs.msgCt)

	return p
}

func TestSuccessMultipleCases(t *testing.T) {
	cases := []struct {
		name     string
		interval time.Duration
		timeout  time.Duration
		delay    time.Duration
		pktCount int64
	}{
		// 10 packets, at the interval of 200ms, with 100ms timeout and 10ms delay on server.
		{"success_normal", 200, 100, 10, 10},
		// 20 packets, at the interval of 100ms, with 1000ms timeout and 50ms delay on server.
		{"success_timeout_larger_than_interval_1", 100, 1000, 50, 20},
		// 20 packets, at the interval of 100ms, with 1000ms timeout and 200ms delay on server.
		{"success_timeout_larger_than_interval_2", 100, 1000, 200, 20},
	}

	for _, c := range cases {
		ctx, cancelCtx := context.WithCancel(context.Background())
		port, scs := startUDPServer(ctx, t, false, c.delay*time.Millisecond)
		t.Logf("Case(%s): started server on port %d with delay %v", c.name, port, c.delay)
		p := runProbe(ctx, t, port, c.interval*time.Millisecond, c.timeout*time.Millisecond, int(c.pktCount), scs)
		cancelCtx()

		res := p.res["localhost"]
		if res.total != c.pktCount {
			t.Errorf("Case(%s): got total=%d, want %d", c.name, res.total, c.pktCount)
		}
		if res.success != c.pktCount {
			t.Errorf("Case(%s): got success=%d want %d", c.name, res.success, c.pktCount)
		}
		if res.delayed != 0 {
			t.Errorf("Case(%s): got delayed=%d, want 0", c.name, res.delayed)
		}
	}
}

func TestLossAndDelayed(t *testing.T) {
	var pktCount int64 = 10
	cases := []struct {
		name     string
		drop     bool
		interval time.Duration
		timeout  time.Duration
		delay    time.Duration
		delayCt  int64
	}{
		// 10 packets, at the interval of 100ms, with 50ms timeout and drop on server.
		{"loss", true, 100, 50, 0, 0},
		// 10 packets, at the interval of 100ms, with 50ms timeout and 67ms delay on server.
		{"delayed_1", false, 100, 50, 67, pktCount},
		// 10 packets, at the interval of 100ms, with 250ms timeout and 300ms delay on server.
		{"delayed_2", false, 100, 250, 300, pktCount},
	}

	for _, c := range cases {
		ctx, cancelCtx := context.WithCancel(context.Background())
		port, scs := startUDPServer(ctx, t, c.drop, c.delay*time.Millisecond)
		t.Logf("Case(%s): started server on port %d with loss %v delay %v", c.name, port, c.drop, c.delay)
		p := runProbe(ctx, t, port, c.interval*time.Millisecond, c.timeout*time.Millisecond, int(pktCount), scs)
		cancelCtx()

		res := p.res["localhost"]
		if res.total != pktCount {
			t.Errorf("Case(%s): got total=%d, want %d", c.name, res.total, pktCount)
		}
		if res.success != 0 {
			t.Errorf("Case(%s): got success=%d want 0", c.name, res.success)
		}
		if res.delayed != c.delayCt {
			t.Errorf("Case(%s): got delayed=%d, want %d", c.name, res.delayed, c.delayCt)
		}
	}
}
<|endoftext|>


<commit_before>package gaerecovery

import (
	"net/http"
	"runtime/debug"

	"google.golang.org/appengine"
	"google.golang.org/appengine/log"
)

type recovery struct {
	PrintStack bool
}

func Recovery() *recovery {
	return &recovery{
		PrintStack: true,
	}
}

func (rec *recovery) ServeHTTP(writer http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	defer func() {
		if err := recover(); err != nil {
			writer.WriteHeader(http.StatusInternalServerError)

			ctx := appengine.NewContext(req)
			log.Criticalf(ctx, "%s", err.Error())
			if rec.PrintStack {
				log.Debugf(ctx, "%s", debug.Stack())
			}
		}
	}()

	next(writer, req)
}
<commit_msg>fixed err logging<commit_after>package gaerecovery

import (
	"net/http"
	"runtime/debug"

	"google.golang.org/appengine"
	"google.golang.org/appengine/log"
)

type recovery struct {
	PrintStack bool
}

func Recovery() *recovery {
	return &recovery{
		PrintStack: true,
	}
}

func (rec *recovery) ServeHTTP(writer http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	defer func() {
		if err := recover(); err != nil {
			writer.WriteHeader(http.StatusInternalServerError)

			ctx := appengine.NewContext(req)
			log.Criticalf(ctx, "%s", err)
			if rec.PrintStack {
				log.Debugf(ctx, "%s", debug.Stack())
			}
		}
	}()

	next(writer, req)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"io"
	"strings"

	"github.com/Nitro/sidecar-executor/container"
	"github.com/Nitro/sidecar-executor/loghooks"
	log "github.com/sirupsen/logrus"
)

func (exec *sidecarExecutor) configureLogRelay(containerId string,
	labels map[string]string, output io.Writer) *log.Entry {

	syslogger := log.New()
	// We relay UDP syslog because we don't plan to ship it off the box
	// and because it's simplest since there is no backpressure issue to
	// deal with.
	hook, err := loghooks.NewUDPHook(exec.config.SyslogAddr)
	if err != nil {
		log.Fatalf("Error adding hook: %s", err)
	}

	syslogger.Hooks.Add(hook)
	syslogger.SetFormatter(&log.JSONFormatter{
		FieldMap: log.FieldMap{
			log.FieldKeyTime:  "Timestamp",
			log.FieldKeyLevel: "Level",
			log.FieldKeyMsg:   "Payload",
			log.FieldKeyFunc:  "Func",
		},
	})
	syslogger.SetOutput(output)

	// Loop through the fields we're supposed to pass, and add them from the
	// Docker labels on this container
	fields := make(log.Fields, len(exec.config.SendDockerLabels) + 1)
	for _, field := range exec.config.SendDockerLabels {
		if val, ok := labels[field]; ok {
			fields[field] = val
		}
	}
	fields["Hostname"] = exec.config.LogHostname

	return syslogger.WithFields(fields)
}

// relayLogs will watch a container and send the logs to Syslog
func (exec *sidecarExecutor) relayLogs(quitChan chan struct{},
	containerId string, labels map[string]string, output io.Writer) {

	logger := exec.configureLogRelay(containerId, labels, output)

	logger.Infof("sidecar-executor starting log pump for '%s'", containerId[:12])
	log.Info("Started syslog log pump") // Send to local log output

	outrd, outwr := io.Pipe()
	errrd, errwr := io.Pipe()

	// Tell Docker client to start pumping logs into our pipes
	container.FollowLogs(exec.client, containerId, 0, outwr, errwr)

	go exec.handleOneStream(quitChan, "stdout", logger, outrd)
	go exec.handleOneStream(quitChan, "stderr", logger, errrd)

	<-quitChan
}

// handleOneStream will process one data stream into logs
func (exec *sidecarExecutor) handleOneStream(quitChan chan struct{}, name string,
	logger *log.Entry, in io.Reader) {

	scanner := bufio.NewScanner(in) // Defaults to splitting as lines

	for scanner.Scan() {
		text := scanner.Text()
		log.Debugf("docker: %s", text)

		switch name {
		case "stdout":
			logger.Info(text) // Send to syslog "info"
		case "stderr":
			// Pretty basic attempt to scrape only errors from the logs
			if strings.Contains(strings.ToLower(text), "error") {
				logger.Error(text) // Send to syslog "error"
			} else {
				logger.Info(text) // Send to syslog "info"
			}
		default:
			log.Errorf("handleOneStream(): Unknown stream type '%s'. Exiting log pump.", name)
			return
		}

		select {
		case <-quitChan:
			return
		default:
			// nothing
		}
	}
	if err := scanner.Err(); err != nil {
		log.Errorf("handleOneStream() error reading Docker log input: '%s'. Exiting log pump '%s'.", err, name)
	}

	log.Warnf("Log pump exited for '%s'", name)
}
<commit_msg>Clarify with comment<commit_after>package main

import (
	"bufio"
	"io"
	"strings"

	"github.com/Nitro/sidecar-executor/container"
	"github.com/Nitro/sidecar-executor/loghooks"
	log "github.com/sirupsen/logrus"
)

func (exec *sidecarExecutor) configureLogRelay(containerId string,
	labels map[string]string, output io.Writer) *log.Entry {

	syslogger := log.New()
	// We relay UDP syslog because we don't plan to ship it off the box
	// and because it's simplest since there is no backpressure issue to
	// deal with.
	hook, err := loghooks.NewUDPHook(exec.config.SyslogAddr)
	if err != nil {
		log.Fatalf("Error adding hook: %s", err)
	}

	syslogger.Hooks.Add(hook)
	syslogger.SetFormatter(&log.JSONFormatter{
		FieldMap: log.FieldMap{
			log.FieldKeyTime:  "Timestamp",
			log.FieldKeyLevel: "Level",
			log.FieldKeyMsg:   "Payload",
			log.FieldKeyFunc:  "Func",
		},
	})
	syslogger.SetOutput(output)

	// Add one to the labels length to account for hostname
	fields := make(log.Fields, len(exec.config.SendDockerLabels) + 1)

	// Loop through the fields we're supposed to pass, and add them from the
	// Docker labels on this container
	for _, field := range exec.config.SendDockerLabels {
		if val, ok := labels[field]; ok {
			fields[field] = val
		}
	}
	fields["Hostname"] = exec.config.LogHostname

	return syslogger.WithFields(fields)
}

// relayLogs will watch a container and send the logs to Syslog
func (exec *sidecarExecutor) relayLogs(quitChan chan struct{},
	containerId string, labels map[string]string, output io.Writer) {

	logger := exec.configureLogRelay(containerId, labels, output)

	logger.Infof("sidecar-executor starting log pump for '%s'", containerId[:12])
	log.Info("Started syslog log pump") // Send to local log output

	outrd, outwr := io.Pipe()
	errrd, errwr := io.Pipe()

	// Tell Docker client to start pumping logs into our pipes
	container.FollowLogs(exec.client, containerId, 0, outwr, errwr)

	go exec.handleOneStream(quitChan, "stdout", logger, outrd)
	go exec.handleOneStream(quitChan, "stderr", logger, errrd)

	<-quitChan
}

// handleOneStream will process one data stream into logs
func (exec *sidecarExecutor) handleOneStream(quitChan chan struct{}, name string,
	logger *log.Entry, in io.Reader) {

	scanner := bufio.NewScanner(in) // Defaults to splitting as lines

	for scanner.Scan() {
		text := scanner.Text()
		log.Debugf("docker: %s", text)

		switch name {
		case "stdout":
			logger.Info(text) // Send to syslog "info"
		case "stderr":
			// Pretty basic attempt to scrape only errors from the logs
			if strings.Contains(strings.ToLower(text), "error") {
				logger.Error(text) // Send to syslog "error"
			} else {
				logger.Info(text) // Send to syslog "info"
			}
		default:
			log.Errorf("handleOneStream(): Unknown stream type '%s'. Exiting log pump.", name)
			return
		}

		select {
		case <-quitChan:
			return
		default:
			// nothing
		}
	}
	if err := scanner.Err(); err != nil {
		log.Errorf("handleOneStream() error reading Docker log input: '%s'. Exiting log pump '%s'.", err, name)
	}

	log.Warnf("Log pump exited for '%s'", name)
}
<|endoftext|>


<commit_before>package keyctl

import "testing"

func mustInfo(r Reference) Info {
	info, err := r.Info()
	if err != nil {
		if msg := err.Error(); msg == "key has expired" {
			return Info{Name: msg}
		}
	}
	return info
}

func helperTestKeyRefs(ring Keyring, t *testing.T) []Reference {
	var err error

	if ring == nil {
		if ring, err = UserSessionKeyring(); err != nil {
			t.Fatal(err)
		}
	}

	refs, err := ListKeyring(ring)
	if err != nil {
		t.Fatal(err)
	}

	for _, r := range refs {
		t.Logf("%d: %+v [%s]\n", r.Id, mustInfo(r), mustInfo(r).Permissions())
	}

	return refs
}

func helperRecurseKeyringRefs(kr Keyring, t *testing.T) {
	for _, r := range helperTestKeyRefs(kr, t) {
		if !r.Valid() {
			continue
		}
		key, err := r.Get()
		if err != nil {
			t.Fatal(err)
		}
		switch k := key.(type) {
		case *namedKeyring:
			t.Logf("keyring %v: %q, parent %v", k.id, k.Name(), k.parent)
			helperRecurseKeyringRefs(k, t)
		case *keyring:
			t.Logf("keyring %v", k.id)
			helperRecurseKeyringRefs(k, t)
		case *Key:
			t.Logf("key %v: %q, keyring %v", k.id, k.Name, k.ring)
			data, err := k.Get()
			if err != nil {
				t.Fatal(err)
			}
			t.Logf("   %v: %v", k.id, data)
		default:
			panic("unsupported type")
		}
	}
}

func TestUserSessionKeyringRefs(t *testing.T) {
	helperRecurseKeyringRefs(nil, t)
}
<commit_msg>fix for travis-ci keyring perrmissions issue<commit_after>package keyctl

import (
	"syscall"
	"testing"
)

func mustInfo(r Reference) Info {
	info, err := r.Info()
	if err != nil {
		if msg := err.Error(); msg == "key has expired" {
			return Info{Name: msg}
		}
	}
	return info
}

func helperTestKeyRefs(ring Keyring, t *testing.T) []Reference {
	var err error

	if ring == nil {
		if ring, err = SessionKeyring(); err != nil {
			t.Fatal(err)
		}
	}

	refs, err := ListKeyring(ring)
	if err != nil {
		t.Fatal(err)
	}

	for _, r := range refs {
		t.Logf("%d: %+v [%s]\n", r.Id, mustInfo(r), mustInfo(r).Permissions())
	}

	return refs
}

func filterErrno(e error, ignore ...syscall.Errno) error {
	if en, ok := e.(syscall.Errno); ok {
		for _, enok := range ignore {
			if enok == en {
				return nil
			}
		}
	}

	return e
}

func helperRecurseKeyringRefs(kr Keyring, t *testing.T) {
	for _, r := range helperTestKeyRefs(kr, t) {
		if !r.Valid() {
			continue
		}
		key, err := r.Get()
		if filterErrno(err, syscall.EPERM, syscall.EACCES) != nil {
			t.Fatal(err)
		}
		if err != nil {
			return
		}
		switch k := key.(type) {
		case *namedKeyring:
			t.Logf("keyring %v: %q, parent %v", k.id, k.Name(), k.parent)
			helperRecurseKeyringRefs(k, t)
		case *keyring:
			t.Logf("keyring %v", k.id)
			helperRecurseKeyringRefs(k, t)
		case *Key:
			t.Logf("key %v: %q, keyring %v", k.id, k.Name, k.ring)
			data, err := k.Get()
			if filterErrno(err, syscall.EPERM, syscall.EACCES) != nil {
				t.Fatalf("%v %T(%d)", err, err, err)
			}
			t.Logf("   %v: %v", k.id, data)
		default:
			panic("unsupported type")
		}
	}
}

func TestSessionKeyringRefs(t *testing.T) {
	helperRecurseKeyringRefs(nil, t)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"
)

type register struct {
	clientCmd
	exitStatus   int
	exitSignalCh chan os.Signal
	host *string
}

func (cmd *register) Name() string {
	return "register"
}

func (cmd *register) DefineFlags(fs *flag.FlagSet) {
	cmd.SetRegisterFlags(fs)
}

func (cmd *register) SetRegisterFlags(fs *flag.FlagSet) {
	cmd.host = fs.String("h", "", "Specify a particular host for the service")
}

func (cmd *register) RegisterWithExitHook(name, port string, verbose bool) {
	cmd.exitSignalCh = make(chan os.Signal, 1)
	signal.Notify(cmd.exitSignalCh, os.Interrupt, syscall.SIGTERM)
	go func() {
		<-cmd.exitSignalCh
		if verbose {
			log.Println("Unregistering service...")
		}
		if *cmd.host == "" {
			cmd.client.Unregister(name, port)
		} else {
			cmd.client.UnregisterWithHost(name, *cmd.host, port)
		}
		os.Exit(cmd.exitStatus)
	}()

	if *cmd.host == "" {
		cmd.client.Register(name, port, nil)
	} else {
		cmd.client.RegisterWithHost(name, *cmd.host, port, nil)
	}
}

func (cmd *register) Run(fs *flag.FlagSet) {
	cmd.InitClient(false)
	cmd.exitStatus = 0

	mapping := strings.SplitN(fs.Arg(0), ":", 2)
	name := mapping[0]
	port := mapping[1]

	cmd.RegisterWithExitHook(name, port, true)

	log.Printf("Registered service '%s' on port %s.", name, port)
	for {
		time.Sleep(time.Second)
	}
}
<commit_msg>sdutil: Fix discoverd usage<commit_after>package main

import (
	"flag"
	"log"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"
)

type register struct {
	clientCmd
	exitStatus   int
	exitSignalCh chan os.Signal
	host         *string
}

func (cmd *register) Name() string {
	return "register"
}

func (cmd *register) DefineFlags(fs *flag.FlagSet) {
	cmd.SetRegisterFlags(fs)
}

func (cmd *register) SetRegisterFlags(fs *flag.FlagSet) {
	cmd.host = fs.String("h", "", "Specify a particular host for the service")
}

func (cmd *register) RegisterWithExitHook(name, port string, verbose bool) {
	cmd.exitSignalCh = make(chan os.Signal, 1)
	signal.Notify(cmd.exitSignalCh, os.Interrupt, syscall.SIGTERM)
	go func() {
		<-cmd.exitSignalCh
		if verbose {
			log.Println("Unregistering service...")
		}
		cmd.client.Unregister(name, *cmd.host+":"+port)
		os.Exit(cmd.exitStatus)
	}()
	cmd.client.Register(name, *cmd.host+":"+port)
}

func (cmd *register) Run(fs *flag.FlagSet) {
	cmd.InitClient(false)
	cmd.exitStatus = 0

	mapping := strings.SplitN(fs.Arg(0), ":", 2)
	name := mapping[0]
	port := mapping[1]

	cmd.RegisterWithExitHook(name, port, true)

	log.Printf("Registered service '%s' on port %s.", name, port)
	for {
		time.Sleep(time.Second)
	}
}
<|endoftext|>


<commit_before>/*

   Copyright 2016 Wenhui Shen <www.webx.top>

   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 echo

var (
	_ ICore = &Echo{}
	_ ICore = &Group{}
)

type RouteRegister interface {
	Group(prefix string, middleware ...interface{}) *Group
	Any(path string, h interface{}, middleware ...interface{}) IRouter
	Route(methods string, path string, h interface{}, middleware ...interface{}) IRouter
	Match(methods []string, path string, h interface{}, middleware ...interface{}) IRouter
	Connect(path string, h interface{}, m ...interface{}) IRouter
	Delete(path string, h interface{}, m ...interface{}) IRouter
	Get(path string, h interface{}, m ...interface{}) IRouter
	Head(path string, h interface{}, m ...interface{}) IRouter
	Options(path string, h interface{}, m ...interface{}) IRouter
	Patch(path string, h interface{}, m ...interface{}) IRouter
	Post(path string, h interface{}, m ...interface{}) IRouter
	Put(path string, h interface{}, m ...interface{}) IRouter
	Trace(path string, h interface{}, m ...interface{}) IRouter
	Static(prefix, root string)
	File(path, file string)
}

type ContextRegister interface {
	SetContext(Context)
}

type RendererRegister interface {
	SetRenderer(Renderer)
}

type MiddlewareRegister interface {
	Use(middleware ...interface{})
	Pre(middleware ...interface{})
}

type URLBuilder interface {
	URL(interface{}, ...interface{}) string
}

type ICore interface {
	RouteRegister
	MiddlewareRegister
	URLBuilder
	RendererRegister
	Prefixer
}

type IRouter interface {
	SetName(string) IRouter
}

type Closer interface {
	Close() error
}

type Prefixer interface {
	Prefix() string
}
<commit_msg>improved<commit_after>/*

   Copyright 2016 Wenhui Shen <www.webx.top>

   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 echo

var (
	_ ICore = &Echo{}
	_ ICore = &Group{}
)

type RouteRegister interface {
	MiddlewareRegister
	Group(prefix string, middleware ...interface{}) *Group
	Any(path string, h interface{}, middleware ...interface{}) IRouter
	Route(methods string, path string, h interface{}, middleware ...interface{}) IRouter
	Match(methods []string, path string, h interface{}, middleware ...interface{}) IRouter
	Connect(path string, h interface{}, m ...interface{}) IRouter
	Delete(path string, h interface{}, m ...interface{}) IRouter
	Get(path string, h interface{}, m ...interface{}) IRouter
	Head(path string, h interface{}, m ...interface{}) IRouter
	Options(path string, h interface{}, m ...interface{}) IRouter
	Patch(path string, h interface{}, m ...interface{}) IRouter
	Post(path string, h interface{}, m ...interface{}) IRouter
	Put(path string, h interface{}, m ...interface{}) IRouter
	Trace(path string, h interface{}, m ...interface{}) IRouter
	Static(prefix, root string)
	File(path, file string)
}

type ContextRegister interface {
	SetContext(Context)
}

type RendererRegister interface {
	SetRenderer(Renderer)
}

type MiddlewareRegister interface {
	Use(middleware ...interface{})
	Pre(middleware ...interface{})
}

type URLBuilder interface {
	URL(interface{}, ...interface{}) string
}

type ICore interface {
	RouteRegister
	URLBuilder
	RendererRegister
	Prefixer
}

type IRouter interface {
	SetName(string) IRouter
}

type Closer interface {
	Close() error
}

type Prefixer interface {
	Prefix() string
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"io/ioutil"
	"strings"
	"time"
)

var serverId string

func init() {
	flag.StringVar(&serverId, "nodeID", "",
		"Node ID (defaults to what's stored in guid file or arbitrary)")
}

func validateServerId(s string) error {
	invalid := errors.New("Invalid server id: " + s)
	switch {
	case len(s) == 0:
		return invalid
	case s[0] == '/' || s[0] == '@':
		return invalid
	}
	return nil
}

func initServerId() error {
	var err error
	var bytes []byte
	if serverId == "" {
		bytes, err = ioutil.ReadFile(*guidFile)
	}
	if len(bytes) > 0 && err == nil {
		serverId = strings.TrimSpace(string(bytes))
	} else {
		serverId = time.Now().UTC().Format(time.RFC3339Nano)
		err = ioutil.WriteFile(*guidFile,
			[]byte(serverId), 0666)
	}
	return err
}
<commit_msg>Don't generate a nodeID if the user supplied one.<commit_after>package main

import (
	"errors"
	"flag"
	"io/ioutil"
	"strings"
	"time"
)

var serverId string

func init() {
	flag.StringVar(&serverId, "nodeID", "",
		"Node ID (defaults to what's stored in guid file or arbitrary)")
}

func validateServerId(s string) error {
	invalid := errors.New("Invalid server id: " + s)
	switch {
	case len(s) == 0:
		return invalid
	case s[0] == '/' || s[0] == '@':
		return invalid
	}
	return nil
}

func initServerId() error {
	var err error
	var bytes []byte
	if serverId == "" {
		bytes, err = ioutil.ReadFile(*guidFile)
	}
	if len(bytes) > 0 && err == nil {
		serverId = strings.TrimSpace(string(bytes))
	} else {
		if serverId == "" {
			serverId = time.Now().UTC().Format(time.RFC3339Nano)
		}
		err = ioutil.WriteFile(*guidFile,
			[]byte(serverId), 0666)
	}
	return err
}
<|endoftext|>


<commit_before>package main

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

type StashContainer struct {
	Repository StashRepository  `json:"repository"`
	RefChanges []StashRefChange `json:"refChanges"`

	PushEvent
}

type StashRepository struct {
	Slug    string       `json:"slug"`
	Project StashProject `json:"project"`
}

type StashProject struct {
	Key string `json:"key"`
}

type StashRefChange struct {
	RefID string `json:"refId"`
}

func (stash StashContainer) ProjectKey() string {
	return fmt.Sprintf("%s/%s", stash.Repository.Project, stash.Repository.Slug)
}

func (stash StashContainer) Branches() []string {
	branches := make([]string, 0)
	for _, v := range stash.RefChanges {
		branches = append(branches, strings.ToLower(strings.Replace(v.RefID, "refs/heads/", "", -1)))
	}
	return branches
}

type StashHandler struct {
	K8sBase K8sBase
	Handler
}

func (han StashHandler) handle(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(200)

	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		Log.Println(err)
		return
	}
	Log.Printf("post-receive hook received: %s\n", data)

	var stashContainer StashContainer
	if err := json.Unmarshal(data, &stashContainer); err != nil {
		Log.Println(err)
		return
	}
	go han.K8sBase.launchBuild(stashContainer)
}
<commit_msg>rename stash container to stashevent<commit_after>package main

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

// See https://confluence.atlassian.com/stash/post-service-webhook-for-stash-393284006.html for payload information.
type StashEvent struct {
	Repository StashRepository  `json:"repository"`
	RefChanges []StashRefChange `json:"refChanges"`

	PushEvent
}

type StashRepository struct {
	Slug    string       `json:"slug"`
	Project StashProject `json:"project"`
}

type StashProject struct {
	Key string `json:"key"`
}

type StashRefChange struct {
	RefID string `json:"refId"`
}

func (stash StashEvent) ProjectKey() string {
	return fmt.Sprintf("%s/%s", stash.Repository.Project, stash.Repository.Slug)
}

func (stash StashEvent) Branches() []string {
	branches := make([]string, 0)
	for _, v := range stash.RefChanges {
		branches = append(branches, strings.ToLower(strings.Replace(v.RefID, "refs/heads/", "", -1)))
	}
	return branches
}

type StashHandler struct {
	K8sBase K8sBase
	Handler
}

func (han StashHandler) handle(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(200)

	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		Log.Println(err)
		return
	}
	Log.Printf("post-receive hook received: %s\n", data)

	var stashContainer StashEvent
	if err := json.Unmarshal(data, &stashContainer); err != nil {
		Log.Println(err)
		return
	}
	go han.K8sBase.launchBuild(stashContainer)
}
<|endoftext|>


<commit_before>package organization_test

import (
	"code.cloudfoundry.org/cli/cf/commands/user/userfakes"
	"code.cloudfoundry.org/cli/cf/errors"
	"code.cloudfoundry.org/cli/cf/models"
	"code.cloudfoundry.org/cli/cf/requirements"
	"code.cloudfoundry.org/cli/cf/requirements/requirementsfakes"

	"code.cloudfoundry.org/cli/cf/api/featureflags/featureflagsfakes"
	"code.cloudfoundry.org/cli/cf/api/organizations/organizationsfakes"
	"code.cloudfoundry.org/cli/cf/api/quotas/quotasfakes"
	"code.cloudfoundry.org/cli/cf/configuration/coreconfig"
	testcmd "code.cloudfoundry.org/cli/util/testhelpers/commands"
	testconfig "code.cloudfoundry.org/cli/util/testhelpers/configuration"
	testterm "code.cloudfoundry.org/cli/util/testhelpers/terminal"

	"code.cloudfoundry.org/cli/cf/commandregistry"
	. "code.cloudfoundry.org/cli/util/testhelpers/matchers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("create-org command", func() {
	var (
		config              coreconfig.Repository
		ui                  *testterm.FakeUI
		requirementsFactory *requirementsfakes.FakeFactory
		orgRepo             *organizationsfakes.FakeOrganizationRepository
		quotaRepo           *quotasfakes.FakeQuotaRepository
		deps                commandregistry.Dependency
		orgRoleSetter       *userfakes.FakeOrgRoleSetter
		flagRepo            *featureflagsfakes.FakeFeatureFlagRepository
		OriginalCommand     commandregistry.Command
	)

	updateCommandDependency := func(pluginCall bool) {
		deps.UI = ui
		deps.RepoLocator = deps.RepoLocator.SetOrganizationRepository(orgRepo)
		deps.RepoLocator = deps.RepoLocator.SetQuotaRepository(quotaRepo)
		deps.RepoLocator = deps.RepoLocator.SetFeatureFlagRepository(flagRepo)
		deps.Config = config

		//inject fake 'command dependency' into registry
		commandregistry.Register(orgRoleSetter)

		commandregistry.Commands.SetCommand(commandregistry.Commands.FindCommand("create-org").SetDependency(deps, pluginCall))
	}

	BeforeEach(func() {
		ui = &testterm.FakeUI{}
		config = testconfig.NewRepositoryWithDefaults()
		requirementsFactory = new(requirementsfakes.FakeFactory)
		requirementsFactory.NewLoginRequirementReturns(requirements.Passing{})
		orgRepo = new(organizationsfakes.FakeOrganizationRepository)
		quotaRepo = new(quotasfakes.FakeQuotaRepository)
		flagRepo = new(featureflagsfakes.FakeFeatureFlagRepository)
		config.SetAPIVersion("2.36.9")

		orgRoleSetter = new(userfakes.FakeOrgRoleSetter)
		//setup fakes to correctly interact with commandregistry
		orgRoleSetter.SetDependencyStub = func(_ commandregistry.Dependency, _ bool) commandregistry.Command {
			return orgRoleSetter
		}
		orgRoleSetter.MetaDataReturns(commandregistry.CommandMetadata{Name: "set-org-role"})

		//save original command and restore later
		OriginalCommand = commandregistry.Commands.FindCommand("set-org-role")
	})

	AfterEach(func() {
		commandregistry.Register(OriginalCommand)
	})

	runCommand := func(args ...string) bool {
		return testcmd.RunCLICommand("create-org", args, requirementsFactory, updateCommandDependency, false, ui)
	}

	Describe("requirements", func() {
		It("fails with usage when not provided exactly one arg", func() {
			runCommand()
			Expect(ui.Outputs()).To(ContainSubstrings(
				[]string{"Incorrect Usage", "Requires an argument"},
			))
		})

		It("fails when not logged in", func() {
			requirementsFactory.NewLoginRequirementReturns(requirements.Failing{Message: "not logged in"})
			Expect(runCommand("my-org")).To(BeFalse())
		})
	})

	Context("when logged in and provided the name of an org to create", func() {
		BeforeEach(func() {
			orgRepo.CreateReturns(nil)
		})

		It("creates an org", func() {
			runCommand("my-org")

			Expect(ui.Outputs()).To(ContainSubstrings(
				[]string{"Creating org", "my-org", "my-user"},
				[]string{"OK"},
			))
			Expect(orgRepo.CreateArgsForCall(0).Name).To(Equal("my-org"))
		})

		It("fails and warns the user when the org already exists", func() {
			err := errors.NewHTTPError(400, errors.OrganizationNameTaken, "org already exists")
			orgRepo.CreateReturns(err)
			runCommand("my-org")

			Expect(ui.Outputs()).To(ContainSubstrings(
				[]string{"Creating org", "my-org"},
				[]string{"OK"},
				[]string{"my-org", "already exists"},
			))
		})

		Context("when CC api version supports assigning orgRole by name, and feature-flag 'set_roles_by_username' is enabled", func() {
			BeforeEach(func() {
				config.SetAPIVersion("2.37.0")
				flagRepo.FindByNameReturns(models.FeatureFlag{
					Name:    "set_roles_by_username",
					Enabled: true,
				}, nil)
				orgRepo.FindByNameReturns(models.Organization{
					OrganizationFields: models.OrganizationFields{
						GUID: "my-org-guid",
					},
				}, nil)
			})

			It("assigns manager role to user", func() {
				runCommand("my-org")

				orgGUID, role, userGUID, userName := orgRoleSetter.SetOrgRoleArgsForCall(0)

				Expect(orgRoleSetter.SetOrgRoleCallCount()).To(Equal(1))
				Expect(orgGUID).To(Equal("my-org-guid"))
				Expect(role).To(Equal(models.RoleOrgManager))
				Expect(userGUID).To(Equal(""))
				Expect(userName).To(Equal("my-user"))
			})

			It("warns user about problem accessing feature-flag", func() {
				flagRepo.FindByNameReturns(models.FeatureFlag{}, errors.New("error error error"))

				runCommand("my-org")

				Expect(orgRoleSetter.SetOrgRoleCallCount()).To(Equal(0))
				Expect(ui.Outputs()).To(ContainSubstrings(
					[]string{"Warning", "error error error"},
				))

			})

			It("fails on failing getting the guid of the newly created org", func() {
				orgRepo.FindByNameReturns(models.Organization{}, errors.New("cannot get org guid"))

				runCommand("my-org")

				Expect(orgRoleSetter.SetOrgRoleCallCount()).To(Equal(0))
				Expect(ui.Outputs()).To(ContainSubstrings(
					[]string{"FAILED"},
					[]string{"cannot get org guid"},
				))

			})

			It("fails on failing assigning org role to user", func() {
				orgRoleSetter.SetOrgRoleReturns(errors.New("failed to assign role"))

				runCommand("my-org")

				Expect(orgRoleSetter.SetOrgRoleCallCount()).To(Equal(1))
				Expect(ui.Outputs()).To(ContainSubstrings(
					[]string{"Assigning role OrgManager to user my-user in org my-org ..."},
					[]string{"FAILED"},
					[]string{"failed to assign role"},
				))

			})
		})

		Context("when allowing a non-defualt quota", func() {
			var (
				quota models.QuotaFields
			)

			BeforeEach(func() {
				quota = models.QuotaFields{
					Name: "non-default-quota",
					GUID: "non-default-quota-guid",
				}
			})

			It("creates an org with a non-default quota", func() {
				quotaRepo.FindByNameReturns(quota, nil)
				runCommand("-q", "non-default-quota", "my-org")

				Expect(quotaRepo.FindByNameArgsForCall(0)).To(Equal("non-default-quota"))
				Expect(orgRepo.CreateArgsForCall(0).QuotaDefinition.GUID).To(Equal("non-default-quota-guid"))
				Expect(ui.Outputs()).To(ContainSubstrings(
					[]string{"Creating org", "my-org"},
					[]string{"OK"},
				))
			})

			It("fails and warns the user when the quota cannot be found", func() {
				quotaRepo.FindByNameReturns(models.QuotaFields{}, errors.New("Could not find quota"))
				runCommand("-q", "non-default-quota", "my-org")

				Expect(ui.Outputs()).To(ContainSubstrings(
					[]string{"Creating org", "my-org"},
					[]string{"Could not find quota"},
				))
			})
		})
	})
})
<commit_msg>Added tests for #1149 (quotes around create-org tip)<commit_after>package organization_test

import (
	"code.cloudfoundry.org/cli/cf/commands/user/userfakes"
	"code.cloudfoundry.org/cli/cf/errors"
	"code.cloudfoundry.org/cli/cf/models"
	"code.cloudfoundry.org/cli/cf/requirements"
	"code.cloudfoundry.org/cli/cf/requirements/requirementsfakes"

	"code.cloudfoundry.org/cli/cf/api/featureflags/featureflagsfakes"
	"code.cloudfoundry.org/cli/cf/api/organizations/organizationsfakes"
	"code.cloudfoundry.org/cli/cf/api/quotas/quotasfakes"
	"code.cloudfoundry.org/cli/cf/configuration/coreconfig"
	testcmd "code.cloudfoundry.org/cli/util/testhelpers/commands"
	testconfig "code.cloudfoundry.org/cli/util/testhelpers/configuration"
	testterm "code.cloudfoundry.org/cli/util/testhelpers/terminal"

	"code.cloudfoundry.org/cli/cf/commandregistry"
	. "code.cloudfoundry.org/cli/util/testhelpers/matchers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("create-org command", func() {
	var (
		config              coreconfig.Repository
		ui                  *testterm.FakeUI
		requirementsFactory *requirementsfakes.FakeFactory
		orgRepo             *organizationsfakes.FakeOrganizationRepository
		quotaRepo           *quotasfakes.FakeQuotaRepository
		deps                commandregistry.Dependency
		orgRoleSetter       *userfakes.FakeOrgRoleSetter
		flagRepo            *featureflagsfakes.FakeFeatureFlagRepository
		OriginalCommand     commandregistry.Command
	)

	updateCommandDependency := func(pluginCall bool) {
		deps.UI = ui
		deps.RepoLocator = deps.RepoLocator.SetOrganizationRepository(orgRepo)
		deps.RepoLocator = deps.RepoLocator.SetQuotaRepository(quotaRepo)
		deps.RepoLocator = deps.RepoLocator.SetFeatureFlagRepository(flagRepo)
		deps.Config = config

		//inject fake 'command dependency' into registry
		commandregistry.Register(orgRoleSetter)

		commandregistry.Commands.SetCommand(commandregistry.Commands.FindCommand("create-org").SetDependency(deps, pluginCall))
	}

	BeforeEach(func() {
		ui = &testterm.FakeUI{}
		config = testconfig.NewRepositoryWithDefaults()
		requirementsFactory = new(requirementsfakes.FakeFactory)
		requirementsFactory.NewLoginRequirementReturns(requirements.Passing{})
		orgRepo = new(organizationsfakes.FakeOrganizationRepository)
		quotaRepo = new(quotasfakes.FakeQuotaRepository)
		flagRepo = new(featureflagsfakes.FakeFeatureFlagRepository)
		config.SetAPIVersion("2.36.9")

		orgRoleSetter = new(userfakes.FakeOrgRoleSetter)
		//setup fakes to correctly interact with commandregistry
		orgRoleSetter.SetDependencyStub = func(_ commandregistry.Dependency, _ bool) commandregistry.Command {
			return orgRoleSetter
		}
		orgRoleSetter.MetaDataReturns(commandregistry.CommandMetadata{Name: "set-org-role"})

		//save original command and restore later
		OriginalCommand = commandregistry.Commands.FindCommand("set-org-role")
	})

	AfterEach(func() {
		commandregistry.Register(OriginalCommand)
	})

	runCommand := func(args ...string) bool {
		return testcmd.RunCLICommand("create-org", args, requirementsFactory, updateCommandDependency, false, ui)
	}

	Describe("requirements", func() {
		It("fails with usage when not provided exactly one arg", func() {
			runCommand()
			Expect(ui.Outputs()).To(ContainSubstrings(
				[]string{"Incorrect Usage", "Requires an argument"},
			))
		})

		It("fails when not logged in", func() {
			requirementsFactory.NewLoginRequirementReturns(requirements.Failing{Message: "not logged in"})
			Expect(runCommand("my-org")).To(BeFalse())
		})
	})

	Context("when logged in and provided the name of an org to create", func() {
		BeforeEach(func() {
			orgRepo.CreateReturns(nil)
		})

		It("creates an org", func() {
			runCommand("my-org")

			Expect(ui.Outputs()).To(ContainSubstrings(
				[]string{"Creating org", "my-org", "my-user"},
				[]string{"OK"},
				[]string{`TIP: Use 'cf target -o "my-org"' to target new org`},
			))
			Expect(orgRepo.CreateArgsForCall(0).Name).To(Equal("my-org"))
		})

		It("fails and warns the user when the org already exists", func() {
			err := errors.NewHTTPError(400, errors.OrganizationNameTaken, "org already exists")
			orgRepo.CreateReturns(err)
			runCommand("my-org")

			Expect(ui.Outputs()).To(ContainSubstrings(
				[]string{"Creating org", "my-org"},
				[]string{"OK"},
				[]string{"my-org", "already exists"},
			))

			Expect(ui.Outputs()).NotTo(ContainSubstrings(
				[]string{`TIP: Use 'cf target -o "my-org"' to target new org`},
			))
		})

		Context("when CC api version supports assigning orgRole by name, and feature-flag 'set_roles_by_username' is enabled", func() {
			BeforeEach(func() {
				config.SetAPIVersion("2.37.0")
				flagRepo.FindByNameReturns(models.FeatureFlag{
					Name:    "set_roles_by_username",
					Enabled: true,
				}, nil)
				orgRepo.FindByNameReturns(models.Organization{
					OrganizationFields: models.OrganizationFields{
						GUID: "my-org-guid",
					},
				}, nil)
			})

			It("assigns manager role to user", func() {
				runCommand("my-org")

				orgGUID, role, userGUID, userName := orgRoleSetter.SetOrgRoleArgsForCall(0)

				Expect(orgRoleSetter.SetOrgRoleCallCount()).To(Equal(1))
				Expect(orgGUID).To(Equal("my-org-guid"))
				Expect(role).To(Equal(models.RoleOrgManager))
				Expect(userGUID).To(Equal(""))
				Expect(userName).To(Equal("my-user"))
			})

			It("warns user about problem accessing feature-flag", func() {
				flagRepo.FindByNameReturns(models.FeatureFlag{}, errors.New("error error error"))

				runCommand("my-org")

				Expect(orgRoleSetter.SetOrgRoleCallCount()).To(Equal(0))
				Expect(ui.Outputs()).To(ContainSubstrings(
					[]string{"Warning", "error error error"},
				))

			})

			It("fails on failing getting the guid of the newly created org", func() {
				orgRepo.FindByNameReturns(models.Organization{}, errors.New("cannot get org guid"))

				runCommand("my-org")

				Expect(orgRoleSetter.SetOrgRoleCallCount()).To(Equal(0))
				Expect(ui.Outputs()).To(ContainSubstrings(
					[]string{"FAILED"},
					[]string{"cannot get org guid"},
				))

			})

			It("fails on failing assigning org role to user", func() {
				orgRoleSetter.SetOrgRoleReturns(errors.New("failed to assign role"))

				runCommand("my-org")

				Expect(orgRoleSetter.SetOrgRoleCallCount()).To(Equal(1))
				Expect(ui.Outputs()).To(ContainSubstrings(
					[]string{"Assigning role OrgManager to user my-user in org my-org ..."},
					[]string{"FAILED"},
					[]string{"failed to assign role"},
				))

			})
		})

		Context("when allowing a non-defualt quota", func() {
			var (
				quota models.QuotaFields
			)

			BeforeEach(func() {
				quota = models.QuotaFields{
					Name: "non-default-quota",
					GUID: "non-default-quota-guid",
				}
			})

			It("creates an org with a non-default quota", func() {
				quotaRepo.FindByNameReturns(quota, nil)
				runCommand("-q", "non-default-quota", "my-org")

				Expect(quotaRepo.FindByNameArgsForCall(0)).To(Equal("non-default-quota"))
				Expect(orgRepo.CreateArgsForCall(0).QuotaDefinition.GUID).To(Equal("non-default-quota-guid"))
				Expect(ui.Outputs()).To(ContainSubstrings(
					[]string{"Creating org", "my-org"},
					[]string{"OK"},
				))
			})

			It("fails and warns the user when the quota cannot be found", func() {
				quotaRepo.FindByNameReturns(models.QuotaFields{}, errors.New("Could not find quota"))
				runCommand("-q", "non-default-quota", "my-org")

				Expect(ui.Outputs()).To(ContainSubstrings(
					[]string{"Creating org", "my-org"},
					[]string{"Could not find quota"},
				))
			})
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"github.com/couchbaselabs/dparval"
	"github.com/couchbaselabs/go-couchbase"
	"github.com/couchbaselabs/indexing/api"
	imclient "github.com/couchbaselabs/indexing/index_manager/client"
	ast "github.com/couchbaselabs/tuqtng/ast"
	"github.com/prataprc/goupr"
	//memcached "github.com/dustin/gomemcached"
	"log"
	"net"
	"net/rpc"
	"net/rpc/jsonrpc"
	"strconv"
	"time"
)

// exponential backoff while connection retry.
const initialRetryInterval = 1 * time.Second
const maximumRetryInterval = 30 * time.Second

var options struct {
	kvhost   string
	imhost   string
	inhost   string
	port     int
	userProd string
	projProd string
	seed     int
	count    int
	proto    string
}

// BucketVBVector maps bucket to a 2 dimensional array of
// [[vbcuket0, startSeq], [vbcuket1, startSeq], ..., [api.MAX_VBUCKETS, seq]]
type BucketVBVector map[string][]uint64

func argParse() {
	flag.StringVar(&options.kvhost, "kvhost", "localhost", "Port to connect")
	flag.StringVar(&options.imhost, "imhost", "localhost", "Port to connect")
	flag.StringVar(&options.inhost, "inhost", "localhost", "Port to connect")
	flag.IntVar(&options.port, "port", 11211, "Host to connect")
	flag.StringVar(&options.userProd, "userProd", "", "monster production for users")
	flag.StringVar(&options.projProd, "projProd", "", "monster production for project")
	flag.IntVar(&options.seed, "seed", 100, "seed for production")
	flag.IntVar(&options.count, "count", 10, "number of documents to generate")
	flag.StringVar(&options.proto, "proto", "tap", "Use either `tap` or `upr`")
	flag.Parse()
}

type Streamer interface {
	OpenStreams([]string, BucketVBVector)
	CloseStreams()
}

func main() {
	argParse()

	//mcdport := int(8091)
	//if options.port == 11212 {
	//    mcdport = 12000
	//}

	// Couchbase client, pool and default bucket
	url := "http://" + options.kvhost + ":" + strconv.Itoa(options.port)
	couch, err := couchbase.Connect(url)
	if err != nil {
		log.Fatalf("Error connecting:  %v", err)
	}
	pool, err := couch.GetPool("default")
	if err != nil {
		log.Fatalf("Error getting pool:  %v", err)
	}

	imURL := "http://" + options.imhost + ":" + strconv.Itoa(8094)
	imanager := imclient.NewRestClient(imURL)
	// nodes := imanager.Nodes()

	inURL := options.imhost + ":" + strconv.Itoa(8096)
	rpcconn, err := net.Dial("tcp", inURL)
	if err != nil {
		panic(err)
	}
	defer rpcconn.Close()
	c := jsonrpc.NewClient(rpcconn)

	eventch := make(chan *goupr.UprEvent)
	var streams Streamer
	switch options.proto {
	//case "tap":
	//    streams = NewTapStreams(&couch, &pool, eventch)
	case "upr":
		streams = NewUprStreams(&couch, &pool, eventch)
	}

	var serverUuid string
	var indexinfos []api.IndexInfo
	for {
		tryIndexManager(func() bool {
			serverUuid, indexinfos, err = imanager.List("")
			if err != nil {
				log.Println(err)
				return false
			}
			return true
		})
		log.Printf("Got %v indexes", len(indexinfos))
		bucketMap := getSequenceVectors(c, indexinfos)
		streams.OpenStreams(indexBuckets(indexinfos), bucketMap)
		bucketexprs := parseExpression(indexinfos)
		notifych := make(chan string, 1)
		go waitNotify(imanager, serverUuid, notifych)
		loop(c, notifych, eventch, bucketexprs)
		streams.CloseStreams()
		log.Println("Projector restarting ...")
	}
}

func loop(c *rpc.Client, notifych chan string, eventch chan *goupr.UprEvent,
	bucketexprs map[*api.IndexInfo][]ast.Expression) {

Loop:
	for {
		select {
		case serverUuid, ok := <-notifych:
			if ok {
				log.Println("Notification received, serverUuid:", serverUuid)
			}
			break Loop
		case e := <-eventch:
			for indexinfo, astexprs := range bucketexprs {
				bucket, idxuuid := indexinfo.Bucket, indexinfo.Uuid
				if e.Bucket != bucket {
					continue
				}
				m := api.Mutation{
					Type:    api.UprEventName(e.Opstr),
					Indexid: idxuuid,
					Docid:   string(e.Key),
					Vbucket: e.Vbucket,
					Seqno:   e.Seqno,
				}
				if indexinfo.IsPrimary && e.Opstr == "INSERT" {
					m.SecondaryKey = [][]byte{e.Key}
				} else if e.Opstr == "INSERT" {
					m.SecondaryKey = evaluate(e.Value, astexprs)
				}
				log.Println("mutation recevied", e.Opstr, idxuuid, bucket,
					m.Docid, fmtSKey(m.SecondaryKey))
				var r bool
				err := c.Call("MutationManager.ProcessSingleMutation", m, &r)
				if err != nil {
					log.Println("ERROR: Mutation manager:", err)
				}
			}
		}
	}
}

func evaluate(value []byte, astexprs []ast.Expression) [][]byte {
	secKey := make([][]byte, 0)
	for _, expr := range astexprs {
		key, err := expr.Evaluate(dparval.NewValueFromBytes([]byte(value)))
		if err != nil {
			log.Println(err)
			secKey = append(secKey, []byte{})
		} else {
			secKey = append(secKey, key.Bytes())
		}
	}
	return secKey
}

func parseExpression(indexinfos []api.IndexInfo) map[*api.IndexInfo][]ast.Expression {
	bucketexprs := make(map[*api.IndexInfo][]ast.Expression)
	for i, indexinfo := range indexinfos {
		astexprs := make([]ast.Expression, 0)
		for _, expr := range indexinfo.OnExprList {
			if ex, err := ast.UnmarshalExpression([]byte(expr)); err == nil {
				astexprs = append(astexprs, ex)
			} else {
				panic(err)
			}
		}
		bucketexprs[&indexinfos[i]] = astexprs
	}
	return bucketexprs
}

func tryIndexManager(fn func() bool) {
	retryInterval := initialRetryInterval
	for {
		ok := fn()
		if ok {
			return
		}
		log.Printf("Retrying after %v seconds ...\n", retryInterval)
		<-time.After(retryInterval)
		if retryInterval *= 2; retryInterval > maximumRetryInterval {
			retryInterval = maximumRetryInterval
		}
	}
}

func waitNotify(imanager *imclient.RestClient, serverUuid string, notifych chan string) {
	if _, serverUuid, err := imanager.Notify(serverUuid); err != nil {
		log.Println("Index manager closed connection:", err)
		close(notifych)
	} else {
		notifych <- serverUuid
	}
}

func indexBuckets(indexinfos []api.IndexInfo) []string {
	buckets := make(map[string]bool)
	for _, indexinfo := range indexinfos {
		if buckets[indexinfo.Bucket] == false {
			buckets[indexinfo.Bucket] = true
		}
	}
	uniquebuckets := make([]string, 0)
	for bucket, _ := range buckets {
		uniquebuckets = append(uniquebuckets, bucket)
	}
	return uniquebuckets
}

func getSequenceVectors(c *rpc.Client,
	indexinfos []api.IndexInfo) BucketVBVector {

	var returnMap api.IndexSequenceMap
	indexMap := make(map[string]api.IndexInfo)
	// Argument to GetSequenceVectors()
	indexList := make([]string, 0)
	for _, ii := range indexinfos {
		indexList = append(indexList, ii.Uuid)
		indexMap[ii.Uuid] = ii
	}
	err := c.Call("MutationManager.GetSequenceVectors", &indexList, &returnMap)
	if err != nil {
		log.Println("ERROR: Mutation manager:", err)
	}
	bvb := make(BucketVBVector)
	for index_uuid, vector := range returnMap {
		log.Println(vector)
		bucket := indexMap[index_uuid].Bucket
		for vb, seqno := range vector {
			if bvb[bucket] == nil {
				bvb[bucket] = make([]uint64, api.MAX_VBUCKETS)
			}
			if bvb[bucket][vb] == 0 || bvb[bucket][vb] > seqno {
				bvb[bucket][vb] = seqno
			}
		}
	}
	log.Println(bvb)
	return bvb
}

func fmtSKey(keys [][]byte) []string {
	ss := make([]string, 0)
	for _, bs := range keys {
		ss = append(ss, string(bs))
	}
	return ss
}
<commit_msg>INSERT and DELETE constance from api/<commit_after>package main

import (
	"flag"
	"github.com/couchbaselabs/dparval"
	"github.com/couchbaselabs/go-couchbase"
	"github.com/couchbaselabs/indexing/api"
	imclient "github.com/couchbaselabs/indexing/index_manager/client"
	ast "github.com/couchbaselabs/tuqtng/ast"
	"github.com/prataprc/goupr"
	//memcached "github.com/dustin/gomemcached"
	"log"
	"net"
	"net/rpc"
	"net/rpc/jsonrpc"
	"strconv"
	"time"
)

// exponential backoff while connection retry.
const initialRetryInterval = 1 * time.Second
const maximumRetryInterval = 30 * time.Second

var options struct {
	kvhost   string
	imhost   string
	inhost   string
	port     int
	userProd string
	projProd string
	seed     int
	count    int
	proto    string
}

// BucketVBVector maps bucket to a 2 dimensional array of
// [[vbcuket0, startSeq], [vbcuket1, startSeq], ..., [api.MAX_VBUCKETS, seq]]
type BucketVBVector map[string][]uint64

func argParse() {
	flag.StringVar(&options.kvhost, "kvhost", "localhost", "Port to connect")
	flag.StringVar(&options.imhost, "imhost", "localhost", "Port to connect")
	flag.StringVar(&options.inhost, "inhost", "localhost", "Port to connect")
	flag.IntVar(&options.port, "port", 11211, "Host to connect")
	flag.StringVar(&options.userProd, "userProd", "", "monster production for users")
	flag.StringVar(&options.projProd, "projProd", "", "monster production for project")
	flag.IntVar(&options.seed, "seed", 100, "seed for production")
	flag.IntVar(&options.count, "count", 10, "number of documents to generate")
	flag.StringVar(&options.proto, "proto", "tap", "Use either `tap` or `upr`")
	flag.Parse()
}

type Streamer interface {
	OpenStreams([]string, BucketVBVector)
	CloseStreams()
}

func main() {
	argParse()

	//mcdport := int(8091)
	//if options.port == 11212 {
	//    mcdport = 12000
	//}

	// Couchbase client, pool and default bucket
	url := "http://" + options.kvhost + ":" + strconv.Itoa(options.port)
	couch, err := couchbase.Connect(url)
	if err != nil {
		log.Fatalf("Error connecting:  %v", err)
	}
	pool, err := couch.GetPool("default")
	if err != nil {
		log.Fatalf("Error getting pool:  %v", err)
	}

	imURL := "http://" + options.imhost + ":" + strconv.Itoa(8094)
	imanager := imclient.NewRestClient(imURL)
	// nodes := imanager.Nodes()

	inURL := options.imhost + ":" + strconv.Itoa(8096)
	rpcconn, err := net.Dial("tcp", inURL)
	if err != nil {
		panic(err)
	}
	defer rpcconn.Close()
	c := jsonrpc.NewClient(rpcconn)

	eventch := make(chan *goupr.UprEvent)
	var streams Streamer
	switch options.proto {
	//case "tap":
	//    streams = NewTapStreams(&couch, &pool, eventch)
	case "upr":
		streams = NewUprStreams(&couch, &pool, eventch)
	}

	var serverUuid string
	var indexinfos []api.IndexInfo
	for {
		tryIndexManager(func() bool {
			serverUuid, indexinfos, err = imanager.List("")
			if err != nil {
				log.Println(err)
				return false
			}
			return true
		})
		log.Printf("Got %v indexes", len(indexinfos))
		bucketMap := getSequenceVectors(c, indexinfos)
		streams.OpenStreams(indexBuckets(indexinfos), bucketMap)
		bucketexprs := parseExpression(indexinfos)
		notifych := make(chan string, 1)
		go waitNotify(imanager, serverUuid, notifych)
		loop(c, notifych, eventch, bucketexprs)
		streams.CloseStreams()
		log.Println("Projector restarting ...")
	}
}

func loop(c *rpc.Client, notifych chan string, eventch chan *goupr.UprEvent,
	bucketexprs map[*api.IndexInfo][]ast.Expression) {

Loop:
	for {
		select {
		case serverUuid, ok := <-notifych:
			if ok {
				log.Println("Notification received, serverUuid:", serverUuid)
			}
			break Loop
		case e := <-eventch:
			for indexinfo, astexprs := range bucketexprs {
				bucket, idxuuid := indexinfo.Bucket, indexinfo.Uuid
				if e.Bucket != bucket {
					continue
				}
				m := api.Mutation{
					Type:    api.UprEventName(e.Opstr),
					Indexid: idxuuid,
					Docid:   string(e.Key),
					Vbucket: e.Vbucket,
					Seqno:   e.Seqno,
				}
				if indexinfo.IsPrimary && e.Opstr == api.INSERT {
					m.SecondaryKey = [][]byte{e.Key}
				} else if e.Opstr == api.INSERT {
					m.SecondaryKey = evaluate(e.Value, astexprs)
				}
				log.Println("mutation recevied", e.Opstr, idxuuid, bucket,
					m.Docid, fmtSKey(m.SecondaryKey))
				var r bool
				err := c.Call("MutationManager.ProcessSingleMutation", m, &r)
				if err != nil {
					log.Println("ERROR: Mutation manager:", err)
				}
			}
		}
	}
}

func evaluate(value []byte, astexprs []ast.Expression) [][]byte {
	secKey := make([][]byte, 0)
	for _, expr := range astexprs {
		key, err := expr.Evaluate(dparval.NewValueFromBytes([]byte(value)))
		if err != nil {
			log.Println(err)
			secKey = append(secKey, []byte{})
		} else {
			secKey = append(secKey, key.Bytes())
		}
	}
	return secKey
}

func parseExpression(indexinfos []api.IndexInfo) map[*api.IndexInfo][]ast.Expression {
	bucketexprs := make(map[*api.IndexInfo][]ast.Expression)
	for i, indexinfo := range indexinfos {
		astexprs := make([]ast.Expression, 0)
		for _, expr := range indexinfo.OnExprList {
			if ex, err := ast.UnmarshalExpression([]byte(expr)); err == nil {
				astexprs = append(astexprs, ex)
			} else {
				panic(err)
			}
		}
		bucketexprs[&indexinfos[i]] = astexprs
	}
	return bucketexprs
}

func tryIndexManager(fn func() bool) {
	retryInterval := initialRetryInterval
	for {
		ok := fn()
		if ok {
			return
		}
		log.Printf("Retrying after %v seconds ...\n", retryInterval)
		<-time.After(retryInterval)
		if retryInterval *= 2; retryInterval > maximumRetryInterval {
			retryInterval = maximumRetryInterval
		}
	}
}

func waitNotify(imanager *imclient.RestClient, serverUuid string, notifych chan string) {
	if _, serverUuid, err := imanager.Notify(serverUuid); err != nil {
		log.Println("Index manager closed connection:", err)
		close(notifych)
	} else {
		notifych <- serverUuid
	}
}

func indexBuckets(indexinfos []api.IndexInfo) []string {
	buckets := make(map[string]bool)
	for _, indexinfo := range indexinfos {
		if buckets[indexinfo.Bucket] == false {
			buckets[indexinfo.Bucket] = true
		}
	}
	uniquebuckets := make([]string, 0)
	for bucket, _ := range buckets {
		uniquebuckets = append(uniquebuckets, bucket)
	}
	return uniquebuckets
}

func getSequenceVectors(c *rpc.Client,
	indexinfos []api.IndexInfo) BucketVBVector {

	var returnMap api.IndexSequenceMap
	indexMap := make(map[string]api.IndexInfo)
	// Argument to GetSequenceVectors()
	indexList := make([]string, 0)
	for _, ii := range indexinfos {
		indexList = append(indexList, ii.Uuid)
		indexMap[ii.Uuid] = ii
	}
	err := c.Call("MutationManager.GetSequenceVectors", &indexList, &returnMap)
	if err != nil {
		log.Println("ERROR: Mutation manager:", err)
	}
	bvb := make(BucketVBVector)
	for index_uuid, vector := range returnMap {
		log.Println(vector)
		bucket := indexMap[index_uuid].Bucket
		for vb, seqno := range vector {
			if bvb[bucket] == nil {
				bvb[bucket] = make([]uint64, api.MAX_VBUCKETS)
			}
			if bvb[bucket][vb] == 0 || bvb[bucket][vb] > seqno {
				bvb[bucket][vb] = seqno
			}
		}
	}
	log.Println(bvb)
	return bvb
}

func fmtSKey(keys [][]byte) []string {
	ss := make([]string, 0)
	for _, bs := range keys {
		ss = append(ss, string(bs))
	}
	return ss
}
<|endoftext|>


<commit_before>package rules

import (
	"github.com/golang/protobuf/v2/reflect/protoreflect"
	"github.com/jgeewax/api-linter/lint"
	"github.com/jgeewax/api-linter/proto"
)

// linter defines an operation that checks a lint Request with a Rule,
// and returns a Response and if applicable, an error.
type linter interface {
	Lint(lint.Request, lint.Rule) (lint.Response, error)
}

type protoLinter struct {
	check    descCheckFunc
	info     ruleInfo
	problems []lint.Problem
	source   lint.DescriptorSource
}

func (l *protoLinter) addProblems(p ...lint.Problem) {
	l.problems = append(l.problems, p...)
}

func (l *protoLinter) ConsumeDescriptor(d protoreflect.Descriptor) error {
	if l.source.IsRuleDisabled(l.info.Name(), d) {
		return nil
	}

	problems, err := l.check(d, l.source)
	if err != nil {
		return err
	}
	l.addProblems(problems...)

	return nil
}

func (l *protoLinter) Lint(req lint.Request, rule lint.Rule) (lint.Response, error) {
	f := req.ProtoFile()
	l.source = req.DescriptorSource()
	if err := proto.WalkDescriptor(f, l); err != nil {
		return lint.Response{}, nil
	}
	return lint.Response{
		Problems: l.problems,
	}, nil
}

func newProtoLinter(info ruleInfo, check descCheckFunc) linter {
	return &protoLinter{
		check: check,
		info:  info,
	}
}
<commit_msg>Added minor improvements.<commit_after>package rules

import (
	"github.com/golang/protobuf/v2/reflect/protoreflect"
	"github.com/jgeewax/api-linter/lint"
	"github.com/jgeewax/api-linter/proto"
)

// linter defines an operation that checks a lint Request with a Rule,
// and returns a Response and if applicable, an error.
type linter interface {
	Lint(lint.Request, lint.Rule) (lint.Response, error)
}

type protoLinter struct {
	check    descCheckFunc
	info     ruleInfo
	problems []lint.Problem
	source   lint.DescriptorSource
}

func (l *protoLinter) addProblems(p ...lint.Problem) {
	l.problems = append(l.problems, p...)
}

func (l *protoLinter) ConsumeDescriptor(d protoreflect.Descriptor) error {
	if l.source.IsRuleDisabled(l.info.Name(), d) {
		return nil
	}

	problems, err := l.check(d, l.source)
	if err != nil {
		return err
	}
	l.addProblems(problems...)

	return nil
}

func (l *protoLinter) Lint(req lint.Request, rule lint.Rule) (lint.Response, error) {
	f := req.ProtoFile()
	l.source = req.DescriptorSource()
	if err := proto.WalkDescriptor(f, l); err != nil {
		return lint.Response{}, err
	}
	return lint.Response{
		Problems: l.problems,
	}, nil
}

func newProtoLinter(info ruleInfo, check descCheckFunc) *protoLinter {
	return &protoLinter{
		check: check,
		info:  info,
	}
}
<|endoftext|>


<commit_before>// Copyright 2022 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
//
//     https://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 ezcx

import (
	"bytes"
	"context"
	"io"
	"log"
	"net/http"

	"github.com/google/uuid"
	cx "google.golang.org/genproto/googleapis/cloud/dialogflow/cx/v3"
	"google.golang.org/protobuf/encoding/protojson"
	"google.golang.org/protobuf/types/known/structpb"
)

type WebhookRequest struct {
	cx.WebhookRequest
	// 2022-10-08: Replaced context.Context with func () context.Context.
	ctx func() context.Context
}

func NewWebhookRequest() *WebhookRequest {
	return new(WebhookRequest)
}

// WebhookRequest Initializations

// Initialize the PageInfo field
func (req *WebhookRequest) initPageInfo() {
	if req.PageInfo == nil {
		req.PageInfo = new(cx.PageInfo)
	}
	if req.PageInfo.FormInfo == nil {
		req.PageInfo.FormInfo = new(cx.PageInfo_FormInfo)
	}
	if req.PageInfo.FormInfo.ParameterInfo == nil {
		req.PageInfo.FormInfo.ParameterInfo = make([]*cx.PageInfo_FormInfo_ParameterInfo, 0)
	}
}

// Initialize the SessionInfo field
func (req *WebhookRequest) initSessionInfo() {
	if req.SessionInfo == nil {
		req.SessionInfo = new(cx.SessionInfo)
	}
}

// Initialize the Payload field
func (req *WebhookRequest) initPayload() {
	if req.Payload == nil {
		req.Payload = new(structpb.Struct)
	}
	if req.Payload.Fields == nil {
		req.Payload.Fields = make(map[string]*structpb.Value)
	}
}

func (req *WebhookRequest) Context() context.Context {
	return req.ctx()
}

func (req *WebhookRequest) Logger() *log.Logger {
	ctx := req.Context()
	ctxLg := ctx.Value(Logger)
	if ctxLg == nil {
		// During testing, it's possible the user defined logger was not
		// flowed down.  This is provided for convenience.
		return log.Default()
	}
	lg, ok := ctxLg.(*log.Logger)
	if !ok {
		return log.Default()
	}
	return lg
}

// Sets (overrides) the PageInfo.ParameterInfos to match the provided map m
func (req *WebhookRequest) setPageFormParameters(m map[string]any) error {
	params := make([]*cx.PageInfo_FormInfo_ParameterInfo, 0)
	for k, v := range m {
		var formParameter cx.PageInfo_FormInfo_ParameterInfo
		pv, err := anyToProto(v)
		if err != nil {
			return err
		}
		formParameter.DisplayName = k
		formParameter.Value = pv
		formParameter.State = cx.PageInfo_FormInfo_ParameterInfo_FILLED
		params = append(params, &formParameter)
	}
	req.PageInfo.FormInfo.ParameterInfo = params
	return nil
}

// Sets (overrides) the SessionInfo.Parameters to match the provided map m
func (req *WebhookRequest) setSessionParameters(m map[string]any) error {
	pm, err := anyToProtoMap(m)
	if err != nil {
		return err
	}
	req.SessionInfo.Parameters = pm
	return nil
}

// Sets (overrides the SessionInfo.Parameters) to match the provided map m
func (req *WebhookRequest) setPayload(m map[string]any) error {
	pm, err := anyToProtoMap(m)
	if err != nil {
		return err
	}
	req.Payload.Fields = pm
	return nil
}

// yaquino@2022-10-11: Dialogflow CX API May include "extra" fields that may
// throw errors and interface with protojson.Unmarshal.  As per the documentation,
// these fields may be ignored. Now also pointing at req.WebhookRequest for unmarshalling..
func WebhookRequestFromReader(rd io.Reader) (*WebhookRequest, error) {
	var req WebhookRequest
	b, err := io.ReadAll(rd)
	if err != nil {
		return nil, err
	}
	unmarshaler := &protojson.UnmarshalOptions{
		AllowPartial:   true,
		DiscardUnknown: true,
	}
	err = unmarshaler.Unmarshal(b, &req.WebhookRequest)
	if err != nil {
		return nil, ErrUnmarshalWrapper("WebhookRequestFromReader", err)
	}
	return &req, nil
}

// yaquino@2022-10-07: Refactored to flow http.Request's context to the
// WebhookRequest instance.
func WebhookRequestFromRequest(r *http.Request) (*WebhookRequest, error) {
	req, err := WebhookRequestFromReader(r.Body)
	if err != nil {
		return nil, err
	}
	return req, nil
}

func (req *WebhookRequest) ReadReader(rd io.Reader) error {
	b, err := io.ReadAll(rd)
	if err != nil {
		return err
	}
	unmarshaler := &protojson.UnmarshalOptions{
		AllowPartial:   true,
		DiscardUnknown: true,
	}
	err = unmarshaler.Unmarshal(b, &req.WebhookRequest)
	if err != nil {
		return err
	}
	return nil
}

func (req *WebhookRequest) ReadRequest(r *http.Request) error {
	return req.ReadReader(r.Body)
}

// Is this the right format??
func (req *WebhookRequest) WriteRequest(w io.Writer) error {
	m := protojson.MarshalOptions{Indent: "\t"}
	b, err := m.Marshal(&req.WebhookRequest)
	if err != nil {
		return err
	}
	r := bytes.NewReader(b)
	_, err = io.Copy(w, r)
	if err != nil {
		return err
	}
	return nil
}

func (req *WebhookRequest) InitializeResponse() *WebhookResponse {
	return req.initializeResponse()
}

func (req *WebhookRequest) initializeResponse() *WebhookResponse {
	resp := NewWebhookResponse()
	return req.copySession(resp)
}

func (req *WebhookRequest) copySession(res *WebhookResponse) *WebhookResponse {
	if res.SessionInfo == nil {
		res.SessionInfo = new(cx.SessionInfo)
	}
	res.SessionInfo.Session = req.SessionInfo.Session
	return res
}

func (req *WebhookRequest) CopyPageInfo(res *WebhookResponse) {
	if req.PageInfo != nil {
		res.PageInfo = req.PageInfo
	}
}

func (req *WebhookRequest) CopySessionInfo(res *WebhookResponse) *WebhookResponse {
	if req.SessionInfo != nil {
		res.SessionInfo = req.SessionInfo
	}
	return res
}

func (req *WebhookRequest) CopyPayload(res *WebhookResponse) *WebhookResponse {
	if req.Payload != nil {
		res.Payload = req.Payload
	}
	return res
}

func (req *WebhookRequest) GetPageFormParameters() map[string]any {
	params := make(map[string]any)

	// Just in case - I don't think we can iterate over a nil map.
	if req.PageInfo == nil {
		return nil
	}
	if req.PageInfo.FormInfo == nil {
		return nil
	}
	if req.PageInfo.FormInfo.ParameterInfo == nil {
		return nil
	}

	for _, paramInfo := range req.PageInfo.FormInfo.ParameterInfo {
		params[paramInfo.DisplayName] = protoToAny(paramInfo.Value)
	}

	return params
}

func (req *WebhookRequest) GetSessionParameters() map[string]any {
	if req.SessionInfo == nil {
		return nil
	}
	if req.SessionInfo.Parameters == nil {
		return nil
	}
	return protoToAnyMap(req.SessionInfo.Parameters)
}

func (req *WebhookRequest) GetSessionParameter(key string) (any, bool) {
	// Check if SessionInfo Parameters is nil.
	if req.SessionInfo == nil {
		return nil, false
	}
	if req.SessionInfo.Parameters == nil {
		return nil, false
	}
	pv, ok := req.SessionInfo.Parameters[key]
	return protoToAny(pv), ok
}

func (req *WebhookRequest) GetPayload() map[string]any {
	if req.Payload == nil {
		return nil
	}
	if req.Payload.Fields == nil {
		return nil
	}
	return protoToAnyMap(req.Payload.Fields)
}

func (req *WebhookRequest) GetPayloadParameter(key string) (any, bool) {
	// Just in case - I don't think we can iterate over a nil map.

	if req.Payload == nil {
		return nil, false
	}
	if req.Payload.Fields == nil {
		return nil, false
	}

	pv, ok := req.Payload.Fields[key]
	return protoToAny(pv), ok
}

// Testing
func NewTestingWebhookRequest(session, payload, pageform map[string]any) (*WebhookRequest, error) {
	return NewWebhookRequest().initTestingWebhookRequest(session, payload, pageform)
}

func (req *WebhookRequest) initTestingWebhookRequest(session, payload, pageform map[string]any) (*WebhookRequest, error) {
	// Provided for testing, normally http.Request.Context is flowed down.
	req.ctx = context.Background

	// All incoming WebhookRequests should have a session.
	req.initSessionInfo()
	req.SessionInfo.Session = uuid.New().String()

	// if session parameters are provided...
	if session != nil {
		err := req.setSessionParameters(session)
		if err != nil {
			return nil, err
		}
	}

	// if payload parameters are provided...
	if payload != nil {
		req.initPayload()
		err := req.setPayload(payload)
		if err != nil {
			return nil, err
		}
	}

	// if pageForm parameters are provided...
	if pageform != nil {
		req.initPageInfo()
		err := req.setPageFormParameters(pageform)
		if err != nil {
			return nil, err
		}
	}
	return req, nil
}

// yaquino: 2022-10-08Review this...!
func (req *WebhookRequest) TestCxHandler(out io.Writer, h HandlerFunc) (*WebhookResponse, error) {
	if req.ctx == nil {
		req.ctx = context.Background
	}
	res := req.initializeResponse()
	err := h(res, req)
	if err != nil {
		return nil, err
	}
	err = res.WriteResponse(out)
	if err != nil {
		return nil, err
	}
	return res, nil
}
<commit_msg>Added Request Logger<commit_after>// Copyright 2022 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
//
//     https://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 ezcx

import (
	"bytes"
	"context"
	"io"
	"log"
	"net/http"

	"github.com/google/uuid"
	cx "google.golang.org/genproto/googleapis/cloud/dialogflow/cx/v3"
	"google.golang.org/protobuf/encoding/protojson"
	"google.golang.org/protobuf/types/known/structpb"
)

type WebhookRequest struct {
	cx.WebhookRequest
	// 2022-10-08: Replaced context.Context with func () context.Context.
	ctx func() context.Context
}

func NewWebhookRequest() *WebhookRequest {
	return new(WebhookRequest)
}

// WebhookRequest Initializations

// Initialize the PageInfo field
func (req *WebhookRequest) initPageInfo() {
	if req.PageInfo == nil {
		req.PageInfo = new(cx.PageInfo)
	}
	if req.PageInfo.FormInfo == nil {
		req.PageInfo.FormInfo = new(cx.PageInfo_FormInfo)
	}
	if req.PageInfo.FormInfo.ParameterInfo == nil {
		req.PageInfo.FormInfo.ParameterInfo = make([]*cx.PageInfo_FormInfo_ParameterInfo, 0)
	}
}

// Initialize the SessionInfo field
func (req *WebhookRequest) initSessionInfo() {
	if req.SessionInfo == nil {
		req.SessionInfo = new(cx.SessionInfo)
	}
}

// Initialize the Payload field
func (req *WebhookRequest) initPayload() {
	if req.Payload == nil {
		req.Payload = new(structpb.Struct)
	}
	if req.Payload.Fields == nil {
		req.Payload.Fields = make(map[string]*structpb.Value)
	}
}

func (req *WebhookRequest) Context() context.Context {
	return req.ctx()
}

// .
func (req *WebhookRequest) Logger() *log.Logger {
	ctx := req.Context()
	ctxLg := ctx.Value(Logger)
	if ctxLg == nil {
		// During testing, it's possible the user defined logger was not
		// flowed down.  This is provided for convenience.
		return log.Default()
	}
	lg, ok := ctxLg.(*log.Logger)
	if !ok {
		return log.Default()
	}
	return lg
}

// Sets (overrides) the PageInfo.ParameterInfos to match the provided map m
func (req *WebhookRequest) setPageFormParameters(m map[string]any) error {
	params := make([]*cx.PageInfo_FormInfo_ParameterInfo, 0)
	for k, v := range m {
		var formParameter cx.PageInfo_FormInfo_ParameterInfo
		pv, err := anyToProto(v)
		if err != nil {
			return err
		}
		formParameter.DisplayName = k
		formParameter.Value = pv
		formParameter.State = cx.PageInfo_FormInfo_ParameterInfo_FILLED
		params = append(params, &formParameter)
	}
	req.PageInfo.FormInfo.ParameterInfo = params
	return nil
}

// Sets (overrides) the SessionInfo.Parameters to match the provided map m
func (req *WebhookRequest) setSessionParameters(m map[string]any) error {
	pm, err := anyToProtoMap(m)
	if err != nil {
		return err
	}
	req.SessionInfo.Parameters = pm
	return nil
}

// Sets (overrides the SessionInfo.Parameters) to match the provided map m
func (req *WebhookRequest) setPayload(m map[string]any) error {
	pm, err := anyToProtoMap(m)
	if err != nil {
		return err
	}
	req.Payload.Fields = pm
	return nil
}

// yaquino@2022-10-11: Dialogflow CX API May include "extra" fields that may
// throw errors and interface with protojson.Unmarshal.  As per the documentation,
// these fields may be ignored. Now also pointing at req.WebhookRequest for unmarshalling..
func WebhookRequestFromReader(rd io.Reader) (*WebhookRequest, error) {
	var req WebhookRequest
	b, err := io.ReadAll(rd)
	if err != nil {
		return nil, err
	}
	unmarshaler := &protojson.UnmarshalOptions{
		AllowPartial:   true,
		DiscardUnknown: true,
	}
	err = unmarshaler.Unmarshal(b, &req.WebhookRequest)
	if err != nil {
		return nil, ErrUnmarshalWrapper("WebhookRequestFromReader", err)
	}
	return &req, nil
}

// yaquino@2022-10-07: Refactored to flow http.Request's context to the
// WebhookRequest instance.
func WebhookRequestFromRequest(r *http.Request) (*WebhookRequest, error) {
	req, err := WebhookRequestFromReader(r.Body)
	if err != nil {
		return nil, err
	}
	return req, nil
}

func (req *WebhookRequest) ReadReader(rd io.Reader) error {
	b, err := io.ReadAll(rd)
	if err != nil {
		return err
	}
	unmarshaler := &protojson.UnmarshalOptions{
		AllowPartial:   true,
		DiscardUnknown: true,
	}
	err = unmarshaler.Unmarshal(b, &req.WebhookRequest)
	if err != nil {
		return err
	}
	return nil
}

func (req *WebhookRequest) ReadRequest(r *http.Request) error {
	return req.ReadReader(r.Body)
}

// Is this the right format??
func (req *WebhookRequest) WriteRequest(w io.Writer) error {
	m := protojson.MarshalOptions{Indent: "\t"}
	b, err := m.Marshal(&req.WebhookRequest)
	if err != nil {
		return err
	}
	r := bytes.NewReader(b)
	_, err = io.Copy(w, r)
	if err != nil {
		return err
	}
	return nil
}

func (req *WebhookRequest) InitializeResponse() *WebhookResponse {
	return req.initializeResponse()
}

func (req *WebhookRequest) initializeResponse() *WebhookResponse {
	resp := NewWebhookResponse()
	return req.copySession(resp)
}

func (req *WebhookRequest) copySession(res *WebhookResponse) *WebhookResponse {
	if res.SessionInfo == nil {
		res.SessionInfo = new(cx.SessionInfo)
	}
	res.SessionInfo.Session = req.SessionInfo.Session
	return res
}

func (req *WebhookRequest) CopyPageInfo(res *WebhookResponse) {
	if req.PageInfo != nil {
		res.PageInfo = req.PageInfo
	}
}

func (req *WebhookRequest) CopySessionInfo(res *WebhookResponse) *WebhookResponse {
	if req.SessionInfo != nil {
		res.SessionInfo = req.SessionInfo
	}
	return res
}

func (req *WebhookRequest) CopyPayload(res *WebhookResponse) *WebhookResponse {
	if req.Payload != nil {
		res.Payload = req.Payload
	}
	return res
}

func (req *WebhookRequest) GetPageFormParameters() map[string]any {
	params := make(map[string]any)

	// Just in case - I don't think we can iterate over a nil map.
	if req.PageInfo == nil {
		return nil
	}
	if req.PageInfo.FormInfo == nil {
		return nil
	}
	if req.PageInfo.FormInfo.ParameterInfo == nil {
		return nil
	}

	for _, paramInfo := range req.PageInfo.FormInfo.ParameterInfo {
		params[paramInfo.DisplayName] = protoToAny(paramInfo.Value)
	}

	return params
}

func (req *WebhookRequest) GetSessionParameters() map[string]any {
	if req.SessionInfo == nil {
		return nil
	}
	if req.SessionInfo.Parameters == nil {
		return nil
	}
	return protoToAnyMap(req.SessionInfo.Parameters)
}

func (req *WebhookRequest) GetSessionParameter(key string) (any, bool) {
	// Check if SessionInfo Parameters is nil.
	if req.SessionInfo == nil {
		return nil, false
	}
	if req.SessionInfo.Parameters == nil {
		return nil, false
	}
	pv, ok := req.SessionInfo.Parameters[key]
	return protoToAny(pv), ok
}

func (req *WebhookRequest) GetPayload() map[string]any {
	if req.Payload == nil {
		return nil
	}
	if req.Payload.Fields == nil {
		return nil
	}
	return protoToAnyMap(req.Payload.Fields)
}

func (req *WebhookRequest) GetPayloadParameter(key string) (any, bool) {
	// Just in case - I don't think we can iterate over a nil map.

	if req.Payload == nil {
		return nil, false
	}
	if req.Payload.Fields == nil {
		return nil, false
	}

	pv, ok := req.Payload.Fields[key]
	return protoToAny(pv), ok
}

// Testing
func NewTestingWebhookRequest(session, payload, pageform map[string]any) (*WebhookRequest, error) {
	return NewWebhookRequest().initTestingWebhookRequest(session, payload, pageform)
}

func (req *WebhookRequest) initTestingWebhookRequest(session, payload, pageform map[string]any) (*WebhookRequest, error) {
	// Provided for testing, normally http.Request.Context is flowed down.
	req.ctx = context.Background

	// All incoming WebhookRequests should have a session.
	req.initSessionInfo()
	req.SessionInfo.Session = uuid.New().String()

	// if session parameters are provided...
	if session != nil {
		err := req.setSessionParameters(session)
		if err != nil {
			return nil, err
		}
	}

	// if payload parameters are provided...
	if payload != nil {
		req.initPayload()
		err := req.setPayload(payload)
		if err != nil {
			return nil, err
		}
	}

	// if pageForm parameters are provided...
	if pageform != nil {
		req.initPageInfo()
		err := req.setPageFormParameters(pageform)
		if err != nil {
			return nil, err
		}
	}
	return req, nil
}

// yaquino: 2022-10-08Review this...!
func (req *WebhookRequest) TestCxHandler(out io.Writer, h HandlerFunc) (*WebhookResponse, error) {
	if req.ctx == nil {
		req.ctx = context.Background
	}
	res := req.initializeResponse()
	err := h(res, req)
	if err != nil {
		return nil, err
	}
	err = res.WriteResponse(out)
	if err != nil {
		return nil, err
	}
	return res, nil
}
<|endoftext|>


<commit_before>package gitmedia

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

const Version = "0.0.1"

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

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

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

	return filepath.Join(path, sha), nil
}

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

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

	return env
}

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

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

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

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

	return recursiveResolveGitDir(wd)
}

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

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

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

	return recursiveResolveGitDir(filepath.Dir(dir))
}

func processDotGitFile(file string) (string, string, error) {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		return "", "", err
	}

	contents := string(data)
	wd, _ := os.Getwd()
	if strings.HasPrefix(contents, gitPtrPrefix) {
		absDir := strings.TrimSpace(strings.Split(contents, gitPtrPrefix)[1])
		return wd, absDir, nil
	}

	return wd, "", nil
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<commit_msg>アーア アアアア アーアー<commit_after>package gitmedia

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

const Version = "0.0.1"

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

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

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

	return filepath.Join(path, sha), nil
}

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

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

	return env
}

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

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

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

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

	return recursiveResolveGitDir(wd)
}

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

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

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

	return recursiveResolveGitDir(filepath.Dir(dir))
}

func processDotGitFile(file string) (string, string, error) {
	f, err := os.Open(file)
	defer f.Close()

	if err != nil {
		return "", "", err
	}

	data := make([]byte, 512)
	n, err := f.Read(data)
	if err != nil {
		return "", "", err
	}

	contents := string(data[0:n])
	wd, _ := os.Getwd()
	if strings.HasPrefix(contents, gitPtrPrefix) {
		absDir := strings.TrimSpace(strings.Split(contents, gitPtrPrefix)[1])
		return wd, absDir, nil
	}

	return wd, "", nil
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<|endoftext|>


<commit_before>package runtime

import (
	"math"
)

// 同时容纳int和引用
type Slot struct {
	number int32
	ref    *Object
}

// 局部变量表
type LocalVars []Slot

func newLocalVars(maxLocals uint) LocalVars {
	if maxLocals > 0 {
		return make([]Slot, maxLocals)
	}
	return nil
}

// 设置整形
func (self LocalVars) SetInt(index uint, value int32) {
	self[index].number = value
}

func (self LocalVars) GetInt(index uint) int32 {
	return self[index].number
}

func (self LocalVars) SetFloat(index uint, value float32) {
	bits := math.Float32bits(value)
	self[index].number = int32(bits)
}

func (self LocalVars) GetFloat(index uint) float32 {
	bits := uint32(self[index].number)
	return math.Float32frombits(bits)
}

// 设置长整形，需要两个int的空间
func (self LocalVars) SetLong(index uint, value int64) {
	self[index].number = int32(value)
	self[index + 1].number = int32(value >> 32)
}

// 得到长整型
func (self LocalVars) GetLong(index uint) int64 {
	low := self[index].number
	high := self[index + 1].number
	return (int64(high) << 32) | int64(low)
}

// 写入64位浮点
func (self LocalVars) SetDouble(index uint, value float64) {
	bits := math.Float64bits(value)
	self.SetLong(index, int64(bits))
}

// 得到浮点数
func (self LocalVars) GetDouble(index uint) float64 {
	bits := uint64(self.GetLong(index))
	return math.Float64frombits(bits)
}

<commit_msg>修复Long类型存储读取的时候，转换错误<commit_after>package runtime

import (
	"math"
)

// 同时容纳int和引用
type Slot struct {
	number int32
	ref    *Object
}

// 局部变量表
type LocalVars []Slot

func newLocalVars(maxLocals uint) LocalVars {
	if maxLocals > 0 {
		return make([]Slot, maxLocals)
	}
	return nil
}

// 设置整形
func (self LocalVars) SetInt(index uint, value int32) {
	self[index].number = value
}

func (self LocalVars) GetInt(index uint) int32 {
	return self[index].number
}

func (self LocalVars) SetFloat(index uint, value float32) {
	bits := math.Float32bits(value)
	self[index].number = int32(bits)
}

func (self LocalVars) GetFloat(index uint) float32 {
	bits := uint32(self[index].number)
	return math.Float32frombits(bits)
}

// 设置长整形，需要两个int的空间
func (self LocalVars) SetLong(index uint, value int64) {
	self[index].number = int32(value)
	self[index + 1].number = int32(value >> 32)
}

// 得到长整型
func (self LocalVars) GetLong(index uint) int64 {
	low := uint32(self[index].number)
	high := uint32(self[index + 1].number)
	return (int64(high) << 32) | int64(low)
}

// 写入64位浮点
func (self LocalVars) SetDouble(index uint, value float64) {
	bits := math.Float64bits(value)
	self.SetLong(index, int64(bits))
}

// 得到浮点数
func (self LocalVars) GetDouble(index uint) float64 {
	bits := uint64(self.GetLong(index))
	return math.Float64frombits(bits)
}

<|endoftext|>


<commit_before>package goutils
import (
 "gopkg.in/cookieo9/resources-go.v2"
 "io/ioutil"
 "strings"
 "log"
)
type Resource struct{}

var DefaultResource *Resource=&Resource{}

func (re *Resource)Load(path string) []byte{
     res,err:=re.Get(path)
     if(err!=nil){
        return []byte{}
      }
     r,_:=res.Open()
     bf,err:=ioutil.ReadAll(r)
     if(err!=nil){
        log.Println("read res[",path,"] failed",err.Error())
      }
     return bf
}

func (re *Resource)Get(path string)(resources.Resource,error){
    path=strings.TrimLeft(path,"/")
    res,err:=resources.Find(path)
    if(err!=nil){
      log.Println("load res[",path,"] failed",err.Error())
      return nil,err
     }
     return res,nil
}
<commit_msg>handle static<commit_after>package goutils
import (
 "gopkg.in/cookieo9/resources-go.v2"
 "io/ioutil"
 "strings"
 "log"
 "mime"
 "time"
 "path/filepath"
 "net/http"
)
type Resource struct{}

var DefaultResource *Resource=&Resource{}

func (re *Resource)Load(path string) []byte{
     res,err:=re.Get(path)
     if(err!=nil){
        return []byte{}
      }
     r,_:=res.Open()
     bf,err:=ioutil.ReadAll(r)
     if(err!=nil){
        log.Println("read res[",path,"] failed",err.Error())
      }
     return bf
}

func (re *Resource)Get(path string)(resources.Resource,error){
    path=strings.TrimLeft(path,"/")
    res,err:=resources.Find(path)
    if(err!=nil){
      log.Println("load res[",path,"] failed",err.Error())
      return nil,err
     }
     return res,nil
}

func (re *Resource)HandleStatic(w http.ResponseWriter,r *http.Request,path string){
    res,err:=re.Get(path)
    if(err!=nil){
        http.NotFound(w,r)
        return;
     }
    finfo,_:=res.Stat()
    modtime:=finfo.ModTime()
    if t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && modtime.Before(t.Add(1*time.Second)) {
           h := w.Header()
           delete(h, "Content-Type")
           delete(h, "Content-Length")
           w.WriteHeader(http.StatusNotModified)
           return
           }
   mimeType:= mime.TypeByExtension(filepath.Ext(path))
   if(mimeType!=""){
       w.Header().Set("Content-Type",mimeType)
     }
    w.Header().Set("Last-Modified",modtime.UTC().Format(http.TimeFormat))
    w.Write(re.Load(path))
}
<|endoftext|>