<commit_before>// TODO: right click to search
// TODO: make scrollbar clickable
// TODO: mouse button chords

package main

import (
	"flag"
	"fmt"
	"image"
	"image/color"
	"io/ioutil"
	"os"
	"runtime"
	"runtime/pprof"
	"time"
	"unicode"

	"sigint.ca/die"
	"sigint.ca/graphics/keys"
	"sigint.ca/graphics/scrollbar"
	"sigint.ca/graphics/text"
	"sigint.ca/plan9/draw"
)

const (
	width   = 800
	height  = 600
	sbWidth = 12 // scrollbar
)

var (
	filePath string
	buf      *text.Buffer
	bufImg   *draw.Image
	bufPos   = image.Pt(sbWidth, 0)
	sb       *scrollbar.Scrollbar
	sbImg    *draw.Image
	disp     *draw.Display
	screen   *draw.Image
	oldClipr image.Rectangle
)

var cprof = flag.String("cprof", "", "save cpu profile to `path`")

type snarfer struct {
	d *draw.Display
}

func (sn snarfer) Get() string {
	b, err := sn.d.ReadSnarf()
	if err != nil {
		fmt.Fprintln(os.Stderr, "buf: error reading from snarf buffer: "+err.Error())
	}
	return string(b)
}

func (sn snarfer) Put(s string) {
	err := sn.d.WriteSnarf([]byte(s))
	if err != nil {
		fmt.Fprintln(os.Stderr, "buf: error writing to snarf buffer: "+err.Error())
	}
}

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

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	flag.Usage = usage
	flag.Parse()
	if len(flag.Args()) > 1 {
		usage()
		os.Exit(1)
	}

	// possibly start cpu profiling
	if *cprof != "" {
		profileWriter, err := os.Create(*cprof)
		die.On(err, "buf: error creating file for cpu profile")
		defer profileWriter.Close()
		pprof.StartCPUProfile(profileWriter)
		defer pprof.StopCPUProfile()
	}

	// load font
	fontPath := os.Getenv("font")
	if fontPath == "" {
		fontPath = os.Getenv("GOPATH") + "/src/sigint.ca/graphics/cmd/buf/proggyfont.ttf"
	}

	// possibly load input file
	var inputFile *os.File
	if len(flag.Args()) == 1 {
		filePath = flag.Arg(0)
		_, err := os.Stat(filePath)
		if err != nil {
			// if there's no file, no worries. otherwise, bail.
			if !os.IsNotExist(err) {
				die.On(err, "buf: error opening input file")
			}
		} else {
			// no issues, open file for reading
			inputFile, err = os.Open(filePath)
			die.On(err, "buf: error opening input file")
		}
	}

	var err error
	if inputFile == nil {
		// even though inputFile is nil, we must use the value nil. Otherwise, NewBuffer will
		// report inputFile != nil because it receives a non-nil interface.
		buf, err = text.NewBuffer(width-sbWidth, height, fontPath, nil, text.AcmeTheme)
	} else {
		buf, err = text.NewBuffer(width-sbWidth, height, fontPath, inputFile, text.AcmeTheme)
		inputFile.Close()
	}
	die.On(err, "buf: error creating new text buffer")

	// scrollbar
	bg := color.RGBA{R: 0x99, G: 0x99, B: 0x4C, A: 0xFF}
	fg := color.RGBA{R: 0xFF, G: 0xFF, B: 0xEA, A: 0xFF}
	sb = scrollbar.New(sbWidth, height, bg, fg)

	// setup display device
	winName := filePath
	if winName == "" {
		winName = "<no file>"
	}
	disp, err = draw.Init(winName, width, height)
	die.On(err, "buf: error initializing display device")
	defer disp.Close()
	screen = disp.ScreenImage

	kbd := disp.InitKeyboard()
	mouse := disp.InitMouse()
	buf.Clipboard = snarfer{disp}
	redraw()

loop:
	for {
		select {
		case <-mouse.Resize:
			resize()
		case me := <-mouse.C:
			buf.SendMouseEvent(me.Point.Sub(bufPos), me.Buttons)
			for len(mouse.C) > 0 {
				me = <-mouse.C
				buf.SendMouseEvent(me.Point.Sub(bufPos), me.Buttons)
			}
		case ke := <-kbd.C:
			switch ke {
			case keys.Return:
				n := buf.Dot.Head.Row
				s := buf.GetLine(n)
				indentation := getIndent(s)
				buf.SendKey('\n')
				buf.Load(indentation)
				buf.Dot = text.Selection{buf.Dot.Tail, buf.Dot.Tail}
			case keys.Escape:
				break loop
			case keys.Save:
				save()
			default:
				buf.SendKey(ke)
			}
		case <-disp.ExitC:
			break loop
		}
		redraw()

		// Rest for a moment. This allows mouse.C to fill up with mouse events,
		// in case we are receiving rapid fire mouse events (in which case we
		// don't need to redraw after each event)
		time.Sleep(1 * time.Millisecond)
	}
}

func redraw() {
	img, clipr, dirty := buf.Img()
	if dirty != image.ZR {
		// it is possible that img.Bounds() has changed, in which case we need to
		// resize bufImg as well.
		if bufImg == nil || bufImg.Bounds() != img.Bounds() {
			var err error
			bufImg, err = disp.AllocImage(img.Bounds(), draw.ABGR32, false, draw.White)
			die.On(err, "buf: error allocating image")
		}
		_, err := bufImg.Load(dirty, img.SubImage(dirty).(*image.RGBA).Pix)
		die.On(err, "buf: error loading buffer image to plan9 image")

		if buf.Saved() {
			err = disp.SetLabel(filePath)
		} else {
			err = disp.SetLabel(filePath + " (unsaved)")
		}
		die.On(err, "buf: error setting window label")
	}
	if dirty != image.ZR || clipr != oldClipr {
		screen.Draw(bufImg.Bounds().Add(bufPos), bufImg, nil, clipr.Min)
		drawScrollbar(clipr, img.Bounds())
		disp.Flush()
	}
	oldClipr = clipr
}

func resize() {
	err := disp.Attach(draw.Refmesg)
	die.On(err, "buf: error reattaching display after resize")
	r := screen.Bounds()
	buf.Resize(r.Dx()-sbWidth, r.Dy())
	sb.Resize(sbWidth, r.Dy())
}

func save() {
	if filePath != "" {
		err := ioutil.WriteFile(filePath, []byte(buf.Contents()), 0666)
		die.On(err, "buf: error writing to file")
	} else {
		fmt.Fprintln(os.Stderr, "buf: error writing to file: no filename")
	}
	buf.SetSaved()
	err := disp.SetLabel(filePath)
	die.On(err, "buf: error setting window label")
}

func getIndent(line string) string {
	if len(line) == 0 {
		return ""
	}
	var indent string
	for _, r := range line {
		if !unicode.IsSpace(r) {
			break
		}
		indent += string(r)
	}
	return indent
}

func drawScrollbar(visible, actual image.Rectangle) {
	actual.Max.Y -= visible.Dy()
	img := sb.Img(visible, actual)
	if sbImg == nil || sbImg.Bounds() != img.Bounds() {
		var err error
		sbImg, err = disp.AllocImage(img.Bounds(), draw.ABGR32, false, draw.White)
		die.On(err, "buf: error allocating image")
	}
	_, err := sbImg.Load(sbImg.Bounds(), img.Pix)
	die.On(err, "buf: error loading scrollbar image to plan9 image")
	screen.Draw(screen.Bounds(), sbImg, nil, image.ZP)
}
<commit_msg>cmd/buf: update error messages<commit_after>// TODO: right click to search
// TODO: make scrollbar clickable
// TODO: mouse button chords

package main

import (
	"flag"
	"fmt"
	"image"
	"image/color"
	"io/ioutil"
	"os"
	"runtime"
	"runtime/pprof"
	"time"
	"unicode"

	"sigint.ca/die"
	"sigint.ca/graphics/keys"
	"sigint.ca/graphics/scrollbar"
	"sigint.ca/graphics/text"
	"sigint.ca/plan9/draw"
)

const (
	width   = 800
	height  = 600
	sbWidth = 12 // scrollbar
)

var (
	filePath string
	buf      *text.Buffer
	bufImg   *draw.Image
	bufPos   = image.Pt(sbWidth, 0)
	sb       *scrollbar.Scrollbar
	sbImg    *draw.Image
	disp     *draw.Display
	screen   *draw.Image
	oldClipr image.Rectangle
)

var cprof = flag.String("cprof", "", "save cpu profile to `path`")

type snarfer struct {
	d *draw.Display
}

func (sn snarfer) Get() string {
	b, err := sn.d.ReadSnarf()
	if err != nil {
		fmt.Fprintln(os.Stderr, "error reading from snarf buffer: "+err.Error())
	}
	return string(b)
}

func (sn snarfer) Put(s string) {
	err := sn.d.WriteSnarf([]byte(s))
	if err != nil {
		fmt.Fprintln(os.Stderr, "error writing to snarf buffer: "+err.Error())
	}
}

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

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	flag.Usage = usage
	flag.Parse()
	if len(flag.Args()) > 1 {
		usage()
		os.Exit(1)
	}

	// possibly start cpu profiling
	if *cprof != "" {
		profileWriter, err := os.Create(*cprof)
		die.On(err, "error creating file for cpu profile")
		defer profileWriter.Close()
		pprof.StartCPUProfile(profileWriter)
		defer pprof.StopCPUProfile()
	}

	// load font
	fontPath := os.Getenv("font")
	if fontPath == "" {
		fontPath = os.Getenv("GOPATH") + "/src/sigint.ca/graphics/cmd/buf/proggyfont.ttf"
	}

	// possibly load input file
	var inputFile *os.File
	if len(flag.Args()) == 1 {
		filePath = flag.Arg(0)
		_, err := os.Stat(filePath)
		if err != nil {
			// if there's no file, no worries. otherwise, bail.
			if !os.IsNotExist(err) {
				die.On(err, "error opening input file")
			}
		} else {
			// no issues, open file for reading
			inputFile, err = os.Open(filePath)
			die.On(err, "error opening input file")
		}
	}

	var err error
	if inputFile == nil {
		// even though inputFile is nil, we must use the value nil. Otherwise, NewBuffer will
		// report inputFile != nil because it receives a non-nil interface.
		buf, err = text.NewBuffer(width-sbWidth, height, fontPath, nil, text.AcmeTheme)
	} else {
		buf, err = text.NewBuffer(width-sbWidth, height, fontPath, inputFile, text.AcmeTheme)
		inputFile.Close()
	}
	die.On(err, "error creating new text buffer")

	// scrollbar
	bg := color.RGBA{R: 0x99, G: 0x99, B: 0x4C, A: 0xFF}
	fg := color.RGBA{R: 0xFF, G: 0xFF, B: 0xEA, A: 0xFF}
	sb = scrollbar.New(sbWidth, height, bg, fg)

	// setup display device
	winName := filePath
	if winName == "" {
		winName = "<no file>"
	}
	disp, err = draw.Init(winName, width, height)
	die.On(err, "error initializing display device")
	defer disp.Close()
	screen = disp.ScreenImage

	kbd := disp.InitKeyboard()
	mouse := disp.InitMouse()
	buf.Clipboard = snarfer{disp}
	redraw()

loop:
	for {
		select {
		case <-mouse.Resize:
			resize()
		case me := <-mouse.C:
			buf.SendMouseEvent(me.Point.Sub(bufPos), me.Buttons)
			for len(mouse.C) > 0 {
				me = <-mouse.C
				buf.SendMouseEvent(me.Point.Sub(bufPos), me.Buttons)
			}
		case ke := <-kbd.C:
			switch ke {
			case keys.Return:
				n := buf.Dot.Head.Row
				s := buf.GetLine(n)
				indentation := getIndent(s)
				buf.SendKey('\n')
				buf.Load(indentation)
				buf.Dot = text.Selection{buf.Dot.Tail, buf.Dot.Tail}
			case keys.Escape:
				break loop
			case keys.Save:
				save()
			default:
				buf.SendKey(ke)
			}
		case <-disp.ExitC:
			break loop
		}
		redraw()

		// Rest for a moment. This allows mouse.C to fill up with mouse events,
		// in case we are receiving rapid fire mouse events (in which case we
		// don't need to redraw after each event)
		time.Sleep(1 * time.Millisecond)
	}
}

func redraw() {
	img, clipr, dirty := buf.Img()
	if dirty != image.ZR {
		// it is possible that img.Bounds() has changed, in which case we need to
		// resize bufImg as well.
		if bufImg == nil || bufImg.Bounds() != img.Bounds() {
			var err error
			bufImg, err = disp.AllocImage(img.Bounds(), draw.ABGR32, false, draw.White)
			die.On(err, "error allocating image")
		}
		_, err := bufImg.Load(dirty, img.SubImage(dirty).(*image.RGBA).Pix)
		die.On(err, "error loading buffer image to plan9 image")

		if buf.Saved() {
			err = disp.SetLabel(filePath)
		} else {
			err = disp.SetLabel(filePath + " (unsaved)")
		}
		die.On(err, "error setting window label")
	}
	if dirty != image.ZR || clipr != oldClipr {
		screen.Draw(bufImg.Bounds().Add(bufPos), bufImg, nil, clipr.Min)
		drawScrollbar(clipr, img.Bounds())
		disp.Flush()
	}
	oldClipr = clipr
}

func resize() {
	err := disp.Attach(draw.Refmesg)
	die.On(err, "error reattaching display after resize")
	r := screen.Bounds()
	buf.Resize(r.Dx()-sbWidth, r.Dy())
	sb.Resize(sbWidth, r.Dy())
}

func save() {
	if filePath != "" {
		err := ioutil.WriteFile(filePath, []byte(buf.Contents()), 0666)
		die.On(err, "error writing to file")
	} else {
		fmt.Fprintln(os.Stderr, "error writing to file: no filename")
	}
	buf.SetSaved()
	err := disp.SetLabel(filePath)
	die.On(err, "error setting window label")
}

func getIndent(line string) string {
	if len(line) == 0 {
		return ""
	}
	var indent string
	for _, r := range line {
		if !unicode.IsSpace(r) {
			break
		}
		indent += string(r)
	}
	return indent
}

func drawScrollbar(visible, actual image.Rectangle) {
	actual.Max.Y -= visible.Dy()
	img := sb.Img(visible, actual)
	if sbImg == nil || sbImg.Bounds() != img.Bounds() {
		var err error
		sbImg, err = disp.AllocImage(img.Bounds(), draw.ABGR32, false, draw.White)
		die.On(err, "error allocating image")
	}
	_, err := sbImg.Load(sbImg.Bounds(), img.Pix)
	die.On(err, "error loading scrollbar image to plan9 image")
	screen.Draw(screen.Bounds(), sbImg, nil, image.ZP)
}
<|endoftext|>


<commit_before>package cmd

import (
	"context"
	"fmt"
	"os"
	"text/tabwriter"
	"time"

	"github.com/urfave/cli"

	"github.com/arigatomachine/cli/api"
	"github.com/arigatomachine/cli/config"
	"github.com/arigatomachine/cli/identity"
)

func init() {
	keypairs := cli.Command{
		Name:     "keypairs",
		Usage:    "View and generate organization keypairs",
		Category: "ORGANIZATIONS",
		Subcommands: []cli.Command{
			{
				Name:  "list",
				Usage: "List your keypairs for an organization",
				Flags: []cli.Flag{
					orgFlag("org to show keypairs for", true),
				},
				Action: chain(
					ensureDaemon, ensureSession, loadDirPrefs, loadPrefDefaults,
					setUserEnv, checkRequiredFlags, listKeypairs,
				),
			},
			{
				Name:  "generate",
				Usage: "Generate keyparis for an organization",
				Flags: []cli.Flag{
					orgFlag("org to show keypairs for", true),
					cli.BoolFlag{
						Name:  "all",
						Usage: "Perform command for all orgs without valid keypairs",
					},
				},
				Action: chain(
					ensureDaemon, ensureSession, loadDirPrefs, loadPrefDefaults,
					setUserEnv, checkRequiredFlags, generateKeypairs,
				),
			},
		},
	}
	Cmds = append(Cmds, keypairs)
}

const keypairListFailed = "Could not list keypairs, please try again."

func listKeypairs(ctx *cli.Context) error {
	cfg, err := config.LoadConfig()
	if err != nil {
		return err
	}

	client := api.NewClient(cfg)
	c := context.Background()

	// Look up the target org
	var org *api.OrgResult
	org, err = client.Orgs.GetByName(c, ctx.String("org"))
	if err != nil {
		return cli.NewExitError(keypairListFailed, -1)
	}
	if org == nil {
		return cli.NewExitError("Org not found.", -1)
	}

	keypairs, err := client.Keypairs.List(c, org.ID)
	if err != nil {
		return cli.NewExitError(keypairListFailed, -1)
	}

	fmt.Println("")

	w := tabwriter.NewWriter(os.Stdout, 0, 0, 8, ' ', 0)
	fmt.Fprintln(w, "ID\tORG\tKEY TYPE\tVALID\tCREATION DATE")
	fmt.Fprintln(w, " \t \t \t \t ")
	for _, keypair := range keypairs {
		fmt.Fprintln(w, keypair.PublicKey.ID.String()+"\t"+org.Body.Name+"\t"+keypair.PublicKey.Body.KeyType+"\tYES\t"+keypair.PublicKey.Body.Created.Format(time.RFC3339))
	}
	w.Flush()
	fmt.Println("")

	return nil
}

func generateKeypairs(ctx *cli.Context) error {
	cfg, err := config.LoadConfig()
	if err != nil {
		return err
	}

	client := api.NewClient(cfg)
	c := context.Background()

	orgNames := make(map[*identity.ID]string)
	subjectOrgs := make(map[*identity.ID]*api.OrgResult)
	regenOrgs := make(map[*identity.ID]string)

	if ctx.Bool("all") {
		// If all flag is supplied, we will get all their orgs
		var orgs []api.OrgResult
		orgs, oErr := client.Orgs.List(c)
		if oErr != nil {
			return cli.NewExitError("Could not retrieve orgs, please try again", -1)
		}
		for _, org := range orgs {
			subjectOrgs[org.ID] = &org
			orgNames[org.ID] = org.Body.Name
		}
	} else {
		// Verify the org they've specified exists
		var org *api.OrgResult
		org, oErr := client.Orgs.GetByName(c, ctx.String("org"))
		if oErr != nil {
			return cli.NewExitError("Org not found", -1)
		}
		subjectOrgs[org.ID] = org
		orgNames[org.ID] = org.Body.Name
	}

	// Iterate over target orgs and identify which keys exist
	var pErr error
	hasKey := make(map[string]map[string]bool, len(subjectOrgs))
	for orgID := range subjectOrgs {
		keypairs, err := client.Keypairs.List(c, orgID)
		if err != nil {
			pErr = err
			break
		}
		for _, kp := range keypairs {
			oID := kp.PublicKey.Body.OrgID.String()
			if hasKey[oID] == nil {
				hasKey[oID] = make(map[string]bool)
			}
			keyType := kp.PublicKey.Body.KeyType
			hasKey[oID][keyType] = true
		}
	}

	if pErr != nil {
		return cli.NewExitError("Error fetching required context", -1)
	}

	// Regenerate for orgs which do not have both keys present
	for orgID := range subjectOrgs {
		if !hasKey[orgID.String()]["encryption"] || !hasKey[orgID.String()]["signing"] {
			regenOrgs[orgID] = orgNames[orgID]
		}
	}

	var rErr error

	for orgID, name := range regenOrgs {
		fmt.Println("Generating signing and encryption keypairs for org: " + name)
		err := client.Keypairs.Generate(c, orgID, &progress)
		if err != nil && rErr == nil {
			rErr = err
			break
		}
	}

	if rErr != nil {
		return cli.NewExitError("Error while regenerating keypairs", -1)
	}

	if len(regenOrgs) > 0 {
		fmt.Println("Keypair generation successful.")
	} else {
		fmt.Println("No keypairs missing.")
	}
	return nil
}

func generateKeypairsForOrg(ctx *cli.Context, c context.Context, client *api.Client, orgID *identity.ID, lookupOrg bool) error {
	var err error

	msg := fmt.Sprintf("Could not generate keypairs for org. Run '%s keypairs generate' to fix.", ctx.App.Name)
	outputErr := cli.NewExitError(msg, -1)
	if orgID == nil && !lookupOrg {
		return outputErr
	}

	// Lookup org if not supplied
	if orgID == nil && lookupOrg {
		orgs, err := client.Orgs.List(c)
		if err != nil || len(orgs) < 1 {
			return outputErr
		}
		org := orgs[0]
		orgID = org.ID
	}

	err = client.Keypairs.Generate(c, orgID, &progress)
	if err != nil {
		return outputErr
	}

	return nil
}
<commit_msg>Handle org not found for keypairs generate<commit_after>package cmd

import (
	"context"
	"fmt"
	"os"
	"text/tabwriter"
	"time"

	"github.com/urfave/cli"

	"github.com/arigatomachine/cli/api"
	"github.com/arigatomachine/cli/config"
	"github.com/arigatomachine/cli/identity"
)

func init() {
	keypairs := cli.Command{
		Name:     "keypairs",
		Usage:    "View and generate organization keypairs",
		Category: "ORGANIZATIONS",
		Subcommands: []cli.Command{
			{
				Name:  "list",
				Usage: "List your keypairs for an organization",
				Flags: []cli.Flag{
					orgFlag("org to show keypairs for", true),
				},
				Action: chain(
					ensureDaemon, ensureSession, loadDirPrefs, loadPrefDefaults,
					setUserEnv, checkRequiredFlags, listKeypairs,
				),
			},
			{
				Name:  "generate",
				Usage: "Generate keyparis for an organization",
				Flags: []cli.Flag{
					orgFlag("org to show keypairs for", true),
					cli.BoolFlag{
						Name:  "all",
						Usage: "Perform command for all orgs without valid keypairs",
					},
				},
				Action: chain(
					ensureDaemon, ensureSession, loadDirPrefs, loadPrefDefaults,
					setUserEnv, checkRequiredFlags, generateKeypairs,
				),
			},
		},
	}
	Cmds = append(Cmds, keypairs)
}

const keypairListFailed = "Could not list keypairs, please try again."

func listKeypairs(ctx *cli.Context) error {
	cfg, err := config.LoadConfig()
	if err != nil {
		return err
	}

	client := api.NewClient(cfg)
	c := context.Background()

	// Look up the target org
	var org *api.OrgResult
	org, err = client.Orgs.GetByName(c, ctx.String("org"))
	if err != nil {
		return cli.NewExitError(keypairListFailed, -1)
	}
	if org == nil {
		return cli.NewExitError("Org not found.", -1)
	}

	keypairs, err := client.Keypairs.List(c, org.ID)
	if err != nil {
		return cli.NewExitError(keypairListFailed, -1)
	}

	fmt.Println("")

	w := tabwriter.NewWriter(os.Stdout, 0, 0, 8, ' ', 0)
	fmt.Fprintln(w, "ID\tORG\tKEY TYPE\tVALID\tCREATION DATE")
	fmt.Fprintln(w, " \t \t \t \t ")
	for _, keypair := range keypairs {
		fmt.Fprintln(w, keypair.PublicKey.ID.String()+"\t"+org.Body.Name+"\t"+keypair.PublicKey.Body.KeyType+"\tYES\t"+keypair.PublicKey.Body.Created.Format(time.RFC3339))
	}
	w.Flush()
	fmt.Println("")

	return nil
}

func generateKeypairs(ctx *cli.Context) error {
	cfg, err := config.LoadConfig()
	if err != nil {
		return err
	}

	client := api.NewClient(cfg)
	c := context.Background()

	orgNames := make(map[*identity.ID]string)
	subjectOrgs := make(map[*identity.ID]*api.OrgResult)
	regenOrgs := make(map[*identity.ID]string)

	if ctx.Bool("all") {
		// If all flag is supplied, we will get all their orgs
		var orgs []api.OrgResult
		orgs, oErr := client.Orgs.List(c)
		if oErr != nil {
			return cli.NewExitError("Could not retrieve orgs, please try again", -1)
		}
		for _, org := range orgs {
			subjectOrgs[org.ID] = &org
			orgNames[org.ID] = org.Body.Name
		}
	} else {
		// Verify the org they've specified exists
		var org *api.OrgResult
		orgName := ctx.String("org")
		org, oErr := client.Orgs.GetByName(c, orgName)
		if oErr != nil || org == nil {
			return cli.NewExitError("Org '"+orgName+"' not found", -1)
		}
		subjectOrgs[org.ID] = org
		orgNames[org.ID] = org.Body.Name
	}

	// Iterate over target orgs and identify which keys exist
	var pErr error
	hasKey := make(map[string]map[string]bool, len(subjectOrgs))
	for orgID := range subjectOrgs {
		keypairs, err := client.Keypairs.List(c, orgID)
		if err != nil {
			pErr = err
			break
		}
		for _, kp := range keypairs {
			oID := kp.PublicKey.Body.OrgID.String()
			if hasKey[oID] == nil {
				hasKey[oID] = make(map[string]bool)
			}
			keyType := kp.PublicKey.Body.KeyType
			hasKey[oID][keyType] = true
		}
	}

	if pErr != nil {
		return cli.NewExitError("Error fetching required context", -1)
	}

	// Regenerate for orgs which do not have both keys present
	for orgID := range subjectOrgs {
		if !hasKey[orgID.String()]["encryption"] || !hasKey[orgID.String()]["signing"] {
			regenOrgs[orgID] = orgNames[orgID]
		}
	}

	var rErr error

	for orgID, name := range regenOrgs {
		fmt.Println("Generating signing and encryption keypairs for org: " + name)
		err := client.Keypairs.Generate(c, orgID, &progress)
		if err != nil && rErr == nil {
			rErr = err
			break
		}
	}

	if rErr != nil {
		return cli.NewExitError("Error while regenerating keypairs", -1)
	}

	if len(regenOrgs) > 0 {
		fmt.Println("Keypair generation successful.")
	} else {
		fmt.Println("No keypairs missing.")
	}
	return nil
}

func generateKeypairsForOrg(ctx *cli.Context, c context.Context, client *api.Client, orgID *identity.ID, lookupOrg bool) error {
	var err error

	msg := fmt.Sprintf("Could not generate keypairs for org. Run '%s keypairs generate' to fix.", ctx.App.Name)
	outputErr := cli.NewExitError(msg, -1)
	if orgID == nil && !lookupOrg {
		return outputErr
	}

	// Lookup org if not supplied
	if orgID == nil && lookupOrg {
		orgs, err := client.Orgs.List(c)
		if err != nil || len(orgs) < 1 {
			return outputErr
		}
		org := orgs[0]
		orgID = org.ID
	}

	err = client.Keypairs.Generate(c, orgID, &progress)
	if err != nil {
		return outputErr
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/NeowayLabs/nash"
	"github.com/NeowayLabs/nash/ast"
	"github.com/NeowayLabs/nash/parser"
	"github.com/NeowayLabs/nash/sh"
	"github.com/chzyer/readline"
)

type (
	Interrupted interface {
		Interrupted() bool
	}

	Ignored interface {
		Ignore() bool
	}

	BlockNotFinished interface {
		Unfinished() bool
	}
)

var completers = []readline.PrefixCompleterInterface{}

func execFn(shell *nash.Shell, fn sh.Fn) {
	fn.SetStdin(shell.Stdin())
	fn.SetStdout(shell.Stdout())
	fn.SetStderr(shell.Stderr())

	if err := fn.Start(); err != nil {
		fmt.Fprintf(os.Stderr, "%s failed: %s\n", fn.Name(), err.Error())
		return
	}

	if err := fn.Wait(); err != nil {
		fmt.Fprintf(os.Stderr, "%s failed: %s\n", fn.Name(), err.Error())
		return
	}
}

func cli(shell *nash.Shell) error {
	var err error

	historyFile := shell.DotDir() + "/history"

	cfg := readline.Config{
		Prompt:          shell.Prompt(),
		HistoryFile:     historyFile,
		InterruptPrompt: "^C",
		EOFPrompt:       "exit",
	}

	term, err := readline.NewTerminal(&cfg)

	if err != nil {
		return err
	}

	op := term.Readline()
	rline := &readline.Instance{
		Config:    &cfg,
		Terminal:  term,
		Operation: op,
	}

	defer rline.Close()

	completer := NewCompleter(op, term, shell)

	cfg.AutoComplete = completer

	if lineMode, ok := shell.Getvar("LINEMODE"); ok {
		if lineStr, ok := lineMode.(*sh.StrObj); ok && lineStr.Str() == "vim" {
			rline.SetVimMode(true)
		} else {
			rline.SetVimMode(false)
		}
	}

	return docli(shell, rline)
}

func docli(shell *nash.Shell, rline *readline.Instance) error {
	var (
		content bytes.Buffer
		lineidx int
		line    string
		parse   *parser.Parser
		tr      *ast.Tree
		err     error
	)

	for {
		if fn, ok := shell.GetFn("nash_repl_before"); ok {
			execFn(shell, fn)
		}

		prompt := shell.Prompt()
		rline.SetPrompt(prompt)

		line, err = rline.Readline()

		if err == readline.ErrInterrupt {
			goto cont
		} else if err == io.EOF {
			err = nil
			break
		}

		lineidx++

		line = strings.TrimSpace(line)

		// handle special cli commands

		switch {
		case strings.HasPrefix(line, "set mode "):
			switch line[9:] {
			case "vi":
				rline.SetVimMode(true)
			case "emacs":
				rline.SetVimMode(false)
			default:
				fmt.Printf("invalid mode: %s\n", line[9:])
			}

			goto cont
		case line == "mode":
			if rline.IsVimMode() {
				fmt.Printf("Current mode: vim\n")
			} else {
				fmt.Printf("Current mode: emacs\n")
			}

			goto cont

		case line == "exit":
			break
		}

		content.Write([]byte(line + "\n"))

		parse = parser.NewParser(fmt.Sprintf("<stdin line %d>", lineidx), string(content.Bytes()))

		line = string(content.Bytes())

		tr, err = parse.Parse()

		if err != nil {
			if interrupted, ok := err.(Interrupted); ok && interrupted.Interrupted() {
				content.Reset()
				goto cont
			} else if errBlock, ok := err.(BlockNotFinished); ok && errBlock.Unfinished() {
				prompt = ">>> "
				goto cont
			}

			fmt.Printf("ERROR: %s\n", err.Error())

			content.Reset()
			goto cont
		}

		content.Reset()

		_, err = shell.ExecuteTree(tr)

		if err != nil {
			fmt.Printf("ERROR: %s\n", err.Error())
		}

	cont:
		if fn, ok := shell.GetFn("nash_repl_after"); ok {
			var status sh.Obj
			var ok bool

			if status, ok = shell.Getvar("status"); !ok {
				status = sh.NewStrObj("")
			}

			err = fn.SetArgs([]sh.Obj{sh.NewStrObj(line), status})

			if err != nil {
				fmt.Fprintf(os.Stderr, "error: %s\n", err.Error())
			} else {
				execFn(shell, fn)
			}
		}

		rline.SetPrompt(prompt)
	}

	return nil
}
<commit_msg>Fix multi line prompt<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/NeowayLabs/nash"
	"github.com/NeowayLabs/nash/ast"
	"github.com/NeowayLabs/nash/parser"
	"github.com/NeowayLabs/nash/sh"
	"github.com/chzyer/readline"
)

type (
	Interrupted interface {
		Interrupted() bool
	}

	Ignored interface {
		Ignore() bool
	}

	BlockNotFinished interface {
		Unfinished() bool
	}
)

var completers = []readline.PrefixCompleterInterface{}

func execFn(shell *nash.Shell, fn sh.Fn) {
	fn.SetStdin(shell.Stdin())
	fn.SetStdout(shell.Stdout())
	fn.SetStderr(shell.Stderr())

	if err := fn.Start(); err != nil {
		fmt.Fprintf(os.Stderr, "%s failed: %s\n", fn.Name(), err.Error())
		return
	}

	if err := fn.Wait(); err != nil {
		fmt.Fprintf(os.Stderr, "%s failed: %s\n", fn.Name(), err.Error())
		return
	}
}

func cli(shell *nash.Shell) error {
	var err error

	historyFile := shell.DotDir() + "/history"

	cfg := readline.Config{
		Prompt:          shell.Prompt(),
		HistoryFile:     historyFile,
		InterruptPrompt: "^C",
		EOFPrompt:       "exit",
	}

	term, err := readline.NewTerminal(&cfg)

	if err != nil {
		return err
	}

	op := term.Readline()
	rline := &readline.Instance{
		Config:    &cfg,
		Terminal:  term,
		Operation: op,
	}

	defer rline.Close()

	completer := NewCompleter(op, term, shell)

	cfg.AutoComplete = completer

	if lineMode, ok := shell.Getvar("LINEMODE"); ok {
		if lineStr, ok := lineMode.(*sh.StrObj); ok && lineStr.Str() == "vim" {
			rline.SetVimMode(true)
		} else {
			rline.SetVimMode(false)
		}
	}

	return docli(shell, rline)
}

func docli(shell *nash.Shell, rline *readline.Instance) error {
	var (
		content    bytes.Buffer
		lineidx    int
		line       string
		parse      *parser.Parser
		tr         *ast.Tree
		err        error
		unfinished bool
		prompt     string
	)

	for {
		if fn, ok := shell.GetFn("nash_repl_before"); ok && !unfinished {
			execFn(shell, fn)
		}

		if !unfinished {
			prompt = shell.Prompt()
		}

		rline.SetPrompt(prompt)

		line, err = rline.Readline()

		if err == readline.ErrInterrupt {
			goto cont
		} else if err == io.EOF {
			err = nil
			break
		}

		lineidx++

		line = strings.TrimSpace(line)

		// handle special cli commands

		switch {
		case strings.HasPrefix(line, "set mode "):
			switch line[9:] {
			case "vi":
				rline.SetVimMode(true)
			case "emacs":
				rline.SetVimMode(false)
			default:
				fmt.Printf("invalid mode: %s\n", line[9:])
			}

			goto cont
		case line == "mode":
			if rline.IsVimMode() {
				fmt.Printf("Current mode: vim\n")
			} else {
				fmt.Printf("Current mode: emacs\n")
			}

			goto cont

		case line == "exit":
			break
		}

		content.Write([]byte(line + "\n"))

		parse = parser.NewParser(fmt.Sprintf("<stdin line %d>", lineidx), string(content.Bytes()))

		line = string(content.Bytes())

		tr, err = parse.Parse()

		if err != nil {
			if interrupted, ok := err.(Interrupted); ok && interrupted.Interrupted() {
				content.Reset()
				goto cont
			} else if errBlock, ok := err.(BlockNotFinished); ok && errBlock.Unfinished() {
				prompt = ">>> "
				unfinished = true
				goto cont
			}

			fmt.Printf("ERROR: %s\n", err.Error())

			content.Reset()
			goto cont
		}

		unfinished = false
		content.Reset()

		_, err = shell.ExecuteTree(tr)

		if err != nil {
			fmt.Printf("ERROR: %s\n", err.Error())
		}

	cont:
		if fn, ok := shell.GetFn("nash_repl_after"); ok && !unfinished {
			var status sh.Obj
			var ok bool

			if status, ok = shell.Getvar("status"); !ok {
				status = sh.NewStrObj("")
			}

			err = fn.SetArgs([]sh.Obj{sh.NewStrObj(line), status})

			if err != nil {
				fmt.Fprintf(os.Stderr, "error: %s\n", err.Error())
			} else {
				execFn(shell, fn)
			}
		}

		rline.SetPrompt(prompt)
	}

	return nil
}
<|endoftext|>


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

package main

import (
	"github.com/globocom/config"
	"github.com/globocom/tsuru/cmd"
	"github.com/globocom/tsuru/provision"
	_ "github.com/globocom/tsuru/provision/docker"
	_ "github.com/globocom/tsuru/provision/juju"
	"os"
)

const defaultConfigPath = "/etc/tsuru/tsuru.conf"

func buildManager() *cmd.Manager {
	m := cmd.NewManager("tsr", "0.3.6", "", os.Stdout, os.Stderr, os.Stdin)
	m.Register(&tsrCommand{Command: &apiCmd{}})
	m.Register(&tsrCommand{Command: &adminCmd{}})
	m.Register(&tsrCommand{Command: &collectorCmd{}})
	m.Register(&tsrCommand{Command: tokenCmd{}})
	m.Register(&tsrCommand{Command: &healerCmd{}})
	registerProvisionersCommands(m)
	return m
}

func registerProvisionersCommands(m *cmd.Manager) {
	provisioners := provision.Registry()
	for _, p := range provisioners {
		if c, ok := p.(provision.Commandable); ok {
			commands := c.Commands()
			for _, cmd := range commands {
				m.Register(&tsrCommand{Command: cmd})
			}
		}
	}
}

func main() {
	config.ReadConfigFile(defaultConfigPath)
	m := buildManager()
	m.Run(os.Args[1:])
}
<commit_msg>cmd/tsr: version 0.3.7<commit_after>// Copyright 2014 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"github.com/globocom/config"
	"github.com/globocom/tsuru/cmd"
	"github.com/globocom/tsuru/provision"
	_ "github.com/globocom/tsuru/provision/docker"
	_ "github.com/globocom/tsuru/provision/juju"
	"os"
)

const defaultConfigPath = "/etc/tsuru/tsuru.conf"

func buildManager() *cmd.Manager {
	m := cmd.NewManager("tsr", "0.3.7", "", os.Stdout, os.Stderr, os.Stdin)
	m.Register(&tsrCommand{Command: &apiCmd{}})
	m.Register(&tsrCommand{Command: &adminCmd{}})
	m.Register(&tsrCommand{Command: &collectorCmd{}})
	m.Register(&tsrCommand{Command: tokenCmd{}})
	m.Register(&tsrCommand{Command: &healerCmd{}})
	registerProvisionersCommands(m)
	return m
}

func registerProvisionersCommands(m *cmd.Manager) {
	provisioners := provision.Registry()
	for _, p := range provisioners {
		if c, ok := p.(provision.Commandable); ok {
			commands := c.Commands()
			for _, cmd := range commands {
				m.Register(&tsrCommand{Command: cmd})
			}
		}
	}
}

func main() {
	config.ReadConfigFile(defaultConfigPath)
	m := buildManager()
	m.Run(os.Args[1:])
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2019 VMware, Inc. All Rights Reserved.

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 cns

import (
	"context"
	"errors"

	cnstypes "github.com/vmware/govmomi/cns/types"
	"github.com/vmware/govmomi/object"
	vim25types "github.com/vmware/govmomi/vim25/types"
)

// version and namespace constants for task client
const (
	// ClientVersion "vSAN 6.7U3" is the stable version for vSphere 6.7u3 release
	taskClientVersion   = "vSAN 6.7U3"
	taskClientNamespace = "urn:vsan"
)

// GetTaskInfo gets the task info given a task
func GetTaskInfo(ctx context.Context, task *object.Task) (*vim25types.TaskInfo, error) {
	task.Client().Version = taskClientVersion
	task.Client().Namespace = taskClientNamespace
	taskInfo, err := task.WaitForResult(ctx, nil)
	if err != nil {
		return nil, err
	}
	return taskInfo, nil
}

// GetTaskResult gets the task result given a task info
func GetTaskResult(ctx context.Context, taskInfo *vim25types.TaskInfo) (cnstypes.BaseCnsVolumeOperationResult, error) {
	if taskInfo == nil {
		return nil, errors.New("TaskInfo is empty")
	}
	volumeOperationBatchResult := taskInfo.Result.(cnstypes.CnsVolumeOperationBatchResult)
	if &volumeOperationBatchResult == nil ||
		volumeOperationBatchResult.VolumeResults == nil ||
		len(volumeOperationBatchResult.VolumeResults) == 0 {
		return nil, errors.New("Cannot get VolumeOperationResult")
	}
	return volumeOperationBatchResult.VolumeResults[0], nil
}
<commit_msg>update taskClientVersion for vsphere 7.0<commit_after>/*
Copyright (c) 2019 VMware, Inc. All Rights Reserved.

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 cns

import (
	"context"
	"errors"

	cnstypes "github.com/vmware/govmomi/cns/types"
	"github.com/vmware/govmomi/object"
	vim25types "github.com/vmware/govmomi/vim25/types"
)

// version and namespace constants for task client
const (
	// ClientVersion "7.0" is mapped to 'vsan.version.version13'
	// This need to be changed if later VMODL version is bumped
	taskClientVersion   = "7.0"
	taskClientNamespace = "urn:vsan"
)

// GetTaskInfo gets the task info given a task
func GetTaskInfo(ctx context.Context, task *object.Task) (*vim25types.TaskInfo, error) {
	task.Client().Version = taskClientVersion
	task.Client().Namespace = taskClientNamespace
	taskInfo, err := task.WaitForResult(ctx, nil)
	if err != nil {
		return nil, err
	}
	return taskInfo, nil
}

// GetTaskResult gets the task result given a task info
func GetTaskResult(ctx context.Context, taskInfo *vim25types.TaskInfo) (cnstypes.BaseCnsVolumeOperationResult, error) {
	if taskInfo == nil {
		return nil, errors.New("TaskInfo is empty")
	}
	volumeOperationBatchResult := taskInfo.Result.(cnstypes.CnsVolumeOperationBatchResult)
	if &volumeOperationBatchResult == nil ||
		volumeOperationBatchResult.VolumeResults == nil ||
		len(volumeOperationBatchResult.VolumeResults) == 0 {
		return nil, errors.New("Cannot get VolumeOperationResult")
	}
	return volumeOperationBatchResult.VolumeResults[0], nil
}
<|endoftext|>


<commit_before>package jsgettext

import "github.com/gopherjs/gopherjs/js"
import "encoding/json"

type msgIdStrPairs map[string]string
type localesMsg map[string]msgIdStrPairs

var msg = localesMsg{}
var document = js.Global.Get("document")

func SetupTranslationMapping(jsonBlob string) {
	err := json.Unmarshal([]byte(jsonBlob), &msg)
	if err != nil {
		panic(err)
	}
}

func gettext(locale, str string) string {
	if val, ok := msg[locale]; ok {
		if val2, ok2 := val[str]; ok2 {
			return val2
		} else {
			return str
		}
	} else {
		return str
	}
}

func Translate(locale string) {
	nodeList := document.Call("querySelectorAll", "[data-default-string]")
	length := nodeList.Get("length").Int()
	for i := 0; i < length; i++ {
		element := nodeList.Call("item", i)
		str := element.Get("dataset").Get("defaultString").String()
		element.Set("textContent", gettext(locale, str))
	}
}
<commit_msg>export Gettext<commit_after>package jsgettext

import "github.com/gopherjs/gopherjs/js"
import "encoding/json"

type msgIdStrPairs map[string]string
type localesMsg map[string]msgIdStrPairs

var msg = localesMsg{}
var document = js.Global.Get("document")

func SetupTranslationMapping(jsonBlob string) {
	err := json.Unmarshal([]byte(jsonBlob), &msg)
	if err != nil {
		panic(err)
	}
}

func Gettext(locale, str string) string {
	if val, ok := msg[locale]; ok {
		if val2, ok2 := val[str]; ok2 {
			return val2
		}
	}
	return str
}

func Translate(locale string) {
	nodeList := document.Call("querySelectorAll", "[data-default-string]")
	length := nodeList.Get("length").Int()
	for i := 0; i < length; i++ {
		element := nodeList.Call("item", i)
		str := element.Get("dataset").Get("defaultString").String()
		element.Set("textContent", Gettext(locale, str))
	}
}
<|endoftext|>


<commit_before>package json

import (
	"bufio"
	"bytes"
	"compress/gzip"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/str1ngs/util/file"
	"io"
	"net/http"
	"os"
	"strings"
	"text/tabwriter"
)

var (
	client = new(http.Client)
)

// Marshal's a interface, and writes it to a gzipped file.
func WriteGz(v interface{}, file string) (err error) {
	fd, err := os.Create(file)
	if err != nil {
		return err
	}
	defer fd.Close()
	return WriteGzIo(v, fd)
}

// Read a gzipped json file and decodes it into an interface.
func ReadGz(v interface{}, file string) (err error) {
	fd, err := os.Open(file)
	if err != nil {
		return err
	}
	defer fd.Close()
	return ReadGzIo(v, fd)
}

func ReadGzIo(v interface{}, r io.Reader) (err error) {
	gz, err := gzip.NewReader(r)
	if err != nil {
		return err
	}
	defer gz.Close()
	return json.NewDecoder(gz).Decode(v)
}

func WriteGzIo(v interface{}, w io.Writer) (err error) {
	gz := gzip.NewWriter(w)
	defer gz.Close()
	b, err := json.Marshal(v)
	if err != nil {
		return err
	}
	buf := new(bytes.Buffer)
	err = json.Indent(buf, b, "", "\t")
	if err != nil {
		return err
	}
	_, err = io.Copy(gz, buf)
	return err
}

// Write marshals a interface and writes it to a file
func Write(v interface{}, path string) (err error) {
	fd, err := os.Create(path)
	if err != nil {
		return err
	}
	defer fd.Close()
	return WritePretty(v, fd)
}

// Reads a json file and decodes it into interface
func Read(v interface{}, path string) (err error) {
	if !file.Exists(path) {
		return fmt.Errorf("%s does not exist.", path)
	}
	fd, err := os.Open(path)
	if err != nil {
		return err
	}
	defer fd.Close()
	return json.NewDecoder(fd).Decode(v)
}

func Clean(v interface{}, w io.Writer) (err error) {
	buf := new(bytes.Buffer)
	err = WritePretty(v, buf)
	if err != nil {
		return err
	}
	for {
		b, err := buf.ReadByte()
		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}
		switch b {
		case '{', '}', '"', ',', '[', ']', '\t':
			continue
		default:
			w.Write([]byte{b})
		}
	}
	return nil
}

func Format(in io.Reader, out io.Writer) error {
	var v interface{}
	err := json.NewDecoder(in).Decode(&v)
	if err != nil {
		return err
	}
	return WritePretty(v, out)
}

// PrintPretty marshal's an interface and ouputs formatted json to writer.
func WritePretty(v interface{}, w io.Writer) (err error) {
	b, err := json.Marshal(v)
	if err != nil {
		return err
	}
	buf := new(bytes.Buffer)
	err = json.Indent(buf, b, "", "\t")
	//err = json.Compact(buf, b)
	if err != nil {
		return err
	}
	br := bufio.NewReader(buf)
	tw := tabwriter.NewWriter(w, 4, 0, 1, ' ', 0)
	for {
		b, _, err := br.ReadLine()
		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}
		line := string(b) + "\n"
		line = strings.Replace(line, "\":", "\"\t:", 1)
		line = strings.Replace(line, "},", "},\t", 1)
		_, err = tw.Write([]byte(line))
		if err != nil {
			return err
		}
	}
	return tw.Flush()
}

// Decodes a URL to interface
func Get(v interface{}, url string) (err error) {
	resp, err := client.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return errors.New(resp.Status)
	}
	return json.NewDecoder(resp.Body).Decode(v)
}
<commit_msg>Don't trail tab after closing brace.<commit_after>package json

import (
	"bufio"
	"bytes"
	"compress/gzip"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/str1ngs/util/file"
	"io"
	"net/http"
	"os"
	"strings"
	"text/tabwriter"
)

var (
	client = new(http.Client)
)

// Marshal's a interface, and writes it to a gzipped file.
func WriteGz(v interface{}, file string) (err error) {
	fd, err := os.Create(file)
	if err != nil {
		return err
	}
	defer fd.Close()
	return WriteGzIo(v, fd)
}

// Read a gzipped json file and decodes it into an interface.
func ReadGz(v interface{}, file string) (err error) {
	fd, err := os.Open(file)
	if err != nil {
		return err
	}
	defer fd.Close()
	return ReadGzIo(v, fd)
}

func ReadGzIo(v interface{}, r io.Reader) (err error) {
	gz, err := gzip.NewReader(r)
	if err != nil {
		return err
	}
	defer gz.Close()
	return json.NewDecoder(gz).Decode(v)
}

func WriteGzIo(v interface{}, w io.Writer) (err error) {
	gz := gzip.NewWriter(w)
	defer gz.Close()
	b, err := json.Marshal(v)
	if err != nil {
		return err
	}
	buf := new(bytes.Buffer)
	err = json.Indent(buf, b, "", "\t")
	if err != nil {
		return err
	}
	_, err = io.Copy(gz, buf)
	return err
}

// Write marshals a interface and writes it to a file
func Write(v interface{}, path string) (err error) {
	fd, err := os.Create(path)
	if err != nil {
		return err
	}
	defer fd.Close()
	return WritePretty(v, fd)
}

// Reads a json file and decodes it into interface
func Read(v interface{}, path string) (err error) {
	if !file.Exists(path) {
		return fmt.Errorf("%s does not exist.", path)
	}
	fd, err := os.Open(path)
	if err != nil {
		return err
	}
	defer fd.Close()
	return json.NewDecoder(fd).Decode(v)
}

func Clean(v interface{}, w io.Writer) (err error) {
	buf := new(bytes.Buffer)
	err = WritePretty(v, buf)
	if err != nil {
		return err
	}
	for {
		b, err := buf.ReadByte()
		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}
		switch b {
		case '{', '}', '"', ',', '[', ']', '\t':
			continue
		default:
			w.Write([]byte{b})
		}
	}
	return nil
}

func Format(in io.Reader, out io.Writer) error {
	var v interface{}
	err := json.NewDecoder(in).Decode(&v)
	if err != nil {
		return err
	}
	return WritePretty(v, out)
}

// PrintPretty marshal's an interface and ouputs formatted json to writer.
func WritePretty(v interface{}, w io.Writer) (err error) {
	b, err := json.Marshal(v)
	if err != nil {
		return err
	}
	buf := new(bytes.Buffer)
	err = json.Indent(buf, b, "", "\t")
	//err = json.Compact(buf, b)
	if err != nil {
		return err
	}
	br := bufio.NewReader(buf)
	tw := tabwriter.NewWriter(w, 4, 0, 1, ' ', 0)
	for {
		b, _, err := br.ReadLine()
		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}
		line := string(b) + "\n"
		line = strings.Replace(line, "\":", "\"\t:", 1)
		_, err = tw.Write([]byte(line))
		if err != nil {
			return err
		}
	}
	return tw.Flush()
}

// Decodes a URL to interface
func Get(v interface{}, url string) (err error) {
	resp, err := client.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return errors.New(resp.Status)
	}
	return json.NewDecoder(resp.Body).Decode(v)
}
<|endoftext|>


<commit_before>package command

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	. "github.com/ForceCLI/force/error"
	. "github.com/ForceCLI/force/lib"
)

// Brief comment to fire commit

var cmdAura = &Command{
	Usage: "aura",
	Short: "force aura push -f <filepath>",
	Long: `
	The aura command needs context to work. If you execute "aura get"
	it will create a folder structure that provides the context for
	aura components on disk.

	The aura components will be created in "metadata/aurabundles/<componentname>"
	relative to the current working directory and a .manifest file will be
	created that associates components and their artifacts with their ids in
	the database.

	To create a new component (application, evt or component), create a new
	folder under "aura". Then create a new file in your new folder. You
	must follow a naming convention for your files to enable proper definition
	of the component type.

	Naming convention <compnentName><artifact type>.<file type extension>
	Examples: 	metadata
					aura
						MyApp
							MyAppApplication.app
							MyAppStyle.css
						MyList
							MyComponent.cmp
							MyComponentHelper.js
							MyComponentStyle.css

	force aura push -f <fullFilePath> -b <bundle name>

	force aura create -t=<entity type> <entityName>

	force aura delete -f=<fullFilePath>

	force aura list

	`,
}

func init() {
	cmdAura.Run = runAura
	cmdAura.Flag.Var(&resourcepaths, "p", "fully qualified file name for entity")
	cmdAura.Flag.Var(&resourcepaths, "f", "fully qualified file name for entity")
	cmdAura.Flag.StringVar(&metadataType, "entitytype", "", "fully qualified file name for entity")
	cmdAura.Flag.StringVar(&auraentityname, "entityname", "", "fully qualified file name for entity")
	cmdAura.Flag.StringVar(&metadataType, "t", "", "fully qualified file name for entity")
	cmdAura.Flag.StringVar(&auraentityname, "n", "", "fully qualified file name for entity")
}

var (
	auraentityname string
	metadataType   string
)

func runAura(cmd *Command, args []string) {
	if err := cmd.Flag.Parse(args[0:]); err != nil {
		os.Exit(2)
	}

	force, _ := ActiveForce()

	subcommand := args[0]
	// Sublime hack - the way sublime passes parameters seems to
	// break the flag parsing by sending a single element array
	// for the args. ARGH!!!
	if strings.HasPrefix(subcommand, "delete ") || strings.HasPrefix(subcommand, "push ") {
		what := strings.Split(subcommand, " ")
		if err := cmd.Flag.Parse(what[1:]); err != nil {
			ErrorAndExit(err.Error())
		}
		subcommand = what[0]
	} else {
		if err := cmd.Flag.Parse(args[1:]); err != nil {
			ErrorAndExit(err.Error())
		}
	}

	switch strings.ToLower(subcommand) {
	case "create":
		/*if *auraentitytype == "" || *auraentityname == "" {
			fmt.Println("Must specify entity type and name")
			os.Exit(2)
		}*/
		ErrorAndExit("force aura create not yet implemented")

	case "delete":
		runDeleteAura()
	case "list":
		bundles, err := force.GetAuraBundlesList()
		if err != nil {
			ErrorAndExit(err.Error())
		}
		for _, bundle := range bundles.Records {
			fmt.Println(bundle["DeveloperName"])
		}
	case "push":
		//		absPath, _ := filepath.Abs(resourcepaths[0])
		runPushAura(cmd, resourcepaths)
	}
}

func runDeleteAura() {
	absPath, _ := filepath.Abs(resourcepaths[0])
	//resourcepaths = absPath

	if InAuraBundlesFolder(absPath) {
		info, err := os.Stat(absPath)
		if err != nil {
			ErrorAndExit(err.Error())
		}
		manifest, err := GetManifest(absPath)
		isBundle := false
		if info.IsDir() {
			force, _ := ActiveForce()
			manifest, err = GetManifest(filepath.Join(absPath, ".manifest"))
			bid := ""
			if err != nil { // Could not find a manifest, use bundle name
				// Try to look up the bundle by name
				b, err := force.GetAuraBundleByName(filepath.Base(absPath))
				if err != nil {
					ErrorAndExit(err.Error())
				} else {
					if len(b.Records) == 0 {
						ErrorAndExit(fmt.Sprintf("No bundle definition named %q", filepath.Base(absPath)))
					} else {
						bid = b.Records[0]["Id"].(string)
					}
				}
			} else {
				bid = manifest.Id
			}

			err = force.DeleteToolingRecord("AuraDefinitionBundle", bid)
			if err != nil {
				ErrorAndExit(err.Error())
			}
			// Now walk the bundle and remove all the atrifacts
			filepath.Walk(absPath, func(path string, inf os.FileInfo, err error) error {
				os.Remove(path)
				return nil
			})
			os.Remove(absPath)
			fmt.Println("Bundle ", filepath.Base(absPath), " deleted.")
			return
		}

		for key := range manifest.Files {
			mfile := manifest.Files[key].FileName
			cfile := absPath
			if !filepath.IsAbs(mfile) {
				cfile = filepath.Base(cfile)
			}
			if isBundle {
				if !filepath.IsAbs(mfile) {
					cfile = filepath.Join(absPath, mfile)
				} else {
					cfile = mfile
					deleteAuraDefinition(manifest, key)
				}
			} else {
				if mfile == cfile {
					deleteAuraDefinition(manifest, key)
					return
				}
			}
		}
		if isBundle {
			// Need to remove the bundle using the id in the manifest
			deleteAuraDefinitionBundle(manifest)
		}
	}
}
func deleteAuraDefinitionBundle(manifest BundleManifest) {
	force, err := ActiveForce()
	err = force.DeleteToolingRecord("AuraDefinitionBundle", manifest.Id)
	if err != nil {
		ErrorAndExit(err.Error())
	}
	os.Remove(filepath.Join(resourcepaths[0], ".manifest"))
	os.Remove(resourcepaths[0])
}

func deleteAuraDefinition(manifest BundleManifest, key int) {
	force, err := ActiveForce()
	err = force.DeleteToolingRecord("AuraDefinition", manifest.Files[key].ComponentId)
	if err != nil {
		ErrorAndExit(err.Error())
	}
	fname := manifest.Files[key].FileName
	os.Remove(fname)
	manifest.Files = append(manifest.Files[:key], manifest.Files[key+1:]...)
	bmBody, _ := json.Marshal(manifest)
	ioutil.WriteFile(filepath.Join(filepath.Dir(fname), ".manifest"), bmBody, 0644)
}
<commit_msg>Remove Incorrect Option From aura push Help<commit_after>package command

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	. "github.com/ForceCLI/force/error"
	. "github.com/ForceCLI/force/lib"
)

// Brief comment to fire commit

var cmdAura = &Command{
	Usage: "aura",
	Short: "force aura push -f <filepath>",
	Long: `
	The aura command needs context to work. If you execute "aura get"
	it will create a folder structure that provides the context for
	aura components on disk.

	The aura components will be created in "metadata/aurabundles/<componentname>"
	relative to the current working directory and a .manifest file will be
	created that associates components and their artifacts with their ids in
	the database.

	To create a new component (application, evt or component), create a new
	folder under "aura". Then create a new file in your new folder. You
	must follow a naming convention for your files to enable proper definition
	of the component type.

	Naming convention <compnentName><artifact type>.<file type extension>
	Examples: 	metadata
					aura
						MyApp
							MyAppApplication.app
							MyAppStyle.css
						MyList
							MyComponent.cmp
							MyComponentHelper.js
							MyComponentStyle.css

	force aura push -f <fullFilePath>

	force aura create -t=<entity type> <entityName>

	force aura delete -f=<fullFilePath>

	force aura list

	`,
}

func init() {
	cmdAura.Run = runAura
	cmdAura.Flag.Var(&resourcepaths, "p", "fully qualified file name for entity")
	cmdAura.Flag.Var(&resourcepaths, "f", "fully qualified file name for entity")
	cmdAura.Flag.StringVar(&metadataType, "entitytype", "", "fully qualified file name for entity")
	cmdAura.Flag.StringVar(&auraentityname, "entityname", "", "fully qualified file name for entity")
	cmdAura.Flag.StringVar(&metadataType, "t", "", "fully qualified file name for entity")
	cmdAura.Flag.StringVar(&auraentityname, "n", "", "fully qualified file name for entity")
}

var (
	auraentityname string
	metadataType   string
)

func runAura(cmd *Command, args []string) {
	if err := cmd.Flag.Parse(args[0:]); err != nil {
		os.Exit(2)
	}

	force, _ := ActiveForce()

	subcommand := args[0]
	// Sublime hack - the way sublime passes parameters seems to
	// break the flag parsing by sending a single element array
	// for the args. ARGH!!!
	if strings.HasPrefix(subcommand, "delete ") || strings.HasPrefix(subcommand, "push ") {
		what := strings.Split(subcommand, " ")
		if err := cmd.Flag.Parse(what[1:]); err != nil {
			ErrorAndExit(err.Error())
		}
		subcommand = what[0]
	} else {
		if err := cmd.Flag.Parse(args[1:]); err != nil {
			ErrorAndExit(err.Error())
		}
	}

	switch strings.ToLower(subcommand) {
	case "create":
		/*if *auraentitytype == "" || *auraentityname == "" {
			fmt.Println("Must specify entity type and name")
			os.Exit(2)
		}*/
		ErrorAndExit("force aura create not yet implemented")

	case "delete":
		runDeleteAura()
	case "list":
		bundles, err := force.GetAuraBundlesList()
		if err != nil {
			ErrorAndExit(err.Error())
		}
		for _, bundle := range bundles.Records {
			fmt.Println(bundle["DeveloperName"])
		}
	case "push":
		//		absPath, _ := filepath.Abs(resourcepaths[0])
		runPushAura(cmd, resourcepaths)
	}
}

func runDeleteAura() {
	absPath, _ := filepath.Abs(resourcepaths[0])
	//resourcepaths = absPath

	if InAuraBundlesFolder(absPath) {
		info, err := os.Stat(absPath)
		if err != nil {
			ErrorAndExit(err.Error())
		}
		manifest, err := GetManifest(absPath)
		isBundle := false
		if info.IsDir() {
			force, _ := ActiveForce()
			manifest, err = GetManifest(filepath.Join(absPath, ".manifest"))
			bid := ""
			if err != nil { // Could not find a manifest, use bundle name
				// Try to look up the bundle by name
				b, err := force.GetAuraBundleByName(filepath.Base(absPath))
				if err != nil {
					ErrorAndExit(err.Error())
				} else {
					if len(b.Records) == 0 {
						ErrorAndExit(fmt.Sprintf("No bundle definition named %q", filepath.Base(absPath)))
					} else {
						bid = b.Records[0]["Id"].(string)
					}
				}
			} else {
				bid = manifest.Id
			}

			err = force.DeleteToolingRecord("AuraDefinitionBundle", bid)
			if err != nil {
				ErrorAndExit(err.Error())
			}
			// Now walk the bundle and remove all the atrifacts
			filepath.Walk(absPath, func(path string, inf os.FileInfo, err error) error {
				os.Remove(path)
				return nil
			})
			os.Remove(absPath)
			fmt.Println("Bundle ", filepath.Base(absPath), " deleted.")
			return
		}

		for key := range manifest.Files {
			mfile := manifest.Files[key].FileName
			cfile := absPath
			if !filepath.IsAbs(mfile) {
				cfile = filepath.Base(cfile)
			}
			if isBundle {
				if !filepath.IsAbs(mfile) {
					cfile = filepath.Join(absPath, mfile)
				} else {
					cfile = mfile
					deleteAuraDefinition(manifest, key)
				}
			} else {
				if mfile == cfile {
					deleteAuraDefinition(manifest, key)
					return
				}
			}
		}
		if isBundle {
			// Need to remove the bundle using the id in the manifest
			deleteAuraDefinitionBundle(manifest)
		}
	}
}
func deleteAuraDefinitionBundle(manifest BundleManifest) {
	force, err := ActiveForce()
	err = force.DeleteToolingRecord("AuraDefinitionBundle", manifest.Id)
	if err != nil {
		ErrorAndExit(err.Error())
	}
	os.Remove(filepath.Join(resourcepaths[0], ".manifest"))
	os.Remove(resourcepaths[0])
}

func deleteAuraDefinition(manifest BundleManifest, key int) {
	force, err := ActiveForce()
	err = force.DeleteToolingRecord("AuraDefinition", manifest.Files[key].ComponentId)
	if err != nil {
		ErrorAndExit(err.Error())
	}
	fname := manifest.Files[key].FileName
	os.Remove(fname)
	manifest.Files = append(manifest.Files[:key], manifest.Files[key+1:]...)
	bmBody, _ := json.Marshal(manifest)
	ioutil.WriteFile(filepath.Join(filepath.Dir(fname), ".manifest"), bmBody, 0644)
}
<|endoftext|>


<commit_before>package commands

import (
	"github.com/codegangsta/cli"
	"github.com/gemnasium/toolbelt/auth"
	"github.com/gemnasium/toolbelt/config"
)

func App() (*cli.App, error) {
	app := cli.NewApp()
	app.Name = "gemnasium"
	app.Usage = "Gemnasium toolbelt"
	app.Version = config.VERSION
	app.Author = "Gemnasium"
	app.Email = "support@gemnasium.com"
	app.Flags = []cli.Flag{
		cli.StringFlag{"token, t", "", "Your api token (available in your account page)"},
		cli.BoolFlag{"raw, r", "Raw format output"},
	}
	app.Before = func(c *cli.Context) error {
		config.RawFormat = c.Bool("raw")
		return nil
	}
	app.Commands = []cli.Command{
		{
			Name:  "auth",
			Usage: "Authentication",
			Subcommands: []cli.Command{
				{
					Name:   "login",
					Usage:  "Login",
					Action: Login,
				},
				{
					Name:   "logout",
					Usage:  "Logout",
					Action: Logout,
				},
			},
		},
		{
			Name:        "configure",
			Usage:       "Install configuration for an existing project",
			Description: "Will create a .gemnasium.yml file in the current directory. This file will be parse if present.\n   Warning: this command will overwrite existing .gemnasium.yml file.\n\n   Arguments: project_slug (the identifier of the project).",
			Action:      Configure,
		},
		{
			Name:      "projects",
			ShortName: "p",
			Usage:     "Manage current project",
			Before:    auth.AttemptLogin,
			Subcommands: []cli.Command{
				{
					Name:      "list",
					ShortName: "l",
					Usage:     "List projects on Gemnasium",
					Flags: []cli.Flag{
						cli.BoolFlag{"private, p", "Display only private projects"},
					},
					Action: ProjectsList,
				},
				{
					Name:      "show",
					ShortName: "s",
					Usage:     "Show projet detail",
					Action:    ProjectsShow,
				},
				{
					Name:      "update",
					ShortName: "u",
					Flags: []cli.Flag{
						cli.StringFlag{"name, n", "", "Project name"},
						cli.StringFlag{"desc, d", "", "A short description"},
						cli.BoolFlag{"monitored, m", "Whether the project is watched by the user. "},
					},
					Usage:  "Edit project details",
					Action: ProjectsUpdate,
				},
				{
					Name:      "create",
					ShortName: "c",
					Usage:     "Create a new project on Gemnasium",
					Action:    ProjectsCreate,
				},
				{
					Name:   "sync",
					Usage:  "Start project synchronization",
					Action: ProjectsSync,
				},
			},
		},
		{
			Name:      "dependencies",
			ShortName: "d",
			Usage:     "Dependencies",
			Before: func(ctx *cli.Context) error {
				auth.AttemptLogin(ctx)
				return nil
			},
			Subcommands: []cli.Command{
				{
					Name:      "list",
					ShortName: "l",
					Usage:     "List the first level dependencies of the requested project. Usage: gemnasium deps list [project_slug]",
					Action:    DependenciesList,
				},
			},
		},
		{
			Name:      "dependency_files",
			ShortName: "df",
			Usage:     "Dependency files",
			Before: func(ctx *cli.Context) error {
				auth.AttemptLogin(ctx)
				return nil
			},
			Subcommands: []cli.Command{
				{
					Name:      "list",
					ShortName: "l",
					Usage:     "List dependency files for project",
					Action:    DependencyFilesList,
				},
				{
					Name:      "push",
					ShortName: "p",
					Usage:     "Push dependency files on Gemnasium",
					Flags: []cli.Flag{
						cli.StringFlag{"files, f", "", "list of files to send, separated with a comma."},
					},
					Description: "Send files to Gemnasium. If --files is not set, all dependency files supported by Gemnasium found in the current path will be sent to Gemnasium API. You can ignore paths with GEMNASIUM_IGNORED_PATHS",
					Action:      DependenciesPush,
				},
			},
		},
		{
			Name:      "alerts",
			ShortName: "a",
			Usage:     "Dependency Alerts",
			Before: func(ctx *cli.Context) error {
				auth.AttemptLogin(ctx)
				return nil
			},
			Subcommands: []cli.Command{
				{
					Name:      "list",
					ShortName: "l",
					Usage:     "List the dependency alerts the given project is affected by",
					Action:    DependencyAlertsList,
				},
			},
		},
		{
			Name:      "eval",
			ShortName: "e",
			Usage:     "Live deps evaluation",
			Flags: []cli.Flag{
				cli.StringFlag{"files, f", "", "list of files to evaluate, separated with a comma."},
			},
			Action: LiveEvaluation,
		},
		{
			Name:      "autoupdate",
			ShortName: "au",
			Usage:     "Auto-update will test updates in your project, and notify Gemnasium of the result",
			Flags: []cli.Flag{
				cli.StringFlag{"project, p", "", "Project slug (identifier on Gemnasium)"},
			},
			Description: `Auto-Update will fetch update sets from Gemnasium and run your test suite against them.
   The test suite can be passed as arguments, or through the env var GEMNASIUM_TESTSUITE.

   Arguments:

   - [test suite commands] (string): Commands to run your test suite (ex: "./test.sh")

   Env Vars:

   - GEMNASIUM_PROJECT_SLUG: override --project flag and project_slug in .gemnasium.yyml.
   - GEMNASIUM_TESTSUITE: will be run for each iteration over update sets. This is typically your test suite script.
   - GEMNASIUM_BUNDLE_INSTALL_CMD: [Ruby Only] during each iteration, the new bundle will be installed. Default: "bundle install"
   - GEMNASIUM_BUNDLE_UPDATE_CMD: [Ruby Only] during each iteration, some gems might be updated. This command will be used. Default: "bundle update"
   - BRANCH: Current branch can be specified with this var, if the git command fails to run (git rev-parse --abbrev-ref HEAD).
   - REVISION: Current revision can be specified with this var, if the git command fails to run (git rev-parse --abbrev-ref HEAD)

   Examples:

   - GEMNASIUM_TESTSUITE="bundle exec rake" GEMNASIUM_PROJECT_SLUG=a907c0f9b8e0b89f23f0042d76ae0358 gemnasium autoupdate
   - cat script.sh | gemnasium autoupdate -p=your_project_slug
   - gemnasium autoupdate my_project_slug bundle exec rake
  `,
			Action: AutoUpdate,
		},
		{
			Name:   "env",
			Usage:  "Display ENV vars used by gemnasium",
			Action: DisplayEnvVars,
		},
	}
	return app, nil
}
<commit_msg>Fix flags initializers<commit_after>package commands

import (
	"github.com/codegangsta/cli"
	"github.com/gemnasium/toolbelt/auth"
	"github.com/gemnasium/toolbelt/config"
)

func App() (*cli.App, error) {
	app := cli.NewApp()
	app.Name = "gemnasium"
	app.Usage = "Gemnasium toolbelt"
	app.Version = config.VERSION
	app.Author = "Gemnasium"
	app.Email = "support@gemnasium.com"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "token, t",
			Usage: "Your api token (available in your account page)",
		},
		cli.BoolFlag{
			Name:  "raw, r",
			Usage: "Raw format output",
		},
	}
	app.Before = func(c *cli.Context) error {
		config.RawFormat = c.Bool("raw")
		return nil
	}
	app.Commands = []cli.Command{
		{
			Name:  "auth",
			Usage: "Authentication",
			Subcommands: []cli.Command{
				{
					Name:   "login",
					Usage:  "Login",
					Action: Login,
				},
				{
					Name:   "logout",
					Usage:  "Logout",
					Action: Logout,
				},
			},
		},
		{
			Name:        "configure",
			Usage:       "Install configuration for an existing project",
			Description: "Will create a .gemnasium.yml file in the current directory. This file will be parse if present.\n   Warning: this command will overwrite existing .gemnasium.yml file.\n\n   Arguments: project_slug (the identifier of the project).",
			Action:      Configure,
		},
		{
			Name:      "projects",
			ShortName: "p",
			Usage:     "Manage current project",
			Before:    auth.AttemptLogin,
			Subcommands: []cli.Command{
				{
					Name:      "list",
					ShortName: "l",
					Usage:     "List projects on Gemnasium",
					Flags: []cli.Flag{
						cli.BoolFlag{
							Name:  "private, p",
							Usage: "Display only private projects",
						},
					},
					Action: ProjectsList,
				},
				{
					Name:      "show",
					ShortName: "s",
					Usage:     "Show projet detail",
					Action:    ProjectsShow,
				},
				{
					Name:      "update",
					ShortName: "u",
					Flags: []cli.Flag{
						cli.StringFlag{
							Name:  "name, n",
							Usage: "Project name",
						},
						cli.StringFlag{
							Name:  "desc, d",
							Usage: "A short description",
						},
						cli.BoolFlag{
							Name:  "monitored, m",
							Usage: "Whether the project is watched by the user.",
						},
					},
					Usage:  "Edit project details",
					Action: ProjectsUpdate,
				},
				{
					Name:      "create",
					ShortName: "c",
					Usage:     "Create a new project on Gemnasium",
					Action:    ProjectsCreate,
				},
				{
					Name:   "sync",
					Usage:  "Start project synchronization",
					Action: ProjectsSync,
				},
			},
		},
		{
			Name:      "dependencies",
			ShortName: "d",
			Usage:     "Dependencies",
			Before: func(ctx *cli.Context) error {
				auth.AttemptLogin(ctx)
				return nil
			},
			Subcommands: []cli.Command{
				{
					Name:      "list",
					ShortName: "l",
					Usage:     "List the first level dependencies of the requested project. Usage: gemnasium deps list [project_slug]",
					Action:    DependenciesList,
				},
			},
		},
		{
			Name:      "dependency_files",
			ShortName: "df",
			Usage:     "Dependency files",
			Before: func(ctx *cli.Context) error {
				auth.AttemptLogin(ctx)
				return nil
			},
			Subcommands: []cli.Command{
				{
					Name:      "list",
					ShortName: "l",
					Usage:     "List dependency files for project",
					Action:    DependencyFilesList,
				},
				{
					Name:      "push",
					ShortName: "p",
					Usage:     "Push dependency files on Gemnasium",
					Flags: []cli.Flag{
						cli.StringFlag{
							Name:  "files, f",
							Usage: "list of files to send, separated with a comma.",
						},
					},
					Description: "Send files to Gemnasium. If --files is not set, all dependency files supported by Gemnasium found in the current path will be sent to Gemnasium API. You can ignore paths with GEMNASIUM_IGNORED_PATHS",
					Action:      DependenciesPush,
				},
			},
		},
		{
			Name:      "alerts",
			ShortName: "a",
			Usage:     "Dependency Alerts",
			Before: func(ctx *cli.Context) error {
				auth.AttemptLogin(ctx)
				return nil
			},
			Subcommands: []cli.Command{
				{
					Name:      "list",
					ShortName: "l",
					Usage:     "List the dependency alerts the given project is affected by",
					Action:    DependencyAlertsList,
				},
			},
		},
		{
			Name:      "eval",
			ShortName: "e",
			Usage:     "Live deps evaluation",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "files, f",
					Usage: "list of files to evaluate, separated with a comma.",
				},
			},
			Action: LiveEvaluation,
		},
		{
			Name:      "autoupdate",
			ShortName: "au",
			Usage:     "Auto-update will test updates in your project, and notify Gemnasium of the result",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "project, p",
					Usage: "Project slug (identifier on Gemnasium)",
				},
			},
			Description: `Auto-Update will fetch update sets from Gemnasium and run your test suite against them.
   The test suite can be passed as arguments, or through the env var GEMNASIUM_TESTSUITE.

   Arguments:

   - [test suite commands] (string): Commands to run your test suite (ex: "./test.sh")

   Env Vars:

   - GEMNASIUM_PROJECT_SLUG: override --project flag and project_slug in .gemnasium.yyml.
   - GEMNASIUM_TESTSUITE: will be run for each iteration over update sets. This is typically your test suite script.
   - GEMNASIUM_BUNDLE_INSTALL_CMD: [Ruby Only] during each iteration, the new bundle will be installed. Default: "bundle install"
   - GEMNASIUM_BUNDLE_UPDATE_CMD: [Ruby Only] during each iteration, some gems might be updated. This command will be used. Default: "bundle update"
   - BRANCH: Current branch can be specified with this var, if the git command fails to run (git rev-parse --abbrev-ref HEAD).
   - REVISION: Current revision can be specified with this var, if the git command fails to run (git rev-parse --abbrev-ref HEAD)

   Examples:

   - GEMNASIUM_TESTSUITE="bundle exec rake" GEMNASIUM_PROJECT_SLUG=a907c0f9b8e0b89f23f0042d76ae0358 gemnasium autoupdate
   - cat script.sh | gemnasium autoupdate -p=your_project_slug
   - gemnasium autoupdate my_project_slug bundle exec rake
  `,
			Action: AutoUpdate,
		},
		{
			Name:   "env",
			Usage:  "Display ENV vars used by gemnasium",
			Action: DisplayEnvVars,
		},
	}
	return app, nil
}
<|endoftext|>


<commit_before>package kintone

import "testing"

func TestDecodeRecordComments(t *testing.T) {
    j := []byte(`
{"comments":[{"id":"2","text":"ほげほげ","createdAt":"2016-11-07T19:53:32Z","creator":{"code":"xxx.tat","name":"さんぷる"},"mentions":[{"code":"wolf","type":"USER"}]},{"id":"1","text":"ふがふが","createdAt":"2016-11-07T19:53:27Z","creator":{"code":"xxx.tat","name":"さんぷる"},"mentions":[]}],"older":false,"newer":false}
`)

	rec, err := DecodeRecordComments(j)
	if err != nil {
		t.Fatal(err)
	}
	if len(rec) != 2 {
		t.Fatal("invalud record count!")
	}
	if rec[0].Id != "2" {
		t.Errorf("comment id mismatch. actual %v", rec[0].Id)
	}
	if rec[0].Text != "ほげほげ" {
		t.Errorf("comment text mismatch. actual %v", rec[0].Text)
	}

	if rec[0].CreatedAt != "2016-11-07T19:53:32Z" {
		t.Errorf("comment createdat mismatch. actual %v", rec[0].CreatedAt)
	}
	if rec[0].Creator.Code != "xxx.tat" {
		t.Errorf("comment creator mismatch. actual %v", rec[0].Creator.Code)
	}
	if rec[0].Mentions[0].Code != "wolf" {
		t.Errorf("comment mention-code mismatch. actual %v", rec[0].Mentions[0].Code)
	}
}
<commit_msg>Correct typo<commit_after>package kintone

import "testing"

func TestDecodeRecordComments(t *testing.T) {
	j := []byte(`
{"comments":[{"id":"2","text":"ほげほげ","createdAt":"2016-11-07T19:53:32Z","creator":{"code":"xxx.tat","name":"さんぷる"},"mentions":[{"code":"wolf","type":"USER"}]},{"id":"1","text":"ふがふが","createdAt":"2016-11-07T19:53:27Z","creator":{"code":"xxx.tat","name":"さんぷる"},"mentions":[]}],"older":false,"newer":false}
`)

	rec, err := DecodeRecordComments(j)
	if err != nil {
		t.Fatal(err)
	}
	if len(rec) != 2 {
		t.Fatal("invalud record count!")
	}
	if rec[0].Id != "2" {
		t.Errorf("comment id mismatch. actual %v", rec[0].Id)
	}
	if rec[0].Text != "ほげほげ" {
		t.Errorf("comment text mismatch. actual %v", rec[0].Text)
	}

	if rec[0].CreatedAt != "2016-11-07T19:53:32Z" {
		t.Errorf("comment createdat mismatch. actual %v", rec[0].CreatedAt)
	}
	if rec[0].Creator.Code != "xxx.tat" {
		t.Errorf("comment creator mismatch. actual %v", rec[0].Creator.Code)
	}
	if rec[0].Mentions[0].Code != "wolf" {
		t.Errorf("comment mention-code mismatch. actual %v", rec[0].Mentions[0].Code)
	}
}
<|endoftext|>


<commit_before>package registry

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/docker/distribution/registry/client/transport"
	registrytypes "github.com/docker/engine-api/types/registry"
)

// V1Endpoint stores basic information about a V1 registry endpoint.
type V1Endpoint struct {
	client   *http.Client
	URL      *url.URL
	IsSecure bool
}

// NewV1Endpoint parses the given address to return a registry endpoint.  v can be used to
// specify a specific endpoint version
func NewV1Endpoint(index *registrytypes.IndexInfo, userAgent string, metaHeaders http.Header) (*V1Endpoint, error) {
	tlsConfig, err := newTLSConfig(index.Name, index.Secure)
	if err != nil {
		return nil, err
	}

	endpoint, err := newV1EndpointFromStr(GetAuthConfigKey(index), tlsConfig, userAgent, metaHeaders)
	if err != nil {
		return nil, err
	}

	if err := validateEndpoint(endpoint); err != nil {
		return nil, err
	}

	return endpoint, nil
}

func validateEndpoint(endpoint *V1Endpoint) error {
	logrus.Debugf("pinging registry endpoint %s", endpoint)

	// Try HTTPS ping to registry
	endpoint.URL.Scheme = "https"
	if _, err := endpoint.Ping(); err != nil {
		if endpoint.IsSecure {
			// If registry is secure and HTTPS failed, show user the error and tell them about `--insecure-registry`
			// in case that's what they need. DO NOT accept unknown CA certificates, and DO NOT fallback to HTTP.
			return fmt.Errorf("invalid registry endpoint %s: %v. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry %s` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/%s/ca.crt", endpoint, err, endpoint.URL.Host, endpoint.URL.Host)
		}

		// If registry is insecure and HTTPS failed, fallback to HTTP.
		logrus.Debugf("Error from registry %q marked as insecure: %v. Insecurely falling back to HTTP", endpoint, err)
		endpoint.URL.Scheme = "http"

		var err2 error
		if _, err2 = endpoint.Ping(); err2 == nil {
			return nil
		}

		return fmt.Errorf("invalid registry endpoint %q. HTTPS attempt: %v. HTTP attempt: %v", endpoint, err, err2)
	}

	return nil
}

func newV1Endpoint(address url.URL, tlsConfig *tls.Config, userAgent string, metaHeaders http.Header) (*V1Endpoint, error) {
	endpoint := &V1Endpoint{
		IsSecure: (tlsConfig == nil || !tlsConfig.InsecureSkipVerify),
		URL:      new(url.URL),
	}

	*endpoint.URL = address

	// TODO(tiborvass): make sure a ConnectTimeout transport is used
	tr := NewTransport(tlsConfig)
	endpoint.client = HTTPClient(transport.NewTransport(tr, DockerHeaders(userAgent, metaHeaders)...))
	return endpoint, nil
}

// trimV1Address trims the version off the address and returns the
// trimmed address or an error if there is a non-V1 version.
func trimV1Address(address string) (string, error) {
	var (
		chunks        []string
		apiVersionStr string
	)

	if strings.HasSuffix(address, "/") {
		address = address[:len(address)-1]
	}

	chunks = strings.Split(address, "/")
	apiVersionStr = chunks[len(chunks)-1]
	if apiVersionStr == "v1" {
		return strings.Join(chunks[:len(chunks)-1], "/"), nil
	}

	for k, v := range apiVersions {
		if k != APIVersion1 && apiVersionStr == v {
			return "", fmt.Errorf("unsupported V1 version path %s", apiVersionStr)
		}
	}

	return address, nil
}

func newV1EndpointFromStr(address string, tlsConfig *tls.Config, userAgent string, metaHeaders http.Header) (*V1Endpoint, error) {
	if !strings.HasPrefix(address, "http://") && !strings.HasPrefix(address, "https://") {
		address = "https://" + address
	}

	address, err := trimV1Address(address)
	if err != nil {
		return nil, err
	}

	uri, err := url.Parse(address)
	if err != nil {
		return nil, err
	}

	endpoint, err := newV1Endpoint(*uri, tlsConfig, userAgent, metaHeaders)
	if err != nil {
		return nil, err
	}

	return endpoint, nil
}

// Get the formatted URL for the root of this registry Endpoint
func (e *V1Endpoint) String() string {
	return e.URL.String() + "/v1/"
}

// Path returns a formatted string for the URL
// of this endpoint with the given path appended.
func (e *V1Endpoint) Path(path string) string {
	return e.URL.String() + "/v1/" + path
}

// Ping returns a PingResult which indicates whether the registry is standalone or not.
func (e *V1Endpoint) Ping() (PingResult, error) {
	logrus.Debugf("attempting v1 ping for registry endpoint %s", e)

	if e.String() == IndexServer {
		// Skip the check, we know this one is valid
		// (and we never want to fallback to http in case of error)
		return PingResult{Standalone: false}, nil
	}

	req, err := http.NewRequest("GET", e.Path("_ping"), nil)
	if err != nil {
		return PingResult{Standalone: false}, err
	}

	resp, err := e.client.Do(req)
	if err != nil {
		return PingResult{Standalone: false}, err
	}

	defer resp.Body.Close()

	jsonString, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return PingResult{Standalone: false}, fmt.Errorf("error while reading the http response: %s", err)
	}

	// If the header is absent, we assume true for compatibility with earlier
	// versions of the registry. default to true
	info := PingResult{
		Standalone: true,
	}
	if err := json.Unmarshal(jsonString, &info); err != nil {
		logrus.Debugf("Error unmarshalling the _ping PingResult: %s", err)
		// don't stop here. Just assume sane defaults
	}
	if hdr := resp.Header.Get("X-Docker-Registry-Version"); hdr != "" {
		logrus.Debugf("Registry version header: '%s'", hdr)
		info.Version = hdr
	}
	logrus.Debugf("PingResult.Version: %q", info.Version)

	standalone := resp.Header.Get("X-Docker-Registry-Standalone")
	logrus.Debugf("Registry standalone header: '%s'", standalone)
	// Accepted values are "true" (case-insensitive) and "1".
	if strings.EqualFold(standalone, "true") || standalone == "1" {
		info.Standalone = true
	} else if len(standalone) > 0 {
		// there is a header set, and it is not "true" or "1", so assume fails
		info.Standalone = false
	}
	logrus.Debugf("PingResult.Standalone: %t", info.Standalone)
	return info, nil
}
<commit_msg>registry: endpoint_v1: fix outdated comment<commit_after>package registry

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/docker/distribution/registry/client/transport"
	registrytypes "github.com/docker/engine-api/types/registry"
)

// V1Endpoint stores basic information about a V1 registry endpoint.
type V1Endpoint struct {
	client   *http.Client
	URL      *url.URL
	IsSecure bool
}

// NewV1Endpoint parses the given address to return a registry endpoint.
func NewV1Endpoint(index *registrytypes.IndexInfo, userAgent string, metaHeaders http.Header) (*V1Endpoint, error) {
	tlsConfig, err := newTLSConfig(index.Name, index.Secure)
	if err != nil {
		return nil, err
	}

	endpoint, err := newV1EndpointFromStr(GetAuthConfigKey(index), tlsConfig, userAgent, metaHeaders)
	if err != nil {
		return nil, err
	}

	if err := validateEndpoint(endpoint); err != nil {
		return nil, err
	}

	return endpoint, nil
}

func validateEndpoint(endpoint *V1Endpoint) error {
	logrus.Debugf("pinging registry endpoint %s", endpoint)

	// Try HTTPS ping to registry
	endpoint.URL.Scheme = "https"
	if _, err := endpoint.Ping(); err != nil {
		if endpoint.IsSecure {
			// If registry is secure and HTTPS failed, show user the error and tell them about `--insecure-registry`
			// in case that's what they need. DO NOT accept unknown CA certificates, and DO NOT fallback to HTTP.
			return fmt.Errorf("invalid registry endpoint %s: %v. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry %s` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/%s/ca.crt", endpoint, err, endpoint.URL.Host, endpoint.URL.Host)
		}

		// If registry is insecure and HTTPS failed, fallback to HTTP.
		logrus.Debugf("Error from registry %q marked as insecure: %v. Insecurely falling back to HTTP", endpoint, err)
		endpoint.URL.Scheme = "http"

		var err2 error
		if _, err2 = endpoint.Ping(); err2 == nil {
			return nil
		}

		return fmt.Errorf("invalid registry endpoint %q. HTTPS attempt: %v. HTTP attempt: %v", endpoint, err, err2)
	}

	return nil
}

func newV1Endpoint(address url.URL, tlsConfig *tls.Config, userAgent string, metaHeaders http.Header) (*V1Endpoint, error) {
	endpoint := &V1Endpoint{
		IsSecure: (tlsConfig == nil || !tlsConfig.InsecureSkipVerify),
		URL:      new(url.URL),
	}

	*endpoint.URL = address

	// TODO(tiborvass): make sure a ConnectTimeout transport is used
	tr := NewTransport(tlsConfig)
	endpoint.client = HTTPClient(transport.NewTransport(tr, DockerHeaders(userAgent, metaHeaders)...))
	return endpoint, nil
}

// trimV1Address trims the version off the address and returns the
// trimmed address or an error if there is a non-V1 version.
func trimV1Address(address string) (string, error) {
	var (
		chunks        []string
		apiVersionStr string
	)

	if strings.HasSuffix(address, "/") {
		address = address[:len(address)-1]
	}

	chunks = strings.Split(address, "/")
	apiVersionStr = chunks[len(chunks)-1]
	if apiVersionStr == "v1" {
		return strings.Join(chunks[:len(chunks)-1], "/"), nil
	}

	for k, v := range apiVersions {
		if k != APIVersion1 && apiVersionStr == v {
			return "", fmt.Errorf("unsupported V1 version path %s", apiVersionStr)
		}
	}

	return address, nil
}

func newV1EndpointFromStr(address string, tlsConfig *tls.Config, userAgent string, metaHeaders http.Header) (*V1Endpoint, error) {
	if !strings.HasPrefix(address, "http://") && !strings.HasPrefix(address, "https://") {
		address = "https://" + address
	}

	address, err := trimV1Address(address)
	if err != nil {
		return nil, err
	}

	uri, err := url.Parse(address)
	if err != nil {
		return nil, err
	}

	endpoint, err := newV1Endpoint(*uri, tlsConfig, userAgent, metaHeaders)
	if err != nil {
		return nil, err
	}

	return endpoint, nil
}

// Get the formatted URL for the root of this registry Endpoint
func (e *V1Endpoint) String() string {
	return e.URL.String() + "/v1/"
}

// Path returns a formatted string for the URL
// of this endpoint with the given path appended.
func (e *V1Endpoint) Path(path string) string {
	return e.URL.String() + "/v1/" + path
}

// Ping returns a PingResult which indicates whether the registry is standalone or not.
func (e *V1Endpoint) Ping() (PingResult, error) {
	logrus.Debugf("attempting v1 ping for registry endpoint %s", e)

	if e.String() == IndexServer {
		// Skip the check, we know this one is valid
		// (and we never want to fallback to http in case of error)
		return PingResult{Standalone: false}, nil
	}

	req, err := http.NewRequest("GET", e.Path("_ping"), nil)
	if err != nil {
		return PingResult{Standalone: false}, err
	}

	resp, err := e.client.Do(req)
	if err != nil {
		return PingResult{Standalone: false}, err
	}

	defer resp.Body.Close()

	jsonString, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return PingResult{Standalone: false}, fmt.Errorf("error while reading the http response: %s", err)
	}

	// If the header is absent, we assume true for compatibility with earlier
	// versions of the registry. default to true
	info := PingResult{
		Standalone: true,
	}
	if err := json.Unmarshal(jsonString, &info); err != nil {
		logrus.Debugf("Error unmarshalling the _ping PingResult: %s", err)
		// don't stop here. Just assume sane defaults
	}
	if hdr := resp.Header.Get("X-Docker-Registry-Version"); hdr != "" {
		logrus.Debugf("Registry version header: '%s'", hdr)
		info.Version = hdr
	}
	logrus.Debugf("PingResult.Version: %q", info.Version)

	standalone := resp.Header.Get("X-Docker-Registry-Standalone")
	logrus.Debugf("Registry standalone header: '%s'", standalone)
	// Accepted values are "true" (case-insensitive) and "1".
	if strings.EqualFold(standalone, "true") || standalone == "1" {
		info.Standalone = true
	} else if len(standalone) > 0 {
		// there is a header set, and it is not "true" or "1", so assume fails
		info.Standalone = false
	}
	logrus.Debugf("PingResult.Standalone: %t", info.Standalone)
	return info, nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/BurntSushi/toml"
	"log"
	"os/user"
)

func getCfgPath() string {
	usr, err := user.Current()
	if err != nil {
		log.Fatal(err)
	}
	return usr.HomeDir + "/.2fa.toml"
}

func getCfg() *config {
	var cfg config
	path := getCfgPath()
	if _, err := toml.DecodeFile(path, &cfg); err != nil {
		log.Fatalln(err)
	}
	return &cfg
}
<commit_msg>Update config.go<commit_after>package main

import (
	"github.com/BurntSushi/toml"
	"log"
	"os/user"
)

func getCfgPath() string {
	usr, err := user.Current()
	if err != nil {
		log.Fatal(err)
	}
	return usr.HomeDir + "/.2fa.toml"
}

func getCfg() *config {
	var cfg config
	path := getCfgPath()
	if _, err := toml.DecodeFile(path, &cfg); err != nil {
		log.Fatal(err)
	}
	return &cfg
}
<|endoftext|>


<commit_before>package main

// Unpack a JPEG file one segment at a time and repackage into a new
// JPEG file.  It can process files using the Multi-Picture Format
// extension to contain multiple images.

import (
	"fmt"
	jseg "github.com/garyhouston/jpegsegs"
	tiff "github.com/garyhouston/tiff66"
	"io"
	"log"
	"os"
)

// Serialize a MPF TIFF tree into a new APP2 segment.
func putMPF(mpfTree *tiff.IFDNode) ([]byte, error) {
	size := jseg.MPFHeaderSize + tiff.HeaderSize + mpfTree.TreeSize()
	newbuf := make([]byte, size)
	next := jseg.PutMPFHeader(newbuf)
	if _, err := jseg.PutMPFTree(newbuf[next:], mpfTree); err != nil {
		return nil, err
	}
	return newbuf, nil
}

// Copy a single image. If a MPF segment is found in APP2, return a
// MPF TIFF tree, the MPF image offsets in the input file, and the
// position where the MPF segment was written in the output file.
func copyImage(writer io.WriteSeeker, reader io.ReadSeeker, mpfSpace tiff.TagSpace) (*tiff.IFDNode, []uint32, uint32, error) {
	scanner, err := jseg.NewScanner(reader)
	if err != nil {
		return nil, nil, 0, err
	}
	dumper, err := jseg.NewDumper(writer)
	if err != nil {
		return nil, nil, 0, err
	}
	var mpfTree *tiff.IFDNode
	var offsets []uint32
	var mpfWritePos uint32
	for {
		marker, buf, err := scanner.Scan()
		if err != nil {
			return nil, nil, 0, err
		}
		if marker == jseg.APP0+2 {
			isMPF, next := jseg.GetMPFHeader(buf)
			if isMPF {
				// Copy buf so that it can be used outside this loop via pointers in the TIFF tree.
				savebuf := make([]byte, len(buf)-jseg.MPFHeaderSize)
				copy(savebuf, buf[next:])
				mpfTree, err = jseg.GetMPFTree(savebuf, mpfSpace)
				if err != nil {
					return nil, nil, 0, err
				}
				mpfTree.Fix()
				if mpfTree.Space == tiff.MPFIndexSpace {
					// MPF offsets are relative to
					// the start of the MPF
					// header, which is 4 bytes
					// past the start of buf.  The
					// current position of the
					// reader is one byte past the
					// data read into buf.
					pos, err := reader.Seek(0, io.SeekCurrent)
					if err != nil {
						return nil, nil, 0, err
					}
					mpfOffset := uint32(pos) - uint32(len(buf)-4)
					offsets, err = jseg.MPFImageOffsets(mpfTree, mpfOffset)
					if err != nil {
						return nil, nil, 0, err
					}
				}
				buf, err = putMPF(mpfTree)
				if err != nil {
					return nil, nil, 0, err
				}
				pos, err := writer.Seek(0, io.SeekCurrent)
				if err != nil {
					return nil, nil, 0, err
				}
				mpfWritePos = uint32(pos)
			}
		}
		if err := dumper.Dump(marker, buf); err != nil {
			return nil, nil, 0, err
		}
		if marker == jseg.EOI {
			break
		}
	}
	return mpfTree, offsets, mpfWritePos, nil
}

// Copy additional images specified with MPF.
func copyMPFImages(writer io.WriteSeeker, reader io.ReadSeeker, offsets []uint32) ([]uint32, error) {
	count := uint32(len(offsets))
	newOffsets := make([]uint32, len(offsets))
	for i := uint32(0); i < count; i++ {
		if offsets[i] > 0 {
			if _, err := reader.Seek(int64(offsets[i]), io.SeekStart); err != nil {
				return nil, err
			}
			pos, err := writer.Seek(0, io.SeekCurrent)
			if err != nil {
				return nil, err
			}
			newOffsets[i] = uint32(pos)
			if _, _, _, err := copyImage(writer, reader, tiff.MPFAttributeSpace); err != nil {
				return nil, err
			}
			pos, err = writer.Seek(0, io.SeekCurrent)
			if err != nil {
				return nil, err
			}
		}
	}
	return newOffsets, nil
}

// Modify a MPF TIFF tree with new image offsets and sizes, then overwrite the
// MPF data in the output stream.
func rewriteMPF(writer io.WriteSeeker, mpfTree *tiff.IFDNode, mpfWritePos uint32, offsets, lengths []uint32) error {
	order := mpfTree.Order
	for _, f := range mpfTree.Fields {
		if f.Tag == jseg.MPFEntry {
			for i := 0; i < len(offsets); i++ {
				var offset uint32
				if offsets[i] > 0 {
					// MPF offsets are relative to
					// the byte after the MPF
					// header, i.e., 8 bytes into
					// the MPF APP2 block.
					offset = offsets[i] - mpfWritePos - 8
				}
				f.PutLong(lengths[i], uint32(i*4+1), order)
				f.PutLong(offset, uint32(i*4+2), order)
				// too far in by 3 bytes ?
			}
		}
	}
	newbuf, err := putMPF(mpfTree)
	if err != nil {
		return err
	}
	if _, err := writer.Seek(int64(mpfWritePos), io.SeekStart); err != nil {
		return err
	}
	if err := jseg.WriteMarker(writer, jseg.APP0+2); err != nil {
		return err
	}
	if err := jseg.WriteData(writer, newbuf); err != nil {
		return err
	}
	return nil
}

func main() {
	if len(os.Args) != 3 {
		fmt.Printf("Usage: %s infile outfile\n", os.Args[0])
		return
	}
	reader, err := os.Open(os.Args[1])
	if err != nil {
		log.Fatal(err)
	}
	defer reader.Close()
	writer, err := os.Create(os.Args[2])
	if err != nil {
		log.Fatal(err)
	}
	defer writer.Close()
	mpfTree, imageOffsets, mpfWritePos, err := copyImage(writer, reader, tiff.MPFIndexSpace)
	if err != nil {
		log.Fatal(err)
	}
	if mpfTree != nil && mpfTree.Space == tiff.MPFIndexSpace {
		newOffsets, err := copyMPFImages(writer, reader, imageOffsets)
		if err != nil {
			log.Fatal(err)
		}
		numImages := len(newOffsets)
		newLengths := make([]uint32, numImages)
		for i := 0; i < numImages-1; i++ {
			newLengths[i] = newOffsets[i+1] - newOffsets[i]
		}
		lastpos, err := writer.Seek(0, io.SeekCurrent)
		if err != nil {
			log.Fatal(err)
		}
		newLengths[numImages-1] = uint32(lastpos) - newOffsets[numImages-1]
		if err = rewriteMPF(writer, mpfTree, mpfWritePos, newOffsets, newLengths); err != nil {
			log.Fatal(err)
		}

	}
}
<commit_msg>Simplify using MakeMPFSegment.<commit_after>package main

// Unpack a JPEG file one segment at a time and repackage into a new
// JPEG file.  It can process files using the Multi-Picture Format
// extension to contain multiple images.

import (
	"fmt"
	jseg "github.com/garyhouston/jpegsegs"
	tiff "github.com/garyhouston/tiff66"
	"io"
	"log"
	"os"
)

// Copy a single image. If a MPF segment is found in APP2, return a
// MPF TIFF tree, the MPF image offsets in the input file, and the
// position where the MPF segment was written in the output file.
func copyImage(writer io.WriteSeeker, reader io.ReadSeeker, mpfSpace tiff.TagSpace) (*tiff.IFDNode, []uint32, uint32, error) {
	scanner, err := jseg.NewScanner(reader)
	if err != nil {
		return nil, nil, 0, err
	}
	dumper, err := jseg.NewDumper(writer)
	if err != nil {
		return nil, nil, 0, err
	}
	var mpfTree *tiff.IFDNode
	var offsets []uint32
	var mpfWritePos uint32
	for {
		marker, buf, err := scanner.Scan()
		if err != nil {
			return nil, nil, 0, err
		}
		if marker == jseg.APP0+2 {
			isMPF, next := jseg.GetMPFHeader(buf)
			if isMPF {
				// Copy buf so that it can be used outside this loop via pointers in the TIFF tree.
				savebuf := make([]byte, len(buf)-jseg.MPFHeaderSize)
				copy(savebuf, buf[next:])
				mpfTree, err = jseg.GetMPFTree(savebuf, mpfSpace)
				if err != nil {
					return nil, nil, 0, err
				}
				mpfTree.Fix()
				if mpfTree.Space == tiff.MPFIndexSpace {
					// MPF offsets are relative to
					// the start of the MPF
					// header, which is 4 bytes
					// past the start of buf.  The
					// current position of the
					// reader is one byte past the
					// data read into buf.
					pos, err := reader.Seek(0, io.SeekCurrent)
					if err != nil {
						return nil, nil, 0, err
					}
					mpfOffset := uint32(pos) - uint32(len(buf)-4)
					offsets, err = jseg.MPFImageOffsets(mpfTree, mpfOffset)
					if err != nil {
						return nil, nil, 0, err
					}
				}
				buf, err = jseg.MakeMPFSegment(mpfTree)
				if err != nil {
					return nil, nil, 0, err
				}
				pos, err := writer.Seek(0, io.SeekCurrent)
				if err != nil {
					return nil, nil, 0, err
				}
				mpfWritePos = uint32(pos)
			}
		}
		if err := dumper.Dump(marker, buf); err != nil {
			return nil, nil, 0, err
		}
		if marker == jseg.EOI {
			break
		}
	}
	return mpfTree, offsets, mpfWritePos, nil
}

// Copy additional images specified with MPF.
func copyMPFImages(writer io.WriteSeeker, reader io.ReadSeeker, offsets []uint32) ([]uint32, error) {
	count := uint32(len(offsets))
	newOffsets := make([]uint32, len(offsets))
	for i := uint32(0); i < count; i++ {
		if offsets[i] > 0 {
			if _, err := reader.Seek(int64(offsets[i]), io.SeekStart); err != nil {
				return nil, err
			}
			pos, err := writer.Seek(0, io.SeekCurrent)
			if err != nil {
				return nil, err
			}
			newOffsets[i] = uint32(pos)
			if _, _, _, err := copyImage(writer, reader, tiff.MPFAttributeSpace); err != nil {
				return nil, err
			}
			pos, err = writer.Seek(0, io.SeekCurrent)
			if err != nil {
				return nil, err
			}
		}
	}
	return newOffsets, nil
}

// Modify a MPF TIFF tree with new image offsets and sizes, then overwrite the
// MPF data in the output stream.
func rewriteMPF(writer io.WriteSeeker, mpfTree *tiff.IFDNode, mpfWritePos uint32, offsets, lengths []uint32) error {
	order := mpfTree.Order
	for _, f := range mpfTree.Fields {
		if f.Tag == jseg.MPFEntry {
			for i := 0; i < len(offsets); i++ {
				var offset uint32
				if offsets[i] > 0 {
					// MPF offsets are relative to
					// the byte after the MPF
					// header, i.e., 8 bytes into
					// the MPF APP2 block.
					offset = offsets[i] - mpfWritePos - 8
				}
				f.PutLong(lengths[i], uint32(i*4+1), order)
				f.PutLong(offset, uint32(i*4+2), order)
				// too far in by 3 bytes ?
			}
		}
	}
	newbuf, err := jseg.MakeMPFSegment(mpfTree)
	if err != nil {
		return err
	}
	if _, err := writer.Seek(int64(mpfWritePos), io.SeekStart); err != nil {
		return err
	}
	if err := jseg.WriteMarker(writer, jseg.APP0+2); err != nil {
		return err
	}
	if err := jseg.WriteData(writer, newbuf); err != nil {
		return err
	}
	return nil
}

func main() {
	if len(os.Args) != 3 {
		fmt.Printf("Usage: %s infile outfile\n", os.Args[0])
		return
	}
	reader, err := os.Open(os.Args[1])
	if err != nil {
		log.Fatal(err)
	}
	defer reader.Close()
	writer, err := os.Create(os.Args[2])
	if err != nil {
		log.Fatal(err)
	}
	defer writer.Close()
	mpfTree, imageOffsets, mpfWritePos, err := copyImage(writer, reader, tiff.MPFIndexSpace)
	if err != nil {
		log.Fatal(err)
	}
	if mpfTree != nil && mpfTree.Space == tiff.MPFIndexSpace {
		newOffsets, err := copyMPFImages(writer, reader, imageOffsets)
		if err != nil {
			log.Fatal(err)
		}
		numImages := len(newOffsets)
		newLengths := make([]uint32, numImages)
		for i := 0; i < numImages-1; i++ {
			newLengths[i] = newOffsets[i+1] - newOffsets[i]
		}
		lastpos, err := writer.Seek(0, io.SeekCurrent)
		if err != nil {
			log.Fatal(err)
		}
		newLengths[numImages-1] = uint32(lastpos) - newOffsets[numImages-1]
		if err = rewriteMPF(writer, mpfTree, mpfWritePos, newOffsets, newLengths); err != nil {
			log.Fatal(err)
		}

	}
}
<|endoftext|>


<commit_before>package docker

import (
	"crypto/tls"
	"fmt"
	"os"
	"path/filepath"
	"runtime"

	"github.com/docker/docker/cliconfig"
	"github.com/docker/docker/opts"
	"github.com/docker/docker/pkg/homedir"
	"github.com/docker/docker/pkg/tlsconfig"
	dockerclient "github.com/fsouza/go-dockerclient"
)

const (
	// DefaultAPIVersion is the default docker API version set by libcompose
	DefaultAPIVersion   = "1.20"
	defaultTrustKeyFile = "key.json"
	defaultCaFile       = "ca.pem"
	defaultKeyFile      = "key.pem"
	defaultCertFile     = "cert.pem"
)

var (
	dockerCertPath = os.Getenv("DOCKER_CERT_PATH")
)

func init() {
	if dockerCertPath == "" {
		dockerCertPath = cliconfig.ConfigDir()
	}
}

// ClientOpts holds docker client options (host, tls, ..)
type ClientOpts struct {
	TLS        bool
	TLSVerify  bool
	TLSOptions tlsconfig.Options
	TrustKey   string
	Host       string
	APIVersion string
}

// CreateClient creates a docker client based on the specified options.
func CreateClient(c ClientOpts) (*dockerclient.Client, error) {
	if c.TLSOptions.CAFile == "" {
		c.TLSOptions.CAFile = filepath.Join(dockerCertPath, defaultCaFile)
	}
	if c.TLSOptions.CertFile == "" {
		c.TLSOptions.CertFile = filepath.Join(dockerCertPath, defaultCertFile)
	}
	if c.TLSOptions.KeyFile == "" {
		c.TLSOptions.KeyFile = filepath.Join(dockerCertPath, defaultKeyFile)
	}

	if c.Host == "" {
		defaultHost := os.Getenv("DOCKER_HOST")
		if defaultHost == "" {
			if runtime.GOOS != "windows" {
				// If we do not have a host, default to unix socket
				defaultHost = fmt.Sprintf("unix://%s", opts.DefaultUnixSocket)
			} else {
				// If we do not have a host, default to TCP socket on Windows
				defaultHost = fmt.Sprintf("tcp://%s:%d", opts.DefaultHTTPHost, opts.DefaultHTTPPort)
			}
		}
		defaultHost, err := opts.ValidateHost(defaultHost)
		if err != nil {
			return nil, err
		}
		c.Host = defaultHost
	}

	if c.TrustKey == "" {
		c.TrustKey = filepath.Join(homedir.Get(), ".docker", defaultTrustKeyFile)
	}

	if c.TLSVerify {
		c.TLS = true
	}

	if c.TLS {
		c.TLSOptions.InsecureSkipVerify = !c.TLSVerify
	}

	var tlsConfig *tls.Config

	if c.TLS {
		var err error
		tlsConfig, err = tlsconfig.Client(c.TLSOptions)
		if err != nil {
			return nil, err
		}
	}

	apiVersion := c.APIVersion
	if apiVersion == "" {
		apiVersion = DefaultAPIVersion
	}
	client, err := dockerclient.NewVersionedClient(c.Host, apiVersion)
	if err != nil {
		return nil, err
	}

	if tlsConfig != nil {
		client.TLSConfig = tlsConfig
	}
	return client, nil
}
<commit_msg>Fix TLS support<commit_after>package docker

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"

	"github.com/docker/docker/cliconfig"
	"github.com/docker/docker/opts"
	"github.com/docker/docker/pkg/homedir"
	"github.com/docker/docker/pkg/tlsconfig"
	dockerclient "github.com/fsouza/go-dockerclient"
)

const (
	// DefaultAPIVersion is the default docker API version set by libcompose
	DefaultAPIVersion   = "1.20"
	defaultTrustKeyFile = "key.json"
	defaultCaFile       = "ca.pem"
	defaultKeyFile      = "key.pem"
	defaultCertFile     = "cert.pem"
)

var (
	dockerCertPath = os.Getenv("DOCKER_CERT_PATH")
)

func init() {
	if dockerCertPath == "" {
		dockerCertPath = cliconfig.ConfigDir()
	}
}

// ClientOpts holds docker client options (host, tls, ..)
type ClientOpts struct {
	TLS        bool
	TLSVerify  bool
	TLSOptions tlsconfig.Options
	TrustKey   string
	Host       string
	APIVersion string
}

// CreateClient creates a docker client based on the specified options.
func CreateClient(c ClientOpts) (*dockerclient.Client, error) {
	if c.TLSOptions.CAFile == "" {
		c.TLSOptions.CAFile = filepath.Join(dockerCertPath, defaultCaFile)
	}
	if c.TLSOptions.CertFile == "" {
		c.TLSOptions.CertFile = filepath.Join(dockerCertPath, defaultCertFile)
	}
	if c.TLSOptions.KeyFile == "" {
		c.TLSOptions.KeyFile = filepath.Join(dockerCertPath, defaultKeyFile)
	}

	if c.Host == "" {
		defaultHost := os.Getenv("DOCKER_HOST")
		if defaultHost == "" {
			if runtime.GOOS != "windows" {
				// If we do not have a host, default to unix socket
				defaultHost = fmt.Sprintf("unix://%s", opts.DefaultUnixSocket)
			} else {
				// If we do not have a host, default to TCP socket on Windows
				defaultHost = fmt.Sprintf("tcp://%s:%d", opts.DefaultHTTPHost, opts.DefaultHTTPPort)
			}
		}
		defaultHost, err := opts.ValidateHost(defaultHost)
		if err != nil {
			return nil, err
		}
		c.Host = defaultHost
	}

	if c.TrustKey == "" {
		c.TrustKey = filepath.Join(homedir.Get(), ".docker", defaultTrustKeyFile)
	}

	if c.TLSVerify {
		c.TLS = true
	}

	if c.TLS {
		c.TLSOptions.InsecureSkipVerify = !c.TLSVerify
	}

	apiVersion := c.APIVersion
	if apiVersion == "" {
		apiVersion = DefaultAPIVersion
	}
	if c.TLS {
		client, err := dockerclient.NewVersionedTLSClient(c.Host, c.TLSOptions.CertFile, c.TLSOptions.KeyFile, c.TLSOptions.CAFile, apiVersion)
		if err != nil {
			return nil, err
		}
		if c.TLSOptions.InsecureSkipVerify {
			client.TLSConfig.InsecureSkipVerify = true
		}
		return client, nil
	}
	return dockerclient.NewVersionedClient(c.Host, apiVersion)
}
<|endoftext|>