<commit_before>// Copyright (c) 2017 Che Wei, Lin
//
// 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 tinynet

import (
	"fmt"

	log "github.com/sirupsen/logrus"
)

// HostConfig is a host network configuration
type HostConfig struct {
	name      string
	address   string
	docker    bool
	ifaceName string
	imageRef  string
	mtu       int
}

// NewHostConfig is a constructor to initial host network configuration.
func NewHostConfig(name, addr, ifaceName string, mtu int, docker bool, imageRef string) HostConfig {
	hostConfig := HostConfig{}
	if name == "" {
		panic("Host name is required")
	}
	if addr == "" {
		panic("Host address is required")
	}
	hostConfig.name = name
	hostConfig.address = addr
	hostConfig.docker = docker
	hostConfig.ifaceName = ifaceName
	if ifaceName == "" {
		hostConfig.ifaceName = "eth1"
	}
	hostConfig.imageRef = imageRef
	if imageRef == "" {
		hostConfig.imageRef = "library/busybox"
	}
	hostConfig.mtu = mtu
	if mtu == 0 {
		hostConfig.mtu = 1500
	}
	return hostConfig
}

// AddHostWithConf will add a host to topology.
func AddHostWithConf(hc hostConfig) (*Host, error) {
	var h *Host
	var err error
	if hc.docker {
		// Create a docker container
		h, err = NewContainer(hc.name, hc.imageRef)
		if err != nil {
			log.Fatal("failed to NewContainer: ", err)
		}
	} else {
		// Create a network namespace
		h, err = NewHost(hc.name)
		if err != nil {
			log.Fatal("failed to NewHost: ", err)
		}
	}
	// setup a veth pair
	_, err = h.setupVeth(hc.ifaceName, hc.mtu)
	if err != nil {
		log.Fatal("failed to setup veth pair: ", err)
	}
	// setup a IP for host
	h.setIfaceIP(hc.address)
	if err != nil {
		log.Fatalf("failed to setIfaceIP for %s: %v", h.Name, err)
		return nil, err
	}
	return h, nil
}

// AddHost will add a host to topology. set docker to true can enable docker container as a host
func AddHost(name string, addr string, docker bool) (*Host, error) {
	log.Warnf("Will be deprecated: use AddHostWithConf instead")
	var h *Host
	var err error
	if docker {
		// Create a docker container
		h, err = NewContainer(name, "library/busybox")
		if err != nil {
			log.Fatal("failed to NewContainer: ", err)
		}
	} else {
		// Create a network namespace
		h, err = NewHost(name)
		if err != nil {
			log.Fatal("failed to NewHost: ", err)
		}
	}
	// setup a veth pair
	_, err = h.setupVeth("eth2", 1500)
	if err != nil {
		log.Fatal("failed to setup veth pair: ", err)
	}
	// setup a IP for host
	h.setIfaceIP(addr)
	if err != nil {
		log.Fatalf("failed to setIfaceIP for %s: %v", h.Name, err)
		return nil, err
	}
	return h, nil
}

// AddSwitch will add a switch to topology.
func AddSwitch(params ...string) (*OVSSwitch, error) {
	// params[0] for brName
	// params[1] for controller remote IP and port
	// Create a Open vSwitch bridge
	sw, err := NewOVSSwitch(params[0])
	if err != nil {
		log.Fatal("failed to NewOVSSwitch: ", err)
	}
	if len(params) == 2 {
		if err := sw.SetCtrl(params[1]); err != nil {
			log.Warnf("failed to SetCtrl for %s: %v", sw.BridgeName, err)
			return nil, err
		}
	} else if len(params) > 2 {
		return nil, fmt.Errorf("Too many arguments")
	}
	return sw, nil
}

// AddLink will add a link between switch to switch or host to switch.
func AddLink(n1, n2 interface{}) error {
	// log.Info(n1.(*OVSSwitch).nodeType)
	// log.Info(n2.(*Host).nodeType)
	var err error
	switch n1.(type) {
	case *OVSSwitch:
		switch n2.(type) {
		case *OVSSwitch:
			tap0, tap1, err := makeVethPair("tap0", "tap1")
			if err != nil {
				log.Fatalf("failed to makeVethPair: %v", err)
			}
			err = n1.(*OVSSwitch).addPort(tap0.Name)
			if err != nil {
				log.Fatalf("failed to addPortswitch - switch: %v", err)
			}
			err = n2.(*OVSSwitch).addPort(tap1.Name)
			if err != nil {
				log.Fatalf("failed to addPort switch - switch: %v", err)
			}
			log.Infof("Adding a link: (%s, %s)", n1.(*OVSSwitch).BridgeName, n2.(*OVSSwitch).BridgeName)
		case *Host:
			err = n1.(*OVSSwitch).addPort(n2.(*Host).VethName)
			if err != nil {
				log.Fatalf("failed to addPort switch - host: %v", err)
			}
			log.Infof("Adding a link: (%s, %s)", n1.(*OVSSwitch).BridgeName, n2.(*Host).Name)
		default:
			log.Fatalf("Type Error")
		}
	case *Host:
		switch n2.(type) {
		case *OVSSwitch:
			err = n2.(*OVSSwitch).addPort(n1.(*Host).VethName)
			if err != nil {
				log.Fatalf("failed to addPort host - switch : %v", err)
			}
			log.Infof("Adding a link: (%s, %s)", n1.(*Host).Name, n2.(*OVSSwitch).BridgeName)
		case *Host:
			log.Fatalf("Type Error: host can not connect to host")
		default:
			log.Fatalf("Type Error")
		}
	default:
		log.Fatalf("Type Error")
	}
	return nil
}

// GetIPs will get IP address from a CIDR notation
// Return an array with IP address. negative num for getting all IP addresses
// (network address and broadcast address are not included)
func GetIPs(cidr string, num int) ([]string, error) {
	ips, err := getAllIPsfromCIDR(cidr)
	if err != nil {
		return nil, err
	}
	if num < 0 {
		return ips, nil
	}
	return ips[0:num], nil
}
<commit_msg>fixed type name<commit_after>// Copyright (c) 2017 Che Wei, Lin
//
// 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 tinynet

import (
	"fmt"

	log "github.com/sirupsen/logrus"
)

// HostConfig is a host network configuration
type HostConfig struct {
	name      string
	address   string
	docker    bool
	ifaceName string
	imageRef  string
	mtu       int
}

// NewHostConfig is a constructor to initial host network configuration.
func NewHostConfig(name, addr, ifaceName string, mtu int, docker bool, imageRef string) HostConfig {
	hostConfig := HostConfig{}
	if name == "" {
		panic("Host name is required")
	}
	if addr == "" {
		panic("Host address is required")
	}
	hostConfig.name = name
	hostConfig.address = addr
	hostConfig.docker = docker
	hostConfig.ifaceName = ifaceName
	if ifaceName == "" {
		hostConfig.ifaceName = "eth1"
	}
	hostConfig.imageRef = imageRef
	if imageRef == "" {
		hostConfig.imageRef = "library/busybox"
	}
	hostConfig.mtu = mtu
	if mtu == 0 {
		hostConfig.mtu = 1500
	}
	return hostConfig
}

// AddHostWithConf will add a host to topology.
func AddHostWithConf(hc HostConfig) (*Host, error) {
	var h *Host
	var err error
	if hc.docker {
		// Create a docker container
		h, err = NewContainer(hc.name, hc.imageRef)
		if err != nil {
			log.Fatal("failed to NewContainer: ", err)
		}
	} else {
		// Create a network namespace
		h, err = NewHost(hc.name)
		if err != nil {
			log.Fatal("failed to NewHost: ", err)
		}
	}
	// setup a veth pair
	_, err = h.setupVeth(hc.ifaceName, hc.mtu)
	if err != nil {
		log.Fatal("failed to setup veth pair: ", err)
	}
	// setup a IP for host
	h.setIfaceIP(hc.address)
	if err != nil {
		log.Fatalf("failed to setIfaceIP for %s: %v", h.Name, err)
		return nil, err
	}
	return h, nil
}

// AddHost will add a host to topology. set docker to true can enable docker container as a host
func AddHost(name string, addr string, docker bool) (*Host, error) {
	log.Warnf("Will be deprecated: use AddHostWithConf instead")
	var h *Host
	var err error
	if docker {
		// Create a docker container
		h, err = NewContainer(name, "library/busybox")
		if err != nil {
			log.Fatal("failed to NewContainer: ", err)
		}
	} else {
		// Create a network namespace
		h, err = NewHost(name)
		if err != nil {
			log.Fatal("failed to NewHost: ", err)
		}
	}
	// setup a veth pair
	_, err = h.setupVeth("eth2", 1500)
	if err != nil {
		log.Fatal("failed to setup veth pair: ", err)
	}
	// setup a IP for host
	h.setIfaceIP(addr)
	if err != nil {
		log.Fatalf("failed to setIfaceIP for %s: %v", h.Name, err)
		return nil, err
	}
	return h, nil
}

// AddSwitch will add a switch to topology.
func AddSwitch(params ...string) (*OVSSwitch, error) {
	// params[0] for brName
	// params[1] for controller remote IP and port
	// Create a Open vSwitch bridge
	sw, err := NewOVSSwitch(params[0])
	if err != nil {
		log.Fatal("failed to NewOVSSwitch: ", err)
	}
	if len(params) == 2 {
		if err := sw.SetCtrl(params[1]); err != nil {
			log.Warnf("failed to SetCtrl for %s: %v", sw.BridgeName, err)
			return nil, err
		}
	} else if len(params) > 2 {
		return nil, fmt.Errorf("Too many arguments")
	}
	return sw, nil
}

// AddLink will add a link between switch to switch or host to switch.
func AddLink(n1, n2 interface{}) error {
	// log.Info(n1.(*OVSSwitch).nodeType)
	// log.Info(n2.(*Host).nodeType)
	var err error
	switch n1.(type) {
	case *OVSSwitch:
		switch n2.(type) {
		case *OVSSwitch:
			tap0, tap1, err := makeVethPair("tap0", "tap1")
			if err != nil {
				log.Fatalf("failed to makeVethPair: %v", err)
			}
			err = n1.(*OVSSwitch).addPort(tap0.Name)
			if err != nil {
				log.Fatalf("failed to addPortswitch - switch: %v", err)
			}
			err = n2.(*OVSSwitch).addPort(tap1.Name)
			if err != nil {
				log.Fatalf("failed to addPort switch - switch: %v", err)
			}
			log.Infof("Adding a link: (%s, %s)", n1.(*OVSSwitch).BridgeName, n2.(*OVSSwitch).BridgeName)
		case *Host:
			err = n1.(*OVSSwitch).addPort(n2.(*Host).VethName)
			if err != nil {
				log.Fatalf("failed to addPort switch - host: %v", err)
			}
			log.Infof("Adding a link: (%s, %s)", n1.(*OVSSwitch).BridgeName, n2.(*Host).Name)
		default:
			log.Fatalf("Type Error")
		}
	case *Host:
		switch n2.(type) {
		case *OVSSwitch:
			err = n2.(*OVSSwitch).addPort(n1.(*Host).VethName)
			if err != nil {
				log.Fatalf("failed to addPort host - switch : %v", err)
			}
			log.Infof("Adding a link: (%s, %s)", n1.(*Host).Name, n2.(*OVSSwitch).BridgeName)
		case *Host:
			log.Fatalf("Type Error: host can not connect to host")
		default:
			log.Fatalf("Type Error")
		}
	default:
		log.Fatalf("Type Error")
	}
	return nil
}

// GetIPs will get IP address from a CIDR notation
// Return an array with IP address. negative num for getting all IP addresses
// (network address and broadcast address are not included)
func GetIPs(cidr string, num int) ([]string, error) {
	ips, err := getAllIPsfromCIDR(cidr)
	if err != nil {
		return nil, err
	}
	if num < 0 {
		return ips, nil
	}
	return ips[0:num], nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	//"math/rand"
	"os"
	"os/exec"
	"time"

	"github.com/james4k/termbox-go"
	"github.com/kr/pty"
	"j4k.co/terminal"
)

func filterESC(r io.Reader) io.Reader {
	pr, pw := io.Pipe()
	go func() {
		br := bufio.NewReader(r)
		for {
			b, err := br.ReadByte()
			if err != nil {
				pw.CloseWithError(err)
				return
			}
			if b == 033 {
				_, err = pw.Write([]byte("ESC"))
			} else {
				_, err = pw.Write([]byte{b})
			}
			if err != nil {
				pw.CloseWithError(err)
				return
			}
		}
	}()
	return pr
}

func update(term *terminal.Term, w, h int) {
	termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
	for i := 0; i < h+2; i++ {
		termbox.SetCell(0, i, '│', termbox.ColorDefault, termbox.ColorDefault)
		termbox.SetCell(w+1, i, '│', termbox.ColorDefault, termbox.ColorDefault)
	}
	for i := 0; i < w+2; i++ {
		termbox.SetCell(i, 0, '─', termbox.ColorDefault, termbox.ColorDefault)
		termbox.SetCell(i, h+1, '─', termbox.ColorDefault, termbox.ColorDefault)
	}
	termbox.SetCell(0, 0, '┌', termbox.ColorDefault, termbox.ColorDefault)
	termbox.SetCell(w+1, 0, '┐', termbox.ColorDefault, termbox.ColorDefault)
	termbox.SetCell(w+1, h+1, '┘', termbox.ColorDefault, termbox.ColorDefault)
	termbox.SetCell(0, h+1, '└', termbox.ColorDefault, termbox.ColorDefault)
	for y := 0; y < h; y++ {
		for x := 0; x < w; x++ {
			c, fg, bg := term.Cell(x, y)
			/*
				// termbox only supports 8 colors
				if fg > 15 {
					fg = 7
				} else if fg > 7 {
					fg -= 8
				}
				if bg > 15 {
					bg = 0
				} else if bg > 7 {
					bg -= 8
				}
			*/
			fg = 6 // colors are an issue for later; just keep it monocolored for now
			bg = 0
			termbox.SetCell(x+1, y+1, c,
				termbox.Attribute(fg+1),
				termbox.Attribute(bg+1))
		}
	}
	if term.CursorHidden() {
		termbox.SetCursor(-1, -1)
	} else {
		curx, cury := term.Cursor()
		curx += 1
		cury += 1
		termbox.SetCursor(curx, cury)
	}
	termbox.Flush()
}

func main() {
	// NOTE: This must be before termbox.Init(). On OSX, at least, we get a
	// kernel panic if we termbox.Init() first! But, only when the process is
	// terminated in some way. Crazy. If this was more than a debug app it
	// might be worth looking more into.
	f, err := pty.Start(exec.Command(os.Getenv("SHELL"), "-i"))
	if err != nil {
		panic(err)
	}
	defer f.Close()

	err = termbox.Init()
	if err != nil {
		panic(err)
	}
	defer termbox.Close()
	wide, tall := termbox.Size()

	term := terminal.New(wide-2, tall-2, f)
	term.Stderr = ioutil.Discard
	// TODO: separate window for the log output
	term.Write([]byte("boxterm - debug frontend\r\n"))

	endc := make(chan bool)
	go func() {
		defer func() {
			if x := recover(); x != nil {
				fmt.Fprintln(os.Stderr, err)
			}
		}()
		_, err := io.Copy(term, f)
		if err != nil && err != io.EOF {
			fmt.Fprintln(os.Stderr, err)
		}
		close(endc)
	}()

	go func() {
		defer func() {
			if x := recover(); x != nil {
				fmt.Fprintln(os.Stderr, err)
			}
		}()
		io.Copy(f, os.Stdin)
	}()

	eventc := make(chan termbox.Event, 4)
	go func() {
		for {
			eventc <- termbox.PollEvent()
		}
	}()

	tickc := time.Tick(50 * time.Millisecond)
	for {
		select {
		case ev := <-eventc:
			if ev.Type == termbox.EventResize {
				wide = ev.Width
				tall = ev.Height
				term.Resize(wide-2, tall-2)
			}
		case <-endc:
			return
		case <-tickc:
			update(term, wide-2, tall-2)
		}
	}
}
<commit_msg>boxterm: renamed termbox-go fork<commit_after>package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	//"math/rand"
	"os"
	"os/exec"
	"time"

	"github.com/james4k/termbox-go-noinput"
	"github.com/kr/pty"
	"j4k.co/terminal"
)

func filterESC(r io.Reader) io.Reader {
	pr, pw := io.Pipe()
	go func() {
		br := bufio.NewReader(r)
		for {
			b, err := br.ReadByte()
			if err != nil {
				pw.CloseWithError(err)
				return
			}
			if b == 033 {
				_, err = pw.Write([]byte("ESC"))
			} else {
				_, err = pw.Write([]byte{b})
			}
			if err != nil {
				pw.CloseWithError(err)
				return
			}
		}
	}()
	return pr
}

func update(term *terminal.Term, w, h int) {
	termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
	for i := 0; i < h+2; i++ {
		termbox.SetCell(0, i, '│', termbox.ColorDefault, termbox.ColorDefault)
		termbox.SetCell(w+1, i, '│', termbox.ColorDefault, termbox.ColorDefault)
	}
	for i := 0; i < w+2; i++ {
		termbox.SetCell(i, 0, '─', termbox.ColorDefault, termbox.ColorDefault)
		termbox.SetCell(i, h+1, '─', termbox.ColorDefault, termbox.ColorDefault)
	}
	termbox.SetCell(0, 0, '┌', termbox.ColorDefault, termbox.ColorDefault)
	termbox.SetCell(w+1, 0, '┐', termbox.ColorDefault, termbox.ColorDefault)
	termbox.SetCell(w+1, h+1, '┘', termbox.ColorDefault, termbox.ColorDefault)
	termbox.SetCell(0, h+1, '└', termbox.ColorDefault, termbox.ColorDefault)
	for y := 0; y < h; y++ {
		for x := 0; x < w; x++ {
			c, fg, bg := term.Cell(x, y)
			/*
				// termbox only supports 8 colors
				if fg > 15 {
					fg = 7
				} else if fg > 7 {
					fg -= 8
				}
				if bg > 15 {
					bg = 0
				} else if bg > 7 {
					bg -= 8
				}
			*/
			fg = 6 // colors are an issue for later; just keep it monocolored for now
			bg = 0
			termbox.SetCell(x+1, y+1, c,
				termbox.Attribute(fg+1),
				termbox.Attribute(bg+1))
		}
	}
	if term.CursorHidden() {
		termbox.SetCursor(-1, -1)
	} else {
		curx, cury := term.Cursor()
		curx += 1
		cury += 1
		termbox.SetCursor(curx, cury)
	}
	termbox.Flush()
}

func main() {
	// NOTE: This must be before termbox.Init(). On OSX, at least, we get a
	// kernel panic if we termbox.Init() first! But, only when the process is
	// terminated in some way. Crazy. If this was more than a debug app it
	// might be worth looking more into.
	f, err := pty.Start(exec.Command(os.Getenv("SHELL"), "-i"))
	if err != nil {
		panic(err)
	}
	defer f.Close()

	err = termbox.Init()
	if err != nil {
		panic(err)
	}
	defer termbox.Close()
	wide, tall := termbox.Size()

	term := terminal.New(wide-2, tall-2, f)
	term.Stderr = ioutil.Discard
	// TODO: separate window for the log output
	term.Write([]byte("boxterm - debug frontend\r\n"))

	endc := make(chan bool)
	go func() {
		defer func() {
			if x := recover(); x != nil {
				fmt.Fprintln(os.Stderr, err)
			}
		}()
		_, err := io.Copy(term, f)
		if err != nil && err != io.EOF {
			fmt.Fprintln(os.Stderr, err)
		}
		close(endc)
	}()

	go func() {
		defer func() {
			if x := recover(); x != nil {
				fmt.Fprintln(os.Stderr, err)
			}
		}()
		io.Copy(f, os.Stdin)
	}()

	eventc := make(chan termbox.Event, 4)
	go func() {
		for {
			eventc <- termbox.PollEvent()
		}
	}()

	tickc := time.Tick(50 * time.Millisecond)
	for {
		select {
		case ev := <-eventc:
			if ev.Type == termbox.EventResize {
				wide = ev.Width
				tall = ev.Height
				term.Resize(wide-2, tall-2)
			}
		case <-endc:
			return
		case <-tickc:
			update(term, wide-2, tall-2)
		}
	}
}
<|endoftext|>


<commit_before>package models

import (
	"fmt"
	"io"
	"net/url"
	"os"
	"time"

	"github.com/coopernurse/gorp"
)

type BundlePlatformType int

const (
	BundlePlatformTypeAndroid BundlePlatformType = 1 + iota
	BundlePlatformTypeIOS
)

func (platformType BundlePlatformType) Extention() BundleFileExtension {
	var ext BundleFileExtension
	if platformType == BundlePlatformTypeAndroid {
		ext = BundleFileExtensionAndroid
	} else if platformType == BundlePlatformTypeIOS {
		ext = BundleFileExtensionIOS
	}
	return ext
}

type BundleFileExtension string

const (
	BundleFileExtensionAndroid BundleFileExtension = ".apk"
	BundleFileExtensionIOS     BundleFileExtension = ".ipa"
)

func (ext BundleFileExtension) IsValid() bool {
	var ok bool
	if ext == BundleFileExtensionAndroid {
		ok = true
	} else if ext == BundleFileExtensionIOS {
		ok = true
	}
	return ok
}

func (ext BundleFileExtension) PlatformType() BundlePlatformType {
	var platformType BundlePlatformType
	if ext == BundleFileExtensionAndroid {
		platformType = BundlePlatformTypeAndroid
	} else if ext == BundleFileExtensionIOS {
		platformType = BundlePlatformTypeIOS
	}
	return platformType
}

type Bundle struct {
	Id            int                `db:"id"`
	AppId         int                `db:"app_id"`
	FileId        string             `db:"file_id"`
	PlatformType  BundlePlatformType `db:"platform_type"`
	BundleVersion string             `db:"bundle_version"`
	Revision      int                `db:"revision"`
	Description   string             `db:"description"`
	CreatedAt     time.Time          `db:"created_at"`
	UpdatedAt     time.Time          `db:"updated_at"`

	BundleInfo *BundleInfo `db:"-"`
	File       *os.File    `db:"-"`
	FileName   string      `db:"-"`
}

type BundleJsonResponse struct {
	FileId     string `json:"file_id"`
	Version    string `json:"version"`
	Revision   int    `json:"revision"`
	InstallUrl string `json:"install_url"`
	QrCodeUrl  string `json:"qr_code_url"`
}

func (bundle *Bundle) JsonResponse(ub UriBuilder) (*BundleJsonResponse, error) {
	installUrl, err := ub.UriFor(fmt.Sprintf("bundle/%d/download", bundle.Id))
	if err != nil {
		return nil, err
	}
	qrCodeUrl, err := ub.UriFor(fmt.Sprintf("bundle/%d", bundle.Id))
	if err != nil {
		return nil, err
	}

	return &BundleJsonResponse{
		FileId:     bundle.FileId,
		Version:    bundle.BundleVersion,
		Revision:   bundle.Revision,
		InstallUrl: installUrl.String(),
		QrCodeUrl:  qrCodeUrl.String(),
	}, nil
}

func (bundle *Bundle) Plist(txn *gorp.Transaction, ipaUrl *url.URL) (*Plist, error) {
	app, err := bundle.App(txn)
	if err != nil {
		return nil, err
	}

	return NewPlist(app.Title, bundle.BundleVersion, ipaUrl.String()), nil
}

func (bundle *Bundle) PlistReader(txn *gorp.Transaction, ipaUrl *url.URL) (io.Reader, error) {
	p, err := bundle.Plist(txn, ipaUrl)
	if err != nil {
		return nil, err
	}

	return p.Reader()
}

func (bundle *Bundle) BuildFileName() string {
	return fmt.Sprintf(
		"app_%d_ver_%s_rev_%d%s",
		bundle.AppId,
		bundle.BundleInfo.Version,
		bundle.Revision,
		bundle.PlatformType.Extention(),
	)
}

func (bundle *Bundle) IsApk() bool {
	var ok bool
	if bundle.PlatformType == BundlePlatformTypeAndroid {
		ok = true
	}
	return ok
}

func (bundle *Bundle) IsIpa() bool {
	var ok bool
	if bundle.PlatformType == BundlePlatformTypeIOS {
		ok = true
	}
	return ok
}

func (bundle *Bundle) App(txn gorp.SqlExecutor) (*App, error) {
	app, err := txn.Get(App{}, bundle.AppId)
	if err != nil {
		return nil, err
	}
	return app.(*App), nil
}

func (bundle *Bundle) PreInsert(s gorp.SqlExecutor) error {
	bundle.BundleVersion = bundle.BundleInfo.Version
	bundle.CreatedAt = time.Now()
	bundle.UpdatedAt = bundle.CreatedAt
	return nil
}

func (bundle *Bundle) PreUpdate(s gorp.SqlExecutor) error {
	bundle.UpdatedAt = time.Now()
	return nil
}

func (bundle *Bundle) Save(txn gorp.SqlExecutor) error {
	return txn.Insert(bundle)
}

func (bundle *Bundle) Update(txn gorp.SqlExecutor) error {
	current, err := GetBundle(txn, bundle.Id)
	if err != nil {
		return err
	}

	current.Description = bundle.Description
	if bundle.FileId != "" {
		current.FileId = bundle.FileId
	}

	_, err = txn.Update(current)
	return err
}

func (bundle *Bundle) DeleteFromDB(txn gorp.SqlExecutor) error {
	_, err := txn.Delete(bundle)
	return err
}

func (bundle *Bundle) DeleteFromGoogleDrive(s *GoogleService) error {
	return s.DeleteFile(bundle.FileId)
}

func (bundle *Bundle) Delete(txn gorp.SqlExecutor, s *GoogleService) error {
	if err := bundle.DeleteFromDB(txn); err != nil {
		return err
	}
	if err := bundle.DeleteFromGoogleDrive(s); err != nil {
		return err
	}
	return nil
}

func CreateBundle(txn gorp.SqlExecutor, bundle *Bundle) error {
	return txn.Insert(bundle)
}

func GetBundle(txn gorp.SqlExecutor, id int) (*Bundle, error) {
	bundle, err := txn.Get(Bundle{}, id)
	if err != nil {
		return nil, err
	}
	return bundle.(*Bundle), nil
}
<commit_msg>*gorp.Transaction -> gorp.SqlExecutor<commit_after>package models

import (
	"fmt"
	"io"
	"net/url"
	"os"
	"time"

	"github.com/coopernurse/gorp"
)

type BundlePlatformType int

const (
	BundlePlatformTypeAndroid BundlePlatformType = 1 + iota
	BundlePlatformTypeIOS
)

func (platformType BundlePlatformType) Extention() BundleFileExtension {
	var ext BundleFileExtension
	if platformType == BundlePlatformTypeAndroid {
		ext = BundleFileExtensionAndroid
	} else if platformType == BundlePlatformTypeIOS {
		ext = BundleFileExtensionIOS
	}
	return ext
}

type BundleFileExtension string

const (
	BundleFileExtensionAndroid BundleFileExtension = ".apk"
	BundleFileExtensionIOS     BundleFileExtension = ".ipa"
)

func (ext BundleFileExtension) IsValid() bool {
	var ok bool
	if ext == BundleFileExtensionAndroid {
		ok = true
	} else if ext == BundleFileExtensionIOS {
		ok = true
	}
	return ok
}

func (ext BundleFileExtension) PlatformType() BundlePlatformType {
	var platformType BundlePlatformType
	if ext == BundleFileExtensionAndroid {
		platformType = BundlePlatformTypeAndroid
	} else if ext == BundleFileExtensionIOS {
		platformType = BundlePlatformTypeIOS
	}
	return platformType
}

type Bundle struct {
	Id            int                `db:"id"`
	AppId         int                `db:"app_id"`
	FileId        string             `db:"file_id"`
	PlatformType  BundlePlatformType `db:"platform_type"`
	BundleVersion string             `db:"bundle_version"`
	Revision      int                `db:"revision"`
	Description   string             `db:"description"`
	CreatedAt     time.Time          `db:"created_at"`
	UpdatedAt     time.Time          `db:"updated_at"`

	BundleInfo *BundleInfo `db:"-"`
	File       *os.File    `db:"-"`
	FileName   string      `db:"-"`
}

type BundleJsonResponse struct {
	FileId     string `json:"file_id"`
	Version    string `json:"version"`
	Revision   int    `json:"revision"`
	InstallUrl string `json:"install_url"`
	QrCodeUrl  string `json:"qr_code_url"`
}

func (bundle *Bundle) JsonResponse(ub UriBuilder) (*BundleJsonResponse, error) {
	installUrl, err := ub.UriFor(fmt.Sprintf("bundle/%d/download", bundle.Id))
	if err != nil {
		return nil, err
	}
	qrCodeUrl, err := ub.UriFor(fmt.Sprintf("bundle/%d", bundle.Id))
	if err != nil {
		return nil, err
	}

	return &BundleJsonResponse{
		FileId:     bundle.FileId,
		Version:    bundle.BundleVersion,
		Revision:   bundle.Revision,
		InstallUrl: installUrl.String(),
		QrCodeUrl:  qrCodeUrl.String(),
	}, nil
}

func (bundle *Bundle) Plist(txn gorp.SqlExecutor, ipaUrl *url.URL) (*Plist, error) {
	app, err := bundle.App(txn)
	if err != nil {
		return nil, err
	}

	return NewPlist(app.Title, bundle.BundleVersion, ipaUrl.String()), nil
}

func (bundle *Bundle) PlistReader(txn gorp.SqlExecutor, ipaUrl *url.URL) (io.Reader, error) {
	p, err := bundle.Plist(txn, ipaUrl)
	if err != nil {
		return nil, err
	}

	return p.Reader()
}

func (bundle *Bundle) BuildFileName() string {
	return fmt.Sprintf(
		"app_%d_ver_%s_rev_%d%s",
		bundle.AppId,
		bundle.BundleInfo.Version,
		bundle.Revision,
		bundle.PlatformType.Extention(),
	)
}

func (bundle *Bundle) IsApk() bool {
	var ok bool
	if bundle.PlatformType == BundlePlatformTypeAndroid {
		ok = true
	}
	return ok
}

func (bundle *Bundle) IsIpa() bool {
	var ok bool
	if bundle.PlatformType == BundlePlatformTypeIOS {
		ok = true
	}
	return ok
}

func (bundle *Bundle) App(txn gorp.SqlExecutor) (*App, error) {
	app, err := txn.Get(App{}, bundle.AppId)
	if err != nil {
		return nil, err
	}
	return app.(*App), nil
}

func (bundle *Bundle) PreInsert(s gorp.SqlExecutor) error {
	bundle.BundleVersion = bundle.BundleInfo.Version
	bundle.CreatedAt = time.Now()
	bundle.UpdatedAt = bundle.CreatedAt
	return nil
}

func (bundle *Bundle) PreUpdate(s gorp.SqlExecutor) error {
	bundle.UpdatedAt = time.Now()
	return nil
}

func (bundle *Bundle) Save(txn gorp.SqlExecutor) error {
	return txn.Insert(bundle)
}

func (bundle *Bundle) Update(txn gorp.SqlExecutor) error {
	current, err := GetBundle(txn, bundle.Id)
	if err != nil {
		return err
	}

	current.Description = bundle.Description
	if bundle.FileId != "" {
		current.FileId = bundle.FileId
	}

	_, err = txn.Update(current)
	return err
}

func (bundle *Bundle) DeleteFromDB(txn gorp.SqlExecutor) error {
	_, err := txn.Delete(bundle)
	return err
}

func (bundle *Bundle) DeleteFromGoogleDrive(s *GoogleService) error {
	return s.DeleteFile(bundle.FileId)
}

func (bundle *Bundle) Delete(txn gorp.SqlExecutor, s *GoogleService) error {
	if err := bundle.DeleteFromDB(txn); err != nil {
		return err
	}
	if err := bundle.DeleteFromGoogleDrive(s); err != nil {
		return err
	}
	return nil
}

func CreateBundle(txn gorp.SqlExecutor, bundle *Bundle) error {
	return txn.Insert(bundle)
}

func GetBundle(txn gorp.SqlExecutor, id int) (*Bundle, error) {
	bundle, err := txn.Get(Bundle{}, id)
	if err != nil {
		return nil, err
	}
	return bundle.(*Bundle), nil
}
<|endoftext|>


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

package main

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

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

// These variables are copied from the gobuilder's environment
// to the envv of its subprocesses.
var extraEnv = []string{
	"GOARM",

	// For Unix derivatives.
	"CC",
	"PATH",
	"TMPDIR",
	"USER",

	// For Plan 9.
	"objtype",
	"cputype",
	"path",
}

// builderEnv represents the environment that a Builder will run tests in.
type builderEnv interface {
	// setup sets up the builder environment and returns the directory to run the buildCmd in.
	setup(repo *Repo, workpath, hash string, envv []string) (string, error)
}

// goEnv represents the builderEnv for the main Go repo.
type goEnv struct {
	goos, goarch string
}

func (b *Builder) envv() []string {
	if runtime.GOOS == "windows" {
		return b.envvWindows()
	}

	var e []string
	if *buildTool == "go" {
		e = []string{
			"GOOS=" + b.goos,
			"GOHOSTOS=" + b.goos,
			"GOARCH=" + b.goarch,
			"GOHOSTARCH=" + b.goarch,
			"GOROOT_FINAL=/usr/local/go",
		}
	}

	for _, k := range extraEnv {
		if s, ok := getenvOk(k); ok {
			e = append(e, k+"="+s)
		}
	}
	return e
}

func (b *Builder) envvWindows() []string {
	var start map[string]string
	if *buildTool == "go" {
		start = map[string]string{
			"GOOS":         b.goos,
			"GOHOSTOS":     b.goos,
			"GOARCH":       b.goarch,
			"GOHOSTARCH":   b.goarch,
			"GOROOT_FINAL": `c:\go`,
			"GOBUILDEXIT":  "1", // exit all.bat with completion status.
		}
	}

	for _, name := range extraEnv {
		if s, ok := getenvOk(name); ok {
			start[name] = s
		}
	}
	skip := map[string]bool{
		"GOBIN":   true,
		"GOROOT":  true,
		"INCLUDE": true,
		"LIB":     true,
	}
	var e []string
	for name, v := range start {
		e = append(e, name+"="+v)
		skip[name] = true
	}
	for _, kv := range os.Environ() {
		s := strings.SplitN(kv, "=", 2)
		name := strings.ToUpper(s[0])
		switch {
		case name == "":
			// variables, like "=C:=C:\", just copy them
			e = append(e, kv)
		case !skip[name]:
			e = append(e, kv)
			skip[name] = true
		}
	}
	return e
}

// setup for a goEnv clones the main go repo to workpath/go at the provided hash
// and returns the path workpath/go/src, the location of all go build scripts.
func (env *goEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
	goworkpath := filepath.Join(workpath, "go")
	if _, err := repo.Clone(goworkpath, hash); err != nil {
		return "", fmt.Errorf("error cloning repository: %s", err)
	}
	return filepath.Join(goworkpath, "src"), nil
}

// gccgoEnv represents the builderEnv for the gccgo compiler.
type gccgoEnv struct{}

// setup for a gccgoEnv clones the gofrontend repo to workpath/go at the hash
// and clones the latest GCC branch to repo.Path/gcc. The gccgo sources are
// replaced with the updated sources in the gofrontend repo and gcc gets
// gets configured and built in workpath/gcc-objdir. The path to
// workpath/gcc-objdir is returned.
func (env *gccgoEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
	gofrontendpath := filepath.Join(workpath, "gofrontend")
	gccpath := filepath.Join(repo.Path, "gcc")
	gccgopath := filepath.Join(gccpath, "gcc", "go", "gofrontend")
	gcclibgopath := filepath.Join(gccpath, "libgo")

	// get a handle to SVN vcs.Cmd for pulling down GCC.
	svn := vcs.ByCmd("svn")

	// only pull down gcc if we don't have a local copy.
	if _, err := os.Stat(gccpath); err != nil {
		if err := timeout(*cmdTimeout, func() error {
			// pull down a working copy of GCC.
			return svn.Create(gccpath, *gccPath)
		}); err != nil {
			return "", err
		}
	} else {
		// make sure to remove gccgopath and gcclibgopath before
		// updating the repo to avoid file clobbering.
		if err := os.RemoveAll(gccgopath); err != nil {
			return "", err
		}
		if err := os.RemoveAll(gcclibgopath); err != nil {
			return "", err
		}
	}
	if err := svn.Download(gccpath); err != nil {
		return "", err
	}

	// clone gofrontend repo at specified revision
	if _, err := repo.Clone(gofrontendpath, hash); err != nil {
		return "", err
	}

	// remove gccgopath and gcclibgopath before copying over gofrontend.
	if err := os.RemoveAll(gccgopath); err != nil {
		return "", err
	}
	if err := os.RemoveAll(gcclibgopath); err != nil {
		return "", err
	}

	// copy gofrontend and libgo to appropriate locations
	if err := copyDir(filepath.Join(gofrontendpath, "go"), gccgopath); err != nil {
		return "", fmt.Errorf("Failed to copy gofrontend/go to gcc/go/gofrontend: %s\n", err)
	}
	if err := copyDir(filepath.Join(gofrontendpath, "libgo"), gcclibgopath); err != nil {
		return "", fmt.Errorf("Failed to copy gofrontend/libgo to gcc/libgo: %s\n", err)
	}

	// make objdir to work in
	gccobjdir := filepath.Join(workpath, "gcc-objdir")
	if err := os.Mkdir(gccobjdir, mkdirPerm); err != nil {
		return "", err
	}

	// configure GCC with substituted gofrontend and libgo
	gccConfigCmd := []string{filepath.Join(gccpath, "configure"), "--enable-languages=c,c++,go", "--disable-bootstrap"}
	if _, err := runOutput(*cmdTimeout, envv, ioutil.Discard, gccobjdir, gccConfigCmd...); err != nil {
		return "", fmt.Errorf("Failed to configure GCC: %s", err)
	}

	// build gcc
	if _, err := runOutput(*buildTimeout, envv, ioutil.Discard, gccobjdir, "make"); err != nil {
		return "", fmt.Errorf("Failed to build GCC: %s", err)
	}

	return gccobjdir, nil
}

// copyDir copies the src directory into the dst
func copyDir(src, dst string) error {
	return filepath.Walk(src, func(path string, f os.FileInfo, err error) error {
		dstPath := strings.Replace(path, src, dst, 1)
		if f.IsDir() {
			return os.Mkdir(dstPath, mkdirPerm)
		}

		srcFile, err := os.Open(path)
		if err != nil {
			return err
		}
		defer srcFile.Close()

		dstFile, err := os.Create(dstPath)
		if err != nil {
			return err
		}

		if _, err := io.Copy(dstFile, srcFile); err != nil {
			return err
		}
		return dstFile.Close()
	})
}

func getenvOk(k string) (v string, ok bool) {
	v = os.Getenv(k)
	if v != "" {
		return v, true
	}
	keq := k + "="
	for _, kv := range os.Environ() {
		if kv == keq {
			return "", true
		}
	}
	return "", false
}
<commit_msg>go.tools/dashboard/builder: ignore GOPATH setting during build (on windows)<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

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

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

// These variables are copied from the gobuilder's environment
// to the envv of its subprocesses.
var extraEnv = []string{
	"GOARM",

	// For Unix derivatives.
	"CC",
	"PATH",
	"TMPDIR",
	"USER",

	// For Plan 9.
	"objtype",
	"cputype",
	"path",
}

// builderEnv represents the environment that a Builder will run tests in.
type builderEnv interface {
	// setup sets up the builder environment and returns the directory to run the buildCmd in.
	setup(repo *Repo, workpath, hash string, envv []string) (string, error)
}

// goEnv represents the builderEnv for the main Go repo.
type goEnv struct {
	goos, goarch string
}

func (b *Builder) envv() []string {
	if runtime.GOOS == "windows" {
		return b.envvWindows()
	}

	var e []string
	if *buildTool == "go" {
		e = []string{
			"GOOS=" + b.goos,
			"GOHOSTOS=" + b.goos,
			"GOARCH=" + b.goarch,
			"GOHOSTARCH=" + b.goarch,
			"GOROOT_FINAL=/usr/local/go",
		}
	}

	for _, k := range extraEnv {
		if s, ok := getenvOk(k); ok {
			e = append(e, k+"="+s)
		}
	}
	return e
}

func (b *Builder) envvWindows() []string {
	var start map[string]string
	if *buildTool == "go" {
		start = map[string]string{
			"GOOS":         b.goos,
			"GOHOSTOS":     b.goos,
			"GOARCH":       b.goarch,
			"GOHOSTARCH":   b.goarch,
			"GOROOT_FINAL": `c:\go`,
			"GOBUILDEXIT":  "1", // exit all.bat with completion status.
		}
	}

	for _, name := range extraEnv {
		if s, ok := getenvOk(name); ok {
			start[name] = s
		}
	}
	skip := map[string]bool{
		"GOBIN":   true,
		"GOPATH":  true,
		"GOROOT":  true,
		"INCLUDE": true,
		"LIB":     true,
	}
	var e []string
	for name, v := range start {
		e = append(e, name+"="+v)
		skip[name] = true
	}
	for _, kv := range os.Environ() {
		s := strings.SplitN(kv, "=", 2)
		name := strings.ToUpper(s[0])
		switch {
		case name == "":
			// variables, like "=C:=C:\", just copy them
			e = append(e, kv)
		case !skip[name]:
			e = append(e, kv)
			skip[name] = true
		}
	}
	return e
}

// setup for a goEnv clones the main go repo to workpath/go at the provided hash
// and returns the path workpath/go/src, the location of all go build scripts.
func (env *goEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
	goworkpath := filepath.Join(workpath, "go")
	if _, err := repo.Clone(goworkpath, hash); err != nil {
		return "", fmt.Errorf("error cloning repository: %s", err)
	}
	return filepath.Join(goworkpath, "src"), nil
}

// gccgoEnv represents the builderEnv for the gccgo compiler.
type gccgoEnv struct{}

// setup for a gccgoEnv clones the gofrontend repo to workpath/go at the hash
// and clones the latest GCC branch to repo.Path/gcc. The gccgo sources are
// replaced with the updated sources in the gofrontend repo and gcc gets
// gets configured and built in workpath/gcc-objdir. The path to
// workpath/gcc-objdir is returned.
func (env *gccgoEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
	gofrontendpath := filepath.Join(workpath, "gofrontend")
	gccpath := filepath.Join(repo.Path, "gcc")
	gccgopath := filepath.Join(gccpath, "gcc", "go", "gofrontend")
	gcclibgopath := filepath.Join(gccpath, "libgo")

	// get a handle to SVN vcs.Cmd for pulling down GCC.
	svn := vcs.ByCmd("svn")

	// only pull down gcc if we don't have a local copy.
	if _, err := os.Stat(gccpath); err != nil {
		if err := timeout(*cmdTimeout, func() error {
			// pull down a working copy of GCC.
			return svn.Create(gccpath, *gccPath)
		}); err != nil {
			return "", err
		}
	} else {
		// make sure to remove gccgopath and gcclibgopath before
		// updating the repo to avoid file clobbering.
		if err := os.RemoveAll(gccgopath); err != nil {
			return "", err
		}
		if err := os.RemoveAll(gcclibgopath); err != nil {
			return "", err
		}
	}
	if err := svn.Download(gccpath); err != nil {
		return "", err
	}

	// clone gofrontend repo at specified revision
	if _, err := repo.Clone(gofrontendpath, hash); err != nil {
		return "", err
	}

	// remove gccgopath and gcclibgopath before copying over gofrontend.
	if err := os.RemoveAll(gccgopath); err != nil {
		return "", err
	}
	if err := os.RemoveAll(gcclibgopath); err != nil {
		return "", err
	}

	// copy gofrontend and libgo to appropriate locations
	if err := copyDir(filepath.Join(gofrontendpath, "go"), gccgopath); err != nil {
		return "", fmt.Errorf("Failed to copy gofrontend/go to gcc/go/gofrontend: %s\n", err)
	}
	if err := copyDir(filepath.Join(gofrontendpath, "libgo"), gcclibgopath); err != nil {
		return "", fmt.Errorf("Failed to copy gofrontend/libgo to gcc/libgo: %s\n", err)
	}

	// make objdir to work in
	gccobjdir := filepath.Join(workpath, "gcc-objdir")
	if err := os.Mkdir(gccobjdir, mkdirPerm); err != nil {
		return "", err
	}

	// configure GCC with substituted gofrontend and libgo
	gccConfigCmd := []string{filepath.Join(gccpath, "configure"), "--enable-languages=c,c++,go", "--disable-bootstrap"}
	if _, err := runOutput(*cmdTimeout, envv, ioutil.Discard, gccobjdir, gccConfigCmd...); err != nil {
		return "", fmt.Errorf("Failed to configure GCC: %s", err)
	}

	// build gcc
	if _, err := runOutput(*buildTimeout, envv, ioutil.Discard, gccobjdir, "make"); err != nil {
		return "", fmt.Errorf("Failed to build GCC: %s", err)
	}

	return gccobjdir, nil
}

// copyDir copies the src directory into the dst
func copyDir(src, dst string) error {
	return filepath.Walk(src, func(path string, f os.FileInfo, err error) error {
		dstPath := strings.Replace(path, src, dst, 1)
		if f.IsDir() {
			return os.Mkdir(dstPath, mkdirPerm)
		}

		srcFile, err := os.Open(path)
		if err != nil {
			return err
		}
		defer srcFile.Close()

		dstFile, err := os.Create(dstPath)
		if err != nil {
			return err
		}

		if _, err := io.Copy(dstFile, srcFile); err != nil {
			return err
		}
		return dstFile.Close()
	})
}

func getenvOk(k string) (v string, ok bool) {
	v = os.Getenv(k)
	if v != "" {
		return v, true
	}
	keq := k + "="
	for _, kv := range os.Environ() {
		if kv == keq {
			return "", true
		}
	}
	return "", false
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/xml"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"strings"
	"time"
)

type XogRead struct {
	Types []struct {
		Type  string `xml:"type,attr"`
		Value string `xml:"value"`
	} `xml:"xogtype"`
	Examples []struct {
		Type  string `xml:"type,attr"`
		Value string `xml:"value"`
	} `xml:"xogExample"`
}

type XogMenu struct {
	Code           string `xml:"code,attr"`
	Action         string `xml:"action,attr"`
	TargetPosition int    `xml:"targetPosition,attr"`
	Links          []struct {
		Code           string `xml:"code,attr"`
		TargetPosition int    `xml:"targetPosition,attr"`
	} `xml:"link"`
}

type XogUnit struct {
	Name             string `xml:"name,attr"`
	ParentName       string `xml:"parentName,attr"`
	RemoveUnitChilds bool   `xml:"removeUnitChilds,attr"`
	Remove           bool   `xml:"remove,attr"`
}

type XogViewSection struct {
	SourceSectionPosition string `xml:"sourceSectionPosition,attr"`
	TargetSectionPosition string `xml:"targetSectionPosition,attr"`
	Action                string `xml:"action,attr"`
	Attributes            []struct {
		Code         string `xml:"code,attr"`
		Column       string `xml:"column,attr"`
		Remove       bool   `xml:"remove,attr"`
		InsertBefore string `xml:"insertBefore,attr"`
	} `xml:"attribute"`
}

type XogViewAction struct {
	Code         string `xml:"code,attr"`
	Remove       bool   `xml:"remove,attr"`
	GroupCode    string `xml:"groupCode,attr"`
	InsertBefore string `xml:"insertBefore,attr"`
}

type XogDriverFile struct {
	Code              string           `xml:"code,attr"`
	Path              string           `xml:"path,attr"`
	Type              string           `xml:"type,attr"`
	ObjCode           string           `xml:"objectCode,attr"`
	SingleView        bool             `xml:"singleView,attr"`
	CopyToView        string           `xml:"copyToView,attr"`
	EnvTarget         string           `xml:"envTarget,attr"`
	IgnoreReading     bool             `xml:"ignoreReading,attr"`
	SourcePartition   string           `xml:"sourcePartition,attr"`
	TargetPartition   string           `xml:"targetPartition,attr"`
	PartitionModel    string           `xml:"partitionModel,attr"`
	OnlyStructure     bool             `xml:"onlyStructure,attr"`
	InsertBefore      string           `xml:"insertBefore,attr"`
	InsertBeforeIndex string           `xml:"insertBeforeIndex,attr"`
	UpdateProgram     bool             `xml:"updateProgram,attr"`
	Sections          []XogViewSection `xml:"section"`
	Actions           []XogViewAction  `xml:"action"`
	Menus             []XogMenu        `xml:"menu"`
	Units             []XogUnit        `xml:"unit"`
	Includes          []struct {
		Type string `xml:"type,attr"`
		Code string `xml:"code,attr"`
	} `xml:"include"`
}

type XogDriver struct {
	Files []XogDriverFile `xml:"file"`
}

type XogEnv struct {
	GlobalVars []struct {
		Name  string `xml:"name,attr"`
		Value string `xml:"value,attr"`
	} `xml:"global>var"`
	Environments []struct {
		Name   string `xml:"name,attr"`
		Params []struct {
			Name  string `xml:"name,attr"`
			Value string `xml:"value,attr"`
		} `xml:"param"`
	} `xml:"environments>env"`
}

var global_env_version = "8.0"
var xog *XogDriver
var env *XogEnv
var readDefault *XogRead
var inputAction, xogDriverFileName string
var envTargetIndex = 0

func main() {

	fmt.Println("")
	fmt.Println("--------------------------------------------")
	fmt.Println("#### Processing XOG Files - Version 1.0 ####")
	fmt.Println("--------------------------------------------")

	env = new(XogEnv)
	xml.Unmarshal(loadFile("xogEnv.xml"), env)

	readDefault = new(XogRead)
	xml.Unmarshal(loadFile("xogRead.xml"), readDefault)

	//read command-line parameters to use in silent mode option
	var driverPath string
	flag.StringVar(&driverPath, "xogdriver", "", "The path to the xog driver file, required for silent mode")
	var create bool
	flag.BoolVar(&create, "create", false, "Create the xog read files")
	var readEnv int
	flag.IntVar(&readEnv, "read", -1, "Read xog from environment")
	var writeEnv int
	flag.IntVar(&writeEnv, "write", -1, "Write xog to environment")
	flag.Parse()

	if driverPath != "" {
		Debug("[CAS-XOG] Silent Mode: \033[92mON\033[0m\n")
	}

	loadXogDriverFile(driverPath)

	fmt.Println("")

	if driverPath != "" {
		if create || readEnv != -1 || writeEnv != -1 {
			if create {
				fmt.Println("[CAS-XOG] Silent Mode - Create XOGs Read files ")
				scanActions("c", -1)
			}
			if readEnv != -1 {
				fmt.Println("[CAS-XOG] Silent Mode - Reading XOGs")
				scanActions("r", readEnv)
			}
			if writeEnv != -1 {
				fmt.Println("[CAS-XOG] Silent Mode - Writing XOGs")
				scanActions("w", writeEnv)
			}
		}
	} else {
		var exit = false
		for {
			exit = scanActions("", -1)
			if exit {
				break
			}
		}
	}
}

func loadXogDriverFile(silentXogDriverPathFile string) {
	//Define xog driver path
	var driverIndex = 0
	xogDriverPath := "drivers/"
	xogDriverFileName = silentXogDriverPathFile

	if silentXogDriverPathFile == "" {
		xogDriverFileList, _ := ioutil.ReadDir(xogDriverPath)

		if len(xogDriverFileList) == 0 {
			Debug("\n[CAS-XOG]\033[91mERROR\033[0m - XogDriver folders or file not found! Press any key to exit...\n")
			scanexit := ""
			fmt.Scanln(&scanexit)
			os.Exit(0)
		}

		fmt.Println("")
		fmt.Println("Available drivers:")
		for k, f := range xogDriverFileList {
			Debug("%d - %s\n", k, f.Name())
		}
		fmt.Print("Choose driver [0]: ")
		var input string = "0"
		fmt.Scanln(&input)

		var err error
		driverIndex, err = strconv.Atoi(input)

		if err != nil || driverIndex < 0 || driverIndex+1 > len(xogDriverFileList) {
			Debug("\n[CAS-XOG]\033[91mERROR\033[0m - Invalid XOG driver! Press any key to exit...\n")
			scanexit := ""
			fmt.Scanln(&scanexit)
			os.Exit(0)
		}

		xogDriverFileName = xogDriverFileList[driverIndex].Name()
	}
	xogDriverPathFile := xogDriverPath + xogDriverFileName

	xog = new(XogDriver)
	xml.Unmarshal(loadFile(xogDriverPathFile), xog)

	Debug("\n[CAS-XOG]\033[92mLoaded XOG Driver file\033[0m: %s\n", xogDriverPathFile)
}

func scanActions(silentAction string, silentEnv int) bool {
	inputAction = silentAction
	var envIndex = silentEnv
	if silentAction == "" {
		//Define action: Write, Read ou Create
		Debug("[CAS-XOG] Using xog driver: \033[96m%s\033[0m\n", xogDriverFileName)
		fmt.Print("Choose action (l = Load new XOG Driver, c = Create XOGs Read files, r = Read XOGs, w = Write XOGs or x = eXit): ")
		fmt.Scanln(&inputAction)

		envIndex = 0
		if inputAction == "w" || inputAction == "r" {
			//Define environment
			fmt.Println("")
			fmt.Println("Available environments:")
			for k, e := range env.Environments {
				Debug("%d - %s\n", k, e.Name)
			}
			fmt.Println("")
			if inputAction == "r" {
				fmt.Print("Choose reading environment [0]: ")
			} else {
				fmt.Print("Choose writing environment [0]: ")
			}
			var input string = "0"
			fmt.Scanln(&input)

			var err error
			envIndex, err = strconv.Atoi(input)

			if err != nil || envIndex < 0 || envIndex+1 > len(env.Environments) {
				Debug("\n[CAS-XOG]\033[91mERROR\033[0m - Invalid environment!\n\n")
				return false
			}

			if inputAction == "w" {
				if envIndex != envTargetIndex {
					Debug("\n[CAS-XOG]\033[93mWARNING\033[0m - Trying to write attributes readed from a different target environment!\n\n")
					fmt.Print("Do you want to continue anyway? (y = Yes, n = No) [y]: ")
					var inputContinue string = "y"
					fmt.Scanln(&inputContinue)
					if inputContinue == "n" || inputContinue != "y" {
						fmt.Println("")
						return false
					}
				}
			}

			if inputAction == "r" {
				fmt.Print("Choose writing environment [0]: ")
				var input string = "0"
				fmt.Scanln(&input)

				var err error
				envTargetIndex, err = strconv.Atoi(input)

				if err != nil || envTargetIndex < 0 || envTargetIndex+1 > len(env.Environments) {
					Debug("\n[CAS-XOG]\033[91mERROR\033[0m - Invalid environment!\n\n")
					return false
				}
			}
		}
	}

	start := time.Now()

	switch strings.ToLower(inputAction) {
	case "w":
		ExecuteXOG(xog, env, envIndex, "write")
	case "r":
		ExecuteXOG(xog, env, envIndex, "read")
	case "c":
		createReadFilesXOG(xog)
	case "l":
		loadXogDriverFile("")
	case "x":
		return true
	default:
		Debug("\n[CAS-XOG]\033[91mERROR\033[0m - Action not implemented!\n\n")
		return false
	}

	elapsed := time.Since(start)

	Debug("\n------------------------------")
	Debug("\n#### Processing concluded ####")
	Debug("\nExecuted in:  %s", elapsed)
	Debug("\n------------------------------\n\n")

	return false
}

func loadFile(path string) []byte {
	xmlFile, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	return xmlFile
}
<commit_msg>Remove envTarget variable<commit_after>package main

import (
	"encoding/xml"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"strings"
	"time"
)

type XogRead struct {
	Types []struct {
		Type  string `xml:"type,attr"`
		Value string `xml:"value"`
	} `xml:"xogtype"`
	Examples []struct {
		Type  string `xml:"type,attr"`
		Value string `xml:"value"`
	} `xml:"xogExample"`
}

type XogMenu struct {
	Code           string `xml:"code,attr"`
	Action         string `xml:"action,attr"`
	TargetPosition int    `xml:"targetPosition,attr"`
	Links          []struct {
		Code           string `xml:"code,attr"`
		TargetPosition int    `xml:"targetPosition,attr"`
	} `xml:"link"`
}

type XogUnit struct {
	Name             string `xml:"name,attr"`
	ParentName       string `xml:"parentName,attr"`
	RemoveUnitChilds bool   `xml:"removeUnitChilds,attr"`
	Remove           bool   `xml:"remove,attr"`
}

type XogViewSection struct {
	SourceSectionPosition string `xml:"sourceSectionPosition,attr"`
	TargetSectionPosition string `xml:"targetSectionPosition,attr"`
	Action                string `xml:"action,attr"`
	Attributes            []struct {
		Code         string `xml:"code,attr"`
		Column       string `xml:"column,attr"`
		Remove       bool   `xml:"remove,attr"`
		InsertBefore string `xml:"insertBefore,attr"`
	} `xml:"attribute"`
}

type XogViewAction struct {
	Code         string `xml:"code,attr"`
	Remove       bool   `xml:"remove,attr"`
	GroupCode    string `xml:"groupCode,attr"`
	InsertBefore string `xml:"insertBefore,attr"`
}

type XogDriverFile struct {
	Code              string           `xml:"code,attr"`
	Path              string           `xml:"path,attr"`
	Type              string           `xml:"type,attr"`
	ObjCode           string           `xml:"objectCode,attr"`
	SingleView        bool             `xml:"singleView,attr"`
	CopyToView        string           `xml:"copyToView,attr"`
	IgnoreReading     bool             `xml:"ignoreReading,attr"`
	SourcePartition   string           `xml:"sourcePartition,attr"`
	TargetPartition   string           `xml:"targetPartition,attr"`
	PartitionModel    string           `xml:"partitionModel,attr"`
	OnlyStructure     bool             `xml:"onlyStructure,attr"`
	InsertBefore      string           `xml:"insertBefore,attr"`
	InsertBeforeIndex string           `xml:"insertBeforeIndex,attr"`
	UpdateProgram     bool             `xml:"updateProgram,attr"`
	Sections          []XogViewSection `xml:"section"`
	Actions           []XogViewAction  `xml:"action"`
	Menus             []XogMenu        `xml:"menu"`
	Units             []XogUnit        `xml:"unit"`
	Includes          []struct {
		Type string `xml:"type,attr"`
		Code string `xml:"code,attr"`
	} `xml:"include"`
}

type XogDriver struct {
	Files []XogDriverFile `xml:"file"`
}

type XogEnv struct {
	GlobalVars []struct {
		Name  string `xml:"name,attr"`
		Value string `xml:"value,attr"`
	} `xml:"global>var"`
	Environments []struct {
		Name   string `xml:"name,attr"`
		Params []struct {
			Name  string `xml:"name,attr"`
			Value string `xml:"value,attr"`
		} `xml:"param"`
	} `xml:"environments>env"`
}

var global_env_version = "8.0"
var xog *XogDriver
var env *XogEnv
var readDefault *XogRead
var inputAction, xogDriverFileName string
var envTargetIndex = 0

func main() {

	fmt.Println("")
	fmt.Println("--------------------------------------------")
	fmt.Println("#### Processing XOG Files - Version 1.0 ####")
	fmt.Println("--------------------------------------------")

	env = new(XogEnv)
	xml.Unmarshal(loadFile("xogEnv.xml"), env)

	readDefault = new(XogRead)
	xml.Unmarshal(loadFile("xogRead.xml"), readDefault)

	//read command-line parameters to use in silent mode option
	var driverPath string
	flag.StringVar(&driverPath, "xogdriver", "", "The path to the xog driver file, required for silent mode")
	var create bool
	flag.BoolVar(&create, "create", false, "Create the xog read files")
	var readEnv int
	flag.IntVar(&readEnv, "read", -1, "Read xog from environment")
	var writeEnv int
	flag.IntVar(&writeEnv, "write", -1, "Write xog to environment")
	flag.Parse()

	if driverPath != "" {
		Debug("[CAS-XOG] Silent Mode: \033[92mON\033[0m\n")
	}

	loadXogDriverFile(driverPath)

	fmt.Println("")

	if driverPath != "" {
		if create || readEnv != -1 || writeEnv != -1 {
			if create {
				fmt.Println("[CAS-XOG] Silent Mode - Create XOGs Read files ")
				scanActions("c", -1)
			}
			if readEnv != -1 {
				fmt.Println("[CAS-XOG] Silent Mode - Reading XOGs")
				scanActions("r", readEnv)
			}
			if writeEnv != -1 {
				fmt.Println("[CAS-XOG] Silent Mode - Writing XOGs")
				scanActions("w", writeEnv)
			}
		}
	} else {
		var exit = false
		for {
			exit = scanActions("", -1)
			if exit {
				break
			}
		}
	}
}

func loadXogDriverFile(silentXogDriverPathFile string) {
	//Define xog driver path
	var driverIndex = 0
	xogDriverPath := "drivers/"
	xogDriverFileName = silentXogDriverPathFile

	if silentXogDriverPathFile == "" {
		xogDriverFileList, _ := ioutil.ReadDir(xogDriverPath)

		if len(xogDriverFileList) == 0 {
			Debug("\n[CAS-XOG]\033[91mERROR\033[0m - XogDriver folders or file not found! Press any key to exit...\n")
			scanexit := ""
			fmt.Scanln(&scanexit)
			os.Exit(0)
		}

		fmt.Println("")
		fmt.Println("Available drivers:")
		for k, f := range xogDriverFileList {
			Debug("%d - %s\n", k, f.Name())
		}
		fmt.Print("Choose driver [0]: ")
		var input string = "0"
		fmt.Scanln(&input)

		var err error
		driverIndex, err = strconv.Atoi(input)

		if err != nil || driverIndex < 0 || driverIndex+1 > len(xogDriverFileList) {
			Debug("\n[CAS-XOG]\033[91mERROR\033[0m - Invalid XOG driver! Press any key to exit...\n")
			scanexit := ""
			fmt.Scanln(&scanexit)
			os.Exit(0)
		}

		xogDriverFileName = xogDriverFileList[driverIndex].Name()
	}
	xogDriverPathFile := xogDriverPath + xogDriverFileName

	xog = new(XogDriver)
	xml.Unmarshal(loadFile(xogDriverPathFile), xog)

	Debug("\n[CAS-XOG]\033[92mLoaded XOG Driver file\033[0m: %s\n", xogDriverPathFile)
}

func scanActions(silentAction string, silentEnv int) bool {
	inputAction = silentAction
	var envIndex = silentEnv
	if silentAction == "" {
		//Define action: Write, Read ou Create
		Debug("[CAS-XOG] Using xog driver: \033[96m%s\033[0m\n", xogDriverFileName)
		fmt.Print("Choose action (l = Load new XOG Driver, c = Create XOGs Read files, r = Read XOGs, w = Write XOGs or x = eXit): ")
		fmt.Scanln(&inputAction)

		envIndex = 0
		if inputAction == "w" || inputAction == "r" {
			//Define environment
			fmt.Println("")
			fmt.Println("Available environments:")
			for k, e := range env.Environments {
				Debug("%d - %s\n", k, e.Name)
			}
			fmt.Println("")
			if inputAction == "r" {
				fmt.Print("Choose reading environment [0]: ")
			} else {
				fmt.Print("Choose writing environment [0]: ")
			}
			var input string = "0"
			fmt.Scanln(&input)

			var err error
			envIndex, err = strconv.Atoi(input)

			if err != nil || envIndex < 0 || envIndex+1 > len(env.Environments) {
				Debug("\n[CAS-XOG]\033[91mERROR\033[0m - Invalid environment!\n\n")
				return false
			}

			if inputAction == "w" {
				if envIndex != envTargetIndex {
					Debug("\n[CAS-XOG]\033[93mWARNING\033[0m - Trying to write attributes readed from a different target environment!\n\n")
					fmt.Print("Do you want to continue anyway? (y = Yes, n = No) [y]: ")
					var inputContinue string = "y"
					fmt.Scanln(&inputContinue)
					if inputContinue == "n" || inputContinue != "y" {
						fmt.Println("")
						return false
					}
				}
			}

			if inputAction == "r" {
				fmt.Print("Choose writing environment [0]: ")
				var input string = "0"
				fmt.Scanln(&input)

				var err error
				envTargetIndex, err = strconv.Atoi(input)

				if err != nil || envTargetIndex < 0 || envTargetIndex+1 > len(env.Environments) {
					Debug("\n[CAS-XOG]\033[91mERROR\033[0m - Invalid environment!\n\n")
					return false
				}
			}
		}
	}

	start := time.Now()

	switch strings.ToLower(inputAction) {
	case "w":
		ExecuteXOG(xog, env, envIndex, "write")
	case "r":
		ExecuteXOG(xog, env, envIndex, "read")
	case "c":
		createReadFilesXOG(xog)
	case "l":
		loadXogDriverFile("")
	case "x":
		return true
	default:
		Debug("\n[CAS-XOG]\033[91mERROR\033[0m - Action not implemented!\n\n")
		return false
	}

	elapsed := time.Since(start)

	Debug("\n------------------------------")
	Debug("\n#### Processing concluded ####")
	Debug("\nExecuted in:  %s", elapsed)
	Debug("\n------------------------------\n\n")

	return false
}

func loadFile(path string) []byte {
	xmlFile, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	return xmlFile
}
<|endoftext|>


<commit_before>// Copyright 2015 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 bigquery

import (
	"errors"
	"fmt"
	"reflect"
	"testing"

	"golang.org/x/net/context"
)

type fetchCall struct {
	tok    string          // The expected value of the pageToken.
	result *readDataResult // The result to return.
	err    error           // The error to return.
}

// cursorStub services fetch requests by returning data from an in-memory list of values.
type cursorStub struct {
	token string

	fetchCalls []fetchCall

	err error
}

func (cur *cursorStub) fetch(ctx context.Context, c *Client, token string) (*readDataResult, error) {
	call := cur.fetchCalls[0]
	cur.fetchCalls = cur.fetchCalls[1:]
	if call.tok != token {
		cur.err = fmt.Errorf("Unexpected pagetoken: got:\n%v\nwant:\n%v", token, call.tok)
	}
	return call.result, call.err
}

func TestIterator(t *testing.T) {
	fetchFailure := errors.New("fetch failure")

	testCases := []struct {
		desc            string
		alreadyConsumed int64 // amount to advance offset before commencing reading.
		fetchCalls      []fetchCall
		want            []ValueList
		wantErr         error
	}{
		{
			desc: "Iteration over single empty page",
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{},
					},
				},
			},
			want: []ValueList{},
		},
		{
			desc: "Iteration over single page",
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
			},
			want: []ValueList{{1, 2}, {11, 12}},
		},
		{
			desc: "Iteration over two pages",
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			want: []ValueList{{1, 2}, {11, 12}, {101, 102}, {111, 112}},
		},
		{
			desc: "Server response includes empty page",
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					result: &readDataResult{
						pageToken: "b",
						rows:      [][]Value{},
					},
				},
				{
					tok: "b",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			want: []ValueList{{1, 2}, {11, 12}, {101, 102}, {111, 112}},
		},
		{
			desc: "Fetch error",
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					// We returns some data from this fetch, but also an error.
					// So the end result should include only data from the previous fetch.
					err: fetchFailure,
					result: &readDataResult{
						pageToken: "b",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			want:    []ValueList{{1, 2}, {11, 12}},
			wantErr: fetchFailure,
		},
		{
			desc: "Fetch of incomplete job",
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					err: errIncompleteJob,
				},
				{
					tok: "a",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			want: []ValueList{{1, 2}, {11, 12}, {101, 102}, {111, 112}},
		},
		{
			desc:            "Skip over a single element",
			alreadyConsumed: 1,
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			want: []ValueList{{11, 12}, {101, 102}, {111, 112}},
		},
		{
			desc:            "Skip over an entire page",
			alreadyConsumed: 2,
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			want: []ValueList{{101, 102}, {111, 112}},
		},
		{
			desc:            "Skip beyond start of second page",
			alreadyConsumed: 3,
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			want: []ValueList{{111, 112}},
		},
		{
			desc:            "Skip beyond all data",
			alreadyConsumed: 4,
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			// In this test case, Next will return false on its first call,
			// so we won't even attempt to call Get.
			want: []ValueList{},
		},
	}

	for _, tc := range testCases {
		cursor := &cursorStub{
			fetchCalls: tc.fetchCalls,
		}
		it := newIterator(nil, cursor)
		it.offset += tc.alreadyConsumed

		values, err := consumeIterator(it)
		if err != nil {
			t.Fatalf("%s: %v", tc.desc, err)
		}

		if !(len(values) == 0 && len(tc.want) == 0) && !reflect.DeepEqual(values, tc.want) {
			t.Errorf("%s: values:\ngot: %v\nwant:%v", tc.desc, values, tc.want)
		}
		if it.Err() != tc.wantErr {
			t.Errorf("%s: iterator.Err:\ngot: %v\nwant: %v", tc.desc, it.Err(), tc.wantErr)
		}

		// Check whether there was an unexpected call to fetch.
		if cursor.err != nil {
			t.Errorf("%s: %v", tc.desc, cursor.err)
		}
		// Check whether any expected calls to fetch were not made.
		if len(cursor.fetchCalls) != 0 {
			t.Errorf("%s: outstanding fetchCalls: %v", tc.desc, cursor.fetchCalls)
		}
	}
}

// consumeIterator reads all values from an iterator and returns them.
func consumeIterator(it *Iterator) ([]ValueList, error) {
	var got []ValueList
	for it.Next(context.Background()) {
		var vals ValueList
		if err := it.Get(&vals); err != nil {
			return nil, fmt.Errorf("err calling Get: %v", err)
		} else {
			got = append(got, vals)
		}
	}

	return got, nil
}

func TestGetBeforeNext(t *testing.T) {
	// TODO: once mashalling/unmarshalling of iterators is implemented, do a similar test for unmarshalled iterators.
	cursor := &cursorStub{
		fetchCalls: []fetchCall{
			{
				tok: "",
				result: &readDataResult{
					pageToken: "",
					rows:      [][]Value{{1, 2}, {11, 12}},
				},
			},
		},
	}
	it := newIterator(nil, cursor)
	var vals ValueList
	if err := it.Get(&vals); err == nil {
		t.Errorf("Expected error calling Get before Next")
	}
}

func TestGetDuringErrorState(t *testing.T) {
	cursor := &cursorStub{
		fetchCalls: []fetchCall{
			{err: errors.New("bang")},
		},
	}
	it := newIterator(nil, cursor)
	var vals ValueList
	it.Next(context.Background())
	if it.Err() == nil {
		t.Errorf("Expected error after calling Next")
	}
	if err := it.Get(&vals); err == nil {
		t.Errorf("Expected error calling Get when iterator has a non-nil error.")
	}
}

func TestGetAfterFinished(t *testing.T) {
	testCases := []struct {
		alreadyConsumed int64 // amount to advance offset before commencing reading.
		fetchCalls      []fetchCall
		want            []ValueList
	}{
		{
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
			},
			want: []ValueList{{1, 2}, {11, 12}},
		},
		{
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{},
					},
				},
			},
			want: []ValueList{},
		},
		{
			alreadyConsumed: 100,
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
			},
			want: []ValueList{},
		},
	}

	for _, tc := range testCases {
		cursor := &cursorStub{
			fetchCalls: tc.fetchCalls,
		}
		it := newIterator(nil, cursor)
		it.offset += tc.alreadyConsumed

		values, err := consumeIterator(it)
		if err != nil {
			t.Fatalf("%s", err)
		}

		if !(len(values) == 0 && len(tc.want) == 0) && !reflect.DeepEqual(values, tc.want) {
			t.Errorf("values: got:\n%v\nwant:\n%v", values, tc.want)
		}
		if it.Err() != nil {
			t.Fatalf("iterator.Err: got:\n%v\nwant:\n:nil", it.Err())
		}
		// Try calling Get again.
		var vals ValueList
		if err := it.Get(&vals); err == nil {
			t.Errorf("Expected error calling Get when there are no more values")
		}
	}
}
<commit_msg>cloud/bigquery: Rename cursor to pageFetcher in iterator test.<commit_after>// Copyright 2015 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 bigquery

import (
	"errors"
	"fmt"
	"reflect"
	"testing"

	"golang.org/x/net/context"
)

type fetchCall struct {
	tok    string          // The expected value of the pageToken.
	result *readDataResult // The result to return.
	err    error           // The error to return.
}

// pageFetcherStub services fetch requests by returning data from an in-memory list of values.
type pageFetcherStub struct {
	token string

	fetchCalls []fetchCall

	err error
}

func (cur *pageFetcherStub) fetch(ctx context.Context, c *Client, token string) (*readDataResult, error) {
	call := cur.fetchCalls[0]
	cur.fetchCalls = cur.fetchCalls[1:]
	if call.tok != token {
		cur.err = fmt.Errorf("Unexpected pagetoken: got:\n%v\nwant:\n%v", token, call.tok)
	}
	return call.result, call.err
}

func TestIterator(t *testing.T) {
	fetchFailure := errors.New("fetch failure")

	testCases := []struct {
		desc            string
		alreadyConsumed int64 // amount to advance offset before commencing reading.
		fetchCalls      []fetchCall
		want            []ValueList
		wantErr         error
	}{
		{
			desc: "Iteration over single empty page",
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{},
					},
				},
			},
			want: []ValueList{},
		},
		{
			desc: "Iteration over single page",
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
			},
			want: []ValueList{{1, 2}, {11, 12}},
		},
		{
			desc: "Iteration over two pages",
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			want: []ValueList{{1, 2}, {11, 12}, {101, 102}, {111, 112}},
		},
		{
			desc: "Server response includes empty page",
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					result: &readDataResult{
						pageToken: "b",
						rows:      [][]Value{},
					},
				},
				{
					tok: "b",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			want: []ValueList{{1, 2}, {11, 12}, {101, 102}, {111, 112}},
		},
		{
			desc: "Fetch error",
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					// We returns some data from this fetch, but also an error.
					// So the end result should include only data from the previous fetch.
					err: fetchFailure,
					result: &readDataResult{
						pageToken: "b",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			want:    []ValueList{{1, 2}, {11, 12}},
			wantErr: fetchFailure,
		},
		{
			desc: "Fetch of incomplete job",
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					err: errIncompleteJob,
				},
				{
					tok: "a",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			want: []ValueList{{1, 2}, {11, 12}, {101, 102}, {111, 112}},
		},
		{
			desc:            "Skip over a single element",
			alreadyConsumed: 1,
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			want: []ValueList{{11, 12}, {101, 102}, {111, 112}},
		},
		{
			desc:            "Skip over an entire page",
			alreadyConsumed: 2,
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			want: []ValueList{{101, 102}, {111, 112}},
		},
		{
			desc:            "Skip beyond start of second page",
			alreadyConsumed: 3,
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			want: []ValueList{{111, 112}},
		},
		{
			desc:            "Skip beyond all data",
			alreadyConsumed: 4,
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "a",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
				{
					tok: "a",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{101, 102}, {111, 112}},
					},
				},
			},
			// In this test case, Next will return false on its first call,
			// so we won't even attempt to call Get.
			want: []ValueList{},
		},
	}

	for _, tc := range testCases {
		pf := &pageFetcherStub{
			fetchCalls: tc.fetchCalls,
		}
		it := newIterator(nil, pf)
		it.offset += tc.alreadyConsumed

		values, err := consumeIterator(it)
		if err != nil {
			t.Fatalf("%s: %v", tc.desc, err)
		}

		if !(len(values) == 0 && len(tc.want) == 0) && !reflect.DeepEqual(values, tc.want) {
			t.Errorf("%s: values:\ngot: %v\nwant:%v", tc.desc, values, tc.want)
		}
		if it.Err() != tc.wantErr {
			t.Errorf("%s: iterator.Err:\ngot: %v\nwant: %v", tc.desc, it.Err(), tc.wantErr)
		}

		// Check whether there was an unexpected call to fetch.
		if pf.err != nil {
			t.Errorf("%s: %v", tc.desc, pf.err)
		}
		// Check whether any expected calls to fetch were not made.
		if len(pf.fetchCalls) != 0 {
			t.Errorf("%s: outstanding fetchCalls: %v", tc.desc, pf.fetchCalls)
		}
	}
}

// consumeIterator reads all values from an iterator and returns them.
func consumeIterator(it *Iterator) ([]ValueList, error) {
	var got []ValueList
	for it.Next(context.Background()) {
		var vals ValueList
		if err := it.Get(&vals); err != nil {
			return nil, fmt.Errorf("err calling Get: %v", err)
		} else {
			got = append(got, vals)
		}
	}

	return got, nil
}

func TestGetBeforeNext(t *testing.T) {
	// TODO: once mashalling/unmarshalling of iterators is implemented, do a similar test for unmarshalled iterators.
	pf := &pageFetcherStub{
		fetchCalls: []fetchCall{
			{
				tok: "",
				result: &readDataResult{
					pageToken: "",
					rows:      [][]Value{{1, 2}, {11, 12}},
				},
			},
		},
	}
	it := newIterator(nil, pf)
	var vals ValueList
	if err := it.Get(&vals); err == nil {
		t.Errorf("Expected error calling Get before Next")
	}
}

func TestGetDuringErrorState(t *testing.T) {
	pf := &pageFetcherStub{
		fetchCalls: []fetchCall{
			{err: errors.New("bang")},
		},
	}
	it := newIterator(nil, pf)
	var vals ValueList
	it.Next(context.Background())
	if it.Err() == nil {
		t.Errorf("Expected error after calling Next")
	}
	if err := it.Get(&vals); err == nil {
		t.Errorf("Expected error calling Get when iterator has a non-nil error.")
	}
}

func TestGetAfterFinished(t *testing.T) {
	testCases := []struct {
		alreadyConsumed int64 // amount to advance offset before commencing reading.
		fetchCalls      []fetchCall
		want            []ValueList
	}{
		{
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
			},
			want: []ValueList{{1, 2}, {11, 12}},
		},
		{
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{},
					},
				},
			},
			want: []ValueList{},
		},
		{
			alreadyConsumed: 100,
			fetchCalls: []fetchCall{
				{
					tok: "",
					result: &readDataResult{
						pageToken: "",
						rows:      [][]Value{{1, 2}, {11, 12}},
					},
				},
			},
			want: []ValueList{},
		},
	}

	for _, tc := range testCases {
		pf := &pageFetcherStub{
			fetchCalls: tc.fetchCalls,
		}
		it := newIterator(nil, pf)
		it.offset += tc.alreadyConsumed

		values, err := consumeIterator(it)
		if err != nil {
			t.Fatalf("%s", err)
		}

		if !(len(values) == 0 && len(tc.want) == 0) && !reflect.DeepEqual(values, tc.want) {
			t.Errorf("values: got:\n%v\nwant:\n%v", values, tc.want)
		}
		if it.Err() != nil {
			t.Fatalf("iterator.Err: got:\n%v\nwant:\n:nil", it.Err())
		}
		// Try calling Get again.
		var vals ValueList
		if err := it.Get(&vals); err == nil {
			t.Errorf("Expected error calling Get when there are no more values")
		}
	}
}
<|endoftext|>


<commit_before>// Package ode provides the Euler-Forward and Runge-Kutta
// Method for solving ordinary differential equations.
package ode

// EulerForward is an implementation of the implicit Euler method.
func EulerForward(from, h, to float64, y []float64, fn func(float64, []float64) []float64) [][]float64 {
	var steps = int((to-from)/h) + 1
	var parameters = len(y)
	var t = from
	yn := make([]float64, parameters)

	// initialize 'outer slice'
	ySlice := make([][]float64, steps)
	// initialize first 'inner slice'
	ySlice[0] = make([]float64, parameters+1)

	// fill with start values
	ySlice[0][0] = t
	for i := 0; i < parameters; i++ {
		ySlice[0][i+1] = y[i]
	}

	for step := 1; step < steps; step++ {
		t = h*float64(step) + from
		// initialize 'inner slice'
		ySlice[step] = make([]float64, parameters+1)
		ySlice[step][0] = t

		for value := 0; value < parameters; value++ {
			yn[value] = ySlice[step-1][value+1]
		}

		for value := 0; value < parameters; value++ {
			//y[value] += h * fn(t, yn)[value]
			ySlice[step][value+1] = ySlice[step-1][value+1] + h*fn(t, yn)[value]
		}
	}
	return ySlice
}

// RungeKutta4 is an implementation of the 4th order Runge-Kutta method.
func RungeKutta4(from, h, to float64, y []float64, fn func(float64, []float64) []float64) [][]float64 {
	var steps = int((to-from)/h) + 1
	var parameters = len(y)
	var t = from

	// initialize 'outer slice'
	ySlice := make([][]float64, steps)
	// initialize first 'inner slice'
	ySlice[0] = make([]float64, parameters+1)

	// fill with start values
	ySlice[0][0] = t
	for i := 0; i < parameters; i++ {
		ySlice[0][i+1] = y[i]
	}

	var k1 = make([]float64, parameters)
	var k2 = make([]float64, parameters)
	var k3 = make([]float64, parameters)
	var k4 = make([]float64, parameters)

	var yn = make([]float64, parameters)

	// the parameters to pass into the corresponding function calls
	var k2p = make([]float64, parameters)
	var k3p = make([]float64, parameters)
	var k4p = make([]float64, parameters)

	for step := 1; step < steps; step++ {
		// initialize 'inner slice'
		ySlice[step] = make([]float64, parameters+1)

		// get last yn from the slice to make the rest of the function shorter
		for value := 0; value < parameters; value++ {
			yn[value] = ySlice[step-1][value+1]
		}

		// generate k1
		for value := 0; value < parameters; value++ {
			k1[value] = fn(t, yn)[value]
		}

		t = float64(step-1)*h + h/2 + from

		// generate the parameter for k2
		for value := 0; value < parameters; value++ {
			k2p[value] = yn[value] + 0.5*h*k1[value]
		}

		// generate k2
		for value := 0; value < parameters; value++ {
			k2[value] = fn(t, k2p)[value]
		}

		// generate the parameter for k3
		for value := 0; value < parameters; value++ {
			k3p[value] = yn[value] + 0.5*h*k2[value]
		}

		// generate k3
		for value := 0; value < parameters; value++ {
			k3[value] = fn(t, k3p)[value]
		}

		// generate the parameter for k4
		for value := 0; value < parameters; value++ {
			k4p[value] = yn[value] + h*fn(t, k3p)[value]
		}

		t = float64(step)*h + from

		// generate k4
		for value := 0; value < parameters; value++ {
			k4[value] = fn(t, k4p)[value]
		}

		ySlice[step][0] = h*float64(step) + from

		// generate yn (saved in the slice)
		for value := 0; value < parameters; value++ {
			ySlice[step][value+1] = ySlice[step-1][value+1] + h*(k1[value]+2*k2[value]+2*k3[value]+k4[value])/6.0
		}
	}
	return ySlice
}
<commit_msg>explicit ...<commit_after>// Package ode provides the Euler-Forward and Runge-Kutta
// Method for solving ordinary differential equations.
package ode

// EulerForward is an implementation of the explicit Euler method.
func EulerForward(from, h, to float64, y []float64, fn func(float64, []float64) []float64) [][]float64 {
	var steps = int((to-from)/h) + 1
	var parameters = len(y)
	var t = from
	yn := make([]float64, parameters)

	// initialize 'outer slice'
	ySlice := make([][]float64, steps)
	// initialize first 'inner slice'
	ySlice[0] = make([]float64, parameters+1)

	// fill with start values
	ySlice[0][0] = t
	for i := 0; i < parameters; i++ {
		ySlice[0][i+1] = y[i]
	}

	for step := 1; step < steps; step++ {
		t = h*float64(step) + from
		// initialize 'inner slice'
		ySlice[step] = make([]float64, parameters+1)
		ySlice[step][0] = t

		for value := 0; value < parameters; value++ {
			yn[value] = ySlice[step-1][value+1]
		}

		for value := 0; value < parameters; value++ {
			//y[value] += h * fn(t, yn)[value]
			ySlice[step][value+1] = ySlice[step-1][value+1] + h*fn(t, yn)[value]
		}
	}
	return ySlice
}

// RungeKutta4 is an implementation of the 4th order Runge-Kutta method.
func RungeKutta4(from, h, to float64, y []float64, fn func(float64, []float64) []float64) [][]float64 {
	var steps = int((to-from)/h) + 1
	var parameters = len(y)
	var t = from

	// initialize 'outer slice'
	ySlice := make([][]float64, steps)
	// initialize first 'inner slice'
	ySlice[0] = make([]float64, parameters+1)

	// fill with start values
	ySlice[0][0] = t
	for i := 0; i < parameters; i++ {
		ySlice[0][i+1] = y[i]
	}

	var k1 = make([]float64, parameters)
	var k2 = make([]float64, parameters)
	var k3 = make([]float64, parameters)
	var k4 = make([]float64, parameters)

	var yn = make([]float64, parameters)

	// the parameters to pass into the corresponding function calls
	var k2p = make([]float64, parameters)
	var k3p = make([]float64, parameters)
	var k4p = make([]float64, parameters)

	for step := 1; step < steps; step++ {
		// initialize 'inner slice'
		ySlice[step] = make([]float64, parameters+1)

		// get last yn from the slice to make the rest of the function shorter
		for value := 0; value < parameters; value++ {
			yn[value] = ySlice[step-1][value+1]
		}

		// generate k1
		for value := 0; value < parameters; value++ {
			k1[value] = fn(t, yn)[value]
		}

		t = float64(step-1)*h + h/2 + from

		// generate the parameter for k2
		for value := 0; value < parameters; value++ {
			k2p[value] = yn[value] + 0.5*h*k1[value]
		}

		// generate k2
		for value := 0; value < parameters; value++ {
			k2[value] = fn(t, k2p)[value]
		}

		// generate the parameter for k3
		for value := 0; value < parameters; value++ {
			k3p[value] = yn[value] + 0.5*h*k2[value]
		}

		// generate k3
		for value := 0; value < parameters; value++ {
			k3[value] = fn(t, k3p)[value]
		}

		// generate the parameter for k4
		for value := 0; value < parameters; value++ {
			k4p[value] = yn[value] + h*fn(t, k3p)[value]
		}

		t = float64(step)*h + from

		// generate k4
		for value := 0; value < parameters; value++ {
			k4[value] = fn(t, k4p)[value]
		}

		ySlice[step][0] = h*float64(step) + from

		// generate yn (saved in the slice)
		for value := 0; value < parameters; value++ {
			ySlice[step][value+1] = ySlice[step-1][value+1] + h*(k1[value]+2*k2[value]+2*k3[value]+k4[value])/6.0
		}
	}
	return ySlice
}
<|endoftext|>


<commit_before>package orm

import (
	"database/sql"
	"errors"
	"fmt"
	"log"
	"reflect"
	"strings"
)

var dbHive map[string]*sql.DB = make(map[string]*sql.DB)

//create new database
func NewDatabase(dbname, dbtype, url string) {
	db, err := sql.Open(dbtype, url)
	if err != nil {
		panic(err.Error())
	}
	err = db.Ping()
	if err != nil {
		panic(err.Error())
	}
	dbHive[dbname] = db
}

//module
type Module struct {
	columnstr string //select field
	tableName string //table
	filters   string //condition
	orderby   string //orderby
	limit     string //limit
	join      string //join
	pk        string //pk
	dbname    string //dbname
}

//create new Module
func NewModule(tableName string) *Module {
	m := &Module{tableName: tableName, columnstr: "*", dbname: "default", pk: "id"}
	return m
}

func (m *Module) Clean() *Module {
	m.columnstr = "*"
	m.filters = ""
	m.orderby = ""
	m.limit = ""
	m.join = ""
	m.pk = "id"
	return m
}

func (m *Module) GetDB() *sql.DB {
	return dbHive[m.dbname]
}

//change db
func (m *Module) User(dbname string) *Module {
	m.dbname = dbname
	return m
}

//select fields
func (m *Module) Select(fields ...string) *Module {
	m.columnstr = ""
	for _, f := range fields {
		m.columnstr = m.columnstr + f + ","
	}
	return m
}

//Filter
func (m *Module) Filter(param ...interface{}) *Module {
	for _, p := range param {
		m.filters += fmt.Sprintf("%v", p)
	}
	return m
}

//orderBy
func (m *Module) OrderBy(param string) *Module {
	m.orderby = fmt.Sprintf("ORDER By %v", param)
	return m
}

//limit
func (m *Module) Limit(size ...int) *Module {
	if len(size) > 1 {
		m.limit = fmt.Sprintf("Limit %d,%d", size[0], size[1])
		return m
	} else {
		m.limit = fmt.Sprintf("Limit %d", size[0])
		return m
	}
}

//leftJoin
func (m *Module) LeftJoin(table, condition string) *Module {
	m.join = fmt.Sprintf("LEFT JOIN %v ON %v", table, condition)
	return m
}

//rightJoin
func (m *Module) RightJoin(table, condition string) *Module {
	m.join = fmt.Sprintf("RIGHT JOIN %v ON %v", table, condition)
	return m
}

//join
func (m *Module) Join(table, condition string) *Module {
	m.join = fmt.Sprintf("INNER JOIN %v ON %v", table, condition)
	return m
}

//fulljoin
func (m *Module) FullJoin(table, condition string) *Module {
	m.join = fmt.Sprintf("FULL JOIN %v ON %v", table, condition)
	return m
}

func (m *Module) getSqlString() string {
	columnstr := m.columnstr
	if l := len(columnstr); l > 1 {
		columnstr = columnstr[:l-1]
	}
	query := m.buildSql(columnstr)
	query += " " + m.limit
	log.Println("sql = ", query)
	return query
}

func (m *Module) buildSql(columnstr string) string {
	where := m.filters
	where = strings.TrimSpace(where)
	if len(where) > 0 {
		where = "where " + where
	}
	query := fmt.Sprintf("select %v from %v %v %v %v", columnstr, m.tableName, m.join, where, m.orderby)
	return query
}

func (m *Module) QueryPage(page *Page, callBackFunc func(*sql.Rows)) error {
	db := dbHive[m.dbname]
	m.Limit(page.StartRow(), page.PageSize)
	query := m.buildSql("count(*)")
	row := db.QueryRow(query)
	err := row.Scan(&page.ResultCount)
	if err != nil {
		return err
	}
	rows, err := db.Query(m.getSqlString())
	if err != nil {
		return err
	}
	defer rows.Close()
	callBackFunc(rows)
	return nil
}

func (m *Module) Query(callBackFunc func(*sql.Rows)) error {
	db := dbHive[m.dbname]
	rows, err := db.Query(m.getSqlString())
	if err != nil {
		return err
	}
	defer rows.Close()
	callBackFunc(rows)
	return nil
}
func (m *Module) QueryOne(callBackFunc func(*sql.Row)) {
	db := dbHive[m.dbname]
	row := db.QueryRow(m.getSqlString())
	callBackFunc(row)
}

func (m *Module) IsExist() (bool, error) {
	count, err := m.Count()
	if count > 0 {
		return true, nil
	}
	return false, err
}

func (m *Module) Count() (int, error) {
	db := dbHive[m.dbname]
	query := m.buildSql("count(*)")
	log.Println("sql = ", query)
	row := db.QueryRow(query)
	var count int
	err := row.Scan(&count)
	return count, err
}

func (m *Module) OneRecord() (record Record, err error) {
	rs, err := m.Limit(1).AllRecords()
	if err != nil {
		return record, err
	}
	if len(rs) == 0 {
		return NewRecord(), errors.New("not fond record")
	}
	return rs[0], nil
}

func (m *Module) AllRecords() ([]Record, error) {
	db := dbHive[m.dbname]
	rows, err := db.Query(m.getSqlString())
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	records := make([]Record, 0)
	columns, _ := rows.Columns()
	values := make([]sql.RawBytes, len(columns))
	scanargs := make([]interface{}, len(values))
	for i := range values {
		scanargs[i] = &values[i]
	}
	for rows.Next() {
		err := rows.Scan(scanargs...)
		if err != nil {
			fmt.Println(err)
		}
		record := NewRecord()
		for i, v := range values {
			record.result[columns[i]] = v
		}
		records = append(records, record)
	}
	return records, nil
}
func (m *Module) SetPK(pk string) *Module {
	m.pk = pk
	return m
}

func (m *Module) FindRecordById(id int) *Module {
	m.Filter(m.pk, "=", id)
	return m
}

func (m *Module) Insert(record Record) error {
	columns := ""
	values := ""
	for c, v := range record.param {
		columns = columns + c + ","
		rv := reflect.ValueOf(v)
		switch rv.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Bool:
			values = values + fmt.Sprintf("%v", v) + ","
		default:
			values = values + fmt.Sprintf("'%v'", v) + ","
		}
	}
	if l := len(columns); l > 0 {
		columns = columns[:l-1]
	}
	if l := len(values); l > 0 {
		values = values[:l-1]
	}
	insertSql := fmt.Sprintf("insert into %v(%v) values(%v)", m.tableName, columns, values)
	fmt.Println(insertSql)
	db := dbHive[m.dbname]
	_, err := db.Exec(insertSql)
	return err
}

func (m *Module) Update(record Record) error {
	values := ""
	for c, v := range record.param {
		values = values + c + "="
		rv := reflect.ValueOf(v)
		switch rv.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Bool:
			values += fmt.Sprintf("%v", v)
		default:
			values += fmt.Sprintf("'%v'", v)
		}
		values += ","
	}
	if l := len(values); l > 0 {
		values = values[:l-1]
	}
	sql := fmt.Sprintf("update %v set %v where %v", m.tableName, values, m.filters)
	log.Println("sql = ", sql)
	db := dbHive[m.dbname]
	_, err := db.Exec(sql)
	return err
}

func (m *Module) DeleteById(id int) error {
	m.Filter(m.pk, "=", id)
	return m.Delete()
}

func (m *Module) FindById(id int) *Module {
	m.Filter(m.pk, "=", id)
	return m
}

func (m *Module) Delete() error {
	where := m.filters
	where = strings.TrimSpace(where)
	if len(where) > 0 {
		where = "where " + where
	}
	delSql := fmt.Sprintf("delete %v %v", m.tableName, where)
	fmt.Println(delSql)
	_, err := dbHive[m.dbname].Exec(delSql)
	return err
}
<commit_msg>fix Insert() function return id<commit_after>package orm

import (
	"database/sql"
	"errors"
	"fmt"
	"log"
	"reflect"
	"strings"
)

var dbHive map[string]*sql.DB = make(map[string]*sql.DB)

//create new database
func NewDatabase(dbname, dbtype, url string) {
	db, err := sql.Open(dbtype, url)
	if err != nil {
		panic(err.Error())
	}
	err = db.Ping()
	if err != nil {
		panic(err.Error())
	}
	dbHive[dbname] = db
}

//module
type Module struct {
	columnstr string //select field
	tableName string //table
	filters   string //condition
	orderby   string //orderby
	limit     string //limit
	join      string //join
	pk        string //pk
	dbname    string //dbname
}

//create new Module
func NewModule(tableName string) *Module {
	m := &Module{tableName: tableName, columnstr: "*", dbname: "default", pk: "id"}
	return m
}

func (m *Module) Clean() *Module {
	m.columnstr = "*"
	m.filters = ""
	m.orderby = ""
	m.limit = ""
	m.join = ""
	m.pk = "id"
	return m
}

func (m *Module) GetDB() *sql.DB {
	return dbHive[m.dbname]
}

//change db
func (m *Module) User(dbname string) *Module {
	m.dbname = dbname
	return m
}

//select fields
func (m *Module) Select(fields ...string) *Module {
	m.columnstr = ""
	for _, f := range fields {
		m.columnstr = m.columnstr + f + ","
	}
	return m
}

//Filter
func (m *Module) Filter(param ...interface{}) *Module {
	for _, p := range param {
		m.filters += fmt.Sprintf("%v", p)
	}
	return m
}

//orderBy
func (m *Module) OrderBy(param string) *Module {
	m.orderby = fmt.Sprintf("ORDER By %v", param)
	return m
}

//limit
func (m *Module) Limit(size ...int) *Module {
	if len(size) > 1 {
		m.limit = fmt.Sprintf("Limit %d,%d", size[0], size[1])
		return m
	} else {
		m.limit = fmt.Sprintf("Limit %d", size[0])
		return m
	}
}

//leftJoin
func (m *Module) LeftJoin(table, condition string) *Module {
	m.join = fmt.Sprintf("LEFT JOIN %v ON %v", table, condition)
	return m
}

//rightJoin
func (m *Module) RightJoin(table, condition string) *Module {
	m.join = fmt.Sprintf("RIGHT JOIN %v ON %v", table, condition)
	return m
}

//join
func (m *Module) Join(table, condition string) *Module {
	m.join = fmt.Sprintf("INNER JOIN %v ON %v", table, condition)
	return m
}

//fulljoin
func (m *Module) FullJoin(table, condition string) *Module {
	m.join = fmt.Sprintf("FULL JOIN %v ON %v", table, condition)
	return m
}

func (m *Module) getSqlString() string {
	columnstr := m.columnstr
	if l := len(columnstr); l > 1 {
		columnstr = columnstr[:l-1]
	}
	query := m.buildSql(columnstr)
	query += " " + m.limit
	log.Println("sql = ", query)
	return query
}

func (m *Module) buildSql(columnstr string) string {
	where := m.filters
	where = strings.TrimSpace(where)
	if len(where) > 0 {
		where = "where " + where
	}
	query := fmt.Sprintf("select %v from %v %v %v %v", columnstr, m.tableName, m.join, where, m.orderby)
	return query
}

func (m *Module) QueryPage(page *Page, callBackFunc func(*sql.Rows)) error {
	db := dbHive[m.dbname]
	m.Limit(page.StartRow(), page.PageSize)
	query := m.buildSql("count(*)")
	row := db.QueryRow(query)
	err := row.Scan(&page.ResultCount)
	if err != nil {
		return err
	}
	rows, err := db.Query(m.getSqlString())
	if err != nil {
		return err
	}
	defer rows.Close()
	callBackFunc(rows)
	return nil
}

func (m *Module) Query(callBackFunc func(*sql.Rows)) error {
	db := dbHive[m.dbname]
	rows, err := db.Query(m.getSqlString())
	if err != nil {
		return err
	}
	defer rows.Close()
	callBackFunc(rows)
	return nil
}
func (m *Module) QueryOne(callBackFunc func(*sql.Row)) {
	db := dbHive[m.dbname]
	row := db.QueryRow(m.getSqlString())
	callBackFunc(row)
}

func (m *Module) IsExist() (bool, error) {
	count, err := m.Count()
	if count > 0 {
		return true, nil
	}
	return false, err
}

func (m *Module) Count() (int, error) {
	db := dbHive[m.dbname]
	query := m.buildSql("count(*)")
	log.Println("sql = ", query)
	row := db.QueryRow(query)
	var count int
	err := row.Scan(&count)
	return count, err
}

func (m *Module) OneRecord() (record Record, err error) {
	rs, err := m.Limit(1).AllRecords()
	if err != nil {
		return record, err
	}
	if len(rs) == 0 {
		return NewRecord(), errors.New("not fond record")
	}
	return rs[0], nil
}

func (m *Module) AllRecords() ([]Record, error) {
	db := dbHive[m.dbname]
	rows, err := db.Query(m.getSqlString())
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	records := make([]Record, 0)
	columns, _ := rows.Columns()
	values := make([]sql.RawBytes, len(columns))
	scanargs := make([]interface{}, len(values))
	for i := range values {
		scanargs[i] = &values[i]
	}
	for rows.Next() {
		err := rows.Scan(scanargs...)
		if err != nil {
			fmt.Println(err)
		}
		record := NewRecord()
		for i, v := range values {
			record.result[columns[i]] = v
		}
		records = append(records, record)
	}
	return records, nil
}
func (m *Module) SetPK(pk string) *Module {
	m.pk = pk
	return m
}

func (m *Module) FindRecordById(id int) *Module {
	m.Filter(m.pk, "=", id)
	return m
}

func (m *Module) Insert(record Record) (int, error) {
	columns := ""
	values := ""
	for c, v := range record.param {
		columns = columns + c + ","
		rv := reflect.ValueOf(v)
		switch rv.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Bool:
			values = values + fmt.Sprintf("%v", v) + ","
		default:
			values = values + fmt.Sprintf("'%v'", v) + ","
		}
	}
	if l := len(columns); l > 0 {
		columns = columns[:l-1]
	}
	if l := len(values); l > 0 {
		values = values[:l-1]
	}
	insertSql := fmt.Sprintf("insert into %v(%v) values(%v)", m.tableName, columns, values)
	fmt.Println(insertSql)
	db := dbHive[m.dbname]
	result, err := db.Exec(insertSql)
	if err != nil {
		return 0, err
	}
	id, err := result.LastInsertId()
	return int(id), err
}

func (m *Module) Update(record Record) error {
	values := ""
	for c, v := range record.param {
		values = values + c + "="
		rv := reflect.ValueOf(v)
		switch rv.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Bool:
			values += fmt.Sprintf("%v", v)
		default:
			values += fmt.Sprintf("'%v'", v)
		}
		values += ","
	}
	if l := len(values); l > 0 {
		values = values[:l-1]
	}
	sql := fmt.Sprintf("update %v set %v where %v", m.tableName, values, m.filters)
	log.Println("sql = ", sql)
	db := dbHive[m.dbname]
	_, err := db.Exec(sql)
	return err
}

func (m *Module) DeleteById(id int) error {
	m.Filter(m.pk, "=", id)
	return m.Delete()
}

func (m *Module) FindById(id int) *Module {
	m.Filter(m.pk, "=", id)
	return m
}

func (m *Module) Delete() error {
	where := m.filters
	where = strings.TrimSpace(where)
	if len(where) > 0 {
		where = "where " + where
	}
	delSql := fmt.Sprintf("delete %v %v", m.tableName, where)
	fmt.Println(delSql)
	_, err := dbHive[m.dbname].Exec(delSql)
	return err
}
<|endoftext|>