<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"sort"
	"strings"
)

func init() {
	Topics = append(Topics, TopicSet{
		{
			Name:        "commands",
			Description: "list all commands",
			Hidden:      true,
			Commands: CommandSet{
				{
					Topic:            "commands",
					Description:      "list all commands",
					Flags:            []Flag{{Name: "json"}},
					DisableAnalytics: true,
					Run: func(ctx *Context) {
						commands := AllCommands().Sort()
						if ctx.Flags["json"] == true {
							commands.loadUsages()
							commands.loadFullHelp()
							doc := map[string]interface{}{"topics": Topics, "commands": commands}
							s, _ := json.Marshal(doc)
							Println(string(s))
							return
						}
						for _, command := range commands {
							if command.Hidden {
								continue
							}
							if command.Command == "" {
								Printf("%s\n", command.Topic)
							} else {
								Printf("%s:%s\n", command.Topic, command.Command)
							}
						}
					},
				},
			},
		},
	}...)
}

// Command represents a CLI command.
// For example, in the command `heroku apps:create` the command would be `create`.
// They must have a Topic name that links to a real topic's name.
type Command struct {
	Topic            string             `json:"topic"`
	Command          string             `json:"command,omitempty"`
	Plugin           string             `json:"plugin"`
	Usage            string             `json:"usage"`
	Description      string             `json:"description"`
	Default          bool               `json:"default"`
	Help             string             `json:"help"`
	FullHelp         string             `json:"fullHelp"`
	Hidden           bool               `json:"hidden"`
	NeedsApp         bool               `json:"needsApp"`
	WantsApp         bool               `json:"wantsApp"`
	NeedsOrg         bool               `json:"needsOrg"`
	WantsOrg         bool               `json:"wantsOrg"`
	NeedsAuth        bool               `json:"needsAuth"`
	VariableArgs     bool               `json:"variableArgs"`
	DisableAnalytics bool               `json:"disableAnalytics"`
	Args             []Arg              `json:"args"`
	Flags            []Flag             `json:"flags"`
	Run              func(ctx *Context) `json:"-"`
}

func (c Command) String() string {
	if c.Command == "" {
		return c.Topic
	}
	return c.Topic + ":" + c.Command
}

// CommandUsage generates the usage for a command
func CommandUsage(c *Command) string {
	if c.Usage != "" {
		return c.Usage
	}
	return c.String() + argsString(c.Args)
}

func (c *Command) buildFlagHelp() string {
	flags := c.Flags
	if c.NeedsApp || c.WantsApp {
		flags = append(flags, *AppFlag, *RemoteFlag)
	}
	if c.NeedsOrg || c.WantsOrg {
		flags = append(flags, *OrgFlag)
	}
	lines := make([]string, 0, len(flags))
	for _, flag := range flags {
		if flag.Hidden {
			continue
		}
		if flag.Description == "" {
			lines = append(lines, flag.String())
		} else {
			lines = append(lines, fmt.Sprintf("%-20s # %s", flag.String(), flag.Description))
		}
	}
	return strings.Join(lines, "\n")
}

func (c *Command) buildFullHelp() string {
	sections := make([]string, 0, 3)
	if c.Description != "" {
		sections = append(sections, c.Description)
	}
	flagHelp := c.buildFlagHelp()
	if flagHelp != "" {
		sections = append(sections, flagHelp)
	}
	if c.Help != "" {
		sections = append(sections, c.Help)
	}
	return strings.TrimSuffix(strings.Join(sections, "\n\n"), "\n")
}

func (c *Command) unexpectedFlagErr(flag string) {
	flagHelp := c.buildFlagHelp()
	cmd := "heroku " + c.String()
	if flagHelp == "" {
		ExitWithMessage(
			`Error: Unexpected flag %s
Usage: %s
This command does not take any flags.

See more information with %s`,
			red(flag),
			cyan("heroku "+CommandUsage(c)),
			cyan(cmd+" --help"),
		)
	}
	ExitWithMessage(
		`Error: Unexpected flag %s
Usage: %s

This flag is invalid for this command. Here are the accepted flags:
%s

See more information with %s`,
		red(flag),
		cyan("heroku "+CommandUsage(c)),
		flagHelp,
		cyan(cmd+" --help"),
	)
}

func (c *Command) appNeededErr() {
	ExitWithMessage(
		`Error: No app specified
Usage: %s
We don't know which app to run this on.
Run this command from inside an app folder or specify which app to use with %s

https://devcenter.heroku.com/articles/using-the-cli#app-commands`,
		cyan("heroku "+CommandUsage(c)+" --app APP"),
		cyan("--app APP"),
	)
}

func (c *Command) unexpectedArgumentsErr(args []string) {
	cmd := "heroku " + c.String()
	ExitWithMessage(
		`Error: Unexpected %s %s
Usage: %s
You gave this command too many arguments. Try the command again without these extra arguments.

See more information with %s`,
		plural("argument", len(args)),
		red(strings.Join(args, " ")),
		cyan("heroku "+CommandUsage(c)),
		cyan(cmd+" --help"),
	)
}

// CommandSet is a slice of Command structs with some helper methods.
type CommandSet []*Command

// Find finds a command and topic matching the cmd string
func (commands CommandSet) Find(cmd string) *Command {
	var topic, command string
	tc := strings.SplitN(cmd, ":", 2)
	topic = tc[0]
	if len(tc) > 1 {
		command = tc[1]
	}
	for _, c := range commands {
		if c.Topic == topic && (c.Command == command || c.Default && command == "") {
			return c
		}
	}
	return nil
}

func (commands CommandSet) loadUsages() {
	for _, c := range commands {
		c.Usage = CommandUsage(c)
	}
}

func (commands CommandSet) loadFullHelp() {
	for _, c := range commands {
		if c.FullHelp == "" {
			c.FullHelp = c.buildFullHelp()
		}
	}
}

func (commands CommandSet) Len() int {
	return len(commands)
}

func (commands CommandSet) Less(i, j int) bool {
	if commands[i].Topic == commands[j].Topic {
		return commands[i].Command < commands[j].Command
	}
	return commands[i].Topic < commands[j].Topic
}

func (commands CommandSet) Swap(i, j int) {
	commands[i], commands[j] = commands[j], commands[i]
}

// NonHidden returns the commands that are not hidden
func (commands CommandSet) NonHidden() []*Command {
	to := make([]*Command, 0, len(commands))
	for _, command := range commands {
		if !command.Hidden {
			to = append(to, command)
		}
	}
	return to
}

// Sort sorts
func (commands CommandSet) Sort() CommandSet {
	sort.Sort(commands)
	return commands
}

// Arg defines an argument for a command.
// These will be parsed in Go and passed to the Run method in the Context struct.
type Arg struct {
	Name     string `json:"name"`
	Optional bool   `json:"optional"`
	Hidden   bool   `json:"hidden"`
}

func (a *Arg) String() string {
	if a.Optional {
		return "[" + strings.ToUpper(a.Name) + "]"
	}
	return strings.ToUpper(a.Name)
}

func argsString(args []Arg) string {
	var buffer bytes.Buffer
	for _, arg := range args {
		if arg.Hidden {
			continue
		}
		if arg.Optional {
			buffer.WriteString(" [" + strings.ToUpper(arg.Name) + "]")
		} else {
			buffer.WriteString(" " + strings.ToUpper(arg.Name))
		}
	}
	return buffer.String()
}

// AllCommands gets all go/core/user commands
func AllCommands() CommandSet {
	commands := Topics.Commands()
	commands = append(commands, CorePlugins.Commands()...)
	commands = append(commands, UserPlugins.Commands()...)
	return commands
}
<commit_msg>use user plugins first<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"sort"
	"strings"
)

func init() {
	Topics = append(Topics, TopicSet{
		{
			Name:        "commands",
			Description: "list all commands",
			Hidden:      true,
			Commands: CommandSet{
				{
					Topic:            "commands",
					Description:      "list all commands",
					Flags:            []Flag{{Name: "json"}},
					DisableAnalytics: true,
					Run: func(ctx *Context) {
						commands := AllCommands().Sort()
						if ctx.Flags["json"] == true {
							commands.loadUsages()
							commands.loadFullHelp()
							doc := map[string]interface{}{"topics": Topics, "commands": commands}
							s, _ := json.Marshal(doc)
							Println(string(s))
							return
						}
						for _, command := range commands {
							if command.Hidden {
								continue
							}
							if command.Command == "" {
								Printf("%s\n", command.Topic)
							} else {
								Printf("%s:%s\n", command.Topic, command.Command)
							}
						}
					},
				},
			},
		},
	}...)
}

// Command represents a CLI command.
// For example, in the command `heroku apps:create` the command would be `create`.
// They must have a Topic name that links to a real topic's name.
type Command struct {
	Topic            string             `json:"topic"`
	Command          string             `json:"command,omitempty"`
	Plugin           string             `json:"plugin"`
	Usage            string             `json:"usage"`
	Description      string             `json:"description"`
	Default          bool               `json:"default"`
	Help             string             `json:"help"`
	FullHelp         string             `json:"fullHelp"`
	Hidden           bool               `json:"hidden"`
	NeedsApp         bool               `json:"needsApp"`
	WantsApp         bool               `json:"wantsApp"`
	NeedsOrg         bool               `json:"needsOrg"`
	WantsOrg         bool               `json:"wantsOrg"`
	NeedsAuth        bool               `json:"needsAuth"`
	VariableArgs     bool               `json:"variableArgs"`
	DisableAnalytics bool               `json:"disableAnalytics"`
	Args             []Arg              `json:"args"`
	Flags            []Flag             `json:"flags"`
	Run              func(ctx *Context) `json:"-"`
}

func (c Command) String() string {
	if c.Command == "" {
		return c.Topic
	}
	return c.Topic + ":" + c.Command
}

// CommandUsage generates the usage for a command
func CommandUsage(c *Command) string {
	if c.Usage != "" {
		return c.Usage
	}
	return c.String() + argsString(c.Args)
}

func (c *Command) buildFlagHelp() string {
	flags := c.Flags
	if c.NeedsApp || c.WantsApp {
		flags = append(flags, *AppFlag, *RemoteFlag)
	}
	if c.NeedsOrg || c.WantsOrg {
		flags = append(flags, *OrgFlag)
	}
	lines := make([]string, 0, len(flags))
	for _, flag := range flags {
		if flag.Hidden {
			continue
		}
		if flag.Description == "" {
			lines = append(lines, flag.String())
		} else {
			lines = append(lines, fmt.Sprintf("%-20s # %s", flag.String(), flag.Description))
		}
	}
	return strings.Join(lines, "\n")
}

func (c *Command) buildFullHelp() string {
	sections := make([]string, 0, 3)
	if c.Description != "" {
		sections = append(sections, c.Description)
	}
	flagHelp := c.buildFlagHelp()
	if flagHelp != "" {
		sections = append(sections, flagHelp)
	}
	if c.Help != "" {
		sections = append(sections, c.Help)
	}
	return strings.TrimSuffix(strings.Join(sections, "\n\n"), "\n")
}

func (c *Command) unexpectedFlagErr(flag string) {
	flagHelp := c.buildFlagHelp()
	cmd := "heroku " + c.String()
	if flagHelp == "" {
		ExitWithMessage(
			`Error: Unexpected flag %s
Usage: %s
This command does not take any flags.

See more information with %s`,
			red(flag),
			cyan("heroku "+CommandUsage(c)),
			cyan(cmd+" --help"),
		)
	}
	ExitWithMessage(
		`Error: Unexpected flag %s
Usage: %s

This flag is invalid for this command. Here are the accepted flags:
%s

See more information with %s`,
		red(flag),
		cyan("heroku "+CommandUsage(c)),
		flagHelp,
		cyan(cmd+" --help"),
	)
}

func (c *Command) appNeededErr() {
	ExitWithMessage(
		`Error: No app specified
Usage: %s
We don't know which app to run this on.
Run this command from inside an app folder or specify which app to use with %s

https://devcenter.heroku.com/articles/using-the-cli#app-commands`,
		cyan("heroku "+CommandUsage(c)+" --app APP"),
		cyan("--app APP"),
	)
}

func (c *Command) unexpectedArgumentsErr(args []string) {
	cmd := "heroku " + c.String()
	ExitWithMessage(
		`Error: Unexpected %s %s
Usage: %s
You gave this command too many arguments. Try the command again without these extra arguments.

See more information with %s`,
		plural("argument", len(args)),
		red(strings.Join(args, " ")),
		cyan("heroku "+CommandUsage(c)),
		cyan(cmd+" --help"),
	)
}

// CommandSet is a slice of Command structs with some helper methods.
type CommandSet []*Command

// Find finds a command and topic matching the cmd string
func (commands CommandSet) Find(cmd string) *Command {
	var topic, command string
	tc := strings.SplitN(cmd, ":", 2)
	topic = tc[0]
	if len(tc) > 1 {
		command = tc[1]
	}
	for _, c := range commands {
		if c.Topic == topic && (c.Command == command || c.Default && command == "") {
			return c
		}
	}
	return nil
}

func (commands CommandSet) loadUsages() {
	for _, c := range commands {
		c.Usage = CommandUsage(c)
	}
}

func (commands CommandSet) loadFullHelp() {
	for _, c := range commands {
		if c.FullHelp == "" {
			c.FullHelp = c.buildFullHelp()
		}
	}
}

func (commands CommandSet) Len() int {
	return len(commands)
}

func (commands CommandSet) Less(i, j int) bool {
	if commands[i].Topic == commands[j].Topic {
		return commands[i].Command < commands[j].Command
	}
	return commands[i].Topic < commands[j].Topic
}

func (commands CommandSet) Swap(i, j int) {
	commands[i], commands[j] = commands[j], commands[i]
}

// NonHidden returns the commands that are not hidden
func (commands CommandSet) NonHidden() []*Command {
	to := make([]*Command, 0, len(commands))
	for _, command := range commands {
		if !command.Hidden {
			to = append(to, command)
		}
	}
	return to
}

// Sort sorts
func (commands CommandSet) Sort() CommandSet {
	sort.Sort(commands)
	return commands
}

// Arg defines an argument for a command.
// These will be parsed in Go and passed to the Run method in the Context struct.
type Arg struct {
	Name     string `json:"name"`
	Optional bool   `json:"optional"`
	Hidden   bool   `json:"hidden"`
}

func (a *Arg) String() string {
	if a.Optional {
		return "[" + strings.ToUpper(a.Name) + "]"
	}
	return strings.ToUpper(a.Name)
}

func argsString(args []Arg) string {
	var buffer bytes.Buffer
	for _, arg := range args {
		if arg.Hidden {
			continue
		}
		if arg.Optional {
			buffer.WriteString(" [" + strings.ToUpper(arg.Name) + "]")
		} else {
			buffer.WriteString(" " + strings.ToUpper(arg.Name))
		}
	}
	return buffer.String()
}

// AllCommands gets all go/core/user commands
func AllCommands() CommandSet {
	commands := Topics.Commands()
	commands = append(commands, UserPlugins.Commands()...)
	commands = append(commands, CorePlugins.Commands()...)
	return commands
}
<|endoftext|>


<commit_before>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

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

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

package main

import (
	"errors"
	"fmt"
	"strconv"
	"encoding/json"

	"github.com/openblockchain/obc-peer/openchain/chaincode/shim"
)

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

var marbleIndex []string
var _allIndex []string						//store all variables names here
var _all string = "_all"					//key name for above. tracks all variables in chaincode state

type Marble struct{
	Name string `json:"name"`				//the fieldtags are needed to keep case from bouncing around
	Color string `json:"color"`
	Size int `json:"size"`
	User string `json:"user"`
}

func (t *SimpleChaincode) init(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var Aval int 																	// Asset holdings
	var err error

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	// Initialize the chaincode
	Aval, err = strconv.Atoi(args[0])
	if err != nil {
		return nil, errors.New("Expecting integer value for asset holding")
	}
	fmt.Printf("Aval = %d\n", Aval)

	// Write the state to the ledger
	err = stub.PutState("a", []byte(strconv.Itoa(Aval)))
	if err != nil {
		return nil, err
	}

	err = stub.PutState(_all, []byte(""))								//clear the _all list
	if err != nil {
		return nil, err
	}

	marbleIndex = marbleIndex[:0]										//clear the marble index
	jsonAsBytes, _ := json.Marshal(marbleIndex)
	err = stub.PutState("marbleIndex", jsonAsBytes)

	return nil, nil
}

// ============================================================================================================================
// Run
// ============================================================================================================================
func (t *SimpleChaincode) Run(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("run is running " + function)

	// Handle different functions
	if function == "init" {													// Initialize the entities and their asset holdings
		return t.init(stub, args)
	} else if function == "delete" {										// Deletes an entity from its state
		return t.Delete(stub, args)
	} else if function == "write" {											// Writes a value to the chaincode state
		return t.Write(stub, args)
	} else if function == "init_marble" {									//init_marble
		return t.init_marble(stub, args)
	} else if function == "set_user" {										//set user permissions
		return t.set_user(stub, args)
	}
	fmt.Println("run issues " + function)

	return nil, errors.New("Received unknown function invocation")
}

// Deletes an entity from state
func (t *SimpleChaincode) Delete(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	name := args[0]

	// Delete the key from the state in ledger
	err := stub.DelState(name)
	if err != nil {
		return nil, errors.New("Failed to delete state")
	}

	for i,val := range marbleIndex{
		if val == name{															//find the correct marble
			marbleIndex = append(marbleIndex[:i], marbleIndex[i+1:]...)			//remove it
			break
		}
	}

	return nil, nil
}

// Query callback representing the query of a chaincode
func (t *SimpleChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	if function != "query" {
		return nil, errors.New("Invalid query function name. Expecting \"query\"")
	}
	var A string // Entities
	var err error

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting name of the person to query")
	}

	A = args[0]

	// Get the state from the ledger
	Avalbytes, err := stub.GetState(A)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
		return nil, errors.New(jsonResp)
	}

	jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
	fmt.Printf("Query Response:%s\n", jsonResp)
	return Avalbytes, nil
}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

//----------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------

// ============================================================================================================================
// Write var into chaincode state
// ============================================================================================================================
func (t *SimpleChaincode) Write(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var name, value string // Entities
	var err error
	fmt.Println("running write - start")

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting name of the variable and value to set")
	}

	name = args[0]
	value = args[1]

	// Write the state back to the ledger
	err = stub.PutState(name, []byte(value))
	if err != nil {
		return nil, err
	}
	t.remember_me(stub, name)

	fmt.Println("running write - fin - for name " + name)
	return nil, nil
}

// ============================================================================================================================
// Remember Me - remember the name of variables we stored in ledger
// ============================================================================================================================
func (t *SimpleChaincode) remember_me(stub *shim.ChaincodeStub, name string) ([]byte, error) {		//dsh - to do, should probably not exist here, move to stub
	var err error
	/*var storedNames string
	storeNamesAsBytes, err := stub.GetState(_all)
	if err != nil {
		return nil, errors.New("Failed to get _all")
	}

	storedNames = string(storeNamesAsBytes)
	// Write the state back to the ledger
	err = stub.PutState(_all, []byte(storedNames + "," + name))										//dsh - to do, should probably be json
	if err != nil {
		return nil, err
	}
	*/

	_allIndex = append(_allIndex, name)									//add var name to index list
	jsonAsBytes, _ := json.Marshal(_allIndex)
	err = stub.PutState(_all, jsonAsBytes)
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// ============================================================================================================================
// Init Person
// ============================================================================================================================
func (t *SimpleChaincode) init_marble(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var err error

	if len(args) != 4 {
		return nil, errors.New("Incorrect number of arguments. Expecting 4")
	}

	val, err := strconv.Atoi(args[2])
	if err != nil {
		val = 16														//default value
	}
	str := `{"name": "` + args[0] + `", "color": "` + args[1] + `", "size": "` + strconv.Itoa(val) + `", "user": "` + args[3] + `"}`

	// Write the state back to the ledger
	err = stub.PutState(args[0], []byte(str))							//store marble with id as key
	if err != nil {
		return nil, err
	}
	t.remember_me(stub, args[0])

	marbleIndex = append(marbleIndex, args[0])							//add marble name to index list
	jsonAsBytes, _ := json.Marshal(marbleIndex)
	err = stub.PutState("marbleIndex", jsonAsBytes)						//store name of marble

	return nil, nil
}

// ============================================================================================================================
// Set User Permissions
// ============================================================================================================================
func (t *SimpleChaincode) set_user(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var err error

	marbleAsBytes, err := stub.GetState(args[0])
	if err != nil {
		return nil, errors.New("Failed to get thing")
	}
	res := Marble{}
	json.Unmarshal(marbleAsBytes, &res)
	fmt.Println(res)

	/*for i,perm := range res.Users{
		if perm.UserId == args[1]{							//find the correct user
			res.Users[i].Permissions[0] = args[2]			//set new perm, dsh - to do make this input as array of all perms
			fmt.Println(res.Users[i].Permissions)
			break
		}
	}*/
	res.User = args[1]

	// Write the state back to the ledger
	jsonAsBytes, _ := json.Marshal(res)
	err = stub.PutState(args[0], jsonAsBytes)
	if err != nil {
		return nil, err
	}

	return nil, nil
}<commit_msg>- fix _allIndex<commit_after>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

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

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

package main

import (
	"errors"
	"fmt"
	"strconv"
	"encoding/json"

	"github.com/openblockchain/obc-peer/openchain/chaincode/shim"
)

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

var marbleIndex []string
var _allIndex []string						//store all variables names here
var _all string = "_all"					//key name for above. tracks all variables in chaincode state

type Marble struct{
	Name string `json:"name"`				//the fieldtags are needed to keep case from bouncing around
	Color string `json:"color"`
	Size int `json:"size"`
	User string `json:"user"`
}

func (t *SimpleChaincode) init(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var Aval int 																	// Asset holdings
	var err error

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	// Initialize the chaincode
	Aval, err = strconv.Atoi(args[0])
	if err != nil {
		return nil, errors.New("Expecting integer value for asset holding")
	}
	fmt.Printf("Aval = %d\n", Aval)

	// Write the state to the ledger
	err = stub.PutState("a", []byte(strconv.Itoa(Aval)))
	if err != nil {
		return nil, err
	}

	_allIndex = _allIndex[:0]											//clear the _all index
	jsonAsBytes1, _ := json.Marshal(_allIndex)
	err = stub.PutState(_all, jsonAsBytes1)
	if err != nil {
		return nil, err
	}

	marbleIndex = marbleIndex[:0]										//clear the marble index
	jsonAsBytes, _ := json.Marshal(marbleIndex)
	err = stub.PutState("marbleIndex", jsonAsBytes)
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// ============================================================================================================================
// Run
// ============================================================================================================================
func (t *SimpleChaincode) Run(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("run is running " + function)

	// Handle different functions
	if function == "init" {													// Initialize the entities and their asset holdings
		return t.init(stub, args)
	} else if function == "delete" {										// Deletes an entity from its state
		return t.Delete(stub, args)
	} else if function == "write" {											// Writes a value to the chaincode state
		return t.Write(stub, args)
	} else if function == "init_marble" {									//init_marble
		return t.init_marble(stub, args)
	} else if function == "set_user" {										//set user permissions
		return t.set_user(stub, args)
	}
	fmt.Println("run issues " + function)

	return nil, errors.New("Received unknown function invocation")
}

// Deletes an entity from state
func (t *SimpleChaincode) Delete(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	name := args[0]

	// Delete the key from the state in ledger
	err := stub.DelState(name)
	if err != nil {
		return nil, errors.New("Failed to delete state")
	}

	for i,val := range marbleIndex{
		if val == name{															//find the correct marble
			marbleIndex = append(marbleIndex[:i], marbleIndex[i+1:]...)			//remove it
			break
		}
	}

	return nil, nil
}

// Query callback representing the query of a chaincode
func (t *SimpleChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	if function != "query" {
		return nil, errors.New("Invalid query function name. Expecting \"query\"")
	}
	var A string // Entities
	var err error

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting name of the person to query")
	}

	A = args[0]

	// Get the state from the ledger
	Avalbytes, err := stub.GetState(A)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
		return nil, errors.New(jsonResp)
	}

	jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
	fmt.Printf("Query Response:%s\n", jsonResp)
	return Avalbytes, nil
}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

//----------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------

// ============================================================================================================================
// Write var into chaincode state
// ============================================================================================================================
func (t *SimpleChaincode) Write(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var name, value string // Entities
	var err error
	fmt.Println("running write - start")

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting name of the variable and value to set")
	}

	name = args[0]
	value = args[1]

	// Write the state back to the ledger
	err = stub.PutState(name, []byte(value))
	if err != nil {
		return nil, err
	}
	t.remember_me(stub, name)

	fmt.Println("running write - fin - for name " + name)
	return nil, nil
}

// ============================================================================================================================
// Remember Me - remember the name of variables we stored in ledger
// ============================================================================================================================
func (t *SimpleChaincode) remember_me(stub *shim.ChaincodeStub, name string) ([]byte, error) {		//dsh - to do, should probably not exist here, move to stub
	var err error
	/*var storedNames string
	storeNamesAsBytes, err := stub.GetState(_all)
	if err != nil {
		return nil, errors.New("Failed to get _all")
	}

	storedNames = string(storeNamesAsBytes)
	// Write the state back to the ledger
	err = stub.PutState(_all, []byte(storedNames + "," + name))										//dsh - to do, should probably be json
	if err != nil {
		return nil, err
	}
	*/

	_allIndex = append(_allIndex, name)									//add var name to index list
	jsonAsBytes, _ := json.Marshal(_allIndex)
	err = stub.PutState(_all, jsonAsBytes)
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// ============================================================================================================================
// Init Person
// ============================================================================================================================
func (t *SimpleChaincode) init_marble(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var err error

	if len(args) != 4 {
		return nil, errors.New("Incorrect number of arguments. Expecting 4")
	}

	val, err := strconv.Atoi(args[2])
	if err != nil {
		val = 16														//default value
	}
	str := `{"name": "` + args[0] + `", "color": "` + args[1] + `", "size": "` + strconv.Itoa(val) + `", "user": "` + args[3] + `"}`

	// Write the state back to the ledger
	err = stub.PutState(args[0], []byte(str))							//store marble with id as key
	if err != nil {
		return nil, err
	}
	t.remember_me(stub, args[0])

	marbleIndex = append(marbleIndex, args[0])							//add marble name to index list
	jsonAsBytes, _ := json.Marshal(marbleIndex)
	err = stub.PutState("marbleIndex", jsonAsBytes)						//store name of marble

	return nil, nil
}

// ============================================================================================================================
// Set User Permissions
// ============================================================================================================================
func (t *SimpleChaincode) set_user(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var err error

	marbleAsBytes, err := stub.GetState(args[0])
	if err != nil {
		return nil, errors.New("Failed to get thing")
	}
	res := Marble{}
	json.Unmarshal(marbleAsBytes, &res)
	fmt.Println(res)

	/*for i,perm := range res.Users{
		if perm.UserId == args[1]{							//find the correct user
			res.Users[i].Permissions[0] = args[2]			//set new perm, dsh - to do make this input as array of all perms
			fmt.Println(res.Users[i].Permissions)
			break
		}
	}*/
	res.User = args[1]

	// Write the state back to the ledger
	jsonAsBytes, _ := json.Marshal(res)
	err = stub.PutState(args[0], jsonAsBytes)
	if err != nil {
		return nil, err
	}

	return nil, nil
}<|endoftext|>


<commit_before>package channel

import (
	"fmt"
	"sync"
)

func Run() {
	c := gen(2, 3, 4, 5, 6)
	out1 := sq(c)
	out2 := sq(c)
	out3 := sq(c)

	done := make(chan struct{}, 2)

	out := merge(done, out1, out2, out3)
	fmt.Println(<-out)

	done <- struct{}{}
	done <- struct{}{}
	done <- struct{}{}

}

func gen(nums ...int) <-chan int {
	out := make(chan int, len(nums))
	for _, n := range nums {
		out <- n
	}
	close(out)
	return out
}

func sq(in <-chan int) <-chan int {
	out := make(chan int)
	go func() {
		for n := range in {
			out <- n * n
		}
		close(out)
	}()
	return out
}

func merge(done <-chan struct{}, cs ...<-chan int) <-chan int {
	var wg sync.WaitGroup
	out := make(chan int)

	output := func(in <-chan int) {
		for v := range in {
			out <- v
			select {
			case out <- v:
			case <-done:
			}
		}
		wg.Done()
	}
	wg.Add(len(cs))
	for _, v := range cs {
		go output(v)
	}
	go func() {
		wg.Wait()
		close(out)
	}()
	return out
}
<commit_msg>add done for gen and sq<commit_after>package channel

import (
	"fmt"
	"sync"
)

func Run() {
	done := make(chan struct{}, 2)
	defer close(done)

	c := gen(done, 2, 3, 4, 5, 6, 7, 8)
	out1 := sq(done, c)
	out2 := sq(done, c)
	out3 := sq(done, c)

	out := merge(done, out1, out2, out3)
	fmt.Println(<-out)
	fmt.Println(<-out)
	fmt.Println(<-out)
}

func gen(done <-chan struct{}, nums ...int) <-chan int {
	out := make(chan int, len(nums))
	go func() {
		defer close(out)
		for _, n := range nums {
			select {
			case out <- n:
			case <-done:
				return
			}
		}
	}()
	return out
}

func sq(done chan struct{}, in <-chan int) <-chan int {
	out := make(chan int)
	go func() {
		defer close(out)
		for n := range in {
			select {
			case out <- n * n:
			case <-done:
				return
			}
		}
	}()
	return out
}

func merge(done <-chan struct{}, cs ...<-chan int) <-chan int {
	var wg sync.WaitGroup
	out := make(chan int)

	output := func(in <-chan int) {
		defer wg.Done()
		for v := range in {
			select {
			case out <- v:
			case <-done:
				return
			}
		}
	}
	wg.Add(len(cs))
	for _, v := range cs {
		go output(v)
	}
	go func() {
		wg.Wait()
		close(out)
	}()
	return out
}
<|endoftext|>


<commit_before>// Copyright 2016 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 render

import (
	"bytes"
	"fmt"
	htmlTemplate "html/template"
	"io"
	"sort"
	"strconv"
	"strings"

	"github.com/googlecodelabs/tools/claat/types"
)

// TODO: render HTML using golang/x/net/html or template.

var (
	doubleQuote = []byte{'"'}
	lessThan    = []byte{'<'}
	greaterThan = []byte{'>'}
	newLine     = []byte{'\n'}
)

// HTML renders nodes as the markup for the target env.
func HTML(env string, nodes ...types.Node) (htmlTemplate.HTML, error) {
	var buf bytes.Buffer
	if err := WriteHTML(&buf, env, nodes...); err != nil {
		return "", err
	}
	return htmlTemplate.HTML(buf.String()), nil
}

// WriteHTML does the same as HTML but outputs rendered markup to w.
func WriteHTML(w io.Writer, env string, nodes ...types.Node) error {
	hw := htmlWriter{w: w, env: env}
	return hw.write(nodes...)
}

type htmlWriter struct {
	w   io.Writer // output writer
	env string    // target environment
	err error     // error during any writeXxx methods
}

func (hw *htmlWriter) matchEnv(v []string) bool {
	if len(v) == 0 || hw.env == "" {
		return true
	}
	i := sort.SearchStrings(v, hw.env)
	return i < len(v) && v[i] == hw.env
}

func (hw *htmlWriter) write(nodes ...types.Node) error {
	for _, n := range nodes {
		if !hw.matchEnv(n.Env()) {
			continue
		}
		switch n := n.(type) {
		case *types.TextNode:
			hw.text(n)
		case *types.ImageNode:
			hw.image(n)
		case *types.URLNode:
			hw.url(n)
		case *types.ButtonNode:
			hw.button(n)
		case *types.CodeNode:
			hw.code(n)
			hw.writeBytes(newLine)
		case *types.ListNode:
			hw.list(n)
			hw.writeBytes(newLine)
		case *types.ImportNode:
			if len(n.Content.Nodes) == 0 {
				break
			}
			hw.list(n.Content)
			hw.writeBytes(newLine)
		case *types.ItemsListNode:
			hw.itemsList(n)
			hw.writeBytes(newLine)
		case *types.GridNode:
			hw.grid(n)
			hw.writeBytes(newLine)
		case *types.InfoboxNode:
			hw.infobox(n)
			hw.writeBytes(newLine)
		case *types.SurveyNode:
			hw.survey(n)
			hw.writeBytes(newLine)
		case *types.HeaderNode:
			hw.header(n)
			hw.writeBytes(newLine)
		case *types.YouTubeNode:
			hw.youtube(n)
			hw.writeBytes(newLine)
		}
		if hw.err != nil {
			return hw.err
		}
	}
	return nil
}

func (hw *htmlWriter) writeBytes(b []byte) {
	if hw.err != nil {
		return
	}
	_, hw.err = hw.w.Write(b)
}

func (hw *htmlWriter) writeString(s string) {
	hw.writeBytes([]byte(s))
}

func (hw *htmlWriter) writeFmt(f string, a ...interface{}) {
	hw.writeString(fmt.Sprintf(f, a...))
}

func (hw *htmlWriter) writeEscape(s string) {
	htmlTemplate.HTMLEscape(hw.w, []byte(s))
}

func (hw *htmlWriter) text(n *types.TextNode) {
	if n.Bold {
		hw.writeString("")
	}
	if n.Italic {
		hw.writeString("")
	}
	if n.Code {
		hw.writeString("")
	}
	s := htmlTemplate.HTMLEscapeString(n.Value)
	hw.writeString(strings.Replace(s, "\n", "
", -1))
	if n.Code {
		hw.writeString("")
	}
	if n.Italic {
		hw.writeString("")
	}
	if n.Bold {
		hw.writeString("")
	}
}

func (hw *htmlWriter) image(n *types.ImageNode) {
	hw.writeString(" 0 {
		hw.writeFmt(` style="max-width: %.2fpx"`, n.MaxWidth)
	}
	hw.writeString(` src="`)
	hw.writeString(n.Src)
	hw.writeBytes(doubleQuote)
	hw.writeBytes(greaterThan)
}

func (hw *htmlWriter) url(n *types.URLNode) {
	hw.writeString("<a")
	if n.URL != "" {
		hw.writeString(` href="`)
		hw.writeString(n.URL)
		hw.writeBytes(doubleQuote)
	}
	if n.Name != "" {
		hw.writeString(` name="`)
		hw.writeEscape(n.Name)
		hw.writeBytes(doubleQuote)
	}
	if n.Target != "" {
		hw.writeString(` target="`)
		hw.writeEscape(n.Target)
		hw.writeBytes(doubleQuote)
	}
	hw.writeBytes(greaterThan)
	hw.write(n.Content.Nodes...)
	hw.writeString("")
}

func (hw *htmlWriter) button(n *types.ButtonNode) {
	hw.writeString("<paper-button")
	if n.Colored {
		hw.writeString(` class="colored"`)
	}
	if n.Raised {
		hw.writeString(" raised")
	}
	hw.writeBytes(greaterThan)
	if n.Download {
		hw.writeString(`<iron-icon icon="file-download"></iron-icon>`)
	}
	hw.write(n.Content.Nodes...)
	hw.writeString("</paper-button>")
}

func (hw *htmlWriter) code(n *types.CodeNode) {
	hw.writeString("
")
	if !n.Term {
		hw.writeString("<code")
		if n.Lang != "" {
			hw.writeFmt(" language=%q class=%q", n.Lang, n.Lang)
		}
		hw.writeBytes(greaterThan)
	}
	hw.writeEscape(n.Value)
	if !n.Term {
		hw.writeString("")
	}
	hw.writeString("
")
}

func (hw *htmlWriter) list(n *types.ListNode) {
	wrap := n.Block() == true
	if wrap {
		hw.writeString("
")
	}
	hw.write(n.Nodes...)
	if wrap {
		hw.writeString("
")
	}
}

func (hw *htmlWriter) itemsList(n *types.ItemsListNode) {
	tag := "ul"
	if n.Type() == types.NodeItemsList && n.Start > 0 {
		tag = "ol"
	}
	hw.writeBytes(lessThan)
	hw.writeString(tag)
	switch n.Type() {
	case types.NodeItemsCheck:
		hw.writeString(` class="checklist"`)
	case types.NodeItemsFAQ:
		hw.writeString(` class="faq"`)
	default:
		if n.ListType != "" {
			hw.writeString(` type="`)
			hw.writeString(n.ListType)
			hw.writeBytes(doubleQuote)
		}
		if n.Start > 0 {
			hw.writeFmt(` start="%d"`, n.Start)
		}
	}
	hw.writeBytes(greaterThan)
	hw.writeBytes(newLine)

	for _, i := range n.Items {
		hw.writeString("
")
		hw.write(i.Nodes...)
		hw.writeString("
\n")
	}

	hw.writeString("</")
	hw.writeString(tag)
	hw.writeBytes(greaterThan)
}

func (hw *htmlWriter) grid(n *types.GridNode) {
	hw.writeString("
\n")
	for _, r := range n.Rows {
		hw.writeString("
")
		for _, c := range r {
			hw.writeFmt(`<td colspan="%d" rowspan="%d">`, c.Colspan, c.Rowspan)
			hw.write(c.Content.Nodes...)
			hw.writeString("	")
		}
		hw.writeString("
\n")
	}
	hw.writeString("
")
}

func (hw *htmlWriter) infobox(n *types.InfoboxNode) {
	hw.writeString(`<aside class="`)
	hw.writeEscape(string(n.Kind))
	hw.writeString(`">`)
	hw.write(n.Content.Nodes...)
	hw.writeString("")
}

func (hw *htmlWriter) survey(n *types.SurveyNode) {
	hw.writeString(`<google-codelab-survey survey-id="`)
	hw.writeString(n.ID)
	hw.writeBytes(doubleQuote)
	hw.writeString(">\n")
	for _, g := range n.Groups {
		hw.writeString("
")
		hw.writeEscape(g.Name)
		hw.writeString("
\n<paper-radio-group>\n")
		for _, o := range g.Options {
			hw.writeString("<paper-radio-button>")
			hw.writeEscape(o)
			hw.writeString("</paper-radio-button>\n")
		}
		hw.writeString("</paper-radio-group>\n")
	}
	hw.writeString("</google-codelab-survey>")
}

func (hw *htmlWriter) header(n *types.HeaderNode) {
	tag := "h" + strconv.Itoa(n.Level)
	hw.writeBytes(lessThan)
	hw.writeString(tag)
	switch n.Type() {
	case types.NodeHeaderCheck:
		hw.writeString(` class="checklist"`)
	case types.NodeHeaderFAQ:
		hw.writeString(` class="faq"`)
	}
	hw.writeBytes(greaterThan)
	hw.write(n.Content.Nodes...)
	hw.writeString("</")
	hw.writeString(tag)
	hw.writeBytes(greaterThan)
}

func (hw *htmlWriter) youtube(n *types.YouTubeNode) {
	hw.writeFmt("<google-youtube fluid video-id=%q></google-youtube>", n.VideoID)
}
<commit_msg>parser/markdown: handle order list items when no start attribute<commit_after>// Copyright 2016 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 render

import (
	"bytes"
	"fmt"
	htmlTemplate "html/template"
	"io"
	"sort"
	"strconv"
	"strings"

	"github.com/googlecodelabs/tools/claat/types"
)

// TODO: render HTML using golang/x/net/html or template.

var (
	doubleQuote = []byte{'"'}
	lessThan    = []byte{'<'}
	greaterThan = []byte{'>'}
	newLine     = []byte{'\n'}
)

// HTML renders nodes as the markup for the target env.
func HTML(env string, nodes ...types.Node) (htmlTemplate.HTML, error) {
	var buf bytes.Buffer
	if err := WriteHTML(&buf, env, nodes...); err != nil {
		return "", err
	}
	return htmlTemplate.HTML(buf.String()), nil
}

// WriteHTML does the same as HTML but outputs rendered markup to w.
func WriteHTML(w io.Writer, env string, nodes ...types.Node) error {
	hw := htmlWriter{w: w, env: env}
	return hw.write(nodes...)
}

type htmlWriter struct {
	w   io.Writer // output writer
	env string    // target environment
	err error     // error during any writeXxx methods
}

func (hw *htmlWriter) matchEnv(v []string) bool {
	if len(v) == 0 || hw.env == "" {
		return true
	}
	i := sort.SearchStrings(v, hw.env)
	return i < len(v) && v[i] == hw.env
}

func (hw *htmlWriter) write(nodes ...types.Node) error {
	for _, n := range nodes {
		if !hw.matchEnv(n.Env()) {
			continue
		}
		switch n := n.(type) {
		case *types.TextNode:
			hw.text(n)
		case *types.ImageNode:
			hw.image(n)
		case *types.URLNode:
			hw.url(n)
		case *types.ButtonNode:
			hw.button(n)
		case *types.CodeNode:
			hw.code(n)
			hw.writeBytes(newLine)
		case *types.ListNode:
			hw.list(n)
			hw.writeBytes(newLine)
		case *types.ImportNode:
			if len(n.Content.Nodes) == 0 {
				break
			}
			hw.list(n.Content)
			hw.writeBytes(newLine)
		case *types.ItemsListNode:
			hw.itemsList(n)
			hw.writeBytes(newLine)
		case *types.GridNode:
			hw.grid(n)
			hw.writeBytes(newLine)
		case *types.InfoboxNode:
			hw.infobox(n)
			hw.writeBytes(newLine)
		case *types.SurveyNode:
			hw.survey(n)
			hw.writeBytes(newLine)
		case *types.HeaderNode:
			hw.header(n)
			hw.writeBytes(newLine)
		case *types.YouTubeNode:
			hw.youtube(n)
			hw.writeBytes(newLine)
		}
		if hw.err != nil {
			return hw.err
		}
	}
	return nil
}

func (hw *htmlWriter) writeBytes(b []byte) {
	if hw.err != nil {
		return
	}
	_, hw.err = hw.w.Write(b)
}

func (hw *htmlWriter) writeString(s string) {
	hw.writeBytes([]byte(s))
}

func (hw *htmlWriter) writeFmt(f string, a ...interface{}) {
	hw.writeString(fmt.Sprintf(f, a...))
}

func (hw *htmlWriter) writeEscape(s string) {
	htmlTemplate.HTMLEscape(hw.w, []byte(s))
}

func (hw *htmlWriter) text(n *types.TextNode) {
	if n.Bold {
		hw.writeString("")
	}
	if n.Italic {
		hw.writeString("")
	}
	if n.Code {
		hw.writeString("")
	}
	s := htmlTemplate.HTMLEscapeString(n.Value)
	hw.writeString(strings.Replace(s, "\n", "
", -1))
	if n.Code {
		hw.writeString("")
	}
	if n.Italic {
		hw.writeString("")
	}
	if n.Bold {
		hw.writeString("")
	}
}

func (hw *htmlWriter) image(n *types.ImageNode) {
	hw.writeString(" 0 {
		hw.writeFmt(` style="max-width: %.2fpx"`, n.MaxWidth)
	}
	hw.writeString(` src="`)
	hw.writeString(n.Src)
	hw.writeBytes(doubleQuote)
	hw.writeBytes(greaterThan)
}

func (hw *htmlWriter) url(n *types.URLNode) {
	hw.writeString("<a")
	if n.URL != "" {
		hw.writeString(` href="`)
		hw.writeString(n.URL)
		hw.writeBytes(doubleQuote)
	}
	if n.Name != "" {
		hw.writeString(` name="`)
		hw.writeEscape(n.Name)
		hw.writeBytes(doubleQuote)
	}
	if n.Target != "" {
		hw.writeString(` target="`)
		hw.writeEscape(n.Target)
		hw.writeBytes(doubleQuote)
	}
	hw.writeBytes(greaterThan)
	hw.write(n.Content.Nodes...)
	hw.writeString("")
}

func (hw *htmlWriter) button(n *types.ButtonNode) {
	hw.writeString("<paper-button")
	if n.Colored {
		hw.writeString(` class="colored"`)
	}
	if n.Raised {
		hw.writeString(" raised")
	}
	hw.writeBytes(greaterThan)
	if n.Download {
		hw.writeString(`<iron-icon icon="file-download"></iron-icon>`)
	}
	hw.write(n.Content.Nodes...)
	hw.writeString("</paper-button>")
}

func (hw *htmlWriter) code(n *types.CodeNode) {
	hw.writeString("
")
	if !n.Term {
		hw.writeString("<code")
		if n.Lang != "" {
			hw.writeFmt(" language=%q class=%q", n.Lang, n.Lang)
		}
		hw.writeBytes(greaterThan)
	}
	hw.writeEscape(n.Value)
	if !n.Term {
		hw.writeString("")
	}
	hw.writeString("
")
}

func (hw *htmlWriter) list(n *types.ListNode) {
	wrap := n.Block() == true
	if wrap {
		hw.writeString("
")
	}
	hw.write(n.Nodes...)
	if wrap {
		hw.writeString("
")
	}
}

func (hw *htmlWriter) itemsList(n *types.ItemsListNode) {
	tag := "ul"
	if n.Type() == types.NodeItemsList && (n.Start > 0 || n.ListType != "") {
		tag = "ol"
	}
	hw.writeBytes(lessThan)
	hw.writeString(tag)
	switch n.Type() {
	case types.NodeItemsCheck:
		hw.writeString(` class="checklist"`)
	case types.NodeItemsFAQ:
		hw.writeString(` class="faq"`)
	default:
		if n.ListType != "" {
			hw.writeString(` type="`)
			hw.writeString(n.ListType)
			hw.writeBytes(doubleQuote)
		}
		if n.Start > 0 {
			hw.writeFmt(` start="%d"`, n.Start)
		}
	}
	hw.writeBytes(greaterThan)
	hw.writeBytes(newLine)

	for _, i := range n.Items {
		hw.writeString("
")
		hw.write(i.Nodes...)
		hw.writeString("
\n")
	}

	hw.writeString("</")
	hw.writeString(tag)
	hw.writeBytes(greaterThan)
}

func (hw *htmlWriter) grid(n *types.GridNode) {
	hw.writeString("
\n")
	for _, r := range n.Rows {
		hw.writeString("
")
		for _, c := range r {
			hw.writeFmt(`<td colspan="%d" rowspan="%d">`, c.Colspan, c.Rowspan)
			hw.write(c.Content.Nodes...)
			hw.writeString("	")
		}
		hw.writeString("
\n")
	}
	hw.writeString("
")
}

func (hw *htmlWriter) infobox(n *types.InfoboxNode) {
	hw.writeString(`<aside class="`)
	hw.writeEscape(string(n.Kind))
	hw.writeString(`">`)
	hw.write(n.Content.Nodes...)
	hw.writeString("")
}

func (hw *htmlWriter) survey(n *types.SurveyNode) {
	hw.writeString(`<google-codelab-survey survey-id="`)
	hw.writeString(n.ID)
	hw.writeBytes(doubleQuote)
	hw.writeString(">\n")
	for _, g := range n.Groups {
		hw.writeString("
")
		hw.writeEscape(g.Name)
		hw.writeString("
\n<paper-radio-group>\n")
		for _, o := range g.Options {
			hw.writeString("<paper-radio-button>")
			hw.writeEscape(o)
			hw.writeString("</paper-radio-button>\n")
		}
		hw.writeString("</paper-radio-group>\n")
	}
	hw.writeString("</google-codelab-survey>")
}

func (hw *htmlWriter) header(n *types.HeaderNode) {
	tag := "h" + strconv.Itoa(n.Level)
	hw.writeBytes(lessThan)
	hw.writeString(tag)
	switch n.Type() {
	case types.NodeHeaderCheck:
		hw.writeString(` class="checklist"`)
	case types.NodeHeaderFAQ:
		hw.writeString(` class="faq"`)
	}
	hw.writeBytes(greaterThan)
	hw.write(n.Content.Nodes...)
	hw.writeString("</")
	hw.writeString(tag)
	hw.writeBytes(greaterThan)
}

func (hw *htmlWriter) youtube(n *types.YouTubeNode) {
	hw.writeFmt("<google-youtube fluid video-id=%q></google-youtube>", n.VideoID)
}
<|endoftext|>


<commit_before>// Package provides ability to print colored text on stdout
package clicolor

import (
	"fmt"
	"io"
	"os"
	"regexp"
	"strings"
	"github.com/shiena/ansicolor"
	"runtime"
)

const (
	startSeq = "\033["
	endSeq   = "\033[0m"
)

type Printer struct {
	text string
}

var colors map[string]string

// Will be used as first argument of fmt.Fprintln
// so with this you are able to redirect output stream
var Out io.Writer

// Printing colored text in one choosed color
func (p *Printer) In(color string) {
	p.text = "{" + color + "}" + p.text
	p.InFormat()
}

// Printing colored text based on user format
// User needs to provide one of supported colors
// Example: `this{red} is red{blue} and this is blue. {default} Now is default`
func (p *Printer) InFormat() {
	// find all text groups which need to be colored
	re := regexp.MustCompile(`(\{\w*\}[^{}]+)`)
	matches := re.FindAllStringSubmatch(p.text, -1)

	for _, value := range matches {
		// extract color from `{color} some text`
		re = regexp.MustCompile(`{(\w*)}`)
		color := re.FindStringSubmatch(value[0])[1]
		colorcode := getColor(color)

		// extract text from `{color} some text`
		re = regexp.MustCompile(`^{\w*}(.*)`)
		text := re.FindStringSubmatch(value[0])[1]

		// format string for ANSI/VT1000 terminal
		clifmt := startSeq + colorcode + text + endSeq
		p.text = strings.Replace(p.text, value[0], clifmt, -1)
	}

	fmt.Fprintln(Out, p.text)
}

// Initialization of supported colors
func init() {
	colors = make(map[string]string)
	colors["black"] = "30m"
	colors["red"] = "31m"
	colors["green"] = "32m"
	colors["yellow"] = "33m"
	colors["blue"] = "34m"
	colors["magenta"] = "35m"
	colors["cyan"] = "36m"
	colors["white"] = "37m"
	colors["default"] = "39m"

	if runtime.GOOS == "windows" {
    	Out = ansicolor.NewAnsiColorWriter(os.Stdout)
	} else {
		Out = os.Stdout
	}
}

// Finding color code, and returning default one if requested doesn't exit
func getColor(color string) string {
	var colorcode string

	if value, ok := colors[color]; ok {
		colorcode = value
	} else {
		colorcode = colors["default"]
	}

	return colorcode
}

// Provide text for printing
func Print(color string) *Printer {
	return &Printer{color}
}
<commit_msg>Compile regexps once, rather than on every call<commit_after>// Package provides ability to print colored text on stdout
package clicolor

import (
	"fmt"
	"io"
	"os"
	"regexp"
	"strings"
	"github.com/shiena/ansicolor"
	"runtime"
)

const (
	startSeq = "\033["
	endSeq   = "\033[0m"
)

type Printer struct {
	text string
}

var colors map[string]string

// Will be used as first argument of fmt.Fprintln
// so with this you are able to redirect output stream
var Out io.Writer

var (
	// Used to find groups that need to be colored
	colorGroupRE *regexp.Regexp = regexp.MustCompile(`(\{\w*\}[^{}]+)`)

	// Used to extract color part of `{color} text`
	colorPartRE *regexp.Regexp = regexp.MustCompile(`{(\w*)}`)

	// Used to extract text part of `{color} text`
	textPartRE *regexp.Regexp = regexp.MustCompile(`^{\w*}(.*)`)
)

// Printing colored text in one choosed color
func (p *Printer) In(color string) {
	p.text = "{" + color + "}" + p.text
	p.InFormat()
}

// Printing colored text based on user format
// User needs to provide one of supported colors
// Example: `this{red} is red{blue} and this is blue. {default} Now is default`
func (p *Printer) InFormat() {
	// find all text groups which need to be colored
	matches := colorGroupRE.FindAllStringSubmatch(p.text, -1)

	for _, value := range matches {
		// extract color from `{color} some text`
		color := colorPartRE.FindStringSubmatch(value[0])[1]
		colorcode := getColor(color)

		// extract text from `{color} some text`
		text := textPartRE.FindStringSubmatch(value[0])[1]

		// format string for ANSI/VT1000 terminal
		clifmt := startSeq + colorcode + text + endSeq
		p.text = strings.Replace(p.text, value[0], clifmt, -1)
	}

	fmt.Fprintln(Out, p.text)
}

// Initialization of supported colors
func init() {
	colors = make(map[string]string)
	colors["black"] = "30m"
	colors["red"] = "31m"
	colors["green"] = "32m"
	colors["yellow"] = "33m"
	colors["blue"] = "34m"
	colors["magenta"] = "35m"
	colors["cyan"] = "36m"
	colors["white"] = "37m"
	colors["default"] = "39m"

	if runtime.GOOS == "windows" {
    	Out = ansicolor.NewAnsiColorWriter(os.Stdout)
	} else {
		Out = os.Stdout
	}
}

// Finding color code, and returning default one if requested doesn't exit
func getColor(color string) string {
	var colorcode string

	if value, ok := colors[color]; ok {
		colorcode = value
	} else {
		colorcode = colors["default"]
	}

	return colorcode
}

// Provide text for printing
func Print(color string) *Printer {
	return &Printer{color}
}
<|endoftext|>


<commit_before>package driver

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"
	"syscall"
	"time"

	"github.com/hashicorp/nomad/client/allocdir"
	"github.com/hashicorp/nomad/client/config"
	cstructs "github.com/hashicorp/nomad/client/driver/structs"
	"github.com/hashicorp/nomad/client/fingerprint"
	"github.com/hashicorp/nomad/helper/args"
	"github.com/hashicorp/nomad/nomad/structs"
	"github.com/mitchellh/mapstructure"
)

var (
	reRktVersion  = regexp.MustCompile(`rkt version (\d[.\d]+)`)
	reAppcVersion = regexp.MustCompile(`appc version (\d[.\d]+)`)
)

// RktDriver is a driver for running images via Rkt
// We attempt to chose sane defaults for now, with more configuration available
// planned in the future
type RktDriver struct {
	DriverContext
	fingerprint.StaticFingerprinter
}

type RktDriverConfig struct {
	ImageName string   `mapstructure:"image"`
	Args      []string `mapstructure:"args"`
}

// rktHandle is returned from Start/Open as a handle to the PID
type rktHandle struct {
	proc   *os.Process
	image  string
	logger *log.Logger
	waitCh chan *cstructs.WaitResult
	doneCh chan struct{}
}

// rktPID is a struct to map the pid running the process to the vm image on
// disk
type rktPID struct {
	Pid   int
	Image string
}

// NewRktDriver is used to create a new exec driver
func NewRktDriver(ctx *DriverContext) Driver {
	return &RktDriver{DriverContext: *ctx}
}

func (d *RktDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
	// Only enable if we are root when running on non-windows systems.
	if runtime.GOOS != "windows" && syscall.Geteuid() != 0 {
		d.logger.Printf("[DEBUG] driver.rkt: must run as root user, disabling")
		return false, nil
	}

	outBytes, err := exec.Command("rkt", "version").Output()
	if err != nil {
		return false, nil
	}
	out := strings.TrimSpace(string(outBytes))

	rktMatches := reRktVersion.FindStringSubmatch(out)
	appcMatches := reAppcVersion.FindStringSubmatch(out)
	if len(rktMatches) != 2 || len(appcMatches) != 2 {
		return false, fmt.Errorf("Unable to parse Rkt version string: %#v", rktMatches)
	}

	node.Attributes["driver.rkt"] = "1"
	node.Attributes["driver.rkt.version"] = rktMatches[1]
	node.Attributes["driver.rkt.appc.version"] = appcMatches[1]

	return true, nil
}

// Run an existing Rkt image.
func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error) {
	var driverConfig RktDriverConfig
	if err := mapstructure.WeakDecode(task.Config, &driverConfig); err != nil {
		return nil, err
	}
	// Validate that the config is valid.
	img := driverConfig.ImageName
	if img == "" {
		return nil, fmt.Errorf("Missing ACI image for rkt")
	}

	// Get the tasks local directory.
	taskName := d.DriverContext.taskName
	taskDir, ok := ctx.AllocDir.TaskDirs[taskName]
	if !ok {
		return nil, fmt.Errorf("Could not find task directory for task: %v", d.DriverContext.taskName)
	}
	taskLocal := filepath.Join(taskDir, allocdir.TaskLocal)

	// Add the given trust prefix
	trustPrefix, trustCmd := task.Config["trust_prefix"]
	if trustCmd {
		var outBuf, errBuf bytes.Buffer
		cmd := exec.Command("rkt", "trust", fmt.Sprintf("--prefix=%s", trustPrefix))
		cmd.Stdout = &outBuf
		cmd.Stderr = &errBuf
		if err := cmd.Run(); err != nil {
			return nil, fmt.Errorf("Error running rkt trust: %s\n\nOutput: %s\n\nError: %s",
				err, outBuf.String(), errBuf.String())
		}
		d.logger.Printf("[DEBUG] driver.rkt: added trust prefix: %q", trustPrefix)
	}

	// Build the command.
	var cmdArgs []string

	// Inject the environment variables.
	envVars := TaskEnvironmentVariables(ctx, task)

	// Clear the task directories as they are not currently supported.
	envVars.ClearTaskLocalDir()
	envVars.ClearAllocDir()

	for k, v := range envVars.Map() {
		cmdArgs = append(cmdArgs, fmt.Sprintf("--set-env=%v=%v", k, v))
	}

	// Disble signature verification if the trust command was not run.
	if !trustCmd {
		cmdArgs = append(cmdArgs, "--insecure-skip-verify")
	}

	// Append the run command.
	cmdArgs = append(cmdArgs, "run", "--mds-register=false", img)

	// Check if the user has overriden the exec command.
	if execCmd, ok := task.Config["command"]; ok {
		cmdArgs = append(cmdArgs, fmt.Sprintf("--exec=%v", execCmd))
	}

	if task.Resources.MemoryMB == 0 {
		return nil, fmt.Errorf("Memory limit cannot be zero")
	}
	if task.Resources.CPU == 0 {
		return nil, fmt.Errorf("CPU limit cannot be zero")
	}

	// Add memory isolator
	cmdArgs = append(cmdArgs, fmt.Sprintf("--memory=%vM", int64(task.Resources.MemoryMB)*1024*1024))

	// Add CPU isolator
	cmdArgs = append(cmdArgs, fmt.Sprintf("--cpu=%vm", int64(task.Resources.CPU)))

	// Add user passed arguments.
	if len(driverConfig.Args) != 0 {
		parsed := args.ParseAndReplace(driverConfig.Args, envVars.Map())

		// Need to start arguments with "--"
		if len(parsed) > 0 {
			cmdArgs = append(cmdArgs, "--")
		}

		for _, arg := range parsed {
			cmdArgs = append(cmdArgs, fmt.Sprintf("%v", arg))
		}
	}

	// Create files to capture stdin and out.
	stdoutFilename := filepath.Join(taskLocal, fmt.Sprintf("%s.stdout", taskName))
	stderrFilename := filepath.Join(taskLocal, fmt.Sprintf("%s.stderr", taskName))

	stdo, err := os.OpenFile(stdoutFilename, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
	if err != nil {
		return nil, fmt.Errorf("Error opening file to redirect stdout: %v", err)
	}

	stde, err := os.OpenFile(stderrFilename, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
	if err != nil {
		return nil, fmt.Errorf("Error opening file to redirect stderr: %v", err)
	}

	cmd := exec.Command("rkt", cmdArgs...)
	cmd.Stdout = stdo
	cmd.Stderr = stde

	if err := cmd.Start(); err != nil {
		return nil, fmt.Errorf("Error running rkt: %v", err)
	}

	d.logger.Printf("[DEBUG] driver.rkt: started ACI %q with: %v", img, cmd.Args)
	h := &rktHandle{
		proc:   cmd.Process,
		image:  img,
		logger: d.logger,
		doneCh: make(chan struct{}),
		waitCh: make(chan *cstructs.WaitResult, 1),
	}
	go h.run()
	return h, nil
}

func (d *RktDriver) Open(ctx *ExecContext, handleID string) (DriverHandle, error) {
	// Parse the handle
	pidBytes := []byte(strings.TrimPrefix(handleID, "Rkt:"))
	qpid := &rktPID{}
	if err := json.Unmarshal(pidBytes, qpid); err != nil {
		return nil, fmt.Errorf("failed to parse Rkt handle '%s': %v", handleID, err)
	}

	// Find the process
	proc, err := os.FindProcess(qpid.Pid)
	if proc == nil || err != nil {
		return nil, fmt.Errorf("failed to find Rkt PID %d: %v", qpid.Pid, err)
	}

	// Return a driver handle
	h := &rktHandle{
		proc:   proc,
		image:  qpid.Image,
		logger: d.logger,
		doneCh: make(chan struct{}),
		waitCh: make(chan *cstructs.WaitResult, 1),
	}

	go h.run()
	return h, nil
}

func (h *rktHandle) ID() string {
	// Return a handle to the PID
	pid := &rktPID{
		Pid:   h.proc.Pid,
		Image: h.image,
	}
	data, err := json.Marshal(pid)
	if err != nil {
		h.logger.Printf("[ERR] driver.rkt: failed to marshal rkt PID to JSON: %s", err)
	}
	return fmt.Sprintf("Rkt:%s", string(data))
}

func (h *rktHandle) WaitCh() chan *cstructs.WaitResult {
	return h.waitCh
}

func (h *rktHandle) Update(task *structs.Task) error {
	// Update is not possible
	return nil
}

// Kill is used to terminate the task. We send an Interrupt
// and then provide a 5 second grace period before doing a Kill.
func (h *rktHandle) Kill() error {
	h.proc.Signal(os.Interrupt)
	select {
	case <-h.doneCh:
		return nil
	case <-time.After(5 * time.Second):
		return h.proc.Kill()
	}
}

func (h *rktHandle) run() {
	ps, err := h.proc.Wait()
	close(h.doneCh)
	code := 0
	if !ps.Success() {
		// TODO: Better exit code parsing.
		code = 1
	}
	h.waitCh <- cstructs.NewWaitResult(code, 0, err)
	close(h.waitCh)
}
<commit_msg>Do not allow rkt version less than 0.14.0<commit_after>package driver

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"
	"syscall"
	"time"

	"github.com/hashicorp/go-version"
	"github.com/hashicorp/nomad/client/allocdir"
	"github.com/hashicorp/nomad/client/config"
	cstructs "github.com/hashicorp/nomad/client/driver/structs"
	"github.com/hashicorp/nomad/client/fingerprint"
	"github.com/hashicorp/nomad/helper/args"
	"github.com/hashicorp/nomad/nomad/structs"
	"github.com/mitchellh/mapstructure"
)

var (
	reRktVersion  = regexp.MustCompile(`rkt version (\d[.\d]+)`)
	reAppcVersion = regexp.MustCompile(`appc version (\d[.\d]+)`)
)

// RktDriver is a driver for running images via Rkt
// We attempt to chose sane defaults for now, with more configuration available
// planned in the future
type RktDriver struct {
	DriverContext
	fingerprint.StaticFingerprinter
}

type RktDriverConfig struct {
	ImageName string   `mapstructure:"image"`
	Args      []string `mapstructure:"args"`
}

// rktHandle is returned from Start/Open as a handle to the PID
type rktHandle struct {
	proc   *os.Process
	image  string
	logger *log.Logger
	waitCh chan *cstructs.WaitResult
	doneCh chan struct{}
}

// rktPID is a struct to map the pid running the process to the vm image on
// disk
type rktPID struct {
	Pid   int
	Image string
}

// NewRktDriver is used to create a new exec driver
func NewRktDriver(ctx *DriverContext) Driver {
	return &RktDriver{DriverContext: *ctx}
}

func (d *RktDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
	// Only enable if we are root when running on non-windows systems.
	if runtime.GOOS != "windows" && syscall.Geteuid() != 0 {
		d.logger.Printf("[DEBUG] driver.rkt: must run as root user, disabling")
		return false, nil
	}

	outBytes, err := exec.Command("rkt", "version").Output()
	if err != nil {
		return false, nil
	}
	out := strings.TrimSpace(string(outBytes))

	rktMatches := reRktVersion.FindStringSubmatch(out)
	appcMatches := reAppcVersion.FindStringSubmatch(out)
	if len(rktMatches) != 2 || len(appcMatches) != 2 {
		return false, fmt.Errorf("Unable to parse Rkt version string: %#v", rktMatches)
	}

	node.Attributes["driver.rkt"] = "1"
	node.Attributes["driver.rkt.version"] = rktMatches[1]
	node.Attributes["driver.rkt.appc.version"] = appcMatches[1]

	minVersion, _ := version.NewVersion("0.14.0")
	currentVersion, _ := version.NewVersion(node.Attributes["driver.rkt.version"])
	if currentVersion.LessThan(minVersion) {
		// Do not allow rkt < 0.14.0
		d.logger.Printf("[WARN] driver.rkt: please upgrade rkt to a version >= %s", minVersion)
		node.Attributes["driver.rkt"] = "0"
	}
	return true, nil
}

// Run an existing Rkt image.
func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error) {
	var driverConfig RktDriverConfig
	if err := mapstructure.WeakDecode(task.Config, &driverConfig); err != nil {
		return nil, err
	}
	// Validate that the config is valid.
	img := driverConfig.ImageName
	if img == "" {
		return nil, fmt.Errorf("Missing ACI image for rkt")
	}

	// Get the tasks local directory.
	taskName := d.DriverContext.taskName
	taskDir, ok := ctx.AllocDir.TaskDirs[taskName]
	if !ok {
		return nil, fmt.Errorf("Could not find task directory for task: %v", d.DriverContext.taskName)
	}
	taskLocal := filepath.Join(taskDir, allocdir.TaskLocal)

	// Add the given trust prefix
	trustPrefix, trustCmd := task.Config["trust_prefix"]
	if trustCmd {
		var outBuf, errBuf bytes.Buffer
		cmd := exec.Command("rkt", "trust", fmt.Sprintf("--prefix=%s", trustPrefix))
		cmd.Stdout = &outBuf
		cmd.Stderr = &errBuf
		if err := cmd.Run(); err != nil {
			return nil, fmt.Errorf("Error running rkt trust: %s\n\nOutput: %s\n\nError: %s",
				err, outBuf.String(), errBuf.String())
		}
		d.logger.Printf("[DEBUG] driver.rkt: added trust prefix: %q", trustPrefix)
	}

	// Build the command.
	var cmdArgs []string

	// Inject the environment variables.
	envVars := TaskEnvironmentVariables(ctx, task)

	// Clear the task directories as they are not currently supported.
	envVars.ClearTaskLocalDir()
	envVars.ClearAllocDir()

	for k, v := range envVars.Map() {
		cmdArgs = append(cmdArgs, fmt.Sprintf("--set-env=%v=%v", k, v))
	}

	// Disble signature verification if the trust command was not run.
	if !trustCmd {
		cmdArgs = append(cmdArgs, "--insecure-skip-verify")
	}

	// Append the run command.
	cmdArgs = append(cmdArgs, "run", "--mds-register=false", img)

	// Check if the user has overriden the exec command.
	if execCmd, ok := task.Config["command"]; ok {
		cmdArgs = append(cmdArgs, fmt.Sprintf("--exec=%v", execCmd))
	}

	if task.Resources.MemoryMB == 0 {
		return nil, fmt.Errorf("Memory limit cannot be zero")
	}
	if task.Resources.CPU == 0 {
		return nil, fmt.Errorf("CPU limit cannot be zero")
	}

	// Add memory isolator
	cmdArgs = append(cmdArgs, fmt.Sprintf("--memory=%vM", int64(task.Resources.MemoryMB)*1024*1024))

	// Add CPU isolator
	cmdArgs = append(cmdArgs, fmt.Sprintf("--cpu=%vm", int64(task.Resources.CPU)))

	// Add user passed arguments.
	if len(driverConfig.Args) != 0 {
		parsed := args.ParseAndReplace(driverConfig.Args, envVars.Map())

		// Need to start arguments with "--"
		if len(parsed) > 0 {
			cmdArgs = append(cmdArgs, "--")
		}

		for _, arg := range parsed {
			cmdArgs = append(cmdArgs, fmt.Sprintf("%v", arg))
		}
	}

	// Create files to capture stdin and out.
	stdoutFilename := filepath.Join(taskLocal, fmt.Sprintf("%s.stdout", taskName))
	stderrFilename := filepath.Join(taskLocal, fmt.Sprintf("%s.stderr", taskName))

	stdo, err := os.OpenFile(stdoutFilename, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
	if err != nil {
		return nil, fmt.Errorf("Error opening file to redirect stdout: %v", err)
	}

	stde, err := os.OpenFile(stderrFilename, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
	if err != nil {
		return nil, fmt.Errorf("Error opening file to redirect stderr: %v", err)
	}

	cmd := exec.Command("rkt", cmdArgs...)
	cmd.Stdout = stdo
	cmd.Stderr = stde

	if err := cmd.Start(); err != nil {
		return nil, fmt.Errorf("Error running rkt: %v", err)
	}

	d.logger.Printf("[DEBUG] driver.rkt: started ACI %q with: %v", img, cmd.Args)
	h := &rktHandle{
		proc:   cmd.Process,
		image:  img,
		logger: d.logger,
		doneCh: make(chan struct{}),
		waitCh: make(chan *cstructs.WaitResult, 1),
	}
	go h.run()
	return h, nil
}

func (d *RktDriver) Open(ctx *ExecContext, handleID string) (DriverHandle, error) {
	// Parse the handle
	pidBytes := []byte(strings.TrimPrefix(handleID, "Rkt:"))
	qpid := &rktPID{}
	if err := json.Unmarshal(pidBytes, qpid); err != nil {
		return nil, fmt.Errorf("failed to parse Rkt handle '%s': %v", handleID, err)
	}

	// Find the process
	proc, err := os.FindProcess(qpid.Pid)
	if proc == nil || err != nil {
		return nil, fmt.Errorf("failed to find Rkt PID %d: %v", qpid.Pid, err)
	}

	// Return a driver handle
	h := &rktHandle{
		proc:   proc,
		image:  qpid.Image,
		logger: d.logger,
		doneCh: make(chan struct{}),
		waitCh: make(chan *cstructs.WaitResult, 1),
	}

	go h.run()
	return h, nil
}

func (h *rktHandle) ID() string {
	// Return a handle to the PID
	pid := &rktPID{
		Pid:   h.proc.Pid,
		Image: h.image,
	}
	data, err := json.Marshal(pid)
	if err != nil {
		h.logger.Printf("[ERR] driver.rkt: failed to marshal rkt PID to JSON: %s", err)
	}
	return fmt.Sprintf("Rkt:%s", string(data))
}

func (h *rktHandle) WaitCh() chan *cstructs.WaitResult {
	return h.waitCh
}

func (h *rktHandle) Update(task *structs.Task) error {
	// Update is not possible
	return nil
}

// Kill is used to terminate the task. We send an Interrupt
// and then provide a 5 second grace period before doing a Kill.
func (h *rktHandle) Kill() error {
	h.proc.Signal(os.Interrupt)
	select {
	case <-h.doneCh:
		return nil
	case <-time.After(5 * time.Second):
		return h.proc.Kill()
	}
}

func (h *rktHandle) run() {
	ps, err := h.proc.Wait()
	close(h.doneCh)
	code := 0
	if !ps.Success() {
		// TODO: Better exit code parsing.
		code = 1
	}
	h.waitCh <- cstructs.NewWaitResult(code, 0, err)
	close(h.waitCh)
}
<|endoftext|>


<commit_before>// Copyright 2016 The Xorm 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 builder

import (
	"fmt"

	"github.com/go-xorm/core"
)

type optype byte

const (
	condType   optype = iota // only conditions
	selectType               // select
	insertType               // insert
	updateType               // update
	deleteType               // delete
	unionType                // union
)

const (
	POSTGRES = "postgres"
	SQLITE   = "sqlite3"
	MYSQL    = "mysql"
	MSSQL    = "mssql"
	ORACLE   = "oracle"
)

type join struct {
	joinType  string
	joinTable string
	joinCond  Cond
}

type union struct {
	unionType string
	builder   *Builder
}

type limit struct {
	limitN int
	offset int
	style  string
	pk     string // Indicate PK when perform a LIMIT action in mssql. Use full name to avoid ambiguity
}

// Builder describes a SQL statement
type Builder struct {
	optype
	tableName  string
	subQuery   *Builder
	cond       Cond
	selects    []string
	joins      []join
	unions     []union
	limitation *limit
	inserts    Eq
	updates    []Eq
	orderBy    string
	groupBy    string
	having     string
	isNested   bool
}

// Select creates a select Builder
func Select(cols ...string) *Builder {
	builder := &Builder{cond: NewCond()}
	return builder.Select(cols...)
}

// Insert creates an insert Builder
func Insert(eq Eq) *Builder {
	builder := &Builder{cond: NewCond()}
	return builder.Insert(eq)
}

// Update creates an update Builder
func Update(updates ...Eq) *Builder {
	builder := &Builder{cond: NewCond()}
	return builder.Update(updates...)
}

// Delete creates a delete Builder
func Delete(conds ...Cond) *Builder {
	builder := &Builder{cond: NewCond()}
	return builder.Delete(conds...)
}

// Where sets where SQL
func (b *Builder) Where(cond Cond) *Builder {
	b.cond = b.cond.And(cond)
	return b
}

// From sets the name of table or the sub query's alias and itself
func (b *Builder) From(tableName string, subQuery ...*Builder) *Builder {
	b.tableName = tableName

	if len(subQuery) > 0 {
		b.subQuery = subQuery[0]
	}

	return b
}

// SetNestedFlag set the nested flag. If turn this on, current builder would accept empty table name when building SQL
// and this builder would also be treated as a nested query at the same time.
func (b *Builder) SetNestedFlag(isNested bool) *Builder {
	b.isNested = isNested

	return b
}

// TableName returns the table name
func (b *Builder) TableName() string {
	return b.tableName
}

// Into sets insert table name
func (b *Builder) Into(tableName string) *Builder {
	b.tableName = tableName
	return b
}

// Join sets join table and conditions
func (b *Builder) Join(joinType, joinTable string, joinCond interface{}) *Builder {
	switch joinCond.(type) {
	case Cond:
		b.joins = append(b.joins, join{joinType, joinTable, joinCond.(Cond)})
	case string:
		b.joins = append(b.joins, join{joinType, joinTable, Expr(joinCond.(string))})
	}

	return b
}

// Union sets union conditions
func (b *Builder) Union(unionTp string, unionCond *Builder) *Builder {
	var builder *Builder
	if b.optype != unionType {
		builder = &Builder{cond: NewCond()}
		builder.optype = unionType

		currentUnions := b.unions
		// erase sub unions (actually append to new Builder.unions)
		b.unions = nil

		builder.unions = append(append(builder.unions, union{"", b}), currentUnions...)
	} else {
		builder = b
	}

	if unionCond != nil {
		builder.unions = append(builder.unions, union{unionTp, unionCond})
	}

	return builder
}

// Limit sets limitN condition
func (b *Builder) Limit(style, pk string, limitN int, offset ...int) *Builder {
	b.limitation = &limit{style: style, limitN: limitN, pk: pk}

	if len(offset) > 0 {
		b.limitation.offset = offset[0]
	}

	return b
}

func (b *Builder) MySQLLimit(limitN int, offset ...int) *Builder {
	return b.Limit(core.MYSQL, "", limitN, offset...)
}

func (b *Builder) SQLLiteLimit(limitN int, offset ...int) *Builder {
	return b.Limit(core.SQLITE, "", limitN, offset...)
}

func (b *Builder) MsSQLLimit(pk string, limitN int, offset ...int) *Builder {
	return b.Limit(core.MSSQL, pk, limitN, offset...)
}

func (b *Builder) OracleLimit(limitN int, offset ...int) *Builder {
	return b.Limit(core.ORACLE, "", limitN, offset...)
}

// InnerJoin sets inner join
func (b *Builder) InnerJoin(joinTable string, joinCond interface{}) *Builder {
	return b.Join("INNER", joinTable, joinCond)
}

// LeftJoin sets left join SQL
func (b *Builder) LeftJoin(joinTable string, joinCond interface{}) *Builder {
	return b.Join("LEFT", joinTable, joinCond)
}

// RightJoin sets right join SQL
func (b *Builder) RightJoin(joinTable string, joinCond interface{}) *Builder {
	return b.Join("RIGHT", joinTable, joinCond)
}

// CrossJoin sets cross join SQL
func (b *Builder) CrossJoin(joinTable string, joinCond interface{}) *Builder {
	return b.Join("CROSS", joinTable, joinCond)
}

// FullJoin sets full join SQL
func (b *Builder) FullJoin(joinTable string, joinCond interface{}) *Builder {
	return b.Join("FULL", joinTable, joinCond)
}

// Select sets select SQL
func (b *Builder) Select(cols ...string) *Builder {
	b.selects = cols
	b.optype = selectType
	return b
}

// And sets AND condition
func (b *Builder) And(cond Cond) *Builder {
	b.cond = And(b.cond, cond)
	return b
}

// Or sets OR condition
func (b *Builder) Or(cond Cond) *Builder {
	b.cond = Or(b.cond, cond)
	return b
}

// Insert sets insert SQL
func (b *Builder) Insert(eq Eq) *Builder {
	b.inserts = eq
	b.optype = insertType
	return b
}

// Update sets update SQL
func (b *Builder) Update(updates ...Eq) *Builder {
	b.updates = updates
	b.optype = updateType
	return b
}

// Delete sets delete SQL
func (b *Builder) Delete(conds ...Cond) *Builder {
	b.cond = b.cond.And(conds...)
	b.optype = deleteType
	return b
}

// WriteTo implements Writer interface
func (b *Builder) WriteTo(w Writer) error {
	switch b.optype {
	case condType:
		return b.cond.WriteTo(w)
	case selectType:
		return b.selectWriteTo(w)
	case insertType:
		return b.insertWriteTo(w)
	case updateType:
		return b.updateWriteTo(w)
	case deleteType:
		return b.deleteWriteTo(w)
	case unionType:
		if b.limitation != nil {
			return b.limitWriteTo(w)
		}

		return b.unionWriteTo(w)
	}

	return ErrNotSupportType
}

// ToSQL convert a builder to SQL and args
func (b *Builder) ToSQL() (string, []interface{}, error) {
	w := NewWriter()
	if err := b.WriteTo(w); err != nil {
		return "", nil, err
	}

	return w.writer.String(), w.args, nil
}

// ConvertPlaceholder replaces ? to $1, $2 ... or :1, :2 ... according prefix
func ConvertPlaceholder(sql, prefix string) (string, error) {
	buf := StringBuilder{}
	var j, start = 0, 0
	for i := 0; i < len(sql); i++ {
		if sql[i] == '?' {
			_, err := buf.WriteString(sql[start:i])
			if err != nil {
				return "", err
			}
			start = i + 1

			_, err = buf.WriteString(prefix)
			if err != nil {
				return "", err
			}

			j = j + 1
			_, err = buf.WriteString(fmt.Sprintf("%d", j))
			if err != nil {
				return "", err
			}
		}
	}
	return buf.String(), nil
}

// ToSQL convert a builder or condtions to SQL and args
func ToSQL(cond interface{}) (string, []interface{}, error) {
	switch cond.(type) {
	case Cond:
		return condToSQL(cond.(Cond))
	case *Builder:
		return cond.(*Builder).ToSQL()
	}
	return "", nil, ErrNotSupportType
}
<commit_msg>Adjust references<commit_after>// Copyright 2016 The Xorm 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 builder

import (
	"fmt"
)

type optype byte

const (
	condType   optype = iota // only conditions
	selectType               // select
	insertType               // insert
	updateType               // update
	deleteType               // delete
	unionType                // union
)

const (
	POSTGRES = "postgres"
	SQLITE   = "sqlite3"
	MYSQL    = "mysql"
	MSSQL    = "mssql"
	ORACLE   = "oracle"
)

type join struct {
	joinType  string
	joinTable string
	joinCond  Cond
}

type union struct {
	unionType string
	builder   *Builder
}

type limit struct {
	limitN int
	offset int
	style  string
	pk     string // Indicate PK when perform a LIMIT action in mssql. Use full name to avoid ambiguity
}

// Builder describes a SQL statement
type Builder struct {
	optype
	tableName  string
	subQuery   *Builder
	cond       Cond
	selects    []string
	joins      []join
	unions     []union
	limitation *limit
	inserts    Eq
	updates    []Eq
	orderBy    string
	groupBy    string
	having     string
	isNested   bool
}

// Select creates a select Builder
func Select(cols ...string) *Builder {
	builder := &Builder{cond: NewCond()}
	return builder.Select(cols...)
}

// Insert creates an insert Builder
func Insert(eq Eq) *Builder {
	builder := &Builder{cond: NewCond()}
	return builder.Insert(eq)
}

// Update creates an update Builder
func Update(updates ...Eq) *Builder {
	builder := &Builder{cond: NewCond()}
	return builder.Update(updates...)
}

// Delete creates a delete Builder
func Delete(conds ...Cond) *Builder {
	builder := &Builder{cond: NewCond()}
	return builder.Delete(conds...)
}

// Where sets where SQL
func (b *Builder) Where(cond Cond) *Builder {
	b.cond = b.cond.And(cond)
	return b
}

// From sets the name of table or the sub query's alias and itself
func (b *Builder) From(tableName string, subQuery ...*Builder) *Builder {
	b.tableName = tableName

	if len(subQuery) > 0 {
		b.subQuery = subQuery[0]
	}

	return b
}

// SetNestedFlag set the nested flag. If turn this on, current builder would accept empty table name when building SQL
// and this builder would also be treated as a nested query at the same time.
func (b *Builder) SetNestedFlag(isNested bool) *Builder {
	b.isNested = isNested

	return b
}

// TableName returns the table name
func (b *Builder) TableName() string {
	return b.tableName
}

// Into sets insert table name
func (b *Builder) Into(tableName string) *Builder {
	b.tableName = tableName
	return b
}

// Join sets join table and conditions
func (b *Builder) Join(joinType, joinTable string, joinCond interface{}) *Builder {
	switch joinCond.(type) {
	case Cond:
		b.joins = append(b.joins, join{joinType, joinTable, joinCond.(Cond)})
	case string:
		b.joins = append(b.joins, join{joinType, joinTable, Expr(joinCond.(string))})
	}

	return b
}

// Union sets union conditions
func (b *Builder) Union(unionTp string, unionCond *Builder) *Builder {
	var builder *Builder
	if b.optype != unionType {
		builder = &Builder{cond: NewCond()}
		builder.optype = unionType

		currentUnions := b.unions
		// erase sub unions (actually append to new Builder.unions)
		b.unions = nil

		builder.unions = append(append(builder.unions, union{"", b}), currentUnions...)
	} else {
		builder = b
	}

	if unionCond != nil {
		builder.unions = append(builder.unions, union{unionTp, unionCond})
	}

	return builder
}

// Limit sets limitN condition
func (b *Builder) Limit(style, pk string, limitN int, offset ...int) *Builder {
	b.limitation = &limit{style: style, limitN: limitN, pk: pk}

	if len(offset) > 0 {
		b.limitation.offset = offset[0]
	}

	return b
}

func (b *Builder) MySQLLimit(limitN int, offset ...int) *Builder {
	return b.Limit(MYSQL, "", limitN, offset...)
}

func (b *Builder) SQLLiteLimit(limitN int, offset ...int) *Builder {
	return b.Limit(SQLITE, "", limitN, offset...)
}

func (b *Builder) MsSQLLimit(pk string, limitN int, offset ...int) *Builder {
	return b.Limit(MSSQL, pk, limitN, offset...)
}

func (b *Builder) OracleLimit(limitN int, offset ...int) *Builder {
	return b.Limit(ORACLE, "", limitN, offset...)
}

// InnerJoin sets inner join
func (b *Builder) InnerJoin(joinTable string, joinCond interface{}) *Builder {
	return b.Join("INNER", joinTable, joinCond)
}

// LeftJoin sets left join SQL
func (b *Builder) LeftJoin(joinTable string, joinCond interface{}) *Builder {
	return b.Join("LEFT", joinTable, joinCond)
}

// RightJoin sets right join SQL
func (b *Builder) RightJoin(joinTable string, joinCond interface{}) *Builder {
	return b.Join("RIGHT", joinTable, joinCond)
}

// CrossJoin sets cross join SQL
func (b *Builder) CrossJoin(joinTable string, joinCond interface{}) *Builder {
	return b.Join("CROSS", joinTable, joinCond)
}

// FullJoin sets full join SQL
func (b *Builder) FullJoin(joinTable string, joinCond interface{}) *Builder {
	return b.Join("FULL", joinTable, joinCond)
}

// Select sets select SQL
func (b *Builder) Select(cols ...string) *Builder {
	b.selects = cols
	b.optype = selectType
	return b
}

// And sets AND condition
func (b *Builder) And(cond Cond) *Builder {
	b.cond = And(b.cond, cond)
	return b
}

// Or sets OR condition
func (b *Builder) Or(cond Cond) *Builder {
	b.cond = Or(b.cond, cond)
	return b
}

// Insert sets insert SQL
func (b *Builder) Insert(eq Eq) *Builder {
	b.inserts = eq
	b.optype = insertType
	return b
}

// Update sets update SQL
func (b *Builder) Update(updates ...Eq) *Builder {
	b.updates = updates
	b.optype = updateType
	return b
}

// Delete sets delete SQL
func (b *Builder) Delete(conds ...Cond) *Builder {
	b.cond = b.cond.And(conds...)
	b.optype = deleteType
	return b
}

// WriteTo implements Writer interface
func (b *Builder) WriteTo(w Writer) error {
	switch b.optype {
	case condType:
		return b.cond.WriteTo(w)
	case selectType:
		return b.selectWriteTo(w)
	case insertType:
		return b.insertWriteTo(w)
	case updateType:
		return b.updateWriteTo(w)
	case deleteType:
		return b.deleteWriteTo(w)
	case unionType:
		if b.limitation != nil {
			return b.limitWriteTo(w)
		}

		return b.unionWriteTo(w)
	}

	return ErrNotSupportType
}

// ToSQL convert a builder to SQL and args
func (b *Builder) ToSQL() (string, []interface{}, error) {
	w := NewWriter()
	if err := b.WriteTo(w); err != nil {
		return "", nil, err
	}

	return w.writer.String(), w.args, nil
}

// ConvertPlaceholder replaces ? to $1, $2 ... or :1, :2 ... according prefix
func ConvertPlaceholder(sql, prefix string) (string, error) {
	buf := StringBuilder{}
	var j, start = 0, 0
	for i := 0; i < len(sql); i++ {
		if sql[i] == '?' {
			_, err := buf.WriteString(sql[start:i])
			if err != nil {
				return "", err
			}
			start = i + 1

			_, err = buf.WriteString(prefix)
			if err != nil {
				return "", err
			}

			j = j + 1
			_, err = buf.WriteString(fmt.Sprintf("%d", j))
			if err != nil {
				return "", err
			}
		}
	}
	return buf.String(), nil
}

// ToSQL convert a builder or condtions to SQL and args
func ToSQL(cond interface{}) (string, []interface{}, error) {
	switch cond.(type) {
	case Cond:
		return condToSQL(cond.(Cond))
	case *Builder:
		return cond.(*Builder).ToSQL()
	}
	return "", nil, ErrNotSupportType
}
<|endoftext|>


<commit_before>package eval

import (
	"fmt"
	"math/big"
	"strings"
	"time"
	"unicode"
)

const (
	ISO8601 string = "2006-01-02T15:04:05.999Z0700"
)

func builtin(name string, args []interface{}, context Context) (val interface{}, err error) {
	switch name {
	//salesforce text functions: CASESAFEID, GETSESSIONID, HYPERLINK, IMAGE, ISPICKVAL not implemented as too specific
	// TEXT should be avoided, use FORMAT instead
	case "BEGINS":
		NumOfParams(args, 2)
		s1 := MustBeString(args, 0)
		s2 := MustBeString(args, 1)
		return strings.Index(s1, s2) == 0, nil
	case "CONTAINS":
		NumOfParams(args, 2)
		s1 := MustBeString(args, 0)
		s2 := MustBeString(args, 1)
		return strings.Index(s1, s2) != -1, nil
	case "FIND":
		NumOfParams(args, 2)
		s1 := MustBeString(args, 0)
		s2 := MustBeString(args, 1)
		return new(big.Rat).SetInt64(int64(strings.Index(s1, s2))), nil
	case "INCLUDES":
		NumOfParams(args, 2)
		s1 := MustBeString(args, 0)
		s2 := MustBeString(args, 1)
		return strings.Index(";"+s1+";", ";"+s2+";") != -1, nil
	case "LEFT":
		NumOfParams(args, 2)
		s1 := MustBeString(args, 0)
		n1 := GetNumberAsInt(args, 1)
		return substr(s1, 0, n1), nil
	case "LEN":
		NumOfParams(args, 1)
		s1 := MustBeString(args, 0)
		return new(big.Rat).SetInt64(int64(len([]rune(s1)))), nil
	case "LOWER":
		NumOfParams(args, 1)
		s1 := MustBeString(args, 0)
		return strings.ToLower(s1), nil
	case "LPAD":
		n1 := GetNumberAsInt(args, 1)
		s1 := MustBeString(args, 0)
		s2 := " "
		if len(args) > 2 {
			NumOfParams(args, 3)
			s2 = MustBeString(args, 2)
		}
		s1r := []rune(s1)
		s2r := []rune(s2)
		if n1 == len(s1r) {
			return s1, nil
		} else if n1 < len(s1r) {
			return string(s1r[:n1]), nil
		}
		n1 = n1 - len(s1r)
		var sr []rune
		for i := 0; len(sr) < n1; i++ {
			sr = append(sr, s2r[i%len(s2r)])
		}
		return string(append(sr, s1r...)), nil
	case "MID":
		NumOfParams(args, 3)
		s1 := MustBeString(args, 0)
		n1 := GetNumberAsInt(args, 1)
		if n1 <= 0 {
			n1 = 1
		}
		n2 := GetNumberAsInt(args, 2)
		if n2 <= 0 {
			return "", nil
		}
		return substr(s1, n1-1, n2), nil
	case "RIGHT":
		NumOfParams(args, 2)
		s1 := MustBeString(args, 0)
		n1 := GetNumberAsInt(args, 1)
		if n1 <= 0 {
			return "", nil
		}
		return substr(s1, -n1, -1), nil
	case "RPAD":
		n1 := GetNumberAsInt(args, 1)
		s1 := MustBeString(args, 0)
		s2 := " "
		if len(args) > 2 {
			NumOfParams(args, 3)
			s2 = MustBeString(args, 2)
		}
		s1r := []rune(s1)
		s2r := []rune(s2)
		if n1 == len(s1r) {
			return s1, nil
		} else if n1 < len(s1r) {
			return string(s1r[:n1]), nil
		}
		for i := 0; len(s1r) < n1; i++ {
			s1r = append(s1r, s2r[i%len(s2r)])
		}
		return string(s1r), nil
	case "SUBSTITUTE":
		NumOfParams(args, 3)
		s1 := MustBeString(args, 0)
		s2 := MustBeString(args, 1)
		s3 := MustBeString(args, 2)
		return strings.Replace(s1, s2, s3, -1), nil
	case "TEXT":
		NumOfParams(args, 1)
		v1 := args[0]
		switch v1.(type) {
		case string:
			return v1.(string), nil
		case big.Rat:
			return v1.(*big.Rat).String(), nil
		case bool:
			if v1.(bool) {
				return "true", nil
			} else {
				return "false", nil
			}
		case time.Time:
			return v1.(time.Time).Format(ISO8601), nil
		}
		panic(fmt.Sprint("unsupported type:", v1))
	case "TRIM":
		NumOfParams(args, 1)
		s1 := MustBeString(args, 0)
		s1 = strings.TrimSpace(s1)
		s1r := []rune(s1)
		sr := make([]rune, 0, len(s1r))
		var first bool = false
		for _, r := range s1r {
			sp := unicode.IsSpace(r)
			if first && sp {
				sr = append(sr, ' ')
				first = false
			} else if !sp {
				sr = append(sr, r)
				first = true
			}
		}
		return string(sr), nil
	case "UPPER":
		NumOfParams(args, 1)
		s1 := MustBeString(args, 0)
		return strings.ToUpper(s1), nil
	case "VALUE":
		NumOfParams(args, 1)
		s1 := MustBeString(args, 0)
		f, ok := new(big.Rat).SetString(s1)
		if ok {
			return f, nil
		}
		panic(fmt.Sprint("not a number", s1))
	// salesforce date functions. DATEVALUE accepts additional format parameter
	case "DATE":
		NumOfParams(args, 3)
		n1 := GetNumberAsInt(args, 0)
		n2 := GetNumberAsInt(args, 1)
		n3 := GetNumberAsInt(args, 2)
		return time.Date(n1, time.Month(n2), n3, 0, 0, 0, 0, context.cast().localTimeZone), nil
	case "DATEVALUE":
		s1 := MustBeString(args, 0)
		s2 := "2006-01-02"
		if len(args) > 1 {
			NumOfParams(args, 2)
			s2 = MustBeString(args, 1)
		}
		return context.ParseDate(s2, s1)
	case "DAY":
		NumOfParams(args, 1)
		d1 := MustBeDate(args, 0)
		return new(big.Rat).SetInt64(int64(d1.Day())), nil
	case "MONTH":
		NumOfParams(args, 1)
		d1 := MustBeDate(args, 0)
		return new(big.Rat).SetInt64(int64(d1.Month())), nil
	case "NOW":
		NumOfParams(args, 0)
		return time.Now().In(context.cast().localTimeZone), nil
	case "TODAY":
		NumOfParams(args, 0)
		return time.Now().In(context.cast().localTimeZone).Truncate(time.Hour * 24), nil
	case "YEAR":
		NumOfParams(args, 1)
		d1 := MustBeDate(args, 0)
		return new(big.Rat).SetInt64(int64(d1.Year())), nil
		// salesforce logical functions: AND, NOT, OR should not be used, use logical operators
	case "CASE":
		MinNumOfParams(args, 3)
		i := 1
		for ; i < len(args)-1; i += 2 {
			switch args[0].(type) {
			case nil:
				if args[i] == nil {
					return args[i+1], nil
				}
			case *big.Rat:
				n := MustBeNumber(args, i)
				if args[0].(*big.Rat).Cmp(n) == 0 {
					return args[i+1], nil
				}
			case string:
				s := MustBeString(args, i)
				if args[0].(string) == s {
					return args[i+1], nil
				}
			case bool:
				b1 := MustBeBool(args, i)
				if args[0].(bool) == b1 {
					return args[i+1], nil
				}
			default:
				panic(fmt.Sprint("unsupported type:", args[i]))
			}
		}
		if i < len(args) {
			return args[i], nil
		}
		panic("missing default value")
	case "IF":
		NumOfParams(args, 3)
		cond := MustBeBool(args, 0)
		if cond {
			return args[1], nil
		}
		return args[2], nil
	case "NULLVALUE":
		NumOfParams(args, 2)
		if args[0] == nil {
			return args[1], nil
		}
		return args[0], nil
	// additional convenience functions for text
	// join(delimiter, strings...) joins non empty strings listed as arguments using delimiter (empty strings are skipped)
	case "JOIN":
		var a []string
		for i, v := range args[1:] {
			if v != nil {
				s := MustBeString(args, i+1)
				if s != "" {
					a = append(a, s)
				}
			}
		}
		s1 := MustBeString(args, 0)
		return strings.Join(a, s1), nil
	}
	panic("unknown function")
}

func substr(s string, b int, l int) string {
	r := []rune(s)
	if len(r) == 0 || l == 0 {
		return ""
	}
	if b < 0 {
		if -b >= len(r) {
			b = 0
		} else {
			b = len(r) + b
		}
	}
	if l < 0 {
		l = len(r)
	}
	e := b + l
	if e > len(r) {
		e = len(r)
	}
	return string(r[b:e])
}
<commit_msg>join added<commit_after>package eval

import (
	"fmt"
	"math/big"
	"strings"
	"time"
	"unicode"
)

const (
	ISO8601 string = "2006-01-02T15:04:05.999Z0700"
)

func builtin(name string, args []interface{}, context Context) (val interface{}, err error) {
	switch name {
	//salesforce text functions: CASESAFEID, GETSESSIONID, HYPERLINK, IMAGE, ISPICKVAL not implemented as too specific
	// TEXT should be avoided, use FORMAT instead
	case "BEGINS":
		NumOfParams(args, 2)
		s1 := MustBeString(args, 0)
		s2 := MustBeString(args, 1)
		return strings.Index(s1, s2) == 0, nil
	case "CONTAINS":
		NumOfParams(args, 2)
		s1 := MustBeString(args, 0)
		s2 := MustBeString(args, 1)
		return strings.Index(s1, s2) != -1, nil
	case "FIND":
		NumOfParams(args, 2)
		s1 := MustBeString(args, 0)
		s2 := MustBeString(args, 1)
		return new(big.Rat).SetInt64(int64(strings.Index(s1, s2))), nil
	case "INCLUDES":
		NumOfParams(args, 2)
		s1 := MustBeString(args, 0)
		s2 := MustBeString(args, 1)
		return strings.Index(";"+s1+";", ";"+s2+";") != -1, nil
	case "LEFT":
		NumOfParams(args, 2)
		s1 := MustBeString(args, 0)
		n1 := GetNumberAsInt(args, 1)
		return substr(s1, 0, n1), nil
	case "LEN":
		NumOfParams(args, 1)
		s1 := MustBeString(args, 0)
		return new(big.Rat).SetInt64(int64(len([]rune(s1)))), nil
	case "LOWER":
		NumOfParams(args, 1)
		s1 := MustBeString(args, 0)
		return strings.ToLower(s1), nil
	case "LPAD":
		n1 := GetNumberAsInt(args, 1)
		s1 := MustBeString(args, 0)
		s2 := " "
		if len(args) > 2 {
			NumOfParams(args, 3)
			s2 = MustBeString(args, 2)
		}
		s1r := []rune(s1)
		s2r := []rune(s2)
		if n1 == len(s1r) {
			return s1, nil
		} else if n1 < len(s1r) {
			return string(s1r[:n1]), nil
		}
		n1 = n1 - len(s1r)
		var sr []rune
		for i := 0; len(sr) < n1; i++ {
			sr = append(sr, s2r[i%len(s2r)])
		}
		return string(append(sr, s1r...)), nil
	case "MID":
		NumOfParams(args, 3)
		s1 := MustBeString(args, 0)
		n1 := GetNumberAsInt(args, 1)
		if n1 <= 0 {
			n1 = 1
		}
		n2 := GetNumberAsInt(args, 2)
		if n2 <= 0 {
			return "", nil
		}
		return substr(s1, n1-1, n2), nil
	case "RIGHT":
		NumOfParams(args, 2)
		s1 := MustBeString(args, 0)
		n1 := GetNumberAsInt(args, 1)
		if n1 <= 0 {
			return "", nil
		}
		return substr(s1, -n1, -1), nil
	case "RPAD":
		n1 := GetNumberAsInt(args, 1)
		s1 := MustBeString(args, 0)
		s2 := " "
		if len(args) > 2 {
			NumOfParams(args, 3)
			s2 = MustBeString(args, 2)
		}
		s1r := []rune(s1)
		s2r := []rune(s2)
		if n1 == len(s1r) {
			return s1, nil
		} else if n1 < len(s1r) {
			return string(s1r[:n1]), nil
		}
		for i := 0; len(s1r) < n1; i++ {
			s1r = append(s1r, s2r[i%len(s2r)])
		}
		return string(s1r), nil
	case "SUBSTITUTE":
		NumOfParams(args, 3)
		s1 := MustBeString(args, 0)
		s2 := MustBeString(args, 1)
		s3 := MustBeString(args, 2)
		return strings.Replace(s1, s2, s3, -1), nil
	case "TEXT":
		NumOfParams(args, 1)
		v1 := args[0]
		switch v1.(type) {
		case string:
			return v1.(string), nil
		case big.Rat:
			return v1.(*big.Rat).String(), nil
		case bool:
			if v1.(bool) {
				return "true", nil
			} else {
				return "false", nil
			}
		case time.Time:
			return v1.(time.Time).Format(ISO8601), nil
		}
		panic(fmt.Sprint("unsupported type:", v1))
	case "TRIM":
		NumOfParams(args, 1)
		s1 := MustBeString(args, 0)
		s1 = strings.TrimSpace(s1)
		s1r := []rune(s1)
		sr := make([]rune, 0, len(s1r))
		var first bool = false
		for _, r := range s1r {
			sp := unicode.IsSpace(r)
			if first && sp {
				sr = append(sr, ' ')
				first = false
			} else if !sp {
				sr = append(sr, r)
				first = true
			}
		}
		return string(sr), nil
	case "UPPER":
		NumOfParams(args, 1)
		s1 := MustBeString(args, 0)
		return strings.ToUpper(s1), nil
	case "ISBLANK":
		NumOfParams(args, 1)
		if args[0] == nil {
			return true, nil
		} else if s, ok := args[0].(string); ok && s == "" {
			return true, nil
		}
		return false, nil
	case "VALUE":
		NumOfParams(args, 1)
		s1 := MustBeString(args, 0)
		f, ok := new(big.Rat).SetString(s1)
		if ok {
			return f, nil
		}
		panic(fmt.Sprint("not a number", s1))
	// salesforce date functions. DATEVALUE accepts additional format parameter
	case "DATE":
		NumOfParams(args, 3)
		n1 := GetNumberAsInt(args, 0)
		n2 := GetNumberAsInt(args, 1)
		n3 := GetNumberAsInt(args, 2)
		return time.Date(n1, time.Month(n2), n3, 0, 0, 0, 0, context.cast().localTimeZone), nil
	case "DATEVALUE":
		s1 := MustBeString(args, 0)
		s2 := "2006-01-02"
		if len(args) > 1 {
			NumOfParams(args, 2)
			s2 = MustBeString(args, 1)
		}
		return context.ParseDate(s2, s1)
	case "DAY":
		NumOfParams(args, 1)
		d1 := MustBeDate(args, 0)
		return new(big.Rat).SetInt64(int64(d1.Day())), nil
	case "MONTH":
		NumOfParams(args, 1)
		d1 := MustBeDate(args, 0)
		return new(big.Rat).SetInt64(int64(d1.Month())), nil
	case "NOW":
		NumOfParams(args, 0)
		return time.Now().In(context.cast().localTimeZone), nil
	case "TODAY":
		NumOfParams(args, 0)
		return time.Now().In(context.cast().localTimeZone).Truncate(time.Hour * 24), nil
	case "YEAR":
		NumOfParams(args, 1)
		d1 := MustBeDate(args, 0)
		return new(big.Rat).SetInt64(int64(d1.Year())), nil
		// salesforce logical functions: AND, NOT, OR should not be used, use logical operators
	case "CASE":
		MinNumOfParams(args, 3)
		i := 1
		for ; i < len(args)-1; i += 2 {
			switch args[0].(type) {
			case nil:
				if args[i] == nil {
					return args[i+1], nil
				}
			case *big.Rat:
				n := MustBeNumber(args, i)
				if args[0].(*big.Rat).Cmp(n) == 0 {
					return args[i+1], nil
				}
			case string:
				s := MustBeString(args, i)
				if args[0].(string) == s {
					return args[i+1], nil
				}
			case bool:
				b1 := MustBeBool(args, i)
				if args[0].(bool) == b1 {
					return args[i+1], nil
				}
			default:
				panic(fmt.Sprint("unsupported type:", args[i]))
			}
		}
		if i < len(args) {
			return args[i], nil
		}
		panic("missing default value")
	case "IF":
		NumOfParams(args, 3)
		cond := MustBeBool(args, 0)
		if cond {
			return args[1], nil
		}
		return args[2], nil
	case "NULLVALUE":
		NumOfParams(args, 2)
		if args[0] == nil {
			return args[1], nil
		}
		return args[0], nil
	// additional convenience functions for text
	// join(delimiter, strings...) joins non empty strings listed as arguments using delimiter (empty strings are skipped)
	case "JOIN":
		var a []string
		for i, v := range args[1:] {
			if v != nil {
				s := MustBeString(args, i+1)
				if s != "" {
					a = append(a, s)
				}
			}
		}
		s1 := MustBeString(args, 0)
		return strings.Join(a, s1), nil
	}
	panic("unknown function")
}

func substr(s string, b int, l int) string {
	r := []rune(s)
	if len(r) == 0 || l == 0 {
		return ""
	}
	if b < 0 {
		if -b >= len(r) {
			b = 0
		} else {
			b = len(r) + b
		}
	}
	if l < 0 {
		l = len(r)
	}
	e := b + l
	if e > len(r) {
		e = len(r)
	}
	return string(r[b:e])
}
<|endoftext|>