<commit_before>package data

import (
	"log"
)

var DEBUG_SIZE int = 100

type Reader struct {
	data []byte
	Cursor uint64
	Size uint64
}

// Creates a new Reader for reading the data from the byte array.
func NewReader (da []byte) *Reader {
	r := new(Reader)
	r.data = da
	r.Cursor = 0
	r.Size = uint64(len(da))
	return r
}

// Reads the number of bytes passed in as size from the data byte array in
// the Reader struct. It then concatinates the bytes and returns them as a
// unsigned integer.
func (r *Reader) Read(size uint) uint {

	var (
		value uint = 0
		i uint64 = 0
	)
	for ; i <uint64(size) ;i++ {
		value |= (uint(r.data[r.Cursor+i]) << ((uint64(size)-i-1)*8))
	}
	r.Cursor += uint64(size)
	return value
}

// Reads the number of bytes passed in as size from the data byte array in the Reader
// struct. It returns a byte array from the cursors current position to the cursor
// plus the size.

func (r *Reader) ReadBytes(size uint64) []byte {
	value:=r.data[r.Cursor:r.Cursor+size]
	r.Cursor += size
	return value
}
<commit_msg>Update data.go<commit_after>package data

var DEBUG_SIZE int = 100

type Reader struct {
	data []byte
	Cursor uint64
	Size uint64
}

// Creates a new Reader for reading the data from the byte array.
func NewReader (da []byte) *Reader {
	r := new(Reader)
	r.data = da
	r.Cursor = 0
	r.Size = uint64(len(da))
	return r
}

// Reads the number of bytes passed in as size from the data byte array in
// the Reader struct. It then concatinates the bytes and returns them as a
// unsigned integer.
func (r *Reader) Read(size uint) uint {

	var (
		value uint = 0
		i uint64 = 0
	)
	for ; i <uint64(size) ;i++ {
		value |= (uint(r.data[r.Cursor+i]) << ((uint64(size)-i-1)*8))
	}
	r.Cursor += uint64(size)
	return value
}

// Reads the number of bytes passed in as size from the data byte array in the Reader
// struct. It returns a byte array from the cursors current position to the cursor
// plus the size.

func (r *Reader) ReadBytes(size uint64) []byte {
	value:=r.data[r.Cursor:r.Cursor+size]
	r.Cursor += size
	return value
}
<|endoftext|>


<commit_before>package command

import (
	"context"
	"github.com/akaspin/cut"
	"github.com/akaspin/logx"
	"github.com/akaspin/soil/agent"
	"github.com/akaspin/soil/agent/api-v1"
	"github.com/akaspin/soil/agent/metadata"
	"github.com/akaspin/soil/agent/public"
	"github.com/akaspin/soil/agent/registry"
	"github.com/akaspin/soil/agent/scheduler"
	"github.com/akaspin/soil/api"
	"github.com/akaspin/soil/manifest"
	"github.com/akaspin/supervisor"
	"github.com/spf13/cobra"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"
)

type AgentOptions struct {
	Id string // Unique Agent ID

	ConfigPath []string // Paths to configuration files
	Meta       []string // Metadata set
	Address    string   // bind address

	Public public.BackendOptions
}

func (o *AgentOptions) Bind(cc *cobra.Command) {
	cc.Flags().StringVarP(&o.Id, "id", "", "localhost", "unique agent id")

	cc.Flags().StringArrayVarP(&o.ConfigPath, "config", "", []string{"/etc/soil/config.hcl"}, "configuration file")
	cc.Flags().StringArrayVarP(&o.Meta, "meta", "", nil, "node metadata in form field=value")
	cc.Flags().StringVarP(&o.Address, "address", "", ":7654", "listen address")

	cc.Flags().BoolVarP(&o.Public.Enabled, "public-enable", "", false, "enable public namespace clustering")
	cc.Flags().StringVarP(&o.Public.Advertise, "public-advertise", "", "127.0.0.1:7654", "advertise address public namespace")
	cc.Flags().StringVarP(&o.Public.URL, "public-backend", "", "consul://127.0.0.1:8500/soil", "backend url for public namespace")
	cc.Flags().DurationVarP(&o.Public.Timeout, "public-timeout", "", time.Second*30, "connect timeout for public namespace backend")
	cc.Flags().IntVarP(&o.Public.Retry, "public-retry", "", 0, "connection retry count for public namespace backend (0 to infinite)")
	cc.Flags().DurationVarP(&o.Public.RetryInterval, "public-retry-interval", "", time.Second*30, "public namespace backend connect retry interval")
	cc.Flags().DurationVarP(&o.Public.TTL, "public-ttl", "", time.Minute*5, "TTL for agent entries in public namespace backend")
}

type Agent struct {
	*cut.Environment
	*AgentOptions

	// reconfigurable
	config      *agent.Config
	privatePods []*manifest.Pod

	log             *logx.Log
	agentSource     *metadata.Plain
	metaSource      *metadata.Plain
	privateRegistry *registry.Private
}

func (c *Agent) Bind(cc *cobra.Command) {
	cc.Short = "Run agent"
}

func (c *Agent) Run(args ...string) (err error) {
	c.log = logx.GetLog("root")

	// parse configs
	c.readConfig()
	c.readPrivatePods()

	ctx := context.Background()

	// sources
	c.agentSource = metadata.NewPlain(ctx, c.log, "agent", false)
	c.metaSource = metadata.NewPlain(ctx, c.log, "meta", false)
	statusSource := metadata.NewAllocation(ctx, c.log)
	sourceSV := supervisor.NewGroup(ctx,
		c.agentSource,
		c.metaSource,
		statusSource,
	)

	//sink, manager, schedulerSv := scheduler.New(
	//	ctx, c.log,
	//	[]agent.EvaluationReporter{statusSource},
	//)
	manager := scheduler.NewManager(ctx, c.log)
	manager.AddProducer(c.agentSource, false, "private", "public")
	manager.AddProducer(c.metaSource, false, "private", "public")
	manager.AddProducer(statusSource, true, "private", "public")

	executor := scheduler.NewEvaluator(ctx, c.log)
	sink := scheduler.NewSink(ctx, c.log, executor, manager)

	schedulerSV := supervisor.NewChain(ctx,
		supervisor.NewGroup(ctx, executor, manager),
		sink,
	)

	c.privateRegistry = registry.NewPrivate(ctx, c.log, sink)

	// bind signals
	signalCh := make(chan os.Signal)
	signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)

	// Agent
	apiRouter := api.NewRouter()
	apiRouter.Get("/v1/agent/reload", api_v1.NewWrapper(func() (err error) {
		signalCh <- syscall.SIGHUP
		return
	}))
	apiRouter.Get("/v1/agent/stop", api_v1.NewWrapper(func() (err error) {
		signalCh <- syscall.SIGTERM
		return
	}))

	// Info
	statusInfoGetEndpoint := api_v1.NewStatusInfoGetEndpoint(ctx, c.agentSource, c.metaSource, statusSource)
	apiRouter.Get("/v1/status/ping", api_v1.NewPingEndpoint(c.Id))
	apiRouter.Get("/v1/status/info", statusInfoGetEndpoint)

	// drain
	apiRouter.Get("/v1/status/drain", api_v1.NewDrainGetEndpoint(c.Id, manager.DrainState))
	apiRouter.Put("/v1/agent/drain", api_v1.NewDrainPutEndpoint(manager.Drain))
	apiRouter.Delete("/v1/agent/drain", api_v1.NewDrainDeleteEndpoint(manager.Drain))

	apiServer := api.NewServer(ctx, c.log, c.Address, apiRouter)
	apiServerSV := supervisor.NewChain(ctx, statusInfoGetEndpoint, apiServer)

	// agent
	agentSV := supervisor.NewChain(ctx,
		sourceSV,
		schedulerSV,
		c.privateRegistry,
		apiServerSV,
	)

	if err = agentSV.Open(); err != nil {
		return
	}

	c.configureArbiters()
	c.configurePrivateRegistry()

LOOP:
	for {
		select {
		case sig := <-signalCh:
			switch sig {
			case syscall.SIGINT, syscall.SIGTERM:
				c.log.Infof("stop received")
				agentSV.Close()
				break LOOP
			case syscall.SIGHUP:
				c.log.Infof("reload received")
				c.reload()
			}
		case <-ctx.Done():
			break LOOP
		}
	}

	err = agentSV.Wait()
	c.log.Info("Bye")
	return
}

func (c *Agent) readConfig() {
	c.config = agent.DefaultConfig()
	for _, meta := range c.Meta {
		split := strings.SplitN(meta, "=", 2)
		if len(split) != 2 {
			c.log.Warningf("bad --meta=%s", meta)
			continue
		}
		c.config.Meta[split[0]] = split[1]
	}
	if err := c.config.Read(c.ConfigPath...); err != nil {
		c.log.Warningf("error reading config %s", err)
	}
	return
}

func (c *Agent) readPrivatePods() {
	var err error
	if c.privatePods, err = manifest.ParseFromFiles("private", c.ConfigPath...); err != nil {
		c.log.Warningf("error reading private pods %s", err)
	}
}

func (c *Agent) configureArbiters() {
	c.agentSource.Configure(map[string]string{
		"id":       c.Id,
		"pod_exec": c.config.Exec,
	})
	c.metaSource.Configure(c.config.Meta)
}

func (c *Agent) configurePrivateRegistry() (err error) {
	c.privateRegistry.Sync(c.privatePods)
	return
}

func (c *Agent) reload() (err error) {
	c.readConfig()
	c.readPrivatePods()
	c.configureArbiters()
	c.configurePrivateRegistry()
	return
}
<commit_msg>- temporary disable public options<commit_after>package command

import (
	"context"
	"github.com/akaspin/cut"
	"github.com/akaspin/logx"
	"github.com/akaspin/soil/agent"
	"github.com/akaspin/soil/agent/api-v1"
	"github.com/akaspin/soil/agent/metadata"
	"github.com/akaspin/soil/agent/public"
	"github.com/akaspin/soil/agent/registry"
	"github.com/akaspin/soil/agent/scheduler"
	"github.com/akaspin/soil/api"
	"github.com/akaspin/soil/manifest"
	"github.com/akaspin/supervisor"
	"github.com/spf13/cobra"
	"os"
	"os/signal"
	"strings"
	"syscall"
)

type AgentOptions struct {
	Id string // Unique Agent ID

	ConfigPath []string // Paths to configuration files
	Meta       []string // Metadata set
	Address    string   // bind address

	Public public.BackendOptions
}

func (o *AgentOptions) Bind(cc *cobra.Command) {
	cc.Flags().StringVarP(&o.Id, "id", "", "localhost", "unique agent id")

	cc.Flags().StringArrayVarP(&o.ConfigPath, "config", "", []string{"/etc/soil/config.hcl"}, "configuration file")
	cc.Flags().StringArrayVarP(&o.Meta, "meta", "", nil, "node metadata in form field=value")
	cc.Flags().StringVarP(&o.Address, "address", "", ":7654", "listen address")

	//cc.Flags().BoolVarP(&o.Public.Enabled, "public-enable", "", false, "enable public namespace clustering")
	//cc.Flags().StringVarP(&o.Public.Advertise, "public-advertise", "", "127.0.0.1:7654", "advertise address public namespace")
	//cc.Flags().StringVarP(&o.Public.URL, "public-backend", "", "consul://127.0.0.1:8500/soil", "backend url for public namespace")
	//cc.Flags().DurationVarP(&o.Public.Timeout, "public-timeout", "", time.Second*30, "connect timeout for public namespace backend")
	//cc.Flags().IntVarP(&o.Public.Retry, "public-retry", "", 0, "connection retry count for public namespace backend (0 to infinite)")
	//cc.Flags().DurationVarP(&o.Public.RetryInterval, "public-retry-interval", "", time.Second*30, "public namespace backend connect retry interval")
	//cc.Flags().DurationVarP(&o.Public.TTL, "public-ttl", "", time.Minute*5, "TTL for agent entries in public namespace backend")
}

type Agent struct {
	*cut.Environment
	*AgentOptions

	// reconfigurable
	config      *agent.Config
	privatePods []*manifest.Pod

	log             *logx.Log
	agentSource     *metadata.Plain
	metaSource      *metadata.Plain
	privateRegistry *registry.Private
}

func (c *Agent) Bind(cc *cobra.Command) {
	cc.Short = "Run agent"
}

func (c *Agent) Run(args ...string) (err error) {
	c.log = logx.GetLog("root")

	// parse configs
	c.readConfig()
	c.readPrivatePods()

	ctx := context.Background()

	// sources
	c.agentSource = metadata.NewPlain(ctx, c.log, "agent", false)
	c.metaSource = metadata.NewPlain(ctx, c.log, "meta", false)
	statusSource := metadata.NewAllocation(ctx, c.log)
	sourceSV := supervisor.NewGroup(ctx,
		c.agentSource,
		c.metaSource,
		statusSource,
	)

	//sink, manager, schedulerSv := scheduler.New(
	//	ctx, c.log,
	//	[]agent.EvaluationReporter{statusSource},
	//)
	manager := scheduler.NewManager(ctx, c.log)
	manager.AddProducer(c.agentSource, false, "private", "public")
	manager.AddProducer(c.metaSource, false, "private", "public")
	manager.AddProducer(statusSource, true, "private", "public")

	executor := scheduler.NewEvaluator(ctx, c.log)
	sink := scheduler.NewSink(ctx, c.log, executor, manager)

	schedulerSV := supervisor.NewChain(ctx,
		supervisor.NewGroup(ctx, executor, manager),
		sink,
	)

	c.privateRegistry = registry.NewPrivate(ctx, c.log, sink)

	// bind signals
	signalCh := make(chan os.Signal)
	signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)

	// Agent
	apiRouter := api.NewRouter()
	apiRouter.Get("/v1/agent/reload", api_v1.NewWrapper(func() (err error) {
		signalCh <- syscall.SIGHUP
		return
	}))
	apiRouter.Get("/v1/agent/stop", api_v1.NewWrapper(func() (err error) {
		signalCh <- syscall.SIGTERM
		return
	}))

	// Info
	statusInfoGetEndpoint := api_v1.NewStatusInfoGetEndpoint(ctx, c.agentSource, c.metaSource, statusSource)
	apiRouter.Get("/v1/status/ping", api_v1.NewPingEndpoint(c.Id))
	apiRouter.Get("/v1/status/info", statusInfoGetEndpoint)

	// drain
	apiRouter.Get("/v1/status/drain", api_v1.NewDrainGetEndpoint(c.Id, manager.DrainState))
	apiRouter.Put("/v1/agent/drain", api_v1.NewDrainPutEndpoint(manager.Drain))
	apiRouter.Delete("/v1/agent/drain", api_v1.NewDrainDeleteEndpoint(manager.Drain))

	apiServer := api.NewServer(ctx, c.log, c.Address, apiRouter)
	apiServerSV := supervisor.NewChain(ctx, statusInfoGetEndpoint, apiServer)

	// agent
	agentSV := supervisor.NewChain(ctx,
		sourceSV,
		schedulerSV,
		c.privateRegistry,
		apiServerSV,
	)

	if err = agentSV.Open(); err != nil {
		return
	}

	c.configureArbiters()
	c.configurePrivateRegistry()

LOOP:
	for {
		select {
		case sig := <-signalCh:
			switch sig {
			case syscall.SIGINT, syscall.SIGTERM:
				c.log.Infof("stop received")
				agentSV.Close()
				break LOOP
			case syscall.SIGHUP:
				c.log.Infof("reload received")
				c.reload()
			}
		case <-ctx.Done():
			break LOOP
		}
	}

	err = agentSV.Wait()
	c.log.Info("Bye")
	return
}

func (c *Agent) readConfig() {
	c.config = agent.DefaultConfig()
	for _, meta := range c.Meta {
		split := strings.SplitN(meta, "=", 2)
		if len(split) != 2 {
			c.log.Warningf("bad --meta=%s", meta)
			continue
		}
		c.config.Meta[split[0]] = split[1]
	}
	if err := c.config.Read(c.ConfigPath...); err != nil {
		c.log.Warningf("error reading config %s", err)
	}
	return
}

func (c *Agent) readPrivatePods() {
	var err error
	if c.privatePods, err = manifest.ParseFromFiles("private", c.ConfigPath...); err != nil {
		c.log.Warningf("error reading private pods %s", err)
	}
}

func (c *Agent) configureArbiters() {
	c.agentSource.Configure(map[string]string{
		"id":       c.Id,
		"pod_exec": c.config.Exec,
	})
	c.metaSource.Configure(c.config.Meta)
}

func (c *Agent) configurePrivateRegistry() (err error) {
	c.privateRegistry.Sync(c.privatePods)
	return
}

func (c *Agent) reload() (err error) {
	c.readConfig()
	c.readPrivatePods()
	c.configureArbiters()
	c.configurePrivateRegistry()
	return
}
<|endoftext|>


<commit_before>// Package xlog acts as a trivial extension of Go's log package.
// It provides functions to prefix the logged output with different
// log levels.
package xlog

import (
	"log"
)

func Debug(v ...interface{}) {
	log.Print(append([]interface{}{"[DEBUG] "}, v...)...)
}

func Debugf(format string, v ...interface{}) {
	log.Printf("[DEBUG] "+format, v...)
}

func Info(v ...interface{}) {
	log.Print(append([]interface{}{"[INFO]  "}, v...)...)
}

func Infof(format string, v ...interface{}) {
	log.Printf("[INFO]  "+format, v...)
}

func Warn(v ...interface{}) {
	log.Print(append([]interface{}{"[WARN]  "}, v...)...)
}

func Warnf(format string, v ...interface{}) {
	log.Printf("[WARN]  "+format, v...)
}

func Error(v ...interface{}) {
	log.Print(append([]interface{}{"[ERROR] "}, v...)...)
}

func Errorf(format string, v ...interface{}) {
	log.Printf("[ERROR] "+format, v...)
}

func Fatal(v ...interface{}) {
	log.Fatal(append([]interface{}{"[FATAL] "}, v...)...)
}

func Fatalf(format string, v ...interface{}) {
	log.Fatalf("[FATAL] "+format, v...)
}

func Panic(v ...interface{}) {
	log.Panic(append([]interface{}{"[PANIC] "}, v...)...)
}

func Panicf(format string, v ...interface{}) {
	log.Panicf("[PANIC] "+format, v...)
}

func Request(v ...interface{}) {
	log.Print(append([]interface{}{"[REQ]   "}, v...)...)
}

func Requestf(format string, v ...interface{}) {
	log.Printf("[REQ]   "+format, v...)
}
<commit_msg>implement SetOutput.<commit_after>// Package xlog acts as a trivial extension of Go's log package.
// It provides functions to prefix the logged output with different
// log levels.
package xlog

import (
	"io"
	"log"
)

func SetOutput(w io.Writer) {
	log.SetOutput(w)
}

func Debug(v ...interface{}) {
	log.Print(append([]interface{}{"[DEBUG] "}, v...)...)
}

func Debugf(format string, v ...interface{}) {
	log.Printf("[DEBUG] "+format, v...)
}

func Info(v ...interface{}) {
	log.Print(append([]interface{}{"[INFO]  "}, v...)...)
}

func Infof(format string, v ...interface{}) {
	log.Printf("[INFO]  "+format, v...)
}

func Warn(v ...interface{}) {
	log.Print(append([]interface{}{"[WARN]  "}, v...)...)
}

func Warnf(format string, v ...interface{}) {
	log.Printf("[WARN]  "+format, v...)
}

func Error(v ...interface{}) {
	log.Print(append([]interface{}{"[ERROR] "}, v...)...)
}

func Errorf(format string, v ...interface{}) {
	log.Printf("[ERROR] "+format, v...)
}

func Fatal(v ...interface{}) {
	log.Fatal(append([]interface{}{"[FATAL] "}, v...)...)
}

func Fatalf(format string, v ...interface{}) {
	log.Fatalf("[FATAL] "+format, v...)
}

func Panic(v ...interface{}) {
	log.Panic(append([]interface{}{"[PANIC] "}, v...)...)
}

func Panicf(format string, v ...interface{}) {
	log.Panicf("[PANIC] "+format, v...)
}

func Request(v ...interface{}) {
	log.Print(append([]interface{}{"[REQ]   "}, v...)...)
}

func Requestf(format string, v ...interface{}) {
	log.Printf("[REQ]   "+format, v...)
}
<|endoftext|>


<commit_before>package common

import (
	"fmt"
	"log"
	"strconv"
	"time"
)

// GitHubAPIKeyModel is a struct representing on individual github key in the database
type GitHubAPIKeyModel struct {
	Key                string
	RemainingUses      int
	RequestsPerHour    int
	RateLimitResetTime time.Time
}

// Should pass the number of remaining here instead of -1
// Pass remaining
func (apiKey *GitHubAPIKeyModel) incrementUsage(remainingRequests string, rateLimitResetTime string) {
	n, _ := strconv.ParseInt(rateLimitResetTime, 0, 64)
	resetTime := time.Unix(n, 0)
	l, _ := strconv.Atoi(remainingRequests)
	log.Println("Remaining uses in save ", l)
	apiKey.RemainingUses = l
	apiKey.RateLimitResetTime = resetTime
}

func (apiKey *GitHubAPIKeyModel) reset() {
	apiKey.RemainingUses = 5000
}

func (apiKey *GitHubAPIKeyModel) print() {
	fmt.Printf("%+v", apiKey)
}
<commit_msg>add sleep logic in the key model<commit_after>package common

import (
	"fmt"
	"log"
	"net/http"
	"strconv"
	"time"
)

var gitHubAPIBaseUrl = "https://api.github.com/"

// GitHubAPIKeyModel is a struct representing on individual github key in the database
type GitHubAPIKeyModel struct {
	Key                string
	RemainingUses      int
	RequestsPerHour    int
	RateLimitResetTime time.Time
}

// Should pass the number of remaining here instead of -1
// Pass remaining
func (apiKey *GitHubAPIKeyModel) incrementUsage(remainingRequests string, rateLimitResetTime string) {
	n, _ := strconv.ParseInt(rateLimitResetTime, 0, 64)
	resetTime := time.Unix(n, 0)
	l, _ := strconv.Atoi(remainingRequests)
	log.Println("Remaining uses in save ", l)
	apiKey.RemainingUses = l
	apiKey.RateLimitResetTime = resetTime
}

// TODO sent request to api route thats passed in
// TODO should return error
func (apiKey *GitHubAPIKeyModel) prime() {
	githubURL := gitHubAPIBaseUrl + "repos/a/b" + "?access_token=" + apiKey.Key
	log.Println(githubURL)
	resp, err := http.Get(githubURL)
	if err != nil {
	}
	defer resp.Body.Close()
	responseHeader := resp.Header
	remaingRequests := responseHeader.Get("X-RateLimit-Remaining")
	rateLimitResetTime := responseHeader.Get("X-RateLimit-Reset")
	apiKey.incrementUsage(remaingRequests, rateLimitResetTime)
}

func (apiKey *GitHubAPIKeyModel) reset() {
	apiKey.RemainingUses = 5000
}

func (apiKey *GitHubAPIKeyModel) print() {
	fmt.Printf("%+v", apiKey)
}
<|endoftext|>


<commit_before>package environment

import (
	"fmt"
	"strconv"
	"strings"
)

// A set of environment variables that are exported by each driver.
const (
	// The path to the alloc directory that is shared across tasks within a task
	// group.
	AllocDir = "NOMAD_ALLOC_DIR"

	// The tasks memory limit in MBs.
	MemLimit = "NOMAD_MEMORY_LIMIT"

	// The tasks limit in MHz.
	CpuLimit = "NOMAD_CPU_LIMIT"

	// The IP address for the task.
	TaskIP = "NOMAD_IP"

	// Prefix for passing both dynamic and static port allocations to
	// tasks.
	// E.g. $NOMAD_PORT_1 or $NOMAD_PORT_http
	PortPrefix = "NOMAD_PORT_"

	// Prefix for passing task meta data.
	MetaPrefix = "NOMAD_META_"
)

type TaskEnvironment map[string]string

func NewTaskEnivornment() TaskEnvironment {
	return make(map[string]string)
}

// Parses a list of strings with NAME=value pairs and returns a TaskEnvironment.
func ParseFromList(envVars []string) (TaskEnvironment, error) {
	t := NewTaskEnivornment()

	for _, pair := range envVars {
		parts := strings.Split(pair, "=")
		if len(parts) != 2 {
			return nil, fmt.Errorf("Couldn't parse environment variable: %v", pair)
		}

		t[parts[0]] = parts[1]
	}

	return t, nil
}

// Returns a list of strings with NAME=value pairs.
func (t TaskEnvironment) List() []string {
	env := []string{}
	for k, v := range t {
		env = append(env, fmt.Sprintf("%s=%s", k, v))
	}

	return env
}

func (t TaskEnvironment) Map() map[string]string {
	return t
}

func (t TaskEnvironment) SetAllocDir(dir string) {
	t[AllocDir] = dir
}

func (t TaskEnvironment) SetMemLimit(limit int) {
	t[MemLimit] = strconv.Itoa(limit)
}

func (t TaskEnvironment) SetCpuLimit(limit int) {
	t[CpuLimit] = strconv.Itoa(limit)
}

func (t TaskEnvironment) SetTaskIp(ip string) {
	t[TaskIP] = ip
}

// Takes a map of port labels to their port value.
func (t TaskEnvironment) SetPorts(ports map[string]int) {
	for label, port := range ports {
		t[fmt.Sprintf("%s%s", PortPrefix, label)] = strconv.Itoa(port)
	}
}

// Takes a map of meta values to be passed to the task. The keys are capatilized
// when the environent variable is set.
func (t TaskEnvironment) SetMeta(m map[string]string) {
	for k, v := range m {
		t[fmt.Sprintf("%s%s", MetaPrefix, strings.ToUpper(k))] = v
	}
}

func (t TaskEnvironment) SetEnvvars(m map[string]string) {
	for k, v := range m {
		t[strings.ToUpper(k)] = v
	}
}
<commit_msg>Removed capitalization of user-defined envvars.<commit_after>package environment

import (
	"fmt"
	"strconv"
	"strings"
)

// A set of environment variables that are exported by each driver.
const (
	// The path to the alloc directory that is shared across tasks within a task
	// group.
	AllocDir = "NOMAD_ALLOC_DIR"

	// The tasks memory limit in MBs.
	MemLimit = "NOMAD_MEMORY_LIMIT"

	// The tasks limit in MHz.
	CpuLimit = "NOMAD_CPU_LIMIT"

	// The IP address for the task.
	TaskIP = "NOMAD_IP"

	// Prefix for passing both dynamic and static port allocations to
	// tasks.
	// E.g. $NOMAD_PORT_1 or $NOMAD_PORT_http
	PortPrefix = "NOMAD_PORT_"

	// Prefix for passing task meta data.
	MetaPrefix = "NOMAD_META_"
)

type TaskEnvironment map[string]string

func NewTaskEnivornment() TaskEnvironment {
	return make(map[string]string)
}

// Parses a list of strings with NAME=value pairs and returns a TaskEnvironment.
func ParseFromList(envVars []string) (TaskEnvironment, error) {
	t := NewTaskEnivornment()

	for _, pair := range envVars {
		parts := strings.Split(pair, "=")
		if len(parts) != 2 {
			return nil, fmt.Errorf("Couldn't parse environment variable: %v", pair)
		}

		t[parts[0]] = parts[1]
	}

	return t, nil
}

// Returns a list of strings with NAME=value pairs.
func (t TaskEnvironment) List() []string {
	env := []string{}
	for k, v := range t {
		env = append(env, fmt.Sprintf("%s=%s", k, v))
	}

	return env
}

func (t TaskEnvironment) Map() map[string]string {
	return t
}

func (t TaskEnvironment) SetAllocDir(dir string) {
	t[AllocDir] = dir
}

func (t TaskEnvironment) SetMemLimit(limit int) {
	t[MemLimit] = strconv.Itoa(limit)
}

func (t TaskEnvironment) SetCpuLimit(limit int) {
	t[CpuLimit] = strconv.Itoa(limit)
}

func (t TaskEnvironment) SetTaskIp(ip string) {
	t[TaskIP] = ip
}

// Takes a map of port labels to their port value.
func (t TaskEnvironment) SetPorts(ports map[string]int) {
	for label, port := range ports {
		t[fmt.Sprintf("%s%s", PortPrefix, label)] = strconv.Itoa(port)
	}
}

// Takes a map of meta values to be passed to the task. The keys are capatilized
// when the environent variable is set.
func (t TaskEnvironment) SetMeta(m map[string]string) {
	for k, v := range m {
		t[fmt.Sprintf("%s%s", MetaPrefix, strings.ToUpper(k))] = v
	}
}

func (t TaskEnvironment) SetEnvvars(m map[string]string) {
	for k, v := range m {
		t[k] = v
	}
}
<|endoftext|>


<commit_before>package commands

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

	"github.com/fatih/color"
	fastly "github.com/sethvargo/go-fastly"
	"github.com/sirupsen/logrus"
)

// Diff compares local VCL to the specificed remote service vcl version
func Diff(f flags.Flags) {
	configureSkipMatch(f)

	client, err := fastly.NewClient(*f.Top.Token)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// store value rather than dereference pointer multiple times later
	fastlyServiceID = *f.Top.Service

	latestVersion, err := getLatestVCLVersion(client)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	selectedVersion := latestVersion

	if *f.Sub.VclVersion != "" {
		selectedVersion = *f.Sub.VclVersion
	}

	processFiles(selectedVersion, getVCL, processDiff, f, client)
}

func getVCL(selectedVersion, path string, client *fastly.Client, ch chan vclResponse) {
	defer wg.Done()

	logger.WithFields(logrus.Fields{
		"channel":  fmt.Sprintf("%p", ch),
		"length":   len(ch),
		"capacity": cap(ch),
	}).Debug("channel view - start of getVCL")

	name := extractName(path)

	v, err := strconv.Atoi(selectedVersion)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	logger.WithFields(logrus.Fields{
		"path": path,
		"name": name,
	}).Debug("file processor")

	vclFile, err := client.GetVCL(&fastly.GetVCLInput{
		Service: fastlyServiceID,
		Version: v,
		Name:    name,
	})

	if err != nil {
		errMsg := fmt.Sprintf("error: %s", err)

		logger.WithFields(logrus.Fields{
			"name":  name,
			"error": errMsg,
		}).Debug("error retrieving vcl file from fastly")

		ch <- vclResponse{
			Path:    path,
			Name:    name,
			Content: errMsg,
			Error:   true,
		}

		logger.WithFields(logrus.Fields{
			"channel":  fmt.Sprintf("%p", ch),
			"length":   len(ch),
			"capacity": cap(ch),
		}).Debug("channel view - failed retrieval")
	} else {
		logger.WithField("name", name).Debug("successfully retrieved vcl file from fastly")

		ch <- vclResponse{
			Path:    path,
			Name:    name,
			Content: vclFile.Content,
			Error:   false,
		}

		logger.WithFields(logrus.Fields{
			"channel":  fmt.Sprintf("%p", ch),
			"length":   len(ch),
			"capacity": cap(ch),
		}).Debug("channel view - successful retrieval")
	}
}

func processDiff(vr vclResponse, debug bool, selectedVersion string) {
	var (
		err    error
		cmdOut []byte
	)
	cmdName := "diff"
	cmdArgs := []string{
		"--ignore-all-space",
		"--ignore-blank-lines",
		"--ignore-matching-lines",
		"^[[:space:]]\\+#",
		"-", // the dash (-) indicates that the first file comes from stdin
		vr.Path,
	}
	cmd := exec.Command(cmdName, cmdArgs...)
	cmd.Stdin = strings.NewReader(vr.Content)

	if cmdOut, err = cmd.Output(); err != nil {
		color.Red("\nThere was a difference between the version (%s) of '%s' and the version found locally\n\t%s\n", selectedVersion, vr.Name, vr.Path)

		if debug == true {
			fmt.Printf("\n%s\n", string(cmdOut))
		}
	} else {
		color.Green("\nNo difference between the version (%s) of '%s' and the version found locally\n\t%s\n", selectedVersion, vr.Name, vr.Path)
	}
}
<commit_msg>Refactor: don't make unnecessary call<commit_after>package commands

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

	"github.com/fatih/color"
	fastly "github.com/sethvargo/go-fastly"
	"github.com/sirupsen/logrus"
)

// Diff compares local VCL to the specificed remote service vcl version
func Diff(f flags.Flags) {
	configureSkipMatch(f)

	client, err := fastly.NewClient(*f.Top.Token)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// store value rather than dereference pointer multiple times later
	fastlyServiceID = *f.Top.Service

	var selectedVersion string

	if *f.Sub.VclVersion != "" {
		selectedVersion = *f.Sub.VclVersion
	} else {
		latestVersion, err := getLatestVCLVersion(client)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		selectedVersion = latestVersion
	}

	processFiles(selectedVersion, getVCL, processDiff, f, client)
}

func getVCL(selectedVersion, path string, client *fastly.Client, ch chan vclResponse) {
	defer wg.Done()

	logger.WithFields(logrus.Fields{
		"channel":  fmt.Sprintf("%p", ch),
		"length":   len(ch),
		"capacity": cap(ch),
	}).Debug("channel view - start of getVCL")

	name := extractName(path)

	v, err := strconv.Atoi(selectedVersion)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	logger.WithFields(logrus.Fields{
		"path": path,
		"name": name,
	}).Debug("file processor")

	vclFile, err := client.GetVCL(&fastly.GetVCLInput{
		Service: fastlyServiceID,
		Version: v,
		Name:    name,
	})

	if err != nil {
		errMsg := fmt.Sprintf("error: %s", err)

		logger.WithFields(logrus.Fields{
			"name":  name,
			"error": errMsg,
		}).Debug("error retrieving vcl file from fastly")

		ch <- vclResponse{
			Path:    path,
			Name:    name,
			Content: errMsg,
			Error:   true,
		}

		logger.WithFields(logrus.Fields{
			"channel":  fmt.Sprintf("%p", ch),
			"length":   len(ch),
			"capacity": cap(ch),
		}).Debug("channel view - failed retrieval")
	} else {
		logger.WithField("name", name).Debug("successfully retrieved vcl file from fastly")

		ch <- vclResponse{
			Path:    path,
			Name:    name,
			Content: vclFile.Content,
			Error:   false,
		}

		logger.WithFields(logrus.Fields{
			"channel":  fmt.Sprintf("%p", ch),
			"length":   len(ch),
			"capacity": cap(ch),
		}).Debug("channel view - successful retrieval")
	}
}

func processDiff(vr vclResponse, debug bool, selectedVersion string) {
	var (
		err    error
		cmdOut []byte
	)
	cmdName := "diff"
	cmdArgs := []string{
		"--ignore-all-space",
		"--ignore-blank-lines",
		"--ignore-matching-lines",
		"^[[:space:]]\\+#",
		"-", // the dash (-) indicates that the first file comes from stdin
		vr.Path,
	}
	cmd := exec.Command(cmdName, cmdArgs...)
	cmd.Stdin = strings.NewReader(vr.Content)

	if cmdOut, err = cmd.Output(); err != nil {
		color.Red("\nThere was a difference between the version (%s) of '%s' and the version found locally\n\t%s\n", selectedVersion, vr.Name, vr.Path)

		if debug == true {
			fmt.Printf("\n%s\n", string(cmdOut))
		}
	} else {
		color.Green("\nNo difference between the version (%s) of '%s' and the version found locally\n\t%s\n", selectedVersion, vr.Name, vr.Path)
	}
}
<|endoftext|>


<commit_before>package iso

import (
	"bytes"
	"fmt"
	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

type StepExport struct {
	Format string
}

func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction {
	c := state.Get("config").(*Config)
	ui := state.Get("ui").(packer.Ui)

	if c.RemoteType != "esx5" || s.Format == "" {
		return multistep.ActionContinue
	}

	ovftool := "ovftool"
	if runtime.GOOS == "windows" {
		ovftool = "ovftool.exe"
	}

	if _, err := exec.LookPath(ovftool); err != nil {
		err := fmt.Errorf("Error %s not found: %s", ovftool, err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	// Export the VM
	outputPath := filepath.Join(c.VMName, c.VMName+"."+s.Format)

	if s.Format == "ova" {
		os.MkdirAll(outputPath, 0755)
	}

	args := []string{
		"--noSSLVerify=true",
		"--skipManifestCheck",
		"-tt=" + s.Format,
		"vi://" + c.RemoteUser + ":" + url.QueryEscape(c.RemotePassword) + "@" + c.RemoteHost + "/" + c.VMName,
		outputPath,
	}

	ui.Say("Exporting virtual machine...")
	ui.Message(fmt.Sprintf("Executing: %s %s", ovftool, strings.Join(args, " ")))
	var out bytes.Buffer
	cmd := exec.Command(ovftool, args...)
	cmd.Stdout = &out
	if err := cmd.Run(); err != nil {
		err := fmt.Errorf("Error exporting virtual machine: %s\n%s\n", err, out.String())
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	ui.Message(fmt.Sprintf("%s", out.String()))

	state.Put("exportPath", outputPath)

	return multistep.ActionContinue
}

func (s *StepExport) Cleanup(state multistep.StateBag) {}
<commit_msg>builder/vmware-esxi: hide password in ovftool command<commit_after>package iso

import (
	"bytes"
	"fmt"
	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

type StepExport struct {
	Format string
}

func (s *StepExport) generateArgs(c *Config, outputPath string, hidePassword bool) []string {
	password := url.QueryEscape(c.RemotePassword)
	if hidePassword {
		password = "****"
	}
	return []string{
		"--noSSLVerify=true",
		"--skipManifestCheck",
		"-tt=" + s.Format,
		"vi://" + c.RemoteUser + ":" + password + "@" + c.RemoteHost + "/" + c.VMName,
		outputPath,
	}
}

func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction {
	c := state.Get("config").(*Config)
	ui := state.Get("ui").(packer.Ui)

	if c.RemoteType != "esx5" || s.Format == "" {
		return multistep.ActionContinue
	}

	ovftool := "ovftool"
	if runtime.GOOS == "windows" {
		ovftool = "ovftool.exe"
	}

	if _, err := exec.LookPath(ovftool); err != nil {
		err := fmt.Errorf("Error %s not found: %s", ovftool, err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	// Export the VM
	outputPath := filepath.Join(c.VMName, c.VMName+"."+s.Format)

	if s.Format == "ova" {
		os.MkdirAll(outputPath, 0755)
	}

	ui.Say("Exporting virtual machine...")
	ui.Message(fmt.Sprintf("Executing: %s %s", ovftool, strings.Join(s.generateArgs(c, outputPath, true), " ")))
	var out bytes.Buffer
	cmd := exec.Command(ovftool, s.generateArgs(c, outputPath, false)...)
	cmd.Stdout = &out
	if err := cmd.Run(); err != nil {
		err := fmt.Errorf("Error exporting virtual machine: %s\n%s\n", err, out.String())
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	ui.Message(fmt.Sprintf("%s", out.String()))

	state.Put("exportPath", outputPath)

	return multistep.ActionContinue
}

func (s *StepExport) Cleanup(state multistep.StateBag) {}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/xml"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"text/template"
)

const TMPAPKPATH = "tmpapk-directory"

var (
	format  = flag.String("f", "{{.package}}/{{.activity}}", "output format")
	apkpath = flag.String("apk", "", "android pkg path")
)

func ParseApk() error {
	toolpath := filepath.Join(SelfDir(), "apktool.jar")
	fmt.Println(toolpath)
	c := exec.Command("java", "-jar", toolpath, "decode", "--force", *apkpath, TMPAPKPATH)
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr
	return c.Run()
}

func SelfDir() string {
	selfDir := filepath.Dir(os.Args[0])
	if !filepath.IsAbs(selfDir) {
		selfDir, _ = filepath.Abs(selfDir)
	}
	return selfDir
}

func ParseManifest() (pkgname string, activity string, err error) {
	manifest := filepath.Join(TMPAPKPATH, "AndroidManifest.xml")
	data, err := ioutil.ReadFile(manifest)
	if err != nil {
		return
	}
	mf := new(Manifest)
	if err = xml.Unmarshal(data, mf); err != nil {
		return
	}
	for _, act := range mf.Application.Activities {
		if act.IntentFilter.Action.Name == "android.intent.action.MAIN" {
			activity = act.Name
			break
		}
	}
	return mf.Package, activity, nil
}

func main() {
	flag.Parse()
	if *apkpath == "" {
		log.Fatal("need apkpath")
	}
	if err := ParseApk(); err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(TMPAPKPATH)

	pkgname, activity, err := ParseManifest()
	if err != nil {
		log.Fatal(err)
	}
	wr := bytes.NewBuffer(nil)
	tmpl, err := template.New("t").Parse(*format)
	if err != nil {
		log.Fatal(err)
	}
	tmpl.Execute(wr, map[string]string{
		"package":  pkgname,
		"activity": activity})
	fmt.Println(string(wr.Bytes()))
}
<commit_msg>add apkview<commit_after>package main

import (
	"bytes"
	"encoding/xml"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"text/template"
)

var TMPAPKPATH string

func init() {
	TMPAPKPATH, _ = ioutil.TempDir(".", "apktmp-") //"tmpapk-directory"
}

var (
	format  = flag.String("f", "{{.package}}/{{.activity}}", "output format")
	apkpath = flag.String("apk", "", "android pkg path")
)

func ParseApk() error {
	toolpath := filepath.Join(SelfDir(), "apktool.jar")
	fmt.Println(toolpath)
	c := exec.Command("java", "-jar", toolpath, "decode", "--force", *apkpath, TMPAPKPATH)
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr
	return c.Run()
}

func SelfDir() string {
	selfDir := filepath.Dir(os.Args[0])
	if !filepath.IsAbs(selfDir) {
		selfDir, _ = filepath.Abs(selfDir)
	}
	return selfDir
}

func ParseManifest() (pkgname string, activity string, err error) {
	manifest := filepath.Join(TMPAPKPATH, "AndroidManifest.xml")
	data, err := ioutil.ReadFile(manifest)
	if err != nil {
		return
	}
	mf := new(Manifest)
	if err = xml.Unmarshal(data, mf); err != nil {
		return
	}
	for _, act := range mf.Application.Activities {
		if act.IntentFilter.Action.Name == "android.intent.action.MAIN" {
			activity = act.Name
			break
		}
	}
	return mf.Package, activity, nil
}

func main() {
	defer os.RemoveAll(TMPAPKPATH)
	flag.Parse()
	if *apkpath == "" {
		log.Fatal("need apkpath")
	}
	if err := ParseApk(); err != nil {
		log.Fatal(err)
	}

	pkgname, activity, err := ParseManifest()
	if err != nil {
		log.Fatal(err)
	}
	wr := bytes.NewBuffer(nil)
	tmpl, err := template.New("t").Parse(*format)
	if err != nil {
		log.Fatal(err)
	}
	tmpl.Execute(wr, map[string]string{
		"package":  pkgname,
		"activity": activity})
	fmt.Println(string(wr.Bytes()))
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/hex"
	"filepicker"
	"fmt"
	"getcommandline"
	"hash"
	"io"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"tokenize"
)

/*
  REVISION HISTORY
  ----------------
   6 Apr 13 -- First modified version of module.  I will use VLI to compare all digits of the hashes.
  23 Apr 13 -- Fixed problem of a single line in the hashes file, that does not contain an EOL character, causes
                an immediate return without processing of the characters just read in.
  24 Apr 13 -- Added output of which file either matches or does not match.
  19 Sep 16 -- Finished conversion to Go, that was started 13 Sep 16.  Added the removed of '*' which is part of a std linux formated hash file.  And I forgot that
                 the routine allowed either order in the file.  If the token has a '.' I assume it is a filename, else it is a hash value.
  21 Sep 16 -- Fixed the case issue in tokenize.GetToken.  Edited code here to correspond to this fix.
  25 Nov 16 -- Need to not panic when target file is not found, only panic when hash file is not found.
                 And added a LastCompiled message and string.
  13 Oct 17 -- No changes here, but tokenize was changed so that horizontal tab char is now a delim.
  14 Oct 17 -- Tweaked output a bit.  And added executable timestamp code.
  19 Oct 17 -- Added ability to ignore the * that standard hash files for linux use.
  22 Oct 17 -- Added filepicker.
  21 Jan 18 -- Really ignore *.  Before method did not work.
  26 Jan 18 -- Changed tokenize so that SetMapDelim change sticks.
  13 Nov 18 -- Will use "-" and "_" also to detech a filename token.
*/

const LastCompiled = "13 Nov 2018"

//* ************************* MAIN ***************************************************************
func main() {

	const K = 1024
	const M = 1024 * 1024

	const (
		md5hash = iota
		sha1hash
		sha256hash
		sha384hash
		sha512hash
		HashType
	)

	const ReadBufferSize = M
	//  const ReadBufferSize = 80 * M;

	var HashName = [...]string{"md5", "sha1", "sha256", "sha384", "sha512"}
	var inbuf, ans, Filename string
	var WhichHash int
	var readErr error
	var TargetFilename, HashValueReadFromFile, HashValueComputedStr string
	var hasher hash.Hash
	var FileSize int64

	fmt.Print(" comparehashes written in Go.  GOOS =", runtime.GOOS, ".  ARCH=", runtime.GOARCH)

	fmt.Println(".  Last altered", LastCompiled)
	//            fmt.Println(".  HashType = md5, sha1, sha256, sha384, sha512.  WhichHash = ",HashName[WhichHash]);
	workingdir, _ := os.Getwd()
	execname, _ := os.Executable()
	ExecFI, _ := os.Stat(execname)
	LastLinkedTimeStamp := ExecFI.ModTime().Format("Mon Jan 2 2006 15:04:05 MST")
	fmt.Printf("%s has timestamp of %s.  Working directory is %s.  Full name of executable is %s.\n", ExecFI.Name(), LastLinkedTimeStamp, workingdir, execname)
	fmt.Println()

	// filepicker stuff.

	if len(os.Args) <= 1 { // need to use filepicker
		filenames := filepicker.GetFilenames("*.sha*")
		for i := 0; i < min(len(filenames), 10); i++ {
			fmt.Println("filename[", i, "] is", filenames[i])
		}
		fmt.Print(" Enter filename choice : ")
		fmt.Scanln(&ans)
		if len(ans) == 0 {
			ans = "0"
		}
		i, err := strconv.Atoi(ans)
		if err == nil {
			Filename = filenames[i]
		} else {
			s := strings.ToUpper(ans)
			s = strings.TrimSpace(s)
			s0 := s[0]
			i = int(s0 - 'A')
			Filename = filenames[i]
		}
		fmt.Println(" Picked filename is", Filename)
	} else { // will use filename entered on commandline
		Filename = getcommandline.GetCommandLineString()
	}

	fmt.Println()

	// process extension

	extension := filepath.Ext(Filename)
	extension = strings.ToLower(extension)
	switch extension {
	case ".md5":
		WhichHash = md5hash
	case ".sha1":
		WhichHash = sha1hash
	case ".sha256":
		WhichHash = sha256hash
	case ".sha384":
		WhichHash = sha384hash
	case ".sha512":
		WhichHash = sha512hash
	default:
		fmt.Println()
		fmt.Println()
		fmt.Println(" Not a recognized hash extension.  Will assume sha1.")
		WhichHash = sha1hash
	} // switch case on extension for HashType

	fmt.Println()

	// Read and parse the file with the hashes.

	HashesFile, err := os.Open(Filename)
	if os.IsNotExist(err) {
		fmt.Println(inbuf, " does not exist.")
		os.Exit(1)
	} else { // we know that the file exists
		check(err, " Error opening hashes file.")
	}
	defer HashesFile.Close()

	scanner := bufio.NewScanner(HashesFile)
	//	scanner.Split(bufio.ScanLines) // I believe this is the default.  I may experiment to see if I need this line for my code to work, AFTER I debug it as it is.

	for { /* to read multiple lines */
		FileSize = 0
		readSuccess := scanner.Scan()
		if !readSuccess {
			break
		} // end main reading loop

		inputline := scanner.Text()
		if readErr = scanner.Err(); readErr != nil {
			if readErr == io.EOF {
				break
			} // reached EOF condition, so there are no more lines to read.
			fmt.Fprintln(os.Stderr, "Unknown error while reading from the HashesFile :", readErr)
			os.Exit(1)
		}

		if strings.HasPrefix(inputline, ";") || strings.HasPrefix(inputline, "#") || (len(inputline) <= 10) {
			continue
		} /* allow comments and essentially blank lines */

		//	inputline = strings.Replace(inputline, "*", " ", -1) // just blank out the * char
		tokenize.INITKN(inputline)

		tokenize.SetMapDelim('*') // this should now work, as of 01/26/2018

		FirstToken, EOL := tokenize.GetTokenString(false)

		if EOL {
			fmt.Errorf(" Error while getting 1st token in the hashing file.  Skipping")
			continue
		}

		if strings.ContainsRune(FirstToken.Str, '.') || strings.ContainsRune(FirstToken.Str, '-') ||
			strings.ContainsRune(FirstToken.Str, '_') { /* have filename first on line */
			TargetFilename = FirstToken.Str
			SecondToken, EOL := tokenize.GetTokenString(false) // Get hash string from the line in the file
			if EOL {
				fmt.Errorf(" Got EOL while getting HashValue (2nd) token in the hashing file.  Skipping \n")
				continue
			} /* if EOL */
			HashValueReadFromFile = SecondToken.Str

		} else { /* have hash first on line */
			HashValueReadFromFile = FirstToken.Str
			SecondToken, EOL := tokenize.GetTokenString(false) // Get name of file on which to compute the hash
			if EOL {
				fmt.Errorf(" Error while gatting TargetFilename token in the hashing file.  Skipping \n")
				continue
			} /* if EOL */

			if strings.ContainsRune(SecondToken.Str, '*') { // If it contains a *, it will be the first position.
				SecondToken.Str = SecondToken.Str[1:]
				if strings.ContainsRune(SecondToken.Str, '*') { // this should not happen
					fmt.Println(" Filename token still contains a * character.  Str:", SecondToken.Str, "  Skipping.")
					continue
				}
			}
			TargetFilename = (SecondToken.Str)
		} /* if have filename first or hash value first */

		/*
		   now to compute the hash, compare them, and output results
		*/
		/* Create Hash Section */
		TargetFile, err := os.Open(TargetFilename)
		//    exists := true;
		if os.IsNotExist(err) {
			fmt.Println(TargetFilename, " does not exist.")
			continue
		} else { // we know that the file exists
			check(err, " Error opening TargetFilename.")
		}

		defer TargetFile.Close()

		switch WhichHash { // Initialing case switch on WhichHash
		case md5hash:
			hasher = md5.New()
		case sha1hash:
			hasher = sha1.New()
		case sha256hash:
			hasher = sha256.New()
		case sha384hash:
			hasher = sha512.New384()
		case sha512hash:
			hasher = sha512.New()
		default:
			hasher = sha256.New()
		} /* initializing switch case on WhichHash */

		/*    This loop works, but there is a much shorter way.  I got this after asking for help on the mailing list.
		      FileReadBuffer := make([]byte,ReadBufferSize);
		      for {   // Repeat Until eof loop.
		        n,err := TargetFile.Read(FileReadBuffer);
		        if n == 0 || err == io.EOF { break }
		        check(err," Unexpected error while reading the target file on which to compute the hash,");
		        hasher.Write(FileReadBuffer[:n]);
		        FileSize += int64(n);
		      } // Repeat Until TargetFile.eof loop;
		*/

		FileSize, readErr = io.Copy(hasher, TargetFile)
		HashValueComputedStr = hex.EncodeToString(hasher.Sum(nil))

		// I got the idea to use the different base64 versions and my own hex converter code, just to see.
		// And I can also use sfprintf with the %x verb.  base64 versions are not useful as they use a larger
		// character set than hex.  I deleted all references to the base64 versions.  And the hex encoded and
		// sprintf using %x were the same, so I removed the sprintf code.
		//    HashValueComputedSprintf := fmt.Sprintf("%x",hasher.Sum(nil));

		//		fmt.Println(" Filename  = ", TargetFilename, ", FileSize = ", FileSize, ", ", HashName[WhichHash], " computed hash string -- ")
		fmt.Printf(" Filename  = %s, filesize = %d, using hash %s.\n", TargetFilename, FileSize, HashName[WhichHash])
		fmt.Println("       Read From File:", HashValueReadFromFile)
		fmt.Println(" Computed hex encoded:", HashValueComputedStr)
		//    fmt.Println(" Computed sprintf:",HashValueComputedSprintf);

		if HashValueReadFromFile == HashValueComputedStr {
			fmt.Print(" Matched.")
		} else {
			fmt.Print(" Not matched.")
		} /* if hashes */
		TargetFile.Close() // Close the handle to allow opening a target from the next line, if there is one.
		fmt.Println()
		fmt.Println()
		fmt.Println()
	} /* outer LOOP to read multiple lines */

	HashesFile.Close() // Don't really need this because of the defer statement.
	fmt.Println()
} // Main for comparehashes.go.

// ------------------------------------------------------- check -------------------------------
func check(e error, msg string) {
	if e != nil {
		fmt.Errorf("%s : ", msg)
		panic(e)
	}
}

// ------------------------------------------------------- min ---------------------------------
func min(a, b int) int {
	if a < b {
		return a
	} else {
		return b
	}
}
<commit_msg>11/10/2019 06:39:53 PM	modified:   comparehashes/comparehashes.go<commit_after>package main

import (
	"bufio"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/hex"
	"filepicker"
	"fmt"
	"getcommandline"
	"hash"
	"io"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"tokenize"
)

/*
  REVISION HISTORY
  ----------------
   6 Apr 13 -- First modified version of module.  I will use VLI to compare all digits of the hashes.
  23 Apr 13 -- Fixed problem of a single line in the hashes file, that does not contain an EOL character, causes
                an immediate return without processing of the characters just read in.
  24 Apr 13 -- Added output of which file either matches or does not match.
  19 Sep 16 -- Finished conversion to Go, that was started 13 Sep 16.  Added the removed of '*' which is part of a std linux formated hash file.  And I forgot that
                 the routine allowed either order in the file.  If the token has a '.' I assume it is a filename, else it is a hash value.
  21 Sep 16 -- Fixed the case issue in tokenize.GetToken.  Edited code here to correspond to this fix.
  25 Nov 16 -- Need to not panic when target file is not found, only panic when hash file is not found.
                 And added a LastCompiled message and string.
  13 Oct 17 -- No changes here, but tokenize was changed so that horizontal tab char is now a delim.
  14 Oct 17 -- Tweaked output a bit.  And added executable timestamp code.
  19 Oct 17 -- Added ability to ignore the * that standard hash files for linux use.
  22 Oct 17 -- Added filepicker.
  21 Jan 18 -- Really ignore *.  Before method did not work.
  26 Jan 18 -- Changed tokenize so that SetMapDelim change sticks.
  13 Nov 18 -- Will use "-" and "_" also to detech a filename token.
  10 Nov 19 -- Now uses ToLower to compare the string hashes, to ignore case.
*/

const LastCompiled = "10 Nov 2019"

//* ************************* MAIN ***************************************************************
func main() {

	const K = 1024
	const M = 1024 * 1024

	const (
		md5hash = iota
		sha1hash
		sha256hash
		sha384hash
		sha512hash
		HashType
	)

	const ReadBufferSize = M
	//  const ReadBufferSize = 80 * M;

	var HashName = [...]string{"md5", "sha1", "sha256", "sha384", "sha512"}
	var inbuf, ans, Filename string
	var WhichHash int
	var readErr error
	var TargetFilename, HashValueReadFromFile, HashValueComputedStr string
	var hasher hash.Hash
	var FileSize int64

	fmt.Print(" comparehashes written in Go.  GOOS =", runtime.GOOS, ".  ARCH=", runtime.GOARCH)

	fmt.Println(".  Last altered", LastCompiled)
	//            fmt.Println(".  HashType = md5, sha1, sha256, sha384, sha512.  WhichHash = ",HashName[WhichHash]);
	workingdir, _ := os.Getwd()
	execname, _ := os.Executable()
	ExecFI, _ := os.Stat(execname)
	LastLinkedTimeStamp := ExecFI.ModTime().Format("Mon Jan 2 2006 15:04:05 MST")
	fmt.Printf("%s has timestamp of %s.  Working directory is %s.  Full name of executable is %s.\n", ExecFI.Name(), LastLinkedTimeStamp, workingdir, execname)
	fmt.Println()

	// filepicker stuff.

	if len(os.Args) <= 1 { // need to use filepicker
		filenames := filepicker.GetFilenames("*.sha*")
		for i := 0; i < min(len(filenames), 10); i++ {
			fmt.Println("filename[", i, "] is", filenames[i])
		}
		fmt.Print(" Enter filename choice : ")
		fmt.Scanln(&ans)
		if len(ans) == 0 {
			ans = "0"
		}
		i, err := strconv.Atoi(ans)
		if err == nil {
			Filename = filenames[i]
		} else {
			s := strings.ToUpper(ans)
			s = strings.TrimSpace(s)
			s0 := s[0]
			i = int(s0 - 'A')
			Filename = filenames[i]
		}
		fmt.Println(" Picked filename is", Filename)
	} else { // will use filename entered on commandline
		Filename = getcommandline.GetCommandLineString()
	}

	fmt.Println()

	// process extension

	extension := filepath.Ext(Filename)
	extension = strings.ToLower(extension)
	switch extension {
	case ".md5":
		WhichHash = md5hash
	case ".sha1":
		WhichHash = sha1hash
	case ".sha256":
		WhichHash = sha256hash
	case ".sha384":
		WhichHash = sha384hash
	case ".sha512":
		WhichHash = sha512hash
	default:
		fmt.Println()
		fmt.Println()
		fmt.Println(" Not a recognized hash extension.  Will assume sha1.")
		WhichHash = sha1hash
	} // switch case on extension for HashType

	fmt.Println()

	// Read and parse the file with the hashes.

	HashesFile, err := os.Open(Filename)
	if os.IsNotExist(err) {
		fmt.Println(inbuf, " does not exist.")
		os.Exit(1)
	} else { // we know that the file exists
		check(err, " Error opening hashes file.")
	}
	defer HashesFile.Close()

	scanner := bufio.NewScanner(HashesFile)
	//	scanner.Split(bufio.ScanLines) // I believe this is the default.  I may experiment to see if I need this line for my code to work, AFTER I debug it as it is.

	for { /* to read multiple lines */
		FileSize = 0
		readSuccess := scanner.Scan()
		if !readSuccess {
			break
		} // end main reading loop

		inputline := scanner.Text()
		if readErr = scanner.Err(); readErr != nil {
			if readErr == io.EOF {
				break
			} // reached EOF condition, so there are no more lines to read.
			fmt.Fprintln(os.Stderr, "Unknown error while reading from the HashesFile :", readErr)
			os.Exit(1)
		}

		if strings.HasPrefix(inputline, ";") || strings.HasPrefix(inputline, "#") || (len(inputline) <= 10) {
			continue
		} /* allow comments and essentially blank lines */

		//	inputline = strings.Replace(inputline, "*", " ", -1) // just blank out the * char
		tokenize.INITKN(inputline)

		tokenize.SetMapDelim('*') // this should now work, as of 01/26/2018

		FirstToken, EOL := tokenize.GetTokenString(false)

		if EOL {
			fmt.Errorf(" Error while getting 1st token in the hashing file.  Skipping")
			continue
		}

		if strings.ContainsRune(FirstToken.Str, '.') || strings.ContainsRune(FirstToken.Str, '-') ||
			strings.ContainsRune(FirstToken.Str, '_') { /* have filename first on line */
			TargetFilename = FirstToken.Str
			SecondToken, EOL := tokenize.GetTokenString(false) // Get hash string from the line in the file
			if EOL {
				fmt.Errorf(" Got EOL while getting HashValue (2nd) token in the hashing file.  Skipping \n")
				continue
			} /* if EOL */
			HashValueReadFromFile = SecondToken.Str

		} else { /* have hash first on line */
			HashValueReadFromFile = FirstToken.Str
			SecondToken, EOL := tokenize.GetTokenString(false) // Get name of file on which to compute the hash
			if EOL {
				fmt.Errorf(" Error while gatting TargetFilename token in the hashing file.  Skipping \n")
				continue
			} /* if EOL */

			if strings.ContainsRune(SecondToken.Str, '*') { // If it contains a *, it will be the first position.
				SecondToken.Str = SecondToken.Str[1:]
				if strings.ContainsRune(SecondToken.Str, '*') { // this should not happen
					fmt.Println(" Filename token still contains a * character.  Str:", SecondToken.Str, "  Skipping.")
					continue
				}
			}
			TargetFilename = (SecondToken.Str)
		} /* if have filename first or hash value first */

		/*
		   now to compute the hash, compare them, and output results
		*/
		/* Create Hash Section */
		TargetFile, err := os.Open(TargetFilename)
		//    exists := true;
		if os.IsNotExist(err) {
			fmt.Println(TargetFilename, " does not exist.")
			continue
		} else { // we know that the file exists
			check(err, " Error opening TargetFilename.")
		}

		defer TargetFile.Close()

		switch WhichHash { // Initialing case switch on WhichHash
		case md5hash:
			hasher = md5.New()
		case sha1hash:
			hasher = sha1.New()
		case sha256hash:
			hasher = sha256.New()
		case sha384hash:
			hasher = sha512.New384()
		case sha512hash:
			hasher = sha512.New()
		default:
			hasher = sha256.New()
		} /* initializing switch case on WhichHash */

		/*    This loop works, but there is a much shorter way.  I got this after asking for help on the mailing list.
		      FileReadBuffer := make([]byte,ReadBufferSize);
		      for {   // Repeat Until eof loop.
		        n,err := TargetFile.Read(FileReadBuffer);
		        if n == 0 || err == io.EOF { break }
		        check(err," Unexpected error while reading the target file on which to compute the hash,");
		        hasher.Write(FileReadBuffer[:n]);
		        FileSize += int64(n);
		      } // Repeat Until TargetFile.eof loop;
		*/

		FileSize, readErr = io.Copy(hasher, TargetFile)
		HashValueComputedStr = hex.EncodeToString(hasher.Sum(nil))

		// I got the idea to use the different base64 versions and my own hex converter code, just to see.
		// And I can also use sfprintf with the %x verb.  base64 versions are not useful as they use a larger
		// character set than hex.  I deleted all references to the base64 versions.  And the hex encoded and
		// sprintf using %x were the same, so I removed the sprintf code.
		//    HashValueComputedSprintf := fmt.Sprintf("%x",hasher.Sum(nil));

		//		fmt.Println(" Filename  = ", TargetFilename, ", FileSize = ", FileSize, ", ", HashName[WhichHash], " computed hash string -- ")
		fmt.Printf(" Filename  = %s, filesize = %d, using hash %s.\n", TargetFilename, FileSize, HashName[WhichHash])
		fmt.Println("       Read From File:", HashValueReadFromFile)
		fmt.Println(" Computed hex encoded:", HashValueComputedStr)
		//    fmt.Println(" Computed sprintf:",HashValueComputedSprintf);

		if strings.ToLower(HashValueReadFromFile) == strings.ToLower(HashValueComputedStr) {
			fmt.Print(" Matched.")
		} else {
			fmt.Print(" Not matched.")
		} /* if hashes */
		TargetFile.Close() // Close the handle to allow opening a target from the next line, if there is one.
		fmt.Println()
		fmt.Println()
		fmt.Println()
	} /* outer LOOP to read multiple lines */

	HashesFile.Close() // Don't really need this because of the defer statement.
	fmt.Println()
} // Main for comparehashes.go.

// ------------------------------------------------------- check -------------------------------
func check(e error, msg string) {
	if e != nil {
		fmt.Errorf("%s : ", msg)
		panic(e)
	}
}

// ------------------------------------------------------- min ---------------------------------
func min(a, b int) int {
	if a < b {
		return a
	} else {
		return b
	}
}
<|endoftext|>


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

// Package gif implements a GIF image decoder.
//
// The GIF specification is at http://www.w3.org/Graphics/GIF/spec-gif89a.txt.
package gif

import (
	"bufio"
	"compress/lzw"
	"fmt"
	"image"
	"io"
	"os"
)

// If the io.Reader does not also have ReadByte, then decode will introduce its own buffering.
type reader interface {
	io.Reader
	io.ByteReader
}

// Masks etc.
const (
	// Fields.
	fColorMapFollows = 1 << 7

	// Image fields.
	ifInterlace = 1 << 6

	// Graphic control flags.
	gcTransparentColorSet = 1 << 0
)

// Section indicators.
const (
	sExtension       = 0x21
	sImageDescriptor = 0x2C
	sTrailer         = 0x3B
)

// Extensions.
const (
	eText           = 0x01 // Plain Text
	eGraphicControl = 0xF9 // Graphic Control
	eComment        = 0xFE // Comment
	eApplication    = 0xFF // Application
)

// decoder is the type used to decode a GIF file.
type decoder struct {
	r reader

	// From header.
	vers            string
	width           int
	height          int
	flags           byte
	headerFields    byte
	backgroundIndex byte
	loopCount       int
	delayTime       int

	// Unused from header.
	aspect byte

	// From image descriptor.
	imageFields byte

	// From graphics control.
	transparentIndex byte

	// Computed.
	pixelSize      uint
	globalColorMap image.PalettedColorModel

	// Used when decoding.
	delay []int
	image []*image.Paletted
	tmp   [1024]byte // must be at least 768 so we can read color map
}

// blockReader parses the block structure of GIF image data, which
// comprises (n, (n bytes)) blocks, with 1 <= n <= 255.  It is the
// reader given to the LZW decoder, which is thus immune to the
// blocking.  After the LZW decoder completes, there will be a 0-byte
// block remaining (0, ()), but under normal execution blockReader
// doesn't consume it, so it is handled in decode.
type blockReader struct {
	r     reader
	slice []byte
	tmp   [256]byte
}

func (b *blockReader) Read(p []byte) (int, os.Error) {
	if len(p) == 0 {
		return 0, nil
	}
	if len(b.slice) == 0 {
		blockLen, err := b.r.ReadByte()
		if err != nil {
			return 0, err
		}
		if blockLen == 0 {
			return 0, os.EOF
		}
		b.slice = b.tmp[0:blockLen]
		if _, err = io.ReadFull(b.r, b.slice); err != nil {
			return 0, err
		}
	}
	n := copy(p, b.slice)
	b.slice = b.slice[n:]
	return n, nil
}

// decode reads a GIF image from r and stores the result in d.
func (d *decoder) decode(r io.Reader, configOnly bool) os.Error {
	// Add buffering if r does not provide ReadByte.
	if rr, ok := r.(reader); ok {
		d.r = rr
	} else {
		d.r = bufio.NewReader(r)
	}

	err := d.readHeaderAndScreenDescriptor()
	if err != nil {
		return err
	}
	if configOnly {
		return nil
	}

	if d.headerFields&fColorMapFollows != 0 {
		if d.globalColorMap, err = d.readColorMap(); err != nil {
			return err
		}
	}

Loop:
	for err == nil {
		var c byte
		c, err = d.r.ReadByte()
		if err == os.EOF {
			break
		}
		switch c {
		case sExtension:
			err = d.readExtension()

		case sImageDescriptor:
			var m *image.Paletted
			m, err = d.newImageFromDescriptor()
			if err != nil {
				break
			}
			if d.imageFields&fColorMapFollows != 0 {
				m.Palette, err = d.readColorMap()
				if err != nil {
					break
				}
				// TODO: do we set transparency in this map too? That would be
				// d.setTransparency(m.Palette)
			} else {
				m.Palette = d.globalColorMap
			}
			var litWidth uint8
			litWidth, err = d.r.ReadByte()
			if err != nil {
				return err
			}
			if litWidth < 2 || litWidth > 8 {
				return fmt.Errorf("gif: pixel size in decode out of range: %d", litWidth)
			}
			// A wonderfully Go-like piece of magic.
			lzwr := lzw.NewReader(&blockReader{r: d.r}, lzw.LSB, int(litWidth))
			if _, err = io.ReadFull(lzwr, m.Pix); err != nil {
				break
			}

			// There should be a "0" block remaining; drain that.
			c, err = d.r.ReadByte()
			if err != nil {
				return err
			}
			if c != 0 {
				return os.NewError("gif: extra data after image")
			}

			// Undo the interlacing if necessary.
			d.uninterlace(m)

			d.image = append(d.image, m)
			d.delay = append(d.delay, d.delayTime)
			d.delayTime = 0 // TODO: is this correct, or should we hold on to the value?

		case sTrailer:
			break Loop

		default:
			err = fmt.Errorf("gif: unknown block type: 0x%.2x", c)
		}
	}
	if err != nil {
		return err
	}
	if len(d.image) == 0 {
		return io.ErrUnexpectedEOF
	}
	return nil
}

func (d *decoder) readHeaderAndScreenDescriptor() os.Error {
	_, err := io.ReadFull(d.r, d.tmp[0:13])
	if err != nil {
		return err
	}
	d.vers = string(d.tmp[0:6])
	if d.vers != "GIF87a" && d.vers != "GIF89a" {
		return fmt.Errorf("gif: can't recognize format %s", d.vers)
	}
	d.width = int(d.tmp[6]) + int(d.tmp[7])<<8
	d.height = int(d.tmp[8]) + int(d.tmp[9])<<8
	d.headerFields = d.tmp[10]
	d.backgroundIndex = d.tmp[11]
	d.aspect = d.tmp[12]
	d.loopCount = -1
	d.pixelSize = uint(d.headerFields&7) + 1
	return nil
}

func (d *decoder) readColorMap() (image.PalettedColorModel, os.Error) {
	if d.pixelSize > 8 {
		return nil, fmt.Errorf("gif: can't handle %d bits per pixel", d.pixelSize)
	}
	numColors := 1 << d.pixelSize
	numValues := 3 * numColors
	_, err := io.ReadFull(d.r, d.tmp[0:numValues])
	if err != nil {
		return nil, fmt.Errorf("gif: short read on color map: %s", err)
	}
	colorMap := make(image.PalettedColorModel, numColors)
	j := 0
	for i := range colorMap {
		colorMap[i] = image.RGBAColor{d.tmp[j+0], d.tmp[j+1], d.tmp[j+2], 0xFF}
		j += 3
	}
	return colorMap, nil
}

func (d *decoder) readExtension() os.Error {
	extension, err := d.r.ReadByte()
	if err != nil {
		return err
	}
	size := 0
	switch extension {
	case eText:
		size = 13
	case eGraphicControl:
		return d.readGraphicControl()
	case eComment:
		// nothing to do but read the data.
	case eApplication:
		b, err := d.r.ReadByte()
		if err != nil {
			return err
		}
		// The spec requires size be 11, but Adobe sometimes uses 10.
		size = int(b)
	default:
		return fmt.Errorf("gif: unknown extension 0x%.2x", extension)
	}
	if size > 0 {
		if _, err := io.ReadFull(d.r, d.tmp[0:size]); err != nil {
			return err
		}
	}

	// Application Extension with "NETSCAPE2.0" as string and 1 in data means
	// this extension defines a loop count.
	if extension == eApplication && string(d.tmp[:size]) == "NETSCAPE2.0" {
		n, err := d.readBlock()
		if n == 0 || err != nil {
			return err
		}
		if n == 3 && d.tmp[0] == 1 {
			d.loopCount = int(d.tmp[1]) | int(d.tmp[2])<<8
		}
	}
	for {
		n, err := d.readBlock()
		if n == 0 || err != nil {
			return err
		}
	}
	panic("unreachable")
}

func (d *decoder) readGraphicControl() os.Error {
	if _, err := io.ReadFull(d.r, d.tmp[0:6]); err != nil {
		return fmt.Errorf("gif: can't read graphic control: %s", err)
	}
	d.flags = d.tmp[1]
	d.delayTime = int(d.tmp[2]) | int(d.tmp[3])<<8
	if d.flags&gcTransparentColorSet != 0 {
		d.transparentIndex = d.tmp[4]
		d.setTransparency(d.globalColorMap)
	}
	return nil
}

func (d *decoder) setTransparency(colorMap image.PalettedColorModel) {
	if int(d.transparentIndex) < len(colorMap) {
		colorMap[d.transparentIndex] = image.RGBAColor{}
	}
}

func (d *decoder) newImageFromDescriptor() (*image.Paletted, os.Error) {
	if _, err := io.ReadFull(d.r, d.tmp[0:9]); err != nil {
		return nil, fmt.Errorf("gif: can't read image descriptor: %s", err)
	}
	// TODO: This code (throughout) ignores the top and left values,
	// and assumes (in interlacing, for example) that the images'
	// widths and heights are all the same.
	_ = int(d.tmp[0]) + int(d.tmp[1])<<8 // TODO: honor left value
	_ = int(d.tmp[2]) + int(d.tmp[3])<<8 // TODO: honor top value
	width := int(d.tmp[4]) + int(d.tmp[5])<<8
	height := int(d.tmp[6]) + int(d.tmp[7])<<8
	d.imageFields = d.tmp[8]
	return image.NewPaletted(width, height, nil), nil
}

func (d *decoder) readBlock() (int, os.Error) {
	n, err := d.r.ReadByte()
	if n == 0 || err != nil {
		return 0, err
	}
	return io.ReadFull(d.r, d.tmp[0:n])
}

// interlaceScan defines the ordering for a pass of the interlace algorithm.
type interlaceScan struct {
	skip, start int
}

// interlacing represents the set of scans in an interlaced GIF image.
var interlacing = []interlaceScan{
	{8, 0}, // Group 1 : Every 8th. row, starting with row 0.
	{8, 4}, // Group 2 : Every 8th. row, starting with row 4.
	{4, 2}, // Group 3 : Every 4th. row, starting with row 2.
	{2, 1}, // Group 4 : Every 2nd. row, starting with row 1.
}

func (d *decoder) uninterlace(m *image.Paletted) {
	if d.imageFields&ifInterlace == 0 {
		return
	}
	var nPix []uint8
	dx := d.width
	dy := d.height
	nPix = make([]uint8, dx*dy)
	offset := 0 // steps through the input by sequential scan lines.
	for _, pass := range interlacing {
		nOffset := pass.start * dx // steps through the output as defined by pass.
		for y := pass.start; y < dy; y += pass.skip {
			copy(nPix[nOffset:nOffset+dx], m.Pix[offset:offset+dx])
			offset += dx
			nOffset += dx * pass.skip
		}
	}
	m.Pix = nPix
}

// Decode reads a GIF image from r and returns the first embedded
// image as an image.Image.
func Decode(r io.Reader) (image.Image, os.Error) {
	var d decoder
	if err := d.decode(r, false); err != nil {
		return nil, err
	}
	return d.image[0], nil
}

// GIF represents the possibly multiple images stored in a GIF file.
type GIF struct {
	Image     []*image.Paletted // The successive images.
	Delay     []int             // The successive delay times, one per frame, in 100ths of a second.
	LoopCount int               // The loop count.
}

// DecodeAll reads a GIF image from r and returns the sequential frames
// and timing information.
func DecodeAll(r io.Reader) (*GIF, os.Error) {
	var d decoder
	if err := d.decode(r, false); err != nil {
		return nil, err
	}
	gif := &GIF{
		Image:     d.image,
		LoopCount: d.loopCount,
		Delay:     d.delay,
	}
	return gif, nil
}

// DecodeConfig returns the global color model and dimensions of a GIF image
// without decoding the entire image.
func DecodeConfig(r io.Reader) (image.Config, os.Error) {
	var d decoder
	if err := d.decode(r, true); err != nil {
		return image.Config{}, err
	}
	return image.Config{d.globalColorMap, d.width, d.height}, nil
}

func init() {
	image.RegisterFormat("gif", "GIF8?a", Decode, DecodeConfig)
}
<commit_msg>gif: fix local color map and coordinates<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package gif implements a GIF image decoder.
//
// The GIF specification is at http://www.w3.org/Graphics/GIF/spec-gif89a.txt.
package gif

import (
	"bufio"
	"compress/lzw"
	"fmt"
	"image"
	"io"
	"os"
)

// If the io.Reader does not also have ReadByte, then decode will introduce its own buffering.
type reader interface {
	io.Reader
	io.ByteReader
}

// Masks etc.
const (
	// Fields.
	fColorMapFollows = 1 << 7

	// Image fields.
	ifLocalColorTable = 1 << 7
	ifInterlace       = 1 << 6
	ifPixelSizeMask   = 7

	// Graphic control flags.
	gcTransparentColorSet = 1 << 0
)

// Section indicators.
const (
	sExtension       = 0x21
	sImageDescriptor = 0x2C
	sTrailer         = 0x3B
)

// Extensions.
const (
	eText           = 0x01 // Plain Text
	eGraphicControl = 0xF9 // Graphic Control
	eComment        = 0xFE // Comment
	eApplication    = 0xFF // Application
)

// decoder is the type used to decode a GIF file.
type decoder struct {
	r reader

	// From header.
	vers            string
	width           int
	height          int
	flags           byte
	headerFields    byte
	backgroundIndex byte
	loopCount       int
	delayTime       int

	// Unused from header.
	aspect byte

	// From image descriptor.
	imageFields byte

	// From graphics control.
	transparentIndex byte

	// Computed.
	pixelSize      uint
	globalColorMap image.PalettedColorModel

	// Used when decoding.
	delay []int
	image []*image.Paletted
	tmp   [1024]byte // must be at least 768 so we can read color map
}

// blockReader parses the block structure of GIF image data, which
// comprises (n, (n bytes)) blocks, with 1 <= n <= 255.  It is the
// reader given to the LZW decoder, which is thus immune to the
// blocking.  After the LZW decoder completes, there will be a 0-byte
// block remaining (0, ()), but under normal execution blockReader
// doesn't consume it, so it is handled in decode.
type blockReader struct {
	r     reader
	slice []byte
	tmp   [256]byte
}

func (b *blockReader) Read(p []byte) (int, os.Error) {
	if len(p) == 0 {
		return 0, nil
	}
	if len(b.slice) == 0 {
		blockLen, err := b.r.ReadByte()
		if err != nil {
			return 0, err
		}
		if blockLen == 0 {
			return 0, os.EOF
		}
		b.slice = b.tmp[0:blockLen]
		if _, err = io.ReadFull(b.r, b.slice); err != nil {
			return 0, err
		}
	}
	n := copy(p, b.slice)
	b.slice = b.slice[n:]
	return n, nil
}

// decode reads a GIF image from r and stores the result in d.
func (d *decoder) decode(r io.Reader, configOnly bool) os.Error {
	// Add buffering if r does not provide ReadByte.
	if rr, ok := r.(reader); ok {
		d.r = rr
	} else {
		d.r = bufio.NewReader(r)
	}

	err := d.readHeaderAndScreenDescriptor()
	if err != nil {
		return err
	}
	if configOnly {
		return nil
	}

	if d.headerFields&fColorMapFollows != 0 {
		if d.globalColorMap, err = d.readColorMap(); err != nil {
			return err
		}
	}

Loop:
	for err == nil {
		var c byte
		c, err = d.r.ReadByte()
		if err == os.EOF {
			break
		}
		switch c {
		case sExtension:
			err = d.readExtension()

		case sImageDescriptor:
			var m *image.Paletted
			m, err = d.newImageFromDescriptor()
			if err != nil {
				break
			}
			if d.imageFields&fColorMapFollows != 0 {
				m.Palette, err = d.readColorMap()
				if err != nil {
					break
				}
				// TODO: do we set transparency in this map too? That would be
				// d.setTransparency(m.Palette)
			} else {
				m.Palette = d.globalColorMap
			}
			var litWidth uint8
			litWidth, err = d.r.ReadByte()
			if err != nil {
				return err
			}
			if litWidth < 2 || litWidth > 8 {
				return fmt.Errorf("gif: pixel size in decode out of range: %d", litWidth)
			}
			// A wonderfully Go-like piece of magic.
			lzwr := lzw.NewReader(&blockReader{r: d.r}, lzw.LSB, int(litWidth))
			if _, err = io.ReadFull(lzwr, m.Pix); err != nil {
				break
			}

			// There should be a "0" block remaining; drain that.
			c, err = d.r.ReadByte()
			if err != nil {
				return err
			}
			if c != 0 {
				return os.NewError("gif: extra data after image")
			}

			// Undo the interlacing if necessary.
			if d.imageFields&ifInterlace != 0 {
				uninterlace(m)
			}

			d.image = append(d.image, m)
			d.delay = append(d.delay, d.delayTime)
			d.delayTime = 0 // TODO: is this correct, or should we hold on to the value?

		case sTrailer:
			break Loop

		default:
			err = fmt.Errorf("gif: unknown block type: 0x%.2x", c)
		}
	}
	if err != nil {
		return err
	}
	if len(d.image) == 0 {
		return io.ErrUnexpectedEOF
	}
	return nil
}

func (d *decoder) readHeaderAndScreenDescriptor() os.Error {
	_, err := io.ReadFull(d.r, d.tmp[0:13])
	if err != nil {
		return err
	}
	d.vers = string(d.tmp[0:6])
	if d.vers != "GIF87a" && d.vers != "GIF89a" {
		return fmt.Errorf("gif: can't recognize format %s", d.vers)
	}
	d.width = int(d.tmp[6]) + int(d.tmp[7])<<8
	d.height = int(d.tmp[8]) + int(d.tmp[9])<<8
	d.headerFields = d.tmp[10]
	d.backgroundIndex = d.tmp[11]
	d.aspect = d.tmp[12]
	d.loopCount = -1
	d.pixelSize = uint(d.headerFields&7) + 1
	return nil
}

func (d *decoder) readColorMap() (image.PalettedColorModel, os.Error) {
	if d.pixelSize > 8 {
		return nil, fmt.Errorf("gif: can't handle %d bits per pixel", d.pixelSize)
	}
	numColors := 1 << d.pixelSize
	if d.imageFields&ifLocalColorTable != 0 {
		numColors = 1 << ((d.imageFields & ifPixelSizeMask) + 1)
	}
	numValues := 3 * numColors
	_, err := io.ReadFull(d.r, d.tmp[0:numValues])
	if err != nil {
		return nil, fmt.Errorf("gif: short read on color map: %s", err)
	}
	colorMap := make(image.PalettedColorModel, numColors)
	j := 0
	for i := range colorMap {
		colorMap[i] = image.RGBAColor{d.tmp[j+0], d.tmp[j+1], d.tmp[j+2], 0xFF}
		j += 3
	}
	return colorMap, nil
}

func (d *decoder) readExtension() os.Error {
	extension, err := d.r.ReadByte()
	if err != nil {
		return err
	}
	size := 0
	switch extension {
	case eText:
		size = 13
	case eGraphicControl:
		return d.readGraphicControl()
	case eComment:
		// nothing to do but read the data.
	case eApplication:
		b, err := d.r.ReadByte()
		if err != nil {
			return err
		}
		// The spec requires size be 11, but Adobe sometimes uses 10.
		size = int(b)
	default:
		return fmt.Errorf("gif: unknown extension 0x%.2x", extension)
	}
	if size > 0 {
		if _, err := io.ReadFull(d.r, d.tmp[0:size]); err != nil {
			return err
		}
	}

	// Application Extension with "NETSCAPE2.0" as string and 1 in data means
	// this extension defines a loop count.
	if extension == eApplication && string(d.tmp[:size]) == "NETSCAPE2.0" {
		n, err := d.readBlock()
		if n == 0 || err != nil {
			return err
		}
		if n == 3 && d.tmp[0] == 1 {
			d.loopCount = int(d.tmp[1]) | int(d.tmp[2])<<8
		}
	}
	for {
		n, err := d.readBlock()
		if n == 0 || err != nil {
			return err
		}
	}
	panic("unreachable")
}

func (d *decoder) readGraphicControl() os.Error {
	if _, err := io.ReadFull(d.r, d.tmp[0:6]); err != nil {
		return fmt.Errorf("gif: can't read graphic control: %s", err)
	}
	d.flags = d.tmp[1]
	d.delayTime = int(d.tmp[2]) | int(d.tmp[3])<<8
	if d.flags&gcTransparentColorSet != 0 {
		d.transparentIndex = d.tmp[4]
		d.setTransparency(d.globalColorMap)
	}
	return nil
}

func (d *decoder) setTransparency(colorMap image.PalettedColorModel) {
	if int(d.transparentIndex) < len(colorMap) {
		colorMap[d.transparentIndex] = image.RGBAColor{}
	}
}

func (d *decoder) newImageFromDescriptor() (*image.Paletted, os.Error) {
	if _, err := io.ReadFull(d.r, d.tmp[0:9]); err != nil {
		return nil, fmt.Errorf("gif: can't read image descriptor: %s", err)
	}
	left := int(d.tmp[0]) + int(d.tmp[1])<<8
	top := int(d.tmp[2]) + int(d.tmp[3])<<8
	width := int(d.tmp[4]) + int(d.tmp[5])<<8
	height := int(d.tmp[6]) + int(d.tmp[7])<<8
	d.imageFields = d.tmp[8]
	m := image.NewPaletted(width, height, nil)
	// Overwrite the rectangle to take account of left and top.
	m.Rect = image.Rect(left, top, left+width, top+height)
	return m, nil
}

func (d *decoder) readBlock() (int, os.Error) {
	n, err := d.r.ReadByte()
	if n == 0 || err != nil {
		return 0, err
	}
	return io.ReadFull(d.r, d.tmp[0:n])
}

// interlaceScan defines the ordering for a pass of the interlace algorithm.
type interlaceScan struct {
	skip, start int
}

// interlacing represents the set of scans in an interlaced GIF image.
var interlacing = []interlaceScan{
	{8, 0}, // Group 1 : Every 8th. row, starting with row 0.
	{8, 4}, // Group 2 : Every 8th. row, starting with row 4.
	{4, 2}, // Group 3 : Every 4th. row, starting with row 2.
	{2, 1}, // Group 4 : Every 2nd. row, starting with row 1.
}

// uninterlace rearranges the pixels in m to account for interlaced input.
func uninterlace(m *image.Paletted) {
	var nPix []uint8
	dx := m.Bounds().Dx()
	dy := m.Bounds().Dy()
	nPix = make([]uint8, dx*dy)
	offset := 0 // steps through the input by sequential scan lines.
	for _, pass := range interlacing {
		nOffset := pass.start * dx // steps through the output as defined by pass.
		for y := pass.start; y < dy; y += pass.skip {
			copy(nPix[nOffset:nOffset+dx], m.Pix[offset:offset+dx])
			offset += dx
			nOffset += dx * pass.skip
		}
	}
	m.Pix = nPix
}

// Decode reads a GIF image from r and returns the first embedded
// image as an image.Image.
func Decode(r io.Reader) (image.Image, os.Error) {
	var d decoder
	if err := d.decode(r, false); err != nil {
		return nil, err
	}
	return d.image[0], nil
}

// GIF represents the possibly multiple images stored in a GIF file.
type GIF struct {
	Image     []*image.Paletted // The successive images.
	Delay     []int             // The successive delay times, one per frame, in 100ths of a second.
	LoopCount int               // The loop count.
}

// DecodeAll reads a GIF image from r and returns the sequential frames
// and timing information.
func DecodeAll(r io.Reader) (*GIF, os.Error) {
	var d decoder
	if err := d.decode(r, false); err != nil {
		return nil, err
	}
	gif := &GIF{
		Image:     d.image,
		LoopCount: d.loopCount,
		Delay:     d.delay,
	}
	return gif, nil
}

// DecodeConfig returns the global color model and dimensions of a GIF image
// without decoding the entire image.
func DecodeConfig(r io.Reader) (image.Config, os.Error) {
	var d decoder
	if err := d.decode(r, true); err != nil {
		return image.Config{}, err
	}
	return image.Config{d.globalColorMap, d.width, d.height}, nil
}

func init() {
	image.RegisterFormat("gif", "GIF8?a", Decode, DecodeConfig)
}
<|endoftext|>


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

package utf16

import (
	"fmt"
	"reflect"
	"testing"
	"unicode"
)

type encodeTest struct {
	in  []int
	out []uint16
}

var encodeTests = []encodeTest{
	encodeTest{[]int{1, 2, 3, 4}, []uint16{1, 2, 3, 4}},
	encodeTest{[]int{0xffff, 0x10000, 0x10001, 0x12345, 0x10ffff},
		[]uint16{0xffff, 0xd800, 0xdc00, 0xd800, 0xdc01, 0xd808, 0xdf45, 0xdbff, 0xdfff}},
	encodeTest{[]int{'a', 'b', 0xd7ff, 0xd800, 0xdfff, 0xe000, 0x110000, -1},
		[]uint16{'a', 'b', 0xd7ff, 0xfffd, 0xfffd, 0xe000, 0xfffd, 0xfffd}},
}

func TestEncode(t *testing.T) {
	for _, tt := range encodeTests {
		out := Encode(tt.in)
		if !reflect.DeepEqual(out, tt.out) {
			t.Errorf("Encode(%v) = %v; want %v", hex(tt.in), hex16(out), hex16(tt.out))
		}
	}
}

func TestEncodeRune(t *testing.T) {
	for i, tt := range encodeTests {
		j := 0
		for _, r := range tt.in {
			r1, r2 := EncodeRune(r)
			if r < 0x10000 || r > unicode.MaxRune {
				if j >= len(tt.out) {
					t.Errorf("#%d: ran out of tt.out", i)
					break
				}
				if r1 != unicode.ReplacementChar || r2 != unicode.ReplacementChar {
					t.Errorf("EncodeRune(%#x) = %#x, %#x; want 0xfffd, 0xfffd", r, r1, r2)
				}
				j++
			} else {
				if j+1 >= len(tt.out) {
					t.Errorf("#%d: ran out of tt.out", i)
					break
				}
				if r1 != int(tt.out[j]) || r2 != int(tt.out[j+1]) {
					t.Errorf("EncodeRune(%#x) = %#x, %#x; want %#x, %#x", r, r1, r2, tt.out[j], tt.out[j+1])
				}
				j += 2
				dec := DecodeRune(r1, r2)
				if dec != r {
					t.Errorf("DecodeRune(%#x, %#x) = %#x; want %#x", r1, r2, dec, r)
				}
			}
		}
		if j != len(tt.out) {
			t.Errorf("#%d: EncodeRune didn't generate enough output", i)
		}
	}
}

type decodeTest struct {
	in  []uint16
	out []int
}

var decodeTests = []decodeTest{
	decodeTest{[]uint16{1, 2, 3, 4}, []int{1, 2, 3, 4}},
	decodeTest{[]uint16{0xffff, 0xd800, 0xdc00, 0xd800, 0xdc01, 0xd808, 0xdf45, 0xdbff, 0xdfff},
		[]int{0xffff, 0x10000, 0x10001, 0x12345, 0x10ffff}},
	decodeTest{[]uint16{0xd800, 'a'}, []int{0xfffd, 'a'}},
	decodeTest{[]uint16{0xdfff}, []int{0xfffd}},
}

func TestDecode(t *testing.T) {
	for _, tt := range decodeTests {
		out := Decode(tt.in)
		if !reflect.DeepEqual(out, tt.out) {
			t.Errorf("Decode(%v) = %v; want %v", hex16(tt.in), hex(out), hex(tt.out))
		}
	}
}

type hex []int

func (h hex) Format(f fmt.State, c int) {
	fmt.Fprint(f, "[")
	for i, v := range h {
		if i > 0 {
			fmt.Fprint(f, " ")
		}
		fmt.Fprintf(f, "%x", v)
	}
	fmt.Fprint(f, "]")
}

type hex16 []uint16

func (h hex16) Format(f fmt.State, c int) {
	fmt.Fprint(f, "[")
	for i, v := range h {
		if i > 0 {
			fmt.Fprint(f, " ")
		}
		fmt.Fprintf(f, "%x", v)
	}
	fmt.Fprint(f, "]")
}
<commit_msg>utf16: fix cyclic dependency when testing on Windows<commit_after>// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package utf16_test

import (
	"fmt"
	"reflect"
	"testing"
	"unicode"
	. "utf16"
)

type encodeTest struct {
	in  []int
	out []uint16
}

var encodeTests = []encodeTest{
	encodeTest{[]int{1, 2, 3, 4}, []uint16{1, 2, 3, 4}},
	encodeTest{[]int{0xffff, 0x10000, 0x10001, 0x12345, 0x10ffff},
		[]uint16{0xffff, 0xd800, 0xdc00, 0xd800, 0xdc01, 0xd808, 0xdf45, 0xdbff, 0xdfff}},
	encodeTest{[]int{'a', 'b', 0xd7ff, 0xd800, 0xdfff, 0xe000, 0x110000, -1},
		[]uint16{'a', 'b', 0xd7ff, 0xfffd, 0xfffd, 0xe000, 0xfffd, 0xfffd}},
}

func TestEncode(t *testing.T) {
	for _, tt := range encodeTests {
		out := Encode(tt.in)
		if !reflect.DeepEqual(out, tt.out) {
			t.Errorf("Encode(%v) = %v; want %v", hex(tt.in), hex16(out), hex16(tt.out))
		}
	}
}

func TestEncodeRune(t *testing.T) {
	for i, tt := range encodeTests {
		j := 0
		for _, r := range tt.in {
			r1, r2 := EncodeRune(r)
			if r < 0x10000 || r > unicode.MaxRune {
				if j >= len(tt.out) {
					t.Errorf("#%d: ran out of tt.out", i)
					break
				}
				if r1 != unicode.ReplacementChar || r2 != unicode.ReplacementChar {
					t.Errorf("EncodeRune(%#x) = %#x, %#x; want 0xfffd, 0xfffd", r, r1, r2)
				}
				j++
			} else {
				if j+1 >= len(tt.out) {
					t.Errorf("#%d: ran out of tt.out", i)
					break
				}
				if r1 != int(tt.out[j]) || r2 != int(tt.out[j+1]) {
					t.Errorf("EncodeRune(%#x) = %#x, %#x; want %#x, %#x", r, r1, r2, tt.out[j], tt.out[j+1])
				}
				j += 2
				dec := DecodeRune(r1, r2)
				if dec != r {
					t.Errorf("DecodeRune(%#x, %#x) = %#x; want %#x", r1, r2, dec, r)
				}
			}
		}
		if j != len(tt.out) {
			t.Errorf("#%d: EncodeRune didn't generate enough output", i)
		}
	}
}

type decodeTest struct {
	in  []uint16
	out []int
}

var decodeTests = []decodeTest{
	decodeTest{[]uint16{1, 2, 3, 4}, []int{1, 2, 3, 4}},
	decodeTest{[]uint16{0xffff, 0xd800, 0xdc00, 0xd800, 0xdc01, 0xd808, 0xdf45, 0xdbff, 0xdfff},
		[]int{0xffff, 0x10000, 0x10001, 0x12345, 0x10ffff}},
	decodeTest{[]uint16{0xd800, 'a'}, []int{0xfffd, 'a'}},
	decodeTest{[]uint16{0xdfff}, []int{0xfffd}},
}

func TestDecode(t *testing.T) {
	for _, tt := range decodeTests {
		out := Decode(tt.in)
		if !reflect.DeepEqual(out, tt.out) {
			t.Errorf("Decode(%v) = %v; want %v", hex16(tt.in), hex(out), hex(tt.out))
		}
	}
}

type hex []int

func (h hex) Format(f fmt.State, c int) {
	fmt.Fprint(f, "[")
	for i, v := range h {
		if i > 0 {
			fmt.Fprint(f, " ")
		}
		fmt.Fprintf(f, "%x", v)
	}
	fmt.Fprint(f, "]")
}

type hex16 []uint16

func (h hex16) Format(f fmt.State, c int) {
	fmt.Fprint(f, "[")
	for i, v := range h {
		if i > 0 {
			fmt.Fprint(f, " ")
		}
		fmt.Fprintf(f, "%x", v)
	}
	fmt.Fprint(f, "]")
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"github.com/fgrehm/devstep-cli/devstep"
	"os"
	"path/filepath"
)

var (
	client  devstep.DockerClient
	project devstep.Project
)

// REFACTOR: This belongs to some other package
func InitDevstepEnv() {
	client = newClient()
	reloadProject()
	return nil
}

func reloadProject() {
	project = newProject()
}

func newProject() devstep.Project {
	config := loadConfig()
	proj, _ := devstep.NewProject(config)
	return proj
}

func newClient() devstep.DockerClient {
	dockerHost := os.Getenv("DOCKER_HOST")
	if dockerHost == "" {
		dockerHost = "unix:///var/run/docker.sock"
	}
	return devstep.NewClient(dockerHost)
}

func loadConfig() *devstep.ProjectConfig {
	projectRoot, err := os.Getwd()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	homeDir := os.Getenv("HOME")
	loader := devstep.NewConfigLoader(client, homeDir, projectRoot)

	config, err := loader.Load()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	pluginsToLoad, err := filepath.Glob(homeDir + "/devstep/plugins/*/plugin.js")
	if err != nil {
		fmt.Printf("Error searching for plugins under '%s'\n%s\n", homeDir, err.Error())
		os.Exit(1)
	}

	if len(pluginsToLoad) > 0 {
		runtime := devstep.NewPluginRuntime(config)
		for _, pluginPath := range pluginsToLoad {
			runtime.Load(pluginPath)
		}
		runtime.Trigger("configLoaded")
	}

	if devstep.LogLevel != "" {
		config.Defaults.Env["DEVSTEP_LOG"] = devstep.LogLevel
	}

	return config
}
<commit_msg>Messed up during rebase<commit_after>package commands

import (
	"fmt"
	"github.com/fgrehm/devstep-cli/devstep"
	"os"
	"path/filepath"
)

var (
	client  devstep.DockerClient
	project devstep.Project
)

// REFACTOR: This belongs to some other package
func InitDevstepEnv() {
	client = newClient()
	reloadProject()
}

func reloadProject() {
	project = newProject()
}

func newProject() devstep.Project {
	config := loadConfig()
	proj, _ := devstep.NewProject(config)
	return proj
}

func newClient() devstep.DockerClient {
	dockerHost := os.Getenv("DOCKER_HOST")
	if dockerHost == "" {
		dockerHost = "unix:///var/run/docker.sock"
	}
	return devstep.NewClient(dockerHost)
}

func loadConfig() *devstep.ProjectConfig {
	projectRoot, err := os.Getwd()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	homeDir := os.Getenv("HOME")
	loader := devstep.NewConfigLoader(client, homeDir, projectRoot)

	config, err := loader.Load()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	pluginsToLoad, err := filepath.Glob(homeDir + "/devstep/plugins/*/plugin.js")
	if err != nil {
		fmt.Printf("Error searching for plugins under '%s'\n%s\n", homeDir, err.Error())
		os.Exit(1)
	}

	if len(pluginsToLoad) > 0 {
		runtime := devstep.NewPluginRuntime(config)
		for _, pluginPath := range pluginsToLoad {
			runtime.Load(pluginPath)
		}
		runtime.Trigger("configLoaded")
	}

	if devstep.LogLevel != "" {
		config.Defaults.Env["DEVSTEP_LOG"] = devstep.LogLevel
	}

	return config
}
<|endoftext|>