<commit_before>package common

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"time"
)

// Merge merges the commits in commitDiffList into the destination branch destBranch of the given database
func Merge(destOwner string, destFolder string, destName string, destBranch string, srcOwner string, srcFolder string, srcName string, commitDiffList []CommitEntry, message string, loggedInUser string) (err error) {
	// Get the details of the head commit for the destination database branch
	branchList, err := GetBranches(destOwner, destFolder, destName) // Destination branch list
	if err != nil {
		return err
	}
	branchDetails, ok := branchList[destBranch]
	if !ok {
		err = fmt.Errorf("Could not retrieve details for the destination branch")
		return
	}
	destCommitID := branchDetails.Commit

	// Check if the MR commits will still apply cleanly to the destination branch so we can fast-forward
	finalCommit := commitDiffList[len(commitDiffList)-1]
	fastForwardPossible := finalCommit.Parent == destCommitID

	// If fast forwarding doesn't work we need to perform an actual merge of the branch heads
	if !fastForwardPossible {
		// Perform merge
		err = performMerge(destOwner, destFolder, destName, destCommitID, srcOwner, srcFolder, srcName, commitDiffList, loggedInUser)
		if err != nil {
			return
		}

		// TODO If the merge is actually successful, stop anyway. This is because storing the resulting
		// database and creating a proper merge commit isn't implemented yet.
		err = fmt.Errorf("Merging other than by fast-forwarding is not yet implemented")
		return
	}

	// Get destination commit list
	destCommitList, err := GetCommitList(destOwner, destFolder, destName)
	if err != nil {
		return err
	}

	// Add the source commits directly to the destination commit list
	for _, j := range commitDiffList {
		destCommitList[j.ID] = j
	}

	// Retrieve details for the logged in user
	usr, err := User(loggedInUser)
	if err != nil {
		return err
	}

	// Create a merge commit, using the details of the source commit (this gets us a correctly filled in DB tree
	// structure easily)
	mrg := commitDiffList[0]
	mrg.AuthorEmail = usr.Email
	mrg.AuthorName = usr.DisplayName
	mrg.Message = message
	mrg.Parent = commitDiffList[0].ID
	mrg.OtherParents = append(mrg.OtherParents, destCommitID)
	mrg.Timestamp = time.Now().UTC()
	mrg.ID = CreateCommitID(mrg)

	// Add the new commit to the destination db commit list, and update the branch list with it
	destCommitList[mrg.ID] = mrg
	b := BranchEntry{
		Commit:      mrg.ID,
		CommitCount: branchDetails.CommitCount + len(commitDiffList) + 1,
		Description: branchDetails.Description,
	}
	branchList[destBranch] = b
	err = StoreCommits(destOwner, destFolder, destName, destCommitList)
	if err != nil {
		return err
	}
	err = StoreBranches(destOwner, destFolder, destName, branchList)
	if err != nil {
		return err
	}

	return
}

// performMerge takes the destination database and applies the changes from commitDiffList on it.
func performMerge(destOwner string, destFolder string, destName string, destCommitID string, srcOwner string, srcFolder string, srcName string, commitDiffList []CommitEntry, loggedInUser string) (err error) {
	// Figure out the last common ancestor and the current head of the branch to merge
	lastCommonAncestorId := commitDiffList[len(commitDiffList)-1].Parent
	currentHeadToMerge := commitDiffList[0].ID

	// Figure out the changes made to the destination branch since this common ancestor.
	// For this we don't need any SQLs generated because this information is only required
	// for checking for conflicts.
	destDiffs, err := Diff(destOwner, destFolder, destName, lastCommonAncestorId, destOwner, destFolder, destName, destCommitID, loggedInUser, NoMerge, false)
	if err != nil {
		return err
	}

	// Figure out the changes made to the source branch since this common ancestor.
	// For this we do want SQLs generated because these need to be applied on top of
	// the destination branch head.
	srcDiffs, err := Diff(srcOwner, srcFolder, srcName, lastCommonAncestorId, srcOwner, srcFolder, srcName, currentHeadToMerge, loggedInUser, NewPkMerge, false)
	if err != nil {
		return err
	}

	// Check for conflicts
	conflicts := checkForConflicts(srcDiffs, destDiffs, NewPkMerge)
	if conflicts != nil {
		// TODO We don't have developed an intelligent conflict strategy yet.
		// So in the case of a conflict, just abort with an error message.
		return fmt.Errorf("The two branches are in conflict. Please fix this manually.\n" + strings.Join(conflicts, "\n"))
	}

	// Merge
	// TODO

	return
}

// checkForConflicts takes two diff changesets and checks whether they are compatible or not.
// Compatible changesets don't change the same objects or rows and thus can be combined without
// side effects. The function returns an empty slice if there are no conflicts. If there are
// conflicts the returned slice contains a list of the detected conflicts.
func checkForConflicts(srcDiffs Diffs, destDiffs Diffs, mergeStrategy MergeStrategy) (conflicts []string) {
	// Check if an object in the source diff is also part of the destination diff
	for _, srcDiff := range srcDiffs.Diff {
		for _, destDiff := range destDiffs.Diff {
			// Check if the object names are the same
			if srcDiff.ObjectName == destDiff.ObjectName {
				// If the schema of this object has changed in one of the branches, this is
				// a conflict we cannot solve
				if srcDiff.Schema != nil || destDiff.Schema != nil {
					conflicts = append(conflicts, "Schema for "+srcDiff.ObjectName+" has changed")

					// No need to look further in this case
					break
				}

				// If both objects have changed data we need to compare that too
				if srcDiff.Data != nil && destDiff.Data != nil {
					// Check if there are any changed rows with the same primary key
					for _, srcRow := range srcDiff.Data {
						for _, destRow := range destDiff.Data {
							if DataValuesMatch(srcRow.Pk, destRow.Pk) {
								// We have found two changes which affect the same primary key. So this is a potential
								// conflict. The question now is whether it is actually a problem or not.

								// Every combination of updates, inserts, and deletes is a conflict except for the
								// case where the source row is inserted using the NewPkMerge strategy which generates
								// a new primary key which doesn't conflict.
								if !(srcRow.ActionType == "add" && mergeStrategy == NewPkMerge) {
									// Generate and add conflict description
									conflictString := "Conflict in " + srcDiff.ObjectName + " for "
									for _, pk := range srcRow.Pk {
										conflictString += pk.Name + "=" + pk.Value.(string) + ","
									}
									conflicts = append(conflicts, strings.TrimSuffix(conflictString, ","))
								}

								// No need to look through the rest of the destination rows
								break
							}
						}
					}
				}

				// No need to look through the remaining destination diff items.
				// Just continue with the next source diff item.
				break
			}
		}
	}

	return
}
<commit_msg>common: Implement the actual merging of databases<commit_after>package common

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"time"

	sqlite "github.com/gwenn/gosqlite"
)

// Merge merges the commits in commitDiffList into the destination branch destBranch of the given database
func Merge(destOwner string, destFolder string, destName string, destBranch string, srcOwner string, srcFolder string, srcName string, commitDiffList []CommitEntry, message string, loggedInUser string) (err error) {
	// Get the details of the head commit for the destination database branch
	branchList, err := GetBranches(destOwner, destFolder, destName) // Destination branch list
	if err != nil {
		return err
	}
	branchDetails, ok := branchList[destBranch]
	if !ok {
		err = fmt.Errorf("Could not retrieve details for the destination branch")
		return
	}
	destCommitID := branchDetails.Commit

	// Check if the MR commits will still apply cleanly to the destination branch so we can fast-forward
	finalCommit := commitDiffList[len(commitDiffList)-1]
	fastForwardPossible := finalCommit.Parent == destCommitID

	// If fast forwarding doesn't work we need to perform an actual merge of the branch heads
	if !fastForwardPossible {
		// Perform merge
		err = performMerge(destOwner, destFolder, destName, destCommitID, srcOwner, srcFolder, srcName, commitDiffList, loggedInUser)
		if err != nil {
			return
		}

		// TODO If the merge is actually successful, stop anyway. This is because storing the resulting
		// database and creating a proper merge commit isn't implemented yet.
		err = fmt.Errorf("Merging other than by fast-forwarding is not yet implemented")
		return
	}

	// Get destination commit list
	destCommitList, err := GetCommitList(destOwner, destFolder, destName)
	if err != nil {
		return err
	}

	// Add the source commits directly to the destination commit list
	for _, j := range commitDiffList {
		destCommitList[j.ID] = j
	}

	// Retrieve details for the logged in user
	usr, err := User(loggedInUser)
	if err != nil {
		return err
	}

	// Create a merge commit, using the details of the source commit (this gets us a correctly filled in DB tree
	// structure easily)
	mrg := commitDiffList[0]
	mrg.AuthorEmail = usr.Email
	mrg.AuthorName = usr.DisplayName
	mrg.Message = message
	mrg.Parent = commitDiffList[0].ID
	mrg.OtherParents = append(mrg.OtherParents, destCommitID)
	mrg.Timestamp = time.Now().UTC()
	mrg.ID = CreateCommitID(mrg)

	// Add the new commit to the destination db commit list, and update the branch list with it
	destCommitList[mrg.ID] = mrg
	b := BranchEntry{
		Commit:      mrg.ID,
		CommitCount: branchDetails.CommitCount + len(commitDiffList) + 1,
		Description: branchDetails.Description,
	}
	branchList[destBranch] = b
	err = StoreCommits(destOwner, destFolder, destName, destCommitList)
	if err != nil {
		return err
	}
	err = StoreBranches(destOwner, destFolder, destName, branchList)
	if err != nil {
		return err
	}

	return
}

// performMerge takes the destination database and applies the changes from commitDiffList on it.
func performMerge(destOwner string, destFolder string, destName string, destCommitID string, srcOwner string, srcFolder string, srcName string, commitDiffList []CommitEntry, loggedInUser string) (err error) {
	// Figure out the last common ancestor and the current head of the branch to merge
	lastCommonAncestorId := commitDiffList[len(commitDiffList)-1].Parent
	currentHeadToMerge := commitDiffList[0].ID

	// Figure out the changes made to the destination branch since this common ancestor.
	// For this we don't need any SQLs generated because this information is only required
	// for checking for conflicts.
	destDiffs, err := Diff(destOwner, destFolder, destName, lastCommonAncestorId, destOwner, destFolder, destName, destCommitID, loggedInUser, NoMerge, false)
	if err != nil {
		return err
	}

	// Figure out the changes made to the source branch since this common ancestor.
	// For this we do want SQLs generated because these need to be applied on top of
	// the destination branch head.
	srcDiffs, err := Diff(srcOwner, srcFolder, srcName, lastCommonAncestorId, srcOwner, srcFolder, srcName, currentHeadToMerge, loggedInUser, NewPkMerge, false)
	if err != nil {
		return err
	}

	// Check for conflicts
	conflicts := checkForConflicts(srcDiffs, destDiffs, NewPkMerge)
	if conflicts != nil {
		// TODO We don't have developed an intelligent conflict strategy yet.
		// So in the case of a conflict, just abort with an error message.
		return fmt.Errorf("The two branches are in conflict. Please fix this manually.\n" + strings.Join(conflicts, "\n"))
	}

	// Get Minio location
	bucket, id, _, err := MinioLocation(destOwner, destFolder, destName, destCommitID, loggedInUser)
	if err != nil {
		return
	}

	// Sanity check
	if id == "" {
		// The requested database wasn't found, or the user doesn't have permission to access it
		return fmt.Errorf("Requested database not found")
	}

	// Retrieve database file from Minio, using locally cached version if it's already there
	dbFile, err := RetrieveDatabaseFile(bucket, id)
	if err != nil {
		return
	}

	// Create a temporary file for the new database
	tmpFile, err := ioutil.TempFile(os.TempDir(), "merge-*.db")
	if err != nil {
		return
	}

	// Delete the file when we are done
	defer os.Remove(tmpFile.Name())
	defer tmpFile.Close()

	// Copy destination database to temporary location
	{
		inFile, err := os.Open(dbFile)
		if err != nil {
			return err
		}
		defer inFile.Close()
		_, err = io.Copy(tmpFile, inFile)
		if err != nil {
			return err
		}
	}

	// Open temporary database file for writing
	var sdb *sqlite.Conn
	sdb, err = sqlite.Open(tmpFile.Name(), sqlite.OpenReadWrite)
	if err != nil {
		return err
	}
	defer sdb.Close()
	if err = sdb.EnableExtendedResultCodes(true); err != nil {
		return err
	}

	// Apply all the SQL statements from the diff on the temporary database
	for _, diff := range srcDiffs.Diff {
		// First apply schema changes
		if diff.Schema != nil {
			err = sdb.Exec(diff.Schema.Sql)
			if err != nil {
				return
			}
		}

		// Then apply data changes
		for _, row := range diff.Data {
			err = sdb.Exec(row.Sql)
			if err != nil {
				return
			}
		}
	}

	return
}

// checkForConflicts takes two diff changesets and checks whether they are compatible or not.
// Compatible changesets don't change the same objects or rows and thus can be combined without
// side effects. The function returns an empty slice if there are no conflicts. If there are
// conflicts the returned slice contains a list of the detected conflicts.
func checkForConflicts(srcDiffs Diffs, destDiffs Diffs, mergeStrategy MergeStrategy) (conflicts []string) {
	// Check if an object in the source diff is also part of the destination diff
	for _, srcDiff := range srcDiffs.Diff {
		for _, destDiff := range destDiffs.Diff {
			// Check if the object names are the same
			if srcDiff.ObjectName == destDiff.ObjectName {
				// If the schema of this object has changed in one of the branches, this is
				// a conflict we cannot solve
				if srcDiff.Schema != nil || destDiff.Schema != nil {
					conflicts = append(conflicts, "Schema for "+srcDiff.ObjectName+" has changed")

					// No need to look further in this case
					break
				}

				// Check if there are any changed rows with the same primary key
				for _, srcRow := range srcDiff.Data {
					for _, destRow := range destDiff.Data {
						if DataValuesMatch(srcRow.Pk, destRow.Pk) {
							// We have found two changes which affect the same primary key. So this is a potential
							// conflict. The question now is whether it is actually a problem or not.

							// Every combination of updates, inserts, and deletes is a conflict except for the
							// case where the source row is inserted using the NewPkMerge strategy which generates
							// a new primary key which doesn't conflict.
							if !(srcRow.ActionType == "add" && mergeStrategy == NewPkMerge) {
								// Generate and add conflict description
								conflictString := "Conflict in " + srcDiff.ObjectName + " for "
								for _, pk := range srcRow.Pk {
									conflictString += pk.Name + "=" + pk.Value.(string) + ","
								}
								conflicts = append(conflicts, strings.TrimSuffix(conflictString, ","))
							}

							// No need to look through the rest of the destination rows
							break
						}
					}
				}

				// No need to look through the remaining destination diff items.
				// Just continue with the next source diff item.
				break
			}
		}
	}

	return
}
<|endoftext|>


<commit_before>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package state

import (
	"fmt"

	"labix.org/v2/mgo/txn"
)

type actionDoc struct {
	Id string `bson:"_id"`

	// Name identifies the action; it should match an action defined by
	// the unit's charm.
	Name string

	// Payload holds the action's parameters, if any; it should validate
	// against the schema defined by the named action in the unit's charm
	Payload map[string]interface{}
}

// Action represents an instruction to do some "action" and is expected
// to match an action definition in a charm.
type Action struct {
	st  *State
	doc actionDoc
}

// newAction builds an Action from the supplied state and actionDoc
func newAction(st *State, adoc actionDoc) *Action {
	return &Action{
		st:  st,
		doc: adoc,
	}
}

// actionPrefix returns a suitable prefix for an action given the
// globalKey of a containing item
func actionPrefix(globalKey string) string {
	return globalKey + "#a#"
}

// newActionId generates a new unique key from another globalKey as
// a prefix, and a generated unique number
func newActionId(st *State, globalKey string) (string, error) {
	prefix := actionPrefix(globalKey)
	suffix, err := st.sequence(prefix)
	if err != nil {
		return "", fmt.Errorf("cannot assign new sequence for prefix '%s': %v", prefix, err)
	}
	return fmt.Sprintf("%s%d", prefix, suffix), nil
}

// Name returns the name of the Action
func (a *Action) Name() string {
	return a.doc.Name
}

// Id returns the id of the Action
func (a *Action) Id() string {
	return a.doc.Id
}

// Payload will contain a structure representing arguments or parameters to
// an action, and is expected to be validated by the Unit using the Charm
// definition of the Action
func (a *Action) Payload() map[string]interface{} {
	return a.doc.Payload
}

// Fail removes an Action from the queue, and documents the reason for the
// failure.
func (a *Action) Fail(reason string) error {
	// TODO(jcw4) add logging
	return a.st.runTransaction([]txn.Op{{
		C:      a.st.actions.Name,
		Id:     a.doc.Id,
		Remove: true,
	}})
}
<commit_msg>log Action.Fail()<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package state

import (
	"fmt"

	"labix.org/v2/mgo/txn"
)

type actionDoc struct {
	Id string `bson:"_id"`

	// Name identifies the action; it should match an action defined by
	// the unit's charm.
	Name string

	// Payload holds the action's parameters, if any; it should validate
	// against the schema defined by the named action in the unit's charm
	Payload map[string]interface{}
}

// Action represents an instruction to do some "action" and is expected
// to match an action definition in a charm.
type Action struct {
	st  *State
	doc actionDoc
}

// newAction builds an Action from the supplied state and actionDoc
func newAction(st *State, adoc actionDoc) *Action {
	return &Action{
		st:  st,
		doc: adoc,
	}
}

// actionPrefix returns a suitable prefix for an action given the
// globalKey of a containing item
func actionPrefix(globalKey string) string {
	return globalKey + "#a#"
}

// newActionId generates a new unique key from another globalKey as
// a prefix, and a generated unique number
func newActionId(st *State, globalKey string) (string, error) {
	prefix := actionPrefix(globalKey)
	suffix, err := st.sequence(prefix)
	if err != nil {
		return "", fmt.Errorf("cannot assign new sequence for prefix '%s': %v", prefix, err)
	}
	return fmt.Sprintf("%s%d", prefix, suffix), nil
}

// Name returns the name of the Action
func (a *Action) Name() string {
	return a.doc.Name
}

// Id returns the id of the Action
func (a *Action) Id() string {
	return a.doc.Id
}

// Payload will contain a structure representing arguments or parameters to
// an action, and is expected to be validated by the Unit using the Charm
// definition of the Action
func (a *Action) Payload() map[string]interface{} {
	return a.doc.Payload
}

// Fail removes an Action from the queue, and documents the reason for the
// failure.
func (a *Action) Fail(reason string) error {
	// TODO(jcw4) replace with code to generate a result that records this failure
	logger.Warningf("action '%s' failed because '%s'", a.doc.Name, reason)
	return a.st.runTransaction([]txn.Op{{
		C:      a.st.actions.Name,
		Id:     a.doc.Id,
		Remove: true,
	}})
}
<|endoftext|>


<commit_before>package mpb

import (
	"context"
	"errors"
	"io"
	"log"
	"os"
	"sync"
	"time"
	"unicode/utf8"

	"github.com/vbauerster/mpb/cwriter"
)

var logger = log.New(os.Stderr, "mpb: ", log.LstdFlags|log.Lshortfile)

// ErrCallAfterStop thrown by panic, if Progress methods like AddBar() are called
// after Stop() has been called
var ErrCallAfterStop = errors.New("method call on stopped Progress instance")

type (
	// BeforeRender is a func, which gets called before render process
	BeforeRender func([]*Bar)
	barOpType    uint

	operation struct {
		kind   barOpType
		bar    *Bar
		result chan bool
	}

	indexedBarBuffer struct {
		index int
		buf   []byte
	}

	indexedBar struct {
		index     int
		termWidth int
		bar       *Bar
	}
)

const (
	barAdd barOpType = iota
	barRemove
)

const (
	// default RefreshRate
	rr = 100
	// default width
	pwidth = 70
	// number of format runes for bar
	numFmtRunes = 5
)

// Progress represents the container that renders Progress bars
type Progress struct {
	// Context for canceling bars rendering
	ctx context.Context
	// WaitGroup for internal rendering sync
	wg *sync.WaitGroup

	out    io.Writer
	width  int
	format string

	operationCh    chan *operation
	rrChangeReqCh  chan time.Duration
	outChangeReqCh chan io.Writer
	barCountReqCh  chan chan int
	brCh           chan BeforeRender
	done           chan struct{}
}

// New creates new Progress instance, which will orchestrate bars rendering
// process. It acceepts context.Context, for cancellation.
// If you don't plan to cancel, it is safe to feed with nil
func New(ctx context.Context) *Progress {
	if ctx == nil {
		ctx = context.Background()
	}
	p := &Progress{
		width:          pwidth,
		operationCh:    make(chan *operation),
		rrChangeReqCh:  make(chan time.Duration),
		outChangeReqCh: make(chan io.Writer),
		barCountReqCh:  make(chan chan int),
		brCh:           make(chan BeforeRender),
		done:           make(chan struct{}),
		wg:             new(sync.WaitGroup),
		ctx:            ctx,
	}
	go p.server(cwriter.New(os.Stdout), time.NewTicker(rr*time.Millisecond))
	return p
}

// SetWidth overrides default (70) width of bar(s)
func (p *Progress) SetWidth(n int) *Progress {
	if n <= 0 {
		return p
	}
	p.width = n
	return p
}

// SetOut sets underlying writer of progress. Default is os.Stdout
// pancis, if called on stopped Progress instance, i.e after Stop()
func (p *Progress) SetOut(w io.Writer) *Progress {
	if IsClosed(p.done) {
		panic(ErrCallAfterStop)
	}
	if w == nil {
		return p
	}
	p.outChangeReqCh <- w
	return p
}

// RefreshRate overrides default (100ms) refresh rate value
// pancis, if called on stopped Progress instance, i.e after Stop()
func (p *Progress) RefreshRate(d time.Duration) *Progress {
	if IsClosed(p.done) {
		panic(ErrCallAfterStop)
	}
	p.rrChangeReqCh <- d
	return p
}

func (p *Progress) BeforeRenderFunc(f BeforeRender) *Progress {
	if IsClosed(p.done) {
		panic(ErrCallAfterStop)
	}
	p.brCh <- f
	return p
}

// AddBar creates a new progress bar and adds to the container
// pancis, if called on stopped Progress instance, i.e after Stop()
func (p *Progress) AddBar(total int64) *Bar {
	return p.AddBarWithID(0, total)
}

// AddBarWithID creates a new progress bar and adds to the container
// pancis, if called on stopped Progress instance, i.e after Stop()
func (p *Progress) AddBarWithID(id int, total int64) *Bar {
	if IsClosed(p.done) {
		panic(ErrCallAfterStop)
	}
	result := make(chan bool)
	bar := newBar(p.ctx, p.wg, id, total, p.width, p.format)
	p.operationCh <- &operation{barAdd, bar, result}
	if <-result {
		p.wg.Add(1)
	}
	return bar
}

// RemoveBar removes bar at any time
// pancis, if called on stopped Progress instance, i.e after Stop()
func (p *Progress) RemoveBar(b *Bar) bool {
	if IsClosed(p.done) {
		panic(ErrCallAfterStop)
	}
	result := make(chan bool)
	p.operationCh <- &operation{barRemove, b, result}
	return <-result
}

// BarCount returns bars count in the container.
// Pancis if called on stopped Progress instance, i.e after Stop()
func (p *Progress) BarCount() int {
	if IsClosed(p.done) {
		panic(ErrCallAfterStop)
	}
	respCh := make(chan int)
	p.barCountReqCh <- respCh
	return <-respCh
}

// Format sets custom format for underlying bar(s).
// The default one is "[=>-]"
func (p *Progress) Format(format string) *Progress {
	if utf8.RuneCountInString(format) != numFmtRunes {
		return p
	}
	p.format = format
	return p
}

// Stop waits for bars to finish rendering and stops the rendering goroutine
func (p *Progress) Stop() {
	p.wg.Wait()
	if IsClosed(p.done) {
		return
	}
	close(p.operationCh)
}

// server monitors underlying channels and renders any progress bars
func (p *Progress) server(cw *cwriter.Writer, t *time.Ticker) {
	defer func() {
		t.Stop()
		close(p.done)
	}()
	const numDrawers = 3
	bars := make([]*Bar, 0, 4)
	var beforeRender BeforeRender
	var wg sync.WaitGroup
	recoverIfPanic := func() {
		if e := recover(); e != nil {
			logger.Printf("unexpected panic: %+v\n", e)
		}
		wg.Done()
	}
	for {
		select {
		case w := <-p.outChangeReqCh:
			cw.Flush()
			cw = cwriter.New(w)
		case op, ok := <-p.operationCh:
			if !ok {
				return
			}
			switch op.kind {
			case barAdd:
				bars = append(bars, op.bar)
				op.result <- true
			case barRemove:
				var ok bool
				for i, b := range bars {
					if b == op.bar {
						bars = append(bars[:i], bars[i+1:]...)
						ok = true
						b.remove()
						break
					}
				}
				op.result <- ok
			}
		case respCh := <-p.barCountReqCh:
			respCh <- len(bars)
		case beforeRender = <-p.brCh:
		case <-t.C:
			if beforeRender != nil {
				beforeRender(bars)
			}

			width, _, _ := cwriter.GetTermSize()
			ibars := iBarsGen(bars, width)
			c := make(chan indexedBarBuffer)
			wg.Add(numDrawers)
			for i := 0; i < numDrawers; i++ {
				go func() {
					defer recoverIfPanic()
					drawer(ibars, c)
				}()
			}
			go func() {
				wg.Wait()
				close(c)
			}()

			m := make(map[int][]byte, len(bars))
			for r := range c {
				m[r.index] = r.buf
			}
			for i := 0; i < len(bars); i++ {
				cw.Write(m[i])
			}

			cw.Flush()

			for _, b := range bars {
				b.flushed()
			}
		case d := <-p.rrChangeReqCh:
			t.Stop()
			t = time.NewTicker(d)
		case <-p.ctx.Done():
			return
		}
	}
}

func drawer(ibars <-chan indexedBar, c chan<- indexedBarBuffer) {
	for b := range ibars {
		buf := b.bar.bytes(b.termWidth)
		buf = append(buf, '\n')
		c <- indexedBarBuffer{b.index, buf}
	}
}

func iBarsGen(bars []*Bar, width int) <-chan indexedBar {
	ibars := make(chan indexedBar)
	go func() {
		defer close(ibars)
		for i, b := range bars {
			ibars <- indexedBar{i, width, b}
		}
	}()
	return ibars
}

// IsClosed check if ch closed
// caution see: http://www.tapirgames.com/blog/golang-channel-closing
func IsClosed(ch <-chan struct{}) bool {
	select {
	case <-ch:
		return true
	default:
		return false
	}
}
<commit_msg>BeforeRenderFunc public comment<commit_after>package mpb

import (
	"context"
	"errors"
	"io"
	"log"
	"os"
	"sync"
	"time"
	"unicode/utf8"

	"github.com/vbauerster/mpb/cwriter"
)

var logger = log.New(os.Stderr, "mpb: ", log.LstdFlags|log.Lshortfile)

// ErrCallAfterStop thrown by panic, if Progress methods like AddBar() are called
// after Stop() has been called
var ErrCallAfterStop = errors.New("method call on stopped Progress instance")

type (
	// BeforeRender is a func, which gets called before render process
	BeforeRender func([]*Bar)
	barOpType    uint

	operation struct {
		kind   barOpType
		bar    *Bar
		result chan bool
	}

	indexedBarBuffer struct {
		index int
		buf   []byte
	}

	indexedBar struct {
		index     int
		termWidth int
		bar       *Bar
	}
)

const (
	barAdd barOpType = iota
	barRemove
)

const (
	// default RefreshRate
	rr = 100
	// default width
	pwidth = 70
	// number of format runes for bar
	numFmtRunes = 5
)

// Progress represents the container that renders Progress bars
type Progress struct {
	// Context for canceling bars rendering
	ctx context.Context
	// WaitGroup for internal rendering sync
	wg *sync.WaitGroup

	out    io.Writer
	width  int
	format string

	operationCh    chan *operation
	rrChangeReqCh  chan time.Duration
	outChangeReqCh chan io.Writer
	barCountReqCh  chan chan int
	brCh           chan BeforeRender
	done           chan struct{}
}

// New creates new Progress instance, which will orchestrate bars rendering
// process. It acceepts context.Context, for cancellation.
// If you don't plan to cancel, it is safe to feed with nil
func New(ctx context.Context) *Progress {
	if ctx == nil {
		ctx = context.Background()
	}
	p := &Progress{
		width:          pwidth,
		operationCh:    make(chan *operation),
		rrChangeReqCh:  make(chan time.Duration),
		outChangeReqCh: make(chan io.Writer),
		barCountReqCh:  make(chan chan int),
		brCh:           make(chan BeforeRender),
		done:           make(chan struct{}),
		wg:             new(sync.WaitGroup),
		ctx:            ctx,
	}
	go p.server(cwriter.New(os.Stdout), time.NewTicker(rr*time.Millisecond))
	return p
}

// SetWidth overrides default (70) width of bar(s)
func (p *Progress) SetWidth(n int) *Progress {
	if n <= 0 {
		return p
	}
	p.width = n
	return p
}

// SetOut sets underlying writer of progress. Default is os.Stdout
// pancis, if called on stopped Progress instance, i.e after Stop()
func (p *Progress) SetOut(w io.Writer) *Progress {
	if IsClosed(p.done) {
		panic(ErrCallAfterStop)
	}
	if w == nil {
		return p
	}
	p.outChangeReqCh <- w
	return p
}

// RefreshRate overrides default (100ms) refresh rate value
// pancis, if called on stopped Progress instance, i.e after Stop()
func (p *Progress) RefreshRate(d time.Duration) *Progress {
	if IsClosed(p.done) {
		panic(ErrCallAfterStop)
	}
	p.rrChangeReqCh <- d
	return p
}

// BeforeRenderFunc accepts a func, which gets called before render process.
func (p *Progress) BeforeRenderFunc(f BeforeRender) *Progress {
	if IsClosed(p.done) {
		panic(ErrCallAfterStop)
	}
	p.brCh <- f
	return p
}

// AddBar creates a new progress bar and adds to the container
// pancis, if called on stopped Progress instance, i.e after Stop()
func (p *Progress) AddBar(total int64) *Bar {
	return p.AddBarWithID(0, total)
}

// AddBarWithID creates a new progress bar and adds to the container
// pancis, if called on stopped Progress instance, i.e after Stop()
func (p *Progress) AddBarWithID(id int, total int64) *Bar {
	if IsClosed(p.done) {
		panic(ErrCallAfterStop)
	}
	result := make(chan bool)
	bar := newBar(p.ctx, p.wg, id, total, p.width, p.format)
	p.operationCh <- &operation{barAdd, bar, result}
	if <-result {
		p.wg.Add(1)
	}
	return bar
}

// RemoveBar removes bar at any time
// pancis, if called on stopped Progress instance, i.e after Stop()
func (p *Progress) RemoveBar(b *Bar) bool {
	if IsClosed(p.done) {
		panic(ErrCallAfterStop)
	}
	result := make(chan bool)
	p.operationCh <- &operation{barRemove, b, result}
	return <-result
}

// BarCount returns bars count in the container.
// Pancis if called on stopped Progress instance, i.e after Stop()
func (p *Progress) BarCount() int {
	if IsClosed(p.done) {
		panic(ErrCallAfterStop)
	}
	respCh := make(chan int)
	p.barCountReqCh <- respCh
	return <-respCh
}

// Format sets custom format for underlying bar(s).
// The default one is "[=>-]"
func (p *Progress) Format(format string) *Progress {
	if utf8.RuneCountInString(format) != numFmtRunes {
		return p
	}
	p.format = format
	return p
}

// Stop waits for bars to finish rendering and stops the rendering goroutine
func (p *Progress) Stop() {
	p.wg.Wait()
	if IsClosed(p.done) {
		return
	}
	close(p.operationCh)
}

// server monitors underlying channels and renders any progress bars
func (p *Progress) server(cw *cwriter.Writer, t *time.Ticker) {
	defer func() {
		t.Stop()
		close(p.done)
	}()
	const numDrawers = 3
	bars := make([]*Bar, 0, 4)
	var beforeRender BeforeRender
	var wg sync.WaitGroup
	recoverIfPanic := func() {
		if e := recover(); e != nil {
			logger.Printf("unexpected panic: %+v\n", e)
		}
		wg.Done()
	}
	for {
		select {
		case w := <-p.outChangeReqCh:
			cw.Flush()
			cw = cwriter.New(w)
		case op, ok := <-p.operationCh:
			if !ok {
				return
			}
			switch op.kind {
			case barAdd:
				bars = append(bars, op.bar)
				op.result <- true
			case barRemove:
				var ok bool
				for i, b := range bars {
					if b == op.bar {
						bars = append(bars[:i], bars[i+1:]...)
						ok = true
						b.remove()
						break
					}
				}
				op.result <- ok
			}
		case respCh := <-p.barCountReqCh:
			respCh <- len(bars)
		case beforeRender = <-p.brCh:
		case <-t.C:
			if beforeRender != nil {
				beforeRender(bars)
			}

			width, _, _ := cwriter.GetTermSize()
			ibars := iBarsGen(bars, width)
			c := make(chan indexedBarBuffer)
			wg.Add(numDrawers)
			for i := 0; i < numDrawers; i++ {
				go func() {
					defer recoverIfPanic()
					drawer(ibars, c)
				}()
			}
			go func() {
				wg.Wait()
				close(c)
			}()

			m := make(map[int][]byte, len(bars))
			for r := range c {
				m[r.index] = r.buf
			}
			for i := 0; i < len(bars); i++ {
				cw.Write(m[i])
			}

			cw.Flush()

			for _, b := range bars {
				b.flushed()
			}
		case d := <-p.rrChangeReqCh:
			t.Stop()
			t = time.NewTicker(d)
		case <-p.ctx.Done():
			return
		}
	}
}

func drawer(ibars <-chan indexedBar, c chan<- indexedBarBuffer) {
	for b := range ibars {
		buf := b.bar.bytes(b.termWidth)
		buf = append(buf, '\n')
		c <- indexedBarBuffer{b.index, buf}
	}
}

func iBarsGen(bars []*Bar, width int) <-chan indexedBar {
	ibars := make(chan indexedBar)
	go func() {
		defer close(ibars)
		for i, b := range bars {
			ibars <- indexedBar{i, width, b}
		}
	}()
	return ibars
}

// IsClosed check if ch closed
// caution see: http://www.tapirgames.com/blog/golang-channel-closing
func IsClosed(ch <-chan struct{}) bool {
	select {
	case <-ch:
		return true
	default:
		return false
	}
}
<|endoftext|>


<commit_before>package inline_edit

import (
	"fmt"
	"html/template"
	"net/http"

	"github.com/qor/i18n"
)

func enabledInlineEdit(request *http.Request) bool {
	return true
}

func GenerateFuncMaps(I18n *i18n.I18n, locale string, request *http.Request) template.FuncMap {
	return template.FuncMap{
		"t": inlineEdit(I18n, locale, enabledInlineEdit(request)),
	}
}

func inlineEdit(I18n *i18n.I18n, locale string, isInline bool) func(string, ...interface{}) template.HTML {
	return func(key string, args ...interface{}) template.HTML {
		// Get Translation Value
		var value template.HTML
		var defaultValue string
		if len(args) > 0 {
			if args[0] == nil {
				defaultValue = key
			} else {
				defaultValue = fmt.Sprint(args[0])
			}
			value = I18n.Default(defaultValue).T(locale, key, args[1:]...)
		} else {
			value = I18n.T(locale, key)
		}

		// Append inline-edit script/tag
		if isInline {
			var editType string
			if len(value) > 25 {
				editType = "data-type=\"textarea\""
			}
			assetsTag := fmt.Sprintf("", I18n.Resource.GetAdmin().GetRouter().Prefix)
			return template.HTML(fmt.Sprintf("%s%s", assetsTag, editType, locale, key, string(value)))
		}
		return value
	}
}
<commit_msg>inline-edit: real admin prefix<commit_after>package inline_edit

import (
	"fmt"
	"html/template"
	"net/http"

	"github.com/qor/i18n"
)

func enabledInlineEdit(request *http.Request) bool {
	return true
}

func GenerateFuncMaps(I18n *i18n.I18n, locale string, request *http.Request) template.FuncMap {
	return template.FuncMap{
		"t": inlineEdit(I18n, locale, enabledInlineEdit(request)),
	}
}

func inlineEdit(I18n *i18n.I18n, locale string, isInline bool) func(string, ...interface{}) template.HTML {
	return func(key string, args ...interface{}) template.HTML {
		// Get Translation Value
		var value template.HTML
		var defaultValue string
		if len(args) > 0 {
			if args[0] == nil {
				defaultValue = key
			} else {
				defaultValue = fmt.Sprint(args[0])
			}
			value = I18n.Default(defaultValue).T(locale, key, args[1:]...)
		} else {
			value = I18n.T(locale, key)
		}

		// Append inline-edit script/tag
		if isInline {
			var editType string
			if len(value) > 25 {
				editType = "data-type=\"textarea\""
			}
			prefix := I18n.Resource.GetAdmin().GetRouter().Prefix
			assetsTag := fmt.Sprintf("", prefix, prefix)
			return template.HTML(fmt.Sprintf("%s%s", assetsTag, editType, locale, key, string(value)))
		}
		return value
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 The go-instagram 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 instagram

import (
	"fmt"
)

// RelationshipsService handles communication with the user's relationships related
// methods of the Instagram API.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/
type RelationshipsService struct {
	client *Client
}

// Relationship represents relationship authenticated user with another user.
type Relationship struct {
	// Current user's relationship to another user. Can be "follows", "requested", or "none".
	OutgoingStatus string `json:"outgoing_status,omitempty"`

	// A user's relationship to current user. Can be "followed_by", "requested_by",
	// "blocked_by_you", or "none".
	IncomingStatus string `json:"incoming_status,omitempty"`
}

// Follows gets the list of users this user follows. If empty string is
// passed then it refers to `self` or curret authenticated user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#get_users_follows
func (s *RelationshipsService) Follows(userId string) ([]User, *ResponsePagination, error) {
	var u string
	if userId != "" {
		u = fmt.Sprintf("users/%v/follows", userId)
	} else {
		u = "users/self/follows"
	}

	req, err := s.client.NewRequest("GET", u, "")
	if err != nil {
		return nil, nil, err
	}

	users := new([]User)

	_, err = s.client.Do(req, users)
	if err != nil {
		return nil, nil, err
	}

	page := new(ResponsePagination)
	if s.client.Response.Pagination != nil {
		page = s.client.Response.Pagination
	}

	return *users, page, err
}

// FollowedBy gets the list of users this user is followed by. If empty string is
// passed then it refers to `self` or curret authenticated user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#get_users_followed_by
func (s *RelationshipsService) FollowedBy(userId string) ([]User, *ResponsePagination, error) {
	var u string
	if userId != "" {
		u = fmt.Sprintf("users/%v/followed-by", userId)
	} else {
		u = "users/self/followed-by"
	}

	req, err := s.client.NewRequest("GET", u, "")
	if err != nil {
		return nil, nil, err
	}

	users := new([]User)

	_, err = s.client.Do(req, users)
	if err != nil {
		return nil, nil, err
	}

	page := new(ResponsePagination)
	if s.client.Response.Pagination != nil {
		page = s.client.Response.Pagination
	}

	return *users, page, err
}

// RequestedBy lists the users who have requested this user's permission to follow.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#get_incoming_requests
func (s *RelationshipsService) RequestedBy() ([]User, *ResponsePagination, error) {
	u := "users/self/requested-by"
	req, err := s.client.NewRequest("GET", u, "")
	if err != nil {
		return nil, nil, err
	}

	users := new([]User)

	_, err = s.client.Do(req, users)
	if err != nil {
		return nil, nil, err
	}

	page := new(ResponsePagination)
	if s.client.Response.Pagination != nil {
		page = s.client.Response.Pagination
	}

	return *users, page, err
}

// Relationship gets information about a relationship to another user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#get_relationship
func (s *RelationshipsService) Relationship(userId string) (*Relationship, error) {
	return relationshipAction(s, userId, "", "GET")
}

// Follow a user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#post_relationship
func (s *RelationshipsService) Follow(userId string) (*Relationship, error) {
	return relationshipAction(s, userId, "follow", "POST")
}

// Unfollow a user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#post_relationship
func (s *RelationshipsService) Unfollow(userId string) (*Relationship, error) {
	return relationshipAction(s, userId, "unfollow", "POST")
}

// Block a user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#post_relationship
func (s *RelationshipsService) Block(userId string) (*Relationship, error) {
	return relationshipAction(s, userId, "block", "POST")
}

// Unblock a user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#post_relationship
func (s *RelationshipsService) Unblock(userId string) (*Relationship, error) {
	return relationshipAction(s, userId, "unblock", "POST")
}

// Approve a user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#post_relationship
func (s *RelationshipsService) Approve(userId string) (*Relationship, error) {
	return relationshipAction(s, userId, "approve", "POST")
}

// Deny a user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#post_relationship
func (s *RelationshipsService) Deny(userId string) (*Relationship, error) {
	return relationshipAction(s, userId, "deny", "POST")
}

func relationshipAction(s *RelationshipsService, userId, action, method string) (*Relationship, error) {
	u := fmt.Sprintf("users/%v/relationship", userId)
	if action != "" {
		action = "action=" + action
	}
	req, err := s.client.NewRequest(method, u, action)
	if err != nil {
		return nil, err
	}

	rel := new(Relationship)
	_, err = s.client.Do(req, rel)
	return rel, err
}
<commit_msg>When checking relationships, indicates whether user is private.<commit_after>// Copyright 2013 The go-instagram 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 instagram

import (
	"fmt"
)

// RelationshipsService handles communication with the user's relationships related
// methods of the Instagram API.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/
type RelationshipsService struct {
	client *Client
}

// Relationship represents relationship authenticated user with another user.
type Relationship struct {
	// Current user's relationship to another user. Can be "follows", "requested", or "none".
	OutgoingStatus string `json:"outgoing_status,omitempty"`

	// A user's relationship to current user. Can be "followed_by", "requested_by",
	// "blocked_by_you", or "none".
	IncomingStatus string `json:"incoming_status,omitempty"`

	// Undocumented part of the API, though was stable at least from 2012-2015
	// Informs whether the target user is a private user
	TargetUserIsPrivate bool `json:"target_user_is_private,omitempty"`
}

// Follows gets the list of users this user follows. If empty string is
// passed then it refers to `self` or curret authenticated user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#get_users_follows
func (s *RelationshipsService) Follows(userId string) ([]User, *ResponsePagination, error) {
	var u string
	if userId != "" {
		u = fmt.Sprintf("users/%v/follows", userId)
	} else {
		u = "users/self/follows"
	}

	req, err := s.client.NewRequest("GET", u, "")
	if err != nil {
		return nil, nil, err
	}

	users := new([]User)

	_, err = s.client.Do(req, users)
	if err != nil {
		return nil, nil, err
	}

	page := new(ResponsePagination)
	if s.client.Response.Pagination != nil {
		page = s.client.Response.Pagination
	}

	return *users, page, err
}

// FollowedBy gets the list of users this user is followed by. If empty string is
// passed then it refers to `self` or curret authenticated user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#get_users_followed_by
func (s *RelationshipsService) FollowedBy(userId string) ([]User, *ResponsePagination, error) {
	var u string
	if userId != "" {
		u = fmt.Sprintf("users/%v/followed-by", userId)
	} else {
		u = "users/self/followed-by"
	}

	req, err := s.client.NewRequest("GET", u, "")
	if err != nil {
		return nil, nil, err
	}

	users := new([]User)

	_, err = s.client.Do(req, users)
	if err != nil {
		return nil, nil, err
	}

	page := new(ResponsePagination)
	if s.client.Response.Pagination != nil {
		page = s.client.Response.Pagination
	}

	return *users, page, err
}

// RequestedBy lists the users who have requested this user's permission to follow.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#get_incoming_requests
func (s *RelationshipsService) RequestedBy() ([]User, *ResponsePagination, error) {
	u := "users/self/requested-by"
	req, err := s.client.NewRequest("GET", u, "")
	if err != nil {
		return nil, nil, err
	}

	users := new([]User)

	_, err = s.client.Do(req, users)
	if err != nil {
		return nil, nil, err
	}

	page := new(ResponsePagination)
	if s.client.Response.Pagination != nil {
		page = s.client.Response.Pagination
	}

	return *users, page, err
}

// Relationship gets information about a relationship to another user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#get_relationship
func (s *RelationshipsService) Relationship(userId string) (*Relationship, error) {
	return relationshipAction(s, userId, "", "GET")
}

// Follow a user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#post_relationship
func (s *RelationshipsService) Follow(userId string) (*Relationship, error) {
	return relationshipAction(s, userId, "follow", "POST")
}

// Unfollow a user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#post_relationship
func (s *RelationshipsService) Unfollow(userId string) (*Relationship, error) {
	return relationshipAction(s, userId, "unfollow", "POST")
}

// Block a user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#post_relationship
func (s *RelationshipsService) Block(userId string) (*Relationship, error) {
	return relationshipAction(s, userId, "block", "POST")
}

// Unblock a user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#post_relationship
func (s *RelationshipsService) Unblock(userId string) (*Relationship, error) {
	return relationshipAction(s, userId, "unblock", "POST")
}

// Approve a user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#post_relationship
func (s *RelationshipsService) Approve(userId string) (*Relationship, error) {
	return relationshipAction(s, userId, "approve", "POST")
}

// Deny a user.
//
// Instagram API docs: http://instagram.com/developer/endpoints/relationships/#post_relationship
func (s *RelationshipsService) Deny(userId string) (*Relationship, error) {
	return relationshipAction(s, userId, "deny", "POST")
}

func relationshipAction(s *RelationshipsService, userId, action, method string) (*Relationship, error) {
	u := fmt.Sprintf("users/%v/relationship", userId)
	if action != "" {
		action = "action=" + action
	}
	req, err := s.client.NewRequest(method, u, action)
	if err != nil {
		return nil, err
	}

	rel := new(Relationship)
	_, err = s.client.Do(req, rel)
	return rel, err
}
<|endoftext|>


<commit_before>package survey

import (
	"bufio"
	"fmt"
	"os"
	"regexp"

	tm "github.com/buger/goterm"
)

// Confirm is a regular text input that accept yes/no answers.
type Confirm struct {
	Message string
	Default bool
	Answer  *bool
}

// data available to the templates when processing
type ConfirmTemplateData struct {
	Confirm
	Answer string
}

// Templates with Color formatting. See Documentation: https://github.com/mgutz/ansi#style-format
var ConfirmQuestionTemplate = `
{{- color "green+hb"}}? {{color "reset"}}
{{- color "default+hb"}}{{ .Message }} {{color "reset"}}
{{- if .Answer}}
  {{- color "cyan"}}{{.Answer}}{{color "reset"}}
{{- else }}
  {{- color "white"}}{{if .Default}}(Y/n) {{else}}(y/N) {{end}}{{color "reset"}}
{{- end}}`

func yesNo(t bool) string {
	if t {
		return "Yes"
	}
	return "No"
}

// Prompt prompts the user with a simple text field and expects a reply followed
// by a carriage return.
func (confirm *Confirm) Prompt() (string, error) {
	if confirm.Answer == nil {
		answer = false
		confirm.Answer = &answer
	}
	out, err := runTemplate(
		ConfirmQuestionTemplate,
		ConfirmTemplateData{Confirm: *confirm},
	)
	if err != nil {
		return "", err
	}

	// print the question we were given to kick off the prompt
	fmt.Print(out)

	// a scanner to look at the input from stdin
	scanner := bufio.NewScanner(os.Stdin)
	// wait for a response
	yesRx := regexp.MustCompile("^(?i:y(?:es)?)$")
	noRx := regexp.MustCompile("^(?i:n(?:o)?)$")
	answer := confirm.Default
	for scanner.Scan() {
		// get the availible text in the scanner
		res := scanner.Text()
		// if there is no answer
		if res == "" {
			// use the default
			break
		}
		// is answer yes?
		if yesRx.Match([]byte(res)) {
			answer = true
			break
		}

		// is answer "no"
		if noRx.Match([]byte(res)) {
			answer = false
			break
		}

		// we didnt get a valid answer, so print error and prompt again
		out, err := runTemplate(ErrorTemplate, fmt.Errorf("%q is not a valid answer, try again", res))
		if err != nil {
			return "", err
		}
		// send the message to the user
		fmt.Print(out)
		return confirm.Prompt()
	}

	// return the value
	*confirm.Answer = answer
	return yesNo(answer), nil
}

// Cleanup overwrite the line with the finalized formatted version
func (confirm *Confirm) Cleanup(val string) error {
	// get the current cursor location
	loc, err := CursorLocation()
	// if something went wrong
	if err != nil {
		// bubble
		return err
	}

	var initLoc int
	// if we are printing at the end of the console
	if loc.col == tm.Height() {
		initLoc = loc.col - 2
	} else {
		initLoc = loc.col - 1
	}

	// move to the beginning of the current line
	tm.MoveCursor(initLoc, 1)

	out, err := runTemplate(
		ConfirmQuestionTemplate,
		ConfirmTemplateData{Confirm: *confirm, Answer: val},
	)
	if err != nil {
		return err
	}

	tm.Print(out, AnsiClearLine)
	tm.Flush()

	// nothing went wrong
	return nil
}
<commit_msg>fix typo, duh<commit_after>package survey

import (
	"bufio"
	"fmt"
	"os"
	"regexp"

	tm "github.com/buger/goterm"
)

// Confirm is a regular text input that accept yes/no answers.
type Confirm struct {
	Message string
	Default bool
	Answer  *bool
}

// data available to the templates when processing
type ConfirmTemplateData struct {
	Confirm
	Answer string
}

// Templates with Color formatting. See Documentation: https://github.com/mgutz/ansi#style-format
var ConfirmQuestionTemplate = `
{{- color "green+hb"}}? {{color "reset"}}
{{- color "default+hb"}}{{ .Message }} {{color "reset"}}
{{- if .Answer}}
  {{- color "cyan"}}{{.Answer}}{{color "reset"}}
{{- else }}
  {{- color "white"}}{{if .Default}}(Y/n) {{else}}(y/N) {{end}}{{color "reset"}}
{{- end}}`

func yesNo(t bool) string {
	if t {
		return "Yes"
	}
	return "No"
}

// Prompt prompts the user with a simple text field and expects a reply followed
// by a carriage return.
func (confirm *Confirm) Prompt() (string, error) {
	if confirm.Answer == nil {
		answer := false
		confirm.Answer = &answer
	}
	out, err := runTemplate(
		ConfirmQuestionTemplate,
		ConfirmTemplateData{Confirm: *confirm},
	)
	if err != nil {
		return "", err
	}

	// print the question we were given to kick off the prompt
	fmt.Print(out)

	// a scanner to look at the input from stdin
	scanner := bufio.NewScanner(os.Stdin)
	// wait for a response
	yesRx := regexp.MustCompile("^(?i:y(?:es)?)$")
	noRx := regexp.MustCompile("^(?i:n(?:o)?)$")
	answer := confirm.Default
	for scanner.Scan() {
		// get the availible text in the scanner
		res := scanner.Text()
		// if there is no answer
		if res == "" {
			// use the default
			break
		}
		// is answer yes?
		if yesRx.Match([]byte(res)) {
			answer = true
			break
		}

		// is answer "no"
		if noRx.Match([]byte(res)) {
			answer = false
			break
		}

		// we didnt get a valid answer, so print error and prompt again
		out, err := runTemplate(ErrorTemplate, fmt.Errorf("%q is not a valid answer, try again", res))
		if err != nil {
			return "", err
		}
		// send the message to the user
		fmt.Print(out)
		return confirm.Prompt()
	}

	// return the value
	*confirm.Answer = answer
	return yesNo(answer), nil
}

// Cleanup overwrite the line with the finalized formatted version
func (confirm *Confirm) Cleanup(val string) error {
	// get the current cursor location
	loc, err := CursorLocation()
	// if something went wrong
	if err != nil {
		// bubble
		return err
	}

	var initLoc int
	// if we are printing at the end of the console
	if loc.col == tm.Height() {
		initLoc = loc.col - 2
	} else {
		initLoc = loc.col - 1
	}

	// move to the beginning of the current line
	tm.MoveCursor(initLoc, 1)

	out, err := runTemplate(
		ConfirmQuestionTemplate,
		ConfirmTemplateData{Confirm: *confirm, Answer: val},
	)
	if err != nil {
		return err
	}

	tm.Print(out, AnsiClearLine)
	tm.Flush()

	// nothing went wrong
	return nil
}
<|endoftext|>


<commit_before>package model

import (
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/stretchr/testify/assert"
)

func TestSetInstance(t *testing.T) {
	i := NewInstance(&ec2.Instance{
		InstanceId: aws.String("i-1000000"),
	})
	eni := NewENI(&ec2.NetworkInterface{})

	eni.SetInstance(i)

	assert.Equal(t, eni.instance, i)
}

func TestInterfaceID(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
	})

	assert.Equal(t, eni.InterfaceID(), "eni-2222222")
}

func TestPrivateDnsName(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		PrivateDnsName: aws.String("ip-10-0-0-100.ap-northeast-1.compute.internal"),
	})

	assert.Equal(t, eni.PrivateDnsName(), "ip-10-0-0-100.ap-northeast-1.compute.internal")
}

func TestPrivateIpAddress(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		PrivateIpAddress: aws.String("10.0.0.100"),
	})

	assert.Equal(t, eni.PrivateIpAddress(), "10.0.0.100")
}

func TestStatus(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Status: aws.String("in-use"),
	})

	assert.Equal(t, eni.Status(), "in-use")
}

func TestAttachmentID(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			AttachmentId: aws.String("eni-attach-11111111"),
		},
	})

	assert.Equal(t, eni.AttachmentID(), "eni-attach-11111111")

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: nil,
	})

	assert.Equal(t, eni.AttachmentID(), "")

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			AttachmentId: nil,
		},
	})

	assert.Equal(t, eni.AttachmentID(), "")
}

func TestAttachedDeviceIndex(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			DeviceIndex: aws.Int64(0),
		},
	})

	assert.Equal(t, eni.AttachedDeviceIndex(), int64(0))

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: nil,
	})

	assert.Equal(t, eni.AttachedDeviceIndex(), int64(-1))

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			DeviceIndex: nil,
		},
	})

	assert.Equal(t, eni.AttachedDeviceIndex(), int64(-1))
}

func TestAttachedStatus(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			Status: aws.String("in-use"),
		},
	})

	assert.Equal(t, eni.AttachedStatus(), "in-use")

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: nil,
	})

	assert.Equal(t, eni.AttachedStatus(), "")

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			Status: nil,
		},
	})

	assert.Equal(t, eni.AttachedStatus(), "")
}

func TestAttachedInstanceID(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			InstanceId: aws.String("i-1111111"),
		},
	})

	assert.Equal(t, eni.AttachedInstanceID(), "i-1111111")

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: nil,
	})

	assert.Equal(t, eni.AttachedInstanceID(), "")

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			InstanceId: nil,
		},
	})

	assert.Equal(t, eni.AttachedInstanceID(), "")
}
<commit_msg>Add TestAttachedInstance<commit_after>package model

import (
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/stretchr/testify/assert"
)

func TestSetInstance(t *testing.T) {
	i := NewInstance(&ec2.Instance{
		InstanceId: aws.String("i-1000000"),
	})
	eni := NewENI(&ec2.NetworkInterface{})

	eni.SetInstance(i)

	assert.Equal(t, eni.instance, i)
}

func TestInterfaceID(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
	})

	assert.Equal(t, eni.InterfaceID(), "eni-2222222")
}

func TestPrivateDnsName(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		PrivateDnsName: aws.String("ip-10-0-0-100.ap-northeast-1.compute.internal"),
	})

	assert.Equal(t, eni.PrivateDnsName(), "ip-10-0-0-100.ap-northeast-1.compute.internal")
}

func TestPrivateIpAddress(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		PrivateIpAddress: aws.String("10.0.0.100"),
	})

	assert.Equal(t, eni.PrivateIpAddress(), "10.0.0.100")
}

func TestStatus(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Status: aws.String("in-use"),
	})

	assert.Equal(t, eni.Status(), "in-use")
}

func TestAttachmentID(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			AttachmentId: aws.String("eni-attach-11111111"),
		},
	})

	assert.Equal(t, eni.AttachmentID(), "eni-attach-11111111")

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: nil,
	})

	assert.Equal(t, eni.AttachmentID(), "")

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			AttachmentId: nil,
		},
	})

	assert.Equal(t, eni.AttachmentID(), "")
}

func TestAttachedDeviceIndex(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			DeviceIndex: aws.Int64(0),
		},
	})

	assert.Equal(t, eni.AttachedDeviceIndex(), int64(0))

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: nil,
	})

	assert.Equal(t, eni.AttachedDeviceIndex(), int64(-1))

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			DeviceIndex: nil,
		},
	})

	assert.Equal(t, eni.AttachedDeviceIndex(), int64(-1))
}

func TestAttachedStatus(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			Status: aws.String("in-use"),
		},
	})

	assert.Equal(t, eni.AttachedStatus(), "in-use")

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: nil,
	})

	assert.Equal(t, eni.AttachedStatus(), "")

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			Status: nil,
		},
	})

	assert.Equal(t, eni.AttachedStatus(), "")
}

func TestAttachedInstanceID(t *testing.T) {
	eni := NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			InstanceId: aws.String("i-1111111"),
		},
	})

	assert.Equal(t, eni.AttachedInstanceID(), "i-1111111")

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: nil,
	})

	assert.Equal(t, eni.AttachedInstanceID(), "")

	eni = NewENI(&ec2.NetworkInterface{
		NetworkInterfaceId: aws.String("eni-2222222"),
		Attachment: &ec2.NetworkInterfaceAttachment{
			InstanceId: nil,
		},
	})

	assert.Equal(t, eni.AttachedInstanceID(), "")
}

func TestAttachedInstance(t *testing.T) {
	i := NewInstance(&ec2.Instance{
		InstanceId: aws.String("i-1000000"),
	})
	eni := NewENI(&ec2.NetworkInterface{})

	eni.SetInstance(i)

	assert.Equal(t, *eni.AttachedInstance().InstanceId, "i-1000000")
}
<|endoftext|>


<commit_before>package config

// Local configuration from the filesystem

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

type FilesConfig struct {
    Path        string
}

type Files struct {
    config      FilesConfig
}

func (self *Files) String() string {
    return fmt.Sprintf("%s", self.config.Path)
}

func (self FilesConfig) Open() (*Files, error) {
    files := &Files{config: self}

    return files, nil
}

// Recursively any Config's under given path
func (self *Files) Scan() (configs []Config, err error) {
    err = filepath.Walk(self.config.Path, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }

        node := Node{
            Path:   strings.Trim(strings.TrimPrefix(path, self.config.Path), "/"),
            IsDir:  info.IsDir(),
        }

        if info.Mode().IsRegular() {
            if value, err := ioutil.ReadFile(path); err != nil {
                return err
            } else {
                node.Value = string(value)
            }
        }

        if config, err := syncConfig(node); err != nil {
            return err
        } else if config != nil {
            configs = append(configs, config)
        }

        return nil
    })

    return
}
<commit_msg>config files: skip .dotfiles<commit_after>package config

// Local configuration from the filesystem

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

type FilesConfig struct {
    Path        string
}

type Files struct {
    config      FilesConfig
}

func (self *Files) String() string {
    return fmt.Sprintf("%s", self.config.Path)
}

func (self FilesConfig) Open() (*Files, error) {
    files := &Files{config: self}

    return files, nil
}

// Recursively any Config's under given path
func (self *Files) Scan() (configs []Config, err error) {
    err = filepath.Walk(self.config.Path, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }

        if strings.HasPrefix(info.Name(), ".") {
            // skip
            return nil
        }

        node := Node{
            Path:   strings.Trim(strings.TrimPrefix(path, self.config.Path), "/"),
            IsDir:  info.IsDir(),
        }

        if info.Mode().IsRegular() {
            if value, err := ioutil.ReadFile(path); err != nil {
                return err
            } else {
                node.Value = string(value)
            }
        }

        if config, err := syncConfig(node); err != nil {
            return err
        } else if config != nil {
            configs = append(configs, config)
        }

        return nil
    })

    return
}
<|endoftext|>


<commit_before>package confl

import (
	// "path/filepath"
	// "strings"
	// . "polydawn.net/docket/util"
)
/*
//Extract a configuration target from loaded settings.
//Each config will override the one after it.
func (cs *ConfigFile) GetConfig(target string) *Settings {
	config := DefaultSettings

	//For each config
	for i := len(cs.configs) - 1; i >= 0; i-- {
		newConfig := cs.configs[i]
		meta   := cs.metas[i]

		//If default target is provided, load it unconditionally
		if meta.IsDefined(DefaultTarget) {
			addConfig(&config, newConfig[DefaultTarget], meta, DefaultTarget)
		}

		//If default target is provided, load it unconditionally
		if target != DefaultTarget && meta.IsDefined(target) {
			addConfig(&config, newConfig[target], meta, target)
		}
	}

	return &config
}

//Preprocess a configuration object
func preprocess(c *Settings, dir string) {
	//Get the absolute directory this config is relative to
	cwd, err := filepath.Abs(dir)
	if err != nil { ExitGently("Cannot determine absolute path: ", dir) }

	//Handle mounts
	for i := range c.Mounts {

		//Check for triple-dot ... notation, which is relative to that config's directory, not the CWD
		if strings.Index(c.Mounts[i][0], "...") != 1 {
			c.Mounts[i][0] = strings.Replace(c.Mounts[i][0], "...", cwd, 1)
		}

		//Find the absolute path for each host mount
		abs, err := filepath.Abs(c.Mounts[i][0])
		if err != nil { ExitGently("Cannot determine absolute path:", c.Mounts[i][0]) }
		c.Mounts[i][0] = abs
	}
}

//Loads a configuration object, overriding the base
func addConfig(base *Settings, inc Settings, meta toml.MetaData, target string) {

	if meta.IsDefined(target, "command") {
		base.Command = inc.Command
	}

	if meta.IsDefined(target, "folder") {
		base.Folder = inc.Folder
	}

	if meta.IsDefined(target, "privileged") {
		base.Privileged = inc.Privileged
	}

	if meta.IsDefined(target, "mounts") {
		base.Mounts = append(base.Mounts, inc.Mounts...)
	}

	if meta.IsDefined(target, "ports") {
		base.Ports = append(base.Ports, inc.Ports...)
	}

	if meta.IsDefined(target, "dns") {
		base.DNS = append(base.DNS, inc.DNS...)
	}

	if meta.IsDefined(target, "attach") {
		base.Attach = inc.Attach
	}

	if meta.IsDefined(target, "purge") {
		base.Purge = inc.Purge
	}

	if meta.IsDefined(target, "environment") {
		base.Environment = append(base.Environment, inc.Environment...)
	}
}
*/
<commit_msg>Removed old file<commit_after><|endoftext|>


<commit_before>package container551

import (
	"github.com/go51/auth551"
	"github.com/go51/cookie551"
	"github.com/go51/log551"
	"github.com/go51/memcache551"
	"github.com/go51/model551"
	"github.com/go51/mysql551"
	"github.com/go51/repository551"
	"github.com/go51/secure551"
	"github.com/go51/string551"
	xoauth2 "golang.org/x/oauth2"
	"net/http"
	"strconv"
)

type Container struct {
	sid     string
	ssid    string
	w       http.ResponseWriter
	r       *http.Request
	logger  *log551.Log551
	cookie  *cookie551.Cookie
	db      *mysql551.Mysql
	session *memcache551.Memcache
	model   *model551.Model
	auth    *auth551.Auth
	user    *auth551.UserModel
	options map[string]string
}

func New() *Container {
	return &Container{}
}

func (c *Container) SetSID(sid string) {
	c.sid = sid
	c.ssid = sid[:10]
}

func (c *Container) SID() string {
	return c.sid
}
func (c *Container) SSID() string {
	return c.ssid
}

func (c *Container) SetResponseWriter(w http.ResponseWriter) {
	c.w = w
}

func (c *Container) ResponseWriter() http.ResponseWriter {
	return c.w
}

func (c *Container) SetRequest(r *http.Request) {
	c.r = r
}

func (c *Container) Request() *http.Request {
	return c.r
}

func (c *Container) SetLogger(logger *log551.Log551) {
	c.logger = logger
}

func (c *Container) Logger() *log551.Log551 {
	return c.logger
}

func (c *Container) SetCookie(cookie *cookie551.Cookie) {
	c.cookie = cookie
}

func (c *Container) Cookie() *cookie551.Cookie {
	return c.cookie
}

func (c *Container) SetDb(db *mysql551.Mysql) {
	c.db = db
}

func (c *Container) Db() *mysql551.Mysql {
	return c.db
}

func (c *Container) SetSession(session *memcache551.Memcache) {
	c.session = session
}

func (c *Container) Session() *memcache551.Memcache {
	return c.session
}

func (c *Container) SetModel(modelManager *model551.Model) {
	c.model = modelManager
}

func (c *Container) ModelManager() *model551.Model {
	return c.model
}

func (c *Container) SetAuth(auth *auth551.Auth) {
	c.auth = auth

	if c.user != nil {
		return
	}

	// Load user from session
	c.session.GetModel("reminder_user", &c.user)

	// Get user id from cookie
	id, err := c.getRemindId()
	if err != nil {
		return
	}

	// Get user model from database
	c.user = c.getUser(id)

	// Set user model to session
	c.session.Set("reminder_user", c.user)

	return

}

func (c *Container) getRemindId() (int64, error) {
	cookieId, err := c.cookie.Get(c.auth.CookieKeyName())
	if err != nil {
		return 0, err
	}

	sid := secure551.Decrypted(cookieId, c.auth.MasterKey())
	id, err := strconv.ParseInt(sid, 10, 64)
	if err != nil {
		return 0, err
	}

	return id, nil

}

func (c *Container) getUser(id int64) *auth551.UserModel {
	repo := repository551.Load()
	miUser := c.ModelManager().Get("UserModel")
	mUser := repo.Find(c.db, miUser, id)
	user, ok := mUser.(*auth551.UserModel)
	if !ok {
		return nil
	}

	return user
}

func (c *Container) Auth() *auth551.Auth {
	return c.auth
}

func (c *Container) SignIn(user *auth551.UserModel) {
	// Set remind id to cookie
	id := string551.Right("0000000000000000"+strconv.FormatInt(user.Id, 10), 16)
	secureId := secure551.Encrypted(id, c.auth.MasterKey())
	c.cookie.Set(c.auth.CookieKeyName(), secureId, 60*60*24*365)

	// Set user model to session
	c.session.Set("reminder_user", user)

}

func (c *Container) SignOut() {
	c.cookie.Delete(c.auth.CookieKeyName())
	c.session.Delete("reminder_user")
}

func (c *Container) IsSignIn() bool {
	return c.user != nil
}

func (c *Container) User() *auth551.UserModel {
	return c.user
}

func (c *Container) ApiClient(vendor auth551.AuthVendor) *http.Client {
	if c.user == nil {
		return nil
	}
	repo := repository551.Load()
	miUserToken := c.model.Get("UserTokenModel")
	param := map[string]interface{}{
		"user_id": c.user.Id,
	}
	mUserToken := repo.FindOneBy(c.db, miUserToken, param)
	userToken, ok := mUserToken.(*auth551.UserTokenModel)
	if !ok {
		return nil
	}

	token := &xoauth2.Token{
		AccessToken:  userToken.AccessToken,
		TokenType:    userToken.TokenType,
		RefreshToken: userToken.RefreshToken,
		Expiry:       userToken.Expiry,
	}

	return c.auth.Client(vendor, token)

}

func (c *Container) SetCommandOptions(options map[string]string) {
	c.options = options
}

func (c *Container) CommandOption(name string) string {
	return c.options[name]
}
<commit_msg>refs #29 URL 生成用の func を保持し使用できるようにする<commit_after>package container551

import (
	"errors"
	"github.com/go51/auth551"
	"github.com/go51/cookie551"
	"github.com/go51/log551"
	"github.com/go51/memcache551"
	"github.com/go51/model551"
	"github.com/go51/mysql551"
	"github.com/go51/repository551"
	"github.com/go51/secure551"
	"github.com/go51/string551"
	xoauth2 "golang.org/x/oauth2"
	"net/http"
	"strconv"
)

type urlFunc func(name string, parameter ...string) string

type Container struct {
	sid         string
	ssid        string
	w           http.ResponseWriter
	r           *http.Request
	logger      *log551.Log551
	cookie      *cookie551.Cookie
	db          *mysql551.Mysql
	session     *memcache551.Memcache
	model       *model551.Model
	auth        *auth551.Auth
	user        *auth551.UserModel
	options     map[string]string
	urlFunction urlFunc
}

func New() *Container {
	return &Container{}
}

func (c *Container) SetSID(sid string) {
	c.sid = sid
	c.ssid = sid[:10]
}

func (c *Container) SID() string {
	return c.sid
}
func (c *Container) SSID() string {
	return c.ssid
}

func (c *Container) SetResponseWriter(w http.ResponseWriter) {
	c.w = w
}

func (c *Container) ResponseWriter() http.ResponseWriter {
	return c.w
}

func (c *Container) SetRequest(r *http.Request) {
	c.r = r
}

func (c *Container) Request() *http.Request {
	return c.r
}

func (c *Container) SetLogger(logger *log551.Log551) {
	c.logger = logger
}

func (c *Container) Logger() *log551.Log551 {
	return c.logger
}

func (c *Container) SetCookie(cookie *cookie551.Cookie) {
	c.cookie = cookie
}

func (c *Container) Cookie() *cookie551.Cookie {
	return c.cookie
}

func (c *Container) SetDb(db *mysql551.Mysql) {
	c.db = db
}

func (c *Container) Db() *mysql551.Mysql {
	return c.db
}

func (c *Container) SetSession(session *memcache551.Memcache) {
	c.session = session
}

func (c *Container) Session() *memcache551.Memcache {
	return c.session
}

func (c *Container) SetModel(modelManager *model551.Model) {
	c.model = modelManager
}

func (c *Container) ModelManager() *model551.Model {
	return c.model
}

func (c *Container) SetAuth(auth *auth551.Auth) {
	c.auth = auth

	if c.user != nil {
		return
	}

	// Load user from session
	c.session.GetModel("reminder_user", &c.user)

	// Get user id from cookie
	id, err := c.getRemindId()
	if err != nil {
		return
	}

	// Get user model from database
	c.user = c.getUser(id)

	// Set user model to session
	c.session.Set("reminder_user", c.user)

	return

}

func (c *Container) getRemindId() (int64, error) {
	cookieId, err := c.cookie.Get(c.auth.CookieKeyName())
	if err != nil {
		return 0, err
	}

	sid := secure551.Decrypted(cookieId, c.auth.MasterKey())
	id, err := strconv.ParseInt(sid, 10, 64)
	if err != nil {
		return 0, err
	}

	return id, nil

}

func (c *Container) getUser(id int64) *auth551.UserModel {
	repo := repository551.Load()
	miUser := c.ModelManager().Get("UserModel")
	mUser := repo.Find(c.db, miUser, id)
	user, ok := mUser.(*auth551.UserModel)
	if !ok {
		return nil
	}

	return user
}

func (c *Container) Auth() *auth551.Auth {
	return c.auth
}

func (c *Container) SignIn(user *auth551.UserModel) {
	// Set remind id to cookie
	id := string551.Right("0000000000000000"+strconv.FormatInt(user.Id, 10), 16)
	secureId := secure551.Encrypted(id, c.auth.MasterKey())
	c.cookie.Set(c.auth.CookieKeyName(), secureId, 60*60*24*365)

	// Set user model to session
	c.session.Set("reminder_user", user)

}

func (c *Container) SignOut() {
	c.cookie.Delete(c.auth.CookieKeyName())
	c.session.Delete("reminder_user")
}

func (c *Container) IsSignIn() bool {
	return c.user != nil
}

func (c *Container) User() *auth551.UserModel {
	return c.user
}

func (c *Container) ApiClient(vendor auth551.AuthVendor) *http.Client {
	if c.user == nil {
		return nil
	}
	repo := repository551.Load()
	miUserToken := c.model.Get("UserTokenModel")
	param := map[string]interface{}{
		"user_id": c.user.Id,
	}
	mUserToken := repo.FindOneBy(c.db, miUserToken, param)
	userToken, ok := mUserToken.(*auth551.UserTokenModel)
	if !ok {
		return nil
	}

	token := &xoauth2.Token{
		AccessToken:  userToken.AccessToken,
		TokenType:    userToken.TokenType,
		RefreshToken: userToken.RefreshToken,
		Expiry:       userToken.Expiry,
	}

	return c.auth.Client(vendor, token)

}

func (c *Container) SetCommandOptions(options map[string]string) {
	c.options = options
}

func (c *Container) CommandOption(name string) string {
	return c.options[name]
}

func (c *Container) Segment(number int) string {
	c.logger.Debugf("%s [ URL.Path ] %s", c.ssid, c.r.URL.Path[1:])
	paths := string551.Split(c.r.URL.Path[1:], "/")
	c.logger.Debugf("%s [ URL.Path ] %#v", c.ssid, paths)
	if len(paths) < number+1 {
		return ""
	}
	return paths[number]
}

func (c *Container) SegmentInt64(number int) (int64, error) {
	c.logger.Debugf("%s [ URL.Path ] %s", c.ssid, c.r.URL.Path[1:])
	paths := string551.Split(c.r.URL.Path[1:], "/")
	c.logger.Debugf("%s [ URL.Path ] %#v", c.ssid, paths)
	if len(paths) < number+1 {
		return 0, errors.New("invalid memory address or nil pointer dereference")
	}
	segment := paths[number]

	return strconv.ParseInt(segment, 10, 64)

}

func (c *Container) SetUrlFunc(urlFunction urlFunc) {
	c.urlFunction = urlFunction
}

func (c *Container) URL(name string, parameter ...string) string {
	return c.urlFunction(name, parameter...)
}
<|endoftext|>


<commit_before>package commands

import (
	"path/filepath"
	"strings"

	"github.com/git-lfs/git-lfs/errors"
	"github.com/git-lfs/git-lfs/git"
	"github.com/git-lfs/git-lfs/git/githistory"
	"github.com/git-lfs/git-lfs/git/githistory/log"
	"github.com/git-lfs/git-lfs/git/odb"
	"github.com/spf13/cobra"
)

var (
	// migrateIncludeRefs is a set of Git references to explicitly include
	// in the migration.
	migrateIncludeRefs []string
	// migrateExcludeRefs is a set of Git references to explicitly exclude
	// in the migration.
	migrateExcludeRefs []string

	// migrateEverything indicates the presence of the --everything flag,
	// and instructs 'git lfs migrate' to migrate all local references.
	migrateEverything bool
)

// migrate takes the given command and arguments, *odb.ObjectDatabase, as well
// as a BlobRewriteFn to apply, and performs a migration.
func migrate(args []string, r *githistory.Rewriter, l *log.Logger, opts *githistory.RewriteOptions) {
	requireInRepo()

	opts, err := rewriteOptions(args, opts, l)
	if err != nil {
		ExitWithError(err)
	}

	_, err = r.Rewrite(opts)
	if err != nil {
		ExitWithError(err)
	}
}

// getObjectDatabase creates a *git.ObjectDatabase from the filesystem pointed
// at the .git directory of the currently checked-out repository.
func getObjectDatabase() (*odb.ObjectDatabase, error) {
	dir, err := git.GitDir()
	if err != nil {
		return nil, errors.Wrap(err, "cannot open root")
	}
	return odb.FromFilesystem(filepath.Join(dir, "objects"))
}

// rewriteOptions returns *githistory.RewriteOptions able to be passed to a
// *githistory.Rewriter that reflect the current arguments and flags passed to
// an invocation of git-lfs-migrate(1).
//
// It is merged with the given "opts". In other words, an identical "opts" is
// returned, where the Include and Exclude fields have been filled based on the
// following rules:
//
// The included and excluded references are determined based on the output of
// includeExcludeRefs (see below for documentation and detail).
//
// If any of the above could not be determined without error, that error will be
// returned immediately.
func rewriteOptions(args []string, opts *githistory.RewriteOptions, l *log.Logger) (*githistory.RewriteOptions, error) {
	include, exclude, err := includeExcludeRefs(l, args)
	if err != nil {
		return nil, err
	}

	return &githistory.RewriteOptions{
		Include: include,
		Exclude: exclude,

		UpdateRefs: opts.UpdateRefs,

		BlobFn:         opts.BlobFn,
		TreeCallbackFn: opts.TreeCallbackFn,
	}, nil
}

// includeExcludeRefs returns fully-qualified sets of references to include, and
// exclude, or an error if those could not be determined.
//
// They are determined based on the following rules:
//
//   - Include all local refs/heads/<branch> references for each branch
//     specified as an argument.
//   - Include the currently checked out branch if no branches are given as
//     arguments and the --include-ref= or --exclude-ref= flag(s) aren't given.
//   - Include all references given in --include-ref=<ref>.
//   - Exclude all references given in --exclude-ref=<ref>.
func includeExcludeRefs(l *log.Logger, args []string) (include, exclude []string, err error) {
	hardcore := len(migrateIncludeRefs) > 0 || len(migrateExcludeRefs) > 0

	if len(args) == 0 && !hardcore && !migrateEverything {
		// If no branches were given explicitly AND neither
		// --include-ref or --exclude-ref flags were given, then add the
		// currently checked out reference.
		current, err := currentRefToMigrate()
		if err != nil {
			return nil, nil, err
		}
		args = append(args, current.Name)
	}

	if migrateEverything && len(args) > 0 {
		return nil, nil, errors.New("fatal: cannot use --everything with explicit reference arguments")
	}

	for _, name := range args {
		// Then, loop through each branch given, resolve that reference,
		// and include it.
		ref, err := git.ResolveRef(name)
		if err != nil {
			return nil, nil, err
		}

		include = append(include, ref.Name)
	}

	if hardcore {
		if migrateEverything {
			return nil, nil, errors.New("fatal: cannot use --everything with --include-ref or --exclude-ref")
		}

		// If either --include-ref=<ref> or --exclude-ref=<ref> were
		// given, append those to the include and excluded reference
		// set, respectively.
		include = append(include, migrateIncludeRefs...)
		exclude = append(exclude, migrateExcludeRefs...)
	} else if migrateEverything {
		localRefs, err := git.LocalRefs()
		if err != nil {
			return nil, nil, err
		}

		for _, ref := range localRefs {
			include = append(include, ref.Name)
		}
	} else {
		// Otherwise, if neither --include-ref=<ref> or
		// --exclude-ref=<ref> were given, include no additional
		// references, and exclude all remote references that are remote
		// branches or remote tags.
		remoteRefs, err := getRemoteRefs(l)
		if err != nil {
			return nil, nil, err
		}

		exclude = append(exclude, remoteRefs...)
	}

	return include, exclude, nil
}

// getRemoteRefs returns a fully qualified set of references belonging to all
// remotes known by the currently checked-out repository, or an error if those
// references could not be determined.
func getRemoteRefs(l *log.Logger) ([]string, error) {
	var refs []string

	remotes, err := git.RemoteList()
	if err != nil {
		return nil, err
	}

	w := l.Waiter("migrate: Fetching remote refs")
	if err := git.Fetch(remotes...); err != nil {
		return nil, err
	}
	w.Complete()

	for _, remote := range remotes {
		refsForRemote, err := git.RemoteRefs(remote)
		if err != nil {
			return nil, err
		}

		for _, ref := range refsForRemote {
			refs = append(refs, formatRefName(ref, remote))
		}
	}

	return refs, nil
}

// formatRefName returns the fully-qualified name for the given Git reference
// "ref".
func formatRefName(ref *git.Ref, remote string) string {
	var name []string

	switch ref.Type {
	case git.RefTypeRemoteBranch:
		name = []string{"refs", "remotes", remote, ref.Name}
	case git.RefTypeRemoteTag:
		name = []string{"refs", "tags", ref.Name}
	default:
		return ref.Name
	}
	return strings.Join(name, "/")

}

// currentRefToMigrate returns the fully-qualified name of the currently
// checked-out reference, or an error if the reference's type was not a local
// branch.
func currentRefToMigrate() (*git.Ref, error) {
	current, err := git.CurrentRef()
	if err != nil {
		return nil, err
	}

	if current.Type == git.RefTypeOther ||
		current.Type == git.RefTypeRemoteBranch ||
		current.Type == git.RefTypeRemoteTag {

		return nil, errors.Errorf("fatal: cannot migrate non-local ref: %s", current.Name)
	}
	return current, nil
}

// getHistoryRewriter returns a history rewriter that includes the filepath
// filter given by the --include and --exclude arguments.
func getHistoryRewriter(cmd *cobra.Command, db *odb.ObjectDatabase, l *log.Logger) *githistory.Rewriter {
	include, exclude := getIncludeExcludeArgs(cmd)
	filter := buildFilepathFilter(cfg, include, exclude)

	return githistory.NewRewriter(db,
		githistory.WithFilter(filter), githistory.WithLogger(l))
}

func init() {
	info := NewCommand("info", migrateInfoCommand)
	info.Flags().IntVar(&migrateInfoTopN, "top", 5, "--top=<n>")
	info.Flags().StringVar(&migrateInfoAboveFmt, "above", "", "--above=<n>")
	info.Flags().StringVar(&migrateInfoUnitFmt, "unit", "", "--unit=<unit>")

	importCmd := NewCommand("import", migrateImportCommand)

	RegisterCommand("migrate", nil, func(cmd *cobra.Command) {
		cmd.PersistentFlags().StringVarP(&includeArg, "include", "I", "", "Include a list of paths")
		cmd.PersistentFlags().StringVarP(&excludeArg, "exclude", "X", "", "Exclude a list of paths")

		cmd.PersistentFlags().StringSliceVar(&migrateIncludeRefs, "include-ref", nil, "An explicit list of refs to include")
		cmd.PersistentFlags().StringSliceVar(&migrateExcludeRefs, "exclude-ref", nil, "An explicit list of refs to exclude")
		cmd.PersistentFlags().BoolVar(&migrateEverything, "everything", false, "Migrate all local references")

		for _, subcommand := range []*cobra.Command{
			importCmd, info,
		} {
			cmd.AddCommand(subcommand)
		}
	})
}
<commit_msg>commands/migrate: use varargs variant of AddCommand<commit_after>package commands

import (
	"path/filepath"
	"strings"

	"github.com/git-lfs/git-lfs/errors"
	"github.com/git-lfs/git-lfs/git"
	"github.com/git-lfs/git-lfs/git/githistory"
	"github.com/git-lfs/git-lfs/git/githistory/log"
	"github.com/git-lfs/git-lfs/git/odb"
	"github.com/spf13/cobra"
)

var (
	// migrateIncludeRefs is a set of Git references to explicitly include
	// in the migration.
	migrateIncludeRefs []string
	// migrateExcludeRefs is a set of Git references to explicitly exclude
	// in the migration.
	migrateExcludeRefs []string

	// migrateEverything indicates the presence of the --everything flag,
	// and instructs 'git lfs migrate' to migrate all local references.
	migrateEverything bool
)

// migrate takes the given command and arguments, *odb.ObjectDatabase, as well
// as a BlobRewriteFn to apply, and performs a migration.
func migrate(args []string, r *githistory.Rewriter, l *log.Logger, opts *githistory.RewriteOptions) {
	requireInRepo()

	opts, err := rewriteOptions(args, opts, l)
	if err != nil {
		ExitWithError(err)
	}

	_, err = r.Rewrite(opts)
	if err != nil {
		ExitWithError(err)
	}
}

// getObjectDatabase creates a *git.ObjectDatabase from the filesystem pointed
// at the .git directory of the currently checked-out repository.
func getObjectDatabase() (*odb.ObjectDatabase, error) {
	dir, err := git.GitDir()
	if err != nil {
		return nil, errors.Wrap(err, "cannot open root")
	}
	return odb.FromFilesystem(filepath.Join(dir, "objects"))
}

// rewriteOptions returns *githistory.RewriteOptions able to be passed to a
// *githistory.Rewriter that reflect the current arguments and flags passed to
// an invocation of git-lfs-migrate(1).
//
// It is merged with the given "opts". In other words, an identical "opts" is
// returned, where the Include and Exclude fields have been filled based on the
// following rules:
//
// The included and excluded references are determined based on the output of
// includeExcludeRefs (see below for documentation and detail).
//
// If any of the above could not be determined without error, that error will be
// returned immediately.
func rewriteOptions(args []string, opts *githistory.RewriteOptions, l *log.Logger) (*githistory.RewriteOptions, error) {
	include, exclude, err := includeExcludeRefs(l, args)
	if err != nil {
		return nil, err
	}

	return &githistory.RewriteOptions{
		Include: include,
		Exclude: exclude,

		UpdateRefs: opts.UpdateRefs,

		BlobFn:         opts.BlobFn,
		TreeCallbackFn: opts.TreeCallbackFn,
	}, nil
}

// includeExcludeRefs returns fully-qualified sets of references to include, and
// exclude, or an error if those could not be determined.
//
// They are determined based on the following rules:
//
//   - Include all local refs/heads/<branch> references for each branch
//     specified as an argument.
//   - Include the currently checked out branch if no branches are given as
//     arguments and the --include-ref= or --exclude-ref= flag(s) aren't given.
//   - Include all references given in --include-ref=<ref>.
//   - Exclude all references given in --exclude-ref=<ref>.
func includeExcludeRefs(l *log.Logger, args []string) (include, exclude []string, err error) {
	hardcore := len(migrateIncludeRefs) > 0 || len(migrateExcludeRefs) > 0

	if len(args) == 0 && !hardcore && !migrateEverything {
		// If no branches were given explicitly AND neither
		// --include-ref or --exclude-ref flags were given, then add the
		// currently checked out reference.
		current, err := currentRefToMigrate()
		if err != nil {
			return nil, nil, err
		}
		args = append(args, current.Name)
	}

	if migrateEverything && len(args) > 0 {
		return nil, nil, errors.New("fatal: cannot use --everything with explicit reference arguments")
	}

	for _, name := range args {
		// Then, loop through each branch given, resolve that reference,
		// and include it.
		ref, err := git.ResolveRef(name)
		if err != nil {
			return nil, nil, err
		}

		include = append(include, ref.Name)
	}

	if hardcore {
		if migrateEverything {
			return nil, nil, errors.New("fatal: cannot use --everything with --include-ref or --exclude-ref")
		}

		// If either --include-ref=<ref> or --exclude-ref=<ref> were
		// given, append those to the include and excluded reference
		// set, respectively.
		include = append(include, migrateIncludeRefs...)
		exclude = append(exclude, migrateExcludeRefs...)
	} else if migrateEverything {
		localRefs, err := git.LocalRefs()
		if err != nil {
			return nil, nil, err
		}

		for _, ref := range localRefs {
			include = append(include, ref.Name)
		}
	} else {
		// Otherwise, if neither --include-ref=<ref> or
		// --exclude-ref=<ref> were given, include no additional
		// references, and exclude all remote references that are remote
		// branches or remote tags.
		remoteRefs, err := getRemoteRefs(l)
		if err != nil {
			return nil, nil, err
		}

		exclude = append(exclude, remoteRefs...)
	}

	return include, exclude, nil
}

// getRemoteRefs returns a fully qualified set of references belonging to all
// remotes known by the currently checked-out repository, or an error if those
// references could not be determined.
func getRemoteRefs(l *log.Logger) ([]string, error) {
	var refs []string

	remotes, err := git.RemoteList()
	if err != nil {
		return nil, err
	}

	w := l.Waiter("migrate: Fetching remote refs")
	if err := git.Fetch(remotes...); err != nil {
		return nil, err
	}
	w.Complete()

	for _, remote := range remotes {
		refsForRemote, err := git.RemoteRefs(remote)
		if err != nil {
			return nil, err
		}

		for _, ref := range refsForRemote {
			refs = append(refs, formatRefName(ref, remote))
		}
	}

	return refs, nil
}

// formatRefName returns the fully-qualified name for the given Git reference
// "ref".
func formatRefName(ref *git.Ref, remote string) string {
	var name []string

	switch ref.Type {
	case git.RefTypeRemoteBranch:
		name = []string{"refs", "remotes", remote, ref.Name}
	case git.RefTypeRemoteTag:
		name = []string{"refs", "tags", ref.Name}
	default:
		return ref.Name
	}
	return strings.Join(name, "/")

}

// currentRefToMigrate returns the fully-qualified name of the currently
// checked-out reference, or an error if the reference's type was not a local
// branch.
func currentRefToMigrate() (*git.Ref, error) {
	current, err := git.CurrentRef()
	if err != nil {
		return nil, err
	}

	if current.Type == git.RefTypeOther ||
		current.Type == git.RefTypeRemoteBranch ||
		current.Type == git.RefTypeRemoteTag {

		return nil, errors.Errorf("fatal: cannot migrate non-local ref: %s", current.Name)
	}
	return current, nil
}

// getHistoryRewriter returns a history rewriter that includes the filepath
// filter given by the --include and --exclude arguments.
func getHistoryRewriter(cmd *cobra.Command, db *odb.ObjectDatabase, l *log.Logger) *githistory.Rewriter {
	include, exclude := getIncludeExcludeArgs(cmd)
	filter := buildFilepathFilter(cfg, include, exclude)

	return githistory.NewRewriter(db,
		githistory.WithFilter(filter), githistory.WithLogger(l))
}

func init() {
	info := NewCommand("info", migrateInfoCommand)
	info.Flags().IntVar(&migrateInfoTopN, "top", 5, "--top=<n>")
	info.Flags().StringVar(&migrateInfoAboveFmt, "above", "", "--above=<n>")
	info.Flags().StringVar(&migrateInfoUnitFmt, "unit", "", "--unit=<unit>")

	importCmd := NewCommand("import", migrateImportCommand)

	RegisterCommand("migrate", nil, func(cmd *cobra.Command) {
		cmd.PersistentFlags().StringVarP(&includeArg, "include", "I", "", "Include a list of paths")
		cmd.PersistentFlags().StringVarP(&excludeArg, "exclude", "X", "", "Exclude a list of paths")

		cmd.PersistentFlags().StringSliceVar(&migrateIncludeRefs, "include-ref", nil, "An explicit list of refs to include")
		cmd.PersistentFlags().StringSliceVar(&migrateExcludeRefs, "exclude-ref", nil, "An explicit list of refs to exclude")
		cmd.PersistentFlags().BoolVar(&migrateEverything, "everything", false, "Migrate all local references")

		cmd.AddCommand(importCmd, info)
	})
}
<|endoftext|>


<commit_before>package GoSDK

//This file provides the interface for establishing connect collections
//that is to say, collections that are interfaced with non-platform databases
//they have to be treated a little bit differently, because a lot of configuration information
//needs to be trucked across the line during setup. enough that it's more helpful to have it in a
//struct than it is just in a map, or an endless list of function arguments.

type connectCollection interface {
	toMap() map[string]interface{}
	tableName() string
}

type MSSqlConfig struct {
	User, Password, Host, Port, DBName, Tablename string
}

func (ms MSSqlConfig) tableName() string { return ms.Tablename }

func (ms MSSqlConfig) toMap() map[string]interface{} {
	m := make(map[string]interface{})
	m["user"] = ms.User
	m["password"] = ms.Password
	m["address"] = ms.Host
	m["port"] = ms.Port
	m["dbname"] = ms.DBName
	m["tablename"] = ms.Tablename
	m["dbtype"] = "mssql"
	return m
}

type PostgresqlConfig struct {
	User, Password, Host, Port, DBName, Tablename string
}

func (pg PostgresqlConfig) toMap() map[string]interface{} {
	m := make(map[string]interface{})
	m["user"] = pg.User
	m["password"] = pg.Password
	m["address"] = pg.Host
	m["port"] = pg.Port
	m["dbname"] = pg.DBName
	m["tablename"] = pg.Tablename
	m["dbtype"] = "postgres"
	return m
}
<commit_msg>finish out interface<commit_after>package GoSDK

//This file provides the interface for establishing connect collections
//that is to say, collections that are interfaced with non-platform databases
//they have to be treated a little bit differently, because a lot of configuration information
//needs to be trucked across the line during setup. enough that it's more helpful to have it in a
//struct than it is just in a map, or an endless list of function arguments.

type connectCollection interface {
	toMap() map[string]interface{}
	tableName() string
}

type MSSqlConfig struct {
	User, Password, Host, Port, DBName, Tablename string
}

func (ms MSSqlConfig) tableName() string { return ms.Tablename }

func (ms MSSqlConfig) toMap() map[string]interface{} {
	m := make(map[string]interface{})
	m["user"] = ms.User
	m["password"] = ms.Password
	m["address"] = ms.Host
	m["port"] = ms.Port
	m["dbname"] = ms.DBName
	m["tablename"] = ms.Tablename
	m["dbtype"] = "mssql"
	return m
}

type PostgresqlConfig struct {
	User, Password, Host, Port, DBName, Tablename string
}

func (pg PostgresqlConfig) toMap() map[string]interface{} {
	m := make(map[string]interface{})
	m["user"] = pg.User
	m["password"] = pg.Password
	m["address"] = pg.Host
	m["port"] = pg.Port
	m["dbname"] = pg.DBName
	m["tablename"] = pg.Tablename
	m["dbtype"] = "postgres"
	return m
}

func (pg PostgresqlConfig) tableName() string { return pg.Tablename }
<|endoftext|>