<commit_before>package lfs

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/github/git-lfs/git"
	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

const Version = "0.5.1"

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "git-lfs")
	UserAgent          string
	LocalWorkingDir    string
	LocalGitDir        string
	LocalMediaDir      string
	LocalLogDir        string
	checkedTempDir     string
)

func TempFile(prefix string) (*os.File, error) {
	if checkedTempDir != TempDir {
		if err := os.MkdirAll(TempDir, 0774); err != nil {
			return nil, err
		}
		checkedTempDir = TempDir
	}

	return ioutil.TempFile(TempDir, prefix)
}

func ResetTempDir() error {
	checkedTempDir = ""
	return os.RemoveAll(TempDir)
}

func LocalMediaPath(sha string) (string, error) {
	path := filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
	if err := os.MkdirAll(path, 0744); err != nil {
		return "", fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha), nil
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 6, len(osEnviron)+6)
	env[0] = fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir)
	env[1] = fmt.Sprintf("LocalGitDir=%s", LocalGitDir)
	env[2] = fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir)
	env[3] = fmt.Sprintf("TempDir=%s", TempDir)
	env[4] = fmt.Sprintf("ConcurrentTransfers=%d", Config.ConcurrentTransfers())
	env[5] = fmt.Sprintf("BatchTransfer=%v", Config.BatchTransfer())

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

func init() {
	var err error

	tracerx.DefaultKey = "GIT"
	tracerx.Prefix = "trace git-lfs: "

	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalMediaDir = filepath.Join(LocalGitDir, "lfs", "objects")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		TempDir = filepath.Join(LocalGitDir, "lfs", "tmp")

		if err := os.MkdirAll(LocalMediaDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create objects directory in '%s': %s", LocalMediaDir, err))
		}

		if err := os.MkdirAll(LocalLogDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create log directory in '%s': %s", LocalLogDir, err))
		}

		if err := os.MkdirAll(TempDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}

	}

	gitVersion, err := git.Config.Version()
	if err != nil {
		gitVersion = "unknown"
	}

	UserAgent = fmt.Sprintf("git-lfs/%s (GitHub; %s %s; git %s; go %s)", Version,
		runtime.GOOS,
		runtime.GOARCH,
		strings.Replace(gitVersion, "git version ", "", 1),
		strings.Replace(runtime.Version(), "go", "", 1))
}

func resolveGitDir() (string, string, error) {
	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	return recursiveResolveGitDir(wd)
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	var cleanDir = filepath.Clean(dir)
	if cleanDir[len(cleanDir)-1] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		return filepath.Dir(dir), dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	info, err := os.Stat(gitDir)
	if err != nil {
		return recursiveResolveGitDir(filepath.Dir(dir))
	}

	if !info.IsDir() {
		return resolveDotGitFile(gitDir)
	}

	return dir, gitDir, nil
}

func resolveDotGitFile(file string) (string, string, error) {
	// The local working directory is the directory the `.git` file is located in.
	wd := filepath.Dir(file)

	// The `.git` file tells us where the submodules `.git` directory is.
	gitDir, err := processDotGitFile(file)
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processDotGitFile(file string) (string, error) {
	f, err := os.Open(file)
	if err != nil {
		return "", err
	}
	defer f.Close()

	data := make([]byte, 512)
	n, err := f.Read(data)
	if err != nil {
		return "", err
	}

	contents := string(data[0:n])

	if !strings.HasPrefix(contents, gitPtrPrefix) {
		// The `.git` file has no entry telling us about gitdir.
		return "", nil
	}

	dir := strings.TrimSpace(strings.Split(contents, gitPtrPrefix)[1])

	if filepath.IsAbs(dir) {
		// The .git file contains an absolute path.
		return dir, nil
	}

	// The .git file contains a relative path.
	// Create an absolute path based on the directory the .git file is located in.
	absDir := filepath.Join(filepath.Dir(file), dir)

	return absDir, nil
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<commit_msg>Added some comments<commit_after>package lfs

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/github/git-lfs/git"
	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

const Version = "0.5.1"

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "git-lfs")
	UserAgent          string
	LocalWorkingDir    string
	LocalGitDir        string
	LocalMediaDir      string
	LocalLogDir        string
	checkedTempDir     string
)

func TempFile(prefix string) (*os.File, error) {
	if checkedTempDir != TempDir {
		if err := os.MkdirAll(TempDir, 0774); err != nil {
			return nil, err
		}
		checkedTempDir = TempDir
	}

	return ioutil.TempFile(TempDir, prefix)
}

func ResetTempDir() error {
	checkedTempDir = ""
	return os.RemoveAll(TempDir)
}

func LocalMediaPath(sha string) (string, error) {
	path := filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
	if err := os.MkdirAll(path, 0744); err != nil {
		return "", fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha), nil
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 6, len(osEnviron)+6)
	env[0] = fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir)
	env[1] = fmt.Sprintf("LocalGitDir=%s", LocalGitDir)
	env[2] = fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir)
	env[3] = fmt.Sprintf("TempDir=%s", TempDir)
	env[4] = fmt.Sprintf("ConcurrentTransfers=%d", Config.ConcurrentTransfers())
	env[5] = fmt.Sprintf("BatchTransfer=%v", Config.BatchTransfer())

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

func init() {
	var err error

	tracerx.DefaultKey = "GIT"
	tracerx.Prefix = "trace git-lfs: "

	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalMediaDir = filepath.Join(LocalGitDir, "lfs", "objects")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		TempDir = filepath.Join(LocalGitDir, "lfs", "tmp")

		if err := os.MkdirAll(LocalMediaDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create objects directory in '%s': %s", LocalMediaDir, err))
		}

		if err := os.MkdirAll(LocalLogDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create log directory in '%s': %s", LocalLogDir, err))
		}

		if err := os.MkdirAll(TempDir, 0744); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}

	}

	gitVersion, err := git.Config.Version()
	if err != nil {
		gitVersion = "unknown"
	}

	UserAgent = fmt.Sprintf("git-lfs/%s (GitHub; %s %s; git %s; go %s)", Version,
		runtime.GOOS,
		runtime.GOARCH,
		strings.Replace(gitVersion, "git version ", "", 1),
		strings.Replace(runtime.Version(), "go", "", 1))
}

func resolveGitDir() (string, string, error) {
	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	return recursiveResolveGitDir(wd)
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	var cleanDir = filepath.Clean(dir)
	if cleanDir[len(cleanDir)-1] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		return filepath.Dir(dir), dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	info, err := os.Stat(gitDir)
	if err != nil {
		// Found neither a directory nor a file named `.git`.
		// Move one directory up.
		return recursiveResolveGitDir(filepath.Dir(dir))
	}

	if !info.IsDir() {
		// Found a file named `.git` (we're in a submodule).
		return resolveDotGitFile(gitDir)
	}

	// Found the `.git` directory.
	return dir, gitDir, nil
}

func resolveDotGitFile(file string) (string, string, error) {
	// The local working directory is the directory the `.git` file is located in.
	wd := filepath.Dir(file)

	// The `.git` file tells us where the submodules `.git` directory is.
	gitDir, err := processDotGitFile(file)
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processDotGitFile(file string) (string, error) {
	f, err := os.Open(file)
	if err != nil {
		return "", err
	}
	defer f.Close()

	data := make([]byte, 512)
	n, err := f.Read(data)
	if err != nil {
		return "", err
	}

	contents := string(data[0:n])

	if !strings.HasPrefix(contents, gitPtrPrefix) {
		// The `.git` file has no entry telling us about gitdir.
		return "", nil
	}

	dir := strings.TrimSpace(strings.Split(contents, gitPtrPrefix)[1])

	if filepath.IsAbs(dir) {
		// The .git file contains an absolute path.
		return dir, nil
	}

	// The .git file contains a relative path.
	// Create an absolute path based on the directory the .git file is located in.
	absDir := filepath.Join(filepath.Dir(file), dir)

	return absDir, nil
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<|endoftext|>


<commit_before>package lfs

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

const Version = "0.5.1"

//
// Setup permissions for the given directories used here.
//
const (
    TempDirPerms       = 0755
    LocalMediaDirPerms = 0755
    LocalLogDirPerms   = 0755
)

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "git-lfs")
	UserAgent          string
	LocalWorkingDir    string
	LocalGitDir        string
	LocalMediaDir      string
	LocalLogDir        string
	checkedTempDir     string
)

func TempFile(prefix string) (*os.File, error) {
	if checkedTempDir != TempDir {
		if err := os.MkdirAll(TempDir, TempDirPerms); err != nil {
			return nil, err
		}
		checkedTempDir = TempDir
	}

	return ioutil.TempFile(TempDir, prefix)
}

func ResetTempDir() error {
	checkedTempDir = ""
	return os.RemoveAll(TempDir)
}

func LocalMediaPath(sha string) (string, error) {
	path := filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
	if err := os.MkdirAll(path, LocalMediaDirPerms); err != nil {
		return "", fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha), nil
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 6, len(osEnviron)+6)
	env[0] = fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir)
	env[1] = fmt.Sprintf("LocalGitDir=%s", LocalGitDir)
	env[2] = fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir)
	env[3] = fmt.Sprintf("TempDir=%s", TempDir)
	env[4] = fmt.Sprintf("ConcurrentTransfers=%d", Config.ConcurrentTransfers())
	env[5] = fmt.Sprintf("BatchTransfer=%v", Config.BatchTransfer())

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

func init() {
	var err error

	tracerx.DefaultKey = "GIT"
	tracerx.Prefix = "trace git-lfs: "

	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalMediaDir = filepath.Join(LocalGitDir, "lfs", "objects")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		TempDir = filepath.Join(LocalGitDir, "lfs", "tmp")

		if err := os.MkdirAll(LocalMediaDir, LocalMediaDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create objects directory in '%s': %s", LocalMediaDir, err))
		}

		if err := os.MkdirAll(LocalLogDir, LocalLogDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create log directory in '%s': %s", LocalLogDir, err))
		}

		if err := os.MkdirAll(TempDir, TempDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}

	}

	UserAgent = fmt.Sprintf("git-lfs/%s (GitHub; %s %s; go %s)", Version,
		runtime.GOOS,
		runtime.GOARCH,
		strings.Replace(runtime.Version(), "go", "", 1))
}

func resolveGitDir() (string, string, error) {
	gitDir := Config.Getenv("GIT_DIR")
	workTree := Config.Getenv("GIT_WORK_TREE")

	if gitDir != "" {
		return processGitDirVar(gitDir, workTree)
	}

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	workTreeR, gitDirR, err := recursiveResolveGitDir(wd)
	if err != nil {
		return "", "", err
	}

	if workTree != "" {
		return processWorkTree(gitDirR, workTree)
	}

	return workTreeR, gitDirR, nil
}

func processGitDirVar(gitDir, workTree string) (string, string, error) {
	if workTree != "" {
		return processWorkTree(gitDir, workTree)
	}

	// See `core.worktree` in `man git-config`:
	// “If --git-dir or GIT_DIR is specified but none of --work-tree, GIT_WORK_TREE and
	// core.worktree is specified, the current working directory is regarded as the top
	// level of your working tree.”

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processWorkTree(gitDir, workTree string) (string, string, error) {
	// See `core.worktree` in `man git-config`:
	// “The value [of core.worktree, GIT_WORK_TREE, or --work-tree] can be an absolute path
	// or relative to the path to the .git directory, which is either specified
	// by --git-dir or GIT_DIR, or automatically discovered.”

	if filepath.IsAbs(workTree) {
		return workTree, gitDir, nil
	}

	base := filepath.Dir(filepath.Clean(gitDir))
	absWorkTree := filepath.Join(base, workTree)
	return absWorkTree, gitDir, nil
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	var cleanDir = filepath.Clean(dir)
	if cleanDir[len(cleanDir)-1] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		// We're in the `.git` directory.  Make no assumptions about the working directory.
		return "", dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	info, err := os.Stat(gitDir)
	if err != nil {
		// Found neither a directory nor a file named `.git`.
		// Move one directory up.
		return recursiveResolveGitDir(filepath.Dir(dir))
	}

	if !info.IsDir() {
		// Found a file named `.git` (we're in a submodule).
		return resolveDotGitFile(gitDir)
	}

	// Found the `.git` directory.
	return dir, gitDir, nil
}

func resolveDotGitFile(file string) (string, string, error) {
	// The local working directory is the directory the `.git` file is located in.
	wd := filepath.Dir(file)

	// The `.git` file tells us where the submodules `.git` directory is.
	gitDir, err := processDotGitFile(file)
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processDotGitFile(file string) (string, error) {
	f, err := os.Open(file)
	if err != nil {
		return "", err
	}
	defer f.Close()

	data := make([]byte, 512)
	n, err := f.Read(data)
	if err != nil {
		return "", err
	}

	contents := string(data[0:n])

	if !strings.HasPrefix(contents, gitPtrPrefix) {
		// The `.git` file has no entry telling us about gitdir.
		return "", nil
	}

	dir := strings.TrimSpace(strings.Split(contents, gitPtrPrefix)[1])

	if filepath.IsAbs(dir) {
		// The .git file contains an absolute path.
		return dir, nil
	}

	// The .git file contains a relative path.
	// Create an absolute path based on the directory the .git file is located in.
	absDir := filepath.Join(filepath.Dir(file), dir)

	return absDir, nil
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<commit_msg>dont export the file mode constants, not needed by lfs package users<commit_after>package lfs

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

const Version = "0.5.1"

//
// Setup permissions for the given directories used here.
//
const (
	tempDirPerms       = 0755
	localMediaDirPerms = 0755
	localLogDirPerms   = 0755
)

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "git-lfs")
	UserAgent          string
	LocalWorkingDir    string
	LocalGitDir        string
	LocalMediaDir      string
	LocalLogDir        string
	checkedTempDir     string
)

func TempFile(prefix string) (*os.File, error) {
	if checkedTempDir != TempDir {
		if err := os.MkdirAll(TempDir, tempDirPerms); err != nil {
			return nil, err
		}
		checkedTempDir = TempDir
	}

	return ioutil.TempFile(TempDir, prefix)
}

func ResetTempDir() error {
	checkedTempDir = ""
	return os.RemoveAll(TempDir)
}

func LocalMediaPath(sha string) (string, error) {
	path := filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
	if err := os.MkdirAll(path, localMediaDirPerms); err != nil {
		return "", fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha), nil
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 6, len(osEnviron)+6)
	env[0] = fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir)
	env[1] = fmt.Sprintf("LocalGitDir=%s", LocalGitDir)
	env[2] = fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir)
	env[3] = fmt.Sprintf("TempDir=%s", TempDir)
	env[4] = fmt.Sprintf("ConcurrentTransfers=%d", Config.ConcurrentTransfers())
	env[5] = fmt.Sprintf("BatchTransfer=%v", Config.BatchTransfer())

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

func init() {
	var err error

	tracerx.DefaultKey = "GIT"
	tracerx.Prefix = "trace git-lfs: "

	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalMediaDir = filepath.Join(LocalGitDir, "lfs", "objects")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		TempDir = filepath.Join(LocalGitDir, "lfs", "tmp")

		if err := os.MkdirAll(LocalMediaDir, localMediaDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create objects directory in '%s': %s", LocalMediaDir, err))
		}

		if err := os.MkdirAll(LocalLogDir, localLogDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create log directory in '%s': %s", LocalLogDir, err))
		}

		if err := os.MkdirAll(TempDir, tempDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}

	}

	UserAgent = fmt.Sprintf("git-lfs/%s (GitHub; %s %s; go %s)", Version,
		runtime.GOOS,
		runtime.GOARCH,
		strings.Replace(runtime.Version(), "go", "", 1))
}

func resolveGitDir() (string, string, error) {
	gitDir := Config.Getenv("GIT_DIR")
	workTree := Config.Getenv("GIT_WORK_TREE")

	if gitDir != "" {
		return processGitDirVar(gitDir, workTree)
	}

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	workTreeR, gitDirR, err := recursiveResolveGitDir(wd)
	if err != nil {
		return "", "", err
	}

	if workTree != "" {
		return processWorkTree(gitDirR, workTree)
	}

	return workTreeR, gitDirR, nil
}

func processGitDirVar(gitDir, workTree string) (string, string, error) {
	if workTree != "" {
		return processWorkTree(gitDir, workTree)
	}

	// See `core.worktree` in `man git-config`:
	// “If --git-dir or GIT_DIR is specified but none of --work-tree, GIT_WORK_TREE and
	// core.worktree is specified, the current working directory is regarded as the top
	// level of your working tree.”

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processWorkTree(gitDir, workTree string) (string, string, error) {
	// See `core.worktree` in `man git-config`:
	// “The value [of core.worktree, GIT_WORK_TREE, or --work-tree] can be an absolute path
	// or relative to the path to the .git directory, which is either specified
	// by --git-dir or GIT_DIR, or automatically discovered.”

	if filepath.IsAbs(workTree) {
		return workTree, gitDir, nil
	}

	base := filepath.Dir(filepath.Clean(gitDir))
	absWorkTree := filepath.Join(base, workTree)
	return absWorkTree, gitDir, nil
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	var cleanDir = filepath.Clean(dir)
	if cleanDir[len(cleanDir)-1] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		// We're in the `.git` directory.  Make no assumptions about the working directory.
		return "", dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	info, err := os.Stat(gitDir)
	if err != nil {
		// Found neither a directory nor a file named `.git`.
		// Move one directory up.
		return recursiveResolveGitDir(filepath.Dir(dir))
	}

	if !info.IsDir() {
		// Found a file named `.git` (we're in a submodule).
		return resolveDotGitFile(gitDir)
	}

	// Found the `.git` directory.
	return dir, gitDir, nil
}

func resolveDotGitFile(file string) (string, string, error) {
	// The local working directory is the directory the `.git` file is located in.
	wd := filepath.Dir(file)

	// The `.git` file tells us where the submodules `.git` directory is.
	gitDir, err := processDotGitFile(file)
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processDotGitFile(file string) (string, error) {
	f, err := os.Open(file)
	if err != nil {
		return "", err
	}
	defer f.Close()

	data := make([]byte, 512)
	n, err := f.Read(data)
	if err != nil {
		return "", err
	}

	contents := string(data[0:n])

	if !strings.HasPrefix(contents, gitPtrPrefix) {
		// The `.git` file has no entry telling us about gitdir.
		return "", nil
	}

	dir := strings.TrimSpace(strings.Split(contents, gitPtrPrefix)[1])

	if filepath.IsAbs(dir) {
		// The .git file contains an absolute path.
		return dir, nil
	}

	// The .git file contains a relative path.
	// Create an absolute path based on the directory the .git file is located in.
	absDir := filepath.Join(filepath.Dir(file), dir)

	return absDir, nil
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<|endoftext|>


<commit_before>package ddb_test

import (
	"math"
	"strconv"

	"github.com/aws/aws-sdk-go/aws/awsutil"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	. "github.com/runtakun/dynamodb-marshaler-go"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type sample struct {
	Str             string                 `json:"str"`
	Bool            bool                   `json:"bool"`
	Blob            []byte                 `json:"blob"`
	Int             int                    `json:"int"`
	Int8            int8                   `json:"int8"`
	Int16           int16                  `json:"int16"`
	Int32           int32                  `json:"int32"`
	Int64           int64                  `json:"int64"`
	Uint            uint                   `json:"uint"`
	Uint8           uint8                  `json:"uint8"`
	Uint16          uint16                 `json:"uint16"`
	Uint32          uint32                 `json:"uint32"`
	Uint64          uint64                 `json:"uint64"`
	Float32         float32                `json:"float32"`
	Float64         float64                `json:"float64"`
	Arr             [3]int                 `json:"arr"`
	InterfaceInt    interface{}            `json:"interface_int"`
	InterfaceString interface{}            `json:"interface_str"`
	Map             map[string]interface{} `json:"map"`
	Ptr             *string                `json:"ptr"`
	Slice           []string               `json:"slice"`
	EmptySlice      []int                  `json:"empty_slice"`
	Child           *child                 `json:"child"`
}

type child struct {
	Content string `json:"content"`
}

var _ = Describe("Marshal", func() {
	Context("input struct", func() {

		var sut map[string]*dynamodb.AttributeValue

		BeforeEach(func() {

			ptr := "ptr"

			s := &sample{
				Str:             "foo",
				Bool:            false,
				Blob:            []byte{0x0, 0x1, 0x2, 0x3, 0x4},
				Int:             1,
				Int8:            2,
				Int16:           3,
				Int32:           4,
				Int64:           5,
				Uint:            1,
				Uint8:           2,
				Uint16:          3,
				Uint32:          4,
				Uint64:          5,
				Float32:         math.E,
				Float64:         math.Pi,
				Arr:             [3]int{1, 2, 3},
				EmptySlice:      []int{},
				InterfaceInt:    12345,
				InterfaceString: "bar",
				Map: map[string]interface{}{
					"map_str": "map_bar",
					"map_int": 54321,
				},
				Ptr:   &ptr,
				Slice: []string{"f", "o", "o"},
				Child: &child{Content: "bar_child"},
			}
			sut = Marshal(s)
			GinkgoWriter.Write([]byte(awsutil.Prettify(sut)))
		})

		It("should not be nil", func() {
			Expect(sut).NotTo(BeNil())
		})

		It("should be `str` element to dynamodb attribute value", func() {
			Expect(*sut["str"].S).To(Equal("foo"))
			Expect(sut["str"].N).To(BeNil())
		})

		It("should be `bool` element to dynamodb attribute value", func() {
			Expect(*sut["bool"].BOOL).To(BeFalse())
			Expect(sut["bool"].S).To(BeNil())
		})

		It("should be `blob` element to dynamodb attribute value", func() {
			Expect(sut["blob"].B).Should(HaveLen(5))
		})

		It("should be `int` element to dynamodb attribute value", func() {
			Expect(*sut["int"].N).To(Equal("1"))
			Expect(sut["int"].S).To(BeNil())
		})

		It("should be `int8` element to dynamodb attribute value", func() {
			Expect(*sut["int8"].N).To(Equal("2"))
			Expect(sut["int8"].S).To(BeNil())
		})

		It("should be `int16` element to dynamodb attribute value", func() {
			Expect(*sut["int16"].N).To(Equal("3"))
			Expect(sut["int16"].S).To(BeNil())
		})

		It("should be `int32` element to dynamodb attribute value", func() {
			Expect(*sut["int32"].N).To(Equal("4"))
			Expect(sut["int32"].S).To(BeNil())
		})

		It("should be `int64` element to dynamodb attribute value", func() {
			Expect(*sut["int64"].N).To(Equal("5"))
			Expect(sut["int64"].S).To(BeNil())
		})

		It("should be `uint` element to dynamodb attribute value", func() {
			Expect(*sut["uint"].N).To(Equal("1"))
			Expect(sut["uint"].S).To(BeNil())
		})

		It("should be `uint8` element to dynamodb attribute value", func() {
			Expect(*sut["uint8"].N).To(Equal("2"))
			Expect(sut["uint8"].S).To(BeNil())
		})

		It("should be `uint16` element to dynamodb attribute value", func() {
			Expect(*sut["uint16"].N).To(Equal("3"))
			Expect(sut["uint16"].S).To(BeNil())
		})

		It("should be `uint32` element to dynamodb attribute value", func() {
			Expect(*sut["uint32"].N).To(Equal("4"))
			Expect(sut["uint32"].S).To(BeNil())
		})

		It("should be `uint64` element to dynamodb attribute value", func() {
			Expect(*sut["uint64"].N).To(Equal("5"))
			Expect(sut["uint64"].S).To(BeNil())
		})

		It("should be `float32` element to dynamodb attribute value", func() {
			f32, _ := strconv.ParseFloat(*sut["float32"].N, 32)
			Expect(f32).Should(BeNumerically("~", math.E, 1e-6))
		})

		It("should be `float64` element to dynamodb attribute value", func() {
			f64, _ := strconv.ParseFloat(*sut["float64"].N, 64)
			Expect(f64).Should(BeNumerically("~", math.Pi, 1e-6))
		})

		It("should be `arr` element to dynamodb attribute value", func() {
			Expect(sut["arr"].L).Should(HaveLen(3))
			Expect(sut["arr"].S).To(BeNil())
		})

		It("should be `empty_slice` element to dynamodb attribute value", func() {
			Expect(sut["empty_slice"].L).Should(HaveLen(0))
			Expect(sut["empty_slice"].N).To(BeNil())
		})

		It("should be interface type to dynamodb attribute value", func() {
			Expect(*sut["interface_int"].N).To(Equal("12345"))
			Expect(*sut["interface_str"].S).To(Equal("bar"))
		})

		It("should be `map` type to dynamodb attribute value", func() {
			m := sut["map"].M
			Expect(*m["map_str"].S).To(Equal("map_bar"))
			Expect(*m["map_int"].N).To(Equal("54321"))
		})

		It("should be `ptr` type to dynamodb attribute value", func() {
			Expect(*sut["ptr"].S).To(Equal("ptr"))
		})

		It("should be `slice` type to dynamodb attribute value", func() {
			Expect(sut["slice"].L).Should(HaveLen(3))
		})

		It("should be `child` type to dynamodb attribute value", func() {
			child := sut["child"].M
			Expect(*child["content"].S).To(Equal("bar_child"))
		})
	})

	Context("empty value", func() {

		var sut map[string]*dynamodb.AttributeValue

		BeforeEach(func() {
			s := &sample{
				Str:   "",
				Map:   nil,
				Child: nil,
			}
			sut = Marshal(s)
			GinkgoWriter.Write([]byte(awsutil.Prettify(sut)))
		})

		It("should be `str` type to null value", func() {
			Expect(*sut["str"].NULL).To(BeTrue())
			Expect(sut["str"].S).To(BeNil())
		})

		It("should be `map` type to null value", func() {
			Expect(*sut["map"].NULL).To(BeTrue())
			Expect(sut["map"].M).To(BeNil())
		})

		It("should be `child` type to null value", func() {
			Expect(*sut["child"].NULL).To(BeTrue())
			Expect(sut["child"].M).To(BeNil())
		})

	})

})
<commit_msg>changed map key name<commit_after>package ddb_test

import (
	"math"
	"strconv"

	"github.com/aws/aws-sdk-go/aws/awsutil"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	. "github.com/runtakun/dynamodb-marshaler-go"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type sample struct {
	Str             string                 `json:"str"`
	Bool            bool                   `json:"bool"`
	Blob            []byte                 `json:"blob"`
	Int             int                    `json:"int"`
	Int8            int8                   `json:"int8"`
	Int16           int16                  `json:"int16"`
	Int32           int32                  `json:"int32"`
	Int64           int64                  `json:"int64"`
	Uint            uint                   `json:"uint"`
	Uint8           uint8                  `json:"uint8"`
	Uint16          uint16                 `json:"uint16"`
	Uint32          uint32                 `json:"uint32"`
	Uint64          uint64                 `json:"uint64"`
	Float32         float32                `json:"float32"`
	Float64         float64                `json:"float64"`
	Arr             [3]int                 `json:"arr"`
	InterfaceInt    interface{}            `json:"interface_int"`
	InterfaceString interface{}            `json:"interface_str"`
	Map             map[string]interface{} `json:"map"`
	Ptr             *string                `json:"ptr"`
	Slice           []string               `json:"slice"`
	EmptySlice      []int                  `json:"empty_slice"`
	Child           *child                 `json:"child"`
}

type child struct {
	Content string `json:"content"`
}

var _ = Describe("Marshal", func() {
	Context("input struct", func() {

		var sut map[string]*dynamodb.AttributeValue

		BeforeEach(func() {

			ptr := "ptr"

			s := &sample{
				Str:             "foo",
				Bool:            false,
				Blob:            []byte{0x0, 0x1, 0x2, 0x3, 0x4},
				Int:             1,
				Int8:            2,
				Int16:           3,
				Int32:           4,
				Int64:           5,
				Uint:            1,
				Uint8:           2,
				Uint16:          3,
				Uint32:          4,
				Uint64:          5,
				Float32:         math.E,
				Float64:         math.Pi,
				Arr:             [3]int{1, 2, 3},
				EmptySlice:      []int{},
				InterfaceInt:    12345,
				InterfaceString: "bar",
				Map: map[string]interface{}{
					"map_foo": "map_bar",
					"map_int": 54321,
				},
				Ptr:   &ptr,
				Slice: []string{"f", "o", "o"},
				Child: &child{Content: "bar_child"},
			}
			sut = Marshal(s)
			GinkgoWriter.Write([]byte(awsutil.Prettify(sut)))
		})

		It("should not be nil", func() {
			Expect(sut).NotTo(BeNil())
		})

		It("should be `str` element to dynamodb attribute value", func() {
			Expect(*sut["str"].S).To(Equal("foo"))
			Expect(sut["str"].N).To(BeNil())
		})

		It("should be `bool` element to dynamodb attribute value", func() {
			Expect(*sut["bool"].BOOL).To(BeFalse())
			Expect(sut["bool"].S).To(BeNil())
		})

		It("should be `blob` element to dynamodb attribute value", func() {
			Expect(sut["blob"].B).Should(HaveLen(5))
		})

		It("should be `int` element to dynamodb attribute value", func() {
			Expect(*sut["int"].N).To(Equal("1"))
			Expect(sut["int"].S).To(BeNil())
		})

		It("should be `int8` element to dynamodb attribute value", func() {
			Expect(*sut["int8"].N).To(Equal("2"))
			Expect(sut["int8"].S).To(BeNil())
		})

		It("should be `int16` element to dynamodb attribute value", func() {
			Expect(*sut["int16"].N).To(Equal("3"))
			Expect(sut["int16"].S).To(BeNil())
		})

		It("should be `int32` element to dynamodb attribute value", func() {
			Expect(*sut["int32"].N).To(Equal("4"))
			Expect(sut["int32"].S).To(BeNil())
		})

		It("should be `int64` element to dynamodb attribute value", func() {
			Expect(*sut["int64"].N).To(Equal("5"))
			Expect(sut["int64"].S).To(BeNil())
		})

		It("should be `uint` element to dynamodb attribute value", func() {
			Expect(*sut["uint"].N).To(Equal("1"))
			Expect(sut["uint"].S).To(BeNil())
		})

		It("should be `uint8` element to dynamodb attribute value", func() {
			Expect(*sut["uint8"].N).To(Equal("2"))
			Expect(sut["uint8"].S).To(BeNil())
		})

		It("should be `uint16` element to dynamodb attribute value", func() {
			Expect(*sut["uint16"].N).To(Equal("3"))
			Expect(sut["uint16"].S).To(BeNil())
		})

		It("should be `uint32` element to dynamodb attribute value", func() {
			Expect(*sut["uint32"].N).To(Equal("4"))
			Expect(sut["uint32"].S).To(BeNil())
		})

		It("should be `uint64` element to dynamodb attribute value", func() {
			Expect(*sut["uint64"].N).To(Equal("5"))
			Expect(sut["uint64"].S).To(BeNil())
		})

		It("should be `float32` element to dynamodb attribute value", func() {
			f32, _ := strconv.ParseFloat(*sut["float32"].N, 32)
			Expect(f32).Should(BeNumerically("~", math.E, 1e-6))
		})

		It("should be `float64` element to dynamodb attribute value", func() {
			f64, _ := strconv.ParseFloat(*sut["float64"].N, 64)
			Expect(f64).Should(BeNumerically("~", math.Pi, 1e-6))
		})

		It("should be `arr` element to dynamodb attribute value", func() {
			Expect(sut["arr"].L).Should(HaveLen(3))
			Expect(sut["arr"].S).To(BeNil())
		})

		It("should be `empty_slice` element to dynamodb attribute value", func() {
			Expect(sut["empty_slice"].L).Should(HaveLen(0))
			Expect(sut["empty_slice"].N).To(BeNil())
		})

		It("should be interface type to dynamodb attribute value", func() {
			Expect(*sut["interface_int"].N).To(Equal("12345"))
			Expect(*sut["interface_str"].S).To(Equal("bar"))
		})

		It("should be `map` type to dynamodb attribute value", func() {
			m := sut["map"].M
			Expect(*m["map_foo"].S).To(Equal("map_bar"))
			Expect(*m["map_int"].N).To(Equal("54321"))
		})

		It("should be `ptr` type to dynamodb attribute value", func() {
			Expect(*sut["ptr"].S).To(Equal("ptr"))
		})

		It("should be `slice` type to dynamodb attribute value", func() {
			Expect(sut["slice"].L).Should(HaveLen(3))
		})

		It("should be `child` type to dynamodb attribute value", func() {
			child := sut["child"].M
			Expect(*child["content"].S).To(Equal("bar_child"))
		})
	})

	Context("empty value", func() {

		var sut map[string]*dynamodb.AttributeValue

		BeforeEach(func() {
			s := &sample{
				Str:   "",
				Map:   nil,
				Child: nil,
			}
			sut = Marshal(s)
			GinkgoWriter.Write([]byte(awsutil.Prettify(sut)))
		})

		It("should be `str` type to null value", func() {
			Expect(*sut["str"].NULL).To(BeTrue())
			Expect(sut["str"].S).To(BeNil())
		})

		It("should be `map` type to null value", func() {
			Expect(*sut["map"].NULL).To(BeTrue())
			Expect(sut["map"].M).To(BeNil())
		})

		It("should be `child` type to null value", func() {
			Expect(*sut["child"].NULL).To(BeTrue())
			Expect(sut["child"].M).To(BeNil())
		})

	})

})
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/42wim/matterbridge/bridge/config"
	"github.com/42wim/matterbridge/gateway"
	"github.com/42wim/matterbridge/gateway/bridgemap"
	"github.com/google/gops/agent"
	prefixed "github.com/matterbridge/logrus-prefixed-formatter"
	"github.com/sirupsen/logrus"
)

var (
	version = "1.13.1"
	githash string
)

func main() {
	logrus.SetFormatter(&prefixed.TextFormatter{PrefixPadding: 13, DisableColors: true, FullTimestamp: true})
	flog := logrus.WithFields(logrus.Fields{"prefix": "main"})
	flagConfig := flag.String("conf", "matterbridge.toml", "config file")
	flagDebug := flag.Bool("debug", false, "enable debug")
	flagVersion := flag.Bool("version", false, "show version")
	flagGops := flag.Bool("gops", false, "enable gops agent")
	flag.Parse()
	if *flagGops {
		if err := agent.Listen(agent.Options{}); err != nil {
			flog.Errorf("failed to start gops agent: %#v", err)
		} else {
			defer agent.Close()
		}
	}
	if *flagVersion {
		fmt.Printf("version: %s %s\n", version, githash)
		return
	}
	if *flagDebug || os.Getenv("DEBUG") == "1" {
		logrus.SetFormatter(&prefixed.TextFormatter{PrefixPadding: 13, DisableColors: true, FullTimestamp: false, ForceFormatting: true})
		flog.Info("Enabling debug")
		logrus.SetLevel(logrus.DebugLevel)
	}
	flog.Printf("Running version %s %s", version, githash)
	if strings.Contains(version, "-dev") {
		flog.Println("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
	}
	cfg := config.NewConfig(*flagConfig)
	cfg.BridgeValues().General.Debug = *flagDebug
	r, err := gateway.NewRouter(cfg, bridgemap.FullMap)
	if err != nil {
		flog.Fatalf("Starting gateway failed: %s", err)
	}
	err = r.Start()
	if err != nil {
		flog.Fatalf("Starting gateway failed: %s", err)
	}
	flog.Printf("Gateway(s) started succesfully. Now relaying messages")
	select {}
}
<commit_msg>Bump version<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/42wim/matterbridge/bridge/config"
	"github.com/42wim/matterbridge/gateway"
	"github.com/42wim/matterbridge/gateway/bridgemap"
	"github.com/google/gops/agent"
	prefixed "github.com/matterbridge/logrus-prefixed-formatter"
	"github.com/sirupsen/logrus"
)

var (
	version = "1.13.2-dev"
	githash string
)

func main() {
	logrus.SetFormatter(&prefixed.TextFormatter{PrefixPadding: 13, DisableColors: true, FullTimestamp: true})
	flog := logrus.WithFields(logrus.Fields{"prefix": "main"})
	flagConfig := flag.String("conf", "matterbridge.toml", "config file")
	flagDebug := flag.Bool("debug", false, "enable debug")
	flagVersion := flag.Bool("version", false, "show version")
	flagGops := flag.Bool("gops", false, "enable gops agent")
	flag.Parse()
	if *flagGops {
		if err := agent.Listen(agent.Options{}); err != nil {
			flog.Errorf("failed to start gops agent: %#v", err)
		} else {
			defer agent.Close()
		}
	}
	if *flagVersion {
		fmt.Printf("version: %s %s\n", version, githash)
		return
	}
	if *flagDebug || os.Getenv("DEBUG") == "1" {
		logrus.SetFormatter(&prefixed.TextFormatter{PrefixPadding: 13, DisableColors: true, FullTimestamp: false, ForceFormatting: true})
		flog.Info("Enabling debug")
		logrus.SetLevel(logrus.DebugLevel)
	}
	flog.Printf("Running version %s %s", version, githash)
	if strings.Contains(version, "-dev") {
		flog.Println("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
	}
	cfg := config.NewConfig(*flagConfig)
	cfg.BridgeValues().General.Debug = *flagDebug
	r, err := gateway.NewRouter(cfg, bridgemap.FullMap)
	if err != nil {
		flog.Fatalf("Starting gateway failed: %s", err)
	}
	err = r.Start()
	if err != nil {
		flog.Fatalf("Starting gateway failed: %s", err)
	}
	flog.Printf("Gateway(s) started succesfully. Now relaying messages")
	select {}
}
<|endoftext|>


<commit_before>package aws

import (
	"bytes"
	"fmt"
	"log"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/waf"
	"github.com/aws/aws-sdk-go/service/wafregional"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsWafRegionalSqlInjectionMatchSet() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsWafRegionalSqlInjectionMatchSetCreate,
		Read:   resourceAwsWafRegionalSqlInjectionMatchSetRead,
		Update: resourceAwsWafRegionalSqlInjectionMatchSetUpdate,
		Delete: resourceAwsWafRegionalSqlInjectionMatchSetDelete,

		Schema: map[string]*schema.Schema{
			"name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"sql_injection_match_tuple": {
				Type:     schema.TypeSet,
				Optional: true,
				Set:      resourceAwsWafRegionalSqlInjectionMatchSetTupleHash,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"field_to_match": {
							Type:     schema.TypeList,
							Required: true,
							MaxItems: 1,
							Elem: &schema.Resource{
								Schema: map[string]*schema.Schema{
									"data": {
										Type:     schema.TypeString,
										Optional: true,
										StateFunc: func(v interface{}) string {
											value := v.(string)
											return strings.ToLower(value)
										},
									},
									"type": {
										Type:     schema.TypeString,
										Required: true,
									},
								},
							},
						},
						"text_transformation": {
							Type:     schema.TypeString,
							Required: true,
						},
					},
				},
			},
		},
	}
}

func resourceAwsWafRegionalSqlInjectionMatchSetCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).wafregionalconn
	region := meta.(*AWSClient).region

	log.Printf("[INFO] Creating Regional WAF SQL Injection Match Set: %s", d.Get("name").(string))

	wr := newWafRegionalRetryer(conn, region)
	out, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
		params := &waf.CreateSqlInjectionMatchSetInput{
			ChangeToken: token,
			Name:        aws.String(d.Get("name").(string)),
		}

		return conn.CreateSqlInjectionMatchSet(params)
	})
	if err != nil {
		return fmt.Errorf("Failed creating Regional WAF SQL Injection Match Set: %s", err)
	}
	resp := out.(*waf.CreateSqlInjectionMatchSetOutput)
	d.SetId(*resp.SqlInjectionMatchSet.SqlInjectionMatchSetId)

	return resourceAwsWafRegionalSqlInjectionMatchSetUpdate(d, meta)
}

func resourceAwsWafRegionalSqlInjectionMatchSetRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).wafregionalconn
	log.Printf("[INFO] Reading Regional WAF SQL Injection Match Set: %s", d.Get("name").(string))
	params := &waf.GetSqlInjectionMatchSetInput{
		SqlInjectionMatchSetId: aws.String(d.Id()),
	}

	resp, err := conn.GetSqlInjectionMatchSet(params)
	if err != nil {
		if isAWSErr(err, wafregional.ErrCodeWAFNonexistentItemException, "") {
			log.Printf("[WARN] Regional WAF SQL Injection Match Set (%s) not found, error code (404)", d.Id())
			d.SetId("")
			return nil
		}

		return err
	}

	d.Set("name", resp.SqlInjectionMatchSet.Name)
	d.Set("sql_injection_match_tuple", flattenWafSqlInjectionMatchTuples(resp.SqlInjectionMatchSet.SqlInjectionMatchTuples))

	return nil
}

func resourceAwsWafRegionalSqlInjectionMatchSetUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).wafregionalconn
	region := meta.(*AWSClient).region

	if d.HasChange("sql_injection_match_tuple") {
		o, n := d.GetChange("sql_injection_match_tuple")
		oldT, newT := o.(*schema.Set).List(), n.(*schema.Set).List()

		err := updateSqlInjectionMatchSetResourceWR(d.Id(), oldT, newT, conn, region)
		if err != nil {
			return fmt.Errorf("Error updating Regional WAF SQL Injection Match Set: %s", err)
		}
	}

	return resourceAwsWafRegionalSqlInjectionMatchSetRead(d, meta)
}

func resourceAwsWafRegionalSqlInjectionMatchSetDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).wafregionalconn
	region := meta.(*AWSClient).region

	oldTuples := d.Get("sql_injection_match_tuple").(*schema.Set).List()

	if len(oldTuples) > 0 {
		noTuples := []interface{}{}
		err := updateSqlInjectionMatchSetResourceWR(d.Id(), oldTuples, noTuples, conn, region)
		if err != nil {
			return fmt.Errorf("Error deleting Regional WAF SQL Injection Match Set: %s", err)
		}
	}

	wr := newWafRegionalRetryer(conn, region)
	_, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
		req := &waf.DeleteSqlInjectionMatchSetInput{
			ChangeToken:            token,
			SqlInjectionMatchSetId: aws.String(d.Id()),
		}

		return conn.DeleteSqlInjectionMatchSet(req)
	})
	if err != nil {
		return fmt.Errorf("Failed deleting Regional WAF SQL Injection Match Set: %s", err)
	}

	return nil
}

func updateSqlInjectionMatchSetResourceWR(id string, oldT, newT []interface{}, conn *wafregional.WAFRegional, region string) error {
	wr := newWafRegionalRetryer(conn, region)
	_, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
		req := &waf.UpdateSqlInjectionMatchSetInput{
			ChangeToken:            token,
			SqlInjectionMatchSetId: aws.String(id),
			Updates:                diffWafSqlInjectionMatchTuplesWR(oldT, newT),
		}

		log.Printf("[INFO] Updating Regional WAF SQL Injection Match Set: %s", req)
		return conn.UpdateSqlInjectionMatchSet(req)
	})
	if err != nil {
		return fmt.Errorf("Failed updating Regional WAF SQL Injection Match Set: %s", err)
	}

	return nil
}

func diffWafSqlInjectionMatchTuplesWR(oldT, newT []interface{}) []*waf.SqlInjectionMatchSetUpdate {
	updates := make([]*waf.SqlInjectionMatchSetUpdate, 0)

	for _, od := range oldT {
		tuple := od.(map[string]interface{})

		if idx, contains := sliceContainsMap(newT, tuple); contains {
			newT = append(newT[:idx], newT[idx+1:]...)
			continue
		}

		ftm := tuple["field_to_match"].([]interface{})

		updates = append(updates, &waf.SqlInjectionMatchSetUpdate{
			Action: aws.String(waf.ChangeActionDelete),
			SqlInjectionMatchTuple: &waf.SqlInjectionMatchTuple{
				FieldToMatch:       expandFieldToMatch(ftm[0].(map[string]interface{})),
				TextTransformation: aws.String(tuple["text_transformation"].(string)),
			},
		})
	}

	for _, nd := range newT {
		tuple := nd.(map[string]interface{})
		ftm := tuple["field_to_match"].([]interface{})

		updates = append(updates, &waf.SqlInjectionMatchSetUpdate{
			Action: aws.String(waf.ChangeActionInsert),
			SqlInjectionMatchTuple: &waf.SqlInjectionMatchTuple{
				FieldToMatch:       expandFieldToMatch(ftm[0].(map[string]interface{})),
				TextTransformation: aws.String(tuple["text_transformation"].(string)),
			},
		})
	}
	return updates
}

func resourceAwsWafRegionalSqlInjectionMatchSetTupleHash(v interface{}) int {
	var buf bytes.Buffer
	m := v.(map[string]interface{})
	if v, ok := m["field_to_match"]; ok {
		ftms := v.([]interface{})
		ftm := ftms[0].(map[string]interface{})

		if v, ok := ftm["data"]; ok {
			buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(v.(string))))
		}
		buf.WriteString(fmt.Sprintf("%s-", ftm["type"].(string)))
	}
	buf.WriteString(fmt.Sprintf("%s-", m["text_transformation"].(string)))

	return hashcode.String(buf.String())
}
<commit_msg>refactor aws_wafregional_sql_injection_match_set resource<commit_after>package aws

import (
	"bytes"
	"fmt"
	"log"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/waf"
	"github.com/aws/aws-sdk-go/service/wafregional"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsWafRegionalSqlInjectionMatchSet() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsWafRegionalSqlInjectionMatchSetCreate,
		Read:   resourceAwsWafRegionalSqlInjectionMatchSetRead,
		Update: resourceAwsWafRegionalSqlInjectionMatchSetUpdate,
		Delete: resourceAwsWafRegionalSqlInjectionMatchSetDelete,

		Schema: map[string]*schema.Schema{
			"name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"sql_injection_match_tuple": {
				Type:     schema.TypeSet,
				Optional: true,
				Set:      resourceAwsWafRegionalSqlInjectionMatchSetTupleHash,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"field_to_match": {
							Type:     schema.TypeList,
							Required: true,
							MaxItems: 1,
							Elem: &schema.Resource{
								Schema: map[string]*schema.Schema{
									"data": {
										Type:     schema.TypeString,
										Optional: true,
										StateFunc: func(v interface{}) string {
											value := v.(string)
											return strings.ToLower(value)
										},
									},
									"type": {
										Type:     schema.TypeString,
										Required: true,
									},
								},
							},
						},
						"text_transformation": {
							Type:     schema.TypeString,
							Required: true,
						},
					},
				},
			},
		},
	}
}

func resourceAwsWafRegionalSqlInjectionMatchSetCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).wafregionalconn
	region := meta.(*AWSClient).region

	log.Printf("[INFO] Creating Regional WAF SQL Injection Match Set: %s", d.Get("name").(string))

	wr := newWafRegionalRetryer(conn, region)
	out, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
		params := &waf.CreateSqlInjectionMatchSetInput{
			ChangeToken: token,
			Name:        aws.String(d.Get("name").(string)),
		}

		return conn.CreateSqlInjectionMatchSet(params)
	})
	if err != nil {
		return fmt.Errorf("Failed creating Regional WAF SQL Injection Match Set: %s", err)
	}
	resp := out.(*waf.CreateSqlInjectionMatchSetOutput)
	d.SetId(aws.StringValue(resp.SqlInjectionMatchSet.SqlInjectionMatchSetId))

	return resourceAwsWafRegionalSqlInjectionMatchSetUpdate(d, meta)
}

func resourceAwsWafRegionalSqlInjectionMatchSetRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).wafregionalconn
	log.Printf("[INFO] Reading Regional WAF SQL Injection Match Set: %s", d.Get("name").(string))
	params := &waf.GetSqlInjectionMatchSetInput{
		SqlInjectionMatchSetId: aws.String(d.Id()),
	}

	resp, err := conn.GetSqlInjectionMatchSet(params)
	if isAWSErr(err, wafregional.ErrCodeWAFNonexistentItemException, "") {
		log.Printf("[WARN] Regional WAF SQL Injection Match Set (%s) not found, error code (404)", d.Id())
		d.SetId("")
		return nil
	}
	if err != nil {
		return fmt.Errorf("Error getting Regional WAF SQL Injection Match Set (%s):%s", d.Id(), err)
	}

	d.Set("name", resp.SqlInjectionMatchSet.Name)
	d.Set("sql_injection_match_tuple", flattenWafSqlInjectionMatchTuples(resp.SqlInjectionMatchSet.SqlInjectionMatchTuples))

	return nil
}

func resourceAwsWafRegionalSqlInjectionMatchSetUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).wafregionalconn
	region := meta.(*AWSClient).region

	if d.HasChange("sql_injection_match_tuple") {
		o, n := d.GetChange("sql_injection_match_tuple")
		oldT, newT := o.(*schema.Set).List(), n.(*schema.Set).List()

		err := updateSqlInjectionMatchSetResourceWR(d.Id(), oldT, newT, conn, region)
		if isAWSErr(err, wafregional.ErrCodeWAFNonexistentItemException, "") {
			log.Printf("[WARN] Regional WAF SQL Injection Match Set (%s) not found, error code (404)", d.Id())
			d.SetId("")
			return nil
		}
		if err != nil {
			return fmt.Errorf("Error updating Regional WAF SQL Injection Match Set (%s): %s", d.Id(), err)
		}
	}

	return resourceAwsWafRegionalSqlInjectionMatchSetRead(d, meta)
}

func resourceAwsWafRegionalSqlInjectionMatchSetDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).wafregionalconn
	region := meta.(*AWSClient).region

	oldTuples := d.Get("sql_injection_match_tuple").(*schema.Set).List()

	if len(oldTuples) > 0 {
		noTuples := []interface{}{}
		err := updateSqlInjectionMatchSetResourceWR(d.Id(), oldTuples, noTuples, conn, region)
		if isAWSErr(err, wafregional.ErrCodeWAFNonexistentItemException, "") {
			return nil
		}
		if err != nil {
			return fmt.Errorf("Error updating Regional WAF SQL Injection Match Set (%s): %s", d.Id(), err)
		}
	}

	wr := newWafRegionalRetryer(conn, region)
	_, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
		req := &waf.DeleteSqlInjectionMatchSetInput{
			ChangeToken:            token,
			SqlInjectionMatchSetId: aws.String(d.Id()),
		}

		return conn.DeleteSqlInjectionMatchSet(req)
	})
	if isAWSErr(err, wafregional.ErrCodeWAFNonexistentItemException, "") {
		return nil
	}
	if err != nil {
		return fmt.Errorf("Failed deleting Regional WAF SQL Injection Match Set (%s): %s", d.Id(), err)
	}

	return nil
}

func updateSqlInjectionMatchSetResourceWR(id string, oldT, newT []interface{}, conn *wafregional.WAFRegional, region string) error {
	wr := newWafRegionalRetryer(conn, region)
	_, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
		req := &waf.UpdateSqlInjectionMatchSetInput{
			ChangeToken:            token,
			SqlInjectionMatchSetId: aws.String(id),
			Updates:                diffWafSqlInjectionMatchTuplesWR(oldT, newT),
		}

		log.Printf("[INFO] Updating Regional WAF SQL Injection Match Set: %s", req)
		return conn.UpdateSqlInjectionMatchSet(req)
	})

	return err
}

func diffWafSqlInjectionMatchTuplesWR(oldT, newT []interface{}) []*waf.SqlInjectionMatchSetUpdate {
	updates := make([]*waf.SqlInjectionMatchSetUpdate, 0)

	for _, od := range oldT {
		tuple := od.(map[string]interface{})

		if idx, contains := sliceContainsMap(newT, tuple); contains {
			newT = append(newT[:idx], newT[idx+1:]...)
			continue
		}

		ftm := tuple["field_to_match"].([]interface{})

		updates = append(updates, &waf.SqlInjectionMatchSetUpdate{
			Action: aws.String(waf.ChangeActionDelete),
			SqlInjectionMatchTuple: &waf.SqlInjectionMatchTuple{
				FieldToMatch:       expandFieldToMatch(ftm[0].(map[string]interface{})),
				TextTransformation: aws.String(tuple["text_transformation"].(string)),
			},
		})
	}

	for _, nd := range newT {
		tuple := nd.(map[string]interface{})
		ftm := tuple["field_to_match"].([]interface{})

		updates = append(updates, &waf.SqlInjectionMatchSetUpdate{
			Action: aws.String(waf.ChangeActionInsert),
			SqlInjectionMatchTuple: &waf.SqlInjectionMatchTuple{
				FieldToMatch:       expandFieldToMatch(ftm[0].(map[string]interface{})),
				TextTransformation: aws.String(tuple["text_transformation"].(string)),
			},
		})
	}
	return updates
}

func resourceAwsWafRegionalSqlInjectionMatchSetTupleHash(v interface{}) int {
	var buf bytes.Buffer
	m := v.(map[string]interface{})
	if v, ok := m["field_to_match"]; ok {
		ftms := v.([]interface{})
		ftm := ftms[0].(map[string]interface{})

		if v, ok := ftm["data"]; ok {
			buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(v.(string))))
		}
		buf.WriteString(fmt.Sprintf("%s-", ftm["type"].(string)))
	}
	buf.WriteString(fmt.Sprintf("%s-", m["text_transformation"].(string)))

	return hashcode.String(buf.String())
}
<|endoftext|>


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

// Package goncurses is a new curses (ncurses) library for the Go programming
// language. It implements all the ncurses extension libraries: form, menu and
// panel.
//
// Minimal operation would consist of initializing the display:
//
// 	src, err := goncurses.Init()
// 	if err != nil {
// 		log.Fatal("init:", err)
// 	}
// 	defer goncurses.End()
//
// It is important to always call End() before your program exits. If you
// fail to do so, the terminal will not perform properly and will either
// need to be reset or restarted completely.
//
// The examples directory contains demontrations of many of the capabilities
// goncurses can provide.
package goncurses

// #cgo pkg-config: ncurses
// #include <ncurses.h>
// #include "goncurses.h"
import "C"

import (
	"errors"
	"fmt"
	"unsafe"
)

// BaudRate returns the speed of the terminal in bits per second
func BaudRate() int {
	return int(C.baudrate())
}

// Beep requests the terminal make an audible bell or, if not available,
// flashes the screen. Note that screen flashing doesn't work on all
// terminals
func Beep() {
	C.beep()
}

// Turn on/off buffering; raw user signals are passed to the program for
// handling. Overrides raw mode
func CBreak(on bool) {
	if on {
		C.cbreak()
		return
	}
	C.nocbreak()
}

// Test whether colour values can be changed
func CanChangeColor() bool {
	return bool(C.bool(C.can_change_color()))
}

// Get RGB values for specified colour
func ColorContent(col int16) (int16, int16, int16) {
	var r, g, b C.short
	C.color_content(C.short(col), (*C.short)(&r), (*C.short)(&g),
		(*C.short)(&b))
	return int16(r), int16(g), int16(b)
}

// Return the value of a color pair which can be passed to functions which
// accept attributes like AddChar, AttrOn/Off and Background.
func ColorPair(pair int) Char {
	return Char(C.COLOR_PAIR(C.int(pair)))
}

// CursesVersion returns the version of the ncurses library currently linked to
func CursesVersion() string {
	return C.GoString(C.curses_version())
}

// Set the cursor visibility. Options are: 0 (invisible/hidden), 1 (normal)
// and 2 (extra-visible)
func Cursor(vis byte) error {
	if C.curs_set(C.int(vis)) == C.ERR {
		return errors.New("Failed to enable ")
	}
	return nil
}

// Echo turns on/off the printing of typed characters
func Echo(on bool) {
	if on {
		C.echo()
		return
	}
	C.noecho()
}

// Must be called prior to exiting the program in order to make sure the
// terminal returns to normal operation
func End() {
	C.endwin()
}

// Flash requests the terminal flashes the screen or, if not available,
// make an audible bell. Note that screen flashing doesn't work on all
// terminals
func Flash() {
	C.flash()
}

// FlushInput flushes all input
func FlushInput() error {
	if C.flushinp() == C.ERR {
		return errors.New("Flush input failed")
	}
	return nil
}

// Returns an array of integers representing the following, in order:
// x, y and z coordinates, id of the device, and a bit masked state of
// the devices buttons
func GetMouse() ([]int, error) {
	if bool(C.ncurses_has_mouse()) != true {
		return nil, errors.New("Mouse support not enabled")
	}
	var event C.MEVENT
	if C.getmouse(&event) != C.OK {
		return nil, errors.New("Failed to get mouse event")
	}
	return []int{int(event.x), int(event.y), int(event.z), int(event.id),
		int(event.bstate)}, nil
}

// Behaves like cbreak() but also adds a timeout for input. If timeout is
// exceeded after a call to Getch() has been made then GetChar will return
// with an error.
func HalfDelay(delay int) error {
	var cerr C.int
	if delay > 0 {
		cerr = C.halfdelay(C.int(delay))
	}
	if cerr == C.ERR {
		return errors.New("Unable to set delay mode")
	}
	return nil
}

// HasColors returns true if terminal can display colors
func HasColors() bool {
	return bool(C.has_colors())
}

// HasInsertChar return true if the terminal has insert and delete
// character capabilities
func HasInsertChar() bool {
	return bool(C.has_ic())
}

// HasInsertLine returns true if the terminal has insert and delete line
// capabilities. See ncurses documentation for more details
func HasInsertLine() bool {
	return bool(C.has_il())
}

// HasKey returns true if terminal recognized the given character
func HasKey(ch Key) bool {
	if C.has_key(C.int(ch)) == 1 {
		return true
	}
	return false
}

// InitColor is used to set 'color' to the specified RGB values. Values may
// be between 0 and 1000.
func InitColor(col, r, g, b int16) error {
	if C.init_color(C.short(col), C.short(r), C.short(g),
		C.short(b)) == C.ERR {
		return errors.New("Failed to set new color definition")
	}
	return nil
}

// InitPair sets a colour pair designated by 'pair' to fg and bg colors
func InitPair(pair, fg, bg int16) error {
	if pair == 0 || C.short(pair) > C.short(C.COLOR_PAIRS-1) {
		return errors.New("Invalid color pair selected")
	}
	if C.init_pair(C.short(pair), C.short(fg), C.short(bg)) == C.ERR {
		return errors.New("Failed to init color pair")
	}
	return nil
}

// Initialize the ncurses library. You must run this function prior to any
// other goncurses function in order for the library to work
func Init() (stdscr Window, err error) {
	stdscr = Window{C.initscr()}
	if unsafe.Pointer(stdscr.win) == nil {
		err = errors.New("An error occurred initializing ncurses")
	}
	return
}

// IsEnd returns true if End() has been called, otherwise false
func IsEnd() bool {
	return bool(C.isendwin())
}

// IsTermResized returns true if ResizeTerm would modify any current Windows
// if called with the given parameters
func IsTermResized(nlines, ncols int) bool {
	return bool(C.is_term_resized(C.int(nlines), C.int(ncols)))
}

// Returns a string representing the value of input returned by Getch
func KeyString(k Key) string {
	key, ok := keyList[k]
	if !ok {
		key = fmt.Sprintf("%c", int(k))
	}
	return key
}

// PairContent returns the current foreground and background colours
// associated with the given pair
func PairContent(pair int16) (fg int16, bg int16, err error) {
	var f, b C.short
	if C.pair_content(C.short(pair), &f, &b) == C.ERR {
		return -1, -1, errors.New("Invalid color pair")
	}
	return int16(f), int16(b), nil
}

func Mouse() bool {
	return bool(C.ncurses_has_mouse())
}

func MouseInterval() {
}

// MouseMask accepts a single int of OR'd mouse events. If a mouse event
// is triggered, GetChar() will return KEY_MOUSE. To retrieve the actual
// event use GetMouse() to pop it off the queue. Pass a pointer as the
// second argument to store the prior events being monitored or nil.
func MouseMask(mask MouseButton, old *MouseButton) int {
	return int(C.mousemask((C.mmask_t)(mask),
		(*C.mmask_t)(unsafe.Pointer(old))))
}

// NapMilliseconds is used to sleep for ms milliseconds
func NapMilliseconds(ms int) {
	C.napms(C.int(ms))
}

// NewWindow creates a window of size h(eight) and w(idth) at y, x
func NewWindow(h, w, y, x int) (window Window, err error) {
	window = Window{C.newwin(C.int(h), C.int(w), C.int(y), C.int(x))}
	if window.win == nil {
		err = errors.New("Failed to create a new window")
	}
	return
}

// NL turns newline translation on/off.
func NL(on bool) {
	if on {
		C.nl()
		return
	}
	C.nonl()
}

// Raw turns on input buffering; user signals are disabled and the key strokes
// are passed directly to input. Set to false if you wish to turn this mode
// off
func Raw(on bool) {
	if on {
		C.raw()
		return
	}
	C.noraw()
}

// ResizeTerm will attempt to resize the terminal. This only has an effect if
// the terminal is in an XWindows (GUI) environment.
func ResizeTerm(nlines, ncols int) error {
	if C.resizeterm(C.int(nlines), C.int(ncols)) == C.ERR {
		return errors.New("Failed to resize terminal")
	}
	return nil
}

// Enables colors to be displayed. Will return an error if terminal is not
// capable of displaying colors
func StartColor() error {
	if C.has_colors() == C.bool(false) {
		return errors.New("Terminal does not support colors")
	}
	if C.start_color() == C.ERR {
		return errors.New("Failed to enable color mode")
	}
	return nil
}

// UnGetChar places the character back into the input queue
func UnGetChar(ch Char) {
	C.ungetch(C.int(ch))
}

// Update the screen, refreshing all windows
func Update() error {
	if C.doupdate() == C.ERR {
		return errors.New("Failed to update")
	}
	return nil
}

// UseEnvironment specifies whether the LINES and COLUMNS environmental
// variables should be used or not
func UseEnvironment(use bool) {
	C.use_env(C.bool(use))
}
<commit_msg>Implement MouseInterval and add godoc for Mouse function<commit_after>// goncurses - ncurses library for Go.
// Copyright 2011 Rob Thornton. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package goncurses is a new curses (ncurses) library for the Go programming
// language. It implements all the ncurses extension libraries: form, menu and
// panel.
//
// Minimal operation would consist of initializing the display:
//
// 	src, err := goncurses.Init()
// 	if err != nil {
// 		log.Fatal("init:", err)
// 	}
// 	defer goncurses.End()
//
// It is important to always call End() before your program exits. If you
// fail to do so, the terminal will not perform properly and will either
// need to be reset or restarted completely.
//
// The examples directory contains demontrations of many of the capabilities
// goncurses can provide.
package goncurses

// #cgo pkg-config: ncurses
// #include <ncurses.h>
// #include "goncurses.h"
import "C"

import (
	"errors"
	"fmt"
	"unsafe"
)

// BaudRate returns the speed of the terminal in bits per second
func BaudRate() int {
	return int(C.baudrate())
}

// Beep requests the terminal make an audible bell or, if not available,
// flashes the screen. Note that screen flashing doesn't work on all
// terminals
func Beep() {
	C.beep()
}

// Turn on/off buffering; raw user signals are passed to the program for
// handling. Overrides raw mode
func CBreak(on bool) {
	if on {
		C.cbreak()
		return
	}
	C.nocbreak()
}

// Test whether colour values can be changed
func CanChangeColor() bool {
	return bool(C.bool(C.can_change_color()))
}

// Get RGB values for specified colour
func ColorContent(col int16) (int16, int16, int16) {
	var r, g, b C.short
	C.color_content(C.short(col), (*C.short)(&r), (*C.short)(&g),
		(*C.short)(&b))
	return int16(r), int16(g), int16(b)
}

// Return the value of a color pair which can be passed to functions which
// accept attributes like AddChar, AttrOn/Off and Background.
func ColorPair(pair int) Char {
	return Char(C.COLOR_PAIR(C.int(pair)))
}

// CursesVersion returns the version of the ncurses library currently linked to
func CursesVersion() string {
	return C.GoString(C.curses_version())
}

// Set the cursor visibility. Options are: 0 (invisible/hidden), 1 (normal)
// and 2 (extra-visible)
func Cursor(vis byte) error {
	if C.curs_set(C.int(vis)) == C.ERR {
		return errors.New("Failed to enable ")
	}
	return nil
}

// Echo turns on/off the printing of typed characters
func Echo(on bool) {
	if on {
		C.echo()
		return
	}
	C.noecho()
}

// Must be called prior to exiting the program in order to make sure the
// terminal returns to normal operation
func End() {
	C.endwin()
}

// Flash requests the terminal flashes the screen or, if not available,
// make an audible bell. Note that screen flashing doesn't work on all
// terminals
func Flash() {
	C.flash()
}

// FlushInput flushes all input
func FlushInput() error {
	if C.flushinp() == C.ERR {
		return errors.New("Flush input failed")
	}
	return nil
}

// Returns an array of integers representing the following, in order:
// x, y and z coordinates, id of the device, and a bit masked state of
// the devices buttons
func GetMouse() ([]int, error) {
	if bool(C.ncurses_has_mouse()) != true {
		return nil, errors.New("Mouse support not enabled")
	}
	var event C.MEVENT
	if C.getmouse(&event) != C.OK {
		return nil, errors.New("Failed to get mouse event")
	}
	return []int{int(event.x), int(event.y), int(event.z), int(event.id),
		int(event.bstate)}, nil
}

// Behaves like cbreak() but also adds a timeout for input. If timeout is
// exceeded after a call to Getch() has been made then GetChar will return
// with an error.
func HalfDelay(delay int) error {
	var cerr C.int
	if delay > 0 {
		cerr = C.halfdelay(C.int(delay))
	}
	if cerr == C.ERR {
		return errors.New("Unable to set delay mode")
	}
	return nil
}

// HasColors returns true if terminal can display colors
func HasColors() bool {
	return bool(C.has_colors())
}

// HasInsertChar return true if the terminal has insert and delete
// character capabilities
func HasInsertChar() bool {
	return bool(C.has_ic())
}

// HasInsertLine returns true if the terminal has insert and delete line
// capabilities. See ncurses documentation for more details
func HasInsertLine() bool {
	return bool(C.has_il())
}

// HasKey returns true if terminal recognized the given character
func HasKey(ch Key) bool {
	if C.has_key(C.int(ch)) == 1 {
		return true
	}
	return false
}

// InitColor is used to set 'color' to the specified RGB values. Values may
// be between 0 and 1000.
func InitColor(col, r, g, b int16) error {
	if C.init_color(C.short(col), C.short(r), C.short(g),
		C.short(b)) == C.ERR {
		return errors.New("Failed to set new color definition")
	}
	return nil
}

// InitPair sets a colour pair designated by 'pair' to fg and bg colors
func InitPair(pair, fg, bg int16) error {
	if pair == 0 || C.short(pair) > C.short(C.COLOR_PAIRS-1) {
		return errors.New("Invalid color pair selected")
	}
	if C.init_pair(C.short(pair), C.short(fg), C.short(bg)) == C.ERR {
		return errors.New("Failed to init color pair")
	}
	return nil
}

// Initialize the ncurses library. You must run this function prior to any
// other goncurses function in order for the library to work
func Init() (stdscr Window, err error) {
	stdscr = Window{C.initscr()}
	if unsafe.Pointer(stdscr.win) == nil {
		err = errors.New("An error occurred initializing ncurses")
	}
	return
}

// IsEnd returns true if End() has been called, otherwise false
func IsEnd() bool {
	return bool(C.isendwin())
}

// IsTermResized returns true if ResizeTerm would modify any current Windows
// if called with the given parameters
func IsTermResized(nlines, ncols int) bool {
	return bool(C.is_term_resized(C.int(nlines), C.int(ncols)))
}

// Returns a string representing the value of input returned by Getch
func KeyString(k Key) string {
	key, ok := keyList[k]
	if !ok {
		key = fmt.Sprintf("%c", int(k))
	}
	return key
}

// PairContent returns the current foreground and background colours
// associated with the given pair
func PairContent(pair int16) (fg int16, bg int16, err error) {
	var f, b C.short
	if C.pair_content(C.short(pair), &f, &b) == C.ERR {
		return -1, -1, errors.New("Invalid color pair")
	}
	return int16(f), int16(b), nil
}

// Mouse returns true if ncurses has built-in mouse support. On ncurses 5.7
// and earlier, this function is not present and so will always return false
func Mouse() bool {
	return bool(C.ncurses_has_mouse())
}

// MouseInterval sets the maximum time in milliseconds that can elapse
// between press and release mouse events and returns the previous setting.
// Use a value of 0 (zero) to disable click resolution. Use a value of -1
// to get the previous value without changing the current value. Default
// value is 1/6 of a second.
func MouseInterval(ms int) int {
	return int(C.mouseinterval(C.int(ms)))
}

// MouseMask accepts a single int of OR'd mouse events. If a mouse event
// is triggered, GetChar() will return KEY_MOUSE. To retrieve the actual
// event use GetMouse() to pop it off the queue. Pass a pointer as the
// second argument to store the prior events being monitored or nil.
func MouseMask(mask MouseButton, old *MouseButton) int {
	return int(C.mousemask((C.mmask_t)(mask),
		(*C.mmask_t)(unsafe.Pointer(old))))
}

// NapMilliseconds is used to sleep for ms milliseconds
func NapMilliseconds(ms int) {
	C.napms(C.int(ms))
}

// NewWindow creates a window of size h(eight) and w(idth) at y, x
func NewWindow(h, w, y, x int) (window Window, err error) {
	window = Window{C.newwin(C.int(h), C.int(w), C.int(y), C.int(x))}
	if window.win == nil {
		err = errors.New("Failed to create a new window")
	}
	return
}

// NL turns newline translation on/off.
func NL(on bool) {
	if on {
		C.nl()
		return
	}
	C.nonl()
}

// Raw turns on input buffering; user signals are disabled and the key strokes
// are passed directly to input. Set to false if you wish to turn this mode
// off
func Raw(on bool) {
	if on {
		C.raw()
		return
	}
	C.noraw()
}

// ResizeTerm will attempt to resize the terminal. This only has an effect if
// the terminal is in an XWindows (GUI) environment.
func ResizeTerm(nlines, ncols int) error {
	if C.resizeterm(C.int(nlines), C.int(ncols)) == C.ERR {
		return errors.New("Failed to resize terminal")
	}
	return nil
}

// Enables colors to be displayed. Will return an error if terminal is not
// capable of displaying colors
func StartColor() error {
	if C.has_colors() == C.bool(false) {
		return errors.New("Terminal does not support colors")
	}
	if C.start_color() == C.ERR {
		return errors.New("Failed to enable color mode")
	}
	return nil
}

// UnGetChar places the character back into the input queue
func UnGetChar(ch Char) {
	C.ungetch(C.int(ch))
}

// Update the screen, refreshing all windows
func Update() error {
	if C.doupdate() == C.ERR {
		return errors.New("Failed to update")
	}
	return nil
}

// UseEnvironment specifies whether the LINES and COLUMNS environmental
// variables should be used or not
func UseEnvironment(use bool) {
	C.use_env(C.bool(use))
}
<|endoftext|>


<commit_before>// +build linux,!no_runc_worker

package runc

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"testing"

	ctdsnapshot "github.com/containerd/containerd/snapshots"
	"github.com/containerd/containerd/snapshots/overlay"
	"github.com/moby/buildkit/cache"
	"github.com/moby/buildkit/client"
	"github.com/moby/buildkit/executor"
	"github.com/moby/buildkit/executor/oci"
	"github.com/moby/buildkit/session"
	"github.com/moby/buildkit/snapshot"
	"github.com/moby/buildkit/util/network/netproviders"
	"github.com/moby/buildkit/worker/base"
	"github.com/moby/buildkit/worker/tests"
	"github.com/stretchr/testify/require"
)

func newWorkerOpt(t *testing.T, processMode oci.ProcessMode) (base.WorkerOpt, func()) {
	tmpdir, err := ioutil.TempDir("", "workertest")
	require.NoError(t, err)
	cleanup := func() { os.RemoveAll(tmpdir) }

	snFactory := SnapshotterFactory{
		Name: "overlayfs",
		New: func(root string) (ctdsnapshot.Snapshotter, error) {
			return overlay.NewSnapshotter(root)
		},
	}
	rootless := false
	workerOpt, err := NewWorkerOpt(tmpdir, snFactory, rootless, processMode, nil, nil, netproviders.Opt{Mode: "host"}, nil, "")
	require.NoError(t, err)

	return workerOpt, cleanup
}

func checkRequirement(t *testing.T) {
	if os.Getuid() != 0 {
		t.Skip("requires root")
	}

	if _, err := exec.LookPath("runc"); err != nil {
		if _, err := exec.LookPath("buildkit-runc"); err != nil {
			t.Skipf("no runc found: %s", err.Error())
		}
	}
}

func TestRuncWorker(t *testing.T) {
	t.Parallel()
	checkRequirement(t)

	workerOpt, cleanupWorkerOpt := newWorkerOpt(t, oci.ProcessSandbox)
	defer cleanupWorkerOpt()
	w, err := base.NewWorker(workerOpt)
	require.NoError(t, err)

	ctx := tests.NewCtx("buildkit-test")
	sm, err := session.NewManager()
	require.NoError(t, err)
	snap := tests.NewBusyboxSourceSnapshot(ctx, t, w, sm)

	mounts, err := snap.Mount(ctx, false, nil)
	require.NoError(t, err)

	lm := snapshot.LocalMounter(mounts)

	target, err := lm.Mount()
	require.NoError(t, err)

	f, err := os.Open(target)
	require.NoError(t, err)

	names, err := f.Readdirnames(-1)
	require.NoError(t, err)
	require.True(t, len(names) > 5)

	err = f.Close()
	require.NoError(t, err)

	lm.Unmount()
	require.NoError(t, err)

	du, err := w.CacheMgr.DiskUsage(ctx, client.DiskUsageInfo{})
	require.NoError(t, err)

	// for _, d := range du {
	// 	fmt.Printf("du: %+v\n", d)
	// }

	for _, d := range du {
		require.True(t, d.Size >= 8192)
	}

	meta := executor.Meta{
		Args: []string{"/bin/sh", "-c", "mkdir /run && echo \"foo\" > /run/bar"},
		Cwd:  "/",
	}

	stderr := bytes.NewBuffer(nil)
	err = w.WorkerOpt.Executor.Run(ctx, "", execMount(snap), nil, executor.ProcessInfo{Meta: meta, Stderr: &nopCloser{stderr}}, nil)
	require.Error(t, err) // Read-only root
	// typical error is like `mkdir /.../rootfs/proc: read-only file system`.
	// make sure the error is caused before running `echo foo > /bar`.
	require.Contains(t, stderr.String(), "read-only file system")

	root, err := w.CacheMgr.New(ctx, snap, nil)
	require.NoError(t, err)

	err = w.WorkerOpt.Executor.Run(ctx, "", execMount(root), nil, executor.ProcessInfo{Meta: meta, Stderr: &nopCloser{stderr}}, nil)
	require.NoError(t, err)

	meta = executor.Meta{
		Args: []string{"/bin/ls", "/etc/resolv.conf"},
		Cwd:  "/",
	}

	err = w.WorkerOpt.Executor.Run(ctx, "", execMount(root), nil, executor.ProcessInfo{Meta: meta, Stderr: &nopCloser{stderr}}, nil)
	require.NoError(t, err)

	rf, err := root.Commit(ctx)
	require.NoError(t, err)

	mounts, err = rf.Mount(ctx, false, nil)
	require.NoError(t, err)

	lm = snapshot.LocalMounter(mounts)

	target, err = lm.Mount()
	require.NoError(t, err)

	//Verifies fix for issue https://github.com/moby/buildkit/issues/429
	dt, err := ioutil.ReadFile(filepath.Join(target, "run", "bar"))

	require.NoError(t, err)
	require.Equal(t, string(dt), "foo\n")

	lm.Unmount()
	require.NoError(t, err)

	err = rf.Release(ctx)
	require.NoError(t, err)

	err = snap.Release(ctx)
	require.NoError(t, err)

	du2, err := w.CacheMgr.DiskUsage(ctx, client.DiskUsageInfo{})
	require.NoError(t, err)
	require.Equal(t, 1, len(du2)-len(du))

}

func TestRuncWorkerNoProcessSandbox(t *testing.T) {
	t.Parallel()
	checkRequirement(t)

	workerOpt, cleanupWorkerOpt := newWorkerOpt(t, oci.NoProcessSandbox)
	defer cleanupWorkerOpt()
	w, err := base.NewWorker(workerOpt)
	require.NoError(t, err)

	ctx := tests.NewCtx("buildkit-test")
	sm, err := session.NewManager()
	require.NoError(t, err)
	snap := tests.NewBusyboxSourceSnapshot(ctx, t, w, sm)
	root, err := w.CacheMgr.New(ctx, snap, nil)
	require.NoError(t, err)

	// ensure the procfs is shared
	selfPID := os.Getpid()
	selfCmdline, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cmdline", selfPID))
	require.NoError(t, err)
	meta := executor.Meta{
		Args: []string{"/bin/cat", fmt.Sprintf("/proc/%d/cmdline", selfPID)},
		Cwd:  "/",
	}
	stdout := bytes.NewBuffer(nil)
	stderr := bytes.NewBuffer(nil)
	err = w.WorkerOpt.Executor.Run(ctx, "", execMount(root), nil, executor.ProcessInfo{Meta: meta, Stdout: &nopCloser{stdout}, Stderr: &nopCloser{stderr}}, nil)
	require.NoError(t, err, fmt.Sprintf("stdout=%q, stderr=%q", stdout.String(), stderr.String()))
	require.Equal(t, string(selfCmdline), stdout.String())
}

func TestRuncWorkerExec(t *testing.T) {
	t.Parallel()
	checkRequirement(t)

	workerOpt, cleanupWorkerOpt := newWorkerOpt(t, oci.ProcessSandbox)
	defer cleanupWorkerOpt()
	w, err := base.NewWorker(workerOpt)
	require.NoError(t, err)

	tests.TestWorkerExec(t, w)
}

func TestRuncWorkerExecFailures(t *testing.T) {
	t.Parallel()
	checkRequirement(t)

	workerOpt, cleanupWorkerOpt := newWorkerOpt(t, oci.ProcessSandbox)
	defer cleanupWorkerOpt()
	w, err := base.NewWorker(workerOpt)
	require.NoError(t, err)

	tests.TestWorkerExecFailures(t, w)
}

type nopCloser struct {
	io.Writer
}

func (n *nopCloser) Close() error {
	return nil
}

func execMount(m cache.Mountable) executor.Mount {
	return executor.Mount{Src: &mountable{m: m}}
}

type mountable struct {
	m cache.Mountable
}

func (m *mountable) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
	return m.m.Mount(ctx, readonly, nil)
}
<commit_msg>add debug for runcworker test<commit_after>// +build linux,!no_runc_worker

package runc

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"testing"
	"time"

	ctdsnapshot "github.com/containerd/containerd/snapshots"
	"github.com/containerd/containerd/snapshots/overlay"
	"github.com/moby/buildkit/cache"
	"github.com/moby/buildkit/client"
	"github.com/moby/buildkit/executor"
	"github.com/moby/buildkit/executor/oci"
	"github.com/moby/buildkit/session"
	"github.com/moby/buildkit/snapshot"
	"github.com/moby/buildkit/util/network/netproviders"
	"github.com/moby/buildkit/worker/base"
	"github.com/moby/buildkit/worker/tests"
	"github.com/stretchr/testify/require"
)

func newWorkerOpt(t *testing.T, processMode oci.ProcessMode) (base.WorkerOpt, func()) {
	tmpdir, err := ioutil.TempDir("", "workertest")
	require.NoError(t, err)
	cleanup := func() { os.RemoveAll(tmpdir) }

	snFactory := SnapshotterFactory{
		Name: "overlayfs",
		New: func(root string) (ctdsnapshot.Snapshotter, error) {
			return overlay.NewSnapshotter(root)
		},
	}
	rootless := false
	workerOpt, err := NewWorkerOpt(tmpdir, snFactory, rootless, processMode, nil, nil, netproviders.Opt{Mode: "host"}, nil, "")
	require.NoError(t, err)

	return workerOpt, cleanup
}

func checkRequirement(t *testing.T) {
	if os.Getuid() != 0 {
		t.Skip("requires root")
	}

	if _, err := exec.LookPath("runc"); err != nil {
		if _, err := exec.LookPath("buildkit-runc"); err != nil {
			t.Skipf("no runc found: %s", err.Error())
		}
	}
}

func TestRuncWorker(t *testing.T) {
	t.Parallel()
	checkRequirement(t)

	workerOpt, cleanupWorkerOpt := newWorkerOpt(t, oci.ProcessSandbox)
	defer cleanupWorkerOpt()
	w, err := base.NewWorker(workerOpt)
	require.NoError(t, err)

	ctx := tests.NewCtx("buildkit-test")
	sm, err := session.NewManager()
	require.NoError(t, err)
	snap := tests.NewBusyboxSourceSnapshot(ctx, t, w, sm)

	mounts, err := snap.Mount(ctx, false, nil)
	require.NoError(t, err)

	lm := snapshot.LocalMounter(mounts)

	target, err := lm.Mount()
	require.NoError(t, err)

	f, err := os.Open(target)
	require.NoError(t, err)

	names, err := f.Readdirnames(-1)
	require.NoError(t, err)
	require.True(t, len(names) > 5)

	err = f.Close()
	require.NoError(t, err)

	lm.Unmount()
	require.NoError(t, err)

	du, err := w.CacheMgr.DiskUsage(ctx, client.DiskUsageInfo{})
	require.NoError(t, err)

	// for _, d := range du {
	// 	fmt.Printf("du: %+v\n", d)
	// }

	for _, d := range du {
		require.True(t, d.Size >= 8192)
	}

	meta := executor.Meta{
		Args: []string{"/bin/sh", "-c", "mkdir /run && echo \"foo\" > /run/bar"},
		Cwd:  "/",
	}

	stderr := bytes.NewBuffer(nil)
	err = w.WorkerOpt.Executor.Run(ctx, "", execMount(snap), nil, executor.ProcessInfo{Meta: meta, Stderr: &nopCloser{stderr}}, nil)
	require.Error(t, err) // Read-only root
	// typical error is like `mkdir /.../rootfs/proc: read-only file system`.
	// make sure the error is caused before running `echo foo > /bar`.
	require.Contains(t, stderr.String(), "read-only file system")

	root, err := w.CacheMgr.New(ctx, snap, nil)
	require.NoError(t, err)

	err = w.WorkerOpt.Executor.Run(ctx, "", execMount(root), nil, executor.ProcessInfo{Meta: meta, Stderr: &nopCloser{stderr}}, nil)
	require.NoError(t, err)

	meta = executor.Meta{
		Args: []string{"/bin/ls", "/etc/resolv.conf"},
		Cwd:  "/",
	}

	err = w.WorkerOpt.Executor.Run(ctx, "", execMount(root), nil, executor.ProcessInfo{Meta: meta, Stderr: &nopCloser{stderr}}, nil)
	require.NoError(t, err)

	rf, err := root.Commit(ctx)
	require.NoError(t, err)

	mounts, err = rf.Mount(ctx, false, nil)
	require.NoError(t, err)

	lm = snapshot.LocalMounter(mounts)

	target, err = lm.Mount()
	require.NoError(t, err)

	//Verifies fix for issue https://github.com/moby/buildkit/issues/429
	dt, err := ioutil.ReadFile(filepath.Join(target, "run", "bar"))

	require.NoError(t, err)
	require.Equal(t, string(dt), "foo\n")

	lm.Unmount()
	require.NoError(t, err)

	err = rf.Release(ctx)
	require.NoError(t, err)

	err = snap.Release(ctx)
	require.NoError(t, err)

	retry := 0
	var du2 []*client.UsageInfo
	for {
		du2, err = w.CacheMgr.DiskUsage(ctx, client.DiskUsageInfo{})
		require.NoError(t, err)
		if len(du2)-len(du) != 1 && retry == 0 {
			t.Logf("invalid expected size: du1: %+v du2: %+v", formatDiskUsage(du), formatDiskUsage(du2))
			time.Sleep(300 * time.Millisecond) // make race non-fatal if it fixes itself
			retry++
			continue
		}
		break
	}
	require.Equal(t, 1, len(du2)-len(du), "du1: %+v du2: %+v", formatDiskUsage(du), formatDiskUsage(du2))
}

func formatDiskUsage(du []*client.UsageInfo) string {
	buf := new(bytes.Buffer)
	for _, d := range du {
		fmt.Fprintf(buf, "%+v ", d)
	}
	return buf.String()
}

func TestRuncWorkerNoProcessSandbox(t *testing.T) {
	t.Parallel()
	checkRequirement(t)

	workerOpt, cleanupWorkerOpt := newWorkerOpt(t, oci.NoProcessSandbox)
	defer cleanupWorkerOpt()
	w, err := base.NewWorker(workerOpt)
	require.NoError(t, err)

	ctx := tests.NewCtx("buildkit-test")
	sm, err := session.NewManager()
	require.NoError(t, err)
	snap := tests.NewBusyboxSourceSnapshot(ctx, t, w, sm)
	root, err := w.CacheMgr.New(ctx, snap, nil)
	require.NoError(t, err)

	// ensure the procfs is shared
	selfPID := os.Getpid()
	selfCmdline, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cmdline", selfPID))
	require.NoError(t, err)
	meta := executor.Meta{
		Args: []string{"/bin/cat", fmt.Sprintf("/proc/%d/cmdline", selfPID)},
		Cwd:  "/",
	}
	stdout := bytes.NewBuffer(nil)
	stderr := bytes.NewBuffer(nil)
	err = w.WorkerOpt.Executor.Run(ctx, "", execMount(root), nil, executor.ProcessInfo{Meta: meta, Stdout: &nopCloser{stdout}, Stderr: &nopCloser{stderr}}, nil)
	require.NoError(t, err, fmt.Sprintf("stdout=%q, stderr=%q", stdout.String(), stderr.String()))
	require.Equal(t, string(selfCmdline), stdout.String())
}

func TestRuncWorkerExec(t *testing.T) {
	t.Parallel()
	checkRequirement(t)

	workerOpt, cleanupWorkerOpt := newWorkerOpt(t, oci.ProcessSandbox)
	defer cleanupWorkerOpt()
	w, err := base.NewWorker(workerOpt)
	require.NoError(t, err)

	tests.TestWorkerExec(t, w)
}

func TestRuncWorkerExecFailures(t *testing.T) {
	t.Parallel()
	checkRequirement(t)

	workerOpt, cleanupWorkerOpt := newWorkerOpt(t, oci.ProcessSandbox)
	defer cleanupWorkerOpt()
	w, err := base.NewWorker(workerOpt)
	require.NoError(t, err)

	tests.TestWorkerExecFailures(t, w)
}

type nopCloser struct {
	io.Writer
}

func (n *nopCloser) Close() error {
	return nil
}

func execMount(m cache.Mountable) executor.Mount {
	return executor.Mount{Src: &mountable{m: m}}
}

type mountable struct {
	m cache.Mountable
}

func (m *mountable) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
	return m.m.Mount(ctx, readonly, nil)
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"errors"
	ggio "github.com/gogo/protobuf/io"
	p2p_peer "github.com/ipfs/go-libp2p-peer"
	p2p_pstore "github.com/ipfs/go-libp2p-peerstore"
	multiaddr "github.com/jbenet/go-multiaddr"
	p2p_net "github.com/libp2p/go-libp2p/p2p/net"
	mc "github.com/mediachain/concat/mc"
	pb "github.com/mediachain/concat/proto"
	"log"
	"time"
)

func (node *Node) goOffline() error {
	return nil
}

func (node *Node) goOnline() error {
	return nil
}

func (node *Node) goPublic() error {
	return nil
}

func (node *Node) pingHandler(s p2p_net.Stream) {
	defer s.Close()

	pid := s.Conn().RemotePeer()
	log.Printf("node/ping: new stream from %s", pid.Pretty())

	var ping pb.Ping
	var pong pb.Pong
	r := ggio.NewDelimitedReader(s, mc.MaxMessageSize)
	w := ggio.NewDelimitedWriter(s)

	for {
		err := r.ReadMsg(&ping)
		if err != nil {
			return
		}

		log.Printf("node/ping: ping from %s; ponging", pid.Pretty())

		err = w.WriteMsg(&pong)
		if err != nil {
			return
		}
	}
}

func (node *Node) registerPeer(addrs ...multiaddr.Multiaddr) {
	// directory failure is a fatality for now
	ctx := context.Background()

	err := node.host.Connect(ctx, *node.dir)
	if err != nil {
		log.Printf("Failed to connect to directory")
		log.Fatal(err)
	}

	s, err := node.host.NewStream(ctx, node.dir.ID, "/mediachain/dir/register")
	if err != nil {
		log.Printf("Failed to open directory stream")
		log.Fatal(err)
	}
	defer s.Close()

	pinfo := p2p_pstore.PeerInfo{node.ID, addrs}
	var pbpi pb.PeerInfo
	mc.PBFromPeerInfo(&pbpi, pinfo)
	msg := pb.RegisterPeer{&pbpi}

	w := ggio.NewDelimitedWriter(s)
	for {
		log.Printf("Registering with directory")
		err = w.WriteMsg(&msg)
		if err != nil {
			log.Printf("Failed to register with directory")
			log.Fatal(err)
		}

		time.Sleep(5 * time.Minute)
	}
}

var NodeOffline = errors.New("Node is offline")

func (node *Node) doPing(ctx context.Context, pid p2p_peer.ID) error {
	if node.status == StatusOffline {
		return NodeOffline
	}

	pinfo, err := node.doLookup(ctx, pid)
	if err != nil {
		return err
	}

	err = node.host.Connect(ctx, pinfo)
	if err != nil {
		return err
	}

	s, err := node.host.NewStream(ctx, pinfo.ID, "/mediachain/node/ping")
	if err != nil {
		return err
	}
	defer s.Close()

	var ping pb.Ping
	w := ggio.NewDelimitedWriter(s)
	err = w.WriteMsg(&ping)
	if err != nil {
		return err
	}

	var pong pb.Pong
	r := ggio.NewDelimitedReader(s, mc.MaxMessageSize)
	err = r.ReadMsg(&pong)

	return err
}

var NoDirectory = errors.New("No directory server")
var UnknownPeer = errors.New("Unknown peer")

func (node *Node) doLookup(ctx context.Context, pid p2p_peer.ID) (empty p2p_pstore.PeerInfo, err error) {
	if node.status == StatusOffline {
		return empty, NodeOffline
	}

	if node.dir == nil {
		return empty, NoDirectory
	}

	s, err := node.host.NewStream(ctx, node.dir.ID, "/mediachain/dir/lookup")
	if err != nil {
		return empty, err
	}
	defer s.Close()

	req := pb.LookupPeerRequest{pid.Pretty()}
	w := ggio.NewDelimitedWriter(s)
	err = w.WriteMsg(&req)
	if err != nil {
		return empty, err
	}

	var resp pb.LookupPeerResponse
	r := ggio.NewDelimitedReader(s, mc.MaxMessageSize)
	err = r.ReadMsg(&resp)
	if err != nil {
		return empty, err
	}

	if resp.Peer == nil {
		return empty, UnknownPeer
	}

	pinfo, err := mc.PBToPeerInfo(resp.Peer)
	if err != nil {
		return empty, err
	}

	return pinfo, nil
}
<commit_msg>mcnode: goOnline<commit_after>package main

import (
	"context"
	"errors"
	ggio "github.com/gogo/protobuf/io"
	p2p_peer "github.com/ipfs/go-libp2p-peer"
	p2p_pstore "github.com/ipfs/go-libp2p-peerstore"
	multiaddr "github.com/jbenet/go-multiaddr"
	p2p_net "github.com/libp2p/go-libp2p/p2p/net"
	mc "github.com/mediachain/concat/mc"
	pb "github.com/mediachain/concat/proto"
	"log"
	"time"
)

var NodeOffline = errors.New("Node is offline")
var NoDirectory = errors.New("No directory server")
var UnknownPeer = errors.New("Unknown peer")

func (node *Node) goOffline() error {
	return nil
}

func (node *Node) goOnline() error {
	node.mx.Lock()
	defer node.mx.Unlock()

	switch node.status {
	case StatusOffline:
		host, err := mc.NewHost(node.Identity, node.laddr)
		if err != nil {
			return err
		}

		host.SetStreamHandler("/mediachain/node/ping", node.pingHandler)
		node.host = host
		node.status = StatusOnline
		log.Printf("Node is online\n")
		return nil
	}

	return nil
}

func (node *Node) goPublic() error {
	return nil
}

func (node *Node) pingHandler(s p2p_net.Stream) {
	defer s.Close()

	pid := s.Conn().RemotePeer()
	log.Printf("node/ping: new stream from %s", pid.Pretty())

	var ping pb.Ping
	var pong pb.Pong
	r := ggio.NewDelimitedReader(s, mc.MaxMessageSize)
	w := ggio.NewDelimitedWriter(s)

	for {
		err := r.ReadMsg(&ping)
		if err != nil {
			return
		}

		log.Printf("node/ping: ping from %s; ponging", pid.Pretty())

		err = w.WriteMsg(&pong)
		if err != nil {
			return
		}
	}
}

func (node *Node) registerPeer(addrs ...multiaddr.Multiaddr) {
	// directory failure is a fatality for now
	ctx := context.Background()

	err := node.host.Connect(ctx, *node.dir)
	if err != nil {
		log.Printf("Failed to connect to directory")
		log.Fatal(err)
	}

	s, err := node.host.NewStream(ctx, node.dir.ID, "/mediachain/dir/register")
	if err != nil {
		log.Printf("Failed to open directory stream")
		log.Fatal(err)
	}
	defer s.Close()

	pinfo := p2p_pstore.PeerInfo{node.ID, addrs}
	var pbpi pb.PeerInfo
	mc.PBFromPeerInfo(&pbpi, pinfo)
	msg := pb.RegisterPeer{&pbpi}

	w := ggio.NewDelimitedWriter(s)
	for {
		log.Printf("Registering with directory")
		err = w.WriteMsg(&msg)
		if err != nil {
			log.Printf("Failed to register with directory")
			log.Fatal(err)
		}

		time.Sleep(5 * time.Minute)
	}
}

func (node *Node) doPing(ctx context.Context, pid p2p_peer.ID) error {
	if node.status == StatusOffline {
		return NodeOffline
	}

	pinfo, err := node.doLookup(ctx, pid)
	if err != nil {
		return err
	}

	err = node.host.Connect(ctx, pinfo)
	if err != nil {
		return err
	}

	s, err := node.host.NewStream(ctx, pinfo.ID, "/mediachain/node/ping")
	if err != nil {
		return err
	}
	defer s.Close()

	var ping pb.Ping
	w := ggio.NewDelimitedWriter(s)
	err = w.WriteMsg(&ping)
	if err != nil {
		return err
	}

	var pong pb.Pong
	r := ggio.NewDelimitedReader(s, mc.MaxMessageSize)
	err = r.ReadMsg(&pong)

	return err
}

func (node *Node) doLookup(ctx context.Context, pid p2p_peer.ID) (empty p2p_pstore.PeerInfo, err error) {
	if node.status == StatusOffline {
		return empty, NodeOffline
	}

	if node.dir == nil {
		return empty, NoDirectory
	}

	s, err := node.host.NewStream(ctx, node.dir.ID, "/mediachain/dir/lookup")
	if err != nil {
		return empty, err
	}
	defer s.Close()

	req := pb.LookupPeerRequest{pid.Pretty()}
	w := ggio.NewDelimitedWriter(s)
	err = w.WriteMsg(&req)
	if err != nil {
		return empty, err
	}

	var resp pb.LookupPeerResponse
	r := ggio.NewDelimitedReader(s, mc.MaxMessageSize)
	err = r.ReadMsg(&resp)
	if err != nil {
		return empty, err
	}

	if resp.Peer == nil {
		return empty, UnknownPeer
	}

	pinfo, err := mc.PBToPeerInfo(resp.Peer)
	if err != nil {
		return empty, err
	}

	return pinfo, nil
}
<|endoftext|>


<commit_before>package atlas

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
)

var (
	allTypes = map[string]bool{
		"dns":        true,
		"http":       true,
		"ntp":        true,
		"ping":       true,
		"sslcert":    true,
		"traceroute": true,
		"wifi":       true,
	}
)

// -- private

// checkType verify that the type is valid
func checkType(d Definition) (valid bool) {
	_, ok := allTypes[d.Type]
	return ok
}

// checkTypeAs is a shortcut
func checkTypeAs(d Definition, t string) bool {
	valid := checkType(d)
	return valid && d.Type == t
}

// checkAllTypesAs is a generalization of checkTypeAs
func checkAllTypesAs(dl []Definition, t string) (valid bool) {
	valid = true
	for _, d := range dl {
		if d.Type != t {
			valid = false
			break
		}
	}
	return
}

// measurementList is our main answer
type measurementList struct {
	Count    int
	Next     string
	Previous string
	Results  []Measurement
}

// fetch the given resource
func (client *Client) fetchOneMeasurementPage(opts map[string]string) (raw *measurementList, err error) {
	client.mergeGlobalOptions(opts)
	req := client.prepareRequest("GET", "measurements", opts)

	//log.Printf("req=%s qp=%#v", MeasurementEP, opts)
	resp, err := client.call(req)
	err = handleAPIResponse(resp)
	if err != nil {
		return
	}

	raw = &measurementList{}
	body, _ := ioutil.ReadAll(resp.Body)
	defer resp.Body.Close()

	err = json.Unmarshal(body, raw)
	//log.Printf("Count=%d raw=%v", raw.Count, resp)
	//log.Printf(">> rawlist=%+v resp=%+v Next=|%s|", rawlist, resp, rawlist.Next)
	return
}

// -- public

// GetMeasurement gets info for a single one
func (client *Client) GetMeasurement(id int) (m *Measurement, err error) {
	opts := make(map[string]string)

	client.mergeGlobalOptions(opts)
	req := client.prepareRequest("GET", fmt.Sprintf("measurements/%d", id), opts)

	//log.Printf("req: %#v", req)
	resp, err := client.call(req)
	err = handleAPIResponse(r)
	if err != nil {
		return
	}

	m = &Measurement{}
	body, _ := ioutil.ReadAll(resp.Body)
	defer resp.Body.Close()

	err = json.Unmarshal(body, m)
	//log.Printf("json: %#v\n", m)
	return
}

// DeleteMeasurement stops (not really deletes) a given measurement
func (client *Client) DeleteMeasurement(id int) (err error) {
	opts := make(map[string]string)

	req := client.prepareRequest("DELETE", fmt.Sprintf("measurements/%d", id), opts)

	//log.Printf("req: %#v", req)
	resp, err := client.call(req)
	err = handleAPIResponse(resp)
	return
}

// GetMeasurements gets info for a set
func (client *Client) GetMeasurements(opts map[string]string) (m []Measurement, err error) {
	// First call
	rawlist, err := client.fetchOneMeasurementPage(opts)

	// Empty answer
	if rawlist.Count == 0 {
		return []Measurement{}, nil
	}

	var res []Measurement

	res = append(res, rawlist.Results...)
	if rawlist.Next != "" {
		// We have pagination
		for pn := getPageNum(rawlist.Next); rawlist.Next != ""; pn = getPageNum(rawlist.Next) {
			opts["page"] = pn

			rawlist, err = client.fetchOneMeasurementPage(opts)
			if err != nil {
				return
			}

			res = append(res, rawlist.Results...)
		}
	}
	m = res
	return
}

<commit_msg>Fix one missing r -> resp.<commit_after>package atlas

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
)

var (
	allTypes = map[string]bool{
		"dns":        true,
		"http":       true,
		"ntp":        true,
		"ping":       true,
		"sslcert":    true,
		"traceroute": true,
		"wifi":       true,
	}
)

// -- private

// checkType verify that the type is valid
func checkType(d Definition) (valid bool) {
	_, ok := allTypes[d.Type]
	return ok
}

// checkTypeAs is a shortcut
func checkTypeAs(d Definition, t string) bool {
	valid := checkType(d)
	return valid && d.Type == t
}

// checkAllTypesAs is a generalization of checkTypeAs
func checkAllTypesAs(dl []Definition, t string) (valid bool) {
	valid = true
	for _, d := range dl {
		if d.Type != t {
			valid = false
			break
		}
	}
	return
}

// measurementList is our main answer
type measurementList struct {
	Count    int
	Next     string
	Previous string
	Results  []Measurement
}

// fetch the given resource
func (client *Client) fetchOneMeasurementPage(opts map[string]string) (raw *measurementList, err error) {
	client.mergeGlobalOptions(opts)
	req := client.prepareRequest("GET", "measurements", opts)

	//log.Printf("req=%s qp=%#v", MeasurementEP, opts)
	resp, err := client.call(req)
	err = handleAPIResponse(resp)
	if err != nil {
		return
	}

	raw = &measurementList{}
	body, _ := ioutil.ReadAll(resp.Body)
	defer resp.Body.Close()

	err = json.Unmarshal(body, raw)
	//log.Printf("Count=%d raw=%v", raw.Count, resp)
	//log.Printf(">> rawlist=%+v resp=%+v Next=|%s|", rawlist, resp, rawlist.Next)
	return
}

// -- public

// GetMeasurement gets info for a single one
func (client *Client) GetMeasurement(id int) (m *Measurement, err error) {
	opts := make(map[string]string)

	client.mergeGlobalOptions(opts)
	req := client.prepareRequest("GET", fmt.Sprintf("measurements/%d", id), opts)

	//log.Printf("req: %#v", req)
	resp, err := client.call(req)
	err = handleAPIResponse(resp)
	if err != nil {
		return
	}

	m = &Measurement{}
	body, _ := ioutil.ReadAll(resp.Body)
	defer resp.Body.Close()

	err = json.Unmarshal(body, m)
	//log.Printf("json: %#v\n", m)
	return
}

// DeleteMeasurement stops (not really deletes) a given measurement
func (client *Client) DeleteMeasurement(id int) (err error) {
	opts := make(map[string]string)

	req := client.prepareRequest("DELETE", fmt.Sprintf("measurements/%d", id), opts)

	//log.Printf("req: %#v", req)
	resp, err := client.call(req)
	err = handleAPIResponse(resp)
	return
}

// GetMeasurements gets info for a set
func (client *Client) GetMeasurements(opts map[string]string) (m []Measurement, err error) {
	// First call
	rawlist, err := client.fetchOneMeasurementPage(opts)

	// Empty answer
	if rawlist.Count == 0 {
		return []Measurement{}, nil
	}

	var res []Measurement

	res = append(res, rawlist.Results...)
	if rawlist.Next != "" {
		// We have pagination
		for pn := getPageNum(rawlist.Next); rawlist.Next != ""; pn = getPageNum(rawlist.Next) {
			opts["page"] = pn

			rawlist, err = client.fetchOneMeasurementPage(opts)
			if err != nil {
				return
			}

			res = append(res, rawlist.Results...)
		}
	}
	m = res
	return
}

<|endoftext|>