<commit_before>package main

import (
	"os"

	"github.com/mitchellh/cli"
	"github.com/openebs/maya/command"
)

// Commands returns the mapping of CLI commands for Maya. The meta
// parameter lets you set meta options for all commands.
func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
	if metaPtr == nil {
		metaPtr = new(command.Meta)
	}

	meta := *metaPtr
	if meta.Ui == nil {
		meta.Ui = &cli.BasicUi{
			Reader:      os.Stdin,
			Writer:      os.Stdout,
			ErrorWriter: os.Stderr,
		}
	}

	return map[string]cli.CommandFactory{
		"setup-omm": func() (cli.Command, error) {
			return &command.InstallMayaCommand{
				M: meta,
			}, nil
		},
		"setup-osh": func() (cli.Command, error) {
			return &command.InstallOpenEBSCommand{
				M: meta,
			}, nil
		},
		"omm-status": func() (cli.Command, error) {
			return &command.ServerMembersCommand{
				Meta: meta,
			}, nil
		},
		"osh-status": func() (cli.Command, error) {
			return &command.NodeStatusCommand{
				Meta: meta,
			}, nil
		},

		"volume": func() (cli.Command, error) {
			return &command.VolumeCommand{}, nil
		},
		"volume create": func() (cli.Command, error) {
			return &command.VsmCreateCommand{
				Meta: meta,
			}, nil
		},
		"volume list": func() (cli.Command, error) {
			return &command.VsmListCommand{
				Meta: meta,
			}, nil
		},
		"volume stats": func() (cli.Command, error) {
			return &command.VsmStatsCommand{
				Meta: meta,
			}, nil
		},
		"volume update": func() (cli.Command, error) {
			return &command.VsmUpdateCommand{
				M: meta,
			}, nil
		},
		"volume stop": func() (cli.Command, error) {
			return &command.VsmStopCommand{
				Meta: meta,
			}, nil
		},
		"snapshot": func() (cli.Command, error) {
			return &command.SnapshotCommand{}, nil
		},

		"snapshot create": func() (cli.Command, error) {
			return &command.SnapshotCreateCommand{
				Meta: meta,
			}, nil
		},
		"snapshot list": func() (cli.Command, error) {
			return &command.SnapshotListCommand{
				Meta: meta,
			}, nil
		},

		"snapshot rm": func() (cli.Command, error) {
			return &command.SnapshotDeleteCommand{
				Meta: meta,
			}, nil
		},
		"snapshot revert": func() (cli.Command, error) {
			return &command.SnapshotRevertCommand{
				Meta: meta,
			}, nil
		},

		/*	"network-install": func() (cli.Command, error) {
				return &command.NetworkInstallCommand{
					M: meta,
				}, nil
			},
		*/
		"version": func() (cli.Command, error) {
			ver := Version
			rel := VersionPrerelease
			if GitDescribe != "" {
				ver = GitDescribe
				// Trim off a leading 'v', we append it anyways.
				if ver[0] == 'v' {
					ver = ver[1:]
				}
			}
			if GitDescribe == "" && rel == "" && VersionPrerelease != "" {
				rel = "dev"
			}

			return &command.VersionCommand{
				Revision:          GitCommit,
				Version:           ver,
				VersionPrerelease: rel,
				Ui:                meta.Ui,
			}, nil
		},
	}
}
<commit_msg>omm-status/osh-status CLI commands are removed(commented) Signed-off-by: gkGaneshR <gkganesh126@gmail.com><commit_after>package main

import (
	"os"

	"github.com/mitchellh/cli"
	"github.com/openebs/maya/command"
)

// Commands returns the mapping of CLI commands for Maya. The meta
// parameter lets you set meta options for all commands.
func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
	if metaPtr == nil {
		metaPtr = new(command.Meta)
	}

	meta := *metaPtr
	if meta.Ui == nil {
		meta.Ui = &cli.BasicUi{
			Reader:      os.Stdin,
			Writer:      os.Stdout,
			ErrorWriter: os.Stderr,
		}
	}

	return map[string]cli.CommandFactory{
		/*
			"setup-omm": func() (cli.Command, error) {
				return &command.InstallMayaCommand{
					M: meta,
				}, nil
			},
			"setup-osh": func() (cli.Command, error) {
				return &command.InstallOpenEBSCommand{
					M: meta,
				}, nil
			},
			"omm-status": func() (cli.Command, error) {
				return &command.ServerMembersCommand{
					Meta: meta,
				}, nil
			},
			"osh-status": func() (cli.Command, error) {
				return &command.NodeStatusCommand{
					Meta: meta,
				}, nil
			},
		*/
		"volume": func() (cli.Command, error) {
			return &command.VolumeCommand{}, nil
		},
		"volume create": func() (cli.Command, error) {
			return &command.VsmCreateCommand{
				Meta: meta,
			}, nil
		},
		"volume list": func() (cli.Command, error) {
			return &command.VsmListCommand{
				Meta: meta,
			}, nil
		},
		"volume stats": func() (cli.Command, error) {
			return &command.VsmStatsCommand{
				Meta: meta,
			}, nil
		},
		"volume update": func() (cli.Command, error) {
			return &command.VsmUpdateCommand{
				M: meta,
			}, nil
		},
		"volume stop": func() (cli.Command, error) {
			return &command.VsmStopCommand{
				Meta: meta,
			}, nil
		},
		"snapshot": func() (cli.Command, error) {
			return &command.SnapshotCommand{}, nil
		},

		"snapshot create": func() (cli.Command, error) {
			return &command.SnapshotCreateCommand{
				Meta: meta,
			}, nil
		},
		"snapshot list": func() (cli.Command, error) {
			return &command.SnapshotListCommand{
				Meta: meta,
			}, nil
		},

		"snapshot rm": func() (cli.Command, error) {
			return &command.SnapshotDeleteCommand{
				Meta: meta,
			}, nil
		},
		"snapshot revert": func() (cli.Command, error) {
			return &command.SnapshotRevertCommand{
				Meta: meta,
			}, nil
		},

		/*	"network-install": func() (cli.Command, error) {
				return &command.NetworkInstallCommand{
					M: meta,
				}, nil
			},
		*/
		"version": func() (cli.Command, error) {
			ver := Version
			rel := VersionPrerelease
			if GitDescribe != "" {
				ver = GitDescribe
				// Trim off a leading 'v', we append it anyways.
				if ver[0] == 'v' {
					ver = ver[1:]
				}
			}
			if GitDescribe == "" && rel == "" && VersionPrerelease != "" {
				rel = "dev"
			}

			return &command.VersionCommand{
				Revision:          GitCommit,
				Version:           ver,
				VersionPrerelease: rel,
				Ui:                meta.Ui,
			}, nil
		},
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"strings"
)

func handleNewKudoCommand(w http.ResponseWriter, memberFrom *Member, target string, extra string) {
	member, err := findMemberByTag(strings.TrimLeft(target, "@"))
	if err != nil {
		fmt.Fprint(w, err)
		return
	}
	kudo := Kudo{0, extra, member, memberFrom, 0}
	kudos = append(kudos, kudo)
	dbSaveKudo(&kudo)

	notifyUser("New kudo from <@"+memberFrom.ID+">!\n"+extra, *member)
	notifyChannel("New kudo from <@" + memberFrom.ID + "> was given to <@" + member.ID + ">!\n" + extra)

	fmt.Fprint(w, "Kudo has been registered!")
}

func handleLikeCommand(w http.ResponseWriter, memberFrom *Member, target string) {
	member, err := findMemberByTag(strings.TrimLeft(target, "@"))
	if err != nil {
		fmt.Fprint(w, err)
		return
	}

	for i := len(kudos) - 1; i >= 0; i-- {
		if kudos[i].MemberTo.ID == member.ID {
			if dbKudoLiked(kudos[i], *memberFrom) {
				fmt.Fprint(w, "You have already liked this.")
				return
			}

			kudos[i].LikeCount++
			dbUpdateKudoLikes(kudos[i])
			addMemberToLike(kudos[i], memberFrom)

			fmt.Fprint(w, "Thank you!")
			notifyUser(fmt.Sprint("<@", memberFrom.ID, "> likes your kudo! Total likes: ", kudos[i].LikeCount, "\n", kudos[i].Kudo), *member)

			return
		}
	}

	fmt.Fprint(w, "Found nothing to like...")
}
<commit_msg>save proper ID in memory<commit_after>package main

import (
	"fmt"
	"net/http"
	"strings"
)

func handleNewKudoCommand(w http.ResponseWriter, memberFrom *Member, target string, extra string) {
	member, err := findMemberByTag(strings.TrimLeft(target, "@"))
	if err != nil {
		fmt.Fprint(w, err)
		return
	}
	kudo := Kudo{0, extra, member, memberFrom, 0}
	dbSaveKudo(&kudo)
	kudos = append(kudos, kudo)

	notifyUser("New kudo from <@"+memberFrom.ID+">!\n"+extra, *member)
	notifyChannel("New kudo from <@" + memberFrom.ID + "> was given to <@" + member.ID + ">!\n" + extra)

	fmt.Fprint(w, "Kudo has been registered!")
}

func handleLikeCommand(w http.ResponseWriter, memberFrom *Member, target string) {
	member, err := findMemberByTag(strings.TrimLeft(target, "@"))
	if err != nil {
		fmt.Fprint(w, err)
		return
	}

	for i := len(kudos) - 1; i >= 0; i-- {
		if kudos[i].MemberTo.ID == member.ID {
			if dbKudoLiked(kudos[i], *memberFrom) {
				fmt.Fprint(w, "You have already liked this.")
				return
			}

			kudos[i].LikeCount++
			dbUpdateKudoLikes(kudos[i])
			addMemberToLike(kudos[i], memberFrom)

			fmt.Fprint(w, "Thank you!")
			notifyUser(fmt.Sprint("<@", memberFrom.ID, "> likes your kudo! Total likes: ", kudos[i].LikeCount, "\n", kudos[i].Kudo), *member)

			return
		}
	}

	fmt.Fprint(w, "Found nothing to like...")
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"os/signal"

	appCustom "github.com/hashicorp/otto/builtin/app/custom"
	appGo "github.com/hashicorp/otto/builtin/app/go"
	appRuby "github.com/hashicorp/otto/builtin/app/ruby"
	foundationConsul "github.com/hashicorp/otto/builtin/foundation/consul"
	infraAws "github.com/hashicorp/otto/builtin/infra/aws"

	"github.com/hashicorp/otto/app"
	"github.com/hashicorp/otto/appfile/detect"
	"github.com/hashicorp/otto/command"
	"github.com/hashicorp/otto/foundation"
	"github.com/hashicorp/otto/infrastructure"
	"github.com/hashicorp/otto/otto"
	"github.com/mitchellh/cli"
)

// Commands is the mapping of all the available Otto commands.
var Commands map[string]cli.CommandFactory

// Ui is the cli.Ui used for communicating to the outside world.
var Ui cli.Ui

const (
	ErrorPrefix  = "e:"
	OutputPrefix = "o:"
)

func init() {
	Ui = &cli.PrefixedUi{
		AskPrefix:    OutputPrefix,
		OutputPrefix: OutputPrefix,
		InfoPrefix:   OutputPrefix,
		ErrorPrefix:  ErrorPrefix,
		Ui:           &cli.BasicUi{Writer: os.Stdout},
	}

	apps := appGo.Tuples.Map(app.StructFactory(new(appGo.App)))
	apps.Add(appCustom.Tuples.Map(app.StructFactory(new(appCustom.App))))
	apps.Add(appRuby.Tuples.Map(app.StructFactory(new(appRuby.App))))

	foundations := foundationConsul.Tuples.Map(foundation.StructFactory(new(foundationConsul.Foundation)))

	meta := command.Meta{
		CoreConfig: &otto.CoreConfig{
			Apps:        apps,
			Foundations: foundations,
			Infrastructures: map[string]infrastructure.Factory{
				"aws": infraAws.Infra,
			},
		},
		Ui: Ui,
	}

	detectors := []*detect.Detector{
		&detect.Detector{
			Type: "go",
			File: "*.go",
		},
		&detect.Detector{
			Type: "ruby",
			File: "Gemfile",
		},
	}

	Commands = map[string]cli.CommandFactory{
		"compile": func() (cli.Command, error) {
			return &command.CompileCommand{
				Meta:      meta,
				Detectors: detectors,
			}, nil
		},

		"build": func() (cli.Command, error) {
			return &command.BuildCommand{
				Meta: meta,
			}, nil
		},

		"deploy": func() (cli.Command, error) {
			return &command.DeployCommand{
				Meta: meta,
			}, nil
		},

		"dev": func() (cli.Command, error) {
			return &command.DevCommand{
				Meta: meta,
			}, nil
		},

		"infra": func() (cli.Command, error) {
			return &command.InfraCommand{
				Meta: meta,
			}, nil
		},

		"version": func() (cli.Command, error) {
			return &command.VersionCommand{
				Meta:              meta,
				Revision:          GitCommit,
				Version:           Version,
				VersionPrerelease: VersionPrerelease,
				CheckFunc:         commandVersionCheck,
			}, nil
		},
	}
}

// makeShutdownCh creates an interrupt listener and returns a channel.
// A message will be sent on the channel for every interrupt received.
func makeShutdownCh() <-chan struct{} {
	resultCh := make(chan struct{})

	signalCh := make(chan os.Signal, 4)
	signal.Notify(signalCh, os.Interrupt)
	go func() {
		for {
			<-signalCh
			resultCh <- struct{}{}
		}
	}()

	return resultCh
}
<commit_msg>main: fix new API<commit_after>package main

import (
	"os"
	"os/signal"

	appCustom "github.com/hashicorp/otto/builtin/app/custom"
	appGo "github.com/hashicorp/otto/builtin/app/go"
	appRuby "github.com/hashicorp/otto/builtin/app/ruby"
	foundationConsul "github.com/hashicorp/otto/builtin/foundation/consul"
	infraAws "github.com/hashicorp/otto/builtin/infra/aws"

	"github.com/hashicorp/otto/app"
	"github.com/hashicorp/otto/appfile/detect"
	"github.com/hashicorp/otto/command"
	"github.com/hashicorp/otto/foundation"
	"github.com/hashicorp/otto/infrastructure"
	"github.com/hashicorp/otto/otto"
	"github.com/mitchellh/cli"
)

// Commands is the mapping of all the available Otto commands.
var Commands map[string]cli.CommandFactory

// Ui is the cli.Ui used for communicating to the outside world.
var Ui cli.Ui

const (
	ErrorPrefix  = "e:"
	OutputPrefix = "o:"
)

func init() {
	Ui = &cli.PrefixedUi{
		AskPrefix:    OutputPrefix,
		OutputPrefix: OutputPrefix,
		InfoPrefix:   OutputPrefix,
		ErrorPrefix:  ErrorPrefix,
		Ui:           &cli.BasicUi{Writer: os.Stdout},
	}

	apps := appGo.Tuples.Map(app.StructFactory(new(appGo.App)))
	apps.Add(appCustom.Tuples.Map(app.StructFactory(new(appCustom.App))))
	apps.Add(appRuby.Tuples.Map(app.StructFactory(new(appRuby.App))))

	foundations := foundationConsul.Tuples.Map(foundation.StructFactory(new(foundationConsul.Foundation)))

	meta := command.Meta{
		CoreConfig: &otto.CoreConfig{
			Apps:        apps,
			Foundations: foundations,
			Infrastructures: map[string]infrastructure.Factory{
				"aws": infraAws.Infra,
			},
		},
		Ui: Ui,
	}

	detectors := []*detect.Detector{
		&detect.Detector{
			Type: "go",
			File: []string{"*.go"},
		},
		&detect.Detector{
			Type: "ruby",
			File: []string{"Gemfile"},
		},
	}

	Commands = map[string]cli.CommandFactory{
		"compile": func() (cli.Command, error) {
			return &command.CompileCommand{
				Meta:      meta,
				Detectors: detectors,
			}, nil
		},

		"build": func() (cli.Command, error) {
			return &command.BuildCommand{
				Meta: meta,
			}, nil
		},

		"deploy": func() (cli.Command, error) {
			return &command.DeployCommand{
				Meta: meta,
			}, nil
		},

		"dev": func() (cli.Command, error) {
			return &command.DevCommand{
				Meta: meta,
			}, nil
		},

		"infra": func() (cli.Command, error) {
			return &command.InfraCommand{
				Meta: meta,
			}, nil
		},

		"version": func() (cli.Command, error) {
			return &command.VersionCommand{
				Meta:              meta,
				Revision:          GitCommit,
				Version:           Version,
				VersionPrerelease: VersionPrerelease,
				CheckFunc:         commandVersionCheck,
			}, nil
		},
	}
}

// makeShutdownCh creates an interrupt listener and returns a channel.
// A message will be sent on the channel for every interrupt received.
func makeShutdownCh() <-chan struct{} {
	resultCh := make(chan struct{})

	signalCh := make(chan os.Signal, 4)
	signal.Notify(signalCh, os.Interrupt)
	go func() {
		for {
			<-signalCh
			resultCh <- struct{}{}
		}
	}()

	return resultCh
}
<|endoftext|>


<commit_before>package goimage

import (
	"io"
	"mime/multipart"
	"os"
	"path/filepath"

	"github.com/omar-h/goimage/utils"
)

// File holds a file.
type File struct {
	File      multipart.File
	Header    multipart.FileHeader
	Basename  string // Without extension
	Fullname  string // With extension
	Extension string
	MIMEType  string
	Size      int
}

// NewFile will create a new file from a multipart.FileHeader.
func NewFile(file multipart.File, fileHeader multipart.FileHeader) *File {
	return &File{
		File:      file,
		Header:    fileHeader,
		Basename:  utils.GetFileBasename(fileHeader.Filename),
		Fullname:  fileHeader.Filename,
		Extension: filepath.Ext(fileHeader.Filename),
		MIMEType:  fileHeader.Header["Content-Type"][0],
		Size:      int(fileHeader.Size),
	}
}

// Place will move the file onto a specific location.
// Returns os package errors. (os.ErrFileExist and os.ErrPermission)
func (f *File) Place(location string) error {
	file, err := os.OpenFile(location+f.Fullname, os.O_WRONLY|os.O_CREATE, 0644)
	if err != nil {
		return err
	}

	defer file.Close()

	_, err = io.Copy(file, f.File)
	if err != nil {
		return err
	}

	return nil
}

// Close will properly close the file.
func (f *File) Close() error {
	return f.File.Close()
}
<commit_msg>Make File.Header a pointer.<commit_after>package goimage

import (
	"io"
	"mime/multipart"
	"os"
	"path/filepath"

	"github.com/omar-h/goimage/utils"
)

// File holds a file.
type File struct {
	File      multipart.File
	Header    *multipart.FileHeader
	Basename  string // Without extension
	Fullname  string // With extension
	Extension string
	MIMEType  string
	Size      int
}

// NewFile will create a new file from a multipart.FileHeader.
func NewFile(file multipart.File, fileHeader *multipart.FileHeader) *File {
	return &File{
		File:      file,
		Header:    fileHeader,
		Basename:  utils.GetFileBasename(fileHeader.Filename),
		Fullname:  fileHeader.Filename,
		Extension: filepath.Ext(fileHeader.Filename),
		MIMEType:  fileHeader.Header["Content-Type"][0],
		Size:      int(fileHeader.Size),
	}
}

// Place will move the file onto a specific location.
// Returns os package errors. (os.ErrFileExist and os.ErrPermission)
func (f *File) Place(location string) error {
	file, err := os.OpenFile(location+f.Fullname, os.O_WRONLY|os.O_CREATE, 0644)
	if err != nil {
		return err
	}

	defer file.Close()

	_, err = io.Copy(file, f.File)
	if err != nil {
		return err
	}

	return nil
}

// GenerateName will generate a new name with a given length.
func (f *File) GenerateName(len int) *File {
	return f.GiveName(utils.GenerateName(len))
}

// GiveName will give the File a new name, and update the basename and fullname.
func (f *File) GiveName(name string) *File {
	f.Basename = name
	f.Fullname = name + f.Extension
	return f
}

// Close will properly close the file.
func (f *File) Close() error {
	return f.File.Close()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/url"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"syscall"

	"github.com/codegangsta/cli"
	"github.com/google/go-github/github"
	"github.com/motemen/ghq/pocket"
	"github.com/motemen/ghq/utils"
)

var Commands = []cli.Command{
	commandGet,
	commandList,
	commandLook,
	commandImport,
}

var commandGet = cli.Command{
	Name:  "get",
	Usage: "Clone/sync with a remote repository",
	Description: `
    Clone a GitHub repository under ghq root direcotry. If the repository is
    already cloned to local, nothing will happen unless '-u' ('--update')
    flag is supplied, in which case 'git remote update' is executed.
`,
	Action: doGet,
	Flags: []cli.Flag{
		cli.BoolFlag{"update, u", "Update local repository if cloned already"},
		cli.BoolFlag{"p", "Clone with SSH"},
	},
}

var commandList = cli.Command{
	Name:  "list",
	Usage: "List local repositories",
	Description: `
    List locally cloned repositories. If a query argument is given, only
    repositories whose names contain that query text are listed. '-e'
    ('--exact') forces the match to be an exact one (i.e. the query equals to
    _project_ or _user_/_project_) If '-p' ('--full-path') is given, the full paths
    to the repository root are printed instead of relative ones.
`,
	Action: doList,
	Flags: []cli.Flag{
		cli.BoolFlag{"exact, e", "Perform an exact match"},
		cli.BoolFlag{"full-path, p", "Print full paths"},
		cli.BoolFlag{"unique", "Print unique subpaths"},
	},
}

var commandLook = cli.Command{
	Name:  "look",
	Usage: "Look into a local repository",
	Description: `
    Look into a locally cloned repository with the shell.
`,
	Action: doLook,
}

var commandImport = cli.Command{
	Name:  "import",
	Usage: "Import repositories from other web services",
	Subcommands: []cli.Command{
		commandImportStarred,
		commandImportPocket,
	},
}

var commandImportStarred = cli.Command{
	Name:  "starred",
	Usage: "Get all starred GitHub repositories",
	Description: `
    Retrieves GitHub repositories that are starred by the user specified and
    performs 'get' for each of them.
`,
	Action: doImportStarred,
	Flags: []cli.Flag{
		cli.BoolFlag{"update, u", "Update local repository if cloned already"},
		cli.BoolFlag{"p", "Clone with SSH"},
	},
}

var commandImportPocket = cli.Command{
	Name:  "pocket",
	Usage: "Get all github.com entries in Pocket",
	Description: `
    Retrieves Pocket <http://getpocket.com/> entries of github.com and
    performs 'get' for each of them.
`,
	Action: doImportPocket,
	Flags: []cli.Flag{
		cli.BoolFlag{"update, u", "Update local repository if cloned already"},
	},
}

type commandDoc struct {
	Parent    string
	Arguments string
}

var commandDocs = map[string]commandDoc{
	"get":     {"", "[-u] <repository URL> | <user>/<project>"},
	"list":    {"", "[-p] [-e] [<query>]"},
	"look":    {"", "<project> | <user>/<project> | <host>/<user>/<project>"},
	"import":  {"", "[-u] starred <user> | pocket"},
	"starred": {"import", "[-u] <user>"},
	"pocket":  {"import", "[-u]"},
}

// Makes template conditionals to generate per-command documents.
func mkCommandsTemplate(genTemplate func(commandDoc) string) string {
	template := "{{if false}}"
	for _, command := range append(Commands, commandImportStarred, commandImportPocket) {
		template = template + fmt.Sprintf("{{else if (eq .Name %q)}}%s", command.Name, genTemplate(commandDocs[command.Name]))
	}
	return template + "{{end}}"
}

func init() {
	argsTemplate := mkCommandsTemplate(func(doc commandDoc) string { return doc.Arguments })
	parentTemplate := mkCommandsTemplate(func(doc commandDoc) string { return string(strings.TrimLeft(doc.Parent+" ", " ")) })

	cli.CommandHelpTemplate = `NAME:
    {{.Name}} - {{.Usage}}

USAGE:
    ghq ` + parentTemplate + `{{.Name}} ` + argsTemplate + `
{{if (len .Description)}}
DESCRIPTION: {{.Description}}
{{end}}{{if (len .Flags)}}
OPTIONS:
    {{range .Flags}}{{.}}
    {{end}}
{{end}}`
}

func doGet(c *cli.Context) {
	argURL := c.Args().Get(0)
	doUpdate := c.Bool("update")

	if argURL == "" {
		cli.ShowCommandHelp(c, "get")
		os.Exit(1)
	}

	url, err := NewURL(argURL)
	utils.DieIf(err)

	if !url.IsAbs() {
		isSSH := c.Bool("p")
		if isSSH {
			url, err = NewURL("git@github.com:" + url.Path)
			utils.DieIf(err)
		} else {
			url.Scheme = "https"
			url.Host = "github.com"
			if url.Path[0] != '/' {
				url.Path = "/" + url.Path
			}
		}
	}

	remote, err := NewRemoteRepository(url)
	utils.DieIf(err)

	if remote.IsValid() == false {
		utils.Log("error", fmt.Sprintf("Not a valid repository: %s", url))
		os.Exit(1)
	}

	getRemoteRepository(remote, doUpdate)
}

func getRemoteRepository(remote RemoteRepository, doUpdate bool) {
	remoteURL := remote.URL()
	local := LocalRepositoryFromURL(remoteURL)

	path := local.FullPath
	newPath := false

	_, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			newPath = true
			err = nil
		}
		utils.PanicIf(err)
	}

	if newPath {
		utils.Log("clone", fmt.Sprintf("%s -> %s", remoteURL, path))
		remote.VCS().Clone(remoteURL, path)
	} else {
		if doUpdate {
			utils.Log("update", path)
			local.VCS().Update(path)
		} else {
			utils.Log("exists", path)
		}
	}
}

func doList(c *cli.Context) {
	query := c.Args().First()
	exact := c.Bool("exact")
	printFullPaths := c.Bool("full-path")
	printUniquePaths := c.Bool("unique")

	var filterFn func(*LocalRepository) bool
	if query == "" {
		filterFn = func(_ *LocalRepository) bool {
			return true
		}
	} else if exact {
		filterFn = func(repo *LocalRepository) bool {
			return repo.Matches(query)
		}
	} else {
		filterFn = func(repo *LocalRepository) bool {
			return strings.Contains(repo.NonHostPath(), query)
		}
	}

	repos := []*LocalRepository{}

	walkLocalRepositories(func(repo *LocalRepository) {
		if filterFn(repo) == false {
			return
		}

		repos = append(repos, repo)
	})

	if printUniquePaths {
		subpathCount := map[string]int{} // Count duplicated subpaths (ex. foo/dotfiles and bar/dotfiles)
		reposCount := map[string]int{}   // Check duplicated repositories among roots

		// Primary first
		for _, repo := range repos {
			if reposCount[repo.RelPath] == 0 {
				for _, p := range repo.Subpaths() {
					subpathCount[p] = subpathCount[p] + 1
				}
			}

			reposCount[repo.RelPath] = reposCount[repo.RelPath] + 1
		}

		for _, repo := range repos {
			if reposCount[repo.RelPath] > 1 && repo.IsUnderPrimaryRoot() == false {
				continue
			}

			for _, p := range repo.Subpaths() {
				if subpathCount[p] == 1 {
					fmt.Println(p)
					break
				}
			}
		}
	} else {
		for _, repo := range repos {
			if printFullPaths {
				fmt.Println(repo.FullPath)
			} else {
				fmt.Println(repo.RelPath)
			}
		}
	}
}

func doLook(c *cli.Context) {
	name := c.Args().First()

	if name == "" {
		cli.ShowCommandHelp(c, "look")
		os.Exit(1)
	}

	reposFound := []*LocalRepository{}
	walkLocalRepositories(func(repo *LocalRepository) {
		if repo.Matches(name) {
			reposFound = append(reposFound, repo)
		}
	})

	switch len(reposFound) {
	case 0:
		utils.Log("error", "No repository found")

	case 1:
		if runtime.GOOS == "windows" {
			cmd := exec.Command(os.Getenv("COMSPEC"))
			cmd.Stdin = os.Stdin
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			cmd.Dir = reposFound[0].FullPath
			err := cmd.Start()
			if err == nil {
				cmd.Wait()
				os.Exit(0)
			}
		} else {
			shell := os.Getenv("SHELL")
			if shell == "" {
				shell = "/bin/sh"
			}

			utils.Log("cd", reposFound[0].FullPath)
			err := os.Chdir(reposFound[0].FullPath)
			utils.PanicIf(err)

			syscall.Exec(shell, []string{shell}, syscall.Environ())
		}

	default:
		utils.Log("error", "More than one repositories are found; Try more precise name")
		for _, repo := range reposFound {
			utils.Log("error", "- "+strings.Join(repo.PathParts, "/"))
		}
	}
}

func doImportStarred(c *cli.Context) {
	user := c.Args().First()

	isSSH := c.Bool("p")

	if user == "" {
		cli.ShowCommandHelp(c, "starred")
		os.Exit(1)
	}

	client := github.NewClient(nil)
	options := &github.ActivityListStarredOptions{Sort: "created"}

	for page := 1; ; page++ {
		options.Page = page

		repositories, res, err := client.Activity.ListStarred(user, options)
		utils.DieIf(err)

		utils.Log("page", fmt.Sprintf("%d/%d", page, res.LastPage))
		for _, repo := range repositories {
			url, err := url.Parse(*repo.HTMLURL)
			if err != nil {
				utils.Log("error", fmt.Sprintf("Could not parse URL <%s>: %s", repo.HTMLURL, err))
				continue
			}
			if isSSH {
				url, err = ConvertGitHubURLHTTPToSSH(url)
				if err != nil {
					utils.Log("error", fmt.Sprintf("Could not convert URL <%s>: %s", repo.HTMLURL, err))
					continue
				}
			}

			remote, err := NewRemoteRepository(url)
			if utils.ErrorIf(err) {
				continue
			}

			if remote.IsValid() == false {
				utils.Log("skip", fmt.Sprintf("Not a valid repository: %s", url))
				continue
			}

			getRemoteRepository(remote, c.Bool("update"))
		}

		if page >= res.LastPage {
			break
		}
	}
}

func doImportPocket(c *cli.Context) {
	if pocket.ConsumerKey == "" {
		utils.Log("error", "Built without consumer key set")
		return
	}

	accessToken, err := GitConfig("ghq.pocket.token")
	utils.PanicIf(err)

	if accessToken == "" {
		receiverURL, ch, err := pocket.StartAccessTokenReceiver()
		utils.PanicIf(err)

		utils.Log("pocket", "Waiting for Pocket authentication callback at "+receiverURL)

		utils.Log("pocket", "Obtaining request token")
		authRequest, err := pocket.ObtainRequestToken(receiverURL)
		utils.DieIf(err)

		url := pocket.GenerateAuthorizationURL(authRequest.Code, receiverURL)
		utils.Log("open", url)

		<-ch

		utils.Log("pocket", "Obtaining access token")
		authorized, err := pocket.ObtainAccessToken(authRequest.Code)
		utils.DieIf(err)

		utils.Log("authorized", authorized.Username)

		accessToken = authorized.AccessToken
		utils.Run("git", "config", "ghq.pocket.token", authorized.AccessToken)
	}

	utils.Log("pocket", "Retrieving github.com entries")
	res, err := pocket.RetrieveGitHubEntries(accessToken)
	utils.DieIf(err)

	for _, item := range res.List {
		url, err := url.Parse(item.ResolvedURL)
		if err != nil {
			utils.Log("error", fmt.Sprintf("Could not parse URL <%s>: %s", item.ResolvedURL, err))
			continue
		}

		remote, err := NewRemoteRepository(url)
		if utils.ErrorIf(err) {
			continue
		}

		if remote.IsValid() == false {
			utils.Log("skip", fmt.Sprintf("Not a valid repository: %s", url))
			continue
		}

		getRemoteRepository(remote, c.Bool("update"))
	}
}
<commit_msg>Add documentations for command line option to get SSH<commit_after>package main

import (
	"fmt"
	"net/url"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"syscall"

	"github.com/codegangsta/cli"
	"github.com/google/go-github/github"
	"github.com/motemen/ghq/pocket"
	"github.com/motemen/ghq/utils"
)

var Commands = []cli.Command{
	commandGet,
	commandList,
	commandLook,
	commandImport,
}

var commandGet = cli.Command{
	Name:  "get",
	Usage: "Clone/sync with a remote repository",
	Description: `
    Clone a GitHub repository under ghq root direcotry. If the repository is
    already cloned to local, nothing will happen unless '-u' ('--update')
    flag is supplied, in which case 'git remote update' is executed.
`,
	Action: doGet,
	Flags: []cli.Flag{
		cli.BoolFlag{"update, u", "Update local repository if cloned already"},
		cli.BoolFlag{"p", "Clone with SSH"},
	},
}

var commandList = cli.Command{
	Name:  "list",
	Usage: "List local repositories",
	Description: `
    List locally cloned repositories. If a query argument is given, only
    repositories whose names contain that query text are listed. '-e'
    ('--exact') forces the match to be an exact one (i.e. the query equals to
    _project_ or _user_/_project_) If '-p' ('--full-path') is given, the full paths
    to the repository root are printed instead of relative ones.
`,
	Action: doList,
	Flags: []cli.Flag{
		cli.BoolFlag{"exact, e", "Perform an exact match"},
		cli.BoolFlag{"full-path, p", "Print full paths"},
		cli.BoolFlag{"unique", "Print unique subpaths"},
	},
}

var commandLook = cli.Command{
	Name:  "look",
	Usage: "Look into a local repository",
	Description: `
    Look into a locally cloned repository with the shell.
`,
	Action: doLook,
}

var commandImport = cli.Command{
	Name:  "import",
	Usage: "Import repositories from other web services",
	Subcommands: []cli.Command{
		commandImportStarred,
		commandImportPocket,
	},
}

var commandImportStarred = cli.Command{
	Name:  "starred",
	Usage: "Get all starred GitHub repositories",
	Description: `
    Retrieves GitHub repositories that are starred by the user specified and
    performs 'get' for each of them.
`,
	Action: doImportStarred,
	Flags: []cli.Flag{
		cli.BoolFlag{"update, u", "Update local repository if cloned already"},
		cli.BoolFlag{"p", "Clone with SSH"},
	},
}

var commandImportPocket = cli.Command{
	Name:  "pocket",
	Usage: "Get all github.com entries in Pocket",
	Description: `
    Retrieves Pocket <http://getpocket.com/> entries of github.com and
    performs 'get' for each of them.
`,
	Action: doImportPocket,
	Flags: []cli.Flag{
		cli.BoolFlag{"update, u", "Update local repository if cloned already"},
	},
}

type commandDoc struct {
	Parent    string
	Arguments string
}

var commandDocs = map[string]commandDoc{
	"get":     {"", "[-u] <repository URL> | [-u] [-p] <user>/<project>"},
	"list":    {"", "[-p] [-e] [<query>]"},
	"look":    {"", "<project> | <user>/<project> | <host>/<user>/<project>"},
	"import":  {"", "[-u] [-p] starred <user> | [-u] pocket"},
	"starred": {"import", "[-u] [-p] <user>"},
	"pocket":  {"import", "[-u]"},
}

// Makes template conditionals to generate per-command documents.
func mkCommandsTemplate(genTemplate func(commandDoc) string) string {
	template := "{{if false}}"
	for _, command := range append(Commands, commandImportStarred, commandImportPocket) {
		template = template + fmt.Sprintf("{{else if (eq .Name %q)}}%s", command.Name, genTemplate(commandDocs[command.Name]))
	}
	return template + "{{end}}"
}

func init() {
	argsTemplate := mkCommandsTemplate(func(doc commandDoc) string { return doc.Arguments })
	parentTemplate := mkCommandsTemplate(func(doc commandDoc) string { return string(strings.TrimLeft(doc.Parent+" ", " ")) })

	cli.CommandHelpTemplate = `NAME:
    {{.Name}} - {{.Usage}}

USAGE:
    ghq ` + parentTemplate + `{{.Name}} ` + argsTemplate + `
{{if (len .Description)}}
DESCRIPTION: {{.Description}}
{{end}}{{if (len .Flags)}}
OPTIONS:
    {{range .Flags}}{{.}}
    {{end}}
{{end}}`
}

func doGet(c *cli.Context) {
	argURL := c.Args().Get(0)
	doUpdate := c.Bool("update")

	if argURL == "" {
		cli.ShowCommandHelp(c, "get")
		os.Exit(1)
	}

	url, err := NewURL(argURL)
	utils.DieIf(err)

	if !url.IsAbs() {
		isSSH := c.Bool("p")
		if isSSH {
			url, err = NewURL("git@github.com:" + url.Path)
			utils.DieIf(err)
		} else {
			url.Scheme = "https"
			url.Host = "github.com"
			if url.Path[0] != '/' {
				url.Path = "/" + url.Path
			}
		}
	}

	remote, err := NewRemoteRepository(url)
	utils.DieIf(err)

	if remote.IsValid() == false {
		utils.Log("error", fmt.Sprintf("Not a valid repository: %s", url))
		os.Exit(1)
	}

	getRemoteRepository(remote, doUpdate)
}

func getRemoteRepository(remote RemoteRepository, doUpdate bool) {
	remoteURL := remote.URL()
	local := LocalRepositoryFromURL(remoteURL)

	path := local.FullPath
	newPath := false

	_, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			newPath = true
			err = nil
		}
		utils.PanicIf(err)
	}

	if newPath {
		utils.Log("clone", fmt.Sprintf("%s -> %s", remoteURL, path))
		remote.VCS().Clone(remoteURL, path)
	} else {
		if doUpdate {
			utils.Log("update", path)
			local.VCS().Update(path)
		} else {
			utils.Log("exists", path)
		}
	}
}

func doList(c *cli.Context) {
	query := c.Args().First()
	exact := c.Bool("exact")
	printFullPaths := c.Bool("full-path")
	printUniquePaths := c.Bool("unique")

	var filterFn func(*LocalRepository) bool
	if query == "" {
		filterFn = func(_ *LocalRepository) bool {
			return true
		}
	} else if exact {
		filterFn = func(repo *LocalRepository) bool {
			return repo.Matches(query)
		}
	} else {
		filterFn = func(repo *LocalRepository) bool {
			return strings.Contains(repo.NonHostPath(), query)
		}
	}

	repos := []*LocalRepository{}

	walkLocalRepositories(func(repo *LocalRepository) {
		if filterFn(repo) == false {
			return
		}

		repos = append(repos, repo)
	})

	if printUniquePaths {
		subpathCount := map[string]int{} // Count duplicated subpaths (ex. foo/dotfiles and bar/dotfiles)
		reposCount := map[string]int{}   // Check duplicated repositories among roots

		// Primary first
		for _, repo := range repos {
			if reposCount[repo.RelPath] == 0 {
				for _, p := range repo.Subpaths() {
					subpathCount[p] = subpathCount[p] + 1
				}
			}

			reposCount[repo.RelPath] = reposCount[repo.RelPath] + 1
		}

		for _, repo := range repos {
			if reposCount[repo.RelPath] > 1 && repo.IsUnderPrimaryRoot() == false {
				continue
			}

			for _, p := range repo.Subpaths() {
				if subpathCount[p] == 1 {
					fmt.Println(p)
					break
				}
			}
		}
	} else {
		for _, repo := range repos {
			if printFullPaths {
				fmt.Println(repo.FullPath)
			} else {
				fmt.Println(repo.RelPath)
			}
		}
	}
}

func doLook(c *cli.Context) {
	name := c.Args().First()

	if name == "" {
		cli.ShowCommandHelp(c, "look")
		os.Exit(1)
	}

	reposFound := []*LocalRepository{}
	walkLocalRepositories(func(repo *LocalRepository) {
		if repo.Matches(name) {
			reposFound = append(reposFound, repo)
		}
	})

	switch len(reposFound) {
	case 0:
		utils.Log("error", "No repository found")

	case 1:
		if runtime.GOOS == "windows" {
			cmd := exec.Command(os.Getenv("COMSPEC"))
			cmd.Stdin = os.Stdin
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			cmd.Dir = reposFound[0].FullPath
			err := cmd.Start()
			if err == nil {
				cmd.Wait()
				os.Exit(0)
			}
		} else {
			shell := os.Getenv("SHELL")
			if shell == "" {
				shell = "/bin/sh"
			}

			utils.Log("cd", reposFound[0].FullPath)
			err := os.Chdir(reposFound[0].FullPath)
			utils.PanicIf(err)

			syscall.Exec(shell, []string{shell}, syscall.Environ())
		}

	default:
		utils.Log("error", "More than one repositories are found; Try more precise name")
		for _, repo := range reposFound {
			utils.Log("error", "- "+strings.Join(repo.PathParts, "/"))
		}
	}
}

func doImportStarred(c *cli.Context) {
	user := c.Args().First()

	isSSH := c.Bool("p")

	if user == "" {
		cli.ShowCommandHelp(c, "starred")
		os.Exit(1)
	}

	client := github.NewClient(nil)
	options := &github.ActivityListStarredOptions{Sort: "created"}

	for page := 1; ; page++ {
		options.Page = page

		repositories, res, err := client.Activity.ListStarred(user, options)
		utils.DieIf(err)

		utils.Log("page", fmt.Sprintf("%d/%d", page, res.LastPage))
		for _, repo := range repositories {
			url, err := url.Parse(*repo.HTMLURL)
			if err != nil {
				utils.Log("error", fmt.Sprintf("Could not parse URL <%s>: %s", repo.HTMLURL, err))
				continue
			}
			if isSSH {
				url, err = ConvertGitHubURLHTTPToSSH(url)
				if err != nil {
					utils.Log("error", fmt.Sprintf("Could not convert URL <%s>: %s", repo.HTMLURL, err))
					continue
				}
			}

			remote, err := NewRemoteRepository(url)
			if utils.ErrorIf(err) {
				continue
			}

			if remote.IsValid() == false {
				utils.Log("skip", fmt.Sprintf("Not a valid repository: %s", url))
				continue
			}

			getRemoteRepository(remote, c.Bool("update"))
		}

		if page >= res.LastPage {
			break
		}
	}
}

func doImportPocket(c *cli.Context) {
	if pocket.ConsumerKey == "" {
		utils.Log("error", "Built without consumer key set")
		return
	}

	accessToken, err := GitConfig("ghq.pocket.token")
	utils.PanicIf(err)

	if accessToken == "" {
		receiverURL, ch, err := pocket.StartAccessTokenReceiver()
		utils.PanicIf(err)

		utils.Log("pocket", "Waiting for Pocket authentication callback at "+receiverURL)

		utils.Log("pocket", "Obtaining request token")
		authRequest, err := pocket.ObtainRequestToken(receiverURL)
		utils.DieIf(err)

		url := pocket.GenerateAuthorizationURL(authRequest.Code, receiverURL)
		utils.Log("open", url)

		<-ch

		utils.Log("pocket", "Obtaining access token")
		authorized, err := pocket.ObtainAccessToken(authRequest.Code)
		utils.DieIf(err)

		utils.Log("authorized", authorized.Username)

		accessToken = authorized.AccessToken
		utils.Run("git", "config", "ghq.pocket.token", authorized.AccessToken)
	}

	utils.Log("pocket", "Retrieving github.com entries")
	res, err := pocket.RetrieveGitHubEntries(accessToken)
	utils.DieIf(err)

	for _, item := range res.List {
		url, err := url.Parse(item.ResolvedURL)
		if err != nil {
			utils.Log("error", fmt.Sprintf("Could not parse URL <%s>: %s", item.ResolvedURL, err))
			continue
		}

		remote, err := NewRemoteRepository(url)
		if utils.ErrorIf(err) {
			continue
		}

		if remote.IsValid() == false {
			utils.Log("skip", fmt.Sprintf("Not a valid repository: %s", url))
			continue
		}

		getRemoteRepository(remote, c.Bool("update"))
	}
}
<|endoftext|>


<commit_before>package configr

import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"path/filepath"
	"strings"

	"github.com/BurntSushi/toml"
)

type Encoding int

const (
	Unknown Encoding = iota - 1
	JSON
	TOML
)

type FileSource struct {
	filePath string
	encoding Encoding
}

var SupportedFileExtensions = []string{"json", "toml"}
var ErrUnknownEncoding = errors.New("configr: Unable to determine file encoding, please set manually")

var globalFileSource *FileSource = NewFileSource("")

func NewFileSource(filePath string) *FileSource {
	f := &FileSource{encoding: Unknown}
	f.SetFilePath(filePath)

	return f
}

// SetFilePath sets the file path of the configuration file and try to determine
// the encoding of the file using its extension. See SupportedFileExtensions for
// a list of supported extensions
func SetFilePath(path string) {
	globalFileSource.SetFilePath(path)
}
func (f *FileSource) SetFilePath(path string) {
	f.filePath = path

	fileExt := getFileExtension(path)
	switch fileExt {
	case SupportedFileExtensions[TOML]:
		f.SetEncoding(TOML)
	case SupportedFileExtensions[JSON]:
		f.SetEncoding(JSON)
	}
}

func FilePath() string {
	return globalFileSource.FilePath()
}
func (f *FileSource) FilePath() string {
	return f.filePath
}

// SetEncoding allows the caller to override the infered file encoding format
func SetEncoding(encoding Encoding) {
	globalFileSource.SetEncoding(encoding)
}
func (f *FileSource) SetEncoding(encoding Encoding) {
	f.encoding = encoding
}

func Unmarshal() (map[string]interface{}, error) {
	return globalFileSource.Unmarshal()
}
func (f *FileSource) Unmarshal() (map[string]interface{}, error) {
	var unmarshaller func([]byte, interface{}) error
	values := make(map[string]interface{})

	switch f.encoding {
	case JSON:
		unmarshaller = json.Unmarshal
	case TOML:
		unmarshaller = toml.Unmarshal
	default:
		return values, ErrUnknownEncoding
	}

	fileBytes, err := ioutil.ReadFile(f.filePath)
	if err != nil {
		return values, err
	}

	err = unmarshaller(fileBytes, &values)
	if err != nil {
		return values, err
	}

	return values, nil
}

func Marshal(v interface{}) ([]byte, error) {
	return globalFileSource.Marshal(v)
}
func (f *FileSource) Marshal(v interface{}) ([]byte, error) {
	switch f.encoding {
	case JSON:
		return json.MarshalIndent(v, "", "	")
	case TOML:
		var tomlBytes bytes.Buffer
		tomlEncoder := toml.NewEncoder(bufio.NewWriter(&tomlBytes))
		err := tomlEncoder.Encode(v)
		if err != nil {
			return tomlBytes.Bytes(), err
		}

		return tomlBytes.Bytes(), nil
	default:
		return []byte{}, ErrUnknownEncoding
	}
}

func getFileExtension(filePath string) string {
	return strings.ToLower(strings.TrimPrefix(filepath.Ext(filePath), "."))
}
<commit_msg>Ditch globals filesource, no need for it<commit_after>package configr

import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"path/filepath"
	"strings"

	"github.com/BurntSushi/toml"
)

type Encoding int

const (
	Unknown Encoding = iota - 1
	JSON
	TOML
)

type FileSource struct {
	filePath string
	encoding Encoding
}

var (
	SupportedFileExtensions = []string{"json", "toml"}
	ErrUnknownEncoding      = errors.New("configr: Unable to determine file encoding, please set manually")
)

func NewFileSource(filePath string) *FileSource {
	f := &FileSource{encoding: Unknown}
	f.SetFilePath(filePath)

	return f
}

// SetFilePath sets the file path of the configuration file and try to determine
// the encoding of the file using its extension. See SupportedFileExtensions for
// a list of supported extensions
func (f *FileSource) SetFilePath(path string) {
	f.filePath = path

	fileExt := getFileExtension(path)
	switch fileExt {
	case SupportedFileExtensions[TOML]:
		f.SetEncoding(TOML)
	case SupportedFileExtensions[JSON]:
		f.SetEncoding(JSON)
	}
}

func (f *FileSource) FilePath() string {
	return f.filePath
}

// SetEncoding allows the caller to override the infered file encoding format
func (f *FileSource) SetEncoding(encoding Encoding) {
	f.encoding = encoding
}

func (f *FileSource) Unmarshal() (map[string]interface{}, error) {
	var unmarshaller func([]byte, interface{}) error
	values := make(map[string]interface{})

	switch f.encoding {
	case JSON:
		unmarshaller = json.Unmarshal
	case TOML:
		unmarshaller = toml.Unmarshal
	default:
		return values, ErrUnknownEncoding
	}

	fileBytes, err := ioutil.ReadFile(f.filePath)
	if err != nil {
		return values, err
	}

	err = unmarshaller(fileBytes, &values)
	if err != nil {
		return values, err
	}

	return values, nil
}

func (f *FileSource) Marshal(v interface{}) ([]byte, error) {
	switch f.encoding {
	case JSON:
		return json.MarshalIndent(v, "", "	")
	case TOML:
		var tomlBytes bytes.Buffer
		tomlEncoder := toml.NewEncoder(bufio.NewWriter(&tomlBytes))
		err := tomlEncoder.Encode(v)
		if err != nil {
			return tomlBytes.Bytes(), err
		}

		return tomlBytes.Bytes(), nil
	default:
		return []byte{}, ErrUnknownEncoding
	}
}

func getFileExtension(filePath string) string {
	return strings.ToLower(strings.TrimPrefix(filepath.Ext(filePath), "."))
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/mattn/go-shellwords"
)

// SlackCommand represents the payload of the Slack slash commands
type SlackCommand struct {
	Token       string `schema:"token"`
	TeamID      string `schema:"team_id"`
	TeamDomain  string `schema:"team_domain"`
	ChannelID   string `schema:"channel_id"`
	ChannelName string `schema:"channel_name"`
	UserID      string `schema:"user_id"`
	UserName    string `schema:"user_name"`
	Command     string `schema:"command"`
	Text        string `schema:"text"`
}

func (command *SlackCommand) getParsedText() []string {
	parsedText, err := shellwords.NewParser().Parse(command.Text)
	if err != nil {
		return []string{}
	}
	return parsedText
}

func (command *SlackCommand) getSubCommand() string {
	parsedText := command.getParsedText()

	if len(parsedText) > 0 {
		return parsedText[0]
	}
	return "help"
}
<commit_msg>Defined first commands<commit_after>package main

import (
	"fmt"
	"github.com/mattn/go-shellwords"
)

// SlackCommand represents the payload of the Slack slash commands
type SlackCommand struct {
	Token       string `schema:"token"`
	TeamID      string `schema:"team_id"`
	TeamDomain  string `schema:"team_domain"`
	ChannelID   string `schema:"channel_id"`
	ChannelName string `schema:"channel_name"`
	UserID      string `schema:"user_id"`
	UserName    string `schema:"user_name"`
	Command     string `schema:"command"`
	Text        string `schema:"text"`
}

func (command *SlackCommand) getParsedText() []string {
	parsedText, err := shellwords.NewParser().Parse(command.Text)
	if err != nil {
		return []string{}
	}
	return parsedText
}

func (command *SlackCommand) getSubCommand() string {
	parsedText := command.getParsedText()

	if len(parsedText) > 0 {
		return parsedText[0]
	}
	return "help"
}

func helpCommand(*SlackCommand) string {
	return "Use one of the following commands:\n\tversion\n\thelp"
}

func versionCommand(*SlackCommand) string {
	return fmt.Sprintf("SlackExact version %s", VERSION)
}
<|endoftext|>


<commit_before>package fuseklient

import (
	"io"
	"time"

	"github.com/jacobsa/fuse/fuseutil"
	"github.com/koding/fuseklient/transport"
)

// File represents a file system file and implements Node interface.
type File struct {
	// Entry is generic structure that contains commonality between File and Dir.
	*Entry

	////// Entry#RWLock protects the fields below.

	// IsDirty indicates if File has been written to, but not yet been synced
	// with remote.
	IsDirty bool

	// Content is the remotely fetched contents of the File.
	Content []byte
}

// NewFile is the required initializeChild for File. If internal cache is empty,
// it'll fetch from remote.
func NewFile(n *Entry) *File {
	return &File{Entry: n, Content: []byte{}}
}

// ReadAt returns contents of file at specified offset.
func (f *File) ReadAt(offset int64) ([]byte, error) {
	f.Lock()
	defer f.Unlock()

	// fetch from remote is no content
	if len(f.Content) == 0 {
		if err := f.updateContentFromRemote(); err != nil {
			return nil, err
		}
	}

	// check offset only after fetching from remote
	if offset > int64(len(f.Content)) {
		return nil, io.EOF
	}

	return f.Content[offset:], nil
}

// Create creates a new file on remote with existing content.
func (f *File) Create() error {
	f.Lock()
	defer f.Unlock()

	return f.writeContentToRemote(f.Content)
}

// WriteAt saves specified content at specified offset. Note, this saves to
// internal cache only.
func (f *File) WriteAt(content []byte, offset int64) {
	f.Lock()
	defer f.Unlock()

	f.IsDirty = true

	var newLen = len(content) + int(offset)
	if len(f.Content) < newLen {
		padding := make([]byte, newLen-len(f.Content))
		f.Content = append(f.Content, padding...)
	}

	copy(f.Content[offset:], content)

	if offset == 0 {
		f.Content = f.Content[0:len(content)]
	}

	f.Attrs.Size = uint64(len(f.Content))
}

// TruncateTo reduces file contents to specified length.
func (f *File) TruncateTo(size uint64) error {
	f.Lock()
	defer f.Unlock()

	s := int(size)
	switch {
	case s < len(f.Content):
		// specified size less than size of file, so remove all content over size
		f.Content = f.Content[:size]
	case s > len(f.Content):
		// specified size greater same as size of file, so add empty padding to
		// existing content
		f.Content = append(f.Content, make([]byte, s-len(f.Content))...)
	case s == len(f.Content):
		// specified size is same as size of file, so nothing to be done
	}

	return f.writeContentToRemote(f.Content)
}

// Flush saves internal cache to remote.
func (f *File) Flush() error {
	f.Lock()
	defer f.Unlock()

	return f.syncToRemote()
}

// Sync saves internal cache to remote.
func (f *File) Sync() error {
	f.Lock()
	defer f.Unlock()

	return f.syncToRemote()
}

///// Node interface

// GetType returns fuseutil.DT_File for identification for fuse library.
func (f *File) GetType() fuseutil.DirentType {
	return fuseutil.DT_File
}

// Expire removes the internal cache of file and fetches it from remote. It's
// required to update from remote since Kernel caches file attrs.
func (f *File) Expire() error {
	f.Lock()
	defer f.Unlock()

	// OH THE HORROR!
	// If remote has a change where size of file hasn't changed, then Kernel
	// doesn't invalidate the local cache, so we replace the InodeId.
	f.ID = f.Parent.IDGen.Next()

	return f.updateContentFromRemote()
}

///// Helpers

func (f *File) syncToRemote() error {
	var isDirty = f.IsDirty
	if !isDirty {
		return nil
	}

	return f.writeContentToRemote(f.Content)
}

func (f *File) writeContentToRemote(content []byte) error {
	f.IsDirty = false

	req := struct {
		Path    string
		Content []byte
	}{
		Path:    f.RemotePath,
		Content: content,
	}
	var res int

	return f.Transport.Trip("fs.writeFile", req, &res)
}

func (f *File) updateContentFromRemote() error {
	content, err := f.getContentFromRemote()
	if err != nil {
		return err
	}

	f.Content = content
	f.Attrs.Size = uint64(len(f.Content))
	f.Attrs.Mtime = time.Now()
	f.Attrs.Ctime = time.Now()

	return nil
}

func (f *File) getContentFromRemote() ([]byte, error) {
	req := struct{ Path string }{f.RemotePath}
	res := transport.FsReadFileRes{}
	if err := f.Trip("fs.readFile", req, &res); err != nil {
		return []byte{}, err
	}

	return res.Content, nil
}
<commit_msg>fix bug where reading updates file modified time<commit_after>package fuseklient

import (
	"io"

	"github.com/jacobsa/fuse/fuseutil"
	"github.com/koding/fuseklient/transport"
)

// File represents a file system file and implements Node interface.
type File struct {
	// Entry is generic structure that contains commonality between File and Dir.
	*Entry

	////// Entry#RWLock protects the fields below.

	// IsDirty indicates if File has been written to, but not yet been synced
	// with remote.
	IsDirty bool

	// Content is the remotely fetched contents of the File.
	Content []byte
}

// NewFile is the required initializeChild for File. If internal cache is empty,
// it'll fetch from remote.
func NewFile(n *Entry) *File {
	return &File{Entry: n, Content: []byte{}}
}

// ReadAt returns contents of file at specified offset.
func (f *File) ReadAt(offset int64) ([]byte, error) {
	f.Lock()
	defer f.Unlock()

	// fetch from remote is no content
	if len(f.Content) == 0 {
		if err := f.updateContentFromRemote(); err != nil {
			return nil, err
		}
	}

	// check offset only after fetching from remote
	if offset > int64(len(f.Content)) {
		return nil, io.EOF
	}

	return f.Content[offset:], nil
}

// Create creates a new file on remote with existing content.
func (f *File) Create() error {
	f.Lock()
	defer f.Unlock()

	return f.writeContentToRemote(f.Content)
}

// WriteAt saves specified content at specified offset. Note, this saves to
// internal cache only.
func (f *File) WriteAt(content []byte, offset int64) {
	f.Lock()
	defer f.Unlock()

	f.IsDirty = true

	var newLen = len(content) + int(offset)
	if len(f.Content) < newLen {
		padding := make([]byte, newLen-len(f.Content))
		f.Content = append(f.Content, padding...)
	}

	copy(f.Content[offset:], content)

	if offset == 0 {
		f.Content = f.Content[0:len(content)]
	}

	f.Attrs.Size = uint64(len(f.Content))
}

// TruncateTo reduces file contents to specified length.
func (f *File) TruncateTo(size uint64) error {
	f.Lock()
	defer f.Unlock()

	s := int(size)
	switch {
	case s < len(f.Content):
		// specified size less than size of file, so remove all content over size
		f.Content = f.Content[:size]
	case s > len(f.Content):
		// specified size greater same as size of file, so add empty padding to
		// existing content
		f.Content = append(f.Content, make([]byte, s-len(f.Content))...)
	case s == len(f.Content):
		// specified size is same as size of file, so nothing to be done
	}

	return f.writeContentToRemote(f.Content)
}

// Flush saves internal cache to remote.
func (f *File) Flush() error {
	f.Lock()
	defer f.Unlock()

	return f.syncToRemote()
}

// Sync saves internal cache to remote.
func (f *File) Sync() error {
	f.Lock()
	defer f.Unlock()

	return f.syncToRemote()
}

///// Node interface

// GetType returns fuseutil.DT_File for identification for fuse library.
func (f *File) GetType() fuseutil.DirentType {
	return fuseutil.DT_File
}

// Expire removes the internal cache of file and fetches it from remote. It's
// required to update from remote since Kernel caches file attrs.
func (f *File) Expire() error {
	f.Lock()
	defer f.Unlock()

	// OH THE HORROR!
	// If remote has a change where size of file hasn't changed, then Kernel
	// doesn't invalidate the local cache, so we replace the InodeId.
	f.ID = f.Parent.IDGen.Next()

	return f.updateContentFromRemote()
}

///// Helpers

func (f *File) syncToRemote() error {
	var isDirty = f.IsDirty
	if !isDirty {
		return nil
	}

	return f.writeContentToRemote(f.Content)
}

func (f *File) writeContentToRemote(content []byte) error {
	f.IsDirty = false

	req := struct {
		Path    string
		Content []byte
	}{
		Path:    f.RemotePath,
		Content: content,
	}
	var res int

	return f.Transport.Trip("fs.writeFile", req, &res)
}

func (f *File) updateContentFromRemote() error {
	content, err := f.getContentFromRemote()
	if err != nil {
		return err
	}

	f.Content = content
	f.Attrs.Size = uint64(len(f.Content))

	return nil
}

func (f *File) getContentFromRemote() ([]byte, error) {
	req := struct{ Path string }{f.RemotePath}
	res := transport.FsReadFileRes{}
	if err := f.Trip("fs.readFile", req, &res); err != nil {
		return []byte{}, err
	}

	return res.Content, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/codegangsta/cli"

	"github.com/yuuki1/grabeni/aws"
	. "github.com/yuuki1/grabeni/log"
)

var Commands = []cli.Command{
	commandStatus,
	commandList,
	commandGrab,
	commandAttach,
	commandDetach,
}

var commandStatus = cli.Command{
	Name:  "status",
	Usage: "Show ENI status",
	Description: `
    Show the information of the ENI identified with <eni-id>.
`,
	Action: doStatus,
}

var commandList = cli.Command{
	Name:  "list",
	Usage: "Show all ENIs",
	Description: `
    List the ENIs owned by your account.
`,
	Action: doList,
}

var commandGrab = cli.Command{
	Name:  "grab",
	Usage: "Detach and attach ENI",
	Description: `
    Detach the ENI identified with <eni-id> whether the eni has already attached or not. And then attach the ENI to EC2 instance identified with --instanceid option.
`,
	Action: doGrab,
	Flags: []cli.Flag{
		cli.IntFlag{Name: "d, deviceindex", Value: 1, Usage: "device index number"},
		cli.StringFlag{Name: "I, instanceid", Usage: "attach-targeted instance id"},
		cli.IntFlag{Name: "t, timeout", Value: 10, Usage: "each attach and detach API request timeout seconds"},
		cli.IntFlag{Name: "i, interval", Value: 2, Usage: "each attach and detach API request polling interval seconds"},
	},
}

var commandAttach = cli.Command{
	Name:  "attach",
	Usage: "Attach ENI",
	Description: `
    Just attach the ENI identified with <eni-id> to EC2 instance identified with --instanceid option.
`,
	Action: doAttach,
	Flags: []cli.Flag{
		cli.IntFlag{Name: "d, deviceindex", Value: 1, Usage: "device index number"},
		cli.StringFlag{Name: "I, instanceid", Usage: "attach-targeted instance id"},
		cli.IntFlag{Name: "t, timeout", Value: 10, Usage: "each attach and detach API request timeout seconds"},
		cli.IntFlag{Name: "i, interval", Value: 2, Usage: "each attach and detach API request polling interval seconds"},
	},
}

var commandDetach = cli.Command{
	Name:  "detach",
	Usage: "Detach ENI",
	Description: `
    Just detach the ENI identified with <eni-id>.
`,
	Action: doDetach,
	Flags: []cli.Flag{
		cli.IntFlag{Name: "t, timeout", Value: 10, Usage: "each attach and detach API request timeout seconds"},
		cli.IntFlag{Name: "i, interval", Value: 2, Usage: "each attach and detach API request polling interval seconds"},
	},
}

type commandDoc struct {
	Parent    string
	Arguments string
}

var commandDocs = map[string]commandDoc{
	"status": {"", "<eni-id>"},
	"list":  {"", ""},
	"grab": {"", "[--deviceindex | -d <device index> (default: 1)] [--instanceid | -i <instance id>] <eni-id>"},
	"attach": {"", "[--deviceindex | -d <device index> (default: 1)] [--instanceid | -i <instance id>] <eni-id>"},
	"detach":  {"", "<eni-id>"},
}

// Makes template conditionals to generate per-command documents.
func mkCommandsTemplate(genTemplate func(commandDoc) string) string {
	template := "{{if false}}"
	for _, command := range append(Commands) {
		template = template + fmt.Sprintf("{{else if (eq .Name %q)}}%s", command.Name, genTemplate(commandDocs[command.Name]))
	}
	return template + "{{end}}"
}

func init() {
	argsTemplate := mkCommandsTemplate(func(doc commandDoc) string { return doc.Arguments })
	parentTemplate := mkCommandsTemplate(func(doc commandDoc) string { return string(strings.TrimLeft(doc.Parent+" ", " ")) })

	cli.CommandHelpTemplate = `NAME:
    {{.Name}} - {{.Usage}}

USAGE:
    grabeni ` + parentTemplate + `{{.Name}} ` + argsTemplate + `
{{if (len .Description)}}
DESCRIPTION: {{.Description}}
{{end}}{{if (len .Flags)}}
OPTIONS:
    {{range .Flags}}{{.}}
    {{end}}
{{end}}`
}

func awsCli(c *cli.Context) *aws.Client {
	client, err := aws.NewClient(
		c.GlobalString("region"),
		c.GlobalString("accesskey"),
		c.GlobalString("secretkey"),
	)
	DieIf(err)
	return client
}

func fetchInstanceIDIfEmpty(c *cli.Context) string {
	if instanceID := c.String("instanceid"); instanceID != "" {
		return c.String(instanceID)
	}

	instanceID, err := aws.GetInstanceID()
	if err != nil {
		cli.ShowCommandHelp(c, c.Command.Name)
		DieIf(err)
	}

	return instanceID
}

func doStatus(c *cli.Context) {
	if len(c.Args()) < 1 {
		cli.ShowCommandHelp(c, "status")
		os.Exit(1)
	}

	eniID := c.Args()[0]
	if eniID == "" {
		cli.ShowCommandHelp(c, "status")
		os.Exit(1)
	}

	eni, err := awsCli(c).DescribeENIByID(eniID)
	DieIf(err)
	if eni == nil {
		os.Exit(0)
	}

	fmt.Println(StatusHeader())
	fmt.Println(StatusRow(eni))
}

func doList(c *cli.Context) {
	enis, err := awsCli(c).DescribeENIs()
	DieIf(err)
	if enis == nil {
		os.Exit(0)
	}

	fmt.Println(StatusHeader())
	for _, eni := range enis {
		fmt.Println(StatusRow(eni))
	}
}

func doGrab(c *cli.Context) {
	if len(c.Args()) < 1 {
		cli.ShowCommandHelp(c, "grab")
		os.Exit(1)
	}

	eniID := c.Args()[0]
	if eniID == "" {
		cli.ShowCommandHelp(c, "grab")
		os.Exit(1)
	}

	instanceID := fetchInstanceIDIfEmpty(c)
	deviceIndex := c.Int("deviceindex")

	err, ok := awsCli(c).GrabENI(&aws.GrabENIParam{
		InterfaceID: eniID,
		InstanceID: instanceID,
		DeviceIndex: deviceIndex,
	}, &aws.RetryParam{
		TimeoutSec: int64(c.Int("timeout")),
		IntervalSec: int64(c.Int("interval")),
	})
	DieIf(err)
	if !ok {
		Logf("attached", "eni %s already attached to %s", eniID, instanceID)
		os.Exit(0)
	}

	Logf("grabbed", "eni %s attached to instance %s", eniID, instanceID)
}

func doAttach(c *cli.Context) {
	if len(c.Args()) < 1 {
		cli.ShowCommandHelp(c, "attach")
		os.Exit(1)
	}

	eniID := c.Args()[0]
	if eniID == "" {
		cli.ShowCommandHelp(c, "attach")
		os.Exit(1)
	}

	instanceID := fetchInstanceIDIfEmpty(c)
	deviceIndex := c.Int("deviceindex")

	err := awsCli(c).AttachENIWithRetry(&aws.AttachENIParam{
		InterfaceID: eniID,
		InstanceID: instanceID,
		DeviceIndex: deviceIndex,
	}, &aws.RetryParam{
		TimeoutSec: int64(c.Int("timeout")),
		IntervalSec: int64(c.Int("interval")),
	})
	DieIf(err)

	Logf("attached", "eni %s attached to instance %s", eniID, instanceID)
}

func doDetach(c *cli.Context) {
	if len(c.Args()) < 1 {
		cli.ShowCommandHelp(c, "detach")
		os.Exit(1)
	}

	eniID := c.Args()[0]
	if eniID == "" {
		cli.ShowCommandHelp(c, "detach")
		os.Exit(1)
	}

	err := awsCli(c).DetachENIWithRetry(&aws.DetachENIParam{
		InterfaceID: eniID,
	}, &aws.RetryParam{
		TimeoutSec: int64(c.Int("timeout")),
		IntervalSec: int64(c.Int("interval")),
	})
	DieIf(err)

	Logf("detached", "eni %s detached", eniID)
}
<commit_msg>Fix --instanceid not working<commit_after>package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/codegangsta/cli"

	"github.com/yuuki1/grabeni/aws"
	. "github.com/yuuki1/grabeni/log"
)

var Commands = []cli.Command{
	commandStatus,
	commandList,
	commandGrab,
	commandAttach,
	commandDetach,
}

var commandStatus = cli.Command{
	Name:  "status",
	Usage: "Show ENI status",
	Description: `
    Show the information of the ENI identified with <eni-id>.
`,
	Action: doStatus,
}

var commandList = cli.Command{
	Name:  "list",
	Usage: "Show all ENIs",
	Description: `
    List the ENIs owned by your account.
`,
	Action: doList,
}

var commandGrab = cli.Command{
	Name:  "grab",
	Usage: "Detach and attach ENI",
	Description: `
    Detach the ENI identified with <eni-id> whether the eni has already attached or not. And then attach the ENI to EC2 instance identified with --instanceid option.
`,
	Action: doGrab,
	Flags: []cli.Flag{
		cli.IntFlag{Name: "d, deviceindex", Value: 1, Usage: "device index number"},
		cli.StringFlag{Name: "I, instanceid", Usage: "attach-targeted instance id"},
		cli.IntFlag{Name: "t, timeout", Value: 10, Usage: "each attach and detach API request timeout seconds"},
		cli.IntFlag{Name: "i, interval", Value: 2, Usage: "each attach and detach API request polling interval seconds"},
	},
}

var commandAttach = cli.Command{
	Name:  "attach",
	Usage: "Attach ENI",
	Description: `
    Just attach the ENI identified with <eni-id> to EC2 instance identified with --instanceid option.
`,
	Action: doAttach,
	Flags: []cli.Flag{
		cli.IntFlag{Name: "d, deviceindex", Value: 1, Usage: "device index number"},
		cli.StringFlag{Name: "I, instanceid", Usage: "attach-targeted instance id"},
		cli.IntFlag{Name: "t, timeout", Value: 10, Usage: "each attach and detach API request timeout seconds"},
		cli.IntFlag{Name: "i, interval", Value: 2, Usage: "each attach and detach API request polling interval seconds"},
	},
}

var commandDetach = cli.Command{
	Name:  "detach",
	Usage: "Detach ENI",
	Description: `
    Just detach the ENI identified with <eni-id>.
`,
	Action: doDetach,
	Flags: []cli.Flag{
		cli.IntFlag{Name: "t, timeout", Value: 10, Usage: "each attach and detach API request timeout seconds"},
		cli.IntFlag{Name: "i, interval", Value: 2, Usage: "each attach and detach API request polling interval seconds"},
	},
}

type commandDoc struct {
	Parent    string
	Arguments string
}

var commandDocs = map[string]commandDoc{
	"status": {"", "<eni-id>"},
	"list":  {"", ""},
	"grab": {"", "[--deviceindex | -d <device index> (default: 1)] [--instanceid | -i <instance id>] <eni-id>"},
	"attach": {"", "[--deviceindex | -d <device index> (default: 1)] [--instanceid | -i <instance id>] <eni-id>"},
	"detach":  {"", "<eni-id>"},
}

// Makes template conditionals to generate per-command documents.
func mkCommandsTemplate(genTemplate func(commandDoc) string) string {
	template := "{{if false}}"
	for _, command := range append(Commands) {
		template = template + fmt.Sprintf("{{else if (eq .Name %q)}}%s", command.Name, genTemplate(commandDocs[command.Name]))
	}
	return template + "{{end}}"
}

func init() {
	argsTemplate := mkCommandsTemplate(func(doc commandDoc) string { return doc.Arguments })
	parentTemplate := mkCommandsTemplate(func(doc commandDoc) string { return string(strings.TrimLeft(doc.Parent+" ", " ")) })

	cli.CommandHelpTemplate = `NAME:
    {{.Name}} - {{.Usage}}

USAGE:
    grabeni ` + parentTemplate + `{{.Name}} ` + argsTemplate + `
{{if (len .Description)}}
DESCRIPTION: {{.Description}}
{{end}}{{if (len .Flags)}}
OPTIONS:
    {{range .Flags}}{{.}}
    {{end}}
{{end}}`
}

func awsCli(c *cli.Context) *aws.Client {
	client, err := aws.NewClient(
		c.GlobalString("region"),
		c.GlobalString("accesskey"),
		c.GlobalString("secretkey"),
	)
	DieIf(err)
	return client
}

func fetchInstanceIDIfEmpty(c *cli.Context) string {
	if instanceID := c.String("instanceid"); instanceID != "" {
		return instanceID
	}

	instanceID, err := aws.GetInstanceID()
	if err != nil {
		cli.ShowCommandHelp(c, c.Command.Name)
		DieIf(err)
	}

	return instanceID
}

func doStatus(c *cli.Context) {
	if len(c.Args()) < 1 {
		cli.ShowCommandHelp(c, "status")
		os.Exit(1)
	}

	eniID := c.Args()[0]
	if eniID == "" {
		cli.ShowCommandHelp(c, "status")
		os.Exit(1)
	}

	eni, err := awsCli(c).DescribeENIByID(eniID)
	DieIf(err)
	if eni == nil {
		os.Exit(0)
	}

	fmt.Println(StatusHeader())
	fmt.Println(StatusRow(eni))
}

func doList(c *cli.Context) {
	enis, err := awsCli(c).DescribeENIs()
	DieIf(err)
	if enis == nil {
		os.Exit(0)
	}

	fmt.Println(StatusHeader())
	for _, eni := range enis {
		fmt.Println(StatusRow(eni))
	}
}

func doGrab(c *cli.Context) {
	if len(c.Args()) < 1 {
		cli.ShowCommandHelp(c, "grab")
		os.Exit(1)
	}

	eniID := c.Args()[0]
	if eniID == "" {
		cli.ShowCommandHelp(c, "grab")
		os.Exit(1)
	}

	instanceID := fetchInstanceIDIfEmpty(c)
	deviceIndex := c.Int("deviceindex")

	err, ok := awsCli(c).GrabENI(&aws.GrabENIParam{
		InterfaceID: eniID,
		InstanceID: instanceID,
		DeviceIndex: deviceIndex,
	}, &aws.RetryParam{
		TimeoutSec: int64(c.Int("timeout")),
		IntervalSec: int64(c.Int("interval")),
	})
	DieIf(err)
	if !ok {
		Logf("attached", "eni %s already attached to %s", eniID, instanceID)
		os.Exit(0)
	}

	Logf("grabbed", "eni %s attached to instance %s", eniID, instanceID)
}

func doAttach(c *cli.Context) {
	if len(c.Args()) < 1 {
		cli.ShowCommandHelp(c, "attach")
		os.Exit(1)
	}

	eniID := c.Args()[0]
	if eniID == "" {
		cli.ShowCommandHelp(c, "attach")
		os.Exit(1)
	}

	instanceID := fetchInstanceIDIfEmpty(c)
	deviceIndex := c.Int("deviceindex")

	err := awsCli(c).AttachENIWithRetry(&aws.AttachENIParam{
		InterfaceID: eniID,
		InstanceID: instanceID,
		DeviceIndex: deviceIndex,
	}, &aws.RetryParam{
		TimeoutSec: int64(c.Int("timeout")),
		IntervalSec: int64(c.Int("interval")),
	})
	DieIf(err)

	Logf("attached", "eni %s attached to instance %s", eniID, instanceID)
}

func doDetach(c *cli.Context) {
	if len(c.Args()) < 1 {
		cli.ShowCommandHelp(c, "detach")
		os.Exit(1)
	}

	eniID := c.Args()[0]
	if eniID == "" {
		cli.ShowCommandHelp(c, "detach")
		os.Exit(1)
	}

	err := awsCli(c).DetachENIWithRetry(&aws.DetachENIParam{
		InterfaceID: eniID,
	}, &aws.RetryParam{
		TimeoutSec: int64(c.Int("timeout")),
		IntervalSec: int64(c.Int("interval")),
	})
	DieIf(err)

	Logf("detached", "eni %s detached", eniID)
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"sync"

	"github.com/jacobsa/gcloud/gcs"
	"golang.org/x/net/context"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
)

// A remote object's name and metadata, along with a local temporary file that
// contains its contents (when initialized).
type file struct {
	bucket     gcs.Bucket
	objectName string
	size       uint64

	mu       sync.RWMutex
	tempFile *os.File // GUARDED_BY(mu)
}

// Make sure file implements the interfaces we think it does.
var (
	_ fs.Node           = &file{}
	_ fs.Handle         = &file{}
	_ fs.HandleReader   = &file{}
	_ fs.HandleReleaser = &file{}
)

func (f *file) Attr() fuse.Attr {
	return fuse.Attr{
		// TODO(jacobsa): Expose ACLs from GCS?
		Mode: 0400,
		Size: f.size,
	}
}

// If the file contents have not yet been fetched to a temporary file, fetch
// them.
func (f *file) ensureTempFile(ctx context.Context) error {
	f.mu.Lock()
	defer f.mu.Unlock()

	// Do we already have a file?
	if f.tempFile != nil {
		return nil
	}

	// Create a temporary file.
	tempFile, err := ioutil.TempFile("", "gcsfs")
	if err != nil {
		return fmt.Errorf("ioutil.TempFile: %v", err)
	}

	// Create a reader for the object.
	readCloser, err := f.bucket.NewReader(ctx, f.objectName)
	if err != nil {
		return fmt.Errorf("bucket.NewReader: %v", err)
	}

	defer readCloser.Close()

	// Copy the object contents into the file.
	if _, err := io.Copy(tempFile, readCloser); err != nil {
		return fmt.Errorf("io.Copy: %v", err)
	}

	// Save the file for later.
	f.tempFile = tempFile

	return nil
}

// Throw away the local temporary file, if any.
func (f *file) Release(ctx context.Context, req *fuse.ReleaseRequest) error {
	f.mu.Lock()
	defer f.mu.Unlock()

	// Is there a file to close?
	if f.tempFile == nil {
		return nil
	}

	// Close it.
	if err := f.tempFile.Close(); err != nil {
		log.Println("Error closing temp file:", err)
	}

	f.tempFile = nil
	return nil
}

// Ensure that the local temporary file is initialized, then read from it.
func (f *file) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
	// Ensure the temp file is present.
	if err := f.ensureTempFile(ctx); err != nil {
		return err
	}

	// Lock to read the temp file. If it went away in the meantime, that means
	// the kernel (erroneously) released us while reading from us.
	f.mu.RLock()
	defer f.mu.RUnlock()

	// Verify our assumptions.
	if len(resp.Data) != req.Size {
		panic(fmt.Sprintf("%v-byte read request with %v-byte buffer.", req.Size, len(resp.Data)))
	}

	// Read the data.
	_, err := f.tempFile.ReadAt(resp.Data, req.Offset)

	return err
}
<commit_msg>Don't forget to delete the temp file.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"sync"

	"github.com/jacobsa/gcloud/gcs"
	"golang.org/x/net/context"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
)

// A remote object's name and metadata, along with a local temporary file that
// contains its contents (when initialized).
type file struct {
	bucket     gcs.Bucket
	objectName string
	size       uint64

	mu       sync.RWMutex
	tempFile *os.File // GUARDED_BY(mu)
}

// Make sure file implements the interfaces we think it does.
var (
	_ fs.Node           = &file{}
	_ fs.Handle         = &file{}
	_ fs.HandleReader   = &file{}
	_ fs.HandleReleaser = &file{}
)

func (f *file) Attr() fuse.Attr {
	return fuse.Attr{
		// TODO(jacobsa): Expose ACLs from GCS?
		Mode: 0400,
		Size: f.size,
	}
}

// If the file contents have not yet been fetched to a temporary file, fetch
// them.
func (f *file) ensureTempFile(ctx context.Context) error {
	f.mu.Lock()
	defer f.mu.Unlock()

	// Do we already have a file?
	if f.tempFile != nil {
		return nil
	}

	// Create a temporary file.
	tempFile, err := ioutil.TempFile("", "gcsfs")
	if err != nil {
		return fmt.Errorf("ioutil.TempFile: %v", err)
	}

	// Create a reader for the object.
	readCloser, err := f.bucket.NewReader(ctx, f.objectName)
	if err != nil {
		return fmt.Errorf("bucket.NewReader: %v", err)
	}

	defer readCloser.Close()

	// Copy the object contents into the file.
	if _, err := io.Copy(tempFile, readCloser); err != nil {
		return fmt.Errorf("io.Copy: %v", err)
	}

	// Save the file for later.
	f.tempFile = tempFile

	return nil
}

// Throw away the local temporary file, if any.
func (f *file) Release(ctx context.Context, req *fuse.ReleaseRequest) error {
	f.mu.Lock()
	defer f.mu.Unlock()

	// Is there a file to close?
	if f.tempFile == nil {
		return nil
	}

	// Close it, after grabbing its path.
	path := f.tempFile.Name()
	if err := f.tempFile.Close(); err != nil {
		log.Println("Error closing temp file:", err)
	}

	// Attempt to delete it.
	if err := os.Remove(path); err != nil {
		log.Println("Error deleting temp file:", err)
	}

	f.tempFile = nil
	return nil
}

// Ensure that the local temporary file is initialized, then read from it.
func (f *file) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
	// Ensure the temp file is present.
	if err := f.ensureTempFile(ctx); err != nil {
		return err
	}

	// Lock to read the temp file. If it went away in the meantime, that means
	// the kernel (erroneously) released us while reading from us.
	f.mu.RLock()
	defer f.mu.RUnlock()

	// Allocate a response buffer.
	resp.Data = make([]byte, req.Size)

	// Read the data.
	_, err := f.tempFile.ReadAt(resp.Data, req.Offset)

	return err
}
<|endoftext|>


<commit_before>package xlsx

import (
	"archive/zip"
	"encoding/xml"
	"fmt"
	"io"
	"os"
	"strconv"
)

// File is a high level structure providing a slice of Sheet structs
// to the user.
type File struct {
	worksheets     map[string]*zip.File
	referenceTable *RefTable
	Date1904       bool
	styles         *xlsxStyleSheet
	Sheets         []*Sheet
	Sheet          map[string]*Sheet
}

// Create a new File
func NewFile() (file *File) {
	file = &File{}
	file.Sheet = make(map[string]*Sheet)
	file.Sheets = make([]*Sheet, 0)
	return
}

// OpenFile() take the name of an XLSX file and returns a populated
// xlsx.File struct for it.
func OpenFile(filename string) (file *File, err error) {
	var f *zip.ReadCloser
	f, err = zip.OpenReader(filename)
	if err != nil {
		return nil, err
	}
	file, err = ReadZip(f)
	return
}

// A convenient wrapper around File.ToSlice, FileToSlice will
// return the raw data contained in an Excel XLSX file as three
// dimensional slice.  The first index represents the sheet number,
// the second the row number, and the third the cell number.
//
// For example:
//
//    var mySlice [][][]string
//    var value string
//    mySlice = xlsx.FileToSlice("myXLSX.xlsx")
//    value = mySlice[0][0][0]
//
// Here, value would be set to the raw value of the cell A1 in the
// first sheet in the XLSX file.
func FileToSlice(path string) ([][][]string, error) {
	f, err := OpenFile(path)
	if err != nil {
		return nil, err
	}
	return f.ToSlice()
}

// Save the File to an xlsx file at the provided path.
func (f *File) Save(path string) (err error) {
	var parts map[string]string
	var target *os.File
	var zipWriter *zip.Writer

	parts, err = f.MarshallParts()
	if err != nil {
		return
	}

	target, err = os.Create(path)
	if err != nil {
		return
	}

	zipWriter = zip.NewWriter(target)

	for partName, part := range parts {
		var writer io.Writer
		writer, err = zipWriter.Create(partName)
		if err != nil {
			return
		}
		_, err = writer.Write([]byte(part))
		if err != nil {
			return
		}
	}
	err = zipWriter.Close()
	if err != nil {
		return
	}

	return target.Close()
}

// Add a new Sheet, with the provided name, to a File
func (f *File) AddSheet(sheetName string) (sheet *Sheet) {
	sheet = &Sheet{Name: sheetName, File: *f}
	f.Sheet[sheetName] = sheet
	f.Sheets = append(f.Sheets, sheet)
	return sheet
}

func (f *File) makeWorkbook() xlsxWorkbook {
	var workbook xlsxWorkbook
	workbook = xlsxWorkbook{}
	workbook.FileVersion = xlsxFileVersion{}
	workbook.FileVersion.AppName = "Go XLSX"
	workbook.WorkbookPr = xlsxWorkbookPr{
		BackupFile:  false,
		ShowObjects: "all"}
	workbook.BookViews = xlsxBookViews{}
	workbook.BookViews.WorkBookView = make([]xlsxWorkBookView, 1)
	workbook.BookViews.WorkBookView[0] = xlsxWorkBookView{
		ActiveTab:            0,
		FirstSheet:           0,
		ShowHorizontalScroll: true,
		ShowSheetTabs:        true,
		ShowVerticalScroll:   true,
		TabRatio:             204,
		WindowHeight:         8192,
		WindowWidth:          16384,
		XWindow:              "0",
		YWindow:              "0"}
	workbook.Sheets = xlsxSheets{}
	workbook.Sheets.Sheet = make([]xlsxSheet, len(f.Sheets))
	workbook.CalcPr.IterateCount = 100
	workbook.CalcPr.RefMode = "A1"
	workbook.CalcPr.Iterate = false
	workbook.CalcPr.IterateDelta = 0.001
	return workbook
}

// Construct a map of file name to XML content representing the file
// in terms of the structure of an XLSX file.
func (f *File) MarshallParts() (map[string]string, error) {
	var parts map[string]string
	var refTable *RefTable = NewSharedStringRefTable()
	refTable.isWrite = true
	var workbookRels WorkBookRels = make(WorkBookRels)
	var err error
	var workbook xlsxWorkbook
	var types xlsxTypes = MakeDefaultContentTypes()

	marshal := func(thing interface{}) (string, error) {
		body, err := xml.Marshal(thing)
		if err != nil {
			return "", err
		}
		return xml.Header + string(body), nil
	}

	parts = make(map[string]string)
	workbook = f.makeWorkbook()
	sheetIndex := 1

	styles := &xlsxStyleSheet{}
	for _, sheet := range f.Sheets {
		xSheet := sheet.makeXLSXSheet(refTable, styles)
		rId := fmt.Sprintf("rId%d", sheetIndex)
		sheetId := strconv.Itoa(sheetIndex)
		sheetPath := fmt.Sprintf("worksheets/sheet%d.xml", sheetIndex)
		partName := "xl/" + sheetPath
		types.Overrides = append(
			types.Overrides,
			xlsxOverride{
				PartName:    "/" + partName,
				ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"})
		workbookRels[rId] = sheetPath
		workbook.Sheets.Sheet[sheetIndex-1] = xlsxSheet{
			Name:    sheet.Name,
			SheetId: sheetId,
			Id:      rId,
			State:   "visible"}
		parts[partName], err = marshal(xSheet)
		if err != nil {
			return parts, err
		}
		sheetIndex++
	}

	parts["xl/workbook.xml"], err = marshal(workbook)
	if err != nil {
		return parts, err
	}

	parts["_rels/.rels"] = TEMPLATE__RELS_DOT_RELS
	parts["docProps/app.xml"] = TEMPLATE_DOCPROPS_APP
	// TODO - do this properly, modification and revision information
	parts["docProps/core.xml"] = TEMPLATE_DOCPROPS_CORE
	parts["xl/theme/theme1.xml"] = TEMPLATE_XL_THEME_THEME

	xSST := refTable.makeXLSXSST()
	parts["xl/sharedStrings.xml"], err = marshal(xSST)
	if err != nil {
		return parts, err
	}

	xWRel := workbookRels.MakeXLSXWorkbookRels()

	parts["xl/_rels/workbook.xml.rels"], err = marshal(xWRel)
	if err != nil {
		return parts, err
	}

	parts["[Content_Types].xml"], err = marshal(types)
	if err != nil {
		return parts, err
	}

	parts["xl/styles.xml"], err = styles.Marshal()
	if err != nil {
		return parts, err
	}

	return parts, nil
}

// Return the raw data contained in the File as three
// dimensional slice.  The first index represents the sheet number,
// the second the row number, and the third the cell number.
//
// For example:
//
//    var mySlice [][][]string
//    var value string
//    mySlice = xlsx.FileToSlice("myXLSX.xlsx")
//    value = mySlice[0][0][0]
//
// Here, value would be set to the raw value of the cell A1 in the
// first sheet in the XLSX file.
func (file *File) ToSlice() (output [][][]string, err error) {
	output = [][][]string{}
	for _, sheet := range file.Sheets {
		s := [][]string{}
		for _, row := range sheet.Rows {
			if row == nil {
				continue
			}
			r := []string{}
			for _, cell := range row.Cells {
				r = append(r, cell.String())
			}
			s = append(s, r)
		}
		output = append(output, s)
	}
	return output, nil
}
<commit_msg>Write File to io.Writer<commit_after>package xlsx

import (
	"archive/zip"
	"encoding/xml"
	"fmt"
	"io"
	"os"
	"strconv"
)

// File is a high level structure providing a slice of Sheet structs
// to the user.
type File struct {
	worksheets     map[string]*zip.File
	referenceTable *RefTable
	Date1904       bool
	styles         *xlsxStyleSheet
	Sheets         []*Sheet
	Sheet          map[string]*Sheet
}

// Create a new File
func NewFile() (file *File) {
	file = &File{}
	file.Sheet = make(map[string]*Sheet)
	file.Sheets = make([]*Sheet, 0)
	return
}

// OpenFile() take the name of an XLSX file and returns a populated
// xlsx.File struct for it.
func OpenFile(filename string) (file *File, err error) {
	var f *zip.ReadCloser
	f, err = zip.OpenReader(filename)
	if err != nil {
		return nil, err
	}
	file, err = ReadZip(f)
	return
}

// A convenient wrapper around File.ToSlice, FileToSlice will
// return the raw data contained in an Excel XLSX file as three
// dimensional slice.  The first index represents the sheet number,
// the second the row number, and the third the cell number.
//
// For example:
//
//    var mySlice [][][]string
//    var value string
//    mySlice = xlsx.FileToSlice("myXLSX.xlsx")
//    value = mySlice[0][0][0]
//
// Here, value would be set to the raw value of the cell A1 in the
// first sheet in the XLSX file.
func FileToSlice(path string) ([][][]string, error) {
	f, err := OpenFile(path)
	if err != nil {
		return nil, err
	}
	return f.ToSlice()
}

// Save the File to an xlsx file at the provided path.
func (f *File) Save(path string) (err error) {
	var target *os.File

	target, err = os.Create(path)
	if err != nil {
		return
	}

	err = f.Write(target)
	if err != nil {
		return
	}

	return target.Close()
}

// Write the File to io.Writer as xlsx
func (f *File) Write(writer io.Writer) (err error) {
	var parts map[string]string
	var zipWriter *zip.Writer

	parts, err = f.MarshallParts()
	if err != nil {
		return
	}

	zipWriter = zip.NewWriter(writer)

	for partName, part := range parts {
		var writer io.Writer
		writer, err = zipWriter.Create(partName)
		if err != nil {
			return
		}
		_, err = writer.Write([]byte(part))
		if err != nil {
			return
		}
	}

	err = zipWriter.Close()

	return
}

// Add a new Sheet, with the provided name, to a File
func (f *File) AddSheet(sheetName string) (sheet *Sheet) {
	sheet = &Sheet{Name: sheetName, File: *f}
	f.Sheet[sheetName] = sheet
	f.Sheets = append(f.Sheets, sheet)
	return sheet
}

func (f *File) makeWorkbook() xlsxWorkbook {
	var workbook xlsxWorkbook
	workbook = xlsxWorkbook{}
	workbook.FileVersion = xlsxFileVersion{}
	workbook.FileVersion.AppName = "Go XLSX"
	workbook.WorkbookPr = xlsxWorkbookPr{
		BackupFile:  false,
		ShowObjects: "all"}
	workbook.BookViews = xlsxBookViews{}
	workbook.BookViews.WorkBookView = make([]xlsxWorkBookView, 1)
	workbook.BookViews.WorkBookView[0] = xlsxWorkBookView{
		ActiveTab:            0,
		FirstSheet:           0,
		ShowHorizontalScroll: true,
		ShowSheetTabs:        true,
		ShowVerticalScroll:   true,
		TabRatio:             204,
		WindowHeight:         8192,
		WindowWidth:          16384,
		XWindow:              "0",
		YWindow:              "0"}
	workbook.Sheets = xlsxSheets{}
	workbook.Sheets.Sheet = make([]xlsxSheet, len(f.Sheets))
	workbook.CalcPr.IterateCount = 100
	workbook.CalcPr.RefMode = "A1"
	workbook.CalcPr.Iterate = false
	workbook.CalcPr.IterateDelta = 0.001
	return workbook
}

// Construct a map of file name to XML content representing the file
// in terms of the structure of an XLSX file.
func (f *File) MarshallParts() (map[string]string, error) {
	var parts map[string]string
	var refTable *RefTable = NewSharedStringRefTable()
	refTable.isWrite = true
	var workbookRels WorkBookRels = make(WorkBookRels)
	var err error
	var workbook xlsxWorkbook
	var types xlsxTypes = MakeDefaultContentTypes()

	marshal := func(thing interface{}) (string, error) {
		body, err := xml.Marshal(thing)
		if err != nil {
			return "", err
		}
		return xml.Header + string(body), nil
	}

	parts = make(map[string]string)
	workbook = f.makeWorkbook()
	sheetIndex := 1

	styles := &xlsxStyleSheet{}
	for _, sheet := range f.Sheets {
		xSheet := sheet.makeXLSXSheet(refTable, styles)
		rId := fmt.Sprintf("rId%d", sheetIndex)
		sheetId := strconv.Itoa(sheetIndex)
		sheetPath := fmt.Sprintf("worksheets/sheet%d.xml", sheetIndex)
		partName := "xl/" + sheetPath
		types.Overrides = append(
			types.Overrides,
			xlsxOverride{
				PartName:    "/" + partName,
				ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"})
		workbookRels[rId] = sheetPath
		workbook.Sheets.Sheet[sheetIndex-1] = xlsxSheet{
			Name:    sheet.Name,
			SheetId: sheetId,
			Id:      rId,
			State:   "visible"}
		parts[partName], err = marshal(xSheet)
		if err != nil {
			return parts, err
		}
		sheetIndex++
	}

	parts["xl/workbook.xml"], err = marshal(workbook)
	if err != nil {
		return parts, err
	}

	parts["_rels/.rels"] = TEMPLATE__RELS_DOT_RELS
	parts["docProps/app.xml"] = TEMPLATE_DOCPROPS_APP
	// TODO - do this properly, modification and revision information
	parts["docProps/core.xml"] = TEMPLATE_DOCPROPS_CORE
	parts["xl/theme/theme1.xml"] = TEMPLATE_XL_THEME_THEME

	xSST := refTable.makeXLSXSST()
	parts["xl/sharedStrings.xml"], err = marshal(xSST)
	if err != nil {
		return parts, err
	}

	xWRel := workbookRels.MakeXLSXWorkbookRels()

	parts["xl/_rels/workbook.xml.rels"], err = marshal(xWRel)
	if err != nil {
		return parts, err
	}

	parts["[Content_Types].xml"], err = marshal(types)
	if err != nil {
		return parts, err
	}

	parts["xl/styles.xml"], err = styles.Marshal()
	if err != nil {
		return parts, err
	}

	return parts, nil
}

// Return the raw data contained in the File as three
// dimensional slice.  The first index represents the sheet number,
// the second the row number, and the third the cell number.
//
// For example:
//
//    var mySlice [][][]string
//    var value string
//    mySlice = xlsx.FileToSlice("myXLSX.xlsx")
//    value = mySlice[0][0][0]
//
// Here, value would be set to the raw value of the cell A1 in the
// first sheet in the XLSX file.
func (file *File) ToSlice() (output [][][]string, err error) {
	output = [][][]string{}
	for _, sheet := range file.Sheets {
		s := [][]string{}
		for _, row := range sheet.Rows {
			if row == nil {
				continue
			}
			r := []string{}
			for _, cell := range row.Cells {
				r = append(r, cell.String())
			}
			s = append(s, r)
		}
		output = append(output, s)
	}
	return output, nil
}
<|endoftext|>


<commit_before>package torrent

import (
	"strings"

	"github.com/anacrolix/torrent/metainfo"
)

// Provides access to regions of torrent data that correspond to its files.
type File struct {
	t      Torrent
	path   string
	offset int64
	length int64
	fi     metainfo.FileInfo
}

func (f *File) Torrent() Torrent {
	return f.t
}

// Data for this file begins this far into the torrent.
func (f *File) Offset() int64 {
	return f.offset
}

func (f File) FileInfo() metainfo.FileInfo {
	return f.fi
}

func (f File) Path() string {
	return f.path
}

func (f *File) Length() int64 {
	return f.length
}

// The relative file path for a multi-file torrent, and the torrent name for a
// single-file torrent.
func (f *File) DisplayPath() string {
	fip := f.FileInfo().Path
	if len(fip) == 0 {
		return f.t.Info().Name
	}
	return strings.Join(fip, "/")

}

type FilePieceState struct {
	Bytes int64 // Bytes within the piece that are part of this File.
	PieceState
}

// Returns the state of pieces in this file.
func (f *File) State() (ret []FilePieceState) {
	pieceSize := int64(f.t.torrent.usualPieceSize())
	off := f.offset % pieceSize
	remaining := f.length
	for i := int(f.offset / pieceSize); ; i++ {
		if remaining == 0 {
			break
		}
		len1 := pieceSize - off
		if len1 > remaining {
			len1 = remaining
		}
		f.t.cl.mu.RLock()
		ps := f.t.torrent.pieceState(i)
		f.t.cl.mu.RUnlock()
		ret = append(ret, FilePieceState{len1, ps})
		off = 0
		remaining -= len1
	}
	return
}

func (f *File) Download() {
	f.t.DownloadPieces(f.t.torrent.byteRegionPieces(f.offset, f.length))
}

func byteRegionExclusivePieces(off, size, pieceSize int64) (begin, end int) {
	begin = int((off + pieceSize - 1) / pieceSize)
	end = int((off + size) / pieceSize)
	return
}

func (f *File) exclusivePieces() (begin, end int) {
	return byteRegionExclusivePieces(f.offset, f.length, int64(f.t.torrent.usualPieceSize()))
}

func (f *File) Cancel() {
	f.t.CancelPieces(f.exclusivePieces())
}
<commit_msg>Reinstate File.PrioritizeRegion() for backward compatibility<commit_after>package torrent

import (
	"strings"

	"github.com/anacrolix/torrent/metainfo"
)

// Provides access to regions of torrent data that correspond to its files.
type File struct {
	t      Torrent
	path   string
	offset int64
	length int64
	fi     metainfo.FileInfo
}

func (f *File) Torrent() Torrent {
	return f.t
}

// Data for this file begins this far into the torrent.
func (f *File) Offset() int64 {
	return f.offset
}

func (f File) FileInfo() metainfo.FileInfo {
	return f.fi
}

func (f File) Path() string {
	return f.path
}

func (f *File) Length() int64 {
	return f.length
}

// The relative file path for a multi-file torrent, and the torrent name for a
// single-file torrent.
func (f *File) DisplayPath() string {
	fip := f.FileInfo().Path
	if len(fip) == 0 {
		return f.t.Info().Name
	}
	return strings.Join(fip, "/")

}

type FilePieceState struct {
	Bytes int64 // Bytes within the piece that are part of this File.
	PieceState
}

// Returns the state of pieces in this file.
func (f *File) State() (ret []FilePieceState) {
	pieceSize := int64(f.t.torrent.usualPieceSize())
	off := f.offset % pieceSize
	remaining := f.length
	for i := int(f.offset / pieceSize); ; i++ {
		if remaining == 0 {
			break
		}
		len1 := pieceSize - off
		if len1 > remaining {
			len1 = remaining
		}
		f.t.cl.mu.RLock()
		ps := f.t.torrent.pieceState(i)
		f.t.cl.mu.RUnlock()
		ret = append(ret, FilePieceState{len1, ps})
		off = 0
		remaining -= len1
	}
	return
}

func (f *File) Download() {
	f.t.DownloadPieces(f.t.torrent.byteRegionPieces(f.offset, f.length))
}

func (f *File) PrioritizeRegion(off, len int64) {
	f.t.DownloadPieces(f.t.torrent.byteRegionPieces(f.offset+off, len))
}

func byteRegionExclusivePieces(off, size, pieceSize int64) (begin, end int) {
	begin = int((off + pieceSize - 1) / pieceSize)
	end = int((off + size) / pieceSize)
	return
}

func (f *File) exclusivePieces() (begin, end int) {
	return byteRegionExclusivePieces(f.offset, f.length, int64(f.t.torrent.usualPieceSize()))
}

func (f *File) Cancel() {
	f.t.CancelPieces(f.exclusivePieces())
}
<|endoftext|>