<commit_before>// estab exports elasticsearch fields as tab separated values
package main

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"runtime/pprof"
	"strconv"
	"strings"

	"github.com/belogik/goes"
	"github.com/miku/estab"
)

func main() {

	host := flag.String("host", "localhost", "elasticsearch host")
	port := flag.String("port", "9200", "elasticsearch port")
	indicesString := flag.String("indices", "", "indices to search (or all)")
	fieldsString := flag.String("f", "_id _index", "field or fields space separated")
	timeout := flag.String("timeout", "10m", "scroll timeout")
	size := flag.Int("size", 10000, "scroll batch size")
	nullValue := flag.String("null", "NOT_AVAILABLE", "value for empty fields")
	separator := flag.String("separator", "|", "separator to use for multiple field values")
	delimiter := flag.String("delimiter", "\t", "column delimiter")
	limit := flag.Int("limit", -1, "maximum number of docs to return (return all by default)")
	version := flag.Bool("v", false, "prints current program version")
	cpuprofile := flag.String("cpuprofile", "", "write cpu profile to file")
	queryString := flag.String("query", "", "custom query to run")
	raw := flag.Bool("raw", false, "stream out the raw json records")
	header := flag.Bool("header", false, "output header row with thie field names")
	singleValue := flag.Bool("1", false, "one value per line (works only with a single column in -f)")
	zeroAsNull := flag.Bool("zero-as-null", false, "treat zero length strings as null values")
	precision := flag.Int("precision", 0, "precision for numeric output")

	flag.Parse()

	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	if *version {
		fmt.Println(estab.Version)
		os.Exit(0)
	}

	var query map[string]interface{}
	if *queryString == "" {
		query = map[string]interface{}{
			"query": map[string]interface{}{
				"match_all": map[string]interface{}{},
			},
		}
	} else {
		err := json.Unmarshal([]byte(*queryString), &query)
		if err != nil {
			log.Fatal(err)
		}
	}

	indices := strings.Fields(*indicesString)
	fields := strings.Fields(*fieldsString)

	if *raw && *singleValue {
		log.Fatal("-1 xor -raw ")
	}

	if *singleValue && len(fields) > 1 {
		log.Fatalf("-1 works only with a single column, %d given: %s\n", len(fields), strings.Join(fields, " "))
	}

	if !*raw {
		query["fields"] = fields
	}

	conn := goes.NewConnection(*host, *port)
	scanResponse, err := conn.Scan(query, indices, []string{""}, *timeout, *size)
	if err != nil {
		log.Fatal(err)
	}

	w := bufio.NewWriter(os.Stdout)
	defer w.Flush()
	i := 0

    if *header {
		fmt.Fprintln(w, strings.Join(fields, *delimiter))
	}

	for {
		scrollResponse, err := conn.Scroll(scanResponse.ScrollId, *timeout)
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatal(err)
		}
		if len(scrollResponse.Hits.Hits) == 0 {
			break
		}
		for _, hit := range scrollResponse.Hits.Hits {
			if i == *limit {
				return
			}
			if *raw {
				b, err := json.Marshal(hit)
				if err != nil {
					log.Fatal(err)
				}
				fmt.Fprintln(w, string(b))
				continue
			}

			var columns []string
			for _, f := range fields {
				var c []string
				switch f {
				case "_id":
					c = append(c, hit.Id)
				case "_index":
					c = append(c, hit.Index)
				case "_type":
					c = append(c, hit.Type)
				case "_score":
					c = append(c, strconv.FormatFloat(hit.Score, 'f', 6, 64))
				default:
					switch value := hit.Fields[f].(type) {
					case nil:
						c = []string{*nullValue}
					case []interface{}:
						for _, e := range value {
							switch e.(type) {
							case string:
								s := e.(string)
								if s == "" && *zeroAsNull {
									c = append(c, *nullValue)
								} else {
									c = append(c, e.(string))
								}
							case float64:
								c = append(c, strconv.FormatFloat(e.(float64), 'f', *precision, 64))
							}
						}
					default:
						log.Fatalf("unknown field type in response: %+v\n", hit.Fields[f])
					}
				}
				if *singleValue {
					for _, value := range c {
						fmt.Fprintln(w, value)
					}
				} else {
					columns = append(columns, strings.Join(c, *separator))
				}
			}
			if !*singleValue {
				fmt.Fprintln(w, strings.Join(columns, *delimiter))
			}
			i++
		}
	}
}
<commit_msg>correct typo and formatting<commit_after>// estab exports elasticsearch fields as tab separated values
package main

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"runtime/pprof"
	"strconv"
	"strings"

	"github.com/belogik/goes"
	"github.com/miku/estab"
)

func main() {

	host := flag.String("host", "localhost", "elasticsearch host")
	port := flag.String("port", "9200", "elasticsearch port")
	indicesString := flag.String("indices", "", "indices to search (or all)")
	fieldsString := flag.String("f", "_id _index", "field or fields space separated")
	timeout := flag.String("timeout", "10m", "scroll timeout")
	size := flag.Int("size", 10000, "scroll batch size")
	nullValue := flag.String("null", "NOT_AVAILABLE", "value for empty fields")
	separator := flag.String("separator", "|", "separator to use for multiple field values")
	delimiter := flag.String("delimiter", "\t", "column delimiter")
	limit := flag.Int("limit", -1, "maximum number of docs to return (return all by default)")
	version := flag.Bool("v", false, "prints current program version")
	cpuprofile := flag.String("cpuprofile", "", "write cpu profile to file")
	queryString := flag.String("query", "", "custom query to run")
	raw := flag.Bool("raw", false, "stream out the raw json records")
	header := flag.Bool("header", false, "output header row with field names")
	singleValue := flag.Bool("1", false, "one value per line (works only with a single column in -f)")
	zeroAsNull := flag.Bool("zero-as-null", false, "treat zero length strings as null values")
	precision := flag.Int("precision", 0, "precision for numeric output")

	flag.Parse()

	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	if *version {
		fmt.Println(estab.Version)
		os.Exit(0)
	}

	var query map[string]interface{}
	if *queryString == "" {
		query = map[string]interface{}{
			"query": map[string]interface{}{
				"match_all": map[string]interface{}{},
			},
		}
	} else {
		err := json.Unmarshal([]byte(*queryString), &query)
		if err != nil {
			log.Fatal(err)
		}
	}

	indices := strings.Fields(*indicesString)
	fields := strings.Fields(*fieldsString)

	if *raw && *singleValue {
		log.Fatal("-1 xor -raw ")
	}

	if *singleValue && len(fields) > 1 {
		log.Fatalf("-1 works only with a single column, %d given: %s\n", len(fields), strings.Join(fields, " "))
	}

	if !*raw {
		query["fields"] = fields
	}

	conn := goes.NewConnection(*host, *port)
	scanResponse, err := conn.Scan(query, indices, []string{""}, *timeout, *size)
	if err != nil {
		log.Fatal(err)
	}

	w := bufio.NewWriter(os.Stdout)
	defer w.Flush()
	i := 0

	if *header {
		fmt.Fprintln(w, strings.Join(fields, *delimiter))
	}

	for {
		scrollResponse, err := conn.Scroll(scanResponse.ScrollId, *timeout)
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatal(err)
		}
		if len(scrollResponse.Hits.Hits) == 0 {
			break
		}
		for _, hit := range scrollResponse.Hits.Hits {
			if i == *limit {
				return
			}
			if *raw {
				b, err := json.Marshal(hit)
				if err != nil {
					log.Fatal(err)
				}
				fmt.Fprintln(w, string(b))
				continue
			}

			var columns []string
			for _, f := range fields {
				var c []string
				switch f {
				case "_id":
					c = append(c, hit.Id)
				case "_index":
					c = append(c, hit.Index)
				case "_type":
					c = append(c, hit.Type)
				case "_score":
					c = append(c, strconv.FormatFloat(hit.Score, 'f', 6, 64))
				default:
					switch value := hit.Fields[f].(type) {
					case nil:
						c = []string{*nullValue}
					case []interface{}:
						for _, e := range value {
							switch e.(type) {
							case string:
								s := e.(string)
								if s == "" && *zeroAsNull {
									c = append(c, *nullValue)
								} else {
									c = append(c, e.(string))
								}
							case float64:
								c = append(c, strconv.FormatFloat(e.(float64), 'f', *precision, 64))
							}
						}
					default:
						log.Fatalf("unknown field type in response: %+v\n", hit.Fields[f])
					}
				}
				if *singleValue {
					for _, value := range c {
						fmt.Fprintln(w, value)
					}
				} else {
					columns = append(columns, strings.Join(c, *separator))
				}
			}
			if !*singleValue {
				fmt.Fprintln(w, strings.Join(columns, *delimiter))
			}
			i++
		}
	}
}
<|endoftext|>


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

package main

import (
	"context"
	"flag"
	"fmt"
	"math"
	"path/filepath"

	"github.com/google/gapid/core/app"
	"github.com/google/gapid/core/log"
	"github.com/google/gapid/gapis/client"
	"github.com/google/gapid/gapis/service"
	"github.com/google/gapid/gapis/service/path"
)

type infoVerb struct{ StatsFlags }

func init() {
	verb := &infoVerb{}
	verb.Frames.Count = -1
	app.AddVerb(&app.Verb{
		Name:      "stats",
		ShortHelp: "Prints information about a capture file",
		Action:    verb,
	})
}

func loadCapture(ctx context.Context, flags flag.FlagSet, gapisFlags GapisFlags) (client.Client, *path.Capture, error) {
	if flags.NArg() != 1 {
		app.Usage(ctx, "Exactly one gfx trace file expected, got %d", flags.NArg())
		return nil, nil, nil
	}

	filepath, err := filepath.Abs(flags.Arg(0))
	if err != nil {
		return nil, nil, log.Errf(ctx, err, "Finding file: %v", flags.Arg(0))
	}

	client, err := getGapis(ctx, gapisFlags, GapirFlags{})
	if err != nil {
		return nil, nil, log.Err(ctx, err, "Failed to connect to the GAPIS server")
	}

	capture, err := client.LoadCapture(ctx, filepath)
	if err != nil {
		return nil, nil, log.Errf(ctx, err, "LoadCapture(%v)", filepath)
	}

	return client, capture, nil
}

func (verb *infoVerb) getEventsInRange(ctx context.Context, client service.Service, capture *path.Capture) ([]*service.Event, error) {
	events, err := getEvents(ctx, client, &path.Events{
		Capture:                 capture,
		AllCommands:             true,
		DrawCalls:               true,
		FirstInFrame:            true,
		FramebufferObservations: true,
	})
	if err != nil {
		return nil, err
	}

	if verb.Frames.Start == 0 && verb.Frames.Count == -1 {
		return events, err
	}

	fifIndices := []uint64{}
	for _, e := range events {
		if e.Kind == service.EventKind_FirstInFrame {
			fifIndices = append(fifIndices, e.Command.Indices[0])
		}
	}

	if verb.Frames.Start > len(fifIndices) {
		return nil, log.Errf(ctx, nil, "Captured only %v frames, less than start frame %v", len(fifIndices), verb.Frames.Start)
	}

	startIndex := fifIndices[verb.Frames.Start]
	endIndex := uint64(math.MaxUint64)
	if verb.Frames.Count >= 0 &&
		verb.Frames.Start+verb.Frames.Count < len(fifIndices) {

		endIndex = fifIndices[verb.Frames.Start+verb.Frames.Count]
	}

	begin, end := len(events), len(events)
	for i, e := range events {
		if i < begin && e.Command.Indices[0] >= startIndex {
			begin = i
		}
		if i < end && e.Command.Indices[0] >= endIndex {
			end = i
		}
	}
	fmt.Println(startIndex, endIndex, begin, end)
	return events[begin:end], nil
}

func (verb *infoVerb) Run(ctx context.Context, flags flag.FlagSet) error {
	client, capture, err := loadCapture(ctx, flags, verb.Gapis)
	if err != nil {
		return err
	}
	defer client.Close()

	events, err := verb.GetEventsInRange(ctx, client, capture)

	if err != nil {
		return log.Err(ctx, err, "Couldn't get events")
	}

	counts := map[service.EventKind]int{}
	for _, e := range events {
		counts[e.Kind] = counts[e.Kind] + 1
	}

	fmt.Println("Commands: ", counts[service.EventKind_AllCommands])
	fmt.Println("Frames:   ", counts[service.EventKind_FirstInFrame])
	fmt.Println("Draws:    ", counts[service.EventKind_DrawCall])
	fmt.Println("FBO:      ", counts[service.EventKind_FramebufferObservation])
	return err
}
<commit_msg>Remove debug print<commit_after>// Copyright (C) 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"context"
	"flag"
	"fmt"
	"math"
	"path/filepath"

	"github.com/google/gapid/core/app"
	"github.com/google/gapid/core/log"
	"github.com/google/gapid/gapis/client"
	"github.com/google/gapid/gapis/service"
	"github.com/google/gapid/gapis/service/path"
)

type infoVerb struct{ StatsFlags }

func init() {
	verb := &infoVerb{}
	verb.Frames.Count = -1
	app.AddVerb(&app.Verb{
		Name:      "stats",
		ShortHelp: "Prints information about a capture file",
		Action:    verb,
	})
}

func loadCapture(ctx context.Context, flags flag.FlagSet, gapisFlags GapisFlags) (client.Client, *path.Capture, error) {
	if flags.NArg() != 1 {
		app.Usage(ctx, "Exactly one gfx trace file expected, got %d", flags.NArg())
		return nil, nil, nil
	}

	filepath, err := filepath.Abs(flags.Arg(0))
	if err != nil {
		return nil, nil, log.Errf(ctx, err, "Finding file: %v", flags.Arg(0))
	}

	client, err := getGapis(ctx, gapisFlags, GapirFlags{})
	if err != nil {
		return nil, nil, log.Err(ctx, err, "Failed to connect to the GAPIS server")
	}

	capture, err := client.LoadCapture(ctx, filepath)
	if err != nil {
		return nil, nil, log.Errf(ctx, err, "LoadCapture(%v)", filepath)
	}

	return client, capture, nil
}

func (verb *infoVerb) getEventsInRange(ctx context.Context, client service.Service, capture *path.Capture) ([]*service.Event, error) {
	events, err := getEvents(ctx, client, &path.Events{
		Capture:                 capture,
		AllCommands:             true,
		DrawCalls:               true,
		FirstInFrame:            true,
		FramebufferObservations: true,
	})
	if err != nil {
		return nil, err
	}

	if verb.Frames.Start == 0 && verb.Frames.Count == -1 {
		return events, err
	}

	fifIndices := []uint64{}
	for _, e := range events {
		if e.Kind == service.EventKind_FirstInFrame {
			fifIndices = append(fifIndices, e.Command.Indices[0])
		}
	}

	if verb.Frames.Start > len(fifIndices) {
		return nil, log.Errf(ctx, nil, "Captured only %v frames, less than start frame %v", len(fifIndices), verb.Frames.Start)
	}

	startIndex := fifIndices[verb.Frames.Start]
	endIndex := uint64(math.MaxUint64)
	if verb.Frames.Count >= 0 &&
		verb.Frames.Start+verb.Frames.Count < len(fifIndices) {

		endIndex = fifIndices[verb.Frames.Start+verb.Frames.Count]
	}

	begin, end := len(events), len(events)
	for i, e := range events {
		if i < begin && e.Command.Indices[0] >= startIndex {
			begin = i
		}
		if i < end && e.Command.Indices[0] >= endIndex {
			end = i
		}
	}
	return events[begin:end], nil
}

func (verb *infoVerb) Run(ctx context.Context, flags flag.FlagSet) error {
	client, capture, err := loadCapture(ctx, flags, verb.Gapis)
	if err != nil {
		return err
	}
	defer client.Close()

	events, err := verb.GetEventsInRange(ctx, client, capture)

	if err != nil {
		return log.Err(ctx, err, "Couldn't get events")
	}

	counts := map[service.EventKind]int{}
	for _, e := range events {
		counts[e.Kind] = counts[e.Kind] + 1
	}

	fmt.Println("Commands: ", counts[service.EventKind_AllCommands])
	fmt.Println("Frames:   ", counts[service.EventKind_FirstInFrame])
	fmt.Println("Draws:    ", counts[service.EventKind_DrawCall])
	fmt.Println("FBO:      ", counts[service.EventKind_FramebufferObservation])
	return err
}
<|endoftext|>


<commit_before>package cmd

import (
	"github.com/Masterminds/cookoo"
	"fmt"
	"os"
)

const (
	NoVCS uint = iota
	Git
	Bzr
	Hg
	Svn
)

func GetImports(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {

	cfg := p.Get("conf", nil).(*Config)

	if len(cfg.Imports) == 0 {
		Info("No dependencies found. Nothing downloaded.")
		return false, nil
	}

	for _, dep := range cfg.Imports {
		if err := VcsGet(dep); err != nil {
			Warn("Skipped getting %s: %s\n", dep.Name, err)
		}
	}

	return true, nil
}

func UpdateImports(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	cfg := p.Get("conf", nil).(*Config)

	if len(cfg.Imports) == 0 {
		Info("No dependencies found. Nothing updated.")
		return false, nil
	}

	for _, dep := range cfg.Imports {
		if err := VcsUpdate(dep); err != nil {
			Warn("Update failed for %s: %s\n", dep.Name, err)
		}
	}

	return true, nil
}

func CowardMode(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	gopath := os.Getenv("GOPATH")
	if len(gopath) == 0 {
		return false, fmt.Errorf("No GOPATH is set.")
	}

	if _, err := os.Stat(gopath); err != nil {
		return false, fmt.Errorf("Did you forget to 'glide install'? GOPATH=%s seems not to exist: %s", gopath, err)
	}

	ggpath := os.Getenv("GLIDE_GOPATH")
	if len(ggpath) > 0 && ggpath != gopath {
		Warn("Your GOPATH is set to %s, and we expected %s\n", gopath, ggpath)
	}
	return true, nil
}

func SetReference(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	cfg := p.Get("conf", nil).(*Config)

	if len(cfg.Imports) == 0 {
		Info("No dependencies found.")
		return false, nil
	}

	for _, dep := range cfg.Imports {
		if err := VcsVersion(dep); err != nil {
			Warn("Failed to set version on %s to %s: %s\n", dep.Name, dep.Reference, err)
		}
	}

	return true, nil
}

type VCS interface {
	Get(*Dependency) error
	Update(*Dependency) error
	Version(*Dependency) error
	LastCommit(*Dependency) (string, error)
}

var (
	goGet VCS = new(GoGetVCS)
	git VCS = new(GitVCS)
	svn VCS = new(SvnVCS)
	bzr VCS = new(BzrVCS)
	hg VCS = new(HgVCS)
)

// VcsGet figures out how to fetch a dependency, and then gets it.
//
// Usually it delegates to lower-level *Get functions.
//
// See https://code.google.com/p/go/source/browse/src/cmd/go/vcs.go
func VcsGet(dep *Dependency) error {

	// See note in VcsUpdate.
	if dep.Repository == "" && dep.Reference == "" {
		Info("Installing %s with 'go get'\n", dep.Name)
		return goGet.Get(dep)
	}

	switch dep.VcsType {
	case Git:
		if dep.Repository == "" {
			dep.Repository = "http://" + dep.Name
		}
		Info("Installing %s with Git (From %s)\n", dep.Name, dep.Repository)
		return git.Get(dep)
	case Bzr:
		Info("Installing %s with Bzr (From %s)\n", dep.Name, dep.Repository)
		return bzr.Get(dep)
	case Hg:
		if dep.Repository == "" {
			dep.Repository = "http://" + dep.Name
		}
		Info("Installing %s with Hg (From %s)\n", dep.Name, dep.Repository)
		return hg.Get(dep)
	case Svn:
		Info("Installing %s with Svn (From %s)\n", dep.Name, dep.Repository)
		return svn.Get(dep)
	default:
		if dep.VcsType == NoVCS {
			Info("Defaulting to 'go get %s'\n", dep.Name)
			if len(dep.Reference) > 0 {
				Warn("Ref is set to %s, but no VCS is set. This can cause inconsistencies.\n", dep.Reference)
			}
		}  else {
			Warn("No handler for %d. Falling back to 'go get %s'.\n", dep.VcsType, dep.Name)
		}
		return goGet.Get(dep)
	}
}

// VcsUpdate updates to a particular checkout based on the VCS setting.
func VcsUpdate(dep *Dependency) error {

	// If there is no Ref set, and if Repository is empty, we should just
	// default to Go Get.
	//
	// Why do we care if Ref is blank? As of Go 1.3, go get builds a .a
	// file for each library. But if we set a Ref, that will switch the source
	// code, but not necessarily build a .a file. So we want to make sure not
	// to default to 'go get' if we're then going to grab a specific version.
	if dep.Reference == "" && dep.Repository == "" {
		Info("No ref or repo. Falling back to 'go get -u %s'.\n", dep.Name)
		return goGet.Update(dep)
	}

	if dep.VcsType == NoVCS {
		guess, err := GuessVCS(dep)
		if err != nil {
			Warn("Tried to guess VCS type, but failed: %s", err)
		} else {
			dep.VcsType = guess
		}
	}

	switch dep.VcsType {
	case Git:
		Info("Updating %s with Git (From %s)\n", dep.Name, dep.Repository)
		return git.Update(dep)
	case Bzr:
		Info("Updating %s with Bzr (From %s)\n", dep.Name, dep.Repository)
		return bzr.Update(dep)
	case Hg:
		Info("Updating %s with Hg (From %s)\n", dep.Name, dep.Repository)
		return hg.Update(dep)
	case Svn:
		Info("Updating %s with Svn (From %s)\n", dep.Name, dep.Repository)
		return svn.Update(dep)
	default:
		if dep.VcsType == NoVCS {
			Info("No VCS set. Updating with 'go get -u %s'\n", dep.Name)
			if len(dep.Reference) > 0 {
				Warn("Ref is set to %s, but no VCS is set. This can cause inconsistencies.\n", dep.Reference)
			}
		} else {
			Warn("No handler for this repo type. Falling back to 'go get -u %s'.\n", dep.Name)
		}
		return goGet.Update(dep)
	}
}

func VcsVersion(dep *Dependency) error {
	if dep.VcsType == NoVCS {
		dep.VcsType, _ = GuessVCS(dep)
	}

	switch dep.VcsType {
	case Git:
		return git.Version(dep)
	case Bzr:
		return bzr.Version(dep)
	case Hg:
		return hg.Version(dep)
	case Svn:
		return svn.Version(dep)
	default:
		if len(dep.Reference) > 0 {
			Warn("Cannot update %s to specific version with VCS %d.\n", dep.Name, dep.VcsType)
			return goGet.Version(dep)
		}
		return nil
	}

}

func VcsLastCommit(dep *Dependency) (string, error) {
	if dep.VcsType == NoVCS {
		dep.VcsType, _ = GuessVCS(dep)
	}

	switch dep.VcsType {
	case Git:
		return git.LastCommit(dep)
	case Bzr:
		return bzr.LastCommit(dep)
	case Hg:
		return hg.LastCommit(dep)
	case Svn:
		return svn.LastCommit(dep)
	default:
		if len(dep.Reference) > 0 {
			Warn("Cannot update %s to specific version with VCS %d.\n", dep.Name, dep.VcsType)
			return goGet.LastCommit(dep)
		}
		return "", nil
	}

}

func VcsSetReference(dep *Dependency) error {
	Warn("Cannot set reference. not implemented.\n")
	return nil
}

func GuessVCS(dep *Dependency) (uint, error) {
	dest := fmt.Sprintf("%s/src/%s", os.Getenv("GOPATH"), dep.Name)
	//Debug("Looking in %s for hints about VCS type.\n", dest)

	if _, err := os.Stat(dest + "/.git"); err == nil {
		Info("Looks like %s is a Git repo.\n", dest)
		return Git, nil
	} else if _, err := os.Stat(dest + "/.bzr"); err == nil {
		Info("Looks like %s is a Bzr repo.\n", dest)
		return Bzr, nil
	} else if _, err := os.Stat(dest + "/.hg"); err == nil {
		Info("Looks like %s is a Mercurial repo.\n", dest)
		return Hg, nil
	} else if _, err := os.Stat(dest + "/.svn"); err == nil {
		Info("Looks like %s is a Subversion repo.\n", dest)
		return Svn, nil
	} else {
		return NoVCS, nil
	}
}
<commit_msg>Fixed info messages on get_imports.go.<commit_after>package cmd

import (
	"github.com/Masterminds/cookoo"
	"fmt"
	"os"
)

const (
	NoVCS uint = iota
	Git
	Bzr
	Hg
	Svn
)

func GetImports(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {

	cfg := p.Get("conf", nil).(*Config)

	if len(cfg.Imports) == 0 {
		Info("No dependencies found. Nothing downloaded.\n")
		return false, nil
	}

	for _, dep := range cfg.Imports {
		if err := VcsGet(dep); err != nil {
			Warn("Skipped getting %s: %s\n", dep.Name, err)
		}
	}

	return true, nil
}

func UpdateImports(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	cfg := p.Get("conf", nil).(*Config)

	if len(cfg.Imports) == 0 {
		Info("No dependencies found. Nothing updated.\n")
		return false, nil
	}

	for _, dep := range cfg.Imports {
		if err := VcsUpdate(dep); err != nil {
			Warn("Update failed for %s: %s\n", dep.Name, err)
		}
	}

	return true, nil
}

func CowardMode(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	gopath := os.Getenv("GOPATH")
	if len(gopath) == 0 {
		return false, fmt.Errorf("No GOPATH is set.\n")
	}

	if _, err := os.Stat(gopath); err != nil {
		return false, fmt.Errorf("Did you forget to 'glide install'? GOPATH=%s seems not to exist: %s\n", gopath, err)
	}

	ggpath := os.Getenv("GLIDE_GOPATH")
	if len(ggpath) > 0 && ggpath != gopath {
		Warn("Your GOPATH is set to %s, and we expected %s\n", gopath, ggpath)
	}
	return true, nil
}

func SetReference(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	cfg := p.Get("conf", nil).(*Config)

	if len(cfg.Imports) == 0 {
		Info("No dependencies found.\n")
		return false, nil
	}

	for _, dep := range cfg.Imports {
		if err := VcsVersion(dep); err != nil {
			Warn("Failed to set version on %s to %s: %s\n", dep.Name, dep.Reference, err)
		}
	}

	return true, nil
}

type VCS interface {
	Get(*Dependency) error
	Update(*Dependency) error
	Version(*Dependency) error
	LastCommit(*Dependency) (string, error)
}

var (
	goGet VCS = new(GoGetVCS)
	git VCS = new(GitVCS)
	svn VCS = new(SvnVCS)
	bzr VCS = new(BzrVCS)
	hg VCS = new(HgVCS)
)

// VcsGet figures out how to fetch a dependency, and then gets it.
//
// Usually it delegates to lower-level *Get functions.
//
// See https://code.google.com/p/go/source/browse/src/cmd/go/vcs.go
func VcsGet(dep *Dependency) error {

	// See note in VcsUpdate.
	if dep.Repository == "" && dep.Reference == "" {
		Info("Installing %s with 'go get'\n", dep.Name)
		return goGet.Get(dep)
	}

	switch dep.VcsType {
	case Git:
		if dep.Repository == "" {
			dep.Repository = "http://" + dep.Name
		}
		Info("Installing %s with Git (From %s)\n", dep.Name, dep.Repository)
		return git.Get(dep)
	case Bzr:
		Info("Installing %s with Bzr (From %s)\n", dep.Name, dep.Repository)
		return bzr.Get(dep)
	case Hg:
		if dep.Repository == "" {
			dep.Repository = "http://" + dep.Name
		}
		Info("Installing %s with Hg (From %s)\n", dep.Name, dep.Repository)
		return hg.Get(dep)
	case Svn:
		Info("Installing %s with Svn (From %s)\n", dep.Name, dep.Repository)
		return svn.Get(dep)
	default:
		if dep.VcsType == NoVCS {
			Info("Defaulting to 'go get %s'\n", dep.Name)
			if len(dep.Reference) > 0 {
				Warn("Ref is set to %s, but no VCS is set. This can cause inconsistencies.\n", dep.Reference)
			}
		}  else {
			Warn("No handler for %d. Falling back to 'go get %s'.\n", dep.VcsType, dep.Name)
		}
		return goGet.Get(dep)
	}
}

// VcsUpdate updates to a particular checkout based on the VCS setting.
func VcsUpdate(dep *Dependency) error {

	// If there is no Ref set, and if Repository is empty, we should just
	// default to Go Get.
	//
	// Why do we care if Ref is blank? As of Go 1.3, go get builds a .a
	// file for each library. But if we set a Ref, that will switch the source
	// code, but not necessarily build a .a file. So we want to make sure not
	// to default to 'go get' if we're then going to grab a specific version.
	if dep.Reference == "" && dep.Repository == "" {
		Info("No ref or repo. Falling back to 'go get -u %s'.\n", dep.Name)
		return goGet.Update(dep)
	}

	if dep.VcsType == NoVCS {
		guess, err := GuessVCS(dep)
		if err != nil {
			Warn("Tried to guess VCS type, but failed: %s", err)
		} else {
			dep.VcsType = guess
		}
	}

	switch dep.VcsType {
	case Git:
		Info("Updating %s with Git (From %s)\n", dep.Name, dep.Repository)
		return git.Update(dep)
	case Bzr:
		Info("Updating %s with Bzr (From %s)\n", dep.Name, dep.Repository)
		return bzr.Update(dep)
	case Hg:
		Info("Updating %s with Hg (From %s)\n", dep.Name, dep.Repository)
		return hg.Update(dep)
	case Svn:
		Info("Updating %s with Svn (From %s)\n", dep.Name, dep.Repository)
		return svn.Update(dep)
	default:
		if dep.VcsType == NoVCS {
			Info("No VCS set. Updating with 'go get -u %s'\n", dep.Name)
			if len(dep.Reference) > 0 {
				Warn("Ref is set to %s, but no VCS is set. This can cause inconsistencies.\n", dep.Reference)
			}
		} else {
			Warn("No handler for this repo type. Falling back to 'go get -u %s'.\n", dep.Name)
		}
		return goGet.Update(dep)
	}
}

func VcsVersion(dep *Dependency) error {
	if dep.VcsType == NoVCS {
		dep.VcsType, _ = GuessVCS(dep)
	}

	switch dep.VcsType {
	case Git:
		return git.Version(dep)
	case Bzr:
		return bzr.Version(dep)
	case Hg:
		return hg.Version(dep)
	case Svn:
		return svn.Version(dep)
	default:
		if len(dep.Reference) > 0 {
			Warn("Cannot update %s to specific version with VCS %d.\n", dep.Name, dep.VcsType)
			return goGet.Version(dep)
		}
		return nil
	}

}

func VcsLastCommit(dep *Dependency) (string, error) {
	if dep.VcsType == NoVCS {
		dep.VcsType, _ = GuessVCS(dep)
	}

	switch dep.VcsType {
	case Git:
		return git.LastCommit(dep)
	case Bzr:
		return bzr.LastCommit(dep)
	case Hg:
		return hg.LastCommit(dep)
	case Svn:
		return svn.LastCommit(dep)
	default:
		if len(dep.Reference) > 0 {
			Warn("Cannot update %s to specific version with VCS %d.\n", dep.Name, dep.VcsType)
			return goGet.LastCommit(dep)
		}
		return "", nil
	}

}

func VcsSetReference(dep *Dependency) error {
	Warn("Cannot set reference. not implemented.\n")
	return nil
}

func GuessVCS(dep *Dependency) (uint, error) {
	dest := fmt.Sprintf("%s/src/%s", os.Getenv("GOPATH"), dep.Name)
	//Debug("Looking in %s for hints about VCS type.\n", dest)

	if _, err := os.Stat(dest + "/.git"); err == nil {
		Info("Looks like %s is a Git repo.\n", dest)
		return Git, nil
	} else if _, err := os.Stat(dest + "/.bzr"); err == nil {
		Info("Looks like %s is a Bzr repo.\n", dest)
		return Bzr, nil
	} else if _, err := os.Stat(dest + "/.hg"); err == nil {
		Info("Looks like %s is a Mercurial repo.\n", dest)
		return Hg, nil
	} else if _, err := os.Stat(dest + "/.svn"); err == nil {
		Info("Looks like %s is a Subversion repo.\n", dest)
		return Svn, nil
	} else {
		return NoVCS, nil
	}
}
<|endoftext|>


<commit_before>/*
This program provides a formatter for ini files.
*/
package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"unicode/utf8"

	ini "github.com/pierrec/go-ini"
)

func main() {
	var outName, comment, sliceSep string
	flag.StringVar(&outName, "w", "", "write result to file instead of stdout")
	flag.StringVar(&comment, "c", string(ini.DefaultComment), "comment character")
	flag.StringVar(&sliceSep, "sep", string(ini.DefaultSliceSeparator), "comment character")
	var sensitive, merge bool
	flag.BoolVar(&sensitive, "s", false, "make section and key names case sensitive")
	flag.BoolVar(&merge, "m", false, "merge sections with same name")
	flag.Usage = usage
	flag.Parse()

	var output io.Writer
	if outName == "" {
		output = os.Stdout
	} else {
		f, err := os.Create(outName)
		if err != nil {
			log.Println(err)
			return
		}
		defer f.Close()
		output = f
	}

	var input io.Reader
	if args := flag.Args(); len(args) == 0 {
		input = os.Stdin
	} else {
		fname := args[0]
		f, err := os.Open(fname)
		if err != nil {
			log.Println(err)
			return
		}
		defer f.Close()
		input = f
	}

	var options []ini.Option
	options = append(options, ini.SliceSeparator(sliceSep))
	if first, n := utf8.DecodeRune([]byte(comment)); n > 0 {
		options = append(options, ini.Comment(first))
	}
	if sensitive {
		options = append(options, ini.CaseSensitive())
	}
	if merge {
		options = append(options, ini.MergeSections())
	}

	conf, _ := ini.New(options...)
	_, err := conf.ReadFrom(input)
	if err != nil {
		log.Println(err)
		return
	}

	_, err = conf.WriteTo(output)
	if err != nil {
		log.Println(err)
		return
	}
}

func usage() {
	fmt.Fprintf(os.Stderr, "usage: %s [flags] [path ...]\n", os.Args[0])
	flag.PrintDefaults()
}
<commit_msg>updated inifmt to work with the package<commit_after>/*
This program provides a formatter for ini files.
*/
package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"

	ini "github.com/pierrec/go-ini"
)

func main() {
	var outName, comment, sliceSep string
	flag.StringVar(&outName, "w", "", "write result to file instead of stdout")
	flag.StringVar(&comment, "c", string(ini.DefaultComment), "comment character")
	flag.StringVar(&sliceSep, "sep", string(ini.DefaultSliceSeparator), "comment character")
	var sensitive, merge bool
	flag.BoolVar(&sensitive, "s", false, "make section and key names case sensitive")
	flag.BoolVar(&merge, "m", false, "merge sections with same name")
	flag.Usage = usage
	flag.Parse()

	var output io.Writer
	if outName == "" {
		output = os.Stdout
	} else {
		f, err := os.Create(outName)
		if err != nil {
			log.Println(err)
			return
		}
		defer f.Close()
		output = f
	}

	var input io.Reader
	if args := flag.Args(); len(args) == 0 {
		input = os.Stdin
	} else {
		fname := args[0]
		f, err := os.Open(fname)
		if err != nil {
			log.Println(err)
			return
		}
		defer f.Close()
		input = f
	}

	var options []ini.Option
	options = append(options, ini.SliceSeparator(sliceSep))
	if comment != "" {
		options = append(options, ini.Comment(comment))
	}
	if sensitive {
		options = append(options, ini.CaseSensitive())
	}
	if merge {
		options = append(options, ini.MergeSections())
	}

	conf, _ := ini.New(options...)
	_, err := conf.ReadFrom(input)
	if err != nil {
		log.Println(err)
		return
	}

	_, err = conf.WriteTo(output)
	if err != nil {
		log.Println(err)
		return
	}
}

func usage() {
	fmt.Fprintf(os.Stderr, "usage: %s [flags] [path ...]\n", os.Args[0])
	flag.PrintDefaults()
}
<|endoftext|>


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

package cmd

import (
	"fmt"
	"io"
	"log"
	"path"
	"strings"

	"github.com/chzyer/readline"
	"github.com/pkg/errors"
	"github.com/sascha-andres/devenv"
	"github.com/sascha-andres/devenv/helper"
	"github.com/sascha-andres/devenv/shell"
	"github.com/spf13/viper"
)

var ev devenv.EnvironmentConfiguration

var completer = readline.NewPrefixCompleter(
	readline.PcItem("repo",
		readline.PcItemDynamic(listRepositories(),
			readline.PcItem("branch"),
			readline.PcItem("commit"),
			readline.PcItem("log"),
			readline.PcItem("pull"),
			readline.PcItem("push"),
			readline.PcItem("status"),
			readline.PcItem("pin"),
			readline.PcItem("unpin"),
		),
	),
	readline.PcItem("addrepo"),
	readline.PcItem("branch"),
	readline.PcItem("commit"),
	readline.PcItem("delrepo"),
	readline.PcItem("log"),
	readline.PcItem("pull"),
	readline.PcItem("push"),
	readline.PcItem("status"),
	readline.PcItem("quit"),
	readline.PcItem("scan"),
)

func filterInput(r rune) (rune, bool) {
	switch r {
	// block CtrlZ feature
	case readline.CharCtrlZ:
		return r, false
	}
	return r, true
}

func setup(projectName string) error {
	if "" == projectName || !devenv.ProjectIsCreated(projectName) {
		return errors.New(fmt.Sprintf("Project '%s' does not yet exist", projectName))
	}
	if ok, err := helper.Exists(path.Join(viper.GetString("configpath"), projectName+".yaml")); ok && err == nil {
		if err := ev.LoadFromFile(path.Join(viper.GetString("configpath"), projectName+".yaml")); err != nil {
			return errors.New(fmt.Sprintf("Error reading env config: '%s'", err.Error()))
		}
	}
	return nil
}

func runInterpreter(args []string) error {
	projectName := strings.Join(args, " ")
	log.Printf("Called to start shell for '%s'\n", projectName)
	setup(projectName)

	interpreter := shell.NewInterpreter(path.Join(viper.GetString("basepath"), projectName), ev)
	l, err := getReadlineConfig(projectName)
	if err != nil {
		return err
	}
	defer func() {
		if err := l.Close(); err != nil {
			log.Fatalf("Error closing readline: " + err.Error())
		}
	}()

	log.SetOutput(l.Stderr())

	for {
		line, doBreak := getLine(l)
		if doBreak {
			break
		}
		line = strings.TrimSpace(line)
		switch line {
		case "quit", "q":
			return nil
		default:
			executeLine(interpreter, line)
			break
		}
	}
	return nil
}

func getLine(l *readline.Instance) (string, bool) {
	line, err := l.Readline()
	if err == readline.ErrInterrupt {
		if len(line) == 0 {
			return "", true
		} else {
			return line, false
		}
	} else if err == io.EOF {
		return "", true
	}
	return line, false
}
func executeLine(interpreter *shell.Interpreter, line string) {
	err := interpreter.Execute(line)
	if err != nil {
		log.Println(err)
	}
}
func getReadlineConfig(projectName string) (*readline.Instance, error) {
	return readline.NewEx(&readline.Config{
		Prompt:          "\033[31m»\033[0m ",
		HistoryFile:     "/tmp/devenv-" + projectName + ".tmp",
		AutoComplete:    completer,
		InterruptPrompt: "^C",
		EOFPrompt:       "exit",

		HistorySearchFold:   true,
		FuncFilterInputRune: filterInput,
	})
}

func listRepositories() func(string) []string {
	return func(line string) []string {
		var repositories []string
		for _, val := range ev.Repositories {
			if !val.Disabled {
				repositories = append(repositories, val.Name)
			}
		}
		return repositories
	}
}
<commit_msg>Added autocompletion<commit_after>// Copyright © 2017 Sascha Andres <sascha.andres@outlook.com>
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
	"fmt"
	"io"
	"log"
	"path"
	"strings"

	"github.com/chzyer/readline"
	"github.com/pkg/errors"
	"github.com/sascha-andres/devenv"
	"github.com/sascha-andres/devenv/helper"
	"github.com/sascha-andres/devenv/shell"
	"github.com/spf13/viper"
)

var ev devenv.EnvironmentConfiguration

var completer = readline.NewPrefixCompleter(
	readline.PcItem("repo",
		readline.PcItemDynamic(listRepositories(),
			readline.PcItem("branch"),
			readline.PcItem("commit"),
			readline.PcItem("log"),
			readline.PcItem("shell"),
			readline.PcItem("pull"),
			readline.PcItem("push"),
			readline.PcItem("status"),
			readline.PcItem("pin"),
			readline.PcItem("unpin"),
		),
	),
	readline.PcItem("addrepo"),
	readline.PcItem("branch"),
	readline.PcItem("commit"),
	readline.PcItem("delrepo"),
	readline.PcItem("log"),
	readline.PcItem("pull"),
	readline.PcItem("push"),
	readline.PcItem("status"),
	readline.PcItem("quit"),
	readline.PcItem("scan"),
	readline.PcItem("shell"),
)

func filterInput(r rune) (rune, bool) {
	switch r {
	// block CtrlZ feature
	case readline.CharCtrlZ:
		return r, false
	}
	return r, true
}

func setup(projectName string) error {
	if "" == projectName || !devenv.ProjectIsCreated(projectName) {
		return errors.New(fmt.Sprintf("Project '%s' does not yet exist", projectName))
	}
	if ok, err := helper.Exists(path.Join(viper.GetString("configpath"), projectName+".yaml")); ok && err == nil {
		if err := ev.LoadFromFile(path.Join(viper.GetString("configpath"), projectName+".yaml")); err != nil {
			return errors.New(fmt.Sprintf("Error reading env config: '%s'", err.Error()))
		}
	}
	return nil
}

func runInterpreter(args []string) error {
	projectName := strings.Join(args, " ")
	log.Printf("Called to start shell for '%s'\n", projectName)
	setup(projectName)

	interpreter := shell.NewInterpreter(path.Join(viper.GetString("basepath"), projectName), ev)
	l, err := getReadlineConfig(projectName)
	if err != nil {
		return err
	}
	defer func() {
		if err := l.Close(); err != nil {
			log.Fatalf("Error closing readline: " + err.Error())
		}
	}()

	log.SetOutput(l.Stderr())

	for {
		line, doBreak := getLine(l)
		if doBreak {
			break
		}
		line = strings.TrimSpace(line)
		switch line {
		case "quit", "q":
			return nil
		default:
			executeLine(interpreter, line)
			break
		}
	}
	return nil
}

func getLine(l *readline.Instance) (string, bool) {
	line, err := l.Readline()
	if err == readline.ErrInterrupt {
		if len(line) == 0 {
			return "", true
		} else {
			return line, false
		}
	} else if err == io.EOF {
		return "", true
	}
	return line, false
}
func executeLine(interpreter *shell.Interpreter, line string) {
	err := interpreter.Execute(line)
	if err != nil {
		log.Println(err)
	}
}
func getReadlineConfig(projectName string) (*readline.Instance, error) {
	return readline.NewEx(&readline.Config{
		Prompt:          "\033[31m»\033[0m ",
		HistoryFile:     "/tmp/devenv-" + projectName + ".tmp",
		AutoComplete:    completer,
		InterruptPrompt: "^C",
		EOFPrompt:       "exit",

		HistorySearchFold:   true,
		FuncFilterInputRune: filterInput,
	})
}

func listRepositories() func(string) []string {
	return func(line string) []string {
		var repositories []string
		for _, val := range ev.Repositories {
			if !val.Disabled {
				repositories = append(repositories, val.Name)
			}
		}
		return repositories
	}
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"strings"

	"github.com/MakeNowJust/heredoc/v2"
	"github.com/rsteube/carapace"
	"github.com/spf13/cobra"
	"github.com/zaquestion/lab/internal/action"
	lab "github.com/zaquestion/lab/internal/gitlab"
)

var issueCloseCmd = &cobra.Command{
	Use:              "close [remote] <id>",
	Aliases:          []string{"delete"},
	Short:            "Close issue by ID",
	Args:             cobra.MinimumNArgs(1),
	PersistentPreRun: LabPersistentPreRun,
	Example: heredoc.Doc(`
		lab issue close 1234
		lab issue close --duplicate 123 1234
		lab issue close --duplicate other-project#123 1234
	`),
	Run: func(cmd *cobra.Command, args []string) {
		rn, id, err := parseArgsRemoteAndID(args)
		if err != nil {
			log.Fatal(err)
		}

		p, err := lab.FindProject(rn)
		if err != nil {
			log.Fatal(err)
		}

		dupId, _ := cmd.Flags().GetString("duplicate")
		if dupId != "" {
			if !strings.Contains(dupId, "#") {
				dupId = "#" + dupId
			}
			err = lab.IssueDuplicate(p.ID, int(id), dupId)
			if err != nil {
				log.Fatal(err)
			}
			fmt.Printf("Issue #%d closed as duplicate of %s\n", id, dupId)
		} else {
			err = lab.IssueClose(p.ID, int(id))
			if err != nil {
				log.Fatal(err)
			}
			fmt.Printf("Issue #%d closed\n", id)
		}
	},
}

func init() {
	issueCloseCmd.Flags().StringP("duplicate", "", "", "mark as duplicate of another issue")
	issueCmd.AddCommand(issueCloseCmd)
	carapace.Gen(issueCloseCmd).PositionalCompletion(
		action.Remotes(),
		action.Issues(issueList),
	)
}
<commit_msg>issue_close: fix variable name<commit_after>package cmd

import (
	"fmt"
	"strings"

	"github.com/MakeNowJust/heredoc/v2"
	"github.com/rsteube/carapace"
	"github.com/spf13/cobra"
	"github.com/zaquestion/lab/internal/action"
	lab "github.com/zaquestion/lab/internal/gitlab"
)

var issueCloseCmd = &cobra.Command{
	Use:              "close [remote] <id>",
	Aliases:          []string{"delete"},
	Short:            "Close issue by ID",
	Args:             cobra.MinimumNArgs(1),
	PersistentPreRun: LabPersistentPreRun,
	Example: heredoc.Doc(`
		lab issue close 1234
		lab issue close --duplicate 123 1234
		lab issue close --duplicate other-project#123 1234
	`),
	Run: func(cmd *cobra.Command, args []string) {
		rn, id, err := parseArgsRemoteAndID(args)
		if err != nil {
			log.Fatal(err)
		}

		p, err := lab.FindProject(rn)
		if err != nil {
			log.Fatal(err)
		}

		dupID, _ := cmd.Flags().GetString("duplicate")
		if dupID != "" {
			if !strings.Contains(dupID, "#") {
				dupID = "#" + dupID
			}
			err = lab.IssueDuplicate(p.ID, int(id), dupID)
			if err != nil {
				log.Fatal(err)
			}
			fmt.Printf("Issue #%d closed as duplicate of %s\n", id, dupID)
		} else {
			err = lab.IssueClose(p.ID, int(id))
			if err != nil {
				log.Fatal(err)
			}
			fmt.Printf("Issue #%d closed\n", id)
		}
	},
}

func init() {
	issueCloseCmd.Flags().StringP("duplicate", "", "", "mark as duplicate of another issue")
	issueCmd.AddCommand(issueCloseCmd)
	carapace.Gen(issueCloseCmd).PositionalCompletion(
		action.Remotes(),
		action.Issues(issueList),
	)
}
<|endoftext|>


<commit_before>package main

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

	"github.com/howeyc/ledger"
)

const (
	transactionDateFormat = "2006/01/02"
	displayPrecision      = 2
)

func main() {
	var startDate, endDate time.Time
	startDate = time.Date(1970, 1, 1, 0, 0, 0, 0, time.Local)
	endDate = time.Now().Add(time.Hour * 24)
	var startString, endString string
	var columnWidth, transactionDepth int
	var showEmptyAccounts bool
	var columnWide bool
	var period string

	var ledgerFileName string

	flag.StringVar(&ledgerFileName, "f", "", "Ledger file name (*Required).")
	flag.StringVar(&startString, "b", startDate.Format(transactionDateFormat), "Begin date of transaction processing.")
	flag.StringVar(&endString, "e", endDate.Format(transactionDateFormat), "End date of transaction processing.")
	flag.StringVar(&period, "period", "", "Split output into periods (Monthly,Quarterly,SemiYearly,Yearly).")
	flag.BoolVar(&showEmptyAccounts, "empty", false, "Show empty (zero balance) accounts.")
	flag.IntVar(&transactionDepth, "depth", -1, "Depth of transaction output (balance).")
	flag.IntVar(&columnWidth, "columns", 80, "Set a column width for output.")
	flag.BoolVar(&columnWide, "wide", false, "Wide output (same as --columns=132).")
	flag.Parse()

	if columnWidth == 80 && columnWide {
		columnWidth = 132
	}

	if len(ledgerFileName) == 0 {
		flag.Usage()
		return
	}

	parsedStartDate, tstartErr := time.Parse(transactionDateFormat, startString)
	parsedEndDate, tendErr := time.Parse(transactionDateFormat, endString)

	if tstartErr != nil || tendErr != nil {
		fmt.Println("Unable to parse start or end date string argument.")
		fmt.Println("Expected format: YYYY/MM/dd")
		return
	}

	args := flag.Args()
	if len(args) == 0 {
		fmt.Println("Specify a command.")
		fmt.Println("Valid commands are:")
		fmt.Println(" bal/balance: summarize account balances")
		fmt.Println(" print: print ledger")
		fmt.Println(" reg/register: print filtered register")
		fmt.Println(" stats: ledger summary")
		return
	}

	ledgerFileReader, err := os.Open(ledgerFileName)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer ledgerFileReader.Close()

	generalLedger, parseError := ledger.ParseLedger(ledgerFileReader)
	if parseError != nil {
		fmt.Printf("%s:%s\n", ledgerFileName, parseError.Error())
		return
	}

	timeStartIndex, timeEndIndex := 0, 0
	for idx := 0; idx < len(generalLedger); idx++ {
		if generalLedger[idx].Date.After(parsedStartDate) {
			timeStartIndex = idx
			break
		}
	}
	for idx := len(generalLedger) - 1; idx >= 0; idx-- {
		if generalLedger[idx].Date.Before(parsedEndDate) {
			timeEndIndex = idx
			break
		}
	}
	generalLedger = generalLedger[timeStartIndex : timeEndIndex+1]

	containsFilterArray := args[1:]
	switch strings.ToLower(args[0]) {
	case "balance", "bal":
		if period == "" {
			PrintBalances(ledger.GetBalances(generalLedger, containsFilterArray), showEmptyAccounts, transactionDepth, columnWidth)
		} else {
			lperiod := ledger.Period(period)
			rbalances := ledger.BalancesByPeriod(generalLedger, lperiod, ledger.RangePartition)
			for rIdx, rb := range rbalances {
				if rIdx > 0 {
					fmt.Println("")
					fmt.Println(strings.Repeat("=", columnWidth))
				}
				fmt.Println(rb.Start.Format(transactionDateFormat), "-", rb.End.Format(transactionDateFormat))
				fmt.Println(strings.Repeat("=", columnWidth))
				PrintBalances(rb.Balances, showEmptyAccounts, transactionDepth, columnWidth)
			}
		}
	case "print":
		PrintLedger(generalLedger, columnWidth)
	case "register", "reg":
		if period == "" {
			PrintRegister(generalLedger, containsFilterArray, columnWidth)
		} else {
			lperiod := ledger.Period(period)
			rtrans := ledger.TransactionsByPeriod(generalLedger, lperiod)
			for rIdx, rt := range rtrans {
				if rIdx > 0 {
					fmt.Println(strings.Repeat("=", columnWidth))
				}
				fmt.Println(rt.Start.Format(transactionDateFormat), "-", rt.End.Format(transactionDateFormat))
				fmt.Println(strings.Repeat("=", columnWidth))
				PrintRegister(rt.Transactions, containsFilterArray, columnWidth)
			}
		}
	case "stats":
		PrintStats(generalLedger)
	}
}
<commit_msg>command line can now filter output by payee<commit_after>package main

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

	"github.com/howeyc/ledger"
)

const (
	transactionDateFormat = "2006/01/02"
	displayPrecision      = 2
)

func main() {
	var startDate, endDate time.Time
	startDate = time.Date(1970, 1, 1, 0, 0, 0, 0, time.Local)
	endDate = time.Now().Add(time.Hour * 24)
	var startString, endString string
	var columnWidth, transactionDepth int
	var showEmptyAccounts bool
	var columnWide bool
	var period string
	var payeeFilter string

	var ledgerFileName string

	flag.StringVar(&ledgerFileName, "f", "", "Ledger file name (*Required).")
	flag.StringVar(&startString, "b", startDate.Format(transactionDateFormat), "Begin date of transaction processing.")
	flag.StringVar(&endString, "e", endDate.Format(transactionDateFormat), "End date of transaction processing.")
	flag.StringVar(&period, "period", "", "Split output into periods (Monthly,Quarterly,SemiYearly,Yearly).")
	flag.StringVar(&payeeFilter, "payee", "", "Filter output to payees that contain this string.")
	flag.BoolVar(&showEmptyAccounts, "empty", false, "Show empty (zero balance) accounts.")
	flag.IntVar(&transactionDepth, "depth", -1, "Depth of transaction output (balance).")
	flag.IntVar(&columnWidth, "columns", 80, "Set a column width for output.")
	flag.BoolVar(&columnWide, "wide", false, "Wide output (same as --columns=132).")
	flag.Parse()

	if columnWidth == 80 && columnWide {
		columnWidth = 132
	}

	if len(ledgerFileName) == 0 {
		flag.Usage()
		return
	}

	parsedStartDate, tstartErr := time.Parse(transactionDateFormat, startString)
	parsedEndDate, tendErr := time.Parse(transactionDateFormat, endString)

	if tstartErr != nil || tendErr != nil {
		fmt.Println("Unable to parse start or end date string argument.")
		fmt.Println("Expected format: YYYY/MM/dd")
		return
	}

	args := flag.Args()
	if len(args) == 0 {
		fmt.Println("Specify a command.")
		fmt.Println("Valid commands are:")
		fmt.Println(" bal/balance: summarize account balances")
		fmt.Println(" print: print ledger")
		fmt.Println(" reg/register: print filtered register")
		fmt.Println(" stats: ledger summary")
		return
	}

	ledgerFileReader, err := os.Open(ledgerFileName)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer ledgerFileReader.Close()

	generalLedger, parseError := ledger.ParseLedger(ledgerFileReader)
	if parseError != nil {
		fmt.Printf("%s:%s\n", ledgerFileName, parseError.Error())
		return
	}

	timeStartIndex, timeEndIndex := 0, 0
	for idx := 0; idx < len(generalLedger); idx++ {
		if generalLedger[idx].Date.After(parsedStartDate) {
			timeStartIndex = idx
			break
		}
	}
	for idx := len(generalLedger) - 1; idx >= 0; idx-- {
		if generalLedger[idx].Date.Before(parsedEndDate) {
			timeEndIndex = idx
			break
		}
	}
	generalLedger = generalLedger[timeStartIndex : timeEndIndex+1]

	origLedger := generalLedger
	generalLedger = make([]*ledger.Transaction, 0)
	for _, trans := range origLedger {
		if strings.Contains(trans.Payee, payeeFilter) {
			generalLedger = append(generalLedger, trans)
		}
	}

	containsFilterArray := args[1:]
	switch strings.ToLower(args[0]) {
	case "balance", "bal":
		if period == "" {
			PrintBalances(ledger.GetBalances(generalLedger, containsFilterArray), showEmptyAccounts, transactionDepth, columnWidth)
		} else {
			lperiod := ledger.Period(period)
			rbalances := ledger.BalancesByPeriod(generalLedger, lperiod, ledger.RangePartition)
			for rIdx, rb := range rbalances {
				if rIdx > 0 {
					fmt.Println("")
					fmt.Println(strings.Repeat("=", columnWidth))
				}
				fmt.Println(rb.Start.Format(transactionDateFormat), "-", rb.End.Format(transactionDateFormat))
				fmt.Println(strings.Repeat("=", columnWidth))
				PrintBalances(rb.Balances, showEmptyAccounts, transactionDepth, columnWidth)
			}
		}
	case "print":
		PrintLedger(generalLedger, columnWidth)
	case "register", "reg":
		if period == "" {
			PrintRegister(generalLedger, containsFilterArray, columnWidth)
		} else {
			lperiod := ledger.Period(period)
			rtrans := ledger.TransactionsByPeriod(generalLedger, lperiod)
			for rIdx, rt := range rtrans {
				if rIdx > 0 {
					fmt.Println(strings.Repeat("=", columnWidth))
				}
				fmt.Println(rt.Start.Format(transactionDateFormat), "-", rt.End.Format(transactionDateFormat))
				fmt.Println(strings.Repeat("=", columnWidth))
				PrintRegister(rt.Transactions, containsFilterArray, columnWidth)
			}
		}
	case "stats":
		PrintStats(generalLedger)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"context"

	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/log/zap"

	"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators"
	"github.com/operator-framework/operator-lifecycle-manager/pkg/feature"
)

func Manager(ctx context.Context, debug bool) (ctrl.Manager, error) {
	ctrl.SetLogger(zap.New(zap.UseDevMode(debug)))
	setupLog := ctrl.Log.WithName("setup").V(1)

	// Setup a Manager
	setupLog.Info("configuring manager")
	mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{MetricsBindAddress: "0"}) // TODO(njhale): Enable metrics on non-conflicting port (not 8080)
	if err != nil {
		return nil, err
	}

	operatorConditionReconciler, err := operators.NewOperatorConditionReconciler(
		mgr.GetClient(),
		ctrl.Log.WithName("controllers").WithName("operatorcondition"),
		mgr.GetScheme(),
	)
	if err != nil {
		return nil, err
	}

	if err = operatorConditionReconciler.SetupWithManager(mgr); err != nil {
		return nil, err
	}

	operatorConditionGeneratorReconciler, err := operators.NewOperatorConditionGeneratorReconciler(
		mgr.GetClient(),
		ctrl.Log.WithName("controllers").WithName("operatorcondition-generator"),
		mgr.GetScheme(),
	)
	if err != nil {
		return nil, err
	}

	if err = operatorConditionGeneratorReconciler.SetupWithManager(mgr); err != nil {
		return nil, err
	}

	if feature.Gate.Enabled(feature.OperatorLifecycleManagerV1) {
		// Setup a new controller to reconcile Operators
		operatorReconciler, err := operators.NewOperatorReconciler(
			mgr.GetClient(),
			ctrl.Log.WithName("controllers").WithName("operator"),
			mgr.GetScheme(),
		)
		if err != nil {
			return nil, err
		}

		if err = operatorReconciler.SetupWithManager(mgr); err != nil {
			return nil, err
		}

		adoptionReconciler, err := operators.NewAdoptionReconciler(
			mgr.GetClient(),
			ctrl.Log.WithName("controllers").WithName("adoption"),
			mgr.GetScheme(),
		)
		if err != nil {
			return nil, err
		}

		if err = adoptionReconciler.SetupWithManager(mgr); err != nil {
			return nil, err
		}

	}
	setupLog.Info("manager configured")

	return mgr, nil
}
<commit_msg>don't watch unlabelled secrets in the operator controller<commit_after>package main

import (
	"context"
	"k8s.io/apimachinery/pkg/labels"

	corev1 "k8s.io/api/core/v1"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/cache"
	"sigs.k8s.io/controller-runtime/pkg/log/zap"

	"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install"
	"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators"
	"github.com/operator-framework/operator-lifecycle-manager/pkg/feature"
)

func Manager(ctx context.Context, debug bool) (ctrl.Manager, error) {
	ctrl.SetLogger(zap.New(zap.UseDevMode(debug)))
	setupLog := ctrl.Log.WithName("setup").V(1)

	// Setup a Manager
	setupLog.Info("configuring manager")
	mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
		MetricsBindAddress: "0", // TODO(njhale): Enable metrics on non-conflicting port (not 8080)
		NewCache: cache.BuilderWithOptions(cache.Options{
			SelectorsByObject: cache.SelectorsByObject{
				&corev1.Secret{}: {
					Label: labels.SelectorFromValidatedSet(map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue}),
				},
			},
		}),
	})
	if err != nil {
		return nil, err
	}

	operatorConditionReconciler, err := operators.NewOperatorConditionReconciler(
		mgr.GetClient(),
		ctrl.Log.WithName("controllers").WithName("operatorcondition"),
		mgr.GetScheme(),
	)
	if err != nil {
		return nil, err
	}

	if err = operatorConditionReconciler.SetupWithManager(mgr); err != nil {
		return nil, err
	}

	operatorConditionGeneratorReconciler, err := operators.NewOperatorConditionGeneratorReconciler(
		mgr.GetClient(),
		ctrl.Log.WithName("controllers").WithName("operatorcondition-generator"),
		mgr.GetScheme(),
	)
	if err != nil {
		return nil, err
	}

	if err = operatorConditionGeneratorReconciler.SetupWithManager(mgr); err != nil {
		return nil, err
	}

	if feature.Gate.Enabled(feature.OperatorLifecycleManagerV1) {
		// Setup a new controller to reconcile Operators
		operatorReconciler, err := operators.NewOperatorReconciler(
			mgr.GetClient(),
			ctrl.Log.WithName("controllers").WithName("operator"),
			mgr.GetScheme(),
		)
		if err != nil {
			return nil, err
		}

		if err = operatorReconciler.SetupWithManager(mgr); err != nil {
			return nil, err
		}

		adoptionReconciler, err := operators.NewAdoptionReconciler(
			mgr.GetClient(),
			ctrl.Log.WithName("controllers").WithName("adoption"),
			mgr.GetScheme(),
		)
		if err != nil {
			return nil, err
		}

		if err = adoptionReconciler.SetupWithManager(mgr); err != nil {
			return nil, err
		}

	}
	setupLog.Info("manager configured")

	return mgr, nil
}
<|endoftext|>


<commit_before>package httpclient

import (
	"bytes"
	"context"
	"crypto/tls"
	"encoding/json"
	"io"
	"net"
	"net/http"
	"time"

	"github.com/pkg/errors"
	"github.com/quan-xie/tuba/util/retry"
	"github.com/quan-xie/tuba/util/xtime"
)

const (
	_minRead              = 16 * 1024 // 16kb
	defaultRetryCount int = 0
)

type Config struct {
	Dial       xtime.Duration
	Timeout    xtime.Duration
	KeepAlive  xtime.Duration
	retryCount int
}

type HttpClient struct {
	conf       *Config
	client     *http.Client
	dialer     *net.Dialer
	transport  *http.Transport
	retryCount int
	retrier    retry.Retriable
}

// NewHTTPClient returns a new instance of httpClient
func NewHTTPClient(c *Config) *HttpClient {
	dialer := &net.Dialer{
		Timeout:   time.Duration(c.Dial),
		KeepAlive: time.Duration(c.KeepAlive),
	}
	transport := &http.Transport{
		DialContext:     dialer.DialContext,
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	return &HttpClient{
		conf: c,
		client: &http.Client{
			Transport: transport,
		},
		retryCount: defaultRetryCount,
		retrier:    retry.NewNoRetrier(),
	}
}

// SetRetryCount sets the retry count for the httpClient
func (c *HttpClient) SetRetryCount(count int) {
	c.retryCount = count
}

// SetRetryCount sets the retry count for the httpClient
func (c *HttpClient) SetRetrier(retrier retry.Retriable) {
	c.retrier = retrier
}

// Get makes a HTTP GET request to provided URL with context passed in
func (c *HttpClient) Get(ctx context.Context, url string, headers http.Header, res interface{}) (err error) {
	request, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return errors.Wrap(err, "GET - request creation failed")
	}

	request.Header = headers

	return c.Do(ctx, request, res)
}

// Post makes a HTTP POST request to provided URL with context passed in
func (c *HttpClient) Post(ctx context.Context, url string, body io.Reader, headers http.Header, res interface{}) (err error) {
	request, err := http.NewRequest(http.MethodPost, url, body)
	if err != nil {
		return errors.Wrap(err, "POST - request creation failed")
	}

	request.Header = headers

	return c.Do(ctx, request, res)
}

// Put makes a HTTP PUT request to provided URL with context passed in
func (c *HttpClient) Put(ctx context.Context, url string, body io.Reader, headers http.Header, res interface{}) (err error) {
	request, err := http.NewRequest(http.MethodPut, url, body)
	if err != nil {
		return errors.Wrap(err, "PUT - request creation failed")
	}

	request.Header = headers

	return c.Do(ctx, request, res)
}

// Patch makes a HTTP PATCH request to provided URL with context passed in
func (c *HttpClient) Patch(ctx context.Context, url string, body io.Reader, headers http.Header, res interface{}) (err error) {
	request, err := http.NewRequest(http.MethodPatch, url, body)
	if err != nil {
		return errors.Wrap(err, "PATCH - request creation failed")
	}

	request.Header = headers

	return c.Do(ctx, request, res)
}

// Delete makes a HTTP DELETE request to provided URL with context passed in
func (c *HttpClient) Delete(ctx context.Context, url string, headers http.Header, res interface{}) (err error) {
	request, err := http.NewRequest(http.MethodDelete, url, nil)
	if err != nil {
		return errors.Wrap(err, "DELETE - request creation failed")
	}

	request.Header = headers

	return c.Do(ctx, request, res)
}

// Do makes an HTTP request with the native `http.Do` interface and context passed in
func (c *HttpClient) Do(ctx context.Context, req *http.Request, res interface{}) (err error) {
	var (
		response *http.Response
		bs       []byte
		cancel   func()
	)
	for i := 0; i <= c.retryCount; i++ {
		contextCancelled := false
		var err error
		ctx, cancel = context.WithTimeout(ctx, time.Duration(c.conf.Timeout))
		defer cancel()
		response, err = c.client.Do(req.WithContext(ctx))
		if err != nil {
			select {
			case <-ctx.Done():
				err = ctx.Err()
				contextCancelled = true
			}
			if contextCancelled {
				break
			}
			backoffTime := c.retrier.NextInterval(i)
			time.Sleep(backoffTime)
			continue
		}
		defer response.Body.Close()
		if response.StatusCode >= http.StatusInternalServerError {

			backoffTime := c.retrier.NextInterval(i)
			time.Sleep(backoffTime)
			continue
		}
		bs, err = readAll(response.Body, _minRead)
		if err != nil {
			err = errors.Wrap(err, "readAll - readAll failed")
			return err
		}
		if res != nil {
			if err = json.Unmarshal(bs, res); err != nil {
				err = errors.Wrap(err, "Unmarshal failed")
				return err
			}
		}
		// Clear errors if any iteration succeeds
		break
	}
	return
}

func readAll(r io.Reader, capacity int64) (b []byte, err error) {
	buf := bytes.NewBuffer(make([]byte, 0, capacity))
	// If the buffer overflows, we will get bytes.ErrTooLarge.
	// Return that as an error. Any other panic remains.
	defer func() {
		e := recover()
		if e == nil {
			return
		}
		if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge {
			err = panicErr
		} else {
			panic(e)
		}
	}()
	_, err = buf.ReadFrom(r)
	return buf.Bytes(), err
}
<commit_msg>format code<commit_after>package httpclient

import (
	"bytes"
	"context"
	"crypto/tls"
	"encoding/json"
	"io"
	"net"
	"net/http"
	"time"

	"github.com/pkg/errors"
	"github.com/quan-xie/tuba/util/retry"
	"github.com/quan-xie/tuba/util/xtime"
)

const (
	minRead               = 16 * 1024 // 16kb
	defaultRetryCount int = 0
)

type Config struct {
	Dial       xtime.Duration
	Timeout    xtime.Duration
	KeepAlive  xtime.Duration
	retryCount int
}

type HttpClient struct {
	conf       *Config
	client     *http.Client
	dialer     *net.Dialer
	transport  *http.Transport
	retryCount int
	retrier    retry.Retriable
}

// NewHTTPClient returns a new instance of httpClient
func NewHTTPClient(c *Config) *HttpClient {
	dialer := &net.Dialer{
		Timeout:   time.Duration(c.Dial),
		KeepAlive: time.Duration(c.KeepAlive),
	}
	transport := &http.Transport{
		DialContext:     dialer.DialContext,
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	return &HttpClient{
		conf: c,
		client: &http.Client{
			Transport: transport,
		},
		retryCount: defaultRetryCount,
		retrier:    retry.NewNoRetrier(),
	}
}

// SetRetryCount sets the retry count for the httpClient
func (c *HttpClient) SetRetryCount(count int) {
	c.retryCount = count
}

// SetRetryCount sets the retry count for the httpClient
func (c *HttpClient) SetRetrier(retrier retry.Retriable) {
	c.retrier = retrier
}

// Get makes a HTTP GET request to provided URL with context passed in
func (c *HttpClient) Get(ctx context.Context, url string, headers http.Header, res interface{}) (err error) {
	request, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return errors.Wrap(err, "GET - request creation failed")
	}

	request.Header = headers

	return c.Do(ctx, request, res)
}

// Post makes a HTTP POST request to provided URL with context passed in
func (c *HttpClient) Post(ctx context.Context, url string, body io.Reader, headers http.Header, res interface{}) (err error) {
	request, err := http.NewRequest(http.MethodPost, url, body)
	if err != nil {
		return errors.Wrap(err, "POST - request creation failed")
	}

	request.Header = headers

	return c.Do(ctx, request, res)
}

// Put makes a HTTP PUT request to provided URL with context passed in
func (c *HttpClient) Put(ctx context.Context, url string, body io.Reader, headers http.Header, res interface{}) (err error) {
	request, err := http.NewRequest(http.MethodPut, url, body)
	if err != nil {
		return errors.Wrap(err, "PUT - request creation failed")
	}

	request.Header = headers

	return c.Do(ctx, request, res)
}

// Patch makes a HTTP PATCH request to provided URL with context passed in
func (c *HttpClient) Patch(ctx context.Context, url string, body io.Reader, headers http.Header, res interface{}) (err error) {
	request, err := http.NewRequest(http.MethodPatch, url, body)
	if err != nil {
		return errors.Wrap(err, "PATCH - request creation failed")
	}

	request.Header = headers

	return c.Do(ctx, request, res)
}

// Delete makes a HTTP DELETE request to provided URL with context passed in
func (c *HttpClient) Delete(ctx context.Context, url string, headers http.Header, res interface{}) (err error) {
	request, err := http.NewRequest(http.MethodDelete, url, nil)
	if err != nil {
		return errors.Wrap(err, "DELETE - request creation failed")
	}

	request.Header = headers

	return c.Do(ctx, request, res)
}

// Do makes an HTTP request with the native `http.Do` interface and context passed in
func (c *HttpClient) Do(ctx context.Context, req *http.Request, res interface{}) (err error) {
	var (
		response *http.Response
		bs       []byte
		cancel   func()
	)
	for i := 0; i <= c.retryCount; i++ {
		contextCancelled := false
		var err error
		ctx, cancel = context.WithTimeout(ctx, time.Duration(c.conf.Timeout))
		defer cancel()
		response, err = c.client.Do(req.WithContext(ctx))
		if err != nil {
			select {
			case <-ctx.Done():
				err = ctx.Err()
				contextCancelled = true
			}
			if contextCancelled {
				break
			}
			backoffTime := c.retrier.NextInterval(i)
			time.Sleep(backoffTime)
			continue
		}
		defer response.Body.Close()
		if response.StatusCode >= http.StatusInternalServerError {

			backoffTime := c.retrier.NextInterval(i)
			time.Sleep(backoffTime)
			continue
		}
		bs, err = readAll(response.Body, minRead)
		if err != nil {
			err = errors.Wrap(err, "readAll - readAll failed")
			return err
		}
		if res != nil {
			if err = json.Unmarshal(bs, res); err != nil {
				err = errors.Wrap(err, "Unmarshal failed")
				return err
			}
		}
		// Clear errors if any iteration succeeds
		break
	}
	return
}

func readAll(r io.Reader, capacity int64) (b []byte, err error) {
	buf := bytes.NewBuffer(make([]byte, 0, capacity))
	// If the buffer overflows, we will get bytes.ErrTooLarge.
	// Return that as an error. Any other panic remains.
	defer func() {
		e := recover()
		if e == nil {
			return
		}
		if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge {
			err = panicErr
		} else {
			panic(e)
		}
	}()
	_, err = buf.ReadFrom(r)
	return buf.Bytes(), err
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"syscall"

	"github.com/Microsoft/hcsshim/internal/appargs"
	"github.com/opencontainers/runtime-spec/specs-go"
	"github.com/urfave/cli"
)

var execCommand = cli.Command{
	Name:  "exec",
	Usage: "execute new process inside the container",
	ArgsUsage: `<container-id> <command> [command options]  || -p process.json <container-id>

Where "<container-id>" is the name for the instance of the container and
"<command>" is the command to be executed in the container.
"<command>" can't be empty unless a "-p" flag provided.

EXAMPLE:
For example, if the container is configured to run the linux ps command the
following will output a list of processes running in the container:

    	# runhcs exec <container-id> ps`,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "cwd",
			Usage: "current working directory in the container",
		},
		cli.StringSliceFlag{
			Name:  "env, e",
			Usage: "set environment variables",
		},
		cli.BoolFlag{
			Name:  "tty, t",
			Usage: "allocate a pseudo-TTY",
		},
		cli.StringFlag{
			Name: "user, u",
		},
		cli.StringFlag{
			Name:  "process, p",
			Usage: "path to the process.json",
		},
		cli.BoolFlag{
			Name:  "detach,d",
			Usage: "detach from the container's process",
		},
		cli.StringFlag{
			Name:  "pid-file",
			Value: "",
			Usage: "specify the file to write the process id to",
		},
		cli.StringFlag{
			Name:  "shim-log",
			Value: "",
			Usage: `path to the log file or named pipe (e.g. \\.\pipe\ProtectedPrefix\Administrators\runhcs-<container-id>-<exec-id>-log) for the launched shim process`,
		},
	},
	Before: appargs.Validate(argID, appargs.Rest(appargs.String)),
	Action: func(context *cli.Context) error {
		id := context.Args().First()
		pidFile, err := absPathOrEmpty(context.String("pid-file"))
		if err != nil {
			return err
		}
		shimLog, err := absPathOrEmpty(context.String("shim-log"))
		if err != nil {
			return err
		}
		c, err := getContainer(id, false)
		if err != nil {
			return err
		}
		status, err := c.Status()
		if err != nil {
			return err
		}
		if status != containerRunning {
			return errContainerStopped
		}
		spec, err := getProcessSpec(context, c)
		if err != nil {
			return err
		}
		p, err := startProcessShim(id, pidFile, shimLog, spec)
		if err != nil {
			return err
		}
		if !context.Bool("detach") {
			state, err := p.Wait()
			if err != nil {
				return err
			}
			os.Exit(int(state.Sys().(syscall.WaitStatus).ExitCode))
		}
		return nil
	},
	SkipArgReorder: true,
}

func getProcessSpec(context *cli.Context, c *container) (*specs.Process, error) {
	if path := context.String("process"); path != "" {
		f, err := os.Open(path)
		if err != nil {
			return nil, err
		}
		defer f.Close()
		var p specs.Process
		if err := json.NewDecoder(f).Decode(&p); err != nil {
			return nil, err
		}
		return &p, validateProcessSpec(&p)
	}

	// process via cli flags
	p := c.Spec.Process

	if len(context.Args()) == 1 {
		return nil, fmt.Errorf("process args cannot be empty")
	}
	p.Args = context.Args()[1:]
	// override the cwd, if passed
	if context.String("cwd") != "" {
		p.Cwd = context.String("cwd")
	}
	// append the passed env variables
	p.Env = append(p.Env, context.StringSlice("env")...)

	// set the tty
	if context.IsSet("tty") {
		p.Terminal = context.Bool("tty")
	}
	// override the user, if passed
	if context.String("user") != "" {
		p.User.Username = context.String("user")
	}
	return p, nil
}

func validateProcessSpec(spec *specs.Process) error {
	if spec.Cwd == "" {
		return fmt.Errorf("Cwd property must not be empty")
	}
	// IsAbs doesnt recognize Unix paths on Windows builds so handle that case
	// here.
	if !filepath.IsAbs(spec.Cwd) && !strings.HasPrefix(spec.Cwd, "/") {
		return fmt.Errorf("Cwd must be an absolute path")
	}
	if len(spec.Args) == 0 {
		return fmt.Errorf("args must not be empty")
	}
	return nil
}
<commit_msg>Fix issue failing to close handle in some cases<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"syscall"

	"github.com/Microsoft/hcsshim/internal/appargs"
	"github.com/opencontainers/runtime-spec/specs-go"
	"github.com/urfave/cli"
)

var execCommand = cli.Command{
	Name:  "exec",
	Usage: "execute new process inside the container",
	ArgsUsage: `<container-id> <command> [command options]  || -p process.json <container-id>

Where "<container-id>" is the name for the instance of the container and
"<command>" is the command to be executed in the container.
"<command>" can't be empty unless a "-p" flag provided.

EXAMPLE:
For example, if the container is configured to run the linux ps command the
following will output a list of processes running in the container:

    	# runhcs exec <container-id> ps`,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "cwd",
			Usage: "current working directory in the container",
		},
		cli.StringSliceFlag{
			Name:  "env, e",
			Usage: "set environment variables",
		},
		cli.BoolFlag{
			Name:  "tty, t",
			Usage: "allocate a pseudo-TTY",
		},
		cli.StringFlag{
			Name: "user, u",
		},
		cli.StringFlag{
			Name:  "process, p",
			Usage: "path to the process.json",
		},
		cli.BoolFlag{
			Name:  "detach,d",
			Usage: "detach from the container's process",
		},
		cli.StringFlag{
			Name:  "pid-file",
			Value: "",
			Usage: "specify the file to write the process id to",
		},
		cli.StringFlag{
			Name:  "shim-log",
			Value: "",
			Usage: `path to the log file or named pipe (e.g. \\.\pipe\ProtectedPrefix\Administrators\runhcs-<container-id>-<exec-id>-log) for the launched shim process`,
		},
	},
	Before: appargs.Validate(argID, appargs.Rest(appargs.String)),
	Action: func(context *cli.Context) error {
		id := context.Args().First()
		pidFile, err := absPathOrEmpty(context.String("pid-file"))
		if err != nil {
			return err
		}
		shimLog, err := absPathOrEmpty(context.String("shim-log"))
		if err != nil {
			return err
		}
		c, err := getContainer(id, false)
		if err != nil {
			return err
		}
		defer c.Close()
		status, err := c.Status()
		if err != nil {
			return err
		}
		if status != containerRunning {
			return errContainerStopped
		}
		spec, err := getProcessSpec(context, c)
		if err != nil {
			return err
		}
		p, err := startProcessShim(id, pidFile, shimLog, spec)
		if err != nil {
			return err
		}
		if !context.Bool("detach") {
			state, err := p.Wait()
			if err != nil {
				return err
			}
			os.Exit(int(state.Sys().(syscall.WaitStatus).ExitCode))
		}
		return nil
	},
	SkipArgReorder: true,
}

func getProcessSpec(context *cli.Context, c *container) (*specs.Process, error) {
	if path := context.String("process"); path != "" {
		f, err := os.Open(path)
		if err != nil {
			return nil, err
		}
		defer f.Close()
		var p specs.Process
		if err := json.NewDecoder(f).Decode(&p); err != nil {
			return nil, err
		}
		return &p, validateProcessSpec(&p)
	}

	// process via cli flags
	p := c.Spec.Process

	if len(context.Args()) == 1 {
		return nil, fmt.Errorf("process args cannot be empty")
	}
	p.Args = context.Args()[1:]
	// override the cwd, if passed
	if context.String("cwd") != "" {
		p.Cwd = context.String("cwd")
	}
	// append the passed env variables
	p.Env = append(p.Env, context.StringSlice("env")...)

	// set the tty
	if context.IsSet("tty") {
		p.Terminal = context.Bool("tty")
	}
	// override the user, if passed
	if context.String("user") != "" {
		p.User.Username = context.String("user")
	}
	return p, nil
}

func validateProcessSpec(spec *specs.Process) error {
	if spec.Cwd == "" {
		return fmt.Errorf("Cwd property must not be empty")
	}
	// IsAbs doesnt recognize Unix paths on Windows builds so handle that case
	// here.
	if !filepath.IsAbs(spec.Cwd) && !strings.HasPrefix(spec.Cwd, "/") {
		return fmt.Errorf("Cwd must be an absolute path")
	}
	if len(spec.Args) == 0 {
		return fmt.Errorf("args must not be empty")
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/ianremmler/setgo"
	"github.com/wsxiaoys/terminal/color"

	"fmt"
	"math/rand"
	"os"
	"strings"
	"time"
)

const (
	keys = "qazwsxedcrfvtgbyhn"
)

var (
	colors = []string{"@r", "@g", "@m"}
	shapes = [][]string{
		{"□", "◨", "■"},
		{"○", "◑", "●"},
		{"△", "◮", "▲"},
	}
	setsFound = 0
	set       *setgo.SetGo
)

func main() {
	rand.Seed(time.Now().UnixNano())
	set = setgo.NewStd()
	play()
}

func play() {
	set.Shuffle()
	set.Deal()
	for {
		printField()
		if set.NumSets() == 0 {
			fmt.Println("\nNo more sets.")
			os.Exit(0)
		}
		fmt.Printf("\n[sets: %02d, deck: %02d] > ", setsFound, set.DeckSize())
		str := ""
		fmt.Scan(&str)
		if len(str) < 3 {
			fmt.Println("\nYou must enter 3 cards.\n")
			continue
		}
		candidate := make([]int, 3)
		for i := range candidate {
			candidate[i] = strings.Index(keys, string(str[i]))
		}

		fmt.Println()
		for _, c := range candidate {
			fmt.Printf("%s ", printCard(c))
		}
		if set.IsSet(candidate) {
			setsFound++
			fmt.Println("is a set!\n")
			set.Remove(candidate)
			set.Deal()
		} else {
			fmt.Println("is not a set.\n")
		}
	}
}

func printCard(i int) string {
	card := set.FieldCard(i)
	str := ""
	if card.Blank {
		str = "[       ]"
	} else {
		num, clr, shp, fil := card.Attr[0], card.Attr[1], card.Attr[2], card.Attr[3]
		shapeStr := strings.Repeat(" "+shapes[shp][fil], num+1)
		colorStr := colors[clr]
		padStr := strings.Repeat(" ", 2-num)
		str = "[" + padStr + colorStr + shapeStr + padStr + "@| ]"
	}
	return color.Sprint(str)
}

func printField() {
	field := set.Field()
	for i := range field {
		numCards := len(field)
		numCols := numCards / 3
		f := (i*3)%numCards + (i / numCols)
		tag := "?"
		if f >= 0 && f < len(keys) {
			tag = string(keys[f])
		}
		fmt.Printf("%s.%s", tag, printCard(f))
		if (i+1)%numCols == 0 {
			fmt.Println()
		} else {
			fmt.Print("  ")
		}
	}
}
<commit_msg>Clear screen between moves.<commit_after>package main

import (
	"github.com/ianremmler/setgo"
	"github.com/wsxiaoys/terminal"
	"github.com/wsxiaoys/terminal/color"

	"fmt"
	"math/rand"
	"os"
	"strings"
	"time"
)

const (
	keys = "qazwsxedcrfvtgbyhn"
)

var (
	colors = []string{"@r", "@g", "@m"}
	shapes = [][]string{
		{"□", "◨", "■"},
		{"○", "◑", "●"},
		{"△", "◮", "▲"},
	}
	setsFound = 0
	set       *setgo.SetGo
)

func main() {
	rand.Seed(time.Now().UnixNano())
	set = setgo.NewStd()
	play()
}

func play() {
	set.Shuffle()
	set.Deal()

	terminal.Stdout.Clear()
	terminal.Stdout.Move(0, 0)

	for {
		printField()
		if set.NumSets() == 0 {
			fmt.Println("\nNo more sets.")
			os.Exit(0)
		}
		fmt.Printf("\n[sets: %02d, deck: %02d] > ", setsFound, set.DeckSize())
		str := ""
		fmt.Scan(&str)

		terminal.Stdout.Clear()
		terminal.Stdout.Move(0, 0)

		if len(str) < 3 {
			fmt.Println("You must enter 3 cards.\n")
			continue
		}
		candidate := make([]int, 3)
		for i := range candidate {
			candidate[i] = strings.Index(keys, string(str[i]))
		}
		for _, c := range candidate {
			fmt.Printf("%s ", printCard(c))
		}
		if set.IsSet(candidate) {
			setsFound++
			fmt.Println("is a set!\n")
			set.Remove(candidate)
			set.Deal()
		} else {
			fmt.Println("is not a set.\n")
		}
	}
}

func printCard(i int) string {
	card := set.FieldCard(i)
	str := ""
	if card.Blank {
		str = "[       ]"
	} else {
		num, clr, shp, fil := card.Attr[0], card.Attr[1], card.Attr[2], card.Attr[3]
		shapeStr := strings.Repeat(" "+shapes[shp][fil], num+1)
		colorStr := colors[clr]
		padStr := strings.Repeat(" ", 2-num)
		str = "[" + padStr + colorStr + shapeStr + padStr + "@| ]"
	}
	return color.Sprint(str)
}

func printField() {
	field := set.Field()
	for i := range field {
		numCards := len(field)
		numCols := numCards / 3
		f := (i*3)%numCards + (i / numCols)
		tag := "?"
		if f >= 0 && f < len(keys) {
			tag = string(keys[f])
		}
		fmt.Printf("%s.%s", tag, printCard(f))
		if (i+1)%numCols == 0 {
			fmt.Println()
		} else {
			fmt.Print("  ")
		}
	}
}
<|endoftext|>


<commit_before>// shade presents a fuse filesystem interface.
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"path"
	"time"

	"bazil.org/fuse"

	"github.com/asjoyner/shade"
	"github.com/asjoyner/shade/config"
	"github.com/asjoyner/shade/drive"
	"github.com/asjoyner/shade/fusefs"

	_ "github.com/asjoyner/shade/drive/amazon"
	_ "github.com/asjoyner/shade/drive/cache"
	_ "github.com/asjoyner/shade/drive/google"
	_ "github.com/asjoyner/shade/drive/local"
	_ "github.com/asjoyner/shade/drive/memory"
)

var (
	defaultConfig = path.Join(shade.ConfigDir(), "config.json")

	readOnly   = flag.Bool("readonly", false, "Mount the filesystem read only.")
	allowOther = flag.Bool("allow_other", false, "If other users are allowed to view the mounted filesystem.")
	configFile = flag.String("config", defaultConfig, fmt.Sprintf("The shade config file. Defaults to %q", defaultConfig))
	cacheDebug = flag.Bool("cacheDebug", false, "Print cache debugging traces")
	treeDebug  = flag.Bool("treeDebug", false, "Print Node tree debugging traces")
)

func main() {
	flag.Usage = usage
	flag.Parse()

	if flag.NArg() != 1 {
		usage()
		os.Exit(2)
	}

	// read in the config
	config, err := config.Read(*configFile)
	if err != nil {
		log.Fatalf("could not read configuration: %s\n", err)
	}

	// initialize client
	client, err := drive.NewClient(config)
	if err != nil {
		log.Fatalf("could not initialize client: %s\n", err)
	}
	/*
		if *cacheDebug {
			cacheClient.Debug()
		}
	*/

	// Setup fuse FS
	conn, err := mountFuse(flag.Arg(0))
	if err != nil {
		log.Fatalf("failed to mount: %s", err)
	}
	fmt.Printf("Mounting Shade FuseFS at %s...\n", flag.Arg(0))

	if err := serviceFuse(conn, client); err != nil {
		log.Fatalf("failed to service mount: %s", err)
	}

	return
}

func usage() {
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "  %s <mountpoint>\n", os.Args[0])
	flag.PrintDefaults()
}

func mountFuse(mountPoint string) (*fuse.Conn, error) {
	if err := sanityCheck(mountPoint); err != nil {
		return nil, fmt.Errorf("sanityCheck failed: %s\n", err)
	}

	options := []fuse.MountOption{
		fuse.FSName("Shade"),
		//fuse.Subtype(""),
		//fuse.VolumeName(<iterate clients?>),
	}

	if *allowOther {
		options = append(options, fuse.AllowOther())
	}
	if *readOnly {
		options = append(options, fuse.ReadOnly())
	}
	options = append(options, fuse.NoAppleDouble())
	c, err := fuse.Mount(mountPoint, options...)
	if err != nil {
		fmt.Println("Is the mount point busy?")
		return nil, err
	}

	// Trap control-c (sig INT) and unmount
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt)
	go func() {
		for _ = range sig {
			if err := fuse.Unmount(mountPoint); err != nil {
				log.Printf("fuse.Unmount failed: %v", err)
			}
		}
	}()

	return c, nil
}

// serviceFuse initializes fusefs, the shade implementation of a fuse file
// server, and services requests from the fuse kernel filesystem until it is
// unmounted.
func serviceFuse(conn *fuse.Conn, client drive.Client) error {
	refresh := time.NewTicker(5 * time.Minute)
	ffs, err := fusefs.New(client, conn, refresh)
	if err != nil {
		return fmt.Errorf("fuse server initialization failed: %s", err)
	}
	if *treeDebug {
		ffs.TreeDebug()
	}

	go func() {
		<-conn.Ready // block until the fuse FS is mounted and ready
		if err := conn.MountError; err != nil {
			fmt.Printf("mounting fuse fs failed: %s", err)
		}
		fmt.Println("Shade FuseFS mounted and ready to serve.")
	}()

	err = ffs.Serve()
	if err != nil {
		return fmt.Errorf("serving fuse connection failed: %s", err)
	}
	return nil

}

func sanityCheck(mountPoint string) error {
	fileInfo, err := os.Stat(mountPoint)
	if os.IsNotExist(err) {
		if err := os.MkdirAll(mountPoint, 0777); err != nil {
			return fmt.Errorf("mountpoint does not exist, could not create it")
		}
		return nil
	}
	if err != nil {
		return fmt.Errorf("error stat()ing mountpoint: %s", err)
	}
	if !fileInfo.IsDir() {
		return fmt.Errorf("the mountpoint is not a directory")
	}
	return nil
}
<commit_msg>Make the encrypt drive package aviailable in shade<commit_after>// shade presents a fuse filesystem interface.
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"path"
	"time"

	"bazil.org/fuse"

	"github.com/asjoyner/shade"
	"github.com/asjoyner/shade/config"
	"github.com/asjoyner/shade/drive"
	"github.com/asjoyner/shade/fusefs"

	_ "github.com/asjoyner/shade/drive/amazon"
	_ "github.com/asjoyner/shade/drive/cache"
	_ "github.com/asjoyner/shade/drive/encrypt"
	_ "github.com/asjoyner/shade/drive/google"
	_ "github.com/asjoyner/shade/drive/local"
	_ "github.com/asjoyner/shade/drive/memory"
)

var (
	defaultConfig = path.Join(shade.ConfigDir(), "config.json")

	readOnly   = flag.Bool("readonly", false, "Mount the filesystem read only.")
	allowOther = flag.Bool("allow_other", false, "If other users are allowed to view the mounted filesystem.")
	configFile = flag.String("config", defaultConfig, fmt.Sprintf("The shade config file. Defaults to %q", defaultConfig))
	cacheDebug = flag.Bool("cacheDebug", false, "Print cache debugging traces")
	treeDebug  = flag.Bool("treeDebug", false, "Print Node tree debugging traces")
)

func main() {
	flag.Usage = usage
	flag.Parse()

	if flag.NArg() != 1 {
		usage()
		os.Exit(2)
	}

	// read in the config
	config, err := config.Read(*configFile)
	if err != nil {
		log.Fatalf("could not read configuration: %s\n", err)
	}

	// initialize client
	client, err := drive.NewClient(config)
	if err != nil {
		log.Fatalf("could not initialize client: %s\n", err)
	}
	/*
		if *cacheDebug {
			cacheClient.Debug()
		}
	*/

	// Setup fuse FS
	conn, err := mountFuse(flag.Arg(0))
	if err != nil {
		log.Fatalf("failed to mount: %s", err)
	}
	fmt.Printf("Mounting Shade FuseFS at %s...\n", flag.Arg(0))

	if err := serviceFuse(conn, client); err != nil {
		log.Fatalf("failed to service mount: %s", err)
	}

	return
}

func usage() {
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "  %s <mountpoint>\n", os.Args[0])
	flag.PrintDefaults()
}

func mountFuse(mountPoint string) (*fuse.Conn, error) {
	if err := sanityCheck(mountPoint); err != nil {
		return nil, fmt.Errorf("sanityCheck failed: %s\n", err)
	}

	options := []fuse.MountOption{
		fuse.FSName("Shade"),
		//fuse.Subtype(""),
		//fuse.VolumeName(<iterate clients?>),
	}

	if *allowOther {
		options = append(options, fuse.AllowOther())
	}
	if *readOnly {
		options = append(options, fuse.ReadOnly())
	}
	options = append(options, fuse.NoAppleDouble())
	c, err := fuse.Mount(mountPoint, options...)
	if err != nil {
		fmt.Println("Is the mount point busy?")
		return nil, err
	}

	// Trap control-c (sig INT) and unmount
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt)
	go func() {
		for _ = range sig {
			if err := fuse.Unmount(mountPoint); err != nil {
				log.Printf("fuse.Unmount failed: %v", err)
			}
		}
	}()

	return c, nil
}

// serviceFuse initializes fusefs, the shade implementation of a fuse file
// server, and services requests from the fuse kernel filesystem until it is
// unmounted.
func serviceFuse(conn *fuse.Conn, client drive.Client) error {
	refresh := time.NewTicker(5 * time.Minute)
	ffs, err := fusefs.New(client, conn, refresh)
	if err != nil {
		return fmt.Errorf("fuse server initialization failed: %s", err)
	}
	if *treeDebug {
		ffs.TreeDebug()
	}

	go func() {
		<-conn.Ready // block until the fuse FS is mounted and ready
		if err := conn.MountError; err != nil {
			fmt.Printf("mounting fuse fs failed: %s", err)
		}
		fmt.Println("Shade FuseFS mounted and ready to serve.")
	}()

	err = ffs.Serve()
	if err != nil {
		return fmt.Errorf("serving fuse connection failed: %s", err)
	}
	return nil

}

func sanityCheck(mountPoint string) error {
	fileInfo, err := os.Stat(mountPoint)
	if os.IsNotExist(err) {
		if err := os.MkdirAll(mountPoint, 0777); err != nil {
			return fmt.Errorf("mountpoint does not exist, could not create it")
		}
		return nil
	}
	if err != nil {
		return fmt.Errorf("error stat()ing mountpoint: %s", err)
	}
	if !fileInfo.IsDir() {
		return fmt.Errorf("the mountpoint is not a directory")
	}
	return nil
}
<|endoftext|>