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

// Package rename contains the implementation of the 'gorename' command
// whose main function is in code.google.com/p/go.tools/refactor/rename.
// See that package for the command documentation.
package rename

import (
	"errors"
	"fmt"
	"go/ast"
	"go/build"
	"go/format"
	"go/parser"
	"go/token"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"code.google.com/p/go.tools/go/loader"
	"code.google.com/p/go.tools/go/types"
	"code.google.com/p/go.tools/refactor/importgraph"
	"code.google.com/p/go.tools/refactor/satisfy"
)

var (
	// Force enables patching of the source files even if conflicts were reported.
	// The resulting program may be ill-formed.
	// It may even cause gorename to crash.  TODO(adonovan): fix that.
	Force bool

	// DryRun causes the tool to report conflicts but not update any files.
	DryRun bool

	// ConflictError is returned by Main when it aborts the renaming due to conflicts.
	// (It is distinguished because the interesting errors are the conflicts themselves.)
	ConflictError = errors.New("renaming aborted due to conflicts")

	// Verbose enables extra logging.
	Verbose bool
)

type renamer struct {
	iprog              *loader.Program
	objsToUpdate       map[types.Object]bool
	hadConflicts       bool
	to                 string
	satisfyConstraints map[satisfy.Constraint]bool
	packages           map[*types.Package]*loader.PackageInfo // subset of iprog.AllPackages to inspect
}

var reportError = func(posn token.Position, message string) {
	fmt.Fprintf(os.Stderr, "%s: %s\n", posn, message)
}

func Main(ctxt *build.Context, offsetFlag, fromFlag, to string) error {
	// -- Parse the -from or -offset specifier ----------------------------

	if (offsetFlag == "") == (fromFlag == "") {
		return fmt.Errorf("exactly one of the -from and -offset flags must be specified")
	}

	if !isValidIdentifier(to) {
		return fmt.Errorf("-to %q: not a valid identifier", to)
	}

	var spec *spec
	var err error
	if fromFlag != "" {
		spec, err = parseFromFlag(ctxt, fromFlag)
	} else {
		spec, err = parseOffsetFlag(ctxt, offsetFlag)
	}
	if err != nil {
		return err
	}

	if spec.fromName == to {
		return fmt.Errorf("the old and new names are the same: %s", to)
	}

	// -- Load the program consisting of the initial package  -------------

	iprog, err := loadProgram(ctxt, map[string]bool{spec.pkg: true})
	if err != nil {
		return err
	}

	fromObjects, err := findFromObjects(iprog, spec)
	if err != nil {
		return err
	}

	// -- Load a larger program, for global renamings ---------------------

	if requiresGlobalRename(fromObjects, to) {
		// For a local refactoring, we needn't load more
		// packages, but if the renaming affects the package's
		// API, we we must load all packages that depend on the
		// package defining the object, plus their tests.

		if Verbose {
			fmt.Fprintln(os.Stderr, "Potentially global renaming; scanning workspace...")
		}

		// Scan the workspace and build the import graph.
		_, rev, errors := importgraph.Build(ctxt)
		if len(errors) > 0 {
			fmt.Fprintf(os.Stderr, "While scanning Go workspace:\n")
			for path, err := range errors {
				fmt.Fprintf(os.Stderr, "Package %q: %s.\n", path, err)
			}
		}

		// Enumerate the set of potentially affected packages.
		affectedPackages := make(map[string]bool)
		for _, obj := range fromObjects {
			// External test packages are never imported,
			// so they will never appear in the graph.
			for path := range rev.Search(obj.Pkg().Path()) {
				affectedPackages[path] = true
			}
		}

		// TODO(adonovan): allow the user to specify the scope,
		// or -ignore patterns?  Computing the scope when we
		// don't (yet) support inputs containing errors can make
		// the tool rather brittle.

		// Re-load the larger program.
		iprog, err = loadProgram(ctxt, affectedPackages)
		if err != nil {
			return err
		}

		fromObjects, err = findFromObjects(iprog, spec)
		if err != nil {
			return err
		}
	}

	// -- Do the renaming -------------------------------------------------

	r := renamer{
		iprog:        iprog,
		objsToUpdate: make(map[types.Object]bool),
		to:           to,
		packages:     make(map[*types.Package]*loader.PackageInfo),
	}

	// Only the initially imported packages (iprog.Imported) and
	// their external tests (iprog.Created) should be inspected or
	// modified, as only they have type-checked functions bodies.
	// The rest are just dependencies, needed only for package-level
	// type information.
	for _, info := range iprog.Imported {
		r.packages[info.Pkg] = info
	}
	for _, info := range iprog.Created { // (tests)
		r.packages[info.Pkg] = info
	}

	for _, from := range fromObjects {
		r.check(from)
	}
	if r.hadConflicts && !Force {
		return ConflictError
	}
	if DryRun {
		// TODO(adonovan): print the delta?
		return nil
	}
	return r.update()
}

// loadProgram loads the specified set of packages (plus their tests)
// and all their dependencies, from source, through the specified build
// context.  Only packages in pkgs will have their functions bodies typechecked.
func loadProgram(ctxt *build.Context, pkgs map[string]bool) (*loader.Program, error) {
	conf := loader.Config{
		Build:         ctxt,
		SourceImports: true,
		ParserMode:    parser.ParseComments,

		// TODO(adonovan): enable this.  Requires making a lot of code more robust!
		AllowErrors: false,
	}

	// Optimization: don't type-check the bodies of functions in our
	// dependencies, since we only need exported package members.
	conf.TypeCheckFuncBodies = func(p string) bool {
		return pkgs[p] || pkgs[strings.TrimSuffix(p, "_test")]
	}

	if Verbose {
		var list []string
		for pkg := range pkgs {
			list = append(list, pkg)
		}
		sort.Strings(list)
		for _, pkg := range list {
			fmt.Fprintf(os.Stderr, "Loading package: %s\n", pkg)
		}
	}

	for pkg := range pkgs {
		if err := conf.ImportWithTests(pkg); err != nil {
			return nil, err
		}
	}
	return conf.Load()
}

// requiresGlobalRename reports whether this renaming could potentially
// affect other packages in the Go workspace.
func requiresGlobalRename(fromObjects []types.Object, to string) bool {
	var tfm bool
	for _, from := range fromObjects {
		if from.Exported() {
			return true
		}
		switch objectKind(from) {
		case "type", "field", "method":
			tfm = true
		}
	}
	if ast.IsExported(to) && tfm {
		// A global renaming may be necessary even if we're
		// exporting a previous unexported name, since if it's
		// the name of a type, field or method, this could
		// change selections in other packages.
		// (We include "type" in this list because a type
		// used as an embedded struct field entails a field
		// renaming.)
		return true
	}
	return false
}

// update updates the input files.
func (r *renamer) update() error {
	// We use token.File, not filename, since a file may appear to
	// belong to multiple packages and be parsed more than once.
	// token.File captures this distinction; filename does not.
	var nidents int
	var filesToUpdate = make(map[*token.File]bool)
	for _, info := range r.packages {
		// Mutate the ASTs and note the filenames.
		for id, obj := range info.Defs {
			if r.objsToUpdate[obj] {
				nidents++
				id.Name = r.to
				filesToUpdate[r.iprog.Fset.File(id.Pos())] = true
			}
		}
		for id, obj := range info.Uses {
			if r.objsToUpdate[obj] {
				nidents++
				id.Name = r.to
				filesToUpdate[r.iprog.Fset.File(id.Pos())] = true
			}
		}
	}

	// TODO(adonovan): don't rewrite cgo + generated files.
	var nerrs, npkgs int
	for _, info := range r.packages {
		first := true
		for _, f := range info.Files {
			tokenFile := r.iprog.Fset.File(f.Pos())
			if filesToUpdate[tokenFile] {
				if first {
					npkgs++
					first = false
					if Verbose {
						fmt.Fprintf(os.Stderr, "Updating package %s\n",
							info.Pkg.Path())
					}
				}
				if err := rewriteFile(r.iprog.Fset, f, tokenFile.Name()); err != nil {
					fmt.Fprintf(os.Stderr, "Error: %s.\n", err)
					nerrs++
				}
			}
		}
	}
	fmt.Fprintf(os.Stderr, "Renamed %d occurrence%s in %d file%s in %d package%s.\n",
		nidents, plural(nidents),
		len(filesToUpdate), plural(len(filesToUpdate)),
		npkgs, plural(npkgs))
	if nerrs > 0 {
		return fmt.Errorf("failed to rewrite %d file%s", nerrs, plural(nerrs))
	}
	return nil
}

func plural(n int) string {
	if n != 1 {
		return "s"
	}
	return ""
}

var rewriteFile = func(fset *token.FileSet, f *ast.File, orig string) (err error) {
	backup := orig + ".prename"
	// TODO(adonovan): print packages and filenames in a form useful
	// to editors (so they can reload files).
	if Verbose {
		fmt.Fprintf(os.Stderr, "\t%s\n", orig)
	}
	if err := os.Rename(orig, backup); err != nil {
		return fmt.Errorf("failed to make backup %s -> %s: %s",
			orig, filepath.Base(backup), err)
	}
	out, err := os.Create(orig)
	if err != nil {
		// assume error includes the filename
		return fmt.Errorf("failed to open file: %s", err)
	}
	defer func() {
		if closeErr := out.Close(); err == nil {
			err = closeErr // don't clobber existing error
		}
	}()
	if err := format.Node(out, fset, f); err != nil {
		return fmt.Errorf("failed to write file: %s", err)
	}
	return nil
}
<commit_msg>refactor: don't litter the source tree with backup turdlets.<commit_after>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package rename contains the implementation of the 'gorename' command
// whose main function is in code.google.com/p/go.tools/refactor/rename.
// See that package for the command documentation.
package rename

import (
	"errors"
	"fmt"
	"go/ast"
	"go/build"
	"go/format"
	"go/parser"
	"go/token"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"code.google.com/p/go.tools/go/loader"
	"code.google.com/p/go.tools/go/types"
	"code.google.com/p/go.tools/refactor/importgraph"
	"code.google.com/p/go.tools/refactor/satisfy"
)

var (
	// Force enables patching of the source files even if conflicts were reported.
	// The resulting program may be ill-formed.
	// It may even cause gorename to crash.  TODO(adonovan): fix that.
	Force bool

	// DryRun causes the tool to report conflicts but not update any files.
	DryRun bool

	// ConflictError is returned by Main when it aborts the renaming due to conflicts.
	// (It is distinguished because the interesting errors are the conflicts themselves.)
	ConflictError = errors.New("renaming aborted due to conflicts")

	// Verbose enables extra logging.
	Verbose bool
)

type renamer struct {
	iprog              *loader.Program
	objsToUpdate       map[types.Object]bool
	hadConflicts       bool
	to                 string
	satisfyConstraints map[satisfy.Constraint]bool
	packages           map[*types.Package]*loader.PackageInfo // subset of iprog.AllPackages to inspect
}

var reportError = func(posn token.Position, message string) {
	fmt.Fprintf(os.Stderr, "%s: %s\n", posn, message)
}

func Main(ctxt *build.Context, offsetFlag, fromFlag, to string) error {
	// -- Parse the -from or -offset specifier ----------------------------

	if (offsetFlag == "") == (fromFlag == "") {
		return fmt.Errorf("exactly one of the -from and -offset flags must be specified")
	}

	if !isValidIdentifier(to) {
		return fmt.Errorf("-to %q: not a valid identifier", to)
	}

	var spec *spec
	var err error
	if fromFlag != "" {
		spec, err = parseFromFlag(ctxt, fromFlag)
	} else {
		spec, err = parseOffsetFlag(ctxt, offsetFlag)
	}
	if err != nil {
		return err
	}

	if spec.fromName == to {
		return fmt.Errorf("the old and new names are the same: %s", to)
	}

	// -- Load the program consisting of the initial package  -------------

	iprog, err := loadProgram(ctxt, map[string]bool{spec.pkg: true})
	if err != nil {
		return err
	}

	fromObjects, err := findFromObjects(iprog, spec)
	if err != nil {
		return err
	}

	// -- Load a larger program, for global renamings ---------------------

	if requiresGlobalRename(fromObjects, to) {
		// For a local refactoring, we needn't load more
		// packages, but if the renaming affects the package's
		// API, we we must load all packages that depend on the
		// package defining the object, plus their tests.

		if Verbose {
			fmt.Fprintln(os.Stderr, "Potentially global renaming; scanning workspace...")
		}

		// Scan the workspace and build the import graph.
		_, rev, errors := importgraph.Build(ctxt)
		if len(errors) > 0 {
			fmt.Fprintf(os.Stderr, "While scanning Go workspace:\n")
			for path, err := range errors {
				fmt.Fprintf(os.Stderr, "Package %q: %s.\n", path, err)
			}
		}

		// Enumerate the set of potentially affected packages.
		affectedPackages := make(map[string]bool)
		for _, obj := range fromObjects {
			// External test packages are never imported,
			// so they will never appear in the graph.
			for path := range rev.Search(obj.Pkg().Path()) {
				affectedPackages[path] = true
			}
		}

		// TODO(adonovan): allow the user to specify the scope,
		// or -ignore patterns?  Computing the scope when we
		// don't (yet) support inputs containing errors can make
		// the tool rather brittle.

		// Re-load the larger program.
		iprog, err = loadProgram(ctxt, affectedPackages)
		if err != nil {
			return err
		}

		fromObjects, err = findFromObjects(iprog, spec)
		if err != nil {
			return err
		}
	}

	// -- Do the renaming -------------------------------------------------

	r := renamer{
		iprog:        iprog,
		objsToUpdate: make(map[types.Object]bool),
		to:           to,
		packages:     make(map[*types.Package]*loader.PackageInfo),
	}

	// Only the initially imported packages (iprog.Imported) and
	// their external tests (iprog.Created) should be inspected or
	// modified, as only they have type-checked functions bodies.
	// The rest are just dependencies, needed only for package-level
	// type information.
	for _, info := range iprog.Imported {
		r.packages[info.Pkg] = info
	}
	for _, info := range iprog.Created { // (tests)
		r.packages[info.Pkg] = info
	}

	for _, from := range fromObjects {
		r.check(from)
	}
	if r.hadConflicts && !Force {
		return ConflictError
	}
	if DryRun {
		// TODO(adonovan): print the delta?
		return nil
	}
	return r.update()
}

// loadProgram loads the specified set of packages (plus their tests)
// and all their dependencies, from source, through the specified build
// context.  Only packages in pkgs will have their functions bodies typechecked.
func loadProgram(ctxt *build.Context, pkgs map[string]bool) (*loader.Program, error) {
	conf := loader.Config{
		Build:         ctxt,
		SourceImports: true,
		ParserMode:    parser.ParseComments,

		// TODO(adonovan): enable this.  Requires making a lot of code more robust!
		AllowErrors: false,
	}

	// Optimization: don't type-check the bodies of functions in our
	// dependencies, since we only need exported package members.
	conf.TypeCheckFuncBodies = func(p string) bool {
		return pkgs[p] || pkgs[strings.TrimSuffix(p, "_test")]
	}

	if Verbose {
		var list []string
		for pkg := range pkgs {
			list = append(list, pkg)
		}
		sort.Strings(list)
		for _, pkg := range list {
			fmt.Fprintf(os.Stderr, "Loading package: %s\n", pkg)
		}
	}

	for pkg := range pkgs {
		if err := conf.ImportWithTests(pkg); err != nil {
			return nil, err
		}
	}
	return conf.Load()
}

// requiresGlobalRename reports whether this renaming could potentially
// affect other packages in the Go workspace.
func requiresGlobalRename(fromObjects []types.Object, to string) bool {
	var tfm bool
	for _, from := range fromObjects {
		if from.Exported() {
			return true
		}
		switch objectKind(from) {
		case "type", "field", "method":
			tfm = true
		}
	}
	if ast.IsExported(to) && tfm {
		// A global renaming may be necessary even if we're
		// exporting a previous unexported name, since if it's
		// the name of a type, field or method, this could
		// change selections in other packages.
		// (We include "type" in this list because a type
		// used as an embedded struct field entails a field
		// renaming.)
		return true
	}
	return false
}

// update updates the input files.
func (r *renamer) update() error {
	// We use token.File, not filename, since a file may appear to
	// belong to multiple packages and be parsed more than once.
	// token.File captures this distinction; filename does not.
	var nidents int
	var filesToUpdate = make(map[*token.File]bool)
	for _, info := range r.packages {
		// Mutate the ASTs and note the filenames.
		for id, obj := range info.Defs {
			if r.objsToUpdate[obj] {
				nidents++
				id.Name = r.to
				filesToUpdate[r.iprog.Fset.File(id.Pos())] = true
			}
		}
		for id, obj := range info.Uses {
			if r.objsToUpdate[obj] {
				nidents++
				id.Name = r.to
				filesToUpdate[r.iprog.Fset.File(id.Pos())] = true
			}
		}
	}

	// TODO(adonovan): don't rewrite cgo + generated files.
	var nerrs, npkgs int
	for _, info := range r.packages {
		first := true
		for _, f := range info.Files {
			tokenFile := r.iprog.Fset.File(f.Pos())
			if filesToUpdate[tokenFile] {
				if first {
					npkgs++
					first = false
					if Verbose {
						fmt.Fprintf(os.Stderr, "Updating package %s\n",
							info.Pkg.Path())
					}
				}
				if err := rewriteFile(r.iprog.Fset, f, tokenFile.Name()); err != nil {
					fmt.Fprintf(os.Stderr, "Error: %s.\n", err)
					nerrs++
				}
			}
		}
	}
	fmt.Fprintf(os.Stderr, "Renamed %d occurrence%s in %d file%s in %d package%s.\n",
		nidents, plural(nidents),
		len(filesToUpdate), plural(len(filesToUpdate)),
		npkgs, plural(npkgs))
	if nerrs > 0 {
		return fmt.Errorf("failed to rewrite %d file%s", nerrs, plural(nerrs))
	}
	return nil
}

func plural(n int) string {
	if n != 1 {
		return "s"
	}
	return ""
}

func writeFile(name string, fset *token.FileSet, f *ast.File) error {
	out, err := os.Create(name)
	if err != nil {
		// assume error includes the filename
		return fmt.Errorf("failed to open file: %s", err)
	}
	if err := format.Node(out, fset, f); err != nil {
		out.Close() // ignore error
		return fmt.Errorf("failed to write file: %s", err)
	}
	return out.Close()
}

var rewriteFile = func(fset *token.FileSet, f *ast.File, orig string) (err error) {
	backup := orig + ".gorename.backup"
	// TODO(adonovan): print packages and filenames in a form useful
	// to editors (so they can reload files).
	if Verbose {
		fmt.Fprintf(os.Stderr, "\t%s\n", orig)
	}
	if err := os.Rename(orig, backup); err != nil {
		return fmt.Errorf("failed to make backup %s -> %s: %s",
			orig, filepath.Base(backup), err)
	}
	if err := writeFile(orig, fset, f); err != nil {
		// Restore the file from the backup.
		os.Remove(orig)         // ignore error
		os.Rename(backup, orig) // ignore error
		return err
	}
	os.Remove(backup) // ignore error
	return nil
}
<|endoftext|>


<commit_before>package common

import (
	"fmt"
	"net"
	"os"
	"strconv"
)

func LocalIP() (string, error) {
	addr, err := net.ResolveUDPAddr("udp", "1.2.3.4:1")
	if err != nil {
		return "", err
	}

	conn, err := net.DialUDP("udp", nil, addr)
	if err != nil {
		return "", err
	}

	host, _, err := net.SplitHostPort(conn.LocalAddr().String())
	if err != nil {
		return "", err
	}

	return host, nil
}

func GrabEphemeralPort() (port uint16, err error) {
	var listener net.Listener
	var portStr string
	var p int

	listener, err = net.Listen("tcp", ":0")
	if err != nil {
		return
	}
	defer listener.Close()

	_, portStr, err = net.SplitHostPort(listener.Addr().String())
	if err != nil {
		return
	}

	p, err = strconv.Atoi(portStr)
	port = uint16(p)

	return
}

func GenerateUUID() string {
	file, _ := os.Open("/dev/urandom")
	b := make([]byte, 16)
	file.Read(b)
	file.Close()

	uuid := fmt.Sprintf("%x", b)
	return uuid
}

func ProcessExist(pid int) bool {
	_, err := os.Stat(fmt.Sprintf("/proc/%d", pid))
	if err != nil {
		return false
	}

	return true
}
<commit_msg>Close connection after using it<commit_after>package common

import (
	"fmt"
	"net"
	"os"
	"strconv"
)

func LocalIP() (string, error) {
	addr, err := net.ResolveUDPAddr("udp", "1.2.3.4:1")
	if err != nil {
		return "", err
	}

	conn, err := net.DialUDP("udp", nil, addr)
	if err != nil {
		return "", err
	}

	defer conn.Close()

	host, _, err := net.SplitHostPort(conn.LocalAddr().String())
	if err != nil {
		return "", err
	}

	return host, nil
}

func GrabEphemeralPort() (port uint16, err error) {
	var listener net.Listener
	var portStr string
	var p int

	listener, err = net.Listen("tcp", ":0")
	if err != nil {
		return
	}
	defer listener.Close()

	_, portStr, err = net.SplitHostPort(listener.Addr().String())
	if err != nil {
		return
	}

	p, err = strconv.Atoi(portStr)
	port = uint16(p)

	return
}

func GenerateUUID() string {
	file, _ := os.Open("/dev/urandom")
	b := make([]byte, 16)
	file.Read(b)
	file.Close()

	uuid := fmt.Sprintf("%x", b)
	return uuid
}

func ProcessExist(pid int) bool {
	_, err := os.Stat(fmt.Sprintf("/proc/%d", pid))
	if err != nil {
		return false
	}

	return true
}
<|endoftext|>


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

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

package runtime

import "unsafe"

const (
	_AT_NULL     = 0
	_AT_PLATFORM = 15 //  introduced in at least 2.6.11
	_AT_HWCAP    = 16 // introduced in at least 2.6.11
	_AT_RANDOM   = 25 // introduced in 2.6.29

	_HWCAP_VFP   = 1 << 6  // introduced in at least 2.6.11
	_HWCAP_VFPv3 = 1 << 13 // introduced in 2.6.30
)

var randomNumber uint32
var armArch uint8 = 6 // we default to ARMv6
var hwcap uint32      // set by setup_auxv
var goarm uint8       // set by 5l

func checkgoarm() {
	if goarm > 5 && hwcap&_HWCAP_VFP == 0 {
		print("runtime: this CPU has no floating point hardware, so it cannot run\n")
		print("this GOARM=", goarm, " binary. Recompile using GOARM=5.\n")
		exit(1)
	}
	if goarm > 6 && hwcap&_HWCAP_VFPv3 == 0 {
		print("runtime: this CPU has no VFPv3 floating point hardware, so it cannot run\n")
		print("this GOARM=", goarm, " binary. Recompile using GOARM=5.\n")
		exit(1)
	}
}

//go:nosplit
func setup_auxv(argc int32, argv **byte) {
	// skip over argv, envv to get to auxv
	n := argc + 1
	for argv_index(argv, n) != nil {
		n++
	}
	n++
	auxv := (*[1 << 28]uint32)(add(unsafe.Pointer(argv), uintptr(n)*ptrSize))

	for i := 0; auxv[i] != _AT_NULL; i += 2 {
		switch auxv[i] {
		case _AT_RANDOM: // kernel provides a pointer to 16-bytes worth of random data
			if auxv[i+1] != 0 {
				// the pointer provided may not be word alined, so we must to treat it
				// as a byte array.
				rnd := (*[16]byte)(unsafe.Pointer(uintptr(auxv[i+1])))
				randomNumber = uint32(rnd[0]) | uint32(rnd[1])<<8 | uint32(rnd[2])<<16 | uint32(rnd[3])<<24
			}

		case _AT_PLATFORM: // v5l, v6l, v7l
			t := *(*uint8)(unsafe.Pointer(uintptr(auxv[i+1] + 1)))
			if '5' <= t && t <= '7' {
				armArch = t - '0'
			}

		case _AT_HWCAP: // CPU capability bit flags
			hwcap = auxv[i+1]
		}
	}
}

func cputicks() int64 {
	// Currently cputicks() is used in blocking profiler and to seed fastrand1().
	// nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
	// randomNumber provides better seeding of fastrand1.
	return nanotime() + int64(randomNumber)
}
<commit_msg>runtime: source startupRandomData from auxv AT_RANDOM on linux/arm.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

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

package runtime

import "unsafe"

const (
	_AT_NULL     = 0
	_AT_PLATFORM = 15 //  introduced in at least 2.6.11
	_AT_HWCAP    = 16 // introduced in at least 2.6.11
	_AT_RANDOM   = 25 // introduced in 2.6.29

	_HWCAP_VFP   = 1 << 6  // introduced in at least 2.6.11
	_HWCAP_VFPv3 = 1 << 13 // introduced in 2.6.30
)

var randomNumber uint32
var armArch uint8 = 6 // we default to ARMv6
var hwcap uint32      // set by setup_auxv
var goarm uint8       // set by 5l

func checkgoarm() {
	if goarm > 5 && hwcap&_HWCAP_VFP == 0 {
		print("runtime: this CPU has no floating point hardware, so it cannot run\n")
		print("this GOARM=", goarm, " binary. Recompile using GOARM=5.\n")
		exit(1)
	}
	if goarm > 6 && hwcap&_HWCAP_VFPv3 == 0 {
		print("runtime: this CPU has no VFPv3 floating point hardware, so it cannot run\n")
		print("this GOARM=", goarm, " binary. Recompile using GOARM=5.\n")
		exit(1)
	}
}

//go:nosplit
func setup_auxv(argc int32, argv **byte) {
	// skip over argv, envv to get to auxv
	n := argc + 1
	for argv_index(argv, n) != nil {
		n++
	}
	n++
	auxv := (*[1 << 28]uint32)(add(unsafe.Pointer(argv), uintptr(n)*ptrSize))

	for i := 0; auxv[i] != _AT_NULL; i += 2 {
		switch auxv[i] {
		case _AT_RANDOM: // kernel provides a pointer to 16-bytes worth of random data
			startupRandomData = (*[16]byte)(unsafe.Pointer(uintptr(auxv[i+1])))[:]
			// the pointer provided may not be word alined, so we must to treat it
			// as a byte array.
			randomNumber = uint32(startupRandomData[4]) | uint32(startupRandomData[5])<<8 |
				uint32(startupRandomData[6])<<16 | uint32(startupRandomData[7])<<24

		case _AT_PLATFORM: // v5l, v6l, v7l
			t := *(*uint8)(unsafe.Pointer(uintptr(auxv[i+1] + 1)))
			if '5' <= t && t <= '7' {
				armArch = t - '0'
			}

		case _AT_HWCAP: // CPU capability bit flags
			hwcap = auxv[i+1]
		}
	}
}

func cputicks() int64 {
	// Currently cputicks() is used in blocking profiler and to seed fastrand1().
	// nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
	// randomNumber provides better seeding of fastrand1.
	return nanotime() + int64(randomNumber)
}
<|endoftext|>


<commit_before>package gorm

import "fmt"

// DefaultCallback default callbacks defined by gorm
var DefaultCallback = &Callback{}

// Callback is a struct that contains all CRUD callbacks
//   Field `creates` contains callbacks will be call when creating object
//   Field `updates` contains callbacks will be call when updating object
//   Field `deletes` contains callbacks will be call when deleting object
//   Field `queries` contains callbacks will be call when querying object with query methods like Find, First, Related, Association...
//   Field `rowQueries` contains callbacks will be call when querying object with Row, Rows...
//   Field `processors` contains all callback processors, will be used to generate above callbacks in order
type Callback struct {
	logger     logger
	creates    []*func(scope *Scope)
	updates    []*func(scope *Scope)
	deletes    []*func(scope *Scope)
	queries    []*func(scope *Scope)
	rowQueries []*func(scope *Scope)
	processors []*CallbackProcessor
}

// CallbackProcessor contains callback informations
type CallbackProcessor struct {
	logger    logger
	name      string              // current callback's name
	before    string              // register current callback before a callback
	after     string              // register current callback after a callback
	replace   bool                // replace callbacks with same name
	remove    bool                // delete callbacks with same name
	kind      string              // callback type: create, update, delete, query, row_query
	processor *func(scope *Scope) // callback handler
	parent    *Callback
}

func (c *Callback) clone(logger logger) *Callback {
	return &Callback{
		logger:     logger,
		creates:    c.creates,
		updates:    c.updates,
		deletes:    c.deletes,
		queries:    c.queries,
		rowQueries: c.rowQueries,
		processors: c.processors,
	}
}

// Create could be used to register callbacks for creating object
//     db.Callback().Create().After("gorm:create").Register("plugin:run_after_create", func(*Scope) {
//       // business logic
//       ...
//
//       // set error if some thing wrong happened, will rollback the creating
//       scope.Err(errors.New("error"))
//     })
func (c *Callback) Create() *CallbackProcessor {
	return &CallbackProcessor{logger: c.logger, kind: "create", parent: c}
}

// Update could be used to register callbacks for updating object, refer `Create` for usage
func (c *Callback) Update() *CallbackProcessor {
	return &CallbackProcessor{logger: c.logger, kind: "update", parent: c}
}

// Delete could be used to register callbacks for deleting object, refer `Create` for usage
func (c *Callback) Delete() *CallbackProcessor {
	return &CallbackProcessor{logger: c.logger, kind: "delete", parent: c}
}

// Query could be used to register callbacks for querying objects with query methods like `Find`, `First`, `Related`, `Association`...
// Refer `Create` for usage
func (c *Callback) Query() *CallbackProcessor {
	return &CallbackProcessor{logger: c.logger, kind: "query", parent: c}
}

// RowQuery could be used to register callbacks for querying objects with `Row`, `Rows`, refer `Create` for usage
func (c *Callback) RowQuery() *CallbackProcessor {
	return &CallbackProcessor{logger: c.logger, kind: "row_query", parent: c}
}

// After insert a new callback after callback `callbackName`, refer `Callbacks.Create`
func (cp *CallbackProcessor) After(callbackName string) *CallbackProcessor {
	cp.after = callbackName
	return cp
}

// Before insert a new callback before callback `callbackName`, refer `Callbacks.Create`
func (cp *CallbackProcessor) Before(callbackName string) *CallbackProcessor {
	cp.before = callbackName
	return cp
}

// Register a new callback, refer `Callbacks.Create`
func (cp *CallbackProcessor) Register(callbackName string, callback func(scope *Scope)) {
	if cp.kind == "row_query" {
		if cp.before == "" && cp.after == "" && callbackName != "gorm:row_query" {
			cp.logger.Print(fmt.Sprintf("Registering RowQuery callback %v without specify order with Before(), After(), applying Before('gorm:row_query') by default for compatibility...\n", callbackName))
			cp.before = "gorm:row_query"
		}
	}

	cp.name = callbackName
	cp.processor = &callback
	cp.parent.processors = append(cp.parent.processors, cp)
	cp.parent.reorder()
}

// Remove a registered callback
//     db.Callback().Create().Remove("gorm:update_time_stamp_when_create")
func (cp *CallbackProcessor) Remove(callbackName string) {
	cp.logger.Print(fmt.Sprintf("[info] removing callback `%v` from %v\n", callbackName, fileWithLineNum()))
	cp.name = callbackName
	cp.remove = true
	cp.parent.processors = append(cp.parent.processors, cp)
	cp.parent.reorder()
}

// Replace a registered callback with new callback
//     db.Callback().Create().Replace("gorm:update_time_stamp_when_create", func(*Scope) {
//		   scope.SetColumn("CreatedAt", now)
//		   scope.SetColumn("UpdatedAt", now)
//     })
func (cp *CallbackProcessor) Replace(callbackName string, callback func(scope *Scope)) {
	cp.logger.Print(fmt.Sprintf("[info] replacing callback `%v` from %v\n", callbackName, fileWithLineNum()))
	cp.name = callbackName
	cp.processor = &callback
	cp.replace = true
	cp.parent.processors = append(cp.parent.processors, cp)
	cp.parent.reorder()
}

// Get registered callback
//    db.Callback().Create().Get("gorm:create")
func (cp *CallbackProcessor) Get(callbackName string) (callback func(scope *Scope)) {
	for _, p := range cp.parent.processors {
		if p.name == callbackName && p.kind == cp.kind {
			if p.remove {
				callback = nil
			} else {
				callback = *p.processor
			}
		}
	}
	return
}

// getRIndex get right index from string slice
func getRIndex(strs []string, str string) int {
	for i := len(strs) - 1; i >= 0; i-- {
		if strs[i] == str {
			return i
		}
	}
	return -1
}

// sortProcessors sort callback processors based on its before, after, remove, replace
func sortProcessors(cps []*CallbackProcessor) []*func(scope *Scope) {
	var (
		allNames, sortedNames []string
		sortCallbackProcessor func(c *CallbackProcessor)
	)

	for _, cp := range cps {
		// show warning message the callback name already exists
		if index := getRIndex(allNames, cp.name); index > -1 && !cp.replace && !cp.remove {
			cp.logger.Print(fmt.Sprintf("[warning] duplicated callback `%v` from %v\n", cp.name, fileWithLineNum()))
		}
		allNames = append(allNames, cp.name)
	}

	sortCallbackProcessor = func(c *CallbackProcessor) {
		if getRIndex(sortedNames, c.name) == -1 { // if not sorted
			if c.before != "" { // if defined before callback
				if index := getRIndex(sortedNames, c.before); index != -1 {
					// if before callback already sorted, append current callback just after it
					sortedNames = append(sortedNames[:index], append([]string{c.name}, sortedNames[index:]...)...)
				} else if index := getRIndex(allNames, c.before); index != -1 {
					// if before callback exists but haven't sorted, append current callback to last
					sortedNames = append(sortedNames, c.name)
					sortCallbackProcessor(cps[index])
				}
			}

			if c.after != "" { // if defined after callback
				if index := getRIndex(sortedNames, c.after); index != -1 {
					// if after callback already sorted, append current callback just before it
					sortedNames = append(sortedNames[:index+1], append([]string{c.name}, sortedNames[index+1:]...)...)
				} else if index := getRIndex(allNames, c.after); index != -1 {
					// if after callback exists but haven't sorted
					cp := cps[index]
					// set after callback's before callback to current callback
					if cp.before == "" {
						cp.before = c.name
					}
					sortCallbackProcessor(cp)
				}
			}

			// if current callback haven't been sorted, append it to last
			if getRIndex(sortedNames, c.name) == -1 {
				sortedNames = append(sortedNames, c.name)
			}
		}
	}

	for _, cp := range cps {
		sortCallbackProcessor(cp)
	}

	var sortedFuncs []*func(scope *Scope)
	for _, name := range sortedNames {
		if index := getRIndex(allNames, name); !cps[index].remove {
			sortedFuncs = append(sortedFuncs, cps[index].processor)
		}
	}

	return sortedFuncs
}

// reorder all registered processors, and reset CRUD callbacks
func (c *Callback) reorder() {
	var creates, updates, deletes, queries, rowQueries []*CallbackProcessor

	for _, processor := range c.processors {
		if processor.name != "" {
			switch processor.kind {
			case "create":
				creates = append(creates, processor)
			case "update":
				updates = append(updates, processor)
			case "delete":
				deletes = append(deletes, processor)
			case "query":
				queries = append(queries, processor)
			case "row_query":
				rowQueries = append(rowQueries, processor)
			}
		}
	}

	c.creates = sortProcessors(creates)
	c.updates = sortProcessors(updates)
	c.deletes = sortProcessors(deletes)
	c.queries = sortProcessors(queries)
	c.rowQueries = sortProcessors(rowQueries)
}
<commit_msg>Fix logging callbacks (#2652)<commit_after>package gorm

import "fmt"

// DefaultCallback default callbacks defined by gorm
var DefaultCallback = &Callback{}

// Callback is a struct that contains all CRUD callbacks
//   Field `creates` contains callbacks will be call when creating object
//   Field `updates` contains callbacks will be call when updating object
//   Field `deletes` contains callbacks will be call when deleting object
//   Field `queries` contains callbacks will be call when querying object with query methods like Find, First, Related, Association...
//   Field `rowQueries` contains callbacks will be call when querying object with Row, Rows...
//   Field `processors` contains all callback processors, will be used to generate above callbacks in order
type Callback struct {
	logger     logger
	creates    []*func(scope *Scope)
	updates    []*func(scope *Scope)
	deletes    []*func(scope *Scope)
	queries    []*func(scope *Scope)
	rowQueries []*func(scope *Scope)
	processors []*CallbackProcessor
}

// CallbackProcessor contains callback informations
type CallbackProcessor struct {
	logger    logger
	name      string              // current callback's name
	before    string              // register current callback before a callback
	after     string              // register current callback after a callback
	replace   bool                // replace callbacks with same name
	remove    bool                // delete callbacks with same name
	kind      string              // callback type: create, update, delete, query, row_query
	processor *func(scope *Scope) // callback handler
	parent    *Callback
}

func (c *Callback) clone(logger logger) *Callback {
	return &Callback{
		logger:     logger,
		creates:    c.creates,
		updates:    c.updates,
		deletes:    c.deletes,
		queries:    c.queries,
		rowQueries: c.rowQueries,
		processors: c.processors,
	}
}

// Create could be used to register callbacks for creating object
//     db.Callback().Create().After("gorm:create").Register("plugin:run_after_create", func(*Scope) {
//       // business logic
//       ...
//
//       // set error if some thing wrong happened, will rollback the creating
//       scope.Err(errors.New("error"))
//     })
func (c *Callback) Create() *CallbackProcessor {
	return &CallbackProcessor{logger: c.logger, kind: "create", parent: c}
}

// Update could be used to register callbacks for updating object, refer `Create` for usage
func (c *Callback) Update() *CallbackProcessor {
	return &CallbackProcessor{logger: c.logger, kind: "update", parent: c}
}

// Delete could be used to register callbacks for deleting object, refer `Create` for usage
func (c *Callback) Delete() *CallbackProcessor {
	return &CallbackProcessor{logger: c.logger, kind: "delete", parent: c}
}

// Query could be used to register callbacks for querying objects with query methods like `Find`, `First`, `Related`, `Association`...
// Refer `Create` for usage
func (c *Callback) Query() *CallbackProcessor {
	return &CallbackProcessor{logger: c.logger, kind: "query", parent: c}
}

// RowQuery could be used to register callbacks for querying objects with `Row`, `Rows`, refer `Create` for usage
func (c *Callback) RowQuery() *CallbackProcessor {
	return &CallbackProcessor{logger: c.logger, kind: "row_query", parent: c}
}

// After insert a new callback after callback `callbackName`, refer `Callbacks.Create`
func (cp *CallbackProcessor) After(callbackName string) *CallbackProcessor {
	cp.after = callbackName
	return cp
}

// Before insert a new callback before callback `callbackName`, refer `Callbacks.Create`
func (cp *CallbackProcessor) Before(callbackName string) *CallbackProcessor {
	cp.before = callbackName
	return cp
}

// Register a new callback, refer `Callbacks.Create`
func (cp *CallbackProcessor) Register(callbackName string, callback func(scope *Scope)) {
	if cp.kind == "row_query" {
		if cp.before == "" && cp.after == "" && callbackName != "gorm:row_query" {
			cp.logger.Print("info", fmt.Sprintf("Registering RowQuery callback %v without specify order with Before(), After(), applying Before('gorm:row_query') by default for compatibility...", callbackName))
			cp.before = "gorm:row_query"
		}
	}

	cp.name = callbackName
	cp.processor = &callback
	cp.parent.processors = append(cp.parent.processors, cp)
	cp.parent.reorder()
}

// Remove a registered callback
//     db.Callback().Create().Remove("gorm:update_time_stamp_when_create")
func (cp *CallbackProcessor) Remove(callbackName string) {
	cp.logger.Print("info", fmt.Sprintf("[info] removing callback `%v` from %v", callbackName, fileWithLineNum()))
	cp.name = callbackName
	cp.remove = true
	cp.parent.processors = append(cp.parent.processors, cp)
	cp.parent.reorder()
}

// Replace a registered callback with new callback
//     db.Callback().Create().Replace("gorm:update_time_stamp_when_create", func(*Scope) {
//		   scope.SetColumn("CreatedAt", now)
//		   scope.SetColumn("UpdatedAt", now)
//     })
func (cp *CallbackProcessor) Replace(callbackName string, callback func(scope *Scope)) {
	cp.logger.Print("info", fmt.Sprintf("[info] replacing callback `%v` from %v", callbackName, fileWithLineNum()))
	cp.name = callbackName
	cp.processor = &callback
	cp.replace = true
	cp.parent.processors = append(cp.parent.processors, cp)
	cp.parent.reorder()
}

// Get registered callback
//    db.Callback().Create().Get("gorm:create")
func (cp *CallbackProcessor) Get(callbackName string) (callback func(scope *Scope)) {
	for _, p := range cp.parent.processors {
		if p.name == callbackName && p.kind == cp.kind {
			if p.remove {
				callback = nil
			} else {
				callback = *p.processor
			}
		}
	}
	return
}

// getRIndex get right index from string slice
func getRIndex(strs []string, str string) int {
	for i := len(strs) - 1; i >= 0; i-- {
		if strs[i] == str {
			return i
		}
	}
	return -1
}

// sortProcessors sort callback processors based on its before, after, remove, replace
func sortProcessors(cps []*CallbackProcessor) []*func(scope *Scope) {
	var (
		allNames, sortedNames []string
		sortCallbackProcessor func(c *CallbackProcessor)
	)

	for _, cp := range cps {
		// show warning message the callback name already exists
		if index := getRIndex(allNames, cp.name); index > -1 && !cp.replace && !cp.remove {
			cp.logger.Print("warning", fmt.Sprintf("[warning] duplicated callback `%v` from %v", cp.name, fileWithLineNum()))
		}
		allNames = append(allNames, cp.name)
	}

	sortCallbackProcessor = func(c *CallbackProcessor) {
		if getRIndex(sortedNames, c.name) == -1 { // if not sorted
			if c.before != "" { // if defined before callback
				if index := getRIndex(sortedNames, c.before); index != -1 {
					// if before callback already sorted, append current callback just after it
					sortedNames = append(sortedNames[:index], append([]string{c.name}, sortedNames[index:]...)...)
				} else if index := getRIndex(allNames, c.before); index != -1 {
					// if before callback exists but haven't sorted, append current callback to last
					sortedNames = append(sortedNames, c.name)
					sortCallbackProcessor(cps[index])
				}
			}

			if c.after != "" { // if defined after callback
				if index := getRIndex(sortedNames, c.after); index != -1 {
					// if after callback already sorted, append current callback just before it
					sortedNames = append(sortedNames[:index+1], append([]string{c.name}, sortedNames[index+1:]...)...)
				} else if index := getRIndex(allNames, c.after); index != -1 {
					// if after callback exists but haven't sorted
					cp := cps[index]
					// set after callback's before callback to current callback
					if cp.before == "" {
						cp.before = c.name
					}
					sortCallbackProcessor(cp)
				}
			}

			// if current callback haven't been sorted, append it to last
			if getRIndex(sortedNames, c.name) == -1 {
				sortedNames = append(sortedNames, c.name)
			}
		}
	}

	for _, cp := range cps {
		sortCallbackProcessor(cp)
	}

	var sortedFuncs []*func(scope *Scope)
	for _, name := range sortedNames {
		if index := getRIndex(allNames, name); !cps[index].remove {
			sortedFuncs = append(sortedFuncs, cps[index].processor)
		}
	}

	return sortedFuncs
}

// reorder all registered processors, and reset CRUD callbacks
func (c *Callback) reorder() {
	var creates, updates, deletes, queries, rowQueries []*CallbackProcessor

	for _, processor := range c.processors {
		if processor.name != "" {
			switch processor.kind {
			case "create":
				creates = append(creates, processor)
			case "update":
				updates = append(updates, processor)
			case "delete":
				deletes = append(deletes, processor)
			case "query":
				queries = append(queries, processor)
			case "row_query":
				rowQueries = append(rowQueries, processor)
			}
		}
	}

	c.creates = sortProcessors(creates)
	c.updates = sortProcessors(updates)
	c.deletes = sortProcessors(deletes)
	c.queries = sortProcessors(queries)
	c.rowQueries = sortProcessors(rowQueries)
}
<|endoftext|>


<commit_before>package worker

import (
	"fmt"
	"os"
	"os/exec"
	"path"
)

var (
	workingdir = os.Getenv("APP_WORKING_DIR")
	scriptsdir = os.Getenv("APP_SCRIPTS_DIR")
)

func RunScript(work *WorkRequest) (string, error) {
	if workingdir == "" {
		workingdir = os.TempDir()
	}
	if scriptsdir == "" {
		scriptsdir = "scripts"
	}

	scriptname := path.Join(scriptsdir, work.Name, fmt.Sprintf("%s.sh", work.Action))
	fmt.Println("Exec script: ", scriptname)

	// Exec script...
	cmd := exec.Command(scriptname, work.Args...)

	// Open the out file for writing
	outfilename := path.Join(workingdir, fmt.Sprintf("%s-%s.txt", work.Name, work.Action))
	outfile, err := os.Create(outfilename)
	if err != nil {
		return "", err
	}

	defer outfile.Close()
	cmd.Stdout = outfile

	err = cmd.Start()
	if err != nil {
		return "", err
	}

	err = cmd.Wait()
	if err != nil {
		return "", err
	}

	return outfilename, nil
}
<commit_msg>fix: Merge stdout and stderr.<commit_after>package worker

import (
	"fmt"
	"os"
	"os/exec"
	"path"
)

var (
	workingdir = os.Getenv("APP_WORKING_DIR")
	scriptsdir = os.Getenv("APP_SCRIPTS_DIR")
)

func RunScript(work *WorkRequest) (string, error) {
	if workingdir == "" {
		workingdir = os.TempDir()
	}
	if scriptsdir == "" {
		scriptsdir = "scripts"
	}

	scriptname := path.Join(scriptsdir, work.Name, fmt.Sprintf("%s.sh", work.Action))
	fmt.Println("Exec script: ", scriptname, "...")

	// Exec script...
	cmd := exec.Command(scriptname, work.Args...)

	// Open the out file for writing
	outfilename := path.Join(workingdir, fmt.Sprintf("%s-%s.txt", work.Name, work.Action))
	outfile, err := os.Create(outfilename)
	if err != nil {
		return "", err
	}

	defer outfile.Close()
	cmd.Stdout = outfile
	cmd.Stderr = outfile

	err = cmd.Start()
	if err != nil {
		return outfilename, err
	}

	err = cmd.Wait()
	if err != nil {
		fmt.Println("Exec script: ", scriptname, "KO!")
		return outfilename, err
	}

	fmt.Println("Exec script: ", scriptname, "OK")
	return outfilename, nil
}
<|endoftext|>


<commit_before>package main

import (
  "fmt"
  "github.com/cloudlibz/gocloud/gocloud"
)

func main() {

  googlecloud, _ := gocloud.CloudProvider(gocloud.Googleprovider)

  InitializeParams := map[string]string{
     "SourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-8-jessie-v20160301",
     "DiskType":    "projects/sheltermap-1493101612061/zones/us-east4-c/diskTypes/pd-standard",
     "DiskSizeGb":  "10",
   }

   disk := []map[string]interface{}{
      {
 	"Boot":  true,
 	"AutoDelete":   false,
 	"DeviceName":   "DeviceName",
 	"Type":         "PERSISTENT",
 	"Mode":         "READ_WRITE",
 	"InitializeParams": InitializeParams,
       },
    }

  AccessConfigs := []map[string]string{{
 	"Name": "external-nat",
 	"Type": "ONE_TO_ONE_NAT",
   },
   }

   NetworkInterfaces := []map[string]interface{}{
    {
 	"Network": "https://www.googleapis.com/compute/v1/projects/sheltermap-1493101612061/global/networks/default",
 	"Subnetwork":    "projects/sheltermap-1493101612061/regions/us-east4/subnetworks/default",
         "AccessConfigs": AccessConfigs,
     },
    }

    createnode := map[string]interface{}{
       "projectid":   "sheltermap-1493101612061",
 	  "Name" :   "testing-scorelab",
     "MachineType":    "https://www.googleapis.com/compute/v1/projects/sheltermap-1493101612061/zones/us-east4-c/machineTypes/n1-standard-1",
     "Zone":        "us-central1-b",
     "disk":        disk,
     "NetworkInterfaces": NetworkInterfaces,
     }

   resp, err := googlecloud.Createnode(createnode)
   fmt.Println(err)
   response := resp.(map[string]interface{})
   fmt.Println(response["body"])

}
<commit_msg>Removed example file<commit_after><|endoftext|>


<commit_before>package core

import (
	"errors"
	"io"
	"strings"
	"unicode"
)

var (
	errInvalidCodePoint = errors.New("invalid code point")
)

type TokenType int

const (
	Invalid TokenType = iota
	Annotation
	LineString
	Indent
	Unindent
	EOF
	_SOF
)

type Token struct {
	Type  TokenType
	Value string
}

type Scanner struct {
	reader
	indents []string
	toks    []Token
	err     error
}

func NewScanner(r io.RuneScanner) *Scanner {
	s := &Scanner{
		reader:  reader{r: r},
		indents: []string{""},
		toks:    []Token{Token{Type: _SOF}},
	}
	return s
}

func (s *Scanner) Scan() bool {
	s.toks = s.toks[1:]
	if len(s.toks) > 0 {
		return true
	}
	if s.err != nil {
		return false
	}
	s.scanLine()
	s.handleEOF()
	return len(s.toks) > 0
}

func (s *Scanner) scanLine() {
	indent, err := s.readIndent()
	if err != nil {
		s.err = err
		return
	}
	n, ok := s.calcIndent(indent)
	if !ok {
		s.err = errors.New("mismatch indent")
		return
	}
	switch n {
	case 0: // same
		s.afterIndent()
	case 1: // indent
		s.indents = append(s.indents, indent)
		s.addTok(Token{Type: Indent})
		s.afterIndent()
	default: // unindent
		n = -n
		s.indents = s.indents[:len(s.indents)-n]
		for i := 0; i < n; i++ {
			s.addTok(Token{Type: Unindent})
		}
	}
}

func (s *Scanner) calcIndent(indent string) (int, bool) {
	last := s.indents[len(s.indents)-1]
	if indent == last {
		return 0, true
	} else if strings.HasPrefix(indent, last) {
		return 1, true
	}
	for i := 1; i < len(s.indents); i++ {
		if indent == s.indents[len(s.indents)-i-1] {
			return -i, true
		}
	}
	return 0, false
}

func (s *Scanner) afterIndent() {
	isAnnotation := (s.ch == '#')
	line, err := s.readLine()
	if isAnnotation {
		s.addTok(Token{Type: Annotation, Value: line[1:]})
	} else {
		s.addTok(Token{Type: LineString, Value: line})
	}
	s.err = err
}

func (s *Scanner) handleEOF() {
	if s.err == io.EOF {
		if len(s.indents) > 1 {
			for i := 0; i < len(s.indents)-1; i++ {
				s.addTok(Token{Type: Unindent})
			}
			s.indents = s.indents[:1]
		}
		s.addTok(Token{Type: EOF})
	}
}

func (s *Scanner) addTok(tok Token) {
	s.toks = append(s.toks, tok)
}

func (s *Scanner) Token() Token {
	return s.toks[0]
}

func (s *Scanner) setError(err error) {
	s.err = err
}

func (s *Scanner) Err() error {
	if s.err == io.EOF {
		return nil
	}
	return s.err
}

type reader struct {
	r   io.RuneScanner
	ch  rune
	err error
}

func (s *reader) readLine() (string, error) {
	rs := []rune{}
	for s.next() {
		if s.ch == '\r' || s.ch == '\n' {
			s.prev()
			break
		}
		rs = append(rs, s.ch)
	}
	return string(rs), s.err
}

func (s *reader) readIndent() (indent string, err error) {
	for {
		var ok bool
		indent, ok = s.indentSpaces()
		if !ok {
			err = s.err
			return
		}
		var hasNewline bool
		hasNewline, ok = s.skipLineBreaks()
		if !ok {
			err = s.err
			return
		} else if !hasNewline {
			return
		}
	}
}
func (s *reader) skipLineBreaks() (hasNewline bool, ok bool) {
	for s.next() {
		switch s.ch {
		case '\r', '\n':
			hasNewline = true
		default:
			s.prev()
			return hasNewline, true
		}
	}
	return hasNewline, false
}
func (s *reader) indentSpaces() (indent string, ok bool) {
	rs := []rune{}
	for s.next() {
		if s.ch != ' ' && s.ch != '\t' {
			s.prev()
			return string(rs), true
		}
		rs = append(rs, s.ch)
	}
	return "", false
}

func (s *reader) next() bool {
	var err error
	s.ch, _, err = s.r.ReadRune()
	if err != nil {
		s.err = err
		return false
	}
	switch s.ch {
	case '\t', ' ', '\r', '\n':
	case unicode.ReplacementChar:
		s.err = errInvalidCodePoint
		return false
	default:
		if '\x00' <= s.ch && s.ch <= '\x19' {
			s.err = errInvalidCodePoint
			return false
		}
	}
	return true
}

func (s *reader) prev() bool {
	s.err = s.r.UnreadRune()
	return s.err == nil
}
<commit_msg>refactor.<commit_after>package core

import (
	"errors"
	"io"
	"strings"
	"unicode"
)

var (
	errInvalidCodePoint = errors.New("invalid code point")
)

type TokenType int

const (
	Invalid TokenType = iota
	Annotation
	LineString
	Indent
	Unindent
	EOF
	_SOF
)

type Token struct {
	Type  TokenType
	Value string
}

type Scanner struct {
	reader
	indenter
	tokenQueue
	err error
}

func NewScanner(r io.RuneScanner) *Scanner {
	s := &Scanner{
		reader: reader{r: r},
		indenter: indenter{
			indents: []string{""},
		},
		tokenQueue: tokenQueue{
			toks: []Token{Token{Type: _SOF}},
		},
	}
	return s
}

func (s *Scanner) Scan() bool {
	s.popTok()
	if s.tokCount() > 0 {
		return true
	}
	if s.err != nil {
		return false
	}
	s.scanLine()
	if s.err == io.EOF {
		for i := 0; i < s.eofIndentLevel(); i++ {
			s.pushTok(Token{Type: Unindent})
		}
		s.pushTok(Token{Type: EOF})
	}
	return s.tokCount() > 0
}

func (s *Scanner) scanLine() {
	indent, err := s.readIndent()
	if err != nil {
		s.err = err
		return
	}
	indentType, n, err := s.indentLevel(indent)
	if err != nil {
		s.err = err
		return
	}
	for i := 0; i < n; i++ {
		s.pushTok(Token{Type: indentType})
	}
	var line string
	line, s.err = s.readLine()
	if line[0] == '#' {
		s.pushTok(Token{Type: Annotation, Value: line[1:]})
	} else {
		s.pushTok(Token{Type: LineString, Value: line})
	}
}

func (s *Scanner) Err() error {
	if s.err == io.EOF {
		return nil
	}
	return s.err
}

type reader struct {
	r   io.RuneScanner
	ch  rune
	err error
}

func (s *reader) readLine() (string, error) {
	rs := []rune{}
	for s.next() {
		switch s.ch {
		case '\r', '\n':
			s.prev()
			goto ret
		}
		rs = append(rs, s.ch)
	}
ret:
	return string(rs), s.err
}

func (s *reader) readIndent() (indent string, err error) {
	for {
		var ok bool
		indent, ok = s.indentSpaces()
		if !ok {
			err = s.err
			return
		}
		var hasNewline bool
		hasNewline, ok = s.skipLineBreaks()
		if !ok {
			err = s.err
			return
		} else if !hasNewline {
			return
		}
	}
}
func (s *reader) skipLineBreaks() (hasNewline bool, ok bool) {
	for s.next() {
		switch s.ch {
		case '\r', '\n':
			hasNewline = true
		default:
			s.prev()
			return hasNewline, true
		}
	}
	return hasNewline, false
}
func (s *reader) indentSpaces() (indent string, ok bool) {
	rs := []rune{}
	for s.next() {
		switch s.ch {
		case ' ', '\t':
		default:
			s.prev()
			return string(rs), true
		}
		rs = append(rs, s.ch)
	}
	return "", false
}

func (s *reader) next() bool {
	var err error
	s.ch, _, err = s.r.ReadRune()
	if err != nil {
		s.err = err
		return false
	}
	switch s.ch {
	case '\t', ' ', '\r', '\n':
	case unicode.ReplacementChar:
		s.err = errInvalidCodePoint
		return false
	default:
		if '\x00' <= s.ch && s.ch <= '\x19' {
			s.err = errInvalidCodePoint
			return false
		}
	}
	return true
}

func (s *reader) prev() bool {
	s.err = s.r.UnreadRune()
	return s.err == nil
}

type indenter struct {
	indents []string
}

func (s *indenter) indentLevel(indent string) (TokenType, int, error) {
	last := s.indents[len(s.indents)-1]
	if indent == last {
		return 0, 0, nil
	} else if strings.HasPrefix(indent, last) {
		s.indents = append(s.indents, indent)
		return Indent, 1, nil
	}
	for i := 1; i < len(s.indents); i++ {
		if indent == s.indents[len(s.indents)-i-1] {
			s.indents = s.indents[:len(s.indents)-i]
			return Unindent, i, nil
		}
	}
	return 0, 0, errors.New("mismatch indent")
}

func (s *indenter) eofIndentLevel() int {
	if len(s.indents) > 1 {
		n := len(s.indents) - 1
		s.indents = s.indents[:1]
		return n
	}
	return 0
}

type tokenQueue struct {
	toks []Token
}

func (s *tokenQueue) Token() Token {
	return s.toks[0]
}

func (s *tokenQueue) pushTok(tok Token) {
	s.toks = append(s.toks, tok)
}

func (s *tokenQueue) popTok() {
	s.toks = s.toks[1:]
}

func (s *tokenQueue) tokCount() int {
	return len(s.toks)
}
<|endoftext|>


<commit_before>package viber

// RichMediaMessage / Carousel
type RichMediaMessage struct {
	AuthToken     string      `json:"auth_token"`
	Receiver      string      `json:"receiver,omitempty"`
	Type          MessageType `json:"type"`
	MinAPIVersion int         `json:"min_api_version"`
	RichMedia     RichMedia   `json:"rich_media"`
	AltText       string      `json:"alt_text,omitempty"`
}

// RichMedia for carousel
type RichMedia struct {
	Type                MessageType `json:"Type"`
	ButtonsGroupColumns int         `json:"ButtonsGroupColumns"`
	ButtonsGroupRows    int         `json:"ButtonsGroupRows"`
	BgColor             string      `json:"BgColor"`
	TrackingData        string      `json:"tracking_data,omitempty"`
	Buttons             []Button    `json:"Buttons"`
}

// Button for carousel
type Button struct {
	Columns    int        `json:"Columns"`
	Rows       int        `json:"Rows"`
	ActionType ActionType `json:"ActionType"`
	ActionBody string     `json:"ActionBody"`
	Image      string     `json:"Image,omitempty"`
	Text       string     `json:"Text,omitempty"`
	TextSize   TextSize   `json:"TextSize,omitempty"`
	TextVAlign TextVAlign `json:"TextVAlign,omitempty"`
	TextHAlign TextHAlign `json:"TextHAlign,omitempty"`
}

// AddButton to rich media message
func (rm *RichMediaMessage) AddButton(b *Button) {
	rm.RichMedia.Buttons = append(rm.RichMedia.Buttons, *b)
}

// NewRichMediaMessage creates new empty carousel message
func (v *Viber) NewRichMediaMessage(cols, rows int, bgColor string) *RichMediaMessage {
	return &RichMediaMessage{
		MinAPIVersion: 2,
		AuthToken:     v.AppKey,
		Type:          TypeRichMediaMessage,
		RichMedia: RichMedia{
			Type:                TypeRichMediaMessage,
			ButtonsGroupColumns: cols,
			ButtonsGroupRows:    rows,
			BgColor:             bgColor,
		},
	}
}

// NewButton helper function for creating button with text and image
func (v *Viber) NewButton(cols, rows int, typ ActionType, actionBody string, text, image string) *Button {
	return &Button{
		Columns:    cols,
		Rows:       rows,
		ActionType: typ,
		ActionBody: actionBody,
		Text:       text,
		Image:      image,
	}
}

// NewImageButton helper function for creating image button struct with common params
func (v *Viber) NewImageButton(cols, rows int, typ ActionType, actionBody string, image string) *Button {
	return &Button{
		Columns:    cols,
		Rows:       rows,
		ActionType: typ,
		ActionBody: actionBody,
		Image:      image,
	}
}

// NewTextButton helper function for creating image button struct with common params
func (v *Viber) NewTextButton(cols, rows int, t ActionType, actionBody, text string) *Button {
	return &Button{
		Columns:    cols,
		Rows:       rows,
		ActionType: t,
		ActionBody: actionBody,
		Text:       text,
	}
}

// SetReceiver for text message
func (rm *RichMediaMessage) SetReceiver(r string) {
	rm.Receiver = r
}

// SetFrom to satisfy interface although RichMedia messages can't be sent to publich chat and don't have From
func (rm *RichMediaMessage) SetFrom(from string) {}

func (b *Button) TextSizeSmall() *Button {
	b.TextSize = Small
	return b
}

func (b *Button) TextSizeMedium() *Button {
	b.TextSize = Medium
	return b
}

func (b *Button) TextSizeLarge() *Button {
	b.TextSize = Large
	return b
}

// TextSize for carousel buttons
// viber.Small
// viber.Medium
// viber.Large
type TextSize string

// TextSize values
const (
	Small  = TextSize("small")
	Medium = TextSize("medium")
	Large  = TextSize("large")
)

// ActionType for carousel buttons
// viber.Reply
// viber.OpenURL
type ActionType string

// ActionType values
const (
	Reply   = ActionType("reply")
	OpenURL = ActionType("open-url")
)

// TextVAlign for carousel buttons
// viber.Top
// viber.Middle
// viber.Bottom
type TextVAlign string

// TextVAlign values
const (
	Top    = TextVAlign("top")
	Middle = TextVAlign("middle")
	Bottom = TextVAlign("bottom")
)

func (b *Button) TextVAlignTop() *Button {
	b.TextVAlign = Top
	return b
}

func (b *Button) TextVAlignMiddle() *Button {
	b.TextVAlign = Middle
	return b
}

func (b *Button) TextVAlignBottom() *Button {
	b.TextVAlign = Bottom
	return b
}

// TextHAlign for carousel buttons
// viber.Left
// viber.Center
// viber.Middle
type TextHAlign string

// TextHAlign values
const (
	Left   = TextHAlign("left")
	Center = TextHAlign("middle")
	Right  = TextHAlign("right")
)

func (b *Button) TextHAlignLeft() *Button {
	b.TextHAlign = Left
	return b
}

func (b *Button) TextHAlignMiddle() *Button {
	b.TextHAlign = Center
	return b
}

func (b *Button) TextHAlignRight() *Button {
	b.TextHAlign = Right
	return b
}
<commit_msg>Add documentation<commit_after>package viber

// RichMediaMessage / Carousel
type RichMediaMessage struct {
	AuthToken     string      `json:"auth_token"`
	Receiver      string      `json:"receiver,omitempty"`
	Type          MessageType `json:"type"`
	MinAPIVersion int         `json:"min_api_version"`
	RichMedia     RichMedia   `json:"rich_media"`
	AltText       string      `json:"alt_text,omitempty"`
}

// RichMedia for carousel
type RichMedia struct {
	Type                MessageType `json:"Type"`
	ButtonsGroupColumns int         `json:"ButtonsGroupColumns"`
	ButtonsGroupRows    int         `json:"ButtonsGroupRows"`
	BgColor             string      `json:"BgColor"`
	TrackingData        string      `json:"tracking_data,omitempty"`
	Buttons             []Button    `json:"Buttons"`
}

// Button for carousel
type Button struct {
	Columns    int        `json:"Columns"`
	Rows       int        `json:"Rows"`
	ActionType ActionType `json:"ActionType"`
	ActionBody string     `json:"ActionBody"`
	Image      string     `json:"Image,omitempty"`
	Text       string     `json:"Text,omitempty"`
	TextSize   TextSize   `json:"TextSize,omitempty"`
	TextVAlign TextVAlign `json:"TextVAlign,omitempty"`
	TextHAlign TextHAlign `json:"TextHAlign,omitempty"`
}

// AddButton to rich media message
func (rm *RichMediaMessage) AddButton(b *Button) {
	rm.RichMedia.Buttons = append(rm.RichMedia.Buttons, *b)
}

// NewRichMediaMessage creates new empty carousel message
func (v *Viber) NewRichMediaMessage(cols, rows int, bgColor string) *RichMediaMessage {
	return &RichMediaMessage{
		MinAPIVersion: 2,
		AuthToken:     v.AppKey,
		Type:          TypeRichMediaMessage,
		RichMedia: RichMedia{
			Type:                TypeRichMediaMessage,
			ButtonsGroupColumns: cols,
			ButtonsGroupRows:    rows,
			BgColor:             bgColor,
		},
	}
}

// NewButton helper function for creating button with text and image
func (v *Viber) NewButton(cols, rows int, typ ActionType, actionBody string, text, image string) *Button {
	return &Button{
		Columns:    cols,
		Rows:       rows,
		ActionType: typ,
		ActionBody: actionBody,
		Text:       text,
		Image:      image,
	}
}

// NewImageButton helper function for creating image button struct with common params
func (v *Viber) NewImageButton(cols, rows int, typ ActionType, actionBody string, image string) *Button {
	return &Button{
		Columns:    cols,
		Rows:       rows,
		ActionType: typ,
		ActionBody: actionBody,
		Image:      image,
	}
}

// NewTextButton helper function for creating image button struct with common params
func (v *Viber) NewTextButton(cols, rows int, t ActionType, actionBody, text string) *Button {
	return &Button{
		Columns:    cols,
		Rows:       rows,
		ActionType: t,
		ActionBody: actionBody,
		Text:       text,
	}
}

// SetReceiver for text message
func (rm *RichMediaMessage) SetReceiver(r string) {
	rm.Receiver = r
}

// SetFrom to satisfy interface although RichMedia messages can't be sent to publich chat and don't have From
func (rm *RichMediaMessage) SetFrom(from string) {}

// TextSizeSmall for button text
func (b *Button) TextSizeSmall() *Button {
	b.TextSize = Small
	return b
}

// TextSizeMedium for button text
func (b *Button) TextSizeMedium() *Button {
	b.TextSize = Medium
	return b
}

// TextSizeLarge for button text
func (b *Button) TextSizeLarge() *Button {
	b.TextSize = Large
	return b
}

// TextSize for carousel buttons
// viber.Small
// viber.Medium
// viber.Large
type TextSize string

// TextSize values
const (
	Small  = TextSize("small")
	Medium = TextSize("medium")
	Large  = TextSize("large")
)

// ActionType for carousel buttons
// viber.Reply
// viber.OpenURL
type ActionType string

// ActionType values
const (
	Reply   = ActionType("reply")
	OpenURL = ActionType("open-url")
)

// TextVAlign for carousel buttons
// viber.Top
// viber.Middle
// viber.Bottom
type TextVAlign string

// TextVAlign values
const (
	Top    = TextVAlign("top")
	Middle = TextVAlign("middle")
	Bottom = TextVAlign("bottom")
)

// TextVAlignTop vertically align text to the top
func (b *Button) TextVAlignTop() *Button {
	b.TextVAlign = Top
	return b
}

// TextVAlignMiddle vertically align text to the middle
func (b *Button) TextVAlignMiddle() *Button {
	b.TextVAlign = Middle
	return b
}

// TextVAlignBottom vertically align text to the bottom
func (b *Button) TextVAlignBottom() *Button {
	b.TextVAlign = Bottom
	return b
}

// TextHAlign for carousel buttons
// viber.Left
// viber.Center
// viber.Middle
type TextHAlign string

// TextHAlign values
const (
	Left   = TextHAlign("left")
	Center = TextHAlign("middle")
	Right  = TextHAlign("right")
)

// TextHAlignLeft horizontaly center text left
func (b *Button) TextHAlignLeft() *Button {
	b.TextHAlign = Left
	return b
}

// TextHAlignMiddle horizontaly center text
func (b *Button) TextHAlignMiddle() *Button {
	b.TextHAlign = Center
	return b
}

// TextHAlignRight horizontaly align text right
func (b *Button) TextHAlignRight() *Button {
	b.TextHAlign = Right
	return b
}
<|endoftext|>


<commit_before>package generic

import (
	"fmt"
	"sync"

	"github.com/workanator/go-ataman/decorate"
	"github.com/workanator/go-ataman/prepared"
)

// Renderer implements generic configurable template renderer. Underlying pool
// is used for pooling string buffers and make the renderer thread safe.
type Renderer struct {
	style decorate.Style
	pool  sync.Pool
}

// NewRenderer constructs the instance of generic renderer with the decoration
// style given.
func NewRenderer(style decorate.Style) *Renderer {
	return &Renderer{
		style: style,
		pool: sync.Pool{
			New: func() interface{} {
				return new(bytesBuffer)
			},
		},
	}
}

// Validate validates the template.
func (rndr *Renderer) Validate(tpl string) error {
	var buf mockBuffer
	return rndr.renderTemplate(&tpl, &buf)
}

// Render renders the template given.
func (rndr *Renderer) Render(tpl string) (string, error) {
	buf := rndr.getBuffer()
	defer rndr.putBuffer(buf)

	err := rndr.renderTemplate(&tpl, buf)

	return buf.String(), err
}

// MustRender renders the template and panics in case of error.
func (rndr *Renderer) MustRender(tpl string) string {
	buf := rndr.getBuffer()
	defer rndr.putBuffer(buf)

	if err := rndr.renderTemplate(&tpl, buf); err != nil {
		panic(err)
	}

	return buf.String()
}

// Renderf formats and renders the template given.
func (rndr *Renderer) Renderf(tpl string, args ...interface{}) (string, error) {
	return rndr.Render(fmt.Sprintf(tpl, args...))
}

// MustRenderf formats and renders the template and panics in case of error.
func (rndr *Renderer) MustRenderf(tpl string, args ...interface{}) string {
	result, err := rndr.Renderf(tpl, args...)
	if err != nil {
		panic(err)
	}

	return result
}

// Len returns the length of the text the user see in terminal.
func (rndr *Renderer) Len(tpl string) int {
	var buf mockBuffer
	var err = rndr.renderTemplate(&tpl, &buf)
	if err != nil {
		return len(tpl)
	}

	return buf.Len()
}

// Lenf calculates and return the length of the formatted template.
func (rndr *Renderer) Lenf(tpl string, args ...interface{}) int {
	return rndr.Len(fmt.Sprintf(tpl, args...))
}

// Prepare prerenders the template given.
func (rndr *Renderer) Prepare(tpl string) (prepared.Template, error) {
	buf := rndr.getBuffer()
	defer rndr.putBuffer(buf)

	err := rndr.renderTemplate(&tpl, buf)
	if err != nil {
		return nil, err
	}

	return preparedTemplate{tpl: buf.String()}, nil
}

// MustPrepare prerenders the template and panics in case of parsing error.
func (rndr *Renderer) MustPrepare(tpl string) (pt prepared.Template) {
	buf := rndr.getBuffer()
	defer rndr.putBuffer(buf)

	err := rndr.renderTemplate(&tpl, buf)
	if err != nil {
		panic(err)
	}

	return preparedTemplate{tpl: buf.String()}
}

func (rndr *Renderer) getBuffer() *bytesBuffer {
	return rndr.pool.Get().(*bytesBuffer)
}

func (rndr *Renderer) putBuffer(buf *bytesBuffer) {
	buf.Buffer.Reset()
	rndr.pool.Put(buf)
}
<commit_msg>Use mutex for pool locking<commit_after>package generic

import (
	"fmt"
	"sync"

	"github.com/workanator/go-ataman/decorate"
	"github.com/workanator/go-ataman/prepared"
)

// Renderer implements generic configurable template renderer. Underlying pool
// is used for pooling string buffers and make the renderer thread safe.
type Renderer struct {
	style decorate.Style
	pool  sync.Pool
	mutex sync.Mutex
}

// NewRenderer constructs the instance of generic renderer with the decoration
// style given.
func NewRenderer(style decorate.Style) *Renderer {
	return &Renderer{
		style: style,
		pool: sync.Pool{
			New: func() interface{} {
				return new(bytesBuffer)
			},
		},
		mutex: sync.Mutex{},
	}
}

// Validate validates the template.
func (rndr *Renderer) Validate(tpl string) error {
	var buf mockBuffer
	return rndr.renderTemplate(&tpl, &buf)
}

// Render renders the template given.
func (rndr *Renderer) Render(tpl string) (string, error) {
	buf := rndr.getBuffer()
	defer rndr.putBuffer(buf)

	err := rndr.renderTemplate(&tpl, buf)

	return buf.String(), err
}

// MustRender renders the template and panics in case of error.
func (rndr *Renderer) MustRender(tpl string) string {
	buf := rndr.getBuffer()
	defer rndr.putBuffer(buf)

	if err := rndr.renderTemplate(&tpl, buf); err != nil {
		panic(err)
	}

	return buf.String()
}

// Renderf formats and renders the template given.
func (rndr *Renderer) Renderf(tpl string, args ...interface{}) (string, error) {
	return rndr.Render(fmt.Sprintf(tpl, args...))
}

// MustRenderf formats and renders the template and panics in case of error.
func (rndr *Renderer) MustRenderf(tpl string, args ...interface{}) string {
	result, err := rndr.Renderf(tpl, args...)
	if err != nil {
		panic(err)
	}

	return result
}

// Len returns the length of the text the user see in terminal.
func (rndr *Renderer) Len(tpl string) int {
	var buf mockBuffer
	var err = rndr.renderTemplate(&tpl, &buf)
	if err != nil {
		return len(tpl)
	}

	return buf.Len()
}

// Lenf calculates and return the length of the formatted template.
func (rndr *Renderer) Lenf(tpl string, args ...interface{}) int {
	return rndr.Len(fmt.Sprintf(tpl, args...))
}

// Prepare prerenders the template given.
func (rndr *Renderer) Prepare(tpl string) (prepared.Template, error) {
	buf := rndr.getBuffer()
	defer rndr.putBuffer(buf)

	err := rndr.renderTemplate(&tpl, buf)
	if err != nil {
		return nil, err
	}

	return preparedTemplate{tpl: buf.String()}, nil
}

// MustPrepare prerenders the template and panics in case of parsing error.
func (rndr *Renderer) MustPrepare(tpl string) (pt prepared.Template) {
	buf := rndr.getBuffer()
	defer rndr.putBuffer(buf)

	err := rndr.renderTemplate(&tpl, buf)
	if err != nil {
		panic(err)
	}

	return preparedTemplate{tpl: buf.String()}
}

func (rndr *Renderer) getBuffer() *bytesBuffer {
	rndr.mutex.Lock()
	defer rndr.mutex.Unlock()

	return rndr.pool.Get().(*bytesBuffer)
}

func (rndr *Renderer) putBuffer(buf *bytesBuffer) {
	rndr.mutex.Lock()
	defer rndr.mutex.Unlock()

	buf.Buffer.Reset()
	rndr.pool.Put(buf)
}
<|endoftext|>


<commit_before>package main

/*
    TODO:
        - Read stdin line by line instead of all at once ( http://stackoverflow.com/questions/12363030/read-from-initial-stdin-in-go )
        - Make it use the CSV writer to write out the stuff instead of println
        - Use flag parsing to determine which field(s) to print out
        - Allow writing out the data with a different delimiter than what it came in with
*/

import (
    //"bufio"
    "encoding/csv"
    "flag"
    "fmt"
    "io"
    "io/ioutil"
    "os"
    "strconv"
    "strings"
    "unicode/utf8"
)

var separator = flag.String("separator", ",", "Single character to be used as a separator between fields")
var fieldNumsRaw = flag.String("fieldNums", "", "Comma-separated list of field indexes (starting at 0) to print to the command line")

var noPrintRealCSV = flag.Bool("noPrintCSV", false, "Program defaults to printing valid, quoted, well-formatted CSV. If this flag is supplied, output is returned as a string joined by outJoinStr. noPrintCSV is assumed to imply you want to pass the output to naive tools like cut or awk.")
var outputJoiner = flag.String("outJoinStr", ",", "Separator to use when printing multiple columns in your output. Only valid if outputting something meant to be passed to cut/awk, and not a properly-formatted, quoted CSV file.")

func main() {
    flag.Parse()

    var fieldNums []int

    if *fieldNumsRaw != "" {
        for _, numStr := range strings.Split(*fieldNumsRaw, ",") {
            numStr := strings.TrimSpace(numStr)
            numInt, err := strconv.Atoi(numStr)
            if err != nil {
                panic(err)
            }
            fieldNums = append(fieldNums, numInt)
        }
    }

    // TODO: Make this stream from stdin, and also stream from a file
    bytes, err := ioutil.ReadAll(os.Stdin)
    if err != nil {
        panic(err)
    }

    lines := strings.Split(string(bytes), "\n")

    csvWriter := csv.NewWriter(os.Stdout)

    for _, line := range lines {
        fields, err := processLine(line)
        if err != nil {
            if err == io.EOF {
                break
            } else {
                panic(err)
            }
        }

        var toPrint []string
        if *fieldNumsRaw == "" {
            for i, _ := range fields {
                toPrint = append(toPrint, fields[i])
            }
        } else {
            for _, num := range fieldNums {
                toPrint = append(toPrint, fields[num])
            }
        }

        if *noPrintRealCSV == false {
            csvWriter.Write(toPrint)
        } else {
            fmt.Println(strings.Join(toPrint, *outputJoiner))
        }
    }
    if *noPrintRealCSV == false {
        csvWriter.Flush()
    }
}

func processLine(line string) ([]string, error) {
    strReader := strings.NewReader(line)
    csvReader := csv.NewReader(strReader)

    sepString := *separator
    /*
    fmt.Println("Separator is", string(sepString[0]))
    fmt.Println("'", rune(sepString[0]), "'")
    fmt.Println("'", string(rune("\t"[0])), "'")
    r, size := utf8.DecodeRuneInString(sepString)
    fmt.Println("'", string(r), "'")
    fmt.Println(size)
    */
    _ = utf8.DecodeRuneInString

    csvReader.Comma = rune(sepString[0])

    fields, err := csvReader.Read()
    if err != nil {
        if err == io.EOF {
            return nil, io.EOF
        } else {
            panic(err)
        }
    }

    return fields, nil
}
<commit_msg>Program now reads '\t' string as separator, instead of requiring literal tab to be passed in. Program also actually honors the output separator for CSV writing.<commit_after>package main

import (
    //"bufio"
    "encoding/csv"
    "flag"
    "fmt"
    "io"
    "io/ioutil"
    "os"
    "strconv"
    "strings"
    "unicode/utf8"
)

var separator = flag.String("separator", ",", "Single character to be used as a separator between fields")
var fieldNumsRaw = flag.String("fieldNums", "", "Comma-separated list of field indexes (starting at 0) to print to the command line")

var noPrintRealCSV = flag.Bool("noPrintCSV", false, "Program defaults to printing valid, quoted, well-formatted CSV. If this flag is supplied, output is returned as a string joined by outJoinStr. noPrintCSV is assumed to imply you want to pass the output to naive tools like cut or awk.")
var outputJoiner = flag.String("outJoinStr", ",", "Separator to use when printing multiple columns in your output. Only valid if outputting something meant to be passed to cut/awk, and not a properly-formatted, quoted CSV file.")

func main() {
    flag.Parse()

    var fieldNums []int

    if *fieldNumsRaw != "" {
        for _, numStr := range strings.Split(*fieldNumsRaw, ",") {
            numStr := strings.TrimSpace(numStr)
            numInt, err := strconv.Atoi(numStr)
            if err != nil {
                panic(err)
            }
            fieldNums = append(fieldNums, numInt)
        }
    }

    // TODO: Make this stream from stdin, and also stream from a file
    bytes, err := ioutil.ReadAll(os.Stdin)
    if err != nil {
        panic(err)
    }

    lines := strings.Split(string(bytes), "\n")

    csvWriter := csv.NewWriter(os.Stdout)
    outSepStr := `'` + *outputJoiner + `'`
    outSepRunes, err := strconv.Unquote(outSepStr)
    if err != nil {
        panic(err)
    }
    outSepRune := ([]rune(outSepRunes))[0]
    csvWriter.Comma = outSepRune

    for _, line := range lines {
        fields, err := processLine(line)
        if err != nil {
            if err == io.EOF {
                break
            } else {
                panic(err)
            }
        }

        var toPrint []string
        if *fieldNumsRaw == "" {
            for i, _ := range fields {
                toPrint = append(toPrint, fields[i])
            }
        } else {
            for _, num := range fieldNums {
                toPrint = append(toPrint, fields[num])
            }
        }

        if *noPrintRealCSV == false {
            csvWriter.Write(toPrint)
        } else {
            fmt.Println(strings.Join(toPrint, *outputJoiner))
        }
    }
    if *noPrintRealCSV == false {
        csvWriter.Flush()
    }
    fmt.Println("Output string is", *outputJoiner)
}

func processLine(line string) ([]string, error) {
    strReader := strings.NewReader(line)
    csvReader := csv.NewReader(strReader)

    sepString := *separator
    /*
    fmt.Println("Separator is", string(sepString[0]))
    fmt.Println("'", rune(sepString[0]), "'")
    fmt.Println("'", string(rune("\t"[0])), "'")
    r, size := utf8.DecodeRuneInString(sepString)
    fmt.Println("'", string(r), "'")
    fmt.Println(size)
    */
    _ = utf8.DecodeRuneInString
    _ = sepString
    sepString = `'` + sepString + `'`
    sepRunes, err := strconv.Unquote(sepString)
    if err != nil {
        panic(err)
    }
    sepRune := ([]rune(sepRunes))[0]

    csvReader.Comma = rune(sepRune)

    fields, err := csvReader.Read()
    if err != nil {
        if err == io.EOF {
            return nil, io.EOF
        } else {
            panic(err)
        }
    }

    return fields, nil
}
<|endoftext|>


<commit_before>// Copyright 2016 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package data

import (
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"github.com/caixw/typing/helper"
	"github.com/caixw/typing/vars"
	"github.com/issue9/utils"
)

// 文章是否过时的比较方式
const (
	outdatedTypeCreated  = "created"  // 以创建时间作为对比
	outdatedTypeModified = "modified" // 以修改时间作为对比
)

// 表示 Post.Order 的各类值
const (
	orderTop     = "top"     // 置顶
	orderLast    = "last"    // 放在尾部
	orderDefault = "default" // 默认情况
)

// 描述过时文章的提示信息。
//
// 理论上把有关 outdatedConfig 的信息，直接在模板中对文章的创建时间戳进行比较，
// 是比通过配置来比较会更加方便，也不会更任何的后期工作量。之所以把这个功能放在后端，
// 而不是模板层面，是因为觉得模板应该只负责展示页面，而不是用于处理逻辑内容。
type outdatedConfig struct {
	Type     string        `yaml:"type"`     // 比较的类型，创建时间或是修改时间
	Duration time.Duration `yaml:"duration"` // 超时的时间，可以使用 time.Duration 的字符串值
	Content  string        `yaml:"content"`  // 提示的内容，普通文字，不能为 html
}

// Post 表示文章的信息
type Post struct {
	Slug       string    `yaml:"-"`               // 唯一名称
	Title      string    `yaml:"title"`           // 标题
	Created    time.Time `yaml:"-"`               // 创建时间
	Modified   time.Time `yaml:"-"`               // 修改时间
	Tags       []*Tag    `yaml:"-"`               // 关联的标签
	Summary    string    `yaml:"summary"`         // 摘要，同时也作为 meta.description 的内容
	Content    string    `yaml:"-"`               // 内容
	TagsString string    `yaml:"tags"`            // 关联标签的列表
	Permalink  string    `yaml:"created"`         // 文章的唯一链接，同时当作 created 的原始值
	Outdated   string    `yaml:"modified"`        // 已过时文章的提示信息，同时当作 modified 的原始值
	Order      string    `yaml:"order,omitempty"` // 排序方式
	Draft      bool      `yaml:"draft,omitempty"` // 是否为草稿，为 true，则不会加载该条数据

	// 以下内容不存在时，则会使用全局的默认选项
	Author   *Author `yaml:"author,omitempty"`   // 作者
	License  *Link   `yaml:"license,omitempty"`  // 版本信息
	Template string  `yaml:"template,omitempty"` // 使用的模板
	Keywords string  `yaml:"keywords,omitempty"` // meta.keywords 标签的内容，如果为空，使用 tags
}

func loadPosts(path *vars.Path) ([]*Post, error) {
	dir := path.PostsDir
	slugs := make([]string, 0, 100)

	// 遍历 data/posts 目录，查找所有的文章。
	walk := func(p string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if !info.IsDir() {
			return nil
		}

		postsDir := filepath.Clean(path.PostsDir)
		slug := strings.TrimPrefix(p, postsDir) // 获取相对于 data/posts 的名称
		slug = strings.Trim(filepath.ToSlash(slug), "/")

		if utils.FileExists(path.PostContentPath(slug)) &&
			utils.FileExists(path.PostMetaPath(slug)) {
			slugs = append(slugs, slug)
		}
		return nil
	}

	if err := filepath.Walk(dir, walk); err != nil {
		return nil, err
	}

	// 开始加载文章的具体内容。
	posts := make([]*Post, 0, len(slugs))
	for _, p := range slugs {
		p = filepath.Clean(p)
		post, err := loadPost(path, p)
		if err != nil {
			return nil, err
		}

		if !post.Draft {
			posts = append(posts, post)
		}
	}

	if err := checkPostsDup(posts); err != nil {
		return nil, err
	}

	sortPosts(posts)

	return posts, nil
}

func loadPost(path *vars.Path, slug string) (*Post, error) {
	post := &Post{}
	if err := helper.LoadYAMLFile(path.PostMetaPath(slug), post); err != nil {
		return nil, err
	}
	if post.Draft {
		return post, nil
	}

	// slug
	post.Slug = slug

	// 加载内容
	data, err := ioutil.ReadFile(path.PostContentPath(slug))
	if err != nil {
		return nil, &helper.FieldError{File: path.PostMetaPath(slug), Message: err.Error(), Field: "path"}
	}
	if len(data) == 0 {
		return nil, &helper.FieldError{File: path.PostMetaPath(slug), Message: "不能为空", Field: "content"}
	}
	post.Content = string(data)

	// created
	// permalink 还用作其它功能，需要首先解析其值
	created, err := time.Parse(vars.DateFormat, post.Permalink)
	if err != nil {
		return nil, &helper.FieldError{File: path.PostMetaPath(slug), Message: err.Error(), Field: "created"}
	}
	post.Created = created

	// permalink
	post.Permalink = vars.PostURL(post.Slug)

	// modified
	// outdated 还用作其它功能，需要首先解析其值
	modified, err := time.Parse(vars.DateFormat, post.Outdated)
	if err != nil {
		return nil, &helper.FieldError{File: path.PostMetaPath(slug), Message: err.Error(), Field: "modified"}
	}
	post.Modified = modified
	post.Outdated = ""

	if len(post.Title) == 0 {
		return nil, &helper.FieldError{File: path.PostMetaPath(slug), Message: "不能为空", Field: "title"}
	}

	if len(post.TagsString) == 0 {
		return nil, &helper.FieldError{File: path.PostMetaPath(slug), Message: "不能为空", Field: "tags"}
	}

	// keywords
	if len(post.Keywords) == 0 && len(post.Tags) > 0 {
		keywords := make([]string, 0, len(post.Tags))
		for _, v := range post.Tags {
			keywords = append(keywords, v.Title)
		}
		post.Keywords = strings.Join(keywords, ",")
	}

	// template
	if len(post.Template) == 0 {
		post.Template = vars.PostTemplateName
	}

	// order
	if len(post.Order) == 0 {
		post.Order = orderDefault
	} else if post.Order != orderDefault && post.Order != orderLast && post.Order != orderTop {
		return nil, &helper.FieldError{File: path.PostMetaPath(slug), Message: "无效的值", Field: "order"}
	}

	return post, nil
}

// 检测是否存在同名的文章
func checkPostsDup(posts []*Post) error {
	count := func(slug string) (cnt int) {
		for _, post := range posts {
			if post.Slug == slug {
				cnt++
			}
		}
		return cnt
	}

	for _, post := range posts {
		if count(post.Slug) > 1 {
			return errors.New("存在同名的文章：" + post.Slug)
		}
	}

	return nil
}

// 对文章进行排序，需保证 created 已经被初始化
func sortPosts(posts []*Post) {
	sort.SliceStable(posts, func(i, j int) bool {
		switch {
		case (posts[i].Order == orderTop) || (posts[j].Order == orderLast):
			return true
		case (posts[i].Order == orderLast) || (posts[j].Order == orderTop):
			return false
		default:
			return posts[i].Created.After(posts[j].Created)
		}
	})
}

func (o *outdatedConfig) sanitize() *helper.FieldError {
	if o.Type != outdatedTypeCreated && o.Type != outdatedTypeModified {
		return &helper.FieldError{Message: "无效的值", Field: "outdated.type"}
	}

	if len(o.Content) == 0 {
		return &helper.FieldError{Message: "不能为空", Field: "outdated.content"}
	}

	return nil
}
<commit_msg>去掉不再需要的 filepath.Clean<commit_after>// Copyright 2016 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package data

import (
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"github.com/caixw/typing/helper"
	"github.com/caixw/typing/vars"
	"github.com/issue9/utils"
)

// 文章是否过时的比较方式
const (
	outdatedTypeCreated  = "created"  // 以创建时间作为对比
	outdatedTypeModified = "modified" // 以修改时间作为对比
)

// 表示 Post.Order 的各类值
const (
	orderTop     = "top"     // 置顶
	orderLast    = "last"    // 放在尾部
	orderDefault = "default" // 默认情况
)

// 描述过时文章的提示信息。
//
// 理论上把有关 outdatedConfig 的信息，直接在模板中对文章的创建时间戳进行比较，
// 是比通过配置来比较会更加方便，也不会更任何的后期工作量。之所以把这个功能放在后端，
// 而不是模板层面，是因为觉得模板应该只负责展示页面，而不是用于处理逻辑内容。
type outdatedConfig struct {
	Type     string        `yaml:"type"`     // 比较的类型，创建时间或是修改时间
	Duration time.Duration `yaml:"duration"` // 超时的时间，可以使用 time.Duration 的字符串值
	Content  string        `yaml:"content"`  // 提示的内容，普通文字，不能为 html
}

// Post 表示文章的信息
type Post struct {
	Slug       string    `yaml:"-"`               // 唯一名称
	Title      string    `yaml:"title"`           // 标题
	Created    time.Time `yaml:"-"`               // 创建时间
	Modified   time.Time `yaml:"-"`               // 修改时间
	Tags       []*Tag    `yaml:"-"`               // 关联的标签
	Summary    string    `yaml:"summary"`         // 摘要，同时也作为 meta.description 的内容
	Content    string    `yaml:"-"`               // 内容
	TagsString string    `yaml:"tags"`            // 关联标签的列表
	Permalink  string    `yaml:"created"`         // 文章的唯一链接，同时当作 created 的原始值
	Outdated   string    `yaml:"modified"`        // 已过时文章的提示信息，同时当作 modified 的原始值
	Order      string    `yaml:"order,omitempty"` // 排序方式
	Draft      bool      `yaml:"draft,omitempty"` // 是否为草稿，为 true，则不会加载该条数据

	// 以下内容不存在时，则会使用全局的默认选项
	Author   *Author `yaml:"author,omitempty"`   // 作者
	License  *Link   `yaml:"license,omitempty"`  // 版本信息
	Template string  `yaml:"template,omitempty"` // 使用的模板
	Keywords string  `yaml:"keywords,omitempty"` // meta.keywords 标签的内容，如果为空，使用 tags
}

func loadPosts(path *vars.Path) ([]*Post, error) {
	dir := path.PostsDir
	slugs := make([]string, 0, 100)

	// 遍历 data/posts 目录，查找所有的文章。
	walk := func(p string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if !info.IsDir() {
			return nil
		}

		postsDir := filepath.Clean(path.PostsDir)
		slug := strings.TrimPrefix(p, postsDir) // 获取相对于 data/posts 的名称
		slug = strings.Trim(filepath.ToSlash(slug), "/")

		if utils.FileExists(path.PostContentPath(slug)) &&
			utils.FileExists(path.PostMetaPath(slug)) {
			slugs = append(slugs, slug)
		}
		return nil
	}

	if err := filepath.Walk(dir, walk); err != nil {
		return nil, err
	}

	// 开始加载文章的具体内容。
	posts := make([]*Post, 0, len(slugs))
	for _, slug := range slugs {
		post, err := loadPost(path, slug)
		if err != nil {
			return nil, err
		}

		if !post.Draft {
			posts = append(posts, post)
		}
	}

	if err := checkPostsDup(posts); err != nil {
		return nil, err
	}

	sortPosts(posts)

	return posts, nil
}

func loadPost(path *vars.Path, slug string) (*Post, error) {
	post := &Post{}
	if err := helper.LoadYAMLFile(path.PostMetaPath(slug), post); err != nil {
		return nil, err
	}
	if post.Draft {
		return post, nil
	}

	// slug
	post.Slug = slug

	// 加载内容
	data, err := ioutil.ReadFile(path.PostContentPath(slug))
	if err != nil {
		return nil, &helper.FieldError{File: path.PostMetaPath(slug), Message: err.Error(), Field: "path"}
	}
	if len(data) == 0 {
		return nil, &helper.FieldError{File: path.PostMetaPath(slug), Message: "不能为空", Field: "content"}
	}
	post.Content = string(data)

	// created
	// permalink 还用作其它功能，需要首先解析其值
	created, err := time.Parse(vars.DateFormat, post.Permalink)
	if err != nil {
		return nil, &helper.FieldError{File: path.PostMetaPath(slug), Message: err.Error(), Field: "created"}
	}
	post.Created = created

	// permalink
	post.Permalink = vars.PostURL(post.Slug)

	// modified
	// outdated 还用作其它功能，需要首先解析其值
	modified, err := time.Parse(vars.DateFormat, post.Outdated)
	if err != nil {
		return nil, &helper.FieldError{File: path.PostMetaPath(slug), Message: err.Error(), Field: "modified"}
	}
	post.Modified = modified
	post.Outdated = ""

	if len(post.Title) == 0 {
		return nil, &helper.FieldError{File: path.PostMetaPath(slug), Message: "不能为空", Field: "title"}
	}

	if len(post.TagsString) == 0 {
		return nil, &helper.FieldError{File: path.PostMetaPath(slug), Message: "不能为空", Field: "tags"}
	}

	// keywords
	if len(post.Keywords) == 0 && len(post.Tags) > 0 {
		keywords := make([]string, 0, len(post.Tags))
		for _, v := range post.Tags {
			keywords = append(keywords, v.Title)
		}
		post.Keywords = strings.Join(keywords, ",")
	}

	// template
	if len(post.Template) == 0 {
		post.Template = vars.PostTemplateName
	}

	// order
	if len(post.Order) == 0 {
		post.Order = orderDefault
	} else if post.Order != orderDefault && post.Order != orderLast && post.Order != orderTop {
		return nil, &helper.FieldError{File: path.PostMetaPath(slug), Message: "无效的值", Field: "order"}
	}

	return post, nil
}

// 检测是否存在同名的文章
func checkPostsDup(posts []*Post) error {
	count := func(slug string) (cnt int) {
		for _, post := range posts {
			if post.Slug == slug {
				cnt++
			}
		}
		return cnt
	}

	for _, post := range posts {
		if count(post.Slug) > 1 {
			return errors.New("存在同名的文章：" + post.Slug)
		}
	}

	return nil
}

// 对文章进行排序，需保证 created 已经被初始化
func sortPosts(posts []*Post) {
	sort.SliceStable(posts, func(i, j int) bool {
		switch {
		case (posts[i].Order == orderTop) || (posts[j].Order == orderLast):
			return true
		case (posts[i].Order == orderLast) || (posts[j].Order == orderTop):
			return false
		default:
			return posts[i].Created.After(posts[j].Created)
		}
	})
}

func (o *outdatedConfig) sanitize() *helper.FieldError {
	if o.Type != outdatedTypeCreated && o.Type != outdatedTypeModified {
		return &helper.FieldError{Message: "无效的值", Field: "outdated.type"}
	}

	if len(o.Content) == 0 {
		return &helper.FieldError{Message: "不能为空", Field: "outdated.content"}
	}

	return nil
}
<|endoftext|>