<commit_before>package croc

import (
	"errors"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"time"

	log "github.com/cihub/seelog"
	"github.com/gorilla/websocket"
	"github.com/schollz/croc/src/relay"
	"github.com/schollz/croc/src/utils"
	"github.com/schollz/peerdiscovery"
)

// Send the file
func (c *Croc) Send(fname, codephrase string) (err error) {
	defer log.Flush()
	log.Debugf("sending %s", fname)
	errChan := make(chan error)

	// normally attempt two connections
	waitingFor := 2

	// use public relay
	if !c.LocalOnly {
		go func() {
			// atttempt to connect to public relay
			errChan <- c.sendReceive(c.Address, c.AddressWebsocketPort, c.AddressTCPPorts, fname, codephrase, true, false)
		}()
	} else {
		waitingFor = 1
	}

	// use local relay
	if !c.NoLocal {
		defer func() {
			log.Debug("sending relay stop signal")
			relay.Stop()
		}()
		go func() {
			// start own relay and connect to it
			go relay.Run(c.RelayWebsocketPort, c.RelayTCPPorts)
			time.Sleep(250 * time.Millisecond) // race condition here, but this should work most of the time :(

			// broadcast for peer discovery
			go func() {
				log.Debug("starting local discovery...")
				discovered, err := peerdiscovery.Discover(peerdiscovery.Settings{
					Limit:     1,
					TimeLimit: 600 * time.Second,
					Delay:     50 * time.Millisecond,
					Payload:   []byte(c.RelayWebsocketPort + "- " + strings.Join(c.RelayTCPPorts, ",")),
				})
				log.Debug(discovered, err)
			}()

			// connect to own relay
			errChan <- c.sendReceive("localhost", c.RelayWebsocketPort, c.RelayTCPPorts, fname, codephrase, true, true)
		}()
	} else {
		waitingFor = 1
	}

	err = <-errChan
	if err == nil || waitingFor == 1 {
		log.Debug("returning")
		return
	}
	log.Debug(err)
	return <-errChan
}

// Receive the file
func (c *Croc) Receive(codephrase string) (err error) {
	log.Debug("receiving")

	// use local relay first
	if !c.NoLocal {
		log.Debug("trying discovering")
		// try to discovery codephrase and server through peer network
		discovered, errDiscover := peerdiscovery.Discover(peerdiscovery.Settings{
			Limit:            1,
			TimeLimit:        300 * time.Millisecond,
			Delay:            50 * time.Millisecond,
			Payload:          []byte("checking"),
			AllowSelf:        true,
			DisableBroadcast: true,
		})
		log.Debug("finished")
		log.Debug(discovered)
		if errDiscover != nil {
			log.Debug(errDiscover)
		}
		if len(discovered) > 0 {
			if discovered[0].Address == utils.LocalIP() {
				discovered[0].Address = "localhost"
			}
			log.Debugf("discovered %s:%s", discovered[0].Address, discovered[0].Payload)
			// see if we can actually connect to it
			timeout := time.Duration(200 * time.Millisecond)
			client := http.Client{
				Timeout: timeout,
			}
			ports := strings.Split(string(discovered[0].Payload), "-")
			if len(ports) != 2 {
				return errors.New("bad payload")
			}
			resp, err := client.Get(fmt.Sprintf("http://%s:%s/", discovered[0].Address, ports[0]))
			if err == nil {
				if resp.StatusCode == http.StatusOK {
					// we connected, so use this
					return c.sendReceive(discovered[0].Address, strings.TrimSpace(ports[0]), strings.Split(strings.TrimSpace(ports[1]), ","), "", codephrase, false, true)
				}
			} else {
				log.Debugf("could not connect: %s", err.Error())
			}
		} else {
			log.Debug("discovered no peers")
		}
	}

	// use public relay
	if !c.LocalOnly {
		log.Debug("using public relay")
		return c.sendReceive(c.Address, c.AddressWebsocketPort, c.AddressTCPPorts, "", codephrase, false, false)
	}

	return errors.New("must use local or public relay")
}

func (c *Croc) sendReceive(address, websocketPort string, tcpPorts []string, fname string, codephrase string, isSender bool, isLocal bool) (err error) {
	defer log.Flush()
	if len(codephrase) < 4 {
		return fmt.Errorf("codephrase is too short")
	}

	// allow interrupts from Ctl+C
	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt)

	done := make(chan error)
	// connect to server
	websocketAddress := ""
	if len(websocketPort) > 0 {
		websocketAddress = fmt.Sprintf("ws://%s:%s/ws?room=%s", address, websocketPort, codephrase[:3])
	} else {
		websocketAddress = fmt.Sprintf("ws://%s/ws?room=%s", address, codephrase[:3])
	}
	log.Debugf("connecting to %s", websocketAddress)
	sock, _, err := websocket.DefaultDialer.Dial(websocketAddress, nil)
	if err != nil {
		log.Error(err)
		return
	}
	defer sock.Close()

	// tell the websockets we are connected
	err = sock.WriteMessage(websocket.BinaryMessage, []byte("connected"))
	if err != nil {
		log.Error(err)
		return err
	}

	if isSender {
		go c.startSender(c.ForceSend, address, tcpPorts, isLocal, done, sock, fname, codephrase, c.UseCompression, c.UseEncryption)
	} else {
		go c.startRecipient(c.ForceSend, address, tcpPorts, isLocal, done, sock, codephrase, c.NoRecipientPrompt, c.Stdout)
	}

	for {
		select {
		case doneError := <-done:
			log.Debug("received done signal")
			if doneError != nil {
				c.StateString = doneError.Error()
				sock.WriteMessage(websocket.TextMessage, []byte("error: "+doneError.Error()))
				time.Sleep(50 * time.Millisecond)
			}
			return doneError
		case <-interrupt:
			if !c.Debug {
				SetDebugLevel("critical")
			}
			log.Debug("interrupt")
			err = sock.WriteMessage(websocket.TextMessage, []byte("error: interrupted by other party"))
			if err != nil {
				return err
			}
			time.Sleep(50 * time.Millisecond)

			// Cleanly close the connection by sending a close message and then
			// waiting (with timeout) for the server to close the connection.
			err := sock.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
			if err != nil {
				log.Debug("write close:", err)
				return nil
			}
			select {
			case <-done:
			case <-time.After(100 * time.Millisecond):
			}
			return nil
		}
	}
}

// Relay will start a relay on the specified port
func (c *Croc) Relay() (err error) {
	return relay.Run(c.RelayWebsocketPort, c.RelayTCPPorts)
}
<commit_msg>customize multicast address<commit_after>package croc

import (
	"errors"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"time"

	log "github.com/cihub/seelog"
	"github.com/gorilla/websocket"
	"github.com/schollz/croc/src/relay"
	"github.com/schollz/croc/src/utils"
	"github.com/schollz/peerdiscovery"
)

// Send the file
func (c *Croc) Send(fname, codephrase string) (err error) {
	defer log.Flush()
	log.Debugf("sending %s", fname)
	errChan := make(chan error)

	// normally attempt two connections
	waitingFor := 2

	// use public relay
	if !c.LocalOnly {
		go func() {
			// atttempt to connect to public relay
			errChan <- c.sendReceive(c.Address, c.AddressWebsocketPort, c.AddressTCPPorts, fname, codephrase, true, false)
		}()
	} else {
		waitingFor = 1
	}

	// use local relay
	if !c.NoLocal {
		defer func() {
			log.Debug("sending relay stop signal")
			relay.Stop()
		}()
		go func() {
			// start own relay and connect to it
			go relay.Run(c.RelayWebsocketPort, c.RelayTCPPorts)
			time.Sleep(250 * time.Millisecond) // race condition here, but this should work most of the time :(

			// broadcast for peer discovery
			go func() {
				log.Debug("starting local discovery...")
				discovered, err := peerdiscovery.Discover(peerdiscovery.Settings{
					Limit:            1,
					TimeLimit:        600 * time.Second,
					Delay:            50 * time.Millisecond,
					Payload:          []byte(c.RelayWebsocketPort + "- " + strings.Join(c.RelayTCPPorts, ",")),
					MulticastAddress: "239.255.255.252",
				})
				log.Debug(discovered, err)
			}()

			// connect to own relay
			errChan <- c.sendReceive("localhost", c.RelayWebsocketPort, c.RelayTCPPorts, fname, codephrase, true, true)
		}()
	} else {
		waitingFor = 1
	}

	err = <-errChan
	if err == nil || waitingFor == 1 {
		log.Debug("returning")
		return
	}
	log.Debug(err)
	return <-errChan
}

// Receive the file
func (c *Croc) Receive(codephrase string) (err error) {
	defer log.Flush()
	log.Debug("receiving")

	// use local relay first
	if !c.NoLocal {
		log.Debug("trying to discover")
		// try to discovery codephrase and server through peer network
		discovered, errDiscover := peerdiscovery.Discover(peerdiscovery.Settings{
			Limit:            1,
			TimeLimit:        300 * time.Millisecond,
			Delay:            50 * time.Millisecond,
			Payload:          []byte("checking"),
			AllowSelf:        true,
			DisableBroadcast: true,
			MulticastAddress: "239.255.255.252",
		})
		log.Debug("finished")
		log.Debug(discovered)
		if errDiscover != nil {
			log.Debug(errDiscover)
		}
		if len(discovered) > 0 {
			if discovered[0].Address == utils.LocalIP() {
				discovered[0].Address = "localhost"
			}
			log.Debugf("discovered %s:%s", discovered[0].Address, discovered[0].Payload)
			// see if we can actually connect to it
			timeout := time.Duration(200 * time.Millisecond)
			client := http.Client{
				Timeout: timeout,
			}
			ports := strings.Split(string(discovered[0].Payload), "-")
			if len(ports) != 2 {
				return errors.New("bad payload")
			}
			resp, err := client.Get(fmt.Sprintf("http://%s:%s/", discovered[0].Address, ports[0]))
			if err == nil {
				if resp.StatusCode == http.StatusOK {
					// we connected, so use this
					return c.sendReceive(discovered[0].Address, strings.TrimSpace(ports[0]), strings.Split(strings.TrimSpace(ports[1]), ","), "", codephrase, false, true)
				}
			} else {
				log.Debugf("could not connect: %s", err.Error())
			}
		} else {
			log.Debug("discovered no peers")
		}
	}

	// use public relay
	if !c.LocalOnly {
		log.Debug("using public relay")
		return c.sendReceive(c.Address, c.AddressWebsocketPort, c.AddressTCPPorts, "", codephrase, false, false)
	}

	return errors.New("must use local or public relay")
}

func (c *Croc) sendReceive(address, websocketPort string, tcpPorts []string, fname string, codephrase string, isSender bool, isLocal bool) (err error) {
	defer log.Flush()
	if len(codephrase) < 4 {
		return fmt.Errorf("codephrase is too short")
	}

	// allow interrupts from Ctl+C
	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt)

	done := make(chan error)
	// connect to server
	websocketAddress := ""
	if len(websocketPort) > 0 {
		websocketAddress = fmt.Sprintf("ws://%s:%s/ws?room=%s", address, websocketPort, codephrase[:3])
	} else {
		websocketAddress = fmt.Sprintf("ws://%s/ws?room=%s", address, codephrase[:3])
	}
	log.Debugf("connecting to %s", websocketAddress)
	sock, _, err := websocket.DefaultDialer.Dial(websocketAddress, nil)
	if err != nil {
		log.Error(err)
		return
	}
	defer sock.Close()

	// tell the websockets we are connected
	err = sock.WriteMessage(websocket.BinaryMessage, []byte("connected"))
	if err != nil {
		log.Error(err)
		return err
	}

	if isSender {
		go c.startSender(c.ForceSend, address, tcpPorts, isLocal, done, sock, fname, codephrase, c.UseCompression, c.UseEncryption)
	} else {
		go c.startRecipient(c.ForceSend, address, tcpPorts, isLocal, done, sock, codephrase, c.NoRecipientPrompt, c.Stdout)
	}

	for {
		select {
		case doneError := <-done:
			log.Debug("received done signal")
			if doneError != nil {
				c.StateString = doneError.Error()
				sock.WriteMessage(websocket.TextMessage, []byte("error: "+doneError.Error()))
				time.Sleep(50 * time.Millisecond)
			}
			return doneError
		case <-interrupt:
			if !c.Debug {
				SetDebugLevel("critical")
			}
			log.Debug("interrupt")
			err = sock.WriteMessage(websocket.TextMessage, []byte("error: interrupted by other party"))
			if err != nil {
				return err
			}
			time.Sleep(50 * time.Millisecond)

			// Cleanly close the connection by sending a close message and then
			// waiting (with timeout) for the server to close the connection.
			err := sock.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
			if err != nil {
				log.Debug("write close:", err)
				return nil
			}
			select {
			case <-done:
			case <-time.After(100 * time.Millisecond):
			}
			return nil
		}
	}
}

// Relay will start a relay on the specified port
func (c *Croc) Relay() (err error) {
	return relay.Run(c.RelayWebsocketPort, c.RelayTCPPorts)
}
<|endoftext|>


<commit_before>package service

import (
	"encoding/json"
	"fmt"
	"runtime/debug"
	"time"
)

const (
	HEARTBEAT_DURATION = 5
)

func Register(service string, host *Host, stop chan bool) error {
	if len(host.Name) == 0 {
		host.Name = hostname
	}

	key := fmt.Sprintf("/services/%s/%s", service, host.Name)
	hostJson, _ := json.Marshal(&host)

	value := string(hostJson)
	err := createOrUpdate(key, value)
	if err != nil {
		return err
	}

	go func() {
		defer func() {
			if r := recover(); r != nil {
				logger.Printf("Error when updating %v %v: %v\n", service, host, r)
				debug.PrintStack()
			}
		}()

		ticker := time.NewTicker((HEARTBEAT_DURATION - 1) * time.Second)
		for {
			select {
			case <-stop:
				ticker.Stop()
				return
			case <-ticker.C:
				err := updateOrCreate(key, value)
				if err != nil {
					panic(err)
				}
			}
		}
	}()

	return nil
}

func createOrUpdate(k, v string) error {
	_, err := client.Create(k, v, HEARTBEAT_DURATION)
	if err != nil {
		if IsKeyAlreadyExistError(err) {
			_, err = client.Update(k, v, HEARTBEAT_DURATION)
			if err != nil {
				return err
			}
		} else {
			return err
		}
	}
	return nil
}

func updateOrCreate(k, v string) error {
	_, err := client.Update(k, v, HEARTBEAT_DURATION)
	if err != nil {
		if IsKeyAlreadyExistError(err) {
			_, err = client.Create(k, v, HEARTBEAT_DURATION)
			if err != nil {
				return err
			}
		} else {
			return err
		}
	}
	return nil
}
<commit_msg>Fix error variables name<commit_after>package service

import (
	"encoding/json"
	"fmt"
	"runtime/debug"
	"time"
)

const (
	HEARTBEAT_DURATION = 5
)

func Register(service string, host *Host, stop chan bool) error {
	if len(host.Name) == 0 {
		host.Name = hostname
	}

	key := fmt.Sprintf("/services/%s/%s", service, host.Name)
	hostJson, _ := json.Marshal(&host)

	value := string(hostJson)
	err := createOrUpdate(key, value)
	if err != nil {
		return err
	}

	go func() {
		defer func() {
			if r := recover(); r != nil {
				logger.Printf("Error when updating %v %v: %v\n", service, host, r)
				debug.PrintStack()
			}
		}()

		ticker := time.NewTicker((HEARTBEAT_DURATION - 1) * time.Second)
		for {
			select {
			case <-stop:
				ticker.Stop()
				return
			case <-ticker.C:
				err := updateOrCreate(key, value)
				if err != nil {
					panic(err)
				}
			}
		}
	}()

	return nil
}

func createOrUpdate(k, v string) error {
	_, errCreate := client.Create(k, v, HEARTBEAT_DURATION)
	if errCreate != nil {
		if IsKeyAlreadyExistError(errCreate) {
			_, errUpdate := client.Update(k, v, HEARTBEAT_DURATION)
			if errUpdate != nil {
				return errUpdate
			}
		} else {
			return errCreate
		}
	}
	return nil
}

func updateOrCreate(k, v string) error {
	_, errUpdate := client.Update(k, v, HEARTBEAT_DURATION)
	if errUpdate != nil {
		if IsKeyNotFoundError(errUpdate) {
			_, errCreate := client.Create(k, v, HEARTBEAT_DURATION)
			if errCreate != nil {
				return errCreate
			}
		} else {
			return errUpdate
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package check

import (
	"fmt"

	"github.com/foomo/petze/config"
)

func checkMinMaxCount(expect config.Expect, length int64) (ok bool, info string) {
	switch true {
	case expect.Min != nil:
		ok = length >= *expect.Min
		if !ok {
			info = fmt.Sprint("min actual: ", length, " < expected: ", *expect.Min)
		}
		return
	case expect.Max != nil:
		ok = length <= *expect.Max
		if !ok {
			info = fmt.Sprint("max actual: ", length, " > expected: ", *expect.Max)
		}
		return
	case expect.Count != nil:
		ok = length == *expect.Count
		if !ok {
			info = fmt.Sprint("count actual: ", length, " != expected: ", *expect.Count)
		}
		return
	default:
		panic("this is a programming error - check your usage of minMaxCount")
	}
}<commit_msg>added checkExpectStringEquals<commit_after>package check

import (
	"fmt"

	"github.com/foomo/petze/config"
)

func checkExpectStringEquals(expect config.Expect, expected, actual string) (ok bool, info string) {
	ok = expected == actual
	if !ok {
		info = "actual: \"" + actual + "\" != expected: \"" + expected + "\""
		return
	}
	return
}

func checkMinMaxCount(expect config.Expect, length int64) (ok bool, info string) {
	switch true {
	case expect.Min != nil:
		ok = length >= *expect.Min
		if !ok {
			info = fmt.Sprint("min actual: ", length, " < expected: ", *expect.Min)
		}
		return
	case expect.Max != nil:
		ok = length <= *expect.Max
		if !ok {
			info = fmt.Sprint("max actual: ", length, " > expected: ", *expect.Max)
		}
		return
	case expect.Count != nil:
		ok = length == *expect.Count
		if !ok {
			info = fmt.Sprint("count actual: ", length, " != expected: ", *expect.Count)
		}
		return
	default:
		panic("this is a programming error - check your usage of minMaxCount")
	}
}
<|endoftext|>


<commit_before>package reflect

import (
	"fmt"

	. "github.com/anaminus/rbxmk"
	"github.com/anaminus/rbxmk/rtypes"
	"github.com/robloxapi/types"
	"github.com/yuin/gopher-lua"
)

// pushPropertyTo behaves like PushVariantTo, except that exprims types are
// reflected as userdata.
func pushPropertyTo(s State, v types.Value) (lv lua.LValue, err error) {
	switch v.(type) {
	case types.Int,
		types.Int64,
		types.Float,
		types.Token,
		types.BinaryString,
		types.ProtectedString,
		types.Content,
		types.SharedString:
	default:
		return PushVariantTo(s, v)
	}
	typ := s.Type(v.Type())
	if typ.Name == "" {
		return nil, fmt.Errorf("unknown type %q", string(v.Type()))
	}
	if typ.PushTo == nil {
		return nil, fmt.Errorf("unable to cast %s to Variant", typ.Name)
	}
	u := s.L.NewUserData()
	u.Value = v
	s.L.SetMetatable(u, s.L.GetTypeMetatable(typ.Name))
	return u, nil
}

func Instance() Type {
	return Type{
		Name:     "Instance",
		PushTo:   PushTypeTo,
		PullFrom: PullTypeFrom,
		Metatable: Metatable{
			"__tostring": func(s State) int {
				s.L.Push(lua.LString(s.Pull(1, "Instance").(*rtypes.Instance).String()))
				return 1
			},
			"__eq": func(s State) int {
				op := s.Pull(2, "Instance").(*rtypes.Instance)
				return s.Push(types.Bool(s.Pull(1, "Instance").(*rtypes.Instance) == op))
			},
			"__index": func(s State) int {
				inst := s.Pull(1, "Instance").(*rtypes.Instance)
				name := string(s.Pull(2, "string").(types.String))

				// Try GetService.
				if inst.IsDataModel() && name == "GetService" {
					s.L.Push(s.L.NewFunction(func(l *lua.LState) int {
						u := l.CheckUserData(1)
						if u.Metatable != l.GetTypeMetatable("Instance") {
							TypeError(l, 1, "Instance")
							return 0
						}
						inst, ok := u.Value.(*rtypes.Instance)
						if !ok {
							TypeError(l, 1, "Instance")
							return 0
						}
						s := State{World: s.World, L: l}
						className := string(s.Pull(2, "string").(types.String))
						if desc := s.Desc(inst); desc != nil {
							classDesc := desc.Classes[className]
							if classDesc == nil || !classDesc.GetTag("Service") {
								s.L.RaiseError("%q is not a valid service", className)
							}
						}
						service := inst.FindFirstChildOfClass(className, false)
						if service == nil {
							service = rtypes.NewInstance(className)
							service.IsService = true
							service.SetName(className)
							service.SetParent(inst)
						}
						return s.Push(service)
					}))
					return 1
				}

				// Try property.
				value := inst.Get(name)
				if value == nil {
					// s.L.RaiseError("%s is not a valid member", name)
					return s.Push(rtypes.Nil)
				}
				lv, err := pushPropertyTo(s, value)
				if err != nil {
					s.L.RaiseError(err.Error())
					return 0
				}
				s.L.Push(lv)
				return 1
			},
			"__newindex": func(s State) int {
				inst := s.Pull(1, "Instance").(*rtypes.Instance)
				name := string(s.Pull(2, "string").(types.String))

				// Try GetService.
				if inst.IsDataModel() && name == "GetService" {
					s.L.RaiseError("%s cannot be assigned to", name)
					return 0
				}

				// Try property.
				value := PullVariant(s, 3)
				prop, ok := value.(types.PropValue)
				if !ok {
					s.L.RaiseError("cannot assign %s as property", value.Type())
					return 0
				}
				inst.Set(name, prop)
				return 0
			},
		},
		Members: Members{
			"ClassName": Member{
				Get: func(s State, v types.Value) int {
					return s.Push(types.String(v.(*rtypes.Instance).ClassName))
				},
				// Allowed to be set for convenience.
				Set: func(s State, v types.Value) {
					inst := v.(*rtypes.Instance)
					if inst.IsDataModel() {
						s.L.RaiseError("%s cannot be assigned to", "ClassName")
						return
					}
					inst.ClassName = string(s.Pull(3, "string").(types.String))
				},
			},
			"Name": Member{
				Get: func(s State, v types.Value) int {
					return s.Push(types.String(v.(*rtypes.Instance).Name()))
				},
				Set: func(s State, v types.Value) {
					v.(*rtypes.Instance).SetName(string(s.Pull(3, "string").(types.String)))
				},
			},
			"Parent": Member{
				Get: func(s State, v types.Value) int {
					if parent := v.(*rtypes.Instance).Parent(); parent != nil {
						return s.Push(parent)
					}
					return s.Push(rtypes.Nil)
				},
				Set: func(s State, v types.Value) {
					var err error
					switch parent := s.PullAnyOf(3, "Instance", "nil").(type) {
					case *rtypes.Instance:
						err = v.(*rtypes.Instance).SetParent(parent)
					case nil:
						err = v.(*rtypes.Instance).SetParent(nil)
					}
					if err != nil {
						s.L.RaiseError(err.Error())
					}
				},
			},
			"ClearAllChildren": Member{Method: true, Get: func(s State, v types.Value) int {
				v.(*rtypes.Instance).RemoveAll()
				return 0
			}},
			"Clone": Member{Method: true, Get: func(s State, v types.Value) int {
				return s.Push(v.(*rtypes.Instance).Clone())
			}},
			"Destroy": Member{Method: true, Get: func(s State, v types.Value) int {
				v.(*rtypes.Instance).SetParent(nil)
				return 0
			}},
			"FindFirstAncestor": Member{Method: true, Get: func(s State, v types.Value) int {
				name := string(s.Pull(2, "string").(types.String))
				if ancestor := v.(*rtypes.Instance).FindFirstAncestorOfClass(name); ancestor != nil {
					return s.Push(ancestor)
				}
				return s.Push(rtypes.Nil)
			}},
			"FindFirstAncestorOfClass": Member{Method: true, Get: func(s State, v types.Value) int {
				className := string(s.Pull(2, "string").(types.String))
				if ancestor := v.(*rtypes.Instance).FindFirstAncestorOfClass(className); ancestor != nil {
					return s.Push(ancestor)
				}
				return s.Push(rtypes.Nil)
			}},
			"FindFirstChild": Member{Method: true, Get: func(s State, v types.Value) int {
				name := string(s.Pull(2, "string").(types.String))
				recurse := bool(s.PullOpt(3, "bool", types.False).(types.Bool))
				if child := v.(*rtypes.Instance).FindFirstChild(name, recurse); child != nil {
					return s.Push(child)
				}
				return s.Push(rtypes.Nil)
			}},
			"FindFirstChildOfClass": Member{Method: true, Get: func(s State, v types.Value) int {
				className := string(s.Pull(2, "string").(types.String))
				recurse := bool(s.PullOpt(3, "bool", types.False).(types.Bool))
				if child := v.(*rtypes.Instance).FindFirstChildOfClass(className, recurse); child != nil {
					return s.Push(child)
				}
				return s.Push(rtypes.Nil)
			}},
			"GetChildren": Member{Method: true, Get: func(s State, v types.Value) int {
				t := v.(*rtypes.Instance).Children()
				return s.Push(rtypes.Instances(t))
			}},
			"GetDescendants": Member{Method: true, Get: func(s State, v types.Value) int {
				return s.Push(rtypes.Instances(v.(*rtypes.Instance).Descendants()))
			}},
			"GetFullName": Member{Method: true, Get: func(s State, v types.Value) int {
				return s.Push(types.String(v.(*rtypes.Instance).GetFullName()))
			}},
			"IsAncestorOf": Member{Method: true, Get: func(s State, v types.Value) int {
				descendant := s.Pull(2, "Instance").(*rtypes.Instance)
				return s.Push(types.Bool(v.(*rtypes.Instance).IsAncestorOf(descendant)))
			}},
			"IsDescendantOf": Member{Method: true, Get: func(s State, v types.Value) int {
				ancestor := s.Pull(2, "Instance").(*rtypes.Instance)
				return s.Push(types.Bool(v.(*rtypes.Instance).IsDescendantOf(ancestor)))
			}},
		},
		Constructors: Constructors{
			"new": func(s State) int {
				className := string(s.Pull(1, "string").(types.String))
				inst := rtypes.NewInstance(className)
				return s.Push(inst)
			},
		},
		Environment: func(s State) {
			t := s.L.CreateTable(0, 1)
			t.RawSetString("new", s.L.NewFunction(func(l *lua.LState) int {
				dataModel := rtypes.NewDataModel()
				return s.Push(dataModel)
			}))
			s.L.SetGlobal("DataModel", t)
		},
	}
}
<commit_msg>Use descriptors to enforce property types.<commit_after>package reflect

import (
	"fmt"

	. "github.com/anaminus/rbxmk"
	"github.com/anaminus/rbxmk/rtypes"
	"github.com/robloxapi/rbxdump"
	"github.com/robloxapi/types"
	"github.com/yuin/gopher-lua"
)

// pushPropertyTo behaves like PushVariantTo, except that exprims types are
// reflected as userdata.
func pushPropertyTo(s State, v types.Value) (lv lua.LValue, err error) {
	switch v.(type) {
	case types.Numberlike:
	case types.Intlike:
	case types.Stringlike:
	default:
		return PushVariantTo(s, v)
	}
	typ := s.Type(v.Type())
	if typ.Name == "" {
		return nil, fmt.Errorf("unknown type %q", string(v.Type()))
	}
	if typ.PushTo == nil {
		return nil, fmt.Errorf("unable to cast %s to Variant", typ.Name)
	}
	u := s.L.NewUserData()
	u.Value = v
	s.L.SetMetatable(u, s.L.GetTypeMetatable(typ.Name))
	return u, nil
}

// convertType tries to convert v to t.
func convertType(s State, t string, v types.Value) (nv types.Value, ok bool) {
	if v.Type() == t {
		return v, true
	}
	if s.Type(t).Name == "" {
		return v, false
	}
	switch t {
	case "int":
		switch v := v.(type) {
		case types.Intlike:
			return types.Int(v.Intlike()), true
		case types.Numberlike:
			return types.Int(v.Numberlike()), true
		}
	case "int64":
		switch v := v.(type) {
		case types.Intlike:
			return types.Int64(v.Intlike()), true
		case types.Numberlike:
			return types.Int64(v.Numberlike()), true
		}
	case "float":
		switch v := v.(type) {
		case types.Numberlike:
			return types.Float(v.Numberlike()), true
		case types.Intlike:
			return types.Float(v.Intlike()), true
		}
	case "double":
		switch v := v.(type) {
		case types.Numberlike:
			return types.Double(v.Numberlike()), true
		case types.Intlike:
			return types.Double(v.Intlike()), true
		}
	case "string":
		if v, ok := v.(types.Stringlike); ok {
			return types.String(v.Stringlike()), true
		}
	case "BinaryString":
		if v, ok := v.(types.Stringlike); ok {
			return types.BinaryString(v.Stringlike()), true
		}
	case "ProtectedString":
		if v, ok := v.(types.Stringlike); ok {
			return types.ProtectedString(v.Stringlike()), true
		}
	case "Content":
		if v, ok := v.(types.Stringlike); ok {
			return types.Content(v.Stringlike()), true
		}
	case "SharedString":
		if v, ok := v.(types.Stringlike); ok {
			return types.SharedString(v.Stringlike()), true
		}
	case "Color3":
		if v, ok := v.(rtypes.Color3uint8); ok {
			return types.Color3(v), true
		}
	case "Color3uint8":
		if v, ok := v.(types.Color3); ok {
			return rtypes.Color3uint8(v), true
		}
	}
	return v, false
}

// getPropDesc gets a property descriptor from a class, or any class it inherits
// from.
func getPropDesc(root *rbxdump.Root, class *rbxdump.Class, name string) (prop *rbxdump.Property) {
	for class != nil {
		prop, _ = class.Members[name].(*rbxdump.Property)
		if prop != nil {
			return prop
		}
		class = root.Classes[class.Superclass]
	}
	return nil
}

func Instance() Type {
	return Type{
		Name:     "Instance",
		PushTo:   PushTypeTo,
		PullFrom: PullTypeFrom,
		Metatable: Metatable{
			"__tostring": func(s State) int {
				s.L.Push(lua.LString(s.Pull(1, "Instance").(*rtypes.Instance).String()))
				return 1
			},
			"__eq": func(s State) int {
				op := s.Pull(2, "Instance").(*rtypes.Instance)
				return s.Push(types.Bool(s.Pull(1, "Instance").(*rtypes.Instance) == op))
			},
			"__index": func(s State) int {
				inst := s.Pull(1, "Instance").(*rtypes.Instance)
				name := string(s.Pull(2, "string").(types.String))
				desc := s.Desc(inst)
				var classDesc *rbxdump.Class
				if desc != nil {
					classDesc = desc.Classes[inst.ClassName]
				}

				// Try GetService.
				if inst.IsDataModel() && name == "GetService" {
					s.L.Push(s.L.NewFunction(func(l *lua.LState) int {
						u := l.CheckUserData(1)
						if u.Metatable != l.GetTypeMetatable("Instance") {
							TypeError(l, 1, "Instance")
							return 0
						}
						inst, ok := u.Value.(*rtypes.Instance)
						if !ok {
							TypeError(l, 1, "Instance")
							return 0
						}
						s := State{World: s.World, L: l}
						className := string(s.Pull(2, "string").(types.String))
						if desc != nil {
							classDesc := desc.Classes[className]
							if classDesc == nil || !classDesc.GetTag("Service") {
								s.L.RaiseError("%q is not a valid service", className)
							}
						}
						service := inst.FindFirstChildOfClass(className, false)
						if service == nil {
							service = rtypes.NewInstance(className)
							service.IsService = true
							service.SetName(className)
							service.SetParent(inst)
						}
						return s.Push(service)
					}))
					return 1
				}

				// Try property.
				var lv lua.LValue
				var err error
				value := inst.Get(name)
				if classDesc != nil {
					propDesc := getPropDesc(desc, classDesc, name)
					if propDesc == nil {
						s.L.RaiseError("%s is not a valid member", name)
						return 0
					}
					if value == nil {
						s.L.RaiseError("property %s not initialized", name)
						return 0
					}
					switch propDesc.ValueType.Category {
					case "Class":
						inst, ok := value.(*rtypes.Instance)
						if !ok {
							s.L.RaiseError("stored value type %s is not an instance", value.Type())
							return 0
						}
						cdesc := desc.Classes[propDesc.ValueType.Name]
						if cdesc == nil {
							s.L.RaiseError(
								"value type of property descriptor %s.%s has unknown class type %q",
								classDesc.Name,
								propDesc.Name,
								propDesc.ValueType.Name,
							)
							return 0
						}
						if inst.ClassName != cdesc.Name {
							s.L.RaiseError("instance of class %s expected, got %s", cdesc.Name, inst.ClassName)
							return 0
						}
						return s.Push(inst)
					case "Enum":
						token, ok := value.(types.Token)
						if !ok {
							s.L.RaiseError("stored value type %s is not a token", value.Type())
							return 0
						}
						enumDesc := desc.Enums[propDesc.ValueType.Name]
						if enumDesc == nil {
							s.L.RaiseError(
								"value type of property descriptor %s.%s has unknown enum type %q",
								classDesc.Name,
								propDesc.Name,
								propDesc.ValueType.Name,
							)
							return 0
						}
						for _, item := range enumDesc.Items {
							if item.Value == int(token) {
								goto getEnumToken
							}
						}
						s.L.RaiseError("unknown value (%d) for enum %s", token, enumDesc.Name)
						return 0
					getEnumToken:
						// TODO: Push as enum item.
						break
					default:
						if a, b := value.Type(), propDesc.ValueType.Name; a != b {
							s.L.RaiseError("stored value type %s does not match property type %s", a, b)
						}
					}
					// Push without converting exprims.
					lv, err = PushVariantTo(s, value)
				} else {
					if value == nil {
						// Fallback to nil.
						return s.Push(rtypes.Nil)
					}
					lv, err = pushPropertyTo(s, value)
				}
				if err != nil {
					s.L.RaiseError(err.Error())
					return 0
				}
				s.L.Push(lv)
				return 1
			},
			"__newindex": func(s State) int {
				inst := s.Pull(1, "Instance").(*rtypes.Instance)
				name := string(s.Pull(2, "string").(types.String))

				// Try GetService.
				if inst.IsDataModel() && name == "GetService" {
					s.L.RaiseError("%s cannot be assigned to", name)
					return 0
				}

				// Try property.
				value := PullVariant(s, 3)
				desc := s.Desc(inst)
				if desc == nil {
					goto nodesc
				}
				if classDesc := desc.Classes[inst.ClassName]; classDesc != nil {
					propDesc := getPropDesc(desc, classDesc, name)
					if propDesc == nil {
						s.L.RaiseError("%s is not a valid member", name)
						return 0
					}
					switch propDesc.ValueType.Category {
					case "Class":
						inst, ok := value.(*rtypes.Instance)
						if !ok {
							s.L.RaiseError("Instance expected, got %s", value.Type())
							return 0
						}
						cdesc := desc.Classes[propDesc.ValueType.Name]
						if cdesc == nil {
							s.L.RaiseError(
								"value type of property descriptor %s.%s has unknown class type %q",
								classDesc.Name,
								propDesc.Name,
								propDesc.ValueType.Name,
							)
							return 0
						}
						if inst.ClassName != cdesc.Name {
							s.L.RaiseError("instance of class %s expected, got %s", cdesc.Name, inst.ClassName)
							return 0
						}
						inst.Set(name, inst)
						return 0
					case "Enum":
						enumDesc := desc.Enums[propDesc.ValueType.Name]
						if enumDesc == nil {
							s.L.RaiseError(
								"value type of property descriptor %s.%s has unknown enum type %q",
								classDesc.Name,
								propDesc.Name,
								propDesc.ValueType.Name,
							)
							return 0
						}
					setEnum:
						switch value := value.(type) {
						case types.Token:
							for _, item := range enumDesc.Items {
								if item.Value == int(value) {
									// TODO: Push as enum item.
									break setEnum
								}
							}
							s.L.RaiseError("unknown value (%d) for enum %s", value, enumDesc.Name)
							return 0
						case types.Intlike:
							v := int(value.Intlike())
							for _, item := range enumDesc.Items {
								if item.Value == v {
									// TODO: Push as enum item.
									break setEnum
								}
							}
							s.L.RaiseError("unknown value (%d) for enum %s", value, enumDesc.Name)
							return 0
						case types.Numberlike:
							v := int(value.Numberlike())
							for _, item := range enumDesc.Items {
								if item.Value == v {
									// TODO: Push as enum item.
									break setEnum
								}
							}
							s.L.RaiseError("unknown value (%d) for enum %s", v, enumDesc.Name)
							return 0
						case types.Stringlike:
							v := value.Stringlike()
							for _, item := range enumDesc.Items {
								if item.Name == v {
									// TODO: Push as enum item.
									break setEnum
								}
							}
							s.L.RaiseError("unknown value (%q) for enum %s", v, enumDesc.Name)
							return 0
						}
					default:
						var ok bool
						value, ok = convertType(s, propDesc.ValueType.Name, value)
						if !ok {
							s.L.RaiseError("%s expected, got %s", propDesc.ValueType.Name, value.Type())
							return 0
						}
					}
				}

			nodesc:
				prop, ok := value.(types.PropValue)
				if !ok {
					s.L.RaiseError("cannot assign %s as property", value.Type())
					return 0
				}
				inst.Set(name, prop)
				return 0
			},
		},
		Members: Members{
			"ClassName": Member{
				Get: func(s State, v types.Value) int {
					return s.Push(types.String(v.(*rtypes.Instance).ClassName))
				},
				// Allowed to be set for convenience.
				Set: func(s State, v types.Value) {
					inst := v.(*rtypes.Instance)
					if inst.IsDataModel() {
						s.L.RaiseError("%s cannot be assigned to", "ClassName")
						return
					}
					inst.ClassName = string(s.Pull(3, "string").(types.String))
				},
			},
			"Name": Member{
				Get: func(s State, v types.Value) int {
					return s.Push(types.String(v.(*rtypes.Instance).Name()))
				},
				Set: func(s State, v types.Value) {
					v.(*rtypes.Instance).SetName(string(s.Pull(3, "string").(types.String)))
				},
			},
			"Parent": Member{
				Get: func(s State, v types.Value) int {
					if parent := v.(*rtypes.Instance).Parent(); parent != nil {
						return s.Push(parent)
					}
					return s.Push(rtypes.Nil)
				},
				Set: func(s State, v types.Value) {
					var err error
					switch parent := s.PullAnyOf(3, "Instance", "nil").(type) {
					case *rtypes.Instance:
						err = v.(*rtypes.Instance).SetParent(parent)
					case nil:
						err = v.(*rtypes.Instance).SetParent(nil)
					}
					if err != nil {
						s.L.RaiseError(err.Error())
					}
				},
			},
			"ClearAllChildren": Member{Method: true, Get: func(s State, v types.Value) int {
				v.(*rtypes.Instance).RemoveAll()
				return 0
			}},
			"Clone": Member{Method: true, Get: func(s State, v types.Value) int {
				return s.Push(v.(*rtypes.Instance).Clone())
			}},
			"Destroy": Member{Method: true, Get: func(s State, v types.Value) int {
				v.(*rtypes.Instance).SetParent(nil)
				return 0
			}},
			"FindFirstAncestor": Member{Method: true, Get: func(s State, v types.Value) int {
				name := string(s.Pull(2, "string").(types.String))
				if ancestor := v.(*rtypes.Instance).FindFirstAncestorOfClass(name); ancestor != nil {
					return s.Push(ancestor)
				}
				return s.Push(rtypes.Nil)
			}},
			"FindFirstAncestorOfClass": Member{Method: true, Get: func(s State, v types.Value) int {
				className := string(s.Pull(2, "string").(types.String))
				if ancestor := v.(*rtypes.Instance).FindFirstAncestorOfClass(className); ancestor != nil {
					return s.Push(ancestor)
				}
				return s.Push(rtypes.Nil)
			}},
			"FindFirstChild": Member{Method: true, Get: func(s State, v types.Value) int {
				name := string(s.Pull(2, "string").(types.String))
				recurse := bool(s.PullOpt(3, "bool", types.False).(types.Bool))
				if child := v.(*rtypes.Instance).FindFirstChild(name, recurse); child != nil {
					return s.Push(child)
				}
				return s.Push(rtypes.Nil)
			}},
			"FindFirstChildOfClass": Member{Method: true, Get: func(s State, v types.Value) int {
				className := string(s.Pull(2, "string").(types.String))
				recurse := bool(s.PullOpt(3, "bool", types.False).(types.Bool))
				if child := v.(*rtypes.Instance).FindFirstChildOfClass(className, recurse); child != nil {
					return s.Push(child)
				}
				return s.Push(rtypes.Nil)
			}},
			"GetChildren": Member{Method: true, Get: func(s State, v types.Value) int {
				t := v.(*rtypes.Instance).Children()
				return s.Push(rtypes.Instances(t))
			}},
			"GetDescendants": Member{Method: true, Get: func(s State, v types.Value) int {
				return s.Push(rtypes.Instances(v.(*rtypes.Instance).Descendants()))
			}},
			"GetFullName": Member{Method: true, Get: func(s State, v types.Value) int {
				return s.Push(types.String(v.(*rtypes.Instance).GetFullName()))
			}},
			"IsAncestorOf": Member{Method: true, Get: func(s State, v types.Value) int {
				descendant := s.Pull(2, "Instance").(*rtypes.Instance)
				return s.Push(types.Bool(v.(*rtypes.Instance).IsAncestorOf(descendant)))
			}},
			"IsDescendantOf": Member{Method: true, Get: func(s State, v types.Value) int {
				ancestor := s.Pull(2, "Instance").(*rtypes.Instance)
				return s.Push(types.Bool(v.(*rtypes.Instance).IsDescendantOf(ancestor)))
			}},
		},
		Constructors: Constructors{
			"new": func(s State) int {
				className := string(s.Pull(1, "string").(types.String))
				inst := rtypes.NewInstance(className)
				return s.Push(inst)
			},
		},
		Environment: func(s State) {
			t := s.L.CreateTable(0, 1)
			t.RawSetString("new", s.L.NewFunction(func(l *lua.LState) int {
				dataModel := rtypes.NewDataModel()
				return s.Push(dataModel)
			}))
			s.L.SetGlobal("DataModel", t)
		},
	}
}
<|endoftext|>


<commit_before>package ginHttp

import (
	"time"

	cmodel "github.com/Cepave/common/model"
	// "github.com/fvbock/endless"
	"log"

	"github.com/Cepave/query/g"
	"github.com/Cepave/query/gin_http/computeFunc"
	"github.com/Cepave/query/gin_http/openFalcon"
	"github.com/gin-gonic/gin"
)

type QueryInput struct {
	StartTs       time.Time
	EndTs         time.Time
	ComputeMethod string
	Endpoint      string
	Counter       string
}

//this function will generate query string obj for QueryRRDtool
func getq(q QueryInput) cmodel.GraphQueryParam {
	request := cmodel.GraphQueryParam{
		Start:     q.StartTs.Unix(),
		End:       q.EndTs.Unix(),
		ConsolFun: q.ComputeMethod,
		Endpoint:  q.Endpoint,
		Counter:   q.Counter,
	}
	return request
}

//accept cross domain request
func CORSMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")

		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(204)
			return
		}

		c.Next()
	}
}

func StartWeb() {
	handler := gin.Default()
	handler.Use(CORSMiddleware())
	compute := handler.Group("/func")
	conf := g.Config()
	compute.GET("/compute", computeFunc.Compute)
	compute.GET("/funcations", computeFunc.GetAvaibleFun)
	compute.GET("/smapledata", computeFunc.GetTestData)
	openfalcon := handler.Group("/owl")
	openfalcon.GET("/endpoints", openFalcon.GetEndpoints)
	openfalcon.GET("/queryrrd", openFalcon.QueryData)
	// endless.ListenAndServe(":8888", handler)
	log.Println("open gin port on:", conf.GinHttp.Listen)
	handler.Run(conf.GinHttp.Listen)
}
<commit_msg>remove endless<commit_after>package ginHttp

import (
	"time"

	"log"

	cmodel "github.com/Cepave/common/model"

	"github.com/Cepave/query/g"
	"github.com/Cepave/query/gin_http/computeFunc"
	"github.com/Cepave/query/gin_http/openFalcon"
	"github.com/gin-gonic/gin"
)

type QueryInput struct {
	StartTs       time.Time
	EndTs         time.Time
	ComputeMethod string
	Endpoint      string
	Counter       string
}

//this function will generate query string obj for QueryRRDtool
func getq(q QueryInput) cmodel.GraphQueryParam {
	request := cmodel.GraphQueryParam{
		Start:     q.StartTs.Unix(),
		End:       q.EndTs.Unix(),
		ConsolFun: q.ComputeMethod,
		Endpoint:  q.Endpoint,
		Counter:   q.Counter,
	}
	return request
}

//accept cross domain request
func CORSMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")

		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(204)
			return
		}

		c.Next()
	}
}

func StartWeb() {
	handler := gin.Default()
	handler.Use(CORSMiddleware())
	compute := handler.Group("/func")
	conf := g.Config()
	compute.GET("/compute", computeFunc.Compute)
	compute.GET("/funcations", computeFunc.GetAvaibleFun)
	compute.GET("/smapledata", computeFunc.GetTestData)
	openfalcon := handler.Group("/owl")
	openfalcon.GET("/endpoints", openFalcon.GetEndpoints)
	openfalcon.GET("/queryrrd", openFalcon.QueryData)
	log.Println("open gin port on:", conf.GinHttp.Listen)
	handler.Run(conf.GinHttp.Listen)
}
<|endoftext|>


<commit_before>/*
                       WARNING WARNING WARNING

                Attention all potential contributors

   This testfile is not in the best state. We've been slowly transitioning
   from the built in "testing" package to using Ginkgo. As you can see, we've
   changed the format, but a lot of the setup, test body, descriptions, etc
   are either hardcoded, completely lacking, or misleading.

   For example:

   Describe("Testing with ginkgo"...)      // This is not a great description
   It("TestDoesSoemthing"...)              // This is a horrible description

   Describe("create-user command"...       // Describe the actual object under test
   It("creates a user when provided ..."   // this is more descriptive

   For good examples of writing Ginkgo tests for the cli, refer to

   src/github.com/cloudfoundry/cli/cf/commands/application/delete_app_test.go
   src/github.com/cloudfoundry/cli/cf/terminal/ui_test.go
   src/github.com/cloudfoundry/loggregator_consumer/consumer_test.go
*/

package domain_test

import (
	"github.com/cloudfoundry/cli/cf/commands/domain"
	"github.com/cloudfoundry/cli/cf/configuration"
	"github.com/cloudfoundry/cli/cf/models"
	testapi "github.com/cloudfoundry/cli/testhelpers/api"
	testcmd "github.com/cloudfoundry/cli/testhelpers/commands"
	testconfig "github.com/cloudfoundry/cli/testhelpers/configuration"
	testreq "github.com/cloudfoundry/cli/testhelpers/requirements"
	testterm "github.com/cloudfoundry/cli/testhelpers/terminal"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	. "github.com/cloudfoundry/cli/testhelpers/matchers"
)

var _ = Describe("Testing with ginkgo", func() {
	It("TestCreateDomainRequirements", func() {
		domainRepo := &testapi.FakeDomainRepository{}
		requirementsFactory := &testreq.FakeReqFactory{LoginSuccess: true}

		callCreateDomain([]string{"my-org", "example.com"}, requirementsFactory, domainRepo)
		Expect(testcmd.CommandDidPassRequirements).To(BeTrue())
		Expect(requirementsFactory.OrganizationName).To(Equal("my-org"))

		requirementsFactory = &testreq.FakeReqFactory{LoginSuccess: false}

		callCreateDomain([]string{"my-org", "example.com"}, requirementsFactory, domainRepo)
		Expect(testcmd.CommandDidPassRequirements).To(BeFalse())
	})
	It("TestCreateDomainFailsWithUsage", func() {

		requirementsFactory := &testreq.FakeReqFactory{LoginSuccess: true}
		domainRepo := &testapi.FakeDomainRepository{}
		ui := callCreateDomain([]string{""}, requirementsFactory, domainRepo)
		Expect(ui.FailedWithUsage).To(BeTrue())

		ui = callCreateDomain([]string{"org1"}, requirementsFactory, domainRepo)
		Expect(ui.FailedWithUsage).To(BeTrue())

		ui = callCreateDomain([]string{"org1", "example.com"}, requirementsFactory, domainRepo)
		Expect(ui.FailedWithUsage).To(BeFalse())
	})
	It("TestCreateDomain", func() {

		org := models.Organization{}
		org.Name = "myOrg"
		org.Guid = "myOrg-guid"
		requirementsFactory := &testreq.FakeReqFactory{LoginSuccess: true, Organization: org}
		domainRepo := &testapi.FakeDomainRepository{}
		ui := callCreateDomain([]string{"myOrg", "example.com"}, requirementsFactory, domainRepo)

		Expect(domainRepo.CreateDomainName).To(Equal("example.com"))
		Expect(domainRepo.CreateDomainOwningOrgGuid).To(Equal("myOrg-guid"))
		Expect(ui.Outputs).To(ContainSubstrings(
			[]string{"Creating domain", "example.com", "myOrg", "my-user"},
			[]string{"OK"},
		))
	})
})

func callCreateDomain(args []string, requirementsFactory *testreq.FakeReqFactory, domainRepo *testapi.FakeDomainRepository) (fakeUI *testterm.FakeUI) {
	fakeUI = new(testterm.FakeUI)
	token := configuration.TokenInfo{Username: "my-user"}
	configRepo := testconfig.NewRepositoryWithAccessToken(token)

	cmd := domain.NewCreateDomain(fakeUI, configRepo, domainRepo)

	testcmd.RunCommand(cmd, args, requirementsFactory)
	return
}
<commit_msg>Clean up create domain test<commit_after>package domain_test

import (
	"github.com/cloudfoundry/cli/cf/commands/domain"
	"github.com/cloudfoundry/cli/cf/configuration"
	"github.com/cloudfoundry/cli/cf/models"
	testapi "github.com/cloudfoundry/cli/testhelpers/api"
	testcmd "github.com/cloudfoundry/cli/testhelpers/commands"
	testconfig "github.com/cloudfoundry/cli/testhelpers/configuration"
	testreq "github.com/cloudfoundry/cli/testhelpers/requirements"
	testterm "github.com/cloudfoundry/cli/testhelpers/terminal"

	. "github.com/cloudfoundry/cli/testhelpers/matchers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("create domain command", func() {

	var (
		requirementsFactory *testreq.FakeReqFactory
		ui                  *testterm.FakeUI
		domainRepo          *testapi.FakeDomainRepository
		configRepo          configuration.ReadWriter
	)

	BeforeEach(func() {
		requirementsFactory = &testreq.FakeReqFactory{LoginSuccess: true}
		domainRepo = &testapi.FakeDomainRepository{}
		configRepo = testconfig.NewRepositoryWithAccessToken(configuration.TokenInfo{Username: "my-user"})
	})

	runCommand := func(args ...string) {
		ui = new(testterm.FakeUI)
		cmd := domain.NewCreateDomain(ui, configRepo, domainRepo)
		testcmd.RunCommand(cmd, args, requirementsFactory)
		return
	}

	It("fails with usage", func() {
		runCommand("")
		Expect(ui.FailedWithUsage).To(BeTrue())

		runCommand("org1")
		Expect(ui.FailedWithUsage).To(BeTrue())

		runCommand("org1", "example.com")
		Expect(ui.FailedWithUsage).To(BeFalse())
	})

	Context("checks login", func() {
		It("passes when logged in", func() {
			runCommand("my-org", "example.com")
			Expect(testcmd.CommandDidPassRequirements).To(BeTrue())
			Expect(requirementsFactory.OrganizationName).To(Equal("my-org"))
		})

		It("fails when not logged in", func() {
			requirementsFactory = &testreq.FakeReqFactory{LoginSuccess: false}

			runCommand("my-org", "example.com")
			Expect(testcmd.CommandDidPassRequirements).To(BeFalse())
		})
	})

	It("creates a domain", func() {
		org := models.Organization{}
		org.Name = "myOrg"
		org.Guid = "myOrg-guid"
		requirementsFactory = &testreq.FakeReqFactory{LoginSuccess: true, Organization: org}
		runCommand("myOrg", "example.com")

		Expect(domainRepo.CreateDomainName).To(Equal("example.com"))
		Expect(domainRepo.CreateDomainOwningOrgGuid).To(Equal("myOrg-guid"))
		Expect(ui.Outputs).To(ContainSubstrings(
			[]string{"Creating domain", "example.com", "myOrg", "my-user"},
			[]string{"OK"},
		))
	})
})
<|endoftext|>


<commit_before>package cipher

import (
	"crypto/sha512"
)

// CKDF (Cheap Key Derivation Function) generates two keys k1 and k2 from the
// given nonce. Specification:
// https://github.com/mutecomm/mute/blob/master/doc/keyserver.md#ckdf-cheap-key-derivation-function
//
// TODO: review!
func CKDF(nonce []byte) (k1, k2 []byte) {
	// a  = SHA512(key)
	a := SHA512(nonce)
	hashsize := sha512.Size

	// a1 = a[0, (hashsize / 2)] | a[0, (hashsize / 2)]
	a1 := make([]byte, hashsize)
	copy(a1, a[:hashsize/2])
	copy(a1[hashsize/2:], a[:hashsize/2])

	// a2 = a[(hashsize / 2), hashsize] | a[(hashsize / 2), hashsize]
	a2 := make([]byte, hashsize)
	copy(a2, a[hashsize/2:])
	copy(a2[hashsize/2:], a[hashsize/2:])

	// k1 = SHA512( a1 ^ [0x5c * hashsize] | SHA512( a2 ^ [0x36 * hashsize] ))
	pad1 := make([]byte, hashsize*2)
	for i := 0; i < hashsize; i++ {
		pad1[i] = a1[i] ^ 0x5c
	}
	for i := 0; i < hashsize; i++ {
		pad1[hashsize+i] = a2[i] ^ 0x36
	}
	copy(pad1[hashsize:], SHA512(pad1[hashsize:]))
	k1 = SHA512(pad1)

	// k2 = SHA512( a2 ^ [0x5c * hashsize] | SHA512( a1 ^ [0x36 * hashsize] ))
	pad2 := make([]byte, hashsize*2)
	for i := 0; i < hashsize; i++ {
		pad2[i] = a2[i] ^ 0x5c
	}
	for i := 0; i < hashsize; i++ {
		pad2[hashsize+i] = a1[i] ^ 0x36
	}
	copy(pad2[hashsize:], SHA512(pad2[hashsize:]))
	k2 = SHA512(pad2)

	return
}
<commit_msg>ciphers: fix link in documentation<commit_after>package cipher

import (
	"crypto/sha512"
)

// CKDF (Cheap Key Derivation Function) generates two keys k1 and k2 from the
// given nonce. Specification:
// https://github.com/mutecomm/mute/blob/master/doc/ciphers.md#ckdf-cheap-key-derivation-function
//
// TODO: review!
func CKDF(nonce []byte) (k1, k2 []byte) {
	// a  = SHA512(key)
	a := SHA512(nonce)
	hashsize := sha512.Size

	// a1 = a[0, (hashsize / 2)] | a[0, (hashsize / 2)]
	a1 := make([]byte, hashsize)
	copy(a1, a[:hashsize/2])
	copy(a1[hashsize/2:], a[:hashsize/2])

	// a2 = a[(hashsize / 2), hashsize] | a[(hashsize / 2), hashsize]
	a2 := make([]byte, hashsize)
	copy(a2, a[hashsize/2:])
	copy(a2[hashsize/2:], a[hashsize/2:])

	// k1 = SHA512( a1 ^ [0x5c * hashsize] | SHA512( a2 ^ [0x36 * hashsize] ))
	pad1 := make([]byte, hashsize*2)
	for i := 0; i < hashsize; i++ {
		pad1[i] = a1[i] ^ 0x5c
	}
	for i := 0; i < hashsize; i++ {
		pad1[hashsize+i] = a2[i] ^ 0x36
	}
	copy(pad1[hashsize:], SHA512(pad1[hashsize:]))
	k1 = SHA512(pad1)

	// k2 = SHA512( a2 ^ [0x5c * hashsize] | SHA512( a1 ^ [0x36 * hashsize] ))
	pad2 := make([]byte, hashsize*2)
	for i := 0; i < hashsize; i++ {
		pad2[i] = a2[i] ^ 0x5c
	}
	for i := 0; i < hashsize; i++ {
		pad2[hashsize+i] = a1[i] ^ 0x36
	}
	copy(pad2[hashsize:], SHA512(pad2[hashsize:]))
	k2 = SHA512(pad2)

	return
}
<|endoftext|>


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

package main

import (
	"archive/zip"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

// Global for tracking whether we've warned user about delay.
var warned = false

// cmdServe is the "claat serve ..." subcommand.
func cmdServe() {
	var depsDir = "bower_components"
	var elemDir = "elements"
	var elemFile = elemDir + "/codelab.html"
	const codelabElem = `
<link rel="import" href="../bower_components/google-codelab-elements/google-codelab-elements.html">
`
	err := os.MkdirAll(depsDir, 0755)
	if err != nil {
		fatalf(err.Error())
	}
	// Go get the dependencies.
	err = fetchRepo(depsDir, "googlecodelabs/codelab-components#2.0.2")
	if err != nil {
		fatalf(err.Error())
	}
	os.Rename(depsDir+"/code-prettify", depsDir+"/google-prettify")
	err = os.MkdirAll(elemDir, 0755)
	if err != nil {
		fatalf(err.Error())
	}
	if _, err := os.Stat(elemFile); os.IsNotExist(err) {
		f, err := os.Create(elemFile)
		if err != nil {
			fatalf(err.Error())
		}
		defer f.Close()
		f.WriteString(codelabElem)
	}
	http.Handle("/", http.FileServer(http.Dir(".")))
	fmt.Println("Serving on " + *addr + ", opening browser tab now...")
	ch := make(chan error, 1)
	go func() {
		ch <- http.ListenAndServe(*addr, nil)
	}()
	openBrowser("http://" + *addr)
	fatalf("claat serve: %v", <-ch)
}

// downloadFile will download a url to a local file. It's efficient because it will
// write as it downloads and not load the whole file into memory.
func downloadFile(filepath string, url string) error {
	if !warned {
		fmt.Println("Fetching dependencies...")
		warned = true
	}
	out, err := os.Create(filepath)
	if err != nil {
		return err
	}
	defer out.Close()
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	_, err = io.Copy(out, resp.Body)
	return err
}

// bowerComp maps non-conforming spec as described in fetchRepo doc comments.
// It is keyed by the name found in a bower.json dependency list,
// with values corresponding to a valid githubuser/repo spec.
var bowerComp = map[string]string{
	"googlecodelabs/codelab-components#2.0.2": "google-codelab-elements",
	"webcomponents/webcomponentsjs":           "webcomponentsjs",
	"google/google-prettify":                  "code-prettify",
}

// fetchRepo downloads a repo from github and unpacks it into basedir/dest,
// calling itself recursively for every dependency found in the unpacked bower.json.
// If the basedir/dest directory already exists, fetchRepo does nothing.
//
// The spec has the following format: "githubuser/repo#version".
// Any non-alphanumeric characters are stripped from the version.
// If version is missing, "master" is used instead.
// The bower registry is not used for naming resolution.
func fetchRepo(basedir, spec string) error {
	var user, repo, path, comp, ver string
	s := strings.Split(spec, "#")
	path = s[0]
	if len(s) > 1 {
		ver = s[1]
	}
	ver = strings.Trim(ver, "^~ ")
	if ver == "" {
		ver = "master"
	}
	s = strings.Split(path, "/")
	user = s[0]
	if len(s) > 1 {
		repo = s[1]
	}
	// Check exception map to see if we should use a special component name.
	comp = repo
	if v, ok := bowerComp[spec]; ok {
		comp = v
	}
	// if repo already exists locally, return immediately, we're done.
	if _, err := os.Stat(basedir + "/" + comp); err == nil {
		return nil
	}
	zipFile := basedir + "/" + comp + ".zip"
	url := "https://github.com/" + user + "/" + repo + "/archive/v" + ver + ".zip"
	err := downloadFile(zipFile, url)
	if err != nil {
		return err
	}
	// If get fails, it will download a file containing only "404: Not Found".
	// We check for that case by looking for an unusually small file.
	var st os.FileInfo
	if st, err = os.Stat(zipFile); err != nil {
		return err
	}
	if st.Size() < 20 {
		os.Remove(zipFile)
		url = "https://github.com/" + user + "/" + repo + "/archive/" + ver + ".zip"
		err = downloadFile(zipFile, url)
		if err != nil {
			return err
		}
	}
	err = unzip(zipFile, basedir)
	if err != nil {
		return err
	}
	os.Remove(zipFile)
	os.Rename(basedir+"/"+repo+"-"+ver, basedir+"/"+comp)

	// if unzipped archive contains a bower.json, parse it, and for each dependency therein,
	// recursively fetch the corresponding repo.
	bowerFile := basedir + "/" + comp + "/bower.json"
	if _, err := os.Stat(bowerFile); os.IsNotExist(err) {
		return nil
	}
	raw, err := ioutil.ReadFile(bowerFile)
	if err != nil {
		return err
	}
	var b struct {
		Dependencies map[string]string
	}
	err = json.Unmarshal(raw, &b)
	if err != nil {
		return err
	}
	for _, v := range b.Dependencies {
		err = fetchRepo(basedir, v)
		if err != nil {
			return err
		}
	}
	return nil
}

// unzip a file to a dest directory.
func unzip(src, dest string) error {
	r, err := zip.OpenReader(src)
	if err != nil {
		return err
	}
	defer r.Close()
	os.MkdirAll(dest, 0755)
	// Closure to address file descriptors issue with all the deferred .Close() methods
	extractAndWriteFile := func(f *zip.File) error {
		rc, err := f.Open()
		if err != nil {
			return err
		}
		defer rc.Close()
		path := filepath.Join(dest, f.Name)
		if f.FileInfo().IsDir() {
			return os.MkdirAll(path, f.Mode())
		}
		os.MkdirAll(filepath.Dir(path), f.Mode())
		f2, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
		if err != nil {
			return err
		}
		_, err = io.Copy(f2, rc)
		// Catch both io.Copy and file.Close errors but prefer returning the former.
		if err1 := f2.Close(); err1 != nil && err == nil {
			err = err1
		}
		return err
	}
	for _, f := range r.File {
		err := extractAndWriteFile(f)
		if err != nil {
			return err
		}
	}
	return nil
}

// openBrowser tries to open the URL in a browser.
func openBrowser(url string) error {
	var args []string
	switch runtime.GOOS {
	case "darwin":
		args = []string{"open"}
	case "windows":
		args = []string{"cmd", "/c", "start"}
	default:
		args = []string{"xdg-open"}
	}
	cmd := exec.Command(args[0], append(args[1:], url)...)
	return cmd.Start()
}
<commit_msg>use earlier version of codelab-components and fix how we search exceptions table to use only path, not version<commit_after>// Copyright 2018 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"archive/zip"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

// Global for tracking whether we've warned user about delay.
var warned = false

// cmdServe is the "claat serve ..." subcommand.
func cmdServe() {
	var depsDir = "bower_components"
	var elemDir = "elements"
	var elemFile = elemDir + "/codelab.html"
	const codelabElem = `
<link rel="import" href="../bower_components/google-codelab-elements/google-codelab-elements.html">
`
	err := os.MkdirAll(depsDir, 0755)
	if err != nil {
		fatalf(err.Error())
	}
	// Go get the dependencies.
	err = fetchRepo(depsDir, "googlecodelabs/codelab-components#1.0.5")
	if err != nil {
		fatalf(err.Error())
	}
	os.Rename(depsDir+"/code-prettify", depsDir+"/google-prettify")
	err = os.MkdirAll(elemDir, 0755)
	if err != nil {
		fatalf(err.Error())
	}
	if _, err := os.Stat(elemFile); os.IsNotExist(err) {
		f, err := os.Create(elemFile)
		if err != nil {
			fatalf(err.Error())
		}
		defer f.Close()
		f.WriteString(codelabElem)
	}
	http.Handle("/", http.FileServer(http.Dir(".")))
	fmt.Println("Serving on " + *addr + ", opening browser tab now...")
	ch := make(chan error, 1)
	go func() {
		ch <- http.ListenAndServe(*addr, nil)
	}()
	openBrowser("http://" + *addr)
	fatalf("claat serve: %v", <-ch)
}

// downloadFile will download a url to a local file. It's efficient because it will
// write as it downloads and not load the whole file into memory.
func downloadFile(filepath string, url string) error {
	if !warned {
		fmt.Println("Fetching dependencies...")
		warned = true
	}
	out, err := os.Create(filepath)
	if err != nil {
		return err
	}
	defer out.Close()
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	_, err = io.Copy(out, resp.Body)
	return err
}

// bowerComp maps non-conforming spec as described in fetchRepo doc comments.
// It is keyed by the name found in a bower.json dependency list,
// with values corresponding to a valid githubuser/repo spec.
var bowerComp = map[string]string{
	"googlecodelabs/codelab-components": "google-codelab-elements",
	"webcomponents/webcomponentsjs":     "webcomponentsjs",
	"google/google-prettify":            "code-prettify",
}

// fetchRepo downloads a repo from github and unpacks it into basedir/dest,
// calling itself recursively for every dependency found in the unpacked bower.json.
// If the basedir/dest directory already exists, fetchRepo does nothing.
//
// The spec has the following format: "githubuser/repo#version".
// Any non-alphanumeric characters are stripped from the version.
// If version is missing, "master" is used instead.
// The bower registry is not used for naming resolution.
func fetchRepo(basedir, spec string) error {
	var user, repo, path, comp, ver string
	s := strings.Split(spec, "#")
	path = s[0]
	if len(s) > 1 {
		ver = s[1]
	}
	ver = strings.Trim(ver, "^~ ")
	if ver == "" {
		ver = "master"
	}
	s = strings.Split(path, "/")
	user = s[0]
	if len(s) > 1 {
		repo = s[1]
	}
	// Check exception map to see if we should use a special component name.
	comp = repo
	if v, ok := bowerComp[path]; ok {
		comp = v
	}
	// if repo already exists locally, return immediately, we're done.
	if _, err := os.Stat(basedir + "/" + comp); err == nil {
		return nil
	}
	zipFile := basedir + "/" + comp + ".zip"
	url := "https://github.com/" + user + "/" + repo + "/archive/v" + ver + ".zip"
	err := downloadFile(zipFile, url)
	if err != nil {
		return err
	}
	// If get fails, it will download a file containing only "404: Not Found".
	// We check for that case by looking for an unusually small file.
	var st os.FileInfo
	if st, err = os.Stat(zipFile); err != nil {
		return err
	}
	if st.Size() < 20 {
		os.Remove(zipFile)
		url = "https://github.com/" + user + "/" + repo + "/archive/" + ver + ".zip"
		err = downloadFile(zipFile, url)
		if err != nil {
			return err
		}
	}
	err = unzip(zipFile, basedir)
	if err != nil {
		return err
	}
	os.Remove(zipFile)
	os.Rename(basedir+"/"+repo+"-"+ver, basedir+"/"+comp)

	// if unzipped archive contains a bower.json, parse it, and for each dependency therein,
	// recursively fetch the corresponding repo.
	bowerFile := basedir + "/" + comp + "/bower.json"
	if _, err := os.Stat(bowerFile); os.IsNotExist(err) {
		return nil
	}
	raw, err := ioutil.ReadFile(bowerFile)
	if err != nil {
		return err
	}
	var b struct {
		Dependencies map[string]string
	}
	err = json.Unmarshal(raw, &b)
	if err != nil {
		return err
	}
	for _, v := range b.Dependencies {
		err = fetchRepo(basedir, v)
		if err != nil {
			return err
		}
	}
	return nil
}

// unzip a file to a dest directory.
func unzip(src, dest string) error {
	r, err := zip.OpenReader(src)
	if err != nil {
		return err
	}
	defer r.Close()
	os.MkdirAll(dest, 0755)
	// Closure to address file descriptors issue with all the deferred .Close() methods
	extractAndWriteFile := func(f *zip.File) error {
		rc, err := f.Open()
		if err != nil {
			return err
		}
		defer rc.Close()
		path := filepath.Join(dest, f.Name)
		if f.FileInfo().IsDir() {
			return os.MkdirAll(path, f.Mode())
		}
		os.MkdirAll(filepath.Dir(path), f.Mode())
		f2, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
		if err != nil {
			return err
		}
		_, err = io.Copy(f2, rc)
		// Catch both io.Copy and file.Close errors but prefer returning the former.
		if err1 := f2.Close(); err1 != nil && err == nil {
			err = err1
		}
		return err
	}
	for _, f := range r.File {
		err := extractAndWriteFile(f)
		if err != nil {
			return err
		}
	}
	return nil
}

// openBrowser tries to open the URL in a browser.
func openBrowser(url string) error {
	var args []string
	switch runtime.GOOS {
	case "darwin":
		args = []string{"open"}
	case "windows":
		args = []string{"cmd", "/c", "start"}
	default:
		args = []string{"xdg-open"}
	}
	cmd := exec.Command(args[0], append(args[1:], url)...)
	return cmd.Start()
}
<|endoftext|>


<commit_before>package relations

import (
	"bytes"
	"io"
	"sort"

	"github.com/oleiade/lane"
	"github.com/s2gatev/hcache"
)

// pair is used in the construction of the subsequential transducer.
// It contains a transducer state and the symbols that remain to be
// added to the output.
type pair struct {
	state     *tState
	remaining string
}

func (p *pair) equal(o *pair) bool {
	return p.state.index == o.state.index && p.remaining == o.remaining
}

// pairs is a slice compatible with the hcache structure.
// The underlying values are of type *pair.
type pairs []hcache.Key

func (ps pairs) Len() int {
	return len(ps)
}

func (ps pairs) Less(i, j int) bool {
	p1 := ps[i].(*pair)
	p2 := ps[j].(*pair)

	if p1.state.index == p2.state.index {
		return p1.remaining < p2.remaining
	}

	return p1.state.index < p2.state.index
}

func (ps pairs) Swap(i, j int) {
	ps[i], ps[j] = ps[j], ps[i]
}

// sState is a state in a subsequential transducer.
type sState struct {
	remainingPairs pairs
	next           map[rune]*sState
	out            map[rune]string
	final          bool
	finalOut       []string
	isVisited      bool
}

func newSState() *sState {
	return &sState{next: make(map[rune]*sState), out: make(map[rune]string)}
}

// getFinalOut gets final outputs if pair has final state.
func (ss *sState) getFinalOut() []string {
	var finalRemaining []string
	for _, p := range ss.remainingPairs {
		p := p.(*pair)
		if p.state.final {
			finalRemaining = append(finalRemaining, p.remaining)
		}
	}
	return finalRemaining
}

// lcp calculates the longest common prefix of the input strings.
func lcp(strs [][]rune) string {
	if len(strs) == 0 {
		return ""
	}

	for i, c := range strs[0] {
		for _, s := range strs[1:] {
			if i == len(s) || s[i] != c {
				return string(strs[0][:i])
			}
		}
	}
	return string(strs[0])
}

// RegularRelation is a struct containing the initial state of the
// subsequential transducer that recognizes the input regular relation.
type RegularRelation struct {
	start *sState
}

// Transduce feeds the input string into the RegularRelation transducer
// and returns all possible results from the output transducer tape.
func (s *RegularRelation) Transduce(input string) ([]string, bool) {
	node := s.start
	var output string

	for _, symbol := range input {
		nextnode, ok := node.next[symbol]
		if !ok {
			return nil, false
		}
		output += node.out[symbol]
		node = nextnode
	}

	if !node.final {
		return nil, false
	}

	var result []string
	for _, o := range node.finalOut {
		result = append(result, output+o)
	}

	return result, true
}

// Build builds a RegularRelation subsequential transducer from the
// input regular relation expression.
// TODO: define regular relation grammar.
func Build(source io.Reader) (*RegularRelation, error) {
	tr, err := newTransducer(source)
	if err != nil {
		return nil, err
	}

	stateQueue := lane.NewQueue()
	sc := hcache.New()

	initPair := &pair{state: tr.root, remaining: ""}
	start := sc.GetOrInsert(newSState(), initPair).(*sState)
	start.remainingPairs = append(start.remainingPairs, initPair)
	stateQueue.Enqueue(start)

	for stateQueue.Size() != 0 {
		state := stateQueue.Dequeue().(*sState)

		// Check if state should be final and add outputs to final output.
		if final := state.getFinalOut(); len(final) != 0 {
			state.final = true
			state.finalOut = append(state.finalOut, final...)
		}

		// Get groups of pairs that have states with same input symbol.
		withInput := make(map[rune]pairs)
		for _, p := range state.remainingPairs {
			p := p.(*pair)
			for in := range p.state.next {
				withInput[in] = append(withInput[in], p)
			}
		}

		for in, ps := range withInput {
			// Get all remaining+out strings from states with given input
			// and map them to corresponding next state.
			var outputs [][]rune
			nextStates := make(map[int]*tState)
			for _, p := range ps {
				p := p.(*pair)
				remaining := bytes.Runes([]byte(p.remaining))
				for _, o := range p.state.next[in] {
					out := append(remaining, bytes.Runes([]byte(o.out))...)
					outputs = append(outputs, out)
					nextStates[len(outputs)-1] = o.state
				}
			}

			// Calculate longest common prefix.
			state.out[in] = lcp(outputs)

			// Create new pairs by removing the longest common prefix from
			// the outputs.
			var newPairs pairs
			for i, out := range outputs {
				newPairs = append(newPairs, &pair{
					state:     nextStates[i],
					remaining: string(out[len(state.out[in]):]),
				})
			}
			sort.Sort(newPairs)

			// Check if state with such state pairs exists...
			nextState := sc.GetOrInsert(newSState(), newPairs...).(*sState)

			// ...and populate the state with the new pairs if necessary.
			if !nextState.isVisited {
				nextState.isVisited = true
				nextState.remainingPairs = newPairs
				stateQueue.Enqueue(nextState)
			}

			state.next[in] = nextState
		}
	}

	return &RegularRelation{start: start}, nil
}
<commit_msg>Add note about explicitly specifying regex operations<commit_after>package relations

import (
	"bytes"
	"io"
	"sort"

	"github.com/oleiade/lane"
	"github.com/s2gatev/hcache"
)

// pair is used in the construction of the subsequential transducer.
// It contains a transducer state and the symbols that remain to be
// added to the output.
type pair struct {
	state     *tState
	remaining string
}

func (p *pair) equal(o *pair) bool {
	return p.state.index == o.state.index && p.remaining == o.remaining
}

// pairs is a slice compatible with the hcache structure.
// The underlying values are of type *pair.
type pairs []hcache.Key

func (ps pairs) Len() int {
	return len(ps)
}

func (ps pairs) Less(i, j int) bool {
	p1 := ps[i].(*pair)
	p2 := ps[j].(*pair)

	if p1.state.index == p2.state.index {
		return p1.remaining < p2.remaining
	}

	return p1.state.index < p2.state.index
}

func (ps pairs) Swap(i, j int) {
	ps[i], ps[j] = ps[j], ps[i]
}

// sState is a state in a subsequential transducer.
type sState struct {
	remainingPairs pairs
	next           map[rune]*sState
	out            map[rune]string
	final          bool
	finalOut       []string
	isVisited      bool
}

func newSState() *sState {
	return &sState{next: make(map[rune]*sState), out: make(map[rune]string)}
}

// getFinalOut gets final outputs if pair has final state.
func (ss *sState) getFinalOut() []string {
	var finalRemaining []string
	for _, p := range ss.remainingPairs {
		p := p.(*pair)
		if p.state.final {
			finalRemaining = append(finalRemaining, p.remaining)
		}
	}
	return finalRemaining
}

// lcp calculates the longest common prefix of the input strings.
func lcp(strs [][]rune) string {
	if len(strs) == 0 {
		return ""
	}

	for i, c := range strs[0] {
		for _, s := range strs[1:] {
			if i == len(s) || s[i] != c {
				return string(strs[0][:i])
			}
		}
	}
	return string(strs[0])
}

// RegularRelation is a struct containing the initial state of the
// subsequential transducer that recognizes the input regular relation.
type RegularRelation struct {
	start *sState
}

// Transduce feeds the input string into the RegularRelation transducer
// and returns all possible results from the output transducer tape.
func (s *RegularRelation) Transduce(input string) ([]string, bool) {
	node := s.start
	var output string

	for _, symbol := range input {
		nextnode, ok := node.next[symbol]
		if !ok {
			return nil, false
		}
		output += node.out[symbol]
		node = nextnode
	}

	if !node.final {
		return nil, false
	}

	var result []string
	for _, o := range node.finalOut {
		result = append(result, output+o)
	}

	return result, true
}

// Build builds a RegularRelation subsequential transducer from the
// input regular relation expression.
// NOTE: All operations must be explicitly written in the regular expression.
func Build(source io.Reader) (*RegularRelation, error) {
	tr, err := newTransducer(source)
	if err != nil {
		return nil, err
	}

	stateQueue := lane.NewQueue()
	sc := hcache.New()

	initPair := &pair{state: tr.root, remaining: ""}
	start := sc.GetOrInsert(newSState(), initPair).(*sState)
	start.remainingPairs = append(start.remainingPairs, initPair)
	stateQueue.Enqueue(start)

	for stateQueue.Size() != 0 {
		state := stateQueue.Dequeue().(*sState)

		// Check if state should be final and add outputs to final output.
		if final := state.getFinalOut(); len(final) != 0 {
			state.final = true
			state.finalOut = append(state.finalOut, final...)
		}

		// Get groups of pairs that have states with same input symbol.
		withInput := make(map[rune]pairs)
		for _, p := range state.remainingPairs {
			p := p.(*pair)
			for in := range p.state.next {
				withInput[in] = append(withInput[in], p)
			}
		}

		for in, ps := range withInput {
			// Get all remaining+out strings from states with given input
			// and map them to corresponding next state.
			var outputs [][]rune
			nextStates := make(map[int]*tState)
			for _, p := range ps {
				p := p.(*pair)
				remaining := bytes.Runes([]byte(p.remaining))
				for _, o := range p.state.next[in] {
					out := append(remaining, bytes.Runes([]byte(o.out))...)
					outputs = append(outputs, out)
					nextStates[len(outputs)-1] = o.state
				}
			}

			// Calculate longest common prefix.
			state.out[in] = lcp(outputs)

			// Create new pairs by removing the longest common prefix from
			// the outputs.
			var newPairs pairs
			for i, out := range outputs {
				newPairs = append(newPairs, &pair{
					state:     nextStates[i],
					remaining: string(out[len(state.out[in]):]),
				})
			}
			sort.Sort(newPairs)

			// Check if state with such state pairs exists...
			nextState := sc.GetOrInsert(newSState(), newPairs...).(*sState)

			// ...and populate the state with the new pairs if necessary.
			if !nextState.isVisited {
				nextState.isVisited = true
				nextState.remainingPairs = newPairs
				stateQueue.Enqueue(nextState)
			}

			state.next[in] = nextState
		}
	}

	return &RegularRelation{start: start}, nil
}
<|endoftext|>


<commit_before>// Convert grep-like commands to SQL for ClouePelican
// Example: cat errors | grep -v 404 | grep -i checkout | grep -e "(100|200)"
// SELECT _raw FROM errors WHERE _raw NOT LIKE '%404%' AND LOWER(_raw) LIKE LOWER('checkout') AND REGEXP_MATCH(_raw, '(100|200)') ORDER BY ts ASC LIMIT 1000
// @author Robin Verlangen

// @todo Support color

package main

import (
	"bytes"
	"errors"
	"fmt"
	"log"
	"strings"
	"text/scanner"
)

type GrepSQL struct {
	input string
	cmds  []GrepCmd
}

type GrepCmd struct {
	flags   map[string]bool // v=exclude, i=case-insensitive, e=regex
	pattern string
}

func (w *GrepCmd) Where() string {
	if verbose {
		log.Printf("%v", w)
	}

	// Column
	var column string = "_raw"

	// Exclude?
	var notSuffix string = ""
	if w.flags["v"] {
		notSuffix = "NOT "
	}

	// Regex?
	if w.flags["e"] {
		if w.flags["i"] && !strings.Contains(w.pattern, "(?i)") {
			// Inject case insensitive into the pattern
			w.pattern = fmt.Sprintf("(?i)%s", w.pattern)
		}
		return fmt.Sprintf("%sREGEXP_MATCH(%s, '%s')", notSuffix, column, w.pattern)
	}

	// Case sensitive?
	if w.flags["i"] {
		return fmt.Sprintf("LOWER(%s) %sLIKE LOWER('%%%s%%')", column, notSuffix, w.pattern)
	}

	// Regular matching
	return fmt.Sprintf("%s %sLIKE '%%%s%%'", column, notSuffix, w.pattern)
}

func (g *GrepSQL) Parse() (string, error) {
	// Tokenize
	var s scanner.Scanner
	s.Init(strings.NewReader(g.input))
	tok := s.Scan()
	var previousTokens []string = make([]string, 0)
	var i int = 0
	var currentCmd *GrepCmd = nil
	for tok != scanner.EOF {
		// Get token
		tok = s.Scan()
		token := s.TokenText()
		if verbose {
			log.Println(fmt.Sprintf("\n\nToken: %s", token))
		}

		// Create list of grep commands
		if i > 0 {
			if verbose {
				log.Printf("prev %s", previousTokens[i-1])
				log.Printf("currentCmd %v", currentCmd)
			}

			// Begin of command
			if previousTokens[i-1] == "|" {
				// Previous token is pipe, this must be grep
				if token != "grep" {
					return "", errors.New(fmt.Sprintf("Invalid token %s", token))
				}

				// Init
				if verbose {
					log.Printf("New token command")
				}
				currentCmd = newGrepCmd()
			} else if previousTokens[i-1] == "-" && currentCmd != nil {
				// Flag
				if token != "v" && token != "e" && token != "i" {
					return "", errors.New(fmt.Sprintf("Invalid flag %s", token))
				}
				// Set flag
				if verbose {
					log.Printf("Flag %s", token)
				}
				currentCmd.flags[token] = true
			} else if token != "-" && currentCmd != nil {
				if verbose {
					log.Printf("pattern %s", token)
				}
				// Pattern
				currentCmd.pattern = strings.Trim(token, "\"'")

				// Add to list
				g.cmds = append(g.cmds, *currentCmd)

				// Reset
				currentCmd = nil
			}
		}

		// Keep track of the previous tokens
		previousTokens = append(previousTokens, token)

		// Counter
		i++
	}

	// Tokens
	if len(previousTokens) < 1 {
		return "", errors.New("Invalid input")
	}

	// Print structure
	if verbose {
		log.Printf("%v", g)
	}

	// Validate & fetch filter
	filter, filterE := supervisorCon.FilterByName(previousTokens[0])
	if filterE != nil {
		return "", filterE
	}

	// Begin builder query
	var qBuf bytes.Buffer
	qBuf.WriteString("SELECT")
	qBuf.WriteString(" ")
	qBuf.WriteString("_raw")
	qBuf.WriteString(" ")
	qBuf.WriteString("FROM")
	qBuf.WriteString(" ")
	qBuf.WriteString(filter.GetSearchTableName())

	// Where part?
	if len(g.cmds) > 0 {
		qBuf.WriteString(" ")
		qBuf.WriteString("WHERE")
		qBuf.WriteString(" ")

		// Build filter
		var wheres []string = make([]string, 0)
		for _, cmd := range g.cmds {
			wheres = append(wheres, cmd.Where())
		}
		qBuf.WriteString(strings.Join(wheres, " AND "))
	}

	// Done
	return qBuf.String(), nil
}

func newGrepCmd() *GrepCmd {
	return &GrepCmd{
		flags: make(map[string]bool),
	}
}

func newGrepSQL(input string) *GrepSQL {
	return &GrepSQL{
		input: input,
		cmds:  make([]GrepCmd, 0),
	}
}
<commit_msg>Very very simple sort and head support<commit_after>// Convert grep-like commands to SQL for ClouePelican
// Example: cat errors | grep -v 404 | grep -i checkout | grep -e "(100|200)"
// SELECT _raw FROM errors WHERE _raw NOT LIKE '%404%' AND LOWER(_raw) LIKE LOWER('checkout') AND REGEXP_MATCH(_raw, '(100|200)') ORDER BY ts ASC LIMIT 1000
// @author Robin Verlangen

// @todo Support color

package main

import (
	"bytes"
	"errors"
	"fmt"
	"log"
	"strings"
	"text/scanner"
)

type GrepSQL struct {
	input string
	cmds  []GrepCmd
}

type GrepCmd struct {
	flags   map[string]bool // v=exclude, i=case-insensitive, e=regex
	pattern string
}

func (w *GrepCmd) Where() string {
	if verbose {
		log.Printf("%v", w)
	}

	// Column
	var column string = "_raw"

	// Exclude?
	var notSuffix string = ""
	if w.flags["v"] {
		notSuffix = "NOT "
	}

	// Regex?
	if w.flags["e"] {
		if w.flags["i"] && !strings.Contains(w.pattern, "(?i)") {
			// Inject case insensitive into the pattern
			w.pattern = fmt.Sprintf("(?i)%s", w.pattern)
		}
		return fmt.Sprintf("%sREGEXP_MATCH(%s, '%s')", notSuffix, column, w.pattern)
	}

	// Case sensitive?
	if w.flags["i"] {
		return fmt.Sprintf("LOWER(%s) %sLIKE LOWER('%%%s%%')", column, notSuffix, w.pattern)
	}

	// Regular matching
	return fmt.Sprintf("%s %sLIKE '%%%s%%'", column, notSuffix, w.pattern)
}

func (g *GrepSQL) Parse() (string, error) {
	// Tokenize
	var s scanner.Scanner
	s.Init(strings.NewReader(g.input))
	tok := s.Scan()
	var previousTokens []string = make([]string, 0)
	var i int = 0
	var sort bool = false
	var head bool = false
	var currentCmd *GrepCmd = nil
	for tok != scanner.EOF {
		// Get token
		tok = s.Scan()
		token := s.TokenText()
		if verbose {
			log.Println(fmt.Sprintf("\n\nToken: %s", token))
		}

		// Create list of grep commands
		if i > 0 {
			if verbose {
				log.Printf("prev %s", previousTokens[i-1])
				log.Printf("currentCmd %v", currentCmd)
			}

			// Begin of command
			if previousTokens[i-1] == "|" {
				// Previous token is pipe, this must be grep
				if token != "grep" && token != "sort" && token != "head" {
					return "", errors.New(fmt.Sprintf("Invalid token %s", token))
				}

				// Init new command
				if token == "grep" {
					if verbose {
						log.Printf("New token command")
					}
					currentCmd = newGrepCmd()
				} else if token == "sort" {
					sort = true
				} else if token == "head" {
					head = true
				}
			} else if previousTokens[i-1] == "-" && currentCmd != nil {
				// Flag
				if token != "v" && token != "e" && token != "i" {
					return "", errors.New(fmt.Sprintf("Invalid flag %s", token))
				}
				// Set flag
				if verbose {
					log.Printf("Flag %s", token)
				}
				currentCmd.flags[token] = true
			} else if token != "-" && currentCmd != nil {
				if verbose {
					log.Printf("pattern %s", token)
				}
				// Pattern
				currentCmd.pattern = strings.Trim(token, "\"'")

				// Add to list
				g.cmds = append(g.cmds, *currentCmd)

				// Reset
				currentCmd = nil
			}
		}

		// Keep track of the previous tokens
		previousTokens = append(previousTokens, token)

		// Counter
		i++
	}

	// Tokens
	if len(previousTokens) < 1 {
		return "", errors.New("Invalid input")
	}

	// Print structure
	if verbose {
		log.Printf("%v", g)
	}

	// Validate & fetch filter
	filter, filterE := supervisorCon.FilterByName(previousTokens[0])
	if filterE != nil {
		return "", filterE
	}

	// Begin builder query
	var qBuf bytes.Buffer
	qBuf.WriteString("SELECT")
	qBuf.WriteString(" ")
	qBuf.WriteString("_raw")
	qBuf.WriteString(" ")
	qBuf.WriteString("FROM")
	qBuf.WriteString(" ")
	qBuf.WriteString(filter.GetSearchTableName())

	// Where part?
	if len(g.cmds) > 0 {
		qBuf.WriteString(" ")
		qBuf.WriteString("WHERE")
		qBuf.WriteString(" ")

		// Build filter
		var wheres []string = make([]string, 0)
		for _, cmd := range g.cmds {
			wheres = append(wheres, cmd.Where())
		}
		qBuf.WriteString(strings.Join(wheres, " AND "))
	}

	// Sort
	if sort {
		qBuf.WriteString(" ORDER BY _raw ASC")
	}

	// Header
	if head {
		qBuf.WriteString(" LIMIT 10")
	}

	// Done
	return qBuf.String(), nil
}

func newGrepCmd() *GrepCmd {
	return &GrepCmd{
		flags: make(map[string]bool),
	}
}

func newGrepSQL(input string) *GrepSQL {
	return &GrepSQL{
		input: input,
		cmds:  make([]GrepCmd, 0),
	}
}
<|endoftext|>


<commit_before>package reprunner

import (
	"os/exec"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
)

type Runner struct {
	binPath string
	Session *gexec.Session
	config  Config
}

type Config struct {
	stack       string
	listenAddr  string
	executorURL string
	etcdCluster string
	logLevel    string
}

func New(binPath, stack, listenAddr, executorURL, etcdCluster, logLevel string) *Runner {
	return &Runner{
		binPath: binPath,
		config: Config{
			stack:       stack,
			listenAddr:  listenAddr,
			executorURL: executorURL,
			etcdCluster: etcdCluster,
			logLevel:    logLevel,
		},
	}
}

func (r *Runner) Start() {
	repSession, err := gexec.Start(
		exec.Command(
			r.binPath,
			"-stack", r.config.stack,
			"-listenAddr", r.config.listenAddr,
			"-executorURL", r.config.executorURL,
			"-etcdCluster", r.config.etcdCluster,
			"-logLevel", r.config.logLevel,
		),
		GinkgoWriter,
		GinkgoWriter,
	)

	Ω(err).ShouldNot(HaveOccurred())
	r.Session = repSession
	Eventually(r.Session.Buffer()).Should(gbytes.Say("started"))
}

func (r *Runner) Stop() {
	if r.Session != nil {
		r.Session.Interrupt().Wait(5 * time.Second)
		r.Session = nil
	}
}

func (r *Runner) KillWithFire() {
	if r.Session != nil {
		r.Session.Kill().Wait()
		r.Session = nil
	}
}
<commit_msg>blow up if started twice<commit_after>package reprunner

import (
	"os/exec"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
)

type Runner struct {
	binPath string
	Session *gexec.Session
	config  Config
}

type Config struct {
	stack       string
	listenAddr  string
	executorURL string
	etcdCluster string
	logLevel    string
}

func New(binPath, stack, listenAddr, executorURL, etcdCluster, logLevel string) *Runner {
	return &Runner{
		binPath: binPath,
		config: Config{
			stack:       stack,
			listenAddr:  listenAddr,
			executorURL: executorURL,
			etcdCluster: etcdCluster,
			logLevel:    logLevel,
		},
	}
}

func (r *Runner) Start() {
	if r.Session != nil {
		panic("starting more than one rep!!!")
	}

	repSession, err := gexec.Start(
		exec.Command(
			r.binPath,
			"-stack", r.config.stack,
			"-listenAddr", r.config.listenAddr,
			"-executorURL", r.config.executorURL,
			"-etcdCluster", r.config.etcdCluster,
			"-logLevel", r.config.logLevel,
		),
		GinkgoWriter,
		GinkgoWriter,
	)

	Ω(err).ShouldNot(HaveOccurred())
	r.Session = repSession
	Eventually(r.Session.Buffer()).Should(gbytes.Say("started"))
}

func (r *Runner) Stop() {
	if r.Session != nil {
		r.Session.Interrupt().Wait(5 * time.Second)
		r.Session = nil
	}
}

func (r *Runner) KillWithFire() {
	if r.Session != nil {
		r.Session.Kill().Wait()
		r.Session = nil
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strconv"
)

func ExpectGithubToBreak(url string) (out string, e error) {
	r, e := http.Get(url)
	if e != nil {
		fmt.Print("!")
	}

	if r.StatusCode != 200 {
		if r.StatusCode == 403 {
			fmt.Println("Github Rate Limit reached.")
			rlreset := r.Header.Get("X-RateLimit-Reset")
			if rlreset != "" {
				i, e := strconv.ParseInt(rlreset, 10, 64)
				if e == nil {
					// I don't really understand how this would happen but its worth checking.
					fmt.Printf("You can expect the rate limit to reset on %d\n", i)
				}
			}
			os.Exit(1)
		}
		return "", fmt.Errorf("Cannot get GH page")
	} else {
		return ioutil.ReadAll(r.Body), e
	}
}
<commit_msg>Add GH Struct<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strconv"
)

func ExpectGithubToBreak(url string) (out string, e error) {
	r, e := http.Get(url)
	if e != nil {
		fmt.Print("!")
	}

	if r.StatusCode != 200 {
		if r.StatusCode == 403 {
			fmt.Println("Github Rate Limit reached.")
			rlreset := r.Header.Get("X-RateLimit-Reset")
			if rlreset != "" {
				i, e := strconv.ParseInt(rlreset, 10, 64)
				if e == nil {
					// I don't really understand how this would happen but its worth checking.
					fmt.Printf("You can expect the rate limit to reset on %d\n", i)
				}
			}
			os.Exit(1)
		}
		return "", fmt.Errorf("Cannot get GH page")
	} else {
		return ioutil.ReadAll(r.Body), e
	}
}

type GHRepo struct {
	ArchiveURL       string      `json:"archive_url"`
	AssigneesURL     string      `json:"assignees_url"`
	BlobsURL         string      `json:"blobs_url"`
	BranchesURL      string      `json:"branches_url"`
	CloneURL         string      `json:"clone_url"`
	CollaboratorsURL string      `json:"collaborators_url"`
	CommentsURL      string      `json:"comments_url"`
	CommitsURL       string      `json:"commits_url"`
	CompareURL       string      `json:"compare_url"`
	ContentsURL      string      `json:"contents_url"`
	ContributorsURL  string      `json:"contributors_url"`
	CreatedAt        string      `json:"created_at"`
	DefaultBranch    string      `json:"default_branch"`
	Description      string      `json:"description"`
	DownloadsURL     string      `json:"downloads_url"`
	EventsURL        string      `json:"events_url"`
	Fork             bool        `json:"fork"`
	Forks            float64     `json:"forks"`
	ForksCount       float64     `json:"forks_count"`
	ForksURL         string      `json:"forks_url"`
	FullName         string      `json:"full_name"`
	GitCommitsURL    string      `json:"git_commits_url"`
	GitRefsURL       string      `json:"git_refs_url"`
	GitTagsURL       string      `json:"git_tags_url"`
	GitURL           string      `json:"git_url"`
	HasDownloads     bool        `json:"has_downloads"`
	HasIssues        bool        `json:"has_issues"`
	HasWiki          bool        `json:"has_wiki"`
	Homepage         interface{} `json:"homepage"`
	HooksURL         string      `json:"hooks_url"`
	HtmlURL          string      `json:"html_url"`
	ID               float64     `json:"id"`
	IssueCommentURL  string      `json:"issue_comment_url"`
	IssueEventsURL   string      `json:"issue_events_url"`
	IssuesURL        string      `json:"issues_url"`
	KeysURL          string      `json:"keys_url"`
	LabelsURL        string      `json:"labels_url"`
	Language         string      `json:"language"`
	LanguagesURL     string      `json:"languages_url"`
	MasterBranch     string      `json:"master_branch"`
	MergesURL        string      `json:"merges_url"`
	MilestonesURL    string      `json:"milestones_url"`
	MirrorURL        interface{} `json:"mirror_url"`
	Name             string      `json:"name"`
	NotificationsURL string      `json:"notifications_url"`
	OpenIssues       float64     `json:"open_issues"`
	OpenIssuesCount  float64     `json:"open_issues_count"`
	Owner            struct {
		AvatarURL         string  `json:"avatar_url"`
		EventsURL         string  `json:"events_url"`
		FollowersURL      string  `json:"followers_url"`
		FollowingURL      string  `json:"following_url"`
		GistsURL          string  `json:"gists_url"`
		GravatarID        string  `json:"gravatar_id"`
		HtmlURL           string  `json:"html_url"`
		ID                float64 `json:"id"`
		Login             string  `json:"login"`
		OrganizationsURL  string  `json:"organizations_url"`
		ReceivedEventsURL string  `json:"received_events_url"`
		ReposURL          string  `json:"repos_url"`
		SiteAdmin         bool    `json:"site_admin"`
		StarredURL        string  `json:"starred_url"`
		SubscriptionsURL  string  `json:"subscriptions_url"`
		Type              string  `json:"type"`
		URL               string  `json:"url"`
	} `json:"owner"`
	Private         bool    `json:"private"`
	PullsURL        string  `json:"pulls_url"`
	PushedAt        string  `json:"pushed_at"`
	ReleasesURL     string  `json:"releases_url"`
	Size            float64 `json:"size"`
	SshURL          string  `json:"ssh_url"`
	StargazersCount float64 `json:"stargazers_count"`
	StargazersURL   string  `json:"stargazers_url"`
	StatusesURL     string  `json:"statuses_url"`
	SubscribersURL  string  `json:"subscribers_url"`
	SubscriptionURL string  `json:"subscription_url"`
	SvnURL          string  `json:"svn_url"`
	TagsURL         string  `json:"tags_url"`
	TeamsURL        string  `json:"teams_url"`
	TreesURL        string  `json:"trees_url"`
	UpdatedAt       string  `json:"updated_at"`
	URL             string  `json:"url"`
	Watchers        float64 `json:"watchers"`
	WatchersCount   float64 `json:"watchers_count"`
}
<|endoftext|>