<commit_before>package main

import (
	"database/sql"
	"flag"
	"fmt"
	"html/template"
	"io"
	"net/http"
	"strings"
	"time"

	"golang.org/x/crypto/acme/autocert"

	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
	"github.com/labstack/gommon/color"
	_ "github.com/mattn/go-sqlite3"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var authDisabled bool
var dbFile = "scan.db"

type port struct {
	Port    int    `json:"port"`
	Proto   string `json:"proto"`
	Status  string `json:"status"`
	Service struct {
		Name   string `json:"name"`
		Banner string `json:"banner"`
	} `json:"service"`
}

// Results posted from masscan
type result struct {
	IP    string `json:"ip"`
	Ports []port `json:"ports"`
}

// Data retrieved from the database for display
type ipInfo struct {
	IP        string
	Port      int
	Proto     string
	FirstSeen string
	LastSeen  string
	New       bool
}

// Load all data for displaying in the browser
func load(s, fs, ls string) ([]ipInfo, error) {
	db, err := sql.Open("sqlite3", dbFile)
	if err != nil {
		return []ipInfo{}, err
	}
	defer db.Close()

	var where string
	var cond []string
	var params []interface{}
	if s != "" {
		cond = append(cond, `ip LIKE ?`)
		params = append(params, fmt.Sprintf("%%%s%%", s))
	}
	if fs != "" {
		cond = append(cond, `firstseen= ?`)
		params = append(params, fs)
	}
	if ls != "" {
		cond = append(cond, `lastseen= ?`)
		params = append(params, ls)
	}
	if len(cond) > 0 {
		where = fmt.Sprintf("WHERE %s", strings.Join(cond, " AND "))
	}

	qry := fmt.Sprintf(`SELECT ip, port, proto, firstseen, lastseen FROM scan %s ORDER BY port, proto, ip, lastseen`, where)
	rows, err := db.Query(qry, params...)
	if err != nil {
		return []ipInfo{}, err
	}

	defer rows.Close()

	var data []ipInfo
	var ip, proto, firstseen, lastseen string
	var port int
	var latest time.Time

	for rows.Next() {
		err := rows.Scan(&ip, &port, &proto, &firstseen, &lastseen)
		if err != nil {
			return []ipInfo{}, err
		}
		last, _ := time.Parse("2006-01-02 15:04", lastseen)
		if last.After(latest) {
			latest = last
		}
		data = append(data, ipInfo{ip, port, proto, firstseen, lastseen, false})
	}

	for i := range data {
		f, _ := time.Parse("2006-01-02 15:04", data[i].FirstSeen)
		l, _ := time.Parse("2006-01-02 15:04", data[i].LastSeen)
		if f.Equal(l) && l == latest {
			data[i].New = true
		}
	}

	return data, nil
}

// Save the results posted
func save(results []result) error {
	db, err := sql.Open("sqlite3", dbFile)
	if err != nil {
		return err
	}
	defer db.Close()

	txn, err := db.Begin()
	if err != nil {
		return err
	}

	insert, err := txn.Prepare(`INSERT INTO scan (ip, port, proto, firstseen, lastseen) VALUES (?, ?, ?, ?, ?)`)
	if err != nil {
		txn.Rollback()
		return err
	}
	qry, err := db.Prepare(`SELECT 1 FROM scan WHERE ip=? AND port=? AND proto=?`)
	if err != nil {
		txn.Rollback()
		return err
	}
	update, err := txn.Prepare(`UPDATE scan SET lastseen=? WHERE ip=? AND port=? AND proto=?`)
	if err != nil {
		txn.Rollback()
		return err
	}

	now := time.Now()
	nowString := now.Format("2006-01-02 15:04")

	for _, r := range results {
		// Although it's an array, only one port is in each
		port := r.Ports[0]

		// Skip results which are (usually) banner-only
		// While it would be nice to store banners, we need to restructure a
		// bit to accommodate this and it just inserts duplicate data for now
		if port.Status == "" || port.Service.Name != "" {
			continue
		}

		// Search for the IP/port/proto combo
		// If it exists, update `lastseen`, else insert a new record

		// Because we have to scan into something
		var x int
		err := qry.QueryRow(r.IP, port.Port, port.Proto).Scan(&x)
		switch {
		case err == sql.ErrNoRows:
			_, err = insert.Exec(r.IP, port.Port, port.Proto, nowString, nowString)
			if err != nil {
				txn.Rollback()
				return err
			}
			continue
		case err != nil:
			txn.Rollback()
			return err
		}

		_, err = update.Exec(nowString, r.IP, port.Port, port.Proto)
		if err != nil {
			txn.Rollback()
			return err
		}
	}

	txn.Commit()
	return nil
}

// Template is a template
type Template struct {
	templates *template.Template
}

// Render renders template
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
	return t.templates.ExecuteTemplate(w, name, data)
}

type indexData struct {
	Authenticated bool
	User          string
	scanData
}

type scanData struct {
	Total    int
	Latest   int
	New      int
	LastSeen string
	Results  []ipInfo
}

func resultData(ip, fs, ls string) (scanData, error) {
	results, err := load(ip, fs, ls)
	if err != nil {
		return scanData{}, err
	}

	timeFmt := "2006-01-02 15:04"
	data := scanData{
		Results: results,
		Total:   len(results),
	}

	// Find all the latest results and store the number in the struct
	var latest time.Time
	for _, r := range results {
		last, _ := time.Parse(timeFmt, r.LastSeen)
		if last.After(latest) {
			latest = last
		}
	}
	for _, r := range results {
		last, _ := time.Parse(timeFmt, r.LastSeen)
		if last.Equal(latest) {
			data.Latest++
		}
		if r.New {
			data.New++
		}
	}
	data.LastSeen = latest.Format(timeFmt)

	return data, nil
}

// Handler for GET /
func index(c echo.Context) error {
	var user string
	if !authDisabled {
		session, err := store.Get(c.Request(), "user")
		if err != nil {
			return c.String(http.StatusInternalServerError, err.Error())
		}
		if _, ok := session.Values["user"]; !ok {
			data := indexData{}
			return c.Render(http.StatusOK, "index", data)
		}
		user = session.Values["user"].(string)
	}

	ip := c.QueryParam("ip")
	firstSeen := c.QueryParam("firstseen")
	lastSeen := c.QueryParam("lastseen")

	results, err := resultData(ip, firstSeen, lastSeen)
	if err != nil {
		return c.String(http.StatusInternalServerError, err.Error())
	}

	data := indexData{Authenticated: true, User: user, scanData: results}

	return c.Render(http.StatusOK, "index", data)
}

// Handler for GET /ips.json
// This is used as the prefetch for Typeahead.js
func ips(c echo.Context) error {
	data, err := load("", "", "")
	if err != nil {
		c.String(http.StatusInternalServerError, err.Error())
	}
	var ips []string
	for _, r := range data {
		ips = append(ips, r.IP)
	}
	return c.JSON(http.StatusOK, ips)
}

// Handler for POST /results
func recvResults(c echo.Context) error {
	res := new([]result)
	err := c.Bind(res)
	if err != nil {
		return c.String(http.StatusInternalServerError, err.Error())
	}

	err = save(*res)
	if err != nil {
		return c.String(http.StatusInternalServerError, err.Error())
	}

	return c.NoContent(http.StatusOK)
}

func main() {
	flag.BoolVar(&authDisabled, "no-auth", false, "Disable authentication")
	httpAddr := flag.String("http.addr", ":80", "HTTP address:port")
	httpsAddr := flag.String("https.addr", ":443", "HTTPS address:port")
	tls := flag.Bool("tls", false, "Enable AutoTLS")
	tlsHostname := flag.String("tls.hostname", "", "(Optional) Hostname to restrict AutoTLS")
	flag.Parse()

	t := &Template{
		templates: template.Must(template.ParseGlob("views/*.html")),
	}

	e := echo.New()

	if authDisabled {
		color.Println(color.Red("Authentication Disabled"))
	}

	if *tls {
		if *tlsHostname != "" {
			e.AutoTLSManager.HostPolicy = autocert.HostWhitelist(*tlsHostname)
		}
		e.AutoTLSManager.Cache = autocert.DirCache(".cache")
		e.Pre(middleware.HTTPSRedirect())
	}

	e.HideBanner = true
	e.Renderer = t
	e.Use(middleware.Logger())
	e.GET("/", index)
	e.GET("/auth", authHandler)
	e.GET("/login", loginHandler)
	e.GET("/ips.json", ips)
	e.POST("/results", recvResults)
	e.Static("/static", "static")
	e.GET("/metrics", echo.WrapHandler(promhttp.Handler()))

	// TODO(jamesog): Remove this and instrument directly from the receive handler
	go metrics()

	if *tls {
		go func() { e.Logger.Fatal(e.Start(*httpAddr)) }()
		e.Logger.Fatal(e.StartAutoTLS(*httpsAddr))
	}
	e.Logger.Fatal(e.Start(*httpAddr))
}
<commit_msg>Standardise time format usage into a global const<commit_after>package main

import (
	"database/sql"
	"flag"
	"fmt"
	"html/template"
	"io"
	"net/http"
	"strings"
	"time"

	"golang.org/x/crypto/acme/autocert"

	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
	"github.com/labstack/gommon/color"
	_ "github.com/mattn/go-sqlite3"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

// Human-readable date-time format
const dateTime = "2006-01-02 15:04"

var authDisabled bool
var dbFile = "scan.db"

type port struct {
	Port    int    `json:"port"`
	Proto   string `json:"proto"`
	Status  string `json:"status"`
	Service struct {
		Name   string `json:"name"`
		Banner string `json:"banner"`
	} `json:"service"`
}

// Results posted from masscan
type result struct {
	IP    string `json:"ip"`
	Ports []port `json:"ports"`
}

// Data retrieved from the database for display
type ipInfo struct {
	IP        string
	Port      int
	Proto     string
	FirstSeen string
	LastSeen  string
	New       bool
}

// Load all data for displaying in the browser
func load(s, fs, ls string) ([]ipInfo, error) {
	db, err := sql.Open("sqlite3", dbFile)
	if err != nil {
		return []ipInfo{}, err
	}
	defer db.Close()

	var where string
	var cond []string
	var params []interface{}
	if s != "" {
		cond = append(cond, `ip LIKE ?`)
		params = append(params, fmt.Sprintf("%%%s%%", s))
	}
	if fs != "" {
		cond = append(cond, `firstseen= ?`)
		params = append(params, fs)
	}
	if ls != "" {
		cond = append(cond, `lastseen= ?`)
		params = append(params, ls)
	}
	if len(cond) > 0 {
		where = fmt.Sprintf("WHERE %s", strings.Join(cond, " AND "))
	}

	qry := fmt.Sprintf(`SELECT ip, port, proto, firstseen, lastseen FROM scan %s ORDER BY port, proto, ip, lastseen`, where)
	rows, err := db.Query(qry, params...)
	if err != nil {
		return []ipInfo{}, err
	}

	defer rows.Close()

	var data []ipInfo
	var ip, proto, firstseen, lastseen string
	var port int
	var latest time.Time

	for rows.Next() {
		err := rows.Scan(&ip, &port, &proto, &firstseen, &lastseen)
		if err != nil {
			return []ipInfo{}, err
		}
		last, _ := time.Parse(dateTime, lastseen)
		if last.After(latest) {
			latest = last
		}
		data = append(data, ipInfo{ip, port, proto, firstseen, lastseen, false})
	}

	for i := range data {
		f, _ := time.Parse(dateTime, data[i].FirstSeen)
		l, _ := time.Parse(dateTime, data[i].LastSeen)
		if f.Equal(l) && l == latest {
			data[i].New = true
		}
	}

	return data, nil
}

// Save the results posted
func save(results []result) error {
	db, err := sql.Open("sqlite3", dbFile)
	if err != nil {
		return err
	}
	defer db.Close()

	txn, err := db.Begin()
	if err != nil {
		return err
	}

	insert, err := txn.Prepare(`INSERT INTO scan (ip, port, proto, firstseen, lastseen) VALUES (?, ?, ?, ?, ?)`)
	if err != nil {
		txn.Rollback()
		return err
	}
	qry, err := db.Prepare(`SELECT 1 FROM scan WHERE ip=? AND port=? AND proto=?`)
	if err != nil {
		txn.Rollback()
		return err
	}
	update, err := txn.Prepare(`UPDATE scan SET lastseen=? WHERE ip=? AND port=? AND proto=?`)
	if err != nil {
		txn.Rollback()
		return err
	}

	now := time.Now().Format(dateTime)

	for _, r := range results {
		// Although it's an array, only one port is in each
		port := r.Ports[0]

		// Skip results which are (usually) banner-only
		// While it would be nice to store banners, we need to restructure a
		// bit to accommodate this and it just inserts duplicate data for now
		if port.Status == "" || port.Service.Name != "" {
			continue
		}

		// Search for the IP/port/proto combo
		// If it exists, update `lastseen`, else insert a new record

		// Because we have to scan into something
		var x int
		err := qry.QueryRow(r.IP, port.Port, port.Proto).Scan(&x)
		switch {
		case err == sql.ErrNoRows:
			_, err = insert.Exec(r.IP, port.Port, port.Proto, now, now)
			if err != nil {
				txn.Rollback()
				return err
			}
			continue
		case err != nil:
			txn.Rollback()
			return err
		}

		_, err = update.Exec(now, r.IP, port.Port, port.Proto)
		if err != nil {
			txn.Rollback()
			return err
		}
	}

	txn.Commit()
	return nil
}

// Template is a template
type Template struct {
	templates *template.Template
}

// Render renders template
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
	return t.templates.ExecuteTemplate(w, name, data)
}

type indexData struct {
	Authenticated bool
	User          string
	scanData
}

type scanData struct {
	Total    int
	Latest   int
	New      int
	LastSeen string
	Results  []ipInfo
}

func resultData(ip, fs, ls string) (scanData, error) {
	results, err := load(ip, fs, ls)
	if err != nil {
		return scanData{}, err
	}

	data := scanData{
		Results: results,
		Total:   len(results),
	}

	// Find all the latest results and store the number in the struct
	var latest time.Time
	for _, r := range results {
		last, _ := time.Parse(dateTime, r.LastSeen)
		if last.After(latest) {
			latest = last
		}
	}
	for _, r := range results {
		last, _ := time.Parse(dateTime, r.LastSeen)
		if last.Equal(latest) {
			data.Latest++
		}
		if r.New {
			data.New++
		}
	}
	data.LastSeen = latest.Format(dateTime)

	return data, nil
}

// Handler for GET /
func index(c echo.Context) error {
	var user string
	if !authDisabled {
		session, err := store.Get(c.Request(), "user")
		if err != nil {
			return c.String(http.StatusInternalServerError, err.Error())
		}
		if _, ok := session.Values["user"]; !ok {
			data := indexData{}
			return c.Render(http.StatusOK, "index", data)
		}
		user = session.Values["user"].(string)
	}

	ip := c.QueryParam("ip")
	firstSeen := c.QueryParam("firstseen")
	lastSeen := c.QueryParam("lastseen")

	results, err := resultData(ip, firstSeen, lastSeen)
	if err != nil {
		return c.String(http.StatusInternalServerError, err.Error())
	}

	data := indexData{Authenticated: true, User: user, scanData: results}

	return c.Render(http.StatusOK, "index", data)
}

// Handler for GET /ips.json
// This is used as the prefetch for Typeahead.js
func ips(c echo.Context) error {
	data, err := load("", "", "")
	if err != nil {
		c.String(http.StatusInternalServerError, err.Error())
	}
	var ips []string
	for _, r := range data {
		ips = append(ips, r.IP)
	}
	return c.JSON(http.StatusOK, ips)
}

// Handler for POST /results
func recvResults(c echo.Context) error {
	res := new([]result)
	err := c.Bind(res)
	if err != nil {
		return c.String(http.StatusInternalServerError, err.Error())
	}

	err = save(*res)
	if err != nil {
		return c.String(http.StatusInternalServerError, err.Error())
	}

	return c.NoContent(http.StatusOK)
}

func main() {
	flag.BoolVar(&authDisabled, "no-auth", false, "Disable authentication")
	httpAddr := flag.String("http.addr", ":80", "HTTP address:port")
	httpsAddr := flag.String("https.addr", ":443", "HTTPS address:port")
	tls := flag.Bool("tls", false, "Enable AutoTLS")
	tlsHostname := flag.String("tls.hostname", "", "(Optional) Hostname to restrict AutoTLS")
	flag.Parse()

	t := &Template{
		templates: template.Must(template.ParseGlob("views/*.html")),
	}

	e := echo.New()

	if authDisabled {
		color.Println(color.Red("Authentication Disabled"))
	}

	if *tls {
		if *tlsHostname != "" {
			e.AutoTLSManager.HostPolicy = autocert.HostWhitelist(*tlsHostname)
		}
		e.AutoTLSManager.Cache = autocert.DirCache(".cache")
		e.Pre(middleware.HTTPSRedirect())
	}

	e.HideBanner = true
	e.Renderer = t
	e.Use(middleware.Logger())
	e.GET("/", index)
	e.GET("/auth", authHandler)
	e.GET("/login", loginHandler)
	e.GET("/ips.json", ips)
	e.POST("/results", recvResults)
	e.Static("/static", "static")
	e.GET("/metrics", echo.WrapHandler(promhttp.Handler()))

	// TODO(jamesog): Remove this and instrument directly from the receive handler
	go metrics()

	if *tls {
		go func() { e.Logger.Fatal(e.Start(*httpAddr)) }()
		e.Logger.Fatal(e.StartAutoTLS(*httpsAddr))
	}
	e.Logger.Fatal(e.Start(*httpAddr))
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"go/build"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strings"

	"sourcegraph.com/sourcegraph/srclib"
	"sourcegraph.com/sourcegraph/srclib/unit"
)

func init() {
	_, err := parser.AddCommand("scan",
		"scan for Go packages",
		"Scan the directory tree rooted at the current directory for Go packages.",
		&scanCmd,
	)
	if err != nil {
		log.Fatal(err)
	}
}

type ScanCmd struct {
	Repo   string `long:"repo" description:"repository URI" value-name:"URI"`
	Subdir string `long:"subdir" description:"subdirectory in repository" value-name:"DIR"`
}

var scanCmd ScanCmd

func (c *ScanCmd) Execute(args []string) error {
	if c.Repo == "" && os.Getenv("IN_DOCKER_CONTAINER") != "" {
		log.Println("Warning: no --repo specified, and tool is running in a Docker container (i.e., without awareness of host's GOPATH). Go import paths in source units produced by the scanner may be inaccurate. To fix this, ensure that the --repo URI is specified. Report this issue if you are seeing it unexpectedly.")
	}

	if err := json.NewDecoder(os.Stdin).Decode(&config); err != nil {
		return err
	}
	if err := os.Stdin.Close(); err != nil {
		return err
	}

	// Automatically detect vendored dirs (check for vendor/src and
	// Godeps/_workspace/src) and set up GOPATH pointing to them if
	// they exist.
	var setAutoGOPATH bool
	if config.GOPATH == "" {
		vendorDirs := []string{"vendor", "Godeps/_workspace"}
		var foundGOPATHs []string
		for _, vdir := range vendorDirs {
			if fi, err := os.Stat(filepath.Join(cwd, vdir, "src")); err == nil && fi.Mode().IsDir() {
				foundGOPATHs = append(foundGOPATHs, vdir)
				setAutoGOPATH = true
				log.Printf("Adding %s to GOPATH (auto-detected Go vendored dependencies source dir %s). If you don't want this, make a Srcfile with a GOPATH property set to something other than the empty string.", vdir, filepath.Join(vdir, "src"))
			}
		}
		config.GOPATH = strings.Join(foundGOPATHs, string(filepath.ListSeparator))
	}

	if err := config.apply(); err != nil {
		return err
	}

	cwd, err := filepath.EvalSymlinks(getCWD())
	if err != nil {
		return err
	}
	scanDir := cwd
	if !isInGopath(scanDir) {
		scanDir = filepath.Join(cwd, srclibGopath, "src", filepath.FromSlash(c.Repo))
		buildContext.GOPATH = filepath.Join(cwd, srclibGopath) + string(os.PathListSeparator) + buildContext.GOPATH

		os.RemoveAll(srclibGopath) // ignore error
		if err := os.MkdirAll(filepath.Dir(scanDir), 0777); err != nil {
			return err
		}
		rel, err := filepath.Rel(filepath.Dir(scanDir), cwd)
		if err != nil {
			return err
		}
		if err := os.Symlink(rel, scanDir); err != nil {
			return err
		}
	}

	units, err := scan(scanDir)
	if err != nil {
		return err
	}

	if len(config.PkgPatterns) != 0 {
		matchers := make([]func(name string) bool, len(config.PkgPatterns))
		for i, pattern := range config.PkgPatterns {
			matchers[i] = matchPattern(pattern)
		}

		var filteredUnits []*unit.SourceUnit
		for _, unit := range units {
			for _, m := range matchers {
				if m(unit.Name) {
					filteredUnits = append(filteredUnits, unit)
					break
				}
			}
		}
		units = filteredUnits
	}

	// Fix up import paths to be consistent when running as a program and as
	// a Docker container. But if a GOROOT is set, then we probably want import
	// paths to not contain the repo, so only do this if there's no GOROOT set
	// in the Srcfile.
	if os.Getenv("IN_DOCKER_CONTAINER") != "" && config.GOROOT == "" {
		for _, u := range units {
			pkg := u.Data.(*build.Package)
			pkg.ImportPath = filepath.Join(c.Repo, c.Subdir, pkg.Dir)
			u.Name = pkg.ImportPath
		}
	}

	// Make vendored dep unit names (package import paths) relative to
	// vendored src dir, not to top-level dir.
	if config.GOPATH != "" {
		dirs := filepath.SplitList(config.GOPATH)
		for _, dir := range dirs {
			relDir, err := filepath.Rel(cwd, dir)
			if err != nil {
				return err
			}
			srcDir := filepath.Join(relDir, "src")
			for _, u := range units {
				pkg := u.Data.(*build.Package)
				if strings.HasPrefix(pkg.Dir, srcDir) {
					relImport, err := filepath.Rel(srcDir, pkg.Dir)
					if err != nil {
						return err
					}
					pkg.ImportPath = relImport
					u.Name = pkg.ImportPath
				}
			}
		}
	}

	// make files relative to repository root
	for _, u := range units {
		pkgSubdir := filepath.Join(c.Subdir, u.Data.(*build.Package).Dir)
		for i, f := range u.Files {
			u.Files[i] = filepath.Join(pkgSubdir, f)
		}
	}

	// If we automatically set the GOPATH based on the presence of
	// vendor dirs, then we need to pass the GOPATH to the units
	// because it is not persisted in the Srcfile. Otherwise the other
	// tools would never see the auto-set GOPATH.
	if setAutoGOPATH {
		for _, u := range units {
			if u.Config == nil {
				u.Config = map[string]interface{}{}
			}

			dirs := filepath.SplitList(config.GOPATH)
			for i, dir := range dirs {
				relDir, err := filepath.Rel(cwd, dir)
				if err != nil {
					return err
				}
				dirs[i] = relDir
			}
			u.Config["GOPATH"] = strings.Join(dirs, string(filepath.ListSeparator))
		}
	}

	b, err := json.MarshalIndent(units, "", "  ")
	if err != nil {
		return err
	}
	if _, err := os.Stdout.Write(b); err != nil {
		return err
	}
	return nil
}

func isInGopath(path string) bool {
	for _, gopath := range filepath.SplitList(buildContext.GOPATH) {
		if strings.HasPrefix(evalSymlinks(path), filepath.Join(evalSymlinks(gopath), "src")) {
			return true
		}
	}
	return false
}

func scan(scanDir string) ([]*unit.SourceUnit, error) {
	// TODO(sqs): include xtest, but we'll have to make them have a distinctly
	// namespaced def path from the non-xtest pkg.

	pkgs, err := scanForPackages(scanDir)
	if err != nil {
		return nil, err
	}

	var units []*unit.SourceUnit
	for _, pkg := range pkgs {
		// Collect all files
		var files []string
		files = append(files, pkg.GoFiles...)
		files = append(files, pkg.CgoFiles...)
		files = append(files, pkg.IgnoredGoFiles...)
		files = append(files, pkg.CFiles...)
		files = append(files, pkg.CXXFiles...)
		files = append(files, pkg.MFiles...)
		files = append(files, pkg.HFiles...)
		files = append(files, pkg.SFiles...)
		files = append(files, pkg.SwigFiles...)
		files = append(files, pkg.SwigCXXFiles...)
		files = append(files, pkg.SysoFiles...)
		files = append(files, pkg.TestGoFiles...)
		files = append(files, pkg.XTestGoFiles...)

		// Collect all imports. We use a map to remove duplicates.
		var imports []string
		imports = append(imports, pkg.Imports...)
		imports = append(imports, pkg.TestImports...)
		imports = append(imports, pkg.XTestImports...)
		imports = uniq(imports)
		sort.Strings(imports)

		// Create appropriate type for (unit).SourceUnit
		deps := make([]interface{}, len(imports))
		for i, imp := range imports {
			deps[i] = imp
		}

		pkg.Dir, err = filepath.Rel(scanDir, pkg.Dir)
		if err != nil {
			return nil, err
		}
		pkg.BinDir = ""
		pkg.ConflictDir = ""

		// Root differs depending on the system, so it's hard to compare results
		// across environments (when running as a program). Clear it so we can
		// compare results in tests more easily.
		pkg.Root = ""
		pkg.SrcRoot = ""
		pkg.PkgRoot = ""

		units = append(units, &unit.SourceUnit{
			Name:         pkg.ImportPath,
			Type:         "GoPackage",
			Dir:          pkg.Dir,
			Files:        files,
			Data:         pkg,
			Dependencies: deps,
			Ops:          map[string]*srclib.ToolRef{"depresolve": nil, "graph": nil},
		})
	}

	return units, nil
}

func scanForPackages(dir string) ([]*build.Package, error) {
	var pkgs []*build.Package

	pkg, err := buildContext.ImportDir(dir, 0)
	if _, isNoGoError := err.(*build.NoGoError); err != nil && !isNoGoError {
		return nil, err
	}
	if err == nil {
		pkgs = append(pkgs, pkg)
	}

	infos, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, err
	}
	for _, info := range infos {
		name := info.Name()
		fullPath := filepath.Join(dir, name)
		if info.IsDir() && ((name[0] != '.' && name[0] != '_' && name != "testdata") || (strings.HasSuffix(fullPath, "Godeps/_workspace") && !config.SkipGodeps)) {
			subPkgs, err := scanForPackages(fullPath)
			if err != nil {
				return nil, err
			}
			pkgs = append(pkgs, subPkgs...)
		}
	}

	return pkgs, nil
}

// matchPattern(pattern)(name) reports whether
// name matches pattern.  Pattern is a limited glob
// pattern in which '...' means 'any string' and there
// is no other special syntax.
func matchPattern(pattern string) func(name string) bool {
	re := regexp.QuoteMeta(pattern)
	re = strings.Replace(re, `\.\.\.`, `.*`, -1)
	// Special case: foo/... matches foo too.
	if strings.HasSuffix(re, `/.*`) {
		re = re[:len(re)-len(`/.*`)] + `(/.*)?`
	}
	reg := regexp.MustCompile(`^` + re + `$`)
	return func(name string) bool {
		return reg.MatchString(name)
	}
}
<commit_msg>don't store import positions<commit_after>package main

import (
	"encoding/json"
	"go/build"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strings"

	"sourcegraph.com/sourcegraph/srclib"
	"sourcegraph.com/sourcegraph/srclib/unit"
)

func init() {
	_, err := parser.AddCommand("scan",
		"scan for Go packages",
		"Scan the directory tree rooted at the current directory for Go packages.",
		&scanCmd,
	)
	if err != nil {
		log.Fatal(err)
	}
}

type ScanCmd struct {
	Repo   string `long:"repo" description:"repository URI" value-name:"URI"`
	Subdir string `long:"subdir" description:"subdirectory in repository" value-name:"DIR"`
}

var scanCmd ScanCmd

func (c *ScanCmd) Execute(args []string) error {
	if c.Repo == "" && os.Getenv("IN_DOCKER_CONTAINER") != "" {
		log.Println("Warning: no --repo specified, and tool is running in a Docker container (i.e., without awareness of host's GOPATH). Go import paths in source units produced by the scanner may be inaccurate. To fix this, ensure that the --repo URI is specified. Report this issue if you are seeing it unexpectedly.")
	}

	if err := json.NewDecoder(os.Stdin).Decode(&config); err != nil {
		return err
	}
	if err := os.Stdin.Close(); err != nil {
		return err
	}

	// Automatically detect vendored dirs (check for vendor/src and
	// Godeps/_workspace/src) and set up GOPATH pointing to them if
	// they exist.
	var setAutoGOPATH bool
	if config.GOPATH == "" {
		vendorDirs := []string{"vendor", "Godeps/_workspace"}
		var foundGOPATHs []string
		for _, vdir := range vendorDirs {
			if fi, err := os.Stat(filepath.Join(cwd, vdir, "src")); err == nil && fi.Mode().IsDir() {
				foundGOPATHs = append(foundGOPATHs, vdir)
				setAutoGOPATH = true
				log.Printf("Adding %s to GOPATH (auto-detected Go vendored dependencies source dir %s). If you don't want this, make a Srcfile with a GOPATH property set to something other than the empty string.", vdir, filepath.Join(vdir, "src"))
			}
		}
		config.GOPATH = strings.Join(foundGOPATHs, string(filepath.ListSeparator))
	}

	if err := config.apply(); err != nil {
		return err
	}

	cwd, err := filepath.EvalSymlinks(getCWD())
	if err != nil {
		return err
	}
	scanDir := cwd
	if !isInGopath(scanDir) {
		scanDir = filepath.Join(cwd, srclibGopath, "src", filepath.FromSlash(c.Repo))
		buildContext.GOPATH = filepath.Join(cwd, srclibGopath) + string(os.PathListSeparator) + buildContext.GOPATH

		os.RemoveAll(srclibGopath) // ignore error
		if err := os.MkdirAll(filepath.Dir(scanDir), 0777); err != nil {
			return err
		}
		rel, err := filepath.Rel(filepath.Dir(scanDir), cwd)
		if err != nil {
			return err
		}
		if err := os.Symlink(rel, scanDir); err != nil {
			return err
		}
	}

	units, err := scan(scanDir)
	if err != nil {
		return err
	}

	if len(config.PkgPatterns) != 0 {
		matchers := make([]func(name string) bool, len(config.PkgPatterns))
		for i, pattern := range config.PkgPatterns {
			matchers[i] = matchPattern(pattern)
		}

		var filteredUnits []*unit.SourceUnit
		for _, unit := range units {
			for _, m := range matchers {
				if m(unit.Name) {
					filteredUnits = append(filteredUnits, unit)
					break
				}
			}
		}
		units = filteredUnits
	}

	// Fix up import paths to be consistent when running as a program and as
	// a Docker container. But if a GOROOT is set, then we probably want import
	// paths to not contain the repo, so only do this if there's no GOROOT set
	// in the Srcfile.
	if os.Getenv("IN_DOCKER_CONTAINER") != "" && config.GOROOT == "" {
		for _, u := range units {
			pkg := u.Data.(*build.Package)
			pkg.ImportPath = filepath.Join(c.Repo, c.Subdir, pkg.Dir)
			u.Name = pkg.ImportPath
		}
	}

	// Make vendored dep unit names (package import paths) relative to
	// vendored src dir, not to top-level dir.
	if config.GOPATH != "" {
		dirs := filepath.SplitList(config.GOPATH)
		for _, dir := range dirs {
			relDir, err := filepath.Rel(cwd, dir)
			if err != nil {
				return err
			}
			srcDir := filepath.Join(relDir, "src")
			for _, u := range units {
				pkg := u.Data.(*build.Package)
				if strings.HasPrefix(pkg.Dir, srcDir) {
					relImport, err := filepath.Rel(srcDir, pkg.Dir)
					if err != nil {
						return err
					}
					pkg.ImportPath = relImport
					u.Name = pkg.ImportPath
				}
			}
		}
	}

	// make files relative to repository root
	for _, u := range units {
		pkgSubdir := filepath.Join(c.Subdir, u.Data.(*build.Package).Dir)
		for i, f := range u.Files {
			u.Files[i] = filepath.Join(pkgSubdir, f)
		}
	}

	// If we automatically set the GOPATH based on the presence of
	// vendor dirs, then we need to pass the GOPATH to the units
	// because it is not persisted in the Srcfile. Otherwise the other
	// tools would never see the auto-set GOPATH.
	if setAutoGOPATH {
		for _, u := range units {
			if u.Config == nil {
				u.Config = map[string]interface{}{}
			}

			dirs := filepath.SplitList(config.GOPATH)
			for i, dir := range dirs {
				relDir, err := filepath.Rel(cwd, dir)
				if err != nil {
					return err
				}
				dirs[i] = relDir
			}
			u.Config["GOPATH"] = strings.Join(dirs, string(filepath.ListSeparator))
		}
	}

	b, err := json.MarshalIndent(units, "", "  ")
	if err != nil {
		return err
	}
	if _, err := os.Stdout.Write(b); err != nil {
		return err
	}
	return nil
}

func isInGopath(path string) bool {
	for _, gopath := range filepath.SplitList(buildContext.GOPATH) {
		if strings.HasPrefix(evalSymlinks(path), filepath.Join(evalSymlinks(gopath), "src")) {
			return true
		}
	}
	return false
}

func scan(scanDir string) ([]*unit.SourceUnit, error) {
	// TODO(sqs): include xtest, but we'll have to make them have a distinctly
	// namespaced def path from the non-xtest pkg.

	pkgs, err := scanForPackages(scanDir)
	if err != nil {
		return nil, err
	}

	var units []*unit.SourceUnit
	for _, pkg := range pkgs {
		// Collect all files
		var files []string
		files = append(files, pkg.GoFiles...)
		files = append(files, pkg.CgoFiles...)
		files = append(files, pkg.IgnoredGoFiles...)
		files = append(files, pkg.CFiles...)
		files = append(files, pkg.CXXFiles...)
		files = append(files, pkg.MFiles...)
		files = append(files, pkg.HFiles...)
		files = append(files, pkg.SFiles...)
		files = append(files, pkg.SwigFiles...)
		files = append(files, pkg.SwigCXXFiles...)
		files = append(files, pkg.SysoFiles...)
		files = append(files, pkg.TestGoFiles...)
		files = append(files, pkg.XTestGoFiles...)

		// Collect all imports. We use a map to remove duplicates.
		var imports []string
		imports = append(imports, pkg.Imports...)
		imports = append(imports, pkg.TestImports...)
		imports = append(imports, pkg.XTestImports...)
		imports = uniq(imports)
		sort.Strings(imports)

		// Create appropriate type for (unit).SourceUnit
		deps := make([]interface{}, len(imports))
		for i, imp := range imports {
			deps[i] = imp
		}

		pkg.Dir, err = filepath.Rel(scanDir, pkg.Dir)
		if err != nil {
			return nil, err
		}
		pkg.BinDir = ""
		pkg.ConflictDir = ""

		// Root differs depending on the system, so it's hard to compare results
		// across environments (when running as a program). Clear it so we can
		// compare results in tests more easily.
		pkg.Root = ""
		pkg.SrcRoot = ""
		pkg.PkgRoot = ""

		pkg.ImportPos = nil
		pkg.TestImportPos = nil
		pkg.XTestImportPos = nil

		units = append(units, &unit.SourceUnit{
			Name:         pkg.ImportPath,
			Type:         "GoPackage",
			Dir:          pkg.Dir,
			Files:        files,
			Data:         pkg,
			Dependencies: deps,
			Ops:          map[string]*srclib.ToolRef{"depresolve": nil, "graph": nil},
		})
	}

	return units, nil
}

func scanForPackages(dir string) ([]*build.Package, error) {
	var pkgs []*build.Package

	pkg, err := buildContext.ImportDir(dir, 0)
	if _, isNoGoError := err.(*build.NoGoError); err != nil && !isNoGoError {
		return nil, err
	}
	if err == nil {
		pkgs = append(pkgs, pkg)
	}

	infos, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, err
	}
	for _, info := range infos {
		name := info.Name()
		fullPath := filepath.Join(dir, name)
		if info.IsDir() && ((name[0] != '.' && name[0] != '_' && name != "testdata") || (strings.HasSuffix(fullPath, "Godeps/_workspace") && !config.SkipGodeps)) {
			subPkgs, err := scanForPackages(fullPath)
			if err != nil {
				return nil, err
			}
			pkgs = append(pkgs, subPkgs...)
		}
	}

	return pkgs, nil
}

// matchPattern(pattern)(name) reports whether
// name matches pattern.  Pattern is a limited glob
// pattern in which '...' means 'any string' and there
// is no other special syntax.
func matchPattern(pattern string) func(name string) bool {
	re := regexp.QuoteMeta(pattern)
	re = strings.Replace(re, `\.\.\.`, `.*`, -1)
	// Special case: foo/... matches foo too.
	if strings.HasSuffix(re, `/.*`) {
		re = re[:len(re)-len(`/.*`)] + `(/.*)?`
	}
	reg := regexp.MustCompile(`^` + re + `$`)
	return func(name string) bool {
		return reg.MatchString(name)
	}
}
<|endoftext|>


<commit_before>/*Package configurationFile represents Encodable/Decodable Golang structures from/to TOML structures.
 *
 *The global structure is ConfigurationFile, which is the simple way to store accurtely your local informations.
 *
 */
package configurationFile

import (
	"bytes"
	"io/ioutil"
	"os"
	"os/user"

	"fmt"

	"path/filepath"

	"sync"

	"github.com/BurntSushi/toml"
	"github.com/k0pernicus/goyave/consts"
	"github.com/k0pernicus/goyave/gitManip"
	"github.com/k0pernicus/goyave/traces"
	"github.com/k0pernicus/goyave/utils"
)

/*GetConfigurationFileContent get the content of the local configuration file.
 *If no configuration file has been found, create a default one and set the bytes array.
 */
func GetConfigurationFileContent(filePointer *os.File, bytesArray *[]byte) {
	fileState, err := filePointer.Stat()
	// If the file is empty, get the default structure and save it
	if err != nil || fileState.Size() == 0 {
		traces.WarningTracer.Println("No (or empty) configuration file - creating default one...")
		var fileBuffer bytes.Buffer
		cLocalhost := utils.GetLocalhost()
		cUser, err := user.Current()
		var cUserName string
		if err != nil {
			cUserName = consts.DefaultUserName
		} else {
			cUserName = cUser.Username
		}
		defaultStructure := Default(cUserName, cLocalhost)
		defaultStructure.Encode(&fileBuffer)
		*bytesArray = fileBuffer.Bytes()
	} else {
		b, _ := ioutil.ReadAll(filePointer)
		*bytesArray = b
	}
}

/*ConfigurationFile represents the TOML structure of the Goyave configuration file
 *
 *Properties:
 *	Author:
 *		The name of the user
 *  Local:
 *		Local informations
 *  Repositories:
 *		Local git repositories
 *	VisibleRepositories:
 *		A list of local ** visible ** git repositories (** used localy **)
 *	Groups:
 *		A list of groups
 *	locker:
 *		Mutex to perform concurrent RW on map data structures
 */
type ConfigurationFile struct {
	Author              string
	Local               LocalInformations        `toml:"local"`
	Repositories        map[string]GitRepository `toml:"repositories"`
	VisibleRepositories VisibleRepositories      `toml:"-"`
	Groups              map[string]Group         `toml:"group"`
	locker              sync.RWMutex             `toml:"-"`
}

/*Default is a constructor for ConfigurationFile
 *
 *Parameters:
 *	author:
 *		The name of the user
 *  hostname:
 *		The machine hostname
 */
func Default(author string, hostname string) *ConfigurationFile {
	return &ConfigurationFile{
		Author: author,
		Local: LocalInformations{
			DefaultTarget: consts.VisibleFlag,
			Group:         hostname,
		},
		Groups: map[string]Group{
			hostname: []string{},
		},
	}
}

/*AddRepository append the given repository to the list of local repositories, if it does not exists
 */
func (c *ConfigurationFile) AddRepository(path, target string) error {
	name := filepath.Base(path)
	hostname := utils.GetLocalhost()
	c.locker.Lock()
	defer c.locker.Unlock()
	robj, ok := c.Repositories[name]
	// If the repository exists and the path is ok, stop
	if ok && robj.Paths[hostname].Path == path {
		return nil
	}
	// Initialize the new GroupPath structure
	cgroup := GroupPath{
		Name: name,
		Path: path,
	}
	// If the repository exists but the path is not ok, update it
	if ok {
		robj.Paths[hostname] = cgroup
		return nil
	}
	// Otherwise, create a new GitRepository structure, and append it in the Repositories field
	c.Repositories[name] = GitRepository{
		Name: name,
		Paths: map[string]GroupPath{
			hostname: cgroup,
		},
		URL: gitManip.GetRemoteURL(path),
	}
	// If the user wants to add automatically new repositories as repositories to "follow", change
	// his flag as a "visible" repository
	if target == consts.VisibleFlag {
		c.Groups[hostname] = append(c.Groups[hostname], name)
	}
	return nil
}

/*GetPath returns the local path file, for a given repository
 */
func (c *ConfigurationFile) GetPath(repository string) (string, bool) {
	gobj, ok := c.VisibleRepositories[repository]
	return gobj, ok
}

/*Process initializes useful fields in the data structure
 */
func (c *ConfigurationFile) Process() error {
	// If the configuration file is new, initialize the map and finish here
	if c.Repositories == nil {
		c.Repositories = make(map[string]GitRepository)
		return nil
	}
	// Otherwise, initialize useful fields
	hostname := utils.GetLocalhost()
	vrepositories, ok := c.Groups[hostname]
	if !ok {
		return fmt.Errorf("the hostname %s has not been found - please to launch 'crawl' before", hostname)
	}
	c.VisibleRepositories = make(VisibleRepositories)
	for _, repository := range vrepositories {
		c.VisibleRepositories[repository] = c.Repositories[repository].Paths[hostname].Path
	}
	return nil
}

/*VisibleRepositories is a map structure to store, for each repository name (and the hostname), the associated path
 */
type VisibleRepositories map[string]string

/*Method that returns if a repository, identified by his name and his path (optional), exists in the given structure
 * If path is empty (empty string), the function will only check the name
 */
func (v VisibleRepositories) exists(name, path string) bool {
	_, ok := v[name]
	if !ok || path == "" {
		return ok
	}
	return v[name] == path
}

/*GitRepository represents the structure of a local git repository
 *
 *Properties:
 *	Name:
 * 		The custom name of the repository
 *  Paths:
 *		Path per group name
 *	URL:
 *		The remote URL of the repository (from origin)
 */
type GitRepository struct {
	Name  string               `toml:"name"`
	Paths map[string]GroupPath `toml:"paths"`
	URL   string               `toml:"url"`
}

/*GroupPath represents the structure of a local path, using a given group
 *
 *Properties:
 *  Name:
 *		The name of the local git repository
 *	Path:
 *		A string that points to the local git repository
 */
type GroupPath struct {
	Name string
	Path string
}

/*Group represents a group of git repositories names
 */
type Group []string

/*LocalInformations represents your local configuration of Goyave
 *
 *Properties:
 *  DefaultEntry:
 *		The default entry to store a git repository (hidden or visible)
 *	Group:
 *		The current group name.
 */
type LocalInformations struct {
	DefaultTarget string
	Group         string
}

/*DecodeString is a function to decode an entire string (which is the content of a given TOML file) to a ConfigurationFile structure
 */
func DecodeString(c *ConfigurationFile, data string) error {
	_, err := toml.Decode(data, *c)
	return err
}

/*DecodeBytesArray is a function to decode an entire string (which is the content of a given TOML file) to a ConfigurationFile structure
 */
func DecodeBytesArray(c *ConfigurationFile, data []byte) error {
	_, err := toml.Decode(string(data[:]), *c)
	return err
}

/*Encode is a function to encode a ConfigurationFile structure to a byffer of bytes
 */
func (c *ConfigurationFile) Encode(buffer *bytes.Buffer) error {
	return toml.NewEncoder(buffer).Encode(c)
}
<commit_msg>Change GetLocalhost to GetHostname<commit_after>/*Package configurationFile represents Encodable/Decodable Golang structures from/to TOML structures.
 *
 *The global structure is ConfigurationFile, which is the simple way to store accurtely your local informations.
 *
 */
package configurationFile

import (
	"bytes"
	"io/ioutil"
	"os"
	"os/user"

	"fmt"

	"path/filepath"

	"sync"

	"github.com/BurntSushi/toml"
	"github.com/k0pernicus/goyave/consts"
	"github.com/k0pernicus/goyave/gitManip"
	"github.com/k0pernicus/goyave/traces"
	"github.com/k0pernicus/goyave/utils"
)

/*GetConfigurationFileContent get the content of the local configuration file.
 *If no configuration file has been found, create a default one and set the bytes array.
 */
func GetConfigurationFileContent(filePointer *os.File, bytesArray *[]byte) {
	fileState, err := filePointer.Stat()
	// If the file is empty, get the default structure and save it
	if err != nil || fileState.Size() == 0 {
		traces.WarningTracer.Println("No (or empty) configuration file - creating default one...")
		var fileBuffer bytes.Buffer
		cLocalhost := utils.GetHostname()
		cUser, err := user.Current()
		var cUserName string
		if err != nil {
			cUserName = consts.DefaultUserName
		} else {
			cUserName = cUser.Username
		}
		defaultStructure := Default(cUserName, cLocalhost)
		defaultStructure.Encode(&fileBuffer)
		*bytesArray = fileBuffer.Bytes()
	} else {
		b, _ := ioutil.ReadAll(filePointer)
		*bytesArray = b
	}
}

/*ConfigurationFile represents the TOML structure of the Goyave configuration file
 *
 *Properties:
 *	Author:
 *		The name of the user
 *  Local:
 *		Local informations
 *  Repositories:
 *		Local git repositories
 *	VisibleRepositories:
 *		A list of local ** visible ** git repositories (** used localy **)
 *	Groups:
 *		A list of groups
 *	locker:
 *		Mutex to perform concurrent RW on map data structures
 */
type ConfigurationFile struct {
	Author              string
	Local               LocalInformations        `toml:"local"`
	Repositories        map[string]GitRepository `toml:"repositories"`
	VisibleRepositories VisibleRepositories      `toml:"-"`
	Groups              map[string]Group         `toml:"group"`
	locker              sync.RWMutex             `toml:"-"`
}

/*Default is a constructor for ConfigurationFile
 *
 *Parameters:
 *	author:
 *		The name of the user
 *  hostname:
 *		The machine hostname
 */
func Default(author string, hostname string) *ConfigurationFile {
	return &ConfigurationFile{
		Author: author,
		Local: LocalInformations{
			DefaultTarget: consts.VisibleFlag,
			Group:         hostname,
		},
		Groups: map[string]Group{
			hostname: []string{},
		},
	}
}

/*AddRepository append the given repository to the list of local repositories, if it does not exists
 */
func (c *ConfigurationFile) AddRepository(path, target string) error {
	name := filepath.Base(path)
	hostname := utils.GetHostname()
	c.locker.Lock()
	defer c.locker.Unlock()
	robj, ok := c.Repositories[name]
	// If the repository exists and the path is ok, stop
	if ok && robj.Paths[hostname].Path == path {
		return nil
	}
	// Initialize the new GroupPath structure
	cgroup := GroupPath{
		Name: name,
		Path: path,
	}
	// If the repository exists but the path is not ok, update it
	if ok {
		robj.Paths[hostname] = cgroup
		return nil
	}
	// Otherwise, create a new GitRepository structure, and append it in the Repositories field
	c.Repositories[name] = GitRepository{
		Name: name,
		Paths: map[string]GroupPath{
			hostname: cgroup,
		},
		URL: gitManip.GetRemoteURL(path),
	}
	// If the user wants to add automatically new repositories as repositories to "follow", change
	// his flag as a "visible" repository
	if target == consts.VisibleFlag {
		c.Groups[hostname] = append(c.Groups[hostname], name)
	}
	return nil
}

/*GetPath returns the local path file, for a given repository
 */
func (c *ConfigurationFile) GetPath(repository string) (string, bool) {
	gobj, ok := c.VisibleRepositories[repository]
	return gobj, ok
}

/*Process initializes useful fields in the data structure
 */
func (c *ConfigurationFile) Process() error {
	// If the configuration file is new, initialize the map and finish here
	if c.Repositories == nil {
		c.Repositories = make(map[string]GitRepository)
		return nil
	}
	// Otherwise, initialize useful fields
	hostname := utils.GetHostname()
	vrepositories, ok := c.Groups[hostname]
	if !ok {
		return fmt.Errorf("the hostname %s has not been found - please to launch 'crawl' before", hostname)
	}
	c.VisibleRepositories = make(VisibleRepositories)
	for _, repository := range vrepositories {
		c.VisibleRepositories[repository] = c.Repositories[repository].Paths[hostname].Path
	}
	return nil
}

/*VisibleRepositories is a map structure to store, for each repository name (and the hostname), the associated path
 */
type VisibleRepositories map[string]string

/*Method that returns if a repository, identified by his name and his path (optional), exists in the given structure
 * If path is empty (empty string), the function will only check the name
 */
func (v VisibleRepositories) exists(name, path string) bool {
	_, ok := v[name]
	if !ok || path == "" {
		return ok
	}
	return v[name] == path
}

/*GitRepository represents the structure of a local git repository
 *
 *Properties:
 *	Name:
 * 		The custom name of the repository
 *  Paths:
 *		Path per group name
 *	URL:
 *		The remote URL of the repository (from origin)
 */
type GitRepository struct {
	Name  string               `toml:"name"`
	Paths map[string]GroupPath `toml:"paths"`
	URL   string               `toml:"url"`
}

/*GroupPath represents the structure of a local path, using a given group
 *
 *Properties:
 *  Name:
 *		The name of the local git repository
 *	Path:
 *		A string that points to the local git repository
 */
type GroupPath struct {
	Name string
	Path string
}

/*Group represents a group of git repositories names
 */
type Group []string

/*LocalInformations represents your local configuration of Goyave
 *
 *Properties:
 *  DefaultEntry:
 *		The default entry to store a git repository (hidden or visible)
 *	Group:
 *		The current group name.
 */
type LocalInformations struct {
	DefaultTarget string
	Group         string
}

/*DecodeString is a function to decode an entire string (which is the content of a given TOML file) to a ConfigurationFile structure
 */
func DecodeString(c *ConfigurationFile, data string) error {
	_, err := toml.Decode(data, *c)
	return err
}

/*DecodeBytesArray is a function to decode an entire string (which is the content of a given TOML file) to a ConfigurationFile structure
 */
func DecodeBytesArray(c *ConfigurationFile, data []byte) error {
	_, err := toml.Decode(string(data[:]), *c)
	return err
}

/*Encode is a function to encode a ConfigurationFile structure to a byffer of bytes
 */
func (c *ConfigurationFile) Encode(buffer *bytes.Buffer) error {
	return toml.NewEncoder(buffer).Encode(c)
}
<|endoftext|>


<commit_before>// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package qemu

import (
	"encoding/json"
	"fmt"
	"net"
)

type qmpVersion struct {
	Package string
	QEMU    struct {
		Major int
		Micro int
		Minor int
	}
}

type qmpBanner struct {
	QMP struct {
		Version qmpVersion
	}
}

type qmpCommand struct {
	Execute   string      `json:"execute"`
	Arguments interface{} `json:"arguments,omitempty"`
}

type hmpCommand struct {
	Command string `json:"command-line"`
	CPU     int    `json:"cpu-index"`
}

type qmpResponse struct {
	Error struct {
		Class string
		Desc  string
	}
	Return interface{}
}

func (inst *instance) qmpConnCheck() error {
	if inst.mon != nil {
		return nil
	}

	addr := fmt.Sprintf("127.0.0.1:%v", inst.monport)
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		return err
	}

	monDec := json.NewDecoder(conn)
	monEnc := json.NewEncoder(conn)

	var banner qmpBanner
	if err := monDec.Decode(&banner); err != nil {
		return err
	}

	inst.monEnc = monEnc
	inst.monDec = monDec
	if _, err := inst.doQmp(&qmpCommand{Execute: "qmp_capabilities"}); err != nil {
		inst.monEnc = nil
		inst.monDec = nil
		return err
	}
	inst.mon = conn

	return nil
}

func (inst *instance) qmpRecv() (*qmpResponse, error) {
	qmp := new(qmpResponse)
	err := inst.monDec.Decode(qmp)

	return qmp, err
}

func (inst *instance) doQmp(cmd *qmpCommand) (*qmpResponse, error) {
	if err := inst.monEnc.Encode(cmd); err != nil {
		return nil, err
	}
	return inst.qmpRecv()
}

func (inst *instance) qmp(cmd *qmpCommand) (interface{}, error) {
	if err := inst.qmpConnCheck(); err != nil {
		return nil, err
	}
	resp, err := inst.doQmp(cmd)
	if err != nil {
		return resp.Return, err
	}
	if resp.Error.Desc != "" {
		return resp.Return, fmt.Errorf("error %v", resp.Error)
	}
	if resp.Return == nil {
		return nil, fmt.Errorf(`no "return" nor "error" in [%v]`, resp)
	}
	return resp.Return, nil
}

func (inst *instance) hmp(cmd string, cpu int) (string, error) {
	req := &qmpCommand{
		Execute: "human-monitor-command",
		Arguments: &hmpCommand{
			Command: cmd,
			CPU:     cpu,
		},
	}
	resp, err := inst.qmp(req)
	if err != nil {
		return "", err
	}
	return resp.(string), nil
}
<commit_msg>vm/qemu: fix nil deref in qmp<commit_after>// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package qemu

import (
	"encoding/json"
	"fmt"
	"net"
)

type qmpVersion struct {
	Package string
	QEMU    struct {
		Major int
		Micro int
		Minor int
	}
}

type qmpBanner struct {
	QMP struct {
		Version qmpVersion
	}
}

type qmpCommand struct {
	Execute   string      `json:"execute"`
	Arguments interface{} `json:"arguments,omitempty"`
}

type hmpCommand struct {
	Command string `json:"command-line"`
	CPU     int    `json:"cpu-index"`
}

type qmpResponse struct {
	Error struct {
		Class string
		Desc  string
	}
	Return interface{}
}

func (inst *instance) qmpConnCheck() error {
	if inst.mon != nil {
		return nil
	}

	addr := fmt.Sprintf("127.0.0.1:%v", inst.monport)
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		return err
	}

	monDec := json.NewDecoder(conn)
	monEnc := json.NewEncoder(conn)

	var banner qmpBanner
	if err := monDec.Decode(&banner); err != nil {
		return err
	}

	inst.monEnc = monEnc
	inst.monDec = monDec
	if _, err := inst.doQmp(&qmpCommand{Execute: "qmp_capabilities"}); err != nil {
		inst.monEnc = nil
		inst.monDec = nil
		return err
	}
	inst.mon = conn

	return nil
}

func (inst *instance) qmpRecv() (*qmpResponse, error) {
	qmp := new(qmpResponse)
	err := inst.monDec.Decode(qmp)

	return qmp, err
}

func (inst *instance) doQmp(cmd *qmpCommand) (*qmpResponse, error) {
	if err := inst.monEnc.Encode(cmd); err != nil {
		return nil, err
	}
	return inst.qmpRecv()
}

func (inst *instance) qmp(cmd *qmpCommand) (interface{}, error) {
	if err := inst.qmpConnCheck(); err != nil {
		return nil, err
	}
	resp, err := inst.doQmp(cmd)
	if err != nil {
		return nil, err
	}
	if resp.Error.Desc != "" {
		return nil, fmt.Errorf("error %v", resp.Error)
	}
	if resp.Return == nil {
		return nil, fmt.Errorf(`no "return" nor "error" in [%v]`, resp)
	}
	return resp.Return, nil
}

func (inst *instance) hmp(cmd string, cpu int) (string, error) {
	req := &qmpCommand{
		Execute: "human-monitor-command",
		Arguments: &hmpCommand{
			Command: cmd,
			CPU:     cpu,
		},
	}
	resp, err := inst.qmp(req)
	if err != nil {
		return "", err
	}
	return resp.(string), nil
}
<|endoftext|>


<commit_before>/* vim: set autoindent noexpandtab tabstop=4 shiftwidth=4: */
package v1

import (
	"errors"
	"slack"
	"strings"
)

func add(data *slack.Slack, args []string) (int, string, error) {
	if len(args) < 2 {
		return 400, "", errors.New("Not enough arguments to add a new item.")
	}

	key := args[0]
	val := strings.Join(args[1:], " ")

	err := Storage.Put(key, val)
	if err != nil {
		return 400, "", err
	}

	return 200, "Item added.", nil
}
<commit_msg>Better output for adding/updating<commit_after>/* vim: set autoindent noexpandtab tabstop=4 shiftwidth=4: */
package v1

import (
	"errors"
	"fmt"
	"slack"
	"strings"
)

func add(data *slack.Slack, args []string) (int, string, error) {
	if len(args) < 2 {
		return 400, "", errors.New("Not enough arguments to add a new item.")
	}

	key := args[0]
	val := strings.Join(args[1:], " ")

	err := Storage.Put(key, val)
	if err != nil {
		return 400, "", err
	}

	return 200, fmt.Sprintf("The key %s now has the value %s.", key, val), nil
}
<|endoftext|>


<commit_before>package glog

import (
	"fmt"
	"time"
)

type Filed map[string]interface{}

func NewFiled() Filed {
	return Filed{}
}

func (self Filed) Set(k string, v interface{}) Filed {
	self[k] = v
	return self
}
func (self Filed) Get(k string) (interface{}, bool) {
	v, b := self[k]
	return v, b
}
func (self Filed) String() string {
	s := "\tShow Filed:\n"
	for k, v := range self {
		s = s + fmt.Sprintf("\t\t%v=%+v\n", k, v)
	}
	return s
}
func (self Filed) Panic(args ...interface{}) {
	paincf(fmt.Sprint(args...), 2, self)
}

func (self Filed) Panicf(format string, args ...interface{}) {
	paincf(fmt.Sprintf(format, args...), 2, self)
}

func (self Filed) Panicln(args ...interface{}) {
	paincf(fmt.Sprintln(args...), 2, self)
}
func (self Filed) Error(args ...interface{}) {
	if level >= ErrorLevel {
		event(Event{
			Level:   ErrorLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Filed) Errorf(format string, args ...interface{}) {
	if level >= ErrorLevel {
		event(Event{
			Level:   ErrorLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Filed) Errorln(args ...interface{}) {
	if level >= ErrorLevel {
		event(Event{
			Level:   ErrorLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

func (self Filed) Warn(args ...interface{}) {
	if level >= WarnLevel {
		event(Event{
			Level:   WarnLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Filed) Warnf(format string, args ...interface{}) {
	if level >= WarnLevel {
		event(Event{
			Level:   WarnLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Filed) Warnln(args ...interface{}) {
	if level >= WarnLevel {
		event(Event{
			Level:   WarnLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

func (self Filed) Info(args ...interface{}) {
	if level >= InfoLevel {
		event(Event{
			Level:   InfoLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Filed) Infof(format string, args ...interface{}) {
	if level >= InfoLevel {
		event(Event{
			Level:   InfoLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Filed) Infoln(args ...interface{}) {
	if level >= InfoLevel {
		event(Event{
			Level:   InfoLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

func (self Filed) Debug(args ...interface{}) {
	if level >= DebugLevel {
		event(Event{
			Level:   DebugLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Filed) Debugf(format string, args ...interface{}) {
	if level >= DebugLevel {
		event(Event{
			Level:   DebugLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Filed) Debugln(args ...interface{}) {
	if level >= DebugLevel {
		event(Event{
			Level:   DebugLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

type TagFiled struct {
	tag   string
	value map[string]interface{}
}

func NewTagFiled(tag string) *TagFiled {
	return &TagFiled{tag: tag, value: make(map[string]interface{})}
}

func (self *TagFiled) Set(k string, v interface{}) *TagFiled {
	self.value[k] = v
	return self
}
func (self *TagFiled) Get(k string) (interface{}, bool) {
	v, b := self.value[k]
	return v, b
}
func (self *TagFiled) GetTag() string {
	return self.tag
}
func (self *TagFiled) SetTag(tag string) *TagFiled {
	self.tag = tag
	return self
}
func (self *TagFiled) String() string {
	s := "\t[" + self.tag + "]Show Filed:\n"
	for k, v := range self.value {
		s = s + fmt.Sprintf("\t\t%v=%+v\n", k, v)
	}
	return s
}
func (self *TagFiled) Panic(args ...interface{}) {
	paincf(fmt.Sprint(args...), 2, self)
}
func (self *TagFiled) Panicf(format string, args ...interface{}) {
	paincf(fmt.Sprintf(format, args...), 2, self)
}
func (self *TagFiled) Panicln(args ...interface{}) {
	paincf(fmt.Sprintln(args...), 2, self)
}
func (self *TagFiled) Error(args ...interface{}) {
	if level >= ErrorLevel {
		event(Event{
			Level:   ErrorLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagFiled) Errorf(format string, args ...interface{}) {
	if level >= ErrorLevel {
		event(Event{
			Level:   ErrorLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagFiled) Errorln(args ...interface{}) {
	if level >= ErrorLevel {
		event(Event{
			Level:   ErrorLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

func (self *TagFiled) Warn(args ...interface{}) {
	if level >= WarnLevel {
		event(Event{
			Level:   WarnLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagFiled) Warnf(format string, args ...interface{}) {
	if level >= WarnLevel {
		event(Event{
			Level:   WarnLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagFiled) Warnln(args ...interface{}) {
	if level >= WarnLevel {
		event(Event{
			Level:   WarnLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

func (self *TagFiled) Info(args ...interface{}) {
	if level >= InfoLevel {
		event(Event{
			Level:   InfoLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagFiled) Infof(format string, args ...interface{}) {
	if level >= InfoLevel {
		event(Event{
			Level:   InfoLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagFiled) Infoln(args ...interface{}) {
	if level >= InfoLevel {
		event(Event{
			Level:   InfoLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

func (self *TagFiled) Debug(args ...interface{}) {
	if level >= DebugLevel {
		event(Event{
			Level:   DebugLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagFiled) Debugf(format string, args ...interface{}) {
	if level >= DebugLevel {
		event(Event{
			Level:   DebugLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagFiled) Debugln(args ...interface{}) {
	if level >= DebugLevel {
		event(Event{
			Level:   DebugLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

type Level uint8

const (
	UnknownLevel Level = iota
	PanicLevel
	ErrorLevel
	WarnLevel
	InfoLevel
	DebugLevel
)

func (level Level) String() string {
	switch level {
	case DebugLevel:
		return "DEBUG"
	case InfoLevel:
		return "INFO"
	case WarnLevel:
		return "WARNING"
	case ErrorLevel:
		return "ERROR"
	case PanicLevel:
		return "PANIC"
	}

	return "UNKNOWN"
}

func ParseLevel(lvl string) (Level, error) {
	switch lvl {
	case "PANIC":
		return PanicLevel, nil
	case "ERROR":
		return ErrorLevel, nil
	case "WARNING":
		return WarnLevel, nil
	case "INFO":
		return InfoLevel, nil
	case "DEBUG":
		return DebugLevel, nil
	default:
		return UnknownLevel, fmt.Errorf("not a valid logrus Level: %q", lvl)
	}
}

type Event struct {
	Level   Level
	Message string
	Time    time.Time
	Data    interface{}
}
<commit_msg>Fix Spelling mistakes<commit_after>package glog

import (
	"fmt"
	"time"
)

type Field map[string]interface{}

func NewField() Field {
	return Field{}
}

func (self Field) Set(k string, v interface{}) Field {
	self[k] = v
	return self
}
func (self Field) Get(k string) (interface{}, bool) {
	v, b := self[k]
	return v, b
}
func (self Field) String() string {
	s := "\tShow Field:\n"
	for k, v := range self {
		s = s + fmt.Sprintf("\t\t%v=%+v\n", k, v)
	}
	return s
}
func (self Field) Panic(args ...interface{}) {
	paincf(fmt.Sprint(args...), 2, self)
}

func (self Field) Panicf(format string, args ...interface{}) {
	paincf(fmt.Sprintf(format, args...), 2, self)
}

func (self Field) Panicln(args ...interface{}) {
	paincf(fmt.Sprintln(args...), 2, self)
}
func (self Field) Error(args ...interface{}) {
	if level >= ErrorLevel {
		event(Event{
			Level:   ErrorLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Field) Errorf(format string, args ...interface{}) {
	if level >= ErrorLevel {
		event(Event{
			Level:   ErrorLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Field) Errorln(args ...interface{}) {
	if level >= ErrorLevel {
		event(Event{
			Level:   ErrorLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

func (self Field) Warn(args ...interface{}) {
	if level >= WarnLevel {
		event(Event{
			Level:   WarnLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Field) Warnf(format string, args ...interface{}) {
	if level >= WarnLevel {
		event(Event{
			Level:   WarnLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Field) Warnln(args ...interface{}) {
	if level >= WarnLevel {
		event(Event{
			Level:   WarnLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

func (self Field) Info(args ...interface{}) {
	if level >= InfoLevel {
		event(Event{
			Level:   InfoLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Field) Infof(format string, args ...interface{}) {
	if level >= InfoLevel {
		event(Event{
			Level:   InfoLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Field) Infoln(args ...interface{}) {
	if level >= InfoLevel {
		event(Event{
			Level:   InfoLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

func (self Field) Debug(args ...interface{}) {
	if level >= DebugLevel {
		event(Event{
			Level:   DebugLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Field) Debugf(format string, args ...interface{}) {
	if level >= DebugLevel {
		event(Event{
			Level:   DebugLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self Field) Debugln(args ...interface{}) {
	if level >= DebugLevel {
		event(Event{
			Level:   DebugLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

type TagField struct {
	tag   string
	value map[string]interface{}
}

func NewTagField(tag string) *TagField {
	return &TagField{tag: tag, value: make(map[string]interface{})}
}

func (self *TagField) Set(k string, v interface{}) *TagField {
	self.value[k] = v
	return self
}
func (self *TagField) Get(k string) (interface{}, bool) {
	v, b := self.value[k]
	return v, b
}
func (self *TagField) GetTag() string {
	return self.tag
}
func (self *TagField) SetTag(tag string) *TagField {
	self.tag = tag
	return self
}
func (self *TagField) String() string {
	s := "\t[" + self.tag + "]Show Field:\n"
	for k, v := range self.value {
		s = s + fmt.Sprintf("\t\t%v=%+v\n", k, v)
	}
	return s
}
func (self *TagField) Panic(args ...interface{}) {
	paincf(fmt.Sprint(args...), 2, self)
}
func (self *TagField) Panicf(format string, args ...interface{}) {
	paincf(fmt.Sprintf(format, args...), 2, self)
}
func (self *TagField) Panicln(args ...interface{}) {
	paincf(fmt.Sprintln(args...), 2, self)
}
func (self *TagField) Error(args ...interface{}) {
	if level >= ErrorLevel {
		event(Event{
			Level:   ErrorLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagField) Errorf(format string, args ...interface{}) {
	if level >= ErrorLevel {
		event(Event{
			Level:   ErrorLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagField) Errorln(args ...interface{}) {
	if level >= ErrorLevel {
		event(Event{
			Level:   ErrorLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

func (self *TagField) Warn(args ...interface{}) {
	if level >= WarnLevel {
		event(Event{
			Level:   WarnLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagField) Warnf(format string, args ...interface{}) {
	if level >= WarnLevel {
		event(Event{
			Level:   WarnLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagField) Warnln(args ...interface{}) {
	if level >= WarnLevel {
		event(Event{
			Level:   WarnLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

func (self *TagField) Info(args ...interface{}) {
	if level >= InfoLevel {
		event(Event{
			Level:   InfoLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagField) Infof(format string, args ...interface{}) {
	if level >= InfoLevel {
		event(Event{
			Level:   InfoLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagField) Infoln(args ...interface{}) {
	if level >= InfoLevel {
		event(Event{
			Level:   InfoLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

func (self *TagField) Debug(args ...interface{}) {
	if level >= DebugLevel {
		event(Event{
			Level:   DebugLevel,
			Message: fmt.Sprint(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagField) Debugf(format string, args ...interface{}) {
	if level >= DebugLevel {
		event(Event{
			Level:   DebugLevel,
			Message: fmt.Sprintf(format, args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}
func (self *TagField) Debugln(args ...interface{}) {
	if level >= DebugLevel {
		event(Event{
			Level:   DebugLevel,
			Message: fmt.Sprintln(args...),
			Time:    time.Now(),
			Data:    self,
		})
	}
}

type Level uint8

const (
	UnknownLevel Level = iota
	PanicLevel
	ErrorLevel
	WarnLevel
	InfoLevel
	DebugLevel
)

func (level Level) String() string {
	switch level {
	case DebugLevel:
		return "DEBUG"
	case InfoLevel:
		return "INFO"
	case WarnLevel:
		return "WARNING"
	case ErrorLevel:
		return "ERROR"
	case PanicLevel:
		return "PANIC"
	}

	return "UNKNOWN"
}

func ParseLevel(lvl string) (Level, error) {
	switch lvl {
	case "PANIC":
		return PanicLevel, nil
	case "ERROR":
		return ErrorLevel, nil
	case "WARNING":
		return WarnLevel, nil
	case "INFO":
		return InfoLevel, nil
	case "DEBUG":
		return DebugLevel, nil
	default:
		return UnknownLevel, fmt.Errorf("not a valid logrus Level: %q", lvl)
	}
}

type Event struct {
	Level   Level
	Message string
	Time    time.Time
	Data    interface{}
}
<|endoftext|>


<commit_before>package pqt

import "fmt"

// Type ...
type Type interface {
	fmt.Stringer
	// Fingerprint returns unique identifier of the type. Two different types can have same SQL representation.
	Fingerprint() string
}

// BaseType ...
type BaseType struct {
	name string
}

// String implements Stringer interface.
func (bt BaseType) String() string {
	return bt.name
}

// Fingerprint implements Type interface.
func (bt BaseType) Fingerprint() string {
	return fmt.Sprintf("base: %s", bt.name)
}

// TypeDecimal ...
func TypeDecimal(precision, scale int) BaseType {
	switch {
	case precision == 0:
		return BaseType{name: "DECIMAL"}
	case precision != 0 && scale == 0:
		return BaseType{name: fmt.Sprintf("DECIMAL(%d)", precision)}
	default:
		return BaseType{name: fmt.Sprintf("DECIMAL(%d,%d)", precision, scale)}
	}
}

// TypeReal ...
func TypeReal() BaseType {
	return BaseType{name: "REAL"}
}

// TypeSerial ...
func TypeSerial() BaseType {
	return BaseType{name: "SERIAL"}
}

// TypeSerialSmall ...
func TypeSerialSmall() BaseType {
	return BaseType{name: "SMALLSERIAL"}
}

// TypeSerialBig ...
func TypeSerialBig() BaseType {
	return BaseType{name: "BIGSERIAL"}
}

// TypeInteger ...
func TypeInteger() BaseType {
	return BaseType{name: "INTEGER"}
}

// TypeIntegerSmall ...
func TypeIntegerSmall() BaseType {
	return BaseType{name: "SMALLINT"}
}

// TypeIntegerBig ...
func TypeIntegerBig() BaseType {
	return BaseType{name: "BIGINT"}
}

// TypeIntegerArray ...
func TypeIntegerArray(l int) BaseType {
	if l == 0 {
		return BaseType{name: "INTEGER[]"}
	}
	return BaseType{name: fmt.Sprintf("INTEGER[%d]", l)}
}

// TypeIntegerBigArray ...
func TypeIntegerBigArray(l int) BaseType {
	if l == 0 {
		return BaseType{name: "BIGINT[]"}
	}
	return BaseType{name: fmt.Sprintf("BIGINT[%d]", l)}
}

// TypeIntegerSmallArray ...
func TypeIntegerSmallArray(l int) BaseType {
	if l == 0 {
		return BaseType{name: "SMALLINT[]"}
	}
	return BaseType{name: fmt.Sprintf("SMALLINT[%d]", l)}
}

// TypeNumeric ...
func TypeNumeric(precision, scale int) BaseType {
	switch {
	case precision == 0:
		return BaseType{name: "NUMERIC"}
	case precision != 0 && scale == 0:
		return BaseType{name: fmt.Sprintf("NUMERIC(%d)", precision)}
	default:
		return BaseType{name: fmt.Sprintf("NUMERIC(%d,%d)", precision, scale)}
	}
}

// TypeDoublePrecision ...
func TypeDoublePrecision() BaseType {
	return BaseType{name: "DOUBLE PRECISION"}
}

// TypeBool ...
func TypeBool() BaseType {
	return BaseType{name: "BOOL"}
}

// TypeText ...
func TypeText() BaseType {
	return BaseType{name: "TEXT"}
}

// TypeTextArray ...
func TypeTextArray(l int) BaseType {
	if l == 0 {
		return BaseType{name: "TEXT[]"}
	}
	return BaseType{name: fmt.Sprintf("TEXT[%d]", l)}
}

// TypeVarchar ...
func TypeVarchar(l int) BaseType {
	if l == 0 {
		return BaseType{name: "VARCHAR"}

	}
	return BaseType{name: fmt.Sprintf("VARCHAR(%d)", l)}
}

// TypeBytea ...
func TypeBytea() BaseType {
	return BaseType{name: "BYTEA"}
}

// TypeTimestamp ...
func TypeTimestamp() BaseType {
	return BaseType{name: "TIMESTAMP"}
}

// TypeTimestampTZ ...
func TypeTimestampTZ() BaseType {
	return BaseType{name: "TIMESTAMPTZ"}
}

// CompositeType ...
type CompositeType struct {
	name       string
	Attributes []*Attribute
}

// String implements Stringer interface.
func (ct CompositeType) String() string {
	return "" // TODO: ?
}

// Fingerprint implements Type interface.
func (ct CompositeType) Fingerprint() string {
	return fmt.Sprintf("composite: %v", ct)
}

// TypeComposite ...
func TypeComposite(name string, attributes ...*Attribute) CompositeType {
	return CompositeType{
		name:       name,
		Attributes: attributes,
	}
}

// EnumeratedType ...
type EnumeratedType struct {
	name  string
	Enums []string
}

// String implements Stringer interface.
func (et EnumeratedType) String() string {
	return et.name
}

// Fingerprint implements Type interface.
func (et EnumeratedType) Fingerprint() string {
	return fmt.Sprintf("enumarated: %v", et)
}

// TypeEnumerated ...
func TypeEnumerated(name string, enums ...string) EnumeratedType {
	return EnumeratedType{
		name:  name,
		Enums: enums,
	}
}

// PseudoType ...
type PseudoType struct {
	name string
	//	input, output Function
}

// String implements Stringer interface.
func (pt PseudoType) String() string {
	return pt.name
}

// Fingerprint implements Type interface.
func (pt PseudoType) Fingerprint() string {
	return fmt.Sprintf("pseudo: %v", pt)
}

// TypePseudo ...
func TypePseudo(name string) PseudoType {
	return PseudoType{
		name: name,
	}
}

// MappableType ...
type MappableType struct {
	from    Type
	Mapping []Type
}

// String implements Stringer interface.
func (mt MappableType) String() string {
	return mt.from.String()
}

// Fingerprint implements Type interface.
func (mt MappableType) Fingerprint() string {
	return fmt.Sprintf("mappable: %v", mt)
}

// TypeMappable ...
func TypeMappable(from Type, mapping ...Type) MappableType {
	return MappableType{
		from:    from,
		Mapping: mapping,
	}
}
<commit_msg>type JSON and JSONB<commit_after>package pqt

import "fmt"

// Type ...
type Type interface {
	fmt.Stringer
	// Fingerprint returns unique identifier of the type. Two different types can have same SQL representation.
	Fingerprint() string
}

// BaseType ...
type BaseType struct {
	name string
}

// String implements Stringer interface.
func (bt BaseType) String() string {
	return bt.name
}

// Fingerprint implements Type interface.
func (bt BaseType) Fingerprint() string {
	return fmt.Sprintf("base: %s", bt.name)
}

// TypeDecimal ...
func TypeDecimal(precision, scale int) BaseType {
	switch {
	case precision == 0:
		return BaseType{name: "DECIMAL"}
	case precision != 0 && scale == 0:
		return BaseType{name: fmt.Sprintf("DECIMAL(%d)", precision)}
	default:
		return BaseType{name: fmt.Sprintf("DECIMAL(%d,%d)", precision, scale)}
	}
}

// TypeReal ...
func TypeReal() BaseType {
	return BaseType{name: "REAL"}
}

// TypeSerial ...
func TypeSerial() BaseType {
	return BaseType{name: "SERIAL"}
}

// TypeSerialSmall ...
func TypeSerialSmall() BaseType {
	return BaseType{name: "SMALLSERIAL"}
}

// TypeSerialBig ...
func TypeSerialBig() BaseType {
	return BaseType{name: "BIGSERIAL"}
}

// TypeInteger ...
func TypeInteger() BaseType {
	return BaseType{name: "INTEGER"}
}

// TypeIntegerSmall ...
func TypeIntegerSmall() BaseType {
	return BaseType{name: "SMALLINT"}
}

// TypeIntegerBig ...
func TypeIntegerBig() BaseType {
	return BaseType{name: "BIGINT"}
}

// TypeIntegerArray ...
func TypeIntegerArray(l int) BaseType {
	if l == 0 {
		return BaseType{name: "INTEGER[]"}
	}
	return BaseType{name: fmt.Sprintf("INTEGER[%d]", l)}
}

// TypeIntegerBigArray ...
func TypeIntegerBigArray(l int) BaseType {
	if l == 0 {
		return BaseType{name: "BIGINT[]"}
	}
	return BaseType{name: fmt.Sprintf("BIGINT[%d]", l)}
}

// TypeIntegerSmallArray ...
func TypeIntegerSmallArray(l int) BaseType {
	if l == 0 {
		return BaseType{name: "SMALLINT[]"}
	}
	return BaseType{name: fmt.Sprintf("SMALLINT[%d]", l)}
}

// TypeNumeric ...
func TypeNumeric(precision, scale int) BaseType {
	switch {
	case precision == 0:
		return BaseType{name: "NUMERIC"}
	case precision != 0 && scale == 0:
		return BaseType{name: fmt.Sprintf("NUMERIC(%d)", precision)}
	default:
		return BaseType{name: fmt.Sprintf("NUMERIC(%d,%d)", precision, scale)}
	}
}

// TypeDoublePrecision ...
func TypeDoublePrecision() BaseType {
	return BaseType{name: "DOUBLE PRECISION"}
}

// TypeBool ...
func TypeBool() BaseType {
	return BaseType{name: "BOOL"}
}

// TypeText ...
func TypeText() BaseType {
	return BaseType{name: "TEXT"}
}

// TypeTextArray ...
func TypeTextArray(l int) BaseType {
	if l == 0 {
		return BaseType{name: "TEXT[]"}
	}
	return BaseType{name: fmt.Sprintf("TEXT[%d]", l)}
}

// TypeVarchar ...
func TypeVarchar(l int) BaseType {
	if l == 0 {
		return BaseType{name: "VARCHAR"}

	}
	return BaseType{name: fmt.Sprintf("VARCHAR(%d)", l)}
}

// TypeBytea ...
func TypeBytea() BaseType {
	return BaseType{name: "BYTEA"}
}

// TypeTimestamp ...
func TypeTimestamp() BaseType {
	return BaseType{name: "TIMESTAMP"}
}

// TypeTimestampTZ ...
func TypeTimestampTZ() BaseType {
	return BaseType{name: "TIMESTAMPTZ"}
}

// TypeJSON ...
func TypeJSON() BaseType {
	return BaseType{name: "JSON"}
}

// TypeJSONB ...
func TypeJSONB() BaseType {
	return BaseType{name: "JSONB"}
}

// CompositeType ...
type CompositeType struct {
	name       string
	Attributes []*Attribute
}

// String implements Stringer interface.
func (ct CompositeType) String() string {
	return "" // TODO: ?
}

// Fingerprint implements Type interface.
func (ct CompositeType) Fingerprint() string {
	return fmt.Sprintf("composite: %v", ct)
}

// TypeComposite ...
func TypeComposite(name string, attributes ...*Attribute) CompositeType {
	return CompositeType{
		name:       name,
		Attributes: attributes,
	}
}

// EnumeratedType ...
type EnumeratedType struct {
	name  string
	Enums []string
}

// String implements Stringer interface.
func (et EnumeratedType) String() string {
	return et.name
}

// Fingerprint implements Type interface.
func (et EnumeratedType) Fingerprint() string {
	return fmt.Sprintf("enumarated: %v", et)
}

// TypeEnumerated ...
func TypeEnumerated(name string, enums ...string) EnumeratedType {
	return EnumeratedType{
		name:  name,
		Enums: enums,
	}
}

// PseudoType ...
type PseudoType struct {
	name string
	//	input, output Function
}

// String implements Stringer interface.
func (pt PseudoType) String() string {
	return pt.name
}

// Fingerprint implements Type interface.
func (pt PseudoType) Fingerprint() string {
	return fmt.Sprintf("pseudo: %v", pt)
}

// TypePseudo ...
func TypePseudo(name string) PseudoType {
	return PseudoType{
		name: name,
	}
}

// MappableType ...
type MappableType struct {
	from    Type
	Mapping []Type
}

// String implements Stringer interface.
func (mt MappableType) String() string {
	return mt.from.String()
}

// Fingerprint implements Type interface.
func (mt MappableType) Fingerprint() string {
	return fmt.Sprintf("mappable: %v", mt)
}

// TypeMappable ...
func TypeMappable(from Type, mapping ...Type) MappableType {
	return MappableType{
		from:    from,
		Mapping: mapping,
	}
}
<|endoftext|>


<commit_before>// Copyright © 2013, S.Çağlar Onur
// Use of this source code is governed by a LGPLv2.1
// license that can be found in the LICENSE file.
//
// Authors:
// S.Çağlar Onur <caglar@10ur.org>

// +build linux

package lxc

// #include <lxc/lxccontainer.h>
import "C"

import (
	"fmt"
)

// Verbosity type
type Verbosity int

const (
	// Quiet makes some API calls not to write anything to stdout
	Quiet Verbosity = 1 << iota
	// Verbose makes some API calls write to stdout
	Verbose
)

// BackendStore type specifies possible backend types.
type BackendStore int

const (
	// Btrfs backendstore type
	Btrfs BackendStore = iota
	// Directory backendstore type
	Directory
	// LVM backendstore type
	LVM
	// ZFS backendstore type
	ZFS
	// AUFS backendstore type
	Aufs
	// Overlayfs backendstore type
	Overlayfs
	// Loopback backendstore type
	Loopback
	// Best backendstore type
	Best
)

// BackendStore as string
func (t BackendStore) String() string {
	switch t {
	case Directory:
		return "dir"
	case ZFS:
		return "zfs"
	case Btrfs:
		return "btrfs"
	case LVM:
		return "lvm"
	case Aufs:
		return "aufs"
	case Overlayfs:
		return "overlayfs"
	case Loopback:
		return "loopback"
	case Best:
		return "best"
	}
	return "<INVALID>"
}

// State type specifies possible container states.
type State int

const (
	// STOPPED means container is not running
	STOPPED State = iota
	// STARTING means container is starting
	STARTING
	// RUNNING means container is running
	RUNNING
	// STOPPING means container is stopping
	STOPPING
	// ABORTING means container is aborting
	ABORTING
	// FREEZING means container is freezing
	FREEZING
	// FROZEN means containe is frozen
	FROZEN
	// THAWED means container is thawed
	THAWED
)

var stateMap = map[string]State{
	"STOPPED":  STOPPED,
	"STARTING": STARTING,
	"RUNNING":  RUNNING,
	"STOPPING": STOPPING,
	"ABORTING": ABORTING,
	"FREEZING": FREEZING,
	"FROZEN":   FROZEN,
	"THAWED":   THAWED,
}

// State as string
func (t State) String() string {
	switch t {
	case STOPPED:
		return "STOPPED"
	case STARTING:
		return "STARTING"
	case RUNNING:
		return "RUNNING"
	case STOPPING:
		return "STOPPING"
	case ABORTING:
		return "ABORTING"
	case FREEZING:
		return "FREEZING"
	case FROZEN:
		return "FROZEN"
	case THAWED:
		return "THAWED"
	}
	return "<INVALID>"
}

// Taken from http://golang.org/doc/effective_go.html#constants

// ByteSize type
type ByteSize float64

const (
	_ = iota
	// KB - kilobyte
	KB ByteSize = 1 << (10 * iota)
	// MB - megabyte
	MB
	// GB - gigabyte
	GB
	// TB - terabyte
	TB
	// PB - petabyte
	PB
	// EB - exabyte
	EB
	// ZB - zettabyte
	ZB
	// YB - yottabyte
	YB
)

func (b ByteSize) String() string {
	switch {
	case b >= YB:
		return fmt.Sprintf("%.2fYB", b/YB)
	case b >= ZB:
		return fmt.Sprintf("%.2fZB", b/ZB)
	case b >= EB:
		return fmt.Sprintf("%.2fEB", b/EB)
	case b >= PB:
		return fmt.Sprintf("%.2fPB", b/PB)
	case b >= TB:
		return fmt.Sprintf("%.2fTB", b/TB)
	case b >= GB:
		return fmt.Sprintf("%.2fGB", b/GB)
	case b >= MB:
		return fmt.Sprintf("%.2fMB", b/MB)
	case b >= KB:
		return fmt.Sprintf("%.2fKB", b/KB)
	}
	return fmt.Sprintf("%.2fB", b)
}

// LogLevel type specifies possible log levels.
type LogLevel int

const (
	// TRACE priority
	TRACE LogLevel = iota
	// DEBUG priority
	DEBUG
	// INFO priority
	INFO
	// NOTICE priority
	NOTICE
	// WARN priority
	WARN
	// ERROR priority
	ERROR
	// CRIT priority
	CRIT
	// ALERT priority
	ALERT
	// FATAL priority
	FATAL
)

var logLevelMap = map[string]LogLevel{
	"TRACE":  TRACE,
	"DEBUG":  DEBUG,
	"INFO":   INFO,
	"NOTICE": NOTICE,
	"WARN":   WARN,
	"ERROR":  ERROR,
	"CRIT":   CRIT,
	"ALERT":  ALERT,
	"FATAL":  FATAL,
}

func (l LogLevel) String() string {
	switch l {
	case TRACE:
		return "TRACE"
	case DEBUG:
		return "DEBUG"
	case INFO:
		return "INFO"
	case NOTICE:
		return "NOTICE"
	case WARN:
		return "WARN"
	case ERROR:
		return "ERROR"
	case CRIT:
		return "CRIT"
	case ALERT:
		return "ALERT"
	case FATAL:
		return "FATAL"
	}
	return "NOTSET"
}

// CloneFlags type
type CloneFlags int

const (
	// CloneKeepName means do not edit the rootfs to change the hostname
	CloneKeepName CloneFlags = 1 << iota
	// CloneKeepMACAddr means do not change the mac address on network interfaces
	CloneKeepMACAddr
	// CloneSnapshot means snapshot the original filesystem(s)
	CloneSnapshot
	// CloneKeepBdevType means use the same bdev type
	CloneKeepBdevType
	// CloneMaybeSnapshot means snapshot only if bdev supports it, else copy
	CloneMaybeSnapshot
)
<commit_msg>Silence minor golint warning<commit_after>// Copyright © 2013, S.Çağlar Onur
// Use of this source code is governed by a LGPLv2.1
// license that can be found in the LICENSE file.
//
// Authors:
// S.Çağlar Onur <caglar@10ur.org>

// +build linux

package lxc

// #include <lxc/lxccontainer.h>
import "C"

import (
	"fmt"
)

// Verbosity type
type Verbosity int

const (
	// Quiet makes some API calls not to write anything to stdout
	Quiet Verbosity = 1 << iota
	// Verbose makes some API calls write to stdout
	Verbose
)

// BackendStore type specifies possible backend types.
type BackendStore int

const (
	// Btrfs backendstore type
	Btrfs BackendStore = iota
	// Directory backendstore type
	Directory
	// LVM backendstore type
	LVM
	// ZFS backendstore type
	ZFS
	// Aufs backendstore type
	Aufs
	// Overlayfs backendstore type
	Overlayfs
	// Loopback backendstore type
	Loopback
	// Best backendstore type
	Best
)

// BackendStore as string
func (t BackendStore) String() string {
	switch t {
	case Directory:
		return "dir"
	case ZFS:
		return "zfs"
	case Btrfs:
		return "btrfs"
	case LVM:
		return "lvm"
	case Aufs:
		return "aufs"
	case Overlayfs:
		return "overlayfs"
	case Loopback:
		return "loopback"
	case Best:
		return "best"
	}
	return "<INVALID>"
}

// State type specifies possible container states.
type State int

const (
	// STOPPED means container is not running
	STOPPED State = iota
	// STARTING means container is starting
	STARTING
	// RUNNING means container is running
	RUNNING
	// STOPPING means container is stopping
	STOPPING
	// ABORTING means container is aborting
	ABORTING
	// FREEZING means container is freezing
	FREEZING
	// FROZEN means containe is frozen
	FROZEN
	// THAWED means container is thawed
	THAWED
)

var stateMap = map[string]State{
	"STOPPED":  STOPPED,
	"STARTING": STARTING,
	"RUNNING":  RUNNING,
	"STOPPING": STOPPING,
	"ABORTING": ABORTING,
	"FREEZING": FREEZING,
	"FROZEN":   FROZEN,
	"THAWED":   THAWED,
}

// State as string
func (t State) String() string {
	switch t {
	case STOPPED:
		return "STOPPED"
	case STARTING:
		return "STARTING"
	case RUNNING:
		return "RUNNING"
	case STOPPING:
		return "STOPPING"
	case ABORTING:
		return "ABORTING"
	case FREEZING:
		return "FREEZING"
	case FROZEN:
		return "FROZEN"
	case THAWED:
		return "THAWED"
	}
	return "<INVALID>"
}

// Taken from http://golang.org/doc/effective_go.html#constants

// ByteSize type
type ByteSize float64

const (
	_ = iota
	// KB - kilobyte
	KB ByteSize = 1 << (10 * iota)
	// MB - megabyte
	MB
	// GB - gigabyte
	GB
	// TB - terabyte
	TB
	// PB - petabyte
	PB
	// EB - exabyte
	EB
	// ZB - zettabyte
	ZB
	// YB - yottabyte
	YB
)

func (b ByteSize) String() string {
	switch {
	case b >= YB:
		return fmt.Sprintf("%.2fYB", b/YB)
	case b >= ZB:
		return fmt.Sprintf("%.2fZB", b/ZB)
	case b >= EB:
		return fmt.Sprintf("%.2fEB", b/EB)
	case b >= PB:
		return fmt.Sprintf("%.2fPB", b/PB)
	case b >= TB:
		return fmt.Sprintf("%.2fTB", b/TB)
	case b >= GB:
		return fmt.Sprintf("%.2fGB", b/GB)
	case b >= MB:
		return fmt.Sprintf("%.2fMB", b/MB)
	case b >= KB:
		return fmt.Sprintf("%.2fKB", b/KB)
	}
	return fmt.Sprintf("%.2fB", b)
}

// LogLevel type specifies possible log levels.
type LogLevel int

const (
	// TRACE priority
	TRACE LogLevel = iota
	// DEBUG priority
	DEBUG
	// INFO priority
	INFO
	// NOTICE priority
	NOTICE
	// WARN priority
	WARN
	// ERROR priority
	ERROR
	// CRIT priority
	CRIT
	// ALERT priority
	ALERT
	// FATAL priority
	FATAL
)

var logLevelMap = map[string]LogLevel{
	"TRACE":  TRACE,
	"DEBUG":  DEBUG,
	"INFO":   INFO,
	"NOTICE": NOTICE,
	"WARN":   WARN,
	"ERROR":  ERROR,
	"CRIT":   CRIT,
	"ALERT":  ALERT,
	"FATAL":  FATAL,
}

func (l LogLevel) String() string {
	switch l {
	case TRACE:
		return "TRACE"
	case DEBUG:
		return "DEBUG"
	case INFO:
		return "INFO"
	case NOTICE:
		return "NOTICE"
	case WARN:
		return "WARN"
	case ERROR:
		return "ERROR"
	case CRIT:
		return "CRIT"
	case ALERT:
		return "ALERT"
	case FATAL:
		return "FATAL"
	}
	return "NOTSET"
}

// CloneFlags type
type CloneFlags int

const (
	// CloneKeepName means do not edit the rootfs to change the hostname
	CloneKeepName CloneFlags = 1 << iota
	// CloneKeepMACAddr means do not change the mac address on network interfaces
	CloneKeepMACAddr
	// CloneSnapshot means snapshot the original filesystem(s)
	CloneSnapshot
	// CloneKeepBdevType means use the same bdev type
	CloneKeepBdevType
	// CloneMaybeSnapshot means snapshot only if bdev supports it, else copy
	CloneMaybeSnapshot
)
<|endoftext|>


<commit_before>package beam

import (
	"fmt"
	"net"
	"os"
	"syscall"
	"bufio"
)

func debugCheckpoint(msg string, args ...interface{}) {
	return
	os.Stdout.Sync()
	tty,_ := os.OpenFile("/dev/tty", os.O_RDWR, 0700)
	fmt.Fprintf(tty, msg, args...)
	bufio.NewScanner(tty).Scan()
	tty.Close()
}

// Send sends a new message on conn with data and f as payload and
// attachment, respectively.
func Send(conn *net.UnixConn, data []byte, f *os.File) error {
	{
		var fd int = -1
		if f != nil {
			fd = int(f.Fd())
		}
		debugCheckpoint("===DEBUG=== about to send '%s'[%d]. Hit enter to confirm: ", data, fd)
	}
	var fds []int
	if f != nil {
		fds = append(fds, int(f.Fd()))
	}
	return sendUnix(conn, data, fds...)
}

// Receive waits for a new message on conn, and receives its payload
// and attachment, or an error if any.
//
// If more than 1 file descriptor is sent in the message, they are all
// closed except for the first, which is the attachment.
// It is legal for a message to have no attachment or an empty payload.
func Receive(conn *net.UnixConn) (rdata []byte, rf *os.File, rerr error) {
	defer func() {
		var fd int = -1
		if rf != nil {
			fd = int(rf.Fd())
		}
		debugCheckpoint("===DEBUG=== Receive() -> '%s'[%d]. Hit enter to continue.\n", rdata, fd)
	}()
	for {
		data, fds, err := receiveUnix(conn)
		if err != nil {
			return nil, nil, err
		}
		var f *os.File
		if len(fds) > 1 {
			for _, fd := range fds {
				syscall.Close(fd)
			}
		}
		if len(fds) >= 1 {
			f = os.NewFile(uintptr(fds[0]), "")
		}
		return data, f, nil
	}
	panic("impossibru")
	return nil, nil, nil
}

// SendPipe creates a new unix socket pair, sends one end as the attachment
// to a beam message with the payload `data`, and returns the other end.
//
// This is a common pattern to open a new service endpoint.
// For example, a service wishing to advertise its presence to clients might
// open an endpoint with:
//
//  endpoint, _ := SendPipe(conn, []byte("sql"))
//  defer endpoint.Close()
//  for {
//  	conn, _ := endpoint.Receive()
//	go func() {
//		Handle(conn)
//		conn.Close()
//	}()
//  }
//
// Note that beam does not distinguish between clients and servers in the logical
// sense: any program wishing to establishing a communication with another program
// may use SendPipe() to create an endpoint.
// For example, here is how an application might use it to connect to a database client.
//
//  endpoint, _ := SendPipe(conn, []byte("userdb"))
//  defer endpoint.Close()
//  conn, _ := endpoint.Receive()
//  defer conn.Close()
//  db := NewDBClient(conn)
//
// In this example note that we only need the first connection out of the endpoint,
// but we could open new ones to retry after a broken connection.
// Note that, because the underlying service transport is abstracted away, this
// allows for arbitrarily complex service discovery and retry logic to take place,
// without complicating application code.
//
func SendPipe(conn *net.UnixConn, data []byte) (endpoint *net.UnixConn, err error) {
	local, remote, err := SocketPair()
	if err != nil {
		return nil, err
	}
	defer func() {
		if err != nil {
			local.Close()
			remote.Close()
		}
	}()
	endpoint, err = FdConn(int(local.Fd()))
	if err != nil {
		return nil, err
	}
	if err := Send(conn, data, remote); err != nil {
		return nil, err
	}
	return endpoint, nil
}

func receiveUnix(conn *net.UnixConn) ([]byte, []int, error) {
	buf := make([]byte, 4096)
	oob := make([]byte, 4096)
	bufn, oobn, _, _, err := conn.ReadMsgUnix(buf, oob)
	if err != nil {
		return nil, nil, err
	}
	return buf[:bufn], extractFds(oob[:oobn]), nil
}

func sendUnix(conn *net.UnixConn, data []byte, fds ...int) error {
	_, _, err := conn.WriteMsgUnix(data, syscall.UnixRights(fds...), nil)
	if err == nil {
		for _, fd := range fds {
			fmt.Printf("Closing sent fd %v\n", fd)
			syscall.Close(fd)
		}
	}
	return err
}

func extractFds(oob []byte) (fds []int) {
	scms, err := syscall.ParseSocketControlMessage(oob)
	if err != nil {
		return
	}
	for _, scm := range scms {
		gotFds, err := syscall.ParseUnixRights(&scm)
		if err != nil {
			continue
		}
		fds = append(fds, gotFds...)
	}
	return
}

func socketpair() ([2]int, error) {
	return syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.FD_CLOEXEC, 0)
}

// SocketPair is a convenience wrapper around the socketpair(2) syscall.
// It returns a unix socket of type SOCK_STREAM in the form of 2 file descriptors
// not bound to the underlying filesystem.
// Messages sent on one end are received on the other, and vice-versa.
// It is the caller's responsibility to close both ends.
func SocketPair() (*os.File, *os.File, error) {
	pair, err := socketpair()
	if err != nil {
		return nil, nil, err
	}
	return os.NewFile(uintptr(pair[0]), ""), os.NewFile(uintptr(pair[1]), ""), nil
}

func USocketPair() (*net.UnixConn, *net.UnixConn, error) {
	a, b, err := SocketPair()
	if err != nil {
		return nil, nil, err
	}
	fmt.Printf("SocketPair() = %v, %v\n", a.Fd(), b.Fd())
	uA, err := FdConn(int(a.Fd()))
	if err != nil {
		a.Close()
		b.Close()
		return nil, nil, err
	}
	uB, err := FdConn(int(b.Fd()))
	if err != nil {
		a.Close()
		b.Close()
		return nil, nil, err
	}
	return uA, uB, nil
}

// FdConn wraps a file descriptor in a standard *net.UnixConn object, or
// returns an error if the file descriptor does not point to a unix socket.
func FdConn(fd int) (*net.UnixConn, error) {
	f := os.NewFile(uintptr(fd), fmt.Sprintf("%d", fd))
	conn, err := net.FileConn(f)
	if err != nil {
		return nil, err
	}
	f.Close()
	uconn, ok := conn.(*net.UnixConn)
	if !ok {
		conn.Close()
		return nil, fmt.Errorf("%d: not a unix connection", fd)
	}
	return uconn, nil
}
<commit_msg>Beam: don't close the attachment FD when closing superfluous FDs<commit_after>package beam

import (
	"fmt"
	"net"
	"os"
	"syscall"
	"bufio"
)

func debugCheckpoint(msg string, args ...interface{}) {
	return
	os.Stdout.Sync()
	tty,_ := os.OpenFile("/dev/tty", os.O_RDWR, 0700)
	fmt.Fprintf(tty, msg, args...)
	bufio.NewScanner(tty).Scan()
	tty.Close()
}

// Send sends a new message on conn with data and f as payload and
// attachment, respectively.
func Send(conn *net.UnixConn, data []byte, f *os.File) error {
	{
		var fd int = -1
		if f != nil {
			fd = int(f.Fd())
		}
		debugCheckpoint("===DEBUG=== about to send '%s'[%d]. Hit enter to confirm: ", data, fd)
	}
	var fds []int
	if f != nil {
		fds = append(fds, int(f.Fd()))
	}
	return sendUnix(conn, data, fds...)
}

// Receive waits for a new message on conn, and receives its payload
// and attachment, or an error if any.
//
// If more than 1 file descriptor is sent in the message, they are all
// closed except for the first, which is the attachment.
// It is legal for a message to have no attachment or an empty payload.
func Receive(conn *net.UnixConn) (rdata []byte, rf *os.File, rerr error) {
	defer func() {
		var fd int = -1
		if rf != nil {
			fd = int(rf.Fd())
		}
		debugCheckpoint("===DEBUG=== Receive() -> '%s'[%d]. Hit enter to continue.\n", rdata, fd)
	}()
	for {
		data, fds, err := receiveUnix(conn)
		if err != nil {
			return nil, nil, err
		}
		var f *os.File
		if len(fds) > 1 {
			for _, fd := range fds[1:] {
				syscall.Close(fd)
			}
		}
		if len(fds) >= 1 {
			f = os.NewFile(uintptr(fds[0]), "")
		}
		return data, f, nil
	}
	panic("impossibru")
	return nil, nil, nil
}

// SendPipe creates a new unix socket pair, sends one end as the attachment
// to a beam message with the payload `data`, and returns the other end.
//
// This is a common pattern to open a new service endpoint.
// For example, a service wishing to advertise its presence to clients might
// open an endpoint with:
//
//  endpoint, _ := SendPipe(conn, []byte("sql"))
//  defer endpoint.Close()
//  for {
//  	conn, _ := endpoint.Receive()
//	go func() {
//		Handle(conn)
//		conn.Close()
//	}()
//  }
//
// Note that beam does not distinguish between clients and servers in the logical
// sense: any program wishing to establishing a communication with another program
// may use SendPipe() to create an endpoint.
// For example, here is how an application might use it to connect to a database client.
//
//  endpoint, _ := SendPipe(conn, []byte("userdb"))
//  defer endpoint.Close()
//  conn, _ := endpoint.Receive()
//  defer conn.Close()
//  db := NewDBClient(conn)
//
// In this example note that we only need the first connection out of the endpoint,
// but we could open new ones to retry after a broken connection.
// Note that, because the underlying service transport is abstracted away, this
// allows for arbitrarily complex service discovery and retry logic to take place,
// without complicating application code.
//
func SendPipe(conn *net.UnixConn, data []byte) (endpoint *net.UnixConn, err error) {
	local, remote, err := SocketPair()
	if err != nil {
		return nil, err
	}
	defer func() {
		if err != nil {
			local.Close()
			remote.Close()
		}
	}()
	endpoint, err = FdConn(int(local.Fd()))
	if err != nil {
		return nil, err
	}
	if err := Send(conn, data, remote); err != nil {
		return nil, err
	}
	return endpoint, nil
}

func receiveUnix(conn *net.UnixConn) ([]byte, []int, error) {
	buf := make([]byte, 4096)
	oob := make([]byte, 4096)
	bufn, oobn, _, _, err := conn.ReadMsgUnix(buf, oob)
	if err != nil {
		return nil, nil, err
	}
	return buf[:bufn], extractFds(oob[:oobn]), nil
}

func sendUnix(conn *net.UnixConn, data []byte, fds ...int) error {
	_, _, err := conn.WriteMsgUnix(data, syscall.UnixRights(fds...), nil)
	if err == nil {
		for _, fd := range fds {
			fmt.Printf("Closing sent fd %v\n", fd)
			syscall.Close(fd)
		}
	}
	return err
}

func extractFds(oob []byte) (fds []int) {
	scms, err := syscall.ParseSocketControlMessage(oob)
	if err != nil {
		return
	}
	for _, scm := range scms {
		gotFds, err := syscall.ParseUnixRights(&scm)
		if err != nil {
			continue
		}
		fds = append(fds, gotFds...)
	}
	return
}

func socketpair() ([2]int, error) {
	return syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.FD_CLOEXEC, 0)
}

// SocketPair is a convenience wrapper around the socketpair(2) syscall.
// It returns a unix socket of type SOCK_STREAM in the form of 2 file descriptors
// not bound to the underlying filesystem.
// Messages sent on one end are received on the other, and vice-versa.
// It is the caller's responsibility to close both ends.
func SocketPair() (*os.File, *os.File, error) {
	pair, err := socketpair()
	if err != nil {
		return nil, nil, err
	}
	return os.NewFile(uintptr(pair[0]), ""), os.NewFile(uintptr(pair[1]), ""), nil
}

func USocketPair() (*net.UnixConn, *net.UnixConn, error) {
	a, b, err := SocketPair()
	if err != nil {
		return nil, nil, err
	}
	fmt.Printf("SocketPair() = %v, %v\n", a.Fd(), b.Fd())
	uA, err := FdConn(int(a.Fd()))
	if err != nil {
		a.Close()
		b.Close()
		return nil, nil, err
	}
	uB, err := FdConn(int(b.Fd()))
	if err != nil {
		a.Close()
		b.Close()
		return nil, nil, err
	}
	return uA, uB, nil
}

// FdConn wraps a file descriptor in a standard *net.UnixConn object, or
// returns an error if the file descriptor does not point to a unix socket.
func FdConn(fd int) (*net.UnixConn, error) {
	f := os.NewFile(uintptr(fd), fmt.Sprintf("%d", fd))
	conn, err := net.FileConn(f)
	if err != nil {
		return nil, err
	}
	f.Close()
	uconn, ok := conn.(*net.UnixConn)
	if !ok {
		conn.Close()
		return nil, fmt.Errorf("%d: not a unix connection", fd)
	}
	return uconn, nil
}
<|endoftext|>