<commit_before>package main

import (
	"fmt"
	"os"
	"os/user"
	"path/filepath"
	"strings"
	"text/template"

	"github.com/gonuts/commander"
	"github.com/gonuts/flag"
)

func hwaf_make_cmd_pkg_create() *commander.Command {
	cmd := &commander.Command{
		Run:       hwaf_run_cmd_pkg_create,
		UsageLine: "create [options] <pkg-full-path>",
		Short:     "create a new package in the current workarea",
		Long: `
create creates a new package in the current workarea.

ex:
 $ hwaf pkg create MyPath/MyPackage
`,
		Flag: *flag.NewFlagSet("hwaf-pkg-create", flag.ExitOnError),
	}
	cmd.Flag.Bool("q", true, "only print error and warning messages, all other output will be suppressed")
	cmd.Flag.String("authors", "", "comma-separated list of authors for the new package")
	return cmd
}

func hwaf_run_cmd_pkg_create(cmd *commander.Command, args []string) {
	var err error
	n := "hwaf-pkg-" + cmd.Name()
	pkgpath := ""
	switch len(args) {
	case 1:
		pkgpath = args[0]
	default:
		err = fmt.Errorf("%s: you need to give a package (full) path", n)
		handle_err(err)
	}

	quiet := cmd.Flag.Lookup("q").Value.Get().(bool)
	authors := func() []string {
		authors := cmd.Flag.Lookup("authors").Value.Get().(string)
		out := make([]string, 0, 1)
		for _, s := range strings.Split(authors, ",") {
			s = strings.Trim(s, " ")
			if s == "" {
				continue
			}
			out = append(out, s)
		}
		return out
	}()

	if len(authors) == 0 {
		usr, err := user.Current()
		handle_err(err)
		//fmt.Printf(">>>>> %v\n", usr)
		usrname := usr.Name
		if usrname == "" {
			usrname = usr.Username
		}
		authors = []string{usrname}
	}

	if !quiet {
		fmt.Printf("%s: create package [%s]...\n", n, pkgpath)
	}

	cfg, err := g_ctx.LocalCfg()
	handle_err(err)

	pkgdir := "src"
	if cfg.HasOption("hwaf-cfg", "cmtpkgs") {
		pkgdir, err = cfg.String("hwaf-cfg", "cmtpkgs")
		handle_err(err)
	}

	dir := filepath.Join(pkgdir, pkgpath)
	if path_exists(dir) {
		err = fmt.Errorf("%s: directory [%s] already exists on filesystem", n, dir)
		handle_err(err)
	}

	err = os.MkdirAll(dir, 0755)
	handle_err(err)

	if g_ctx.PkgDb.HasPkg(dir) {
		err = fmt.Errorf("%s: a package with name [%s] already exists", n, dir)
		handle_err(err)
	}

	pkgname := filepath.Base(pkgpath)

	// create generic structure...
	for _, d := range []string{
		//"cmt",
		pkgname,
		"src",
	} {
		err = os.MkdirAll(filepath.Join(dir, d), 0755)
		handle_err(err)
	}

	wscript, err := os.Create(filepath.Join(dir, "wscript"))
	handle_err(err)
	defer func() {
		err = wscript.Sync()
		handle_err(err)
		err = wscript.Close()
		handle_err(err)
	}()

	const txt = `# -*- python -*-
# automatically generated wscript

import waflib.Logs as msg

PACKAGE = {
    'name': '{{.FullName}}',
    'author': [{{.Authors | printlst }}],
}

def pkg_deps(ctx):
    # put your package dependencies here.
    # e.g.:
    # ctx.use_pkg('AtlasPolicy')
    return

def configure(ctx):
    msg.debug('[configure package name: '+PACKAGE['name']])
    return

def build(ctx):
    # build artifacts
    # e.g.:
    # ctx.build_complib(
    #    name = '{{.Name}}',
    #    source = 'src/*.cxx src/components/*.cxx',
    #    use = ['package1', 'library2', ...],
    # )
    # ctx.install_headers()
    # ctx.build_pymodule(source=['python/*.py'])
    # ctx.install_joboptions(source=['share/*.py'])
    return
`
	/* fill the template */
	pkg := struct {
		FullName string
		Name     string
		Authors  []string
	}{
		FullName: pkgpath,
		Name:     pkgname,
		Authors:  authors,
	}
	tmpl := template.New("wscript").Funcs(template.FuncMap{
		"printlst": func(lst []string) string {
			out := []string{}
			for idx, s := range lst {
				s = strings.Trim(s, " ")
				if s == "" {
					continue
				}
				comma := ","
				if idx+1 == len(lst) {
					comma = ""
				}
				out = append(out, fmt.Sprintf("%q%s", s, comma))
			}
			return strings.Join(out, " ")
		},
	})
	tmpl, err = tmpl.Parse(txt)
	handle_err(err)
	err = tmpl.Execute(wscript, &pkg)
	handle_err(err)

	err = g_ctx.PkgDb.Add("local", "", dir)
	handle_err(err)

	if !quiet {
		fmt.Printf("%s: create package [%s]... [ok]\n", n, pkgpath)
	}
}

// EOF
<commit_msg>pkg-create: fixup typo in wscript + slightly improved example/comment<commit_after>package main

import (
	"fmt"
	"os"
	"os/user"
	"path/filepath"
	"strings"
	"text/template"

	"github.com/gonuts/commander"
	"github.com/gonuts/flag"
)

func hwaf_make_cmd_pkg_create() *commander.Command {
	cmd := &commander.Command{
		Run:       hwaf_run_cmd_pkg_create,
		UsageLine: "create [options] <pkg-full-path>",
		Short:     "create a new package in the current workarea",
		Long: `
create creates a new package in the current workarea.

ex:
 $ hwaf pkg create MyPath/MyPackage
`,
		Flag: *flag.NewFlagSet("hwaf-pkg-create", flag.ExitOnError),
	}
	cmd.Flag.Bool("q", true, "only print error and warning messages, all other output will be suppressed")
	cmd.Flag.String("authors", "", "comma-separated list of authors for the new package")
	return cmd
}

func hwaf_run_cmd_pkg_create(cmd *commander.Command, args []string) {
	var err error
	n := "hwaf-pkg-" + cmd.Name()
	pkgpath := ""
	switch len(args) {
	case 1:
		pkgpath = args[0]
	default:
		err = fmt.Errorf("%s: you need to give a package (full) path", n)
		handle_err(err)
	}

	quiet := cmd.Flag.Lookup("q").Value.Get().(bool)
	authors := func() []string {
		authors := cmd.Flag.Lookup("authors").Value.Get().(string)
		out := make([]string, 0, 1)
		for _, s := range strings.Split(authors, ",") {
			s = strings.Trim(s, " ")
			if s == "" {
				continue
			}
			out = append(out, s)
		}
		return out
	}()

	if len(authors) == 0 {
		usr, err := user.Current()
		handle_err(err)
		//fmt.Printf(">>>>> %v\n", usr)
		usrname := usr.Name
		if usrname == "" {
			usrname = usr.Username
		}
		authors = []string{usrname}
	}

	if !quiet {
		fmt.Printf("%s: create package [%s]...\n", n, pkgpath)
	}

	cfg, err := g_ctx.LocalCfg()
	handle_err(err)

	pkgdir := "src"
	if cfg.HasOption("hwaf-cfg", "cmtpkgs") {
		pkgdir, err = cfg.String("hwaf-cfg", "cmtpkgs")
		handle_err(err)
	}

	dir := filepath.Join(pkgdir, pkgpath)
	if path_exists(dir) {
		err = fmt.Errorf("%s: directory [%s] already exists on filesystem", n, dir)
		handle_err(err)
	}

	err = os.MkdirAll(dir, 0755)
	handle_err(err)

	if g_ctx.PkgDb.HasPkg(dir) {
		err = fmt.Errorf("%s: a package with name [%s] already exists", n, dir)
		handle_err(err)
	}

	pkgname := filepath.Base(pkgpath)

	// create generic structure...
	for _, d := range []string{
		//"cmt",
		pkgname,
		"src",
	} {
		err = os.MkdirAll(filepath.Join(dir, d), 0755)
		handle_err(err)
	}

	wscript, err := os.Create(filepath.Join(dir, "wscript"))
	handle_err(err)
	defer func() {
		err = wscript.Sync()
		handle_err(err)
		err = wscript.Close()
		handle_err(err)
	}()

	const txt = `# -*- python -*-
# automatically generated wscript

import waflib.Logs as msg

PACKAGE = {
    'name': '{{.FullName}}',
    'author': [{{.Authors | printlst }}],
}

def pkg_deps(ctx):
    # put your package dependencies here.
    # e.g.:
    # ctx.use_pkg('AtlasPolicy')
    return

def configure(ctx):
    msg.debug('[configure] package name: '+PACKAGE['name'])
    return

def build(ctx):
    # build artifacts
    # e.g.:
    # ctx.build_complib(
    #    name = '{{.Name}}',
    #    source = 'src/*.cxx src/components/*.cxx',
    #    use = ['lib1', 'lib2', 'ROOT', 'boost', ...],
    # )
    # ctx.install_headers()
    # ctx.build_pymodule(source=['python/*.py'])
    # ctx.install_joboptions(source=['share/*.py'])
    return
`
	/* fill the template */
	pkg := struct {
		FullName string
		Name     string
		Authors  []string
	}{
		FullName: pkgpath,
		Name:     pkgname,
		Authors:  authors,
	}
	tmpl := template.New("wscript").Funcs(template.FuncMap{
		"printlst": func(lst []string) string {
			out := []string{}
			for idx, s := range lst {
				s = strings.Trim(s, " ")
				if s == "" {
					continue
				}
				comma := ","
				if idx+1 == len(lst) {
					comma = ""
				}
				out = append(out, fmt.Sprintf("%q%s", s, comma))
			}
			return strings.Join(out, " ")
		},
	})
	tmpl, err = tmpl.Parse(txt)
	handle_err(err)
	err = tmpl.Execute(wscript, &pkg)
	handle_err(err)

	err = g_ctx.PkgDb.Add("local", "", dir)
	handle_err(err)

	if !quiet {
		fmt.Printf("%s: create package [%s]... [ok]\n", n, pkgpath)
	}
}

// EOF
<|endoftext|>


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

// free reports usage information for physical memory and swap space.
//
// Synopsis:
//     free [-k] [-m] [-g] [-t] [-h] [-json]
//
// Description:
//     Read memory information from /proc/meminfo and display a summary for
//     physical memory and swap space. The unit options use powers of 1024.
//
// Options:
//     -k: display the values in kibibytes
//     -m: display the values in mebibytes
//     -g: display the values in gibibytes
//     -t: display the values in tebibytes
//     -h: display the values in human-readable form
//     -json: use JSON output
package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"strconv"
)

const meminfoFile = "/proc/meminfo"

var humanOutput = flag.Bool("h", false, "Human output: show automatically the shortest three-digits unit")
var inBytes = flag.Bool("b", false, "Express the values in bytes")
var inKB = flag.Bool("k", false, "Express the values in kibibytes (default)")
var inMB = flag.Bool("m", false, "Express the values in mebibytes")
var inGB = flag.Bool("g", false, "Express the values in gibibytes")
var inTB = flag.Bool("t", false, "Express the values in tebibytes")
var toJSON = flag.Bool("json", false, "Use JSON for output")

type unit uint

const (
	// B is bytes
	B unit = 0
	// KB is kibibytes
	KB = 10
	// MB is mebibytes
	MB = 20
	// GB is gibibytes
	GB = 30
	// TB is tebibytes
	TB = 40
)

var units = [...]string{"B", "K", "M", "G", "T"}

// FreeConfig is a structure used to configure the behaviour of Free()
type FreeConfig struct {
	Unit        unit
	HumanOutput bool
	ToJSON      bool
}

// the following types are used for JSON serialization
type mainMemInfo struct {
	Total     uint64 `json:"total"`
	Used      uint64 `json:"used"`
	Free      uint64 `json:"free"`
	Shared    uint64 `json:"shared"`
	Cached    uint64 `json:"cached"`
	Buffers   uint64 `json:"buffers"`
	Available uint64 `json:"available"`
}

type swapInfo struct {
	Total uint64 `json:"total"`
	Used  uint64 `json:"used"`
	Free  uint64 `json:"free"`
}

// MemInfo represents the main memory and swap space information in a structured
// manner, suitable for JSON encoding.
type MemInfo struct {
	Mem  mainMemInfo `json:"mem"`
	Swap swapInfo    `json:"swap"`
}

type meminfomap map[string]uint64

// meminfo returns a mapping that represents the fields contained in
// /proc/meminfo
func meminfo() (meminfomap, error) {
	buf, err := ioutil.ReadFile(meminfoFile)
	if err != nil {
		return nil, err
	}
	return meminfoFromBytes(buf)
}

// meminfoFromBytes returns a mapping that represents the fields contained in a
// byte stream with a content compatible with /proc/meminfo
func meminfoFromBytes(buf []byte) (meminfomap, error) {
	ret := make(meminfomap, 0)
	for _, line := range bytes.Split(buf, []byte{'\n'}) {
		kv := bytes.SplitN(line, []byte{':'}, 2)
		if len(kv) != 2 {
			// invalid line?
			continue
		}
		key := string(kv[0])
		tokens := bytes.SplitN(bytes.TrimSpace(kv[1]), []byte{' '}, 2)
		if len(tokens) > 0 {
			value, err := strconv.ParseUint(string(tokens[0]), 10, 64)
			if err != nil {
				return nil, err
			}
			ret[key] = value
		}
	}
	return ret, nil
}

// missingRequiredFields checks if any of the specified fields are present in
// the input map.
func missingRequiredFields(m meminfomap, fields []string) bool {
	for _, f := range fields {
		if _, ok := m[f]; !ok {
			log.Printf("Missing field '%v'", f)
			return true
		}
	}
	return false
}

// humanReadableValue returns a string representing the input value, treated as
// a size in bytes, interpreted in a human readable form. E.g. the number 10240
// woud return the string "10 kB"
func humanReadableValue(value uint64) string {
	v := value
	// bits to shift. 0 means bytes, 10 means kB, and so on. 40 is the highest
	// and it means tB
	var shift uint
	for {
		if shift >= uint(len(units)*10) {
			// 4 means tebibyte, we don't go further
			break
		}
		if v/1024 < 1 {
			break
		}
		v /= 1024
		shift += 10
	}
	var decimal uint64
	if shift > 0 {
		// no rounding. Is there a better way to do this?
		decimal = ((value - (value >> shift << shift)) >> (shift - 10)) / 100
	}
	return fmt.Sprintf("%v.%v%v",
		value>>shift,
		decimal,
		units[shift/10],
	)
}

// formatValueByConfig formats a size in bytes in the appropriate unit,
// depending on whether FreeConfig specifies a human-readable format or a
// specific unit
func formatValueByConfig(value uint64, config *FreeConfig) string {
	if config.HumanOutput {
		return humanReadableValue(value)
	}
	// units and decimal part are not printed when a unit is explicitly specified
	return fmt.Sprintf("%v", value>>config.Unit)
}

// getMainMemInfo prints the physical memory information in the specified units. Only
// the relevant fields will be used from the input map.
func getMainMemInfo(m meminfomap, config *FreeConfig) (*mainMemInfo, error) {
	fields := []string{
		"MemTotal",
		"MemFree",
		"Buffers",
		"Cached",
		"Shmem",
		"SReclaimable",
		"MemAvailable",
	}
	if missingRequiredFields(m, fields) {
		return nil, fmt.Errorf("Missing required fields from meminfo")
	}

	// These values are expressed in kibibytes, convert to the desired unit
	memTotal := m["MemTotal"] << KB
	memFree := m["MemFree"] << KB
	memShared := m["Shmem"] << KB
	memCached := (m["Cached"] + m["SReclaimable"]) << KB
	memBuffers := (m["Buffers"]) << KB
	memUsed := memTotal - memFree - memCached - memBuffers
	if memUsed < 0 {
		memUsed = memTotal - memFree
	}
	memAvailable := m["MemAvailable"] << KB

	mmi := mainMemInfo{
		Total:     memTotal,
		Used:      memUsed,
		Free:      memFree,
		Shared:    memShared,
		Cached:    memCached,
		Buffers:   memBuffers,
		Available: memAvailable,
	}
	return &mmi, nil
}

// getSwapInfo prints the swap space information in the specified units. Only the
// relevant fields will be used from the input map.
func getSwapInfo(m meminfomap, config *FreeConfig) (*swapInfo, error) {
	fields := []string{
		"SwapTotal",
		"SwapFree",
	}
	if missingRequiredFields(m, fields) {
		return nil, fmt.Errorf("Missing required fields from meminfo")
	}
	// These values are expressed in kibibytes, convert to the desired unit
	swapTotal := m["SwapTotal"] << KB
	swapUsed := (m["SwapTotal"] - m["SwapFree"]) << KB
	swapFree := m["SwapFree"] << KB

	si := swapInfo{
		Total: swapTotal,
		Used:  swapUsed,
		Free:  swapFree,
	}
	return &si, nil
}

// Free prints physical memory and swap space information. The fields will be
// expressed with the specified unit (e.g. KB, MB)
func Free(config *FreeConfig) error {
	m, err := meminfo()
	if err != nil {
		log.Fatal(err)
	}
	mmi, err := getMainMemInfo(m, config)
	if err != nil {
		return err
	}
	si, err := getSwapInfo(m, config)
	if err != nil {
		return err
	}
	mi := MemInfo{Mem: *mmi, Swap: *si}
	if config.ToJSON {
		jsonData, err := json.Marshal(mi)
		if err != nil {
			return err
		}
		fmt.Println(string(jsonData))
	} else {
		fmt.Printf("              total        used        free      shared  buff/cache   available\n")
		fmt.Printf("%-7s %11v %11v %11v %11v %11v %11v\n",
			"Mem:",
			formatValueByConfig(mmi.Total, config),
			formatValueByConfig(mmi.Used, config),
			formatValueByConfig(mmi.Free, config),
			formatValueByConfig(mmi.Shared, config),
			formatValueByConfig(mmi.Buffers+mmi.Cached, config),
			formatValueByConfig(mmi.Available, config),
		)
		fmt.Printf("%-7s %11v %11v %11v\n",
			"Swap:",
			formatValueByConfig(si.Total, config),
			formatValueByConfig(si.Used, config),
			formatValueByConfig(si.Free, config),
		)
	}
	return nil
}

// validateUnits checks that only one option of -b, -k, -m, -g, -t or -h has been
// specified on the command line
func validateUnits() bool {
	count := 0
	if *inBytes {
		count++
	}
	if *inKB {
		count++
	}
	if *inMB {
		count++
	}
	if *inGB {
		count++
	}
	if *inTB {
		count++
	}
	if *humanOutput {
		count++
	}
	if count > 1 {
		return false
	}
	return true
}

func main() {
	flag.Parse()
	if !validateUnits() {
		log.Fatal("Options -k, -m, -g, -t and -h are mutually exclusive")
	}
	config := FreeConfig{ToJSON: *toJSON}
	if *humanOutput {
		config.HumanOutput = true
	} else {
		var unit unit = KB
		if *inBytes {
			unit = B
		} else if *inKB {
			unit = KB
		} else if *inMB {
			unit = MB
		} else if *inGB {
			unit = GB
		} else if *inTB {
			unit = TB
		}
		config.Unit = unit
	}

	if err := Free(&config); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>cmds/free: refactored linux-specific functions<commit_after>// Copyright 2012-2018 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// free reports usage information for physical memory and swap space.
//
// Synopsis:
//     free [-k] [-m] [-g] [-t] [-h] [-json]
//
// Description:
//     Read memory information from /proc/meminfo and display a summary for
//     physical memory and swap space. The unit options use powers of 1024.
//
// Options:
//     -k: display the values in kibibytes
//     -m: display the values in mebibytes
//     -g: display the values in gibibytes
//     -t: display the values in tebibytes
//     -h: display the values in human-readable form
//     -json: use JSON output
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
)

var humanOutput = flag.Bool("h", false, "Human output: show automatically the shortest three-digits unit")
var inBytes = flag.Bool("b", false, "Express the values in bytes")
var inKB = flag.Bool("k", false, "Express the values in kibibytes (default)")
var inMB = flag.Bool("m", false, "Express the values in mebibytes")
var inGB = flag.Bool("g", false, "Express the values in gibibytes")
var inTB = flag.Bool("t", false, "Express the values in tebibytes")
var toJSON = flag.Bool("json", false, "Use JSON for output")

type unit uint

const (
	// B is bytes
	B unit = 0
	// KB is kibibytes
	KB = 10
	// MB is mebibytes
	MB = 20
	// GB is gibibytes
	GB = 30
	// TB is tebibytes
	TB = 40
)

var units = [...]string{"B", "K", "M", "G", "T"}

// FreeConfig is a structure used to configure the behaviour of Free()
type FreeConfig struct {
	Unit        unit
	HumanOutput bool
	ToJSON      bool
}

// the following types are used for JSON serialization
type mainMemInfo struct {
	Total     uint64 `json:"total"`
	Used      uint64 `json:"used"`
	Free      uint64 `json:"free"`
	Shared    uint64 `json:"shared"`
	Cached    uint64 `json:"cached"`
	Buffers   uint64 `json:"buffers"`
	Available uint64 `json:"available"`
}

type swapInfo struct {
	Total uint64 `json:"total"`
	Used  uint64 `json:"used"`
	Free  uint64 `json:"free"`
}

// MemInfo represents the main memory and swap space information in a structured
// manner, suitable for JSON encoding.
type MemInfo struct {
	Mem  mainMemInfo `json:"mem"`
	Swap swapInfo    `json:"swap"`
}

type meminfomap map[string]uint64

// missingRequiredFields checks if any of the specified fields are present in
// the input map.
func missingRequiredFields(m meminfomap, fields []string) bool {
	for _, f := range fields {
		if _, ok := m[f]; !ok {
			log.Printf("Missing field '%v'", f)
			return true
		}
	}
	return false
}

// humanReadableValue returns a string representing the input value, treated as
// a size in bytes, interpreted in a human readable form. E.g. the number 10240
// woud return the string "10 kB". Note that the decimal part is truncated, not
// rounded, so the values are guaranteed to be "at least X"
func humanReadableValue(value uint64) string {
	v := value
	// bits to shift. 0 means bytes, 10 means kB, and so on. 40 is the highest
	// and it means tB
	var shift uint
	for {
		if shift >= uint(len(units)*10) {
			// 4 means tebibyte, we don't go further
			break
		}
		if v/1024 < 1 {
			break
		}
		v /= 1024
		shift += 10
	}
	var decimal uint64
	if shift > 0 {
		// no rounding. Is there a better way to do this?
		decimal = ((value - (value >> shift << shift)) >> (shift - 10)) * 1000 / 1024 / 100
	}
	return fmt.Sprintf("%v.%v%v",
		value>>shift,
		decimal,
		units[shift/10],
	)
}

// formatValueByConfig formats a size in bytes in the appropriate unit,
// depending on whether FreeConfig specifies a human-readable format or a
// specific unit
func formatValueByConfig(value uint64, config *FreeConfig) string {
	if config.HumanOutput {
		return humanReadableValue(value)
	}
	// units and decimal part are not printed when a unit is explicitly specified
	return fmt.Sprintf("%v", value>>config.Unit)
}

// Free prints physical memory and swap space information. The fields will be
// expressed with the specified unit (e.g. KB, MB)
func Free(config *FreeConfig) error {
	m, err := meminfo()
	if err != nil {
		log.Fatal(err)
	}
	mmi, err := getMainMemInfo(m, config)
	if err != nil {
		return err
	}
	si, err := getSwapInfo(m, config)
	if err != nil {
		return err
	}
	mi := MemInfo{Mem: *mmi, Swap: *si}
	if config.ToJSON {
		jsonData, err := json.Marshal(mi)
		if err != nil {
			return err
		}
		fmt.Println(string(jsonData))
	} else {
		fmt.Printf("              total        used        free      shared  buff/cache   available\n")
		fmt.Printf("%-7s %11v %11v %11v %11v %11v %11v\n",
			"Mem:",
			formatValueByConfig(mmi.Total, config),
			formatValueByConfig(mmi.Used, config),
			formatValueByConfig(mmi.Free, config),
			formatValueByConfig(mmi.Shared, config),
			formatValueByConfig(mmi.Buffers+mmi.Cached, config),
			formatValueByConfig(mmi.Available, config),
		)
		fmt.Printf("%-7s %11v %11v %11v\n",
			"Swap:",
			formatValueByConfig(si.Total, config),
			formatValueByConfig(si.Used, config),
			formatValueByConfig(si.Free, config),
		)
	}
	return nil
}

// validateUnits checks that only one option of -b, -k, -m, -g, -t or -h has been
// specified on the command line
func validateUnits() bool {
	count := 0
	if *inBytes {
		count++
	}
	if *inKB {
		count++
	}
	if *inMB {
		count++
	}
	if *inGB {
		count++
	}
	if *inTB {
		count++
	}
	if *humanOutput {
		count++
	}
	if count > 1 {
		return false
	}
	return true
}

func main() {
	flag.Parse()
	if !validateUnits() {
		log.Fatal("Options -k, -m, -g, -t and -h are mutually exclusive")
	}
	config := FreeConfig{ToJSON: *toJSON}
	if *humanOutput {
		config.HumanOutput = true
	} else {
		var unit unit = KB
		if *inBytes {
			unit = B
		} else if *inKB {
			unit = KB
		} else if *inMB {
			unit = MB
		} else if *inGB {
			unit = GB
		} else if *inTB {
			unit = TB
		}
		config.Unit = unit
	}

	if err := Free(&config); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


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

// Wget reads one file from a url and writes to stdout.
//
// Synopsis:
//     wget URL
//
// Example:
//     wget http://google.com/ | tee e100.html
package main

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

func wget(arg string, w io.Writer) error {
	resp, err := http.Get(arg)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	_, err = io.Copy(w, resp.Body)

	return nil
}

func main() {
	// TODO: use flags library
	if len(os.Args) < 2 {
		os.Exit(1)
	}

	if err := wget(os.Args[1], os.Stdout); err != nil {
		log.Fatalf("%v\n", err)
	}
}
<commit_msg>Add improvements to the wget command<commit_after>// Copyright 2012-2017 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Wget reads one file from a url and writes to stdout.
//
// Synopsis:
//     wget [ARGS] URL
//
// Description:
//     Returns a non-zero code on failure.
//
// Options:
//     -O: output filename, defaults to '-' (stdout)
//
// Notes:
//     There are a few differences with GNU wget:
//     - `-O` defaults to `-`.
//     - The protocol (http/https) is mandatory.
//
// Example:
//     wget -O e100.html http://google.com/
package main

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

var (
	outFilename = flag.String("O", "-", "output filename, '-' for stdout")
)

func wget(arg string, w io.Writer) error {
	resp, err := http.Get(arg)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return fmt.Errorf("non-200 HTTP status: %d", resp.StatusCode)
	}
	_, err = io.Copy(w, resp.Body)
	return nil
}

func usage() {
	log.Printf("Usage: %s [ARGS] URL\n", os.Args[0])
	flag.PrintDefaults()
	os.Exit(2)
}

func main() {
	flag.Parse()
	if flag.NArg() != 1 {
		usage()
	}

	url := flag.Arg(0)
	w := os.Stdout
	if *outFilename != "-" {
		var err error
		w, err = os.Create(*outFilename)
		if err != nil {
			log.Fatalln("Cannot create file:", err)
		}
		defer w.Close()
	}

	if err := wget(url, w); err != nil {
		log.Fatalf("%v\n", err)
	}
}
<|endoftext|>


<commit_before>//
// This file is automatically generated by scripts/generate-plugins.go -- Do not edit!
//

package command

import (
	"fmt"
	"log"
	"regexp"
	"strings"

	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/packer/plugin"

	alicloudecsbuilder "github.com/hashicorp/packer/builder/alicloud/ecs"
	alicloudimportpostprocessor "github.com/hashicorp/packer/post-processor/alicloud-import"
	amazonchrootbuilder "github.com/hashicorp/packer/builder/amazon/chroot"
	amazonebsbuilder "github.com/hashicorp/packer/builder/amazon/ebs"
	amazonebssurrogatebuilder "github.com/hashicorp/packer/builder/amazon/ebssurrogate"
	amazonebsvolumebuilder "github.com/hashicorp/packer/builder/amazon/ebsvolume"
	amazonimportpostprocessor "github.com/hashicorp/packer/post-processor/amazon-import"
	amazoninstancebuilder "github.com/hashicorp/packer/builder/amazon/instance"
	ansiblelocalprovisioner "github.com/hashicorp/packer/provisioner/ansible-local"
	ansibleprovisioner "github.com/hashicorp/packer/provisioner/ansible"
	artificepostprocessor "github.com/hashicorp/packer/post-processor/artifice"
	atlaspostprocessor "github.com/hashicorp/packer/post-processor/atlas"
	azurearmbuilder "github.com/hashicorp/packer/builder/azure/arm"
	checksumpostprocessor "github.com/hashicorp/packer/post-processor/checksum"
	chefclientprovisioner "github.com/hashicorp/packer/provisioner/chef-client"
	chefsoloprovisioner "github.com/hashicorp/packer/provisioner/chef-solo"
	cloudstackbuilder "github.com/hashicorp/packer/builder/cloudstack"
	compresspostprocessor "github.com/hashicorp/packer/post-processor/compress"
	convergeprovisioner "github.com/hashicorp/packer/provisioner/converge"
	digitaloceanbuilder "github.com/hashicorp/packer/builder/digitalocean"
	dockerbuilder "github.com/hashicorp/packer/builder/docker"
	dockerimportpostprocessor "github.com/hashicorp/packer/post-processor/docker-import"
	dockerpushpostprocessor "github.com/hashicorp/packer/post-processor/docker-push"
	dockersavepostprocessor "github.com/hashicorp/packer/post-processor/docker-save"
	dockertagpostprocessor "github.com/hashicorp/packer/post-processor/docker-tag"
	filebuilder "github.com/hashicorp/packer/builder/file"
	fileprovisioner "github.com/hashicorp/packer/provisioner/file"
	googlecomputebuilder "github.com/hashicorp/packer/builder/googlecompute"
	googlecomputeexportpostprocessor "github.com/hashicorp/packer/post-processor/googlecompute-export"
	hypervisobuilder "github.com/hashicorp/packer/builder/hyperv/iso"
	hypervvmcxbuilder "github.com/hashicorp/packer/builder/hyperv/vmcx"
	lxcbuilder "github.com/hashicorp/packer/builder/lxc"
	lxdbuilder "github.com/hashicorp/packer/builder/lxd"
	manifestpostprocessor "github.com/hashicorp/packer/post-processor/manifest"
	nullbuilder "github.com/hashicorp/packer/builder/null"
	oneandonebuilder "github.com/hashicorp/packer/builder/oneandone"
	openstackbuilder "github.com/hashicorp/packer/builder/openstack"
	oracleclassicbuilder "github.com/hashicorp/packer/builder/oracle/classic"
	oracleocibuilder "github.com/hashicorp/packer/builder/oracle/oci"
	parallelsisobuilder "github.com/hashicorp/packer/builder/parallels/iso"
	parallelspvmbuilder "github.com/hashicorp/packer/builder/parallels/pvm"
	powershellprovisioner "github.com/hashicorp/packer/provisioner/powershell"
	profitbricksbuilder "github.com/hashicorp/packer/builder/profitbricks"
	puppetmasterlessprovisioner "github.com/hashicorp/packer/provisioner/puppet-masterless"
	puppetserverprovisioner "github.com/hashicorp/packer/provisioner/puppet-server"
	qemubuilder "github.com/hashicorp/packer/builder/qemu"
	saltmasterlessprovisioner "github.com/hashicorp/packer/provisioner/salt-masterless"
	shelllocalpostprocessor "github.com/hashicorp/packer/post-processor/shell-local"
	shelllocalprovisioner "github.com/hashicorp/packer/provisioner/shell-local"
	shellprovisioner "github.com/hashicorp/packer/provisioner/shell"
	tritonbuilder "github.com/hashicorp/packer/builder/triton"
	vagrantcloudpostprocessor "github.com/hashicorp/packer/post-processor/vagrant-cloud"
	vagrantpostprocessor "github.com/hashicorp/packer/post-processor/vagrant"
	virtualboxisobuilder "github.com/hashicorp/packer/builder/virtualbox/iso"
	virtualboxovfbuilder "github.com/hashicorp/packer/builder/virtualbox/ovf"
	vmwareisobuilder "github.com/hashicorp/packer/builder/vmware/iso"
	vmwarevmxbuilder "github.com/hashicorp/packer/builder/vmware/vmx"
	vspherepostprocessor "github.com/hashicorp/packer/post-processor/vsphere"
	vspheretemplatepostprocessor "github.com/hashicorp/packer/post-processor/vsphere-template"
	windowsrestartprovisioner "github.com/hashicorp/packer/provisioner/windows-restart"
	windowsshellprovisioner "github.com/hashicorp/packer/provisioner/windows-shell"

)

type PluginCommand struct {
	Meta
}

var Builders = map[string]packer.Builder{
	"alicloud-ecs":   new(alicloudecsbuilder.Builder),
	"amazon-chroot":   new(amazonchrootbuilder.Builder),
	"amazon-ebs":   new(amazonebsbuilder.Builder),
	"amazon-ebssurrogate":   new(amazonebssurrogatebuilder.Builder),
	"amazon-ebsvolume":   new(amazonebsvolumebuilder.Builder),
	"amazon-instance":   new(amazoninstancebuilder.Builder),
	"azure-arm":   new(azurearmbuilder.Builder),
	"cloudstack":   new(cloudstackbuilder.Builder),
	"digitalocean":   new(digitaloceanbuilder.Builder),
	"docker":   new(dockerbuilder.Builder),
	"file":   new(filebuilder.Builder),
	"googlecompute":   new(googlecomputebuilder.Builder),
	"hyperv-iso":   new(hypervisobuilder.Builder),
	"hyperv-vmcx":   new(hypervvmcxbuilder.Builder),
	"lxc":   new(lxcbuilder.Builder),
	"lxd":   new(lxdbuilder.Builder),
	"null":   new(nullbuilder.Builder),
	"oneandone":   new(oneandonebuilder.Builder),
	"openstack":   new(openstackbuilder.Builder),
	"oracle-classic":   new(oracleclassicbuilder.Builder),
	"oracle-oci":   new(oracleocibuilder.Builder),
	"parallels-iso":   new(parallelsisobuilder.Builder),
	"parallels-pvm":   new(parallelspvmbuilder.Builder),
	"profitbricks":   new(profitbricksbuilder.Builder),
	"qemu":   new(qemubuilder.Builder),
	"triton":   new(tritonbuilder.Builder),
	"virtualbox-iso":   new(virtualboxisobuilder.Builder),
	"virtualbox-ovf":   new(virtualboxovfbuilder.Builder),
	"vmware-iso":   new(vmwareisobuilder.Builder),
	"vmware-vmx":   new(vmwarevmxbuilder.Builder),
}

var Provisioners = map[string]packer.Provisioner{
	"ansible":   new(ansibleprovisioner.Provisioner),
	"ansible-local":   new(ansiblelocalprovisioner.Provisioner),
	"chef-client":   new(chefclientprovisioner.Provisioner),
	"chef-solo":   new(chefsoloprovisioner.Provisioner),
	"converge":   new(convergeprovisioner.Provisioner),
	"file":   new(fileprovisioner.Provisioner),
	"powershell":   new(powershellprovisioner.Provisioner),
	"puppet-masterless":   new(puppetmasterlessprovisioner.Provisioner),
	"puppet-server":   new(puppetserverprovisioner.Provisioner),
	"salt-masterless":   new(saltmasterlessprovisioner.Provisioner),
	"shell":   new(shellprovisioner.Provisioner),
	"shell-local":   new(shelllocalprovisioner.Provisioner),
	"windows-restart":   new(windowsrestartprovisioner.Provisioner),
	"windows-shell":   new(windowsshellprovisioner.Provisioner),
}

var PostProcessors = map[string]packer.PostProcessor{
	"alicloud-import":   new(alicloudimportpostprocessor.PostProcessor),
	"amazon-import":   new(amazonimportpostprocessor.PostProcessor),
	"artifice":   new(artificepostprocessor.PostProcessor),
	"atlas":   new(atlaspostprocessor.PostProcessor),
	"checksum":   new(checksumpostprocessor.PostProcessor),
	"compress":   new(compresspostprocessor.PostProcessor),
	"docker-import":   new(dockerimportpostprocessor.PostProcessor),
	"docker-push":   new(dockerpushpostprocessor.PostProcessor),
	"docker-save":   new(dockersavepostprocessor.PostProcessor),
	"docker-tag":   new(dockertagpostprocessor.PostProcessor),
	"googlecompute-export":   new(googlecomputeexportpostprocessor.PostProcessor),
	"manifest":   new(manifestpostprocessor.PostProcessor),
	"shell-local":   new(shelllocalpostprocessor.PostProcessor),
	"vagrant":   new(vagrantpostprocessor.PostProcessor),
	"vagrant-cloud":   new(vagrantcloudpostprocessor.PostProcessor),
	"vsphere":   new(vspherepostprocessor.PostProcessor),
	"vsphere-template":   new(vspheretemplatepostprocessor.PostProcessor),
}

var pluginRegexp = regexp.MustCompile("packer-(builder|post-processor|provisioner)-(.+)")

func (c *PluginCommand) Run(args []string) int {
	// This is an internal call (users should not call this directly) so we're
	// not going to do much input validation. If there's a problem we'll often
	// just crash. Error handling should be added to facilitate debugging.
	log.Printf("args: %#v", args)
	if len(args) != 1 {
		c.Ui.Error("Wrong number of args")
		return 1
	}

	// Plugin will match something like "packer-builder-amazon-ebs"
	parts := pluginRegexp.FindStringSubmatch(args[0])
	if len(parts) != 3 {
		c.Ui.Error(fmt.Sprintf("Error parsing plugin argument [DEBUG]: %#v", parts))
		return 1
	}
	pluginType := parts[1] // capture group 1 (builder|post-processor|provisioner)
	pluginName := parts[2] // capture group 2 (.+)

	server, err := plugin.Server()
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error starting plugin server: %s", err))
		return 1
	}

	switch pluginType {
	case "builder":
		builder, found := Builders[pluginName]
		if !found {
			c.Ui.Error(fmt.Sprintf("Could not load builder: %s", pluginName))
			return 1
		}
		server.RegisterBuilder(builder)
	case "provisioner":
		provisioner, found := Provisioners[pluginName]
		if !found {
			c.Ui.Error(fmt.Sprintf("Could not load provisioner: %s", pluginName))
			return 1
		}
		server.RegisterProvisioner(provisioner)
	case "post-processor":
		postProcessor, found := PostProcessors[pluginName]
		if !found {
			c.Ui.Error(fmt.Sprintf("Could not load post-processor: %s", pluginName))
			return 1
		}
		server.RegisterPostProcessor(postProcessor)
	}

	server.Serve()

	return 0
}

func (*PluginCommand) Help() string {
	helpText := `
Usage: packer plugin PLUGIN

  Runs an internally-compiled version of a plugin from the packer binary.

  NOTE: this is an internal command and you should not call it yourself.
`

	return strings.TrimSpace(helpText)
}

func (c *PluginCommand) Synopsis() string {
	return "internal plugin command"
}
<commit_msg>make fmt<commit_after>//
// This file is automatically generated by scripts/generate-plugins.go -- Do not edit!
//

package command

import (
	"fmt"
	"log"
	"regexp"
	"strings"

	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/packer/plugin"

	alicloudecsbuilder "github.com/hashicorp/packer/builder/alicloud/ecs"
	amazonchrootbuilder "github.com/hashicorp/packer/builder/amazon/chroot"
	amazonebsbuilder "github.com/hashicorp/packer/builder/amazon/ebs"
	amazonebssurrogatebuilder "github.com/hashicorp/packer/builder/amazon/ebssurrogate"
	amazonebsvolumebuilder "github.com/hashicorp/packer/builder/amazon/ebsvolume"
	amazoninstancebuilder "github.com/hashicorp/packer/builder/amazon/instance"
	azurearmbuilder "github.com/hashicorp/packer/builder/azure/arm"
	cloudstackbuilder "github.com/hashicorp/packer/builder/cloudstack"
	digitaloceanbuilder "github.com/hashicorp/packer/builder/digitalocean"
	dockerbuilder "github.com/hashicorp/packer/builder/docker"
	filebuilder "github.com/hashicorp/packer/builder/file"
	googlecomputebuilder "github.com/hashicorp/packer/builder/googlecompute"
	hypervisobuilder "github.com/hashicorp/packer/builder/hyperv/iso"
	hypervvmcxbuilder "github.com/hashicorp/packer/builder/hyperv/vmcx"
	lxcbuilder "github.com/hashicorp/packer/builder/lxc"
	lxdbuilder "github.com/hashicorp/packer/builder/lxd"
	nullbuilder "github.com/hashicorp/packer/builder/null"
	oneandonebuilder "github.com/hashicorp/packer/builder/oneandone"
	openstackbuilder "github.com/hashicorp/packer/builder/openstack"
	oracleclassicbuilder "github.com/hashicorp/packer/builder/oracle/classic"
	oracleocibuilder "github.com/hashicorp/packer/builder/oracle/oci"
	parallelsisobuilder "github.com/hashicorp/packer/builder/parallels/iso"
	parallelspvmbuilder "github.com/hashicorp/packer/builder/parallels/pvm"
	profitbricksbuilder "github.com/hashicorp/packer/builder/profitbricks"
	qemubuilder "github.com/hashicorp/packer/builder/qemu"
	tritonbuilder "github.com/hashicorp/packer/builder/triton"
	virtualboxisobuilder "github.com/hashicorp/packer/builder/virtualbox/iso"
	virtualboxovfbuilder "github.com/hashicorp/packer/builder/virtualbox/ovf"
	vmwareisobuilder "github.com/hashicorp/packer/builder/vmware/iso"
	vmwarevmxbuilder "github.com/hashicorp/packer/builder/vmware/vmx"
	alicloudimportpostprocessor "github.com/hashicorp/packer/post-processor/alicloud-import"
	amazonimportpostprocessor "github.com/hashicorp/packer/post-processor/amazon-import"
	artificepostprocessor "github.com/hashicorp/packer/post-processor/artifice"
	atlaspostprocessor "github.com/hashicorp/packer/post-processor/atlas"
	checksumpostprocessor "github.com/hashicorp/packer/post-processor/checksum"
	compresspostprocessor "github.com/hashicorp/packer/post-processor/compress"
	dockerimportpostprocessor "github.com/hashicorp/packer/post-processor/docker-import"
	dockerpushpostprocessor "github.com/hashicorp/packer/post-processor/docker-push"
	dockersavepostprocessor "github.com/hashicorp/packer/post-processor/docker-save"
	dockertagpostprocessor "github.com/hashicorp/packer/post-processor/docker-tag"
	googlecomputeexportpostprocessor "github.com/hashicorp/packer/post-processor/googlecompute-export"
	manifestpostprocessor "github.com/hashicorp/packer/post-processor/manifest"
	shelllocalpostprocessor "github.com/hashicorp/packer/post-processor/shell-local"
	vagrantpostprocessor "github.com/hashicorp/packer/post-processor/vagrant"
	vagrantcloudpostprocessor "github.com/hashicorp/packer/post-processor/vagrant-cloud"
	vspherepostprocessor "github.com/hashicorp/packer/post-processor/vsphere"
	vspheretemplatepostprocessor "github.com/hashicorp/packer/post-processor/vsphere-template"
	ansibleprovisioner "github.com/hashicorp/packer/provisioner/ansible"
	ansiblelocalprovisioner "github.com/hashicorp/packer/provisioner/ansible-local"
	chefclientprovisioner "github.com/hashicorp/packer/provisioner/chef-client"
	chefsoloprovisioner "github.com/hashicorp/packer/provisioner/chef-solo"
	convergeprovisioner "github.com/hashicorp/packer/provisioner/converge"
	fileprovisioner "github.com/hashicorp/packer/provisioner/file"
	powershellprovisioner "github.com/hashicorp/packer/provisioner/powershell"
	puppetmasterlessprovisioner "github.com/hashicorp/packer/provisioner/puppet-masterless"
	puppetserverprovisioner "github.com/hashicorp/packer/provisioner/puppet-server"
	saltmasterlessprovisioner "github.com/hashicorp/packer/provisioner/salt-masterless"
	shellprovisioner "github.com/hashicorp/packer/provisioner/shell"
	shelllocalprovisioner "github.com/hashicorp/packer/provisioner/shell-local"
	windowsrestartprovisioner "github.com/hashicorp/packer/provisioner/windows-restart"
	windowsshellprovisioner "github.com/hashicorp/packer/provisioner/windows-shell"
)

type PluginCommand struct {
	Meta
}

var Builders = map[string]packer.Builder{
	"alicloud-ecs":        new(alicloudecsbuilder.Builder),
	"amazon-chroot":       new(amazonchrootbuilder.Builder),
	"amazon-ebs":          new(amazonebsbuilder.Builder),
	"amazon-ebssurrogate": new(amazonebssurrogatebuilder.Builder),
	"amazon-ebsvolume":    new(amazonebsvolumebuilder.Builder),
	"amazon-instance":     new(amazoninstancebuilder.Builder),
	"azure-arm":           new(azurearmbuilder.Builder),
	"cloudstack":          new(cloudstackbuilder.Builder),
	"digitalocean":        new(digitaloceanbuilder.Builder),
	"docker":              new(dockerbuilder.Builder),
	"file":                new(filebuilder.Builder),
	"googlecompute":       new(googlecomputebuilder.Builder),
	"hyperv-iso":          new(hypervisobuilder.Builder),
	"hyperv-vmcx":         new(hypervvmcxbuilder.Builder),
	"lxc":                 new(lxcbuilder.Builder),
	"lxd":                 new(lxdbuilder.Builder),
	"null":                new(nullbuilder.Builder),
	"oneandone":           new(oneandonebuilder.Builder),
	"openstack":           new(openstackbuilder.Builder),
	"oracle-classic":      new(oracleclassicbuilder.Builder),
	"oracle-oci":          new(oracleocibuilder.Builder),
	"parallels-iso":       new(parallelsisobuilder.Builder),
	"parallels-pvm":       new(parallelspvmbuilder.Builder),
	"profitbricks":        new(profitbricksbuilder.Builder),
	"qemu":                new(qemubuilder.Builder),
	"triton":              new(tritonbuilder.Builder),
	"virtualbox-iso":      new(virtualboxisobuilder.Builder),
	"virtualbox-ovf":      new(virtualboxovfbuilder.Builder),
	"vmware-iso":          new(vmwareisobuilder.Builder),
	"vmware-vmx":          new(vmwarevmxbuilder.Builder),
}

var Provisioners = map[string]packer.Provisioner{
	"ansible":           new(ansibleprovisioner.Provisioner),
	"ansible-local":     new(ansiblelocalprovisioner.Provisioner),
	"chef-client":       new(chefclientprovisioner.Provisioner),
	"chef-solo":         new(chefsoloprovisioner.Provisioner),
	"converge":          new(convergeprovisioner.Provisioner),
	"file":              new(fileprovisioner.Provisioner),
	"powershell":        new(powershellprovisioner.Provisioner),
	"puppet-masterless": new(puppetmasterlessprovisioner.Provisioner),
	"puppet-server":     new(puppetserverprovisioner.Provisioner),
	"salt-masterless":   new(saltmasterlessprovisioner.Provisioner),
	"shell":             new(shellprovisioner.Provisioner),
	"shell-local":       new(shelllocalprovisioner.Provisioner),
	"windows-restart":   new(windowsrestartprovisioner.Provisioner),
	"windows-shell":     new(windowsshellprovisioner.Provisioner),
}

var PostProcessors = map[string]packer.PostProcessor{
	"alicloud-import":      new(alicloudimportpostprocessor.PostProcessor),
	"amazon-import":        new(amazonimportpostprocessor.PostProcessor),
	"artifice":             new(artificepostprocessor.PostProcessor),
	"atlas":                new(atlaspostprocessor.PostProcessor),
	"checksum":             new(checksumpostprocessor.PostProcessor),
	"compress":             new(compresspostprocessor.PostProcessor),
	"docker-import":        new(dockerimportpostprocessor.PostProcessor),
	"docker-push":          new(dockerpushpostprocessor.PostProcessor),
	"docker-save":          new(dockersavepostprocessor.PostProcessor),
	"docker-tag":           new(dockertagpostprocessor.PostProcessor),
	"googlecompute-export": new(googlecomputeexportpostprocessor.PostProcessor),
	"manifest":             new(manifestpostprocessor.PostProcessor),
	"shell-local":          new(shelllocalpostprocessor.PostProcessor),
	"vagrant":              new(vagrantpostprocessor.PostProcessor),
	"vagrant-cloud":        new(vagrantcloudpostprocessor.PostProcessor),
	"vsphere":              new(vspherepostprocessor.PostProcessor),
	"vsphere-template":     new(vspheretemplatepostprocessor.PostProcessor),
}

var pluginRegexp = regexp.MustCompile("packer-(builder|post-processor|provisioner)-(.+)")

func (c *PluginCommand) Run(args []string) int {
	// This is an internal call (users should not call this directly) so we're
	// not going to do much input validation. If there's a problem we'll often
	// just crash. Error handling should be added to facilitate debugging.
	log.Printf("args: %#v", args)
	if len(args) != 1 {
		c.Ui.Error("Wrong number of args")
		return 1
	}

	// Plugin will match something like "packer-builder-amazon-ebs"
	parts := pluginRegexp.FindStringSubmatch(args[0])
	if len(parts) != 3 {
		c.Ui.Error(fmt.Sprintf("Error parsing plugin argument [DEBUG]: %#v", parts))
		return 1
	}
	pluginType := parts[1] // capture group 1 (builder|post-processor|provisioner)
	pluginName := parts[2] // capture group 2 (.+)

	server, err := plugin.Server()
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error starting plugin server: %s", err))
		return 1
	}

	switch pluginType {
	case "builder":
		builder, found := Builders[pluginName]
		if !found {
			c.Ui.Error(fmt.Sprintf("Could not load builder: %s", pluginName))
			return 1
		}
		server.RegisterBuilder(builder)
	case "provisioner":
		provisioner, found := Provisioners[pluginName]
		if !found {
			c.Ui.Error(fmt.Sprintf("Could not load provisioner: %s", pluginName))
			return 1
		}
		server.RegisterProvisioner(provisioner)
	case "post-processor":
		postProcessor, found := PostProcessors[pluginName]
		if !found {
			c.Ui.Error(fmt.Sprintf("Could not load post-processor: %s", pluginName))
			return 1
		}
		server.RegisterPostProcessor(postProcessor)
	}

	server.Serve()

	return 0
}

func (*PluginCommand) Help() string {
	helpText := `
Usage: packer plugin PLUGIN

  Runs an internally-compiled version of a plugin from the packer binary.

  NOTE: this is an internal command and you should not call it yourself.
`

	return strings.TrimSpace(helpText)
}

func (c *PluginCommand) Synopsis() string {
	return "internal plugin command"
}
<|endoftext|>


<commit_before>// Package buffer provides unbounded, file-backed byte buffers.
package buffer

import (
	"errors"
	"io"
	"io/ioutil"
	"os"
)

// ErrBadAddress is returned if an operation is given an out-of-range address.
var ErrBadAddress = errors.New("invalid address")

// A Buffer is an unbounded byte buffer backed by a file.
type Buffer struct {
	// F is the file that backs the buffer.
	// It is created lazily.
	f *os.File
	// BlockSize is the maximum number of bytes in a block.
	blockSize int
	// Blocks contains all blocks of the Buffer in order.
	// Free contains blocks that are free to be re-allocated.
	blocks, free []block
	// End is the byte offset of the end of the backing file.
	end int64

	// Cache is the index of the block whose data is currently cached.
	cached int
	// Cache is the cached data.
	cache []byte
	// Dirty tracks whether the cached data has changed since it was read.
	dirty bool

	// Size is the size of the buffer.
	size int64
}

// A block describes a portion of the buffer and its location in the backing file.
type block struct {
	// Start is the byte offset of the block in the file.
	start int64
	// N is the number of bytes in the block.
	n int
}

// New returns a new, empty Buffer.
// No more than blockSize bytes are cached in memory.
func New(blockSize int) *Buffer {
	return &Buffer{
		blockSize: blockSize,
		cached:    -1,
		cache:     make([]byte, blockSize),
	}
}

// Close closes the Buffer and it's backing file.
func (b *Buffer) Close() error {
	b.cache = nil
	if b.f == nil {
		return nil
	}
	path := b.f.Name()
	if err := b.f.Close(); err != nil {
		return err
	}
	return os.Remove(path)
}

// Size returns the size of the Buffer in bytes.
func (b *Buffer) Size() int64 {
	return b.size
}

// ReadAt reads bytes from the Buffer starting at the address.
// The return value is the number of bytes read.
// If fewer than len(bs) bytes are read then the error states why.
// If the address is beyond the end of the Buffer, 0 and io.EOF are returned.
func (b *Buffer) ReadAt(bs []byte, q int64) (int, error) {
	switch {
	case q < 0:
		return 0, ErrBadAddress
	case q >= b.Size():
		return 0, io.EOF
	}
	var n int
	for len(bs) > 0 {
		if q == b.Size() {
			return n, io.EOF
		}
		i, q0 := b.blockAt(q)
		blk, err := b.get(i)
		if err != nil {
			return n, err
		}
		o := q - q0
		m := copy(bs, b.cache[o:blk.n])
		bs = bs[m:]
		q += int64(m)
		n += m
	}
	return n, nil
}

// Insert adds the bytes to the address in the Buffer.
// After adding, the byte at the address is the first of the added bytes.
// The return value is the number of bytes added and any error that was encountered.
// It is an error to add at a negative address or an address that is greater than the Buffer size.
func (b *Buffer) Insert(bs []byte, q int64) (int, error) {
	if q < 0 || q > b.Size() {
		return 0, ErrBadAddress
	}
	var n int
	for len(bs) > 0 {
		i, q0 := b.blockAt(q)
		blk, err := b.get(i)
		if err != nil {
			return n, err
		}
		m := b.blockSize - blk.n
		if m == 0 {
			if i, err = b.insertAt(q); err != nil {
				return n, err
			}
			if blk, err = b.get(i); err != nil {
				return n, err
			}
			q0 = q
			m = b.blockSize
		}
		if m > len(bs) {
			m = len(bs)
		}
		o := q - q0
		copy(b.cache[o+int64(m):], b.cache[o:blk.n])
		copy(b.cache[o:], bs[:m])
		b.dirty = true
		bs = bs[m:]
		blk.n += m
		b.size += int64(m)
		q += int64(m)
		n += m
	}
	return n, nil
}

func (b *Buffer) allocBlock() block {
	if l := len(b.free); l > 0 {
		blk := b.free[l-1]
		b.free = b.free[:l-1]
		return blk
	}
	blk := block{start: b.end}
	b.end += int64(b.blockSize)
	return blk
}

func (b *Buffer) freeBlock(blk block) {
	b.free = append(b.free, blk)
}

// BlockAt returns the index and start address of the block containing the address.
// If the address is one beyond the end of the file, a new block is allocated.
// BlockAt panics if the address is negative or more than one past the end.
func (b *Buffer) blockAt(q int64) (int, int64) {
	if q < 0 || q > b.Size() {
		panic(ErrBadAddress)
	}
	if q == b.Size() {
		i := len(b.blocks)
		blk := b.allocBlock()
		b.blocks = append(b.blocks[:i], append([]block{blk}, b.blocks[i:]...)...)
		return i, q
	}
	var q0 int64
	for i, blk := range b.blocks {
		if q0 <= q && q < q0+int64(blk.n) {
			return i, q0
		}
		q0 += int64(blk.n)
	}
	panic("impossible")
}

// insertAt inserts a block at the address and returns the new block's index.
// If a block contains the address then it is split.
func (b *Buffer) insertAt(q int64) (int, error) {
	i, q0 := b.blockAt(q)
	o := q - q0
	blk := b.blocks[i]
	if q == q0 {
		// Adding immediately before blk, no need to split.
		nblk := b.allocBlock()
		b.blocks = append(b.blocks[:i], append([]block{nblk}, b.blocks[i:]...)...)
		if b.cached == i {
			b.cached = i + 1
		}
		return i, nil
	}

	// Splitting blk.
	// Make sure it's both on disk and in the cache.
	if b.cached == i && b.dirty {
		if err := b.put(); err != nil {
			return -1, err
		}
	} else if _, err := b.get(i); err != nil {
		return -1, err
	}

	// Resize blk.
	b.blocks[i].n = int(o)

	// Insert the new, empty block.
	nblk := b.allocBlock()
	b.blocks = append(b.blocks[:i+1], append([]block{nblk}, b.blocks[i+1:]...)...)

	// Allocate a block for the second half of blk and set it as the cache.
	// The next put will write it out.
	nblk = b.allocBlock()
	b.blocks = append(b.blocks[:i+2], append([]block{nblk}, b.blocks[i+2:]...)...)
	b.blocks[i+2].n = int(int64(blk.n) - o)
	copy(b.cache, b.cache[o:])
	b.cached = i + 2
	b.dirty = true

	return i + 1, nil
}

// File returns an *os.File, creating a new file if one is not created yet.
func (b *Buffer) file() (*os.File, error) {
	if b.f == nil {
		f, err := ioutil.TempFile(os.TempDir(), "edit")
		if err != nil {
			return nil, err
		}
		b.f = f
	}
	return b.f, nil
}

// Put writes the cached block back to the file.
func (b *Buffer) put() error {
	if b.cached < 0 || !b.dirty || len(b.cache) == 0 {
		return nil
	}
	blk := b.blocks[b.cached]
	f, err := b.file()
	if err != nil {
		return err
	}
	if _, err := f.WriteAt(b.cache[:blk.n], blk.start); err != nil {
		return err
	}
	b.dirty = false
	return nil
}

// Get loads the cache with the data from the block at the given index,
// returning a pointer to it.
func (b *Buffer) get(i int) (*block, error) {
	if b.cached == i {
		return &b.blocks[i], nil
	}
	if err := b.put(); err != nil {
		return nil, err
	}

	blk := b.blocks[i]
	f, err := b.file()
	if err != nil {
		return nil, err
	}
	if _, err := f.ReadAt(b.cache[:blk.n], blk.start); err != nil {
		if err == io.EOF {
			panic("unexpected EOF")
		}
		return nil, err
	}
	b.cached = i
	b.dirty = false
	return &b.blocks[i], nil
}
<commit_msg>Rename local byte counts from n to tot.<commit_after>// Package buffer provides unbounded, file-backed byte buffers.
package buffer

import (
	"errors"
	"io"
	"io/ioutil"
	"os"
)

// ErrBadAddress is returned if an operation is given an out-of-range address.
var ErrBadAddress = errors.New("invalid address")

// A Buffer is an unbounded byte buffer backed by a file.
type Buffer struct {
	// F is the file that backs the buffer.
	// It is created lazily.
	f *os.File
	// BlockSize is the maximum number of bytes in a block.
	blockSize int
	// Blocks contains all blocks of the Buffer in order.
	// Free contains blocks that are free to be re-allocated.
	blocks, free []block
	// End is the byte offset of the end of the backing file.
	end int64

	// Cache is the index of the block whose data is currently cached.
	cached int
	// Cache is the cached data.
	cache []byte
	// Dirty tracks whether the cached data has changed since it was read.
	dirty bool

	// Size is the size of the buffer.
	size int64
}

// A block describes a portion of the buffer and its location in the backing file.
type block struct {
	// Start is the byte offset of the block in the file.
	start int64
	// N is the number of bytes in the block.
	n int
}

// New returns a new, empty Buffer.
// No more than blockSize bytes are cached in memory.
func New(blockSize int) *Buffer {
	return &Buffer{
		blockSize: blockSize,
		cached:    -1,
		cache:     make([]byte, blockSize),
	}
}

// Close closes the Buffer and it's backing file.
func (b *Buffer) Close() error {
	b.cache = nil
	if b.f == nil {
		return nil
	}
	path := b.f.Name()
	if err := b.f.Close(); err != nil {
		return err
	}
	return os.Remove(path)
}

// Size returns the size of the Buffer in bytes.
func (b *Buffer) Size() int64 {
	return b.size
}

// ReadAt reads bytes from the Buffer starting at the address.
// The return value is the number of bytes read.
// If fewer than len(bs) bytes are read then the error states why.
// If the address is beyond the end of the Buffer, 0 and io.EOF are returned.
func (b *Buffer) ReadAt(bs []byte, q int64) (int, error) {
	switch {
	case q < 0:
		return 0, ErrBadAddress
	case q >= b.Size():
		return 0, io.EOF
	}
	var tot int
	for len(bs) > 0 {
		if q == b.Size() {
			return tot, io.EOF
		}
		i, q0 := b.blockAt(q)
		blk, err := b.get(i)
		if err != nil {
			return tot, err
		}
		o := q - q0
		m := copy(bs, b.cache[o:blk.n])
		bs = bs[m:]
		q += int64(m)
		tot += m
	}
	return tot, nil
}

// Insert adds the bytes to the address in the Buffer.
// After adding, the byte at the address is the first of the added bytes.
// The return value is the number of bytes added and any error that was encountered.
// It is an error to add at a negative address or an address that is greater than the Buffer size.
func (b *Buffer) Insert(bs []byte, q int64) (int, error) {
	if q < 0 || q > b.Size() {
		return 0, ErrBadAddress
	}
	var tot int
	for len(bs) > 0 {
		i, q0 := b.blockAt(q)
		blk, err := b.get(i)
		if err != nil {
			return tot, err
		}
		m := b.blockSize - blk.n
		if m == 0 {
			if i, err = b.insertAt(q); err != nil {
				return tot, err
			}
			if blk, err = b.get(i); err != nil {
				return tot, err
			}
			q0 = q
			m = b.blockSize
		}
		if m > len(bs) {
			m = len(bs)
		}
		o := q - q0
		copy(b.cache[o+int64(m):], b.cache[o:blk.n])
		copy(b.cache[o:], bs[:m])
		b.dirty = true
		bs = bs[m:]
		blk.n += m
		b.size += int64(m)
		q += int64(m)
		tot += m
	}
	return tot, nil
}

func (b *Buffer) allocBlock() block {
	if l := len(b.free); l > 0 {
		blk := b.free[l-1]
		b.free = b.free[:l-1]
		return blk
	}
	blk := block{start: b.end}
	b.end += int64(b.blockSize)
	return blk
}

func (b *Buffer) freeBlock(blk block) {
	b.free = append(b.free, blk)
}

// BlockAt returns the index and start address of the block containing the address.
// If the address is one beyond the end of the file, a new block is allocated.
// BlockAt panics if the address is negative or more than one past the end.
func (b *Buffer) blockAt(q int64) (int, int64) {
	if q < 0 || q > b.Size() {
		panic(ErrBadAddress)
	}
	if q == b.Size() {
		i := len(b.blocks)
		blk := b.allocBlock()
		b.blocks = append(b.blocks[:i], append([]block{blk}, b.blocks[i:]...)...)
		return i, q
	}
	var q0 int64
	for i, blk := range b.blocks {
		if q0 <= q && q < q0+int64(blk.n) {
			return i, q0
		}
		q0 += int64(blk.n)
	}
	panic("impossible")
}

// insertAt inserts a block at the address and returns the new block's index.
// If a block contains the address then it is split.
func (b *Buffer) insertAt(q int64) (int, error) {
	i, q0 := b.blockAt(q)
	o := q - q0
	blk := b.blocks[i]
	if q == q0 {
		// Adding immediately before blk, no need to split.
		nblk := b.allocBlock()
		b.blocks = append(b.blocks[:i], append([]block{nblk}, b.blocks[i:]...)...)
		if b.cached == i {
			b.cached = i + 1
		}
		return i, nil
	}

	// Splitting blk.
	// Make sure it's both on disk and in the cache.
	if b.cached == i && b.dirty {
		if err := b.put(); err != nil {
			return -1, err
		}
	} else if _, err := b.get(i); err != nil {
		return -1, err
	}

	// Resize blk.
	b.blocks[i].n = int(o)

	// Insert the new, empty block.
	nblk := b.allocBlock()
	b.blocks = append(b.blocks[:i+1], append([]block{nblk}, b.blocks[i+1:]...)...)

	// Allocate a block for the second half of blk and set it as the cache.
	// The next put will write it out.
	nblk = b.allocBlock()
	b.blocks = append(b.blocks[:i+2], append([]block{nblk}, b.blocks[i+2:]...)...)
	b.blocks[i+2].n = int(int64(blk.n) - o)
	copy(b.cache, b.cache[o:])
	b.cached = i + 2
	b.dirty = true

	return i + 1, nil
}

// File returns an *os.File, creating a new file if one is not created yet.
func (b *Buffer) file() (*os.File, error) {
	if b.f == nil {
		f, err := ioutil.TempFile(os.TempDir(), "edit")
		if err != nil {
			return nil, err
		}
		b.f = f
	}
	return b.f, nil
}

// Put writes the cached block back to the file.
func (b *Buffer) put() error {
	if b.cached < 0 || !b.dirty || len(b.cache) == 0 {
		return nil
	}
	blk := b.blocks[b.cached]
	f, err := b.file()
	if err != nil {
		return err
	}
	if _, err := f.WriteAt(b.cache[:blk.n], blk.start); err != nil {
		return err
	}
	b.dirty = false
	return nil
}

// Get loads the cache with the data from the block at the given index,
// returning a pointer to it.
func (b *Buffer) get(i int) (*block, error) {
	if b.cached == i {
		return &b.blocks[i], nil
	}
	if err := b.put(); err != nil {
		return nil, err
	}

	blk := b.blocks[i]
	f, err := b.file()
	if err != nil {
		return nil, err
	}
	if _, err := f.ReadAt(b.cache[:blk.n], blk.start); err != nil {
		if err == io.EOF {
			panic("unexpected EOF")
		}
		return nil, err
	}
	b.cached = i
	b.dirty = false
	return &b.blocks[i], nil
}
<|endoftext|>


<commit_before>// Package buffer provides unbounded, file-backed byte buffers.
package buffer

import (
	"io"
	"io/ioutil"
	"os"
	"strconv"
)

// An AddressError records an error caused by an out-of-bounds address.
type AddressError int64

func (err AddressError) Error() string {
	return "invalid address: " + strconv.FormatInt(int64(err), 10)
}

// A CountError records an error caused by a negative count.
type CountError int

func (err CountError) Error() string {
	return "invalid count: " + strconv.Itoa(int(err))
}

// A Buffer is an unbounded byte buffer backed by a file.
type Buffer struct {
	// F is the file that backs the buffer.
	// It is created lazily.
	f *os.File
	// BlockSize is the maximum number of bytes in a block.
	blockSize int
	// Blocks contains all blocks of the Buffer in order.
	// Free contains blocks that are free to be re-allocated.
	blocks, free []block
	// End is the byte offset of the end of the backing file.
	end int64

	// Cache is the index of the block whose data is currently cached.
	cached int
	// Cache is the cached data.
	cache []byte
	// Dirty tracks whether the cached data has changed since it was read.
	dirty bool

	// Size is the size of the buffer.
	size int64
}

// A block describes a portion of the buffer and its location in the backing file.
type block struct {
	// Start is the byte offset of the block in the file.
	start int64
	// N is the number of bytes in the block.
	n int
}

// New returns a new, empty Buffer.
// No more than blockSize bytes are cached in memory.
func New(blockSize int) *Buffer {
	return &Buffer{
		blockSize: blockSize,
		cached:    -1,
		cache:     make([]byte, blockSize),
	}
}

// Close closes the Buffer and it's backing file.
func (b *Buffer) Close() error {
	b.cache = nil
	if b.f == nil {
		return nil
	}
	path := b.f.Name()
	if err := b.f.Close(); err != nil {
		return err
	}
	return os.Remove(path)
}

// Size returns the size of the Buffer in bytes.
func (b *Buffer) Size() int64 {
	return b.size
}

// ReadAt reads bytes from the Buffer starting at the address.
// The return value is the number of bytes read.
// If fewer than len(bs) bytes are read then the error states why.
// If the address is beyond the end of the Buffer, 0 and io.EOF are returned.
func (b *Buffer) ReadAt(bs []byte, at int64) (int, error) {
	switch {
	case at < 0:
		return 0, AddressError(at)
	case at >= b.Size():
		return 0, io.EOF
	}
	var tot int
	for len(bs) > 0 {
		if at == b.Size() {
			return tot, io.EOF
		}
		i, q0 := b.blockAt(at)
		blk, err := b.get(i)
		if err != nil {
			return tot, err
		}
		o := int(at - q0)
		m := copy(bs, b.cache[o:blk.n])
		bs = bs[m:]
		at += int64(m)
		tot += m
	}
	return tot, nil
}

// Insert adds the bytes to the address in the Buffer.
// After adding, the byte at the address is the first of the added bytes.
// The return value is the number of bytes added and any error that was encountered.
// It is an error to add at a negative address or an address that is greater than the Buffer size.
func (b *Buffer) Insert(bs []byte, at int64) (int, error) {
	if at < 0 || at > b.Size() {
		return 0, AddressError(at)
	}
	var tot int
	for len(bs) > 0 {
		i, q0 := b.blockAt(at)
		blk, err := b.get(i)
		if err != nil {
			return tot, err
		}
		m := b.blockSize - blk.n
		if m == 0 {
			if i, err = b.insertAt(at); err != nil {
				return tot, err
			}
			if blk, err = b.get(i); err != nil {
				return tot, err
			}
			q0 = at
			m = b.blockSize
		}
		if m > len(bs) {
			m = len(bs)
		}
		o := int(at - q0)
		copy(b.cache[o+m:], b.cache[o:blk.n])
		copy(b.cache[o:], bs[:m])
		b.dirty = true
		bs = bs[m:]
		blk.n += m
		b.size += int64(m)
		at += int64(m)
		tot += m
	}
	return tot, nil
}

// Delete deletes a range of bytes from the Buffer.
// The return value is the number of bytes deleted.
// If fewer than n bytes are deleted, the error states why.
func (b *Buffer) Delete(n, at int64) (int, error) {
	if n < 0 {
		return 0, CountError(n)
	}
	if at < 0 || at+n > b.Size() {
		return 0, AddressError(at)
	}
	var tot int
	for n > 0 {
		i, q0 := b.blockAt(at)
		blk, err := b.get(i)
		if err != nil {
			return tot, err
		}
		o := int(at - q0)
		m := blk.n - o
		if int64(m) > n {
			m = int(n)
		}
		if o == 0 && n >= int64(blk.n) {
			// Remove the entire block.
			b.freeBlock(*blk)
			b.blocks = append(b.blocks[:i], b.blocks[i+1:]...)
			b.cached = -1
		} else {
			// Remove a portion of the block.
			copy(b.cache[o:], b.cache[o+m:])
			b.dirty = true
			blk.n -= m
		}
		n -= int64(m)
		tot += m
		b.size -= int64(m)
	}
	return tot, nil
}

func (b *Buffer) allocBlock() block {
	if l := len(b.free); l > 0 {
		blk := b.free[l-1]
		b.free = b.free[:l-1]
		return blk
	}
	blk := block{start: b.end}
	b.end += int64(b.blockSize)
	return blk
}

func (b *Buffer) freeBlock(blk block) {
	b.free = append(b.free, block{start: blk.start})
}

// BlockAt returns the index and start address of the block containing the address.
// If the address is one beyond the end of the file, a new block is allocated.
// BlockAt panics if the address is negative or more than one past the end.
func (b *Buffer) blockAt(at int64) (int, int64) {
	if at < 0 || at > b.Size() {
		panic(AddressError(at))
	}
	if at == b.Size() {
		i := len(b.blocks)
		blk := b.allocBlock()
		b.blocks = append(b.blocks[:i], append([]block{blk}, b.blocks[i:]...)...)
		return i, at
	}
	var q0 int64
	for i, blk := range b.blocks {
		if q0 <= at && at < q0+int64(blk.n) {
			return i, q0
		}
		q0 += int64(blk.n)
	}
	panic("impossible")
}

// insertAt inserts a block at the address and returns the new block's index.
// If a block contains the address then it is split.
func (b *Buffer) insertAt(at int64) (int, error) {
	i, q0 := b.blockAt(at)
	o := int(at - q0)
	blk := b.blocks[i]
	if at == q0 {
		// Adding immediately before blk, no need to split.
		nblk := b.allocBlock()
		b.blocks = append(b.blocks[:i], append([]block{nblk}, b.blocks[i:]...)...)
		if b.cached == i {
			b.cached = i + 1
		}
		return i, nil
	}

	// Splitting blk.
	// Make sure it's both on disk and in the cache.
	if b.cached == i && b.dirty {
		if err := b.put(); err != nil {
			return -1, err
		}
	} else if _, err := b.get(i); err != nil {
		return -1, err
	}

	// Resize blk.
	b.blocks[i].n = int(o)

	// Insert the new, empty block.
	nblk := b.allocBlock()
	b.blocks = append(b.blocks[:i+1], append([]block{nblk}, b.blocks[i+1:]...)...)

	// Allocate a block for the second half of blk and set it as the cache.
	// The next put will write it out.
	nblk = b.allocBlock()
	b.blocks = append(b.blocks[:i+2], append([]block{nblk}, b.blocks[i+2:]...)...)
	b.blocks[i+2].n = blk.n - o
	copy(b.cache, b.cache[o:])
	b.cached = i + 2
	b.dirty = true

	return i + 1, nil
}

// File returns an *os.File, creating a new file if one is not created yet.
func (b *Buffer) file() (*os.File, error) {
	if b.f == nil {
		f, err := ioutil.TempFile(os.TempDir(), "edit")
		if err != nil {
			return nil, err
		}
		b.f = f
	}
	return b.f, nil
}

// Put writes the cached block back to the file.
func (b *Buffer) put() error {
	if b.cached < 0 || !b.dirty || len(b.cache) == 0 {
		return nil
	}
	blk := b.blocks[b.cached]
	f, err := b.file()
	if err != nil {
		return err
	}
	if _, err := f.WriteAt(b.cache[:blk.n], blk.start); err != nil {
		return err
	}
	b.dirty = false
	return nil
}

// Get loads the cache with the data from the block at the given index,
// returning a pointer to it.
func (b *Buffer) get(i int) (*block, error) {
	if b.cached == i {
		return &b.blocks[i], nil
	}
	if err := b.put(); err != nil {
		return nil, err
	}

	blk := b.blocks[i]
	f, err := b.file()
	if err != nil {
		return nil, err
	}
	if _, err := f.ReadAt(b.cache[:blk.n], blk.start); err != nil {
		if err == io.EOF {
			panic("unexpected EOF")
		}
		return nil, err
	}
	b.cached = i
	b.dirty = false
	return &b.blocks[i], nil
}
<commit_msg>Don't return EOF if reading 0 bytes from the end of the buffer.<commit_after>// Package buffer provides unbounded, file-backed byte buffers.
package buffer

import (
	"io"
	"io/ioutil"
	"os"
	"strconv"
)

// An AddressError records an error caused by an out-of-bounds address.
type AddressError int64

func (err AddressError) Error() string {
	return "invalid address: " + strconv.FormatInt(int64(err), 10)
}

// A CountError records an error caused by a negative count.
type CountError int

func (err CountError) Error() string {
	return "invalid count: " + strconv.Itoa(int(err))
}

// A Buffer is an unbounded byte buffer backed by a file.
type Buffer struct {
	// F is the file that backs the buffer.
	// It is created lazily.
	f *os.File
	// BlockSize is the maximum number of bytes in a block.
	blockSize int
	// Blocks contains all blocks of the Buffer in order.
	// Free contains blocks that are free to be re-allocated.
	blocks, free []block
	// End is the byte offset of the end of the backing file.
	end int64

	// Cache is the index of the block whose data is currently cached.
	cached int
	// Cache is the cached data.
	cache []byte
	// Dirty tracks whether the cached data has changed since it was read.
	dirty bool

	// Size is the size of the buffer.
	size int64
}

// A block describes a portion of the buffer and its location in the backing file.
type block struct {
	// Start is the byte offset of the block in the file.
	start int64
	// N is the number of bytes in the block.
	n int
}

// New returns a new, empty Buffer.
// No more than blockSize bytes are cached in memory.
func New(blockSize int) *Buffer {
	return &Buffer{
		blockSize: blockSize,
		cached:    -1,
		cache:     make([]byte, blockSize),
	}
}

// Close closes the Buffer and it's backing file.
func (b *Buffer) Close() error {
	b.cache = nil
	if b.f == nil {
		return nil
	}
	path := b.f.Name()
	if err := b.f.Close(); err != nil {
		return err
	}
	return os.Remove(path)
}

// Size returns the size of the Buffer in bytes.
func (b *Buffer) Size() int64 {
	return b.size
}

// ReadAt reads bytes from the Buffer starting at the address.
// The return value is the number of bytes read.
// If fewer than len(bs) bytes are read then the error states why.
// If the address is beyond the end of the Buffer, 0 and io.EOF are returned.
func (b *Buffer) ReadAt(bs []byte, at int64) (int, error) {
	switch {
	case at < 0:
		return 0, AddressError(at)
	case at == b.Size() && len(bs) == 0:
		return 0, nil
	case at >= b.Size():
		return 0, io.EOF
	}
	var tot int
	for len(bs) > 0 {
		if at == b.Size() {
			return tot, io.EOF
		}
		i, q0 := b.blockAt(at)
		blk, err := b.get(i)
		if err != nil {
			return tot, err
		}
		o := int(at - q0)
		m := copy(bs, b.cache[o:blk.n])
		bs = bs[m:]
		at += int64(m)
		tot += m
	}
	return tot, nil
}

// Insert adds the bytes to the address in the Buffer.
// After adding, the byte at the address is the first of the added bytes.
// The return value is the number of bytes added and any error that was encountered.
// It is an error to add at a negative address or an address that is greater than the Buffer size.
func (b *Buffer) Insert(bs []byte, at int64) (int, error) {
	if at < 0 || at > b.Size() {
		return 0, AddressError(at)
	}
	var tot int
	for len(bs) > 0 {
		i, q0 := b.blockAt(at)
		blk, err := b.get(i)
		if err != nil {
			return tot, err
		}
		m := b.blockSize - blk.n
		if m == 0 {
			if i, err = b.insertAt(at); err != nil {
				return tot, err
			}
			if blk, err = b.get(i); err != nil {
				return tot, err
			}
			q0 = at
			m = b.blockSize
		}
		if m > len(bs) {
			m = len(bs)
		}
		o := int(at - q0)
		copy(b.cache[o+m:], b.cache[o:blk.n])
		copy(b.cache[o:], bs[:m])
		b.dirty = true
		bs = bs[m:]
		blk.n += m
		b.size += int64(m)
		at += int64(m)
		tot += m
	}
	return tot, nil
}

// Delete deletes a range of bytes from the Buffer.
// The return value is the number of bytes deleted.
// If fewer than n bytes are deleted, the error states why.
func (b *Buffer) Delete(n, at int64) (int, error) {
	if n < 0 {
		return 0, CountError(n)
	}
	if at < 0 || at+n > b.Size() {
		return 0, AddressError(at)
	}
	var tot int
	for n > 0 {
		i, q0 := b.blockAt(at)
		blk, err := b.get(i)
		if err != nil {
			return tot, err
		}
		o := int(at - q0)
		m := blk.n - o
		if int64(m) > n {
			m = int(n)
		}
		if o == 0 && n >= int64(blk.n) {
			// Remove the entire block.
			b.freeBlock(*blk)
			b.blocks = append(b.blocks[:i], b.blocks[i+1:]...)
			b.cached = -1
		} else {
			// Remove a portion of the block.
			copy(b.cache[o:], b.cache[o+m:])
			b.dirty = true
			blk.n -= m
		}
		n -= int64(m)
		tot += m
		b.size -= int64(m)
	}
	return tot, nil
}

func (b *Buffer) allocBlock() block {
	if l := len(b.free); l > 0 {
		blk := b.free[l-1]
		b.free = b.free[:l-1]
		return blk
	}
	blk := block{start: b.end}
	b.end += int64(b.blockSize)
	return blk
}

func (b *Buffer) freeBlock(blk block) {
	b.free = append(b.free, block{start: blk.start})
}

// BlockAt returns the index and start address of the block containing the address.
// If the address is one beyond the end of the file, a new block is allocated.
// BlockAt panics if the address is negative or more than one past the end.
func (b *Buffer) blockAt(at int64) (int, int64) {
	if at < 0 || at > b.Size() {
		panic(AddressError(at))
	}
	if at == b.Size() {
		i := len(b.blocks)
		blk := b.allocBlock()
		b.blocks = append(b.blocks[:i], append([]block{blk}, b.blocks[i:]...)...)
		return i, at
	}
	var q0 int64
	for i, blk := range b.blocks {
		if q0 <= at && at < q0+int64(blk.n) {
			return i, q0
		}
		q0 += int64(blk.n)
	}
	panic("impossible")
}

// insertAt inserts a block at the address and returns the new block's index.
// If a block contains the address then it is split.
func (b *Buffer) insertAt(at int64) (int, error) {
	i, q0 := b.blockAt(at)
	o := int(at - q0)
	blk := b.blocks[i]
	if at == q0 {
		// Adding immediately before blk, no need to split.
		nblk := b.allocBlock()
		b.blocks = append(b.blocks[:i], append([]block{nblk}, b.blocks[i:]...)...)
		if b.cached == i {
			b.cached = i + 1
		}
		return i, nil
	}

	// Splitting blk.
	// Make sure it's both on disk and in the cache.
	if b.cached == i && b.dirty {
		if err := b.put(); err != nil {
			return -1, err
		}
	} else if _, err := b.get(i); err != nil {
		return -1, err
	}

	// Resize blk.
	b.blocks[i].n = int(o)

	// Insert the new, empty block.
	nblk := b.allocBlock()
	b.blocks = append(b.blocks[:i+1], append([]block{nblk}, b.blocks[i+1:]...)...)

	// Allocate a block for the second half of blk and set it as the cache.
	// The next put will write it out.
	nblk = b.allocBlock()
	b.blocks = append(b.blocks[:i+2], append([]block{nblk}, b.blocks[i+2:]...)...)
	b.blocks[i+2].n = blk.n - o
	copy(b.cache, b.cache[o:])
	b.cached = i + 2
	b.dirty = true

	return i + 1, nil
}

// File returns an *os.File, creating a new file if one is not created yet.
func (b *Buffer) file() (*os.File, error) {
	if b.f == nil {
		f, err := ioutil.TempFile(os.TempDir(), "edit")
		if err != nil {
			return nil, err
		}
		b.f = f
	}
	return b.f, nil
}

// Put writes the cached block back to the file.
func (b *Buffer) put() error {
	if b.cached < 0 || !b.dirty || len(b.cache) == 0 {
		return nil
	}
	blk := b.blocks[b.cached]
	f, err := b.file()
	if err != nil {
		return err
	}
	if _, err := f.WriteAt(b.cache[:blk.n], blk.start); err != nil {
		return err
	}
	b.dirty = false
	return nil
}

// Get loads the cache with the data from the block at the given index,
// returning a pointer to it.
func (b *Buffer) get(i int) (*block, error) {
	if b.cached == i {
		return &b.blocks[i], nil
	}
	if err := b.put(); err != nil {
		return nil, err
	}

	blk := b.blocks[i]
	f, err := b.file()
	if err != nil {
		return nil, err
	}
	if _, err := f.ReadAt(b.cache[:blk.n], blk.start); err != nil {
		if err == io.EOF {
			panic("unexpected EOF")
		}
		return nil, err
	}
	b.cached = i
	b.dirty = false
	return &b.blocks[i], nil
}
<|endoftext|>


<commit_before>package isogram

import (
	"strings"
	"unicode"
)

// IsIsogram returns whether the provided string is an isogram.
// In other words, whether the string does not contain any duplicate characters.
func IsIsogram(s string) bool {
	parsed := strings.ToLower(preserveOnlyLetters(s))
	seen := make(map[rune]bool)
	for _, c := range parsed {
		if (seen[c]) == true {
			return false
		}
		seen[c] = true
	}
	return true
}

func preserveOnlyLetters(s string) string {
	return strings.Map(func(r rune) rune {
		if unicode.IsLetter(r) {
			return r
		}
		return -1
	}, s)
}
<commit_msg>Extract does contain unique letters<commit_after>package isogram

import (
	"strings"
	"unicode"
)

// IsIsogram returns whether the provided string is an isogram.
// In other words, whether the string does not contain any duplicate characters.
func IsIsogram(s string) bool {
	parsed := strings.ToLower(preserveOnlyLetters(s))
	return doesContainUniqueLetters(parsed)
}

func preserveOnlyLetters(s string) string {
	return strings.Map(func(r rune) rune {
		if unicode.IsLetter(r) {
			return r
		}
		return -1
	}, s)
}

func doesContainUniqueLetters(s string) bool {
	seen := make(map[rune]bool)

	for _, c := range s {
		if (seen[c]) == true {
			return false
		}
		seen[c] = true
	}
	return true
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package goapp

import (
	"bytes"
	"code.google.com/p/go.net/html"
	"code.google.com/p/go.net/html/atom"
	"errors"
	"io"
)

var ErrNoRssLink = errors.New("No rss link found")

func Autodiscover(b []byte) (string, error) {
	r := bytes.NewReader(b)
	z := html.NewTokenizer(r)
	inHtml := false
	inHead := false
	for {
		if z.Next() == html.ErrorToken {
			if err := z.Err(); err == io.EOF {
				break
			} else {
				return "", ErrNoRssLink
			}
		}
		t := z.Token()
		switch t.DataAtom {
		case atom.Html:
			inHtml = !inHtml
		case atom.Head:
			inHead = !inHead
		case atom.Link:
			if inHead && inHtml && (t.Type == html.StartTagToken || t.Type == html.SelfClosingTagToken) {
				attrs := make(map[string]string)
				for _, a := range t.Attr {
					attrs[a.Key] = a.Val
				}
				if attrs["rel"] == "alternate" && attrs["type"] == "application/rss+xml" && attrs["href"] != "" {
					return attrs["href"], nil
				}
			}
		}
	}

	return "", ErrNoRssLink
}
<commit_msg>Support atom+rss for autodiscover<commit_after>/*
 * Copyright (c) 2013 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package goapp

import (
	"bytes"
	"code.google.com/p/go.net/html"
	"code.google.com/p/go.net/html/atom"
	"errors"
	"io"
)

var ErrNoRssLink = errors.New("No rss link found")

func Autodiscover(b []byte) (string, error) {
	r := bytes.NewReader(b)
	z := html.NewTokenizer(r)
	inHtml := false
	inHead := false
	for {
		if z.Next() == html.ErrorToken {
			if err := z.Err(); err == io.EOF {
				break
			} else {
				return "", ErrNoRssLink
			}
		}
		t := z.Token()
		switch t.DataAtom {
		case atom.Html:
			inHtml = !inHtml
		case atom.Head:
			inHead = !inHead
		case atom.Link:
			if inHead && inHtml && (t.Type == html.StartTagToken || t.Type == html.SelfClosingTagToken) {
				attrs := make(map[string]string)
				for _, a := range t.Attr {
					attrs[a.Key] = a.Val
				}
				if attrs["rel"] == "alternate" && attrs["href"] != "" &&
					(attrs["type"] == "application/rss+xml" || attrs["type"] == "application/atom+xml") {
					return attrs["href"], nil
				}
			}
		}
	}

	return "", ErrNoRssLink
}
<|endoftext|>


<commit_before>package gocbcore

const (
	GoCbVersionStr = "v1.0.5"
)

type CommandMagic uint8

const (
	ReqMagic = CommandMagic(0x80)
	ResMagic = CommandMagic(0x81)
)

// CommandCode for memcached packets.
type CommandCode uint8

const (
	CmdGet                  = CommandCode(0x00)
	CmdSet                  = CommandCode(0x01)
	CmdAdd                  = CommandCode(0x02)
	CmdReplace              = CommandCode(0x03)
	CmdDelete               = CommandCode(0x04)
	CmdIncrement            = CommandCode(0x05)
	CmdDecrement            = CommandCode(0x06)
	CmdAppend               = CommandCode(0x0e)
	CmdPrepend              = CommandCode(0x0f)
	CmdStat                 = CommandCode(0x10)
	CmdTouch                = CommandCode(0x1c)
	CmdGAT                  = CommandCode(0x1d)
	CmdHello                = CommandCode(0x1f)
	CmdSASLListMechs        = CommandCode(0x20)
	CmdSASLAuth             = CommandCode(0x21)
	CmdSASLStep             = CommandCode(0x22)
	CmdGetAllVBSeqnos       = CommandCode(0x48)
	CmdDcpOpenConnection    = CommandCode(0x50)
	CmdDcpAddStream         = CommandCode(0x51)
	CmdDcpCloseStream       = CommandCode(0x52)
	CmdDcpStreamReq         = CommandCode(0x53)
	CmdDcpGetFailoverLog    = CommandCode(0x54)
	CmdDcpStreamEnd         = CommandCode(0x55)
	CmdDcpSnapshotMarker    = CommandCode(0x56)
	CmdDcpMutation          = CommandCode(0x57)
	CmdDcpDeletion          = CommandCode(0x58)
	CmdDcpExpiration        = CommandCode(0x59)
	CmdDcpFlush             = CommandCode(0x5a)
	CmdDcpSetVbucketState   = CommandCode(0x5b)
	CmdDcpNoop              = CommandCode(0x5c)
	CmdDcpBufferAck         = CommandCode(0x5d)
	CmdDcpControl           = CommandCode(0x5e)
	CmdGetReplica           = CommandCode(0x83)
	CmdSelectBucket         = CommandCode(0x89)
	CmdObserveSeqNo         = CommandCode(0x91)
	CmdObserve              = CommandCode(0x92)
	CmdGetLocked            = CommandCode(0x94)
	CmdUnlockKey            = CommandCode(0x95)
	CmdSetMeta              = CommandCode(0xa2)
	CmdDetMeta              = CommandCode(0xa8)
	CmdGetClusterConfig     = CommandCode(0xb5)
	CmdGetRandom            = CommandCode(0xb6)
	CmdSubDocGet            = CommandCode(0xc5)
	CmdSubDocExists         = CommandCode(0xc6)
	CmdSubDocDictAdd        = CommandCode(0xc7)
	CmdSubDocDictSet        = CommandCode(0xc8)
	CmdSubDocDelete         = CommandCode(0xc9)
	CmdSubDocReplace        = CommandCode(0xca)
	CmdSubDocArrayPushLast  = CommandCode(0xcb)
	CmdSubDocArrayPushFirst = CommandCode(0xcc)
	CmdSubDocArrayInsert    = CommandCode(0xcd)
	CmdSubDocArrayAddUnique = CommandCode(0xce)
	CmdSubDocCounter        = CommandCode(0xcf)
	CmdSubDocMultiLookup    = CommandCode(0xd0)
	CmdSubDocMultiMutation  = CommandCode(0xd1)
)

type SubDocFlag uint16

const (
	SubDocFlagMkDirP = SubDocFlag(0x00)
)

type SubDocOpType uint8

const (
	SubDocOpGet            = SubDocOpType(CmdSubDocGet)
	SubDocOpExists         = SubDocOpType(CmdSubDocExists)
	SubDocOpDictAdd        = SubDocOpType(CmdSubDocDictAdd)
	SubDocOpDictSet        = SubDocOpType(CmdSubDocDictSet)
	SubDocOpDelete         = SubDocOpType(CmdSubDocDelete)
	SubDocOpReplace        = SubDocOpType(CmdSubDocReplace)
	SubDocOpArrayPushLast  = SubDocOpType(CmdSubDocArrayPushLast)
	SubDocOpArrayPushFirst = SubDocOpType(CmdSubDocArrayPushFirst)
	SubDocOpArrayInsert    = SubDocOpType(CmdSubDocArrayInsert)
	SubDocOpArrayAddUnique = SubDocOpType(CmdSubDocArrayAddUnique)
	SubDocOpCounter        = SubDocOpType(CmdSubDocCounter)
)

type HelloFeature uint16

const (
	FeatureDatatype = HelloFeature(0x01)
	FeatureSeqNo    = HelloFeature(0x04)
)

// Status field for memcached response.
type StatusCode uint16

const (
	StatusSuccess            = StatusCode(0x00)
	StatusKeyNotFound        = StatusCode(0x01)
	StatusKeyExists          = StatusCode(0x02)
	StatusTooBig             = StatusCode(0x03)
	StatusInvalidArgs        = StatusCode(0x04)
	StatusNotStored          = StatusCode(0x05)
	StatusBadDelta           = StatusCode(0x06)
	StatusNotMyVBucket       = StatusCode(0x07)
	StatusNoBucket           = StatusCode(0x08)
	StatusAuthStale          = StatusCode(0x1f)
	StatusAuthError          = StatusCode(0x20)
	StatusAuthContinue       = StatusCode(0x21)
	StatusRangeError         = StatusCode(0x22)
	StatusRollback           = StatusCode(0x23)
	StatusAccessError        = StatusCode(0x24)
	StatusNotInitialized     = StatusCode(0x25)
	StatusUnknownCommand     = StatusCode(0x81)
	StatusOutOfMemory        = StatusCode(0x82)
	StatusNotSupported       = StatusCode(0x83)
	StatusInternalError      = StatusCode(0x84)
	StatusBusy               = StatusCode(0x85)
	StatusTmpFail            = StatusCode(0x86)
	StatusSubDocPathNotFound = StatusCode(0xc0)
	StatusSubDocPathMismatch = StatusCode(0xc1)
	StatusSubDocPathInvalid  = StatusCode(0xc2)
	StatusSubDocPathTooBig   = StatusCode(0xc3)
	StatusSubDocDocTooDeep   = StatusCode(0xc4)
	StatusSubDocCantInsert   = StatusCode(0xc5)
	StatusSubDocNotJson      = StatusCode(0xc6)
	StatusSubDocBadRange     = StatusCode(0xc7)
	StatusSubDocBadDelta     = StatusCode(0xc8)
	StatusSubDocPathExists   = StatusCode(0xc9)
	StatusSubDocValueTooDeep = StatusCode(0xca)
	StatusSubDocBadCombo     = StatusCode(0xcb)
	StatusSubDocBadMulti     = StatusCode(0xcc)
)

type KeyState uint8

const (
	KeyStateNotPersisted = KeyState(0x00)
	KeyStatePersisted    = KeyState(0x01)
	KeyStateNotFound     = KeyState(0x80)
	KeyStateDeleted      = KeyState(0x81)
)

type StreamEndStatus uint32

const (
	StreamEndOK           = StreamEndStatus(0x00)
	StreamEndClosed       = StreamEndStatus(0x01)
	StreamEndStateChanged = StreamEndStatus(0x02)
	StreamEndDisconnected = StreamEndStatus(0x03)
	StreamEndTooSlow      = StreamEndStatus(0x04)
)

type BucketType int

const (
	BktTypeInvalid   BucketType = 0
	BktTypeCouchbase            = iota
	BktTypeMemcached            = iota
)

type VBucketState uint32

const (
	VBucketStateActive  = VBucketState(0x01)
	VBucketStateReplica = VBucketState(0x02)
	VBucketStatePending = VBucketState(0x03)
	VBucketStateDead    = VBucketState(0x04)
)
<commit_msg>Release v1.0.6<commit_after>package gocbcore

const (
	GoCbVersionStr = "v1.0.6"
)

type CommandMagic uint8

const (
	ReqMagic = CommandMagic(0x80)
	ResMagic = CommandMagic(0x81)
)

// CommandCode for memcached packets.
type CommandCode uint8

const (
	CmdGet                  = CommandCode(0x00)
	CmdSet                  = CommandCode(0x01)
	CmdAdd                  = CommandCode(0x02)
	CmdReplace              = CommandCode(0x03)
	CmdDelete               = CommandCode(0x04)
	CmdIncrement            = CommandCode(0x05)
	CmdDecrement            = CommandCode(0x06)
	CmdAppend               = CommandCode(0x0e)
	CmdPrepend              = CommandCode(0x0f)
	CmdStat                 = CommandCode(0x10)
	CmdTouch                = CommandCode(0x1c)
	CmdGAT                  = CommandCode(0x1d)
	CmdHello                = CommandCode(0x1f)
	CmdSASLListMechs        = CommandCode(0x20)
	CmdSASLAuth             = CommandCode(0x21)
	CmdSASLStep             = CommandCode(0x22)
	CmdGetAllVBSeqnos       = CommandCode(0x48)
	CmdDcpOpenConnection    = CommandCode(0x50)
	CmdDcpAddStream         = CommandCode(0x51)
	CmdDcpCloseStream       = CommandCode(0x52)
	CmdDcpStreamReq         = CommandCode(0x53)
	CmdDcpGetFailoverLog    = CommandCode(0x54)
	CmdDcpStreamEnd         = CommandCode(0x55)
	CmdDcpSnapshotMarker    = CommandCode(0x56)
	CmdDcpMutation          = CommandCode(0x57)
	CmdDcpDeletion          = CommandCode(0x58)
	CmdDcpExpiration        = CommandCode(0x59)
	CmdDcpFlush             = CommandCode(0x5a)
	CmdDcpSetVbucketState   = CommandCode(0x5b)
	CmdDcpNoop              = CommandCode(0x5c)
	CmdDcpBufferAck         = CommandCode(0x5d)
	CmdDcpControl           = CommandCode(0x5e)
	CmdGetReplica           = CommandCode(0x83)
	CmdSelectBucket         = CommandCode(0x89)
	CmdObserveSeqNo         = CommandCode(0x91)
	CmdObserve              = CommandCode(0x92)
	CmdGetLocked            = CommandCode(0x94)
	CmdUnlockKey            = CommandCode(0x95)
	CmdSetMeta              = CommandCode(0xa2)
	CmdDetMeta              = CommandCode(0xa8)
	CmdGetClusterConfig     = CommandCode(0xb5)
	CmdGetRandom            = CommandCode(0xb6)
	CmdSubDocGet            = CommandCode(0xc5)
	CmdSubDocExists         = CommandCode(0xc6)
	CmdSubDocDictAdd        = CommandCode(0xc7)
	CmdSubDocDictSet        = CommandCode(0xc8)
	CmdSubDocDelete         = CommandCode(0xc9)
	CmdSubDocReplace        = CommandCode(0xca)
	CmdSubDocArrayPushLast  = CommandCode(0xcb)
	CmdSubDocArrayPushFirst = CommandCode(0xcc)
	CmdSubDocArrayInsert    = CommandCode(0xcd)
	CmdSubDocArrayAddUnique = CommandCode(0xce)
	CmdSubDocCounter        = CommandCode(0xcf)
	CmdSubDocMultiLookup    = CommandCode(0xd0)
	CmdSubDocMultiMutation  = CommandCode(0xd1)
)

type SubDocFlag uint16

const (
	SubDocFlagMkDirP = SubDocFlag(0x00)
)

type SubDocOpType uint8

const (
	SubDocOpGet            = SubDocOpType(CmdSubDocGet)
	SubDocOpExists         = SubDocOpType(CmdSubDocExists)
	SubDocOpDictAdd        = SubDocOpType(CmdSubDocDictAdd)
	SubDocOpDictSet        = SubDocOpType(CmdSubDocDictSet)
	SubDocOpDelete         = SubDocOpType(CmdSubDocDelete)
	SubDocOpReplace        = SubDocOpType(CmdSubDocReplace)
	SubDocOpArrayPushLast  = SubDocOpType(CmdSubDocArrayPushLast)
	SubDocOpArrayPushFirst = SubDocOpType(CmdSubDocArrayPushFirst)
	SubDocOpArrayInsert    = SubDocOpType(CmdSubDocArrayInsert)
	SubDocOpArrayAddUnique = SubDocOpType(CmdSubDocArrayAddUnique)
	SubDocOpCounter        = SubDocOpType(CmdSubDocCounter)
)

type HelloFeature uint16

const (
	FeatureDatatype = HelloFeature(0x01)
	FeatureSeqNo    = HelloFeature(0x04)
)

// Status field for memcached response.
type StatusCode uint16

const (
	StatusSuccess            = StatusCode(0x00)
	StatusKeyNotFound        = StatusCode(0x01)
	StatusKeyExists          = StatusCode(0x02)
	StatusTooBig             = StatusCode(0x03)
	StatusInvalidArgs        = StatusCode(0x04)
	StatusNotStored          = StatusCode(0x05)
	StatusBadDelta           = StatusCode(0x06)
	StatusNotMyVBucket       = StatusCode(0x07)
	StatusNoBucket           = StatusCode(0x08)
	StatusAuthStale          = StatusCode(0x1f)
	StatusAuthError          = StatusCode(0x20)
	StatusAuthContinue       = StatusCode(0x21)
	StatusRangeError         = StatusCode(0x22)
	StatusRollback           = StatusCode(0x23)
	StatusAccessError        = StatusCode(0x24)
	StatusNotInitialized     = StatusCode(0x25)
	StatusUnknownCommand     = StatusCode(0x81)
	StatusOutOfMemory        = StatusCode(0x82)
	StatusNotSupported       = StatusCode(0x83)
	StatusInternalError      = StatusCode(0x84)
	StatusBusy               = StatusCode(0x85)
	StatusTmpFail            = StatusCode(0x86)
	StatusSubDocPathNotFound = StatusCode(0xc0)
	StatusSubDocPathMismatch = StatusCode(0xc1)
	StatusSubDocPathInvalid  = StatusCode(0xc2)
	StatusSubDocPathTooBig   = StatusCode(0xc3)
	StatusSubDocDocTooDeep   = StatusCode(0xc4)
	StatusSubDocCantInsert   = StatusCode(0xc5)
	StatusSubDocNotJson      = StatusCode(0xc6)
	StatusSubDocBadRange     = StatusCode(0xc7)
	StatusSubDocBadDelta     = StatusCode(0xc8)
	StatusSubDocPathExists   = StatusCode(0xc9)
	StatusSubDocValueTooDeep = StatusCode(0xca)
	StatusSubDocBadCombo     = StatusCode(0xcb)
	StatusSubDocBadMulti     = StatusCode(0xcc)
)

type KeyState uint8

const (
	KeyStateNotPersisted = KeyState(0x00)
	KeyStatePersisted    = KeyState(0x01)
	KeyStateNotFound     = KeyState(0x80)
	KeyStateDeleted      = KeyState(0x81)
)

type StreamEndStatus uint32

const (
	StreamEndOK           = StreamEndStatus(0x00)
	StreamEndClosed       = StreamEndStatus(0x01)
	StreamEndStateChanged = StreamEndStatus(0x02)
	StreamEndDisconnected = StreamEndStatus(0x03)
	StreamEndTooSlow      = StreamEndStatus(0x04)
)

type BucketType int

const (
	BktTypeInvalid   BucketType = 0
	BktTypeCouchbase            = iota
	BktTypeMemcached            = iota
)

type VBucketState uint32

const (
	VBucketStateActive  = VBucketState(0x01)
	VBucketStateReplica = VBucketState(0x02)
	VBucketStatePending = VBucketState(0x03)
	VBucketStateDead    = VBucketState(0x04)
)
<|endoftext|>


<commit_before>package json

import (
	"encoding/json"
	"fmt"
	"github.com/Shopify/go-lua"
)

func Open(l *lua.State) {
	jsonOpen := func(l *lua.State) int {
		lua.NewLibrary(l, jsonLibrary)
		return 1
	}
	lua.Require(l, "goluago/encoding/json", jsonOpen, false)
	lua.Pop(l, 1)
}

var jsonLibrary = []lua.RegistryFunction{
	{"unmarshal", unmarshal},
}

func unmarshal(l *lua.State) int {
	payload := lua.CheckString(l, 1)

	var output interface{}

	if err := json.Unmarshal([]byte(payload), &output); err != nil {
		lua.Errorf(l, err.Error())
		panic("unreachable")
	}

	var recurseOnArray func([]interface{})

	var recurseOnMap func(map[string]interface{})

	forwardOnType := func(val interface{}) {

		switch val.(type) {
		case nil:
			lua.PushNil(l)

		case bool:
			lua.PushBoolean(l, val.(bool))

		case string:
			lua.PushString(l, val.(string))

		case uint8, uint16, uint32, uint64, uint:
			lua.PushUnsigned(l, val.(uint))

		case int8, int16, int32, int64, int:
			lua.PushInteger(l, val.(int))

		case float32, float64:
			lua.PushNumber(l, val.(float64))

		case []interface{}:
			a := val.([]interface{})
			lua.CreateTable(l, len(a), 0)
			recurseOnArray(a)

		case map[string]interface{}:
			m := val.(map[string]interface{})
			lua.CreateTable(l, 0, len(m))
			recurseOnMap(m)

		default:
			lua.Errorf(l, fmt.Sprintf("unmarshal: payload contains unsupported type: %T", val))
			panic("unreachable")
		}
	}

	recurseOnMap = func(input map[string]interface{}) {
		// -1 is a table
		for key, val := range input {
			lua.PushString(l, key)
			// -1: key, -2: table
			forwardOnType(val)
			// -1: something, -2: key, -3: table
			lua.RawSet(l, -3)
		}
	}

	recurseOnArray = func(input []interface{}) {
		// -1 is a table
		for i, val := range input {
			forwardOnType(val)
			// -1: something, -2: table
			lua.RawSetInt(l, -2, i+1)
		}
	}

	forwardOnType(output)

	return 1
}
<commit_msg>Do a convertion instead of assertions on ints. Grab `val := val.(type)`.<commit_after>package json

import (
	"encoding/json"
	"fmt"
	"github.com/Shopify/go-lua"
)

func Open(l *lua.State) {
	jsonOpen := func(l *lua.State) int {
		lua.NewLibrary(l, jsonLibrary)
		return 1
	}
	lua.Require(l, "goluago/encoding/json", jsonOpen, false)
	lua.Pop(l, 1)
}

var jsonLibrary = []lua.RegistryFunction{
	{"unmarshal", unmarshal},
}

func unmarshal(l *lua.State) int {
	payload := lua.CheckString(l, 1)

	var output interface{}

	if err := json.Unmarshal([]byte(payload), &output); err != nil {
		lua.Errorf(l, err.Error())
		panic("unreachable")
	}

	var recurseOnArray func([]interface{})

	var recurseOnMap func(map[string]interface{})

	forwardOnType := func(val interface{}) {

		switch val := val.(type) {
		case nil:
			lua.PushNil(l)

		case bool:
			lua.PushBoolean(l, val)

		case string:
			lua.PushString(l, val)

		case uint8:
			lua.PushUnsigned(l, uint(val))
		case uint16:
			lua.PushUnsigned(l, uint(val))
		case uint32:
			lua.PushUnsigned(l, uint(val))
		case uint64:
			lua.PushUnsigned(l, uint(val))
		case uint:
			lua.PushUnsigned(l, val)

		case int8:
			lua.PushInteger(l, int(val))
		case int16:
			lua.PushInteger(l, int(val))
		case int32:
			lua.PushInteger(l, int(val))
		case int64:
			lua.PushInteger(l, int(val))
		case int:
			lua.PushInteger(l, val)

		case float32:
			lua.PushNumber(l, float64(val))
		case float64:
			lua.PushNumber(l, float64(val))

		case []interface{}:
			lua.CreateTable(l, len(val), 0)
			recurseOnArray(val)

		case map[string]interface{}:
			lua.CreateTable(l, 0, len(val))
			recurseOnMap(val)

		default:
			lua.Errorf(l, fmt.Sprintf("unmarshal: payload contains unsupported type: %T", val))
			panic("unreachable")
		}
	}

	recurseOnMap = func(input map[string]interface{}) {
		// -1 is a table
		for key, val := range input {
			lua.PushString(l, key)
			// -1: key, -2: table
			forwardOnType(val)
			// -1: something, -2: key, -3: table
			lua.RawSet(l, -3)
		}
	}

	recurseOnArray = func(input []interface{}) {
		// -1 is a table
		for i, val := range input {
			forwardOnType(val)
			// -1: something, -2: table
			lua.RawSetInt(l, -2, i+1)
		}
	}

	forwardOnType(output)

	return 1
}
<|endoftext|>