<commit_before>// Package sanitized_anchor_name provides a func to create sanitized anchor names.
//
// Its logic can be reused by multiple packages to create interoperable anchor names
// and links to those anchors.
//
// At this time, it does not try to ensure that generated anchor names
// are unique, that responsibility falls on the caller.
package sanitized_anchor_name // import "github.com/shurcooL/sanitized_anchor_name"

import "unicode"

// Create returns a sanitized anchor name for the given text.
func Create(text string) string {
	var anchorName []rune
	var futureDash = false
	for _, r := range []rune(text) {
		switch {
		case unicode.IsLetter(r) || unicode.IsNumber(r):
			if futureDash && len(anchorName) > 0 {
				anchorName = append(anchorName, '-')
			}
			futureDash = false
			anchorName = append(anchorName, unicode.ToLower(r))
		default:
			futureDash = true
		}
	}
	return string(anchorName)
}
<commit_msg>Simplify range over runes.<commit_after>// Package sanitized_anchor_name provides a func to create sanitized anchor names.
//
// Its logic can be reused by multiple packages to create interoperable anchor names
// and links to those anchors.
//
// At this time, it does not try to ensure that generated anchor names
// are unique, that responsibility falls on the caller.
package sanitized_anchor_name // import "github.com/shurcooL/sanitized_anchor_name"

import "unicode"

// Create returns a sanitized anchor name for the given text.
func Create(text string) string {
	var anchorName []rune
	var futureDash = false
	for _, r := range text {
		switch {
		case unicode.IsLetter(r) || unicode.IsNumber(r):
			if futureDash && len(anchorName) > 0 {
				anchorName = append(anchorName, '-')
			}
			futureDash = false
			anchorName = append(anchorName, unicode.ToLower(r))
		default:
			futureDash = true
		}
	}
	return string(anchorName)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/codegangsta/negroni"
	"github.com/craigfurman/bovine/indexer"
	"github.com/craigfurman/bovine/web"
)

func main() {
	commaSeparatedKeywords := flag.String("keywords", "", "")
	flag.Parse()
	keywords := strings.Split(*commaSeparatedKeywords, ",")

	// TODO make redis URL configurable. Use VCAP services if on CF
	i := indexer.New("localhost:6379", clock{})
	api := web.New(i, keywords, clock{})
	server := negroni.Classic()
	server.UseHandler(api)
	server.Run(fmt.Sprintf(":%s", port()))
}

func port() string {
	if os.Getenv("PORT") != "" {
		return os.Getenv("PORT")
	} else {
		return "3000"
	}
}

type clock struct{}

func (clock) Now() time.Time {
	return time.Now()
}
<commit_msg>use env vars not command line args for app<commit_after>package main

import (
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/codegangsta/negroni"
	"github.com/craigfurman/bovine/indexer"
	"github.com/craigfurman/bovine/web"
)

func main() {
	commaSeparatedKeywords := os.Getenv("KEYWORDS")
	keywords := strings.Split(commaSeparatedKeywords, ",")

	// TODO make redis URL configurable. Use VCAP services if on CF
	i := indexer.New("localhost:6379", clock{})
	api := web.New(i, keywords, clock{})
	server := negroni.Classic()
	server.UseHandler(api)
	server.Run(fmt.Sprintf(":%s", port()))
}

func port() string {
	if os.Getenv("PORT") != "" {
		return os.Getenv("PORT")
	} else {
		return "3000"
	}
}

type clock struct{}

func (clock) Now() time.Time {
	return time.Now()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"github.com/eknkc/amber"
	"log"
	"net/http"
	"strconv"
)

const (
	TLS_CERT       = "tls/cert-unified.pem"
	TLS_KEY        = "tls/cert.key"
	COUNT_DEFAULT  = 5
	LENGTH_DEFAULT = 5
)

var word_map = map[string][]string{}

func main() {
	log.Printf("Loading word map")
	word_map = LoadWordMap()
	log.Printf("Starting and listening on 4343")
	fs := http.FileServer(http.Dir("static"))
	http.Handle("/static", http.StripPrefix("/static/", fs))
	http.HandleFunc("/", Root)
	http.HandleFunc("/passphrases", Passphrases)
	//http.ListenAndServeTLS("0.0.0.0:4343", TLS_CERT, TLS_KEY, nil)
	http.ListenAndServe("0.0.0.0:8000", nil)
}

func Root(w http.ResponseWriter, r *http.Request) {
	compiler := amber.New()
	err := compiler.ParseFile("views/main.amber")
	if err != nil {
		http.Error(w, "Bad template: main.amber", 500)
	}
	tpl, err := compiler.Compile()
	if err != nil {
		http.Error(w, "Error compiling template: main.amber", 500)
	}
	tpl.Execute(w, nil)
}

func Passphrases(w http.ResponseWriter, r *http.Request) {
	query_values := r.URL.Query()
	count := COUNT_DEFAULT
	length := LENGTH_DEFAULT

	type passphrase_output struct {
		Count       int
		Length      int
		Passphrases []string
	}
	var output passphrase_output

	log.Printf("got Query: %v\n", query_values)

	var err error
	if val, ok := query_values["count"]; ok {
		count, err = strconv.Atoi(val[0])
		if err != nil {
			log.Printf("WARNING: bad count parameter passed: %v; %v\n", err, val[0])
		}
	}

	if val, ok := query_values["length"]; ok {
		length, err = strconv.Atoi(val[0])
		if err != nil {
			log.Printf("WARNING: bad lenth parameter passed: %v; %v\n", err, val[0])
		}
	}

	log.Printf("COUNT: %v\n", count)
	log.Printf("LENGTH: %v\n", length)

	passphrases := GeneratePassphrases(word_map, count, length)

	for i, val := range passphrases {
		log.Printf("phrase %v: %v\n", i, val)
	}

	output.Count = count
	output.Length = length
	output.Passphrases = passphrases

	//emit json
	w.Header().Set("Content-Type", "application/json")
	j, err := json.Marshal(output)
	if err != nil {
		log.Printf("ERROR marshalling json: %v\n", err)
		http.Error(w, "Internal Server Error", 500)
	}
	w.Write(j)
}
<commit_msg>fix muxing<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/eknkc/amber"
	"log"
	"net/http"
	"strconv"
)

const (
	TLS_CERT       = "tls/cert-unified.pem"
	TLS_KEY        = "tls/cert.key"
	COUNT_DEFAULT  = 5
	LENGTH_DEFAULT = 5
	LISTEN_PORT    = 8000
)

var word_map = map[string][]string{}

func main() {
	log.Printf("Loading word map")
	word_map = LoadWordMap()
	log.Printf("Starting and listening on %v\n", LISTEN_PORT)
	http.Handle("/static/", http.StripPrefix("/static", http.FileServer(http.Dir("./static"))))
	http.HandleFunc("/", Root)
	http.HandleFunc("/passphrases", Passphrases)
	//http.ListenAndServeTLS("0.0.0.0:4343", TLS_CERT, TLS_KEY, nil)
	http.ListenAndServe(fmt.Sprintf("0.0.0.0:%v", LISTEN_PORT), nil)
}

func Root(w http.ResponseWriter, r *http.Request) {
	compiler := amber.New()
	err := compiler.ParseFile("views/main.amber")
	if err != nil {
		http.Error(w, "Bad template: main.amber", 500)
	}
	tpl, err := compiler.Compile()
	if err != nil {
		http.Error(w, "Error compiling template: main.amber", 500)
	}
	tpl.Execute(w, nil)
}

func Passphrases(w http.ResponseWriter, r *http.Request) {
	query_values := r.URL.Query()
	count := COUNT_DEFAULT
	length := LENGTH_DEFAULT

	type passphrase_output struct {
		Count       int
		Length      int
		Passphrases []string
	}
	var output passphrase_output

	log.Printf("got Query: %v\n", query_values)

	var err error
	if val, ok := query_values["count"]; ok {
		count, err = strconv.Atoi(val[0])
		if err != nil {
			log.Printf("WARNING: bad count parameter passed: %v; %v\n", err, val[0])
		}
	}

	if val, ok := query_values["length"]; ok {
		length, err = strconv.Atoi(val[0])
		if err != nil {
			log.Printf("WARNING: bad lenth parameter passed: %v; %v\n", err, val[0])
		}
	}

	log.Printf("COUNT: %v\n", count)
	log.Printf("LENGTH: %v\n", length)

	passphrases := GeneratePassphrases(word_map, count, length)

	for i, val := range passphrases {
		log.Printf("phrase %v: %v\n", i, val)
	}

	output.Count = count
	output.Length = length
	output.Passphrases = passphrases

	//emit json
	w.Header().Set("Content-Type", "application/json")
	j, err := json.Marshal(output)
	if err != nil {
		log.Printf("ERROR marshalling json: %v\n", err)
		http.Error(w, "Internal Server Error", 500)
	}
	w.Write(j)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"github.com/starmanmartin/simple-fs"
)

const (
	install = "install"
	test    = "test"
)

var runTypes = []string{install, test}

var (
 lastPart *regexp.Regexp
 isTest, isBenchTest, isExecute, isWatch bool
 newRoot, packageName, currentPath, outputString string
 restArgs []string
)

func init() {
	lastPart, _ = regexp.Compile(`[^\\/]*$`)

	flag.BoolVar(&isTest, "t", false, "Run as Test")
	flag.BoolVar(&isBenchTest, "b", false, "Bench tests (only if test)")
	flag.BoolVar(&isExecute, "e", false, "Execute (only if not test)")
	flag.BoolVar(&isWatch, "w", false, "Execute (only if not test)")
	flag.StringVar(&outputString, "p", "", "Make Package")
}

func startCmd(cmdCommand []string) (*exec.Cmd, error) {
	parts := cmdCommand
	head := parts[0]
	parts = parts[1:len(parts)]

	cmd := exec.Command(head, parts...)

	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

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

	return cmd, nil
}

func exeCmd(cmdCommand []string) (*exec.Cmd, error) {
	var cmd *exec.Cmd

	if cmd, err := startCmd(cmdCommand); err != nil {
		return cmd, err;
	}

	return cmd, nil//cmd.Wait()
}

func buildCommand(packageName string) []string {
	buffer := make([]string, 0, 6)

	buffer = append(buffer, "go")

	if isTest {
		buffer = append(buffer, "test")
		if isBenchTest {
			buffer = append(buffer, "-bench=.")
		}
	} else {
		buffer = append(buffer, "install")
	}

	buffer = append(buffer, "-v")

	return buffer
}

func handelPathArgs() (string, string, []string, error) {
	args := flag.Args()
	if len(args) == 0 {
		return "", "", nil, errors.New("No Args")
	}

	if len(args) == 1 || args[0][:11] == "github.com/" {
		dir, err := os.Getwd()
		if err != nil {
			return "", "", nil, (err)
		}

		return dir, args[0], args[1:], nil
	}

	absPath, err := filepath.Abs(args[0])
	if err != nil {
		return "", "", nil, (err)
	}

	return absPath, args[1], args[1:], nil
}

func copyPackage(dir, packageName, funcName string) (isPackage bool, err error) {
	if len(outputString) == 0 {
		return
	}

	isPackage = true
	dest := dir + "/bin/" + funcName + "/"
	src := dir + "/src/" + packageName + "/"

	output := strings.Split(outputString, " ")

	for _, dirName := range output {
		err = fs.CopyFolder(src+dirName, dest+dirName)
		if err != nil {
			return
		}
	}

	return
}

func main() {
	flag.Parse()
    var err error
	newRoot, packageName, restArgs, err = handelPathArgs()
	if err != nil {
		log.Fatal(err)
		return
	}

    runBuild()
}

func runBuild() {
	buildCommandList := buildCommand(packageName)
	buildCommandList = append(buildCommandList, packageName)
	currentPath := os.Getenv("GOPATH")
	defer os.Setenv("GOPATH", currentPath)
	newPath := []string{newRoot, ";", currentPath}

	os.Setenv("GOPATH", strings.Join(newPath, ""))
	_, err := exeCmd(buildCommandList)
	if err != nil {
		log.Fatal(err)
	}

	funcName := lastPart.FindString(packageName)
	isPackage, err := copyPackage(newRoot, packageName, funcName)

	if err != nil {
		log.Fatal(err)
		return
	} else if isPackage {
		fs.SyncFile(newRoot+"/bin/"+funcName+".exe", newRoot+"/bin/"+funcName+"/"+funcName+".exe")
		funcName = funcName + "/" + funcName
	}

	if isExecute && !isTest {
		log.Printf("Running %s\n", funcName)
		executionPath := newRoot + "/bin/" + funcName + ".exe"
		exArgs := []string{executionPath}
		exArgs = append(exArgs, restArgs...)
		if isWatch {
			watch(exArgs, newRoot+"/src/"+packageName)
		} else {
			_, err := exeCmd(exArgs)
            if err != nil {
                log.Fatal(err)
                return
            }
		}
	} else {
		log.Printf("Builded %s\n", funcName)
	}
}

func watch(args []string, rootPath string) {
	done := make(chan error, 1)

	cmd, err := startCmd(args)
    if err != nil {
        log.Fatal(err)
    }

	go func() {
		err := cmd.Wait()
        if err != nil {
            done <- err
        }
	}()

	restart := make(chan bool, 1)

	go func() {
		ticker := time.NewTicker(5 * time.Second)
		lastChaek := time.Now()
		for _ = range ticker.C {
			isUpdated, _ := fs.CheckIfFolderUpdated(rootPath, lastChaek)
			if isUpdated {
				restart <- true
				ticker.Stop()
			}
		}
	}()

	select {
	case <-restart:
		if err := cmd.Process.Kill(); err != nil {
			log.Fatal("failed to kill: ", err)
		}

		log.Println("process restarted")
        runBuild();
	case err := <-done:
		if err != nil {
			log.Fatal("process done with error = %v", err)
		} else {
			log.Print("process done gracefully without error")
		}
	}

}
<commit_msg>bug fix<commit_after>package main

import (
	"errors"
	"flag"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"github.com/starmanmartin/simple-fs"
)

const (
	install = "install"
	test    = "test"
)

var runTypes = []string{install, test}

var (
 lastPart *regexp.Regexp
 isTest, isBenchTest, isExecute, isWatch bool
 newRoot, packageName, currentPath, outputString string
 restArgs []string
)

func init() {
	lastPart, _ = regexp.Compile(`[^\\/]*$`)

	flag.BoolVar(&isTest, "t", false, "Run as Test")
	flag.BoolVar(&isBenchTest, "b", false, "Bench tests (only if test)")
	flag.BoolVar(&isExecute, "e", false, "Execute (only if not test)")
	flag.BoolVar(&isWatch, "w", false, "Execute (only if not test)")
	flag.StringVar(&outputString, "p", "", "Make Package")
}

func getCmd(cmdCommand []string) (*exec.Cmd) {
	parts := cmdCommand
	head := parts[0]
	parts = parts[1:len(parts)]

	cmd := exec.Command(head, parts...)

	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	return cmd
}

func exeCmd(cmdCommand []string) (*exec.Cmd, error) {
	cmd := getCmd(cmdCommand)

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

	return cmd, nil
}

func buildCommand(packageName string) []string {
	buffer := make([]string, 0, 6)

	buffer = append(buffer, "go")

	if isTest {
		buffer = append(buffer, "test")
		if isBenchTest {
			buffer = append(buffer, "-bench=.")
		}
	} else {
		buffer = append(buffer, "install")
	}

	buffer = append(buffer, "-v")

	return buffer
}

func handelPathArgs() (string, string, []string, error) {
	args := flag.Args()
	if len(args) == 0 {
		return "", "", nil, errors.New("No Args")
	}

	if len(args) == 1 || args[0][:11] == "github.com/" {
		dir, err := os.Getwd()
		if err != nil {
			return "", "", nil, (err)
		}

		return dir, args[0], args[1:], nil
	}

	absPath, err := filepath.Abs(args[0])
	if err != nil {
		return "", "", nil, (err)
	}

	return absPath, args[1], args[1:], nil
}

func copyPackage(dir, packageName, funcName string) (isPackage bool, err error) {
	if len(outputString) == 0 {
		return
	}

	isPackage = true
	dest := dir + "/bin/" + funcName + "/"
	src := dir + "/src/" + packageName + "/"

	output := strings.Split(outputString, " ")

	for _, dirName := range output {
		err = fs.CopyFolder(src+dirName, dest+dirName)
		if err != nil {
			return
		}
	}

	return
}

func main() {
	flag.Parse()
    var err error
	newRoot, packageName, restArgs, err = handelPathArgs()
	if err != nil {
		log.Fatal(err)
		return
	}

    runBuild()
}

func runBuild() {
	buildCommandList := buildCommand(packageName)
	buildCommandList = append(buildCommandList, packageName)
	currentPath := os.Getenv("GOPATH")
	defer os.Setenv("GOPATH", currentPath)
	newPath := []string{newRoot, ";", currentPath}

	os.Setenv("GOPATH", strings.Join(newPath, ""))
	_, err := exeCmd(buildCommandList)
	if err != nil {
		log.Fatal(err)
	}

	funcName := lastPart.FindString(packageName)
	isPackage, err := copyPackage(newRoot, packageName, funcName)

	if err != nil {
		log.Fatal(err)
		return
	} else if isPackage {
		fs.SyncFile(newRoot+"/bin/"+funcName+".exe", newRoot+"/bin/"+funcName+"/"+funcName+".exe")
		funcName = funcName + "/" + funcName
	}

	if isExecute && !isTest {
		log.Printf("Running %s\n", funcName)
		executionPath := newRoot + "/bin/" + funcName + ".exe"
		exArgs := []string{executionPath}
		exArgs = append(exArgs, restArgs...)
		if isWatch {
			watch(exArgs, newRoot+"/src/"+packageName)
		} else {
			_, err := exeCmd(exArgs)
            if err != nil {
                log.Fatal(err)
                return
            }
		}
	} else {
		log.Printf("Builded %s\n", funcName)
	}
}

func watch(args []string, rootPath string) {
	done := make(chan error, 1)

	cmd := getCmd(args)

	go func() {
		err := cmd.Run()
        if err != nil {
            done <- err
        }
	}()

	restart := make(chan bool, 1)

	go func() {
		ticker := time.NewTicker(5 * time.Second)
		lastChaek := time.Now()
		for _ = range ticker.C {
			isUpdated, _ := fs.CheckIfFolderUpdated(rootPath, lastChaek)
			if isUpdated {
				restart <- true
				ticker.Stop()
			}
		}
	}()

	select {
	case <-restart:
		if err := cmd.Process.Kill(); err != nil {
			log.Fatal("failed to kill: ", err)
		}

		log.Println("process restarted")
        runBuild();
	case err := <-done:
		if err != nil {
			log.Fatal("process done with error = %v", err)
		} else {
			log.Print("process done gracefully without error")
		}
	}

}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"flag"
	"fmt"
	"github.com/gorilla/mux"
	"github.com/kylelemons/go-gypsy/yaml"
	_ "github.com/mattn/go-sqlite3"
	"github.com/shawnps/gr"
	"github.com/shawnps/rt"
	"github.com/shawnps/sp"
	"html/template"
	"log"
	"net/http"
	"net/url"
	"strings"
	"sync"
)

var (
	port       = flag.String("p", "8000", "Port number (default 8000)")
	configFile = flag.String("c", "config.yml", "Config file (default config.yml)")
)

func getYAMLString(n yaml.Node, key string) string {
	return strings.TrimSpace(n.(yaml.Map)[key].(yaml.Scalar).String())
}

func parseYAML() (rtKey, grKey, grSecret string) {
	config, err := yaml.ReadFile(*configFile)
	if err != nil {
		log.Fatal(err)
	}
	configRoot, _ := config.Root.(yaml.Map)
	rtKey = configRoot["rt"].(yaml.Scalar).String()
	g := configRoot["gr"]
	grKey = getYAMLString(g, "key")
	grSecret = getYAMLString(g, "secret")

	return rtKey, grKey, grSecret
}

func createDb() {
	db, err := sql.Open("sqlite3", "./watchreadlisten.db")
	if err != nil {
		log.Println("Error opening or creating deploy_log.db: " + err.Error())
		return
	}
	defer db.Close()
	sql := `create table if not exists entries (id integer not null primary key autoincrement, title text, link text, media_type text, timestamp datetime default current_timestamp);`
	_, err = db.Exec(sql)
	if err != nil {
		log.Println("Error creating logs table: " + err.Error())
		return
	}
}

// Search Rotten Tomatoes, Goodreads, and Spotify.
func Search(q string, rtClient rt.RottenTomatoes, grClient gr.Goodreads, spClient sp.Spotify) (m []rt.Movie, g gr.GoodreadsResponse, s sp.SearchAlbumsResponse) {
	var wg sync.WaitGroup
	wg.Add(3)
	go func(q string) {
		defer wg.Done()
		movies, err := rtClient.SearchMovies(q)
		if err != nil {
			fmt.Println("ERROR (rt): ", err.Error())
		}
		for _, mov := range movies {
			m = append(m, mov)
		}
	}(q)
	go func(q string) {
		defer wg.Done()
		books, err := grClient.SearchBooks(q)
		if err != nil {
			fmt.Println("ERROR (gr): ", err.Error())
		}
		g = books
	}(q)
	go func(q string) {
		defer wg.Done()
		albums, err := spClient.SearchAlbums(q)
		if err != nil {
			fmt.Println("ERROR (sp): ", err.Error())
		}
		s = albums
	}(q)
	wg.Wait()
	return m, g, s
}

func HomeHandler(w http.ResponseWriter, r *http.Request) {
	t, err := template.New("index.html").ParseFiles("templates/index.html", "templates/base.html")
	if err != nil {
		log.Panic(err)
	}
	// Render the template
	err = t.ExecuteTemplate(w, "base", nil)
	if err != nil {
		log.Panic(err)
	}
}

func SearchHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	q := vars["query"]
	q, err := url.QueryUnescape(q)
	if err != nil {
		log.Panic(err)
	}
	rtKey, grKey, grSecret := parseYAML()
	rtClient := rt.RottenTomatoes{rtKey}
	grClient := gr.Goodreads{grKey, grSecret}
	spClient := sp.Spotify{}
	m, g, s := Search(q, rtClient, grClient, spClient)
	// Since spotify: URIs are not trusted, have to pass a
	// URL function to the template to use in hrefs
	funcMap := template.FuncMap{
		"URL": func(q string) template.URL { return template.URL(q) },
	}
	t, err := template.New("search.html").Funcs(funcMap).ParseFiles("templates/search.html", "templates/base.html")
	if err != nil {
		log.Panic(err)
	}
	// Render the template
	err = t.ExecuteTemplate(w, "base", map[string]interface{}{"Movies": m, "Books": g, "Albums": s.Albums})
	if err != nil {
		log.Panic(err)
	}
}

func main() {
	createDb()
	r := mux.NewRouter()
	r.HandleFunc("/", HomeHandler)
	r.HandleFunc("/search/{query}", SearchHandler)
	http.Handle("/", r)
	fmt.Println("Running on localhost:" + *port)

	log.Fatal(http.ListenAndServe(":"+*port, nil))
}
<commit_msg>add function to insert into db, add handler for saving entries<commit_after>package main

import (
	"database/sql"
	"flag"
	"fmt"
	"github.com/gorilla/mux"
	"github.com/kylelemons/go-gypsy/yaml"
	_ "github.com/mattn/go-sqlite3"
	"github.com/shawnps/gr"
	"github.com/shawnps/rt"
	"github.com/shawnps/sp"
	"html/template"
	"log"
	"net/http"
	"net/url"
	"strings"
	"sync"
)

var (
	port       = flag.String("p", "8000", "Port number (default 8000)")
	configFile = flag.String("c", "config.yml", "Config file (default config.yml)")
)

func getYAMLString(n yaml.Node, key string) string {
	return strings.TrimSpace(n.(yaml.Map)[key].(yaml.Scalar).String())
}

func parseYAML() (rtKey, grKey, grSecret string) {
	config, err := yaml.ReadFile(*configFile)
	if err != nil {
		log.Fatal(err)
	}
	configRoot, _ := config.Root.(yaml.Map)
	rtKey = configRoot["rt"].(yaml.Scalar).String()
	g := configRoot["gr"]
	grKey = getYAMLString(g, "key")
	grSecret = getYAMLString(g, "secret")

	return rtKey, grKey, grSecret
}

func createDb() {
	db, err := sql.Open("sqlite3", "./watchreadlisten.db")
	if err != nil {
		log.Println("Error opening or creating deploy_log.db: " + err.Error())
		return
	}
	defer db.Close()
	sql := `create table if not exists entries (id integer not null primary key autoincrement, title text, link text, media_type text, timestamp datetime default current_timestamp);`
	_, err = db.Exec(sql)
	if err != nil {
		log.Println("Error creating logs table: " + err.Error())
		return
	}
}

func insertEntry(db sql.DB, title, link, mediaType string) error {
	tx, err := db.Begin()
	if err != nil {
		log.Println("Error connecting to database: " + err.Error())
		return err
	}
	stmt, err := tx.Prepare("insert into entries(title, link, media_type) values(?, ?, ?)")
	if err != nil {
		log.Println("Error inserting to database: " + err.Error())
		return err
	}
	defer stmt.Close()
	_, err = stmt.Exec(title, link, mediaType)
	if err != nil {
		log.Println("Error executing statement on database: " + err.Error())
		return err
	}
	tx.Commit()
	return nil
}

// Search Rotten Tomatoes, Goodreads, and Spotify.
func Search(q string, rtClient rt.RottenTomatoes, grClient gr.Goodreads, spClient sp.Spotify) (m []rt.Movie, g gr.GoodreadsResponse, s sp.SearchAlbumsResponse) {
	var wg sync.WaitGroup
	wg.Add(3)
	go func(q string) {
		defer wg.Done()
		movies, err := rtClient.SearchMovies(q)
		if err != nil {
			fmt.Println("ERROR (rt): ", err.Error())
		}
		for _, mov := range movies {
			m = append(m, mov)
		}
	}(q)
	go func(q string) {
		defer wg.Done()
		books, err := grClient.SearchBooks(q)
		if err != nil {
			fmt.Println("ERROR (gr): ", err.Error())
		}
		g = books
	}(q)
	go func(q string) {
		defer wg.Done()
		albums, err := spClient.SearchAlbums(q)
		if err != nil {
			fmt.Println("ERROR (sp): ", err.Error())
		}
		s = albums
	}(q)
	wg.Wait()
	return m, g, s
}

func HomeHandler(w http.ResponseWriter, r *http.Request) {
	t, err := template.New("index.html").ParseFiles("templates/index.html", "templates/base.html")
	if err != nil {
		log.Panic(err)
	}
	// Render the template
	err = t.ExecuteTemplate(w, "base", nil)
	if err != nil {
		log.Panic(err)
	}
}

func SearchHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	q := vars["query"]
	q, err := url.QueryUnescape(q)
	if err != nil {
		log.Panic(err)
	}
	rtKey, grKey, grSecret := parseYAML()
	rtClient := rt.RottenTomatoes{rtKey}
	grClient := gr.Goodreads{grKey, grSecret}
	spClient := sp.Spotify{}
	m, g, s := Search(q, rtClient, grClient, spClient)
	// Since spotify: URIs are not trusted, have to pass a
	// URL function to the template to use in hrefs
	funcMap := template.FuncMap{
		"URL": func(q string) template.URL { return template.URL(q) },
	}
	t, err := template.New("search.html").Funcs(funcMap).ParseFiles("templates/search.html", "templates/base.html")
	if err != nil {
		log.Panic(err)
	}
	// Render the template
	err = t.ExecuteTemplate(w, "base", map[string]interface{}{"Movies": m, "Books": g, "Albums": s.Albums})
	if err != nil {
		log.Panic(err)
	}
}

func SaveHandler(w http.ResponseWriter, r *http.Request) {
	db, err := sql.Open("sqlite3", "./watchreadlisten.db")
	if err != nil {
		log.Println("Error opening sqlite db: " + err.Error())
		return
	}
	defer db.Close()
	t := r.FormValue("title")
	l := r.FormValue("link")
	m := r.FormValue("media_type")
	err = insertEntry(*db, t, l, m)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	http.Redirect(w, r, "/", http.StatusFound)
}

func main() {
	createDb()
	r := mux.NewRouter()
	r.HandleFunc("/", HomeHandler)
	r.HandleFunc("/search/{query}", SearchHandler)
	r.HandleFunc("/save", SaveHandler)
	http.Handle("/", r)
	fmt.Println("Running on localhost:" + *port)

	log.Fatal(http.ListenAndServe(":"+*port, nil))
}
<|endoftext|>


<commit_before>package main

/*
TODO: html display of data.
TODO: Setup scripts
TODO: README.md
TODO: Document.
TODO: Blog post
*/

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"os"

	"github.com/wselwood/gompcreader"
)

const maxDistance = 6.0
const gridSize int = int(maxDistance * 10)

var inputfile = flag.String("in", "", "the minor planet center file to read")
var outputDir = flag.String("out", "", "the output path to write the structure")

func outputGrid(dimentions []Dimension, resultTable [][]Grid) {
	for i := 0; i < NumDimentions; i++ {
		for j := 0; j < NumDimentions; j++ {
			path := fmt.Sprintf("%s/%s/%s/", *outputDir, dimentions[i].Name, dimentions[j].Name)
			os.MkdirAll(path, 0777)

			f, err := os.Create(fmt.Sprintf("%s/data.json", path))
			if err != nil {
				log.Fatal("Error opening datafile", err)
			}
			defer f.Close()
			f.WriteString("[")
			first := true

			var table = resultTable[i][j].G

			for x := 0; x < resultTable[i][j].SizeX; x++ {
				for y := 0; y < resultTable[i][j].SizeY; y++ {
					entry := table[x][y]
					if entry.Count > 0 || entry.Special != "" {
						if first {
							first = false
						} else {
							f.WriteString(",\n")
						}

						js, e := json.Marshal(entry)
						if e == nil {
							f.WriteString(fmt.Sprintf("%s", js))
						} else {
							log.Fatal("error json marshal", e)
						}
					}
				}
			}
			f.WriteString("]")
		}
	}
}

func createPathIfNeeded(path string) {
	os.MkdirAll(path, 0777)
}

func openOrCreateFile(path string) (*os.File, error) {
	_, err := os.Stat(path)
	if err != nil && os.IsNotExist(err) {
		// create the file.
		f, err := os.Create(path)
		f.WriteString("id\n")
		return f, err
	} else if err != nil {
		return nil, err
	}
	return os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0666)
}

func pathIsDir(path string) (bool, error) {
	pathStat, err := os.Stat(path)
	if err != nil && os.IsNotExist(err) {
		return false, nil
	} else if err != nil {
		return false, err
	}
	return pathStat.IsDir(), err
}

func main() {

	flag.Parse()

	if *inputfile == "" {
		log.Fatal("No input file provided. Use the -in /path/to/file")
	}

	if *outputDir == "" {
		log.Fatal("No output path provided Use -out /output/path")
	}

	exists, err := pathIsDir(*outputDir)
	if err != nil {
		log.Fatal("Could not check output path existance")
	} else if !exists {
		log.Fatal("Output path does not exist or is not a directory")
	}

	mpcReader, err := gompcreader.NewMpcReader(*inputfile)
	if err != nil {
		log.Fatal("error creating mpcReader ", err)
	}
	defer mpcReader.Close()

	var dimentions = BuildDimensions()
	var resultTable = BuildResultsGrid(dimentions[:])

	var count int64

	//var resultTable = newGrid()

	result, err := mpcReader.ReadEntry()

	for err == nil {

		for i := 0; i < NumDimentions; i++ {
			for j := 0; j < NumDimentions; j++ {

				x := dimentions[i].Extractor.ExtractCell(result)
				y := dimentions[j].Extractor.ExtractCell(result)
				if x > 0 && y > 0 {
					grid := resultTable[i][j].G

					//fmt.Printf("i:%2d, j:%2d, x:%3d, y:%3d, c:%d\n", i, j, x, y, count)

					grid[x][y].Count = grid[x][y].Count + 1

					if grid[x][y].X == 0 {
						grid[x][y].X = int(x)
						grid[x][y].Y = int(y)
						grid[x][y].StartX = dimentions[i].Extractor.Extract(result)
						grid[x][y].StartY = dimentions[j].Extractor.Extract(result)
					}
				}
			}
		}

		result, err = mpcReader.ReadEntry()
		count = count + 1
	}

	if err != nil && err != io.EOF {
		log.Fatal(fmt.Sprintf("error reading line %d\n", count), err)
	}

	outputGrid(dimentions[:], resultTable)
	RenderDimensions(*outputDir, dimentions[:])
}
<commit_msg>add debug option<commit_after>package main

/*
TODO: html display of data.
TODO: Setup scripts
TODO: README.md
TODO: Document.
TODO: Blog post
*/

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"os"

	"github.com/wselwood/gompcreader"
)

const maxDistance = 6.0
const gridSize int = int(maxDistance * 10)

var inputfile = flag.String("in", "", "the minor planet center file to read")
var outputDir = flag.String("out", "", "the output path to write the structure")
var debugMode = flag.Bool("debug", false, "add flag if you want extra debug logging. This has a big performance impact.")

func outputGrid(dimentions []Dimension, resultTable [][]Grid) {
	for i := 0; i < NumDimentions; i++ {
		for j := 0; j < NumDimentions; j++ {
			path := fmt.Sprintf("%s/%s/%s/", *outputDir, dimentions[i].Name, dimentions[j].Name)
			os.MkdirAll(path, 0777)

			f, err := os.Create(fmt.Sprintf("%s/data.json", path))
			if err != nil {
				log.Fatal("Error opening datafile", err)
			}
			defer f.Close()
			f.WriteString("[")
			first := true

			var table = resultTable[i][j].G

			for x := 0; x < resultTable[i][j].SizeX; x++ {
				for y := 0; y < resultTable[i][j].SizeY; y++ {
					entry := table[x][y]
					if entry.Count > 0 || entry.Special != "" {
						if first {
							first = false
						} else {
							f.WriteString(",\n")
						}

						js, e := json.Marshal(entry)
						if e == nil {
							f.WriteString(fmt.Sprintf("%s", js))
						} else {
							log.Fatal("error json marshal", e)
						}
					}
				}
			}
			f.WriteString("]")
		}
	}
}

func createPathIfNeeded(path string) {
	os.MkdirAll(path, 0777)
}

func openOrCreateFile(path string) (*os.File, error) {
	_, err := os.Stat(path)
	if err != nil && os.IsNotExist(err) {
		// create the file.
		f, err := os.Create(path)
		f.WriteString("id\n")
		return f, err
	} else if err != nil {
		return nil, err
	}
	return os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0666)
}

func pathIsDir(path string) (bool, error) {
	pathStat, err := os.Stat(path)
	if err != nil && os.IsNotExist(err) {
		return false, nil
	} else if err != nil {
		return false, err
	}
	return pathStat.IsDir(), err
}

func main() {

	flag.Parse()

	if *inputfile == "" {
		log.Fatal("No input file provided. Use the -in /path/to/file")
	}

	if *outputDir == "" {
		log.Fatal("No output path provided Use -out /output/path")
	}

	exists, err := pathIsDir(*outputDir)
	if err != nil {
		log.Fatal("Could not check output path existance")
	} else if !exists {
		log.Fatal("Output path does not exist or is not a directory")
	}

	mpcReader, err := gompcreader.NewMpcReader(*inputfile)
	if err != nil {
		log.Fatal("error creating mpcReader ", err)
	}
	defer mpcReader.Close()

	var dimentions = BuildDimensions()
	var resultTable = BuildResultsGrid(dimentions[:])

	var count int64

	//var resultTable = newGrid()

	result, err := mpcReader.ReadEntry()

	for err == nil {

		for i := 0; i < NumDimentions; i++ {
			for j := 0; j < NumDimentions; j++ {

				x := dimentions[i].Extractor.ExtractCell(result)
				y := dimentions[j].Extractor.ExtractCell(result)
				if x > 0 && y > 0 {
					grid := resultTable[i][j].G
					if *debugMode {
						fmt.Printf("i:%2d, j:%2d, x:%3d, y:%3d, c:%d\n", i, j, x, y, count)
					}
					grid[x][y].Count = grid[x][y].Count + 1

					if grid[x][y].X == 0 {
						grid[x][y].X = int(x)
						grid[x][y].Y = int(y)
						grid[x][y].StartX = dimentions[i].Extractor.Extract(result)
						grid[x][y].StartY = dimentions[j].Extractor.Extract(result)
					}
				}
			}
		}

		result, err = mpcReader.ReadEntry()
		count = count + 1
	}

	if err != nil && err != io.EOF {
		log.Fatal(fmt.Sprintf("error reading line %d\n", count), err)
	}

	outputGrid(dimentions[:], resultTable)
	RenderDimensions(*outputDir, dimentions[:])
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2017 Jon Carlson.  All rights reserved.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
//

package main

import (
	"bytes"
	"database/sql"
	"fmt"
	"github.com/joncrlsn/misc"
	"github.com/joncrlsn/pgutil"
	"sort"
	"text/template"
)

var (
	ownerSqlTemplate = initOwnerSqlTemplate()
)

// Initializes the Sql template
func initOwnerSqlTemplate() *template.Template {
	sql := `
SELECT n.nspname AS schema_name
    , {{if eq $.DbSchema "*" }}n.nspname || '.' || {{end}}c.relname || '.' || c.relname AS compare_name
    , c.relname AS relationship_name
    , a.rolname AS owner
    , CASE WHEN c.relkind = 'r' THEN 'TABLE'
        WHEN c.relkind = 'S' THEN 'SEQUENCE'
        WHEN c.relkind = 'v' THEN 'VIEW'
        ELSE c.relkind::varchar END AS type
FROM pg_class AS c
INNER JOIN pg_authid AS a ON (a.oid = c.relowner)
INNER JOIN pg_namespace AS n ON (n.oid = c.relnamespace)
WHERE c.relkind IN ('r', 'S', 'v')
{{if eq $.DbSchema "*" }}
AND n.nspname NOT LIKE 'pg_%'
AND n.nspname <> 'information_schema'
{{else}}
AND n.nspname = '{{$.DbSchema}}'
{{end}}
;`

	t := template.New("OwnerSqlTmpl")
	template.Must(t.Parse(sql))
	return t
}

// ==================================
// OwnerRows definition
// ==================================

// OwnerRows is a sortable slice of string maps
type OwnerRows []map[string]string

func (slice OwnerRows) Len() int {
	return len(slice)
}

func (slice OwnerRows) Less(i, j int) bool {
	return slice[i]["compare_name"] < slice[j]["compare_name"]
}

func (slice OwnerRows) Swap(i, j int) {
	slice[i], slice[j] = slice[j], slice[i]
}

// ==================================
// OwnerSchema definition
// (implements Schema -- defined in pgdiff.go)
// ==================================

// OwnerSchema holds a slice of rows from one of the databases as well as
// a reference to the current row of data we're viewing.
type OwnerSchema struct {
	rows   OwnerRows
	rowNum int
	done   bool
}

// get returns the value from the current row for the given key
func (c *OwnerSchema) get(key string) string {
	if c.rowNum >= len(c.rows) {
		return ""
	}
	return c.rows[c.rowNum][key]
}

// get returns the current row for the given key
func (c *OwnerSchema) getRow() map[string]string {
	if c.rowNum >= len(c.rows) {
		return make(map[string]string)
	}
	return c.rows[c.rowNum]
}

// NextRow increments the rowNum and tells you whether or not there are more
func (c *OwnerSchema) NextRow() bool {
	if c.rowNum >= len(c.rows)-1 {
		c.done = true
	}
	c.rowNum = c.rowNum + 1
	return !c.done
}

// Compare tells you, in one pass, whether or not the first row matches, is less than, or greater than the second row
func (c *OwnerSchema) Compare(obj interface{}) int {
	c2, ok := obj.(*OwnerSchema)
	if !ok {
		fmt.Println("Error!!!, Compare needs a OwnerSchema instance", c2)
		return +999
	}

	val := misc.CompareStrings(c.get("compare_name"), c2.get("compare_name"))
	return val
}

// Add generates SQL to add the table/view owner
func (c OwnerSchema) Add() {
	fmt.Printf("-- Notice!, db2 has no %s named %s.  First, run pgdiff with the %s option.\n", c.get("type"), c.get("relationship_name"), c.get("type"))
}

// Drop generates SQL to drop the owner
func (c OwnerSchema) Drop() {
	fmt.Printf("-- Notice!, db2 has a %s that db1 does not: %s.   First, run pgdiff with the %s option.\n", c.get("type"), c.get("relationship_name"), c.get("type"))
}

// Change handles the case where the relationship name matches, but the owner does not
func (c OwnerSchema) Change(obj interface{}) {
	c2, ok := obj.(*OwnerSchema)
	if !ok {
		fmt.Println("-- Error!!!, Change needs a OwnerSchema instance", c2)
	}

	if c.get("owner") != c2.get("owner") {
		fmt.Printf("ALTER %s %s.%s OWNER TO %s; \n", c.get("type"), c2.get("schema_name"), c.get("relationship_name"), c.get("owner"))
	}
}

// compareOwners compares the ownership of tables, sequences, and views between two databases or schemas
func compareOwners(conn1 *sql.DB, conn2 *sql.DB) {

	buf1 := new(bytes.Buffer)
	ownerSqlTemplate.Execute(buf1, dbInfo1)

	buf2 := new(bytes.Buffer)
	ownerSqlTemplate.Execute(buf2, dbInfo2)

	rowChan1, _ := pgutil.QueryStrings(conn1, buf1.String())
	rowChan2, _ := pgutil.QueryStrings(conn2, buf2.String())

	rows1 := make(OwnerRows, 0)
	for row := range rowChan1 {
		rows1 = append(rows1, row)
	}
	sort.Sort(rows1)

	rows2 := make(OwnerRows, 0)
	for row := range rowChan2 {
		rows2 = append(rows2, row)
	}
	sort.Sort(rows2)

	// We have to explicitly type this as Schema here for some unknown reason
	var schema1 Schema = &OwnerSchema{rows: rows1, rowNum: -1}
	var schema2 Schema = &OwnerSchema{rows: rows2, rowNum: -1}

	doDiff(schema1, schema2)
}
<commit_msg>Use pg_roles instead of pg_authid<commit_after>//
// Copyright (c) 2017 Jon Carlson.  All rights reserved.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
//

package main

import (
	"bytes"
	"database/sql"
	"fmt"
	"github.com/joncrlsn/misc"
	"github.com/joncrlsn/pgutil"
	"sort"
	"text/template"
)

var (
	ownerSqlTemplate = initOwnerSqlTemplate()
)

// Initializes the Sql template
func initOwnerSqlTemplate() *template.Template {
	sql := `
SELECT n.nspname AS schema_name
    , {{if eq $.DbSchema "*" }}n.nspname || '.' || {{end}}c.relname || '.' || c.relname AS compare_name
    , c.relname AS relationship_name
    , a.rolname AS owner
    , CASE WHEN c.relkind = 'r' THEN 'TABLE'
        WHEN c.relkind = 'S' THEN 'SEQUENCE'
        WHEN c.relkind = 'v' THEN 'VIEW'
        ELSE c.relkind::varchar END AS type
FROM pg_class AS c
INNER JOIN pg_roles AS a ON (a.oid = c.relowner)
INNER JOIN pg_namespace AS n ON (n.oid = c.relnamespace)
WHERE c.relkind IN ('r', 'S', 'v')
{{if eq $.DbSchema "*" }}
AND n.nspname NOT LIKE 'pg_%'
AND n.nspname <> 'information_schema'
{{else}}
AND n.nspname = '{{$.DbSchema}}'
{{end}}
;`

	t := template.New("OwnerSqlTmpl")
	template.Must(t.Parse(sql))
	return t
}

// ==================================
// OwnerRows definition
// ==================================

// OwnerRows is a sortable slice of string maps
type OwnerRows []map[string]string

func (slice OwnerRows) Len() int {
	return len(slice)
}

func (slice OwnerRows) Less(i, j int) bool {
	return slice[i]["compare_name"] < slice[j]["compare_name"]
}

func (slice OwnerRows) Swap(i, j int) {
	slice[i], slice[j] = slice[j], slice[i]
}

// ==================================
// OwnerSchema definition
// (implements Schema -- defined in pgdiff.go)
// ==================================

// OwnerSchema holds a slice of rows from one of the databases as well as
// a reference to the current row of data we're viewing.
type OwnerSchema struct {
	rows   OwnerRows
	rowNum int
	done   bool
}

// get returns the value from the current row for the given key
func (c *OwnerSchema) get(key string) string {
	if c.rowNum >= len(c.rows) {
		return ""
	}
	return c.rows[c.rowNum][key]
}

// get returns the current row for the given key
func (c *OwnerSchema) getRow() map[string]string {
	if c.rowNum >= len(c.rows) {
		return make(map[string]string)
	}
	return c.rows[c.rowNum]
}

// NextRow increments the rowNum and tells you whether or not there are more
func (c *OwnerSchema) NextRow() bool {
	if c.rowNum >= len(c.rows)-1 {
		c.done = true
	}
	c.rowNum = c.rowNum + 1
	return !c.done
}

// Compare tells you, in one pass, whether or not the first row matches, is less than, or greater than the second row
func (c *OwnerSchema) Compare(obj interface{}) int {
	c2, ok := obj.(*OwnerSchema)
	if !ok {
		fmt.Println("Error!!!, Compare needs a OwnerSchema instance", c2)
		return +999
	}

	val := misc.CompareStrings(c.get("compare_name"), c2.get("compare_name"))
	return val
}

// Add generates SQL to add the table/view owner
func (c OwnerSchema) Add() {
	fmt.Printf("-- Notice!, db2 has no %s named %s.  First, run pgdiff with the %s option.\n", c.get("type"), c.get("relationship_name"), c.get("type"))
}

// Drop generates SQL to drop the owner
func (c OwnerSchema) Drop() {
	fmt.Printf("-- Notice!, db2 has a %s that db1 does not: %s.   First, run pgdiff with the %s option.\n", c.get("type"), c.get("relationship_name"), c.get("type"))
}

// Change handles the case where the relationship name matches, but the owner does not
func (c OwnerSchema) Change(obj interface{}) {
	c2, ok := obj.(*OwnerSchema)
	if !ok {
		fmt.Println("-- Error!!!, Change needs a OwnerSchema instance", c2)
	}

	if c.get("owner") != c2.get("owner") {
		fmt.Printf("ALTER %s %s.%s OWNER TO %s; \n", c.get("type"), c2.get("schema_name"), c.get("relationship_name"), c.get("owner"))
	}
}

// compareOwners compares the ownership of tables, sequences, and views between two databases or schemas
func compareOwners(conn1 *sql.DB, conn2 *sql.DB) {

	buf1 := new(bytes.Buffer)
	ownerSqlTemplate.Execute(buf1, dbInfo1)

	buf2 := new(bytes.Buffer)
	ownerSqlTemplate.Execute(buf2, dbInfo2)

	rowChan1, _ := pgutil.QueryStrings(conn1, buf1.String())
	rowChan2, _ := pgutil.QueryStrings(conn2, buf2.String())

	rows1 := make(OwnerRows, 0)
	for row := range rowChan1 {
		rows1 = append(rows1, row)
	}
	sort.Sort(rows1)

	rows2 := make(OwnerRows, 0)
	for row := range rowChan2 {
		rows2 = append(rows2, row)
	}
	sort.Sort(rows2)

	// We have to explicitly type this as Schema here for some unknown reason
	var schema1 Schema = &OwnerSchema{rows: rows1, rowNum: -1}
	var schema2 Schema = &OwnerSchema{rows: rows2, rowNum: -1}

	doDiff(schema1, schema2)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"os"
	"path"
	"strconv"
	"time"
	//	"github.com/davecgh/go-spew/spew"
)

//RawImage contains data we got from API that needs to be modified before further usage
type RawImage struct {
	Imgid          int    `json:"id_number"`
	URL            string `json:"image"`
	Score          int    `json:"score"`
	OriginalFormat string `json:"original_format"`
	Faves          int    `json:"faves"`
}

//Image contains data needed to filter fetch and save image
type Image struct {
	Imgid    int
	URL      string
	Filename string
	Score    int
	Faves    int
}

//Search returns to us array of searched images...
type Search struct {
	Images []RawImage `json:"search"`
}

func (imgdata *Image) isDeepEqual(b Image) bool {
	if b.Imgid == imgdata.Imgid &&
		b.URL == imgdata.URL &&
		b.Filename == imgdata.Filename &&
		b.Score == imgdata.Score &&
		b.Faves == imgdata.Faves {
		return true
	}
	return false
}

//ImageCh is a channel of image data. You can put images into channel by parsing
//Derpibooru API by id(s) or  by tags and you can download images that are already
//in channel
type ImageCh chan Image

//Push gets unmarchalled JSON info, massages it and plugs it into channel so it
//would be processed in other places
func (imgchan ImageCh) push(dat RawImage) {

	tfn := strconv.Itoa(dat.Imgid) + "." + dat.OriginalFormat
	imgchan <- Image{
		Imgid:    dat.Imgid,
		Filename: tfn,
		URL:      prefix + "/" + path.Dir(dat.URL) + "/" + tfn,
		Score:    dat.Score,
		Faves:    dat.Faves,
	}
}

//ParseImg gets image IDs, fetches information about those images from Derpibooru and pushes them into the channel.
func (imgchan ImageCh) ParseImg(ids []int, key string) {

	for _, imgid := range ids {
		source := prefix + "//derpibooru.org/images/" + strconv.Itoa(imgid) + ".json"
		if key != "" {
			source = source + "?key=" + key
		}

		lInfo("Getting image info at:", source)

		body, err := getRemoteJSON(source)
		if err != nil {
			lErr(err)
			continue
		}
		var dat RawImage
		if err := json.Unmarshal(body, &dat); //transforming json into native map

		err != nil {
			lErr(err)
			continue
		}

		imgchan.push(dat)
	}

	close(imgchan) //closing channel, we are done here

	return
}

//DlImg reads image data from channel and downloads specified images to disc
func (imgchan ImageCh) downloadImages(opts *Config) {

	lInfo("Worker started; reading channel") //nice notification that we are not forgotten
	var n, size int
	for imgdata := range imgchan {

		if imgdata.Filename == "" {
			lErr("Empty filename. Oops?") //something somewhere had gone wrong, not a cause to die, going to the next image
			continue
		}

		lInfo("Saving as", imgdata.Filename)

		size += imgdata.saveImage(opts)
		n++
	}
	lInfof("Downloaded %d images, for a total of %s", n, fmtbytes(float64(size)))
}

func (imgdata Image) saveImage(opts *Config) (size int) { // To not hold all the files open when there is no need. All pointers to files are in the scope of this function.

	output, err := os.Create(opts.ImageDir + string(os.PathSeparator) + imgdata.Filename) //And now, THE FILE!
	if err != nil {
		lErr("Error when creating file for image: ", strconv.Itoa(imgdata.Imgid))
		lErr(err) //Either we got no permisson or no space, end of line
		return
	}
	defer func() {
		err = output.Close() //Not forgetting to deal with it after completing download
		if err != nil {
			lFatal("Could  not close downloaded file")
		}
	}()

	start := time.Now() //timing download time. We can't begin it sooner, not sure if we can begin it later

	body, header, err := getImage(imgdata.URL)

	if err != nil {
		lErr("Error when getting image: ", strconv.Itoa(imgdata.Imgid))
		lErr(err)
		return
	}

	size, err = output.Write(body) //
	if err != nil {
		lErr("Unable to write image on disk, id: ", strconv.Itoa(imgdata.Imgid))
		lErr(err)
		return
	}
	timed := time.Since(start).Seconds()

	lInfof("Downloaded %d bytes in %.2fs, speed %s/s\n", size, timed, fmtbytes(float64(size)/timed))

	sizestring, prs := header["Content-Length"]
	if !prs {
		lErr("Filesize not provided")
		return
	}

	expsize, err := strconv.Atoi(sizestring[0])
	if err != nil {
		lErr("Unable to get expected filesize")
		return
	}
	if expsize != size {
		lErr("Unable to download full image")
		return 0
	}
	return
}

//ParseTag gets image tags, fetches information about all images it could from Derpibooru and pushes them into the channel.
func (imgchan ImageCh) ParseTag(opts *TagOpts, key string) {

	//Unlike main, I don't see how I could separate bits out to decrease complexity
	source := prefix + "//derpibooru.org/search.json?q=" + opts.Tag //yay hardwiring url strings!

	if key != "" {
		source = source + "&key=" + key
	}

	lInfo("Searching as", source)

	for i := opts.StartPage; opts.StopPage == 0 || i <= opts.StopPage; i++ {
		lInfo("Searching page", i)

		body, err := getRemoteJSON(source + "&page=" + strconv.Itoa(i))
		if err != nil {
			lErr("Error while json from page ", i)
			lErr(err)
			continue
		}

		var dats Search                   //Because we got array incoming instead of single object, we using a slive of maps!
		err = json.Unmarshal(body, &dats) //transforming json into native view

		if err != nil {
			lErr("Error while parsing search page", i)
			lErr(err)
			if serr, ok := err.(*json.SyntaxError); ok { //In case crap was still given, we are looking at it.
				lErr("Occurred at offset: ", serr.Offset)
			}
			continue

		}

		if len(dats.Images) == 0 {
			lInfo("Pages are all over") //Does not mean that process is over.
			break
		} //exit due to finishing all pages

		for _, dat := range dats.Images {
			imgchan.push(dat)
		}

	}

	close(imgchan)
}
<commit_msg>Flattened execution pipeline - less passing of image channel<commit_after>package main

import (
	"encoding/json"
	"os"
	"path"
	"strconv"
	"time"
	//	"github.com/davecgh/go-spew/spew"
)

//RawImage contains data we got from API that needs to be modified before further usage
type RawImage struct {
	Imgid          int    `json:"id_number"`
	URL            string `json:"image"`
	Score          int    `json:"score"`
	OriginalFormat string `json:"original_format"`
	Faves          int    `json:"faves"`
}

//Image contains data needed to filter fetch and save image
type Image struct {
	Imgid    int
	URL      string
	Filename string
	Score    int
	Faves    int
}

//Search returns to us array of searched images...
type Search struct {
	Images []RawImage `json:"search"`
}

func (imgdata *Image) isDeepEqual(b Image) bool {
	if b.Imgid == imgdata.Imgid &&
		b.URL == imgdata.URL &&
		b.Filename == imgdata.Filename &&
		b.Score == imgdata.Score &&
		b.Faves == imgdata.Faves {
		return true
	}
	return false
}

//ImageCh is a channel of image data. You can put images into channel by parsing
//Derpibooru API by id(s) or  by tags and you can download images that are already
//in channel
type ImageCh chan Image

//Push gets unmarchalled JSON info, massages it and plugs it into channel so it
//would be processed in other places
func trim(dat RawImage) Image {

	tfn := strconv.Itoa(dat.Imgid) + "." + dat.OriginalFormat
	return Image{
		Imgid:    dat.Imgid,
		Filename: tfn,
		URL:      prefix + "/" + path.Dir(dat.URL) + "/" + tfn,
		Score:    dat.Score,
		Faves:    dat.Faves,
	}
}

//ParseImg gets image IDs, fetches information about those images from Derpibooru and pushes them into the channel.
func (imgchan ImageCh) ParseImg(ids []int, key string) {

	for _, imgid := range ids {
		source := prefix + "//derpibooru.org/images/" + strconv.Itoa(imgid) + ".json"
		if key != "" {
			source = source + "?key=" + key
		}

		lInfo("Getting image info at:", source)

		body, err := getRemoteJSON(source)
		if err != nil {
			lErr(err)
			continue
		}
		var dat RawImage
		if err := json.Unmarshal(body, &dat); //transforming json into native map

		err != nil {
			lErr(err)
			continue
		}

		imgchan <- trim(dat)
	}

	close(imgchan) //closing channel, we are done here

	return
}

//DlImg reads image data from channel and downloads specified images to disc
func (imgchan ImageCh) downloadImages(opts *Config) {

	lInfo("Worker started; reading channel") //nice notification that we are not forgotten
	var n, size int
	for imgdata := range imgchan {

		if imgdata.Filename == "" {
			lErr("Empty filename. Oops?") //something somewhere had gone wrong, not a cause to die, going to the next image
			continue
		}

		lInfo("Saving as", imgdata.Filename)

		size += imgdata.saveImage(opts)
		n++
	}
	lInfof("Downloaded %d images, for a total of %s", n, fmtbytes(float64(size)))
}

func (imgdata Image) saveImage(opts *Config) (size int) { // To not hold all the files open when there is no need. All pointers to files are in the scope of this function.

	output, err := os.Create(opts.ImageDir + string(os.PathSeparator) + imgdata.Filename) //And now, THE FILE!
	if err != nil {
		lErr("Error when creating file for image: ", strconv.Itoa(imgdata.Imgid))
		lErr(err) //Either we got no permisson or no space, end of line
		return
	}
	defer func() {
		err = output.Close() //Not forgetting to deal with it after completing download
		if err != nil {
			lFatal("Could  not close downloaded file")
		}
	}()

	start := time.Now() //timing download time. We can't begin it sooner, not sure if we can begin it later

	body, header, err := getImage(imgdata.URL)

	if err != nil {
		lErr("Error when getting image: ", strconv.Itoa(imgdata.Imgid))
		lErr(err)
		return
	}

	size, err = output.Write(body) //
	if err != nil {
		lErr("Unable to write image on disk, id: ", strconv.Itoa(imgdata.Imgid))
		lErr(err)
		return
	}
	timed := time.Since(start).Seconds()

	lInfof("Downloaded %d bytes in %.2fs, speed %s/s\n", size, timed, fmtbytes(float64(size)/timed))

	sizestring, prs := header["Content-Length"]
	if !prs {
		lErr("Filesize not provided")
		return
	}

	expsize, err := strconv.Atoi(sizestring[0])
	if err != nil {
		lErr("Unable to get expected filesize")
		return
	}
	if expsize != size {
		lErr("Unable to download full image")
		return 0
	}
	return
}

//ParseTag gets image tags, fetches information about all images it could from Derpibooru and pushes them into the channel.
func (imgchan ImageCh) ParseTag(opts *TagOpts, key string) {

	//Unlike main, I don't see how I could separate bits out to decrease complexity
	source := prefix + "//derpibooru.org/search.json?q=" + opts.Tag //yay hardwiring url strings!

	if key != "" {
		source = source + "&key=" + key
	}

	lInfo("Searching as", source)

	for i := opts.StartPage; opts.StopPage == 0 || i <= opts.StopPage; i++ {
		lInfo("Searching page", i)

		body, err := getRemoteJSON(source + "&page=" + strconv.Itoa(i))
		if err != nil {
			lErr("Error while json from page ", i)
			lErr(err)
			continue
		}

		var dats Search                   //Because we got array incoming instead of single object, we using a slive of maps!
		err = json.Unmarshal(body, &dats) //transforming json into native view

		if err != nil {
			lErr("Error while parsing search page", i)
			lErr(err)
			if serr, ok := err.(*json.SyntaxError); ok { //In case crap was still given, we are looking at it.
				lErr("Occurred at offset: ", serr.Offset)
			}
			continue

		}

		if len(dats.Images) == 0 {
			lInfo("Pages are all over") //Does not mean that process is over.
			break
		} //exit due to finishing all pages

		for _, dat := range dats.Images {
			imgchan <- trim(dat)
		}

	}

	close(imgchan)
}
<|endoftext|>


<commit_before>package main

import (
	"regexp"
	"strings"
)

var KEYS_LIST = regexp.MustCompile(`(?:[^,\\]|\\.)*`)

func ParseKeysList(list string) []string {
	keys := KEYS_LIST.FindAllString(list, -1)
	for i := 0; i < len(keys); i++ {
		keys[i] = strings.Replace(keys[i], `\,`, `,`, -1)
	}
	return keys
}
<commit_msg>Unescape escaped backslash<commit_after>package main

import (
	"regexp"
	"strings"
)

var KEYS_LIST = regexp.MustCompile(`(?:[^,\\]|\\.)*`)

func ParseKeysList(list string) []string {
	keys := KEYS_LIST.FindAllString(list, -1)
	for i := 0; i < len(keys); i++ {
		keys[i] = strings.Replace(keys[i], `\,`, `,`, -1)
		keys[i] = strings.Replace(keys[i], `\\`, `\`, -1)
	}
	return keys
}
<|endoftext|>


<commit_before>// Copyright 2016 fluter

package paste

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	urlparser "net/url"
	"regexp"
)

var NotSupported = errors.New("Not supported")

type replace struct {
	from, to string
}

// list of pastebins and substitutions for getting raw content
var pastebins map[string]interface{} = map[string]interface{}{
	"bpaste.net":   replace{"show", "raw"},
	"codepad.org":  "%s/raw.c",
	"dpaste.com":   "%s.txt",
	"ideone.com":   "/plain%s",
	"pastebin.com": "/raw%s",
	"pastie.org":   "/pastes%s/download",
	"sprunge.us":   "%s",
}

// Get the raw content of the paste given in url
// Returns the raw text and errors if any
func Get(url string) (string, error) {
	reader, err := GetReader(url)
	if err != nil {
		return "", err
	}

	if rc, ok := reader.(io.ReadCloser); ok {
		defer rc.Close()
	}
	body, err := ioutil.ReadAll(reader)
	if err != nil {
		return "", err
	}

	return string(body), nil
}

// Get a io.Reader for reading the paste
func GetReader(url string) (io.Reader, error) {
	var err error
	var u *urlparser.URL
	var newpath string
	var newurl string

	u, err = urlparser.Parse(url)
	if err != nil {
		return nil, err
	}

	sub, ok := pastebins[u.Host]
	if !ok {
		return nil, NotSupported
	}

	switch sub.(type) {
	case string:
		rep := sub.(string)
		newpath = fmt.Sprintf(rep, u.Path)
	case replace:
		rep := sub.(replace)
		re := regexp.MustCompile(rep.from)
		newpath = re.ReplaceAllString(u.Path, rep.to)
	default:
		return nil, NotSupported
	}
	u.Path = newpath
	newurl = u.String()

	var rsp *http.Response

	rsp, err = http.Get(newurl)
	if err != nil {
		return nil, err
	}

	if rsp.StatusCode != 200 {
		defer rsp.Body.Close()
		return nil, errors.New(rsp.Status)
	}

	return rsp.Body, nil
}

const Sprunge = "http://sprunge.us"

// Send text to paste.
// Returns the paste URL or error if any.
func Paste(text string) (string, error) {
	var err error
	var resp *http.Response
	var body []byte

	formData := urlparser.Values{"sprunge": {text}}

	resp, err = http.PostForm(Sprunge, formData)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return "", errors.New(resp.Status)
	}

	body, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	return string(bytes.TrimSpace(body)), nil
}
<commit_msg>add some more docs<commit_after>// Copyright 2016 fluter

package paste

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	urlparser "net/url"
	"regexp"
)

// The error to indicate getting paste from the site is
// not yet supported. Create an issue on github.com :)
var NotSupported = errors.New("Not supported")

type replace struct {
	from, to string
}

// list of pastebins and substitutions for getting raw content
var pastebins map[string]interface{} = map[string]interface{}{
	"bpaste.net":   replace{"show", "raw"},
	"codepad.org":  "%s/raw.c",
	"dpaste.com":   "%s.txt",
	"ideone.com":   "/plain%s",
	"pastebin.com": "/raw%s",
	"pastie.org":   "/pastes%s/download",
	"sprunge.us":   "%s",
}

// Get the raw content of the paste given in url
// Returns the raw text and errors if any
func Get(url string) (string, error) {
	reader, err := GetReader(url)
	if err != nil {
		return "", err
	}

	if rc, ok := reader.(io.ReadCloser); ok {
		defer rc.Close()
	}
	body, err := ioutil.ReadAll(reader)
	if err != nil {
		return "", err
	}

	return string(body), nil
}

// Get a io.Reader for reading the paste
func GetReader(url string) (io.Reader, error) {
	var err error
	var u *urlparser.URL
	var newpath string
	var newurl string

	u, err = urlparser.Parse(url)
	if err != nil {
		return nil, err
	}

	sub, ok := pastebins[u.Host]
	if !ok {
		return nil, NotSupported
	}

	switch sub.(type) {
	case string:
		rep := sub.(string)
		newpath = fmt.Sprintf(rep, u.Path)
	case replace:
		rep := sub.(replace)
		re := regexp.MustCompile(rep.from)
		newpath = re.ReplaceAllString(u.Path, rep.to)
	default:
		return nil, NotSupported
	}
	u.Path = newpath
	newurl = u.String()

	var rsp *http.Response

	rsp, err = http.Get(newurl)
	if err != nil {
		return nil, err
	}

	if rsp.StatusCode != 200 {
		defer rsp.Body.Close()
		return nil, errors.New(rsp.Status)
	}

	return rsp.Body, nil
}

const Sprunge = "http://sprunge.us"

// Send text to paste.
// Returns the paste URL or error if any.
func Paste(text string) (string, error) {
	var err error
	var resp *http.Response
	var body []byte

	formData := urlparser.Values{"sprunge": {text}}

	resp, err = http.PostForm(Sprunge, formData)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return "", errors.New(resp.Status)
	}

	body, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	return string(bytes.TrimSpace(body)), nil
}
<|endoftext|>


<commit_before>package net2

import (
	"testing"
)

func TestGetIP(t *testing.T) {
	if ips, err := GetIP("127.0.0.1"); err != nil || len(ips) != 1 || ips[0] != "127.0.0.1" {
		t.Fail()
	}

	if ips, err := GetIP("lo"); err != nil || ips[0] != "127.0.0.1" {
		t.Fail()
	}
}

func TestGetInterfaceByIP(t *testing.T) {
	if iface, err := GetInterfaceByIP("127.0.0.1"); err != nil || iface != "lo" {
		return t.Fail()
	}
}
<commit_msg>Fix a test error<commit_after>package net2

import (
	"testing"
)

func TestGetIP(t *testing.T) {
	if ips, err := GetIP("127.0.0.1"); err != nil || len(ips) != 1 || ips[0] != "127.0.0.1" {
		t.Fail()
	}

	if ips, err := GetIP("lo"); err != nil || ips[0] != "127.0.0.1" {
		t.Fail()
	}
}

func TestGetInterfaceByIP(t *testing.T) {
	if iface, err := GetInterfaceByIP("127.0.0.1"); err != nil || iface != "lo" {
		t.Fail()
	}
}
<|endoftext|>


<commit_before>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package state_test

import (
	stdtesting "testing"

	"github.com/juju/names"
	gitjujutesting "github.com/juju/testing"
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"
	"gopkg.in/mgo.v2"

	"github.com/juju/juju/state"
	statetesting "github.com/juju/juju/state/testing"
	"github.com/juju/juju/testing"
	"github.com/juju/juju/testing/factory"
)

// TestPackage integrates the tests into gotest.
func TestPackage(t *stdtesting.T) {
	testing.MgoTestPackage(t)
}

// ConnSuite provides the infrastructure for all other
// test suites (StateSuite, CharmSuite, MachineSuite, etc).
type ConnSuite struct {
	gitjujutesting.MgoSuite
	testing.BaseSuite
	annotations  *mgo.Collection
	charms       *mgo.Collection
	machines     *mgo.Collection
	relations    *mgo.Collection
	services     *mgo.Collection
	units        *mgo.Collection
	stateServers *mgo.Collection
	State        *state.State
	policy       statetesting.MockPolicy
	factory      *factory.Factory
	envTag       names.EnvironTag
	owner        names.UserTag
}

func (cs *ConnSuite) SetUpSuite(c *gc.C) {
	cs.BaseSuite.SetUpSuite(c)
	cs.MgoSuite.SetUpSuite(c)
}

func (cs *ConnSuite) TearDownSuite(c *gc.C) {
	cs.MgoSuite.TearDownSuite(c)
	cs.BaseSuite.TearDownSuite(c)
}

func (cs *ConnSuite) SetUpTest(c *gc.C) {
	c.Log("SetUpTest")
	cs.BaseSuite.SetUpTest(c)
	cs.MgoSuite.SetUpTest(c)
	cs.policy = statetesting.MockPolicy{}
	cfg := testing.EnvironConfig(c)
	cs.owner = names.NewLocalUserTag("test-admin")
	cs.State = TestingInitialize(c, cs.owner, cfg, &cs.policy)
	uuid, ok := cfg.UUID()
	c.Assert(ok, jc.IsTrue)
	cs.envTag = names.NewEnvironTag(uuid)
	cs.annotations = cs.MgoSuite.Session.DB("juju").C("annotations")
	cs.charms = cs.MgoSuite.Session.DB("juju").C("charms")
	cs.machines = cs.MgoSuite.Session.DB("juju").C("machines")
	cs.relations = cs.MgoSuite.Session.DB("juju").C("relations")
	cs.services = cs.MgoSuite.Session.DB("juju").C("services")
	cs.units = cs.MgoSuite.Session.DB("juju").C("units")
	cs.stateServers = cs.MgoSuite.Session.DB("juju").C("stateServers")
	cs.factory = factory.NewFactory(cs.State)
	c.Log("SetUpTest done")
}

func (cs *ConnSuite) TearDownTest(c *gc.C) {
	if cs.State != nil {
		// If setup fails, we don't have a State yet
		cs.State.Close()
	}
	cs.MgoSuite.TearDownTest(c)
	cs.BaseSuite.TearDownTest(c)
}

func (s *ConnSuite) AddTestingCharm(c *gc.C, name string) *state.Charm {
	return state.AddTestingCharm(c, s.State, name)
}

func (s *ConnSuite) AddTestingService(c *gc.C, name string, ch *state.Charm) *state.Service {
	return state.AddTestingService(c, s.State, name, ch, s.owner)
}

func (s *ConnSuite) AddTestingServiceWithNetworks(c *gc.C, name string, ch *state.Charm, networks []string) *state.Service {
	return state.AddTestingServiceWithNetworks(c, s.State, name, ch, s.owner, networks)
}

func (s *ConnSuite) AddSeriesCharm(c *gc.C, name, series string) *state.Charm {
	return state.AddCustomCharm(c, s.State, name, "", "", series, -1)
}

// AddConfigCharm clones a testing charm, replaces its config with
// the given YAML string and adds it to the state, using the given
// revision.
func (s *ConnSuite) AddConfigCharm(c *gc.C, name, configYaml string, revision int) *state.Charm {
	return state.AddCustomCharm(c, s.State, name, "config.yaml", configYaml, "quantal", revision)
}

// AddActionsCharm clones a testing charm, replaces its actions schema with
// the given YAML, and adds it to the state, using the given revision.
func (s *ConnSuite) AddActionsCharm(c *gc.C, name, actionsYaml string, revision int) *state.Charm {
	return state.AddCustomCharm(c, s.State, name, "actions.yaml", actionsYaml, "quantal", revision)
}

// AddMetaCharm clones a testing charm, replaces its metadata with the
// given YAML string and adds it to the state, using the given revision.
func (s *ConnSuite) AddMetaCharm(c *gc.C, name, metaYaml string, revsion int) *state.Charm {
	return state.AddCustomCharm(c, s.State, name, "metadata.yaml", metaYaml, "quantal", revsion)
}
<commit_msg>Added instanceData to ConnSuite setup<commit_after>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package state_test

import (
	stdtesting "testing"

	"github.com/juju/names"
	gitjujutesting "github.com/juju/testing"
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"
	"gopkg.in/mgo.v2"

	"github.com/juju/juju/state"
	statetesting "github.com/juju/juju/state/testing"
	"github.com/juju/juju/testing"
	"github.com/juju/juju/testing/factory"
)

// TestPackage integrates the tests into gotest.
func TestPackage(t *stdtesting.T) {
	testing.MgoTestPackage(t)
}

// ConnSuite provides the infrastructure for all other
// test suites (StateSuite, CharmSuite, MachineSuite, etc).
type ConnSuite struct {
	gitjujutesting.MgoSuite
	testing.BaseSuite
	annotations  *mgo.Collection
	charms       *mgo.Collection
	machines     *mgo.Collection
	instanceData *mgo.Collection
	relations    *mgo.Collection
	services     *mgo.Collection
	units        *mgo.Collection
	stateServers *mgo.Collection
	State        *state.State
	policy       statetesting.MockPolicy
	factory      *factory.Factory
	envTag       names.EnvironTag
	owner        names.UserTag
}

func (cs *ConnSuite) SetUpSuite(c *gc.C) {
	cs.BaseSuite.SetUpSuite(c)
	cs.MgoSuite.SetUpSuite(c)
}

func (cs *ConnSuite) TearDownSuite(c *gc.C) {
	cs.MgoSuite.TearDownSuite(c)
	cs.BaseSuite.TearDownSuite(c)
}

func (cs *ConnSuite) SetUpTest(c *gc.C) {
	c.Log("SetUpTest")
	cs.BaseSuite.SetUpTest(c)
	cs.MgoSuite.SetUpTest(c)
	cs.policy = statetesting.MockPolicy{}
	cfg := testing.EnvironConfig(c)
	cs.owner = names.NewLocalUserTag("test-admin")
	cs.State = TestingInitialize(c, cs.owner, cfg, &cs.policy)
	uuid, ok := cfg.UUID()
	c.Assert(ok, jc.IsTrue)
	cs.envTag = names.NewEnvironTag(uuid)
	cs.factory = factory.NewFactory(cs.State)

	jujuDB := cs.MgoSuite.Session.DB("juju")
	cs.annotations = jujuDB.C("annotations")
	cs.charms = jujuDB.C("charms")
	cs.machines = jujuDB.C("machines")
	cs.instanceData = jujuDB.C("instanceData")
	cs.relations = jujuDB.C("relations")
	cs.services = jujuDB.C("services")
	cs.units = jujuDB.C("units")
	cs.stateServers = jujuDB.C("stateServers")

	c.Log("SetUpTest done")
}

func (cs *ConnSuite) TearDownTest(c *gc.C) {
	if cs.State != nil {
		// If setup fails, we don't have a State yet
		cs.State.Close()
	}
	cs.MgoSuite.TearDownTest(c)
	cs.BaseSuite.TearDownTest(c)
}

func (s *ConnSuite) AddTestingCharm(c *gc.C, name string) *state.Charm {
	return state.AddTestingCharm(c, s.State, name)
}

func (s *ConnSuite) AddTestingService(c *gc.C, name string, ch *state.Charm) *state.Service {
	return state.AddTestingService(c, s.State, name, ch, s.owner)
}

func (s *ConnSuite) AddTestingServiceWithNetworks(c *gc.C, name string, ch *state.Charm, networks []string) *state.Service {
	return state.AddTestingServiceWithNetworks(c, s.State, name, ch, s.owner, networks)
}

func (s *ConnSuite) AddSeriesCharm(c *gc.C, name, series string) *state.Charm {
	return state.AddCustomCharm(c, s.State, name, "", "", series, -1)
}

// AddConfigCharm clones a testing charm, replaces its config with
// the given YAML string and adds it to the state, using the given
// revision.
func (s *ConnSuite) AddConfigCharm(c *gc.C, name, configYaml string, revision int) *state.Charm {
	return state.AddCustomCharm(c, s.State, name, "config.yaml", configYaml, "quantal", revision)
}

// AddActionsCharm clones a testing charm, replaces its actions schema with
// the given YAML, and adds it to the state, using the given revision.
func (s *ConnSuite) AddActionsCharm(c *gc.C, name, actionsYaml string, revision int) *state.Charm {
	return state.AddCustomCharm(c, s.State, name, "actions.yaml", actionsYaml, "quantal", revision)
}

// AddMetaCharm clones a testing charm, replaces its metadata with the
// given YAML string and adds it to the state, using the given revision.
func (s *ConnSuite) AddMetaCharm(c *gc.C, name, metaYaml string, revsion int) *state.Charm {
	return state.AddCustomCharm(c, s.State, name, "metadata.yaml", metaYaml, "quantal", revsion)
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package cli

import (
	"os"
	"sort"
	"strings"

	"github.com/spf13/cobra"
	"mynewt.apache.org/newt/newt/downloader"
	"mynewt.apache.org/newt/newt/interfaces"
	"mynewt.apache.org/newt/newt/newtutil"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/newt/repo"
	"mynewt.apache.org/newt/util"
)

func newRunCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		NewtUsage(cmd, util.NewNewtError("Must specify "+
			"a project directory to newt new"))
	}

	newDir := args[0]

	if util.NodeExist(newDir) {
		NewtUsage(cmd, util.NewNewtError("Cannot create new project, "+
			"directory already exists"))
	}

	util.StatusMessage(util.VERBOSITY_DEFAULT, "Downloading "+
		"project skeleton from apache/mynewt-blinky...\n")
	dl := downloader.NewGithubDownloader()
	dl.User = "apache"
	dl.Repo = "mynewt-blinky"

	tmpdir, err := newtutil.MakeTempRepoDir()
	if err != nil {
		NewtUsage(nil, err)
	}
	defer os.RemoveAll(tmpdir)

	if err := dl.Clone(newtutil.NewtBlinkyTag, tmpdir); err != nil {
		NewtUsage(nil, err)
	}

	util.StatusMessage(util.VERBOSITY_DEFAULT, "Installing "+
		"skeleton in %s...\n", newDir)

	if err := util.CopyDir(tmpdir, newDir); err != nil {
		NewtUsage(cmd, err)
	}

	if err := os.RemoveAll(newDir + "/" + "/.git/"); err != nil {
		NewtUsage(cmd, err)
	}

	util.StatusMessage(util.VERBOSITY_DEFAULT,
		"Project %s successfully created.\n", newDir)
}

// Builds a repo selection predicate based on the specified names.  If no names
// are specified, the resulting function selects all non-local repos.
// Otherwise, the function selects each non-local repo whose name is specified.
func makeRepoPredicate(repoNames []string) func(r *repo.Repo) bool {
	// If the user didn't specify any repo names, apply the operation to all
	// repos in `project.yml`.
	if len(repoNames) == 0 {
		proj := project.GetProject()
		return func(r *repo.Repo) bool { return proj.RepoIsRoot(r.Name()) }
	}

	return func(r *repo.Repo) bool {
		if !r.IsLocal() {
			for _, arg := range repoNames {
				if r.Name() == arg {
					return true
				}
			}
		}
		return false
	}
}

func installRunCmd(cmd *cobra.Command, args []string) {
	proj := TryGetProject()
	interfaces.SetProject(proj)

	pred := makeRepoPredicate(args)
	if err := proj.InstallIf(
		false, newtutil.NewtForce, newtutil.NewtAsk, pred); err != nil {

		NewtUsage(nil, err)
	}
}

func upgradeRunCmd(cmd *cobra.Command, args []string) {
	proj := TryGetProject()
	interfaces.SetProject(proj)

	pred := makeRepoPredicate(args)
	if err := proj.InstallIf(
		true, newtutil.NewtForce, newtutil.NewtAsk, pred); err != nil {

		NewtUsage(nil, err)
	}
}

func infoRunCmd(cmd *cobra.Command, args []string) {
	reqRepoName := ""
	if len(args) >= 1 {
		reqRepoName = strings.TrimPrefix(args[0], "@")
	}

	proj := TryGetProject()

	repoNames := []string{}
	for repoName, _ := range proj.PackageList() {
		repoNames = append(repoNames, repoName)
	}
	sort.Strings(repoNames)

	if reqRepoName == "" {
		util.StatusMessage(util.VERBOSITY_DEFAULT, "Repositories in %s:\n",
			proj.Name())

		for _, repoName := range repoNames {
			util.StatusMessage(util.VERBOSITY_DEFAULT, "    * @%s\n", repoName)
		}

		// Now display the packages in the local repository.
		util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
		reqRepoName = "local"
	}

	firstRepo := true
	for _, repoName := range repoNames {
		if reqRepoName == "all" || reqRepoName == repoName {
			packNames := []string{}
			for _, pack := range *proj.PackageList()[repoName] {
				// Don't display the special unittest target; this is used
				// internally by newt, so the user doesn't need to know about
				// it.
				// XXX: This is a hack; come up with a better solution for
				// unit testing.
				if !strings.HasSuffix(pack.Name(), "/unittest") {
					packNames = append(packNames, pack.Name())
				}
			}

			sort.Strings(packNames)
			if !firstRepo {
				util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
			} else {
				firstRepo = false
			}
			util.StatusMessage(util.VERBOSITY_DEFAULT, "Packages in @%s:\n",
				repoName)
			for _, pkgName := range packNames {
				util.StatusMessage(util.VERBOSITY_DEFAULT, "    * %s\n",
					pkgName)
			}
		}
	}
}

func syncRunCmd(cmd *cobra.Command, args []string) {
	proj := TryGetProject()
	pred := makeRepoPredicate(args)

	if err := proj.SyncIf(
		newtutil.NewtForce, newtutil.NewtAsk, pred); err != nil {

		NewtUsage(nil, err)
	}
}

func AddProjectCommands(cmd *cobra.Command) {
	installHelpText := ""
	installHelpEx := "  newt install\n"
	installHelpEx += "    Installs all repositories specified in project.yml.\n\n"
	installHelpEx += "  newt install apache-mynewt-core\n"
	installHelpEx += "    Installs the apache-mynewt-core repository."
	installCmd := &cobra.Command{
		Use:     "install [repo-1] [repo-2] [...]",
		Short:   "Install project dependencies",
		Long:    installHelpText,
		Example: installHelpEx,
		Run:     installRunCmd,
	}
	installCmd.PersistentFlags().BoolVarP(&newtutil.NewtForce,
		"force", "f", false,
		"Force install of the repositories in project, regardless of what "+
			"exists in repos directory")
	installCmd.PersistentFlags().BoolVarP(&newtutil.NewtAsk,
		"ask", "a", false, "Prompt user before installing any repos")

	cmd.AddCommand(installCmd)

	upgradeHelpText := ""
	upgradeHelpEx := "  newt upgrade\n"
	upgradeHelpEx += "    Upgrades all repositories specified in project.yml.\n\n"
	upgradeHelpEx += "  newt upgrade apache-mynewt-core\n"
	upgradeHelpEx += "    Upgrades the apache-mynewt-core repository."
	upgradeCmd := &cobra.Command{
		Use:     "upgrade [repo-1] [repo-2] [...]",
		Short:   "Upgrade project dependencies",
		Long:    upgradeHelpText,
		Example: upgradeHelpEx,
		Run:     upgradeRunCmd,
	}
	upgradeCmd.PersistentFlags().BoolVarP(&newtutil.NewtForce,
		"force", "f", false,
		"Force upgrade of the repositories to latest state in project.yml")
	upgradeCmd.PersistentFlags().BoolVarP(&newtutil.NewtAsk,
		"ask", "a", false, "Prompt user before upgrading any repos")

	cmd.AddCommand(upgradeCmd)

	syncHelpText := ""
	syncHelpEx := "  newt sync\n"
	syncHelpEx += "    Syncs all repositories specified in project.yml.\n\n"
	syncHelpEx += "  newt sync apache-mynewt-core\n"
	syncHelpEx += "    Syncs the apache-mynewt-core repository."
	syncCmd := &cobra.Command{
		Use:     "sync [repo-1] [repo-2] [...]",
		Short:   "Synchronize project dependencies",
		Long:    syncHelpText,
		Example: syncHelpEx,
		Run:     syncRunCmd,
	}
	syncCmd.PersistentFlags().BoolVarP(&newtutil.NewtForce,
		"force", "f", false,
		"Force overwrite of existing remote repositories.")
	syncCmd.PersistentFlags().BoolVarP(&newtutil.NewtAsk,
		"ask", "a", false, "Prompt user before syncing any repos")
	cmd.AddCommand(syncCmd)

	newHelpText := ""
	newHelpEx := ""
	newCmd := &cobra.Command{
		Use:     "new <project-dir>",
		Short:   "Create a new project",
		Long:    newHelpText,
		Example: newHelpEx,
		Run:     newRunCmd,
	}

	cmd.AddCommand(newCmd)

	infoHelpText := "Show information about the current project."
	infoHelpEx := "  newt info\n"

	infoCmd := &cobra.Command{
		Use:     "info",
		Short:   "Show project info",
		Long:    infoHelpText,
		Example: infoHelpEx,
		Run:     infoRunCmd,
	}

	cmd.AddCommand(infoCmd)
}
<commit_msg>Allow "@" in install / upgrade / sync arguments<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package cli

import (
	"os"
	"sort"
	"strings"

	"github.com/spf13/cobra"
	"mynewt.apache.org/newt/newt/downloader"
	"mynewt.apache.org/newt/newt/interfaces"
	"mynewt.apache.org/newt/newt/newtutil"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/newt/repo"
	"mynewt.apache.org/newt/util"
)

func newRunCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		NewtUsage(cmd, util.NewNewtError("Must specify "+
			"a project directory to newt new"))
	}

	newDir := args[0]

	if util.NodeExist(newDir) {
		NewtUsage(cmd, util.NewNewtError("Cannot create new project, "+
			"directory already exists"))
	}

	util.StatusMessage(util.VERBOSITY_DEFAULT, "Downloading "+
		"project skeleton from apache/mynewt-blinky...\n")
	dl := downloader.NewGithubDownloader()
	dl.User = "apache"
	dl.Repo = "mynewt-blinky"

	tmpdir, err := newtutil.MakeTempRepoDir()
	if err != nil {
		NewtUsage(nil, err)
	}
	defer os.RemoveAll(tmpdir)

	if err := dl.Clone(newtutil.NewtBlinkyTag, tmpdir); err != nil {
		NewtUsage(nil, err)
	}

	util.StatusMessage(util.VERBOSITY_DEFAULT, "Installing "+
		"skeleton in %s...\n", newDir)

	if err := util.CopyDir(tmpdir, newDir); err != nil {
		NewtUsage(cmd, err)
	}

	if err := os.RemoveAll(newDir + "/" + "/.git/"); err != nil {
		NewtUsage(cmd, err)
	}

	util.StatusMessage(util.VERBOSITY_DEFAULT,
		"Project %s successfully created.\n", newDir)
}

// Builds a repo selection predicate based on the specified names.  If no names
// are specified, the resulting function selects all non-local repos.
// Otherwise, the function selects each non-local repo whose name is specified.
func makeRepoPredicate(repoNames []string) func(r *repo.Repo) bool {
	// If the user didn't specify any repo names, apply the operation to all
	// repos in `project.yml`.
	if len(repoNames) == 0 {
		proj := project.GetProject()
		return func(r *repo.Repo) bool { return proj.RepoIsRoot(r.Name()) }
	}

	return func(r *repo.Repo) bool {
		if !r.IsLocal() {
			for _, arg := range repoNames {
				if strings.TrimPrefix(r.Name(), "@") == arg {
					return true
				}
			}
		}
		return false
	}
}

func installRunCmd(cmd *cobra.Command, args []string) {
	proj := TryGetProject()
	interfaces.SetProject(proj)

	pred := makeRepoPredicate(args)
	if err := proj.InstallIf(
		false, newtutil.NewtForce, newtutil.NewtAsk, pred); err != nil {

		NewtUsage(nil, err)
	}
}

func upgradeRunCmd(cmd *cobra.Command, args []string) {
	proj := TryGetProject()
	interfaces.SetProject(proj)

	pred := makeRepoPredicate(args)
	if err := proj.InstallIf(
		true, newtutil.NewtForce, newtutil.NewtAsk, pred); err != nil {

		NewtUsage(nil, err)
	}
}

func infoRunCmd(cmd *cobra.Command, args []string) {
	reqRepoName := ""
	if len(args) >= 1 {
		reqRepoName = strings.TrimPrefix(args[0], "@")
	}

	proj := TryGetProject()

	repoNames := []string{}
	for repoName, _ := range proj.PackageList() {
		repoNames = append(repoNames, repoName)
	}
	sort.Strings(repoNames)

	if reqRepoName == "" {
		util.StatusMessage(util.VERBOSITY_DEFAULT, "Repositories in %s:\n",
			proj.Name())

		for _, repoName := range repoNames {
			util.StatusMessage(util.VERBOSITY_DEFAULT, "    * @%s\n", repoName)
		}

		// Now display the packages in the local repository.
		util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
		reqRepoName = "local"
	}

	firstRepo := true
	for _, repoName := range repoNames {
		if reqRepoName == "all" || reqRepoName == repoName {
			packNames := []string{}
			for _, pack := range *proj.PackageList()[repoName] {
				// Don't display the special unittest target; this is used
				// internally by newt, so the user doesn't need to know about
				// it.
				// XXX: This is a hack; come up with a better solution for
				// unit testing.
				if !strings.HasSuffix(pack.Name(), "/unittest") {
					packNames = append(packNames, pack.Name())
				}
			}

			sort.Strings(packNames)
			if !firstRepo {
				util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
			} else {
				firstRepo = false
			}
			util.StatusMessage(util.VERBOSITY_DEFAULT, "Packages in @%s:\n",
				repoName)
			for _, pkgName := range packNames {
				util.StatusMessage(util.VERBOSITY_DEFAULT, "    * %s\n",
					pkgName)
			}
		}
	}
}

func syncRunCmd(cmd *cobra.Command, args []string) {
	proj := TryGetProject()
	pred := makeRepoPredicate(args)

	if err := proj.SyncIf(
		newtutil.NewtForce, newtutil.NewtAsk, pred); err != nil {

		NewtUsage(nil, err)
	}
}

func AddProjectCommands(cmd *cobra.Command) {
	installHelpText := ""
	installHelpEx := "  newt install\n"
	installHelpEx += "    Installs all repositories specified in project.yml.\n\n"
	installHelpEx += "  newt install apache-mynewt-core\n"
	installHelpEx += "    Installs the apache-mynewt-core repository."
	installCmd := &cobra.Command{
		Use:     "install [repo-1] [repo-2] [...]",
		Short:   "Install project dependencies",
		Long:    installHelpText,
		Example: installHelpEx,
		Run:     installRunCmd,
	}
	installCmd.PersistentFlags().BoolVarP(&newtutil.NewtForce,
		"force", "f", false,
		"Force install of the repositories in project, regardless of what "+
			"exists in repos directory")
	installCmd.PersistentFlags().BoolVarP(&newtutil.NewtAsk,
		"ask", "a", false, "Prompt user before installing any repos")

	cmd.AddCommand(installCmd)

	upgradeHelpText := ""
	upgradeHelpEx := "  newt upgrade\n"
	upgradeHelpEx += "    Upgrades all repositories specified in project.yml.\n\n"
	upgradeHelpEx += "  newt upgrade apache-mynewt-core\n"
	upgradeHelpEx += "    Upgrades the apache-mynewt-core repository."
	upgradeCmd := &cobra.Command{
		Use:     "upgrade [repo-1] [repo-2] [...]",
		Short:   "Upgrade project dependencies",
		Long:    upgradeHelpText,
		Example: upgradeHelpEx,
		Run:     upgradeRunCmd,
	}
	upgradeCmd.PersistentFlags().BoolVarP(&newtutil.NewtForce,
		"force", "f", false,
		"Force upgrade of the repositories to latest state in project.yml")
	upgradeCmd.PersistentFlags().BoolVarP(&newtutil.NewtAsk,
		"ask", "a", false, "Prompt user before upgrading any repos")

	cmd.AddCommand(upgradeCmd)

	syncHelpText := ""
	syncHelpEx := "  newt sync\n"
	syncHelpEx += "    Syncs all repositories specified in project.yml.\n\n"
	syncHelpEx += "  newt sync apache-mynewt-core\n"
	syncHelpEx += "    Syncs the apache-mynewt-core repository."
	syncCmd := &cobra.Command{
		Use:     "sync [repo-1] [repo-2] [...]",
		Short:   "Synchronize project dependencies",
		Long:    syncHelpText,
		Example: syncHelpEx,
		Run:     syncRunCmd,
	}
	syncCmd.PersistentFlags().BoolVarP(&newtutil.NewtForce,
		"force", "f", false,
		"Force overwrite of existing remote repositories.")
	syncCmd.PersistentFlags().BoolVarP(&newtutil.NewtAsk,
		"ask", "a", false, "Prompt user before syncing any repos")
	cmd.AddCommand(syncCmd)

	newHelpText := ""
	newHelpEx := ""
	newCmd := &cobra.Command{
		Use:     "new <project-dir>",
		Short:   "Create a new project",
		Long:    newHelpText,
		Example: newHelpEx,
		Run:     newRunCmd,
	}

	cmd.AddCommand(newCmd)

	infoHelpText := "Show information about the current project."
	infoHelpEx := "  newt info\n"

	infoCmd := &cobra.Command{
		Use:     "info",
		Short:   "Show project info",
		Long:    infoHelpText,
		Example: infoHelpEx,
		Run:     infoRunCmd,
	}

	cmd.AddCommand(infoCmd)
}
<|endoftext|>


<commit_before>package telsh

import (
	"testing"
)

func TestServeTELNET(t *testing.T) {
t.Errorf("TODO")
}
<commit_msg>added tests<commit_after>package telsh

import (
	"bytes"
	"strings"

	"testing"
)

func TestServeTELNETCommandNotFound(t *testing.T) {

	tests := []struct{
		ClientSends string
		Expected   string
	}{
		{
			ClientSends: "\r\n",
			Expected: "",
		},

		{
			ClientSends: "apple\r\n",
			Expected:    "apple: command not found\r\n",
		},
		{
			ClientSends: "banana\r\n",
			Expected:    "banana: command not found\r\n",
		},
		{
			ClientSends: "cherry\r\n",
			Expected:    "cherry: command not found\r\n",
		},

		{
			ClientSends: "\t\r\n",
			Expected: "",
		},
		{
			ClientSends: "\t\t\r\n",
			Expected: "",
		},
		{
			ClientSends: "\t\t\t\r\n",
			Expected: "",
		},

		{
			ClientSends: " \r\n",
			Expected: "",
		},
		{
			ClientSends: "  \r\n",
			Expected: "",
		},
		{
			ClientSends: "   \r\n",
			Expected: "",
		},

		{
			ClientSends: " \t\r\n",
			Expected: "",
		},
		{
			ClientSends: "\t \r\n",
			Expected: "",
		},

		{
			ClientSends: "ls -alF\r\n",
			Expected:    "ls: command not found\r\n",
		},
	}

	for testNumber, test := range tests {

		shellHandler := NewShellHandler()
		if nil == shellHandler {
			t.Errorf("For test #%d, did not expect to get nil, but actually got it: %v; for client sent: %q", testNumber, shellHandler, test.ClientSends)
			continue
		}

		var ctx Context

		var buffer bytes.Buffer

		shellHandler.ServeTELNET(ctx, &buffer, strings.NewReader(test.ClientSends))

		if expected, actual := shellHandler.WelcomeMessage+shellHandler.Prompt+test.Expected+shellHandler.Prompt+shellHandler.ExitMessage, buffer.String(); expected != actual {
			t.Errorf("For test #%d, expect %q, but actually got %q; for client sent: %q", testNumber, expected, actual, test.ClientSends)
			continue
		}
	}
}
<|endoftext|>


<commit_before><commit_msg>path: sync code with httprouter (#2212)<commit_after><|endoftext|>


<commit_before>package connectors

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"regexp"
	"strings"

	"github.com/projectjane/jane/models"
)

type Jira struct {
}

func (x Jira) Listen(commandMsgs chan<- models.Message, connector models.Connector) {
	return
}

func (x Jira) Command(message models.Message, publishMsgs chan<- models.Message, connector models.Connector) {
	if strings.HasPrefix(strings.ToLower(message.In.Text), strings.ToLower("jira create")) {
		createJiraIssue(message, publishMsgs, connector)
	} else {
		parseJiraIssue(message, publishMsgs, connector)
	}
}

func (x Jira) Publish(connector models.Connector, message models.Message, target string) {
	return
}

func (x Jira) Help(connector models.Connector) (help string) {
	help += "jira {key-number}\n"
	help += "jira create {issueType} {project key} {summary}\n"
	return help
}

type ticket struct {
	Key    string `json:"key"`
	Fields fields `json:"fields"`
}

type fields struct {
	Summary     string   `json:"summary"`
	Status      status   `json:"status"`
	Description string   `json:"description"`
	Priority    priority `json:"priority"`
	Assignee    assignee `json:"assignee"`
}

type status struct {
	Description string `json:"description"`
	Name        string `json:"name"`
}

type priority struct {
	Name string `json:"name"`
}

type assignee struct {
	DisplayName string `json:"displayName"`
}

type createObject struct {
	Fields createFields `json:"fields"`
}

type createFields struct {
	Project   project   `json:"project"`
	Summary   string    `json:"summary"`
	IssueType issueType `json:"issueType"`
}

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

type issueType struct {
	Name string `json:"name"`
}

type createdIssue struct {
	Id   string `json:"id"`
	Key  string `json:"key"`
	Self string `json:"self"`
}

func createJiraIssue(message models.Message, publishMsgs chan<- models.Message, connector models.Connector) {
	msg := strings.TrimSpace(strings.Replace(message.In.Text, "jira create", "", 1))
	fields := strings.Fields(msg)
	summary := strings.Join(fields[2:], " ")
	client := &http.Client{}
	auth := encodeB64(connector.Login + ":" + connector.Pass)

	issuetype := issueType{
		Name: fields[0],
	}

	project := project{
		Key: fields[1],
	}

	issueFields := createFields{
		Project:   project,
		Summary:   summary,
		IssueType: issuetype,
	}

	issue := createObject{
		Fields: issueFields,
	}

	issueJson, err := json.Marshal(issue)
	if err != nil {
		log.Printf("Error marshaling jira json: %s", err)
		return
	}

	req, err := http.NewRequest("POST", "https://"+connector.Server+"/rest/api/2/issue", bytes.NewBuffer(issueJson))
	if err != nil {
		log.Printf("Jira Create Error: %s", err)
		message.Out.Text = "Failed to create issue"
		publishMsgs <- message
		return
	}

	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", "Basic "+auth)

	response, err := client.Do(req)
	if err != nil {
		log.Printf("Error performing jira create request: %s", err)
	}
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Print(err)
	}

	var created createdIssue
	json.Unmarshal(body, &created)

	message.Out.Text = created.Key
	publishMsgs <- message
}

func parseJiraIssue(message models.Message, publishMsgs chan<- models.Message, connector models.Connector) {
	var jiraRegex = regexp.MustCompile("[a-zA-Z]{2,12}-[0-9]{1,10}")
	issues := jiraRegex.FindAllString(message.In.Text, -1)
	for _, issue := range issues {
		if connector.Debug {
			log.Println("Jira match: " + issue)
		}

		client := &http.Client{}
		auth := encodeB64(connector.Login + ":" + connector.Pass)
		req, err := http.NewRequest("GET", "https://"+connector.Server+"/rest/api/2/issue/"+issue, nil)
		if err != nil {
			log.Printf("Error creating jira request: %s", err)
			return
		}

		req.Header.Add("Content-Type", "application/json")
		req.Header.Add("Authorization", "Basic "+auth)

		response, err := client.Do(req)
		if err != nil {
			log.Printf("Error requesting jira issue: %s", err)
			return
		}
		defer response.Body.Close()
		body, err := ioutil.ReadAll(response.Body)
		if err != nil {
			log.Println(err)
		}
		var ticket ticket
		json.Unmarshal(body, &ticket)
		if connector.Debug {
			log.Printf("Jira result: %+v", ticket)
		}
		if ticket.Fields.Status.Name == "" {
			return
		}
		message.Out.Link = "https://" + connector.Server + "/browse/" + issue
		message.Out.Text = strings.ToUpper(issue) + " - " + ticket.Fields.Summary
		message.Out.Detail = fmt.Sprintf("Status: %s\nPriority: %s\nAssignee: %s\n",
			ticket.Fields.Status.Name, ticket.Fields.Priority.Name, ticket.Fields.Assignee.DisplayName)
		publishMsgs <- message
	}
}

func encodeB64(message string) string {
	base64Text := make([]byte, base64.StdEncoding.EncodedLen(len(message)))
	base64.StdEncoding.Encode(base64Text, []byte(message))
	return string(base64Text)
}
<commit_msg>Removing the help for ticket mentioning because it doesn't make sense anymore<commit_after>package connectors

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"regexp"
	"strings"

	"github.com/projectjane/jane/models"
)

type Jira struct {
}

func (x Jira) Listen(commandMsgs chan<- models.Message, connector models.Connector) {
	return
}

func (x Jira) Command(message models.Message, publishMsgs chan<- models.Message, connector models.Connector) {
	if strings.HasPrefix(strings.ToLower(message.In.Text), strings.ToLower("jira create")) {
		createJiraIssue(message, publishMsgs, connector)
	} else {
		parseJiraIssue(message, publishMsgs, connector)
	}
}

func (x Jira) Publish(connector models.Connector, message models.Message, target string) {
	return
}

func (x Jira) Help(connector models.Connector) (help string) {
	help += "jira create {issueType} {project key} {summary}\n"
	return help
}

type ticket struct {
	Key    string `json:"key"`
	Fields fields `json:"fields"`
}

type fields struct {
	Summary     string   `json:"summary"`
	Status      status   `json:"status"`
	Description string   `json:"description"`
	Priority    priority `json:"priority"`
	Assignee    assignee `json:"assignee"`
}

type status struct {
	Description string `json:"description"`
	Name        string `json:"name"`
}

type priority struct {
	Name string `json:"name"`
}

type assignee struct {
	DisplayName string `json:"displayName"`
}

type createObject struct {
	Fields createFields `json:"fields"`
}

type createFields struct {
	Project   project   `json:"project"`
	Summary   string    `json:"summary"`
	IssueType issueType `json:"issueType"`
}

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

type issueType struct {
	Name string `json:"name"`
}

type createdIssue struct {
	Id   string `json:"id"`
	Key  string `json:"key"`
	Self string `json:"self"`
}

func createJiraIssue(message models.Message, publishMsgs chan<- models.Message, connector models.Connector) {
	msg := strings.TrimSpace(strings.Replace(message.In.Text, "jira create", "", 1))
	fields := strings.Fields(msg)
	summary := strings.Join(fields[2:], " ")
	client := &http.Client{}
	auth := encodeB64(connector.Login + ":" + connector.Pass)

	issuetype := issueType{
		Name: fields[0],
	}

	project := project{
		Key: fields[1],
	}

	issueFields := createFields{
		Project:   project,
		Summary:   summary,
		IssueType: issuetype,
	}

	issue := createObject{
		Fields: issueFields,
	}

	issueJson, err := json.Marshal(issue)
	if err != nil {
		log.Printf("Error marshaling jira json: %s", err)
		return
	}

	req, err := http.NewRequest("POST", "https://"+connector.Server+"/rest/api/2/issue", bytes.NewBuffer(issueJson))
	if err != nil {
		log.Printf("Jira Create Error: %s", err)
		message.Out.Text = "Failed to create issue"
		publishMsgs <- message
		return
	}

	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", "Basic "+auth)

	response, err := client.Do(req)
	if err != nil {
		log.Printf("Error performing jira create request: %s", err)
	}
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Print(err)
	}

	var created createdIssue
	json.Unmarshal(body, &created)

	message.Out.Text = created.Key
	publishMsgs <- message
}

func parseJiraIssue(message models.Message, publishMsgs chan<- models.Message, connector models.Connector) {
	var jiraRegex = regexp.MustCompile("[a-zA-Z]{2,12}-[0-9]{1,10}")
	issues := jiraRegex.FindAllString(message.In.Text, -1)
	for _, issue := range issues {
		if connector.Debug {
			log.Println("Jira match: " + issue)
		}

		client := &http.Client{}
		auth := encodeB64(connector.Login + ":" + connector.Pass)
		req, err := http.NewRequest("GET", "https://"+connector.Server+"/rest/api/2/issue/"+issue, nil)
		if err != nil {
			log.Printf("Error creating jira request: %s", err)
			return
		}

		req.Header.Add("Content-Type", "application/json")
		req.Header.Add("Authorization", "Basic "+auth)

		response, err := client.Do(req)
		if err != nil {
			log.Printf("Error requesting jira issue: %s", err)
			return
		}
		defer response.Body.Close()
		body, err := ioutil.ReadAll(response.Body)
		if err != nil {
			log.Println(err)
		}
		var ticket ticket
		json.Unmarshal(body, &ticket)
		if connector.Debug {
			log.Printf("Jira result: %+v", ticket)
		}
		if ticket.Fields.Status.Name == "" {
			return
		}
		message.Out.Link = "https://" + connector.Server + "/browse/" + issue
		message.Out.Text = strings.ToUpper(issue) + " - " + ticket.Fields.Summary
		message.Out.Detail = fmt.Sprintf("Status: %s\nPriority: %s\nAssignee: %s\n",
			ticket.Fields.Status.Name, ticket.Fields.Priority.Name, ticket.Fields.Assignee.DisplayName)
		publishMsgs <- message
	}
}

func encodeB64(message string) string {
	base64Text := make([]byte, base64.StdEncoding.EncodedLen(len(message)))
	base64.StdEncoding.Encode(base64Text, []byte(message))
	return string(base64Text)
}
<|endoftext|>