<commit_before>package api

import (
	"encoding/base64"
	"encoding/json"
)

// CertificateTypeClient indicates a client certificate type.
const CertificateTypeClient = "client"

// CertificateTypeServer indicates a server certificate type.
const CertificateTypeServer = "server"

// CertificateTypeMetrics indicates a metrics certificate type.
const CertificateTypeMetrics = "metrics"

// CertificateTypeUnknown indicates an unknown certificate type.
const CertificateTypeUnknown = "unknown"

// CertificatesPost represents the fields of a new LXD certificate
//
// swagger:model
type CertificatesPost struct {
	CertificatePut `yaml:",inline"`

	// Server trust password (used to add an untrusted client)
	// Example: blah
	Password string `json:"password" yaml:"password"`

	// Whether to create a certificate add token
	// Example: true
	//
	// API extension: certificate_token
	Token bool `json:"token" yaml:"token"`
}

// CertificatePut represents the modifiable fields of a LXD certificate
//
// swagger:model
//
// API extension: certificate_update
type CertificatePut struct {
	// Name associated with the certificate
	// Example: castiana
	Name string `json:"name" yaml:"name"`

	// Usage type for the certificate (only client currently)
	// Example: client
	Type string `json:"type" yaml:"type"`

	// Whether to limit the certificate to listed projects
	// Example: true
	//
	// API extension: certificate_project
	Restricted bool `json:"restricted" yaml:"restricted"`

	// List of allowed projects (applies when restricted)
	// Example: ["default", "foo", "bar"]
	//
	// API extension: certificate_project
	Projects []string `json:"projects" yaml:"projects"`

	// The certificate itself, as PEM encoded X509
	// Example: X509 PEM certificate
	//
	// API extension: certificate_self_renewal
	Certificate string `json:"certificate" yaml:"certificate"`
}

// Certificate represents a LXD certificate
//
// swagger:model
type Certificate struct {
	CertificatePut `yaml:",inline"`

	// SHA256 fingerprint of the certificate
	// Read only: true
	// Example: fd200419b271f1dc2a5591b693cc5774b7f234e1ff8c6b78ad703b6888fe2b69
	Fingerprint string `json:"fingerprint" yaml:"fingerprint"`
}

// Writable converts a full Certificate struct into a CertificatePut struct (filters read-only fields)
func (cert *Certificate) Writable() CertificatePut {
	return cert.CertificatePut
}

// CertificateAddToken represents the fields contained within an encoded certificate add token.
//
// swagger:model
//
// API extension: certificate_token
type CertificateAddToken struct {
	// The name of the new client
	// Example: user@host
	ClientName string `json:"client_name" yaml:"client_name"`

	// The fingerprint of the network certificate
	// Example: 57bb0ff4340b5bb28517e062023101adf788c37846dc8b619eb2c3cb4ef29436
	Fingerprint string `json:"fingerprint" yaml:"fingerprint"`

	// The addresses of the server
	// Example: ["10.98.30.229:8443"]
	Addresses []string `json:"addresses" yaml:"addresses"`

	// The random join secret
	// Example: 2b2284d44db32675923fe0d2020477e0e9be11801ff70c435e032b97028c35cd
	Secret string `json:"secret" yaml:"secret"`
}

// String encodes the certificate add token as JSON and then base64.
func (t *CertificateAddToken) String() string {
	joinTokenJSON, err := json.Marshal(t)
	if err != nil {
		return ""
	}

	return base64.StdEncoding.EncodeToString(joinTokenJSON)
}
<commit_msg>shared/api: nowadays various types of certs are accepted<commit_after>package api

import (
	"encoding/base64"
	"encoding/json"
)

// CertificateTypeClient indicates a client certificate type.
const CertificateTypeClient = "client"

// CertificateTypeServer indicates a server certificate type.
const CertificateTypeServer = "server"

// CertificateTypeMetrics indicates a metrics certificate type.
const CertificateTypeMetrics = "metrics"

// CertificateTypeUnknown indicates an unknown certificate type.
const CertificateTypeUnknown = "unknown"

// CertificatesPost represents the fields of a new LXD certificate
//
// swagger:model
type CertificatesPost struct {
	CertificatePut `yaml:",inline"`

	// Server trust password (used to add an untrusted client)
	// Example: blah
	Password string `json:"password" yaml:"password"`

	// Whether to create a certificate add token
	// Example: true
	//
	// API extension: certificate_token
	Token bool `json:"token" yaml:"token"`
}

// CertificatePut represents the modifiable fields of a LXD certificate
//
// swagger:model
//
// API extension: certificate_update
type CertificatePut struct {
	// Name associated with the certificate
	// Example: castiana
	Name string `json:"name" yaml:"name"`

	// Usage type for the certificate
	// Example: client
	Type string `json:"type" yaml:"type"`

	// Whether to limit the certificate to listed projects
	// Example: true
	//
	// API extension: certificate_project
	Restricted bool `json:"restricted" yaml:"restricted"`

	// List of allowed projects (applies when restricted)
	// Example: ["default", "foo", "bar"]
	//
	// API extension: certificate_project
	Projects []string `json:"projects" yaml:"projects"`

	// The certificate itself, as PEM encoded X509
	// Example: X509 PEM certificate
	//
	// API extension: certificate_self_renewal
	Certificate string `json:"certificate" yaml:"certificate"`
}

// Certificate represents a LXD certificate
//
// swagger:model
type Certificate struct {
	CertificatePut `yaml:",inline"`

	// SHA256 fingerprint of the certificate
	// Read only: true
	// Example: fd200419b271f1dc2a5591b693cc5774b7f234e1ff8c6b78ad703b6888fe2b69
	Fingerprint string `json:"fingerprint" yaml:"fingerprint"`
}

// Writable converts a full Certificate struct into a CertificatePut struct (filters read-only fields)
func (cert *Certificate) Writable() CertificatePut {
	return cert.CertificatePut
}

// CertificateAddToken represents the fields contained within an encoded certificate add token.
//
// swagger:model
//
// API extension: certificate_token
type CertificateAddToken struct {
	// The name of the new client
	// Example: user@host
	ClientName string `json:"client_name" yaml:"client_name"`

	// The fingerprint of the network certificate
	// Example: 57bb0ff4340b5bb28517e062023101adf788c37846dc8b619eb2c3cb4ef29436
	Fingerprint string `json:"fingerprint" yaml:"fingerprint"`

	// The addresses of the server
	// Example: ["10.98.30.229:8443"]
	Addresses []string `json:"addresses" yaml:"addresses"`

	// The random join secret
	// Example: 2b2284d44db32675923fe0d2020477e0e9be11801ff70c435e032b97028c35cd
	Secret string `json:"secret" yaml:"secret"`
}

// String encodes the certificate add token as JSON and then base64.
func (t *CertificateAddToken) String() string {
	joinTokenJSON, err := json.Marshal(t)
	if err != nil {
		return ""
	}

	return base64.StdEncoding.EncodeToString(joinTokenJSON)
}
<|endoftext|>


<commit_before>package controllers

import (
	"github.com/UserStack/ustackweb/models"
	"github.com/astaxie/beego"
)

type InstallController struct {
	BaseController
}

type PermissionRequirement struct {
	Name     string
	Exists   bool
	Assigned bool
}

func (this *InstallController) rootUserId() string {
	return "admin"
}

func (this *InstallController) Index() {
	this.Layout = "layouts/default.html.tpl"
	this.TplNames = "config/index.html.tpl"
	rootUser, err := models.Users().FindByName(this.rootUserId())
	this.Data["rootUserError"] = err
	this.Data["rootUser"] = rootUser
	groups, err := models.Groups().All()
	this.Data["groupsError"] = err
	userGroups, err := models.Groups().AllByUser(this.rootUserId())
	this.Data["userGroupsError"] = err
	permissionRequirements := this.permissionRequirements()
	for _, permissionRequirement := range permissionRequirements {
		for _, group := range groups {
			if group.Name == permissionRequirement.Name {
				permissionRequirement.Exists = true
				break
			}
		}
		for _, userGroup := range userGroups {
			if userGroup.Name == permissionRequirement.Name {
				permissionRequirement.Assigned = true
				break
			}
		}
	}
	this.Data["permissionRequirements"] = permissionRequirements
}

func (this *InstallController) CreateRootUser() {
	models.Users().Create("admin", "admin")
	this.Redirect(beego.UrlFor("InstallController.Index"), 302)
}

func (this *InstallController) CreatePermissions() {
	permissionRequirements := this.permissionRequirements()
	for _, permissionRequirement := range permissionRequirements {
		models.Groups().Create(permissionRequirement.Name)
	}
	this.Redirect(beego.UrlFor("InstallController.Index"), 302)
}

func (this *InstallController) AssignPermissions() {
	permissionRequirements := this.permissionRequirements()
	for _, permissionRequirement := range permissionRequirements {
		models.Users().AddUserToGroup(this.rootUserId(), permissionRequirement.Name)
	}
	this.Redirect(beego.UrlFor("InstallController.Index"), 302)
}

func (this *InstallController) permissionRequirements() (permissionRequirements []*PermissionRequirement) {
	permissionRequirements = []*PermissionRequirement{
		&PermissionRequirement{Name: "perm.user.list"},
		&PermissionRequirement{Name: "perm.user.read"},
		&PermissionRequirement{Name: "perm.user.write"},
	}
	return
}
<commit_msg>Move permissions to top.,<commit_after>package controllers

import (
	"github.com/UserStack/ustackweb/models"
	"github.com/astaxie/beego"
)

type InstallController struct {
	BaseController
}

type PermissionRequirement struct {
	Name     string
	Exists   bool
	Assigned bool
}

func (this *InstallController) rootUserId() string {
	return "admin"
}

func (this *InstallController) permissionRequirements() (permissionRequirements []*PermissionRequirement) {
	permissionRequirements = []*PermissionRequirement{
		&PermissionRequirement{Name: "perm.user.list"},
		&PermissionRequirement{Name: "perm.user.read"},
		&PermissionRequirement{Name: "perm.user.write"},
	}
	return
}

func (this *InstallController) Index() {
	this.Layout = "layouts/default.html.tpl"
	this.TplNames = "config/index.html.tpl"
	rootUser, err := models.Users().FindByName(this.rootUserId())
	this.Data["rootUserError"] = err
	this.Data["rootUser"] = rootUser
	groups, err := models.Groups().All()
	this.Data["groupsError"] = err
	userGroups, err := models.Groups().AllByUser(this.rootUserId())
	this.Data["userGroupsError"] = err
	permissionRequirements := this.permissionRequirements()
	for _, permissionRequirement := range permissionRequirements {
		for _, group := range groups {
			if group.Name == permissionRequirement.Name {
				permissionRequirement.Exists = true
				break
			}
		}
		for _, userGroup := range userGroups {
			if userGroup.Name == permissionRequirement.Name {
				permissionRequirement.Assigned = true
				break
			}
		}
	}
	this.Data["permissionRequirements"] = permissionRequirements
}

func (this *InstallController) CreateRootUser() {
	models.Users().Create("admin", "admin")
	this.Redirect(beego.UrlFor("InstallController.Index"), 302)
}

func (this *InstallController) CreatePermissions() {
	permissionRequirements := this.permissionRequirements()
	for _, permissionRequirement := range permissionRequirements {
		models.Groups().Create(permissionRequirement.Name)
	}
	this.Redirect(beego.UrlFor("InstallController.Index"), 302)
}

func (this *InstallController) AssignPermissions() {
	permissionRequirements := this.permissionRequirements()
	for _, permissionRequirement := range permissionRequirements {
		models.Users().AddUserToGroup(this.rootUserId(), permissionRequirement.Name)
	}
	this.Redirect(beego.UrlFor("InstallController.Index"), 302)
}
<|endoftext|>


<commit_before>package client

import (
	"context"
	"fmt"
	"os"
	"time"

	"google.golang.org/grpc"
)

const (
	// ConnectorSocketName is the path used when communicating to the connector process
	ConnectorSocketName = "/tmp/telepresence-connector.socket"

	// DaemonSocketName is the path used when communicating to the daemon process
	DaemonSocketName = "/var/run/telepresence-daemon.socket"
)

// SocketExists returns true if a socket is found at the given path
func SocketExists(path string) bool {
	s, err := os.Stat(path)
	return err == nil && s.Mode()&os.ModeSocket != 0
}

// WaitUntilSocketVanishes waits until the socket at the given path is removed
// and returns when that happens. The wait will be max ttw (time to wait) long.
// An error is returned if that time is exceeded before the socket is removed.
func WaitUntilSocketVanishes(name, path string, ttw time.Duration) (err error) {
	giveUp := time.Now().Add(ttw)
	for giveUp.After(time.Now()) {
		_, err = os.Stat(path)
		if err != nil {
			if os.IsNotExist(err) {
				err = nil
			}
			return err
		}
		time.Sleep(250 * time.Millisecond)
	}
	return fmt.Errorf("timeout while waiting for %s to exit", name)
}

// WaitUntilSocketAppears waits until the socket at the given path comes into
// existence and returns when that happens. The wait will be max ttw (time to wait) long.
// An error is returned if that time is exceeded before the socket is removed.
func WaitUntilSocketAppears(name, path string, ttw time.Duration) (err error) {
	giveUp := time.Now().Add(ttw)
	for giveUp.After(time.Now()) {
		_, err = os.Stat(path)
		if err == nil {
			return
		}
		if !os.IsNotExist(err) {
			return err
		}
		time.Sleep(250 * time.Millisecond)
	}
	return fmt.Errorf("timeout while waiting for %s to exit", name)
}

// SocketURL returns the URL that corresponds to the given unix socket filesystem path.
func SocketURL(socket string) string {
	// The unix URL scheme was implemented in google.golang.org/grpc v1.34.0
	return "unix:" + socket
}

// DialSocket dials the given unix socket and returns the resulting connection
func DialSocket(c context.Context, socketName string) (*grpc.ClientConn, error) {
	return grpc.DialContext(c, SocketURL(socketName), grpc.WithInsecure(), grpc.WithNoProxy())
}
<commit_msg>Fix typo "exit" -> "start" when waiting for Unix socket to appear.<commit_after>package client

import (
	"context"
	"fmt"
	"os"
	"time"

	"google.golang.org/grpc"
)

const (
	// ConnectorSocketName is the path used when communicating to the connector process
	ConnectorSocketName = "/tmp/telepresence-connector.socket"

	// DaemonSocketName is the path used when communicating to the daemon process
	DaemonSocketName = "/var/run/telepresence-daemon.socket"
)

// SocketExists returns true if a socket is found at the given path
func SocketExists(path string) bool {
	s, err := os.Stat(path)
	return err == nil && s.Mode()&os.ModeSocket != 0
}

// WaitUntilSocketVanishes waits until the socket at the given path is removed
// and returns when that happens. The wait will be max ttw (time to wait) long.
// An error is returned if that time is exceeded before the socket is removed.
func WaitUntilSocketVanishes(name, path string, ttw time.Duration) (err error) {
	giveUp := time.Now().Add(ttw)
	for giveUp.After(time.Now()) {
		_, err = os.Stat(path)
		if err != nil {
			if os.IsNotExist(err) {
				err = nil
			}
			return err
		}
		time.Sleep(250 * time.Millisecond)
	}
	return fmt.Errorf("timeout while waiting for %s to exit", name)
}

// WaitUntilSocketAppears waits until the socket at the given path comes into
// existence and returns when that happens. The wait will be max ttw (time to wait) long.
// An error is returned if that time is exceeded before the socket is removed.
func WaitUntilSocketAppears(name, path string, ttw time.Duration) (err error) {
	giveUp := time.Now().Add(ttw)
	for giveUp.After(time.Now()) {
		_, err = os.Stat(path)
		if err == nil {
			return
		}
		if !os.IsNotExist(err) {
			return err
		}
		time.Sleep(250 * time.Millisecond)
	}
	return fmt.Errorf("timeout while waiting for %s to start", name)
}

// SocketURL returns the URL that corresponds to the given unix socket filesystem path.
func SocketURL(socket string) string {
	// The unix URL scheme was implemented in google.golang.org/grpc v1.34.0
	return "unix:" + socket
}

// DialSocket dials the given unix socket and returns the resulting connection
func DialSocket(c context.Context, socketName string) (*grpc.ClientConn, error) {
	return grpc.DialContext(c, SocketURL(socketName), grpc.WithInsecure(), grpc.WithNoProxy())
}
<|endoftext|>


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

package main

import (
	"go/build"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
)

func runTest(t *testing.T, path string) {
	exitCode = 0

	*recursive = false
	if suffix := ".go"; strings.HasSuffix(path, suffix) {
		// single file
		path = filepath.Join(runtime.GOROOT(), "src/pkg", path)
		path, file := filepath.Split(path)
		*pkgName = file[:len(file)-len(suffix)]
		processFiles([]string{path}, true)
	} else {
		// package directory
		// TODO(gri) gotype should use the build package instead
		pkg, err := build.Import(path, "", 0)
		if err != nil {
			t.Errorf("build.Import error for path = %s: %s", path, err)
			return
		}
		// TODO(gri) there ought to be a more direct way using the build package...
		files := make([]string, len(pkg.GoFiles))
		for i, file := range pkg.GoFiles {
			files[i] = filepath.Join(pkg.Dir, file)
		}
		*pkgName = pkg.Name
		processFiles(files, true)
	}

	if exitCode != 0 {
		t.Errorf("processing %s failed: exitCode = %d", path, exitCode)
	}
}

var tests = []string{
	// individual files
	"exp/gotype/testdata/test1.go",

	// directories
	// Note: packages that don't typecheck yet are commented out
	"archive/tar",
	"archive/zip",

	"bufio",
	"bytes",

	"compress/bzip2",
	"compress/flate",
	"compress/gzip",
	"compress/lzw",
	"compress/zlib",

	"container/heap",
	"container/list",
	"container/ring",

	"crypto",
	"crypto/aes",
	"crypto/cipher",
	"crypto/des",
	"crypto/dsa",
	"crypto/ecdsa",
	"crypto/elliptic",
	"crypto/hmac",
	"crypto/md5",
	"crypto/rand",
	"crypto/rc4",
	// "crypto/rsa", // src/pkg/crypto/rsa/pkcs1v15.go:21:27: undeclared name: io
	"crypto/sha1",
	"crypto/sha256",
	"crypto/sha512",
	"crypto/subtle",
	"crypto/tls",
	// "crypto/x509", // src/pkg/crypto/x509/root.go:15:10: undeclared name: initSystemRoots
	"crypto/x509/pkix",

	"database/sql",
	"database/sql/driver",

	"debug/dwarf",
	"debug/elf",
	"debug/gosym",
	"debug/macho",
	"debug/pe",

	"encoding/ascii85",
	"encoding/asn1",
	"encoding/base32",
	"encoding/base64",
	"encoding/binary",
	"encoding/csv",
	"encoding/gob",
	"encoding/hex",
	"encoding/json",
	"encoding/pem",
	"encoding/xml",

	"errors",
	"expvar",
	"flag",
	"fmt",

	"exp/types",
	"exp/gotype",

	"go/ast",
	"go/build",
	"go/doc",
	"go/format",
	"go/parser",
	"go/printer",
	"go/scanner",
	"go/token",

	"hash/adler32",
	"hash/crc32",
	"hash/crc64",
	"hash/fnv",

	"image",
	"image/color",
	"image/draw",
	"image/gif",
	"image/jpeg",
	"image/png",

	"index/suffixarray",

	"io",
	"io/ioutil",

	"log",
	"log/syslog",

	"math",
	"math/big",
	"math/cmplx",
	"math/rand",

	"mime",
	"mime/multipart",

	// "net", // src/pkg/net/lookup_unix.go:56:20: undeclared name: cgoLookupHost
	"net/http",
	"net/http/cgi",
	"net/http/fcgi",
	"net/http/httptest",
	"net/http/httputil",
	"net/http/pprof",
	"net/mail",
	"net/rpc",
	"net/rpc/jsonrpc",
	"net/smtp",
	"net/textproto",
	"net/url",

	"path",
	"path/filepath",

	// "reflect", // unsafe.Sizeof must return size > 0 for pointer types

	"regexp",
	"regexp/syntax",

	"runtime",
	"runtime/cgo",
	"runtime/debug",
	"runtime/pprof",

	"sort",
	// "strconv", // bug in switch case duplicate detection
	"strings",

	"sync",
	"sync/atomic",

	"syscall",

	"testing",
	"testing/iotest",
	"testing/quick",

	"text/scanner",
	"text/tabwriter",
	"text/template",
	"text/template/parse",

	// "time", // local const decls without initialization expressions
	"unicode",
	"unicode/utf16",
	"unicode/utf8",
}

func Test(t *testing.T) {
	for _, test := range tests {
		runTest(t, test)
	}
}
<commit_msg>exp/gotype: disable failing tests and add a few more<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"go/build"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
)

func runTest(t *testing.T, path string) {
	exitCode = 0

	*recursive = false
	if suffix := ".go"; strings.HasSuffix(path, suffix) {
		// single file
		path = filepath.Join(runtime.GOROOT(), "src/pkg", path)
		path, file := filepath.Split(path)
		*pkgName = file[:len(file)-len(suffix)]
		processFiles([]string{path}, true)
	} else {
		// package directory
		// TODO(gri) gotype should use the build package instead
		ctxt := build.Default
		ctxt.CgoEnabled = false
		pkg, err := ctxt.Import(path, "", 0)
		if err != nil {
			t.Errorf("build.Import error for path = %s: %s", path, err)
			return
		}
		// TODO(gri) there ought to be a more direct way using the build package...
		files := make([]string, len(pkg.GoFiles))
		for i, file := range pkg.GoFiles {
			files[i] = filepath.Join(pkg.Dir, file)
		}
		*pkgName = pkg.Name
		processFiles(files, true)
	}

	if exitCode != 0 {
		t.Errorf("processing %s failed: exitCode = %d", path, exitCode)
	}
}

var tests = []string{
	// individual files
	"exp/gotype/testdata/test1.go",

	// directories
	// Note: packages that don't typecheck yet are commented out
	"archive/tar",
	"archive/zip",

	"bufio",
	"bytes",

	"compress/bzip2",
	"compress/flate",
	"compress/gzip",
	"compress/lzw",
	"compress/zlib",

	"container/heap",
	"container/list",
	"container/ring",

	"crypto",
	"crypto/aes",
	"crypto/cipher",
	"crypto/des",
	"crypto/dsa",
	"crypto/ecdsa",
	"crypto/elliptic",
	"crypto/hmac",
	"crypto/md5",
	"crypto/rand",
	"crypto/rc4",
	// "crypto/rsa", // intermittent failure: /home/gri/go2/src/pkg/crypto/rsa/pkcs1v15.go:21:27: undeclared name: io
	"crypto/sha1",
	"crypto/sha256",
	"crypto/sha512",
	"crypto/subtle",
	"crypto/tls",
	"crypto/x509",
	"crypto/x509/pkix",

	"database/sql",
	"database/sql/driver",

	"debug/dwarf",
	"debug/elf",
	"debug/gosym",
	"debug/macho",
	"debug/pe",

	"encoding/ascii85",
	"encoding/asn1",
	"encoding/base32",
	"encoding/base64",
	"encoding/binary",
	"encoding/csv",
	"encoding/gob",
	"encoding/hex",
	"encoding/json",
	"encoding/pem",
	"encoding/xml",

	"errors",
	"expvar",
	"flag",
	"fmt",

	"exp/types",
	"exp/gotype",

	"go/ast",
	"go/build",
	"go/doc",
	"go/format",
	"go/parser",
	"go/printer",
	"go/scanner",
	"go/token",

	"hash/adler32",
	"hash/crc32",
	"hash/crc64",
	"hash/fnv",

	"image",
	"image/color",
	"image/draw",
	"image/gif",
	"image/jpeg",
	"image/png",

	"index/suffixarray",

	"io",
	"io/ioutil",

	"log",
	"log/syslog",

	"math",
	"math/big",
	"math/cmplx",
	"math/rand",

	"mime",
	"mime/multipart",

	// "net", // c:\go\root\src\pkg\net\interface_windows.go:54:13: invalid operation: division by zero
	"net/http",
	"net/http/cgi",
	"net/http/fcgi",
	"net/http/httptest",
	"net/http/httputil",
	"net/http/pprof",
	"net/mail",
	"net/rpc",
	"net/rpc/jsonrpc",
	"net/smtp",
	"net/textproto",
	"net/url",

	"path",
	"path/filepath",

	// "reflect", // unsafe.Sizeof must return size > 0 for pointer types

	"regexp",
	"regexp/syntax",

	"runtime",
	"runtime/cgo",
	"runtime/debug",
	"runtime/pprof",

	"sort",
	// "strconv", // bug in switch case duplicate detection
	"strings",

	"sync",
	"sync/atomic",

	// "syscall", c:\go\root\src\pkg\syscall\syscall_windows.go:35:16: cannot convert EINVAL (constant 536870951) to error

	"testing",
	"testing/iotest",
	"testing/quick",

	"text/scanner",
	"text/tabwriter",
	"text/template",
	"text/template/parse",

	// "time", // local const decls without initialization expressions
	"unicode",
	"unicode/utf16",
	"unicode/utf8",
}

func Test(t *testing.T) {
	for _, test := range tests {
		runTest(t, test)
	}
}
<|endoftext|>


<commit_before>// Copyright 2012 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 format implements standard formatting of Go source.
package format

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/parser"
	"go/printer"
	"go/token"
	"io"
	"strings"
)

var config = printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 8}

// Node formats node in canonical gofmt style and writes the result to dst.
//
// The node type must be *ast.File, *printer.CommentedNode, []ast.Decl,
// []ast.Stmt, or assignment-compatible to ast.Expr, ast.Decl, ast.Spec,
// or ast.Stmt. Node does not modify node. Imports are not sorted for
// nodes representing partial source files (i.e., if the node is not an
// *ast.File or a *printer.CommentedNode not wrapping an *ast.File).
//
// The function may return early (before the entire result is written)
// and return a formatting error, for instance due to an incorrect AST.
//
func Node(dst io.Writer, fset *token.FileSet, node interface{}) error {
	// Determine if we have a complete source file (file != nil).
	var file *ast.File
	var cnode *printer.CommentedNode
	switch n := node.(type) {
	case *ast.File:
		file = n
	case *printer.CommentedNode:
		if f, ok := n.Node.(*ast.File); ok {
			file = f
			cnode = n
		}
	}

	// Sort imports if necessary.
	if file != nil && hasUnsortedImports(file) {
		// Make a copy of the AST because ast.SortImports is destructive.
		// TODO(gri) Do this more efficiently.
		var buf bytes.Buffer
		err := config.Fprint(&buf, fset, file)
		if err != nil {
			return err
		}
		file, err = parser.ParseFile(fset, "", buf.Bytes(), parser.ParseComments)
		if err != nil {
			// We should never get here. If we do, provide good diagnostic.
			return fmt.Errorf("format.Node internal error (%s)", err)
		}
		ast.SortImports(fset, file)

		// Use new file with sorted imports.
		node = file
		if cnode != nil {
			node = &printer.CommentedNode{Node: file, Comments: cnode.Comments}
		}
	}

	return config.Fprint(dst, fset, node)
}

// Source formats src in canonical gofmt style and writes the result to dst
// or returns an I/O or syntax error. src is expected to be a syntactically
// correct Go source file, or a list of Go declarations or statements.
//
// If src is a partial source file, the leading and trailing space of src
// is applied to the result (such that it has the same leading and trailing
// space as src), and the formatted src is indented by the same amount as
// the first line of src containing code. Imports are not sorted for partial
// source files.
//
func Source(src []byte) ([]byte, error) {
	fset := token.NewFileSet()
	node, err := parse(fset, src)
	if err != nil {
		return nil, err
	}

	var buf bytes.Buffer
	if file, ok := node.(*ast.File); ok {
		// Complete source file.
		ast.SortImports(fset, file)
		err := config.Fprint(&buf, fset, file)
		if err != nil {
			return nil, err
		}

	} else {
		// Partial source file.
		// Determine and prepend leading space.
		i, j := 0, 0
		for j < len(src) && isSpace(src[j]) {
			if src[j] == '\n' {
				i = j + 1 // index of last line in leading space
			}
			j++
		}
		buf.Write(src[:i])

		// Determine indentation of first code line.
		// Spaces are ignored unless there are no tabs,
		// in which case spaces count as one tab.
		indent := 0
		hasSpace := false
		for _, b := range src[i:j] {
			switch b {
			case ' ':
				hasSpace = true
			case '\t':
				indent++
			}
		}
		if indent == 0 && hasSpace {
			indent = 1
		}

		// Format the source.
		cfg := config
		cfg.Indent = indent
		err := cfg.Fprint(&buf, fset, node)
		if err != nil {
			return nil, err
		}

		// Determine and append trailing space.
		i = len(src)
		for i > 0 && isSpace(src[i-1]) {
			i--
		}
		buf.Write(src[i:])
	}

	return buf.Bytes(), nil
}

func hasUnsortedImports(file *ast.File) bool {
	for _, d := range file.Decls {
		d, ok := d.(*ast.GenDecl)
		if !ok || d.Tok != token.IMPORT {
			// Not an import declaration, so we're done.
			// Imports are always first.
			return false
		}
		if d.Lparen.IsValid() {
			// For now assume all grouped imports are unsorted.
			// TODO(gri) Should check if they are sorted already.
			return true
		}
		// Ungrouped imports are sorted by default.
	}
	return false
}

func isSpace(b byte) bool {
	return b == ' ' || b == '\t' || b == '\n' || b == '\r'
}

func parse(fset *token.FileSet, src []byte) (interface{}, error) {
	// Try as a complete source file.
	file, err := parser.ParseFile(fset, "", src, parser.ParseComments)
	if err == nil {
		return file, nil
	}
	// If the source is missing a package clause, try as a source fragment; otherwise fail.
	if !strings.Contains(err.Error(), "expected 'package'") {
		return nil, err
	}

	// Try as a declaration list by prepending a package clause in front of src.
	// Use ';' not '\n' to keep line numbers intact.
	psrc := append([]byte("package p;"), src...)
	file, err = parser.ParseFile(fset, "", psrc, parser.ParseComments)
	if err == nil {
		return file.Decls, nil
	}
	// If the source is missing a declaration, try as a statement list; otherwise fail.
	if !strings.Contains(err.Error(), "expected declaration") {
		return nil, err
	}

	// Try as statement list by wrapping a function around src.
	fsrc := append(append([]byte("package p; func _() {"), src...), '}')
	file, err = parser.ParseFile(fset, "", fsrc, parser.ParseComments)
	if err == nil {
		return file.Decls[0].(*ast.FuncDecl).Body.List, nil
	}

	// Failed, and out of options.
	return nil, err
}
<commit_msg>go/format: fix documentation<commit_after>// Copyright 2012 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 format implements standard formatting of Go source.
package format

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/parser"
	"go/printer"
	"go/token"
	"io"
	"strings"
)

var config = printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 8}

// Node formats node in canonical gofmt style and writes the result to dst.
//
// The node type must be *ast.File, *printer.CommentedNode, []ast.Decl,
// []ast.Stmt, or assignment-compatible to ast.Expr, ast.Decl, ast.Spec,
// or ast.Stmt. Node does not modify node. Imports are not sorted for
// nodes representing partial source files (i.e., if the node is not an
// *ast.File or a *printer.CommentedNode not wrapping an *ast.File).
//
// The function may return early (before the entire result is written)
// and return a formatting error, for instance due to an incorrect AST.
//
func Node(dst io.Writer, fset *token.FileSet, node interface{}) error {
	// Determine if we have a complete source file (file != nil).
	var file *ast.File
	var cnode *printer.CommentedNode
	switch n := node.(type) {
	case *ast.File:
		file = n
	case *printer.CommentedNode:
		if f, ok := n.Node.(*ast.File); ok {
			file = f
			cnode = n
		}
	}

	// Sort imports if necessary.
	if file != nil && hasUnsortedImports(file) {
		// Make a copy of the AST because ast.SortImports is destructive.
		// TODO(gri) Do this more efficiently.
		var buf bytes.Buffer
		err := config.Fprint(&buf, fset, file)
		if err != nil {
			return err
		}
		file, err = parser.ParseFile(fset, "", buf.Bytes(), parser.ParseComments)
		if err != nil {
			// We should never get here. If we do, provide good diagnostic.
			return fmt.Errorf("format.Node internal error (%s)", err)
		}
		ast.SortImports(fset, file)

		// Use new file with sorted imports.
		node = file
		if cnode != nil {
			node = &printer.CommentedNode{Node: file, Comments: cnode.Comments}
		}
	}

	return config.Fprint(dst, fset, node)
}

// Source formats src in canonical gofmt style and returns the result
// or an (I/O or syntax) error. src is expected to be a syntactically
// correct Go source file, or a list of Go declarations or statements.
//
// If src is a partial source file, the leading and trailing space of src
// is applied to the result (such that it has the same leading and trailing
// space as src), and the result is indented by the same amount as the first
// line of src containing code. Imports are not sorted for partial source files.
//
func Source(src []byte) ([]byte, error) {
	fset := token.NewFileSet()
	node, err := parse(fset, src)
	if err != nil {
		return nil, err
	}

	var buf bytes.Buffer
	if file, ok := node.(*ast.File); ok {
		// Complete source file.
		ast.SortImports(fset, file)
		err := config.Fprint(&buf, fset, file)
		if err != nil {
			return nil, err
		}

	} else {
		// Partial source file.
		// Determine and prepend leading space.
		i, j := 0, 0
		for j < len(src) && isSpace(src[j]) {
			if src[j] == '\n' {
				i = j + 1 // index of last line in leading space
			}
			j++
		}
		buf.Write(src[:i])

		// Determine indentation of first code line.
		// Spaces are ignored unless there are no tabs,
		// in which case spaces count as one tab.
		indent := 0
		hasSpace := false
		for _, b := range src[i:j] {
			switch b {
			case ' ':
				hasSpace = true
			case '\t':
				indent++
			}
		}
		if indent == 0 && hasSpace {
			indent = 1
		}

		// Format the source.
		cfg := config
		cfg.Indent = indent
		err := cfg.Fprint(&buf, fset, node)
		if err != nil {
			return nil, err
		}

		// Determine and append trailing space.
		i = len(src)
		for i > 0 && isSpace(src[i-1]) {
			i--
		}
		buf.Write(src[i:])
	}

	return buf.Bytes(), nil
}

func hasUnsortedImports(file *ast.File) bool {
	for _, d := range file.Decls {
		d, ok := d.(*ast.GenDecl)
		if !ok || d.Tok != token.IMPORT {
			// Not an import declaration, so we're done.
			// Imports are always first.
			return false
		}
		if d.Lparen.IsValid() {
			// For now assume all grouped imports are unsorted.
			// TODO(gri) Should check if they are sorted already.
			return true
		}
		// Ungrouped imports are sorted by default.
	}
	return false
}

func isSpace(b byte) bool {
	return b == ' ' || b == '\t' || b == '\n' || b == '\r'
}

func parse(fset *token.FileSet, src []byte) (interface{}, error) {
	// Try as a complete source file.
	file, err := parser.ParseFile(fset, "", src, parser.ParseComments)
	if err == nil {
		return file, nil
	}
	// If the source is missing a package clause, try as a source fragment; otherwise fail.
	if !strings.Contains(err.Error(), "expected 'package'") {
		return nil, err
	}

	// Try as a declaration list by prepending a package clause in front of src.
	// Use ';' not '\n' to keep line numbers intact.
	psrc := append([]byte("package p;"), src...)
	file, err = parser.ParseFile(fset, "", psrc, parser.ParseComments)
	if err == nil {
		return file.Decls, nil
	}
	// If the source is missing a declaration, try as a statement list; otherwise fail.
	if !strings.Contains(err.Error(), "expected declaration") {
		return nil, err
	}

	// Try as statement list by wrapping a function around src.
	fsrc := append(append([]byte("package p; func _() {"), src...), '}')
	file, err = parser.ParseFile(fset, "", fsrc, parser.ParseComments)
	if err == nil {
		return file.Decls[0].(*ast.FuncDecl).Body.List, nil
	}

	// Failed, and out of options.
	return nil, err
}
<|endoftext|>


<commit_before>package engo

import (
	"sync"
)

//A MessageHandler is used to dispatch a message to the subscribed handler.
type MessageHandler func(msg Message)

// in order to track handlers, each handler will get a unique ID
type MessageHandlerId uint64

var currentHandlerId MessageHandlerId

func init() {
	currentHandlerId = 0
}
func getNewHandlerId() MessageHandlerId {
	currentHandlerId++
	return currentHandlerId
}

type HandlerIDPair struct {
	MessageHandlerId
	MessageHandler
}

// A Message is used to send messages within the MessageManager
type Message interface {
	Type() string
}

// MessageManager manages messages and subscribed handlers
type MessageManager struct {
	// this mutex will prevent race
	// conditions on listeners and
	// sync its state across the game
	sync.RWMutex
	listeners        map[string][]HandlerIDPair
	handlersToRemove map[string][]MessageHandlerId
}

// Dispatch sends a message to all subscribed handlers of the message's type
func (mm *MessageManager) Dispatch(message Message) {
	mm.Lock()
	mm.clearRemovedHandlers()
	handlers := mm.listeners[message.Type()]
	mm.Unlock()

	mm.RLock()
	defer mm.RUnlock()
	for _, handler := range handlers {
		handler.MessageHandler(message)
	}

}

// Listen subscribes to the specified message type and calls the specified handler when fired
func (mm *MessageManager) Listen(messageType string, handler MessageHandler) MessageHandlerId {
	mm.Lock()
	defer mm.Unlock()
	if mm.listeners == nil {
		mm.listeners = make(map[string][]HandlerIDPair)
	}
	handlerID := getNewHandlerId()
	newHandlerIdPair := HandlerIDPair{MessageHandlerId: handlerID, MessageHandler: handler}
	mm.listeners[messageType] = append(mm.listeners[messageType], newHandlerIdPair)
	return handlerID
}

// ListenOnce is a convenience wrapper around StopListen() to only listen to a specified message once
func (mm *MessageManager) ListenOnce(messageType string, handler MessageHandler) {
	handlerId := MessageHandlerId(0)
	handlerId = mm.Listen(messageType, func(msg Message) {
		handler(msg)
		mm.StopListen(messageType, handlerId)
	})
}

// StopListen removes a previously added handler from the listener queue
func (mm *MessageManager) StopListen(messageType string, handlerId MessageHandlerId) {
	if mm.handlersToRemove == nil {
		mm.handlersToRemove = make(map[string][]MessageHandlerId)
	}
	mm.handlersToRemove[messageType] = append(mm.handlersToRemove[messageType], handlerId)
}

// Will deleted all queued handlers that are scheduled for removal due to StopListen()
func (mm *MessageManager) clearRemovedHandlers() {
	for messageType, handlerList := range mm.handlersToRemove {
		for _, handlerId := range handlerList {
			mm.removeHandler(messageType, handlerId)
		}
	}
}

// Removes a single handler from the handler queue, called during cleanup of all handlers scheduled for removal
func (mm *MessageManager) removeHandler(messageType string, handlerId MessageHandlerId) {
	indexOfHandler := -1
	for i, activeHandler := range mm.listeners[messageType] {
		if activeHandler.MessageHandlerId == handlerId {
			indexOfHandler = i
			break
		}
	}
	// A handler might have already been removed during a previous Dispatch(), no action necessary
	if indexOfHandler == -1 {
		return
	}
	mm.listeners[messageType] = append(mm.listeners[messageType][:indexOfHandler], mm.listeners[messageType][indexOfHandler+1:]...)
}

// WindowResizeMessage is a message that's being dispatched whenever the game window is being resized by the gamer
type WindowResizeMessage struct {
	OldWidth, OldHeight int
	NewWidth, NewHeight int
}

// Type returns the type of the current object "WindowResizeMessage"
func (WindowResizeMessage) Type() string { return "WindowResizeMessage" }
<commit_msg>Clear handlers-to-delete list after removal has run<commit_after>package engo

import (
	"sync"
)

//A MessageHandler is used to dispatch a message to the subscribed handler.
type MessageHandler func(msg Message)

// in order to track handlers, each handler will get a unique ID
type MessageHandlerId uint64

var currentHandlerId MessageHandlerId

func init() {
	currentHandlerId = 0
}
func getNewHandlerId() MessageHandlerId {
	currentHandlerId++
	return currentHandlerId
}

type HandlerIDPair struct {
	MessageHandlerId
	MessageHandler
}

// A Message is used to send messages within the MessageManager
type Message interface {
	Type() string
}

// MessageManager manages messages and subscribed handlers
type MessageManager struct {
	// this mutex will prevent race
	// conditions on listeners and
	// sync its state across the game
	sync.RWMutex
	listeners        map[string][]HandlerIDPair
	handlersToRemove map[string][]MessageHandlerId
}

// Dispatch sends a message to all subscribed handlers of the message's type
func (mm *MessageManager) Dispatch(message Message) {
	mm.Lock()
	mm.clearRemovedHandlers()
	handlers := mm.listeners[message.Type()]
	mm.Unlock()

	mm.RLock()
	defer mm.RUnlock()
	for _, handler := range handlers {
		handler.MessageHandler(message)
	}

}

// Listen subscribes to the specified message type and calls the specified handler when fired
func (mm *MessageManager) Listen(messageType string, handler MessageHandler) MessageHandlerId {
	mm.Lock()
	defer mm.Unlock()
	if mm.listeners == nil {
		mm.listeners = make(map[string][]HandlerIDPair)
	}
	handlerID := getNewHandlerId()
	newHandlerIdPair := HandlerIDPair{MessageHandlerId: handlerID, MessageHandler: handler}
	mm.listeners[messageType] = append(mm.listeners[messageType], newHandlerIdPair)
	return handlerID
}

// ListenOnce is a convenience wrapper around StopListen() to only listen to a specified message once
func (mm *MessageManager) ListenOnce(messageType string, handler MessageHandler) {
	handlerId := MessageHandlerId(0)
	handlerId = mm.Listen(messageType, func(msg Message) {
		handler(msg)
		mm.StopListen(messageType, handlerId)
	})
}

// StopListen removes a previously added handler from the listener queue
func (mm *MessageManager) StopListen(messageType string, handlerId MessageHandlerId) {
	if mm.handlersToRemove == nil {
		mm.handlersToRemove = make(map[string][]MessageHandlerId)
	}
	mm.handlersToRemove[messageType] = append(mm.handlersToRemove[messageType], handlerId)
}

// Will deleted all queued handlers that are scheduled for removal due to StopListen()
func (mm *MessageManager) clearRemovedHandlers() {
	for messageType, handlerList := range mm.handlersToRemove {
		for _, handlerId := range handlerList {
			mm.removeHandler(messageType, handlerId)
		}
	}
	mm.handlersToRemove = make(map[string][]MessageHandlerId)
}

// Removes a single handler from the handler queue, called during cleanup of all handlers scheduled for removal
func (mm *MessageManager) removeHandler(messageType string, handlerId MessageHandlerId) {
	indexOfHandler := -1
	for i, activeHandler := range mm.listeners[messageType] {
		if activeHandler.MessageHandlerId == handlerId {
			indexOfHandler = i
			break
		}
	}
	// A handler might have already been removed during a previous Dispatch(), no action necessary
	if indexOfHandler == -1 {
		return
	}
	mm.listeners[messageType] = append(mm.listeners[messageType][:indexOfHandler], mm.listeners[messageType][indexOfHandler+1:]...)
}

// WindowResizeMessage is a message that's being dispatched whenever the game window is being resized by the gamer
type WindowResizeMessage struct {
	OldWidth, OldHeight int
	NewWidth, NewHeight int
}

// Type returns the type of the current object "WindowResizeMessage"
func (WindowResizeMessage) Type() string { return "WindowResizeMessage" }
<|endoftext|>


<commit_before>package ionic

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

	"github.com/ion-channel/ionic/analyses"
	"github.com/ion-channel/ionic/pagination"
)

// GetAnalysis takes an analysis ID, team ID, project ID, and token.  It returns the
// analysis found.  If the analysis is not found it will return an error, and
// will return an error for any other API issues it encounters.
func (ic *IonClient) GetAnalysis(id, teamID, projectID, token string) (*analyses.Analysis, error) {
	params := &url.Values{}
	params.Set("id", id)
	params.Set("team_id", teamID)
	params.Set("project_id", projectID)

	b, _, err := ic.Get(analyses.AnalysisGetAnalysisEndpoint, token, params, nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get analysis: %v", err.Error())
	}

	var a analyses.Analysis
	err = json.Unmarshal(b, &a)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal analysis: %v", err.Error())
	}

	return &a, nil
}

// GetAnalyses takes a team ID, project ID, and token. It returns a slice of
// analyses for the project or an error for any API issues it encounters.
func (ic *IonClient) GetAnalyses(teamID, projectID, token string, page *pagination.Pagination) ([]analyses.Analysis, error) {
	params := &url.Values{}
	params.Set("team_id", teamID)
	params.Set("project_id", projectID)

	b, _, err := ic.Get(analyses.AnalysisGetAnalysesEndpoint, token, params, nil, page)
	if err != nil {
		return nil, fmt.Errorf("failed to get analyses: %v", err.Error())
	}

	var as []analyses.Analysis
	err = json.Unmarshal(b, &as)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal analyses: %v", err.Error())
	}

	return as, nil
}

// GetLatestPublicAnalysis takes a project ID and branch.  It returns the
// analysis found.  If the analysis is not found it will return an error, and
// will return an error for any other API issues it encounters.
func (ic *IonClient) GetLatestPublicAnalysis(projectID, branch string) (*analyses.Analysis, error) {
	params := &url.Values{}
	params.Set("project_id", projectID)
	params.Set("branch", branch)

	b, _, err := ic.Get(analyses.AnalysisGetLatestPublicAnalysisEndpoint, "", params, nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get analysis: %v", err.Error())
	}

	var a analyses.Analysis
	err = json.Unmarshal(b, &a)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal analysis: %v", err.Error())
	}

	return &a, nil
}

// GetPublicAnalysis takes an analysis ID.  It returns the
// analysis found.  If the analysis is not found it will return an error, and
// will return an error for any other API issues it encounters.
func (ic *IonClient) GetPublicAnalysis(id string) (*analyses.Analysis, error) {
	params := &url.Values{}
	params.Set("id", id)

	b, _, err := ic.Get(analyses.AnalysisGetPublicAnalysisEndpoint, "", params, nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get analysis: %v", err.Error())
	}

	var a analyses.Analysis
	err = json.Unmarshal(b, &a)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal analysis: %v", err.Error())
	}

	return &a, nil
}

// GetRawAnalysis takes an analysis ID, team ID, project ID, and token.  It returns the
// raw JSON from the API.  It returns an error for any API issues it encounters.
func (ic *IonClient) GetRawAnalysis(id, teamID, projectID, token string) (json.RawMessage, error) {
	params := &url.Values{}
	params.Set("id", id)
	params.Set("team_id", teamID)
	params.Set("project_id", projectID)

	b, _, err := ic.Get(analyses.AnalysisGetAnalysisEndpoint, token, params, nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get analysis: %v", err.Error())
	}

	return b, nil
}

// GetRawAnalyses takes a team ID, project ID, and token. It returns the raw
// JSON from the API. It returns an error for any API issue it encounters.
func (ic *IonClient) GetRawAnalyses(teamID, projectID, token string, page *pagination.Pagination) (json.RawMessage, error) {
	params := &url.Values{}
	params.Set("team_id", teamID)
	params.Set("project_id", projectID)

	b, _, err := ic.Get(analyses.AnalysisGetAnalysesEndpoint, token, params, nil, page)
	if err != nil {
		return nil, fmt.Errorf("failed to get analysis: %v", err.Error())
	}

	return b, nil
}

// GetLatestAnalysisSummary takes a team ID, project ID, and token. It returns the
// latest analysis summary for the project. It returns an error for any API
// issues it encounters.
func (ic *IonClient) GetLatestAnalysisSummary(teamID, projectID, token string) (*analyses.Summary, error) {
	params := &url.Values{}
	params.Set("team_id", teamID)
	params.Set("project_id", projectID)

	b, _, err := ic.Get(analyses.AnalysisGetLatestAnalysisSummaryEndpoint, token, params, nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get latest analysis: %v", err.Error())
	}

	var a analyses.Summary
	err = json.Unmarshal(b, &a)
	if err != nil {
		return nil, fmt.Errorf("failed to get latest analysis: %v", err.Error())
	}

	return &a, nil
}

// GetRawLatestAnalysisSummary takes a team ID, project ID, and token. It returns the
// raw JSON from the API.  It returns an error for any API issues it encounters.
func (ic *IonClient) GetRawLatestAnalysisSummary(teamID, projectID, token string) (json.RawMessage, error) {
	params := &url.Values{}
	params.Set("team_id", teamID)
	params.Set("project_id", projectID)

	b, _, err := ic.Get(analyses.AnalysisGetLatestAnalysisSummaryEndpoint, token, params, nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get latest analysis: %v", err.Error())
	}

	return b, nil
}
<commit_msg>adding get latest anslysis method<commit_after>package ionic

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

	"github.com/ion-channel/ionic/analyses"
	"github.com/ion-channel/ionic/pagination"
)

// GetAnalysis takes an analysis ID, team ID, project ID, and token.  It returns the
// analysis found.  If the analysis is not found it will return an error, and
// will return an error for any other API issues it encounters.
func (ic *IonClient) GetAnalysis(id, teamID, projectID, token string) (*analyses.Analysis, error) {
	params := &url.Values{}
	params.Set("id", id)
	params.Set("team_id", teamID)
	params.Set("project_id", projectID)

	b, _, err := ic.Get(analyses.AnalysisGetAnalysisEndpoint, token, params, nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get analysis: %v", err.Error())
	}

	var a analyses.Analysis
	err = json.Unmarshal(b, &a)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal analysis: %v", err.Error())
	}

	return &a, nil
}

// GetLatestAnalysis takes a team ID, project ID, and token.  It returns the
// latest analysis found.  If the analysis is not found it will return an error, and
// will return an error for any other API issues it encounters.
func (ic *IonClient) GetLatestAnalysis(teamID, projectID, token string) (*analyses.Analysis, error) {
	params := &url.Values{}
	params.Set("team_id", teamID)
	params.Set("project_id", projectID)

	b, _, err := ic.Get(analyses.AnalysisGetLatestAnalysisEndpoint, token, params, nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get analysis: %v", err.Error())
	}

	var a analyses.Analysis
	err = json.Unmarshal(b, &a)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal analysis: %v", err.Error())
	}

	return &a, nil
}

// GetAnalyses takes a team ID, project ID, and token. It returns a slice of
// analyses for the project or an error for any API issues it encounters.
func (ic *IonClient) GetAnalyses(teamID, projectID, token string, page *pagination.Pagination) ([]analyses.Analysis, error) {
	params := &url.Values{}
	params.Set("team_id", teamID)
	params.Set("project_id", projectID)

	b, _, err := ic.Get(analyses.AnalysisGetAnalysesEndpoint, token, params, nil, page)
	if err != nil {
		return nil, fmt.Errorf("failed to get analyses: %v", err.Error())
	}

	var as []analyses.Analysis
	err = json.Unmarshal(b, &as)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal analyses: %v", err.Error())
	}

	return as, nil
}

// GetLatestPublicAnalysis takes a project ID and branch.  It returns the
// analysis found.  If the analysis is not found it will return an error, and
// will return an error for any other API issues it encounters.
func (ic *IonClient) GetLatestPublicAnalysis(projectID, branch string) (*analyses.Analysis, error) {
	params := &url.Values{}
	params.Set("project_id", projectID)
	params.Set("branch", branch)

	b, _, err := ic.Get(analyses.AnalysisGetLatestPublicAnalysisEndpoint, "", params, nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get analysis: %v", err.Error())
	}

	var a analyses.Analysis
	err = json.Unmarshal(b, &a)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal analysis: %v", err.Error())
	}

	return &a, nil
}

// GetPublicAnalysis takes an analysis ID.  It returns the
// analysis found.  If the analysis is not found it will return an error, and
// will return an error for any other API issues it encounters.
func (ic *IonClient) GetPublicAnalysis(id string) (*analyses.Analysis, error) {
	params := &url.Values{}
	params.Set("id", id)

	b, _, err := ic.Get(analyses.AnalysisGetPublicAnalysisEndpoint, "", params, nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get analysis: %v", err.Error())
	}

	var a analyses.Analysis
	err = json.Unmarshal(b, &a)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal analysis: %v", err.Error())
	}

	return &a, nil
}

// GetRawAnalysis takes an analysis ID, team ID, project ID, and token.  It returns the
// raw JSON from the API.  It returns an error for any API issues it encounters.
func (ic *IonClient) GetRawAnalysis(id, teamID, projectID, token string) (json.RawMessage, error) {
	params := &url.Values{}
	params.Set("id", id)
	params.Set("team_id", teamID)
	params.Set("project_id", projectID)

	b, _, err := ic.Get(analyses.AnalysisGetAnalysisEndpoint, token, params, nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get analysis: %v", err.Error())
	}

	return b, nil
}

// GetRawAnalyses takes a team ID, project ID, and token. It returns the raw
// JSON from the API. It returns an error for any API issue it encounters.
func (ic *IonClient) GetRawAnalyses(teamID, projectID, token string, page *pagination.Pagination) (json.RawMessage, error) {
	params := &url.Values{}
	params.Set("team_id", teamID)
	params.Set("project_id", projectID)

	b, _, err := ic.Get(analyses.AnalysisGetAnalysesEndpoint, token, params, nil, page)
	if err != nil {
		return nil, fmt.Errorf("failed to get analysis: %v", err.Error())
	}

	return b, nil
}

// GetLatestAnalysisSummary takes a team ID, project ID, and token. It returns the
// latest analysis summary for the project. It returns an error for any API
// issues it encounters.
func (ic *IonClient) GetLatestAnalysisSummary(teamID, projectID, token string) (*analyses.Summary, error) {
	params := &url.Values{}
	params.Set("team_id", teamID)
	params.Set("project_id", projectID)

	b, _, err := ic.Get(analyses.AnalysisGetLatestAnalysisSummaryEndpoint, token, params, nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get latest analysis: %v", err.Error())
	}

	var a analyses.Summary
	err = json.Unmarshal(b, &a)
	if err != nil {
		return nil, fmt.Errorf("failed to get latest analysis: %v", err.Error())
	}

	return &a, nil
}

// GetRawLatestAnalysisSummary takes a team ID, project ID, and token. It returns the
// raw JSON from the API.  It returns an error for any API issues it encounters.
func (ic *IonClient) GetRawLatestAnalysisSummary(teamID, projectID, token string) (json.RawMessage, error) {
	params := &url.Values{}
	params.Set("team_id", teamID)
	params.Set("project_id", projectID)

	b, _, err := ic.Get(analyses.AnalysisGetLatestAnalysisSummaryEndpoint, token, params, nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get latest analysis: %v", err.Error())
	}

	return b, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"gonat.googlecode.com/hg/nat/stun"
	"io/ioutil"
	"net"
	"path/filepath"
)

func main() {
	paths, err := filepath.Glob("test-files/*")
	if err != nil {
		panic(err)
	}
	for _, path := range paths {
		data, err := ioutil.ReadFile(path)
		fmt.Printf("%#v\n", data)
		if err != nil {
			panic(err)
		}
		packet, err := stun.ParsePacket(data, []byte{})
		fmt.Println(packet, err)
	}
	pkt, err := stun.BindRequest([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2}, []byte{1, 2, 3}, true)
	packet, err := stun.ParsePacket(pkt, []byte{1, 2, 3})
	fmt.Println(packet, err)

	pkt, err = stun.BindResponse([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2}, &net.UDPAddr{net.IP([]byte{192, 168, 1, 42}), 4242}, []byte{1, 2, 3}, true)
	packet, err = stun.ParsePacket(pkt, []byte{1, 2, 3})
	fmt.Println(packet, err)
}
<commit_msg>Remove debugging statement.<commit_after>package main

import (
	"fmt"
	"gonat.googlecode.com/hg/nat/stun"
	"io/ioutil"
	"net"
	"path/filepath"
)

func main() {
	paths, err := filepath.Glob("test-files/*")
	if err != nil {
		panic(err)
	}
	for _, path := range paths {
		data, err := ioutil.ReadFile(path)
		if err != nil {
			panic(err)
		}
		packet, err := stun.ParsePacket(data, []byte{})
		fmt.Println(packet, err)
	}
	pkt, err := stun.BindRequest([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2}, []byte{1, 2, 3}, true)
	packet, err := stun.ParsePacket(pkt, []byte{1, 2, 3})
	fmt.Println(packet, err)

	pkt, err = stun.BindResponse([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2}, &net.UDPAddr{net.IP([]byte{192, 168, 1, 42}), 4242}, []byte{1, 2, 3}, true)
	packet, err = stun.ParsePacket(pkt, []byte{1, 2, 3})
	fmt.Println(packet, err)
}
<|endoftext|>


<commit_before>// Copyright 2017-2020 The Usacloud Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package core

import (
	"fmt"
	"strings"

	"github.com/sacloud/usacloud/pkg/version"

	"github.com/spf13/cobra"
)

const originalCommandsUsage = `Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
  {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}`

const commandUsageTemplate = ` === %s ===
%s
`

const commandUsageWrapperTemplate = `Available Commands:
%s`

func buildRootCommandUsages(rootCmd *cobra.Command, resources []*Resource) string {
	line := "    %s %s"
	var usages []string
	for _, r := range resources {
		cmd := lookupCmd(rootCmd, r.Name)

		if cmd.IsAvailableCommand() {
			t := fmt.Sprintf("%%-%ds", cmd.NamePadding())
			name := fmt.Sprintf(t, cmd.Name())
			usages = append(usages, fmt.Sprintf(line, name, cmd.Short))
		}
	}
	// completionを追加
	if cmd := lookupCmd(rootCmd, "completion"); cmd != nil {
		t := fmt.Sprintf("%%-%ds", cmd.NamePadding())
		name := fmt.Sprintf(t, cmd.Name())
		usages = append(usages, fmt.Sprintf(line, name, cmd.Short))
	}
	return strings.TrimRight(strings.Join(usages, "\n"), "\n")
}

func BuildRootCommandsUsage(cmd *cobra.Command, commands []*CategorizedResources) {
	cmd.SetUsageTemplate("")
	var usages []string
	for _, c := range commands {
		usages = append(usages, fmt.Sprintf(commandUsageTemplate, c.Category.DisplayName, buildRootCommandUsages(cmd, c.Resources)))
	}
	usage := fmt.Sprintf(commandUsageWrapperTemplate, strings.TrimRight(strings.Join(usages, "\n"), "\n"))
	cmd.SetUsageTemplate(strings.Replace(cmd.UsageTemplate(), originalCommandsUsage, usage, 1))
	cmd.SetUsageTemplate(cmd.UsageTemplate() + fmt.Sprintf("\nCopyright %s The Usacloud Authors\n", version.CopyrightYear))
}

func buildCommandUsages(rootCmd *cobra.Command, commands []*Command) string {
	line := "    %s %s"
	var usages []string
	for _, c := range commands {
		cmd := lookupCmd(rootCmd, c.Name)

		if cmd.IsAvailableCommand() {
			t := fmt.Sprintf("%%-%ds", cmd.NamePadding())
			name := fmt.Sprintf(t, cmd.Name())
			usages = append(usages, fmt.Sprintf(line, name, cmd.Short))
		}
	}
	return strings.TrimRight(strings.Join(usages, "\n"), "\n")
}

func buildCommandsUsage(cmd *cobra.Command, commands []*CategorizedCommands) {
	cmd.SetUsageTemplate("")
	var usages []string
	for _, c := range commands {
		usages = append(usages, fmt.Sprintf(commandUsageTemplate, c.Category.DisplayName, buildCommandUsages(cmd, c.Commands)))
	}
	usage := fmt.Sprintf(commandUsageWrapperTemplate, strings.TrimRight(strings.Join(usages, "\n"), "\n"))
	cmd.SetUsageTemplate(strings.Replace(cmd.UsageTemplate(), originalCommandsUsage, usage, 1))
}

const originalFlagsUsage = `Flags:
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}`

const flagsUsageTemplate = `  === %s ===

%s`

const flagsUsageWrapperTemplate = `Flags:

%s`

func BuildFlagsUsage(cmd *cobra.Command, sets []*FlagSet) {
	var usages []string
	for _, fs := range sets {
		usages = append(usages, fmt.Sprintf(flagsUsageTemplate, fs.Title, fs.Flags.FlagUsages()))
	}
	usage := fmt.Sprintf(flagsUsageWrapperTemplate, strings.TrimRight(strings.Join(usages, "\n"), "\n"))
	cmd.SetUsageTemplate(strings.Replace(cmd.UsageTemplate(), originalFlagsUsage, usage, 1))
}
<commit_msg>Fix completion usage<commit_after>// Copyright 2017-2020 The Usacloud Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package core

import (
	"fmt"
	"strings"

	"github.com/sacloud/usacloud/pkg/version"

	"github.com/spf13/cobra"
)

const originalCommandsUsage = `Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
  {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}`

const commandUsageTemplate = ` === %s ===
%s
`

const commandUsageWrapperTemplate = `Available Commands:
%s`

func buildRootCommandUsages(rootCmd *cobra.Command, resources []*Resource, appendCompletion bool) string {
	line := "    %s %s"
	var usages []string
	for _, r := range resources {
		cmd := lookupCmd(rootCmd, r.Name)

		if cmd.IsAvailableCommand() {
			t := fmt.Sprintf("%%-%ds", cmd.NamePadding())
			name := fmt.Sprintf(t, cmd.Name())
			usages = append(usages, fmt.Sprintf(line, name, cmd.Short))
		}
	}
	// completionを追加
	if appendCompletion {
		if cmd := lookupCmd(rootCmd, "completion"); cmd != nil {
			t := fmt.Sprintf("%%-%ds", cmd.NamePadding())
			name := fmt.Sprintf(t, cmd.Name())
			usages = append(usages, fmt.Sprintf(line, name, cmd.Short))
		}
	}
	return strings.TrimRight(strings.Join(usages, "\n"), "\n")
}

func BuildRootCommandsUsage(cmd *cobra.Command, commands []*CategorizedResources) {
	cmd.SetUsageTemplate("")
	var usages []string
	for _, c := range commands {
		usages = append(usages, fmt.Sprintf(commandUsageTemplate, c.Category.DisplayName, buildRootCommandUsages(cmd, c.Resources, c.Category == ResourceCategoryOther)))
	}
	usage := fmt.Sprintf(commandUsageWrapperTemplate, strings.TrimRight(strings.Join(usages, "\n"), "\n"))
	cmd.SetUsageTemplate(strings.Replace(cmd.UsageTemplate(), originalCommandsUsage, usage, 1))
	cmd.SetUsageTemplate(cmd.UsageTemplate() + fmt.Sprintf("\nCopyright %s The Usacloud Authors\n", version.CopyrightYear))
}

func buildCommandUsages(rootCmd *cobra.Command, commands []*Command) string {
	line := "    %s %s"
	var usages []string
	for _, c := range commands {
		cmd := lookupCmd(rootCmd, c.Name)

		if cmd.IsAvailableCommand() {
			t := fmt.Sprintf("%%-%ds", cmd.NamePadding())
			name := fmt.Sprintf(t, cmd.Name())
			usages = append(usages, fmt.Sprintf(line, name, cmd.Short))
		}
	}
	return strings.TrimRight(strings.Join(usages, "\n"), "\n")
}

func buildCommandsUsage(cmd *cobra.Command, commands []*CategorizedCommands) {
	cmd.SetUsageTemplate("")
	var usages []string
	for _, c := range commands {
		usages = append(usages, fmt.Sprintf(commandUsageTemplate, c.Category.DisplayName, buildCommandUsages(cmd, c.Commands)))
	}
	usage := fmt.Sprintf(commandUsageWrapperTemplate, strings.TrimRight(strings.Join(usages, "\n"), "\n"))
	cmd.SetUsageTemplate(strings.Replace(cmd.UsageTemplate(), originalCommandsUsage, usage, 1))
}

const originalFlagsUsage = `Flags:
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}`

const flagsUsageTemplate = `  === %s ===

%s`

const flagsUsageWrapperTemplate = `Flags:

%s`

func BuildFlagsUsage(cmd *cobra.Command, sets []*FlagSet) {
	var usages []string
	for _, fs := range sets {
		usages = append(usages, fmt.Sprintf(flagsUsageTemplate, fs.Title, fs.Flags.FlagUsages()))
	}
	usage := fmt.Sprintf(flagsUsageWrapperTemplate, strings.TrimRight(strings.Join(usages, "\n"), "\n"))
	cmd.SetUsageTemplate(strings.Replace(cmd.UsageTemplate(), originalFlagsUsage, usage, 1))
}
<|endoftext|>


<commit_before>package controllers

import (
	"strings"

	"github.com/lfq7413/tomato/errs"
	"github.com/lfq7413/tomato/orm"
	"github.com/lfq7413/tomato/types"
	"github.com/lfq7413/tomato/utils"
)

// SchemasController 处理 /schemas 接口的请求
type SchemasController struct {
	ObjectsController
}

// Prepare 访问 /schemas 接口需要 master key
func (s *SchemasController) Prepare() {
	s.ObjectsController.Prepare()
	if s.Auth.IsMaster == false {
		s.Data["json"] = errs.ErrorMessageToMap(errs.OperationForbidden, "Need master key!")
		s.ServeJSON()
	}
}

// HandleFind 处理 schema 查找请求
// @router / [get]
func (s *SchemasController) HandleFind() {
	schema := orm.TomatoDBController.LoadSchema()
	schemas, err := schema.GetAllSchemas()
	if err != nil {
		s.Data["json"] = types.M{
			"results": types.S{},
		}
		s.ServeJSON()
		return
	}
	s.Data["json"] = types.M{
		"results": schemas,
	}
	s.ServeJSON()
}

// HandleGet 处理查找指定的类请求
// @router /:className [get]
func (s *SchemasController) HandleGet() {
	className := s.Ctx.Input.Param(":className")
	schema := orm.TomatoDBController.LoadSchema()
	sch, err := schema.GetOneSchema(className, false)
	if err != nil {
		s.Data["json"] = errs.ErrorMessageToMap(errs.InvalidClassName, "Class "+className+" does not exist.")
		s.ServeJSON()
		return
	}
	s.Data["json"] = sch
	s.ServeJSON()
}

// HandleCreate 处理创建类请求，同时可匹配 / 的 POST 请求
// @router /:className [post]
func (s *SchemasController) HandleCreate() {
	className := s.Ctx.Input.Param(":className")
	var data = s.JSONBody
	if data == nil {
		s.Data["json"] = errs.ErrorMessageToMap(errs.InvalidJSON, "request body is empty")
		s.ServeJSON()
		return
	}

	bodyClassName := ""
	if data["className"] != nil && utils.String(data["className"]) != "" {
		bodyClassName = utils.String(data["className"])
	}
	if className != "" && bodyClassName != "" {
		if className != bodyClassName {
			s.Data["json"] = errs.ErrorMessageToMap(errs.InvalidClassName, "Class name mismatch between "+bodyClassName+" and "+className+".")
			s.ServeJSON()
			return
		}
	}
	if className == "" {
		className = bodyClassName
	}
	if className == "" {
		s.Data["json"] = errs.ErrorMessageToMap(errs.MissingRequiredFieldError, "POST schemas needs a class name.")
		s.ServeJSON()
		return
	}

	schema := orm.TomatoDBController.LoadSchema()
	result, err := schema.AddClassIfNotExists(className, utils.MapInterface(data["fields"]), utils.MapInterface(data["classLevelPermissions"]))
	if err != nil {
		s.Data["json"] = errs.ErrorToMap(err)
		s.ServeJSON()
		return
	}

	s.Data["json"] = result
	s.ServeJSON()
}

// HandleUpdate 处理更新类请求
// @router /:className [put]
func (s *SchemasController) HandleUpdate() {
	className := s.Ctx.Input.Param(":className")
	var data = s.JSONBody
	if data == nil {
		s.Data["json"] = errs.ErrorMessageToMap(errs.InvalidJSON, "request body is empty")
		s.ServeJSON()
		return
	}

	bodyClassName := ""
	if data["className"] != nil && utils.String(data["className"]) != "" {
		bodyClassName = utils.String(data["className"])
	}
	if className != bodyClassName {
		s.Data["json"] = errs.ErrorMessageToMap(errs.InvalidClassName, "Class name mismatch between "+bodyClassName+" and "+className+".")
		s.ServeJSON()
		return
	}

	submittedFields := types.M{}
	if data["fields"] != nil && utils.MapInterface(data["fields"]) != nil {
		submittedFields = utils.MapInterface(data["fields"])
	}

	schema := orm.TomatoDBController.LoadSchema()
	result, err := schema.UpdateClass(className, submittedFields, utils.MapInterface(data["classLevelPermissions"]))
	if err != nil {
		s.Data["json"] = errs.ErrorToMap(err)
		s.ServeJSON()
		return
	}

	s.Data["json"] = result
	s.ServeJSON()
}

// HandleDelete 处理删除指定类请求
// @router /:className [delete]
func (s *SchemasController) HandleDelete() {
	className := s.Ctx.Input.Param(":className")
	if orm.ClassNameIsValid(className) == false {
		s.Data["json"] = errs.ErrorMessageToMap(errs.InvalidClassName, orm.InvalidClassNameMessage(className))
		s.ServeJSON()
		return
	}

	err := orm.TomatoDBController.DeleteSchema(className)
	if err != nil {
		s.Data["json"] = errs.ErrorToMap(err)
		s.ServeJSON()
		return
	}

	// 从 _SCHEMA 表中删除类信息，清除相关的 _Join 表
	coll := orm.TomatoDBController.SchemaCollection()
	document, err := coll.FindAndDeleteSchema(className)
	if err != nil {
		s.Data["json"] = errs.ErrorToMap(err)
		s.ServeJSON()
		return
	}
	if document != nil {
		err = removeJoinTables(document)
		if err != nil {
			s.Data["json"] = errs.ErrorToMap(err)
			s.ServeJSON()
			return
		}
	}
	s.Data["json"] = types.M{}
	s.ServeJSON()
	return
}

// removeJoinTables 清除类中的所有关联表
// 需要查找的类型： "field":"relation<otherClass>"
// 需要删除的表明： "_Join:field:className"
func removeJoinTables(mongoSchema types.M) error {
	for field, v := range mongoSchema {
		fieldType := utils.String(v)
		if strings.HasPrefix(fieldType, "relation<") {
			collectionName := "_Join:" + field + ":" + utils.String(mongoSchema["_id"])
			err := orm.Adapter.DeleteOneSchema(collectionName)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// Delete ...
// @router / [delete]
func (s *SchemasController) Delete() {
	s.ObjectsController.Delete()
}

// Put ...
// @router / [put]
func (s *SchemasController) Put() {
	s.ObjectsController.Put()
}

// injectDefaultSchema 为 schema 添加默认字段
func injectDefaultSchema(schema types.M) types.M {
	defaultSchema := orm.DefaultColumns[schema["className"].(string)]
	if defaultSchema != nil {
		fields := schema["fields"].(map[string]interface{})
		for k, v := range defaultSchema {
			fields[k] = v
		}
		schema["fields"] = fields
	}
	return schema
}
<commit_msg>排除 _metadata 字段<commit_after>package controllers

import (
	"strings"

	"github.com/lfq7413/tomato/errs"
	"github.com/lfq7413/tomato/orm"
	"github.com/lfq7413/tomato/types"
	"github.com/lfq7413/tomato/utils"
)

// SchemasController 处理 /schemas 接口的请求
type SchemasController struct {
	ObjectsController
}

// Prepare 访问 /schemas 接口需要 master key
func (s *SchemasController) Prepare() {
	s.ObjectsController.Prepare()
	if s.Auth.IsMaster == false {
		s.Data["json"] = errs.ErrorMessageToMap(errs.OperationForbidden, "Need master key!")
		s.ServeJSON()
	}
}

// HandleFind 处理 schema 查找请求
// @router / [get]
func (s *SchemasController) HandleFind() {
	schema := orm.TomatoDBController.LoadSchema()
	schemas, err := schema.GetAllSchemas()
	if err != nil {
		s.Data["json"] = types.M{
			"results": types.S{},
		}
		s.ServeJSON()
		return
	}
	s.Data["json"] = types.M{
		"results": schemas,
	}
	s.ServeJSON()
}

// HandleGet 处理查找指定的类请求
// @router /:className [get]
func (s *SchemasController) HandleGet() {
	className := s.Ctx.Input.Param(":className")
	schema := orm.TomatoDBController.LoadSchema()
	sch, err := schema.GetOneSchema(className, false)
	if err != nil {
		s.Data["json"] = errs.ErrorMessageToMap(errs.InvalidClassName, "Class "+className+" does not exist.")
		s.ServeJSON()
		return
	}
	s.Data["json"] = sch
	s.ServeJSON()
}

// HandleCreate 处理创建类请求，同时可匹配 / 的 POST 请求
// @router /:className [post]
func (s *SchemasController) HandleCreate() {
	className := s.Ctx.Input.Param(":className")
	var data = s.JSONBody
	if data == nil {
		s.Data["json"] = errs.ErrorMessageToMap(errs.InvalidJSON, "request body is empty")
		s.ServeJSON()
		return
	}

	bodyClassName := ""
	if data["className"] != nil && utils.String(data["className"]) != "" {
		bodyClassName = utils.String(data["className"])
	}
	if className != "" && bodyClassName != "" {
		if className != bodyClassName {
			s.Data["json"] = errs.ErrorMessageToMap(errs.InvalidClassName, "Class name mismatch between "+bodyClassName+" and "+className+".")
			s.ServeJSON()
			return
		}
	}
	if className == "" {
		className = bodyClassName
	}
	if className == "" {
		s.Data["json"] = errs.ErrorMessageToMap(errs.MissingRequiredFieldError, "POST schemas needs a class name.")
		s.ServeJSON()
		return
	}

	schema := orm.TomatoDBController.LoadSchema()
	result, err := schema.AddClassIfNotExists(className, utils.MapInterface(data["fields"]), utils.MapInterface(data["classLevelPermissions"]))
	if err != nil {
		s.Data["json"] = errs.ErrorToMap(err)
		s.ServeJSON()
		return
	}

	s.Data["json"] = result
	s.ServeJSON()
}

// HandleUpdate 处理更新类请求
// @router /:className [put]
func (s *SchemasController) HandleUpdate() {
	className := s.Ctx.Input.Param(":className")
	var data = s.JSONBody
	if data == nil {
		s.Data["json"] = errs.ErrorMessageToMap(errs.InvalidJSON, "request body is empty")
		s.ServeJSON()
		return
	}

	bodyClassName := ""
	if data["className"] != nil && utils.String(data["className"]) != "" {
		bodyClassName = utils.String(data["className"])
	}
	if className != bodyClassName {
		s.Data["json"] = errs.ErrorMessageToMap(errs.InvalidClassName, "Class name mismatch between "+bodyClassName+" and "+className+".")
		s.ServeJSON()
		return
	}

	submittedFields := types.M{}
	if data["fields"] != nil && utils.MapInterface(data["fields"]) != nil {
		submittedFields = utils.MapInterface(data["fields"])
	}

	schema := orm.TomatoDBController.LoadSchema()
	result, err := schema.UpdateClass(className, submittedFields, utils.MapInterface(data["classLevelPermissions"]))
	if err != nil {
		s.Data["json"] = errs.ErrorToMap(err)
		s.ServeJSON()
		return
	}

	s.Data["json"] = result
	s.ServeJSON()
}

// HandleDelete 处理删除指定类请求
// @router /:className [delete]
func (s *SchemasController) HandleDelete() {
	className := s.Ctx.Input.Param(":className")
	if orm.ClassNameIsValid(className) == false {
		s.Data["json"] = errs.ErrorMessageToMap(errs.InvalidClassName, orm.InvalidClassNameMessage(className))
		s.ServeJSON()
		return
	}

	err := orm.TomatoDBController.DeleteSchema(className)
	if err != nil {
		s.Data["json"] = errs.ErrorToMap(err)
		s.ServeJSON()
		return
	}

	// 从 _SCHEMA 表中删除类信息，清除相关的 _Join 表
	coll := orm.TomatoDBController.SchemaCollection()
	document, err := coll.FindAndDeleteSchema(className)
	if err != nil {
		s.Data["json"] = errs.ErrorToMap(err)
		s.ServeJSON()
		return
	}
	if document != nil {
		err = removeJoinTables(document)
		if err != nil {
			s.Data["json"] = errs.ErrorToMap(err)
			s.ServeJSON()
			return
		}
	}
	s.Data["json"] = types.M{}
	s.ServeJSON()
	return
}

// removeJoinTables 清除类中的所有关联表
// 需要查找的类型： "field":"relation<otherClass>"
// 需要删除的表明： "_Join:field:className"
func removeJoinTables(mongoSchema types.M) error {
	for field, v := range mongoSchema {
		fieldType := utils.String(v)
		if field != "_metadata" && strings.HasPrefix(fieldType, "relation<") {
			collectionName := "_Join:" + field + ":" + utils.String(mongoSchema["_id"])
			err := orm.Adapter.DeleteOneSchema(collectionName)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// Delete ...
// @router / [delete]
func (s *SchemasController) Delete() {
	s.ObjectsController.Delete()
}

// Put ...
// @router / [put]
func (s *SchemasController) Put() {
	s.ObjectsController.Put()
}

// injectDefaultSchema 为 schema 添加默认字段
func injectDefaultSchema(schema types.M) types.M {
	defaultSchema := orm.DefaultColumns[schema["className"].(string)]
	if defaultSchema != nil {
		fields := schema["fields"].(map[string]interface{})
		for k, v := range defaultSchema {
			fields[k] = v
		}
		schema["fields"] = fields
	}
	return schema
}
<|endoftext|>


<commit_before>package acme

import (
	"bytes"
	"crypto"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rsa"
	"fmt"
	"net/http"
	"sync"

	"gopkg.in/square/go-jose.v1"
)

type jws struct {
	directoryURL string
	privKey      crypto.PrivateKey
	nonces       []string
	sync.Mutex
}

func keyAsJWK(key interface{}) *jose.JsonWebKey {
	switch k := key.(type) {
	case *ecdsa.PublicKey:
		return &jose.JsonWebKey{Key: k, Algorithm: "EC"}
	case *rsa.PublicKey:
		return &jose.JsonWebKey{Key: k, Algorithm: "RSA"}

	default:
		return nil
	}
}

// Posts a JWS signed message to the specified URL
func (j *jws) post(url string, content []byte) (*http.Response, error) {
	signedContent, err := j.signContent(content)
	if err != nil {
		return nil, err
	}

	resp, err := httpPost(url, "application/jose+json", bytes.NewBuffer([]byte(signedContent.FullSerialize())))
	if err != nil {
		return nil, err
	}

	j.Lock()
	defer j.Unlock()
	j.getNonceFromResponse(resp)

	return resp, err
}

func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) {

	var alg jose.SignatureAlgorithm
	switch k := j.privKey.(type) {
	case *rsa.PrivateKey:
		alg = jose.RS256
	case *ecdsa.PrivateKey:
		if k.Curve == elliptic.P256() {
			alg = jose.ES256
		} else if k.Curve == elliptic.P384() {
			alg = jose.ES384
		}
	}

	signer, err := jose.NewSigner(alg, j.privKey)
	if err != nil {
		return nil, err
	}
	signer.SetNonceSource(j)

	signed, err := signer.Sign(content)
	if err != nil {
		return nil, err
	}
	return signed, nil
}

func (j *jws) getNonceFromResponse(resp *http.Response) (string, error) {
	nonce := resp.Header.Get("Replay-Nonce")
	if nonce == "" {
		return "", fmt.Errorf("Server did not respond with a proper nonce header.")
	}

	j.nonces = append(j.nonces, nonce)
	return nonce, nil
}

func (j *jws) getNonce() (string, error) {
	resp, err := httpHead(j.directoryURL)
	if err != nil {
		return "", err
	}

	return j.getNonceFromResponse(resp)
}

func (j *jws) Nonce() (string, error) {
	j.Lock()
	defer j.Unlock()
	nonce := ""
	if len(j.nonces) == 0 {
		_, err := j.getNonce()
		if err != nil {
			return nonce, err
		}
	}
	if len(j.nonces) == 0 {
		return "", fmt.Errorf("Can't get nonce")
	}
	nonce, j.nonces = j.nonces[len(j.nonces)-1], j.nonces[:len(j.nonces)-1]
	return nonce, nil
}
<commit_msg>[reduce-locking] Do not lock on http request<commit_after>package acme

import (
	"bytes"
	"crypto"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rsa"
	"fmt"
	"net/http"
	"sync"

	"gopkg.in/square/go-jose.v1"
)

type jws struct {
	directoryURL string
	privKey      crypto.PrivateKey
	nonces       []string
	sync.Mutex
}

func keyAsJWK(key interface{}) *jose.JsonWebKey {
	switch k := key.(type) {
	case *ecdsa.PublicKey:
		return &jose.JsonWebKey{Key: k, Algorithm: "EC"}
	case *rsa.PublicKey:
		return &jose.JsonWebKey{Key: k, Algorithm: "RSA"}

	default:
		return nil
	}
}

// Posts a JWS signed message to the specified URL
func (j *jws) post(url string, content []byte) (*http.Response, error) {
	signedContent, err := j.signContent(content)
	if err != nil {
		return nil, err
	}

	resp, err := httpPost(url, "application/jose+json", bytes.NewBuffer([]byte(signedContent.FullSerialize())))
	if err != nil {
		return nil, err
	}

	nonce, nonceErr := j.getNonceFromResponse(resp)
	if nonceErr == nil {
		j.Lock()
		j.nonces = append(j.nonces, nonce)
		j.Unlock()
	}

	return resp, err
}

func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) {

	var alg jose.SignatureAlgorithm
	switch k := j.privKey.(type) {
	case *rsa.PrivateKey:
		alg = jose.RS256
	case *ecdsa.PrivateKey:
		if k.Curve == elliptic.P256() {
			alg = jose.ES256
		} else if k.Curve == elliptic.P384() {
			alg = jose.ES384
		}
	}

	signer, err := jose.NewSigner(alg, j.privKey)
	if err != nil {
		return nil, err
	}
	signer.SetNonceSource(j)

	signed, err := signer.Sign(content)
	if err != nil {
		return nil, err
	}
	return signed, nil
}

func (j *jws) getNonceFromResponse(resp *http.Response) (string, error) {
	nonce := resp.Header.Get("Replay-Nonce")
	if nonce == "" {
		return "", fmt.Errorf("Server did not respond with a proper nonce header.")
	}

	return nonce, nil
}

func (j *jws) getNonce() (string, error) {
	resp, err := httpHead(j.directoryURL)
	if err != nil {
		return "", err
	}

	return j.getNonceFromResponse(resp)
}

func (j *jws) Nonce() (string, error) {
	j.Lock()
	if len(j.nonces) == 0 {
		j.Unlock()
		return j.getNonce()
	}

	defer j.Unlock()
	nonce := j.nonces[len(j.nonces)-1]
	j.nonces = j.nonces[:len(j.nonces)-1]
	return nonce, nil
}
<|endoftext|>


<commit_before>package common

import (
	"context"
	"crypto/sha1"
	"encoding/hex"
	"fmt"
	"log"
	"os"
	"runtime"
	"strings"

	getter "github.com/hashicorp/go-getter"
	urlhelper "github.com/hashicorp/go-getter/helper/url"
	"github.com/hashicorp/packer/common/filelock"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

// StepDownload downloads a remote file using the download client within
// this package. This step handles setting up the download configuration,
// progress reporting, interrupt handling, etc.
//
// Uses:
//   cache packer.Cache
//   ui    packer.Ui
type StepDownload struct {
	// The checksum and the type of the checksum for the download
	Checksum     string
	ChecksumType string

	// A short description of the type of download being done. Example:
	// "ISO" or "Guest Additions"
	Description string

	// The name of the key where the final path of the ISO will be put
	// into the state.
	ResultKey string

	// The path where the result should go, otherwise it goes to the
	// cache directory.
	TargetPath string

	// A list of URLs to attempt to download this thing.
	Url []string

	// Extension is the extension to force for the file that is downloaded.
	// Some systems require a certain extension. If this isn't set, the
	// extension on the URL is used. Otherwise, this will be forced
	// on the downloaded file for every URL.
	Extension string
}

func (s *StepDownload) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
	ui := state.Get("ui").(packer.Ui)
	defer ui.Say(fmt.Sprintf("leaving retrieve loop for %s", s.Description))

	ui.Say(fmt.Sprintf("Retrieving %s", s.Description))

	var errs []error
	for _, source := range s.Url {
		if ctx.Err() != nil {
			state.Put("error", fmt.Errorf("Download cancelled: %v", errs))
			return multistep.ActionHalt
		}
		ui.Say(fmt.Sprintf("Trying %s", source))
		var err error
		var dst string
		if s.Description == "OVF/OVA" && strings.HasSuffix(source, ".ovf") {
			// TODO(adrien): make go-getter allow using files in place.
			// ovf files usually point to a file in the same directory, so
			// using them in place is the only way.
			ui.Say(fmt.Sprintf("Using ovf inplace"))
			dst = source
		} else {
			dst, err = s.download(ctx, ui, source)
		}
		if err == nil {
			state.Put(s.ResultKey, dst)
			return multistep.ActionContinue
		}
		// may be another url will work
		errs = append(errs, err)
	}

	err := fmt.Errorf("error downloading %s: %v", s.Description, errs)
	state.Put("error", err)
	ui.Error(err.Error())
	return multistep.ActionHalt
}

var (
	getters = getter.Getters
)

func init() {
	if runtime.GOOS == "windows" {
		getters["file"] = &getter.FileGetter{
			// always copy local files instead of symlinking to fix GH-7534. The
			// longer term fix for this would be to change the go-getter so that it
			// can leave the source file where it is & tell us where it is.
			Copy: true,
		}
		getters["smb"] = &getter.FileGetter{
			Copy: true,
		}
	}
}

func (s *StepDownload) download(ctx context.Context, ui packer.Ui, source string) (string, error) {
	u, err := urlhelper.Parse(source)
	if err != nil {
		return "", fmt.Errorf("url parse: %s", err)
	}
	if checksum := u.Query().Get("checksum"); checksum != "" {
		s.Checksum = checksum
	}
	if s.ChecksumType != "" && s.ChecksumType != "none" {
		// add checksum to url query params as go getter will checksum for us
		q := u.Query()
		q.Set("checksum", s.ChecksumType+":"+s.Checksum)
		u.RawQuery = q.Encode()
	} else if s.Checksum != "" {
		q := u.Query()
		q.Set("checksum", s.Checksum)
		u.RawQuery = q.Encode()
	}

	targetPath := s.TargetPath
	if targetPath == "" {
		// store file under sha1(hash) if set
		// hash can sometimes be a checksum url
		// otherwise, use sha1(source_url)
		var shaSum [20]byte
		if s.Checksum != "" {
			shaSum = sha1.Sum([]byte(s.Checksum))
		} else {
			shaSum = sha1.Sum([]byte(u.String()))
		}
		targetPath = hex.EncodeToString(shaSum[:])
		if s.Extension != "" {
			targetPath += "." + s.Extension
		}
	}
	targetPath, err = packer.CachePath(targetPath)
	if err != nil {
		return "", fmt.Errorf("CachePath: %s", err)
	}
	lockFile := targetPath + ".lock"

	log.Printf("Acquiring lock for: %s (%s)", u.String(), lockFile)
	lock := filelock.New(lockFile)
	lock.Lock()
	defer lock.Unlock()

	wd, err := os.Getwd()
	if err != nil {
		log.Printf("get working directory: %v", err)
		// here we ignore the error in case the
		// working directory is not needed.
		// It would be better if the go-getter
		// could guess it only in cases it is
		// necessary.
	}

	ui.Say(fmt.Sprintf("Trying %s", u.String()))
	gc := getter.Client{
		Ctx:              ctx,
		Dst:              targetPath,
		Src:              u.String(),
		ProgressListener: ui,
		Pwd:              wd,
		Dir:              false,
		Getters:          getters,
	}

	switch err := gc.Get(); err.(type) {
	case nil: // success !
		ui.Say(fmt.Sprintf("%s => %s", u.String(), targetPath))
		return targetPath, nil
	case *getter.ChecksumError:
		ui.Say(fmt.Sprintf("Checksum did not match, removing %s", targetPath))
		if err := os.Remove(targetPath); err != nil {
			ui.Error(fmt.Sprintf("Failed to remove cache file. Please remove manually: %s", targetPath))
		}
		return "", err
	default:
		ui.Say(fmt.Sprintf("Download failed %s", err))
		return "", err
	}
}

func (s *StepDownload) Cleanup(multistep.StateBag) {}
<commit_msg>enable smb share double backslash pathing too<commit_after>package common

import (
	"context"
	"crypto/sha1"
	"encoding/hex"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	getter "github.com/hashicorp/go-getter"
	urlhelper "github.com/hashicorp/go-getter/helper/url"
	"github.com/hashicorp/packer/common/filelock"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

// StepDownload downloads a remote file using the download client within
// this package. This step handles setting up the download configuration,
// progress reporting, interrupt handling, etc.
//
// Uses:
//   cache packer.Cache
//   ui    packer.Ui
type StepDownload struct {
	// The checksum and the type of the checksum for the download
	Checksum     string
	ChecksumType string

	// A short description of the type of download being done. Example:
	// "ISO" or "Guest Additions"
	Description string

	// The name of the key where the final path of the ISO will be put
	// into the state.
	ResultKey string

	// The path where the result should go, otherwise it goes to the
	// cache directory.
	TargetPath string

	// A list of URLs to attempt to download this thing.
	Url []string

	// Extension is the extension to force for the file that is downloaded.
	// Some systems require a certain extension. If this isn't set, the
	// extension on the URL is used. Otherwise, this will be forced
	// on the downloaded file for every URL.
	Extension string
}

func (s *StepDownload) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
	ui := state.Get("ui").(packer.Ui)
	defer ui.Say(fmt.Sprintf("leaving retrieve loop for %s", s.Description))

	ui.Say(fmt.Sprintf("Retrieving %s", s.Description))

	var errs []error
	for _, source := range s.Url {
		if ctx.Err() != nil {
			state.Put("error", fmt.Errorf("Download cancelled: %v", errs))
			return multistep.ActionHalt
		}
		ui.Say(fmt.Sprintf("Trying %s", source))
		var err error
		var dst string
		if s.Description == "OVF/OVA" && strings.HasSuffix(source, ".ovf") {
			// TODO(adrien): make go-getter allow using files in place.
			// ovf files usually point to a file in the same directory, so
			// using them in place is the only way.
			ui.Say(fmt.Sprintf("Using ovf inplace"))
			dst = source
		} else {
			dst, err = s.download(ctx, ui, source)
		}
		if err == nil {
			state.Put(s.ResultKey, dst)
			return multistep.ActionContinue
		}
		// may be another url will work
		errs = append(errs, err)
	}

	err := fmt.Errorf("error downloading %s: %v", s.Description, errs)
	state.Put("error", err)
	ui.Error(err.Error())
	return multistep.ActionHalt
}

var (
	getters = getter.Getters
)

func init() {
	if runtime.GOOS == "windows" {
		getters["file"] = &getter.FileGetter{
			// always copy local files instead of symlinking to fix GH-7534. The
			// longer term fix for this would be to change the go-getter so that it
			// can leave the source file where it is & tell us where it is.
			Copy: true,
		}
		getters["smb"] = &getter.FileGetter{
			Copy: true,
		}
	}
}

func (s *StepDownload) download(ctx context.Context, ui packer.Ui, source string) (string, error) {
	if runtime.GOOS == "windows" {
		// Check that the user specified a UNC path, and promote it to an smb:// uri.
		if strings.HasPrefix(source, "\\\\") && len(source) > 2 && source[2] != '?' {
			source = filepath.ToSlash(source[2:])
			source = fmt.Sprintf("smb://%s", source)
		}
	}

	u, err := urlhelper.Parse(source)
	if err != nil {
		return "", fmt.Errorf("url parse: %s", err)
	}
	if checksum := u.Query().Get("checksum"); checksum != "" {
		s.Checksum = checksum
	}
	if s.ChecksumType != "" && s.ChecksumType != "none" {
		// add checksum to url query params as go getter will checksum for us
		q := u.Query()
		q.Set("checksum", s.ChecksumType+":"+s.Checksum)
		u.RawQuery = q.Encode()
	} else if s.Checksum != "" {
		q := u.Query()
		q.Set("checksum", s.Checksum)
		u.RawQuery = q.Encode()
	}

	targetPath := s.TargetPath
	if targetPath == "" {
		// store file under sha1(hash) if set
		// hash can sometimes be a checksum url
		// otherwise, use sha1(source_url)
		var shaSum [20]byte
		if s.Checksum != "" {
			shaSum = sha1.Sum([]byte(s.Checksum))
		} else {
			shaSum = sha1.Sum([]byte(u.String()))
		}
		targetPath = hex.EncodeToString(shaSum[:])
		if s.Extension != "" {
			targetPath += "." + s.Extension
		}
	}
	targetPath, err = packer.CachePath(targetPath)
	if err != nil {
		return "", fmt.Errorf("CachePath: %s", err)
	}
	lockFile := targetPath + ".lock"

	log.Printf("Acquiring lock for: %s (%s)", u.String(), lockFile)
	lock := filelock.New(lockFile)
	lock.Lock()
	defer lock.Unlock()

	wd, err := os.Getwd()
	if err != nil {
		log.Printf("get working directory: %v", err)
		// here we ignore the error in case the
		// working directory is not needed.
		// It would be better if the go-getter
		// could guess it only in cases it is
		// necessary.
	}

	ui.Say(fmt.Sprintf("Trying %s", u.String()))
	gc := getter.Client{
		Ctx:              ctx,
		Dst:              targetPath,
		Src:              u.String(),
		ProgressListener: ui,
		Pwd:              wd,
		Dir:              false,
		Getters:          getters,
	}

	switch err := gc.Get(); err.(type) {
	case nil: // success !
		ui.Say(fmt.Sprintf("%s => %s", u.String(), targetPath))
		return targetPath, nil
	case *getter.ChecksumError:
		ui.Say(fmt.Sprintf("Checksum did not match, removing %s", targetPath))
		if err := os.Remove(targetPath); err != nil {
			ui.Error(fmt.Sprintf("Failed to remove cache file. Please remove manually: %s", targetPath))
		}
		return "", err
	default:
		ui.Say(fmt.Sprintf("Download failed %s", err))
		return "", err
	}
}

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