<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
)

type loggingHandler struct {
	h http.Handler
}

func (f *loggingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	log.Printf("%s %s", r.Method, r.URL)
	f.h.ServeHTTP(w, r)
}

func main() {
	wd, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}

	lh := &loggingHandler{http.FileServer(http.Dir(wd))}

	port := 8001

	log.Printf("Starting server on port %d", port)

	addr := fmt.Sprintf(":%d", port)

	log.Fatal(http.ListenAndServe(addr, lh))
}
<commit_msg>ResponseWriter wrap to log status code.<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
)

type loggingResponseWriter struct {
	http.ResponseWriter
}

func (w *loggingResponseWriter) WriteHeader(code int) {
	log.Printf("%d", code)
	w.ResponseWriter.WriteHeader(code)
}

func wrapHandler(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		lw := &loggingResponseWriter{w}
		log.Printf("%s %s", r.Method, r.URL)
		handler.ServeHTTP(lw, r)
	})
}

func main() {
	wd, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}

	port := 8001

	log.Printf("Starting server on port %d", port)

	addr := fmt.Sprintf(":%d", port)

	log.Fatal(http.ListenAndServe(addr, wrapHandler(http.FileServer(http.Dir(wd)))))
}
<|endoftext|>


<commit_before>// Copyright 2016 The Upspin 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 flags defines command-line flags to make them consistent between binaries.
// Not all flags make sense for all binaries.
package flags // import "upspin.io/flags"

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"upspin.io/config"
	"upspin.io/log"
)

// flagVar represents a flag in this package.
type flagVar struct {
	set  func()        // Set the value at parse time.
	arg  func() string // Return the argument to set the flag.
	arg2 func() string // Return the argument to set the second flag; usually nil.
}

const (
	defaultBlockSize  = 1024 * 1024 // Keep in sync with upspin.BlockSize.]
	defaultHTTPAddr   = ":80"
	defaultHTTPSAddr  = ":443"
	defaultLog        = "info"
	defaultServerKind = "inprocess"
)

// None is the set of no flags. It is rarely needed as most programs
// use either the Server or Client set.
var None = []string{}

// Server is the set of flags most useful in servers. It can be passed as the
// argument to Parse to set up the package for a server.
var Server = []string{
	"config", "log", "http", "https", "letscache", "tls", "addr", "insecure",
}

// Client is the set of flags most useful in clients. It can be passed as the
// argument to Parse to set up the package for a client.
var Client = []string{
	"config", "log", "blocksize", "prudent",
}

// The Parse and Register functions bind these variables to their respective
// command-line flags.
var (
	// BlockSize ("blocksize") is the block size used when writing large files.
	// The default is 1MB.
	BlockSize = defaultBlockSize

	// CacheDir ("cachedir") specifies the directory for the various file
	// caches.
	CacheDir = defaultCacheDir

	defaultCacheDir = filepath.Join(config.Home(), "upspin")

	// Config ("config") names the Upspin configuration file to use.
	Config = defaultConfig

	defaultConfig = filepath.Join(config.Home(), "upspin", "config")

	// HTTPAddr ("http") is the network address on which to listen for
	// incoming insecure network connections.
	HTTPAddr = defaultHTTPAddr

	// HTTPSAddr ("https") is the network address on which to listen for
	// incoming secure network connections.
	HTTPSAddr = defaultHTTPSAddr

	// InsecureHTTP ("insecure") specifies whether to serve insecure HTTP
	// on HTTPAddr, instead of serving HTTPS (secured by TLS) on HTTPSAddr.
	InsecureHTTP = false

	// LetsEncryptCache ("letscache") is the location of a file in which
	// the Let's Encrypt certificates are stored. The containing directory
	// should be owner-accessible only (chmod 0700).
	LetsEncryptCache = defaultLetsEncryptCache

	defaultLetsEncryptCache = filepath.Join(config.Home(), "upspin", "letsencrypt")

	// Log ("log") sets the level of logging (implements flag.Value).
	Log logFlag

	// NetAddr ("addr") is the publicly accessible network address of this
	// server.
	NetAddr = ""

	// ServerConfig ("serverconfig") specifies configuration options for
	// servers in "key=value" pairs.
	ServerConfig []string

	// ServerKind ("kind") is the implementation kind of this server.
	ServerKind = defaultServerKind

	// Prudent ("prudent") sets an extra security mode in the client to
	// check for malicious or buggy servers, at possible cost in
	// performance or convenience. Specifically, one check is that the
	// writer listed in a directory entry is either the owner or a user
	// currently with write permission. This protects against a forged
	// directory entry at the cost of potentially blocking a legitimate
	// file written by a user who no longer has write permission.
	Prudent = false

	// TLSCertFile and TLSKeyFile ("tls") specify the location of a TLS
	// certificate/key pair used for serving TLS (HTTPS).
	TLSCertFile = ""
	TLSKeyFile  = ""
)

// flags is a map of flag registration functions keyed by flag name,
// used by Parse to register specific (or all) flags.
var flags = map[string]*flagVar{
	"addr": strVar(&NetAddr, "addr", NetAddr, "publicly accessible network address (`host:port`)"),
	"blocksize": &flagVar{
		set: func() {
			flag.IntVar(&BlockSize, "blocksize", BlockSize, "`size` of blocks when writing large files")
		},
		arg: func() string {
			if BlockSize == defaultBlockSize {
				return ""
			}
			return fmt.Sprintf("-blocksize=%d", BlockSize)
		},
	},
	"cachedir": strVar(&CacheDir, "cachedir", CacheDir, "`directory` containing all file caches"),
	"config":   strVar(&Config, "config", Config, "user's configuration `file`"),
	"http":     strVar(&HTTPAddr, "http", HTTPAddr, "`address` for incoming insecure network connections"),
	"https":    strVar(&HTTPSAddr, "https", HTTPSAddr, "`address` for incoming secure network connections"),
	"insecure": &flagVar{
		set: func() {
			flag.BoolVar(&InsecureHTTP, "insecure", false, "whether to serve insecure HTTP instead of HTTPS")
		},
		arg: func() string {
			if InsecureHTTP {
				return "-insecure"
			}
			return ""
		},
	},
	"kind":      strVar(&ServerKind, "kind", ServerKind, "server implementation `kind` (inprocess, gcp)"),
	"letscache": strVar(&LetsEncryptCache, "letscache", defaultLetsEncryptCache, "Let's Encrypt cache `directory`"),
	"log": &flagVar{
		set: func() {
			Log.Set("info")
			flag.Var(&Log, "log", "`level` of logging: debug, info, error, disabled")
		},
		arg: func() string { return strArg("log", Log.String(), defaultLog) },
	},
	"serverconfig": &flagVar{
		set: func() {
			flag.Var(configFlag{&ServerConfig}, "serverconfig", "comma-separated list of configuration options (key=value) for this server")
		},
		arg: func() string { return strArg("serverconfig", configFlag{&ServerConfig}.String(), "") },
	},
	"prudent": &flagVar{
		set: func() {
			flag.BoolVar(&Prudent, "prudent", false, "protect against malicious directory server")
		},
		arg: func() string {
			if !Prudent {
				return ""
			}
			return "-prudent"
		},
	},
	"tls": &flagVar{
		set: func() {
			flag.StringVar(&TLSCertFile, "tls_cert", "", "TLS Certificate `file` in PEM format")
			flag.StringVar(&TLSKeyFile, "tls_key", "", "TLS Key `file` in PEM format")
		},
		arg:  func() string { return strArg("tls_cert", TLSCertFile, "") },
		arg2: func() string { return strArg("tls_key", TLSKeyFile, "") },
	},
}

// Parse registers the command-line flags for the given default flags list, plus
// any extra flag names, and calls flag.Parse. Passing no flag names in either
// list registers all flags. Passing an unknown name triggers a panic.
// The Server and Client variables contain useful default sets.
//
// Examples:
// 	flags.Parse(flags.Client) // Register all client flags.
//	flags.Parse(flags.Server, "cachedir") // Register all server flags plus cachedir.
// 	flags.Parse(nil) // Register all flags.
// 	flags.Parse(flags.None, "config", "endpoint") // Register only config and endpoint.
func Parse(defaultList []string, extras ...string) {
	ParseArgs(os.Args[1:], defaultList, extras...)
}

// ParseArgs is the same as Parse but uses the provided argument list
// instead of those provided on the command line. For ParseArgs, the
// initial command name should not be provided.
func ParseArgs(args, defaultList []string, extras ...string) {
	if len(defaultList) == 0 && len(extras) == 0 {
		Register()
	} else {
		if len(defaultList) > 0 {
			Register(defaultList...)
		}
		if len(extras) > 0 {
			Register(extras...)
		}
	}
	flag.CommandLine.Parse(args)
}

// Register registers the command-line flags for the given flag names.
// Unlike Parse, it may be called multiple times.
// Passing zero names install all flags.
// Passing an unknown name triggers a panic.
//
// For example:
// 	flags.Register("config", "endpoint") // Register Config and Endpoint.
// or
// 	flags.Register() // Register all flags.
func Register(names ...string) {
	if len(names) == 0 {
		// Register all flags if no names provided.
		for _, flag := range flags {
			flag.set()
		}
	} else {
		for _, n := range names {
			flag, ok := flags[n]
			if !ok {
				panic(fmt.Sprintf("unknown flag %q", n))
			}
			flag.set()
		}
	}
}

// Args returns a slice of -flag=value strings that will recreate
// the state of the flags. Flags set to their default value are elided.
func Args() []string {
	var args []string
	for _, flag := range flags {
		arg := flag.arg()
		if arg == "" {
			continue
		}
		args = append(args, arg)
		if flag.arg2 != nil {
			args = append(args, flag.arg2())
		}
	}
	return args
}

// strVar returns a flagVar for the given string flag.
func strVar(value *string, name, _default, usage string) *flagVar {
	return &flagVar{
		set: func() {
			flag.StringVar(value, name, _default, usage)
		},
		arg: func() string {
			return strArg(name, *value, _default)
		},
	}
}

// strArg returns a command-line argument that will recreate the flag,
// or the empty string if the value is the default.
func strArg(name, value, _default string) string {
	if value == _default {
		return ""
	}
	return "-" + name + "=" + value
}

type logFlag string

// String implements flag.Value.
func (f logFlag) String() string {
	return string(f)
}

// Set implements flag.Value.
func (f *logFlag) Set(level string) error {
	err := log.SetLevel(level)
	if err != nil {
		return err
	}
	*f = logFlag(log.GetLevel())
	return nil
}

// Get implements flag.Getter.
func (logFlag) Get() interface{} {
	return log.GetLevel()
}

type configFlag struct {
	s *[]string
}

// String implements flag.Value.
func (f configFlag) String() string {
	if f.s == nil {
		return ""
	}
	return strings.Join(*f.s, ",")
}

// Set implements flag.Value.
func (f configFlag) Set(s string) error {
	ss := strings.Split(strings.TrimSpace(s), ",")
	// Drop empty elements.
	for i := 0; i < len(ss); i++ {
		if ss[i] == "" {
			ss = append(ss[:i], ss[i+1:]...)
		}
	}
	*f.s = ss
	return nil
}

// Get implements flag.Getter.
func (f configFlag) Get() interface{} {
	if f.s == nil {
		return ""
	}
	return *f.s
}
<commit_msg>flags: do not panic if home directory is unavailable<commit_after>// Copyright 2016 The Upspin 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 flags defines command-line flags to make them consistent between binaries.
// Not all flags make sense for all binaries.
package flags // import "upspin.io/flags"

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"upspin.io/config"
	"upspin.io/log"
)

// flagVar represents a flag in this package.
type flagVar struct {
	set  func()        // Set the value at parse time.
	arg  func() string // Return the argument to set the flag.
	arg2 func() string // Return the argument to set the second flag; usually nil.
}

const (
	defaultBlockSize  = 1024 * 1024 // Keep in sync with upspin.BlockSize.]
	defaultHTTPAddr   = ":80"
	defaultHTTPSAddr  = ":443"
	defaultLog        = "info"
	defaultServerKind = "inprocess"
)

var (
	defaultCacheDir         = upspinDir("")
	defaultLetsEncryptCache = upspinDir("letsencrypt")
	defaultConfig           = upspinDir("config")
)

func upspinDir(subdir string) string {
	home, err := config.Homedir()
	if err != nil {
		log.Error.Printf("flags: could not locate home directory: %v", err)
		home = "."
	}
	return filepath.Join(home, "upspin", subdir)
}

// None is the set of no flags. It is rarely needed as most programs
// use either the Server or Client set.
var None = []string{}

// Server is the set of flags most useful in servers. It can be passed as the
// argument to Parse to set up the package for a server.
var Server = []string{
	"config", "log", "http", "https", "letscache", "tls", "addr", "insecure",
}

// Client is the set of flags most useful in clients. It can be passed as the
// argument to Parse to set up the package for a client.
var Client = []string{
	"config", "log", "blocksize", "prudent",
}

// The Parse and Register functions bind these variables to their respective
// command-line flags.
var (
	// BlockSize ("blocksize") is the block size used when writing large files.
	// The default is 1MB.
	BlockSize = defaultBlockSize

	// CacheDir ("cachedir") specifies the directory for the various file
	// caches.
	CacheDir = defaultCacheDir

	// Config ("config") names the Upspin configuration file to use.
	Config = defaultConfig

	// HTTPAddr ("http") is the network address on which to listen for
	// incoming insecure network connections.
	HTTPAddr = defaultHTTPAddr

	// HTTPSAddr ("https") is the network address on which to listen for
	// incoming secure network connections.
	HTTPSAddr = defaultHTTPSAddr

	// InsecureHTTP ("insecure") specifies whether to serve insecure HTTP
	// on HTTPAddr, instead of serving HTTPS (secured by TLS) on HTTPSAddr.
	InsecureHTTP = false

	// LetsEncryptCache ("letscache") is the location of a file in which
	// the Let's Encrypt certificates are stored. The containing directory
	// should be owner-accessible only (chmod 0700).
	LetsEncryptCache = defaultLetsEncryptCache

	// Log ("log") sets the level of logging (implements flag.Value).
	Log logFlag

	// NetAddr ("addr") is the publicly accessible network address of this
	// server.
	NetAddr = ""

	// ServerConfig ("serverconfig") specifies configuration options for
	// servers in "key=value" pairs.
	ServerConfig []string

	// ServerKind ("kind") is the implementation kind of this server.
	ServerKind = defaultServerKind

	// Prudent ("prudent") sets an extra security mode in the client to
	// check for malicious or buggy servers, at possible cost in
	// performance or convenience. Specifically, one check is that the
	// writer listed in a directory entry is either the owner or a user
	// currently with write permission. This protects against a forged
	// directory entry at the cost of potentially blocking a legitimate
	// file written by a user who no longer has write permission.
	Prudent = false

	// TLSCertFile and TLSKeyFile ("tls") specify the location of a TLS
	// certificate/key pair used for serving TLS (HTTPS).
	TLSCertFile = ""
	TLSKeyFile  = ""
)

// flags is a map of flag registration functions keyed by flag name,
// used by Parse to register specific (or all) flags.
var flags = map[string]*flagVar{
	"addr": strVar(&NetAddr, "addr", NetAddr, "publicly accessible network address (`host:port`)"),
	"blocksize": &flagVar{
		set: func() {
			flag.IntVar(&BlockSize, "blocksize", BlockSize, "`size` of blocks when writing large files")
		},
		arg: func() string {
			if BlockSize == defaultBlockSize {
				return ""
			}
			return fmt.Sprintf("-blocksize=%d", BlockSize)
		},
	},
	"cachedir": strVar(&CacheDir, "cachedir", CacheDir, "`directory` containing all file caches"),
	"config":   strVar(&Config, "config", Config, "user's configuration `file`"),
	"http":     strVar(&HTTPAddr, "http", HTTPAddr, "`address` for incoming insecure network connections"),
	"https":    strVar(&HTTPSAddr, "https", HTTPSAddr, "`address` for incoming secure network connections"),
	"insecure": &flagVar{
		set: func() {
			flag.BoolVar(&InsecureHTTP, "insecure", false, "whether to serve insecure HTTP instead of HTTPS")
		},
		arg: func() string {
			if InsecureHTTP {
				return "-insecure"
			}
			return ""
		},
	},
	"kind":      strVar(&ServerKind, "kind", ServerKind, "server implementation `kind` (inprocess, gcp)"),
	"letscache": strVar(&LetsEncryptCache, "letscache", defaultLetsEncryptCache, "Let's Encrypt cache `directory`"),
	"log": &flagVar{
		set: func() {
			Log.Set("info")
			flag.Var(&Log, "log", "`level` of logging: debug, info, error, disabled")
		},
		arg: func() string { return strArg("log", Log.String(), defaultLog) },
	},
	"serverconfig": &flagVar{
		set: func() {
			flag.Var(configFlag{&ServerConfig}, "serverconfig", "comma-separated list of configuration options (key=value) for this server")
		},
		arg: func() string { return strArg("serverconfig", configFlag{&ServerConfig}.String(), "") },
	},
	"prudent": &flagVar{
		set: func() {
			flag.BoolVar(&Prudent, "prudent", false, "protect against malicious directory server")
		},
		arg: func() string {
			if !Prudent {
				return ""
			}
			return "-prudent"
		},
	},
	"tls": &flagVar{
		set: func() {
			flag.StringVar(&TLSCertFile, "tls_cert", "", "TLS Certificate `file` in PEM format")
			flag.StringVar(&TLSKeyFile, "tls_key", "", "TLS Key `file` in PEM format")
		},
		arg:  func() string { return strArg("tls_cert", TLSCertFile, "") },
		arg2: func() string { return strArg("tls_key", TLSKeyFile, "") },
	},
}

// Parse registers the command-line flags for the given default flags list, plus
// any extra flag names, and calls flag.Parse. Passing no flag names in either
// list registers all flags. Passing an unknown name triggers a panic.
// The Server and Client variables contain useful default sets.
//
// Examples:
// 	flags.Parse(flags.Client) // Register all client flags.
//	flags.Parse(flags.Server, "cachedir") // Register all server flags plus cachedir.
// 	flags.Parse(nil) // Register all flags.
// 	flags.Parse(flags.None, "config", "endpoint") // Register only config and endpoint.
func Parse(defaultList []string, extras ...string) {
	ParseArgs(os.Args[1:], defaultList, extras...)
}

// ParseArgs is the same as Parse but uses the provided argument list
// instead of those provided on the command line. For ParseArgs, the
// initial command name should not be provided.
func ParseArgs(args, defaultList []string, extras ...string) {
	if len(defaultList) == 0 && len(extras) == 0 {
		Register()
	} else {
		if len(defaultList) > 0 {
			Register(defaultList...)
		}
		if len(extras) > 0 {
			Register(extras...)
		}
	}
	flag.CommandLine.Parse(args)
}

// Register registers the command-line flags for the given flag names.
// Unlike Parse, it may be called multiple times.
// Passing zero names install all flags.
// Passing an unknown name triggers a panic.
//
// For example:
// 	flags.Register("config", "endpoint") // Register Config and Endpoint.
// or
// 	flags.Register() // Register all flags.
func Register(names ...string) {
	if len(names) == 0 {
		// Register all flags if no names provided.
		for _, flag := range flags {
			flag.set()
		}
	} else {
		for _, n := range names {
			flag, ok := flags[n]
			if !ok {
				panic(fmt.Sprintf("unknown flag %q", n))
			}
			flag.set()
		}
	}
}

// Args returns a slice of -flag=value strings that will recreate
// the state of the flags. Flags set to their default value are elided.
func Args() []string {
	var args []string
	for _, flag := range flags {
		arg := flag.arg()
		if arg == "" {
			continue
		}
		args = append(args, arg)
		if flag.arg2 != nil {
			args = append(args, flag.arg2())
		}
	}
	return args
}

// strVar returns a flagVar for the given string flag.
func strVar(value *string, name, _default, usage string) *flagVar {
	return &flagVar{
		set: func() {
			flag.StringVar(value, name, _default, usage)
		},
		arg: func() string {
			return strArg(name, *value, _default)
		},
	}
}

// strArg returns a command-line argument that will recreate the flag,
// or the empty string if the value is the default.
func strArg(name, value, _default string) string {
	if value == _default {
		return ""
	}
	return "-" + name + "=" + value
}

type logFlag string

// String implements flag.Value.
func (f logFlag) String() string {
	return string(f)
}

// Set implements flag.Value.
func (f *logFlag) Set(level string) error {
	err := log.SetLevel(level)
	if err != nil {
		return err
	}
	*f = logFlag(log.GetLevel())
	return nil
}

// Get implements flag.Getter.
func (logFlag) Get() interface{} {
	return log.GetLevel()
}

type configFlag struct {
	s *[]string
}

// String implements flag.Value.
func (f configFlag) String() string {
	if f.s == nil {
		return ""
	}
	return strings.Join(*f.s, ",")
}

// Set implements flag.Value.
func (f configFlag) Set(s string) error {
	ss := strings.Split(strings.TrimSpace(s), ",")
	// Drop empty elements.
	for i := 0; i < len(ss); i++ {
		if ss[i] == "" {
			ss = append(ss[:i], ss[i+1:]...)
		}
	}
	*f.s = ss
	return nil
}

// Get implements flag.Getter.
func (f configFlag) Get() interface{} {
	if f.s == nil {
		return ""
	}
	return *f.s
}
<|endoftext|>


<commit_before>package flags

import (
	"errors"
	"flag"
	"strings"

	"github.com/alistanis/st/sterrors"
)

var (
	Case string
	Tag  string

	Append               bool
	Overwrite            bool
	c                    bool
	s                    bool
	Verbose              bool
	Write                bool
	IgnoredFields        []string
	IgnoredFieldsString  string
	IgnoredStructs       []string
	IgnoredStructsString string
)

const (
	Camel = "camel"
	Snake = "snake"
)

func StringVars() {
	flag.StringVar(&Tag, "t", "json", "The struct tag to use when tagging. Example: -t=json ")
	flag.StringVar(&IgnoredFieldsString, "i", "", "A comma separated list of fields to ignore. Will use the format json:\"-\".")
	flag.StringVar(&IgnoredStructsString, "is", "", "A comma separated list of structs to ignore. Will not tag any fields in the struct.")

}

func BoolVars() {
	flag.BoolVar(&c, "c", false, "Sets the struct tag to camel case.")
	flag.BoolVar(&s, "s", false, "Sets the struct tag to snake case.")
	flag.BoolVar(&Append, "a", false, "Sets mode to append mode. Will append to existing tags. Default behavior skips existing tags.")
	flag.BoolVar(&Verbose, "v", false, "Sets mode to verbose.")
	flag.BoolVar(&Write, "w", false, "Sets mode to write to source file.")
	flag.BoolVar(&Overwrite, "o", false, "Sets mode to overwrite mode. Will overwrite existing tags (completely). Default behavior skips existing tags.")
}

func SetVars() {
	StringVars()
	BoolVars()
}

func ParseFlags() error {
	SetVars()
	flag.Parse()
	return verify()
}

func verify() error {
	if flag.NArg() < 1 {
		return errors.New("No path was provided. The -path parameter is required.")
	}

	if c && s {
		return sterrors.MutuallyExclusiveParameters("c", "s")
	}

	if Overwrite && Append {
		return sterrors.MutuallyExclusiveParameters("o", "a")
	}

	if c {
		Case = Camel
	}

	if s {
		Case = Snake
	}
	sterrors.Verbose = Verbose

	if IgnoredFieldsString != "" {
		IgnoredFields = strings.Split(IgnoredFieldsString, ",")
	}

	if IgnoredStructsString != "" {
		IgnoredStructs = strings.Split(IgnoredStructsString, ",")
	}
	return nil
}
<commit_msg>remove part of error message<commit_after>package flags

import (
	"errors"
	"flag"
	"strings"

	"github.com/alistanis/st/sterrors"
)

var (
	Case string
	Tag  string

	Append               bool
	Overwrite            bool
	c                    bool
	s                    bool
	Verbose              bool
	Write                bool
	IgnoredFields        []string
	IgnoredFieldsString  string
	IgnoredStructs       []string
	IgnoredStructsString string
)

const (
	Camel = "camel"
	Snake = "snake"
)

func StringVars() {
	flag.StringVar(&Tag, "t", "json", "The struct tag to use when tagging. Example: -t=json ")
	flag.StringVar(&IgnoredFieldsString, "i", "", "A comma separated list of fields to ignore. Will use the format json:\"-\".")
	flag.StringVar(&IgnoredStructsString, "is", "", "A comma separated list of structs to ignore. Will not tag any fields in the struct.")

}

func BoolVars() {
	flag.BoolVar(&c, "c", false, "Sets the struct tag to camel case.")
	flag.BoolVar(&s, "s", false, "Sets the struct tag to snake case.")
	flag.BoolVar(&Append, "a", false, "Sets mode to append mode. Will append to existing tags. Default behavior skips existing tags.")
	flag.BoolVar(&Verbose, "v", false, "Sets mode to verbose.")
	flag.BoolVar(&Write, "w", false, "Sets mode to write to source file.")
	flag.BoolVar(&Overwrite, "o", false, "Sets mode to overwrite mode. Will overwrite existing tags (completely). Default behavior skips existing tags.")
}

func SetVars() {
	StringVars()
	BoolVars()
}

func ParseFlags() error {
	SetVars()
	flag.Parse()
	return verify()
}

func verify() error {
	if flag.NArg() < 1 {
		return errors.New("No path was provided.")
	}

	if c && s {
		return sterrors.MutuallyExclusiveParameters("c", "s")
	}

	if Overwrite && Append {
		return sterrors.MutuallyExclusiveParameters("o", "a")
	}

	if c {
		Case = Camel
	}

	if s {
		Case = Snake
	}
	sterrors.Verbose = Verbose

	if IgnoredFieldsString != "" {
		IgnoredFields = strings.Split(IgnoredFieldsString, ",")
	}

	if IgnoredStructsString != "" {
		IgnoredStructs = strings.Split(IgnoredStructsString, ",")
	}
	return nil
}
<|endoftext|>


<commit_before>/*
Package golang provides a concrete Cataloger implementation for go.mod files.
*/
package golang

import (
	"fmt"

	"github.com/anchore/syft/internal/log"
	"github.com/anchore/syft/syft/pkg"
	"github.com/anchore/syft/syft/source"
)

const catalogerName = "go-module-binary-cataloger"

// current mime types to search by to discover go binaries
var mimeTypes = []string{
	"application/x-executable",
	"application/x-mach-binary",
	"application/x-elf",
	"application/x-sharedlib",
	"application/vnd.microsoft.portable-executable",
}

type Cataloger struct{}

// NewGoModuleBinaryCataloger returns a new Golang cataloger object.
func NewGoModuleBinaryCataloger() *Cataloger {
	return &Cataloger{}
}

// Name returns a string that uniquely describes a cataloger
func (c *Cataloger) Name() string {
	return catalogerName
}

// Catalog is given an object to resolve file references and content, this function returns any discovered Packages after analyzing rpm db installation.
func (c *Cataloger) Catalog(resolver source.FileResolver) ([]pkg.Package, error) {
	pkgs := make([]pkg.Package, 0)
	fileMatches, err := resolver.FilesByMIMEType(mimeTypes...)
	if err != nil {
		return pkgs, fmt.Errorf("failed to find bin by mime types: %w", err)
	}

	for _, location := range fileMatches {
		r, err := resolver.FileContentsByLocation(location)
		if err != nil {
			return pkgs, fmt.Errorf("failed to resolve file contents by location: %w", err)
		}

		goPkgs, err := parseGoBin(location.RealPath, r)
		if err != nil {
			log.Infof("could not parse go bin for: %w", err)
		}

		r.Close()
		pkgs = append(pkgs, goPkgs...)
	}

	return pkgs, nil
}
<commit_msg>swap go binary parsing warning logging entry (#579)<commit_after>/*
Package golang provides a concrete Cataloger implementation for go.mod files.
*/
package golang

import (
	"fmt"

	"github.com/anchore/syft/internal/log"
	"github.com/anchore/syft/syft/pkg"
	"github.com/anchore/syft/syft/source"
)

const catalogerName = "go-module-binary-cataloger"

// current mime types to search by to discover go binaries
var mimeTypes = []string{
	"application/x-executable",
	"application/x-mach-binary",
	"application/x-elf",
	"application/x-sharedlib",
	"application/vnd.microsoft.portable-executable",
}

type Cataloger struct{}

// NewGoModuleBinaryCataloger returns a new Golang cataloger object.
func NewGoModuleBinaryCataloger() *Cataloger {
	return &Cataloger{}
}

// Name returns a string that uniquely describes a cataloger
func (c *Cataloger) Name() string {
	return catalogerName
}

// Catalog is given an object to resolve file references and content, this function returns any discovered Packages after analyzing rpm db installation.
func (c *Cataloger) Catalog(resolver source.FileResolver) ([]pkg.Package, error) {
	pkgs := make([]pkg.Package, 0)
	fileMatches, err := resolver.FilesByMIMEType(mimeTypes...)
	if err != nil {
		return pkgs, fmt.Errorf("failed to find bin by mime types: %w", err)
	}

	for _, location := range fileMatches {
		r, err := resolver.FileContentsByLocation(location)
		if err != nil {
			return pkgs, fmt.Errorf("failed to resolve file contents by location: %w", err)
		}

		goPkgs, err := parseGoBin(location.RealPath, r)
		if err != nil {
			log.Warnf("could not parse possible go binary: %+v", err)
		}

		r.Close()
		pkgs = append(pkgs, goPkgs...)
	}

	return pkgs, nil
}
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.22"
<commit_msg>: 0.3.23 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.23"
<|endoftext|>


<commit_before>// Package handler is the handler collection of the logger.
package handler

import (
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"sync"
	"time"

	"github.com/xgfone/go-tools/file"
	"github.com/xgfone/go-tools/function"
)

const (
	// DAY_FMT is the date-rotaed format.
	DAY_FMT = "2006-01-02"

	// FILE_MODE is the mode to open the log file.
	FILE_MODE = os.O_APPEND | os.O_CREATE | os.O_WRONLY

	// FILE_PERM is the default permission to open the log file.
	FILE_PERM os.FileMode = 0644
)

var (
	dayRE       = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}(\.\w+)?$`)
	day   int64 = 3600 * 24

	time2fmt = map[int64]string{
		day: DAY_FMT,
	}

	filePerm = FILE_PERM
)

var (
	// ErrFileNotOpen is the error to open the log file.
	ErrFileNotOpen = errors.New("The file is not opened")
)

// ResetDefaultFilePerm resets the default permission to open the log file.
func ResetDefaultFilePerm(perm int) {
	filePerm = os.FileMode(perm)
}

// TimedRotatingFile is a file handler based on the timed rotating, like
// `logging.handlers.TimedRotatingFileHandler` in Python.
// Now only support the rotation by day.
type TimedRotatingFile struct {
	sync.Mutex
	w io.WriteCloser

	filename    string
	backupCount int
	interval    int64
	when        int64
	rotatorAt   int64
	extRE       *regexp.Regexp
}

// NewTimedRotatingFile creates a new TimedRotatingFile.
//
// If failed, it will panic.
func NewTimedRotatingFile(filename string) *TimedRotatingFile {
	filename, _ = filepath.Abs(filename)
	t := TimedRotatingFile{filename: filename, when: day, extRE: dayRE}
	t.SetBackupCount(31).SetInterval(1)
	if err := t.open(); err != nil {
		panic(err)
	}
	return &t
}

// WriteString writes the string data into the file, which may rotate the file if necessary.
func (t *TimedRotatingFile) WriteString(data string) (n int, err error) {
	return t.Write([]byte(data))
}

// Write writes the byte slice data into the file, which may rotate the file if necessary.
func (t *TimedRotatingFile) Write(data []byte) (n int, err error) {
	t.Lock()
	defer t.Unlock()

	if t.w == nil {
		err = ErrFileNotOpen
		return
	}

	if t.shouldRollover() {
		if err = t.doRollover(); err != nil {
			return
		}
	}

	return t.w.Write(data)
}

// SetBackupCount sets the number of the backup file. The default is 31.
func (t *TimedRotatingFile) SetBackupCount(num int) *TimedRotatingFile {
	t.backupCount = num
	return t
}

// SetInterval sets the interval day number to rotate. The default is 1.
func (t *TimedRotatingFile) SetInterval(interval int) *TimedRotatingFile {
	t.interval = int64(interval) * t.when
	t.reComputeRollover()
	return t
}

func (t *TimedRotatingFile) shouldRollover() bool {
	return time.Now().Unix() >= t.rotatorAt
}

// Close closes the handler.
// Return ErrFileNotOpen when to write the data to the handler after closed.
func (t *TimedRotatingFile) Close() (err error) {
	if err = t.w.Close(); err != nil {
		return
	}
	t.w = nil
	return
}

func (t *TimedRotatingFile) open() error {
	file, err := os.OpenFile(t.filename, FILE_MODE, FILE_PERM)
	if err != nil {
		return err
	}
	t.w = file
	return nil
}

func (t *TimedRotatingFile) doRollover() (err error) {
	if err = t.Close(); err != nil {
		return
	}

	dstTime := t.rotatorAt - t.interval
	dstPath := t.filename + "." + time.Unix(dstTime, 0).Format(time2fmt[t.when])
	if file.IsExist(dstPath) {
		os.Remove(dstPath)
	}

	if file.IsFile(t.filename) {
		if err = os.Rename(t.filename, dstPath); err != nil {
			return err
		}
	}

	if t.backupCount > 0 {
		for _, file := range t.getFilesToDelete() {
			os.Remove(file)
		}
	}

	t.reComputeRollover()
	return t.open()
}

func (t *TimedRotatingFile) getFilesToDelete() []string {
	result := make([]string, 0, 30)
	dirName, baseName := filepath.Split(t.filename)
	fileNames, err := file.ListDir(dirName)
	if err != nil {
		return result
	}

	var suffix, prefix string
	_prefix := baseName + "."
	plen := len(_prefix)
	for _, fileName := range fileNames {
		if len(fileName) <= plen {
			continue
		}
		prefix = string(fileName[:plen])
		if _prefix == prefix {
			suffix = string(fileName[plen:])
			if t.extRE.MatchString(suffix) {
				result = append(result, filepath.Join(dirName, fileName))
			}
		}
	}

	if len(result) <= t.backupCount {
		return []string{}
	}
	sort.Strings(result)
	return result[:len(result)-t.backupCount]
}

func (t *TimedRotatingFile) reComputeRollover() {
	currentTime := time.Now().Unix()

	_time := time.Unix(currentTime, 0)
	currentHour := _time.Hour()
	currentMinute := _time.Minute()
	currentSecond := _time.Second()

	r := t.interval - int64((currentHour*60+currentMinute)*60+currentSecond)
	t.rotatorAt = currentTime + r
}

// RotatingFile is a rotating logging handler based on the size.
type RotatingFile struct {
	sync.Mutex
	w *WriteCloser

	filename    string
	maxSize     int
	backupCount int
	nbytes      int
}

// NewRotatingFile returns a new RotatingFile.
func NewRotatingFile(filename string, size, count int) *RotatingFile {
	r := &RotatingFile{
		filename:    filename,
		maxSize:     size,
		backupCount: count,
	}

	if err := r.open(); err != nil {
		panic(err)
	}
	return r
}

// Write implements the interface io.Writer.
func (r *RotatingFile) Write(data []byte) (n int, err error) {
	r.Lock()
	defer r.Unlock()

	if r.w == nil || r.w.Closed() {
		err = ErrFileNotOpen
		return
	}

	if r.nbytes+len(data) > r.maxSize {
		if err = r.doRollover(); err != nil {
			return
		}
	}

	if n, err = r.w.Write(data); err != nil {
		return
	}
	r.nbytes += n
	return
}

// WriteString writes the string.
func (r *RotatingFile) WriteString(data string) (n int, err error) {
	return r.Write([]byte(data))
}

// Close implements the interface io.Closer.
func (r *RotatingFile) Close() (err error) {
	r.Lock()
	err = r.close()
	r.Unlock()
	return
}

func (r *RotatingFile) close() (err error) {
	if r.w != nil {
		err = r.w.Close()
		r.w = nil
	}
	return
}

func (r *RotatingFile) doRollover() (err error) {
	if r.backupCount > 0 {
		if err = r.close(); err != nil {
			return
		}
		for _, i := range function.Range(r.backupCount-1, 0, -1) {
			sfn := fmt.Sprintf("%s.%d", r.filename, i)
			dfn := fmt.Sprintf("%s.%d", r.filename, i+1)
			if file.IsExist(sfn) {
				if file.IsExist(dfn) {
					os.Remove(dfn)
				}
				if err = os.Rename(sfn, dfn); err != nil {
					return
				}
			}
		}
		dfn := r.filename + ".1"
		if file.IsExist(dfn) {
			if err = os.Remove(dfn); err != nil {
				return
			}
		}
		if file.IsExist(r.filename) {
			if err = os.Rename(r.filename, dfn); err != nil {
				return
			}
		}
		err = r.open()
	}
	return
}

func (r *RotatingFile) open() (err error) {
	file, err := os.OpenFile(r.filename, FILE_MODE, FILE_PERM)
	if err != nil {
		return
	}
	info, err := file.Stat()
	if err != nil {
		return
	}
	r.nbytes = int(info.Size())
	r.w = NewWriteCloser(file)
	return
}
<commit_msg>Correct the const variable name<commit_after>// Package handler is the handler collection of the logger.
package handler

import (
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"sync"
	"time"

	"github.com/xgfone/go-tools/file"
	"github.com/xgfone/go-tools/function"
)

const (
	// FileMode is the mode to open the log file.
	FileMode = os.O_APPEND | os.O_CREATE | os.O_WRONLY

	// FilePerm is the default permission to open the log file.
	FilePerm os.FileMode = 0644
)

var (
	dayRE       = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}(\.\w+)?$`)
	day   int64 = 3600 * 24

	time2fmt = map[int64]string{
		day: "2006-01-02",
	}

	filePerm = FilePerm
)

var (
	// ErrFileNotOpen is the error to open the log file.
	ErrFileNotOpen = errors.New("The file is not opened")
)

// ResetDefaultFilePerm resets the default permission to open the log file.
func ResetDefaultFilePerm(perm int) {
	filePerm = os.FileMode(perm)
}

// TimedRotatingFile is a file handler based on the timed rotating, like
// `logging.handlers.TimedRotatingFileHandler` in Python.
// Now only support the rotation by day.
type TimedRotatingFile struct {
	sync.Mutex
	w io.WriteCloser

	filename    string
	backupCount int
	interval    int64
	when        int64
	rotatorAt   int64
	extRE       *regexp.Regexp
}

// NewTimedRotatingFile creates a new TimedRotatingFile.
//
// If failed, it will panic.
func NewTimedRotatingFile(filename string) *TimedRotatingFile {
	filename, _ = filepath.Abs(filename)
	t := TimedRotatingFile{filename: filename, when: day, extRE: dayRE}
	t.SetBackupCount(31).SetInterval(1)
	if err := t.open(); err != nil {
		panic(err)
	}
	return &t
}

// WriteString writes the string data into the file, which may rotate the file if necessary.
func (t *TimedRotatingFile) WriteString(data string) (n int, err error) {
	return t.Write([]byte(data))
}

// Write writes the byte slice data into the file, which may rotate the file if necessary.
func (t *TimedRotatingFile) Write(data []byte) (n int, err error) {
	t.Lock()
	defer t.Unlock()

	if t.w == nil {
		err = ErrFileNotOpen
		return
	}

	if t.shouldRollover() {
		if err = t.doRollover(); err != nil {
			return
		}
	}

	return t.w.Write(data)
}

// SetBackupCount sets the number of the backup file. The default is 31.
func (t *TimedRotatingFile) SetBackupCount(num int) *TimedRotatingFile {
	t.backupCount = num
	return t
}

// SetInterval sets the interval day number to rotate. The default is 1.
func (t *TimedRotatingFile) SetInterval(interval int) *TimedRotatingFile {
	t.interval = int64(interval) * t.when
	t.reComputeRollover()
	return t
}

func (t *TimedRotatingFile) shouldRollover() bool {
	return time.Now().Unix() >= t.rotatorAt
}

// Close closes the handler.
// Return ErrFileNotOpen when to write the data to the handler after closed.
func (t *TimedRotatingFile) Close() (err error) {
	if err = t.w.Close(); err != nil {
		return
	}
	t.w = nil
	return
}

func (t *TimedRotatingFile) open() error {
	file, err := os.OpenFile(t.filename, FileMode, FilePerm)
	if err != nil {
		return err
	}
	t.w = file
	return nil
}

func (t *TimedRotatingFile) doRollover() (err error) {
	if err = t.Close(); err != nil {
		return
	}

	dstTime := t.rotatorAt - t.interval
	dstPath := t.filename + "." + time.Unix(dstTime, 0).Format(time2fmt[t.when])
	if file.IsExist(dstPath) {
		os.Remove(dstPath)
	}

	if file.IsFile(t.filename) {
		if err = os.Rename(t.filename, dstPath); err != nil {
			return err
		}
	}

	if t.backupCount > 0 {
		for _, file := range t.getFilesToDelete() {
			os.Remove(file)
		}
	}

	t.reComputeRollover()
	return t.open()
}

func (t *TimedRotatingFile) getFilesToDelete() []string {
	result := make([]string, 0, 30)
	dirName, baseName := filepath.Split(t.filename)
	fileNames, err := file.ListDir(dirName)
	if err != nil {
		return result
	}

	var suffix, prefix string
	_prefix := baseName + "."
	plen := len(_prefix)
	for _, fileName := range fileNames {
		if len(fileName) <= plen {
			continue
		}
		prefix = string(fileName[:plen])
		if _prefix == prefix {
			suffix = string(fileName[plen:])
			if t.extRE.MatchString(suffix) {
				result = append(result, filepath.Join(dirName, fileName))
			}
		}
	}

	if len(result) <= t.backupCount {
		return []string{}
	}
	sort.Strings(result)
	return result[:len(result)-t.backupCount]
}

func (t *TimedRotatingFile) reComputeRollover() {
	currentTime := time.Now().Unix()

	_time := time.Unix(currentTime, 0)
	currentHour := _time.Hour()
	currentMinute := _time.Minute()
	currentSecond := _time.Second()

	r := t.interval - int64((currentHour*60+currentMinute)*60+currentSecond)
	t.rotatorAt = currentTime + r
}

// RotatingFile is a rotating logging handler based on the size.
type RotatingFile struct {
	sync.Mutex
	w *WriteCloser

	filename    string
	maxSize     int
	backupCount int
	nbytes      int
}

// NewRotatingFile returns a new RotatingFile.
func NewRotatingFile(filename string, size, count int) *RotatingFile {
	r := &RotatingFile{
		filename:    filename,
		maxSize:     size,
		backupCount: count,
	}

	if err := r.open(); err != nil {
		panic(err)
	}
	return r
}

// Write implements the interface io.Writer.
func (r *RotatingFile) Write(data []byte) (n int, err error) {
	r.Lock()
	defer r.Unlock()

	if r.w == nil || r.w.Closed() {
		err = ErrFileNotOpen
		return
	}

	if r.nbytes+len(data) > r.maxSize {
		if err = r.doRollover(); err != nil {
			return
		}
	}

	if n, err = r.w.Write(data); err != nil {
		return
	}
	r.nbytes += n
	return
}

// WriteString writes the string.
func (r *RotatingFile) WriteString(data string) (n int, err error) {
	return r.Write([]byte(data))
}

// Close implements the interface io.Closer.
func (r *RotatingFile) Close() (err error) {
	r.Lock()
	err = r.close()
	r.Unlock()
	return
}

func (r *RotatingFile) close() (err error) {
	if r.w != nil {
		err = r.w.Close()
		r.w = nil
	}
	return
}

func (r *RotatingFile) doRollover() (err error) {
	if r.backupCount > 0 {
		if err = r.close(); err != nil {
			return
		}
		for _, i := range function.Range(r.backupCount-1, 0, -1) {
			sfn := fmt.Sprintf("%s.%d", r.filename, i)
			dfn := fmt.Sprintf("%s.%d", r.filename, i+1)
			if file.IsExist(sfn) {
				if file.IsExist(dfn) {
					os.Remove(dfn)
				}
				if err = os.Rename(sfn, dfn); err != nil {
					return
				}
			}
		}
		dfn := r.filename + ".1"
		if file.IsExist(dfn) {
			if err = os.Remove(dfn); err != nil {
				return
			}
		}
		if file.IsExist(r.filename) {
			if err = os.Rename(r.filename, dfn); err != nil {
				return
			}
		}
		err = r.open()
	}
	return
}

func (r *RotatingFile) open() (err error) {
	file, err := os.OpenFile(r.filename, FileMode, FilePerm)
	if err != nil {
		return
	}
	info, err := file.Stat()
	if err != nil {
		return
	}
	r.nbytes = int(info.Size())
	r.w = NewWriteCloser(file)
	return
}
<|endoftext|>


<commit_before><commit_msg>Clean up of misc static check errors (S1002, S1021)<commit_after><|endoftext|>


<commit_before>package main

import (
    "testing"
    "os"
    "database/sql"
    _ "github.com/mattn/go-sqlite3"
)

// Database file to craete/use that will not interfere with the one
// created during the normal operation on the RSS Reader
const TEST_DB_FILE = "testing_db.db"

// A URI for Hacker News' RSS feed
const TEST_FEED_URL = "https://news.ycombinator.com/rss"

/**
 * Test that the database has been intialized properly and that we
 * can, without error, insert some data into the feeds table and then
 * retrieve it successfully.
 */
func TestDBInitialization(t *testing.T) {
    t.Log("Testing database initialization")
    var db *sql.DB
    var err error
    db, err = InitDBConnection(TEST_DB_FILE)
    defer db.Close()
    if err != nil {
        t.Error(err)
    }
    tx, _ := db.Begin()
    stmt, _ := tx.Prepare("insert into feeds(url, type, charset) values(?, ?, ?)")
    _, err = stmt.Exec(TEST_FEED_URL, "RSS", "")
    if err != nil {
        t.Error(err)
    }
    tx.Commit()
    rows, err2 := db.Query("select url, type, charset from feeds")
    if err2 != nil {
        t.Error(err2)
    }
    var foundTestData bool = false
    for rows.Next() {
        var url, _type, charset string
        rows.Scan(&url, &_type, &charset)
        if url == TEST_FEED_URL && (_type == "RSS" || _type == "rss") && charset == "" {
            foundTestData = true
            break
        }
    }
    if !foundTestData {
        t.Log("Could not find the test data that was inserted into the database.")
        t.Fail()
    }
}

/**
 * Test that our abstraction over Go's builtin database operations work
 * well enough for an operation to save new feed data to work.
 */
func TestSaveNewFeed(t *testing.T) {
    t.Log("Testing SaveNewFeed")
    db, err := InitDBConnection(TEST_DB_FILE)
    if err != nil {
        t.Error(err)
    }
    defer db.Close()
    feed := FeedInfo{0, TEST_FEED_URL, "RSS", "test-charset"}
    err = SaveNewFeed(db, feed)
    if err != nil {
        t.Error(err)
    }
    rows, err2 := db.Query("select url, type, charset from feeds")
    if err2 != nil {
        t.Error(err2)
    }
    var foundTestData bool = false
    for rows.Next() {
        var url, _type, charset string
        rows.Scan(&url, &_type, &charset)
        if url == TEST_FEED_URL &&
            (_type == "RSS" || _type == "rss") &&
            charset == "test-charset" {
            foundTestData = true
            break
        }
    }
    if !foundTestData {
        t.Log("Could not find the test data that was inserted into the database")
        t.Fail()
    }
}

func TestMain(m *testing.M) {
    // Create the DB ahead of time.
    db, _ := InitDBConnection(TEST_DB_FILE)
    db.Close()
    result := m.Run()
    // Quite effectively deletes the entire SQLite database.
    os.Remove(TEST_DB_FILE)
    os.Exit(result)
}
<commit_msg>Working on test for AllFeeds<commit_after>package main

import (
    "testing"
    "os"
    "database/sql"
    _ "github.com/mattn/go-sqlite3"
)

// Database file to craete/use that will not interfere with the one
// created during the normal operation on the RSS Reader
const TEST_DB_FILE = "testing_db.db"

// A URI for Hacker News' RSS feed
const TEST_FEED_URL = "https://news.ycombinator.com/rss"

/**
 * Test that the database has been intialized properly and that we
 * can, without error, insert some data into the feeds table and then
 * retrieve it successfully.
 */
func TestDBInitialization(t *testing.T) {
    t.Log("Testing database initialization")
    var db *sql.DB
    var err error
    db, err = InitDBConnection(TEST_DB_FILE)
    defer db.Close()
    if err != nil {
        t.Error(err)
    }
    tx, _ := db.Begin()
    stmt, _ := tx.Prepare("insert into feeds(url, type, charset) values(?, ?, ?)")
    _, err = stmt.Exec(TEST_FEED_URL, "RSS", "")
    if err != nil {
        t.Error(err)
    }
    tx.Commit()
    rows, err2 := db.Query("select url, type, charset from feeds")
    if err2 != nil {
        t.Error(err2)
    }
    var foundTestData bool = false
    for rows.Next() {
        var url, _type, charset string
        rows.Scan(&url, &_type, &charset)
        if url == TEST_FEED_URL && (_type == "RSS" || _type == "rss") && charset == "" {
            foundTestData = true
            break
        }
    }
    if !foundTestData {
        t.Log("Could not find the test data that was inserted into the database.")
        t.Fail()
    }
}

/**
 * Test that our abstraction over Go's builtin database operations work
 * well enough for an operation to save new feed data to work.
 */
func TestSaveNewFeed(t *testing.T) {
    t.Log("Testing SaveNewFeed")
    db, err := InitDBConnection(TEST_DB_FILE)
    if err != nil {
        t.Error(err)
    }
    defer db.Close()
    feed := FeedInfo{0, TEST_FEED_URL, "RSS", "test-charset"}
    err = SaveNewFeed(db, feed)
    if err != nil {
        t.Error(err)
    }
    rows, err2 := db.Query("select url, type, charset from feeds")
    if err2 != nil {
        t.Error(err2)
    }
    var foundTestData bool = false
    for rows.Next() {
        var url, _type, charset string
        rows.Scan(&url, &_type, &charset)
        if url == TEST_FEED_URL &&
            (_type == "RSS" || _type == "rss") &&
            charset == "test-charset" {
            foundTestData = true
            break
        }
    }
    if !foundTestData {
        t.Log("Could not find the test data that was inserted into the database")
        t.Fail()
    }
}

/**
 * Test that we can create a handful of feeds and then retrieve them all.
 */
func TestAllFeeds(t *testing.T) {
    testFeeds := []FeedInfo{
        {0, "URL1", "RSS", "chs1"},
        {1, "URL2", "Atom", "chs2"},
        {2, "URL3", "RSS", "chs3"},
    }
    // A parallel array signalling which testFeeds have been retrieved.
    // Note that the values each default to `false` so they don't need to be set manually.
    var testsMatched []bool = make([]bool, len(testFeeds))
    db, err := InitDBConnection(TEST_DB_FILE)
    if err != nil {
        t.Error(err)
    }
    defer db.Close()
    tx, _ := db.Begin()
    // Insert all the test feeds into the database
    for _, feed := range testFeeds {
        stmt, err2 := tx.Prepare("insert into feeds (url, type, charset) values (?, ?, ?)")
        if err2 != nil {
            t.Error(err2)
        }
        defer stmt.Close()
        stmt.Exec(feed.URL, feed.Type, feed.Charset)
    }
    tx.Commit()
    // Retrieve all the test feeds from the database and make sure
    // we got everything we put in
    feeds, err3 := AllFeeds(db)
    if err3 != nil {
        t.Error(err3)
    }
    if len(feeds) < len(testFeeds) {
        t.Log("Did not retrieve as many feeds as were inserted for testing.")
        t.Fail()
    }
    for _, feed := range feeds {
        for i, testCase := range testFeeds {
            if feed.URL == testCase.URL &&
                feed.Type == testCase.Type &&
                feed.Charset == testCase.Charset {
                testsMatched[i] = true
                break
            }
        }
    }
    for i, match := range testsMatched {
        if !match {
            t.Logf("Did not retrieve test feed #%d.", i)
            t.Fail()
        }
    }
}

func TestMain(m *testing.M) {
    // Create the DB ahead of time.
    db, _ := InitDBConnection(TEST_DB_FILE)
    db.Close()
    result := m.Run()
    // Quite effectively deletes the entire SQLite database.
    os.Remove(TEST_DB_FILE)
    os.Exit(result)
}
<|endoftext|>


<commit_before>package influxdb

import (
	"encoding/json"
	"fmt"
	"testing"

	"go.skia.org/infra/go/testutils"

	client "github.com/influxdata/influxdb/client/v2"
	"github.com/influxdb/influxdb/models"
	assert "github.com/stretchr/testify/require"
)

type dummyClient struct {
	queryFn func(client.Query) (*client.Response, error)
}

func (c dummyClient) Query(q client.Query) (*client.Response, error) {
	return c.queryFn(q)
}

func (c dummyClient) Write(client.BatchPoints) error {
	return nil
}

func TestQueryNumber(t *testing.T) {
	type queryCase struct {
		Name        string
		QueryFunc   func(client.Query) (*client.Response, error)
		ExpectedVal []*Point
		ExpectedErr error
	}
	cases := []queryCase{
		queryCase{
			Name: "QueryFailed",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return nil, fmt.Errorf("<dummy error>")
			},
			ExpectedVal: nil,
			ExpectedErr: fmt.Errorf("Failed to query InfluxDB with query \"<dummy query>\": <dummy error>"),
		},
		queryCase{
			Name: "EmptyResults",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{}, nil
			},
			ExpectedVal: nil,
			ExpectedErr: fmt.Errorf("Query returned no results: d=\"nodatabase\" q=\"<dummy query>\""),
		},
		queryCase{
			Name: "MultipleResults",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{},
						client.Result{},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: nil,
			ExpectedErr: fmt.Errorf("Query returned more than one result: d=\"nodatabase\" q=\"<dummy query>\""),
		},
		queryCase{
			Name: "NoSeries",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{
							Series: []models.Row{},
						},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: []*Point{},
			ExpectedErr: nil,
		},
		queryCase{
			Name: "MultipleSeries",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{
							Series: []models.Row{

								models.Row{
									Columns: []string{"time", "value"},
									Values: [][]interface{}{
										[]interface{}{
											interface{}(12345),
											interface{}(json.Number("1.5")),
										},
									},
								},
								models.Row{
									Columns: []string{"time", "value"},
									Values: [][]interface{}{
										[]interface{}{
											interface{}(12345),
											interface{}(json.Number("3.5")),
										},
									},
								},
							},
						},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: []*Point{
				&Point{
					Tags:  nil,
					Value: json.Number("1.5"),
				},
				&Point{
					Tags:  nil,
					Value: json.Number("3.5"),
				},
			},
			ExpectedErr: nil,
		},
		queryCase{
			Name: "NotEnoughCols",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{
							Series: []models.Row{
								models.Row{
									Columns: []string{"value"},
									Values: [][]interface{}{
										[]interface{}{
											interface{}(12345),
											interface{}(1.004),
										},
									},
								},
							},
						},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: nil,
			ExpectedErr: fmt.Errorf("Invalid data from InfluxDB: Point data does not match column spec:\nCols:\n[value]\nVals:\n[12345 1.004]"),
		},
		queryCase{
			Name: "TooManyCols",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{
							Series: []models.Row{
								models.Row{
									Columns: []string{"time", "label", "value"},
									Values: [][]interface{}{
										[]interface{}{
											interface{}(12345),
											interface{}(1.004),
										},
									},
								},
							},
						},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: nil,
			ExpectedErr: fmt.Errorf("Query returned an incorrect set of columns: \"<dummy query>\" [time label value]"),
		},
		queryCase{
			Name: "NoPoints",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{
							Series: []models.Row{
								models.Row{
									Columns: []string{"time", "value"},
									Values:  [][]interface{}{},
								},
							},
						},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: nil,
			ExpectedErr: fmt.Errorf("Query returned no points: \"<dummy query>\""),
		},
		queryCase{
			Name: "GoodData",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{
							Series: []models.Row{
								models.Row{
									Columns: []string{"time", "value"},
									Values: [][]interface{}{
										[]interface{}{
											interface{}(12345),
											interface{}(json.Number("1.5")),
										},
									},
								},
							},
						},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: []*Point{
				&Point{
					Tags:  nil,
					Value: json.Number("1.5"),
				},
			},
			ExpectedErr: nil,
		},
		queryCase{
			Name: "GoodWithSequenceNumber",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{
							Series: []models.Row{
								models.Row{
									Columns: []string{"time", "sequence_number", "value"},
									Values: [][]interface{}{
										[]interface{}{
											interface{}(12345),
											interface{}(10001),
											interface{}(json.Number("1.5")),
										},
									},
								},
							},
						},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: []*Point{
				&Point{
					Tags:  nil,
					Value: json.Number("1.5"),
				},
			},
			ExpectedErr: nil,
		},
	}

	errorStr := "Case %s:\nExpected:\n%v\nActual:\n%v"
	for _, c := range cases {
		client := Client{
			Database:     "nodatabase",
			influxClient: dummyClient{c.QueryFunc},
		}
		res, err := client.Query(client.Database, "<dummy query>")
		assert.Equal(t, c.ExpectedErr, err, fmt.Sprintf(errorStr, c.Name, c.ExpectedErr, err))
		if err != nil {
			continue
		}
		testutils.AssertDeepEqual(t, res, c.ExpectedVal)
	}

}
<commit_msg>Speculative fix for infra trybot<commit_after>package influxdb

import (
	"encoding/json"
	"fmt"
	"testing"

	"go.skia.org/infra/go/testutils"

	client "github.com/influxdata/influxdb/client/v2"
	"github.com/influxdata/influxdb/models"
	assert "github.com/stretchr/testify/require"
)

type dummyClient struct {
	queryFn func(client.Query) (*client.Response, error)
}

func (c dummyClient) Query(q client.Query) (*client.Response, error) {
	return c.queryFn(q)
}

func (c dummyClient) Write(client.BatchPoints) error {
	return nil
}

func TestQueryNumber(t *testing.T) {
	type queryCase struct {
		Name        string
		QueryFunc   func(client.Query) (*client.Response, error)
		ExpectedVal []*Point
		ExpectedErr error
	}
	cases := []queryCase{
		queryCase{
			Name: "QueryFailed",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return nil, fmt.Errorf("<dummy error>")
			},
			ExpectedVal: nil,
			ExpectedErr: fmt.Errorf("Failed to query InfluxDB with query \"<dummy query>\": <dummy error>"),
		},
		queryCase{
			Name: "EmptyResults",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{}, nil
			},
			ExpectedVal: nil,
			ExpectedErr: fmt.Errorf("Query returned no results: d=\"nodatabase\" q=\"<dummy query>\""),
		},
		queryCase{
			Name: "MultipleResults",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{},
						client.Result{},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: nil,
			ExpectedErr: fmt.Errorf("Query returned more than one result: d=\"nodatabase\" q=\"<dummy query>\""),
		},
		queryCase{
			Name: "NoSeries",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{
							Series: []models.Row{},
						},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: []*Point{},
			ExpectedErr: nil,
		},
		queryCase{
			Name: "MultipleSeries",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{
							Series: []models.Row{

								models.Row{
									Columns: []string{"time", "value"},
									Values: [][]interface{}{
										[]interface{}{
											interface{}(12345),
											interface{}(json.Number("1.5")),
										},
									},
								},
								models.Row{
									Columns: []string{"time", "value"},
									Values: [][]interface{}{
										[]interface{}{
											interface{}(12345),
											interface{}(json.Number("3.5")),
										},
									},
								},
							},
						},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: []*Point{
				&Point{
					Tags:  nil,
					Value: json.Number("1.5"),
				},
				&Point{
					Tags:  nil,
					Value: json.Number("3.5"),
				},
			},
			ExpectedErr: nil,
		},
		queryCase{
			Name: "NotEnoughCols",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{
							Series: []models.Row{
								models.Row{
									Columns: []string{"value"},
									Values: [][]interface{}{
										[]interface{}{
											interface{}(12345),
											interface{}(1.004),
										},
									},
								},
							},
						},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: nil,
			ExpectedErr: fmt.Errorf("Invalid data from InfluxDB: Point data does not match column spec:\nCols:\n[value]\nVals:\n[12345 1.004]"),
		},
		queryCase{
			Name: "TooManyCols",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{
							Series: []models.Row{
								models.Row{
									Columns: []string{"time", "label", "value"},
									Values: [][]interface{}{
										[]interface{}{
											interface{}(12345),
											interface{}(1.004),
										},
									},
								},
							},
						},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: nil,
			ExpectedErr: fmt.Errorf("Query returned an incorrect set of columns: \"<dummy query>\" [time label value]"),
		},
		queryCase{
			Name: "NoPoints",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{
							Series: []models.Row{
								models.Row{
									Columns: []string{"time", "value"},
									Values:  [][]interface{}{},
								},
							},
						},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: nil,
			ExpectedErr: fmt.Errorf("Query returned no points: \"<dummy query>\""),
		},
		queryCase{
			Name: "GoodData",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{
							Series: []models.Row{
								models.Row{
									Columns: []string{"time", "value"},
									Values: [][]interface{}{
										[]interface{}{
											interface{}(12345),
											interface{}(json.Number("1.5")),
										},
									},
								},
							},
						},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: []*Point{
				&Point{
					Tags:  nil,
					Value: json.Number("1.5"),
				},
			},
			ExpectedErr: nil,
		},
		queryCase{
			Name: "GoodWithSequenceNumber",
			QueryFunc: func(q client.Query) (*client.Response, error) {
				return &client.Response{
					Results: []client.Result{
						client.Result{
							Series: []models.Row{
								models.Row{
									Columns: []string{"time", "sequence_number", "value"},
									Values: [][]interface{}{
										[]interface{}{
											interface{}(12345),
											interface{}(10001),
											interface{}(json.Number("1.5")),
										},
									},
								},
							},
						},
					},
					Err: "",
				}, nil
			},
			ExpectedVal: []*Point{
				&Point{
					Tags:  nil,
					Value: json.Number("1.5"),
				},
			},
			ExpectedErr: nil,
		},
	}

	errorStr := "Case %s:\nExpected:\n%v\nActual:\n%v"
	for _, c := range cases {
		client := Client{
			Database:     "nodatabase",
			influxClient: dummyClient{c.QueryFunc},
		}
		res, err := client.Query(client.Database, "<dummy query>")
		assert.Equal(t, c.ExpectedErr, err, fmt.Sprintf(errorStr, c.Name, c.ExpectedErr, err))
		if err != nil {
			continue
		}
		testutils.AssertDeepEqual(t, res, c.ExpectedVal)
	}

}
<|endoftext|>


<commit_before>// An image/draw compatible interface to the linux framebuffer
package framebuffer

import (
	"image"
	"image/color"

	"os"
)

const (
	red   = 2
	green = 1
	blue  = 0
	x     = 3 // not sure what this does, but there's a slot for it.

	colorBytes = 4
)

type FrameBuffer struct {
	buf  []byte
	h, w int
	file *os.File
}

func (fb *FrameBuffer) ColorModel() color.Model {
	return color.RGBAModel
}

func (fb *FrameBuffer) Bounds() image.Rectangle {
	return image.Rectangle{
		Min: image.Point{X: 0, Y: 0},
		Max: image.Point{X: fb.w, Y: fb.h},
	}
}

func (fb *FrameBuffer) getPixelStart(x, y int) int {
	return (y*fb.w + x) * colorBytes
}

func (fb *FrameBuffer) At(x, y int) color.Color {
	pixelStart := fb.getPixelStart(x, y)
	return color.RGBA{
		R: fb.buf[pixelStart+red],
		G: fb.buf[pixelStart+green],
		B: fb.buf[pixelStart+blue],
		A: 0,
	}
}

func (fb *FrameBuffer) Set(x, y int, c color.Color) {
	pixelStart := fb.getPixelStart(x, y)
	r, g, b, _ := c.RGBA()
	fb.buf[pixelStart+red] = uint8(r)
	fb.buf[pixelStart+green] = uint8(g)
	fb.buf[pixelStart+blue] = uint8(b)
}

func (fb *FrameBuffer) Flush() error {
	fb.file.Seek(0, 0)
	_, err := fb.file.Write(fb.buf)
	return err
}

// Opens/initializes the framebuffer with device node located at <filename>.
// width and height should be the width and height of the display, in pixels.
func Open(filename string, width, height int) (*FrameBuffer, error) {
	file, err := os.OpenFile(filename, os.O_RDWR, 0)
	if err != nil {
		return nil, err
	}

	return &FrameBuffer{buf: make([]byte, height*width*colorBytes), w: width, h: height, file: file}, nil
}
<commit_msg>Added some documentation.<commit_after>// An image/draw compatible interface to the linux framebuffer
//
// Use Open() to get a framebuffer object, draw on it using the
// facilities of image/draw, and call its Flush() method to sync changes
// to the display.
package framebuffer

import (
	"image"
	"image/color"

	"os"
)

const (
	red   = 2
	green = 1
	blue  = 0
	x     = 3 // not sure what this does, but there's a slot for it.

	colorBytes = 4
)

type FrameBuffer struct {
	buf  []byte
	h, w int
	file *os.File
}

func (fb *FrameBuffer) ColorModel() color.Model {
	return color.RGBAModel
}

func (fb *FrameBuffer) Bounds() image.Rectangle {
	return image.Rectangle{
		Min: image.Point{X: 0, Y: 0},
		Max: image.Point{X: fb.w, Y: fb.h},
	}
}

func (fb *FrameBuffer) getPixelStart(x, y int) int {
	return (y*fb.w + x) * colorBytes
}

func (fb *FrameBuffer) At(x, y int) color.Color {
	pixelStart := fb.getPixelStart(x, y)
	return color.RGBA{
		R: fb.buf[pixelStart+red],
		G: fb.buf[pixelStart+green],
		B: fb.buf[pixelStart+blue],
		A: 0,
	}
}

func (fb *FrameBuffer) Set(x, y int, c color.Color) {
	pixelStart := fb.getPixelStart(x, y)
	r, g, b, _ := c.RGBA()
	fb.buf[pixelStart+red] = uint8(r)
	fb.buf[pixelStart+green] = uint8(g)
	fb.buf[pixelStart+blue] = uint8(b)
}

// Sync changes to video memory - nothing will actually appear on the
// screen until this is called.
func (fb *FrameBuffer) Flush() error {
	fb.file.Seek(0, 0)
	_, err := fb.file.Write(fb.buf)
	return err
}

// Opens/initializes the framebuffer with device node located at <filename>.
// width and height should be the width and height of the display, in pixels.
func Open(filename string, width, height int) (*FrameBuffer, error) {
	file, err := os.OpenFile(filename, os.O_RDWR, 0)
	if err != nil {
		return nil, err
	}

	return &FrameBuffer{buf: make([]byte, height*width*colorBytes), w: width, h: height, file: file}, nil
}
<|endoftext|>


<commit_before>package handlers

import (
	"bytes"
	"crypto/md5"
	"fmt"
	"image/png"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/getfider/fider/app/pkg/web"
	"github.com/goenning/letteravatar"
)

//Avatar returns a gravatar picture of fallsback to letter avatar based on name
func Avatar() web.HandlerFunc {
	return func(c web.Context) error {
		name := c.Param("name")
		size, _ := c.ParamAsInt("size")
		id, err := c.ParamAsInt("id")

		if err == nil && id > 0 {
			user, err := c.Services().Users.GetByID(id)
			if err == nil && user.Tenant.ID == c.Tenant().ID {
				if user.Email != "" {
					hash := md5.Sum([]byte(user.Email))
					url := fmt.Sprintf("https://www.gravatar.com/avatar/%x?s=%d&d=404", hash, size)
					c.Logger().Debugf("Requesting gravatar: %s", url)
					resp, err := http.Get(url)
					if err == nil && resp != nil && resp.StatusCode == http.StatusOK {
						bytes, err := ioutil.ReadAll(resp.Body)
						if err == nil {
							return c.Blob(http.StatusOK, "image/png", bytes)
						}
					}
				}
			}
		}

		img, err := letteravatar.Draw(size, strings.ToUpper(letteravatar.Extract(name)), &letteravatar.Options{PaletteKey: name})
		if err != nil {
			return c.Failure(err)
		}

		buf := new(bytes.Buffer)
		err = png.Encode(buf, img)
		if err != nil {
			return c.Failure(err)
		}

		return c.Blob(http.StatusOK, "image/png", buf.Bytes())
	}
}
<commit_msg>fix: close response body from avatar get (#290)<commit_after>package handlers

import (
	"bytes"
	"crypto/md5"
	"fmt"
	"image/png"
	"io"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/getfider/fider/app/pkg/web"
	"github.com/goenning/letteravatar"
)

//Avatar returns a gravatar picture of fallsback to letter avatar based on name
func Avatar() web.HandlerFunc {
	return func(c web.Context) error {
		name := c.Param("name")
		size, _ := c.ParamAsInt("size")
		id, err := c.ParamAsInt("id")

		if err == nil && id > 0 {
			user, err := c.Services().Users.GetByID(id)
			if err == nil && user.Tenant.ID == c.Tenant().ID {
				if user.Email != "" {
					hash := md5.Sum([]byte(user.Email))
					url := fmt.Sprintf("https://www.gravatar.com/avatar/%x?s=%d&d=404", hash, size)
					c.Logger().Debugf("Requesting gravatar: %s", url)
					resp, err := http.Get(url)
					if err == nil {
						defer resp.Body.Close()

						if resp.StatusCode == http.StatusOK {
							bytes, err := ioutil.ReadAll(resp.Body)
							if err == nil {
								return c.Blob(http.StatusOK, "image/png", bytes)
							}
						} else {
							io.Copy(ioutil.Discard, resp.Body)
						}
					}
				}
			}
		}

		img, err := letteravatar.Draw(size, strings.ToUpper(letteravatar.Extract(name)), &letteravatar.Options{PaletteKey: name})
		if err != nil {
			return c.Failure(err)
		}

		buf := new(bytes.Buffer)
		err = png.Encode(buf, img)
		if err != nil {
			return c.Failure(err)
		}

		return c.Blob(http.StatusOK, "image/png", buf.Bytes())
	}
}
<|endoftext|>


<commit_before><commit_msg>magneticod: fix database open error logging<commit_after><|endoftext|>


<commit_before>// Copyright 2013 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 gccgoimporter implements Import for gccgo-generated object files.
package gccgoimporter

import (
	"debug/elf"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"

	"code.google.com/p/go.tools/go/types"
)

// Locate the file from which to read export data.
// This is intended to replicate the logic in gofrontend.
func findExportFile(searchpaths []string, pkgpath string) (string, error) {
	for _, spath := range searchpaths {
		pkgfullpath := filepath.Join(spath, pkgpath)
		pkgdir, name := filepath.Split(pkgfullpath)

		for _, filepath := range [...]string{
			pkgfullpath,
			pkgfullpath + ".gox",
			pkgdir + "lib" + name + ".so",
			pkgdir + "lib" + name + ".a",
			pkgfullpath + ".o",
		} {
			fi, err := os.Stat(filepath)
			if err == nil && !fi.IsDir() {
				return filepath, nil
			}
		}
	}

	return "", fmt.Errorf("%s: could not find export data (tried %s)", pkgpath, strings.Join(searchpaths, ":"))
}

// Opens the export data file at the given path. If this is an ELF file,
// searches for and opens the .go_export section.
// This is intended to replicate the logic in gofrontend, although it doesn't handle archive files yet.
func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err error) {
	f, err := os.Open(fpath)
	if err != nil {
		return
	}
	closer = f

	var magic [4]byte
	_, err = f.ReadAt(magic[:], 0)
	if err != nil {
		f.Close()
		return
	}

	if string(magic[:]) == "v1;\n" {
		// Raw export data.
		reader = f
		return
	}

	ef, err := elf.NewFile(f)
	if err != nil {
		f.Close()
		return
	}

	sec := ef.Section(".go_export")
	if sec == nil {
		err = fmt.Errorf("%s: .go_export section not found", fpath)
		f.Close()
		return
	}

	reader = sec.Open()
	return
}

func GetImporter(searchpaths []string) types.Importer {
	return func(imports map[string]*types.Package, pkgpath string) (pkg *types.Package, err error) {
		if pkgpath == "unsafe" {
			return types.Unsafe, nil
		}

		fpath, err := findExportFile(searchpaths, pkgpath)
		if err != nil {
			return
		}

		reader, closer, err := openExportFile(fpath)
		if err != nil {
			return
		}
		defer closer.Close()

		var p parser
		p.init(fpath, reader, imports)
		pkg = p.parsePackage()
		return
	}
}
<commit_msg>go.tools/go/gccgoimporter: backported some changes from godex implementation<commit_after>// Copyright 2013 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 gccgoimporter implements Import for gccgo-generated object files.
package gccgoimporter

import (
	"debug/elf"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"

	"code.google.com/p/go.tools/go/types"
)

// Locate the file from which to read export data.
// This is intended to replicate the logic in gofrontend.
func findExportFile(searchpaths []string, pkgpath string) (string, error) {
	for _, spath := range searchpaths {
		pkgfullpath := filepath.Join(spath, pkgpath)
		pkgdir, name := filepath.Split(pkgfullpath)

		for _, filepath := range [...]string{
			pkgfullpath,
			pkgfullpath + ".gox",
			pkgdir + "lib" + name + ".so",
			pkgdir + "lib" + name + ".a",
			pkgfullpath + ".o",
		} {
			fi, err := os.Stat(filepath)
			if err == nil && !fi.IsDir() {
				return filepath, nil
			}
		}
	}

	return "", fmt.Errorf("%s: could not find export data (tried %s)", pkgpath, strings.Join(searchpaths, ":"))
}

// Opens the export data file at the given path. If this is an ELF file,
// searches for and opens the .go_export section.
// This is intended to replicate the logic in gofrontend, although it doesn't handle archive files yet.
func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err error) {
	f, err := os.Open(fpath)
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			f.Close()
		}
	}()
	closer = f

	var magic [4]byte
	_, err = f.ReadAt(magic[:], 0)
	if err != nil {
		return
	}

	if string(magic[:]) == "v1;\n" {
		// Raw export data.
		reader = f
		return
	}

	ef, err := elf.NewFile(f)
	if err != nil {
		return
	}

	sec := ef.Section(".go_export")
	if sec == nil {
		err = fmt.Errorf("%s: .go_export section not found", fpath)
		return
	}

	reader = sec.Open()
	return
}

func GetImporter(searchpaths []string) types.Importer {
	return func(imports map[string]*types.Package, pkgpath string) (pkg *types.Package, err error) {
		if pkgpath == "unsafe" {
			return types.Unsafe, nil
		}

		fpath, err := findExportFile(searchpaths, pkgpath)
		if err != nil {
			return
		}

		reader, closer, err := openExportFile(fpath)
		if err != nil {
			return
		}
		defer closer.Close()

		var p parser
		p.init(fpath, reader, imports)
		pkg = p.parsePackage()
		return
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"github.com/howeyc/fsnotify"
	"koding/newkite/kite"
	"koding/newkite/protocol"
	"koding/tools/dnode"
	"koding/tools/fsutils"
	"log"
	"os"
	"path"
	"sync"
)

type Os struct{}

var (
	port = flag.String("port", "4002", "port to bind itself")

	// watcher variables
	once               sync.Once
	newPaths, oldPaths = make(chan string), make(chan string)
	watchCallbacks     = make(map[string]func(*fsnotify.FileEvent), 100) // Limit of watching folders
)

func main() {
	flag.Parse()
	options := &protocol.Options{
		PublicIP: "localhost",
		Kitename: "fs",
		Version:  "1",
		Port:     *port,
	}

	methods := map[string]string{
		"fs.createDirectory":       "ReadDirectory",
		"fs.ensureNonexistentPath": "EnsureNonexistentPath",
		"fs.getInfo":               "GetInfo",
		"fs.glob":                  "Glob",
		"fs.readDirectory":         "ReadDirectory",
		"fs.readFile":              "ReadFile",
		"fs.remove":                "Remove",
		"fs.rename ":               "Rename",
		"fs.setPermissions":        "SetPermissions",
		"fs.writeFile":             "WriteFile",
	}

	k := kite.New(options)
	k.AddMethods(new(Os), methods)
	k.Start()
}

func (Os) ReadDirectory(r *protocol.KiteDnodeRequest, result *map[string]interface{}) error {

	var params struct {
		Path                string
		OnChange            dnode.Callback
		WatchSubdirectories bool
	}

	if r.Args.Unmarshal(&params) != nil || params.Path == "" {
		return errors.New("{ path: [string], onChange: [function], watchSubdirectories: [bool] }")
	}

	response := make(map[string]interface{})

	if params.OnChange != nil {
		onceBody := func() { startWatcher() }
		go once.Do(onceBody)

		// notify new paths to the watcher
		newPaths <- params.Path

		var event string
		var fileEntry *fsutils.FileEntry
		changer := func(ev *fsnotify.FileEvent) {
			if ev.IsCreate() {
				event = "added"
				fileEntry, _ = fsutils.GetInfo(ev.Name)
			} else if ev.IsDelete() {
				event = "removed"
				fileEntry = fsutils.NewFileEntry(path.Base(ev.Name), ev.Name)
			}

			params.OnChange(map[string]interface{}{
				"event": event,
				"file":  fileEntry,
			})
			return
		}

		watchCallbacks[params.Path] = changer

		// this callback is called whenever we receive a 'stopWatching' from the client
		response["stopWatching"] = func() {
			delete(watchCallbacks, params.Path)
			oldPaths <- params.Path
		}
	}

	files, err := fsutils.ReadDirectory(params.Path)
	if err != nil {
		return err
	}

	response["files"] = files
	*result = response
	return nil
}

func (Os) Glob(r *protocol.KiteDnodeRequest, result *[]string) error {
	var params struct {
		Pattern string
	}

	if r.Args.Unmarshal(&params) != nil || params.Pattern == "" {
		return errors.New("{ pattern: [string] }")
	}

	files, err := fsutils.Glob(params.Pattern)
	if err != nil {
		return err
	}

	*result = files
	return nil
}

func (Os) ReadFile(r *protocol.KiteDnodeRequest, result *map[string]interface{}) error {
	var params struct {
		Path string
	}
	if r.Args.Unmarshal(&params) != nil || params.Path == "" {
		return errors.New("{ path: [string] }")
	}

	buf, err := fsutils.ReadFile(params.Path)
	if err != nil {
		return err
	}

	*result = map[string]interface{}{"content": buf}
	return nil
}

func (Os) WriteFile(r *protocol.KiteDnodeRequest, result *string) error {
	var params struct {
		Path           string
		Content        []byte
		DoNotOverwrite bool
		Append         bool
	}

	if r.Args.Unmarshal(&params) != nil || params.Path == "" || params.Content == nil {
		return errors.New("{ path: [string], content: [base64], doNotOverwrite: [bool], append: [bool] }")
	}

	err := fsutils.WriteFile(params.Path, params.Content, params.DoNotOverwrite, params.Append)
	if err != nil {
		return err
	}

	*result = fmt.Sprintf("content written to %s", params.Path)
	return nil
}

func (Os) EnsureNonexistentPath(r *protocol.KiteDnodeRequest, result *string) error {
	var params struct {
		Path string
	}

	if r.Args.Unmarshal(&params) != nil || params.Path == "" {
		return errors.New("{ path: [string] }")
	}

	name, err := fsutils.EnsureNonexistentPath(params.Path)
	if err != nil {
		return err
	}

	*result = name
	return nil
}

func (Os) GetInfo(r *protocol.KiteDnodeRequest, result *fsutils.FileEntry) error {
	var params struct {
		Path string
	}
	if r.Args.Unmarshal(&params) != nil || params.Path == "" {
		return errors.New("{ path: [string] }")
	}

	fileEntry, err := fsutils.GetInfo(params.Path)
	if err != nil {
		return err
	}

	*result = *fileEntry
	return nil
}

func (Os) SetPermissions(r *protocol.KiteDnodeRequest, result *bool) error {
	var params struct {
		Path      string
		Mode      os.FileMode
		Recursive bool
	}
	if r.Args.Unmarshal(&params) != nil || params.Path == "" {
		return errors.New("{ path: [string], mode: [integer], recursive: [bool] }")
	}

	err := fsutils.SetPermissions(params.Path, params.Mode, params.Recursive)
	if err != nil {
		return err
	}

	*result = true
	return nil

}

func (Os) Remove(r *protocol.KiteDnodeRequest, result *bool) error {
	var params struct {
		Path      string
		Recursive bool
	}

	if r.Args.Unmarshal(&params) != nil || params.Path == "" {
		return errors.New("{ path: [string], recursive: [bool] }")
	}

	err := fsutils.Remove(params.Path)
	if err != nil {
		return err
	}

	*result = true
	return nil
}

func (Os) Rename(r *protocol.KiteDnodeRequest, result *bool) error {
	var params struct {
		OldPath string
		NewPath string
	}

	if r.Args.Unmarshal(&params) != nil || params.OldPath == "" || params.NewPath == "" {
		return errors.New("{ oldPath: [string], newPath: [string] }")
	}

	err := fsutils.Rename(params.OldPath, params.NewPath)
	if err != nil {
		return err
	}

	*result = true
	return nil
}

func (Os) CreateDirectory(r *protocol.KiteDnodeRequest, result *bool) error {
	var params struct {
		Path      string
		Recursive bool
	}
	if r.Args.Unmarshal(&params) != nil || params.Path == "" {
		return errors.New("{ path: [string], recursive: [bool] }")
	}

	err := fsutils.CreateDirectory(params.Path, params.Recursive)
	if err != nil {
		return err
	}
	*result = true
	return nil
}

func startWatcher() {
	var err error
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}

	go func() {
		for {
			select {
			case p := <-newPaths:
				err := watcher.Watch(p)
				if err != nil {
					log.Println("watch path adding", err)
				}
			case p := <-oldPaths:
				err := watcher.RemoveWatch(p)
				if err != nil {
					log.Println("watch remove adding", err)
				}
			}
		}
	}()

	for event := range watcher.Event {
		f, ok := watchCallbacks[path.Dir(event.Name)]
		if !ok {
			continue
		}

		f(event)
	}
}
<commit_msg>kite: rename Os to Fs<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"github.com/howeyc/fsnotify"
	"koding/newkite/kite"
	"koding/newkite/protocol"
	"koding/tools/dnode"
	"koding/tools/fsutils"
	"log"
	"os"
	"path"
	"sync"
)

type Fs struct{}

var (
	port = flag.String("port", "4002", "port to bind itself")

	// watcher variables
	once               sync.Once
	newPaths, oldPaths = make(chan string), make(chan string)
	watchCallbacks     = make(map[string]func(*fsnotify.FileEvent), 100) // Limit of watching folders
)

func main() {
	flag.Parse()
	options := &protocol.Options{
		PublicIP: "localhost",
		Kitename: "fs",
		Version:  "1",
		Port:     *port,
	}

	methods := map[string]string{
		"fs.createDirectory":       "ReadDirectory",
		"fs.ensureNonexistentPath": "EnsureNonexistentPath",
		"fs.getInfo":               "GetInfo",
		"fs.glob":                  "Glob",
		"fs.readDirectory":         "ReadDirectory",
		"fs.readFile":              "ReadFile",
		"fs.remove":                "Remove",
		"fs.rename ":               "Rename",
		"fs.setPermissions":        "SetPermissions",
		"fs.writeFile":             "WriteFile",
	}

	k := kite.New(options)
	k.AddMethods(new(Fs), methods)
	k.Start()
}

func (Fs) ReadDirectory(r *protocol.KiteDnodeRequest, result *map[string]interface{}) error {

	var params struct {
		Path                string
		OnChange            dnode.Callback
		WatchSubdirectories bool
	}

	if r.Args.Unmarshal(&params) != nil || params.Path == "" {
		return errors.New("{ path: [string], onChange: [function], watchSubdirectories: [bool] }")
	}

	response := make(map[string]interface{})

	if params.OnChange != nil {
		onceBody := func() { startWatcher() }
		go once.Do(onceBody)

		// notify new paths to the watcher
		newPaths <- params.Path

		var event string
		var fileEntry *fsutils.FileEntry
		changer := func(ev *fsnotify.FileEvent) {
			if ev.IsCreate() {
				event = "added"
				fileEntry, _ = fsutils.GetInfo(ev.Name)
			} else if ev.IsDelete() {
				event = "removed"
				fileEntry = fsutils.NewFileEntry(path.Base(ev.Name), ev.Name)
			}

			params.OnChange(map[string]interface{}{
				"event": event,
				"file":  fileEntry,
			})
			return
		}

		watchCallbacks[params.Path] = changer

		// this callback is called whenever we receive a 'stopWatching' from the client
		response["stopWatching"] = func() {
			delete(watchCallbacks, params.Path)
			oldPaths <- params.Path
		}
	}

	files, err := fsutils.ReadDirectory(params.Path)
	if err != nil {
		return err
	}

	response["files"] = files
	*result = response
	return nil
}

func (Fs) Glob(r *protocol.KiteDnodeRequest, result *[]string) error {
	var params struct {
		Pattern string
	}

	if r.Args.Unmarshal(&params) != nil || params.Pattern == "" {
		return errors.New("{ pattern: [string] }")
	}

	files, err := fsutils.Glob(params.Pattern)
	if err != nil {
		return err
	}

	*result = files
	return nil
}

func (Fs) ReadFile(r *protocol.KiteDnodeRequest, result *map[string]interface{}) error {
	var params struct {
		Path string
	}
	if r.Args.Unmarshal(&params) != nil || params.Path == "" {
		return errors.New("{ path: [string] }")
	}

	buf, err := fsutils.ReadFile(params.Path)
	if err != nil {
		return err
	}

	*result = map[string]interface{}{"content": buf}
	return nil
}

func (Fs) WriteFile(r *protocol.KiteDnodeRequest, result *string) error {
	var params struct {
		Path           string
		Content        []byte
		DoNotOverwrite bool
		Append         bool
	}

	if r.Args.Unmarshal(&params) != nil || params.Path == "" || params.Content == nil {
		return errors.New("{ path: [string], content: [base64], doNotOverwrite: [bool], append: [bool] }")
	}

	err := fsutils.WriteFile(params.Path, params.Content, params.DoNotOverwrite, params.Append)
	if err != nil {
		return err
	}

	*result = fmt.Sprintf("content written to %s", params.Path)
	return nil
}

func (Fs) EnsureNonexistentPath(r *protocol.KiteDnodeRequest, result *string) error {
	var params struct {
		Path string
	}

	if r.Args.Unmarshal(&params) != nil || params.Path == "" {
		return errors.New("{ path: [string] }")
	}

	name, err := fsutils.EnsureNonexistentPath(params.Path)
	if err != nil {
		return err
	}

	*result = name
	return nil
}

func (Fs) GetInfo(r *protocol.KiteDnodeRequest, result *fsutils.FileEntry) error {
	var params struct {
		Path string
	}
	if r.Args.Unmarshal(&params) != nil || params.Path == "" {
		return errors.New("{ path: [string] }")
	}

	fileEntry, err := fsutils.GetInfo(params.Path)
	if err != nil {
		return err
	}

	*result = *fileEntry
	return nil
}

func (Fs) SetPermissions(r *protocol.KiteDnodeRequest, result *bool) error {
	var params struct {
		Path      string
		Mode      os.FileMode
		Recursive bool
	}
	if r.Args.Unmarshal(&params) != nil || params.Path == "" {
		return errors.New("{ path: [string], mode: [integer], recursive: [bool] }")
	}

	err := fsutils.SetPermissions(params.Path, params.Mode, params.Recursive)
	if err != nil {
		return err
	}

	*result = true
	return nil

}

func (Fs) Remove(r *protocol.KiteDnodeRequest, result *bool) error {
	var params struct {
		Path      string
		Recursive bool
	}

	if r.Args.Unmarshal(&params) != nil || params.Path == "" {
		return errors.New("{ path: [string], recursive: [bool] }")
	}

	err := fsutils.Remove(params.Path)
	if err != nil {
		return err
	}

	*result = true
	return nil
}

func (Fs) Rename(r *protocol.KiteDnodeRequest, result *bool) error {
	var params struct {
		OldPath string
		NewPath string
	}

	if r.Args.Unmarshal(&params) != nil || params.OldPath == "" || params.NewPath == "" {
		return errors.New("{ oldPath: [string], newPath: [string] }")
	}

	err := fsutils.Rename(params.OldPath, params.NewPath)
	if err != nil {
		return err
	}

	*result = true
	return nil
}

func (Fs) CreateDirectory(r *protocol.KiteDnodeRequest, result *bool) error {
	var params struct {
		Path      string
		Recursive bool
	}
	if r.Args.Unmarshal(&params) != nil || params.Path == "" {
		return errors.New("{ path: [string], recursive: [bool] }")
	}

	err := fsutils.CreateDirectory(params.Path, params.Recursive)
	if err != nil {
		return err
	}
	*result = true
	return nil
}

func startWatcher() {
	var err error
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}

	go func() {
		for {
			select {
			case p := <-newPaths:
				err := watcher.Watch(p)
				if err != nil {
					log.Println("watch path adding", err)
				}
			case p := <-oldPaths:
				err := watcher.RemoveWatch(p)
				if err != nil {
					log.Println("watch remove adding", err)
				}
			}
		}
	}()

	for event := range watcher.Event {
		f, ok := watchCallbacks[path.Dir(event.Name)]
		if !ok {
			continue
		}

		f(event)
	}
}
<|endoftext|>