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

package main

import (
	"bytes"
	"fmt"
	"os/exec"
	"regexp"
	"strings"
)

// Branch describes a Git branch.
type Branch struct {
	Name          string    // branch name
	loadedPending bool      // following fields are valid
	originBranch  string    // upstream origin branch
	commitsAhead  int       // number of commits ahead of origin branch
	commitsBehind int       // number of commits behind origin branch
	branchpoint   string    // latest commit hash shared with origin branch
	pending       []*Commit // pending commits, newest first (children before parents)
}

// A Commit describes a single pending commit on a Git branch.
type Commit struct {
	Hash      string // commit hash
	ShortHash string // abbreviated commit hash
	Parent    string // parent hash
	Merge     string // for merges, hash of commit being merged into Parent
	Message   string // commit message
	Subject   string // first line of commit message
	ChangeID  string // Change-Id in commit message ("" if missing)

	// For use by pending command.
	g         *GerritChange // associated Gerrit change data
	gerr      error         // error loading Gerrit data
	committed []string      // list of files in this commit
}

// CurrentBranch returns the current branch.
func CurrentBranch() *Branch {
	name := strings.TrimPrefix(trim(cmdOutput("git", "rev-parse", "--abbrev-ref", "HEAD")), "heads/")
	return &Branch{Name: name}
}

// DetachedHead reports whether branch b corresponds to a detached HEAD
// (does not have a real branch name).
func (b *Branch) DetachedHead() bool {
	return b.Name == "HEAD"
}

// OriginBranch returns the name of the origin branch that branch b tracks.
// The returned name is like "origin/master" or "origin/dev.garbage" or
// "origin/release-branch.go1.4".
func (b *Branch) OriginBranch() string {
	if b.DetachedHead() {
		// Detached head mode.
		// "origin/HEAD" is clearly false, but it should be easy to find when it
		// appears in other commands. Really any caller of OriginBranch
		// should check for detached head mode.
		return "origin/HEAD"
	}

	if b.originBranch != "" {
		return b.originBranch
	}
	argv := []string{"git", "rev-parse", "--abbrev-ref", b.Name + "@{u}"}
	out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput()
	if err == nil && len(out) > 0 {
		b.originBranch = string(bytes.TrimSpace(out))
		return b.originBranch
	}

	// Have seen both "No upstream configured" and "no upstream configured".
	if strings.Contains(string(out), "upstream configured") {
		// Assume branch was created before we set upstream correctly.
		b.originBranch = "origin/master"
		return b.originBranch
	}
	fmt.Fprintf(stderr(), "%v\n%s\n", commandString(argv[0], argv[1:]), out)
	dief("%v", err)
	panic("not reached")
}

func (b *Branch) FullName() string {
	if b.Name != "HEAD" {
		return "refs/heads/" + b.Name
	}
	return b.Name
}

// IsLocalOnly reports whether b is a local work branch (only local, not known to remote server).
func (b *Branch) IsLocalOnly() bool {
	return "origin/"+b.Name != b.OriginBranch()
}

// HasPendingCommit reports whether b has any pending commits.
func (b *Branch) HasPendingCommit() bool {
	b.loadPending()
	return b.commitsAhead > 0
}

// Pending returns b's pending commits, newest first (children before parents).
func (b *Branch) Pending() []*Commit {
	b.loadPending()
	return b.pending
}

// Branchpoint returns an identifier for the latest revision
// common to both this branch and its upstream branch.
func (b *Branch) Branchpoint() string {
	b.loadPending()
	return b.branchpoint
}

func (b *Branch) loadPending() {
	if b.loadedPending {
		return
	}
	b.loadedPending = true

	// In case of early return.
	b.branchpoint = trim(cmdOutput("git", "rev-parse", "HEAD"))

	if b.DetachedHead() {
		return
	}

	// Note: --topo-order means child first, then parent.
	origin := b.OriginBranch()
	const numField = 5
	all := trim(cmdOutput("git", "log", "--topo-order", "--format=format:%H%x00%h%x00%P%x00%B%x00%s%x00", origin+".."+b.FullName(), "--"))
	fields := strings.Split(all, "\x00")
	if len(fields) < numField {
		return // nothing pending
	}
	for i, field := range fields {
		fields[i] = strings.TrimLeft(field, "\r\n")
	}
	foundMergeBranchpoint := false
	for i := 0; i+numField <= len(fields); i += numField {
		c := &Commit{
			Hash:      fields[i],
			ShortHash: fields[i+1],
			Parent:    strings.TrimSpace(fields[i+2]), // %P starts with \n for some reason
			Message:   fields[i+3],
			Subject:   fields[i+4],
		}
		if j := strings.Index(c.Parent, " "); j >= 0 {
			c.Parent, c.Merge = c.Parent[:j], c.Parent[j+1:]
			// Found merge point.
			// Merges break the invariant that the last shared commit (the branchpoint)
			// is the parent of the final commit in the log output.
			// If c.Parent is on the origin branch, then since we are reading the log
			// in (reverse) topological order, we know that c.Parent is the actual branchpoint,
			// even if we later see additional commits on a different branch leading down to
			// a lower location on the same origin branch.
			// Check c.Merge (the second parent) too, so we don't depend on the parent order.
			if strings.Contains(cmdOutput("git", "branch", "-a", "--contains", c.Parent), " "+origin+"\n") {
				foundMergeBranchpoint = true
				b.branchpoint = c.Parent
			}
			if strings.Contains(cmdOutput("git", "branch", "-a", "--contains", c.Merge), " "+origin+"\n") {
				foundMergeBranchpoint = true
				b.branchpoint = c.Merge
			}
		}
		for _, line := range lines(c.Message) {
			// Note: Keep going even if we find one, so that
			// we take the last Change-Id line, just in case
			// there is a commit message quoting another
			// commit message.
			// I'm not sure this can come up at all, but just in case.
			if strings.HasPrefix(line, "Change-Id: ") {
				c.ChangeID = line[len("Change-Id: "):]
			}
		}

		b.pending = append(b.pending, c)
		if !foundMergeBranchpoint {
			b.branchpoint = c.Parent
		}
	}
	b.commitsAhead = len(b.pending)
	b.commitsBehind = len(lines(cmdOutput("git", "log", "--format=format:x", b.FullName()+".."+b.OriginBranch(), "--")))
}

// Submitted reports whether some form of b's pending commit
// has been cherry picked to origin.
func (b *Branch) Submitted(id string) bool {
	if id == "" {
		return false
	}
	line := "Change-Id: " + id
	out := cmdOutput("git", "log", "-n", "1", "-F", "--grep", line, b.Name+".."+b.OriginBranch(), "--")
	return strings.Contains(out, line)
}

var stagedRE = regexp.MustCompile(`^[ACDMR]  `)

// HasStagedChanges reports whether the working directory contains staged changes.
func HasStagedChanges() bool {
	for _, s := range nonBlankLines(cmdOutput("git", "status", "-b", "--porcelain")) {
		if stagedRE.MatchString(s) {
			return true
		}
	}
	return false
}

var unstagedRE = regexp.MustCompile(`^.[ACDMR]`)

// HasUnstagedChanges reports whether the working directory contains unstaged changes.
func HasUnstagedChanges() bool {
	for _, s := range nonBlankLines(cmdOutput("git", "status", "-b", "--porcelain")) {
		if unstagedRE.MatchString(s) {
			return true
		}
	}
	return false
}

// LocalChanges returns a list of files containing staged, unstaged, and untracked changes.
// The elements of the returned slices are typically file names, always relative to the root,
// but there are a few alternate forms. First, for renaming or copying, the element takes
// the form `from -> to`. Second, in the case of files with names that contain unusual characters,
// the files (or the from, to fields of a rename or copy) are quoted C strings.
// For now, we expect the caller only shows these to the user, so these exceptions are okay.
func LocalChanges() (staged, unstaged, untracked []string) {
	for _, s := range lines(cmdOutput("git", "status", "-b", "--porcelain")) {
		if len(s) < 4 || s[2] != ' ' {
			continue
		}
		switch s[0] {
		case 'A', 'C', 'D', 'M', 'R':
			staged = append(staged, s[3:])
		case '?':
			untracked = append(untracked, s[3:])
		}
		switch s[1] {
		case 'A', 'C', 'D', 'M', 'R':
			unstaged = append(unstaged, s[3:])
		}
	}
	return
}

// LocalBranches returns a list of all known local branches.
// If the current directory is in detached HEAD mode, one returned
// branch will have Name == "HEAD" and DetachedHead() == true.
func LocalBranches() []*Branch {
	var branches []*Branch
	current := CurrentBranch()
	for _, s := range nonBlankLines(cmdOutput("git", "branch", "-q")) {
		s = strings.TrimSpace(s)
		if strings.HasPrefix(s, "* ") {
			// * marks current branch in output.
			// Normally the current branch has a name like any other,
			// but in detached HEAD mode the branch listing shows
			// a localized (translated) textual description instead of
			// a branch name. Avoid language-specific differences
			// by using CurrentBranch().Name for the current branch.
			// It detects detached HEAD mode in a more portable way.
			// (git rev-parse --abbrev-ref HEAD returns 'HEAD').
			s = current.Name
		}
		branches = append(branches, &Branch{Name: s})
	}
	return branches
}

func OriginBranches() []string {
	var branches []string
	for _, line := range nonBlankLines(cmdOutput("git", "branch", "-a", "-q")) {
		line = strings.TrimSpace(line)
		if i := strings.Index(line, " -> "); i >= 0 {
			line = line[:i]
		}
		name := strings.TrimSpace(strings.TrimPrefix(line, "* "))
		if strings.HasPrefix(name, "remotes/origin/") {
			branches = append(branches, strings.TrimPrefix(name, "remotes/"))
		}
	}
	return branches
}

// GerritChange returns the change metadata from the Gerrit server
// for the branch's pending change.
// The extra strings are passed to the Gerrit API request as o= parameters,
// to enable additional information. Typical values include "LABELS" and "CURRENT_REVISION".
// See https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html for details.
func (b *Branch) GerritChange(c *Commit, extra ...string) (*GerritChange, error) {
	if !b.HasPendingCommit() {
		return nil, fmt.Errorf("no changes pending")
	}
	id := fullChangeID(b, c)
	for i, x := range extra {
		if i == 0 {
			id += "?"
		} else {
			id += "&"
		}
		id += "o=" + x
	}
	return readGerritChange(id)
}

// CommitByRev finds a unique pending commit by its git <rev>.
// It dies if rev cannot be resolved to a commit or that commit is not
// pending on b using the action ("mail", "submit") in the failure message.
func (b *Branch) CommitByRev(action, rev string) *Commit {
	// Parse rev to a commit hash.
	hash, err := cmdOutputErr("git", "rev-parse", "--verify", rev+"^{commit}")
	if err != nil {
		msg := strings.TrimPrefix(trim(err.Error()), "fatal: ")
		dief("cannot %s: %s", action, msg)
	}
	hash = trim(hash)

	// Check that hash is a pending commit.
	var c *Commit
	for _, c1 := range b.Pending() {
		if c1.Hash == hash {
			c = c1
			break
		}
	}
	if c == nil {
		dief("cannot %s: commit hash %q not found in the current branch", action, hash)
	}
	return c
}

// DefaultCommit returns the default pending commit for this branch.
// It dies if there is not exactly one pending commit,
// using the action (e.g. "mail", "submit") and optional extra instructions
// in the failure message.
func (b *Branch) DefaultCommit(action, extra string) *Commit {
	work := b.Pending()
	if len(work) == 0 {
		dief("cannot %s: no changes pending", action)
	}
	if len(work) >= 2 {
		var buf bytes.Buffer
		for _, c := range work {
			fmt.Fprintf(&buf, "\n\t%s %s", c.ShortHash, c.Subject)
		}
		if extra != "" {
			extra = "; " + extra
		}
		dief("cannot %s: multiple changes pending%s:%s", action, extra, buf.String())
	}
	return work[0]
}

// ListFiles returns the list of files in a given commit.
func ListFiles(c *Commit) []string {
	return nonBlankLines(cmdOutput("git", "diff", "--name-only", c.Parent, c.Hash, "--"))
}

func cmdBranchpoint(args []string) {
	expectZeroArgs(args, "sync")
	fmt.Fprintf(stdout(), "%s\n", CurrentBranch().Branchpoint())
}

func cmdRebaseWork(args []string) {
	expectZeroArgs(args, "rebase-work")
	b := CurrentBranch()
	if HasStagedChanges() || HasUnstagedChanges() {
		dief("cannot rebase with uncommitted work")
	}
	if len(b.Pending()) == 0 {
		dief("no pending work")
	}
	run("git", "rebase", "-i", b.Branchpoint())
}
<commit_msg>review: Fix error of git change on windows<commit_after>// Copyright 2014 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
)

// Branch describes a Git branch.
type Branch struct {
	Name          string    // branch name
	loadedPending bool      // following fields are valid
	originBranch  string    // upstream origin branch
	commitsAhead  int       // number of commits ahead of origin branch
	commitsBehind int       // number of commits behind origin branch
	branchpoint   string    // latest commit hash shared with origin branch
	pending       []*Commit // pending commits, newest first (children before parents)
}

// A Commit describes a single pending commit on a Git branch.
type Commit struct {
	Hash      string // commit hash
	ShortHash string // abbreviated commit hash
	Parent    string // parent hash
	Merge     string // for merges, hash of commit being merged into Parent
	Message   string // commit message
	Subject   string // first line of commit message
	ChangeID  string // Change-Id in commit message ("" if missing)

	// For use by pending command.
	g         *GerritChange // associated Gerrit change data
	gerr      error         // error loading Gerrit data
	committed []string      // list of files in this commit
}

// CurrentBranch returns the current branch.
func CurrentBranch() *Branch {
	name := strings.TrimPrefix(trim(cmdOutput("git", "rev-parse", "--abbrev-ref", "HEAD")), "heads/")
	return &Branch{Name: name}
}

// DetachedHead reports whether branch b corresponds to a detached HEAD
// (does not have a real branch name).
func (b *Branch) DetachedHead() bool {
	return b.Name == "HEAD"
}

// OriginBranch returns the name of the origin branch that branch b tracks.
// The returned name is like "origin/master" or "origin/dev.garbage" or
// "origin/release-branch.go1.4".
func (b *Branch) OriginBranch() string {
	if b.DetachedHead() {
		// Detached head mode.
		// "origin/HEAD" is clearly false, but it should be easy to find when it
		// appears in other commands. Really any caller of OriginBranch
		// should check for detached head mode.
		return "origin/HEAD"
	}

	if b.originBranch != "" {
		return b.originBranch
	}
	argv := []string{"git", "rev-parse", "--abbrev-ref", b.Name + "@{u}"}
	cmd := exec.Command(argv[0], argv[1:]...)
	if runtime.GOOS == "windows" {
		// Workaround on windows. git for windows can't handle @{u} as same as
		// given. Disable glob for this command if running on Cygwin or MSYS2.
		envs := os.Environ()
		envs = append(envs, "CYGWIN=noglob "+os.Getenv("CYGWIN"))
		envs = append(envs, "MSYS=noglob "+os.Getenv("MSYS"))
		cmd.Env = envs
	}

	out, err := cmd.CombinedOutput()
	if err == nil && len(out) > 0 {
		b.originBranch = string(bytes.TrimSpace(out))
		return b.originBranch
	}

	// Have seen both "No upstream configured" and "no upstream configured".
	if strings.Contains(string(out), "upstream configured") {
		// Assume branch was created before we set upstream correctly.
		b.originBranch = "origin/master"
		return b.originBranch
	}
	fmt.Fprintf(stderr(), "%v\n%s\n", commandString(argv[0], argv[1:]), out)
	dief("%v", err)
	panic("not reached")
}

func (b *Branch) FullName() string {
	if b.Name != "HEAD" {
		return "refs/heads/" + b.Name
	}
	return b.Name
}

// IsLocalOnly reports whether b is a local work branch (only local, not known to remote server).
func (b *Branch) IsLocalOnly() bool {
	return "origin/"+b.Name != b.OriginBranch()
}

// HasPendingCommit reports whether b has any pending commits.
func (b *Branch) HasPendingCommit() bool {
	b.loadPending()
	return b.commitsAhead > 0
}

// Pending returns b's pending commits, newest first (children before parents).
func (b *Branch) Pending() []*Commit {
	b.loadPending()
	return b.pending
}

// Branchpoint returns an identifier for the latest revision
// common to both this branch and its upstream branch.
func (b *Branch) Branchpoint() string {
	b.loadPending()
	return b.branchpoint
}

func (b *Branch) loadPending() {
	if b.loadedPending {
		return
	}
	b.loadedPending = true

	// In case of early return.
	b.branchpoint = trim(cmdOutput("git", "rev-parse", "HEAD"))

	if b.DetachedHead() {
		return
	}

	// Note: --topo-order means child first, then parent.
	origin := b.OriginBranch()
	const numField = 5
	all := trim(cmdOutput("git", "log", "--topo-order", "--format=format:%H%x00%h%x00%P%x00%B%x00%s%x00", origin+".."+b.FullName(), "--"))
	fields := strings.Split(all, "\x00")
	if len(fields) < numField {
		return // nothing pending
	}
	for i, field := range fields {
		fields[i] = strings.TrimLeft(field, "\r\n")
	}
	foundMergeBranchpoint := false
	for i := 0; i+numField <= len(fields); i += numField {
		c := &Commit{
			Hash:      fields[i],
			ShortHash: fields[i+1],
			Parent:    strings.TrimSpace(fields[i+2]), // %P starts with \n for some reason
			Message:   fields[i+3],
			Subject:   fields[i+4],
		}
		if j := strings.Index(c.Parent, " "); j >= 0 {
			c.Parent, c.Merge = c.Parent[:j], c.Parent[j+1:]
			// Found merge point.
			// Merges break the invariant that the last shared commit (the branchpoint)
			// is the parent of the final commit in the log output.
			// If c.Parent is on the origin branch, then since we are reading the log
			// in (reverse) topological order, we know that c.Parent is the actual branchpoint,
			// even if we later see additional commits on a different branch leading down to
			// a lower location on the same origin branch.
			// Check c.Merge (the second parent) too, so we don't depend on the parent order.
			if strings.Contains(cmdOutput("git", "branch", "-a", "--contains", c.Parent), " "+origin+"\n") {
				foundMergeBranchpoint = true
				b.branchpoint = c.Parent
			}
			if strings.Contains(cmdOutput("git", "branch", "-a", "--contains", c.Merge), " "+origin+"\n") {
				foundMergeBranchpoint = true
				b.branchpoint = c.Merge
			}
		}
		for _, line := range lines(c.Message) {
			// Note: Keep going even if we find one, so that
			// we take the last Change-Id line, just in case
			// there is a commit message quoting another
			// commit message.
			// I'm not sure this can come up at all, but just in case.
			if strings.HasPrefix(line, "Change-Id: ") {
				c.ChangeID = line[len("Change-Id: "):]
			}
		}

		b.pending = append(b.pending, c)
		if !foundMergeBranchpoint {
			b.branchpoint = c.Parent
		}
	}
	b.commitsAhead = len(b.pending)
	b.commitsBehind = len(lines(cmdOutput("git", "log", "--format=format:x", b.FullName()+".."+b.OriginBranch(), "--")))
}

// Submitted reports whether some form of b's pending commit
// has been cherry picked to origin.
func (b *Branch) Submitted(id string) bool {
	if id == "" {
		return false
	}
	line := "Change-Id: " + id
	out := cmdOutput("git", "log", "-n", "1", "-F", "--grep", line, b.Name+".."+b.OriginBranch(), "--")
	return strings.Contains(out, line)
}

var stagedRE = regexp.MustCompile(`^[ACDMR]  `)

// HasStagedChanges reports whether the working directory contains staged changes.
func HasStagedChanges() bool {
	for _, s := range nonBlankLines(cmdOutput("git", "status", "-b", "--porcelain")) {
		if stagedRE.MatchString(s) {
			return true
		}
	}
	return false
}

var unstagedRE = regexp.MustCompile(`^.[ACDMR]`)

// HasUnstagedChanges reports whether the working directory contains unstaged changes.
func HasUnstagedChanges() bool {
	for _, s := range nonBlankLines(cmdOutput("git", "status", "-b", "--porcelain")) {
		if unstagedRE.MatchString(s) {
			return true
		}
	}
	return false
}

// LocalChanges returns a list of files containing staged, unstaged, and untracked changes.
// The elements of the returned slices are typically file names, always relative to the root,
// but there are a few alternate forms. First, for renaming or copying, the element takes
// the form `from -> to`. Second, in the case of files with names that contain unusual characters,
// the files (or the from, to fields of a rename or copy) are quoted C strings.
// For now, we expect the caller only shows these to the user, so these exceptions are okay.
func LocalChanges() (staged, unstaged, untracked []string) {
	for _, s := range lines(cmdOutput("git", "status", "-b", "--porcelain")) {
		if len(s) < 4 || s[2] != ' ' {
			continue
		}
		switch s[0] {
		case 'A', 'C', 'D', 'M', 'R':
			staged = append(staged, s[3:])
		case '?':
			untracked = append(untracked, s[3:])
		}
		switch s[1] {
		case 'A', 'C', 'D', 'M', 'R':
			unstaged = append(unstaged, s[3:])
		}
	}
	return
}

// LocalBranches returns a list of all known local branches.
// If the current directory is in detached HEAD mode, one returned
// branch will have Name == "HEAD" and DetachedHead() == true.
func LocalBranches() []*Branch {
	var branches []*Branch
	current := CurrentBranch()
	for _, s := range nonBlankLines(cmdOutput("git", "branch", "-q")) {
		s = strings.TrimSpace(s)
		if strings.HasPrefix(s, "* ") {
			// * marks current branch in output.
			// Normally the current branch has a name like any other,
			// but in detached HEAD mode the branch listing shows
			// a localized (translated) textual description instead of
			// a branch name. Avoid language-specific differences
			// by using CurrentBranch().Name for the current branch.
			// It detects detached HEAD mode in a more portable way.
			// (git rev-parse --abbrev-ref HEAD returns 'HEAD').
			s = current.Name
		}
		branches = append(branches, &Branch{Name: s})
	}
	return branches
}

func OriginBranches() []string {
	var branches []string
	for _, line := range nonBlankLines(cmdOutput("git", "branch", "-a", "-q")) {
		line = strings.TrimSpace(line)
		if i := strings.Index(line, " -> "); i >= 0 {
			line = line[:i]
		}
		name := strings.TrimSpace(strings.TrimPrefix(line, "* "))
		if strings.HasPrefix(name, "remotes/origin/") {
			branches = append(branches, strings.TrimPrefix(name, "remotes/"))
		}
	}
	return branches
}

// GerritChange returns the change metadata from the Gerrit server
// for the branch's pending change.
// The extra strings are passed to the Gerrit API request as o= parameters,
// to enable additional information. Typical values include "LABELS" and "CURRENT_REVISION".
// See https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html for details.
func (b *Branch) GerritChange(c *Commit, extra ...string) (*GerritChange, error) {
	if !b.HasPendingCommit() {
		return nil, fmt.Errorf("no changes pending")
	}
	id := fullChangeID(b, c)
	for i, x := range extra {
		if i == 0 {
			id += "?"
		} else {
			id += "&"
		}
		id += "o=" + x
	}
	return readGerritChange(id)
}

// CommitByRev finds a unique pending commit by its git <rev>.
// It dies if rev cannot be resolved to a commit or that commit is not
// pending on b using the action ("mail", "submit") in the failure message.
func (b *Branch) CommitByRev(action, rev string) *Commit {
	// Parse rev to a commit hash.
	hash, err := cmdOutputErr("git", "rev-parse", "--verify", rev+"^{commit}")
	if err != nil {
		msg := strings.TrimPrefix(trim(err.Error()), "fatal: ")
		dief("cannot %s: %s", action, msg)
	}
	hash = trim(hash)

	// Check that hash is a pending commit.
	var c *Commit
	for _, c1 := range b.Pending() {
		if c1.Hash == hash {
			c = c1
			break
		}
	}
	if c == nil {
		dief("cannot %s: commit hash %q not found in the current branch", action, hash)
	}
	return c
}

// DefaultCommit returns the default pending commit for this branch.
// It dies if there is not exactly one pending commit,
// using the action (e.g. "mail", "submit") and optional extra instructions
// in the failure message.
func (b *Branch) DefaultCommit(action, extra string) *Commit {
	work := b.Pending()
	if len(work) == 0 {
		dief("cannot %s: no changes pending", action)
	}
	if len(work) >= 2 {
		var buf bytes.Buffer
		for _, c := range work {
			fmt.Fprintf(&buf, "\n\t%s %s", c.ShortHash, c.Subject)
		}
		if extra != "" {
			extra = "; " + extra
		}
		dief("cannot %s: multiple changes pending%s:%s", action, extra, buf.String())
	}
	return work[0]
}

// ListFiles returns the list of files in a given commit.
func ListFiles(c *Commit) []string {
	return nonBlankLines(cmdOutput("git", "diff", "--name-only", c.Parent, c.Hash, "--"))
}

func cmdBranchpoint(args []string) {
	expectZeroArgs(args, "sync")
	fmt.Fprintf(stdout(), "%s\n", CurrentBranch().Branchpoint())
}

func cmdRebaseWork(args []string) {
	expectZeroArgs(args, "rebase-work")
	b := CurrentBranch()
	if HasStagedChanges() || HasUnstagedChanges() {
		dief("cannot rebase with uncommitted work")
	}
	if len(b.Pending()) == 0 {
		dief("no pending work")
	}
	run("git", "rebase", "-i", b.Branchpoint())
}
<|endoftext|>


<commit_before>package github

import (
	"io"
	"io/ioutil"

	"github.com/BurntSushi/toml"
	"gopkg.in/yaml.v2"
)

type configDecoder interface {
	Decode(r io.Reader, c *Config) error
}

type tomlConfigDecoder struct {
}

func (t *tomlConfigDecoder) Decode(r io.Reader, c *Config) error {
	_, err := toml.DecodeReader(r, c)
	return err
}

type yamlConfigDecoder struct {
}

func (y *yamlConfigDecoder) Decode(r io.Reader, c *Config) error {
	d, err := ioutil.ReadAll(r)
	if err != nil {
		return err
	}

	yc := make(yamlConfig)
	err = yaml.Unmarshal(d, &yc)

	if err != nil {
		return err
	}

	for h, v := range yc {
		vv := v[0]
		host := &Host{
			Host:        h,
			User:        vv.User,
			AccessToken: vv.OAuthToken,
			Protocol:    vv.Protocol,
		}
		c.Hosts = append(c.Hosts, host)
	}

	return nil
}
<commit_msg>Ignore crash for malformed config file<commit_after>package github

import (
	"io"
	"io/ioutil"

	"github.com/BurntSushi/toml"
	"gopkg.in/yaml.v2"
)

type configDecoder interface {
	Decode(r io.Reader, c *Config) error
}

type tomlConfigDecoder struct {
}

func (t *tomlConfigDecoder) Decode(r io.Reader, c *Config) error {
	_, err := toml.DecodeReader(r, c)
	return err
}

type yamlConfigDecoder struct {
}

func (y *yamlConfigDecoder) Decode(r io.Reader, c *Config) error {
	d, err := ioutil.ReadAll(r)
	if err != nil {
		return err
	}

	yc := make(yamlConfig)
	err = yaml.Unmarshal(d, &yc)

	if err != nil {
		return err
	}

	for h, v := range yc {
		if len(v) < 1 {
			continue
		}
		vv := v[0]
		host := &Host{
			Host:        h,
			User:        vv.User,
			AccessToken: vv.OAuthToken,
			Protocol:    vv.Protocol,
		}
		c.Hosts = append(c.Hosts, host)
	}

	return nil
}
<|endoftext|>


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

// Repository contents API methods.
// http://developer.github.com/v3/repos/contents/

package github

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"path"
)

// RepositoryContent represents a file or directory in a github repository.
type RepositoryContent struct {
	Type     *string `json:"type,omitempty"`
	Encoding *string `json:"encoding,omitempty"`
	Size     *int    `json:"size,omitempty"`
	Name     *string `json:"name,omitempty"`
	Path     *string `json:"path,omitempty"`
	// Content contains the actual file content, which may be encoded.
	// Callers should call GetContent which will decode the content if
	// necessary.
	Content     *string `json:"content,omitempty"`
	SHA         *string `json:"sha,omitempty"`
	URL         *string `json:"url,omitempty"`
	GitURL      *string `json:"git_url,omitempty"`
	HTMLURL     *string `json:"html_url,omitempty"`
	DownloadURL *string `json:"download_url,omitempty"`
}

// RepositoryContentResponse holds the parsed response from CreateFile, UpdateFile, and DeleteFile.
type RepositoryContentResponse struct {
	Content *RepositoryContent `json:"content,omitempty"`
	Commit  `json:"commit,omitempty"`
}

// RepositoryContentFileOptions specifies optional parameters for CreateFile, UpdateFile, and DeleteFile.
type RepositoryContentFileOptions struct {
	Message   *string       `json:"message,omitempty"`
	Content   []byte        `json:"content,omitempty"` // unencoded
	SHA       *string       `json:"sha,omitempty"`
	Branch    *string       `json:"branch,omitempty"`
	Author    *CommitAuthor `json:"author,omitempty"`
	Committer *CommitAuthor `json:"committer,omitempty"`
}

// RepositoryContentGetOptions represents an optional ref parameter, which can be a SHA,
// branch, or tag
type RepositoryContentGetOptions struct {
	Ref string `url:"ref,omitempty"`
}

// String converts RepositoryContent to a string. It's primarily for testing.
func (r RepositoryContent) String() string {
	return Stringify(r)
}

// Decode decodes the file content if it is base64 encoded.
//
// Deprecated: Use GetContent instead.
func (r *RepositoryContent) Decode() ([]byte, error) {
	if *r.Encoding != "base64" {
		return nil, errors.New("cannot decode non-base64")
	}
	o, err := base64.StdEncoding.DecodeString(*r.Content)
	if err != nil {
		return nil, err
	}
	return o, nil
}

// GetContent returns the content of r, decoding it if necessary.
func (r *RepositoryContent) GetContent() (string, error) {
	var encoding string
	if r.Encoding != nil {
		encoding = *r.Encoding
	}

	switch encoding {
	case "base64":
		c, err := base64.StdEncoding.DecodeString(*r.Content)
		return string(c), err
	case "":
		if r.Content == nil {
			return "", nil
		}
		return *r.Content, nil
	default:
		return "", fmt.Errorf("unsupported content encoding: %v", encoding)
	}
}

// GetReadme gets the Readme file for the repository.
//
// GitHub API docs: http://developer.github.com/v3/repos/contents/#get-the-readme
func (s *RepositoriesService) GetReadme(owner, repo string, opt *RepositoryContentGetOptions) (*RepositoryContent, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/readme", owner, repo)
	u, err := addOptions(u, opt)
	if err != nil {
		return nil, nil, err
	}
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}
	readme := new(RepositoryContent)
	resp, err := s.client.Do(req, readme)
	if err != nil {
		return nil, resp, err
	}
	return readme, resp, err
}

// DownloadContents returns an io.ReadCloser that reads the contents of the
// specified file. This function will work with files of any size, as opposed
// to GetContents which is limited to 1 Mb files. It is the caller's
// responsibility to close the ReadCloser.
func (s *RepositoriesService) DownloadContents(owner, repo, filepath string, opt *RepositoryContentGetOptions) (io.ReadCloser, error) {
	dir := path.Dir(filepath)
	filename := path.Base(filepath)
	_, dirContents, _, err := s.GetContents(owner, repo, dir, opt)
	if err != nil {
		return nil, err
	}
	for _, contents := range dirContents {
		if *contents.Name == filename {
			if contents.DownloadURL == nil || *contents.DownloadURL == "" {
				return nil, fmt.Errorf("No download link found for %s", filepath)
			}
			resp, err := s.client.client.Get(*contents.DownloadURL)
			if err != nil {
				return nil, err
			}
			return resp.Body, nil
		}
	}
	return nil, fmt.Errorf("No file named %s found in %s", filename, dir)
}

// GetContents can return either the metadata and content of a single file
// (when path references a file) or the metadata of all the files and/or
// subdirectories of a directory (when path references a directory). To make it
// easy to distinguish between both result types and to mimic the API as much
// as possible, both result types will be returned but only one will contain a
// value and the other will be nil.
//
// GitHub API docs: http://developer.github.com/v3/repos/contents/#get-contents
func (s *RepositoriesService) GetContents(owner, repo, path string, opt *RepositoryContentGetOptions) (fileContent *RepositoryContent, directoryContent []*RepositoryContent, resp *Response, err error) {
	escapedPath := (&url.URL{Path: path}).String()
	u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, escapedPath)
	u, err = addOptions(u, opt)
	if err != nil {
		return nil, nil, nil, err
	}
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, nil, err
	}
	var rawJSON json.RawMessage
	resp, err = s.client.Do(req, &rawJSON)
	if err != nil {
		return nil, nil, resp, err
	}
	fileUnmarshalError := json.Unmarshal(rawJSON, &fileContent)
	if fileUnmarshalError == nil {
		return fileContent, nil, resp, fileUnmarshalError
	}
	directoryUnmarshalError := json.Unmarshal(rawJSON, &directoryContent)
	if directoryUnmarshalError == nil {
		return nil, directoryContent, resp, directoryUnmarshalError
	}
	return nil, nil, resp, fmt.Errorf("unmarshalling failed for both file and directory content: %s and %s ", fileUnmarshalError, directoryUnmarshalError)
}

// CreateFile creates a new file in a repository at the given path and returns
// the commit and file metadata.
//
// GitHub API docs: http://developer.github.com/v3/repos/contents/#create-a-file
func (s *RepositoriesService) CreateFile(owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) {
	u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path)
	req, err := s.client.NewRequest("PUT", u, opt)
	if err != nil {
		return nil, nil, err
	}
	createResponse := new(RepositoryContentResponse)
	resp, err := s.client.Do(req, createResponse)
	if err != nil {
		return nil, resp, err
	}
	return createResponse, resp, err
}

// UpdateFile updates a file in a repository at the given path and returns the
// commit and file metadata. Requires the blob SHA of the file being updated.
//
// GitHub API docs: http://developer.github.com/v3/repos/contents/#update-a-file
func (s *RepositoriesService) UpdateFile(owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) {
	u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path)
	req, err := s.client.NewRequest("PUT", u, opt)
	if err != nil {
		return nil, nil, err
	}
	updateResponse := new(RepositoryContentResponse)
	resp, err := s.client.Do(req, updateResponse)
	if err != nil {
		return nil, resp, err
	}
	return updateResponse, resp, err
}

// DeleteFile deletes a file from a repository and returns the commit.
// Requires the blob SHA of the file to be deleted.
//
// GitHub API docs: http://developer.github.com/v3/repos/contents/#delete-a-file
func (s *RepositoriesService) DeleteFile(owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) {
	u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path)
	req, err := s.client.NewRequest("DELETE", u, opt)
	if err != nil {
		return nil, nil, err
	}
	deleteResponse := new(RepositoryContentResponse)
	resp, err := s.client.Do(req, deleteResponse)
	if err != nil {
		return nil, resp, err
	}
	return deleteResponse, resp, err
}

// archiveFormat is used to define the archive type when calling GetArchiveLink.
type archiveFormat string

const (
	// Tarball specifies an archive in gzipped tar format.
	Tarball archiveFormat = "tarball"

	// Zipball specifies an archive in zip format.
	Zipball archiveFormat = "zipball"
)

// GetArchiveLink returns an URL to download a tarball or zipball archive for a
// repository. The archiveFormat can be specified by either the github.Tarball
// or github.Zipball constant.
//
// GitHub API docs: http://developer.github.com/v3/repos/contents/#get-archive-link
func (s *RepositoriesService) GetArchiveLink(owner, repo string, archiveformat archiveFormat, opt *RepositoryContentGetOptions) (*url.URL, *Response, error) {
	u := fmt.Sprintf("repos/%s/%s/%s", owner, repo, archiveformat)
	if opt != nil && opt.Ref != "" {
		u += fmt.Sprintf("/%s", opt.Ref)
	}
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}
	var resp *http.Response
	// Use http.DefaultTransport if no custom Transport is configured
	if s.client.client.Transport == nil {
		resp, err = http.DefaultTransport.RoundTrip(req)
	} else {
		resp, err = s.client.client.Transport.RoundTrip(req)
	}
	if err != nil || resp.StatusCode != http.StatusFound {
		return nil, newResponse(resp), err
	}
	parsedURL, err := url.Parse(resp.Header.Get("Location"))
	return parsedURL, newResponse(resp), err
}
<commit_msg>Make GetArchiveLink behave the same as other calls<commit_after>// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Repository contents API methods.
// http://developer.github.com/v3/repos/contents/

package github

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"path"
)

// RepositoryContent represents a file or directory in a github repository.
type RepositoryContent struct {
	Type     *string `json:"type,omitempty"`
	Encoding *string `json:"encoding,omitempty"`
	Size     *int    `json:"size,omitempty"`
	Name     *string `json:"name,omitempty"`
	Path     *string `json:"path,omitempty"`
	// Content contains the actual file content, which may be encoded.
	// Callers should call GetContent which will decode the content if
	// necessary.
	Content     *string `json:"content,omitempty"`
	SHA         *string `json:"sha,omitempty"`
	URL         *string `json:"url,omitempty"`
	GitURL      *string `json:"git_url,omitempty"`
	HTMLURL     *string `json:"html_url,omitempty"`
	DownloadURL *string `json:"download_url,omitempty"`
}

// RepositoryContentResponse holds the parsed response from CreateFile, UpdateFile, and DeleteFile.
type RepositoryContentResponse struct {
	Content *RepositoryContent `json:"content,omitempty"`
	Commit  `json:"commit,omitempty"`
}

// RepositoryContentFileOptions specifies optional parameters for CreateFile, UpdateFile, and DeleteFile.
type RepositoryContentFileOptions struct {
	Message   *string       `json:"message,omitempty"`
	Content   []byte        `json:"content,omitempty"` // unencoded
	SHA       *string       `json:"sha,omitempty"`
	Branch    *string       `json:"branch,omitempty"`
	Author    *CommitAuthor `json:"author,omitempty"`
	Committer *CommitAuthor `json:"committer,omitempty"`
}

// RepositoryContentGetOptions represents an optional ref parameter, which can be a SHA,
// branch, or tag
type RepositoryContentGetOptions struct {
	Ref string `url:"ref,omitempty"`
}

// String converts RepositoryContent to a string. It's primarily for testing.
func (r RepositoryContent) String() string {
	return Stringify(r)
}

// Decode decodes the file content if it is base64 encoded.
//
// Deprecated: Use GetContent instead.
func (r *RepositoryContent) Decode() ([]byte, error) {
	if *r.Encoding != "base64" {
		return nil, errors.New("cannot decode non-base64")
	}
	o, err := base64.StdEncoding.DecodeString(*r.Content)
	if err != nil {
		return nil, err
	}
	return o, nil
}

// GetContent returns the content of r, decoding it if necessary.
func (r *RepositoryContent) GetContent() (string, error) {
	var encoding string
	if r.Encoding != nil {
		encoding = *r.Encoding
	}

	switch encoding {
	case "base64":
		c, err := base64.StdEncoding.DecodeString(*r.Content)
		return string(c), err
	case "":
		if r.Content == nil {
			return "", nil
		}
		return *r.Content, nil
	default:
		return "", fmt.Errorf("unsupported content encoding: %v", encoding)
	}
}

// GetReadme gets the Readme file for the repository.
//
// GitHub API docs: http://developer.github.com/v3/repos/contents/#get-the-readme
func (s *RepositoriesService) GetReadme(owner, repo string, opt *RepositoryContentGetOptions) (*RepositoryContent, *Response, error) {
	u := fmt.Sprintf("repos/%v/%v/readme", owner, repo)
	u, err := addOptions(u, opt)
	if err != nil {
		return nil, nil, err
	}
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}
	readme := new(RepositoryContent)
	resp, err := s.client.Do(req, readme)
	if err != nil {
		return nil, resp, err
	}
	return readme, resp, err
}

// DownloadContents returns an io.ReadCloser that reads the contents of the
// specified file. This function will work with files of any size, as opposed
// to GetContents which is limited to 1 Mb files. It is the caller's
// responsibility to close the ReadCloser.
func (s *RepositoriesService) DownloadContents(owner, repo, filepath string, opt *RepositoryContentGetOptions) (io.ReadCloser, error) {
	dir := path.Dir(filepath)
	filename := path.Base(filepath)
	_, dirContents, _, err := s.GetContents(owner, repo, dir, opt)
	if err != nil {
		return nil, err
	}
	for _, contents := range dirContents {
		if *contents.Name == filename {
			if contents.DownloadURL == nil || *contents.DownloadURL == "" {
				return nil, fmt.Errorf("No download link found for %s", filepath)
			}
			resp, err := s.client.client.Get(*contents.DownloadURL)
			if err != nil {
				return nil, err
			}
			return resp.Body, nil
		}
	}
	return nil, fmt.Errorf("No file named %s found in %s", filename, dir)
}

// GetContents can return either the metadata and content of a single file
// (when path references a file) or the metadata of all the files and/or
// subdirectories of a directory (when path references a directory). To make it
// easy to distinguish between both result types and to mimic the API as much
// as possible, both result types will be returned but only one will contain a
// value and the other will be nil.
//
// GitHub API docs: http://developer.github.com/v3/repos/contents/#get-contents
func (s *RepositoriesService) GetContents(owner, repo, path string, opt *RepositoryContentGetOptions) (fileContent *RepositoryContent, directoryContent []*RepositoryContent, resp *Response, err error) {
	escapedPath := (&url.URL{Path: path}).String()
	u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, escapedPath)
	u, err = addOptions(u, opt)
	if err != nil {
		return nil, nil, nil, err
	}
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, nil, err
	}
	var rawJSON json.RawMessage
	resp, err = s.client.Do(req, &rawJSON)
	if err != nil {
		return nil, nil, resp, err
	}
	fileUnmarshalError := json.Unmarshal(rawJSON, &fileContent)
	if fileUnmarshalError == nil {
		return fileContent, nil, resp, fileUnmarshalError
	}
	directoryUnmarshalError := json.Unmarshal(rawJSON, &directoryContent)
	if directoryUnmarshalError == nil {
		return nil, directoryContent, resp, directoryUnmarshalError
	}
	return nil, nil, resp, fmt.Errorf("unmarshalling failed for both file and directory content: %s and %s ", fileUnmarshalError, directoryUnmarshalError)
}

// CreateFile creates a new file in a repository at the given path and returns
// the commit and file metadata.
//
// GitHub API docs: http://developer.github.com/v3/repos/contents/#create-a-file
func (s *RepositoriesService) CreateFile(owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) {
	u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path)
	req, err := s.client.NewRequest("PUT", u, opt)
	if err != nil {
		return nil, nil, err
	}
	createResponse := new(RepositoryContentResponse)
	resp, err := s.client.Do(req, createResponse)
	if err != nil {
		return nil, resp, err
	}
	return createResponse, resp, err
}

// UpdateFile updates a file in a repository at the given path and returns the
// commit and file metadata. Requires the blob SHA of the file being updated.
//
// GitHub API docs: http://developer.github.com/v3/repos/contents/#update-a-file
func (s *RepositoriesService) UpdateFile(owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) {
	u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path)
	req, err := s.client.NewRequest("PUT", u, opt)
	if err != nil {
		return nil, nil, err
	}
	updateResponse := new(RepositoryContentResponse)
	resp, err := s.client.Do(req, updateResponse)
	if err != nil {
		return nil, resp, err
	}
	return updateResponse, resp, err
}

// DeleteFile deletes a file from a repository and returns the commit.
// Requires the blob SHA of the file to be deleted.
//
// GitHub API docs: http://developer.github.com/v3/repos/contents/#delete-a-file
func (s *RepositoriesService) DeleteFile(owner, repo, path string, opt *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) {
	u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path)
	req, err := s.client.NewRequest("DELETE", u, opt)
	if err != nil {
		return nil, nil, err
	}
	deleteResponse := new(RepositoryContentResponse)
	resp, err := s.client.Do(req, deleteResponse)
	if err != nil {
		return nil, resp, err
	}
	return deleteResponse, resp, err
}

// archiveFormat is used to define the archive type when calling GetArchiveLink.
type archiveFormat string

const (
	// Tarball specifies an archive in gzipped tar format.
	Tarball archiveFormat = "tarball"

	// Zipball specifies an archive in zip format.
	Zipball archiveFormat = "zipball"
)

// GetArchiveLink returns an URL to download a tarball or zipball archive for a
// repository. The archiveFormat can be specified by either the github.Tarball
// or github.Zipball constant.
//
// GitHub API docs: http://developer.github.com/v3/repos/contents/#get-archive-link
func (s *RepositoriesService) GetArchiveLink(owner, repo string, archiveformat archiveFormat, opt *RepositoryContentGetOptions) (*url.URL, *Response, error) {
	u := fmt.Sprintf("repos/%s/%s/%s", owner, repo, archiveformat)
	if opt != nil && opt.Ref != "" {
		u += fmt.Sprintf("/%s", opt.Ref)
	}
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}
	var resp *http.Response
	// Use http.DefaultTransport if no custom Transport is configured
	if s.client.client.Transport == nil {
		resp, err = http.DefaultTransport.RoundTrip(req)
	} else {
		resp, err = s.client.client.Transport.RoundTrip(req)
	}
	if err != nil {
		return nil, nil, err
	}
	resp.Body.Close()
	if resp.StatusCode != http.StatusFound {
		return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status)
	}
	parsedURL, err := url.Parse(resp.Header.Get("Location"))
	return parsedURL, newResponse(resp), err
}
<|endoftext|>


<commit_before>package x86_64

import (
	"github.com/lunixbochs/ghostrace/ghost/sys/num"
	uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"

	"github.com/lunixbochs/usercorn/go/models"
	"github.com/lunixbochs/usercorn/go/syscalls"
)

func DarwinInit(u models.Usercorn, args, env []string) error {
	exe := u.Exe()
	addr, err := u.PushBytes([]byte(exe + "\x00"))
	if err != nil {
		return err
	}
	var tmp [16]byte
	_, err = u.PackAddr(tmp[8:], addr)
	if err != nil {
		return err
	}
	err = AbiInit(u, args, env, tmp[:], DarwinSyscall)
	if err != nil {
		return err
	}
	// offset to exe[0:] in guest memory
	textOffset, _, _ := u.Loader().Header()
	offset := u.Base() + textOffset
	_, err = u.Push(offset)
	return err
}

func mach_vm_allocate(u syscalls.U, a []uint64) uint64 {
	addr, err := u.Mmap(0, a[2])
	if err != nil {
		return syscalls.UINT64_MAX // FIXME
	}
	var tmp [8]byte
	buf, _ := u.PackAddr(tmp[:], addr)
	if err := u.MemWrite(a[1], buf); err != nil {
		return syscalls.UINT64_MAX // FIXME
	}
	return 0
}

func mach_vm_deallocate(u syscalls.U, a []uint64) uint64 {
	return 0
}

func task_self_trap(u syscalls.U, a []uint64) uint64 {
	return 1
}

func mach_reply_port(u syscalls.U, a []uint64) uint64 {
	return 1
}

func thread_selfid(u syscalls.U, a []uint64) uint64 {
	return 1
}

func thread_fast_set_cthread_self(u syscalls.U, a []uint64) uint64 {
	return 0
}

var darwinOverrides = map[string]*syscalls.Syscall{
	"task_self_trap":                    {task_self_trap, A{}, INT},
	"mach_reply_port":                   {mach_reply_port, A{}, INT},
	"__thread_selfid":                   {thread_selfid, A{}, INT},
	"kernelrpc_mach_vm_allocate_trap":   {mach_vm_allocate, A{INT, INT, INT, INT}, INT},
	"kernelrpc_mach_vm_deallocate_trap": {mach_vm_deallocate, A{INT, INT, INT}, INT},
	"thread_fast_set_cthread_self":      {thread_fast_set_cthread_self, A{}, INT},
}

func DarwinSyscall(u models.Usercorn) {
	rax, _ := u.RegRead(uc.X86_REG_RAX)
	name, _ := num.Darwin_x86_mach[int(rax)]
	override, _ := darwinOverrides[name]
	ret, _ := u.Syscall(int(rax), name, syscalls.RegArgs(u, AbiRegs), override)
	u.RegWrite(uc.X86_REG_RAX, ret)
}

func DarwinInterrupt(u models.Usercorn, intno uint32) {
	if intno == 0x80 {
		DarwinSyscall(u)
	}
}

func init() {
	Arch.RegisterOS(&models.OS{Name: "darwin", Init: DarwinInit, Interrupt: DarwinInterrupt})
}
<commit_msg>fix apple[0] location<commit_after>package x86_64

import (
	"github.com/lunixbochs/ghostrace/ghost/sys/num"
	uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"

	"github.com/lunixbochs/usercorn/go/models"
	"github.com/lunixbochs/usercorn/go/syscalls"
)

func DarwinInit(u models.Usercorn, args, env []string) error {
	exe := u.Exe()
	addr, err := u.PushBytes([]byte(exe + "\x00"))
	if err != nil {
		return err
	}
	var tmp [8]byte
	auxv, err := u.PackAddr(tmp[:], addr)
	if err != nil {
		return err
	}
	err = AbiInit(u, args, env, auxv, DarwinSyscall)
	if err != nil {
		return err
	}
	// offset to mach_header at exe[0:] in guest memory
	textOffset, _, _ := u.Loader().Header()
	offset := u.Base() + textOffset
	_, err = u.Push(offset)
	return err
}

func mach_vm_allocate(u syscalls.U, a []uint64) uint64 {
	addr, err := u.Mmap(0, a[2])
	if err != nil {
		return syscalls.UINT64_MAX // FIXME
	}
	var tmp [8]byte
	buf, _ := u.PackAddr(tmp[:], addr)
	if err := u.MemWrite(a[1], buf); err != nil {
		return syscalls.UINT64_MAX // FIXME
	}
	return 0
}

func mach_vm_deallocate(u syscalls.U, a []uint64) uint64 {
	return 0
}

func task_self_trap(u syscalls.U, a []uint64) uint64 {
	return 1
}

func mach_reply_port(u syscalls.U, a []uint64) uint64 {
	return 1
}

func thread_selfid(u syscalls.U, a []uint64) uint64 {
	return 1
}

func thread_fast_set_cthread_self(u syscalls.U, a []uint64) uint64 {
	return 0
}

var darwinOverrides = map[string]*syscalls.Syscall{
	"task_self_trap":                    {task_self_trap, A{}, INT},
	"mach_reply_port":                   {mach_reply_port, A{}, INT},
	"__thread_selfid":                   {thread_selfid, A{}, INT},
	"kernelrpc_mach_vm_allocate_trap":   {mach_vm_allocate, A{INT, INT, INT, INT}, INT},
	"kernelrpc_mach_vm_deallocate_trap": {mach_vm_deallocate, A{INT, INT, INT}, INT},
	"thread_fast_set_cthread_self":      {thread_fast_set_cthread_self, A{}, INT},
}

func DarwinSyscall(u models.Usercorn) {
	rax, _ := u.RegRead(uc.X86_REG_RAX)
	name, _ := num.Darwin_x86_mach[int(rax)]
	override, _ := darwinOverrides[name]
	ret, _ := u.Syscall(int(rax), name, syscalls.RegArgs(u, AbiRegs), override)
	u.RegWrite(uc.X86_REG_RAX, ret)
}

func DarwinInterrupt(u models.Usercorn, intno uint32) {
	if intno == 0x80 {
		DarwinSyscall(u)
	}
}

func init() {
	Arch.RegisterOS(&models.OS{Name: "darwin", Init: DarwinInit, Interrupt: DarwinInterrupt})
}
<|endoftext|>


<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package client

import (
	"fmt"

	"golang.org/x/net/context"

	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol"
)

type SaltPackUI struct {
	libkb.Contextified
	terminal    libkb.TerminalUI
	interactive bool
	force       bool
}

func (s *SaltPackUI) doNonInteractive(arg keybase1.SaltPackPromptForDecryptArg) error {
	switch arg.Sender.SenderType {
	case keybase1.SaltPackSenderType_TRACKING_BROKE:
		if s.force {
			s.G().Log.Warning("Tracking statement is broken for sender, but forcing through.")
			return nil
		}
		return libkb.IdentifyFailedError{Assertion: arg.Sender.Username, Reason: "tracking broke"}
	default:
		return nil
	}
}

func (s *SaltPackUI) doInteractive(arg keybase1.SaltPackPromptForDecryptArg) error {
	var why string
	def := libkb.PromptDefaultYes
	switch arg.Sender.SenderType {
	case keybase1.SaltPackSenderType_TRACKING_OK:
		return nil
	case keybase1.SaltPackSenderType_NOT_TRACKED:
		why = "The sender of this message is a Keybase user you don't track"
	case keybase1.SaltPackSenderType_UNKNOWN:
		why = "The sender of this message is unknown to Keybase"
	case keybase1.SaltPackSenderType_ANONYMOUS:
		why = "The sender of this message has choosen to remain anonymous"
	case keybase1.SaltPackSenderType_TRACKING_BROKE:
		why = "You track the sender of this message, but their tracking statement is broken"
		def = libkb.PromptDefaultNo
	}
	why += ". Go ahead and decrypt?"
	ok, err := s.terminal.PromptYesNo(PromptDescriptorDecryptInteractive, why, def)
	if err != nil {
		return err
	}
	if !ok {
		return libkb.CanceledError{M: "decryption canceled"}
	}

	return nil
}

func (s *SaltPackUI) SaltPackPromptForDecrypt(_ context.Context, arg keybase1.SaltPackPromptForDecryptArg) (err error) {
	if !s.interactive {
		return s.doNonInteractive(arg)
	}
	return s.doInteractive(arg)
}

func (s *SaltPackUI) SaltPackSignatureSuccess(_ context.Context, arg keybase1.SaltPackSignatureSuccessArg) error {
	var un string
	if arg.Sender.SenderType == keybase1.SaltPackSenderType_UNKNOWN {
		un = "The signer of this message is unknown to Keybase"
	} else {
		un = fmt.Sprintf("Signed by %s", ColorString("bold", arg.Sender.Username))
	}
	s.terminal.Printf(ColorString("green", fmt.Sprintf("Signature verified. %s.\n", un)))
	s.terminal.Printf(ColorString("green", fmt.Sprintf("Signing key ID: %x.\n", arg.SigningKID.ToShortIDString())))

	return nil
}
<commit_msg>Display signing KID only if sender unknown<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package client

import (
	"fmt"

	"golang.org/x/net/context"

	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol"
)

type SaltPackUI struct {
	libkb.Contextified
	terminal    libkb.TerminalUI
	interactive bool
	force       bool
}

func (s *SaltPackUI) doNonInteractive(arg keybase1.SaltPackPromptForDecryptArg) error {
	switch arg.Sender.SenderType {
	case keybase1.SaltPackSenderType_TRACKING_BROKE:
		if s.force {
			s.G().Log.Warning("Tracking statement is broken for sender, but forcing through.")
			return nil
		}
		return libkb.IdentifyFailedError{Assertion: arg.Sender.Username, Reason: "tracking broke"}
	default:
		return nil
	}
}

func (s *SaltPackUI) doInteractive(arg keybase1.SaltPackPromptForDecryptArg) error {
	var why string
	def := libkb.PromptDefaultYes
	switch arg.Sender.SenderType {
	case keybase1.SaltPackSenderType_TRACKING_OK:
		return nil
	case keybase1.SaltPackSenderType_NOT_TRACKED:
		why = "The sender of this message is a Keybase user you don't track"
	case keybase1.SaltPackSenderType_UNKNOWN:
		why = "The sender of this message is unknown to Keybase"
	case keybase1.SaltPackSenderType_ANONYMOUS:
		why = "The sender of this message has choosen to remain anonymous"
	case keybase1.SaltPackSenderType_TRACKING_BROKE:
		why = "You track the sender of this message, but their tracking statement is broken"
		def = libkb.PromptDefaultNo
	}
	why += ". Go ahead and decrypt?"
	ok, err := s.terminal.PromptYesNo(PromptDescriptorDecryptInteractive, why, def)
	if err != nil {
		return err
	}
	if !ok {
		return libkb.CanceledError{M: "decryption canceled"}
	}

	return nil
}

func (s *SaltPackUI) SaltPackPromptForDecrypt(_ context.Context, arg keybase1.SaltPackPromptForDecryptArg) (err error) {
	if !s.interactive {
		return s.doNonInteractive(arg)
	}
	return s.doInteractive(arg)
}

func (s *SaltPackUI) SaltPackSignatureSuccess(_ context.Context, arg keybase1.SaltPackSignatureSuccessArg) error {
	var un string
	if arg.Sender.SenderType == keybase1.SaltPackSenderType_UNKNOWN {
		un = "The signer of this message is unknown to Keybase"
	} else {
		un = fmt.Sprintf("Signed by %s", ColorString("bold", arg.Sender.Username))
	}
	s.terminal.Printf(ColorString("green", fmt.Sprintf("Signature verified. %s.\n", un)))
	if arg.Sender.SenderType == keybase1.SaltPackSenderType_UNKNOWN {
		s.terminal.Printf(ColorString("green", fmt.Sprintf("Signing key ID: %x.\n", arg.SigningKID.ToShortIDString())))
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package engine

import (
	"crypto/rand"
	"encoding/hex"
	"errors"
	"fmt"
	"testing"

	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol"
	insecureTriplesec "github.com/keybase/go-triplesec-insecure"
)

func SetupEngineTest(tb testing.TB, name string) libkb.TestContext {
	tc := libkb.SetupTest(tb, name, 2)
	tc.G.NewTriplesec = func(passphrase []byte, salt []byte) (libkb.Triplesec, error) {
		warner := func() { tc.G.Log.Warning("Installing insecure Triplesec with weak stretch parameters") }
		isProduction := func() bool {
			runMode, err := tc.G.Env.GetRunMode()
			return err != nil || runMode == libkb.ProductionRunMode
		}
		return insecureTriplesec.NewCipher(passphrase, salt, warner, isProduction)
	}
	return tc
}

func SetupEngineTestRealTriplesec(tb testing.TB, name string) libkb.TestContext {
	tc := libkb.SetupTest(tb, name, 2)
	tc.G.NewTriplesec = libkb.NewSecureTriplesec
	return tc
}

type FakeUser struct {
	Username      string
	Email         string
	Passphrase    string
	User          *libkb.User
	EncryptionKey libkb.GenericKey
}

func NewFakeUser(prefix string) (fu *FakeUser, err error) {
	buf := make([]byte, 5)
	if _, err = rand.Read(buf); err != nil {
		return
	}
	username := fmt.Sprintf("%s_%s", prefix, hex.EncodeToString(buf))
	email := fmt.Sprintf("%s@noemail.keybase.io", username)
	buf = make([]byte, 12)
	if _, err = rand.Read(buf); err != nil {
		return
	}
	passphrase := hex.EncodeToString(buf)
	fu = &FakeUser{Username: username, Email: email, Passphrase: passphrase}
	return
}

func (fu FakeUser) NormalizedUsername() libkb.NormalizedUsername {
	return libkb.NewNormalizedUsername(fu.Username)
}

func NewFakeUserOrBust(tb testing.TB, prefix string) (fu *FakeUser) {
	var err error
	if fu, err = NewFakeUser(prefix); err != nil {
		tb.Fatal(err)
	}
	return fu
}

const defaultDeviceName = "my device"

// MakeTestSignupEngineRunArg fills a SignupEngineRunArg with the most
// common parameters for testing and returns it.
func MakeTestSignupEngineRunArg(fu *FakeUser) SignupEngineRunArg {
	return SignupEngineRunArg{
		Username:    fu.Username,
		Email:       fu.Email,
		InviteCode:  libkb.TestInvitationCode,
		Passphrase:  fu.Passphrase,
		StoreSecret: false,
		DeviceName:  defaultDeviceName,
		SkipGPG:     true,
		SkipMail:    true,
	}
}

func SignupFakeUserWithArg(tc libkb.TestContext, fu *FakeUser, arg SignupEngineRunArg) *SignupEngine {
	ctx := &Context{
		LogUI:    tc.G.UI.GetLogUI(),
		GPGUI:    &gpgtestui{},
		SecretUI: fu.NewSecretUI(),
		LoginUI:  &libkb.TestLoginUI{Username: fu.Username},
	}
	s := NewSignupEngine(&arg, tc.G)
	err := RunEngine(s, ctx)
	if err != nil {
		tc.T.Fatal(err)
	}
	fu.EncryptionKey = s.encryptionKey
	return s
}

func CreateAndSignupFakeUser(tc libkb.TestContext, prefix string) *FakeUser {
	fu := NewFakeUserOrBust(tc.T, prefix)
	tc.G.Log.Debug("New test user: %s / %s", fu.Username, fu.Email)
	arg := MakeTestSignupEngineRunArg(fu)
	_ = SignupFakeUserWithArg(tc, fu, arg)
	return fu
}

func CreateAndSignupFakeUserSafe(g *libkb.GlobalContext, prefix string) (*FakeUser, error) {
	fu, err := NewFakeUser(prefix)
	if err != nil {
		return nil, err
	}

	arg := MakeTestSignupEngineRunArg(fu)
	ctx := &Context{
		LogUI:    g.UI.GetLogUI(),
		GPGUI:    &gpgtestui{},
		SecretUI: fu.NewSecretUI(),
		LoginUI:  &libkb.TestLoginUI{Username: fu.Username},
	}
	s := NewSignupEngine(&arg, g)
	err = RunEngine(s, ctx)
	if err != nil {
		return nil, err
	}
	return fu, nil
}

func CreateAndSignupFakeUserGPG(tc libkb.TestContext, prefix string) *FakeUser {
	fu := NewFakeUserOrBust(tc.T, prefix)
	if err := tc.GenerateGPGKeyring(fu.Email); err != nil {
		tc.T.Fatal(err)
	}
	arg := MakeTestSignupEngineRunArg(fu)
	arg.SkipGPG = false
	ctx := &Context{
		LogUI:    tc.G.UI.GetLogUI(),
		GPGUI:    &gpgtestui{},
		SecretUI: fu.NewSecretUI(),
		LoginUI:  &libkb.TestLoginUI{Username: fu.Username},
	}
	s := NewSignupEngine(&arg, tc.G)
	err := RunEngine(s, ctx)
	if err != nil {
		tc.T.Fatal(err)
	}
	return fu
}

func CreateAndSignupFakeUserCustomArg(tc libkb.TestContext, prefix string, fmod func(*SignupEngineRunArg)) (*FakeUser, libkb.GenericKey) {
	fu := NewFakeUserOrBust(tc.T, prefix)
	arg := MakeTestSignupEngineRunArg(fu)
	fmod(&arg)
	ctx := &Context{
		LogUI:    tc.G.UI.GetLogUI(),
		GPGUI:    &gpgtestui{},
		SecretUI: fu.NewSecretUI(),
		LoginUI:  &libkb.TestLoginUI{Username: fu.Username},
	}
	s := NewSignupEngine(&arg, tc.G)
	err := RunEngine(s, ctx)
	if err != nil {
		tc.T.Fatal(err)
	}
	return fu, s.signingKey
}

func (fu *FakeUser) LoginWithSecretUI(secui libkb.SecretUI, g *libkb.GlobalContext) error {
	ctx := &Context{
		ProvisionUI: newTestProvisionUI(),
		LogUI:       g.UI.GetLogUI(),
		GPGUI:       &gpgtestui{},
		SecretUI:    secui,
		LoginUI:     &libkb.TestLoginUI{Username: fu.Username},
	}
	li := NewLogin(g, libkb.DeviceTypeDesktop, fu.Username, keybase1.ClientType_CLI)
	return RunEngine(li, ctx)
}

func (fu *FakeUser) Login(g *libkb.GlobalContext) error {
	s := fu.NewSecretUI()
	return fu.LoginWithSecretUI(s, g)
}

func (fu *FakeUser) LoginOrBust(tc libkb.TestContext) {
	if err := fu.Login(tc.G); err != nil {
		tc.T.Fatal(err)
	}
}

func (fu *FakeUser) NewSecretUI() *libkb.TestSecretUI {
	return &libkb.TestSecretUI{Passphrase: fu.Passphrase}
}

func AssertProvisioned(tc libkb.TestContext) error {
	prov, err := tc.G.LoginState().LoggedInProvisionedLoad()
	if err != nil {
		return err
	}
	if !prov {
		return libkb.LoginRequiredError{}
	}
	return nil
}

func AssertNotProvisioned(tc libkb.TestContext) error {
	prov, err := tc.G.LoginState().LoggedInProvisionedLoad()
	if err != nil {
		return err
	}
	if prov {
		return errors.New("AssertNotProvisioned failed:  user is provisioned")
	}
	return nil
}

func AssertLoggedIn(tc libkb.TestContext) error {
	if !LoggedIn(tc) {
		return libkb.LoginRequiredError{}
	}
	return nil
}

func AssertLoggedOut(tc libkb.TestContext) error {
	if LoggedIn(tc) {
		return libkb.LogoutError{}
	}
	return nil
}

func LoggedIn(tc libkb.TestContext) bool {
	lin, _ := tc.G.LoginState().LoggedInLoad()
	return lin
}

func Logout(tc libkb.TestContext) {
	if err := tc.G.Logout(); err != nil {
		tc.T.Fatalf("logout error: %s", err)
	}
}

// TODO: Add tests that use testEngineWithSecretStore for every engine
// that should work with the secret store.

// testEngineWithSecretStore takes a given engine-running function and
// makes sure that it works with the secret store, i.e. that it stores
// data into it when told to and reads data out from it.
func testEngineWithSecretStore(
	t *testing.T,
	runEngine func(libkb.TestContext, *FakeUser, libkb.SecretUI)) {

	tc := SetupEngineTest(t, "wss")
	defer tc.Cleanup()

	fu := CreateAndSignupFakeUser(tc, "wss")
	tc.ResetLoginState()

	testSecretUI := libkb.TestSecretUI{
		Passphrase:  fu.Passphrase,
		StoreSecret: true,
	}
	runEngine(tc, fu, &testSecretUI)

	if !testSecretUI.CalledGetPassphrase {
		t.Fatal("GetPassphrase() unexpectedly not called")
	}

	tc.ResetLoginState()

	testSecretUI = libkb.TestSecretUI{}
	runEngine(tc, fu, &testSecretUI)

	if testSecretUI.CalledGetPassphrase {
		t.Fatal("GetPassphrase() unexpectedly called")
	}
}

func SetupTwoDevices(t *testing.T, nm string) (user *FakeUser, dev1 libkb.TestContext, dev2 libkb.TestContext, cleanup func()) {

	if len(nm) > 5 {
		t.Fatalf("Sorry, test name must be fewer than 6 chars (got %q)", nm)
	}

	// device X (provisioner) context:
	dev1 = SetupEngineTest(t, nm)

	// device Y (provisionee) context:
	dev2 = SetupEngineTest(t, nm)

	user = NewFakeUserOrBust(t, nm)
	arg := MakeTestSignupEngineRunArg(user)
	loginUI := &paperLoginUI{Username: user.Username}
	ctx := &Context{
		LogUI:    dev1.G.UI.GetLogUI(),
		GPGUI:    &gpgtestui{},
		SecretUI: user.NewSecretUI(),
		LoginUI:  loginUI,
	}
	s := NewSignupEngine(&arg, dev1.G)
	err := RunEngine(s, ctx)
	if err != nil {
		t.Fatal(err)
	}

	assertNumDevicesAndKeys(dev1, user, 2, 4)

	if len(loginUI.PaperPhrase) == 0 {
		t.Fatal("login ui has no paper key phrase")
	}

	secUI := user.NewSecretUI()
	secUI.Passphrase = loginUI.PaperPhrase
	provUI := newTestProvisionUIPaper()
	provLoginUI := &libkb.TestLoginUI{Username: user.Username}
	ctx = &Context{
		ProvisionUI: provUI,
		LogUI:       dev2.G.UI.GetLogUI(),
		SecretUI:    secUI,
		LoginUI:     provLoginUI,
		GPGUI:       &gpgtestui{},
	}
	eng := NewLogin(dev2.G, libkb.DeviceTypeDesktop, "", keybase1.ClientType_CLI)
	if err := RunEngine(eng, ctx); err != nil {
		t.Fatal(err)
	}

	testUserHasDeviceKey(dev2)

	assertNumDevicesAndKeys(dev2, user, 3, 6)

	if err := AssertProvisioned(dev2); err != nil {
		t.Fatal(err)
	}

	cleanup = func() {
		dev1.Cleanup()
		dev2.Cleanup()
	}

	return user, dev1, dev2, cleanup
}

func ResetAccount(tc libkb.TestContext, u *FakeUser) {
	pps, err := tc.G.LoginState().GetPassphraseStreamWithPassphrase(u.Passphrase)
	if err != nil {
		tc.T.Fatal(err)
	}
	arg := libkb.APIArg{
		Endpoint:    "nuke",
		NeedSession: true,
		Args: libkb.HTTPArgs{
			"pwh": libkb.HexArg(pps.PWHash()),
		},
	}
	res, err := tc.G.API.Post(arg)
	if err != nil {
		tc.T.Fatal(err)
	}
	tc.T.Logf("nuke api result: %+v", res)
	Logout(tc)
}
<commit_msg>triple-seatbelts<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package engine

import (
	"crypto/rand"
	"encoding/hex"
	"errors"
	"fmt"
	"testing"

	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol"
	insecureTriplesec "github.com/keybase/go-triplesec-insecure"
)

func SetupEngineTest(tb testing.TB, name string) libkb.TestContext {
	tc := libkb.SetupTest(tb, name, 2)
	tc.G.NewTriplesec = func(passphrase []byte, salt []byte) (libkb.Triplesec, error) {
		warner := func() { tc.G.Log.Warning("Installing insecure Triplesec with weak stretch parameters") }
		isProduction := func() bool {
			return tc.G.Env.GetRunMode() == libkb.ProductionRunMode
		}
		return insecureTriplesec.NewCipher(passphrase, salt, warner, isProduction)
	}
	return tc
}

func SetupEngineTestRealTriplesec(tb testing.TB, name string) libkb.TestContext {
	tc := libkb.SetupTest(tb, name, 2)
	tc.G.NewTriplesec = libkb.NewSecureTriplesec
	return tc
}

type FakeUser struct {
	Username      string
	Email         string
	Passphrase    string
	User          *libkb.User
	EncryptionKey libkb.GenericKey
}

func NewFakeUser(prefix string) (fu *FakeUser, err error) {
	buf := make([]byte, 5)
	if _, err = rand.Read(buf); err != nil {
		return
	}
	username := fmt.Sprintf("%s_%s", prefix, hex.EncodeToString(buf))
	email := fmt.Sprintf("%s@noemail.keybase.io", username)
	buf = make([]byte, 12)
	if _, err = rand.Read(buf); err != nil {
		return
	}
	passphrase := hex.EncodeToString(buf)
	fu = &FakeUser{Username: username, Email: email, Passphrase: passphrase}
	return
}

func (fu FakeUser) NormalizedUsername() libkb.NormalizedUsername {
	return libkb.NewNormalizedUsername(fu.Username)
}

func NewFakeUserOrBust(tb testing.TB, prefix string) (fu *FakeUser) {
	var err error
	if fu, err = NewFakeUser(prefix); err != nil {
		tb.Fatal(err)
	}
	return fu
}

const defaultDeviceName = "my device"

// MakeTestSignupEngineRunArg fills a SignupEngineRunArg with the most
// common parameters for testing and returns it.
func MakeTestSignupEngineRunArg(fu *FakeUser) SignupEngineRunArg {
	return SignupEngineRunArg{
		Username:    fu.Username,
		Email:       fu.Email,
		InviteCode:  libkb.TestInvitationCode,
		Passphrase:  fu.Passphrase,
		StoreSecret: false,
		DeviceName:  defaultDeviceName,
		SkipGPG:     true,
		SkipMail:    true,
	}
}

func SignupFakeUserWithArg(tc libkb.TestContext, fu *FakeUser, arg SignupEngineRunArg) *SignupEngine {
	ctx := &Context{
		LogUI:    tc.G.UI.GetLogUI(),
		GPGUI:    &gpgtestui{},
		SecretUI: fu.NewSecretUI(),
		LoginUI:  &libkb.TestLoginUI{Username: fu.Username},
	}
	s := NewSignupEngine(&arg, tc.G)
	err := RunEngine(s, ctx)
	if err != nil {
		tc.T.Fatal(err)
	}
	fu.EncryptionKey = s.encryptionKey
	return s
}

func CreateAndSignupFakeUser(tc libkb.TestContext, prefix string) *FakeUser {
	fu := NewFakeUserOrBust(tc.T, prefix)
	tc.G.Log.Debug("New test user: %s / %s", fu.Username, fu.Email)
	arg := MakeTestSignupEngineRunArg(fu)
	_ = SignupFakeUserWithArg(tc, fu, arg)
	return fu
}

func CreateAndSignupFakeUserSafe(g *libkb.GlobalContext, prefix string) (*FakeUser, error) {
	fu, err := NewFakeUser(prefix)
	if err != nil {
		return nil, err
	}

	arg := MakeTestSignupEngineRunArg(fu)
	ctx := &Context{
		LogUI:    g.UI.GetLogUI(),
		GPGUI:    &gpgtestui{},
		SecretUI: fu.NewSecretUI(),
		LoginUI:  &libkb.TestLoginUI{Username: fu.Username},
	}
	s := NewSignupEngine(&arg, g)
	err = RunEngine(s, ctx)
	if err != nil {
		return nil, err
	}
	return fu, nil
}

func CreateAndSignupFakeUserGPG(tc libkb.TestContext, prefix string) *FakeUser {
	fu := NewFakeUserOrBust(tc.T, prefix)
	if err := tc.GenerateGPGKeyring(fu.Email); err != nil {
		tc.T.Fatal(err)
	}
	arg := MakeTestSignupEngineRunArg(fu)
	arg.SkipGPG = false
	ctx := &Context{
		LogUI:    tc.G.UI.GetLogUI(),
		GPGUI:    &gpgtestui{},
		SecretUI: fu.NewSecretUI(),
		LoginUI:  &libkb.TestLoginUI{Username: fu.Username},
	}
	s := NewSignupEngine(&arg, tc.G)
	err := RunEngine(s, ctx)
	if err != nil {
		tc.T.Fatal(err)
	}
	return fu
}

func CreateAndSignupFakeUserCustomArg(tc libkb.TestContext, prefix string, fmod func(*SignupEngineRunArg)) (*FakeUser, libkb.GenericKey) {
	fu := NewFakeUserOrBust(tc.T, prefix)
	arg := MakeTestSignupEngineRunArg(fu)
	fmod(&arg)
	ctx := &Context{
		LogUI:    tc.G.UI.GetLogUI(),
		GPGUI:    &gpgtestui{},
		SecretUI: fu.NewSecretUI(),
		LoginUI:  &libkb.TestLoginUI{Username: fu.Username},
	}
	s := NewSignupEngine(&arg, tc.G)
	err := RunEngine(s, ctx)
	if err != nil {
		tc.T.Fatal(err)
	}
	return fu, s.signingKey
}

func (fu *FakeUser) LoginWithSecretUI(secui libkb.SecretUI, g *libkb.GlobalContext) error {
	ctx := &Context{
		ProvisionUI: newTestProvisionUI(),
		LogUI:       g.UI.GetLogUI(),
		GPGUI:       &gpgtestui{},
		SecretUI:    secui,
		LoginUI:     &libkb.TestLoginUI{Username: fu.Username},
	}
	li := NewLogin(g, libkb.DeviceTypeDesktop, fu.Username, keybase1.ClientType_CLI)
	return RunEngine(li, ctx)
}

func (fu *FakeUser) Login(g *libkb.GlobalContext) error {
	s := fu.NewSecretUI()
	return fu.LoginWithSecretUI(s, g)
}

func (fu *FakeUser) LoginOrBust(tc libkb.TestContext) {
	if err := fu.Login(tc.G); err != nil {
		tc.T.Fatal(err)
	}
}

func (fu *FakeUser) NewSecretUI() *libkb.TestSecretUI {
	return &libkb.TestSecretUI{Passphrase: fu.Passphrase}
}

func AssertProvisioned(tc libkb.TestContext) error {
	prov, err := tc.G.LoginState().LoggedInProvisionedLoad()
	if err != nil {
		return err
	}
	if !prov {
		return libkb.LoginRequiredError{}
	}
	return nil
}

func AssertNotProvisioned(tc libkb.TestContext) error {
	prov, err := tc.G.LoginState().LoggedInProvisionedLoad()
	if err != nil {
		return err
	}
	if prov {
		return errors.New("AssertNotProvisioned failed:  user is provisioned")
	}
	return nil
}

func AssertLoggedIn(tc libkb.TestContext) error {
	if !LoggedIn(tc) {
		return libkb.LoginRequiredError{}
	}
	return nil
}

func AssertLoggedOut(tc libkb.TestContext) error {
	if LoggedIn(tc) {
		return libkb.LogoutError{}
	}
	return nil
}

func LoggedIn(tc libkb.TestContext) bool {
	lin, _ := tc.G.LoginState().LoggedInLoad()
	return lin
}

func Logout(tc libkb.TestContext) {
	if err := tc.G.Logout(); err != nil {
		tc.T.Fatalf("logout error: %s", err)
	}
}

// TODO: Add tests that use testEngineWithSecretStore for every engine
// that should work with the secret store.

// testEngineWithSecretStore takes a given engine-running function and
// makes sure that it works with the secret store, i.e. that it stores
// data into it when told to and reads data out from it.
func testEngineWithSecretStore(
	t *testing.T,
	runEngine func(libkb.TestContext, *FakeUser, libkb.SecretUI)) {

	tc := SetupEngineTest(t, "wss")
	defer tc.Cleanup()

	fu := CreateAndSignupFakeUser(tc, "wss")
	tc.ResetLoginState()

	testSecretUI := libkb.TestSecretUI{
		Passphrase:  fu.Passphrase,
		StoreSecret: true,
	}
	runEngine(tc, fu, &testSecretUI)

	if !testSecretUI.CalledGetPassphrase {
		t.Fatal("GetPassphrase() unexpectedly not called")
	}

	tc.ResetLoginState()

	testSecretUI = libkb.TestSecretUI{}
	runEngine(tc, fu, &testSecretUI)

	if testSecretUI.CalledGetPassphrase {
		t.Fatal("GetPassphrase() unexpectedly called")
	}
}

func SetupTwoDevices(t *testing.T, nm string) (user *FakeUser, dev1 libkb.TestContext, dev2 libkb.TestContext, cleanup func()) {

	if len(nm) > 5 {
		t.Fatalf("Sorry, test name must be fewer than 6 chars (got %q)", nm)
	}

	// device X (provisioner) context:
	dev1 = SetupEngineTest(t, nm)

	// device Y (provisionee) context:
	dev2 = SetupEngineTest(t, nm)

	user = NewFakeUserOrBust(t, nm)
	arg := MakeTestSignupEngineRunArg(user)
	loginUI := &paperLoginUI{Username: user.Username}
	ctx := &Context{
		LogUI:    dev1.G.UI.GetLogUI(),
		GPGUI:    &gpgtestui{},
		SecretUI: user.NewSecretUI(),
		LoginUI:  loginUI,
	}
	s := NewSignupEngine(&arg, dev1.G)
	err := RunEngine(s, ctx)
	if err != nil {
		t.Fatal(err)
	}

	assertNumDevicesAndKeys(dev1, user, 2, 4)

	if len(loginUI.PaperPhrase) == 0 {
		t.Fatal("login ui has no paper key phrase")
	}

	secUI := user.NewSecretUI()
	secUI.Passphrase = loginUI.PaperPhrase
	provUI := newTestProvisionUIPaper()
	provLoginUI := &libkb.TestLoginUI{Username: user.Username}
	ctx = &Context{
		ProvisionUI: provUI,
		LogUI:       dev2.G.UI.GetLogUI(),
		SecretUI:    secUI,
		LoginUI:     provLoginUI,
		GPGUI:       &gpgtestui{},
	}
	eng := NewLogin(dev2.G, libkb.DeviceTypeDesktop, "", keybase1.ClientType_CLI)
	if err := RunEngine(eng, ctx); err != nil {
		t.Fatal(err)
	}

	testUserHasDeviceKey(dev2)

	assertNumDevicesAndKeys(dev2, user, 3, 6)

	if err := AssertProvisioned(dev2); err != nil {
		t.Fatal(err)
	}

	cleanup = func() {
		dev1.Cleanup()
		dev2.Cleanup()
	}

	return user, dev1, dev2, cleanup
}

func ResetAccount(tc libkb.TestContext, u *FakeUser) {
	pps, err := tc.G.LoginState().GetPassphraseStreamWithPassphrase(u.Passphrase)
	if err != nil {
		tc.T.Fatal(err)
	}
	arg := libkb.APIArg{
		Endpoint:    "nuke",
		NeedSession: true,
		Args: libkb.HTTPArgs{
			"pwh": libkb.HexArg(pps.PWHash()),
		},
	}
	res, err := tc.G.API.Post(arg)
	if err != nil {
		tc.T.Fatal(err)
	}
	tc.T.Logf("nuke api result: %+v", res)
	Logout(tc)
}
<|endoftext|>


<commit_before>package teams

import (
	"testing"
	"time"

	"github.com/keybase/client/go/kbtest"

	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/stretchr/testify/require"

	"golang.org/x/net/context"
)

func TestAccessRequestAccept(t *testing.T) {
	tc, owner, u1, _, teamName := memberSetupMultiple(t)
	defer tc.Cleanup()

	// owner is logged in and created teamName
	err := tc.Logout()
	require.NoError(t, err)

	// u1 requests access to the team
	err = u1.Login(tc.G)
	require.NoError(t, err)
	_, err = RequestAccess(context.Background(), tc.G, teamName)
	require.NoError(t, err)

	myReqs, err := ListMyAccessRequests(context.Background(), tc.G, &teamName)
	require.NoError(t, err)
	require.Equal(t, 1, len(myReqs))
	require.Equal(t, teamName, myReqs[0].String())

	// teamName is optional, if not given, all pending requests will be returned.
	myReqs, err = ListMyAccessRequests(context.Background(), tc.G, nil)
	require.NoError(t, err)
	require.Equal(t, 1, len(myReqs))
	require.Equal(t, teamName, myReqs[0].String())

	// owner lists requests, sees u1 request
	err = tc.Logout()
	require.NoError(t, err)
	err = owner.Login(tc.G)
	require.NoError(t, err)

	reqs, err := ListRequests(context.Background(), tc.G, nil)
	require.NoError(t, err)
	require.Equal(t, 1, len(reqs))
	require.Equal(t, teamName, reqs[0].Name)
	require.Equal(t, u1.Username, reqs[0].Username)
	require.True(t, reqs[0].Ctime.Time().After(time.Now().Add(-1*time.Minute)))
	require.Equal(t, "", reqs[0].FullName.String()) // no fullname in this case

	// owner add u1 to team
	_, err = AddMember(context.Background(), tc.G, teamName, u1.Username, keybase1.TeamRole_WRITER, nil)
	require.NoError(t, err)

	// owner lists requests, sees no requests
	assertNoRequests(tc)

	// u1 requests access to the team again
	err = tc.Logout()
	require.NoError(t, err)
	err = u1.Login(tc.G)
	require.NoError(t, err)

	_, err = RequestAccess(context.Background(), tc.G, teamName)
	require.Error(t, err)
	aerr, ok := err.(libkb.AppStatusError)
	if !ok {
		t.Fatalf("error %s (%T), expected libkb.AppStatusError", err, err)
	}
	if aerr.Code != libkb.SCTeamMemberExists {
		t.Errorf("status code: %d, expected %d", aerr.Code, libkb.SCTeamMemberExists)
	}
	err = tc.Logout()
	require.NoError(t, err)

	// owner lists requests, sees no requests
	err = owner.Login(tc.G)
	require.NoError(t, err)
	assertNoRequests(tc)
}

func TestAccessRequestIgnore(t *testing.T) {
	tc, owner, u1, _, teamName := memberSetupMultiple(t)
	defer tc.Cleanup()

	// owner is logged in and created teamName
	err := tc.Logout()
	require.NoError(t, err)

	// u1 requests access to the team
	if err := u1.Login(tc.G); err != nil {
		t.Fatal(err)
	}
	if _, err := RequestAccess(context.Background(), tc.G, teamName); err != nil {
		t.Fatal(err)
	}
	fullName, err := libkb.RandString("test", 5)
	if err != nil {
		t.Fatal(err)
	}
	if err := kbtest.EditProfile(u1.User.MetaContext(context.Background()), keybase1.ProfileEditArg{
		FullName: fullName,
	}); err != nil {
		t.Fatal(err)
	}

	// owner lists requests, sees u1 request
	err = tc.Logout()
	require.NoError(t, err)
	if err := owner.Login(tc.G); err != nil {
		t.Fatal(err)
	}
	require.NoError(t, tc.G.UIDMapper.ClearUIDFullName(context.Background(), tc.G, u1.User.GetUID()))
	reqs, err := ListRequests(context.Background(), tc.G, nil)
	if err != nil {
		t.Fatal(err)
	}
	if len(reqs) != 1 {
		t.Fatalf("num requests: %d, expected 1", len(reqs))
	}
	if reqs[0].Name != teamName {
		t.Errorf("request team name: %q, expected %q", reqs[0].Name, teamName)
	}
	if reqs[0].Username != u1.Username {
		t.Errorf("request username: %q, expected %q", reqs[0].Username, u1.Username)
	}
	if !reqs[0].Ctime.Time().After(time.Now().Add(-1 * time.Minute)) {
		t.Errorf("request ctime %q, expected during last minute", reqs[0].Ctime)
	}
	if reqs[0].FullName.String() != fullName {
		t.Errorf("request full name %q, expected %q", reqs[0].FullName, fullName)
	}

	// owner ignores u1 request
	if err := IgnoreRequest(context.Background(), tc.G, reqs[0].Name, reqs[0].Username); err != nil {
		t.Fatal(err)
	}

	// owner lists requests, sees no requests
	assertNoRequests(tc)

	// u1 requests access to the team again
	err = tc.Logout()
	require.NoError(t, err)
	if err := u1.Login(tc.G); err != nil {
		t.Fatal(err)
	}
	_, err = RequestAccess(context.Background(), tc.G, teamName)
	if err == nil {
		t.Fatal("second RequestAccess success, expected error")
	}
	aerr, ok := err.(libkb.AppStatusError)
	if !ok {
		t.Fatalf("error %s (%T), expected libkb.AppStatusError", err, err)
	}
	if aerr.Code != libkb.SCTeamTarDuplicate {
		t.Errorf("status code: %d, expected %d", aerr.Code, libkb.SCTeamTarDuplicate)
	}
	err = tc.Logout()
	require.NoError(t, err)

	// owner lists requests, sees no requests
	if err := owner.Login(tc.G); err != nil {
		t.Fatal(err)
	}
	assertNoRequests(tc)
}

func assertNoRequests(tc libkb.TestContext) {
	reqs, err := ListRequests(context.Background(), tc.G, nil)
	if err != nil {
		tc.T.Fatal(err)
	}
	if len(reqs) != 0 {
		tc.T.Fatalf("num requests: %d, expected 0", len(reqs))
	}
}
<commit_msg>Skip TestAccessRequestIgnore<commit_after>package teams

import (
	"testing"
	"time"

	"github.com/keybase/client/go/kbtest"

	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/stretchr/testify/require"

	"golang.org/x/net/context"
)

func TestAccessRequestAccept(t *testing.T) {
	tc, owner, u1, _, teamName := memberSetupMultiple(t)
	defer tc.Cleanup()

	// owner is logged in and created teamName
	err := tc.Logout()
	require.NoError(t, err)

	// u1 requests access to the team
	err = u1.Login(tc.G)
	require.NoError(t, err)
	_, err = RequestAccess(context.Background(), tc.G, teamName)
	require.NoError(t, err)

	myReqs, err := ListMyAccessRequests(context.Background(), tc.G, &teamName)
	require.NoError(t, err)
	require.Equal(t, 1, len(myReqs))
	require.Equal(t, teamName, myReqs[0].String())

	// teamName is optional, if not given, all pending requests will be returned.
	myReqs, err = ListMyAccessRequests(context.Background(), tc.G, nil)
	require.NoError(t, err)
	require.Equal(t, 1, len(myReqs))
	require.Equal(t, teamName, myReqs[0].String())

	// owner lists requests, sees u1 request
	err = tc.Logout()
	require.NoError(t, err)
	err = owner.Login(tc.G)
	require.NoError(t, err)

	reqs, err := ListRequests(context.Background(), tc.G, nil)
	require.NoError(t, err)
	require.Equal(t, 1, len(reqs))
	require.Equal(t, teamName, reqs[0].Name)
	require.Equal(t, u1.Username, reqs[0].Username)
	require.True(t, reqs[0].Ctime.Time().After(time.Now().Add(-1*time.Minute)))
	require.Equal(t, "", reqs[0].FullName.String()) // no fullname in this case

	// owner add u1 to team
	_, err = AddMember(context.Background(), tc.G, teamName, u1.Username, keybase1.TeamRole_WRITER, nil)
	require.NoError(t, err)

	// owner lists requests, sees no requests
	assertNoRequests(tc)

	// u1 requests access to the team again
	err = tc.Logout()
	require.NoError(t, err)
	err = u1.Login(tc.G)
	require.NoError(t, err)

	_, err = RequestAccess(context.Background(), tc.G, teamName)
	require.Error(t, err)
	aerr, ok := err.(libkb.AppStatusError)
	if !ok {
		t.Fatalf("error %s (%T), expected libkb.AppStatusError", err, err)
	}
	if aerr.Code != libkb.SCTeamMemberExists {
		t.Errorf("status code: %d, expected %d", aerr.Code, libkb.SCTeamMemberExists)
	}
	err = tc.Logout()
	require.NoError(t, err)

	// owner lists requests, sees no requests
	err = owner.Login(tc.G)
	require.NoError(t, err)
	assertNoRequests(tc)
}

func TestAccessRequestIgnore(t *testing.T) {
	t.Skip() // Y2K-1455

	tc, owner, u1, _, teamName := memberSetupMultiple(t)
	defer tc.Cleanup()

	// owner is logged in and created teamName
	err := tc.Logout()
	require.NoError(t, err)

	// u1 requests access to the team
	if err := u1.Login(tc.G); err != nil {
		t.Fatal(err)
	}
	if _, err := RequestAccess(context.Background(), tc.G, teamName); err != nil {
		t.Fatal(err)
	}
	fullName, err := libkb.RandString("test", 5)
	if err != nil {
		t.Fatal(err)
	}
	if err := kbtest.EditProfile(u1.User.MetaContext(context.Background()), keybase1.ProfileEditArg{
		FullName: fullName,
	}); err != nil {
		t.Fatal(err)
	}

	// owner lists requests, sees u1 request
	err = tc.Logout()
	require.NoError(t, err)
	if err := owner.Login(tc.G); err != nil {
		t.Fatal(err)
	}
	require.NoError(t, tc.G.UIDMapper.ClearUIDFullName(context.Background(), tc.G, u1.User.GetUID()))
	reqs, err := ListRequests(context.Background(), tc.G, nil)
	if err != nil {
		t.Fatal(err)
	}
	if len(reqs) != 1 {
		t.Fatalf("num requests: %d, expected 1", len(reqs))
	}
	if reqs[0].Name != teamName {
		t.Errorf("request team name: %q, expected %q", reqs[0].Name, teamName)
	}
	if reqs[0].Username != u1.Username {
		t.Errorf("request username: %q, expected %q", reqs[0].Username, u1.Username)
	}
	if !reqs[0].Ctime.Time().After(time.Now().Add(-1 * time.Minute)) {
		t.Errorf("request ctime %q, expected during last minute", reqs[0].Ctime)
	}
	if reqs[0].FullName.String() != fullName {
		t.Errorf("request full name %q, expected %q", reqs[0].FullName, fullName)
	}

	// owner ignores u1 request
	if err := IgnoreRequest(context.Background(), tc.G, reqs[0].Name, reqs[0].Username); err != nil {
		t.Fatal(err)
	}

	// owner lists requests, sees no requests
	assertNoRequests(tc)

	// u1 requests access to the team again
	err = tc.Logout()
	require.NoError(t, err)
	if err := u1.Login(tc.G); err != nil {
		t.Fatal(err)
	}
	_, err = RequestAccess(context.Background(), tc.G, teamName)
	if err == nil {
		t.Fatal("second RequestAccess success, expected error")
	}
	aerr, ok := err.(libkb.AppStatusError)
	if !ok {
		t.Fatalf("error %s (%T), expected libkb.AppStatusError", err, err)
	}
	if aerr.Code != libkb.SCTeamTarDuplicate {
		t.Errorf("status code: %d, expected %d", aerr.Code, libkb.SCTeamTarDuplicate)
	}
	err = tc.Logout()
	require.NoError(t, err)

	// owner lists requests, sees no requests
	if err := owner.Login(tc.G); err != nil {
		t.Fatal(err)
	}
	assertNoRequests(tc)
}

func assertNoRequests(tc libkb.TestContext) {
	reqs, err := ListRequests(context.Background(), tc.G, nil)
	if err != nil {
		tc.T.Fatal(err)
	}
	if len(reqs) != 0 {
		tc.T.Fatalf("num requests: %d, expected 0", len(reqs))
	}
}
<|endoftext|>


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

package etcdtopo

import (
	"github.com/coreos/go-etcd/etcd"
)

func newEtcdClient(machines []string) Client {
	return etcd.NewClient(machines)
}

// Client contains the parts of etcd.Client that are needed.
type Client interface {
	CompareAndDelete(key string, prevValue string, prevIndex uint64) (*etcd.Response, error)
	CompareAndSwap(key string, value string, ttl uint64,
		prevValue string, prevIndex uint64) (*etcd.Response, error)
	Create(key string, value string, ttl uint64) (*etcd.Response, error)
	Delete(key string, recursive bool) (*etcd.Response, error)
	DeleteDir(key string) (*etcd.Response, error)
	Get(key string, sort, recursive bool) (*etcd.Response, error)
	Set(key string, value string, ttl uint64) (*etcd.Response, error)
	SetCluster(machines []string) bool
	Watch(prefix string, waitIndex uint64, recursive bool,
		receiver chan *etcd.Response, stop chan bool) (*etcd.Response, error)
}
<commit_msg>etcd: Require strong consistency (quorum reads).<commit_after>// Copyright 2014, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package etcdtopo

import (
	"github.com/coreos/go-etcd/etcd"
)

func newEtcdClient(machines []string) Client {
	c := etcd.NewClient(machines)
	// Vitess requires strong consistency mode for etcd.
	if err := c.SetConsistency(etcd.STRONG_CONSISTENCY); err != nil {
		panic("failed to set consistency on etcd client: " + err.Error())
	}
	return c
}

// Client contains the parts of etcd.Client that are needed.
type Client interface {
	CompareAndDelete(key string, prevValue string, prevIndex uint64) (*etcd.Response, error)
	CompareAndSwap(key string, value string, ttl uint64,
		prevValue string, prevIndex uint64) (*etcd.Response, error)
	Create(key string, value string, ttl uint64) (*etcd.Response, error)
	Delete(key string, recursive bool) (*etcd.Response, error)
	DeleteDir(key string) (*etcd.Response, error)
	Get(key string, sort, recursive bool) (*etcd.Response, error)
	Set(key string, value string, ttl uint64) (*etcd.Response, error)
	SetCluster(machines []string) bool
	Watch(prefix string, waitIndex uint64, recursive bool,
		receiver chan *etcd.Response, stop chan bool) (*etcd.Response, error)
}
<|endoftext|>


<commit_before>package memes

const defaultConfig = `
# You can delete everything up to Config: below
# To edit the memes or add your own, copy all of the help and command matchers
# to your own local config.
Disabled: true
Help:
- Keywords: [ "meme", "gosh" ]
  Helptext: [ "(bot), <something>, gosh! - Let Napoleon Dynamite express your indignation" ]
- Keywords: [ "meme", "best", "worst" ]
  Helptext: [ "(bot), this is pretty much the best/worst <something> ever <something> - Napoleon expresses his opinion" ]
- Keywords: [ "meme", "skill", "skills" ]
  Helptext: [ "(bot), <something> skill(s) with <something> - Hear about Napoleon's incredible skills" ]
- Keywords: [ "meme", "simply" ]
  Helptext: [ "(bot), one does not simply <do something> - Summon Boromir to make your point" ]
- Keywords: [ "meme", "prepare" ]
  Helptext: [ "(bot), you <did something>, prepare to die - Let Inigo threaten your friends" ]
- Keywords: [ "meme", "brace" ]
  Helptext: [ "(bot), brace yourselves, <something> - Boromir warns your" ]
- Keywords: [ "meme" ]
  Helptest: [ "(bot), Y U no <something> - express your angst" ]

CommandMatchers:
- Command: "18304105"
  Regex: '(?i:([\w’'' ]+,) (gosh!))'
- Command: "8070362"
  Regex: '(?i:([\w''’ ]+ pretty much the) ((?:best|worst) [\w''’]+ ever [\w''’!]+))'
- Command: "20509936"
  Regex: '(?i:([\w''’ ]+ skills?) ((with|in) [\w''’! ]+))'
- Command: "61579"
  Regex: '(?i:(one does not simply) ([\w!\n''’ ]+))'
- Command: "47779539"
  Regex: '(?i:(you [\w!''’ ]+,?) (prepare to die!?))'
- Command: "61546"
  Regex: '(?i:(brace yourselves,?) ([\w''’ !]+))'
- Command: "61527"
  Regex: '(?i:(y u no) ([\w''’ !?]+))'
# Custom configuration for memes - you need to supply a username and password,
# and a map of commands to meme ID #.
Config:
  Username: '<your-imgflip-username>'
  Password: '<your-password>'
`
<commit_msg>Fix typo<commit_after>package memes

const defaultConfig = `
# You can delete everything up to Config: below
# To edit the memes or add your own, copy all of the help and command matchers
# to your own local config.
Disabled: true
Help:
- Keywords: [ "meme", "gosh" ]
  Helptext: [ "(bot), <something>, gosh! - Let Napoleon Dynamite express your indignation" ]
- Keywords: [ "meme", "best", "worst" ]
  Helptext: [ "(bot), this is pretty much the best/worst <something> ever <something> - Napoleon expresses his opinion" ]
- Keywords: [ "meme", "skill", "skills" ]
  Helptext: [ "(bot), <something> skill(s) with <something> - Hear about Napoleon's incredible skills" ]
- Keywords: [ "meme", "simply" ]
  Helptext: [ "(bot), one does not simply <do something> - Summon Boromir to make your point" ]
- Keywords: [ "meme", "prepare" ]
  Helptext: [ "(bot), you <did something>, prepare to die - Let Inigo threaten your friends" ]
- Keywords: [ "meme", "brace" ]
  Helptext: [ "(bot), brace yourselves, <something> - Boromir warns your" ]
- Keywords: [ "meme" ]
  Helptext: [ "(bot), Y U no <something> - express your angst" ]

CommandMatchers:
- Command: "18304105"
  Regex: '(?i:([\w’'' ]+,) (gosh!))'
- Command: "8070362"
  Regex: '(?i:([\w''’ ]+ pretty much the) ((?:best|worst) [\w''’]+ ever [\w''’!]+))'
- Command: "20509936"
  Regex: '(?i:([\w''’ ]+ skills?) ((with|in) [\w''’! ]+))'
- Command: "61579"
  Regex: '(?i:(one does not simply) ([\w!\n''’ ]+))'
- Command: "47779539"
  Regex: '(?i:(you [\w!''’ ]+,?) (prepare to die!?))'
- Command: "61546"
  Regex: '(?i:(brace yourselves,?) ([\w''’ !]+))'
- Command: "61527"
  Regex: '(?i:(y u no) ([\w''’ !?]+))'
# Custom configuration for memes - you need to supply a username and password,
# and a map of commands to meme ID #.
Config:
  Username: '<your-imgflip-username>'
  Password: '<your-password>'
`
<|endoftext|>