<commit_before>package signifai

import (
	"bytes"
	"errors"

	"encoding/json"
	"github.com/intelsdi-x/snap-plugin-lib-go/v1/plugin"
	"log"
	"net/http"

	"strings"
)

var MissingHostServiceApplication = errors.New("Your Configuration is Missing a Host, Service, or Application Field")
var MissingAPI = errors.New("Your Configuration is Missing an API field - {metrics, deployments, incidents}")
var MissingAuth = errors.New("Your Configuration is Missing a token fields")

var updateSend = "https://collectors.signifai.io/v1"

func (p Publisher) postit(list []interface{}) error {
	postList := make(map[string][]interface{})
	postList["events"] = list
	jbytes, err := json.Marshal(postList)
	if err != nil {
		return err
	}

	req, err := http.NewRequest("POST", updateSend+"/"+p.api, bytes.NewBuffer(jbytes))
	req.Header.Set("Authorization", "Bearer "+p.token)
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	return nil
}

// Publisher is a publisher to the SignifAi System
type Publisher struct {
	api         string // api to use {metrics, incidents, deployment}
	token       string // JWT token to use
	host        string // host that is being collected from
	service     string // service that is being collected from
	application string // application that is being collected from
	initialized bool   // indicates that we've initialized the plugin
}

func New() *Publisher {
	return new(Publisher)
}

// GetConfigPolicy returns the configuration Policy needed for using
// this plugin
//
// we have quite a few optional parameters here
func (p *Publisher) GetConfigPolicy() (plugin.ConfigPolicy, error) {
	policy := plugin.NewConfigPolicy()
	policy.AddNewStringRule([]string{""}, "api", true)
	policy.AddNewStringRule([]string{""}, "token", false)
	policy.AddNewStringRule([]string{""}, "host", false)
	policy.AddNewStringRule([]string{""}, "service", false)
	policy.AddNewStringRule([]string{""}, "application", false)

	return *policy, nil
}

// prob. want to refactor me
// the default Get* functions from plugin do assertations along w/nil
// chks
func (p *Publisher) setConfig(cfg plugin.Config) error {

	if p.initialized {
		return nil
	}

	// mandatory
	api, err := cfg.GetString("api")
	if err != nil {
		log.Println(err)
		return err
	}
	p.api = api

	token, err := cfg.GetString("token")
	if err != nil {
		if err != plugin.ErrConfigNotFound {
			log.Println(err)
			return err
		}
	} else {
		p.token = token
	}

	host, err := cfg.GetString("host")
	if err != nil {
		if err != plugin.ErrConfigNotFound {
			log.Println(err)
			return err
		}
	} else {
		p.host = host
	}

	service, err := cfg.GetString("service")
	if err != nil {
		if err != plugin.ErrConfigNotFound {
			log.Println(err)
			return err
		}
	} else {
		p.service = service
	}

	application, err := cfg.GetString("application")
	if err != nil {
		if err != plugin.ErrConfigNotFound {
			log.Println(err)
			return err
		}
	} else {
		p.application = application
	}

	if p.api == "" {
		return MissingAPI
	}

	if p.host == "" && p.application == "" && p.service == "" {
		return MissingHostServiceApplication
	}

	if p.token == "" {
		return MissingAuth
	}

	p.initialized = true

	return nil
}

// Publish publishes snap metrics to SignifAI API
func (p *Publisher) Publish(mts []plugin.Metric, cfg plugin.Config) error {
	err := p.setConfig(cfg)
	if err != nil {
		return err
	}

	batch := 5
	total := len(mts)

	// break it up first into batches of 5
	if total > batch {
		loops := total / batch
		if total%batch != 0 {
			loops += 1
		}

		x := 0
		for i := 0; i < loops; i++ {
			if i+1 == loops {
				p.addMetrics(mts[x : total-1])
			} else {
				p.addMetrics(mts[x : x+batch])
			}
			x += batch
		}

	} else {
		p.addMetrics(mts)
	}

	return nil
}

func (p Publisher) addMetrics(mts []plugin.Metric) {
	var list []interface{}

	for _, m := range mts {

		var statics []string
		var attributes = make(map[string]interface{})
		for _, element := range m.Namespace {
			if element.IsDynamic() {
				attributes[element.Name] = element.Value
			} else {
				statics = append(statics, element.Value)
			}
		}

		switch p.api {
		case "metrics":
			o := Metric{
				EventSource: "Snap",
				Name:        strings.Join(statics, "."),
				Value:       m.Data,
				Timestamp:   m.Timestamp.Unix(),
				Attributes:  attributes,
			}

			if p.host != "" {
				o.Host = p.host
			}

			if p.service != "" {
				o.Service = p.service
			}

			if p.application != "" {
				o.Application = p.application
			}
			list = append(list, o)

		default:
			log.Println("sorry - incidents && deployments are not support yet.")
		}

	}

	err := p.postit(list)
	if err != nil {
		log.Println(err)
	}
}
<commit_msg>update license<commit_after>/*
http://www.apache.org/licenses/LICENSE-2.0.txt
Copyright 2017 SignifAI Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package signifai

import (
	"bytes"
	"errors"

	"encoding/json"
	"github.com/intelsdi-x/snap-plugin-lib-go/v1/plugin"
	"log"
	"net/http"

	"strings"
)

var MissingHostServiceApplication = errors.New("Your Configuration is Missing a Host, Service, or Application Field")
var MissingAPI = errors.New("Your Configuration is Missing an API field - {metrics, deployments, incidents}")
var MissingAuth = errors.New("Your Configuration is Missing a token fields")

var updateSend = "https://collectors.signifai.io/v1"

func (p Publisher) postit(list []interface{}) error {
	postList := make(map[string][]interface{})
	postList["events"] = list
	jbytes, err := json.Marshal(postList)
	if err != nil {
		return err
	}

	req, err := http.NewRequest("POST", updateSend+"/"+p.api, bytes.NewBuffer(jbytes))
	req.Header.Set("Authorization", "Bearer "+p.token)
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	return nil
}

// Publisher is a publisher to the SignifAi System
type Publisher struct {
	api         string // api to use {metrics, incidents, deployment}
	token       string // JWT token to use
	host        string // host that is being collected from
	service     string // service that is being collected from
	application string // application that is being collected from
	initialized bool   // indicates that we've initialized the plugin
}

func New() *Publisher {
	return new(Publisher)
}

// GetConfigPolicy returns the configuration Policy needed for using
// this plugin
//
// we have quite a few optional parameters here
func (p *Publisher) GetConfigPolicy() (plugin.ConfigPolicy, error) {
	policy := plugin.NewConfigPolicy()
	policy.AddNewStringRule([]string{""}, "api", true)
	policy.AddNewStringRule([]string{""}, "token", false)
	policy.AddNewStringRule([]string{""}, "host", false)
	policy.AddNewStringRule([]string{""}, "service", false)
	policy.AddNewStringRule([]string{""}, "application", false)

	return *policy, nil
}

// prob. want to refactor me
// the default Get* functions from plugin do assertations along w/nil
// chks
func (p *Publisher) setConfig(cfg plugin.Config) error {

	if p.initialized {
		return nil
	}

	// mandatory
	api, err := cfg.GetString("api")
	if err != nil {
		log.Println(err)
		return err
	}
	p.api = api

	token, err := cfg.GetString("token")
	if err != nil {
		if err != plugin.ErrConfigNotFound {
			log.Println(err)
			return err
		}
	} else {
		p.token = token
	}

	host, err := cfg.GetString("host")
	if err != nil {
		if err != plugin.ErrConfigNotFound {
			log.Println(err)
			return err
		}
	} else {
		p.host = host
	}

	service, err := cfg.GetString("service")
	if err != nil {
		if err != plugin.ErrConfigNotFound {
			log.Println(err)
			return err
		}
	} else {
		p.service = service
	}

	application, err := cfg.GetString("application")
	if err != nil {
		if err != plugin.ErrConfigNotFound {
			log.Println(err)
			return err
		}
	} else {
		p.application = application
	}

	if p.api == "" {
		return MissingAPI
	}

	if p.host == "" && p.application == "" && p.service == "" {
		return MissingHostServiceApplication
	}

	if p.token == "" {
		return MissingAuth
	}

	p.initialized = true

	return nil
}

// Publish publishes snap metrics to SignifAI API
func (p *Publisher) Publish(mts []plugin.Metric, cfg plugin.Config) error {
	err := p.setConfig(cfg)
	if err != nil {
		return err
	}

	batch := 5
	total := len(mts)

	// break it up first into batches of 5
	if total > batch {
		loops := total / batch
		if total%batch != 0 {
			loops += 1
		}

		x := 0
		for i := 0; i < loops; i++ {
			if i+1 == loops {
				p.addMetrics(mts[x : total-1])
			} else {
				p.addMetrics(mts[x : x+batch])
			}
			x += batch
		}

	} else {
		p.addMetrics(mts)
	}

	return nil
}

func (p Publisher) addMetrics(mts []plugin.Metric) {
	var list []interface{}

	for _, m := range mts {

		var statics []string
		var attributes = make(map[string]interface{})
		for _, element := range m.Namespace {
			if element.IsDynamic() {
				attributes[element.Name] = element.Value
			} else {
				statics = append(statics, element.Value)
			}
		}

		switch p.api {
		case "metrics":
			o := Metric{
				EventSource: "Snap",
				Name:        strings.Join(statics, "."),
				Value:       m.Data,
				Timestamp:   m.Timestamp.Unix(),
				Attributes:  attributes,
			}

			if p.host != "" {
				o.Host = p.host
			}

			if p.service != "" {
				o.Service = p.service
			}

			if p.application != "" {
				o.Application = p.application
			}
			list = append(list, o)

		default:
			log.Println("sorry - incidents && deployments are not support yet.")
		}

	}

	err := p.postit(list)
	if err != nil {
		log.Println(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/docopt/docopt-go"
	"io/ioutil"
	"net/http"
	"os"
	"os/user"
	"strings"
)

type Buckets struct {
	Buckets []string `json:"buckets"`
}

type Keys struct {
	Keys []string `json:"keys"`
}

type Command int

const (
	buckets = iota
	keys
	obj
	put
)

type Config struct {
	Url     string `json:"url"`
	Command Command
	Verbose bool `json:"verbose"`
	Bucket  string
	Key     string
	Show    bool `json:"show"`
}

type Args map[string]interface{}

func main() {
	args := parse_options()
	config := init_config(args)
	switch config.Command {
	case buckets:
		show_buckets(config)
	case obj:
		show_obj(config, config.Bucket, config.Key)
	case keys:
		if config.Show {
			show_objs(config)
		} else {
			show_keys(config)
		}
	case put:
		obj := read_stdin()
		put_obj(config, config.Bucket, config.Key, obj)
	}
}

func parse_options() Args {
	usage := `clerc - Command LinE Riak Client

Usage:
  clerc BUCKET KEY [--url=URL] [--put|--delete] [--verbose]
  clerc BUCKET [KEY] [--url=URL] [--verbose] [--show]
  clerc -h | --help
  clerc --version

Options:
  --url=URL  Set the URL of the riak web API. [default: http://127.0.0.1:8098]
  --verbose  Show additional information, useful for debugging.
  --show     List objects instead of keys when listing a bucket.
  -h --help  Show this screen.
  --version  Show version.
`
	args, err := docopt.Parse(usage, nil, true, "clerc (Command LinE Riak Client) 0.1", false)
	perror(err)
	return args
}

func init_config(args Args) Config {
	config := read_config_file()
	if args["--verbose"] == true {
		config.Verbose = true
	}
	if args["--show"] == true {
		config.Show = true
	}
	if args["--url"] != nil {
		config.Url = args["--url"].(string)
	}
	if args["BUCKET"] == "/" {
		config.Command = buckets
	} else if args["BUCKET"] != nil {
		config.Command = keys
		config.Bucket = args["BUCKET"].(string)
	}
	if args["KEY"] != nil {
		config.Command = obj
		config.Key = args["KEY"].(string)
	}
	if args["--put"] == true {
		config.Command = put
	}
	return config
}

func read_config_file() Config {
	config := new_config()
	usr, err := user.Current()
	perror(err)
	bytes, err := ioutil.ReadFile(usr.HomeDir + "/.clerc")
	if err != nil {
		log(config, "unable to read file :(")
	} else {
		err = json.Unmarshal(bytes, &config)
		log(config, "config: "+string(bytes))
		perror(err)
	}
	return config
}

func new_config() Config {
	return Config{
		Url:     "http://127.0.0.1:8098",
		Verbose: false,
		Show:    false,
	}
}

func read_stdin() []byte {
	bytes, err := ioutil.ReadAll(os.Stdin)
	perror(err)
	return bytes
}

func show_keys(config Config) {
	keys := get_keys(config)
	log(config, "Listing keys:")
	for _, key := range keys.Keys {
		fmt.Println(key)
	}
}

func get_keys(config Config) Keys {
	var keys Keys
	make_request(&keys, config,
		"/buckets/"+config.Bucket+"/keys?keys=true")
	return keys
}

func show_objs(config Config) {
	keys := get_keys(config)
	for _, key := range keys.Keys {
		fmt.Println("Key: " + key)
		show_obj(config, config.Bucket, key)
		fmt.Println("")
	}
	return
}

func show_obj(config Config, bucket string, key string) {
	obj := get_obj(config, bucket, key)
	log(config, "Showing object: "+bucket+"/"+key)
	fmt.Println(obj)
}

func put_obj(config Config, bucket string, key string, obj []byte) {
	resource := "/riak/" + config.Bucket + "/" + config.Key
	log(config, "Making request: "+config.Url+resource)
	reader := strings.NewReader(string(obj))
	resp, err := http.Post(config.Url+resource, "application/json", reader)
	perror(err)
	assert_status(resp, 204)
	read_body(config, resp)
}

func read_body(config Config, resp *http.Response) []byte {
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	perror(err)
	log(config, "Got response: "+string(body))
	return body
}

func get_obj(config Config, bucket string, key string) string {
	resource := "/buckets/" + bucket + "/keys/" + key
	log(config, "Making request: "+config.Url+resource)
	resp, err := http.Get(config.Url + resource)
	perror(err)
	assert_status(resp, 200)
	body := read_body(config, resp)
	return prettify(body)
}

func assert_status(resp *http.Response, status int) {
	if resp.StatusCode != status {
		perror(errors.New("Unexpected status: " + resp.Status))
	}
}

func prettify(data []byte) string {
	var prettyJson bytes.Buffer
	err := json.Indent(&prettyJson, data, "", "    ")
	if err != nil {
		return string(data)
	} else {
		return string(prettyJson.Bytes())
	}
}

func show_buckets(config Config) {
	buckets := get_buckets(config)
	log(config, "Listing buckets:")
	for _, bucket := range buckets.Buckets {
		fmt.Println(bucket)
	}
}

func get_buckets(config Config) Buckets {
	var buckets Buckets
	make_request(&buckets, config, "/buckets?buckets=true")
	return buckets
}

func make_request(data interface{}, config Config, resource string) {
	log(config, "Making request: "+config.Url+resource)
	resp, err := http.Get(config.Url + resource)
	perror(err)
	assert_status(resp, 200)
	body := read_body(config, resp)
	json.Unmarshal(body, &data)
}

func log(config Config, str string) {
	if config.Verbose {
		fmt.Println("*** " + str)
	}
}

func perror(err error) {
	if err != nil {
		panic(err)
	}
}
<commit_msg>Change name of variable resp to response<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/docopt/docopt-go"
	"io/ioutil"
	"net/http"
	"os"
	"os/user"
	"strings"
)

type Buckets struct {
	Buckets []string `json:"buckets"`
}

type Keys struct {
	Keys []string `json:"keys"`
}

type Command int

const (
	buckets = iota
	keys
	obj
	put
)

type Config struct {
	Url     string `json:"url"`
	Command Command
	Verbose bool `json:"verbose"`
	Bucket  string
	Key     string
	Show    bool `json:"show"`
}

type Args map[string]interface{}

func main() {
	args := parse_options()
	config := init_config(args)
	switch config.Command {
	case buckets:
		show_buckets(config)
	case obj:
		show_obj(config, config.Bucket, config.Key)
	case keys:
		if config.Show {
			show_objs(config)
		} else {
			show_keys(config)
		}
	case put:
		obj := read_stdin()
		put_obj(config, config.Bucket, config.Key, obj)
	}
}

func parse_options() Args {
	usage := `clerc - Command LinE Riak Client

Usage:
  clerc BUCKET KEY [--url=URL] [--put|--delete] [--verbose]
  clerc BUCKET [KEY] [--url=URL] [--verbose] [--show]
  clerc -h | --help
  clerc --version

Options:
  --url=URL  Set the URL of the riak web API. [default: http://127.0.0.1:8098]
  --verbose  Show additional information, useful for debugging.
  --show     List objects instead of keys when listing a bucket.
  -h --help  Show this screen.
  --version  Show version.
`
	args, err := docopt.Parse(usage, nil, true, "clerc (Command LinE Riak Client) 0.1", false)
	perror(err)
	return args
}

func init_config(args Args) Config {
	config := read_config_file()
	if args["--verbose"] == true {
		config.Verbose = true
	}
	if args["--show"] == true {
		config.Show = true
	}
	if args["--url"] != nil {
		config.Url = args["--url"].(string)
	}
	if args["BUCKET"] == "/" {
		config.Command = buckets
	} else if args["BUCKET"] != nil {
		config.Command = keys
		config.Bucket = args["BUCKET"].(string)
	}
	if args["KEY"] != nil {
		config.Command = obj
		config.Key = args["KEY"].(string)
	}
	if args["--put"] == true {
		config.Command = put
	}
	return config
}

func read_config_file() Config {
	config := new_config()
	usr, err := user.Current()
	perror(err)
	bytes, err := ioutil.ReadFile(usr.HomeDir + "/.clerc")
	if err != nil {
		log(config, "unable to read file :(")
	} else {
		err = json.Unmarshal(bytes, &config)
		log(config, "config: "+string(bytes))
		perror(err)
	}
	return config
}

func new_config() Config {
	return Config{
		Url:     "http://127.0.0.1:8098",
		Verbose: false,
		Show:    false,
	}
}

func read_stdin() []byte {
	bytes, err := ioutil.ReadAll(os.Stdin)
	perror(err)
	return bytes
}

func show_keys(config Config) {
	keys := get_keys(config)
	log(config, "Listing keys:")
	for _, key := range keys.Keys {
		fmt.Println(key)
	}
}

func get_keys(config Config) Keys {
	var keys Keys
	make_request(&keys, config,
		"/buckets/"+config.Bucket+"/keys?keys=true")
	return keys
}

func show_objs(config Config) {
	keys := get_keys(config)
	for _, key := range keys.Keys {
		fmt.Println("Key: " + key)
		show_obj(config, config.Bucket, key)
		fmt.Println("")
	}
	return
}

func show_obj(config Config, bucket string, key string) {
	obj := get_obj(config, bucket, key)
	log(config, "Showing object: "+bucket+"/"+key)
	fmt.Println(obj)
}

func put_obj(config Config, bucket string, key string, obj []byte) {
	resource := "/riak/" + config.Bucket + "/" + config.Key
	log(config, "Making request: "+config.Url+resource)
	reader := strings.NewReader(string(obj))
	response, err := http.Post(config.Url+resource, "application/json", reader)
	perror(err)
	assert_status(response, 204)
	read_body(config, response)
}

func read_body(config Config, response *http.Response) []byte {
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	perror(err)
	log(config, "Got response: "+string(body))
	return body
}

func get_obj(config Config, bucket string, key string) string {
	resource := "/buckets/" + bucket + "/keys/" + key
	log(config, "Making request: "+config.Url+resource)
	response, err := http.Get(config.Url + resource)
	perror(err)
	assert_status(response, 200)
	body := read_body(config, response)
	return prettify(body)
}

func assert_status(response *http.Response, status int) {
	if response.StatusCode != status {
		perror(errors.New("Unexpected status: " + response.Status))
	}
}

func prettify(data []byte) string {
	var prettyJson bytes.Buffer
	err := json.Indent(&prettyJson, data, "", "    ")
	if err != nil {
		return string(data)
	} else {
		return string(prettyJson.Bytes())
	}
}

func show_buckets(config Config) {
	buckets := get_buckets(config)
	log(config, "Listing buckets:")
	for _, bucket := range buckets.Buckets {
		fmt.Println(bucket)
	}
}

func get_buckets(config Config) Buckets {
	var buckets Buckets
	make_request(&buckets, config, "/buckets?buckets=true")
	return buckets
}

func make_request(data interface{}, config Config, resource string) {
	log(config, "Making request: "+config.Url+resource)
	response, err := http.Get(config.Url + resource)
	perror(err)
	assert_status(response, 200)
	body := read_body(config, response)
	json.Unmarshal(body, &data)
}

func log(config Config, str string) {
	if config.Verbose {
		fmt.Println("*** " + str)
	}
}

func perror(err error) {
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package wallet

import (
	"io/ioutil"
	"os"
	"testing"

	dbm "github.com/tendermint/tmlibs/db"

	"chain/testutil"
	"github.com/bytom/account"
	"github.com/bytom/asset"
	"github.com/bytom/blockchain/pseudohsm"
	"github.com/bytom/blockchain/query"
	"github.com/bytom/consensus"
	"github.com/bytom/crypto/ed25519/chainkd"
	"github.com/bytom/protocol/bc/types"
)

func TestWalletUnconfirmedTxs(t *testing.T) {
	dirPath, err := ioutil.TempDir(".", "")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dirPath)

	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")

	accountManager := account.NewManager(testDB, nil)
	hsm, err := pseudohsm.New(dirPath)
	if err != nil {
		t.Fatal(err)
	}

	xpub1, err := hsm.XCreate("test_pub1", "password")
	if err != nil {
		t.Fatal(err)
	}

	testAccount, err := accountManager.Create(nil, []chainkd.XPub{xpub1.XPub}, 1, "testAccount")
	if err != nil {
		t.Fatal(err)
	}

	controlProg, err := accountManager.CreateAddress(nil, testAccount.ID, false)
	if err != nil {
		t.Fatal(err)
	}

	controlProg.KeyIndex = 1

	reg := asset.NewRegistry(testDB, nil)
	asset, err := reg.Define([]chainkd.XPub{xpub1.XPub}, 1, nil, "TESTASSET")
	if err != nil {
		t.Fatal(err)
	}

	w := mockWallet(testDB, accountManager, reg, nil)
	utxos := []*account.UTXO{}
	btmUtxo := mockUTXO(controlProg, consensus.BTMAssetID)
	utxos = append(utxos, btmUtxo)

	_, txData, err := mockTxData(utxos, testAccount)
	if err != nil {
		t.Fatal(err)
	}
	testTx1 := types.NewTx(*txData)
	w.SaveUnconfirmedTx(testTx1)

	OtherUtxo := mockUTXO(controlProg, &asset.AssetID)
	utxos = append(utxos, OtherUtxo)
	_, txData, err = mockTxData(utxos, testAccount)
	if err != nil {
		t.Fatal(err)
	}
	testTx2 := types.NewTx(*txData)
	w.SaveUnconfirmedTx(testTx2)

	txs := AnnotatedTxs([]*types.Tx{testTx1}, w)
	wantTx := txs[0]
	gotTx, err := w.GetUnconfirmedTxByTxID(testTx1.ID.String())
	if !testutil.DeepEqual(gotTx.ID, wantTx.ID) {
		t.Errorf(`transaction got=%#v; want=%#v`, gotTx.ID, wantTx.ID)
	}

	wantTxs := AnnotatedTxs([]*types.Tx{testTx1, testTx2}, w)
	gotTxs, err := w.GetUnconfirmedTxs("")
	for i, want := range wantTxs {
		if !testutil.DeepEqual(gotTxs[i].ID, want.ID) {
			t.Errorf(`the NO %i transaction, tx got=%#v; want=%#v`, i, gotTxs[i].ID.String(), want.ID.String())
		}

		for j, input := range want.Inputs {
			if !testutil.DeepEqual(gotTxs[i].Inputs[j].AccountID, input.AccountID) {
				t.Errorf(`the NO %i transaction input, accountID got=%#v; want=%#v`, j, gotTxs[i].Inputs[j].AccountID, input.AccountID)
			}

			if !testutil.DeepEqual(gotTxs[i].Inputs[j].AssetID, input.AssetID) {
				t.Errorf(`the NO %i transaction input, assetID got=%#v; want=%#v`, j, gotTxs[i].Inputs[j].AssetID, input.AssetID)
			}
		}

		for k, output := range want.Outputs {
			if !testutil.DeepEqual(gotTxs[i].Outputs[k].AccountID, output.AccountID) {
				t.Errorf(`the NO %i transaction input, accountID got=%#v; want=%#v`, k, gotTxs[i].Inputs[k].AccountID, output.AccountID)
			}

			if !testutil.DeepEqual(gotTxs[i].Outputs[k].AssetID, output.AssetID) {
				t.Errorf(`the NO %i transaction input, assetID got=%#v; want=%#v`, k, gotTxs[i].Inputs[k].AssetID, output.AssetID)
			}
		}
	}
}

func AnnotatedTxs(txs []*types.Tx, w *Wallet) []*query.AnnotatedTx {
	// annotate account and asset
	annotatedTxs := []*query.AnnotatedTx{}
	for _, tx := range txs {
		annotatedTx := &query.AnnotatedTx{
			ID:      tx.ID,
			Inputs:  make([]*query.AnnotatedInput, 0, len(tx.Inputs)),
			Outputs: make([]*query.AnnotatedOutput, 0, len(tx.Outputs)),
			Size:    tx.SerializedSize,
		}

		for i := range tx.Inputs {
			annotatedTx.Inputs = append(annotatedTx.Inputs, w.BuildAnnotatedInput(tx, uint32(i)))
		}
		for i := range tx.Outputs {
			annotatedTx.Outputs = append(annotatedTx.Outputs, w.BuildAnnotatedOutput(tx, i))
		}
		annotatedTxs = append(annotatedTxs, annotatedTx)
	}

	annotateTxsAccount(annotatedTxs, w.DB)
	annotateTxsAsset(w, annotatedTxs)

	return annotatedTxs
}
<commit_msg>optimise test<commit_after>package wallet

import (
	"io/ioutil"
	"os"
	"testing"

	dbm "github.com/tendermint/tmlibs/db"

	"github.com/bytom/testutil"
	"github.com/bytom/account"
	"github.com/bytom/asset"
	"github.com/bytom/blockchain/pseudohsm"
	"github.com/bytom/blockchain/query"
	"github.com/bytom/consensus"
	"github.com/bytom/crypto/ed25519/chainkd"
	"github.com/bytom/protocol/bc/types"
)

func TestWalletUnconfirmedTxs(t *testing.T) {
	dirPath, err := ioutil.TempDir(".", "")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dirPath)

	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")

	accountManager := account.NewManager(testDB, nil)
	hsm, err := pseudohsm.New(dirPath)
	if err != nil {
		t.Fatal(err)
	}

	xpub1, err := hsm.XCreate("test_pub1", "password")
	if err != nil {
		t.Fatal(err)
	}

	testAccount, err := accountManager.Create(nil, []chainkd.XPub{xpub1.XPub}, 1, "testAccount")
	if err != nil {
		t.Fatal(err)
	}

	controlProg, err := accountManager.CreateAddress(nil, testAccount.ID, false)
	if err != nil {
		t.Fatal(err)
	}

	controlProg.KeyIndex = 1

	reg := asset.NewRegistry(testDB, nil)
	asset, err := reg.Define([]chainkd.XPub{xpub1.XPub}, 1, nil, "TESTASSET")
	if err != nil {
		t.Fatal(err)
	}

	w := mockWallet(testDB, accountManager, reg, nil)
	utxos := []*account.UTXO{}
	btmUtxo := mockUTXO(controlProg, consensus.BTMAssetID)
	utxos = append(utxos, btmUtxo)

	_, txData, err := mockTxData(utxos, testAccount)
	if err != nil {
		t.Fatal(err)
	}
	testTx1 := types.NewTx(*txData)
	w.SaveUnconfirmedTx(testTx1)

	OtherUtxo := mockUTXO(controlProg, &asset.AssetID)
	utxos = append(utxos, OtherUtxo)
	_, txData, err = mockTxData(utxos, testAccount)
	if err != nil {
		t.Fatal(err)
	}
	testTx2 := types.NewTx(*txData)
	w.SaveUnconfirmedTx(testTx2)

	txs := AnnotatedTxs([]*types.Tx{testTx1}, w)
	wantTx := txs[0]
	gotTx, err := w.GetUnconfirmedTxByTxID(testTx1.ID.String())
	if !testutil.DeepEqual(gotTx.ID, wantTx.ID) {
		t.Errorf(`transaction got=%#v; want=%#v`, gotTx.ID, wantTx.ID)
	}

	wantTxs := AnnotatedTxs([]*types.Tx{testTx1, testTx2}, w)
	gotTxs, err := w.GetUnconfirmedTxs("")
	for i, want := range wantTxs {
		if !testutil.DeepEqual(gotTxs[i].ID, want.ID) {
			t.Errorf(`the NO %i transaction, tx got=%#v; want=%#v`, i, gotTxs[i].ID.String(), want.ID.String())
		}

		for j, input := range want.Inputs {
			if !testutil.DeepEqual(gotTxs[i].Inputs[j].AccountID, input.AccountID) {
				t.Errorf(`the NO %i transaction input, accountID got=%#v; want=%#v`, j, gotTxs[i].Inputs[j].AccountID, input.AccountID)
			}

			if !testutil.DeepEqual(gotTxs[i].Inputs[j].AssetID, input.AssetID) {
				t.Errorf(`the NO %i transaction input, assetID got=%#v; want=%#v`, j, gotTxs[i].Inputs[j].AssetID, input.AssetID)
			}
		}

		for k, output := range want.Outputs {
			if !testutil.DeepEqual(gotTxs[i].Outputs[k].AccountID, output.AccountID) {
				t.Errorf(`the NO %i transaction input, accountID got=%#v; want=%#v`, k, gotTxs[i].Inputs[k].AccountID, output.AccountID)
			}

			if !testutil.DeepEqual(gotTxs[i].Outputs[k].AssetID, output.AssetID) {
				t.Errorf(`the NO %i transaction input, assetID got=%#v; want=%#v`, k, gotTxs[i].Inputs[k].AssetID, output.AssetID)
			}
		}
	}
}

func AnnotatedTxs(txs []*types.Tx, w *Wallet) []*query.AnnotatedTx {
	// annotate account and asset
	annotatedTxs := []*query.AnnotatedTx{}
	for _, tx := range txs {
		annotatedTx := &query.AnnotatedTx{
			ID:      tx.ID,
			Inputs:  make([]*query.AnnotatedInput, 0, len(tx.Inputs)),
			Outputs: make([]*query.AnnotatedOutput, 0, len(tx.Outputs)),
			Size:    tx.SerializedSize,
		}

		for i := range tx.Inputs {
			annotatedTx.Inputs = append(annotatedTx.Inputs, w.BuildAnnotatedInput(tx, uint32(i)))
		}
		for i := range tx.Outputs {
			annotatedTx.Outputs = append(annotatedTx.Outputs, w.BuildAnnotatedOutput(tx, i))
		}
		annotatedTxs = append(annotatedTxs, annotatedTx)
	}

	annotateTxsAccount(annotatedTxs, w.DB)
	annotateTxsAsset(w, annotatedTxs)

	return annotatedTxs
}
<|endoftext|>


<commit_before>package cmd

import (
	"os"
	"os/exec"
	"path"
	"testing"
	"time"

	"github.com/pkg/errors"
	"github.com/stretchr/testify/require"
	lab "github.com/zaquestion/lab/internal/gitlab"
)

func cleanupFork(t *testing.T, project string) {
	// Failing to find the project will fail the test and is a legit
	// failure case since its the only thing asserting the project exists
	// (was forked)
	p, err := lab.FindProject(project)
	if err != nil {
		t.Fatal(errors.Wrap(err, "failed to find project "+project+" for cleanup"))
	}
	err = lab.ProjectDelete(p.ID)
	if err != nil {
		t.Fatal(errors.Wrap(err, "failed to delete project "+project+" during cleanup"))
	}
}

func Test_fork(t *testing.T) {
	tests := []struct {
		desc      string
		args      []string
		name      string
		path      string
		namespace string
	}{
		{
			desc:      "do_fork",
			args:      []string{},
			name:      "fork_test",
			path:      "",
			namespace: "",
		},
		{
			desc:      "do_fork_name",
			args:      []string{"-n", "fork_test_name"},
			name:      "fork_test_name",
			path:      "",
			namespace: "",
		},
		{
			desc:      "do_fork_path",
			args:      []string{"-p", "fork_test_path"},
			name:      "fork_test",
			path:      "fork_test_path",
			namespace: "",
		},
		{
			desc:      "do_fork_name_path",
			args:      []string{"-n", "fork_test_name_1", "-p", "fork_test_path_1"},
			name:      "fork_test_name_1",
			path:      "fork_test_path_1",
			namespace: "",
		},
		{
			desc:      "do_fork_namespace",
			args:      []string{"-g", "lab-testing-test-group"},
			name:      "fork_test",
			path:      "",
			namespace: "lab-testing-test-group",
		},
		{
			desc:      "do_fork_namespace_name",
			args:      []string{"-g", "lab-testing-test-group", "-n", "fork_test_name"},
			name:      "fork_test_name",
			path:      "",
			namespace: "lab-testing-test-group",
		},
		{
			desc:      "do_fork_namespace_path",
			args:      []string{"-g", "lab-testing-test-group", "-p", "fork_test_path"},
			name:      "fork_test",
			path:      "fork_test_path",
			namespace: "lab-testing-test-group",
		},
		{
			desc:      "do_fork_namespace_name_path",
			args:      []string{"-g", "lab-testing-test-group", "-n", "fork_test_name_1", "-p", "fork_test_path_1"},
			name:      "fork_test_name_1",
			path:      "fork_test_path_1",
			namespace: "lab-testing-test-group",
		},
	}

	t.Parallel()

	for _, test := range tests {
		test := test
		t.Run(test.desc, func(t *testing.T) {
			// remove the .git/config so no remotes exist
			repo := copyTestRepo(t)
			os.Remove(path.Join(repo, ".git/config"))

			cmd := exec.Command("git", "remote", "add", "origin", "git@gitlab.com:zaquestion/fork_test")
			cmd.Dir = repo
			err := cmd.Run()
			if err != nil {
				t.Fatal(err)
			}

			args := []string{"fork"}
			if len(test.args) > 0 {
				args = append(args, test.args...)
			}
			cmd = exec.Command(labBinaryPath, args...)
			cmd.Dir = repo
			b, err := cmd.CombinedOutput()
			out := string(b)
			if err != nil {
				t.Log(out)
				t.Fatal(err)
			}

			namespace := "lab-testing"
			if test.namespace != "" {
				namespace = test.namespace
			}
			name := test.name
			if test.path != "" {
				name = test.path
			}
			project := namespace + "/" + name

			require.Contains(t, out, "From gitlab.com:"+project)
			require.Contains(t, out, "new remote: "+namespace)

			cmd = exec.Command("git", "remote", "-v")
			cmd.Dir = repo

			b, err = cmd.CombinedOutput()
			if err != nil {
				t.Fatal(err)
			}
			require.Contains(t, string(b), namespace)
			time.Sleep(2 * time.Second)
			cleanupFork(t, project)
		})
	}
}

func Test_forkWait(t *testing.T) {
	repo := copyTestRepo(t)
	os.Remove(path.Join(repo, ".git/config"))

	cmd := exec.Command("git", "remote", "add", "origin", "git@gitlab.com:zaquestion/fork_test")
	cmd.Dir = repo
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

	// The default behavior is to "wait" for the fork and it's already being
	// tested in the Test_fork() test. Here we only test the --no-wait
	// option, which we can't effectively test because we don't have a big
	// enough repo.
	t.Run("fork_nowait", func(t *testing.T) {
		cmd = exec.Command(labBinaryPath, []string{"fork", "--no-wait"}...)
		cmd.Dir = repo
		b, err := cmd.CombinedOutput()
		out := string(b)
		if err != nil {
			t.Log(out)
			t.Fatal(err)
		}
		require.Contains(t, out, "From gitlab.com:lab-testing/fork_test")
		require.Contains(t, out, "new remote: lab-testing")
		cleanupFork(t, "fork_test")
	})
}

func Test_determineForkRemote(t *testing.T) {
	tests := []struct {
		desc     string
		custom   string
		project  string
		expected string
	}{
		{"project is forked from repo", "", "zaquestion", "lab-testing"},
		{"project is user", "", "lab-testing", "upstream"},
		{"project is user", "custom-test", "lab-testing", "custom-test"},
	}

	for _, test := range tests {
		test := test
		remoteName = test.custom
		t.Run(test.desc, func(t *testing.T) {
			require.Equal(t, test.expected, determineForkRemote(test.project))
		})
	}
}
<commit_msg>fork test: Delete fork project on error<commit_after>package cmd

import (
	"os"
	"os/exec"
	"path"
	"testing"
	"time"

	"github.com/pkg/errors"
	"github.com/stretchr/testify/require"
	lab "github.com/zaquestion/lab/internal/gitlab"
)

func cleanupFork(t *testing.T, project string) {
	// Failing to find the project will fail the test and is a legit
	// failure case since its the only thing asserting the project exists
	// (was forked)
	p, err := lab.FindProject(project)
	if err != nil {
		t.Fatal(errors.Wrap(err, "failed to find project "+project+" for cleanup"))
	}
	err = lab.ProjectDelete(p.ID)
	if err != nil {
		t.Fatal(errors.Wrap(err, "failed to delete project "+project+" during cleanup"))
	}
}

func Test_fork(t *testing.T) {
	tests := []struct {
		desc      string
		args      []string
		name      string
		path      string
		namespace string
	}{
		{
			desc:      "do_fork",
			args:      []string{},
			name:      "fork_test",
			path:      "",
			namespace: "",
		},
		{
			desc:      "do_fork_name",
			args:      []string{"-n", "fork_test_name"},
			name:      "fork_test_name",
			path:      "",
			namespace: "",
		},
		{
			desc:      "do_fork_path",
			args:      []string{"-p", "fork_test_path"},
			name:      "fork_test",
			path:      "fork_test_path",
			namespace: "",
		},
		{
			desc:      "do_fork_name_path",
			args:      []string{"-n", "fork_test_name_1", "-p", "fork_test_path_1"},
			name:      "fork_test_name_1",
			path:      "fork_test_path_1",
			namespace: "",
		},
		{
			desc:      "do_fork_namespace",
			args:      []string{"-g", "lab-testing-test-group"},
			name:      "fork_test",
			path:      "",
			namespace: "lab-testing-test-group",
		},
		{
			desc:      "do_fork_namespace_name",
			args:      []string{"-g", "lab-testing-test-group", "-n", "fork_test_name"},
			name:      "fork_test_name",
			path:      "",
			namespace: "lab-testing-test-group",
		},
		{
			desc:      "do_fork_namespace_path",
			args:      []string{"-g", "lab-testing-test-group", "-p", "fork_test_path"},
			name:      "fork_test",
			path:      "fork_test_path",
			namespace: "lab-testing-test-group",
		},
		{
			desc:      "do_fork_namespace_name_path",
			args:      []string{"-g", "lab-testing-test-group", "-n", "fork_test_name_1", "-p", "fork_test_path_1"},
			name:      "fork_test_name_1",
			path:      "fork_test_path_1",
			namespace: "lab-testing-test-group",
		},
	}

	t.Parallel()

	for _, test := range tests {
		test := test
		t.Run(test.desc, func(t *testing.T) {
			// remove the .git/config so no remotes exist
			repo := copyTestRepo(t)
			os.Remove(path.Join(repo, ".git/config"))

			cmd := exec.Command("git", "remote", "add", "origin", "git@gitlab.com:zaquestion/fork_test")
			cmd.Dir = repo
			err := cmd.Run()
			if err != nil {
				t.Fatal(err)
			}

			namespace := "lab-testing"
			if test.namespace != "" {
				namespace = test.namespace
			}
			name := test.name
			if test.path != "" {
				name = test.path
			}
			project := namespace + "/" + name

			args := []string{"fork"}
			if len(test.args) > 0 {
				args = append(args, test.args...)
			}
			cmd = exec.Command(labBinaryPath, args...)
			cmd.Dir = repo
			b, err := cmd.CombinedOutput()
			out := string(b)
			if err != nil {
				t.Log(out)
				cleanupFork(t, project)
				t.Fatal(err)
			}

			require.Contains(t, out, "From gitlab.com:"+project)
			require.Contains(t, out, "new remote: "+namespace)

			cmd = exec.Command("git", "remote", "-v")
			cmd.Dir = repo

			b, err = cmd.CombinedOutput()
			if err != nil {
				t.Fatal(err)
			}
			require.Contains(t, string(b), namespace)
			time.Sleep(2 * time.Second)
			cleanupFork(t, project)
		})
	}
}

func Test_forkWait(t *testing.T) {
	repo := copyTestRepo(t)
	os.Remove(path.Join(repo, ".git/config"))

	cmd := exec.Command("git", "remote", "add", "origin", "git@gitlab.com:zaquestion/fork_test")
	cmd.Dir = repo
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

	// The default behavior is to "wait" for the fork and it's already being
	// tested in the Test_fork() test. Here we only test the --no-wait
	// option, which we can't effectively test because we don't have a big
	// enough repo.
	t.Run("fork_nowait", func(t *testing.T) {
		cmd = exec.Command(labBinaryPath, []string{"fork", "--no-wait"}...)
		cmd.Dir = repo
		b, err := cmd.CombinedOutput()
		out := string(b)
		if err != nil {
			t.Log(out)
			t.Fatal(err)
		}
		require.Contains(t, out, "From gitlab.com:lab-testing/fork_test")
		require.Contains(t, out, "new remote: lab-testing")
		cleanupFork(t, "fork_test")
	})
}

func Test_determineForkRemote(t *testing.T) {
	tests := []struct {
		desc     string
		custom   string
		project  string
		expected string
	}{
		{"project is forked from repo", "", "zaquestion", "lab-testing"},
		{"project is user", "", "lab-testing", "upstream"},
		{"project is user", "custom-test", "lab-testing", "custom-test"},
	}

	for _, test := range tests {
		test := test
		remoteName = test.custom
		t.Run(test.desc, func(t *testing.T) {
			require.Equal(t, test.expected, determineForkRemote(test.project))
		})
	}
}
<|endoftext|>


<commit_before>// Package main provides cli for gene package
package main

import (
	"log"

	"github.com/cihangir/gene/generators/clients"
	"github.com/cihangir/gene/generators/common"
	gerr "github.com/cihangir/gene/generators/errors"
	"github.com/cihangir/gene/generators/functions"
	"github.com/cihangir/gene/generators/mainfile"
	"github.com/cihangir/gene/generators/models"
	"github.com/cihangir/gene/generators/sql/statements"
	"github.com/cihangir/geneddl"
	"github.com/cihangir/generows"
	"github.com/koding/multiconfig"

	_ "github.com/cihangir/govalidator"
	_ "github.com/cihangir/stringext"
	_ "github.com/koding/logging"
	_ "github.com/lann/squirrel"
	_ "golang.org/x/net/context"
)

type Config struct {
	// Schema holds the given schema file
	Schema string `required:"true"`

	// Target holds the target folder
	Target string `required:"true" default:"./"`

	DDL    geneddl.Generator
	Models models.Generator

	Rows       generows.Generator
	Statements statements.Generator
	Errors     gerr.Generator
	Mainfile   mainfile.Generator
	Clients    clients.Generator
	Functions  functions.Generator
}

func main() {
	conf := &Config{}

	loader := multiconfig.MultiLoader(
		&multiconfig.TagLoader{},  // assign default values
		&multiconfig.FlagLoader{}, // read flag params
	)

	if err := loader.Load(conf); err != nil {
		log.Fatalf("config read err:", err.Error())
	}

	if err := (&multiconfig.RequiredValidator{}).Validate(conf); err != nil {
		log.Fatalf("validation err: %s", err.Error())
	}

	c := common.NewContext()
	c.Config.Schema = conf.Schema
	c.Config.Target = conf.Target
	c.FieldNameFunc = geneddl.GetFieldNameFunc(conf.DDL.FieldNameCase)

	s, err := common.Read(c.Config.Schema)
	if err != nil {
		log.Fatalf("schema read err: %s", err.Error())
	}

	s.Resolve(s)

	//
	// generate sql definitions
	//
	c.Config.Target = conf.Target + "db" + "/"
	output, err := conf.DDL.Generate(c, s)
	if err != nil {
		log.Fatal("geneddl err: %s", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	//
	// generate models
	//
	c.Config.Target = conf.Target + "models" + "/"
	output, err = conf.Models.Generate(c, s)
	if err != nil {
		log.Fatalf("err while generating models", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	//
	// generate rowsscanner
	//
	c.Config.Target = conf.Target + "models" + "/"
	output, err = conf.Rows.Generate(c, s)
	if err != nil {
		log.Fatalf("err while generating rows", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	//
	// generate crud statements
	//
	c.Config.Target = conf.Target + "models" + "/"
	output, err = conf.Statements.Generate(c, s)
	if err != nil {
		log.Fatalf("err while generating crud statements", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	//
	// generate errors
	//
	c.Config.Target = conf.Target + "errors" + "/"
	output, err = conf.Errors.Generate(c, s)
	if err != nil {
		log.Fatalf("err while generating errors", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	//
	// generate main file
	//
	c.Config.Target = conf.Target + "cmd" + "/"
	output, err = conf.Mainfile.Generate(c, s)
	if err != nil {
		log.Fatalf("err while generating main file", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	//
	// generate clients
	//
	c.Config.Target = conf.Target + "workers" + "/"
	output, err = conf.Clients.Generate(c, s)
	if err != nil {
		log.Fatalf("err while generating clients", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	//
	// generate exported functions
	//
	c.Config.Target = conf.Target + "workers" + "/"
	output, err = conf.Functions.Generate(c, s)
	if err != nil {
		log.Fatalf("err while generating clients", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	log.Println("module created with success")
}
<commit_msg>Gene/Kit: added kit generation into cmd<commit_after>// Package main provides cli for gene package
package main

import (
	"log"

	"github.com/cihangir/gene/generators/clients"
	"github.com/cihangir/gene/generators/common"
	gerr "github.com/cihangir/gene/generators/errors"
	"github.com/cihangir/gene/generators/functions"
	"github.com/cihangir/gene/generators/kit"
	"github.com/cihangir/gene/generators/mainfile"
	"github.com/cihangir/gene/generators/models"
	"github.com/cihangir/gene/generators/sql/statements"
	"github.com/cihangir/geneddl"
	"github.com/cihangir/generows"
	"github.com/koding/multiconfig"

	_ "github.com/cihangir/govalidator"
	_ "github.com/cihangir/stringext"
	_ "github.com/koding/logging"
	_ "github.com/lann/squirrel"
	_ "golang.org/x/net/context"
)

type Config struct {
	// Schema holds the given schema file
	Schema string `required:"true"`

	// Target holds the target folder
	Target string `required:"true" default:"./"`

	DDL    geneddl.Generator
	Models models.Generator

	Rows       generows.Generator
	Statements statements.Generator
	Errors     gerr.Generator
	Mainfile   mainfile.Generator
	Clients    clients.Generator
	Functions  functions.Generator
	Kit        kit.Generator
}

func main() {
	conf := &Config{}

	loader := multiconfig.MultiLoader(
		&multiconfig.TagLoader{},  // assign default values
		&multiconfig.FlagLoader{}, // read flag params
	)

	if err := loader.Load(conf); err != nil {
		log.Fatalf("config read err:", err.Error())
	}

	if err := (&multiconfig.RequiredValidator{}).Validate(conf); err != nil {
		log.Fatalf("validation err: %s", err.Error())
	}

	c := common.NewContext()
	c.Config.Schema = conf.Schema
	c.Config.Target = conf.Target
	c.FieldNameFunc = geneddl.GetFieldNameFunc(conf.DDL.FieldNameCase)

	s, err := common.Read(c.Config.Schema)
	if err != nil {
		log.Fatalf("schema read err: %s", err.Error())
	}

	s.Resolve(s)

	//
	// generate sql definitions
	//
	c.Config.Target = conf.Target + "db" + "/"
	output, err := conf.DDL.Generate(c, s)
	if err != nil {
		log.Fatal("geneddl err: %s", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	//
	// generate models
	//
	c.Config.Target = conf.Target + "models" + "/"
	output, err = conf.Models.Generate(c, s)
	if err != nil {
		log.Fatalf("err while generating models", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	//
	// generate rowsscanner
	//
	c.Config.Target = conf.Target + "models" + "/"
	output, err = conf.Rows.Generate(c, s)
	if err != nil {
		log.Fatalf("err while generating rows", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	//
	// generate crud statements
	//
	c.Config.Target = conf.Target + "models" + "/"
	output, err = conf.Statements.Generate(c, s)
	if err != nil {
		log.Fatalf("err while generating crud statements", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	//
	// generate errors
	//
	c.Config.Target = conf.Target + "errors" + "/"
	output, err = conf.Errors.Generate(c, s)
	if err != nil {
		log.Fatalf("err while generating errors", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	//
	// generate main file
	//
	c.Config.Target = conf.Target + "cmd" + "/"
	output, err = conf.Mainfile.Generate(c, s)
	if err != nil {
		log.Fatalf("err while generating main file", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	//
	// generate clients
	//
	c.Config.Target = conf.Target + "workers" + "/"
	output, err = conf.Clients.Generate(c, s)
	if err != nil {
		log.Fatalf("err while generating clients", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	//
	// generate exported functions
	//
	c.Config.Target = conf.Target + "workers" + "/"
	output, err = conf.Functions.Generate(c, s)
	if err != nil {
		log.Fatalf("err while generating clients", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("output write err: %s", err.Error())
	}

	//
	// generate kit server handlers
	//
	c.Config.Target = conf.Target + "kit" + "/"
	output, err = conf.Kit.Generate(c, s)
	if err != nil {
		log.Fatalf("err while generating kit server", err.Error())
	}

	if err := common.WriteOutput(output); err != nil {
		log.Fatal("kit output write err: %s", err.Error())
	}

	log.Println("module created with success")
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"html/template"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"gopkg.in/yaml.v2"
)

type config struct {
	Project struct {
		Name        string `yaml:"name"`
		Description string `yaml:"description"`
	} `yaml:"project"`
	Repo struct {
		Type string `yaml:"type"`
		Link string `yaml:"link"`
	} `yaml:"repo"`
	Copyright struct {
		Owner string `yaml:"owner"`
		Year  string `yaml:"year"`
	} `yaml:"copyright"`
	Maintainers []struct {
		Name string `yaml:"name"`
		Nick string `yaml:"nick,omitempty"`
	} `yaml:"maintainers,omitempty"`
	Emails struct {
		CommercialSupport string `yaml:"commercialSupport,omitempty"`
		Security          string `yaml:"security"`
		Coc               string `yaml:"coc"`
	} `yaml:"emails"`
	SupportLinks struct {
		Documentation   string `yaml:"documentation,omitempty"`
		Examples        string `yaml:"examples,omitempty"`
		Troubleshooting string `yaml:"troubleshooting,omitempty"`
	} `yaml:"supportLinks,omitempty"`
	SupportPlatforms []struct {
		Service string `yaml:"service"`
		Link    string `yaml:"link"`
	} `yaml:"supportPlatforms,omitempty"`
	IssueTemplate struct {
		Questions []struct {
			Question string `yaml:"question"`
		} `yaml:"questions"`
	} `yaml:"issueTemplate"`
	ContributionLinks struct {
		IssueTemplate string `yaml:"issueTemplate,omitempty"`
		StarterIssues string `yaml:"starterIssues,omitempty"`
	} `yaml:"contributionLinks"`
}

func parseConfig(path string) config {
	var conf config

	filename, _ := filepath.Abs(path)
	file, err := ioutil.ReadFile(filename)
	if err != nil {
		panic(err)
	}
	err = yaml.Unmarshal(file, &conf)
	if err != nil {
		panic(err)
	}
	return conf
}

func generateFile(config config, path string, newPath string) {
	temp, err := template.ParseFiles(path)
	if err != nil {
		log.Println("Unable to parse file: ", err)
		return
	}

	if _, err := os.Stat(newPath); os.IsNotExist(err) {
	    	os.MkdirAll(filepath.Dir(newPath), os.ModePerm)
	}

	file, err := os.Create(newPath)
	defer file.Close()
	if err != nil {
		log.Println("Unable to create file: ", err)
		return
	}

	err = temp.Execute(file, config)
	if err != nil {
		log.Print("Unable to parse template: ", err)
		return
	}
}
func main() {
	var tempDir string
	var conf string
	flag.StringVar(&tempDir, "input", "templates", "Template directory")
	flag.StringVar(&conf, "conf", ".seed-config.yaml", "Config file")
	flag.Parse()

        config := parseConfig(conf)
	tempDir, _ = filepath.Abs(tempDir)

	bl := make(map[string]bool)
	bl["seed-config.example.yaml"] = true

	filepath.Walk(tempDir, func(path string, info os.FileInfo, err error) error {
		if bl[info.Name()] {
			return filepath.SkipDir
		}
		if !info.IsDir() {
			newPath, _ := filepath.Rel(tempDir, path)
			generateFile(config, path, newPath)
		}
		return nil
	})

}
<commit_msg>Extensive linter fixes<commit_after>package main

import (
	"flag"
	"html/template"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"gopkg.in/yaml.v2"
)

type config struct {
	Project struct {
		Name        string `yaml:"name"`
		Description string `yaml:"description"`
	} `yaml:"project"`
	Repo struct {
		Type string `yaml:"type"`
		Link string `yaml:"link"`
	} `yaml:"repo"`
	Copyright struct {
		Owner string `yaml:"owner"`
		Year  string `yaml:"year"`
	} `yaml:"copyright"`
	Maintainers []struct {
		Name string `yaml:"name"`
		Nick string `yaml:"nick,omitempty"`
	} `yaml:"maintainers,omitempty"`
	Emails struct {
		CommercialSupport string `yaml:"commercialSupport,omitempty"`
		Security          string `yaml:"security"`
		Coc               string `yaml:"coc"`
	} `yaml:"emails"`
	SupportLinks struct {
		Documentation   string `yaml:"documentation,omitempty"`
		Examples        string `yaml:"examples,omitempty"`
		Troubleshooting string `yaml:"troubleshooting,omitempty"`
	} `yaml:"supportLinks,omitempty"`
	SupportPlatforms []struct {
		Service string `yaml:"service"`
		Link    string `yaml:"link"`
	} `yaml:"supportPlatforms,omitempty"`
	IssueTemplate struct {
		Questions []struct {
			Question string `yaml:"question"`
		} `yaml:"questions"`
	} `yaml:"issueTemplate"`
	ContributionLinks struct {
		IssueTemplate string `yaml:"issueTemplate,omitempty"`
		StarterIssues string `yaml:"starterIssues,omitempty"`
	} `yaml:"contributionLinks"`
}

func parseConfig(path string) config {
	var conf config

	filename, _ := filepath.Abs(path)
	file, err := ioutil.ReadFile(filename)
	if err != nil {
		panic(err)
	}
	err = yaml.Unmarshal(file, &conf)
	if err != nil {
		panic(err)
	}
	return conf
}

func generateFile(config config, path string, newPath string) {
	temp, err := template.ParseFiles(path)
	if err != nil {
		log.Println("Unable to parse file: ", err)
		return
	}

	if _, err := os.Stat(newPath); os.IsNotExist(err) {
		os.MkdirAll(filepath.Dir(newPath), os.ModePerm)
	}

	file, err := os.Create(newPath)
	defer file.Close()
	if err != nil {
		log.Println("Unable to create file: ", err)
		return
	}

	err = temp.Execute(file, config)
	if err != nil {
		log.Print("Unable to parse template: ", err)
		return
	}
}
func main() {
	var tempDir string
	var conf string
	flag.StringVar(&tempDir, "input", "templates", "Template directory")
	flag.StringVar(&conf, "conf", ".seed-config.yaml", "Config file")
	flag.Parse()

	config := parseConfig(conf)
	tempDir, _ = filepath.Abs(tempDir)

	bl := make(map[string]bool)
	bl["seed-config.example.yaml"] = true

	filepath.Walk(tempDir, func(path string, info os.FileInfo, err error) error {
		if bl[info.Name()] {
			return filepath.SkipDir
		}
		if !info.IsDir() {
			newPath, _ := filepath.Rel(tempDir, path)
			generateFile(config, path, newPath)
		}
		return nil
	})

}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"os/exec"
	"strconv"
	"strings"

	"github.com/PuerkitoBio/goquery"
)

const file = "./gvpf.html"

func main() {
	if err := search(); err != nil {
		panic(err)
	}

	cmd := exec.Command("open", file)

	if err := cmd.Start(); err != nil {
		panic(err)
	}

	if err := cmd.Wait(); err != nil {
		panic(err)
	}
}

func search() error {
	doc, err := goquery.NewDocument("https://www.gv.com/portfolio/")
	if err != nil {
		return err
	}

	f, err := os.Create(file)
	if err != nil {
		return err
	}

	defer f.Close()

	f.WriteString("
")

	doc.Find("div.portfolio-all div.investments ul.more-investments li").Each(func(i int, s *goquery.Selection) {
		name := strings.TrimSpace(strings.Split(s.Text(), "\n")[2])
		desc := strings.TrimSpace(strings.Split(s.Text(), "\n")[4])
		url, _ := s.Find("a").Attr("href")

		f.WriteString("
" + strconv.Itoa(i+1) + "	" + name + "	" + desc + "
")
	})

	f.WriteString("
")

	return nil
}
<commit_msg>Update cmd/gvpf/main.go<commit_after>package main

import (
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/PuerkitoBio/goquery"
)

var file = filepath.Join(os.TempDir(), "./gvpf.html")

func main() {
	if err := search(); err != nil {
		panic(err)
	}

	cmd := exec.Command("open", file)

	if err := cmd.Start(); err != nil {
		panic(err)
	}

	if err := cmd.Wait(); err != nil {
		panic(err)
	}
}

func search() error {
	doc, err := goquery.NewDocument("https://www.gv.com/portfolio/")
	if err != nil {
		return err
	}

	f, err := os.Create(file)
	if err != nil {
		return err
	}

	defer f.Close()

	f.WriteString("
")

	doc.Find("div.portfolio-all div.investments ul.more-investments li").Each(func(i int, s *goquery.Selection) {
		name := strings.TrimSpace(strings.Split(s.Text(), "\n")[2])
		desc := strings.TrimSpace(strings.Split(s.Text(), "\n")[4])
		url, _ := s.Find("a").Attr("href")

		f.WriteString("
" + strconv.Itoa(i+1) + "	" + name + "	" + desc + "
")
	})

	f.WriteString("
")

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright The Helm Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package main

import (
	"fmt"
	"io"
	"os"
	"strconv"

	"github.com/gosuri/uitable"
	"github.com/spf13/cobra"

	"helm.sh/helm/v3/cmd/helm/require"
	"helm.sh/helm/v3/pkg/action"
	"helm.sh/helm/v3/pkg/cli/output"
	"helm.sh/helm/v3/pkg/release"
)

var listHelp = `
This command lists all of the releases for a specified namespace (uses current namespace context if namespace not specified).

By default, it lists only releases that are deployed or failed. Flags like
'--uninstalled' and '--all' will alter this behavior. Such flags can be combined:
'--uninstalled --failed'.

By default, items are sorted alphabetically. Use the '-d' flag to sort by
release date.

If the --filter flag is provided, it will be treated as a filter. Filters are
regular expressions (Perl compatible) that are applied to the list of releases.
Only items that match the filter will be returned.

    $ helm list --filter 'ara[a-z]+'
    NAME                UPDATED                                  CHART
    maudlin-arachnid    2020-06-18 14:17:46.125134977 +0000 UTC  alpine-0.1.0

If no results are found, 'helm list' will exit 0, but with no output (or in
the case of no '-q' flag, only headers).

By default, up to 256 items may be returned. To limit this, use the '--max' flag.
Setting '--max' to 0 will not return all results. Rather, it will return the
server's default, which may be much higher than 256. Pairing the '--max'
flag with the '--offset' flag allows you to page through results.
`

func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
	client := action.NewList(cfg)
	var outfmt output.Format

	cmd := &cobra.Command{
		Use:               "list",
		Short:             "list releases",
		Long:              listHelp,
		Aliases:           []string{"ls"},
		Args:              require.NoArgs,
		ValidArgsFunction: noCompletions,
		RunE: func(cmd *cobra.Command, args []string) error {
			if client.AllNamespaces {
				if err := cfg.Init(settings.RESTClientGetter(), "", os.Getenv("HELM_DRIVER"), debug); err != nil {
					return err
				}
			}
			client.SetStateMask()

			results, err := client.Run()
			if err != nil {
				return err
			}

			if client.Short {

				names := make([]string, 0)
				for _, res := range results {
					names = append(names, res.Name)
				}

				outputFlag := cmd.Flag("output")

				switch outputFlag.Value.String() {
				case "json":
					output.EncodeJSON(out, names)
					return nil
				case "yaml":
					output.EncodeYAML(out, names)
					return nil
				case "table":
					for _, res := range results {
						fmt.Fprintln(out, res.Name)
					}
					return nil
				default:
					return outfmt.Write(out, newReleaseListWriter(results, client.TimeFormat))
				}
			}

			return outfmt.Write(out, newReleaseListWriter(results, client.TimeFormat))
		},
	}

	f := cmd.Flags()
	f.BoolVarP(&client.Short, "short", "q", false, "output short (quiet) listing format")
	f.StringVar(&client.TimeFormat, "time-format", "", "format time. Example: --time-format 2009-11-17 20:34:10 +0000 UTC")
	f.BoolVarP(&client.ByDate, "date", "d", false, "sort by release date")
	f.BoolVarP(&client.SortReverse, "reverse", "r", false, "reverse the sort order")
	f.BoolVarP(&client.All, "all", "a", false, "show all releases without any filter applied")
	f.BoolVar(&client.Uninstalled, "uninstalled", false, "show uninstalled releases (if 'helm uninstall --keep-history' was used)")
	f.BoolVar(&client.Superseded, "superseded", false, "show superseded releases")
	f.BoolVar(&client.Uninstalling, "uninstalling", false, "show releases that are currently being uninstalled")
	f.BoolVar(&client.Deployed, "deployed", false, "show deployed releases. If no other is specified, this will be automatically enabled")
	f.BoolVar(&client.Failed, "failed", false, "show failed releases")
	f.BoolVar(&client.Pending, "pending", false, "show pending releases")
	f.BoolVarP(&client.AllNamespaces, "all-namespaces", "A", false, "list releases across all namespaces")
	f.IntVarP(&client.Limit, "max", "m", 256, "maximum number of releases to fetch")
	f.IntVar(&client.Offset, "offset", 0, "next release index in the list, used to offset from start value")
	f.StringVarP(&client.Filter, "filter", "f", "", "a regular expression (Perl compatible). Any releases that match the expression will be included in the results")
	f.StringVarP(&client.Selector, "selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2). Works only for secret(default) and configmap storage backends.")
	bindOutputFlag(cmd, &outfmt)

	return cmd
}

type releaseElement struct {
	Name       string `json:"name"`
	Namespace  string `json:"namespace"`
	Revision   string `json:"revision"`
	Updated    string `json:"updated"`
	Status     string `json:"status"`
	Chart      string `json:"chart"`
	AppVersion string `json:"app_version"`
}

type releaseListWriter struct {
	releases []releaseElement
}

func newReleaseListWriter(releases []*release.Release, timeFormat string) *releaseListWriter {
	// Initialize the array so no results returns an empty array instead of null
	elements := make([]releaseElement, 0, len(releases))
	for _, r := range releases {
		element := releaseElement{
			Name:       r.Name,
			Namespace:  r.Namespace,
			Revision:   strconv.Itoa(r.Version),
			Status:     r.Info.Status.String(),
			Chart:      fmt.Sprintf("%s-%s", r.Chart.Metadata.Name, r.Chart.Metadata.Version),
			AppVersion: r.Chart.Metadata.AppVersion,
		}

		t := "-"
		if tspb := r.Info.LastDeployed; !tspb.IsZero() {
			if timeFormat != "" {
				t = tspb.Format(timeFormat)
			} else {
				t = tspb.String()
			}
		}
		element.Updated = t

		elements = append(elements, element)
	}
	return &releaseListWriter{elements}
}

func (r *releaseListWriter) WriteTable(out io.Writer) error {
	table := uitable.New()
	table.AddRow("NAME", "NAMESPACE", "REVISION", "UPDATED", "STATUS", "CHART", "APP VERSION")
	for _, r := range r.releases {
		table.AddRow(r.Name, r.Namespace, r.Revision, r.Updated, r.Status, r.Chart, r.AppVersion)
	}
	return output.EncodeTable(out, table)
}

func (r *releaseListWriter) WriteJSON(out io.Writer) error {
	return output.EncodeJSON(out, r.releases)
}

func (r *releaseListWriter) WriteYAML(out io.Writer) error {
	return output.EncodeYAML(out, r.releases)
}

// Provide dynamic auto-completion for release names
func compListReleases(toComplete string, cfg *action.Configuration) ([]string, cobra.ShellCompDirective) {
	cobra.CompDebugln(fmt.Sprintf("compListReleases with toComplete %s", toComplete), settings.Debug)

	client := action.NewList(cfg)
	client.All = true
	client.Limit = 0
	client.Filter = fmt.Sprintf("^%s", toComplete)

	client.SetStateMask()
	releases, err := client.Run()
	if err != nil {
		return nil, cobra.ShellCompDirectiveDefault
	}

	var choices []string
	for _, rel := range releases {
		choices = append(choices,
			fmt.Sprintf("%s\t%s-%s -> %s", rel.Name, rel.Chart.Metadata.Name, rel.Chart.Metadata.Version, rel.Info.Status.String()))
	}

	return choices, cobra.ShellCompDirectiveNoFileComp
}
<commit_msg>Fix the example for --time-format flag<commit_after>/*
Copyright The Helm Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package main

import (
	"fmt"
	"io"
	"os"
	"strconv"

	"github.com/gosuri/uitable"
	"github.com/spf13/cobra"

	"helm.sh/helm/v3/cmd/helm/require"
	"helm.sh/helm/v3/pkg/action"
	"helm.sh/helm/v3/pkg/cli/output"
	"helm.sh/helm/v3/pkg/release"
)

var listHelp = `
This command lists all of the releases for a specified namespace (uses current namespace context if namespace not specified).

By default, it lists only releases that are deployed or failed. Flags like
'--uninstalled' and '--all' will alter this behavior. Such flags can be combined:
'--uninstalled --failed'.

By default, items are sorted alphabetically. Use the '-d' flag to sort by
release date.

If the --filter flag is provided, it will be treated as a filter. Filters are
regular expressions (Perl compatible) that are applied to the list of releases.
Only items that match the filter will be returned.

    $ helm list --filter 'ara[a-z]+'
    NAME                UPDATED                                  CHART
    maudlin-arachnid    2020-06-18 14:17:46.125134977 +0000 UTC  alpine-0.1.0

If no results are found, 'helm list' will exit 0, but with no output (or in
the case of no '-q' flag, only headers).

By default, up to 256 items may be returned. To limit this, use the '--max' flag.
Setting '--max' to 0 will not return all results. Rather, it will return the
server's default, which may be much higher than 256. Pairing the '--max'
flag with the '--offset' flag allows you to page through results.
`

func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
	client := action.NewList(cfg)
	var outfmt output.Format

	cmd := &cobra.Command{
		Use:               "list",
		Short:             "list releases",
		Long:              listHelp,
		Aliases:           []string{"ls"},
		Args:              require.NoArgs,
		ValidArgsFunction: noCompletions,
		RunE: func(cmd *cobra.Command, args []string) error {
			if client.AllNamespaces {
				if err := cfg.Init(settings.RESTClientGetter(), "", os.Getenv("HELM_DRIVER"), debug); err != nil {
					return err
				}
			}
			client.SetStateMask()

			results, err := client.Run()
			if err != nil {
				return err
			}

			if client.Short {

				names := make([]string, 0)
				for _, res := range results {
					names = append(names, res.Name)
				}

				outputFlag := cmd.Flag("output")

				switch outputFlag.Value.String() {
				case "json":
					output.EncodeJSON(out, names)
					return nil
				case "yaml":
					output.EncodeYAML(out, names)
					return nil
				case "table":
					for _, res := range results {
						fmt.Fprintln(out, res.Name)
					}
					return nil
				default:
					return outfmt.Write(out, newReleaseListWriter(results, client.TimeFormat))
				}
			}

			return outfmt.Write(out, newReleaseListWriter(results, client.TimeFormat))
		},
	}

	f := cmd.Flags()
	f.BoolVarP(&client.Short, "short", "q", false, "output short (quiet) listing format")
	f.StringVar(&client.TimeFormat, "time-format", "", `format time using golang time formatter. Example: --time-format "2006-01-02 15:04:05Z0700"`)
	f.BoolVarP(&client.ByDate, "date", "d", false, "sort by release date")
	f.BoolVarP(&client.SortReverse, "reverse", "r", false, "reverse the sort order")
	f.BoolVarP(&client.All, "all", "a", false, "show all releases without any filter applied")
	f.BoolVar(&client.Uninstalled, "uninstalled", false, "show uninstalled releases (if 'helm uninstall --keep-history' was used)")
	f.BoolVar(&client.Superseded, "superseded", false, "show superseded releases")
	f.BoolVar(&client.Uninstalling, "uninstalling", false, "show releases that are currently being uninstalled")
	f.BoolVar(&client.Deployed, "deployed", false, "show deployed releases. If no other is specified, this will be automatically enabled")
	f.BoolVar(&client.Failed, "failed", false, "show failed releases")
	f.BoolVar(&client.Pending, "pending", false, "show pending releases")
	f.BoolVarP(&client.AllNamespaces, "all-namespaces", "A", false, "list releases across all namespaces")
	f.IntVarP(&client.Limit, "max", "m", 256, "maximum number of releases to fetch")
	f.IntVar(&client.Offset, "offset", 0, "next release index in the list, used to offset from start value")
	f.StringVarP(&client.Filter, "filter", "f", "", "a regular expression (Perl compatible). Any releases that match the expression will be included in the results")
	f.StringVarP(&client.Selector, "selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2). Works only for secret(default) and configmap storage backends.")
	bindOutputFlag(cmd, &outfmt)

	return cmd
}

type releaseElement struct {
	Name       string `json:"name"`
	Namespace  string `json:"namespace"`
	Revision   string `json:"revision"`
	Updated    string `json:"updated"`
	Status     string `json:"status"`
	Chart      string `json:"chart"`
	AppVersion string `json:"app_version"`
}

type releaseListWriter struct {
	releases []releaseElement
}

func newReleaseListWriter(releases []*release.Release, timeFormat string) *releaseListWriter {
	// Initialize the array so no results returns an empty array instead of null
	elements := make([]releaseElement, 0, len(releases))
	for _, r := range releases {
		element := releaseElement{
			Name:       r.Name,
			Namespace:  r.Namespace,
			Revision:   strconv.Itoa(r.Version),
			Status:     r.Info.Status.String(),
			Chart:      fmt.Sprintf("%s-%s", r.Chart.Metadata.Name, r.Chart.Metadata.Version),
			AppVersion: r.Chart.Metadata.AppVersion,
		}

		t := "-"
		if tspb := r.Info.LastDeployed; !tspb.IsZero() {
			if timeFormat != "" {
				t = tspb.Format(timeFormat)
			} else {
				t = tspb.String()
			}
		}
		element.Updated = t

		elements = append(elements, element)
	}
	return &releaseListWriter{elements}
}

func (r *releaseListWriter) WriteTable(out io.Writer) error {
	table := uitable.New()
	table.AddRow("NAME", "NAMESPACE", "REVISION", "UPDATED", "STATUS", "CHART", "APP VERSION")
	for _, r := range r.releases {
		table.AddRow(r.Name, r.Namespace, r.Revision, r.Updated, r.Status, r.Chart, r.AppVersion)
	}
	return output.EncodeTable(out, table)
}

func (r *releaseListWriter) WriteJSON(out io.Writer) error {
	return output.EncodeJSON(out, r.releases)
}

func (r *releaseListWriter) WriteYAML(out io.Writer) error {
	return output.EncodeYAML(out, r.releases)
}

// Provide dynamic auto-completion for release names
func compListReleases(toComplete string, cfg *action.Configuration) ([]string, cobra.ShellCompDirective) {
	cobra.CompDebugln(fmt.Sprintf("compListReleases with toComplete %s", toComplete), settings.Debug)

	client := action.NewList(cfg)
	client.All = true
	client.Limit = 0
	client.Filter = fmt.Sprintf("^%s", toComplete)

	client.SetStateMask()
	releases, err := client.Run()
	if err != nil {
		return nil, cobra.ShellCompDirectiveDefault
	}

	var choices []string
	for _, rel := range releases {
		choices = append(choices,
			fmt.Sprintf("%s\t%s-%s -> %s", rel.Name, rel.Chart.Metadata.Name, rel.Chart.Metadata.Version, rel.Info.Status.String()))
	}

	return choices, cobra.ShellCompDirectiveNoFileComp
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"path"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	cmds "github.com/jbenet/go-ipfs/commands"
	core "github.com/jbenet/go-ipfs/core"
	corecmds "github.com/jbenet/go-ipfs/core/commands"
	core_io "github.com/jbenet/go-ipfs/core/io"
	ci "github.com/jbenet/go-ipfs/p2p/crypto"
	peer "github.com/jbenet/go-ipfs/p2p/peer"
	repo "github.com/jbenet/go-ipfs/repo"
	config "github.com/jbenet/go-ipfs/repo/config"
	fsrepo "github.com/jbenet/go-ipfs/repo/fsrepo"
	u "github.com/jbenet/go-ipfs/util"
	debugerror "github.com/jbenet/go-ipfs/util/debugerror"
)

const nBitsForKeypairDefault = 4096

var initCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline:          "Initializes IPFS config file",
		ShortDescription: "Initializes IPFS configuration files and generates a new keypair.",
	},

	Options: []cmds.Option{
		cmds.IntOption("bits", "b", "Number of bits to use in the generated RSA private key (defaults to 4096)"),
		cmds.StringOption("passphrase", "p", "Passphrase for encrypting the private key"),
		cmds.BoolOption("force", "f", "Overwrite existing config (if it exists)"),

		// TODO need to decide whether to expose the override as a file or a
		// directory. That is: should we allow the user to also specify the
		// name of the file?
		// TODO cmds.StringOption("event-logs", "l", "Location for machine-readable event logs"),
	},
	Run: func(req cmds.Request) (interface{}, error) {

		force, _, err := req.Option("f").Bool() // if !found, it's okay force == false
		if err != nil {
			return nil, err
		}

		nBitsForKeypair, bitsOptFound, err := req.Option("b").Int()
		if err != nil {
			return nil, err
		}
		if !bitsOptFound {
			nBitsForKeypair = nBitsForKeypairDefault
		}

		return doInit(req.Context().ConfigRoot, force, nBitsForKeypair)
	},
}

var errRepoExists = debugerror.New(`ipfs configuration file already exists!
Reinitializing would overwrite your keys.
(use -f to force overwrite)
`)

var welcomeMsg = `Hello and Welcome to IPFS!

██╗██████╗ ███████╗███████╗
██║██╔══██╗██╔════╝██╔════╝
██║██████╔╝█████╗  ███████╗
██║██╔═══╝ ██╔══╝  ╚════██║
██║██║     ██║     ███████║
╚═╝╚═╝     ╚═╝     ╚══════╝

If you're seeing this, you have successfully installed
IPFS and are now interfacing with the ipfs merkledag!

For a short demo of what you can do, enter 'ipfs tour'
`

func initWithDefaults(repoRoot string) error {
	_, err := doInit(repoRoot, false, nBitsForKeypairDefault)
	return debugerror.Wrap(err)
}

func doInit(repoRoot string, force bool, nBitsForKeypair int) (interface{}, error) {

	u.POut("initializing ipfs node at %s\n", repoRoot)

	if fsrepo.IsInitialized(repoRoot) && !force {
		return nil, errRepoExists
	}

	conf, err := initConfig(nBitsForKeypair)
	if err != nil {
		return nil, err
	}
	if fsrepo.IsInitialized(repoRoot) {
		if err := fsrepo.Remove(repoRoot); err != nil {
			return nil, err
		}
	}
	if err := fsrepo.Init(repoRoot, conf); err != nil {
		return nil, err
	}
	if err := repo.ConfigureEventLogger(conf.Logs); err != nil {
		return nil, err
	}
	err = addTheWelcomeFile(repoRoot)
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// addTheWelcomeFile adds a file containing the welcome message to the newly
// minted node. On success, it calls onSuccess
func addTheWelcomeFile(repoRoot string) error {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	r := fsrepo.At(repoRoot)
	if err := r.Open(); err != nil { // NB: repo is owned by the node
		return err
	}
	nd, err := core.NewIPFSNode(ctx, core.Offline(r))
	if err != nil {
		return err
	}
	defer nd.Close()

	// Set up default file
	reader := bytes.NewBufferString(welcomeMsg)
	k, err := core_io.Add(nd, reader)
	if err != nil {
		return fmt.Errorf("failed to write test file: %s", err)
	}
	fmt.Printf("\nto get started, enter: ipfs cat %s\n", k)
	return nil
}

func datastoreConfig() (*config.Datastore, error) {
	dspath, err := config.DataStorePath("")
	if err != nil {
		return nil, err
	}
	return &config.Datastore{
		Path: dspath,
		Type: "leveldb",
	}, nil
}

func initConfig(nBitsForKeypair int) (*config.Config, error) {
	ds, err := datastoreConfig()
	if err != nil {
		return nil, err
	}

	identity, err := identityConfig(nBitsForKeypair)
	if err != nil {
		return nil, err
	}

	logConfig, err := initLogs()
	if err != nil {
		return nil, err
	}

	bootstrapPeers, err := corecmds.DefaultBootstrapPeers()
	if err != nil {
		return nil, err
	}

	conf := &config.Config{

		// setup the node's default addresses.
		// Note: two swarm listen addrs, one tcp, one utp.
		Addresses: config.Addresses{
			Swarm: []string{
				"/ip4/0.0.0.0/tcp/4001",
				// "/ip4/0.0.0.0/udp/4002/utp", // disabled for now.
			},
			API: "/ip4/127.0.0.1/tcp/5001",
		},

		Bootstrap: bootstrapPeers,
		Datastore: *ds,
		Logs:      *logConfig,
		Identity:  identity,

		// setup the node mount points.
		Mounts: config.Mounts{
			IPFS: "/ipfs",
			IPNS: "/ipns",
		},

		// tracking ipfs version used to generate the init folder and adding
		// update checker default setting.
		Version: config.VersionDefaultValue(),
	}

	return conf, nil
}

// identityConfig initializes a new identity.
func identityConfig(nbits int) (config.Identity, error) {
	// TODO guard higher up
	ident := config.Identity{}
	if nbits < 1024 {
		return ident, debugerror.New("Bitsize less than 1024 is considered unsafe.")
	}

	fmt.Printf("generating key pair...")
	sk, pk, err := ci.GenerateKeyPair(ci.RSA, nbits)
	if err != nil {
		return ident, err
	}
	fmt.Printf("done\n")

	// currently storing key unencrypted. in the future we need to encrypt it.
	// TODO(security)
	skbytes, err := sk.Bytes()
	if err != nil {
		return ident, err
	}
	ident.PrivKey = base64.StdEncoding.EncodeToString(skbytes)

	id, err := peer.IDFromPublicKey(pk)
	if err != nil {
		return ident, err
	}
	ident.PeerID = id.Pretty()
	fmt.Printf("peer identity: %s\n", ident.PeerID)
	return ident, nil
}

// initLogs initializes the event logger.
func initLogs() (*config.Logs, error) {
	logpath, err := config.LogsPath("")
	if err != nil {
		return nil, err
	}
	conf := config.Logs{
		Filename: path.Join(logpath, "events.log"),
	}
	return &conf, nil
}
<commit_msg>fix(command/init) rm stale comment<commit_after>package main

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"path"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	cmds "github.com/jbenet/go-ipfs/commands"
	core "github.com/jbenet/go-ipfs/core"
	corecmds "github.com/jbenet/go-ipfs/core/commands"
	core_io "github.com/jbenet/go-ipfs/core/io"
	ci "github.com/jbenet/go-ipfs/p2p/crypto"
	peer "github.com/jbenet/go-ipfs/p2p/peer"
	repo "github.com/jbenet/go-ipfs/repo"
	config "github.com/jbenet/go-ipfs/repo/config"
	fsrepo "github.com/jbenet/go-ipfs/repo/fsrepo"
	u "github.com/jbenet/go-ipfs/util"
	debugerror "github.com/jbenet/go-ipfs/util/debugerror"
)

const nBitsForKeypairDefault = 4096

var initCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline:          "Initializes IPFS config file",
		ShortDescription: "Initializes IPFS configuration files and generates a new keypair.",
	},

	Options: []cmds.Option{
		cmds.IntOption("bits", "b", "Number of bits to use in the generated RSA private key (defaults to 4096)"),
		cmds.StringOption("passphrase", "p", "Passphrase for encrypting the private key"),
		cmds.BoolOption("force", "f", "Overwrite existing config (if it exists)"),

		// TODO need to decide whether to expose the override as a file or a
		// directory. That is: should we allow the user to also specify the
		// name of the file?
		// TODO cmds.StringOption("event-logs", "l", "Location for machine-readable event logs"),
	},
	Run: func(req cmds.Request) (interface{}, error) {

		force, _, err := req.Option("f").Bool() // if !found, it's okay force == false
		if err != nil {
			return nil, err
		}

		nBitsForKeypair, bitsOptFound, err := req.Option("b").Int()
		if err != nil {
			return nil, err
		}
		if !bitsOptFound {
			nBitsForKeypair = nBitsForKeypairDefault
		}

		return doInit(req.Context().ConfigRoot, force, nBitsForKeypair)
	},
}

var errRepoExists = debugerror.New(`ipfs configuration file already exists!
Reinitializing would overwrite your keys.
(use -f to force overwrite)
`)

var welcomeMsg = `Hello and Welcome to IPFS!

██╗██████╗ ███████╗███████╗
██║██╔══██╗██╔════╝██╔════╝
██║██████╔╝█████╗  ███████╗
██║██╔═══╝ ██╔══╝  ╚════██║
██║██║     ██║     ███████║
╚═╝╚═╝     ╚═╝     ╚══════╝

If you're seeing this, you have successfully installed
IPFS and are now interfacing with the ipfs merkledag!

For a short demo of what you can do, enter 'ipfs tour'
`

func initWithDefaults(repoRoot string) error {
	_, err := doInit(repoRoot, false, nBitsForKeypairDefault)
	return debugerror.Wrap(err)
}

func doInit(repoRoot string, force bool, nBitsForKeypair int) (interface{}, error) {

	u.POut("initializing ipfs node at %s\n", repoRoot)

	if fsrepo.IsInitialized(repoRoot) && !force {
		return nil, errRepoExists
	}

	conf, err := initConfig(nBitsForKeypair)
	if err != nil {
		return nil, err
	}
	if fsrepo.IsInitialized(repoRoot) {
		if err := fsrepo.Remove(repoRoot); err != nil {
			return nil, err
		}
	}
	if err := fsrepo.Init(repoRoot, conf); err != nil {
		return nil, err
	}
	if err := repo.ConfigureEventLogger(conf.Logs); err != nil {
		return nil, err
	}
	err = addTheWelcomeFile(repoRoot)
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// addTheWelcomeFile adds a file containing the welcome message to the newly
// minted node.
func addTheWelcomeFile(repoRoot string) error {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	r := fsrepo.At(repoRoot)
	if err := r.Open(); err != nil { // NB: repo is owned by the node
		return err
	}
	nd, err := core.NewIPFSNode(ctx, core.Offline(r))
	if err != nil {
		return err
	}
	defer nd.Close()

	// Set up default file
	reader := bytes.NewBufferString(welcomeMsg)
	k, err := core_io.Add(nd, reader)
	if err != nil {
		return fmt.Errorf("failed to write test file: %s", err)
	}
	fmt.Printf("\nto get started, enter: ipfs cat %s\n", k)
	return nil
}

func datastoreConfig() (*config.Datastore, error) {
	dspath, err := config.DataStorePath("")
	if err != nil {
		return nil, err
	}
	return &config.Datastore{
		Path: dspath,
		Type: "leveldb",
	}, nil
}

func initConfig(nBitsForKeypair int) (*config.Config, error) {
	ds, err := datastoreConfig()
	if err != nil {
		return nil, err
	}

	identity, err := identityConfig(nBitsForKeypair)
	if err != nil {
		return nil, err
	}

	logConfig, err := initLogs()
	if err != nil {
		return nil, err
	}

	bootstrapPeers, err := corecmds.DefaultBootstrapPeers()
	if err != nil {
		return nil, err
	}

	conf := &config.Config{

		// setup the node's default addresses.
		// Note: two swarm listen addrs, one tcp, one utp.
		Addresses: config.Addresses{
			Swarm: []string{
				"/ip4/0.0.0.0/tcp/4001",
				// "/ip4/0.0.0.0/udp/4002/utp", // disabled for now.
			},
			API: "/ip4/127.0.0.1/tcp/5001",
		},

		Bootstrap: bootstrapPeers,
		Datastore: *ds,
		Logs:      *logConfig,
		Identity:  identity,

		// setup the node mount points.
		Mounts: config.Mounts{
			IPFS: "/ipfs",
			IPNS: "/ipns",
		},

		// tracking ipfs version used to generate the init folder and adding
		// update checker default setting.
		Version: config.VersionDefaultValue(),
	}

	return conf, nil
}

// identityConfig initializes a new identity.
func identityConfig(nbits int) (config.Identity, error) {
	// TODO guard higher up
	ident := config.Identity{}
	if nbits < 1024 {
		return ident, debugerror.New("Bitsize less than 1024 is considered unsafe.")
	}

	fmt.Printf("generating key pair...")
	sk, pk, err := ci.GenerateKeyPair(ci.RSA, nbits)
	if err != nil {
		return ident, err
	}
	fmt.Printf("done\n")

	// currently storing key unencrypted. in the future we need to encrypt it.
	// TODO(security)
	skbytes, err := sk.Bytes()
	if err != nil {
		return ident, err
	}
	ident.PrivKey = base64.StdEncoding.EncodeToString(skbytes)

	id, err := peer.IDFromPublicKey(pk)
	if err != nil {
		return ident, err
	}
	ident.PeerID = id.Pretty()
	fmt.Printf("peer identity: %s\n", ident.PeerID)
	return ident, nil
}

// initLogs initializes the event logger.
func initLogs() (*config.Logs, error) {
	logpath, err := config.LogsPath("")
	if err != nil {
		return nil, err
	}
	conf := config.Logs{
		Filename: path.Join(logpath, "events.log"),
	}
	return &conf, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"

	"github.com/atotto/clipboard"
	"github.com/docopt/docopt-go"
	"github.com/yml/keep"
)

const (
	exitCodeOk    = 0
	exitCodeNotOk = 1
)

var input string

// printAndExitOnError exit the program with 1 as exit code after printing the message if the error is not nil.
func printAndExitOnError(err error, msg string) {
	if err != nil {
		fmt.Println(msg, err)
		os.Exit(exitCodeNotOk)
	}
}

func printFileNames(files []os.FileInfo) {
	for i, file := range files {
		fmt.Printf("%d - %s\n", i, file.Name())
	}
}

func main() {

	usage := `keep password manager

Usage:
	keep read [options] <file> [<number>] [--print]
	keep list [options] [<file>]
	keep add [options]

Options:
	-r --recipients=KEYS   List of key ids the message should be encypted
	-d --dir=PATH          Account Directory
	-p --profile=NAME      Profile name
	-c --clipboard         Copy password to the clipboard

Examples:

	Read the account information for example.com:

		keep read -c example.com
`

	args, err := docopt.Parse(usage, nil, true, "keep cli version: 0.1", false)
	printAndExitOnError(err, "Docopt specification cannot be parsed")

	store, err := keep.LoadProfileStore()
	printAndExitOnError(err, "An error occured while loading the profile store")

	// defaulting to the first profile
	profile := store[0]
	profileName, ok := args["--profile"].(string)
	if ok {
		profileFound := false
		for _, p := range store {
			if profileName == p.Name {
				profile = p
				profileFound = true
				break
			}
		}
		if !profileFound {
			fmt.Printf("Profile (%s) not found\n", profileName)
			os.Exit(exitCodeNotOk)
		}
	}
	fmt.Println("Using profile : ", profile.Name)

	conf := keep.NewConfig(&profile)
	// Overriding the config with information from the cli parameters
	accountDir, ok := args["--dir"].(string)
	if ok {
		conf.AccountDir = accountDir
	}
	recipients, ok := args["--recipients"].(string)
	if ok {
		conf.RecipientKeyIds = recipients
	}

	//fmt.Println(args, "\n", conf)
	if val, ok := args["read"]; ok == true && val == true {
		fmt.Printf("Reading ...\n\n")
		fname, ok := args["<file>"].(string)
		if !ok {
			fmt.Println("An error occured while converting <file> into string")
			os.Exit(exitCodeOk)
		}

		var accountPosition *int
		snumber, ok := args["<number>"].(string)
		if ok {
			number, err := strconv.Atoi(snumber)
			printAndExitOnError(err, "An error occured while converting the <number> to an int")
			accountPosition = &number
		}

		var copyToclipboard bool
		if val, ok := args["-c"]; ok == true && val == true {
			copyToclipboard = true
		} else if val, ok := args["--clipboard"]; ok == true && val == true {
			copyToclipboard = true
		}

		files, err := conf.ListAccountFiles(fname)
		printAndExitOnError(err, "An error occured while gathering the accounts")
		switch l := len(files); {
		case l == 1:
			// Automatically fallback to the first match if there is only one option
			f := files[0]
			fname = f.Name()
		case l > 1 && accountPosition != nil && *accountPosition < l:
			// If there is more than one option and an accountPosition is given we are going to use it
			f := files[*accountPosition]
			fname = f.Name()
		case l == 0:
			// 0 matching account
			fmt.Println("No account name match :", fname)
			os.Exit(exitCodeNotOk)
		default:
			// We couldn't guess what to do so we list all the options
			fmt.Println("There is more than one match")
			printFileNames(files)
			os.Exit(exitCodeNotOk)
		}

		account, err := keep.NewAccountFromFile(conf, fname)
		if os.IsNotExist(err) {
			fmt.Printf("Account name (%s) does not exist.\n Listing ...\n\n", fname)
			os.Exit(exitCodeNotOk)
		}
		printAndExitOnError(err, "An error occured while creating and account from the clear text reader")

		fmt.Println("file path :", account.Path())
		if account.IsSigned {
			fmt.Printf("Credentials have been signed by : %s\n\n", account.SignedBy.PrivateKey.KeyIdShortString())
		} else {
			fmt.Printf("\nWARNING: This credential is not signed !!!\n\n")
		}

		fmt.Println("Name : ", account.Name)
		fmt.Println("Username : ", account.Username)
		fmt.Println("Notes : ", account.Notes)
		if printOpt, ok := args["--print"]; ok && printOpt.(bool) == true {
			fmt.Println("Password : ", account.Password)
		}

		if copyToclipboard {
			err = clipboard.WriteAll(account.Password)
			printAndExitOnError(err, "An error occured while writing the password to the clipboard")
		}
	} else if val, ok := args["list"]; ok == true && val == true {
		fmt.Printf("Listing ...\n\n")
		fileSubStr, ok := args["<file>"].(string)
		if !ok {
			fileSubStr = ""
		}
		files, err := conf.ListAccountFiles(fileSubStr)
		printAndExitOnError(err, "An error occured while gathering the accounts")
		printFileNames(files)

	} else if val, ok := args["add"]; ok == true && val == true {
		fmt.Printf("Adding ...\n\n")
		account, err := keep.NewAccountFromConsole(conf)
		printAndExitOnError(err, "An error occured while retrieving account info from the console :")

		content, err := account.Encrypt()
		printAndExitOnError(err, "An error occured while encrypting the account to bytes")

		fpath := filepath.Join(conf.AccountDir, account.Name)
		if _, err := os.Stat(fpath); !os.IsNotExist(err) {
			fmt.Printf("Account %s already exists\n", fpath)
			os.Exit(exitCodeNotOk)
		}
		fmt.Println("Writing file :", fpath)
		err = ioutil.WriteFile(fpath, content, 0600)
		printAndExitOnError(err, "An error occured while writing the new account to disk")
	}
}
<commit_msg>Better handle the case `signedBy` == nil<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"time"

	"github.com/atotto/clipboard"
	"github.com/docopt/docopt-go"
	"github.com/yml/keep"
)

const (
	exitCodeOk    = 0
	exitCodeNotOk = 1
)

var input string

// printAndExitOnError exit the program with 1 as exit code after printing the message if the error is not nil.
func printAndExitOnError(err error, msg string) {
	if err != nil {
		fmt.Println(msg, err)
		os.Exit(exitCodeNotOk)
	}
}

func printFileNames(files []os.FileInfo) {
	for i, file := range files {
		fmt.Printf("%d - %s\n", i, file.Name())
	}
}

func main() {

	usage := `keep password manager

Usage:
	keep read [options] <file> [<number>] [--print]
	keep list [options] [<file>]
	keep add [options]

Options:
	-r --recipients=KEYS   List of key ids the message should be encypted
	-d --dir=PATH          Account Directory
	-p --profile=NAME      Profile name
	-c --clipboard         Copy password to the clipboard

Examples:

	Read the account information for example.com:

		keep read -c example.com
`

	args, err := docopt.Parse(usage, nil, true, "keep cli version: 0.1", false)
	printAndExitOnError(err, "Docopt specification cannot be parsed")

	store, err := keep.LoadProfileStore()
	printAndExitOnError(err, "An error occured while loading the profile store")

	// defaulting to the first profile
	profile := store[0]
	profileName, ok := args["--profile"].(string)
	if ok {
		profileFound := false
		for _, p := range store {
			if profileName == p.Name {
				profile = p
				profileFound = true
				break
			}
		}
		if !profileFound {
			fmt.Printf("Profile (%s) not found\n", profileName)
			os.Exit(exitCodeNotOk)
		}
	}
	fmt.Println("Using profile : ", profile.Name)

	conf := keep.NewConfig(&profile)
	// Overriding the config with information from the cli parameters
	accountDir, ok := args["--dir"].(string)
	if ok {
		conf.AccountDir = accountDir
	}
	recipients, ok := args["--recipients"].(string)
	if ok {
		conf.RecipientKeyIds = recipients
	}

	//fmt.Println(args, "\n", conf)
	if val, ok := args["read"]; ok == true && val == true {
		fmt.Printf("Reading ...\n\n")
		fname, ok := args["<file>"].(string)
		if !ok {
			fmt.Println("An error occured while converting <file> into string")
			os.Exit(exitCodeOk)
		}

		var accountPosition *int
		snumber, ok := args["<number>"].(string)
		if ok {
			number, err := strconv.Atoi(snumber)
			printAndExitOnError(err, "An error occured while converting the <number> to an int")
			accountPosition = &number
		}

		var copyToclipboard bool
		if val, ok := args["-c"]; ok == true && val == true {
			copyToclipboard = true
		} else if val, ok := args["--clipboard"]; ok == true && val == true {
			copyToclipboard = true
		}

		files, err := conf.ListAccountFiles(fname)
		printAndExitOnError(err, "An error occured while gathering the accounts")
		switch l := len(files); {
		case l == 1:
			// Automatically fallback to the first match if there is only one option
			f := files[0]
			fname = f.Name()
		case l > 1 && accountPosition != nil && *accountPosition < l:
			// If there is more than one option and an accountPosition is given we are going to use it
			f := files[*accountPosition]
			fname = f.Name()
		case l == 0:
			// 0 matching account
			fmt.Println("No account name match :", fname)
			os.Exit(exitCodeNotOk)
		default:
			// We couldn't guess what to do so we list all the options
			fmt.Println("There is more than one match")
			printFileNames(files)
			os.Exit(exitCodeNotOk)
		}

		account, err := keep.NewAccountFromFile(conf, fname)
		if os.IsNotExist(err) {
			fmt.Printf("Account name (%s) does not exist.\n Listing ...\n\n", fname)
			os.Exit(exitCodeNotOk)
		}
		printAndExitOnError(err, "An error occured while creating and account from the clear text reader")

		fmt.Println("file path :", account.Path())
		if account.IsSigned && account.SignedBy != nil {
			fmt.Printf("Credentials have been signed by : %s\n\n", account.SignedBy.PrivateKey.KeyIdShortString())
		} else {
			fmt.Printf("\nWARNING: This credential is not signed !!!\n\n")
		}

		fmt.Println("Name : ", account.Name)
		fmt.Println("Username : ", account.Username)
		fmt.Println("Notes : ", account.Notes)
		if printOpt, ok := args["--print"]; ok && printOpt.(bool) == true {
			fmt.Println("Password : ", account.Password)
		}

		if copyToclipboard {
			err = clipboard.WriteAll(account.Password)
			printAndExitOnError(err, "An error occured while writing the password to the clipboard")
			defer func() {
				time.Sleep(15 * time.Second)
				err = clipboard.WriteAll("keep: cleared value")
				printAndExitOnError(err, "An error occured while clearing the clipboard")
			}()
		}
	} else if val, ok := args["list"]; ok == true && val == true {
		fmt.Printf("Listing ...\n\n")
		fileSubStr, ok := args["<file>"].(string)
		if !ok {
			fileSubStr = ""
		}
		files, err := conf.ListAccountFiles(fileSubStr)
		printAndExitOnError(err, "An error occured while gathering the accounts")
		printFileNames(files)

	} else if val, ok := args["add"]; ok == true && val == true {
		fmt.Printf("Adding ...\n\n")
		account, err := keep.NewAccountFromConsole(conf)
		printAndExitOnError(err, "An error occured while retrieving account info from the console :")

		content, err := account.Encrypt()
		printAndExitOnError(err, "An error occured while encrypting the account to bytes")

		fpath := filepath.Join(conf.AccountDir, account.Name)
		if _, err := os.Stat(fpath); !os.IsNotExist(err) {
			fmt.Printf("Account %s already exists\n", fpath)
			os.Exit(exitCodeNotOk)
		}
		fmt.Println("Writing file :", fpath)
		err = ioutil.WriteFile(fpath, content, 0600)
		printAndExitOnError(err, "An error occured while writing the new account to disk")
	}
}
<|endoftext|>


<commit_before>package cmd

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

var join = filepath.Join

// makeTestData constructs
func makeTestdata(t *testing.T) string {
	tempdir, err := filepath.EvalSymlinks(os.TempDir())
	if err != nil {
		t.Fatal(err)
	}

	root, err := ioutil.TempDir(tempdir, "path-test")
	if err != nil {
		t.Fatal(err)
	}
	mkdir := func(args ...string) string {
		path := join(args...)
		if err := os.MkdirAll(path, 0777); err != nil {
			t.Fatal(err)
		}
		return path
	}
	mkfile := func(path string, content string) {
		if err := ioutil.WriteFile(path, []byte(content), 0755); err != nil {
			t.Fatal(err)
		}
	}

	srcdir := mkdir(root, "src")
	mkfile(join(mkdir(srcdir, "a"), "a.go"), "package a")

	return root
}

func TestFindProjectroot(t *testing.T) {
	root := makeTestdata(t)
	defer os.RemoveAll(root)
	tests := []struct {
		path string
		want string
		err  error
	}{
		{path: root, want: root},
		{path: join(root, "src"), want: root},
		{path: join(join(root, "src"), "a"), want: root},
		{path: join(root, ".."), err: fmt.Errorf(`could not find project root in "%s" or its parents`, join(root, ".."))},
	}

	for _, tt := range tests {
		got, err := FindProjectroot(tt.path)
		if got != tt.want || !sameErr(err, tt.err) {
			t.Errorf("FindProjectroot(%v): want: %v, %v, got %v, %v", tt.path, tt.want, tt.err, got, err)
		}
	}
}

func sameErr(e1, e2 error) bool {
	if e1 != nil && e2 != nil {
		return e1.Error() == e2.Error()
	}
	return e1 == e2
}
<commit_msg>remove unused sameErr<commit_after>package cmd

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"testing"
)

var join = filepath.Join

// makeTestData constructs
func makeTestdata(t *testing.T) string {
	tempdir, err := filepath.EvalSymlinks(os.TempDir())
	if err != nil {
		t.Fatal(err)
	}

	root, err := ioutil.TempDir(tempdir, "path-test")
	if err != nil {
		t.Fatal(err)
	}
	mkdir := func(args ...string) string {
		path := join(args...)
		if err := os.MkdirAll(path, 0777); err != nil {
			t.Fatal(err)
		}
		return path
	}
	mkfile := func(path string, content string) {
		if err := ioutil.WriteFile(path, []byte(content), 0755); err != nil {
			t.Fatal(err)
		}
	}

	srcdir := mkdir(root, "src")
	mkfile(join(mkdir(srcdir, "a"), "a.go"), "package a")

	return root
}

func TestFindProjectroot(t *testing.T) {
	root := makeTestdata(t)
	defer os.RemoveAll(root)
	tests := []struct {
		path string
		want string
		err  error
	}{
		{path: root, want: root},
		{path: join(root, "src"), want: root},
		{path: join(join(root, "src"), "a"), want: root},
		{path: join(root, ".."), err: fmt.Errorf(`could not find project root in "%s" or its parents`, join(root, ".."))},
	}

	for _, tt := range tests {
		got, err := FindProjectroot(tt.path)
		if got != tt.want || !reflect.DeepEqual(err, tt.err) {
			t.Errorf("FindProjectroot(%v): want: %v, %v, got %v, %v", tt.path, tt.want, tt.err, got, err)
		}
	}
}
<|endoftext|>