<commit_before>package slt

import (
	"bufio"
	"compress/gzip"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"sync"
	"time"

	"github.com/brunetto/goutils/debug"
)

// StichThemAll launch the stiching in parallel on all the simulation files in
// the folder, accordingly to their names (run 01 is different from run 02 and so on).
func StichThemAll(conf *ConfigStruct) {
	if Debug {
		defer debug.TimeMe(time.Now())
	}

	var (
		err          error
		wg           sync.WaitGroup // to wait the end of the goroutines
		inFiles      []string
		prefixes                    = []string{"out-", "err-"}
		outRegexp    *regexp.Regexp = regexp.MustCompile(`\S` + conf.BaseName() + `-run(\d+)-rnd\d+.\S`)
		outRegResult []string
		runs         StringSet // set = list of unique objects (run numbers)
		nRuns        []int
		globName     string
	)

	nRuns = make([]int, 0)

	// Search for all the STDOUT and STDERR files in the folder
	for idx := 0; idx < 2; idx++ {
		globName = prefixes[idx] + conf.BaseName() + "*"
		if Verb {
			log.Println("Searching for: ", globName)
		}
		if inFiles, err = filepath.Glob(globName); err != nil {
			log.Fatal("Error globbing for stiching all the run outputs, ", globName, " ,  in this folder: ", err)
		}
		// Sort file names
		sort.Strings(inFiles)

		runs = NewStringSet()

		// Find the numbers of the different runs
		for _, inFileName := range inFiles {
			outRegResult = outRegexp.FindStringSubmatch(inFileName)
			if outRegResult == nil {
				log.Fatal("Can't find parameters in out name ", inFileName)
			}
			// Add the new number in the set
			runs.Add(outRegResult[1])
		}
		if Verb {
			log.Println("Found runs:")
			fmt.Println(runs.String())
		}
		nRuns = append(nRuns, len(runs))
	}

	// Check for missing run outputs
	if nRuns[0] != nRuns[1] {
		log.Println("WARNING, missing runs. Found ", nRuns[0], " STDOUT but ", nRuns[1], " STDERR.")
	}
	if nRuns[0] != conf.Runs {
		log.Println("WARNING, missing runs. Found ", nRuns[0], " STDOUT of ", conf.Runs, " planned in config file.")
	}

	log.Println("Found ", nRuns[0], " runs in this folder: ")
	fmt.Println(runs.String())

	// Launch all the stiching
	for _, runIdx := range runs.Sorted() {
		name := "out-" + conf.BaseName() + "-run" + runIdx + "-rnd00.*"
		if Verb {
			log.Println("Launching stich based on ", name)
		}
		// Count the goroutine as running
		wg.Add(1)
		// Launch one stiching
		go func(name string, conf *ConfigStruct) {
			// Decrement the counter when the goroutine completes.
			defer wg.Done()
			StichOutput(name, conf)
		}(name, conf)
	}

	// Wait for all the goroutine to finish
	wg.Wait()

}

// FIXME: Workaround to call StichOutput not in parallel
// because now StichOutput contain a call to wg.Done
// and I don't want to import "sync" in command.go
func StichOutputSingle(inFileName string, conf *ConfigStruct) {
	if Debug {
		defer debug.TimeMe(time.Now())
	}
	var wg sync.WaitGroup
	wg.Add(1)
	go func(name string, conf *ConfigStruct) {
		// Decrement the counter when the goroutine completes.
		defer wg.Done()
		StichOutput(name, conf)
	}(inFileName, conf)
	wg.Wait()
}

// StichOutput stiches the STDOUT and STDERR of a simulation.
func StichOutput(inFileName string, conf *ConfigStruct) {
	if Debug {
		defer debug.TimeMe(time.Now())
	}

	var (
		outRegexp    *regexp.Regexp = regexp.MustCompile(`\S` + conf.BaseName() + `-run(\d+)-rnd\d+.\S`)
		outRegResult []string
		run          string
		stdOuts      string
		stdErrs      string
	)

	// Extract parameters from the name
	outRegResult = outRegexp.FindStringSubmatch(inFileName)
	if outRegResult == nil {
		log.Fatal("Can't find parameters in out name ", inFileName)
	}

	run = outRegResult[1]

	if inFileName == "" {
		log.Fatal("You need to specify an input file template with the -i flag!!!")
	}

	log.Println("Stiching *-" + conf.BaseName() + `-run` + run + `-rnd*.*`)

	// Check if only have to run STDERR stich
	if !OnlyErr {
		//
		// STDOUT
		//
		stdOuts = "out-" + conf.BaseName() + `-run` + run + `-rnd*.*`
		StdStich(stdOuts, run, "out", conf)
	} else {
		log.Println("Only stich STDERRs")
	}

	// Check if only have to run STDOUT stich
	if !OnlyOut {
		//
		// STDERR
		//
		stdErrs = "err-" + conf.BaseName() + `-run` + run + `-rnd*.*`
		StdStich(stdErrs, run, "err", conf)

	} else {
		log.Println("Only stich STDOUTs")
	}
}

// StdStich stiches a given STD??? according to the type passed with stdWhat.
func StdStich(stdFiles, run, stdWhat string, conf *ConfigStruct) {
	if Debug {
		defer debug.TimeMe(time.Now())
	}

	var (
		fZip                                  *gzip.Reader
		inFile                                *os.File
		snapshot/*s = make([]*/ *DumbSnapshot /*, 2)*/
		inFiles                               []string
		outFileName                           string
		outFile                               *os.File
		err                                   error
		nReader                               *bufio.Reader
		nWriter                               *bufio.Writer
		timestep                              int64
		timesteps                             = make([]int64, 0)
		ext                                   string
	)

	log.Println("Stich std" + stdWhat)
	outFileName = stdWhat + "-" + conf.BaseName() + "-run" + run + "-all.txt"
	log.Println("Output file will be ", outFileName)

	log.Println("Opening STDOUT output file...")

	// Open output file
	if outFile, err = os.Create(outFileName); err != nil {
		log.Fatal(err)
	}
	defer outFile.Close()

	// Create reader and writerq
	nWriter = bufio.NewWriter(outFile)
	defer nWriter.Flush()

	log.Println("Globbing and sorting " + stdWhat + " input files")
	// Open infiles
	if inFiles, err = filepath.Glob(stdFiles); err != nil {
		log.Fatal("Error globbing "+stdWhat+" files for output stiching: ", err)
	}

	sort.Strings(inFiles)

	if Verb {
		log.Println("Found:")
		for idx, file := range inFiles {
			fmt.Println(idx, ": ", file)
		}
	}

	for _, inFileName := range inFiles {
		if Verb {
			log.Println("Working on ", inFileName)
		}
		if inFile, err = os.Open(inFileName); err != nil {
			log.Fatal(err)
		}
		defer inFile.Close()
		ext = filepath.Ext(inFileName)
		// Try to open the file if it is a gzipped one or a simple txt
		switch ext {
		case ".txt":
			{
				nReader = bufio.NewReader(inFile)
			}
		case ".gz":
			{
				fZip, err = gzip.NewReader(inFile)
				if err != nil {
					log.Fatal("Can't open %s: error: %s\n", inFileName, err)
					os.Exit(1)
				}
				nReader = bufio.NewReader(fZip)
			}
		default:
			{
				log.Fatal("Unrecognized file type", inFileName)
			}
		}

		if stdWhat == "err" {

		}

		//Read snapshots and write them if everything is OK
	SnapLoop:
		for {
			if stdWhat == "out" {
				snapshot, err = ReadOutSnapshot(nReader)
			} else if stdWhat == "err" {
				snapshot, err = ReadErrSnapshot(nReader)
			} else {
				log.Fatal("Unrecognized stdWhat: ", stdWhat)
			}
			if err != nil {
				if Verb {
					log.Println("Incomplete snapshot, moving to the next file")
				}
				break SnapLoop
			}
			// -1 is the "ICs to 0" timestep, skipping
			// I will skip this also because it creates problems of duplication
			// and timestep check
			if snapshot.Timestep == "-1" && len(timesteps) > 0 {
				continue SnapLoop /*to the next timestep*/
			}

			// I will loose the last timestep on STDERR because it is probably not complete
			// TODO: find out how to manage this
			// BUG: I can't find a univoque way to define the last snapshot complete
			if snapshot.Integrity == true {
				timestep, err = strconv.ParseInt(snapshot.Timestep, 10, 64)
				// Skip the first loop (=first timestep) with len = 0
				if len(timesteps) > 0 {
					if AbsInt(timestep-timesteps[len(timesteps)-1]) > 1 {
						if Verb {
							log.Println("Read timestep: ")
							for _, ts := range timesteps {
								fmt.Print(ts, " ")
							}
							fmt.Println()
						}
						log.Fatal("More that one timestep of distance between ", timesteps[len(timesteps)-1], " and ", timestep)
					} else if AbsInt(timestep-timesteps[len(timesteps)-1]) < 1 {
						log.Println("Duplicated timestep ", timestep, ", continue.")
						continue SnapLoop /*to the next timestep*/
					}
				}
				timesteps = append(timesteps, timestep) // Write the snapshot
				if err = snapshot.WriteSnapshot(nWriter); err != nil {
					log.Fatal("Error while writing snapshot to file: ", err)
				}
			} else {
				// This shouldn't happend because of the break in reading the snapshots
				// This shoud be a redundant check
				// TODO: check if it is true!!!
				fmt.Println("************************ ATTENTION *************************")
				fmt.Println("************************************************************")
				log.Println("Skipping incomplete snapshot at timestep", snapshot.Timestep)
				fmt.Println("************************************************************")
				fmt.Println("************************************************************")
			}
		} // end reading snapshot from a single file loop
	} // end reading file loop
	fmt.Println("\n")
	log.Println("Wrote ", len(timesteps), "snapshots to ", outFileName)
	fmt.Println(timesteps)

}

// StdStich stiches a given STD??? according to the type passed with stdWhat.
func DumbStich(stdFiles, run, stdWhat string, conf *ConfigStruct) {
	if Debug {
		defer debug.TimeMe(time.Now())
	}

	var (
		fZip                                  *gzip.Reader
		inFile                                *os.File
		snapshot/*s = make([]*/ *DumbSnapshot /*, 2)*/
		inFiles                               []string
		outFileName                           string
		outFile                               *os.File
		err                                   error
		nReader                               *bufio.Reader
		nWriter                               *bufio.Writer
		timestep                              int64
		timesteps                             = make([]int64, 0)
		ext                                   string
	)

	log.Println("Stich std" + stdWhat)
	outFileName = stdWhat + "-" + conf.BaseName() + "-run" + run + "-all.txt"
	log.Println("Output file will be ", outFileName)

	log.Println("Opening STDOUT output file...")

	// Open output file
	if outFile, err = os.Create(outFileName); err != nil {
		log.Fatal(err)
	}
	defer outFile.Close()

	// Create reader and writerq
	nWriter = bufio.NewWriter(outFile)
	defer nWriter.Flush()

	log.Println("Globbing and sorting " + stdWhat + " input files")
	// Open infiles
	if inFiles, err = filepath.Glob(stdFiles); err != nil {
		log.Fatal("Error globbing "+stdWhat+" files for output stiching: ", err)
	}

	sort.Strings(inFiles)

	if Verb {
		log.Println("Found:")
		for idx, file := range inFiles {
			fmt.Println(idx, ": ", file)
		}
	}

	for _, inFileName := range inFiles {
		if Verb {
			log.Println("Working on ", inFileName)
		}
		if inFile, err = os.Open(inFileName); err != nil {
			log.Fatal(err)
		}
		defer inFile.Close()
		ext = filepath.Ext(inFileName)
		// Try to open the file if it is a gzipped one or a simple txt
		switch ext {
		case ".txt":
			{
				nReader = bufio.NewReader(inFile)
			}
		case ".gz":
			{
				fZip, err = gzip.NewReader(inFile)
				if err != nil {
					log.Fatal("Can't open %s: error: %s\n", inFileName, err)
					os.Exit(1)
				}
				nReader = bufio.NewReader(fZip)
			}
		default:
			{
				log.Fatal("Unrecognized file type", inFileName)
			}
		}

		//Read snapshots and write them if everything is OK
	SnapLoop:
		for {
			if stdWhat == "out" {
				snapshot, err = ReadOutSnapshot(nReader)
			} else if stdWhat == "err" {
				snapshot, err = ReadErrSnapshot(nReader)
			} else {
				log.Fatal("Unrecognized stdWhat: ", stdWhat)
			}
			if err != nil {
				if Verb {
					log.Println("Incomplete snapshot, moving to the next file")
				}
				break SnapLoop
			}
			// -1 is the "ICs to 0" timestep, skipping
			// I will skip this also because it creates problems of duplication
			// and timestep check
			if snapshot.Timestep == "-1" {
				continue SnapLoop /*to the next timestep*/
			}

			// I will loose the last timestep on STDERR because it is probably not complete
			// TODO: find out how to manage this
			// BUG: I can't find a univoque way to define the last snapshot complete
			if snapshot.Integrity == true {
				timestep, err = strconv.ParseInt(snapshot.Timestep, 10, 64)
				// Skip the first loop (=first timestep) with len = 0
				if len(timesteps) > 0 {
					if AbsInt(timestep-timesteps[len(timesteps)-1]) > 1 {
						if Verb {
							log.Println("Read timestep: ")
							for _, ts := range timesteps {
								fmt.Print(ts, " ")
							}
							fmt.Println()
						}
						log.Fatal("More that one timestep of distance between ", timesteps[len(timesteps)-1], " and ", timestep)
					} else if AbsInt(timestep-timesteps[len(timesteps)-1]) < 1 {
						log.Println("Duplicated timestep ", timestep, ", continue.")
						continue SnapLoop /*to the next timestep*/
					}
				}
				timesteps = append(timesteps, timestep) // Write the snapshot
				if err = snapshot.WriteSnapshot(nWriter); err != nil {
					log.Fatal("Error while writing snapshot to file: ", err)
				}
			} else {
				// This shouldn't happend because of the break in reading the snapshots
				// This shoud be a redundant check
				// TODO: check if it is true!!!
				fmt.Println("************************ ATTENTION *************************")
				fmt.Println("************************************************************")
				log.Println("Skipping incomplete snapshot at timestep", snapshot.Timestep)
				fmt.Println("************************************************************")
				fmt.Println("************************************************************")
			}
		} // end reading snapshot from a single file loop
	} // end reading file loop
	fmt.Println("\n")
	log.Println("Wrote ", len(timesteps), "snapshots to ", outFileName)
	fmt.Println(timesteps)

}
<commit_msg>modified createStartScript<commit_after>package slt

import (
	"bufio"
	"compress/gzip"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"sync"
	"time"

	"github.com/brunetto/goutils/debug"
)

// StichThemAll launch the stiching in parallel on all the simulation files in
// the folder, accordingly to their names (run 01 is different from run 02 and so on).
func StichThemAll(conf *ConfigStruct) {
	if Debug {
		defer debug.TimeMe(time.Now())
	}

	var (
		err          error
		wg           sync.WaitGroup // to wait the end of the goroutines
		inFiles      []string
		prefixes                    = []string{"out-", "err-"}
		outRegexp    *regexp.Regexp = regexp.MustCompile(`\S` + conf.BaseName() + `-run(\d+)-rnd\d+.\S`)
		outRegResult []string
		runs         StringSet // set = list of unique objects (run numbers)
		nRuns        []int
		globName     string
	)

	nRuns = make([]int, 0)

	// Search for all the STDOUT and STDERR files in the folder
	for idx := 0; idx < 2; idx++ {
		globName = prefixes[idx] + conf.BaseName() + "*"
		if Verb {
			log.Println("Searching for: ", globName)
		}
		if inFiles, err = filepath.Glob(globName); err != nil {
			log.Fatal("Error globbing for stiching all the run outputs, ", globName, " ,  in this folder: ", err)
		}
		// Sort file names
		sort.Strings(inFiles)

		runs = NewStringSet()

		// Find the numbers of the different runs
		for _, inFileName := range inFiles {
			outRegResult = outRegexp.FindStringSubmatch(inFileName)
			if outRegResult == nil {
				log.Fatal("Can't find parameters in out name ", inFileName)
			}
			// Add the new number in the set
			runs.Add(outRegResult[1])
		}
		if Verb {
			log.Println("Found runs:")
			fmt.Println(runs.String())
		}
		nRuns = append(nRuns, len(runs))
	}

	// Check for missing run outputs
	if nRuns[0] != nRuns[1] {
		log.Println("WARNING, missing runs. Found ", nRuns[0], " STDOUT but ", nRuns[1], " STDERR.")
	}
	if nRuns[0] != conf.Runs {
		log.Println("WARNING, missing runs. Found ", nRuns[0], " STDOUT of ", conf.Runs, " planned in config file.")
	}

	log.Println("Found ", nRuns[0], " runs in this folder: ")
	fmt.Println(runs.String())

	// Launch all the stiching
	for _, runIdx := range runs.Sorted() {
		name := "out-" + conf.BaseName() + "-run" + runIdx + "-rnd00.*"
		if Verb {
			log.Println("Launching stich based on ", name)
		}
		// Count the goroutine as running
		wg.Add(1)
		// Launch one stiching
		go func(name string, conf *ConfigStruct) {
			// Decrement the counter when the goroutine completes.
			defer wg.Done()
			StichOutput(name, conf)
		}(name, conf)
	}

	// Wait for all the goroutine to finish
	wg.Wait()

}

// FIXME: Workaround to call StichOutput not in parallel
// because now StichOutput contain a call to wg.Done
// and I don't want to import "sync" in command.go
func StichOutputSingle(inFileName string, conf *ConfigStruct) {
	if Debug {
		defer debug.TimeMe(time.Now())
	}
	var wg sync.WaitGroup
	wg.Add(1)
	go func(name string, conf *ConfigStruct) {
		// Decrement the counter when the goroutine completes.
		defer wg.Done()
		StichOutput(name, conf)
	}(inFileName, conf)
	wg.Wait()
}

// StichOutput stiches the STDOUT and STDERR of a simulation.
func StichOutput(inFileName string, conf *ConfigStruct) {
	if Debug {
		defer debug.TimeMe(time.Now())
	}

	var (
		outRegexp    *regexp.Regexp = regexp.MustCompile(`\S` + conf.BaseName() + `-run(\d+)-rnd\d+.\S`)
		outRegResult []string
		run          string
		stdOuts      string
		stdErrs      string
	)

	// Extract parameters from the name
	outRegResult = outRegexp.FindStringSubmatch(inFileName)
	if outRegResult == nil {
		log.Fatal("Can't find parameters in out name ", inFileName)
	}

	run = outRegResult[1]

	if inFileName == "" {
		log.Fatal("You need to specify an input file template with the -i flag!!!")
	}

	log.Println("Stiching *-" + conf.BaseName() + `-run` + run + `-rnd*.*`)

	// Check if only have to run STDERR stich
	if !OnlyErr {
		//
		// STDOUT
		//
		stdOuts = "out-" + conf.BaseName() + `-run` + run + `-rnd*.*`
		StdStich(stdOuts, run, "out", conf)
	} else {
		log.Println("Only stich STDERRs")
	}

	// Check if only have to run STDOUT stich
	if !OnlyOut {
		//
		// STDERR
		//
		stdErrs = "err-" + conf.BaseName() + `-run` + run + `-rnd*.*`
		StdStich(stdErrs, run, "err", conf)

	} else {
		log.Println("Only stich STDOUTs")
	}
}

// StdStich stiches a given STD??? according to the type passed with stdWhat.
func StdStich(stdFiles, run, stdWhat string, conf *ConfigStruct) {
	if Debug {
		defer debug.TimeMe(time.Now())
	}

	var (
		fZip                                  *gzip.Reader
		inFile                                *os.File
		snapshot/*s = make([]*/ *DumbSnapshot /*, 2)*/
		inFiles                               []string
		outFileName                           string
		outFile                               *os.File
		err                                   error
		nReader                               *bufio.Reader
		nWriter                               *bufio.Writer
		timestep                              int64
		timesteps                             = make([]int64, 0)
		ext                                   string
	)

	log.Println("Stich std" + stdWhat)
	outFileName = stdWhat + "-" + conf.BaseName() + "-run" + run + "-all.txt"
	log.Println("Output file will be ", outFileName)

	log.Println("Opening STDOUT output file...")

	// Open output file
	if outFile, err = os.Create(outFileName); err != nil {
		log.Fatal(err)
	}
	defer outFile.Close()

	// Create reader and writerq
	nWriter = bufio.NewWriter(outFile)
	defer nWriter.Flush()

	log.Println("Globbing and sorting " + stdWhat + " input files")
	// Open infiles
	if inFiles, err = filepath.Glob(stdFiles); err != nil {
		log.Fatal("Error globbing "+stdWhat+" files for output stiching: ", err)
	}

	sort.Strings(inFiles)

	if Verb {
		log.Println("Found:")
		for idx, file := range inFiles {
			fmt.Println(idx, ": ", file)
		}
	}

	for _, inFileName := range inFiles {
		if Verb {
			log.Println("Working on ", inFileName)
		}
		if inFile, err = os.Open(inFileName); err != nil {
			log.Fatal(err)
		}
		defer inFile.Close()
		ext = filepath.Ext(inFileName)
		// Try to open the file if it is a gzipped one or a simple txt
		switch ext {
		case ".txt":
			{
				nReader = bufio.NewReader(inFile)
			}
		case ".gz":
			{
				fZip, err = gzip.NewReader(inFile)
				if err != nil {
					log.Fatal("Can't open %s: error: %s\n", inFileName, err)
					os.Exit(1)
				}
				nReader = bufio.NewReader(fZip)
			}
		default:
			{
				log.Fatal("Unrecognized file type", inFileName)
			}
		}

		//Read snapshots and write them if everything is OK
	SnapLoop:
		for {
			if stdWhat == "out" {
				snapshot, err = ReadOutSnapshot(nReader)
			} else if stdWhat == "err" {
				snapshot, err = ReadErrSnapshot(nReader)
			} else {
				log.Fatal("Unrecognized stdWhat: ", stdWhat)
			}
			if err != nil {
				if Verb {
					log.Println("Incomplete snapshot, moving to the next file")
				}
				break SnapLoop
			}
			// -1 is the "ICs to 0" timestep, skipping
			// I will skip this also because it creates problems of duplication
			// and timestep check
			if snapshot.Timestep == "-1" && len(timesteps) > 0 {
				continue SnapLoop /*to the next timestep*/
			}

			// I will loose the last timestep on STDERR because it is probably not complete
			// TODO: find out how to manage this
			// BUG: I can't find a univoque way to define the last snapshot complete
			if snapshot.Integrity == true {
				timestep, err = strconv.ParseInt(snapshot.Timestep, 10, 64)
				// Skip the first loop (=first timestep) with len = 0
				if len(timesteps) > 0 {
					if AbsInt(timestep-timesteps[len(timesteps)-1]) > 1 {
						if Verb {
							log.Println("Read timestep: ")
							for _, ts := range timesteps {
								fmt.Print(ts, " ")
							}
							fmt.Println()
						}
						log.Fatal("More that one timestep of distance between ", timesteps[len(timesteps)-1], " and ", timestep)
					} else if AbsInt(timestep-timesteps[len(timesteps)-1]) < 1 {
						log.Println("Duplicated timestep ", timestep, ", continue.")
						continue SnapLoop /*to the next timestep*/
					}
				}
				timesteps = append(timesteps, timestep) // Write the snapshot
				if err = snapshot.WriteSnapshot(nWriter); err != nil {
					log.Fatal("Error while writing snapshot to file: ", err)
				}
			} else {
				// This shouldn't happend because of the break in reading the snapshots
				// This shoud be a redundant check
				// TODO: check if it is true!!!
				fmt.Println("************************ ATTENTION *************************")
				fmt.Println("************************************************************")
				log.Println("Skipping incomplete snapshot at timestep", snapshot.Timestep)
				fmt.Println("************************************************************")
				fmt.Println("************************************************************")
			}
		} // end reading snapshot from a single file loop
	} // end reading file loop
	fmt.Println("\n")
	log.Println("Wrote ", len(timesteps), "snapshots to ", outFileName)
	fmt.Println(timesteps)

}

<|endoftext|>


<commit_before>package sse

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"net/http"
)

// EventFeed is a type for something that can return events in a form
// this API can write them to the write
type EventFeed interface {
	GetEventChan(clientCloseChan <-chan struct{}) <-chan SinkEvent
}

// SinkEvent is a generic type for things which can be marshalled to
// bytes.  They might also implement any of the below interfaces to
// control behavior.
type SinkEvent interface {
	GetData() ([]byte, error)
}

// EventSink is a structure used by the event sink writer
type EventSink struct {
	w           http.ResponseWriter
	flusher     http.Flusher
	feed        <-chan SinkEvent
	closeNotify <-chan bool
	closedChan  chan struct{}
}

// SinkEvents is an more-or-less drop-in replacement for a responder
// in a net/http response handler.  It handles all the SSE protocol
// for you - just feed it events.
func SinkEvents(w http.ResponseWriter, code int, feed EventFeed) error {
	sink, err := NewEventSink(w, feed)
	if err != nil {
		http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
		return err
	}
	sink.Respond(code)
	return sink.Sink()
}

// NewEventSink returns an Event
func NewEventSink(w http.ResponseWriter, feed EventFeed) (*EventSink, error) {
	sink := &EventSink{
		w: w,
	}
	var ok bool
	sink.flusher, ok = sink.w.(http.Flusher)
	if !ok {
		return nil, fmt.Errorf("ResponseWriter %v does not implement http.Flusher", w)
	}

	// Listen to the closing of the http connection via the CloseNotifier
	if closeNotifier, ok := sink.w.(http.CloseNotifier); ok {
		sink.closeNotify = closeNotifier.CloseNotify()
	} else {
		return nil, fmt.Errorf("ResponseWriter %v does not implement http.CloseNotifier", w)
	}

	// pass the message via channel-close semantics
	sink.closedChan = make(chan struct{})
	sink.feed = feed.GetEventChan(sink.closedChan)

	return sink, nil
}

// Respond sets up the event channel - sends the HTTP headers, and
// starts writing a response.  The keepalive timer is started.
func (sink *EventSink) Respond(code int) {
	// Set essential headers related to event streaming.  Set your own headers prior to
	// calling NewEventSink if you need more.
	sink.w.Header().Set("Content-Type", "text/event-stream")
	sink.w.Header().Set("Cache-Control", "no-cache")
	sink.w.Header().Set("Connection", "keep-alive")

	sink.w.WriteHeader(code)
	sink.flusher.Flush()
}

func (sink *EventSink) closeFeed() {
	if sink.closedChan != nil {
		close(sink.closedChan)
		sink.closedChan = nil
	}
}

// Sink is the main event sink loop for the EventSink.  Caller to
// provide the goroutine if required.
func (sink *EventSink) Sink() error {
	var sinkErr error
sinkLoop:
	for {
		select {
		case <-sink.closeNotify:
			sink.closeFeed()
			// wait for eventFeed to empty/close instead of breaking out here

		case event, ok := <-sink.feed:
			if !ok {
				sink.feed = nil
				break sinkLoop
			}
			if sinkErr = sink.sinkEvent(event); sinkErr != nil {
				sink.closeFeed()
			}
		}
	}
	sink.safeClose()
	return sinkErr
}

// prevent deadlocks by emptying channels instead of letting them block on write
func (sink *EventSink) safeClose() {
	sink.closeFeed()
	if sink.feed != nil {
		go func() {
			for {
				_, ok := <-sink.feed
				if !ok {
					break
				}
			}
		}()
	}
}

func (sink *EventSink) sinkEvent(event SinkEvent) error {

	var writeErr error

	if writeErr == nil {
		eventBody, _ := event.GetData() // FIXME - surface an error here

		// returning an empty interface value permits options like keepalive and retry
		// to be passed down the channel without generating a wire event
		if len(eventBody) != 0 {
			writeErr = writeDataLines(sink.w, eventBody)
		}
	}

	// a newline delimits events, but is also safe to send if no event was sent.
	if writeErr == nil {
		_, writeErr = sink.w.Write(endOfLine)
		sink.flusher.Flush()
	}

	return writeErr
}

// writeDataLines writes the data as an SSE event, making sure not to
// violate the protocol by inadvertantly emitting either of the two
// reserved characters: \n and \r
func writeDataLines(w io.Writer, data []byte) error {
	scanner := bufio.NewScanner(bytes.NewReader(data))
	var err error
	for (err == nil) && scanner.Scan() {
		line := scanner.Bytes()
		// I care more about SSE protocol conformance than junk input;
		// throw away everything from the first \r on the line
		if pos := bytes.IndexRune(line, '\r'); pos > -1 {
			line = line[:pos]
		}
		_, err = w.Write(DataHeader)
		if err == nil {
			_, err = w.Write(fieldDelim)
		}
		if err == nil {
			_, err = w.Write(line)
		}
		if err == nil {
			_, err = w.Write(endOfLine)
		}
	}
	return err
}
<commit_msg>sink.go: avoid unnecessary nesting in branch<commit_after>package sse

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"net/http"
)

// EventFeed is a type for something that can return events in a form
// this API can write them to the write
type EventFeed interface {
	GetEventChan(clientCloseChan <-chan struct{}) <-chan SinkEvent
}

// SinkEvent is a generic type for things which can be marshalled to
// bytes.  They might also implement any of the below interfaces to
// control behavior.
type SinkEvent interface {
	GetData() ([]byte, error)
}

// EventSink is a structure used by the event sink writer
type EventSink struct {
	w           http.ResponseWriter
	flusher     http.Flusher
	feed        <-chan SinkEvent
	closeNotify <-chan bool
	closedChan  chan struct{}
}

// SinkEvents is an more-or-less drop-in replacement for a responder
// in a net/http response handler.  It handles all the SSE protocol
// for you - just feed it events.
func SinkEvents(w http.ResponseWriter, code int, feed EventFeed) error {
	sink, err := NewEventSink(w, feed)
	if err != nil {
		http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
		return err
	}
	sink.Respond(code)
	return sink.Sink()
}

// NewEventSink returns an Event
func NewEventSink(w http.ResponseWriter, feed EventFeed) (*EventSink, error) {
	sink := &EventSink{
		w: w,
	}
	var ok bool
	sink.flusher, ok = sink.w.(http.Flusher)
	if !ok {
		return nil, fmt.Errorf("ResponseWriter %v does not implement http.Flusher", w)
	}

	// Listen to the closing of the http connection via the CloseNotifier
	closeNotifier, ok := sink.w.(http.CloseNotifier)
	if !ok {
		return nil, fmt.Errorf("ResponseWriter %v does not implement http.CloseNotifier", w)
	}
	sink.closeNotify = closeNotifier.CloseNotify()

	// pass the message via channel-close semantics
	sink.closedChan = make(chan struct{})
	sink.feed = feed.GetEventChan(sink.closedChan)

	return sink, nil
}

// Respond sets up the event channel - sends the HTTP headers, and
// starts writing a response.  The keepalive timer is started.
func (sink *EventSink) Respond(code int) {
	// Set essential headers related to event streaming.  Set your own headers prior to
	// calling NewEventSink if you need more.
	sink.w.Header().Set("Content-Type", "text/event-stream")
	sink.w.Header().Set("Cache-Control", "no-cache")
	sink.w.Header().Set("Connection", "keep-alive")

	sink.w.WriteHeader(code)
	sink.flusher.Flush()
}

func (sink *EventSink) closeFeed() {
	if sink.closedChan != nil {
		close(sink.closedChan)
		sink.closedChan = nil
	}
}

// Sink is the main event sink loop for the EventSink.  Caller to
// provide the goroutine if required.
func (sink *EventSink) Sink() error {
	var sinkErr error
sinkLoop:
	for {
		select {
		case <-sink.closeNotify:
			sink.closeFeed()
			// wait for eventFeed to empty/close instead of breaking out here

		case event, ok := <-sink.feed:
			if !ok {
				sink.feed = nil
				break sinkLoop
			}
			if sinkErr = sink.sinkEvent(event); sinkErr != nil {
				sink.closeFeed()
			}
		}
	}
	sink.safeClose()
	return sinkErr
}

// prevent deadlocks by emptying channels instead of letting them block on write
func (sink *EventSink) safeClose() {
	sink.closeFeed()
	if sink.feed != nil {
		go func() {
			for {
				_, ok := <-sink.feed
				if !ok {
					break
				}
			}
		}()
	}
}

func (sink *EventSink) sinkEvent(event SinkEvent) error {

	var writeErr error

	if writeErr == nil {
		eventBody, _ := event.GetData() // FIXME - surface an error here

		// returning an empty interface value permits options like keepalive and retry
		// to be passed down the channel without generating a wire event
		if len(eventBody) != 0 {
			writeErr = writeDataLines(sink.w, eventBody)
		}
	}

	// a newline delimits events, but is also safe to send if no event was sent.
	if writeErr == nil {
		_, writeErr = sink.w.Write(endOfLine)
		sink.flusher.Flush()
	}

	return writeErr
}

// writeDataLines writes the data as an SSE event, making sure not to
// violate the protocol by inadvertantly emitting either of the two
// reserved characters: \n and \r
func writeDataLines(w io.Writer, data []byte) error {
	scanner := bufio.NewScanner(bytes.NewReader(data))
	var err error
	for (err == nil) && scanner.Scan() {
		line := scanner.Bytes()
		// I care more about SSE protocol conformance than junk input;
		// throw away everything from the first \r on the line
		if pos := bytes.IndexRune(line, '\r'); pos > -1 {
			line = line[:pos]
		}
		_, err = w.Write(DataHeader)
		if err == nil {
			_, err = w.Write(fieldDelim)
		}
		if err == nil {
			_, err = w.Write(line)
		}
		if err == nil {
			_, err = w.Write(endOfLine)
		}
	}
	return err
}
<|endoftext|>


<commit_before><commit_msg>Fix BatchSubscribeMembers Response<commit_after><|endoftext|>


<commit_before><commit_msg>I guess that was not so unreachable<commit_after><|endoftext|>


<commit_before>package gohavestorage

import (
	"encoding/json"
	"fmt"
	"gohavestorage/gohavestoragecommon"
	"reflect"
	"testing"
)

var Key = ""
var Account = ""
var Table = "TestTable"

func TestTableMethods(t *testing.T) {
	goHaveStorage := NewWithDebug(Account, Key, false)
func TestCreateTable(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()
	tableStorageProxy.CreateTable(Table)
}

	httpStatusCode := tableStorageProxy.CreateTable("TableForTestingTableMethods")
	if httpStatusCode != 201 {
		fmt.Printf("Faild http code other than expected:%d", httpStatusCode)
		t.Fail()
	}

	body, httpStatusCode := tableStorageProxy.QueryTables()
	if httpStatusCode != 200 {
		fmt.Printf("Faild http code other than expected:%d", httpStatusCode)
		t.Fail()
	}
	if strings.Contains(string(body), "\"TableName\":\"TableForTestingTableMethods\"") != true {
		t.Fail()
	}

	httpStatusCode = tableStorageProxy.DeleteTable("TableForTestingTableMethods")
	if httpStatusCode != 204 {
		fmt.Printf("Faild http code other than expected:%d", httpStatusCode)
		t.Fail()
	}
func TestQueryTables(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()
	tableStorageProxy.QueryTables()
}

func TestInsertEntity(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	entity := &TestEntity{}
	entity.PartitionKey = "ABC"
	entity.RowKey = "123"
	entity.Property1 = "Value1"
	entity.Property2 = "Value2"
	entity.Property3 = "Value3"

	json1, _ := json.Marshal(entity)
	tableStorageProxy.InsertEntity(Table, json1)

	entity.RowKey = "456"
	json2, _ := json.Marshal(entity)
	tableStorageProxy.InsertEntity(Table, json2)

	entity.RowKey = "789"
	json3, _ := json.Marshal(entity)
	tableStorageProxy.InsertEntity(Table, json3)
}

func TestQueryEntity(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.QueryEntity(Table, "ABC", "123", "")
}

func TestQueryEntityWithSelect(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.QueryEntity(Table, "ABC", "123", "RowKey,Property1,Property3")
}

func TestQueryEntities(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.QueryEntities(Table, "", "", "")
}

func TestQueryEntitiesWithSelect(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.QueryEntities(Table, "RowKey,Property1,Property3", "", "")
}

func TestQueryEntitiesWithTop(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.QueryEntities(Table, "", "", "1")
}

func TestQueryEntitiesWithSelectAndTop(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.QueryEntities(Table, "RowKey,Property1,Property3", "", "1")
}

func TestQueryEntitiesWithSelectAndFilterAndTop(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.QueryEntities(Table, "RowKey,Property1,Property3", "RowKey%20gt%20'123'", "1")
}

func TestDeleteEntity(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.DeleteEntity(Table, "ABC", "123")
}

func TestUpdateEntity(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	entity := &TestEntity{}
	entity.PartitionKey = "ABC"
	entity.RowKey = "123"
	entity.Property1 = "Value1"
	entity.Property2 = "Value2"
	entity.Property3 = "Value3"

	json, _ := json.Marshal(entity)
	tableStorageProxy.UpdateEntity(Table, "ABC", "456", json)
}

func TestMergeEntity(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	entity := &TestEntity{}
	entity.PartitionKey = "ABC"
	entity.RowKey = "123"
	entity.Property1 = "Value1"
	entity.Property2 = "Value2"
	entity.Property3 = "Value3"

	json, _ := json.Marshal(entity)
	tableStorageProxy.MergeEntity(Table, "ABC", "456", json)
}

func TestInsertOrMergeEntity(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	entity := &TestEntity{}
	entity.PartitionKey = "ABC"
	entity.RowKey = "123"
	entity.Property1 = "Value1"
	entity.Property2 = "Value2"
	entity.Property3 = "Value3"

	json, _ := json.Marshal(entity)
	tableStorageProxy.InsertOrMergeEntity(Table, "ABC", "456", json)
}

func TestInsertOrReplaceEntity(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	entity := &TestEntity{}
	entity.PartitionKey = "ABC"
	entity.RowKey = "123"
	entity.Property1 = "Value1"
	entity.Property2 = "Value2"
	entity.Property3 = "Value3"

	json, _ := json.Marshal(entity)
	tableStorageProxy.InsertOrReplaceEntity(Table, "ABC", "456", json)
}

func TestDeleteTable(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()
	tableStorageProxy.DeleteTable(Table)
}

func TestTableServiceProperties(t *testing.T) {
	goHaveStorage := NewWithDebug(Account, Key, false)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()
	properties, _ := tableStorageProxy.GetTableServiceProperties()
	httpStatusCode := tableStorageProxy.SetTableServiceProperties(properties)

	lastestProperties, _ := tableStorageProxy.GetTableServiceProperties()

	if httpStatusCode != 202 {
		fmt.Printf("Faild http code other than expected:%d", httpStatusCode)
		t.Fail()
	}
	if reflect.DeepEqual(properties, lastestProperties) == false {
		fmt.Printf("Dump:\n%+v\n\nvs\n\n%+v", properties, lastestProperties)
		t.Fail()
	}
}

func TestGetTableServiceStats(t *testing.T) {
	goHaveStorage := NewWithDebug(Account, Key, false)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()
	stats, httpStatusCode := tableStorageProxy.GetTableServiceStats()

	if httpStatusCode != 200 {
		fmt.Printf("Faild http code other than expected:%d", httpStatusCode)
		t.Fail()
	}
	if stats.GeoReplication.Status == "" || stats.GeoReplication.LastSyncTime == "" {
		t.Fail()
	}
}

func TestTableACL(t *testing.T) {
	goHaveStorage := NewWithDebug(Account, Key, false)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	accessPolicy := gohavestoragecommon.AccessPolicy{Start: "2014-12-31T00:00:00.0000000Z", Expiry: "2114-12-31T00:00:00.0000000Z", Permission: "raud"}
	signedIdentifier := gohavestoragecommon.SignedIdentifier{Id: "b54df8ab0e2d52759110f48c8d0c19e2", AccessPolicy: accessPolicy}
	signedIdentifiers := &gohavestoragecommon.SignedIdentifiers{[]gohavestoragecommon.SignedIdentifier{signedIdentifier}}
	tableStorageProxy.SetTableACL(Table, signedIdentifiers)

	acl, httpStatusCode := tableStorageProxy.GetTableACL(Table)

	if httpStatusCode != 200 {
		fmt.Printf("Faild http code other than expected:%d", httpStatusCode)
		t.Fail()
	}
	if reflect.DeepEqual(signedIdentifiers, acl) == false {
		fmt.Printf("Dump:\n%+v\n\nvs\n\n%+v", signedIdentifiers, acl)
		t.Fail()
	}
}

type TestEntity struct {
	PartitionKey string
	RowKey       string
	Property1    string
	Property2    string
	Property3    string
}
<commit_msg>Remove depricated tests<commit_after>package gohavestorage

import (
	"encoding/json"
	"fmt"
	"gohavestorage/gohavestoragecommon"
	"reflect"
	"testing"
)

var Key = ""
var Account = ""
var Table = "TestTable"

func TestTableMethods(t *testing.T) {
	goHaveStorage := NewWithDebug(Account, Key, false)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	httpStatusCode := tableStorageProxy.CreateTable("TableForTestingTableMethods")
	if httpStatusCode != 201 {
		fmt.Printf("Faild http code other than expected:%d", httpStatusCode)
		t.Fail()
	}

	body, httpStatusCode := tableStorageProxy.QueryTables()
	if httpStatusCode != 200 {
		fmt.Printf("Faild http code other than expected:%d", httpStatusCode)
		t.Fail()
	}
	if strings.Contains(string(body), "\"TableName\":\"TableForTestingTableMethods\"") != true {
		t.Fail()
	}

	httpStatusCode = tableStorageProxy.DeleteTable("TableForTestingTableMethods")
	if httpStatusCode != 204 {
		fmt.Printf("Faild http code other than expected:%d", httpStatusCode)
		t.Fail()
	}
}

func TestInsertEntity(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	entity := &TestEntity{}
	entity.PartitionKey = "ABC"
	entity.RowKey = "123"
	entity.Property1 = "Value1"
	entity.Property2 = "Value2"
	entity.Property3 = "Value3"

	json1, _ := json.Marshal(entity)
	tableStorageProxy.InsertEntity(Table, json1)

	entity.RowKey = "456"
	json2, _ := json.Marshal(entity)
	tableStorageProxy.InsertEntity(Table, json2)

	entity.RowKey = "789"
	json3, _ := json.Marshal(entity)
	tableStorageProxy.InsertEntity(Table, json3)
}

func TestQueryEntity(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.QueryEntity(Table, "ABC", "123", "")
}

func TestQueryEntityWithSelect(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.QueryEntity(Table, "ABC", "123", "RowKey,Property1,Property3")
}

func TestQueryEntities(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.QueryEntities(Table, "", "", "")
}

func TestQueryEntitiesWithSelect(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.QueryEntities(Table, "RowKey,Property1,Property3", "", "")
}

func TestQueryEntitiesWithTop(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.QueryEntities(Table, "", "", "1")
}

func TestQueryEntitiesWithSelectAndTop(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.QueryEntities(Table, "RowKey,Property1,Property3", "", "1")
}

func TestQueryEntitiesWithSelectAndFilterAndTop(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.QueryEntities(Table, "RowKey,Property1,Property3", "RowKey%20gt%20'123'", "1")
}

func TestDeleteEntity(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	tableStorageProxy.DeleteEntity(Table, "ABC", "123")
}

func TestUpdateEntity(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	entity := &TestEntity{}
	entity.PartitionKey = "ABC"
	entity.RowKey = "123"
	entity.Property1 = "Value1"
	entity.Property2 = "Value2"
	entity.Property3 = "Value3"

	json, _ := json.Marshal(entity)
	tableStorageProxy.UpdateEntity(Table, "ABC", "456", json)
}

func TestMergeEntity(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	entity := &TestEntity{}
	entity.PartitionKey = "ABC"
	entity.RowKey = "123"
	entity.Property1 = "Value1"
	entity.Property2 = "Value2"
	entity.Property3 = "Value3"

	json, _ := json.Marshal(entity)
	tableStorageProxy.MergeEntity(Table, "ABC", "456", json)
}

func TestInsertOrMergeEntity(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	entity := &TestEntity{}
	entity.PartitionKey = "ABC"
	entity.RowKey = "123"
	entity.Property1 = "Value1"
	entity.Property2 = "Value2"
	entity.Property3 = "Value3"

	json, _ := json.Marshal(entity)
	tableStorageProxy.InsertOrMergeEntity(Table, "ABC", "456", json)
}

func TestInsertOrReplaceEntity(t *testing.T) {
	goHaveStorage := New(Account, Key)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	entity := &TestEntity{}
	entity.PartitionKey = "ABC"
	entity.RowKey = "123"
	entity.Property1 = "Value1"
	entity.Property2 = "Value2"
	entity.Property3 = "Value3"

	json, _ := json.Marshal(entity)
	tableStorageProxy.InsertOrReplaceEntity(Table, "ABC", "456", json)
}

func TestTableServiceProperties(t *testing.T) {
	goHaveStorage := NewWithDebug(Account, Key, false)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()
	properties, _ := tableStorageProxy.GetTableServiceProperties()
	httpStatusCode := tableStorageProxy.SetTableServiceProperties(properties)

	lastestProperties, _ := tableStorageProxy.GetTableServiceProperties()

	if httpStatusCode != 202 {
		fmt.Printf("Faild http code other than expected:%d", httpStatusCode)
		t.Fail()
	}
	if reflect.DeepEqual(properties, lastestProperties) == false {
		fmt.Printf("Dump:\n%+v\n\nvs\n\n%+v", properties, lastestProperties)
		t.Fail()
	}
}

func TestGetTableServiceStats(t *testing.T) {
	goHaveStorage := NewWithDebug(Account, Key, false)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()
	stats, httpStatusCode := tableStorageProxy.GetTableServiceStats()

	if httpStatusCode != 200 {
		fmt.Printf("Faild http code other than expected:%d", httpStatusCode)
		t.Fail()
	}
	if stats.GeoReplication.Status == "" || stats.GeoReplication.LastSyncTime == "" {
		t.Fail()
	}
}

func TestTableACL(t *testing.T) {
	goHaveStorage := NewWithDebug(Account, Key, false)
	tableStorageProxy := goHaveStorage.NewTableStorageProxy()

	accessPolicy := gohavestoragecommon.AccessPolicy{Start: "2014-12-31T00:00:00.0000000Z", Expiry: "2114-12-31T00:00:00.0000000Z", Permission: "raud"}
	signedIdentifier := gohavestoragecommon.SignedIdentifier{Id: "b54df8ab0e2d52759110f48c8d0c19e2", AccessPolicy: accessPolicy}
	signedIdentifiers := &gohavestoragecommon.SignedIdentifiers{[]gohavestoragecommon.SignedIdentifier{signedIdentifier}}
	tableStorageProxy.SetTableACL(Table, signedIdentifiers)

	acl, httpStatusCode := tableStorageProxy.GetTableACL(Table)

	if httpStatusCode != 200 {
		fmt.Printf("Faild http code other than expected:%d", httpStatusCode)
		t.Fail()
	}
	if reflect.DeepEqual(signedIdentifiers, acl) == false {
		fmt.Printf("Dump:\n%+v\n\nvs\n\n%+v", signedIdentifiers, acl)
		t.Fail()
	}
}

type TestEntity struct {
	PartitionKey string
	RowKey       string
	Property1    string
	Property2    string
	Property3    string
}
<|endoftext|>


<commit_before>/*
The MIT License (MIT)

Copyright (c) 2016 Ivan Dejanovic

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package lexer

import (
	"errors"
	"fmt"
	"mlpl/types"
	"strconv"
)

type lexBuffer struct {
	token  types.Token
	index  int
	tokens []types.Token
}

func syntaxError(token types.Token) {
	fmt.Printf("Syntax error at line %d, unexpected token -> ", token.Lineno)

	switch token.TokenType {
	case types.IF, types.THEN, types.ELSE, types.END, types.REPEAT, types.UNTIL, types.READ, types.WRITE:
		fmt.Printf("reserved word: %s\n", token.TokenString)
	case types.ASSIGN:
		fmt.Printf(":=\n")
	case types.LT:
		fmt.Printf("<\n")
	case types.EQ:
		fmt.Printf("=\n")
	case types.LPAREN:
		fmt.Printf("(\n")
	case types.RPAREN:
		fmt.Printf(")\n")
	case types.SEMI:
		fmt.Printf(";\n")
	case types.PLUS:
		fmt.Printf("+\n")
	case types.MINUS:
		fmt.Printf("-\n")
	case types.TIMES:
		fmt.Printf("*\n")
	case types.OVER:
		fmt.Printf("/\n")
	case types.ENDFILE:
		fmt.Printf("EOF\n")
	case types.NUM:
		fmt.Printf("NUM, name= %s\n", token.TokenString)
	case types.ID:
		fmt.Printf("ID, name= %s\n", token.TokenString)
	case types.ERROR:
		fmt.Printf("ERROR: %s\n", token.TokenString)
	default:
		// Should never happen.
		fmt.Printf("Unknown token: %d\n", token.TokenType)
	}

	err := errors.New("Aborting.")
	if err != nil {
		panic(err)
	}
}

func getToken(buffer *lexBuffer) {
	if buffer.index < len(buffer.tokens) {
		buffer.index += 1
		buffer.token = buffer.tokens[buffer.index]
	}
}

func match(expected types.TokenType, buffer *lexBuffer) {
	if buffer.token.TokenType == expected {
		getToken(buffer)
	} else {
		syntaxError(buffer.token)
	}
}

func newStmtNode(kind types.StmtKind, lineno int) *types.TreeNode {
	node := new(types.TreeNode)

	node.Children = make([]*types.TreeNode, 0, 0)
	node.Sibling = nil
	node.Node = types.StmtK
	node.Stmt = kind
	node.Lineno = lineno

	return node
}

func newExpNode(kind types.ExpKind, lineno int) *types.TreeNode {
	node := new(types.TreeNode)

	node.Children = make([]*types.TreeNode, 0, 0)
	node.Sibling = nil
	node.Node = types.ExpK
	node.Exp = kind
	node.Lineno = lineno

	return node
}

func factor(buffer *lexBuffer) *types.TreeNode {
	var node *types.TreeNode
	var err error

	switch buffer.token.TokenType {
	case types.NUM:
		node = newExpNode(types.ConstK, buffer.token.Lineno)
		if buffer.token.TokenType == types.NUM {
			node.Val, err = strconv.Atoi(buffer.token.TokenString)
			if err != nil {
				panic(err)
			}
		}
		match(types.NUM, buffer)
	case types.ID:
		node = newExpNode(types.IdK, buffer.token.Lineno)
		if buffer.token.TokenType == types.ID {
			node.Name = buffer.token.TokenString
		}
		match(types.ID, buffer)
	case types.STRING:
		node = newExpNode(types.StringK, buffer.token.Lineno)
		node.ValString = buffer.token.TokenString
		match(types.STRING, buffer)
	case types.LPAREN:
		match(types.LPAREN, buffer)
		node = exp(buffer)
		match(types.RPAREN, buffer)
	default:
		syntaxError(buffer.token)
	}

	return node
}

func term(buffer *lexBuffer) *types.TreeNode {
	node := factor(buffer)

	for buffer.token.TokenType == types.TIMES || buffer.token.TokenType == types.OVER {
		p := newExpNode(types.OpK, buffer.token.Lineno)
		p.Children = append(p.Children, node)
		p.Op = buffer.token.TokenType
		node = p
		match(buffer.token.TokenType, buffer)
		node.Children = append(node.Children, factor(buffer))
	}

	return node
}

func simple_exp(buffer *lexBuffer) *types.TreeNode {
	node := term(buffer)

	for buffer.token.TokenType == types.PLUS || buffer.token.TokenType == types.MINUS {
		p := newExpNode(types.OpK, buffer.token.Lineno)
		p.Children = append(p.Children, node)
		p.Op = buffer.token.TokenType
		node = p
		match(buffer.token.TokenType, buffer)
		node.Children = append(node.Children, term(buffer))
	}

	return node
}

func exp(buffer *lexBuffer) *types.TreeNode {
	node := simple_exp(buffer)

	if buffer.token.TokenType == types.LT || buffer.token.TokenType == types.EQ {
		p := newExpNode(types.OpK, buffer.token.Lineno)
		p.Children = append(p.Children, node)
		p.Op = buffer.token.TokenType
		node = p
		match(buffer.token.TokenType, buffer)
		node.Children = append(node.Children, simple_exp(buffer))
	}

	return node
}

func if_stmt(buffer *lexBuffer) *types.TreeNode {
	node := newStmtNode(types.IfK, buffer.token.Lineno)

	match(types.IF, buffer)
	node.Children = append(node.Children, exp(buffer))
	match(types.THEN, buffer)
	node.Children = append(node.Children, stmt_sequence(buffer))
	if buffer.token.TokenType == types.ELSE {
		match(types.ELSE, buffer)
		node.Children = append(node.Children, stmt_sequence(buffer))
	}

	return node
}

func repeat_stmt(buffer *lexBuffer) *types.TreeNode {
	node := newStmtNode(types.RepeatK, buffer.token.Lineno)

	match(types.REPEAT, buffer)
	node.Children = append(node.Children, stmt_sequence(buffer))
	match(types.UNTIL, buffer)
	node.Children = append(node.Children, exp(buffer))

	return node
}

func assign_stmt(buffer *lexBuffer) *types.TreeNode {
	node := newStmtNode(types.AssignK, buffer.token.Lineno)

	if buffer.token.TokenType == types.ID {
		node.Name = buffer.token.TokenString
	}
	match(types.ID, buffer)
	match(types.ASSIGN, buffer)
	node.Children = append(node.Children, exp(buffer))

	return node
}

func read_stmt(buffer *lexBuffer) *types.TreeNode {
	node := newStmtNode(types.ReadK, buffer.token.Lineno)

	match(types.READ, buffer)
	if buffer.token.TokenType == types.ID {
		node.Name = buffer.token.TokenString
	}
	match(types.ID, buffer)

	return node
}

func write_stmt(buffer *lexBuffer) *types.TreeNode {
	node := newStmtNode(types.WriteK, buffer.token.Lineno)

	match(types.WRITE, buffer)
	node.Children = append(node.Children, exp(buffer))

	return node
}

func statement(buffer *lexBuffer) *types.TreeNode {
	var node *types.TreeNode

	switch buffer.token.TokenType {
	case types.IF:
		node = if_stmt(buffer)
	case types.REPEAT:
		node = repeat_stmt(buffer)
	case types.ID:
		node = assign_stmt(buffer)
	case types.READ:
		node = read_stmt(buffer)
	case types.WRITE:
		node = write_stmt(buffer)
	default:
		syntaxError(buffer.token)
	}

	return node
}

func stmt_sequence(buffer *lexBuffer) *types.TreeNode {
	node := statement(buffer)
	p := node

	for buffer.token.TokenType != types.ENDFILE &&
		buffer.token.TokenType != types.END &&
		buffer.token.TokenType != types.ELSE &&
		buffer.token.TokenType != types.UNTIL {
		match(types.SEMI, buffer)
		q := statement(buffer)
		if q != nil {
			if node == nil {
				p = q
				node = p
			} else {
				// Now p cannot be nil either.
				p.Sibling = q
				p = q
			}
		}
	}

	return node
}

func Lex(tokens []types.Token) *types.TreeNode {
	buffer := lexBuffer{tokens[0], 0, tokens}

	return stmt_sequence(&buffer)
}
<commit_msg>Fixed bug with lexer stopping to soon.<commit_after>/*
The MIT License (MIT)

Copyright (c) 2016 Ivan Dejanovic

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package lexer

import (
	"errors"
	"fmt"
	"mlpl/types"
	"strconv"
)

type lexBuffer struct {
	token  types.Token
	index  int
	tokens []types.Token
}

func syntaxError(token types.Token) {
	fmt.Printf("Syntax error at line %d, unexpected token -> ", token.Lineno)

	switch token.TokenType {
	case types.IF, types.THEN, types.ELSE, types.END, types.REPEAT, types.UNTIL, types.READ, types.WRITE:
		fmt.Printf("reserved word: %s\n", token.TokenString)
	case types.ASSIGN:
		fmt.Printf(":=\n")
	case types.LT:
		fmt.Printf("<\n")
	case types.EQ:
		fmt.Printf("=\n")
	case types.LPAREN:
		fmt.Printf("(\n")
	case types.RPAREN:
		fmt.Printf(")\n")
	case types.SEMI:
		fmt.Printf(";\n")
	case types.PLUS:
		fmt.Printf("+\n")
	case types.MINUS:
		fmt.Printf("-\n")
	case types.TIMES:
		fmt.Printf("*\n")
	case types.OVER:
		fmt.Printf("/\n")
	case types.ENDFILE:
		fmt.Printf("EOF\n")
	case types.NUM:
		fmt.Printf("NUM, name= %s\n", token.TokenString)
	case types.ID:
		fmt.Printf("ID, name= %s\n", token.TokenString)
	case types.ERROR:
		fmt.Printf("ERROR: %s\n", token.TokenString)
	default:
		// Should never happen.
		fmt.Printf("Unknown token: %d\n", token.TokenType)
	}

	err := errors.New("Aborting.")
	if err != nil {
		panic(err)
	}
}

func getToken(buffer *lexBuffer) {
	if buffer.index < len(buffer.tokens) {
		buffer.index += 1
		buffer.token = buffer.tokens[buffer.index]
	}
}

func match(expected types.TokenType, buffer *lexBuffer) {
	if buffer.token.TokenType == expected {
		getToken(buffer)
	} else {
		syntaxError(buffer.token)
	}
}

func newStmtNode(kind types.StmtKind, lineno int) *types.TreeNode {
	node := new(types.TreeNode)

	node.Children = make([]*types.TreeNode, 0, 0)
	node.Sibling = nil
	node.Node = types.StmtK
	node.Stmt = kind
	node.Lineno = lineno

	return node
}

func newExpNode(kind types.ExpKind, lineno int) *types.TreeNode {
	node := new(types.TreeNode)

	node.Children = make([]*types.TreeNode, 0, 0)
	node.Sibling = nil
	node.Node = types.ExpK
	node.Exp = kind
	node.Lineno = lineno

	return node
}

func factor(buffer *lexBuffer) *types.TreeNode {
	var node *types.TreeNode
	var err error

	switch buffer.token.TokenType {
	case types.NUM:
		node = newExpNode(types.ConstK, buffer.token.Lineno)
		if buffer.token.TokenType == types.NUM {
			node.Val, err = strconv.Atoi(buffer.token.TokenString)
			if err != nil {
				panic(err)
			}
		}
		match(types.NUM, buffer)
	case types.ID:
		node = newExpNode(types.IdK, buffer.token.Lineno)
		if buffer.token.TokenType == types.ID {
			node.Name = buffer.token.TokenString
		}
		match(types.ID, buffer)
	case types.STRING:
		node = newExpNode(types.StringK, buffer.token.Lineno)
		node.ValString = buffer.token.TokenString
		match(types.STRING, buffer)
	case types.LPAREN:
		match(types.LPAREN, buffer)
		node = exp(buffer)
		match(types.RPAREN, buffer)
	default:
		syntaxError(buffer.token)
	}

	return node
}

func term(buffer *lexBuffer) *types.TreeNode {
	node := factor(buffer)

	for buffer.token.TokenType == types.TIMES || buffer.token.TokenType == types.OVER {
		p := newExpNode(types.OpK, buffer.token.Lineno)
		p.Children = append(p.Children, node)
		p.Op = buffer.token.TokenType
		node = p
		match(buffer.token.TokenType, buffer)
		node.Children = append(node.Children, factor(buffer))
	}

	return node
}

func simple_exp(buffer *lexBuffer) *types.TreeNode {
	node := term(buffer)

	for buffer.token.TokenType == types.PLUS || buffer.token.TokenType == types.MINUS {
		p := newExpNode(types.OpK, buffer.token.Lineno)
		p.Children = append(p.Children, node)
		p.Op = buffer.token.TokenType
		node = p
		match(buffer.token.TokenType, buffer)
		node.Children = append(node.Children, term(buffer))
	}

	return node
}

func exp(buffer *lexBuffer) *types.TreeNode {
	node := simple_exp(buffer)

	if buffer.token.TokenType == types.LT || buffer.token.TokenType == types.EQ {
		p := newExpNode(types.OpK, buffer.token.Lineno)
		p.Children = append(p.Children, node)
		p.Op = buffer.token.TokenType
		node = p
		match(buffer.token.TokenType, buffer)
		node.Children = append(node.Children, simple_exp(buffer))
	}

	return node
}

func if_stmt(buffer *lexBuffer) *types.TreeNode {
	node := newStmtNode(types.IfK, buffer.token.Lineno)

	match(types.IF, buffer)
	node.Children = append(node.Children, exp(buffer))
	match(types.THEN, buffer)
	node.Children = append(node.Children, stmt_sequence(buffer))
	if buffer.token.TokenType == types.ELSE {
		match(types.ELSE, buffer)
		node.Children = append(node.Children, stmt_sequence(buffer))
	}

	return node
}

func repeat_stmt(buffer *lexBuffer) *types.TreeNode {
	node := newStmtNode(types.RepeatK, buffer.token.Lineno)

	match(types.REPEAT, buffer)
	node.Children = append(node.Children, stmt_sequence(buffer))
	match(types.UNTIL, buffer)
	node.Children = append(node.Children, exp(buffer))

	return node
}

func assign_stmt(buffer *lexBuffer) *types.TreeNode {
	node := newStmtNode(types.AssignK, buffer.token.Lineno)

	if buffer.token.TokenType == types.ID {
		node.Name = buffer.token.TokenString
	}
	match(types.ID, buffer)
	match(types.ASSIGN, buffer)
	node.Children = append(node.Children, exp(buffer))

	return node
}

func read_stmt(buffer *lexBuffer) *types.TreeNode {
	node := newStmtNode(types.ReadK, buffer.token.Lineno)

	match(types.READ, buffer)
	if buffer.token.TokenType == types.ID {
		node.Name = buffer.token.TokenString
	}
	match(types.ID, buffer)

	return node
}

func write_stmt(buffer *lexBuffer) *types.TreeNode {
	node := newStmtNode(types.WriteK, buffer.token.Lineno)

	match(types.WRITE, buffer)
	node.Children = append(node.Children, exp(buffer))

	return node
}

func statement(buffer *lexBuffer) *types.TreeNode {
	var node *types.TreeNode

	switch buffer.token.TokenType {
	case types.IF:
		node = if_stmt(buffer)
	case types.REPEAT:
		node = repeat_stmt(buffer)
	case types.ID:
		node = assign_stmt(buffer)
	case types.READ:
		node = read_stmt(buffer)
	case types.WRITE:
		node = write_stmt(buffer)
	default:
		syntaxError(buffer.token)
	}

	return node
}

func stmt_sequence(buffer *lexBuffer) *types.TreeNode {
	node := statement(buffer)
	p := node

	for buffer.token.TokenType != types.ENDFILE &&
		buffer.token.TokenType != types.END &&
		buffer.token.TokenType != types.ELSE &&
		buffer.token.TokenType != types.UNTIL {
		match(types.SEMI, buffer)
		q := statement(buffer)
		if q != nil {
			if node == nil {
				p = q
				node = p
			} else {
				// Now p cannot be nil either.
				p.Sibling = q
				p = q
			}
		}
	}

	return node
}

func lexSequence(buffer *lexBuffer) *types.TreeNode {
	var node, p, q *types.TreeNode = nil, nil, nil

	for buffer.token.TokenType != types.ENDFILE {
		if buffer.token.TokenType == types.END ||
			buffer.token.TokenType == types.ELSE ||
			buffer.token.TokenType == types.UNTIL {
			getToken(buffer)
		}
		if buffer.token.TokenType == types.ENDFILE {
			break
		}
		p = stmt_sequence(buffer)

		if node == nil {
			node = p
		} else {
			q = node

			for q.Sibling != nil {
				q = q.Sibling
			}
			q.Sibling = p
		}
	}

	return node
}

func Lex(tokens []types.Token) *types.TreeNode {
	buffer := lexBuffer{tokens[0], 0, tokens}

	return lexSequence(&buffer)
}
<|endoftext|>


<commit_before>package tsize

import (
	"errors"
	"os"

	isatty "github.com/mattn/go-isatty"
)

type Size struct {
	Width  int
	Height int
}

var NotATerminal = errors.New("Given file is not a terminal")

func GetSize() (s Size, err error) {
	return FgetSize(os.Stdout)
}

func FgetSize(fp *os.File) (s Size, err error) {
	if fp == nil || !isatty.IsTerminal(fp.Fd()) {
		err = NotATerminal
		return
	}

	s.Width, s.Height, err = getTerminalSize(fp)
	return
}

type SizeChanger struct {
	Change <-chan Size

	done chan struct{}
}

func (sc *SizeChanger) Close() (err error) {
	if sc.done != nil {
		close(sc.done)
		sc.done = nil
		sc.Change = nil
	}

	return
}

func NewSizeChanger() (sc *SizeChanger, err error) {
	sc = &SizeChanger{}

	sizechan := make(chan Size, 1)
	sc.Change = sizechan
	sc.done = make(chan struct{})

	err = getTerminalSizeChanges(sizechan, sc.done)
	if err != nil {
		close(sizechan)
		close(sc.done)
		sc = &SizeChanger{}
		return
	}

	return
}
<commit_msg>size: add documentation<commit_after>// Get terminal size. Supports Linux and Windows.

package tsize

import (
	"errors"
	"os"

	isatty "github.com/mattn/go-isatty"
)

// Terminal size in columns and rows as Width and Height, respectively.
type Size struct {
	Width  int
	Height int
}

// Error to return if the given file to FgetSize isn't a terminal
var NotATerminal = errors.New("Given file is not a terminal")

// Get the current terminal size.
func GetSize() (s Size, err error) {
	return FgetSize(os.Stdout)
}

// Get the terminal size of a given os.File.
func FgetSize(fp *os.File) (s Size, err error) {
	if fp == nil || !isatty.IsTerminal(fp.Fd()) {
		err = NotATerminal
		return
	}

	s.Width, s.Height, err = getTerminalSize(fp)
	return
}

// Listens to terminal size changes
type SizeChanger struct {
	Change <-chan Size

	done chan struct{}
}

// Stop listening to terminal size changes
func (sc *SizeChanger) Close() (err error) {
	if sc.done != nil {
		close(sc.done)
		sc.done = nil
		sc.Change = nil
	}

	return
}

// Create a new size change listener
func NewSizeChanger() (sc *SizeChanger, err error) {
	sc = &SizeChanger{}

	sizechan := make(chan Size, 1)
	sc.Change = sizechan
	sc.done = make(chan struct{})

	err = getTerminalSizeChanges(sizechan, sc.done)
	if err != nil {
		close(sizechan)
		close(sc.done)
		sc = &SizeChanger{}
		return
	}

	return
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"text/tabwriter"
)

func main() {
	flag.Parse()

	args := flag.Args()
	if len(args) == 0 {
		args = append(args, `.`)
	}

	for _, n := range args {
		add(n)
	}

	for _, f := range files {
		c, err := ioutil.ReadFile(f)
		if err != nil {
			fmt.Fprintf(os.Stderr, "  ! %s\n", f)
		}
		cs := string(c)
		handleFile(f, cs)
	}
	printInfo()
}

type Matcher interface{
	Match(string) bool
}

type Language interface{
	Name() string
	Matcher
	Update(string, *Stats)
}

type lName string

func (l lName) Name() string {
	return string(l)
}

type lMatch func(string) bool

func (m lMatch) Match(fname string) bool {
	return m(fname)
}

func mExt(exts ...string) lMatch {
	return func(fname string) bool {
		for _, ext := range exts {
			if ext == path.Ext(fname) {
				return true
			}
		}
		return false
	}
}

func mName(names ...string) lMatch {
	return func(fname string) bool {
		for _, name := range names {
			if name == fname {
				return true
			}
		}
		return false
	}
}

type Stats struct{
	FileCount    int
	TotalLines   int
	CodeLines    int
	BlankLines   int
	CommentLines int
}

var info = map[string]*Stats{}

var languages = []Language{
	LineLanguage{"C", mExt(".c")},
	LineLanguage{"C++", mExt(".cc", ".cpp", ".cxx")},
	LineLanguage{"Go", mExt(".go")},
	LineLanguage{"Haskell", mExt(".hs", ".lhs")},
	LineLanguage{"Python", mExt(".py")},
	LineLanguage{"Lisp", mExt(".lsp")},
	LineLanguage{"Make", mName("makefile", "Makefile", "MAKEFILE")},
	LineLanguage{"HTML", mExt(".htm", ".html", ".xhtml")},
}

func handleFile(fname, content string) {
	var l Language
	ok := false
	for _, lang := range languages {
		if lang.Match(fname) {
			ok = true
			l = lang
			break
		}
	}
	if !ok {
		return // ignore this file
	}
	i, ok := info[l.Name()]
	if !ok {
		i = &Stats{}
		info[l.Name()] = i
	}
	c, err := ioutil.ReadFile(fname)
	if err != nil {
		fmt.Fprintf(os.Stderr, "  ! %s\n", fname)
		return
	}
	l.Update(string(c), i)
}

func printInfo() {
	w := tabwriter.NewWriter(os.Stdout, 2, 8, 2, ' ', tabwriter.AlignRight)
	fmt.Fprintln(w, "Language\tFiles\tLines\t")
	for n, i := range info {
		fmt.Fprintf(w, "%s\t%d\t%d\t\n", n, i.FileCount, i.TotalLines)
	}
	w.Flush()
}

var files []string

func add(n string) {
	fi, err := os.Stat(n)
	if err != nil {
		goto invalid
	}
	if fi.IsDir() {
		fs, err := ioutil.ReadDir(n)
		if err != nil {
			goto invalid
		}
		for _, f := range fs {
			if f.Name()[0] != '.' {
				add(path.Join(n, f.Name()))
			}
		}
		return
	}
	if fi.Mode() & os.ModeType == 0 {
		files = append(files, n)
		return
	}

	println(fi.Mode())

invalid:
	fmt.Fprintf(os.Stderr, "  ! %s\n", n)
}
<commit_msg>Bugfix<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"text/tabwriter"
)

func main() {
	flag.Parse()

	args := flag.Args()
	if len(args) == 0 {
		args = append(args, `.`)
	}

	for _, n := range args {
		add(n)
	}

	for _, f := range files {
		c, err := ioutil.ReadFile(f)
		if err != nil {
			fmt.Fprintf(os.Stderr, "  ! %s\n", f)
		}
		cs := string(c)
		handleFile(f, cs)
	}
	printInfo()
}

type Matcher interface{
	Match(string) bool
}

type Language interface{
	Name() string
	Matcher
	Update(string, *Stats)
}

type lName string

func (l lName) Name() string {
	return string(l)
}

type lMatch func(string) bool

func (m lMatch) Match(fname string) bool {
	return m(fname)
}

func mExt(exts ...string) lMatch {
	return func(fname string) bool {
		for _, ext := range exts {
			if ext == path.Ext(fname) {
				return true
			}
		}
		return false
	}
}

func mName(names ...string) lMatch {
	return func(fname string) bool {
		for _, name := range names {
			if name == path.Base(fname) {
				return true
			}
		}
		return false
	}
}

type Stats struct{
	FileCount    int
	TotalLines   int
	CodeLines    int
	BlankLines   int
	CommentLines int
}

var info = map[string]*Stats{}

var languages = []Language{
	LineLanguage{"C", mExt(".c")},
	LineLanguage{"C++", mExt(".cc", ".cpp", ".cxx")},
	LineLanguage{"Go", mExt(".go")},
	LineLanguage{"Haskell", mExt(".hs", ".lhs")},
	LineLanguage{"Python", mExt(".py")},
	LineLanguage{"Lisp", mExt(".lsp")},
	LineLanguage{"Make", mName("makefile", "Makefile", "MAKEFILE")},
	LineLanguage{"HTML", mExt(".htm", ".html", ".xhtml")},
}

func handleFile(fname, content string) {
	var l Language
	ok := false
	for _, lang := range languages {
		if lang.Match(fname) {
			ok = true
			l = lang
			break
		}
	}
	if !ok {
		return // ignore this file
	}
	i, ok := info[l.Name()]
	if !ok {
		i = &Stats{}
		info[l.Name()] = i
	}
	c, err := ioutil.ReadFile(fname)
	if err != nil {
		fmt.Fprintf(os.Stderr, "  ! %s\n", fname)
		return
	}
	l.Update(string(c), i)
}

func printInfo() {
	w := tabwriter.NewWriter(os.Stdout, 2, 8, 2, ' ', tabwriter.AlignRight)
	fmt.Fprintln(w, "Language\tFiles\tLines\t")
	for n, i := range info {
		fmt.Fprintf(w, "%s\t%d\t%d\t\n", n, i.FileCount, i.TotalLines)
	}
	w.Flush()
}

var files []string

func add(n string) {
	fi, err := os.Stat(n)
	if err != nil {
		goto invalid
	}
	if fi.IsDir() {
		fs, err := ioutil.ReadDir(n)
		if err != nil {
			goto invalid
		}
		for _, f := range fs {
			if f.Name()[0] != '.' {
				add(path.Join(n, f.Name()))
			}
		}
		return
	}
	if fi.Mode() & os.ModeType == 0 {
		files = append(files, n)
		return
	}

	println(fi.Mode())

invalid:
	fmt.Fprintf(os.Stderr, "  ! %s\n", n)
}
<|endoftext|>


<commit_before>// Package slug provides an utility for generating URL-friendly slugs.
//
// Example:
//
//	package main
//
//	import "github.com/peferron/slug"
//
//	func main() {
//		s := slug.Generate("Hello World!")
//		print(s) // Prints "hello-world"
//	}
package slug

import (
	"regexp"
	"strings"

	"github.com/fiam/gounidecode/unidecode"
)

// Generate returns a slug generated from s, with sensible default parameters.
func Generate(s string) string {
	return GenerateWith(s, ` ,./\-_=~|()[]{}:;?!<>`, "-", 100)
}

// GenerateWith returns a slug generated from s, with all Unicode code points in chars replaced by
// the separator sep, and the final maximum length l.
func GenerateWith(s, chars, sep string, l int) string {
	slug := unidecode.Unidecode(s)
	slug = strings.ToLower(slug)

	// remove non-alphanumeric chars, except those in `chars`
	slug = replaceAll("[^a-z0-9" + regexp.QuoteMeta(chars) + "]", slug, "")

	// replace everything appearing in `chars` with seperator
	if len(chars) > 0 {
		slug = replaceAll("[" + regexp.QuoteMeta(chars) + "]+", slug, sep)
	}

	// remove prefixed seperator if present and enforce max length
	slug = strings.TrimPrefix(slug, sep)
	if len(slug) > l {
		slug = slug[:l]
	}

	return strings.TrimSuffix(slug, sep)
}

// replaceAll replaces everything in src matching regex with repl
func replaceAll(regex string, src string, repl string) string {
	re := regexp.MustCompile(regex)
	return re.ReplaceAllString(src, repl)
}
<commit_msg>Save QuoteMeta() result<commit_after>// Package slug provides an utility for generating URL-friendly slugs.
//
// Example:
//
//	package main
//
//	import "github.com/peferron/slug"
//
//	func main() {
//		s := slug.Generate("Hello World!")
//		print(s) // Prints "hello-world"
//	}
package slug

import (
	"regexp"
	"strings"

	"github.com/fiam/gounidecode/unidecode"
)

// Generate returns a slug generated from s, with sensible default parameters.
func Generate(s string) string {
	return GenerateWith(s, ` ,./\-_=~|()[]{}:;?!<>`, "-", 100)
}

// GenerateWith returns a slug generated from s, with all Unicode code points in chars replaced by
// the separator sep, and the final maximum length l.
func GenerateWith(s, chars, sep string, l int) string {
	slug := unidecode.Unidecode(s)
	slug = strings.ToLower(slug)

	// remove non-alphanumeric chars, except those in `chars`
	quotedChars := regexp.QuoteMeta(chars)
	slug = replaceAll("[^a-z0-9"+quotedChars+"]", slug, "")

	// replace everything appearing in `chars` with seperator
	if len(chars) > 0 {
		slug = replaceAll("["+quotedChars+"]+", slug, sep)
	}

	// remove prefixed seperator if present and enforce max length
	slug = strings.TrimPrefix(slug, sep)
	if len(slug) > l {
		slug = slug[:l]
	}

	return strings.TrimSuffix(slug, sep)
}

// replaceAll replaces everything in src matching regex with repl
func replaceAll(regex string, src string, repl string) string {
	re := regexp.MustCompile(regex)
	return re.ReplaceAllString(src, repl)
}
<|endoftext|>


<commit_before>package build

import (
	"fmt"
	"gopkg.in/yaml.v2"
	"neon/util"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"regexp"
	"strings"
)

const (
	// location of the repository root
	REPO_ROOT = "~/.neon"
	// regexp for plugin name
	RE_PLUGIN = `[\w-]+/[\w-]+`
)

// Possible fields for a build file
var FIELDS = []string{"doc", "default", "extends", "repository", "context",
	"singleton", "properties", "configuration", "environment", "targets"}

// Build structure
type Build struct {
	File        string
	Dir         string
	Here        string
	Default     []string
	Doc         string
	Repository  string
	Singleton   int
	Scripts     []string
	Extends     []string
	Config      []string
	Properties  util.Object
	Environment map[string]string
	Targets     map[string]*Target
	Context     *Context
	Parents     []*Build
	Index       *Index
	Stack       *Stack
}

// Make a build from a build file
func NewBuild(file string) (*Build, error) {
	build := &Build{}
	path := util.ExpandUserHome(file)
	build.File = filepath.Base(path)
	base, err := filepath.Abs(filepath.Dir(path))
	if err != nil {
		return nil, fmt.Errorf("getting build file directory: %v", err)
	}
	build.Dir = base
	here, err := os.Getwd()
	if err != nil {
		return nil, fmt.Errorf("getting current directory: %v", err)
	}
	build.Here = here
	source, err := util.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("loading build file '%s': %v", path, err)
	}
	var object util.Object
	err = yaml.Unmarshal(source, &object)
	if err != nil {
		return nil, fmt.Errorf("build must be a map with string keys")
	}
	if err := object.CheckFields(FIELDS); err != nil {
		return nil, fmt.Errorf("parsing build file: %v", err)
	}
	if err := ParseSingleton(object, build); err != nil {
		return nil, err
	}
	if err := ParseDefault(object, build); err != nil {
		return nil, err
	}
	if err := ParseDoc(object, build); err != nil {
		return nil, err
	}
	if err := ParseRepository(object, build); err != nil {
		return nil, err
	}
	if err := ParseContext(object, build); err != nil {
		return nil, err
	}
	if err := ParseExtends(object, build); err != nil {
		// we return build because it can be used to install plugin
		return build, err
	}
	if err := ParseProperties(object, build); err != nil {
		return nil, err
	}
	if err := ParseConfiguration(object, build); err != nil {
		return nil, err
	}
	if err := ParseEnvironment(object, build); err != nil {
		return nil, err
	}
	if err := ParseTargets(object, build); err != nil {
		return nil, err
	}
	return build, nil
}

// Return the build properties, including those inherited from parents
func (build *Build) GetProperties() util.Object {
	var properties = make(map[string]interface{})
	for _, parent := range build.Parents {
		for name, value := range parent.GetProperties() {
			properties[name] = value
		}
	}
	for name, value := range build.Properties {
		properties[name] = value
	}
	return properties
}

// Return the build environment, including those inherited from parents
func (build *Build) GetEnvironment() map[string]string {
	var environment = make(map[string]string)
	for _, parent := range build.Parents {
		for name, value := range parent.GetEnvironment() {
			environment[name] = value
		}
	}
	for name, value := range build.Environment {
		environment[name] = value
	}
	return environment
}

// Return the build targets, including those inherited from parents
func (build *Build) GetTargets() map[string]*Target {
	var targets = make(map[string]*Target)
	for _, parent := range build.Parents {
		for name, target := range parent.GetTargets() {
			targets[name] = target
		}
	}
	for name, target := range build.Targets {
		targets[name] = target
	}
	return targets
}

// Return target with given name. If not defined in build, return target
// inherited from parent
func (build *Build) GetTargetByName(name string) *Target {
	target, found := build.Targets[name]
	if found {
		return target
	} else {
		for _, parent := range build.Parents {
			target = parent.GetTargetByName(name)
			if target != nil {
				return target
			}
		}
	}
	return nil
}

// Initialize build:
// - Set build dir and change to it
// - Create context and set it for build
func (build *Build) Init() error {
	os.Chdir(build.Dir)
	context, err := NewContext(build)
	if err != nil {
		return fmt.Errorf("evaluating context: %v", err)
	}
	build.SetDir(build.Dir)
	build.SetContext(context)
	build.SetStack(NewStack())
	return nil
}

// Parse extends field of the build
func (build *Build) LoadParents() error {
	var parents []*Build
	for _, extend := range build.Extends {
		file := build.PluginPath(extend)
		parent, err := NewBuild(file)
		if err != nil {
			if err != nil {
				return fmt.Errorf("loading parent build file '%s': %v", extend, err)
			}
		}
		parents = append(parents, parent)
	}
	build.Parents = parents
	return nil
}

// Set the build directory, propagating to parents
func (build *Build) SetDir(dir string) {
	build.Dir = dir
	for _, parent := range build.Parents {
		parent.SetDir(dir)
	}
}

// Set the build context, propagating to parents
func (build *Build) SetContext(context *Context) {
	build.Context = context
	for _, parent := range build.Parents {
		parent.SetContext(context)
	}
}

// Set the build stack, propagating to parents
func (build *Build) SetStack(stack *Stack) {
	build.Stack = stack
	for _, parent := range build.Parents {
		parent.SetStack(stack)
	}
}

// Set command line properties, that overwrite build ones
func (build *Build) SetCommandLineProperties(props string) error {
	var object util.Object
	err := yaml.Unmarshal([]byte(props), &object)
	if err != nil {
		return fmt.Errorf("parsing command line properties: properties must be a map with string keys")
	}
	for name, value := range object {
		build.Properties[name] = value
	}
	return nil
}

// Return default targets. If none is defined in build, return those from
// parents
func (build *Build) GetDefault() []string {
	if len(build.Default) > 0 {
		return build.Default
	} else {
		for _, parent := range build.Parents {
			if len(parent.Default) > 0 {
				return parent.Default
			}
		}
		for _, parent := range build.Parents {
			parentDefault := parent.GetDefault()
			if len(parentDefault) > 0 {
				return parentDefault
			}
		}
	}
	return build.Default
}

// Run build given targets. If no target is given, run default one.
func (build *Build) Run(targets []string) error {
	if len(targets) == 0 {
		targets = build.GetDefault()
		if len(targets) == 0 {
			return fmt.Errorf("no default target")
		}
	}
	for _, target := range targets {
		err := build.RunTarget(target)
		if err != nil {
			return err
		}
	}
	return nil
}

// Run given target
func (build *Build) RunTarget(name string) error {
	target := build.GetTargetByName(name)
	if target == nil {
		return fmt.Errorf("target '%s' not found", name)
	}
	err := target.Run()
	if err != nil {
		return fmt.Errorf("running target '%s': %v", name, err)
	}
	return nil
}

// Run parent target
func (build *Build) RunParentTarget(name string) (bool, error) {
	for _, parent := range build.Parents {
		target := parent.GetTargetByName(name)
		if target != nil {
			err := target.RunSteps()
			if err != nil {
				return true, fmt.Errorf("running target '%s': %v", name, err)
			}
			return true, nil
		} else {
			ok, err := parent.RunParentTarget(name)
			if ok || err != nil {
				return ok, err
			}
		}
	}
	return false, nil
}

// Get parent build file path
func (build *Build) PluginPath(name string) string {
	if path.IsAbs(name) {
		return name
	} else if strings.HasPrefix(name, "./") {
		return filepath.Join(build.Dir, name)
	} else {
		repo := util.ExpandAndJoinToRoot(build.Dir, build.Repository)
		return filepath.Join(repo, name)
	}
}

// Get plugin name for given resource
func (build *Build) PluginName(name string) string {
	re := regexp.MustCompile(`^(` + RE_PLUGIN + `)/.+$`)
	if re.MatchString(name) {
		return re.FindStringSubmatch(name)[1]
	} else {
		return ""
	}
}

// Install given plugin
func (build *Build) Install(plugin string) error {
	re := regexp.MustCompile(`^` + RE_PLUGIN + `$`)
	if !re.MatchString(plugin) {
		return fmt.Errorf("plugin name '%s' is invalid", plugin)
	}
	path := build.PluginPath(plugin)
	if util.DirExists(path) {
		Message("Plugin '%s' already installed in '%s'", plugin, path)
		return nil
	}
	absolute := util.ExpandUserHome(path)
	repo := "git@github.com:" + plugin + ".git"
	command := exec.Command("git", "clone", repo, absolute)
	Message("Running command '%s'...", strings.Join(command.Args, " "))
	output, err := command.CombinedOutput()
	if err != nil {
		re = regexp.MustCompile("\n\n")
		message := re.ReplaceAllString(string(output), "\n")
		message = strings.TrimSpace(message)
		Message(message)
		return fmt.Errorf("installing plugin '%s'", plugin)
	} else {
		Message("Plugin '%s' installed in '%s'", plugin, path)
	}
	return nil
}
<commit_msg>Fixed plugin installation from github<commit_after>package build

import (
	"fmt"
	"gopkg.in/yaml.v2"
	"neon/util"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"regexp"
	"strings"
)

const (
	// location of the repository root
	REPO_ROOT = "~/.neon"
	// regexp for plugin name
	RE_PLUGIN = `[\w-]+/[\w-]+`
)

// Possible fields for a build file
var FIELDS = []string{"doc", "default", "extends", "repository", "context",
	"singleton", "properties", "configuration", "environment", "targets"}

// Build structure
type Build struct {
	File        string
	Dir         string
	Here        string
	Default     []string
	Doc         string
	Repository  string
	Singleton   int
	Scripts     []string
	Extends     []string
	Config      []string
	Properties  util.Object
	Environment map[string]string
	Targets     map[string]*Target
	Context     *Context
	Parents     []*Build
	Index       *Index
	Stack       *Stack
}

// Make a build from a build file
func NewBuild(file string) (*Build, error) {
	build := &Build{}
	path := util.ExpandUserHome(file)
	build.File = filepath.Base(path)
	base, err := filepath.Abs(filepath.Dir(path))
	if err != nil {
		return nil, fmt.Errorf("getting build file directory: %v", err)
	}
	build.Dir = base
	here, err := os.Getwd()
	if err != nil {
		return nil, fmt.Errorf("getting current directory: %v", err)
	}
	build.Here = here
	source, err := util.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("loading build file '%s': %v", path, err)
	}
	var object util.Object
	err = yaml.Unmarshal(source, &object)
	if err != nil {
		return nil, fmt.Errorf("build must be a map with string keys")
	}
	if err := object.CheckFields(FIELDS); err != nil {
		return nil, fmt.Errorf("parsing build file: %v", err)
	}
	if err := ParseSingleton(object, build); err != nil {
		return nil, err
	}
	if err := ParseDefault(object, build); err != nil {
		return nil, err
	}
	if err := ParseDoc(object, build); err != nil {
		return nil, err
	}
	if err := ParseRepository(object, build); err != nil {
		return nil, err
	}
	if err := ParseContext(object, build); err != nil {
		return nil, err
	}
	if err := ParseExtends(object, build); err != nil {
		// we return build because it can be used to install plugin
		return build, err
	}
	if err := ParseProperties(object, build); err != nil {
		return nil, err
	}
	if err := ParseConfiguration(object, build); err != nil {
		return nil, err
	}
	if err := ParseEnvironment(object, build); err != nil {
		return nil, err
	}
	if err := ParseTargets(object, build); err != nil {
		return nil, err
	}
	return build, nil
}

// Return the build properties, including those inherited from parents
func (build *Build) GetProperties() util.Object {
	var properties = make(map[string]interface{})
	for _, parent := range build.Parents {
		for name, value := range parent.GetProperties() {
			properties[name] = value
		}
	}
	for name, value := range build.Properties {
		properties[name] = value
	}
	return properties
}

// Return the build environment, including those inherited from parents
func (build *Build) GetEnvironment() map[string]string {
	var environment = make(map[string]string)
	for _, parent := range build.Parents {
		for name, value := range parent.GetEnvironment() {
			environment[name] = value
		}
	}
	for name, value := range build.Environment {
		environment[name] = value
	}
	return environment
}

// Return the build targets, including those inherited from parents
func (build *Build) GetTargets() map[string]*Target {
	var targets = make(map[string]*Target)
	for _, parent := range build.Parents {
		for name, target := range parent.GetTargets() {
			targets[name] = target
		}
	}
	for name, target := range build.Targets {
		targets[name] = target
	}
	return targets
}

// Return target with given name. If not defined in build, return target
// inherited from parent
func (build *Build) GetTargetByName(name string) *Target {
	target, found := build.Targets[name]
	if found {
		return target
	} else {
		for _, parent := range build.Parents {
			target = parent.GetTargetByName(name)
			if target != nil {
				return target
			}
		}
	}
	return nil
}

// Initialize build:
// - Set build dir and change to it
// - Create context and set it for build
func (build *Build) Init() error {
	os.Chdir(build.Dir)
	context, err := NewContext(build)
	if err != nil {
		return fmt.Errorf("evaluating context: %v", err)
	}
	build.SetDir(build.Dir)
	build.SetContext(context)
	build.SetStack(NewStack())
	return nil
}

// Parse extends field of the build
func (build *Build) LoadParents() error {
	var parents []*Build
	for _, extend := range build.Extends {
		file := build.PluginPath(extend)
		parent, err := NewBuild(file)
		if err != nil {
			if err != nil {
				return fmt.Errorf("loading parent build file '%s': %v", extend, err)
			}
		}
		parents = append(parents, parent)
	}
	build.Parents = parents
	return nil
}

// Set the build directory, propagating to parents
func (build *Build) SetDir(dir string) {
	build.Dir = dir
	for _, parent := range build.Parents {
		parent.SetDir(dir)
	}
}

// Set the build context, propagating to parents
func (build *Build) SetContext(context *Context) {
	build.Context = context
	for _, parent := range build.Parents {
		parent.SetContext(context)
	}
}

// Set the build stack, propagating to parents
func (build *Build) SetStack(stack *Stack) {
	build.Stack = stack
	for _, parent := range build.Parents {
		parent.SetStack(stack)
	}
}

// Set command line properties, that overwrite build ones
func (build *Build) SetCommandLineProperties(props string) error {
	var object util.Object
	err := yaml.Unmarshal([]byte(props), &object)
	if err != nil {
		return fmt.Errorf("parsing command line properties: properties must be a map with string keys")
	}
	for name, value := range object {
		build.Properties[name] = value
	}
	return nil
}

// Return default targets. If none is defined in build, return those from
// parents
func (build *Build) GetDefault() []string {
	if len(build.Default) > 0 {
		return build.Default
	} else {
		for _, parent := range build.Parents {
			if len(parent.Default) > 0 {
				return parent.Default
			}
		}
		for _, parent := range build.Parents {
			parentDefault := parent.GetDefault()
			if len(parentDefault) > 0 {
				return parentDefault
			}
		}
	}
	return build.Default
}

// Run build given targets. If no target is given, run default one.
func (build *Build) Run(targets []string) error {
	if len(targets) == 0 {
		targets = build.GetDefault()
		if len(targets) == 0 {
			return fmt.Errorf("no default target")
		}
	}
	for _, target := range targets {
		err := build.RunTarget(target)
		if err != nil {
			return err
		}
	}
	return nil
}

// Run given target
func (build *Build) RunTarget(name string) error {
	target := build.GetTargetByName(name)
	if target == nil {
		return fmt.Errorf("target '%s' not found", name)
	}
	err := target.Run()
	if err != nil {
		return fmt.Errorf("running target '%s': %v", name, err)
	}
	return nil
}

// Run parent target
func (build *Build) RunParentTarget(name string) (bool, error) {
	for _, parent := range build.Parents {
		target := parent.GetTargetByName(name)
		if target != nil {
			err := target.RunSteps()
			if err != nil {
				return true, fmt.Errorf("running target '%s': %v", name, err)
			}
			return true, nil
		} else {
			ok, err := parent.RunParentTarget(name)
			if ok || err != nil {
				return ok, err
			}
		}
	}
	return false, nil
}

// Get parent build file path
func (build *Build) PluginPath(name string) string {
	if path.IsAbs(name) {
		return name
	} else if strings.HasPrefix(name, "./") {
		return filepath.Join(build.Dir, name)
	} else {
		repo := util.ExpandAndJoinToRoot(build.Dir, build.Repository)
		return filepath.Join(repo, name)
	}
}

// Get plugin name for given resource
func (build *Build) PluginName(name string) string {
	re := regexp.MustCompile(`^(` + RE_PLUGIN + `)/.+$`)
	if re.MatchString(name) {
		return re.FindStringSubmatch(name)[1]
	} else {
		return ""
	}
}

// Install given plugin
func (build *Build) Install(plugin string) error {
	re := regexp.MustCompile(`^` + RE_PLUGIN + `$`)
	if !re.MatchString(plugin) {
		return fmt.Errorf("plugin name '%s' is invalid", plugin)
	}
	path := build.PluginPath(plugin)
	if util.DirExists(path) {
		Message("Plugin '%s' already installed in '%s'", plugin, path)
		return nil
	}
	absolute := util.ExpandUserHome(path)
	repo := "git://github.com/" + plugin + ".git"
	command := exec.Command("git", "clone", repo, absolute)
	Message("Running command '%s'...", strings.Join(command.Args, " "))
	output, err := command.CombinedOutput()
	if err != nil {
		re = regexp.MustCompile("\n\n")
		message := re.ReplaceAllString(string(output), "\n")
		message = strings.TrimSpace(message)
		Message(message)
		return fmt.Errorf("installing plugin '%s'", plugin)
	} else {
		Message("Plugin '%s' installed in '%s'", plugin, path)
	}
	return nil
}
<|endoftext|>


<commit_before>package sqrt

import (
	"math"
)

// Calcutates square root of x using
// Newton's approximation up to p precison
// returning the square root and the number of
// iterations.
func Sqrt(x float64, p float64) (float64, int) {
	i := 0
	z := float64(1)
	d := float64(0)
	for math.Abs(z-d) > p {
		i++
		d = z
		z = z - ((z*z - x) / 2 * z)
	}
	return z, i
}
<commit_msg>simplify a little bit<commit_after>package sqrt

import (
	"math"
)

// Calcutates square root of x using
// Newton's approximation up to p precison
// returning the square root and the number of
// iterations.
func Sqrt(x float64, p float64) (float64, int) {
	i := 0
	z := float64(1)
	d := float64(0)
	for math.Abs(z-d) > p {
		i++
		d = z
		z -= (z*z - x) / (2 * z)
	}
	return z, i
}
<|endoftext|>