<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"github.com/codegangsta/cli"
	"github.com/leeola/service"
)

// newService provides a preconfigured (based on klientctl's config)
// service object to install, uninstall, start and stop Klient.
func newService() (service.Service, error) {
	// TODO: Add hosts's username
	svcConfig := &service.Config{
		Name:        "klient",
		DisplayName: "klient",
		Description: "Koding Service Connector",
		Executable:  filepath.Join(KlientDirectory, "klient.sh"),
		Option: map[string]interface{}{
			"LogStderr": true,
			"LogStdout": true,
		},
	}

	return service.New(&serviceProgram{}, svcConfig)
}

type serviceProgram struct{}

func (p *serviceProgram) Start(s service.Service) error {
	fmt.Println("Error: serviceProgram Start called")
	return nil
}

func (p *serviceProgram) Stop(s service.Service) error {
	fmt.Println("Error: serviceProgram Stop called")
	return nil
}

// InstallCommandFactory is the factory method for InstallCommand.
func InstallCommandFactory(c *cli.Context) int {
	if len(c.Args()) != 1 {
		cli.ShowCommandHelp(c, "install")
		return 1
	}

	authToken := c.Args().Get(0)

	// We need to check if the authToken is somehow empty, because klient
	// will default to user/pass if there is no auth token (despite setting
	// the token flag)
	if strings.TrimSpace(authToken) == "" {
		cli.ShowCommandHelp(c, "install")
		return 1
	}

	// Get the supplied kontrolURL, defaulting to the prod kontrol if
	// empty.
	kontrolURL := strings.TrimSpace(c.String("kontrol"))
	if kontrolURL == "" {
		// Default to the config's url
		kontrolURL = KontrolURL
	}

	klientShPath, err := filepath.Abs(filepath.Join(KlientDirectory, "klient.sh"))
	if err != nil {
		fmt.Printf("Error getting %s wrapper path: '%s'\n", KlientName, err)
		return 1
	}

	klientBinPath, err := filepath.Abs(filepath.Join(KlientDirectory, "klient"))
	if err != nil {
		fmt.Printf("Error getting %s path: '%s'\n", KlientName, err)
		return 1
	}

	// Create the installation dir, if needed.
	err = os.MkdirAll(KlientDirectory, 0755)
	if err != nil {
		fmt.Printf("Error creating directory to hold %s: %q\n", KlientName, err)
		return 1
	}

	// TODO: Accept `kd install --user foo` flag to replace the
	// environ checking.
	var sudoCmd string
	for _, s := range os.Environ() {
		env := strings.Split(s, "=")

		if len(env) != 2 {
			continue
		}

		if env[0] == "SUDO_USER" {
			sudoCmd = fmt.Sprintf("sudo -u %s ", env[1])
			break
		}
	}

	// TODO: Stop using this klient.sh file.
	// If the klient.sh file is missing, write it. We can use build tags
	// for os specific tags, if needed.
	_, err = os.Stat(klientShPath)
	if err != nil {
		if os.IsNotExist(err) {
			klientShFile := []byte(fmt.Sprintf(`#!/bin/sh
%sKITE_HOME=%s %s --kontrol-url=%s
`,
				sudoCmd, KiteHome, klientBinPath, kontrolURL))

			// perm -rwr-xr-x, same as klient
			err := ioutil.WriteFile(klientShPath, klientShFile, 0755)
			if err != nil {
				fmt.Printf("Error creating %s wrapper: '%s'\n", KlientName, err)
				return 1
			}

			fmt.Printf("Created %s\n", klientShPath)

		} else {
			// Unknown error stating (possibly permission), exit
			// TODO: Print UX friendly err
			fmt.Println("Error:", err)
			return 1
		}
	}

	fmt.Println("Downloading...")

	if err = downloadRemoteToLocal(S3KlientPath, klientBinPath); err != nil {
		fmt.Printf("Error downloading %s: '%s'\n", KlientName, err)
		return 1
	}

	fmt.Printf("Created %s\n", klientBinPath)
	fmt.Printf(`Authenticating you to the %s

`, KlientName)

	cmd := exec.Command(klientBinPath, "-register",
		"-token", authToken,
		"--kontrol-url", kontrolURL,
		"--kite-home", KiteHome,
	)
	// Note that we are *only* printing to Stdout. This is done because
	// Klient logs error messages to Stderr, and we want to control the UX for
	// that interaction.
	//
	// TODO: Logg Klient's Stderr message on error, if any.
	cmd.Stdout = os.Stdout
	cmd.Stdin = os.Stdin

	err = cmd.Run()
	if err != nil {
		// TODO: Log the error, or handle it somehow so it doesn't leak.
		// log.Errorf("Error registering klient. %q", err)
		fmt.Printf(`Error: Failed to authenticate the %s.

Please go back to Koding to get a new code and try again.
`,
			KlientName)
		return 1
	}

	fmt.Printf("Created %s\n", filepath.Join(KiteHome, "kite.key"))

	// Klient is setting the wrong file permissions when installed by ctl,
	// so since this is just ctl problem, we'll just fix the permission
	// here for now.
	if err = os.Chmod(KiteHome, 0755); err != nil {
		fmt.Printf("Error installing %s: '%s'\n", KlientName, err)
		return 1
	}

	if err = os.Chmod(filepath.Join(KiteHome, "kite.key"), 0644); err != nil {
		fmt.Printf("Error installing kite.key: '%s'\n", err)
		return 1
	}

	// Create our interface to the OS specific service
	s, err := newService()
	if err != nil {
		fmt.Printf("Error starting service: '%s'\n", err)
		return 1
	}

	// Install the klient binary as a OS service
	if err = s.Install(); err != nil {
		fmt.Printf("Error installing service: '%s'\n", err)
		return 1
	}

	// Tell the service to start. Normally it starts automatically, but
	// if the user told the service to stop (previously), it may not
	// start automatically.
	//
	// Note that the service may error if it is already running, so
	// we're ignoring any starting errors here. We will verify the
	// connection below, anyway.
	s.Start()

	fmt.Println("Verifying installation...")
	err = WaitUntilStarted(KlientAddress, 5, 1*time.Second)

	// After X times, if err != nil we failed to connect to klient.
	// Inform the user.
	if err != nil {
		fmt.Printf("Error verifying the installation of %s: '%s'\n", KlientName, err)
		return 1
	}

	fmt.Printf("\n\nSuccessfully installed and started the %s!\n", KlientName)

	return 0
}
<commit_msg>styleguide: If err embed<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"github.com/codegangsta/cli"
	"github.com/leeola/service"
)

// newService provides a preconfigured (based on klientctl's config)
// service object to install, uninstall, start and stop Klient.
func newService() (service.Service, error) {
	// TODO: Add hosts's username
	svcConfig := &service.Config{
		Name:        "klient",
		DisplayName: "klient",
		Description: "Koding Service Connector",
		Executable:  filepath.Join(KlientDirectory, "klient.sh"),
		Option: map[string]interface{}{
			"LogStderr": true,
			"LogStdout": true,
		},
	}

	return service.New(&serviceProgram{}, svcConfig)
}

type serviceProgram struct{}

func (p *serviceProgram) Start(s service.Service) error {
	fmt.Println("Error: serviceProgram Start called")
	return nil
}

func (p *serviceProgram) Stop(s service.Service) error {
	fmt.Println("Error: serviceProgram Stop called")
	return nil
}

// InstallCommandFactory is the factory method for InstallCommand.
func InstallCommandFactory(c *cli.Context) int {
	if len(c.Args()) != 1 {
		cli.ShowCommandHelp(c, "install")
		return 1
	}

	authToken := c.Args().Get(0)

	// We need to check if the authToken is somehow empty, because klient
	// will default to user/pass if there is no auth token (despite setting
	// the token flag)
	if strings.TrimSpace(authToken) == "" {
		cli.ShowCommandHelp(c, "install")
		return 1
	}

	// Get the supplied kontrolURL, defaulting to the prod kontrol if
	// empty.
	kontrolURL := strings.TrimSpace(c.String("kontrol"))
	if kontrolURL == "" {
		// Default to the config's url
		kontrolURL = KontrolURL
	}

	klientShPath, err := filepath.Abs(filepath.Join(KlientDirectory, "klient.sh"))
	if err != nil {
		fmt.Printf("Error getting %s wrapper path: '%s'\n", KlientName, err)
		return 1
	}

	klientBinPath, err := filepath.Abs(filepath.Join(KlientDirectory, "klient"))
	if err != nil {
		fmt.Printf("Error getting %s path: '%s'\n", KlientName, err)
		return 1
	}

	// Create the installation dir, if needed.
	err = os.MkdirAll(KlientDirectory, 0755)
	if err != nil {
		fmt.Printf("Error creating directory to hold %s: %q\n", KlientName, err)
		return 1
	}

	// TODO: Accept `kd install --user foo` flag to replace the
	// environ checking.
	var sudoCmd string
	for _, s := range os.Environ() {
		env := strings.Split(s, "=")

		if len(env) != 2 {
			continue
		}

		if env[0] == "SUDO_USER" {
			sudoCmd = fmt.Sprintf("sudo -u %s ", env[1])
			break
		}
	}

	// TODO: Stop using this klient.sh file.
	// If the klient.sh file is missing, write it. We can use build tags
	// for os specific tags, if needed.
	_, err = os.Stat(klientShPath)
	if err != nil {
		if os.IsNotExist(err) {
			klientShFile := []byte(fmt.Sprintf(`#!/bin/sh
%sKITE_HOME=%s %s --kontrol-url=%s
`,
				sudoCmd, KiteHome, klientBinPath, kontrolURL))

			// perm -rwr-xr-x, same as klient
			err := ioutil.WriteFile(klientShPath, klientShFile, 0755)
			if err != nil {
				fmt.Printf("Error creating %s wrapper: '%s'\n", KlientName, err)
				return 1
			}

			fmt.Printf("Created %s\n", klientShPath)

		} else {
			// Unknown error stating (possibly permission), exit
			// TODO: Print UX friendly err
			fmt.Println("Error:", err)
			return 1
		}
	}

	fmt.Println("Downloading...")

	if err = downloadRemoteToLocal(S3KlientPath, klientBinPath); err != nil {
		fmt.Printf("Error downloading %s: '%s'\n", KlientName, err)
		return 1
	}

	fmt.Printf("Created %s\n", klientBinPath)
	fmt.Printf(`Authenticating you to the %s

`, KlientName)

	cmd := exec.Command(klientBinPath, "-register",
		"-token", authToken,
		"--kontrol-url", kontrolURL,
		"--kite-home", KiteHome,
	)
	// Note that we are *only* printing to Stdout. This is done because
	// Klient logs error messages to Stderr, and we want to control the UX for
	// that interaction.
	//
	// TODO: Logg Klient's Stderr message on error, if any.
	cmd.Stdout = os.Stdout
	cmd.Stdin = os.Stdin

	if err := cmd.Run(); err != nil {
		// TODO: Log the error, or handle it somehow so it doesn't leak.
		// log.Errorf("Error registering klient. %q", err)
		fmt.Printf(`Error: Failed to authenticate the %s.

Please go back to Koding to get a new code and try again.
`,
			KlientName)
		return 1
	}

	fmt.Printf("Created %s\n", filepath.Join(KiteHome, "kite.key"))

	// Klient is setting the wrong file permissions when installed by ctl,
	// so since this is just ctl problem, we'll just fix the permission
	// here for now.
	if err = os.Chmod(KiteHome, 0755); err != nil {
		fmt.Printf("Error installing %s: '%s'\n", KlientName, err)
		return 1
	}

	if err = os.Chmod(filepath.Join(KiteHome, "kite.key"), 0644); err != nil {
		fmt.Printf("Error installing kite.key: '%s'\n", err)
		return 1
	}

	// Create our interface to the OS specific service
	s, err := newService()
	if err != nil {
		fmt.Printf("Error starting service: '%s'\n", err)
		return 1
	}

	// Install the klient binary as a OS service
	if err = s.Install(); err != nil {
		fmt.Printf("Error installing service: '%s'\n", err)
		return 1
	}

	// Tell the service to start. Normally it starts automatically, but
	// if the user told the service to stop (previously), it may not
	// start automatically.
	//
	// Note that the service may error if it is already running, so
	// we're ignoring any starting errors here. We will verify the
	// connection below, anyway.
	s.Start()

	fmt.Println("Verifying installation...")
	err = WaitUntilStarted(KlientAddress, 5, 1*time.Second)

	// After X times, if err != nil we failed to connect to klient.
	// Inform the user.
	if err != nil {
		fmt.Printf("Error verifying the installation of %s: '%s'\n", KlientName, err)
		return 1
	}

	fmt.Printf("\n\nSuccessfully installed and started the %s!\n", KlientName)

	return 0
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////

package h2j

////////////////////////////////////////////////////////////////////////////////

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	"sync"

	"github.com/recogni/sorten/gcloud"
	"github.com/recogni/sorten/logger"

	"google.golang.org/api/iterator"
)

////////////////////////////////////////////////////////////////////////////////

var (
	CLI = struct {
		// Command line args common to all commands
		inputDir   string
		outputDir  string
		magickBins string
		lumiBins   string

		// Private stuff
		useImageMagick bool
		numWorkers     int
	}{}
)

////////////////////////////////////////////////////////////////////////////////

// hdrToJpegJob represents a source file path and the desired destination
// location after conversion.
type hdrToJpegJob struct {
	source      string
	destination string
}

// hdrToJpegWorker is a specialized worker which will run imagemagick on one
// goroutine to convert the source file into the appropriate destination
// file / format (as specified by the destination file's extension).
func hdrToJpegWorker(workerId int, jobs <-chan *hdrToJpegJob, wg *sync.WaitGroup, wl *logger.WorkerLogger) {
	wl.Log(workerId, "is ready for work")
	for job := range jobs {
		source := job.source
		if gcloud.IsBucketPath(job.source) {
			source = path.Join(os.TempDir(), fmt.Sprintf("worker_%d_input.hdr", workerId))
			bp, _ := gcloud.NewBucketPath(job.source)
			bm, _ := gcloud.GetBucketManager(bp.Bucket)

			wl.Log(workerId, "attempting to download %s -> %s", job.source, source)
			if err := bm.BucketDownloadFile(source, bp); err != nil {
				wl.Log(workerId, "Warning: unable to download %s from bucket, error: %s", job.source, err.Error())
			} else {
				wl.Log(workerId, "download successful!")
			}
		}

		isBucketDst := false
		destination := job.destination
		if gcloud.IsBucketPath(job.destination) {
			isBucketDst = true
			destination = path.Join(os.TempDir(), fmt.Sprintf("worker_%d_output.jpeg", workerId))
		} else {
			// Local file - verify that its parent directory exists
			dir := path.Dir(destination)
			if _, err := os.Stat(dir); os.IsNotExist(err) {
				if err := os.MkdirAll(dir, 0755); err != nil {
					// TODO: This should be done from a mutex :)
					// TODO: Ignore this error for now
					// return err
				}
			}
		}

		// 1. Convert from HDR -> TIFF using luminance-hdr-cli
		tempFile := path.Join(os.TempDir(), fmt.Sprintf("worker_%d_temporary.tiff", workerId))
		wl.Log(workerId, "converting HDR -> TIFF %s -> %s", source, tempFile)
		cmd0 := exec.Command(path.Join(CLI.lumiBins, "luminance-hdr-cli"), "-l", source, "-t", "durand", "-o", tempFile)
		if _, err := cmd0.CombinedOutput(); err != nil {
			wl.Log(workerId, "Warning: `luminance-hdr-cli %s %s` had error: %s", source, tempFile, err.Error())
		} else {
			wl.Log(workerId, "conversion successful!")
		}

		// 2. Convert from TIFF -> JPEG using image-magick
		wl.Log(workerId, "converting TIFF -> JPEG %s -> %s", tempFile, destination)
		cmd1 := exec.Command(path.Join(CLI.magickBins, "convert"), tempFile, "-quality", "100", destination)
		if _, err := cmd1.CombinedOutput(); err != nil {
			wl.Log(workerId, "Warning: `convert %s %s` had error: %s", tempFile, destination, err.Error())
		} else {
			wl.Log(workerId, "conversion successful!")
		}

		if isBucketDst {
			wl.Log(workerId, "uploading %s to google bucket %s", destination, job.destination)
			bp, _ := gcloud.NewBucketPath(job.destination)
			bm, _ := gcloud.GetBucketManager(bp.Bucket)

			if err := bm.BucketUploadFile(bp, destination); err != nil {
				wl.Log(workerId, "Error: %s\n", err.Error())
			}
		}

		// Job done, tag the workgroup and check for more work.
		wg.Done()
		wl.Log(workerId, "is now idle")
	}
}

// queuqHdrToJpegJobFiltered checks the given file for the appropriate extension, and if
// it matches queues the current file as work for the next available worker queue.
func queuqHdrToJpegJobFiltered(fp string, jobs chan *hdrToJpegJob, wg *sync.WaitGroup) {
	fmt.Printf("Found file: %s", fp)
	if strings.ToLower(path.Ext(fp)) == ".hdr" {
		d, fn := filepath.Dir(fp), filepath.Base(fp)
		rd, err := filepath.Rel(CLI.inputDir, d)
		if err != nil {
			// TODO: Handle error case if we can open a file!
		} else {
			dstfile := fn[0:len(fn)-len(filepath.Ext(fn))] + ".jpeg"
			dpitems := []string{CLI.outputDir}
			if rd != "." {
				dpitems = append(dpitems, []string{rd, dstfile}...)
			} else {
				dpitems = append(dpitems, dstfile)
			}
			dp := strings.Join(dpitems, string(filepath.Separator))

			wg.Add(1)
			jobs <- &hdrToJpegJob{source: fp, destination: dp}
		}
	}
}

////////////////////////////////////////////////////////////////////////////////

func RunJob(nworkers int, args []string, wl *logger.WorkerLogger) error {
	var wg sync.WaitGroup

	// Parse arguments for this sub-command.
	fs := flag.NewFlagSet("HdrToJpeg", flag.ExitOnError)
	fs.StringVar(&CLI.inputDir, "input", "", "input directory to read images from")
	fs.StringVar(&CLI.outputDir, "output", "", "output directory to read images from")
	fs.StringVar(&CLI.magickBins, "magic", "/usr/local/bin/", "path to imagemagick binaries")
	fs.StringVar(&CLI.lumiBins, "luminance", "/usr/local/bin/", "path to luminance-hdr binaries")
	fs.Parse(args)

	if len(CLI.inputDir) == 0 {
		errors.New("specify input directory with --input")
	}
	if len(CLI.outputDir) == 0 {
		errors.New("specify output directory with --output")
	}
	if !gcloud.IsBucketPath(CLI.outputDir) {
		if _, err := os.Stat(CLI.outputDir); os.IsNotExist(err) {
			if err := os.MkdirAll(CLI.outputDir, 0755); err != nil {
				return err
			}
		}
	}
	if _, err := os.Stat(path.Join(CLI.magickBins, "convert")); os.IsNotExist(err) {
		return errors.New("Imagemagick not correctly installed! convert utility missing!")
	}
	if _, err := os.Stat(path.Join(CLI.lumiBins, "luminance-hdr-cli")); os.IsNotExist(err) {
		return errors.New("Luminance-hdr not correctly installed! luminance-hdr-cli missing!")
	}
	CLI.numWorkers = nworkers

	// Create a channel for the variable number of jobs to run.
	jobs := make(chan *hdrToJpegJob)

	// Create the workers based on how many CPU cores the system has.
	for wId := 0; wId < CLI.numWorkers; wId++ {
		go hdrToJpegWorker(wId, jobs, &wg, wl)
	}

	// TODO: SHABA_BOILERPLATE_ITERATOR
	// The below code is SUPER boilerplate! and can be abstracted out fi the
	// signature for the worker queue is identical (which it should be ... )
	if gcloud.IsBucketPath(CLI.inputDir) {
		bp, err := gcloud.NewBucketPath(CLI.inputDir)
		if err != nil {
			return err
		}

		wl.Status("Using google cloud APIs to access bucket: %s", bp.Bucket)
		bm, err := gcloud.GetBucketManager(bp.Bucket)

		it, err := bm.GetBucketIterator(bp.Subpath)
		if err != nil {
			return err
		}

		c := 0
		for {
			attrs, err := it.Next()
			if err == iterator.Done {
				break
			} else if err != nil {
				wl.Status("Warning found error: %s", err.Error())
			}

			fp := "gs://" + strings.Join([]string{bp.Bucket, attrs.Name}, string(filepath.Separator))
			queuqHdrToJpegJobFiltered(fp, jobs, &wg)

			c += 1
			wl.Status("found %d files so far ...", c)
		}

	} else {
		wl.Status("Building file list ... (this can take a while on large mounted dirs) ...")
		err := (filepath.Walk(CLI.inputDir, func(fp string, fi os.FileInfo, err error) error {
			if err != nil {
				wl.Status("Warning found error walking dir. Error: %s", err.Error())
			} else {
				queuqHdrToJpegJobFiltered(fp, jobs, &wg)
			}
			return nil
		}))
		if err != nil {
			return err
		}
	}

	// We are done feeding work to the workers, close the jobs channel so that
	// they can end their routines.
	close(jobs)

	// Wait for all the wait groups to finish their work.
	wg.Wait()

	return nil
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>Convert JPEG to RGB colorspace<commit_after>////////////////////////////////////////////////////////////////////////////////

package h2j

////////////////////////////////////////////////////////////////////////////////

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	"sync"

	"github.com/recogni/sorten/gcloud"
	"github.com/recogni/sorten/logger"

	"google.golang.org/api/iterator"
)

////////////////////////////////////////////////////////////////////////////////

var (
	CLI = struct {
		// Command line args common to all commands
		inputDir   string
		outputDir  string
		magickBins string
		lumiBins   string
		numWorkers int

		// Private stuff
		useImageMagick bool
	}{}
)

////////////////////////////////////////////////////////////////////////////////

// hdrToJpegJob represents a source file path and the desired destination
// location after conversion.
type hdrToJpegJob struct {
	source      string
	destination string
}

// hdrToJpegWorker is a specialized worker which will run imagemagick on one
// goroutine to convert the source file into the appropriate destination
// file / format (as specified by the destination file's extension).
func hdrToJpegWorker(workerId int, jobs <-chan *hdrToJpegJob, wg *sync.WaitGroup, wl *logger.WorkerLogger) {
	wl.Log(workerId, "is ready for work")
	for job := range jobs {
		source := job.source
		if gcloud.IsBucketPath(job.source) {
			source = path.Join(os.TempDir(), fmt.Sprintf("worker_%d_input.hdr", workerId))
			bp, _ := gcloud.NewBucketPath(job.source)
			bm, _ := gcloud.GetBucketManager(bp.Bucket)

			wl.Log(workerId, "attempting to download %s -> %s", job.source, source)
			if err := bm.BucketDownloadFile(source, bp); err != nil {
				wl.Log(workerId, "Warning: unable to download %s from bucket, error: %s", job.source, err.Error())
			} else {
				wl.Log(workerId, "download successful!")
			}
		}

		isBucketDst := false
		destination := job.destination
		if gcloud.IsBucketPath(job.destination) {
			isBucketDst = true
			destination = path.Join(os.TempDir(), fmt.Sprintf("worker_%d_output.jpeg", workerId))
		} else {
			// Local file - verify that its parent directory exists
			dir := path.Dir(destination)
			if _, err := os.Stat(dir); os.IsNotExist(err) {
				if err := os.MkdirAll(dir, 0755); err != nil {
					// TODO: This should be done from a mutex :)
					// TODO: Ignore this error for now
					// return err
				}
			}
		}

		// 1. Convert from HDR -> TIFF using luminance-hdr-cli
		tempFile := path.Join(os.TempDir(), fmt.Sprintf("worker_%d_temporary.tiff", workerId))
		wl.Log(workerId, "converting HDR -> TIFF %s -> %s", source, tempFile)
		cmd0 := exec.Command(path.Join(CLI.lumiBins, "luminance-hdr-cli"), "-l", source, "-t", "durand", "-o", tempFile)
		if _, err := cmd0.CombinedOutput(); err != nil {
			wl.Log(workerId, "Warning: `luminance-hdr-cli %s %s` had error: %s", source, tempFile, err.Error())
		} else {
			wl.Log(workerId, "conversion successful!")
		}

		// 2. Convert from TIFF -> JPEG using image-magick
		wl.Log(workerId, "converting TIFF -> JPEG %s -> %s", tempFile, destination)
		cmd1 := exec.Command(path.Join(CLI.magickBins, "convert"), tempFile /*"-quality", "100",*/, "-colorspace", "RGB", destination)
		if _, err := cmd1.CombinedOutput(); err != nil {
			wl.Log(workerId, "Warning: `convert %s %s` had error: %s", tempFile, destination, err.Error())
		} else {
			wl.Log(workerId, "conversion successful!")
		}

		if isBucketDst {
			wl.Log(workerId, "uploading %s to google bucket %s", destination, job.destination)
			bp, _ := gcloud.NewBucketPath(job.destination)
			bm, _ := gcloud.GetBucketManager(bp.Bucket)

			if err := bm.BucketUploadFile(bp, destination); err != nil {
				wl.Log(workerId, "Error: %s\n", err.Error())
			}
		}

		// Job done, tag the workgroup and check for more work.
		wg.Done()
		wl.Log(workerId, "is now idle")
	}
}

// queuqHdrToJpegJobFiltered checks the given file for the appropriate extension, and if
// it matches queues the current file as work for the next available worker queue.
func queuqHdrToJpegJobFiltered(fp string, jobs chan *hdrToJpegJob, wg *sync.WaitGroup) {
	fmt.Printf("Found file: %s", fp)
	if strings.ToLower(path.Ext(fp)) == ".hdr" {
		d, fn := filepath.Dir(fp), filepath.Base(fp)
		rd, err := filepath.Rel(CLI.inputDir, d)
		if err != nil {
			// TODO: Handle error case if we can open a file!
		} else {
			dstfile := fn[0:len(fn)-len(filepath.Ext(fn))] + ".jpeg"
			dpitems := []string{CLI.outputDir}
			if rd != "." {
				dpitems = append(dpitems, []string{rd, dstfile}...)
			} else {
				dpitems = append(dpitems, dstfile)
			}
			dp := strings.Join(dpitems, string(filepath.Separator))

			wg.Add(1)
			jobs <- &hdrToJpegJob{source: fp, destination: dp}
		}
	}
}

////////////////////////////////////////////////////////////////////////////////

func RunJob(nworkers int, args []string, wl *logger.WorkerLogger) error {
	var wg sync.WaitGroup

	// Parse arguments for this sub-command.
	fs := flag.NewFlagSet("HdrToJpeg", flag.ExitOnError)
	fs.StringVar(&CLI.inputDir, "input", "", "input directory to read images from")
	fs.StringVar(&CLI.outputDir, "output", "", "output directory to read images from")
	fs.StringVar(&CLI.magickBins, "magic", "/usr/local/bin/", "path to imagemagick binaries")
	fs.StringVar(&CLI.lumiBins, "luminance", "/usr/local/bin/", "path to luminance-hdr binaries")
	fs.IntVar(&CLI.numWorkers, "workers", nworkers, "number of workers to use (default == num cpus)")
	fs.Parse(args)

	if len(CLI.inputDir) == 0 {
		errors.New("specify input directory with --input")
	}
	if len(CLI.outputDir) == 0 {
		errors.New("specify output directory with --output")
	}
	if !gcloud.IsBucketPath(CLI.outputDir) {
		if _, err := os.Stat(CLI.outputDir); os.IsNotExist(err) {
			if err := os.MkdirAll(CLI.outputDir, 0755); err != nil {
				return err
			}
		}
	}
	if _, err := os.Stat(path.Join(CLI.magickBins, "convert")); os.IsNotExist(err) {
		return errors.New("Imagemagick not correctly installed! convert utility missing!")
	}
	if _, err := os.Stat(path.Join(CLI.lumiBins, "luminance-hdr-cli")); os.IsNotExist(err) {
		return errors.New("Luminance-hdr not correctly installed! luminance-hdr-cli missing!")
	}

	// Create a channel for the variable number of jobs to run.
	jobs := make(chan *hdrToJpegJob)

	// Create the workers based on how many CPU cores the system has.
	for wId := 0; wId < CLI.numWorkers; wId++ {
		go hdrToJpegWorker(wId, jobs, &wg, wl)
	}

	// TODO: SHABA_BOILERPLATE_ITERATOR
	// The below code is SUPER boilerplate! and can be abstracted out fi the
	// signature for the worker queue is identical (which it should be ... )
	if gcloud.IsBucketPath(CLI.inputDir) {
		bp, err := gcloud.NewBucketPath(CLI.inputDir)
		if err != nil {
			return err
		}

		wl.Status("Using google cloud APIs to access bucket: %s", bp.Bucket)
		bm, err := gcloud.GetBucketManager(bp.Bucket)

		it, err := bm.GetBucketIterator(bp.Subpath)
		if err != nil {
			return err
		}

		c := 0
		for {
			attrs, err := it.Next()
			if err == iterator.Done {
				break
			} else if err != nil {
				wl.Status("Warning found error: %s", err.Error())
			}

			fp := "gs://" + strings.Join([]string{bp.Bucket, attrs.Name}, string(filepath.Separator))
			queuqHdrToJpegJobFiltered(fp, jobs, &wg)

			c += 1
			wl.Status("found %d files so far ...", c)
		}

	} else {
		wl.Status("Building file list ... (this can take a while on large mounted dirs) ...")
		err := (filepath.Walk(CLI.inputDir, func(fp string, fi os.FileInfo, err error) error {
			if err != nil {
				wl.Status("Warning found error walking dir. Error: %s", err.Error())
			} else {
				queuqHdrToJpegJobFiltered(fp, jobs, &wg)
			}
			return nil
		}))
		if err != nil {
			return err
		}
	}

	// We are done feeding work to the workers, close the jobs channel so that
	// they can end their routines.
	close(jobs)

	// Wait for all the wait groups to finish their work.
	wg.Wait()

	return nil
}

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>package fuse

import (
	"sync"
	"fmt"
	"unsafe"
	"log"
)

var _ = log.Println

// This implements a pool of buffers that returns slices with capacity
// (2^e * PAGESIZE) for e=0,1,...  which have possibly been used, and
// may contain random contents.
type BufferPool struct {
	lock sync.Mutex

	// For each exponent a list of slice pointers.
	buffersByExponent [][][]byte

	// start of slice -> exponent.
	outstandingBuffers map[uintptr]uint

	// Total count of created buffers.  Handy for finding memory
	// leaks.
	createdBuffers int
}

// Returns the smallest E such that 2^E >= Z.
func IntToExponent(z int) uint {
	x := z
	var exp uint = 0
	for x > 1 {
		exp++
		x >>= 1
	}

	if z > (1 << exp) {
		exp++
	}
	return exp
}

func NewBufferPool() *BufferPool {
	bp := new(BufferPool)
	bp.buffersByExponent = make([][][]byte, 0, 8)
	bp.outstandingBuffers = make(map[uintptr]uint)
	return bp
}

func (me *BufferPool) String() string {
	s := ""
	for exp, bufs := range me.buffersByExponent {
		s = s + fmt.Sprintf("%d = %d\n", exp, len(bufs))
	}
	return s
}

func (me *BufferPool) getBuffer(exponent uint) []byte {
	if len(me.buffersByExponent) <= int(exponent) {
		return nil
	}
	bufferList := me.buffersByExponent[exponent]
	if len(bufferList) == 0 {
		return nil
	}

	result := bufferList[len(bufferList)-1]
	me.buffersByExponent[exponent] = me.buffersByExponent[exponent][:len(bufferList)-1]
	return result
}

func (me *BufferPool) addBuffer(slice []byte, exp uint) {
	for len(me.buffersByExponent) <= int(exp) {
		me.buffersByExponent = append(me.buffersByExponent, make([][]byte, 0))
	}
	me.buffersByExponent[exp] = append(me.buffersByExponent[exp], slice)
}

func (me *BufferPool) AllocCount() int {
	me.lock.Lock()
	defer me.lock.Unlock()

	return me.createdBuffers
}

func (me *BufferPool) AllocBuffer(size uint32) []byte {
	sz := int(size)
	if sz < PAGESIZE {
		sz = PAGESIZE
	}

	exp := IntToExponent(sz)
	rounded := 1 << exp

	exp -= IntToExponent(PAGESIZE)

	me.lock.Lock()
	defer me.lock.Unlock()

	b := me.getBuffer(exp)

	if b == nil {
		me.createdBuffers++
		b = make([]byte, size, rounded)
	} else {
		b = b[:size]
	}

	me.outstandingBuffers[uintptr(unsafe.Pointer(&b[0]))] = exp
	return b
}

// Takes back a buffer if it was allocated through AllocBuffer.  It is
// not an error to call FreeBuffer() on a slice obtained elsewhere.
func (me *BufferPool) FreeBuffer(slice []byte) {
	if cap(slice) < PAGESIZE {
		return
	}
	slice = slice[:cap(slice)]
	key := uintptr(unsafe.Pointer(&slice[0]))

	me.lock.Lock()
	defer me.lock.Unlock()
	exp, ok := me.outstandingBuffers[key]
	if ok {
		me.addBuffer(slice, exp)
		me.outstandingBuffers[key] = 0, false
	}
}
<commit_msg>Add a check for memory leaks in BufferPool.<commit_after>package fuse

import (
	"sync"
	"fmt"
	"unsafe"
	"log"
)

var _ = log.Println

// This implements a pool of buffers that returns slices with capacity
// (2^e * PAGESIZE) for e=0,1,...  which have possibly been used, and
// may contain random contents.
type BufferPool struct {
	lock sync.Mutex

	// For each exponent a list of slice pointers.
	buffersByExponent [][][]byte

	// start of slice -> exponent.
	outstandingBuffers map[uintptr]uint

	// Total count of created buffers.  Handy for finding memory
	// leaks.
	createdBuffers int
}

// Returns the smallest E such that 2^E >= Z.
func IntToExponent(z int) uint {
	x := z
	var exp uint = 0
	for x > 1 {
		exp++
		x >>= 1
	}

	if z > (1 << exp) {
		exp++
	}
	return exp
}

func NewBufferPool() *BufferPool {
	bp := new(BufferPool)
	bp.buffersByExponent = make([][][]byte, 0, 8)
	bp.outstandingBuffers = make(map[uintptr]uint)
	return bp
}

func (me *BufferPool) String() string {
	s := ""
	for exp, bufs := range me.buffersByExponent {
		s = s + fmt.Sprintf("%d = %d\n", exp, len(bufs))
	}
	return s
}

func (me *BufferPool) getBuffer(exponent uint) []byte {
	if len(me.buffersByExponent) <= int(exponent) {
		return nil
	}
	bufferList := me.buffersByExponent[exponent]
	if len(bufferList) == 0 {
		return nil
	}

	result := bufferList[len(bufferList)-1]
	me.buffersByExponent[exponent] = me.buffersByExponent[exponent][:len(bufferList)-1]
	return result
}

func (me *BufferPool) addBuffer(slice []byte, exp uint) {
	for len(me.buffersByExponent) <= int(exp) {
		me.buffersByExponent = append(me.buffersByExponent, make([][]byte, 0))
	}
	me.buffersByExponent[exp] = append(me.buffersByExponent[exp], slice)
}

func (me *BufferPool) AllocCount() int {
	me.lock.Lock()
	defer me.lock.Unlock()

	return me.createdBuffers
}

func (me *BufferPool) AllocBuffer(size uint32) []byte {
	sz := int(size)
	if sz < PAGESIZE {
		sz = PAGESIZE
	}

	exp := IntToExponent(sz)
	rounded := 1 << exp

	exp -= IntToExponent(PAGESIZE)

	me.lock.Lock()
	defer me.lock.Unlock()

	b := me.getBuffer(exp)

	if b == nil {
		me.createdBuffers++
		b = make([]byte, size, rounded)
	} else {
		b = b[:size]
	}

	me.outstandingBuffers[uintptr(unsafe.Pointer(&b[0]))] = exp

	// FUSE throttles to ~10 outstanding requests, no normally,
	// should not have more than 20 buffers outstanding.
	if len(me.outstandingBuffers) > 200 {
		panic("Leaking buffers")
	}

	return b
}

// Takes back a buffer if it was allocated through AllocBuffer.  It is
// not an error to call FreeBuffer() on a slice obtained elsewhere.
func (me *BufferPool) FreeBuffer(slice []byte) {
	if cap(slice) < PAGESIZE {
		return
	}
	slice = slice[:cap(slice)]
	key := uintptr(unsafe.Pointer(&slice[0]))

	me.lock.Lock()
	defer me.lock.Unlock()
	exp, ok := me.outstandingBuffers[key]
	if ok {
		me.addBuffer(slice, exp)
		me.outstandingBuffers[key] = 0, false
	}
}
<|endoftext|>


<commit_before>package nodefs

import (
	"log"

	"github.com/hanwen/go-fuse/fuse"
)

type connectorDir struct {
	node       Node
	stream     []fuse.DirEntry
	lastOffset uint64
	rawFS      fuse.RawFileSystem
}

func (d *connectorDir) ReadDir(input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) {
	if d.stream == nil {
		return fuse.OK
	}
	// rewinddir() should be as if reopening directory.
	// TODO - test this.
	if d.lastOffset > 0 && input.Offset == 0 {
		d.stream, code = d.node.OpenDir((*fuse.Context)(&input.Context))
		if !code.Ok() {
			return code
		}
	}

	if input.Offset > uint64(len(d.stream)) {
		// This shouldn't happen, but let's not crash.
		return fuse.EINVAL
	}

	todo := d.stream[input.Offset:]
	for _, e := range todo {
		if e.Name == "" {
			log.Printf("got emtpy directory entry, mode %o.", e.Mode)
			continue
		}
		ok, off := out.AddDirEntry(e)
		d.lastOffset = off
		if !ok {
			break
		}
	}
	return fuse.OK
}

func (d *connectorDir) ReadDirPlus(input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) {
	if d.stream == nil {
		return fuse.OK
	}

	// rewinddir() should be as if reopening directory.
	if d.lastOffset > 0 && input.Offset == 0 {
		d.stream, code = d.node.OpenDir((*fuse.Context)(&input.Context))
		if !code.Ok() {
			return code
		}
	}

	if input.Offset > uint64(len(d.stream)) {
		// This shouldn't happen, but let's not crash.
		return fuse.EINVAL
	}
	todo := d.stream[input.Offset:]
	for _, e := range todo {
		if e.Name == "" {
			log.Printf("got empty directory entry, mode %o.", e.Mode)
			continue
		}

		// we have to be sure entry will fit if we try to add
		// it, or we'll mess up the lookup counts.
		entryDest, off := out.AddDirLookupEntry(e)
		if entryDest == nil {
			break
		}
		entryDest.Ino = uint64(fuse.FUSE_UNKNOWN_INO)

		// No need to fill attributes for . and ..
		if e.Name == "." || e.Name == ".." {
			continue
		}

		// Clear entryDest before use it, some fields can be corrupted if does not set all fields in rawFS.Lookup
		*entryDest = fuse.EntryOut{}

		d.rawFS.Lookup(&input.InHeader, e.Name, entryDest)
		d.lastOffset = off
	}
	return fuse.OK

}

type rawDir interface {
	ReadDir(out *fuse.DirEntryList, input *fuse.ReadIn, c *fuse.Context) fuse.Status
	ReadDirPlus(out *fuse.DirEntryList, input *fuse.ReadIn, c *fuse.Context) fuse.Status
}
<commit_msg>fuse/nodefs: typo.<commit_after>package nodefs

import (
	"log"

	"github.com/hanwen/go-fuse/fuse"
)

type connectorDir struct {
	node       Node
	stream     []fuse.DirEntry
	lastOffset uint64
	rawFS      fuse.RawFileSystem
}

func (d *connectorDir) ReadDir(input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) {
	if d.stream == nil {
		return fuse.OK
	}
	// rewinddir() should be as if reopening directory.
	// TODO - test this.
	if d.lastOffset > 0 && input.Offset == 0 {
		d.stream, code = d.node.OpenDir((*fuse.Context)(&input.Context))
		if !code.Ok() {
			return code
		}
	}

	if input.Offset > uint64(len(d.stream)) {
		// This shouldn't happen, but let's not crash.
		return fuse.EINVAL
	}

	todo := d.stream[input.Offset:]
	for _, e := range todo {
		if e.Name == "" {
			log.Printf("got empty directory entry, mode %o.", e.Mode)
			continue
		}
		ok, off := out.AddDirEntry(e)
		d.lastOffset = off
		if !ok {
			break
		}
	}
	return fuse.OK
}

func (d *connectorDir) ReadDirPlus(input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) {
	if d.stream == nil {
		return fuse.OK
	}

	// rewinddir() should be as if reopening directory.
	if d.lastOffset > 0 && input.Offset == 0 {
		d.stream, code = d.node.OpenDir((*fuse.Context)(&input.Context))
		if !code.Ok() {
			return code
		}
	}

	if input.Offset > uint64(len(d.stream)) {
		// This shouldn't happen, but let's not crash.
		return fuse.EINVAL
	}
	todo := d.stream[input.Offset:]
	for _, e := range todo {
		if e.Name == "" {
			log.Printf("got empty directory entry, mode %o.", e.Mode)
			continue
		}

		// we have to be sure entry will fit if we try to add
		// it, or we'll mess up the lookup counts.
		entryDest, off := out.AddDirLookupEntry(e)
		if entryDest == nil {
			break
		}
		entryDest.Ino = uint64(fuse.FUSE_UNKNOWN_INO)

		// No need to fill attributes for . and ..
		if e.Name == "." || e.Name == ".." {
			continue
		}

		// Clear entryDest before use it, some fields can be corrupted if does not set all fields in rawFS.Lookup
		*entryDest = fuse.EntryOut{}

		d.rawFS.Lookup(&input.InHeader, e.Name, entryDest)
		d.lastOffset = off
	}
	return fuse.OK

}

type rawDir interface {
	ReadDir(out *fuse.DirEntryList, input *fuse.ReadIn, c *fuse.Context) fuse.Status
	ReadDirPlus(out *fuse.DirEntryList, input *fuse.ReadIn, c *fuse.Context) fuse.Status
}
<|endoftext|>


<commit_before>// This file is part of Monsti, a web content management system.
// Copyright 2012-2013 Christian Neumann
//
// Monsti is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// Monsti is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Monsti.  If not, see <http://www.gnu.org/licenses/>.

package main

import (
	utesting "pkg.monsti.org/util/testing"
	"os"
	"path/filepath"
	"reflect"
	"testing"
)

/*
func TestGetNav(t *testing.T) {
	root, cleanup, err := utesting.CreateDirectoryTree(map[string]string{
		"/foo/node.yaml": "title: Node Foo\nshorttitle: Foo",
		"/foo/child1/node.yaml": "title: Node a Foo Child 1\n" +
			"shorttitle: a Foo Child 1",
		"/foo/child2/node.yaml":        "title: Node Foo Child 2\n" +
			"shorttitle: Foo Child 2",
		"/foo/child2/child1/node.yaml": "title: Node a Foo Child 2 Child 1\n" +
			"shorttitle: a Foo Child 2 Child 1",
		"/bar/node.yaml":               "title: Node Bar\norder: 2\n" +
			"shorttitle: Bar",
		"/hideme/node.yaml":            "title: Node Hide me!\nhide: true\n" +
			"shorttitle: Hide me!",
		"/cruz/node.yaml":              "title: Node Cruz\norder: -2\n" +
			"shorttitle: Cruz",
		"/cruz/child1/node.yaml":       "title: Node Cruz Child 1\n" +
			"shorttitle: Cruz Child 1"}, "TestGetNav")
	if err != nil {
		t.Fatalf("Could not create directory tree: ", err)
	}
	defer cleanup()
	tests := []struct {
		Path, Active string
		Expected     navigation
	}{
		{"/", "/", navigation{
			{Name: "Cruz", Target: "cruz", Child: true, Order: -2},
			{Name: "Foo", Target: "foo", Child: true},
			{Name: "Bar", Target: "bar", Child: true, Order: 2}}},
		{"/", "/foo/child1/child2", navigation{
			{Name: "Cruz", Target: "../../../cruz", Child: true, Order: -2},
			{Name: "Foo", Target: "../..", Child: true, Active: true},
			{Name: "Bar", Target: "../../../bar", Child: true, Order: 2}}},
		{"/foo", "/foo", navigation{
			{Name: "Foo", Target: ".", Active: true},
			{Name: "Foo Child 2", Target: "child2", Child: true},
			{Name: "a Foo Child 1", Target: "child1", Child: true}}},
		{"/foo/child1", "/foo/child1", navigation{
			{Name: "Foo", Target: ".."},
			{Name: "Foo Child 2", Target: "../child2", Child: true},
			{Name: "a Foo Child 1", Target: ".", Child: true, Active: true}}},
		{"/foo/child2", "/foo/child2", navigation{
			{Name: "Foo Child 2", Target: ".", Active: true},
			{Name: "a Foo Child 2 Child 1", Target: "child1", Child: true},
			{Name: "a Foo Child 1", Target: "../child1"}}},
		{"/foo/child2/child1", "/foo/child2/child1", navigation{
			{Name: "Foo Child 2", Target: ".."},
			{Name: "a Foo Child 2 Child 1", Target: ".", Active: true, Child: true},
			{Name: "a Foo Child 1", Target: "../../child1"}}},
		{"/bar", "/bar", navigation{}},
		{"/cruz", "/cruz", navigation{
			{Name: "Cruz", Target: ".", Active: true, Order: -2},
			{Name: "Cruz Child 1", Target: "child1", Child: true}}}}
	for _, test := range tests {
		ret, err := getNav(test.Path, test.Active, root)
		if err != nil || !(len(ret) == 0 && len(test.Expected) == 0 || reflect.DeepEqual(ret, test.Expected)) {
			t.Errorf(`getNav(%q, %q, _) = %v, %v, should be %v, nil`,
				test.Path, test.Active, ret, err, test.Expected)
		}
	}
}
*/

func TestNavigationMakeAbsolute(t *testing.T) {
	nav := navigation{
		{Target: "foo"},
		{Target: "."},
		{Target: "../bar"}}
	nav.MakeAbsolute("/root")
	expected := navigation{
		{Target: "/root/foo/"},
		{Target: "/root/"},
		{Target: "/bar/"}}
	if !(reflect.DeepEqual(nav, expected)) {
		t.Errorf(`navigation.MakeAbsolute("/root") = %q, should be %q`,
			nav, expected)
	}
}

func TestRemoveNode(t *testing.T) {
	root, cleanup, err := utesting.CreateDirectoryTree(map[string]string{
		"/navigation.yaml": `
- name: foo Page
  target: foo
- name: bar Page
  target: bar`,
		"/foo/__empty__":       "",
		"/bar/navigation.yaml": ""}, "TestRemoveNode")
	if err != nil {
		t.Fatalf("Could not create directory tree: ", err)
	}
	defer cleanup()
	removeNode("/foo", root)
	if f, err := os.Open(filepath.Join(root, "foo")); !os.IsNotExist(err) {
		f.Close()
		t.Errorf(`/foo does still exist, should be removed`)
	}
}
<commit_msg>Remove unneeded test.<commit_after>// This file is part of Monsti, a web content management system.
// Copyright 2012-2013 Christian Neumann
//
// Monsti is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// Monsti is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Monsti.  If not, see <http://www.gnu.org/licenses/>.

package main

import (
	"reflect"
	"testing"
)

/*
func TestGetNav(t *testing.T) {
	root, cleanup, err := utesting.CreateDirectoryTree(map[string]string{
		"/foo/node.yaml": "title: Node Foo\nshorttitle: Foo",
		"/foo/child1/node.yaml": "title: Node a Foo Child 1\n" +
			"shorttitle: a Foo Child 1",
		"/foo/child2/node.yaml":        "title: Node Foo Child 2\n" +
			"shorttitle: Foo Child 2",
		"/foo/child2/child1/node.yaml": "title: Node a Foo Child 2 Child 1\n" +
			"shorttitle: a Foo Child 2 Child 1",
		"/bar/node.yaml":               "title: Node Bar\norder: 2\n" +
			"shorttitle: Bar",
		"/hideme/node.yaml":            "title: Node Hide me!\nhide: true\n" +
			"shorttitle: Hide me!",
		"/cruz/node.yaml":              "title: Node Cruz\norder: -2\n" +
			"shorttitle: Cruz",
		"/cruz/child1/node.yaml":       "title: Node Cruz Child 1\n" +
			"shorttitle: Cruz Child 1"}, "TestGetNav")
	if err != nil {
		t.Fatalf("Could not create directory tree: ", err)
	}
	defer cleanup()
	tests := []struct {
		Path, Active string
		Expected     navigation
	}{
		{"/", "/", navigation{
			{Name: "Cruz", Target: "cruz", Child: true, Order: -2},
			{Name: "Foo", Target: "foo", Child: true},
			{Name: "Bar", Target: "bar", Child: true, Order: 2}}},
		{"/", "/foo/child1/child2", navigation{
			{Name: "Cruz", Target: "../../../cruz", Child: true, Order: -2},
			{Name: "Foo", Target: "../..", Child: true, Active: true},
			{Name: "Bar", Target: "../../../bar", Child: true, Order: 2}}},
		{"/foo", "/foo", navigation{
			{Name: "Foo", Target: ".", Active: true},
			{Name: "Foo Child 2", Target: "child2", Child: true},
			{Name: "a Foo Child 1", Target: "child1", Child: true}}},
		{"/foo/child1", "/foo/child1", navigation{
			{Name: "Foo", Target: ".."},
			{Name: "Foo Child 2", Target: "../child2", Child: true},
			{Name: "a Foo Child 1", Target: ".", Child: true, Active: true}}},
		{"/foo/child2", "/foo/child2", navigation{
			{Name: "Foo Child 2", Target: ".", Active: true},
			{Name: "a Foo Child 2 Child 1", Target: "child1", Child: true},
			{Name: "a Foo Child 1", Target: "../child1"}}},
		{"/foo/child2/child1", "/foo/child2/child1", navigation{
			{Name: "Foo Child 2", Target: ".."},
			{Name: "a Foo Child 2 Child 1", Target: ".", Active: true, Child: true},
			{Name: "a Foo Child 1", Target: "../../child1"}}},
		{"/bar", "/bar", navigation{}},
		{"/cruz", "/cruz", navigation{
			{Name: "Cruz", Target: ".", Active: true, Order: -2},
			{Name: "Cruz Child 1", Target: "child1", Child: true}}}}
	for _, test := range tests {
		ret, err := getNav(test.Path, test.Active, root)
		if err != nil || !(len(ret) == 0 && len(test.Expected) == 0 || reflect.DeepEqual(ret, test.Expected)) {
			t.Errorf(`getNav(%q, %q, _) = %v, %v, should be %v, nil`,
				test.Path, test.Active, ret, err, test.Expected)
		}
	}
}
*/

func TestNavigationMakeAbsolute(t *testing.T) {
	nav := navigation{
		{Target: "foo"},
		{Target: "."},
		{Target: "../bar"}}
	nav.MakeAbsolute("/root")
	expected := navigation{
		{Target: "/root/foo/"},
		{Target: "/root/"},
		{Target: "/bar/"}}
	if !(reflect.DeepEqual(nav, expected)) {
		t.Errorf(`navigation.MakeAbsolute("/root") = %q, should be %q`,
			nav, expected)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os/exec"
)

func main() {
	cmd := exec.Command("/tmp/stdout")
	stdout := new(bytes.Buffer)
	stderr := new(bytes.Buffer)

	cmd.Stdout = stdout
	cmd.Stderr = stderr

	if err := cmd.Start(); err != nil {
		panic(err)
	}

	if err := cmd.Wait(); err != nil {
		panic(err)
	}

	in := bufio.NewScanner(io.MultiReader(stdout, stderr))
	for in.Scan() {
		fmt.Println(in.Text())
	}

}
<commit_msg>	modified:   main.go<commit_after>package main

import (
	"fmt"
	"io"
	"os"
	"os/exec"
)

func main() {
	cmd := exec.Command("/tmp/stdout")

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		panic(err)
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		panic(err)
	}

	if err := cmd.Start(); err != nil {
		panic(err)
	}

	defer cmd.Wait()

	// Non-blockingly echo command output to terminal
	go io.Copy(os.Stdout, stdout)
	go io.Copy(os.Stderr, stderr)

	fmt.Println("...")
}
<|endoftext|>


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

// Package stats is a wrapper for expvar. It addtionally
// exports new types that can be used to track performance.
// It also provides a callback hook that allows a program
// to export the variables using methods other than /debug/vars.
// All variables support a String function that
// is expected to return a JSON representation
// of the variable.
// Any function named Add will add the specified
// number to the variable.
// Any function named Counts returns a map of counts
// that can be used by Rates to track rates over time.
package stats

import (
	"bytes"
	"expvar"
	"flag"
	"fmt"
	"strconv"
	"sync"
	"time"

	log "github.com/golang/glog"
	"github.com/youtube/vitess/go/sync2"
)

var emitStats = flag.Bool("emit_stats", false, "true iff we should emit stats to push-based monitoring/stats backends")
var statsEmitPeriod = flag.Duration("stats_emit_period", time.Duration(60*time.Second), "Interval between emitting stats to all registered backends")

// NewVarHook is the type of a hook to export variables in a different way
type NewVarHook func(name string, v expvar.Var)

type varGroup struct {
	sync.Mutex
	vars       map[string]expvar.Var
	newVarHook NewVarHook
}

func (vg *varGroup) register(nvh NewVarHook) {
	vg.Lock()
	defer vg.Unlock()
	if vg.newVarHook != nil {
		panic("You've already registered a function")
	}
	if nvh == nil {
		panic("nil not allowed")
	}
	vg.newVarHook = nvh
	// Call hook on existing vars because some might have been
	// created before the call to register
	for k, v := range vg.vars {
		nvh(k, v)
	}
	vg.vars = nil
}

func (vg *varGroup) publish(name string, v expvar.Var) {
	vg.Lock()
	defer vg.Unlock()
	expvar.Publish(name, v)
	if vg.newVarHook != nil {
		vg.newVarHook(name, v)
	} else {
		vg.vars[name] = v
	}
}

var defaultVarGroup = varGroup{vars: make(map[string]expvar.Var)}

// Register allows you to register a callback function
// that will be called whenever a new stats variable gets
// created. This can be used to build alternate methods
// of exporting stats variables.
func Register(nvh NewVarHook) {
	defaultVarGroup.register(nvh)
}

// Publish is expvar.Publish+hook
func Publish(name string, v expvar.Var) {
	defaultVarGroup.publish(name, v)
}

// PushBackend is an interface for any stats/metrics backend that requires data
// to be pushed to it. It's used to support push-based metrics backends, as expvar
// by default only supports pull-based ones.
type PushBackend interface {
	// PushAll pushes all stats from expvar to the backend
	PushAll() error
}

var pushBackends = make(map[string]PushBackend)
var once sync.Once

// RegisterPushBackend allows modules to register PushBackend implementations.
// Should be called on init().
func RegisterPushBackend(name string, backend PushBackend) {
	if _, ok := pushBackends[name]; ok {
		log.Fatalf("RegisterPushBackend %s already exists", name)
	}
	pushBackends[name] = backend
	if *emitStats {
		// Start a single goroutine to emit stats periodically
		once.Do(func() {
			go emitToBackends(statsEmitPeriod)
		})
	}
}

// emitToBackends does a periodic emit to all registered PushBackends. If a push
// fails, it will be logged as a warning (but things will otherwise proceed as normal).
func emitToBackends(emitPeriod *time.Duration) {
	for _ = range time.Tick(*emitPeriod) {
		for name, backend := range pushBackends {
			err := backend.PushAll()
			if err != nil {
				// TODO(aaijazi): This might cause log spam...
				log.Warningf("Pushing stats to backend %v failed: %v", name, err)
			}
		}
	}
}

// Float is expvar.Float+Get+hook
type Float struct {
	mu sync.Mutex
	f  float64
}

// NewFloat creates a new Float and exports it.
func NewFloat(name string) *Float {
	v := new(Float)
	Publish(name, v)
	return v
}

// Add adds the provided value to the Float
func (v *Float) Add(delta float64) {
	v.mu.Lock()
	v.f += delta
	v.mu.Unlock()
}

// Set sets the value
func (v *Float) Set(value float64) {
	v.mu.Lock()
	v.f = value
	v.mu.Unlock()
}

// Get returns the value
func (v *Float) Get() float64 {
	v.mu.Lock()
	f := v.f
	v.mu.Unlock()
	return f
}

// String is the implementation of expvar.var
func (v *Float) String() string {
	return strconv.FormatFloat(v.Get(), 'g', -1, 64)
}

// FloatFunc converts a function that returns
// a float64 as an expvar.
type FloatFunc func() float64

// String is the implementation of expvar.var
func (f FloatFunc) String() string {
	return strconv.FormatFloat(f(), 'g', -1, 64)
}

// Int is expvar.Int+Get+hook
type Int struct {
	i sync2.AtomicInt64
}

// NewInt returns a new Int
func NewInt(name string) *Int {
	v := new(Int)
	Publish(name, v)
	return v
}

// Add adds the provided value to the Int
func (v *Int) Add(delta int64) {
	v.i.Add(delta)
}

// Set sets the value
func (v *Int) Set(value int64) {
	v.i.Set(value)
}

// Get returns the value
func (v *Int) Get() int64 {
	return v.i.Get()
}

// String is the implementation of expvar.var
func (v *Int) String() string {
	return strconv.FormatInt(v.i.Get(), 10)
}

// Duration exports a time.Duration
type Duration struct {
	i sync2.AtomicDuration
}

// NewDuration returns a new Duration
func NewDuration(name string) *Duration {
	v := new(Duration)
	Publish(name, v)
	return v
}

// Add adds the provided value to the Duration
func (v *Duration) Add(delta time.Duration) {
	v.i.Add(delta)
}

// Set sets the value
func (v *Duration) Set(value time.Duration) {
	v.i.Set(value)
}

// Get returns the value
func (v *Duration) Get() time.Duration {
	return v.i.Get()
}

// String is the implementation of expvar.var
func (v *Duration) String() string {
	return strconv.FormatInt(int64(v.i.Get()), 10)
}

// IntFunc converts a function that returns
// an int64 as an expvar.
type IntFunc func() int64

// String is the implementation of expvar.var
func (f IntFunc) String() string {
	return strconv.FormatInt(f(), 10)
}

// DurationFunc converts a function that returns
// an time.Duration as an expvar.
type DurationFunc func() time.Duration

// String is the implementation of expvar.var
func (f DurationFunc) String() string {
	return strconv.FormatInt(int64(f()), 10)
}

// String is expvar.String+Get+hook
type String struct {
	mu sync.Mutex
	s  string
}

// NewString returns a new String
func NewString(name string) *String {
	v := new(String)
	Publish(name, v)
	return v
}

// Set sets the value
func (v *String) Set(value string) {
	v.mu.Lock()
	v.s = value
	v.mu.Unlock()
}

// Get returns the value
func (v *String) Get() string {
	v.mu.Lock()
	s := v.s
	v.mu.Unlock()
	return s
}

// String is the implementation of expvar.var
func (v *String) String() string {
	return strconv.Quote(v.Get())
}

// StringFunc converts a function that returns
// an string as an expvar.
type StringFunc func() string

// String is the implementation of expvar.var
func (f StringFunc) String() string {
	return strconv.Quote(f())
}

// JSONFunc is the public type for a single function that returns json directly.
type JSONFunc func() string

// String is the implementation of expvar.var
func (f JSONFunc) String() string {
	return f()
}

// PublishJSONFunc publishes any function that returns
// a JSON string as a variable. The string is sent to
// expvar as is.
func PublishJSONFunc(name string, f func() string) {
	Publish(name, JSONFunc(f))
}

// StringMap is a map of string -> string
type StringMap struct {
	mu     sync.Mutex
	values map[string]string
}

// NewStringMap returns a new StringMap
func NewStringMap(name string) *StringMap {
	v := &StringMap{values: make(map[string]string)}
	Publish(name, v)
	return v
}

// Set will set a value (existing or not)
func (v *StringMap) Set(name, value string) {
	v.mu.Lock()
	v.values[name] = value
	v.mu.Unlock()
}

// Get will return the value, or "" f not set.
func (v *StringMap) Get(name string) string {
	v.mu.Lock()
	s := v.values[name]
	v.mu.Unlock()
	return s
}

// String is the implementation of expvar.Var
func (v *StringMap) String() string {
	v.mu.Lock()
	defer v.mu.Unlock()
	return stringMapToString(v.values)
}

// StringMapFunc is the function equivalent of StringMap
type StringMapFunc func() map[string]string

// String is used by expvar.
func (f StringMapFunc) String() string {
	m := f()
	if m == nil {
		return "{}"
	}
	return stringMapToString(m)
}

func stringMapToString(m map[string]string) string {
	b := bytes.NewBuffer(make([]byte, 0, 4096))
	fmt.Fprintf(b, "{")
	firstValue := true
	for k, v := range m {
		if firstValue {
			firstValue = false
		} else {
			fmt.Fprintf(b, ", ")
		}
		fmt.Fprintf(b, "\"%v\": %v", k, strconv.Quote(v))
	}
	fmt.Fprintf(b, "}")
	return b.String()
}
<commit_msg>Only support emitting stats to a single backend at a time, selected with the --stats_backend flag<commit_after>// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package stats is a wrapper for expvar. It addtionally
// exports new types that can be used to track performance.
// It also provides a callback hook that allows a program
// to export the variables using methods other than /debug/vars.
// All variables support a String function that
// is expected to return a JSON representation
// of the variable.
// Any function named Add will add the specified
// number to the variable.
// Any function named Counts returns a map of counts
// that can be used by Rates to track rates over time.
package stats

import (
	"bytes"
	"expvar"
	"flag"
	"fmt"
	"strconv"
	"sync"
	"time"

	log "github.com/golang/glog"
	"github.com/youtube/vitess/go/sync2"
)

var emitStats = flag.Bool("emit_stats", false, "true iff we should emit stats to push-based monitoring/stats backends")
var statsEmitPeriod = flag.Duration("stats_emit_period", time.Duration(60*time.Second), "Interval between emitting stats to all registered backends")
var statsBackend = flag.String("stats_backend", "influxdb", "The name of the registered push-based monitoring/stats backend to use")

// NewVarHook is the type of a hook to export variables in a different way
type NewVarHook func(name string, v expvar.Var)

type varGroup struct {
	sync.Mutex
	vars       map[string]expvar.Var
	newVarHook NewVarHook
}

func (vg *varGroup) register(nvh NewVarHook) {
	vg.Lock()
	defer vg.Unlock()
	if vg.newVarHook != nil {
		panic("You've already registered a function")
	}
	if nvh == nil {
		panic("nil not allowed")
	}
	vg.newVarHook = nvh
	// Call hook on existing vars because some might have been
	// created before the call to register
	for k, v := range vg.vars {
		nvh(k, v)
	}
	vg.vars = nil
}

func (vg *varGroup) publish(name string, v expvar.Var) {
	vg.Lock()
	defer vg.Unlock()
	expvar.Publish(name, v)
	if vg.newVarHook != nil {
		vg.newVarHook(name, v)
	} else {
		vg.vars[name] = v
	}
}

var defaultVarGroup = varGroup{vars: make(map[string]expvar.Var)}

// Register allows you to register a callback function
// that will be called whenever a new stats variable gets
// created. This can be used to build alternate methods
// of exporting stats variables.
func Register(nvh NewVarHook) {
	defaultVarGroup.register(nvh)
}

// Publish is expvar.Publish+hook
func Publish(name string, v expvar.Var) {
	defaultVarGroup.publish(name, v)
}

// PushBackend is an interface for any stats/metrics backend that requires data
// to be pushed to it. It's used to support push-based metrics backends, as expvar
// by default only supports pull-based ones.
type PushBackend interface {
	// PushAll pushes all stats from expvar to the backend
	PushAll() error
}

var pushBackends = make(map[string]PushBackend)
var once sync.Once

// RegisterPushBackend allows modules to register PushBackend implementations.
// Should be called on init().
func RegisterPushBackend(name string, backend PushBackend) {
	if _, ok := pushBackends[name]; ok {
		log.Fatalf("PushBackend %s already exists; can't register the same name multiple times", name)
	}
	pushBackends[name] = backend
	if *emitStats {
		// Start a single goroutine to emit stats periodically
		once.Do(func() {
			go emitToBackend(statsEmitPeriod)
		})
	}
}

// emitToBackend does a periodic emit to the selected PushBackend. If a push fails,
// it will be logged as a warning (but things will otherwise proceed as normal).
func emitToBackend(emitPeriod *time.Duration) {
	ticker := time.NewTicker(*emitPeriod)
	defer ticker.Stop()
	for _ = range ticker.C {
		backend, ok := pushBackends[*statsBackend]
		if !ok {
			log.Errorf("No PushBackend registered with name %s", *statsBackend)
			return
		}
		err := backend.PushAll()
		if err != nil {
			// TODO(aaijazi): This might cause log spam...
			log.Warningf("Pushing stats to backend %v failed: %v", *statsBackend, err)
		}
	}
}

// Float is expvar.Float+Get+hook
type Float struct {
	mu sync.Mutex
	f  float64
}

// NewFloat creates a new Float and exports it.
func NewFloat(name string) *Float {
	v := new(Float)
	Publish(name, v)
	return v
}

// Add adds the provided value to the Float
func (v *Float) Add(delta float64) {
	v.mu.Lock()
	v.f += delta
	v.mu.Unlock()
}

// Set sets the value
func (v *Float) Set(value float64) {
	v.mu.Lock()
	v.f = value
	v.mu.Unlock()
}

// Get returns the value
func (v *Float) Get() float64 {
	v.mu.Lock()
	f := v.f
	v.mu.Unlock()
	return f
}

// String is the implementation of expvar.var
func (v *Float) String() string {
	return strconv.FormatFloat(v.Get(), 'g', -1, 64)
}

// FloatFunc converts a function that returns
// a float64 as an expvar.
type FloatFunc func() float64

// String is the implementation of expvar.var
func (f FloatFunc) String() string {
	return strconv.FormatFloat(f(), 'g', -1, 64)
}

// Int is expvar.Int+Get+hook
type Int struct {
	i sync2.AtomicInt64
}

// NewInt returns a new Int
func NewInt(name string) *Int {
	v := new(Int)
	Publish(name, v)
	return v
}

// Add adds the provided value to the Int
func (v *Int) Add(delta int64) {
	v.i.Add(delta)
}

// Set sets the value
func (v *Int) Set(value int64) {
	v.i.Set(value)
}

// Get returns the value
func (v *Int) Get() int64 {
	return v.i.Get()
}

// String is the implementation of expvar.var
func (v *Int) String() string {
	return strconv.FormatInt(v.i.Get(), 10)
}

// Duration exports a time.Duration
type Duration struct {
	i sync2.AtomicDuration
}

// NewDuration returns a new Duration
func NewDuration(name string) *Duration {
	v := new(Duration)
	Publish(name, v)
	return v
}

// Add adds the provided value to the Duration
func (v *Duration) Add(delta time.Duration) {
	v.i.Add(delta)
}

// Set sets the value
func (v *Duration) Set(value time.Duration) {
	v.i.Set(value)
}

// Get returns the value
func (v *Duration) Get() time.Duration {
	return v.i.Get()
}

// String is the implementation of expvar.var
func (v *Duration) String() string {
	return strconv.FormatInt(int64(v.i.Get()), 10)
}

// IntFunc converts a function that returns
// an int64 as an expvar.
type IntFunc func() int64

// String is the implementation of expvar.var
func (f IntFunc) String() string {
	return strconv.FormatInt(f(), 10)
}

// DurationFunc converts a function that returns
// an time.Duration as an expvar.
type DurationFunc func() time.Duration

// String is the implementation of expvar.var
func (f DurationFunc) String() string {
	return strconv.FormatInt(int64(f()), 10)
}

// String is expvar.String+Get+hook
type String struct {
	mu sync.Mutex
	s  string
}

// NewString returns a new String
func NewString(name string) *String {
	v := new(String)
	Publish(name, v)
	return v
}

// Set sets the value
func (v *String) Set(value string) {
	v.mu.Lock()
	v.s = value
	v.mu.Unlock()
}

// Get returns the value
func (v *String) Get() string {
	v.mu.Lock()
	s := v.s
	v.mu.Unlock()
	return s
}

// String is the implementation of expvar.var
func (v *String) String() string {
	return strconv.Quote(v.Get())
}

// StringFunc converts a function that returns
// an string as an expvar.
type StringFunc func() string

// String is the implementation of expvar.var
func (f StringFunc) String() string {
	return strconv.Quote(f())
}

// JSONFunc is the public type for a single function that returns json directly.
type JSONFunc func() string

// String is the implementation of expvar.var
func (f JSONFunc) String() string {
	return f()
}

// PublishJSONFunc publishes any function that returns
// a JSON string as a variable. The string is sent to
// expvar as is.
func PublishJSONFunc(name string, f func() string) {
	Publish(name, JSONFunc(f))
}

// StringMap is a map of string -> string
type StringMap struct {
	mu     sync.Mutex
	values map[string]string
}

// NewStringMap returns a new StringMap
func NewStringMap(name string) *StringMap {
	v := &StringMap{values: make(map[string]string)}
	Publish(name, v)
	return v
}

// Set will set a value (existing or not)
func (v *StringMap) Set(name, value string) {
	v.mu.Lock()
	v.values[name] = value
	v.mu.Unlock()
}

// Get will return the value, or "" f not set.
func (v *StringMap) Get(name string) string {
	v.mu.Lock()
	s := v.values[name]
	v.mu.Unlock()
	return s
}

// String is the implementation of expvar.Var
func (v *StringMap) String() string {
	v.mu.Lock()
	defer v.mu.Unlock()
	return stringMapToString(v.values)
}

// StringMapFunc is the function equivalent of StringMap
type StringMapFunc func() map[string]string

// String is used by expvar.
func (f StringMapFunc) String() string {
	m := f()
	if m == nil {
		return "{}"
	}
	return stringMapToString(m)
}

func stringMapToString(m map[string]string) string {
	b := bytes.NewBuffer(make([]byte, 0, 4096))
	fmt.Fprintf(b, "{")
	firstValue := true
	for k, v := range m {
		if firstValue {
			firstValue = false
		} else {
			fmt.Fprintf(b, ", ")
		}
		fmt.Fprintf(b, "\"%v\": %v", k, strconv.Quote(v))
	}
	fmt.Fprintf(b, "}")
	return b.String()
}
<|endoftext|>


<commit_before>package api

import (
	"archive/zip"
	"cf"
	"cf/configuration"
	"cf/net"
	"fileutils"
	"fmt"
	"github.com/stretchr/testify/assert"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	testapi "testhelpers/api"
	testnet "testhelpers/net"
	"testing"
	"time"
)

var expectedResources = testnet.RemoveWhiteSpaceFromBody(`[
    {
        "fn": "Gemfile",
        "sha1": "d9c3a51de5c89c11331d3b90b972789f1a14699a",
        "size": 59
    },
    {
        "fn": "Gemfile.lock",
        "sha1": "345f999aef9070fb9a608e65cf221b7038156b6d",
        "size": 229
    },
    {
        "fn": "app.rb",
        "sha1": "2474735f5163ba7612ef641f438f4b5bee00127b",
        "size": 51
    },
    {
        "fn": "config.ru",
        "sha1": "f097424ce1fa66c6cb9f5e8a18c317376ec12e05",
        "size": 70
    },
    {
        "fn": "manifest.yml",
        "sha1": "19b5b4225dc64da3213b1ffaa1e1920ee5faf36c",
        "size": 111
    }
]`)

var permissionsToSet os.FileMode
var expectedPermissionBits os.FileMode

func init() {
	permissionsToSet = 0467
	fileutils.TempFile("permissionedFile", func(file *os.File, err error) {
		if err != nil {
			panic("could not create tmp file")
		}

		fileInfo, err := file.Stat()
		if err != nil {
			panic("could not stat tmp file")
		}

		expectedPermissionBits = fileInfo.Mode()
		if runtime.GOOS != "windows" {
			expectedPermissionBits |= permissionsToSet & 0111
		}
	})
}

var matchedResources = testnet.RemoveWhiteSpaceFromBody(`[
	{
        "fn": "app.rb",
        "sha1": "2474735f5163ba7612ef641f438f4b5bee00127b",
        "size": 51
    },
    {
        "fn": "config.ru",
        "sha1": "f097424ce1fa66c6cb9f5e8a18c317376ec12e05",
        "size": 70
    }
]`)

var uploadApplicationRequest = testapi.NewCloudControllerTestRequest(testnet.TestRequest{
	Method:  "PUT",
	Path:    "/v2/apps/my-cool-app-guid/bits",
	Matcher: uploadBodyMatcher,
	Response: testnet.TestResponse{
		Status: http.StatusCreated,
		Body: `
{
	"metadata":{
		"guid": "my-job-guid",
		"url": "/v2/jobs/my-job-guid"
	}
}
	`},
})

var matchResourceRequest = testnet.TestRequest{
	Method:  "PUT",
	Path:    "/v2/resource_match",
	Matcher: testnet.RequestBodyMatcher(expectedResources),
	Response: testnet.TestResponse{
		Status: http.StatusOK,
		Body:   matchedResources,
	},
}

var defaultRequests = []testnet.TestRequest{
	matchResourceRequest,
	uploadApplicationRequest,
	createProgressEndpoint("running"),
	createProgressEndpoint("finished"),
}

var expectedApplicationContent = []string{"Gemfile", "Gemfile.lock", "manifest.yml"}

var uploadBodyMatcher = func(t *testing.T, request *http.Request) {
	err := request.ParseMultipartForm(4096)
	if err != nil {
		assert.Fail(t, "Failed parsing multipart form", err)
		return
	}
	defer request.MultipartForm.RemoveAll()

	assert.Equal(t, len(request.MultipartForm.Value), 1, "Should have 1 value")
	valuePart, ok := request.MultipartForm.Value["resources"]
	assert.True(t, ok, "Resource manifest not present")
	assert.Equal(t, len(valuePart), 1, "Wrong number of values")

	resourceManifest := valuePart[0]
	chompedResourceManifest := strings.Replace(resourceManifest, "\n", "", -1)
	assert.Equal(t, chompedResourceManifest, matchedResources, "Resources do not match")

	assert.Equal(t, len(request.MultipartForm.File), 1, "Wrong number of files")

	fileHeaders, ok := request.MultipartForm.File["application"]
	assert.True(t, ok, "Application file part not present")
	assert.Equal(t, len(fileHeaders), 1, "Wrong number of files")

	applicationFile := fileHeaders[0]
	assert.Equal(t, applicationFile.Filename, "application.zip", "Wrong file name")

	file, err := applicationFile.Open()
	if err != nil {
		assert.Fail(t, "Cannot get multipart file", err.Error())
		return
	}

	length, err := strconv.ParseInt(applicationFile.Header.Get("content-length"), 10, 64)
	if err != nil {
		assert.Fail(t, "Cannot convert content-length to int", err.Error())
		return
	}

	zipReader, err := zip.NewReader(file, length)
	if err != nil {
		assert.Fail(t, "Error reading zip content", err.Error())
		return
	}

	assert.Equal(t, len(zipReader.File), 3, "Wrong number of files in zip")
	assert.Equal(t, zipReader.File[0].Mode(), uint32(expectedPermissionBits))

nextFile:
	for _, f := range zipReader.File {
		for _, expected := range expectedApplicationContent {
			if f.Name == expected {
				continue nextFile
			}
		}
		assert.Fail(t, "Missing file: "+f.Name)
	}
}

func createProgressEndpoint(status string) (req testnet.TestRequest) {
	body := fmt.Sprintf(`
	{
		"entity":{
			"status":"%s"
		}
	}`, status)

	req.Method = "GET"
	req.Path = "/v2/jobs/my-job-guid"
	req.Response = testnet.TestResponse{
		Status: http.StatusCreated,
		Body:   body,
	}

	return
}

func TestUploadWithInvalidDirectory(t *testing.T) {
	config := &configuration.Configuration{}
	gateway := net.NewCloudControllerGateway()
	zipper := &cf.ApplicationZipper{}

	repo := NewCloudControllerApplicationBitsRepository(config, gateway, zipper)

	apiResponse := repo.UploadApp("app-guid", "/foo/bar")
	assert.True(t, apiResponse.IsNotSuccessful())
	assert.Contains(t, apiResponse.Message, "/foo/bar")
}

func TestUploadApp(t *testing.T) {
	dir, err := os.Getwd()
	assert.NoError(t, err)
	dir = filepath.Join(dir, "../../fixtures/example-app")
	err = os.Chmod(filepath.Join(dir, "Gemfile"), permissionsToSet)

	assert.NoError(t, err)

	_, apiResponse := testUploadApp(t, dir, defaultRequests)
	assert.True(t, apiResponse.IsSuccessful())
}

func TestCreateUploadDirWithAZipFile(t *testing.T) {
	dir, err := os.Getwd()
	assert.NoError(t, err)
	dir = filepath.Join(dir, "../../fixtures/example-app.zip")

	_, apiResponse := testUploadApp(t, dir, defaultRequests)
	assert.True(t, apiResponse.IsSuccessful())
}

func TestUploadAppFailsWhilePushingBits(t *testing.T) {
	dir, err := os.Getwd()
	assert.NoError(t, err)
	dir = filepath.Join(dir, "../../fixtures/example-app")

	requests := []testnet.TestRequest{
		matchResourceRequest,
		uploadApplicationRequest,
		createProgressEndpoint("running"),
		createProgressEndpoint("failed"),
	}
	_, apiResponse := testUploadApp(t, dir, requests)
	assert.False(t, apiResponse.IsSuccessful())
}

func testUploadApp(t *testing.T, dir string, requests []testnet.TestRequest) (app cf.Application, apiResponse net.ApiResponse) {
	ts, handler := testnet.NewTLSServer(t, requests)
	defer ts.Close()

	config := &configuration.Configuration{
		AccessToken: "BEARER my_access_token",
		Target:      ts.URL,
	}
	gateway := net.NewCloudControllerGateway()
	gateway.PollingThrottle = time.Duration(0)
	zipper := cf.ApplicationZipper{}
	repo := NewCloudControllerApplicationBitsRepository(config, gateway, zipper)

	apiResponse = repo.UploadApp("my-cool-app-guid", dir)
	assert.True(t, handler.AllRequestsCalled())

	return
}
<commit_msg>Make application test less brittle<commit_after>package api

import (
	"archive/zip"
	"cf"
	"cf/configuration"
	"cf/net"
	"fileutils"
	"fmt"
	"github.com/stretchr/testify/assert"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	testapi "testhelpers/api"
	testnet "testhelpers/net"
	"testing"
	"time"
)

var expectedResources = testnet.RemoveWhiteSpaceFromBody(`[
    {
        "fn": "Gemfile",
        "sha1": "d9c3a51de5c89c11331d3b90b972789f1a14699a",
        "size": 59
    },
    {
        "fn": "Gemfile.lock",
        "sha1": "345f999aef9070fb9a608e65cf221b7038156b6d",
        "size": 229
    },
    {
        "fn": "app.rb",
        "sha1": "2474735f5163ba7612ef641f438f4b5bee00127b",
        "size": 51
    },
    {
        "fn": "config.ru",
        "sha1": "f097424ce1fa66c6cb9f5e8a18c317376ec12e05",
        "size": 70
    },
    {
        "fn": "manifest.yml",
        "sha1": "19b5b4225dc64da3213b1ffaa1e1920ee5faf36c",
        "size": 111
    }
]`)

var permissionsToSet os.FileMode
var expectedPermissionBits os.FileMode

func init() {
	permissionsToSet = 0467
	fileutils.TempFile("permissionedFile", func(file *os.File, err error) {
		if err != nil {
			panic("could not create tmp file")
		}

		fileInfo, err := file.Stat()
		if err != nil {
			panic("could not stat tmp file")
		}

		expectedPermissionBits = fileInfo.Mode()
		if runtime.GOOS != "windows" {
			expectedPermissionBits |= permissionsToSet & 0111
		}
	})
}

var matchedResources = testnet.RemoveWhiteSpaceFromBody(`[
	{
        "fn": "app.rb",
        "sha1": "2474735f5163ba7612ef641f438f4b5bee00127b",
        "size": 51
    },
    {
        "fn": "config.ru",
        "sha1": "f097424ce1fa66c6cb9f5e8a18c317376ec12e05",
        "size": 70
    }
]`)

var uploadApplicationRequest = testapi.NewCloudControllerTestRequest(testnet.TestRequest{
	Method:  "PUT",
	Path:    "/v2/apps/my-cool-app-guid/bits",
	Matcher: uploadBodyMatcher,
	Response: testnet.TestResponse{
		Status: http.StatusCreated,
		Body: `
{
	"metadata":{
		"guid": "my-job-guid",
		"url": "/v2/jobs/my-job-guid"
	}
}
	`},
})

var matchResourceRequest = testnet.TestRequest{
	Method:  "PUT",
	Path:    "/v2/resource_match",
	Matcher: testnet.RequestBodyMatcher(expectedResources),
	Response: testnet.TestResponse{
		Status: http.StatusOK,
		Body:   matchedResources,
	},
}

var defaultRequests = []testnet.TestRequest{
	matchResourceRequest,
	uploadApplicationRequest,
	createProgressEndpoint("running"),
	createProgressEndpoint("finished"),
}

var expectedApplicationContent = []string{"Gemfile", "Gemfile.lock", "manifest.yml"}

var uploadBodyMatcher = func(t *testing.T, request *http.Request) {
	err := request.ParseMultipartForm(4096)
	if err != nil {
		assert.Fail(t, "Failed parsing multipart form", err)
		return
	}
	defer request.MultipartForm.RemoveAll()

	assert.Equal(t, len(request.MultipartForm.Value), 1, "Should have 1 value")
	valuePart, ok := request.MultipartForm.Value["resources"]
	assert.True(t, ok, "Resource manifest not present")
	assert.Equal(t, len(valuePart), 1, "Wrong number of values")

	resourceManifest := valuePart[0]
	chompedResourceManifest := strings.Replace(resourceManifest, "\n", "", -1)
	assert.Equal(t, chompedResourceManifest, matchedResources, "Resources do not match")

	assert.Equal(t, len(request.MultipartForm.File), 1, "Wrong number of files")

	fileHeaders, ok := request.MultipartForm.File["application"]
	assert.True(t, ok, "Application file part not present")
	assert.Equal(t, len(fileHeaders), 1, "Wrong number of files")

	applicationFile := fileHeaders[0]
	assert.Equal(t, applicationFile.Filename, "application.zip", "Wrong file name")

	file, err := applicationFile.Open()
	if err != nil {
		assert.Fail(t, "Cannot get multipart file", err.Error())
		return
	}

	length, err := strconv.ParseInt(applicationFile.Header.Get("content-length"), 10, 64)
	if err != nil {
		assert.Fail(t, "Cannot convert content-length to int", err.Error())
		return
	}

	zipReader, err := zip.NewReader(file, length)
	if err != nil {
		assert.Fail(t, "Error reading zip content", err.Error())
		return
	}

	assert.Equal(t, len(zipReader.File), 3, "Wrong number of files in zip")
	assert.Equal(t, zipReader.File[0].Mode(), uint32(expectedPermissionBits))

nextFile:
	for _, f := range zipReader.File {
		for _, expected := range expectedApplicationContent {
			if f.Name == expected {
				continue nextFile
			}
		}
		assert.Fail(t, "Missing file: "+f.Name)
	}
}

func createProgressEndpoint(status string) (req testnet.TestRequest) {
	body := fmt.Sprintf(`
	{
		"entity":{
			"status":"%s"
		}
	}`, status)

	req.Method = "GET"
	req.Path = "/v2/jobs/my-job-guid"
	req.Response = testnet.TestResponse{
		Status: http.StatusCreated,
		Body:   body,
	}

	return
}

func TestUploadWithInvalidDirectory(t *testing.T) {
	config := &configuration.Configuration{}
	gateway := net.NewCloudControllerGateway()
	zipper := &cf.ApplicationZipper{}

	repo := NewCloudControllerApplicationBitsRepository(config, gateway, zipper)

	apiResponse := repo.UploadApp("app-guid", "/foo/bar")
	assert.True(t, apiResponse.IsNotSuccessful())
	assert.Contains(t, apiResponse.Message, filepath.Join("foo", "bar"))
}

func TestUploadApp(t *testing.T) {
	dir, err := os.Getwd()
	assert.NoError(t, err)
	dir = filepath.Join(dir, "../../fixtures/example-app")
	err = os.Chmod(filepath.Join(dir, "Gemfile"), permissionsToSet)

	assert.NoError(t, err)

	_, apiResponse := testUploadApp(t, dir, defaultRequests)
	assert.True(t, apiResponse.IsSuccessful())
}

func TestCreateUploadDirWithAZipFile(t *testing.T) {
	dir, err := os.Getwd()
	assert.NoError(t, err)
	dir = filepath.Join(dir, "../../fixtures/example-app.zip")

	_, apiResponse := testUploadApp(t, dir, defaultRequests)
	assert.True(t, apiResponse.IsSuccessful())
}

func TestUploadAppFailsWhilePushingBits(t *testing.T) {
	dir, err := os.Getwd()
	assert.NoError(t, err)
	dir = filepath.Join(dir, "../../fixtures/example-app")

	requests := []testnet.TestRequest{
		matchResourceRequest,
		uploadApplicationRequest,
		createProgressEndpoint("running"),
		createProgressEndpoint("failed"),
	}
	_, apiResponse := testUploadApp(t, dir, requests)
	assert.False(t, apiResponse.IsSuccessful())
}

func testUploadApp(t *testing.T, dir string, requests []testnet.TestRequest) (app cf.Application, apiResponse net.ApiResponse) {
	ts, handler := testnet.NewTLSServer(t, requests)
	defer ts.Close()

	config := &configuration.Configuration{
		AccessToken: "BEARER my_access_token",
		Target:      ts.URL,
	}
	gateway := net.NewCloudControllerGateway()
	gateway.PollingThrottle = time.Duration(0)
	zipper := cf.ApplicationZipper{}
	repo := NewCloudControllerApplicationBitsRepository(config, gateway, zipper)

	apiResponse = repo.UploadApp("my-cool-app-guid", dir)
	assert.True(t, handler.AllRequestsCalled())

	return
}
<|endoftext|>


<commit_before>package compiler

import (
	"github.com/GeertJohan/go.rice"
	"github.com/dop251/goja"
	"github.com/mitchellh/mapstructure"
)

var (
	lib      = rice.MustFindBox("lib")
	babelSrc = lib.MustString("babel-standalone-bower/babel.js")

	DefaultOpts = map[string]interface{}{
		"presets":       []string{"latest"},
		"ast":           false,
		"sourceMaps":    true,
		"babelrc":       false,
		"compact":       false,
		"highlightCode": false,
	}
)

// A Compiler uses Babel to compile ES6 code into something ES5-compatible.
type Compiler struct {
	vm *goja.Runtime

	// JS pointers.
	this      goja.Value
	transform goja.Callable
}

// Constructs a new compiler.
func New() (*Compiler, error) {
	c := &Compiler{vm: goja.New()}
	if _, err := c.vm.RunString(babelSrc); err != nil {
		return nil, err
	}

	c.this = c.vm.Get("Babel")
	thisObj := c.this.ToObject(c.vm)
	if err := c.vm.ExportTo(thisObj.Get("transform"), &c.transform); err != nil {
		return nil, err
	}

	return c, nil
}

func (c *Compiler) Transform(src, filename string) (code string, srcmap SourceMap, err error) {
	opts := make(map[string]interface{})
	for k, v := range DefaultOpts {
		opts[k] = v
	}
	opts["filename"] = filename

	v, err := c.transform(c.this, c.vm.ToValue(src), c.vm.ToValue(opts))
	if err != nil {
		return code, srcmap, err
	}
	vO := v.ToObject(c.vm)

	if err := c.vm.ExportTo(vO.Get("code"), &code); err != nil {
		return code, srcmap, err
	}

	var rawmap map[string]interface{}
	if err := c.vm.ExportTo(vO.Get("map"), &rawmap); err != nil {
		return code, srcmap, err
	}
	if err := mapstructure.Decode(rawmap, &srcmap); err != nil {
		return code, srcmap, err
	}

	return code, srcmap, nil
}
<commit_msg>Use minified babel builds, saves memory<commit_after>package compiler

import (
	"github.com/GeertJohan/go.rice"
	"github.com/dop251/goja"
	"github.com/mitchellh/mapstructure"
)

var (
	lib      = rice.MustFindBox("lib")
	babelSrc = lib.MustString("babel-standalone-bower/babel.min.js")

	DefaultOpts = map[string]interface{}{
		"presets":       []string{"latest"},
		"ast":           false,
		"sourceMaps":    true,
		"babelrc":       false,
		"compact":       false,
		"highlightCode": false,
	}
)

// A Compiler uses Babel to compile ES6 code into something ES5-compatible.
type Compiler struct {
	vm *goja.Runtime

	// JS pointers.
	this      goja.Value
	transform goja.Callable
}

// Constructs a new compiler.
func New() (*Compiler, error) {
	c := &Compiler{vm: goja.New()}
	if _, err := c.vm.RunString(babelSrc); err != nil {
		return nil, err
	}

	c.this = c.vm.Get("Babel")
	thisObj := c.this.ToObject(c.vm)
	if err := c.vm.ExportTo(thisObj.Get("transform"), &c.transform); err != nil {
		return nil, err
	}

	return c, nil
}

func (c *Compiler) Transform(src, filename string) (code string, srcmap SourceMap, err error) {
	opts := make(map[string]interface{})
	for k, v := range DefaultOpts {
		opts[k] = v
	}
	opts["filename"] = filename

	v, err := c.transform(c.this, c.vm.ToValue(src), c.vm.ToValue(opts))
	if err != nil {
		return code, srcmap, err
	}
	vO := v.ToObject(c.vm)

	if err := c.vm.ExportTo(vO.Get("code"), &code); err != nil {
		return code, srcmap, err
	}

	var rawmap map[string]interface{}
	if err := c.vm.ExportTo(vO.Get("map"), &rawmap); err != nil {
		return code, srcmap, err
	}
	if err := mapstructure.Decode(rawmap, &srcmap); err != nil {
		return code, srcmap, err
	}

	return code, srcmap, nil
}
<|endoftext|>


<commit_before>package arm

var Anames = []string{
	"XXX ",
	"CALL",
	"CHECKNIL",
	"DATA",
	"DUFFCOPY",
	"DUFFZERO",
	"END",
	"FUNCDATA",
	"GLOBL",
	"JMP",
	"NOP",
	"PCDATA",
	"RET",
	"TEXT",
	"TYPE",
	"UNDEF",
	"USEFIELD",
	"VARDEF",
	"VARKILL",
	"AND ",
	"EOR",
	"SUB",
	"RSB",
	"ADD",
	"ADC",
	"SBC",
	"RSC",
	"TST",
	"TEQ",
	"CMP",
	"CMN",
	"ORR",
	"BIC",
	"MVN",
	"BEQ",
	"BNE",
	"BCS",
	"BHS",
	"BCC",
	"BLO",
	"BMI",
	"BPL",
	"BVS",
	"BVC",
	"BHI",
	"BLS",
	"BGE",
	"BLT",
	"BGT",
	"BLE",
	"MOVWD",
	"MOVWF",
	"MOVDW",
	"MOVFW",
	"MOVFD",
	"MOVDF",
	"MOVF",
	"MOVD",
	"CMPF",
	"CMPD",
	"ADDF",
	"ADDD",
	"SUBF",
	"SUBD",
	"MULF",
	"MULD",
	"DIVF",
	"DIVD",
	"SQRTF",
	"SQRTD",
	"ABSF",
	"ABSD",
	"SRL",
	"SRA",
	"SLL",
	"MULU",
	"DIVU",
	"MUL",
	"DIV",
	"MOD",
	"MODU",
	"MOVB",
	"MOVBS",
	"MOVBU",
	"MOVH",
	"MOVHS",
	"MOVHU",
	"MOVW",
	"MOVM",
	"SWPBU",
	"SWPW",
	"RFE",
	"SWI",
	"MULA",
	"WORD",
	"BCASE",
	"CASE",
	"MULL",
	"MULAL",
	"MULLU",
	"MULALU",
	"BX",
	"BXRET",
	"DWORD",
	"LDREX",
	"STREX",
	"LDREXD",
	"STREXD",
	"PLD",
	"CLZ",
	"MULWT",
	"MULWB",
	"MULAWT",
	"MULAWB",
	"DATABUNDLE",
	"DATABUNDLEEND",
	"MRC",
	"LAST",
}

var cnames5 = []string{
	"NONE",
	"REG",
	"REGREG",
	"REGREG2",
	"SHIFT",
	"FREG",
	"PSR",
	"FCR",
	"RCON",
	"NCON",
	"SCON",
	"LCON",
	"LCONADDR",
	"ZFCON",
	"SFCON",
	"LFCON",
	"RACON",
	"LACON",
	"SBRA",
	"LBRA",
	"HAUTO",
	"FAUTO",
	"HFAUTO",
	"SAUTO",
	"LAUTO",
	"HOREG",
	"FOREG",
	"HFOREG",
	"SOREG",
	"ROREG",
	"SROREG",
	"LOREG",
	"PC",
	"SP",
	"HREG",
	"ADDR",
	"TEXTSIZE",
	"GOK",
	"NCLASS",
	"SCOND = (1<<4)-1",
	"SBIT = 1<<4",
	"PBIT = 1<<5",
	"WBIT = 1<<6",
	"FBIT = 1<<7",
	"UBIT = 1<<7",
	"SCOND_XOR = 14",
	"SCOND_EQ = 0 ^ C_SCOND_XOR",
	"SCOND_NE = 1 ^ C_SCOND_XOR",
	"SCOND_HS = 2 ^ C_SCOND_XOR",
	"SCOND_LO = 3 ^ C_SCOND_XOR",
	"SCOND_MI = 4 ^ C_SCOND_XOR",
	"SCOND_PL = 5 ^ C_SCOND_XOR",
	"SCOND_VS = 6 ^ C_SCOND_XOR",
	"SCOND_VC = 7 ^ C_SCOND_XOR",
	"SCOND_HI = 8 ^ C_SCOND_XOR",
	"SCOND_LS = 9 ^ C_SCOND_XOR",
	"SCOND_GE = 10 ^ C_SCOND_XOR",
	"SCOND_LT = 11 ^ C_SCOND_XOR",
	"SCOND_GT = 12 ^ C_SCOND_XOR",
	"SCOND_LE = 13 ^ C_SCOND_XOR",
	"SCOND_NONE = 14 ^ C_SCOND_XOR",
	"SCOND_NV = 15 ^ C_SCOND_XOR",
}
<commit_msg>[dev.cc] cmd/internal/obj/arm: delete trailing space from AND instruction<commit_after>package arm

var Anames = []string{
	"XXX ",
	"CALL",
	"CHECKNIL",
	"DATA",
	"DUFFCOPY",
	"DUFFZERO",
	"END",
	"FUNCDATA",
	"GLOBL",
	"JMP",
	"NOP",
	"PCDATA",
	"RET",
	"TEXT",
	"TYPE",
	"UNDEF",
	"USEFIELD",
	"VARDEF",
	"VARKILL",
	"AND",
	"EOR",
	"SUB",
	"RSB",
	"ADD",
	"ADC",
	"SBC",
	"RSC",
	"TST",
	"TEQ",
	"CMP",
	"CMN",
	"ORR",
	"BIC",
	"MVN",
	"BEQ",
	"BNE",
	"BCS",
	"BHS",
	"BCC",
	"BLO",
	"BMI",
	"BPL",
	"BVS",
	"BVC",
	"BHI",
	"BLS",
	"BGE",
	"BLT",
	"BGT",
	"BLE",
	"MOVWD",
	"MOVWF",
	"MOVDW",
	"MOVFW",
	"MOVFD",
	"MOVDF",
	"MOVF",
	"MOVD",
	"CMPF",
	"CMPD",
	"ADDF",
	"ADDD",
	"SUBF",
	"SUBD",
	"MULF",
	"MULD",
	"DIVF",
	"DIVD",
	"SQRTF",
	"SQRTD",
	"ABSF",
	"ABSD",
	"SRL",
	"SRA",
	"SLL",
	"MULU",
	"DIVU",
	"MUL",
	"DIV",
	"MOD",
	"MODU",
	"MOVB",
	"MOVBS",
	"MOVBU",
	"MOVH",
	"MOVHS",
	"MOVHU",
	"MOVW",
	"MOVM",
	"SWPBU",
	"SWPW",
	"RFE",
	"SWI",
	"MULA",
	"WORD",
	"BCASE",
	"CASE",
	"MULL",
	"MULAL",
	"MULLU",
	"MULALU",
	"BX",
	"BXRET",
	"DWORD",
	"LDREX",
	"STREX",
	"LDREXD",
	"STREXD",
	"PLD",
	"CLZ",
	"MULWT",
	"MULWB",
	"MULAWT",
	"MULAWB",
	"DATABUNDLE",
	"DATABUNDLEEND",
	"MRC",
	"LAST",
}

var cnames5 = []string{
	"NONE",
	"REG",
	"REGREG",
	"REGREG2",
	"SHIFT",
	"FREG",
	"PSR",
	"FCR",
	"RCON",
	"NCON",
	"SCON",
	"LCON",
	"LCONADDR",
	"ZFCON",
	"SFCON",
	"LFCON",
	"RACON",
	"LACON",
	"SBRA",
	"LBRA",
	"HAUTO",
	"FAUTO",
	"HFAUTO",
	"SAUTO",
	"LAUTO",
	"HOREG",
	"FOREG",
	"HFOREG",
	"SOREG",
	"ROREG",
	"SROREG",
	"LOREG",
	"PC",
	"SP",
	"HREG",
	"ADDR",
	"TEXTSIZE",
	"GOK",
	"NCLASS",
	"SCOND = (1<<4)-1",
	"SBIT = 1<<4",
	"PBIT = 1<<5",
	"WBIT = 1<<6",
	"FBIT = 1<<7",
	"UBIT = 1<<7",
	"SCOND_XOR = 14",
	"SCOND_EQ = 0 ^ C_SCOND_XOR",
	"SCOND_NE = 1 ^ C_SCOND_XOR",
	"SCOND_HS = 2 ^ C_SCOND_XOR",
	"SCOND_LO = 3 ^ C_SCOND_XOR",
	"SCOND_MI = 4 ^ C_SCOND_XOR",
	"SCOND_PL = 5 ^ C_SCOND_XOR",
	"SCOND_VS = 6 ^ C_SCOND_XOR",
	"SCOND_VC = 7 ^ C_SCOND_XOR",
	"SCOND_HI = 8 ^ C_SCOND_XOR",
	"SCOND_LS = 9 ^ C_SCOND_XOR",
	"SCOND_GE = 10 ^ C_SCOND_XOR",
	"SCOND_LT = 11 ^ C_SCOND_XOR",
	"SCOND_GT = 12 ^ C_SCOND_XOR",
	"SCOND_LE = 13 ^ C_SCOND_XOR",
	"SCOND_NONE = 14 ^ C_SCOND_XOR",
	"SCOND_NV = 15 ^ C_SCOND_XOR",
}
<|endoftext|>


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

package sparc64

import (
	"cmd/internal/obj"
	"encoding/binary"
)

var unaryDst = map[int]bool{
	AWORD:   true,
	ADWORD:  true,
	ARDPC:   true,
	ARDTICK: true,
	ARDCCR:  true,
}

var Linksparc64 = obj.LinkArch{
	ByteOrder: binary.BigEndian,
	Name:      "sparc64",
	Thechar:   'u',
	UnaryDst:  unaryDst,
	Minlc:     4,
	Ptrsize:   8,
	Regsize:   8,
}
<commit_msg>cmd/internal/obj/sparc64: add preprocess stub<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sparc64

import (
	"cmd/internal/obj"
	"encoding/binary"
)

// TODO(aram):
func preprocess(ctxt *obj.Link, cursym *obj.LSym) {}

var unaryDst = map[int]bool{
	AWORD:   true,
	ADWORD:  true,
	ARDPC:   true,
	ARDTICK: true,
	ARDCCR:  true,
}

var Linksparc64 = obj.LinkArch{
	ByteOrder:  binary.BigEndian,
	Name:       "sparc64",
	Thechar:    'u',
	Preprocess: preprocess,
	UnaryDst:   unaryDst,
	Minlc:      4,
	Ptrsize:    8,
	Regsize:    8,
}
<|endoftext|>