<commit_before>package main

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

	"code.cloudfoundry.org/lager"
	"github.com/concourse/baggageclaim/baggageclaimcmd"
	"github.com/concourse/bin/bindata"
	"github.com/concourse/flag"
	concourseWorker "github.com/concourse/worker"
	"github.com/concourse/worker/beacon"
	"github.com/concourse/worker/reaper"
	workerConfig "github.com/concourse/worker/start"
	"github.com/concourse/worker/sweeper"
	"github.com/concourse/worker/tsa"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/grouper"
	"github.com/tedsuo/ifrit/sigmon"
)

type WorkerCommand struct {
	Worker workerConfig.Config

	TSA tsa.Config `group:"TSA Configuration" namespace:"tsa"`

	Certs Certs

	WorkDir flag.Dir `long:"work-dir" required:"true" description:"Directory in which to place container data."`

	BindIP   flag.IP `long:"bind-ip"   default:"127.0.0.1" description:"IP address on which to listen for the Garden server."`
	BindPort uint16  `long:"bind-port" default:"7777"      description:"Port on which to listen for the Garden server."`
	PeerIP   flag.IP `long:"peer-ip" description:"IP used to reach this worker from the ATC nodes."`

	Garden GardenBackend `group:"Garden Configuration" namespace:"garden"`

	Baggageclaim baggageclaimcmd.BaggageclaimCommand `group:"Baggageclaim Configuration" namespace:"baggageclaim"`

	Logger  flag.Lager
	Metrics struct {
		YellerAPIKey      string `long:"yeller-api-key"     description:"Yeller API key. If specified, all errors logged will be emitted."`
		YellerEnvironment string `long:"yeller-environment" description:"Environment to tag on all Yeller events emitted."`
	} `group:"Metrics & Diagnostics"`
}

func (cmd *WorkerCommand) Execute(args []string) error {
	runner, err := cmd.Runner(args)
	if err != nil {
		return err
	}

	return <-ifrit.Invoke(sigmon.New(runner)).Wait()
}

func (cmd *WorkerCommand) Runner(args []string) (ifrit.Runner, error) {
	logger, _ := cmd.Logger.Logger("worker")

	hasAssets, err := cmd.setup(logger.Session("setup"))
	if err != nil {
		return nil, err
	}

	worker, gardenRunner, err := cmd.gardenRunner(logger.Session("garden"), hasAssets)
	if err != nil {
		return nil, err
	}

	worker.Version = WorkerVersion

	baggageclaimRunner, err := cmd.baggageclaimRunner(logger.Session("baggageclaim"), hasAssets)
	if err != nil {
		return nil, err
	}

	members := grouper.Members{
		{
			Name:   "garden",
			Runner: gardenRunner,
		},
		{
			Name:   "baggageclaim",
			Runner: baggageclaimRunner,
		},
	}

	if cmd.TSA.WorkerPrivateKey.PrivateKey != nil {
		beaconConfig := beacon.Config{
			TSAConfig: cmd.TSA,
		}

		if cmd.PeerIP.IP != nil {
			worker.GardenAddr = fmt.Sprintf("%s:%d", cmd.PeerIP.IP, cmd.BindPort)
			worker.BaggageclaimURL = fmt.Sprintf("http://%s:%d", cmd.PeerIP.IP, cmd.Baggageclaim.BindPort)

			beaconConfig.RegistrationMode = "direct"
		} else {
			beaconConfig.RegistrationMode = "forward"
			beaconConfig.GardenForwardAddr = fmt.Sprintf("%s:%d", cmd.BindIP.IP, cmd.BindPort)
			beaconConfig.BaggageclaimForwardAddr = fmt.Sprintf("%s:%d", cmd.Baggageclaim.BindIP.IP, cmd.Baggageclaim.BindPort)

			worker.GardenAddr = beaconConfig.GardenForwardAddr
			worker.BaggageclaimURL = fmt.Sprintf("http://%s", beaconConfig.BaggageclaimForwardAddr)
		}

		members = append(members, grouper.Member{
			Name: "beacon",
			Runner: concourseWorker.BeaconRunner(
				logger.Session("beacon"),
				worker,
				beaconConfig,
			),
		})
		members = append(members, grouper.Member{
			Name: "reaper",
			Runner: reaper.NewReaperRunner(
				logger.Session("reaper"),
				worker.GardenAddr,
				"7799",
			),
		})

		members = append(members, grouper.Member{
			Name: "sweep-container",
			Runner: sweeper.NewSweeperRunner(
				logger,
				worker,
				beaconConfig,
			),
		})
	}

	return grouper.NewParallel(os.Interrupt, members), nil
}

func (cmd *WorkerCommand) assetPath(paths ...string) string {
	return filepath.Join(append([]string{cmd.WorkDir.Path(), Version, "assets"}, paths...)...)
}

func (cmd *WorkerCommand) setup(logger lager.Logger) (bool, error) {
	okMarker := cmd.assetPath("ok")

	_, err := os.Stat(okMarker)
	if err == nil {
		logger.Info("already-done")
		return true, nil
	}

	_, err = bindata.AssetDir("assets")
	if err != nil {
		logger.Info("no-assets")
		return false, nil
	}

	logger.Info("unpacking")

	err = bindata.RestoreAssets(filepath.Split(cmd.assetPath()))
	if err != nil {
		logger.Error("failed-to-unpack", err)
		return false, err
	}

	_, err = os.Stat(cmd.assetPath())
	if os.IsNotExist(err) {
		logger.Info("no-assets")
		return false, nil
	}

	ok, err := os.Create(okMarker)
	if err != nil {
		logger.Error("failed-to-create-ok-marker", err)
		return false, err
	}

	err = ok.Close()
	if err != nil {
		logger.Error("failed-to-close-ok-marker", err)
		return false, err
	}

	logger.Info("done")

	return true, nil
}

func (cmd *WorkerCommand) workerName() (string, error) {
	if cmd.Worker.Name != "" {
		return cmd.Worker.Name, nil
	}

	return os.Hostname()
}

func (cmd *WorkerCommand) baggageclaimRunner(logger lager.Logger, hasAssets bool) (ifrit.Runner, error) {
	volumesDir := filepath.Join(cmd.WorkDir.Path(), "volumes")

	err := os.MkdirAll(volumesDir, 0755)
	if err != nil {
		return nil, err
	}

	cmd.Baggageclaim.Metrics = cmd.Metrics
	cmd.Baggageclaim.VolumesDir = flag.Dir(volumesDir)

	cmd.Baggageclaim.OverlaysDir = filepath.Join(cmd.WorkDir.Path(), "overlays")

	if hasAssets {
		cmd.Baggageclaim.MkfsBin = cmd.assetPath("btrfs", "mkfs.btrfs")
		cmd.Baggageclaim.BtrfsBin = cmd.assetPath("btrfs", "btrfs")
	}

	return cmd.Baggageclaim.Runner(nil)
}
<commit_msg>renaming<commit_after>package main

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

	"code.cloudfoundry.org/lager"
	"github.com/concourse/baggageclaim/baggageclaimcmd"
	"github.com/concourse/bin/bindata"
	"github.com/concourse/flag"
	concourseWorker "github.com/concourse/worker"
	"github.com/concourse/worker/beacon"
	"github.com/concourse/worker/reaper"
	workerConfig "github.com/concourse/worker/start"
	"github.com/concourse/worker/sweeper"
	"github.com/concourse/worker/tsa"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/grouper"
	"github.com/tedsuo/ifrit/sigmon"
)

type WorkerCommand struct {
	Worker workerConfig.Config

	TSA tsa.Config `group:"TSA Configuration" namespace:"tsa"`

	Certs Certs

	WorkDir flag.Dir `long:"work-dir" required:"true" description:"Directory in which to place container data."`

	BindIP   flag.IP `long:"bind-ip"   default:"127.0.0.1" description:"IP address on which to listen for the Garden server."`
	BindPort uint16  `long:"bind-port" default:"7777"      description:"Port on which to listen for the Garden server."`
	PeerIP   flag.IP `long:"peer-ip" description:"IP used to reach this worker from the ATC nodes."`

	Garden GardenBackend `group:"Garden Configuration" namespace:"garden"`

	Baggageclaim baggageclaimcmd.BaggageclaimCommand `group:"Baggageclaim Configuration" namespace:"baggageclaim"`

	Logger  flag.Lager
	Metrics struct {
		YellerAPIKey      string `long:"yeller-api-key"     description:"Yeller API key. If specified, all errors logged will be emitted."`
		YellerEnvironment string `long:"yeller-environment" description:"Environment to tag on all Yeller events emitted."`
	} `group:"Metrics & Diagnostics"`
}

func (cmd *WorkerCommand) Execute(args []string) error {
	runner, err := cmd.Runner(args)
	if err != nil {
		return err
	}

	return <-ifrit.Invoke(sigmon.New(runner)).Wait()
}

func (cmd *WorkerCommand) Runner(args []string) (ifrit.Runner, error) {
	logger, _ := cmd.Logger.Logger("worker")

	hasAssets, err := cmd.setup(logger.Session("setup"))
	if err != nil {
		return nil, err
	}

	worker, gardenRunner, err := cmd.gardenRunner(logger.Session("garden"), hasAssets)
	if err != nil {
		return nil, err
	}

	worker.Version = WorkerVersion

	baggageclaimRunner, err := cmd.baggageclaimRunner(logger.Session("baggageclaim"), hasAssets)
	if err != nil {
		return nil, err
	}

	members := grouper.Members{
		{
			Name:   "garden",
			Runner: gardenRunner,
		},
		{
			Name:   "baggageclaim",
			Runner: baggageclaimRunner,
		},
	}

	if cmd.TSA.WorkerPrivateKey.PrivateKey != nil {
		beaconConfig := beacon.Config{
			TSAConfig: cmd.TSA,
		}

		if cmd.PeerIP.IP != nil {
			worker.GardenAddr = fmt.Sprintf("%s:%d", cmd.PeerIP.IP, cmd.BindPort)
			worker.BaggageclaimURL = fmt.Sprintf("http://%s:%d", cmd.PeerIP.IP, cmd.Baggageclaim.BindPort)

			beaconConfig.RegistrationMode = "direct"
		} else {
			beaconConfig.RegistrationMode = "forward"
			beaconConfig.GardenForwardAddr = fmt.Sprintf("%s:%d", cmd.BindIP.IP, cmd.BindPort)
			beaconConfig.BaggageclaimForwardAddr = fmt.Sprintf("%s:%d", cmd.Baggageclaim.BindIP.IP, cmd.Baggageclaim.BindPort)

			worker.GardenAddr = beaconConfig.GardenForwardAddr
			worker.BaggageclaimURL = fmt.Sprintf("http://%s", beaconConfig.BaggageclaimForwardAddr)
		}

		members = append(members, grouper.Member{
			Name: "beacon",
			Runner: concourseWorker.BeaconRunner(
				logger.Session("beacon"),
				worker,
				beaconConfig,
			),
		})
		members = append(members, grouper.Member{
			Name: "reaper",
			Runner: reaper.NewReaperRunner(
				logger.Session("reaper"),
				worker.GardenAddr,
				"7799",
			),
		})

		members = append(members, grouper.Member{
			Name: "sweeper",
			Runner: sweeper.NewSweeperRunner(
				logger,
				worker,
				beaconConfig,
			),
		})
	}

	return grouper.NewParallel(os.Interrupt, members), nil
}

func (cmd *WorkerCommand) assetPath(paths ...string) string {
	return filepath.Join(append([]string{cmd.WorkDir.Path(), Version, "assets"}, paths...)...)
}

func (cmd *WorkerCommand) setup(logger lager.Logger) (bool, error) {
	okMarker := cmd.assetPath("ok")

	_, err := os.Stat(okMarker)
	if err == nil {
		logger.Info("already-done")
		return true, nil
	}

	_, err = bindata.AssetDir("assets")
	if err != nil {
		logger.Info("no-assets")
		return false, nil
	}

	logger.Info("unpacking")

	err = bindata.RestoreAssets(filepath.Split(cmd.assetPath()))
	if err != nil {
		logger.Error("failed-to-unpack", err)
		return false, err
	}

	_, err = os.Stat(cmd.assetPath())
	if os.IsNotExist(err) {
		logger.Info("no-assets")
		return false, nil
	}

	ok, err := os.Create(okMarker)
	if err != nil {
		logger.Error("failed-to-create-ok-marker", err)
		return false, err
	}

	err = ok.Close()
	if err != nil {
		logger.Error("failed-to-close-ok-marker", err)
		return false, err
	}

	logger.Info("done")

	return true, nil
}

func (cmd *WorkerCommand) workerName() (string, error) {
	if cmd.Worker.Name != "" {
		return cmd.Worker.Name, nil
	}

	return os.Hostname()
}

func (cmd *WorkerCommand) baggageclaimRunner(logger lager.Logger, hasAssets bool) (ifrit.Runner, error) {
	volumesDir := filepath.Join(cmd.WorkDir.Path(), "volumes")

	err := os.MkdirAll(volumesDir, 0755)
	if err != nil {
		return nil, err
	}

	cmd.Baggageclaim.Metrics = cmd.Metrics
	cmd.Baggageclaim.VolumesDir = flag.Dir(volumesDir)

	cmd.Baggageclaim.OverlaysDir = filepath.Join(cmd.WorkDir.Path(), "overlays")

	if hasAssets {
		cmd.Baggageclaim.MkfsBin = cmd.assetPath("btrfs", "mkfs.btrfs")
		cmd.Baggageclaim.BtrfsBin = cmd.assetPath("btrfs", "btrfs")
	}

	return cmd.Baggageclaim.Runner(nil)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/asdine/storm"

	"gopkg.in/natefinch/lumberjack.v2"

	"github.com/filebrowser/filebrowser"
	"github.com/filebrowser/filebrowser/bolt"
	h "github.com/filebrowser/filebrowser/http"
	"github.com/filebrowser/filebrowser/staticgen"
	"github.com/hacdias/fileutils"
	flag "github.com/spf13/pflag"
	"github.com/spf13/viper"
)

var (
	addr            string
	config          string
	database        string
	scope           string
	commands        string
	logfile         string
	staticg         string
	locale          string
	baseurl         string
	prefixurl       string
	viewMode        string
	recaptchakey    string
	recaptchasecret string
	port            int
	noAuth          bool
	allowCommands   bool
	allowEdit       bool
	allowNew        bool
	allowPublish    bool
	showVer         bool
	alterRecaptcha  bool
)

func init() {
	flag.StringVarP(&config, "config", "c", "", "Configuration file")
	flag.IntVarP(&port, "port", "p", 0, "HTTP Port (default is random)")
	flag.StringVarP(&addr, "address", "a", "", "Address to listen to (default is all of them)")
	flag.StringVarP(&database, "database", "d", "./filebrowser.db", "Database file")
	flag.StringVarP(&logfile, "log", "l", "stdout", "Errors logger; can use 'stdout', 'stderr' or file")
	flag.StringVarP(&scope, "scope", "s", ".", "Default scope option for new users")
	flag.StringVarP(&baseurl, "baseurl", "b", "", "Base URL")
	flag.StringVar(&commands, "commands", "git svn hg", "Default commands option for new users")
	flag.StringVar(&prefixurl, "prefixurl", "", "Prefix URL")
	flag.StringVar(&viewMode, "view-mode", "mosaic", "Default view mode for new users")
	flag.StringVar(&recaptchakey, "recaptcha-key", "", "ReCaptcha site key")
	flag.StringVar(&recaptchasecret, "recaptcha-secret", "", "ReCaptcha secret")
	flag.BoolVar(&allowCommands, "allow-commands", true, "Default allow commands option for new users")
	flag.BoolVar(&allowEdit, "allow-edit", true, "Default allow edit option for new users")
	flag.BoolVar(&allowPublish, "allow-publish", true, "Default allow publish option for new users")
	flag.BoolVar(&allowNew, "allow-new", true, "Default allow new option for new users")
	flag.BoolVar(&noAuth, "no-auth", false, "Disables authentication")
	flag.BoolVar(&alterRecaptcha, "alternative-recaptcha", false, "Use recaptcha.net for serving and handling, useful in China")
	flag.StringVar(&locale, "locale", "", "Default locale for new users, set it empty to enable auto detect from browser")
	flag.StringVar(&staticg, "staticgen", "", "Static Generator you want to enable")
	flag.BoolVarP(&showVer, "version", "v", false, "Show version")
}

func setupViper() {
	viper.SetDefault("Address", "")
	viper.SetDefault("Port", "0")
	viper.SetDefault("Database", "./filebrowser.db")
	viper.SetDefault("Scope", ".")
	viper.SetDefault("Logger", "stdout")
	viper.SetDefault("Commands", []string{"git", "svn", "hg"})
	viper.SetDefault("AllowCommmands", true)
	viper.SetDefault("AllowEdit", true)
	viper.SetDefault("AllowNew", true)
	viper.SetDefault("AllowPublish", true)
	viper.SetDefault("StaticGen", "")
	viper.SetDefault("Locale", "")
	viper.SetDefault("NoAuth", false)
	viper.SetDefault("BaseURL", "")
	viper.SetDefault("PrefixURL", "")
	viper.SetDefault("ViewMode", filebrowser.MosaicViewMode)
	viper.SetDefault("AlternativeRecaptcha", false)
	viper.SetDefault("ReCaptchaKey", "")
	viper.SetDefault("ReCaptchaSecret", "")

	viper.BindPFlag("Port", flag.Lookup("port"))
	viper.BindPFlag("Address", flag.Lookup("address"))
	viper.BindPFlag("Database", flag.Lookup("database"))
	viper.BindPFlag("Scope", flag.Lookup("scope"))
	viper.BindPFlag("Logger", flag.Lookup("log"))
	viper.BindPFlag("Commands", flag.Lookup("commands"))
	viper.BindPFlag("AllowCommands", flag.Lookup("allow-commands"))
	viper.BindPFlag("AllowEdit", flag.Lookup("allow-edit"))
	viper.BindPFlag("AlowNew", flag.Lookup("allow-new"))
	viper.BindPFlag("AllowPublish", flag.Lookup("allow-publish"))
	viper.BindPFlag("Locale", flag.Lookup("locale"))
	viper.BindPFlag("StaticGen", flag.Lookup("staticgen"))
	viper.BindPFlag("NoAuth", flag.Lookup("no-auth"))
	viper.BindPFlag("BaseURL", flag.Lookup("baseurl"))
	viper.BindPFlag("PrefixURL", flag.Lookup("prefixurl"))
	viper.BindPFlag("ViewMode", flag.Lookup("view-mode"))
	viper.BindPFlag("AlternativeRecaptcha", flag.Lookup("alternative-recaptcha"))
	viper.BindPFlag("ReCaptchaKey", flag.Lookup("recaptcha-key"))
	viper.BindPFlag("ReCaptchaSecret", flag.Lookup("recaptcha-secret"))

	viper.SetConfigName("filebrowser")
	viper.AddConfigPath(".")
}

func printVersion() {
	fmt.Println("filebrowser version", filebrowser.Version)
	os.Exit(0)
}

func main() {
	setupViper()
	flag.Parse()

	if showVer {
		printVersion()
	}

	// Add a configuration file if set.
	if config != "" {
		ext := filepath.Ext(config)
		dir := filepath.Dir(config)
		config = strings.TrimSuffix(config, ext)

		if dir != "" {
			viper.AddConfigPath(dir)
			config = strings.TrimPrefix(config, dir)
		}

		viper.SetConfigName(config)
	}

	// Read configuration from a file if exists.
	err := viper.ReadInConfig()
	if err != nil {
		if _, ok := err.(viper.ConfigParseError); ok {
			panic(err)
		}
	}

	// Set up process log before anything bad happens.
	switch viper.GetString("Logger") {
	case "stdout":
		log.SetOutput(os.Stdout)
	case "stderr":
		log.SetOutput(os.Stderr)
	case "":
		log.SetOutput(ioutil.Discard)
	default:
		log.SetOutput(&lumberjack.Logger{
			Filename:   logfile,
			MaxSize:    100,
			MaxAge:     14,
			MaxBackups: 10,
		})
	}

	// Builds the address and a listener.
	laddr := viper.GetString("Address") + ":" + viper.GetString("Port")
	listener, err := net.Listen("tcp", laddr)
	if err != nil {
		log.Fatal(err)
	}

	// Tell the user the port in which is listening.
	fmt.Println("Listening on", listener.Addr().String())

	// Starts the server.
	if err := http.Serve(listener, handler()); err != nil {
		log.Fatal(err)
	}
}

func handler() http.Handler {
	db, err := storm.Open(viper.GetString("Database"))
	if err != nil {
		log.Fatal(err)
	}

	recaptchaHost := "https://www.google.com"
	if viper.GetBool("AlternativeRecaptcha") {
		recaptchaHost = "https://recaptcha.net"
	}

	fm := &filebrowser.FileBrowser{
		NoAuth:          viper.GetBool("NoAuth"),
		BaseURL:         viper.GetString("BaseURL"),
		PrefixURL:       viper.GetString("PrefixURL"),
		ReCaptchaHost:   recaptchaHost,
		ReCaptchaKey:    viper.GetString("ReCaptchaKey"),
		ReCaptchaSecret: viper.GetString("ReCaptchaSecret"),
		DefaultUser: &filebrowser.User{
			AllowCommands: viper.GetBool("AllowCommands"),
			AllowEdit:     viper.GetBool("AllowEdit"),
			AllowNew:      viper.GetBool("AllowNew"),
			AllowPublish:  viper.GetBool("AllowPublish"),
			Commands:      viper.GetStringSlice("Commands"),
			Rules:         []*filebrowser.Rule{},
			Locale:        viper.GetString("Locale"),
			CSS:           "",
			Scope:         viper.GetString("Scope"),
			FileSystem:    fileutils.Dir(viper.GetString("Scope")),
			ViewMode:      viper.GetString("ViewMode"),
		},
		Store: &filebrowser.Store{
			Config: bolt.ConfigStore{DB: db},
			Users:  bolt.UsersStore{DB: db},
			Share:  bolt.ShareStore{DB: db},
		},
		NewFS: func(scope string) filebrowser.FileSystem {
			return fileutils.Dir(scope)
		},
	}

	err = fm.Setup()
	if err != nil {
		log.Fatal(err)
	}

	switch viper.GetString("StaticGen") {
	case "hugo":
		hugo := &staticgen.Hugo{
			Root:        viper.GetString("Scope"),
			Public:      filepath.Join(viper.GetString("Scope"), "public"),
			Args:        []string{},
			CleanPublic: true,
		}

		if err = fm.Attach(hugo); err != nil {
			log.Fatal(err)
		}
	case "jekyll":
		jekyll := &staticgen.Jekyll{
			Root:        viper.GetString("Scope"),
			Public:      filepath.Join(viper.GetString("Scope"), "_site"),
			Args:        []string{"build"},
			CleanPublic: true,
		}

		if err = fm.Attach(jekyll); err != nil {
			log.Fatal(err)
		}
	}

	return h.Handler(fm)
}
<commit_msg>Fix typo preventing "--allow-edit" from being set (#392)<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/asdine/storm"

	"gopkg.in/natefinch/lumberjack.v2"

	"github.com/filebrowser/filebrowser"
	"github.com/filebrowser/filebrowser/bolt"
	h "github.com/filebrowser/filebrowser/http"
	"github.com/filebrowser/filebrowser/staticgen"
	"github.com/hacdias/fileutils"
	flag "github.com/spf13/pflag"
	"github.com/spf13/viper"
)

var (
	addr            string
	config          string
	database        string
	scope           string
	commands        string
	logfile         string
	staticg         string
	locale          string
	baseurl         string
	prefixurl       string
	viewMode        string
	recaptchakey    string
	recaptchasecret string
	port            int
	noAuth          bool
	allowCommands   bool
	allowEdit       bool
	allowNew        bool
	allowPublish    bool
	showVer         bool
	alterRecaptcha  bool
)

func init() {
	flag.StringVarP(&config, "config", "c", "", "Configuration file")
	flag.IntVarP(&port, "port", "p", 0, "HTTP Port (default is random)")
	flag.StringVarP(&addr, "address", "a", "", "Address to listen to (default is all of them)")
	flag.StringVarP(&database, "database", "d", "./filebrowser.db", "Database file")
	flag.StringVarP(&logfile, "log", "l", "stdout", "Errors logger; can use 'stdout', 'stderr' or file")
	flag.StringVarP(&scope, "scope", "s", ".", "Default scope option for new users")
	flag.StringVarP(&baseurl, "baseurl", "b", "", "Base URL")
	flag.StringVar(&commands, "commands", "git svn hg", "Default commands option for new users")
	flag.StringVar(&prefixurl, "prefixurl", "", "Prefix URL")
	flag.StringVar(&viewMode, "view-mode", "mosaic", "Default view mode for new users")
	flag.StringVar(&recaptchakey, "recaptcha-key", "", "ReCaptcha site key")
	flag.StringVar(&recaptchasecret, "recaptcha-secret", "", "ReCaptcha secret")
	flag.BoolVar(&allowCommands, "allow-commands", true, "Default allow commands option for new users")
	flag.BoolVar(&allowEdit, "allow-edit", true, "Default allow edit option for new users")
	flag.BoolVar(&allowPublish, "allow-publish", true, "Default allow publish option for new users")
	flag.BoolVar(&allowNew, "allow-new", true, "Default allow new option for new users")
	flag.BoolVar(&noAuth, "no-auth", false, "Disables authentication")
	flag.BoolVar(&alterRecaptcha, "alternative-recaptcha", false, "Use recaptcha.net for serving and handling, useful in China")
	flag.StringVar(&locale, "locale", "", "Default locale for new users, set it empty to enable auto detect from browser")
	flag.StringVar(&staticg, "staticgen", "", "Static Generator you want to enable")
	flag.BoolVarP(&showVer, "version", "v", false, "Show version")
}

func setupViper() {
	viper.SetDefault("Address", "")
	viper.SetDefault("Port", "0")
	viper.SetDefault("Database", "./filebrowser.db")
	viper.SetDefault("Scope", ".")
	viper.SetDefault("Logger", "stdout")
	viper.SetDefault("Commands", []string{"git", "svn", "hg"})
	viper.SetDefault("AllowCommmands", true)
	viper.SetDefault("AllowEdit", true)
	viper.SetDefault("AllowNew", true)
	viper.SetDefault("AllowPublish", true)
	viper.SetDefault("StaticGen", "")
	viper.SetDefault("Locale", "")
	viper.SetDefault("NoAuth", false)
	viper.SetDefault("BaseURL", "")
	viper.SetDefault("PrefixURL", "")
	viper.SetDefault("ViewMode", filebrowser.MosaicViewMode)
	viper.SetDefault("AlternativeRecaptcha", false)
	viper.SetDefault("ReCaptchaKey", "")
	viper.SetDefault("ReCaptchaSecret", "")

	viper.BindPFlag("Port", flag.Lookup("port"))
	viper.BindPFlag("Address", flag.Lookup("address"))
	viper.BindPFlag("Database", flag.Lookup("database"))
	viper.BindPFlag("Scope", flag.Lookup("scope"))
	viper.BindPFlag("Logger", flag.Lookup("log"))
	viper.BindPFlag("Commands", flag.Lookup("commands"))
	viper.BindPFlag("AllowCommands", flag.Lookup("allow-commands"))
	viper.BindPFlag("AllowEdit", flag.Lookup("allow-edit"))
	viper.BindPFlag("AllowNew", flag.Lookup("allow-new"))
	viper.BindPFlag("AllowPublish", flag.Lookup("allow-publish"))
	viper.BindPFlag("Locale", flag.Lookup("locale"))
	viper.BindPFlag("StaticGen", flag.Lookup("staticgen"))
	viper.BindPFlag("NoAuth", flag.Lookup("no-auth"))
	viper.BindPFlag("BaseURL", flag.Lookup("baseurl"))
	viper.BindPFlag("PrefixURL", flag.Lookup("prefixurl"))
	viper.BindPFlag("ViewMode", flag.Lookup("view-mode"))
	viper.BindPFlag("AlternativeRecaptcha", flag.Lookup("alternative-recaptcha"))
	viper.BindPFlag("ReCaptchaKey", flag.Lookup("recaptcha-key"))
	viper.BindPFlag("ReCaptchaSecret", flag.Lookup("recaptcha-secret"))

	viper.SetConfigName("filebrowser")
	viper.AddConfigPath(".")
}

func printVersion() {
	fmt.Println("filebrowser version", filebrowser.Version)
	os.Exit(0)
}

func main() {
	setupViper()
	flag.Parse()

	if showVer {
		printVersion()
	}

	// Add a configuration file if set.
	if config != "" {
		ext := filepath.Ext(config)
		dir := filepath.Dir(config)
		config = strings.TrimSuffix(config, ext)

		if dir != "" {
			viper.AddConfigPath(dir)
			config = strings.TrimPrefix(config, dir)
		}

		viper.SetConfigName(config)
	}

	// Read configuration from a file if exists.
	err := viper.ReadInConfig()
	if err != nil {
		if _, ok := err.(viper.ConfigParseError); ok {
			panic(err)
		}
	}

	// Set up process log before anything bad happens.
	switch viper.GetString("Logger") {
	case "stdout":
		log.SetOutput(os.Stdout)
	case "stderr":
		log.SetOutput(os.Stderr)
	case "":
		log.SetOutput(ioutil.Discard)
	default:
		log.SetOutput(&lumberjack.Logger{
			Filename:   logfile,
			MaxSize:    100,
			MaxAge:     14,
			MaxBackups: 10,
		})
	}

	// Builds the address and a listener.
	laddr := viper.GetString("Address") + ":" + viper.GetString("Port")
	listener, err := net.Listen("tcp", laddr)
	if err != nil {
		log.Fatal(err)
	}

	// Tell the user the port in which is listening.
	fmt.Println("Listening on", listener.Addr().String())

	// Starts the server.
	if err := http.Serve(listener, handler()); err != nil {
		log.Fatal(err)
	}
}

func handler() http.Handler {
	db, err := storm.Open(viper.GetString("Database"))
	if err != nil {
		log.Fatal(err)
	}

	recaptchaHost := "https://www.google.com"
	if viper.GetBool("AlternativeRecaptcha") {
		recaptchaHost = "https://recaptcha.net"
	}

	fm := &filebrowser.FileBrowser{
		NoAuth:          viper.GetBool("NoAuth"),
		BaseURL:         viper.GetString("BaseURL"),
		PrefixURL:       viper.GetString("PrefixURL"),
		ReCaptchaHost:   recaptchaHost,
		ReCaptchaKey:    viper.GetString("ReCaptchaKey"),
		ReCaptchaSecret: viper.GetString("ReCaptchaSecret"),
		DefaultUser: &filebrowser.User{
			AllowCommands: viper.GetBool("AllowCommands"),
			AllowEdit:     viper.GetBool("AllowEdit"),
			AllowNew:      viper.GetBool("AllowNew"),
			AllowPublish:  viper.GetBool("AllowPublish"),
			Commands:      viper.GetStringSlice("Commands"),
			Rules:         []*filebrowser.Rule{},
			Locale:        viper.GetString("Locale"),
			CSS:           "",
			Scope:         viper.GetString("Scope"),
			FileSystem:    fileutils.Dir(viper.GetString("Scope")),
			ViewMode:      viper.GetString("ViewMode"),
		},
		Store: &filebrowser.Store{
			Config: bolt.ConfigStore{DB: db},
			Users:  bolt.UsersStore{DB: db},
			Share:  bolt.ShareStore{DB: db},
		},
		NewFS: func(scope string) filebrowser.FileSystem {
			return fileutils.Dir(scope)
		},
	}

	err = fm.Setup()
	if err != nil {
		log.Fatal(err)
	}

	switch viper.GetString("StaticGen") {
	case "hugo":
		hugo := &staticgen.Hugo{
			Root:        viper.GetString("Scope"),
			Public:      filepath.Join(viper.GetString("Scope"), "public"),
			Args:        []string{},
			CleanPublic: true,
		}

		if err = fm.Attach(hugo); err != nil {
			log.Fatal(err)
		}
	case "jekyll":
		jekyll := &staticgen.Jekyll{
			Root:        viper.GetString("Scope"),
			Public:      filepath.Join(viper.GetString("Scope"), "_site"),
			Args:        []string{"build"},
			CleanPublic: true,
		}

		if err = fm.Attach(jekyll); err != nil {
			log.Fatal(err)
		}
	}

	return h.Handler(fm)
}
<|endoftext|>


<commit_before>package main_test

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"net/url"
	"testing"

	"github.com/influxdb/influxdb/client"
	main "github.com/influxdb/influxdb/cmd/influx"
)

func TestParseCommand_CommandsExist(t *testing.T) {
	t.Parallel()
	c := main.CommandLine{}
	tests := []struct {
		cmd string
	}{
		{cmd: "gopher"},
		{cmd: "connect"},
		{cmd: "help"},
		{cmd: "history"},
		{cmd: "pretty"},
		{cmd: "use"},
		{cmd: ""}, // test that a blank command just returns
	}
	for _, test := range tests {
		if !c.ParseCommand(test.cmd) {
			t.Fatalf(`Command failed for %q.`, test.cmd)
		}
	}
}

func TestParseCommand_TogglePretty(t *testing.T) {
	t.Parallel()
	c := main.CommandLine{}
	if c.Pretty {
		t.Fatalf(`Pretty should be false.`)
	}
	c.ParseCommand("pretty")
	if !c.Pretty {
		t.Fatalf(`Pretty should be true.`)
	}
	c.ParseCommand("pretty")
	if c.Pretty {
		t.Fatalf(`Pretty should be false.`)
	}
}

func TestParseCommand_Exit(t *testing.T) {
	t.Parallel()
	c := main.CommandLine{}
	tests := []struct {
		cmd string
	}{
		{cmd: "exit"},
		{cmd: " exit"},
		{cmd: "exit "},
		{cmd: "Exit "},
	}

	for _, test := range tests {
		if c.ParseCommand(test.cmd) {
			t.Fatalf(`Command "exit" failed for %q.`, test.cmd)
		}
	}
}

func TestParseCommand_Use(t *testing.T) {
	t.Parallel()
	c := main.CommandLine{}
	tests := []struct {
		cmd string
	}{
		{cmd: "use db"},
		{cmd: " use db"},
		{cmd: "use db "},
		{cmd: "use db;"},
		{cmd: "use db; "},
		{cmd: "Use db"},
	}

	for _, test := range tests {
		if !c.ParseCommand(test.cmd) {
			t.Fatalf(`Command "use" failed for %q.`, test.cmd)
		}

		if c.Database != "db" {
			t.Fatalf(`Command "use" changed database to %q. Expected db`, c.Database)
		}
	}
}

func TestParseCommand_Consistency(t *testing.T) {
	t.Parallel()
	c := main.CommandLine{}
	tests := []struct {
		cmd string
	}{
		{cmd: "consistency one"},
		{cmd: " consistency one"},
		{cmd: "consistency one "},
		{cmd: "consistency one;"},
		{cmd: "consistency one; "},
		{cmd: "Consistency one"},
	}

	for _, test := range tests {
		if !c.ParseCommand(test.cmd) {
			t.Fatalf(`Command "consistency" failed for %q.`, test.cmd)
		}

		if c.WriteConsistency != "one" {
			t.Fatalf(`Command "consistency" changed consistency to %q. Expected one`, c.WriteConsistency)
		}
	}
}

func TestParseCommand_Insert(t *testing.T) {
	t.Parallel()
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var data client.Response
		w.WriteHeader(http.StatusNoContent)
		_ = json.NewEncoder(w).Encode(data)
	}))
	defer ts.Close()

	u, _ := url.Parse(ts.URL)
	config := client.Config{URL: *u}
	c, err := client.NewClient(config)
	if err != nil {
		t.Fatalf("unexpected error.  expected %v, actual %v", nil, err)
	}
	m := main.CommandLine{Client: c}

	tests := []struct {
		cmd string
	}{
		{cmd: "INSERT cpu,host=serverA,region=us-west value=1.0"},
		{cmd: " INSERT cpu,host=serverA,region=us-west value=1.0"},
		{cmd: "INSERT   cpu,host=serverA,region=us-west value=1.0"},
		{cmd: "insert cpu,host=serverA,region=us-west    value=1.0    "},
		{cmd: "insert"},
		{cmd: "Insert "},
		{cmd: "insert c"},
		{cmd: "insert int"},
	}

	for _, test := range tests {
		if !m.ParseCommand(test.cmd) {
			t.Fatalf(`Command "insert" failed for %q.`, test.cmd)
		}
	}
}

func TestParseCommand_InsertInto(t *testing.T) {
	t.Parallel()
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var data client.Response
		w.WriteHeader(http.StatusNoContent)
		_ = json.NewEncoder(w).Encode(data)
	}))
	defer ts.Close()

	u, _ := url.Parse(ts.URL)
	config := client.Config{URL: *u}
	c, err := client.NewClient(config)
	if err != nil {
		t.Fatalf("unexpected error.  expected %v, actual %v", nil, err)
	}
	m := main.CommandLine{Client: c}

	tests := []struct {
		cmd, db, rp string
	}{
		{
			cmd: `INSERT INTO test cpu,host=serverA,region=us-west value=1.0`,
			db:  "",
			rp:  "test",
		},
		{
			cmd: ` INSERT INTO .test cpu,host=serverA,region=us-west value=1.0`,
			db:  "",
			rp:  "test",
		},
		{
			cmd: `INSERT INTO   "test test" cpu,host=serverA,region=us-west value=1.0`,
			db:  "",
			rp:  "test test",
		},
		{
			cmd: `Insert iNTO test.test cpu,host=serverA,region=us-west value=1.0`,
			db:  "test",
			rp:  "test",
		},
		{
			cmd: `insert into "test test" cpu,host=serverA,region=us-west value=1.0`,
			db:  "test",
			rp:  "test test",
		},
		{
			cmd: `insert into "d b"."test test" cpu,host=serverA,region=us-west value=1.0`,
			db:  "d b",
			rp:  "test test",
		},
	}

	for _, test := range tests {
		if !m.ParseCommand(test.cmd) {
			t.Fatalf(`Command "insert into" failed for %q.`, test.cmd)
		}
		if m.Database != test.db {
			t.Fatalf(`Command "insert into" db parsing failed, expected: %q, actual: %q`, test.db, m.Database)
		}
		if m.RetentionPolicy != test.rp {
			t.Fatalf(`Command "insert into" rp parsing failed, expected: %q, actual: %q`, test.rp, m.RetentionPolicy)
		}
	}
}

func TestParseCommand_History(t *testing.T) {
	t.Parallel()
	c := main.CommandLine{}
	tests := []struct {
		cmd string
	}{
		{cmd: "history"},
		{cmd: " history"},
		{cmd: "history "},
		{cmd: "History "},
	}

	for _, test := range tests {
		if !c.ParseCommand(test.cmd) {
			t.Fatalf(`Command "history" failed for %q.`, test.cmd)
		}
	}
}
<commit_msg>Added tests related to #4704<commit_after>package main_test

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"net/url"
	"testing"

	"github.com/influxdb/influxdb/client"
	main "github.com/influxdb/influxdb/cmd/influx"
)

func TestParseCommand_CommandsExist(t *testing.T) {
	t.Parallel()
	c := main.CommandLine{}
	tests := []struct {
		cmd string
	}{
		{cmd: "gopher"},
		{cmd: "connect"},
		{cmd: "help"},
		{cmd: "history"},
		{cmd: "pretty"},
		{cmd: "use"},
		{cmd: ""}, // test that a blank command just returns
	}
	for _, test := range tests {
		if !c.ParseCommand(test.cmd) {
			t.Fatalf(`Command failed for %q.`, test.cmd)
		}
	}
}

func TestParseCommand_CommandsSamePrefix(t *testing.T) {
	t.Parallel()
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var data client.Response
		w.WriteHeader(http.StatusNoContent)
		_ = json.NewEncoder(w).Encode(data)
	}))
	defer ts.Close()

	u, _ := url.Parse(ts.URL)
	config := client.Config{URL: *u}
	c, err := client.NewClient(config)
	if err != nil {
		t.Fatalf("unexpected error.  expected %v, actual %v", nil, err)
	}
	m := main.CommandLine{Client: c}

	tests := []struct {
		cmd string
	}{
		{cmd: "use db"},
		{cmd: "user nodb"},
		{cmd: "puse nodb"},
		{cmd: ""}, // test that a blank command just returns
	}
	for _, test := range tests {
		if !m.ParseCommand(test.cmd) {
			t.Fatalf(`Command failed for %q.`, test.cmd)
		}
	}

	if m.Database != "db" {
		t.Fatalf(`Command "use" changed database to %q. Expected db`, m.Database)
	}
}

func TestParseCommand_TogglePretty(t *testing.T) {
	t.Parallel()
	c := main.CommandLine{}
	if c.Pretty {
		t.Fatalf(`Pretty should be false.`)
	}
	c.ParseCommand("pretty")
	if !c.Pretty {
		t.Fatalf(`Pretty should be true.`)
	}
	c.ParseCommand("pretty")
	if c.Pretty {
		t.Fatalf(`Pretty should be false.`)
	}
}

func TestParseCommand_Exit(t *testing.T) {
	t.Parallel()
	c := main.CommandLine{}
	tests := []struct {
		cmd string
	}{
		{cmd: "exit"},
		{cmd: " exit"},
		{cmd: "exit "},
		{cmd: "Exit "},
	}

	for _, test := range tests {
		if c.ParseCommand(test.cmd) {
			t.Fatalf(`Command "exit" failed for %q.`, test.cmd)
		}
	}
}

func TestParseCommand_Use(t *testing.T) {
	t.Parallel()
	c := main.CommandLine{}
	tests := []struct {
		cmd string
	}{
		{cmd: "use db"},
		{cmd: " use db"},
		{cmd: "use db "},
		{cmd: "use db;"},
		{cmd: "use db; "},
		{cmd: "Use db"},
	}

	for _, test := range tests {
		if !c.ParseCommand(test.cmd) {
			t.Fatalf(`Command "use" failed for %q.`, test.cmd)
		}

		if c.Database != "db" {
			t.Fatalf(`Command "use" changed database to %q. Expected db`, c.Database)
		}
	}
}

func TestParseCommand_Consistency(t *testing.T) {
	t.Parallel()
	c := main.CommandLine{}
	tests := []struct {
		cmd string
	}{
		{cmd: "consistency one"},
		{cmd: " consistency one"},
		{cmd: "consistency one "},
		{cmd: "consistency one;"},
		{cmd: "consistency one; "},
		{cmd: "Consistency one"},
	}

	for _, test := range tests {
		if !c.ParseCommand(test.cmd) {
			t.Fatalf(`Command "consistency" failed for %q.`, test.cmd)
		}

		if c.WriteConsistency != "one" {
			t.Fatalf(`Command "consistency" changed consistency to %q. Expected one`, c.WriteConsistency)
		}
	}
}

func TestParseCommand_Insert(t *testing.T) {
	t.Parallel()
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var data client.Response
		w.WriteHeader(http.StatusNoContent)
		_ = json.NewEncoder(w).Encode(data)
	}))
	defer ts.Close()

	u, _ := url.Parse(ts.URL)
	config := client.Config{URL: *u}
	c, err := client.NewClient(config)
	if err != nil {
		t.Fatalf("unexpected error.  expected %v, actual %v", nil, err)
	}
	m := main.CommandLine{Client: c}

	tests := []struct {
		cmd string
	}{
		{cmd: "INSERT cpu,host=serverA,region=us-west value=1.0"},
		{cmd: " INSERT cpu,host=serverA,region=us-west value=1.0"},
		{cmd: "INSERT   cpu,host=serverA,region=us-west value=1.0"},
		{cmd: "insert cpu,host=serverA,region=us-west    value=1.0    "},
		{cmd: "insert"},
		{cmd: "Insert "},
		{cmd: "insert c"},
		{cmd: "insert int"},
	}

	for _, test := range tests {
		if !m.ParseCommand(test.cmd) {
			t.Fatalf(`Command "insert" failed for %q.`, test.cmd)
		}
	}
}

func TestParseCommand_InsertInto(t *testing.T) {
	t.Parallel()
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var data client.Response
		w.WriteHeader(http.StatusNoContent)
		_ = json.NewEncoder(w).Encode(data)
	}))
	defer ts.Close()

	u, _ := url.Parse(ts.URL)
	config := client.Config{URL: *u}
	c, err := client.NewClient(config)
	if err != nil {
		t.Fatalf("unexpected error.  expected %v, actual %v", nil, err)
	}
	m := main.CommandLine{Client: c}

	tests := []struct {
		cmd, db, rp string
	}{
		{
			cmd: `INSERT INTO test cpu,host=serverA,region=us-west value=1.0`,
			db:  "",
			rp:  "test",
		},
		{
			cmd: ` INSERT INTO .test cpu,host=serverA,region=us-west value=1.0`,
			db:  "",
			rp:  "test",
		},
		{
			cmd: `INSERT INTO   "test test" cpu,host=serverA,region=us-west value=1.0`,
			db:  "",
			rp:  "test test",
		},
		{
			cmd: `Insert iNTO test.test cpu,host=serverA,region=us-west value=1.0`,
			db:  "test",
			rp:  "test",
		},
		{
			cmd: `insert into "test test" cpu,host=serverA,region=us-west value=1.0`,
			db:  "test",
			rp:  "test test",
		},
		{
			cmd: `insert into "d b"."test test" cpu,host=serverA,region=us-west value=1.0`,
			db:  "d b",
			rp:  "test test",
		},
	}

	for _, test := range tests {
		if !m.ParseCommand(test.cmd) {
			t.Fatalf(`Command "insert into" failed for %q.`, test.cmd)
		}
		if m.Database != test.db {
			t.Fatalf(`Command "insert into" db parsing failed, expected: %q, actual: %q`, test.db, m.Database)
		}
		if m.RetentionPolicy != test.rp {
			t.Fatalf(`Command "insert into" rp parsing failed, expected: %q, actual: %q`, test.rp, m.RetentionPolicy)
		}
	}
}

func TestParseCommand_History(t *testing.T) {
	t.Parallel()
	c := main.CommandLine{}
	tests := []struct {
		cmd string
	}{
		{cmd: "history"},
		{cmd: " history"},
		{cmd: "history "},
		{cmd: "History "},
	}

	for _, test := range tests {
		if !c.ParseCommand(test.cmd) {
			t.Fatalf(`Command "history" failed for %q.`, test.cmd)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
    "testing"
    . "github.com/smartystreets/goconvey/convey"
    "time"
    mtestutils "github.com/nebtex/menshend/pkg/utils/test"
    mutils "github.com/nebtex/menshend/pkg/utils"
    mconfig "github.com/nebtex/menshend/pkg/config"
    "os"
    vault "github.com/hashicorp/vault/api"
    "net/http/httptest"
    "github.com/ansel1/merry"
    "net/url"
)

func TestSetToken(t *testing.T) {
    mutils.CheckPanic(os.Setenv(vault.EnvVaultAddress, "http://127.0.0.1:8200"))

    Convey("should panic if token has no the lookup-self permission", t, func(c C) {
        defer func() {
            r := recover()
            if (r == nil) {
                t.Error("did not panicked")
                t.Fail()
            }
            switch x := r.(type) {
            case error:
                c.So(merry.Is(x, mutils.PermissionError), ShouldBeTrue)
            default:
                t.Errorf("%v", x)
                t.Fail()
            }
        }()
        httpWriter := httptest.NewRecorder()
        mtestutils.CleanVault()
        vClient, err := vault.NewClient(vault.DefaultConfig())
        So(err, ShouldBeNil)
        vClient.SetToken("myroot")
        err = vClient.Sys().PutPolicy("without-lookup-permission", `
        path "auth/token/lookup-self" {
            capabilities = ["deny"]
        }`)
        So(err, ShouldBeNil)
        secret, err := vClient.Auth().Token().Create(&vault.TokenCreateRequest{Policies:[]string{"without-lookup-permission"}})
        So(err, ShouldBeNil)
        setToken(secret.Auth.ClientToken, tokenProvider, httpWriter)

    })

    Convey("if vault token ttl  is different from 0, the cookie should use it as expiration time", t, func() {
        httpWriter := httptest.NewRecorder()
        vClient, err := vault.NewClient(vault.DefaultConfig())
        So(err, ShouldBeNil)
        vClient.SetToken("myroot")
        secret, err := vClient.Auth().Token().Create(&vault.TokenCreateRequest{TTL:"1h"})
        So(err, ShouldBeNil)
        setToken(secret.Auth.ClientToken, tokenProvider, httpWriter)
        So(httpWriter.Result().Cookies()[0].Expires.Unix(), ShouldAlmostEqual, time.Now().Unix() + 3600, 10)

    })

    Convey("when menshend base url use https, token should have the property secure marked as true", t, func() {
        mconfig.Config.Uris.BaseUrl = "https://nebtex.com"
        httpWriter := httptest.NewRecorder()
        setToken("myroot", tokenProvider, httpWriter)
        So(httpWriter.Result().Cookies()[0].Secure, ShouldBeTrue)

    })

    Convey("token domain should use the menshend baseurl", t, func() {
        mconfig.Config.Uris.BaseUrl = "https://nebtex.com:65656"
        httpWriter := httptest.NewRecorder()
        setToken("myroot", tokenProvider, httpWriter)
        So(httpWriter.Result().Cookies()[0].Domain, ShouldEqual, "nebtex.com")

    })
}

func TestProviderRedirect(t *testing.T) {
    mconfig.Config.Github.ClientID = "test"
    mconfig.Config.Github.ClientSecret = "test-test"
    mconfig.LoadConfig()
    Convey("if not subdamin was provided should not set the redirect_uri property", t, func(c C) {
        rt:=  loginRouters()
        httpWriter := httptest.NewRecorder()
        request := httptest.NewRequest("GET", "/ui/auth/github", nil)
        rt.ServeHTTP(httpWriter, request)
        URL, err := httpWriter.Result().Location()
        So(err, ShouldBeNil)
        So(URL.Query().Get("redirect_uri"), ShouldEqual, mconfig.Config.GetCallbackUrl("github", ""))

    })
    Convey("if  subdamin was provided the redirect uri should use a subdomain as subpath", t, func(c C) {
        rt:=  loginRouters()
        httpWriter := httptest.NewRecorder()
        request := httptest.NewRequest("GET", "/ui/auth/github/gitlab.", nil)
        rt.ServeHTTP(httpWriter, request)
        URL, err := httpWriter.Result().Location()
        So(err, ShouldBeNil)
        So(URL.Query().Get("redirect_uri"), ShouldEqual, mconfig.Config.GetCallbackUrl("github", "gitlab."))

    })

}

func TestTokenLogin(t *testing.T) {
    mconfig.LoadConfig()
    mutils.CheckPanic(os.Setenv(vault.EnvVaultAddress, "http://127.0.0.1:8200"))

    Convey("test login method, without subdomain", t, func(c C) {
        rt:=  loginRouters()
        httpWriter := httptest.NewRecorder()
        request := httptest.NewRequest("POST", "/ui/login", nil)
        form := url.Values{}
        form.Add("method", "token")
        form.Add("token", "myroot")
        request.PostForm = form
        request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
        rt.ServeHTTP(httpWriter, request)
        URL, err := httpWriter.Result().Location()
        So(err, ShouldBeNil)
        So(URL.String(), ShouldEqual, mconfig.Config.GetServicePath())
        So(httpWriter.Result().Cookies()[0].Value, ShouldEqual, "myroot")
    })

    Convey("test login method, with subdomain", t, func(c C) {
        rt:=  loginRouters()
        httpWriter := httptest.NewRecorder()
        request := httptest.NewRequest("POST", "/ui/login/mongo.", nil)
        form := url.Values{}
        form.Add("method", "token")
        form.Add("token", "myroot")
        request.PostForm = form
        request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
        rt.ServeHTTP(httpWriter, request)
        URL, err := httpWriter.Result().Location()
        So(err, ShouldBeNil)
        So(URL.String(), ShouldEqual, mconfig.Config.GetSubdomainFullUrl("mongo."))
        So(httpWriter.Result().Cookies()[0].Value, ShouldEqual, "myroot")
    })
}

func TestTokenUsername(t *testing.T) {
    mconfig.LoadConfig()
    mutils.CheckPanic(os.Setenv(vault.EnvVaultAddress, "http://127.0.0.1:8200"))

    Convey("test user/pass  method", t, func(c C) {
        rt:=  loginRouters()
        httpWriter := httptest.NewRecorder()
        request := httptest.NewRequest("POST", "/ui/login", nil)
        form := url.Values{}
        form.Add("method", "userpass")
        form.Add("user", "menshend")
        form.Add("password", "test")
        request.PostForm = form
        request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
        rt.ServeHTTP(httpWriter, request)
        URL, err := httpWriter.Result().Location()
        So(err, ShouldBeNil)
        So(URL.String(), ShouldEqual, mconfig.Config.GetServicePath())
        So(httpWriter.Result().Cookies()[0].Value, ShouldNotBeEmpty)
    })

}

func TestSameOriginHandler(t *testing.T) {
    mconfig.Config.Github.ClientID = ""
    mconfig.Config.Github.ClientSecret = ""
    mconfig.LoadConfig()
    mutils.CheckPanic(os.Setenv(vault.EnvVaultAddress, "http://127.0.0.1:8200"))

    Convey("should ignore same origin policy with method=get", t, func(c C) {
        rt:=  uiHandler()
        httpWriter := httptest.NewRecorder()
        request := httptest.NewRequest("GET", "/ui/auth/github/callback", nil)
        request.Header.Add("Origin", "http://evil.com")
        rt.ServeHTTP(httpWriter, request)
        URL, err := httpWriter.Result().Location()
        So(err, ShouldBeNil)
        So(URL.String(), ShouldEqual, mconfig.Config.GetLoginPath()+"?loginError=Github")
    })

}
<commit_msg>fix windows tests<commit_after>package main

import (
    "testing"
    . "github.com/smartystreets/goconvey/convey"
    "time"
    mtestutils "github.com/nebtex/menshend/pkg/utils/test"
    mutils "github.com/nebtex/menshend/pkg/utils"
    mconfig "github.com/nebtex/menshend/pkg/config"
    "os"
    vault "github.com/hashicorp/vault/api"
    "net/http/httptest"
    "github.com/ansel1/merry"
    "net/url"
    "github.com/markbates/goth"
    "github.com/markbates/goth/providers/github"

)

func TestSetToken(t *testing.T) {
    mutils.CheckPanic(os.Setenv(vault.EnvVaultAddress, "http://127.0.0.1:8200"))

    Convey("should panic if token has no the lookup-self permission", t, func(c C) {
        defer func() {
            r := recover()
            if (r == nil) {
                t.Error("did not panicked")
                t.Fail()
            }
            switch x := r.(type) {
            case error:
                c.So(merry.Is(x, mutils.PermissionError), ShouldBeTrue)
            default:
                t.Errorf("%v", x)
                t.Fail()
            }
        }()
        httpWriter := httptest.NewRecorder()
        mtestutils.CleanVault()
        vClient, err := vault.NewClient(vault.DefaultConfig())
        So(err, ShouldBeNil)
        vClient.SetToken("myroot")
        err = vClient.Sys().PutPolicy("without-lookup-permission", `
        path "auth/token/lookup-self" {
            capabilities = ["deny"]
        }`)
        So(err, ShouldBeNil)
        secret, err := vClient.Auth().Token().Create(&vault.TokenCreateRequest{Policies:[]string{"without-lookup-permission"}})
        So(err, ShouldBeNil)
        setToken(secret.Auth.ClientToken, tokenProvider, httpWriter)

    })

    Convey("if vault token ttl  is different from 0, the cookie should use it as expiration time", t, func() {
        httpWriter := httptest.NewRecorder()
        vClient, err := vault.NewClient(vault.DefaultConfig())
        So(err, ShouldBeNil)
        vClient.SetToken("myroot")
        secret, err := vClient.Auth().Token().Create(&vault.TokenCreateRequest{TTL:"1h"})
        So(err, ShouldBeNil)
        setToken(secret.Auth.ClientToken, tokenProvider, httpWriter)
        So(httpWriter.Result().Cookies()[0].Expires.Unix(), ShouldAlmostEqual, time.Now().Unix() + 3600, 10)

    })

    Convey("when menshend base url use https, token should have the property secure marked as true", t, func() {
        mconfig.Config.Uris.BaseUrl = "https://nebtex.com"
        httpWriter := httptest.NewRecorder()
        setToken("myroot", tokenProvider, httpWriter)
        So(httpWriter.Result().Cookies()[0].Secure, ShouldBeTrue)

    })

    Convey("token domain should use the menshend baseurl", t, func() {
        mconfig.Config.Uris.BaseUrl = "https://nebtex.com:65656"
        httpWriter := httptest.NewRecorder()
        setToken("myroot", tokenProvider, httpWriter)
        So(httpWriter.Result().Cookies()[0].Domain, ShouldEqual, "nebtex.com")

    })
}

func TestProviderRedirect(t *testing.T) {
    mconfig.Config.Github.ClientID = "test"
    mconfig.Config.Github.ClientSecret = "test-test"
    mconfig.LoadConfig()
    Convey("if not subdamin was provided should not set the redirect_uri property", t, func(c C) {
        rt:=  loginRouters()
        httpWriter := httptest.NewRecorder()
        request := httptest.NewRequest("GET", "/ui/auth/github", nil)
        rt.ServeHTTP(httpWriter, request)
        URL, err := httpWriter.Result().Location()
        So(err, ShouldBeNil)
        So(URL.Query().Get("redirect_uri"), ShouldEqual, mconfig.Config.GetCallbackUrl("github", ""))

    })
    Convey("if  subdamin was provided the redirect uri should use a subdomain as subpath", t, func(c C) {
        rt:=  loginRouters()
        httpWriter := httptest.NewRecorder()
        request := httptest.NewRequest("GET", "/ui/auth/github/gitlab.", nil)
        rt.ServeHTTP(httpWriter, request)
        URL, err := httpWriter.Result().Location()
        So(err, ShouldBeNil)
        So(URL.Query().Get("redirect_uri"), ShouldEqual, mconfig.Config.GetCallbackUrl("github", "gitlab."))

    })

}

func TestTokenLogin(t *testing.T) {
    mconfig.LoadConfig()
    mutils.CheckPanic(os.Setenv(vault.EnvVaultAddress, "http://127.0.0.1:8200"))
    goth.UseProviders(
        github.New("test", "test-test", "read:org"),
    )
    Convey("test login method, without subdomain", t, func(c C) {
        rt:=  loginRouters()
        httpWriter := httptest.NewRecorder()
        request := httptest.NewRequest("POST", "/ui/login", nil)
        form := url.Values{}
        form.Add("method", "token")
        form.Add("token", "myroot")
        request.PostForm = form
        request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
        rt.ServeHTTP(httpWriter, request)
        URL, err := httpWriter.Result().Location()
        So(err, ShouldBeNil)
        So(URL.String(), ShouldEqual, mconfig.Config.GetServicePath())
        So(httpWriter.Result().Cookies()[0].Value, ShouldEqual, "myroot")
    })

    Convey("test login method, with subdomain", t, func(c C) {
        rt:=  loginRouters()
        httpWriter := httptest.NewRecorder()
        request := httptest.NewRequest("POST", "/ui/login/mongo.", nil)
        form := url.Values{}
        form.Add("method", "token")
        form.Add("token", "myroot")
        request.PostForm = form
        request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
        rt.ServeHTTP(httpWriter, request)
        URL, err := httpWriter.Result().Location()
        So(err, ShouldBeNil)
        So(URL.String(), ShouldEqual, mconfig.Config.GetSubdomainFullUrl("mongo."))
        So(httpWriter.Result().Cookies()[0].Value, ShouldEqual, "myroot")
    })
}

func TestTokenUsername(t *testing.T) {
    mconfig.LoadConfig()
    mutils.CheckPanic(os.Setenv(vault.EnvVaultAddress, "http://127.0.0.1:8200"))
    goth.UseProviders(
        github.New("test", "test-test", "read:org"),
    )
    Convey("test user/pass  method", t, func(c C) {
        rt:=  loginRouters()
        httpWriter := httptest.NewRecorder()
        request := httptest.NewRequest("POST", "/ui/login", nil)
        form := url.Values{}
        form.Add("method", "userpass")
        form.Add("user", "menshend")
        form.Add("password", "test")
        request.PostForm = form
        request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
        rt.ServeHTTP(httpWriter, request)
        URL, err := httpWriter.Result().Location()
        So(err, ShouldBeNil)
        So(URL.String(), ShouldEqual, mconfig.Config.GetServicePath())
        So(httpWriter.Result().Cookies()[0].Value, ShouldNotBeEmpty)
    })

}

func TestSameOriginHandler(t *testing.T) {
    mconfig.Config.Github.ClientID = ""
    mconfig.Config.Github.ClientSecret = ""
    mconfig.LoadConfig()
    mutils.CheckPanic(os.Setenv(vault.EnvVaultAddress, "http://127.0.0.1:8200"))
    goth.UseProviders(
        github.New("test", "test-test", "read:org"),
    )
    Convey("should ignore same origin policy with method=get", t, func(c C) {
        rt:=  uiHandler()
        httpWriter := httptest.NewRecorder()
        request := httptest.NewRequest("GET", "/ui/auth/github/callback", nil)
        request.Header.Add("Origin", "http://evil.com")
        rt.ServeHTTP(httpWriter, request)
        URL, err := httpWriter.Result().Location()
        So(err, ShouldBeNil)
        So(URL.String(), ShouldEqual, mconfig.Config.GetLoginPath()+"?loginError=Github")
    })

}
<|endoftext|>


<commit_before>package main

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

	"nym.se/mole/conf"
)

var lenToMaskMap = map[string]string{
	"0":  "0.0.0.0",
	"1":  "128.0.0.0",
	"2":  "192.0.0.0",
	"3":  "224.0.0.0",
	"4":  "240.0.0.0",
	"5":  "248.0.0.0",
	"6":  "252.0.0.0",
	"7":  "254.0.0.0",
	"8":  "255.0.0.0",
	"9":  "255.128.0.0",
	"10": "255.192.0.0",
	"11": "255.224.0.0",
	"12": "255.240.0.0",
	"13": "255.248.0.0",
	"14": "255.252.0.0",
	"15": "255.254.0.0",
	"16": "255.255.0.0",
	"17": "255.255.128.0",
	"18": "255.255.192.0",
	"19": "255.255.224.0",
	"20": "255.255.240.0",
	"21": "255.255.248.0",
	"22": "255.255.252.0",
	"23": "255.255.254.0",
	"24": "255.255.255.0",
	"25": "255.255.255.128",
	"26": "255.255.255.192",
	"27": "255.255.255.224",
	"28": "255.255.255.240",
	"29": "255.255.255.248",
	"30": "255.255.255.252",
	"31": "255.255.255.254",
	"32": "255.255.255.255",
}

func writeVpncScript(cfg *conf.Config) string {
	f, e := ioutil.TempFile("", "vpnc-script.")
	fatalErr(e)
	debugln(f.Name())

	_, e = f.Write([]byte(vpncScript(cfg)))
	fatalErr(e)

	e = f.Close()
	fatalErr(e)

	e = os.Chmod(f.Name(), 0x755)
	fatalErr(e)

	return f.Name()
}

func vpncScript(cfg *conf.Config) string {
	script := `#!/bin/bash

has_init="no"
init() {
	if [ "$has_init" == "no" ] ; then
		has_init="yes"
		export CISCO_SPLIT_INC=0
		unset INTERNAL_IP4_DNS
	fi
}

add_route() {
	init
	export CISCO_SPLIT_INC_${CISCO_SPLIT_INC}_ADDR=$1
	export CISCO_SPLIT_INC_${CISCO_SPLIT_INC}_MASKLEN=$2
	export CISCO_SPLIT_INC_${CISCO_SPLIT_INC}_MASK=$3
	export CISCO_SPLIT_INC=$(($CISCO_SPLIT_INC + 1))
}

{add_cmds}

[ -f /usr/local/etc/vpnc/vpnc-script ] && /usr/local/etc/vpnc/vpnc-script
[ -f /etc/vpnc/vpnc-script ] && /etc/vpnc/vpnc-script

if [ "$reason" == "connect" ] ; then
	echo mole-vpnc-script-next
fi
`

	var addCmds []string
	for _, route := range cfg.VpnRoutes {
		ps := strings.SplitN(route, "/", 2)
		addCmds = append(addCmds, "add_route "+ps[0]+" "+ps[1]+" "+lenToMaskMap[ps[1]])
	}

	script = strings.Replace(script, "{add_cmds}", strings.Join(addCmds, "\n"), 1)
	debugln(script)
	return script
}
<commit_msg>Always prevent vpnc/opnc from frobbing /etc/resolv.conf<commit_after>package main

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

	"nym.se/mole/conf"
)

var lenToMaskMap = map[string]string{
	"0":  "0.0.0.0",
	"1":  "128.0.0.0",
	"2":  "192.0.0.0",
	"3":  "224.0.0.0",
	"4":  "240.0.0.0",
	"5":  "248.0.0.0",
	"6":  "252.0.0.0",
	"7":  "254.0.0.0",
	"8":  "255.0.0.0",
	"9":  "255.128.0.0",
	"10": "255.192.0.0",
	"11": "255.224.0.0",
	"12": "255.240.0.0",
	"13": "255.248.0.0",
	"14": "255.252.0.0",
	"15": "255.254.0.0",
	"16": "255.255.0.0",
	"17": "255.255.128.0",
	"18": "255.255.192.0",
	"19": "255.255.224.0",
	"20": "255.255.240.0",
	"21": "255.255.248.0",
	"22": "255.255.252.0",
	"23": "255.255.254.0",
	"24": "255.255.255.0",
	"25": "255.255.255.128",
	"26": "255.255.255.192",
	"27": "255.255.255.224",
	"28": "255.255.255.240",
	"29": "255.255.255.248",
	"30": "255.255.255.252",
	"31": "255.255.255.254",
	"32": "255.255.255.255",
}

func writeVpncScript(cfg *conf.Config) string {
	f, e := ioutil.TempFile("", "vpnc-script.")
	fatalErr(e)
	debugln(f.Name())

	_, e = f.Write([]byte(vpncScript(cfg)))
	fatalErr(e)

	e = f.Close()
	fatalErr(e)

	e = os.Chmod(f.Name(), 0x755)
	fatalErr(e)

	return f.Name()
}

func vpncScript(cfg *conf.Config) string {
	script := `#!/bin/bash

has_init="no"
init() {
	if [ "$has_init" == "no" ] ; then
		has_init="yes"
		export CISCO_SPLIT_INC=0
	fi
}

unset INTERNAL_IP4_DNS

add_route() {
	init
	export CISCO_SPLIT_INC_${CISCO_SPLIT_INC}_ADDR=$1
	export CISCO_SPLIT_INC_${CISCO_SPLIT_INC}_MASKLEN=$2
	export CISCO_SPLIT_INC_${CISCO_SPLIT_INC}_MASK=$3
	export CISCO_SPLIT_INC=$(($CISCO_SPLIT_INC + 1))
}

{add_cmds}

[ -f /usr/local/etc/vpnc/vpnc-script ] && /usr/local/etc/vpnc/vpnc-script
[ -f /etc/vpnc/vpnc-script ] && /etc/vpnc/vpnc-script

if [ "$reason" == "connect" ] ; then
	echo mole-vpnc-script-next
fi
`

	var addCmds []string
	for _, route := range cfg.VpnRoutes {
		ps := strings.SplitN(route, "/", 2)
		addCmds = append(addCmds, "add_route "+ps[0]+" "+ps[1]+" "+lenToMaskMap[ps[1]])
	}

	script = strings.Replace(script, "{add_cmds}", strings.Join(addCmds, "\n"), 1)
	debugln(script)
	return script
}
<|endoftext|>


<commit_before>package cmd

import (
	"context"
	"errors"
	"github.com/opalmer/dockertest"
	"github.com/opalmer/gerrittest"
	"github.com/spf13/cobra"
)

// Stop implements the `stop` subcommand.
var Stop = &cobra.Command{
	Use:   "stop",
	Short: "Responsible for starting an instance of Gerrit.",
	RunE: func(cmd *cobra.Command, args []string) error {
		path, err := cmd.Flags().GetString("json")
		if err != nil {
			return err
		}
		if path == "" {
			return errors.New("--json not provided")
		}

		spec, err := gerrittest.ReadServiceSpecFromArg(cmd)
		if err != nil {
			return err
		}

		// Terminate the container.
		docker, err := dockertest.NewClient()
		if err != nil {
			return err
		}
		return docker.RemoveContainer(context.Background(), spec.Container)
	},
}

func init() {
	Stop.Flags().String(
		"json", "",
		"The json file containing the container to stop.")
}
<commit_msg>typo fix<commit_after>package cmd

import (
	"context"
	"errors"
	"github.com/opalmer/dockertest"
	"github.com/opalmer/gerrittest"
	"github.com/spf13/cobra"
)

// Stop implements the `stop` subcommand.
var Stop = &cobra.Command{
	Use:   "stop",
	Short: "Responsible for stopping an instance of Gerrit.",
	RunE: func(cmd *cobra.Command, args []string) error {
		path, err := cmd.Flags().GetString("json")
		if err != nil {
			return err
		}
		if path == "" {
			return errors.New("--json not provided")
		}

		spec, err := gerrittest.ReadServiceSpecFromArg(cmd)
		if err != nil {
			return err
		}

		// Terminate the container.
		docker, err := dockertest.NewClient()
		if err != nil {
			return err
		}
		return docker.RemoveContainer(context.Background(), spec.Container)
	},
}

func init() {
	Stop.Flags().String(
		"json", "",
		"The json file containing the container to stop.")
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/eaigner/hood"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"reflect"
	"sort"
	"strconv"
	"strings"
)

import (
	"fmt"
)

type (
	M          struct{}
	Migrations struct {
		Id      hood.Id
		Current int
	}
)

func main() {
	wd, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	// Determine direction
	up := false
	verbose := false
	if n := len(os.Args); n > 1 {
		for i := 1; i < n; i++ {
			switch os.Args[i] {
			case "db:migrate":
				up = true
			case "-v":
				verbose = true
			}
		}
	}
	if up {
		fmt.Println("applying migrations...")
	} else {
		fmt.Println("rolling back...")
	}
	// Get up/down migration methods
	v := reflect.ValueOf(&M{})
	numMethods := v.NumMethod()
	stamps := make([]int, 0, numMethods)
	ups := make(map[int]reflect.Method)
	downs := make(map[int]reflect.Method)
	for i := 0; i < numMethods; i++ {
		method := v.Type().Method(i)
		chunks := strings.Split(method.Name, "_")
		if l := len(chunks); l >= 3 {
			ts, _ := strconv.Atoi(chunks[l-2])
			direction := chunks[l-1]
			if strings.ToLower(direction) == "up" {
				ups[ts] = method
				stamps = append(stamps, ts)
			} else {
				downs[ts] = method
			}
		}
	}
	sort.Ints(stamps)
	// Open hood
	hd, err := hood.Load(
		path.Join(wd, "db", "config.json"),
		os.Getenv("HOOD_ENV"),
	)
	if err != nil {
		panic(err)
	}
	// Check migration table
	err = hd.CreateTableIfNotExists(&Migrations{})
	if err != nil {
		panic(err)
	}
	var rows []Migrations
	err = hd.Find(&rows)
	if err != nil {
		panic(err)
	}
	info := Migrations{}
	if len(rows) > 0 {
		info = rows[0]
	}
	runCount := 0
	for i, ts := range stamps {
		if up {
			if ts > info.Current {
				tx := hd.Begin()
				tx.Log = verbose
				method := ups[ts]
				method.Func.Call([]reflect.Value{v, reflect.ValueOf(tx)})
				info.Current = ts
				tx.Save(&info)
				err = tx.Commit()
				if err != nil {
					panic(err)
				} else {
					runCount++
					fmt.Printf("applied %s\n", method.Name)
				}
			}
		} else {
			if info.Current == ts {
				tx := hd.Begin()
				tx.Log = verbose
				method := downs[ts]
				method.Func.Call([]reflect.Value{v, reflect.ValueOf(tx)})
				if i > 0 {
					info.Current = stamps[i-1]
				} else {
					info.Current = 0
				}
				tx.Save(&info)
				err = tx.Commit()
				if err != nil {
					panic(err)
				} else {
					runCount++
					fmt.Printf("rolled back %s\n", method.Name)
					break
				}
			}
		}
	}
	if up {
		fmt.Printf("applied %d migrations\n", runCount)
	} else {
		fmt.Printf("rolled back %d migrations\n", runCount)
	}
	fmt.Println("generating new schema...")
	dry := hood.Dry()
	for _, ts := range stamps {
		if ts <= info.Current {
			method := ups[ts]
			method.Func.Call([]reflect.Value{v, reflect.ValueOf(dry)})
		}
	}
	schema := fmt.Sprintf(
		"package db\n\nimport (\n\t\"github.com/eaigner/hood\"\n)\n\n%s",
		dry.SchemaDefinition(),
	)
	schemaPath := path.Join(wd, "db", "schema.go")
	err = ioutil.WriteFile(schemaPath, []byte(schema), 0666)
	if err != nil {
		panic(err)
	}
	err = exec.Command("go", "fmt", schemaPath).Run()
	if err != nil {
		panic(err)
	}
	fmt.Printf("wrote schema %s\n", schemaPath)
	fmt.Println("done.")
}
<commit_msg>always log runner sql<commit_after>package main

import (
	"github.com/eaigner/hood"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"reflect"
	"sort"
	"strconv"
	"strings"
)

import (
	"fmt"
)

type (
	M          struct{}
	Migrations struct {
		Id      hood.Id
		Current int
	}
)

func main() {
	wd, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	// Determine direction
	up := false
	verbose := false
	if n := len(os.Args); n > 1 {
		for i := 1; i < n; i++ {
			switch os.Args[i] {
			case "db:migrate":
				up = true
			case "-v":
				verbose = true
			}
		}
	}
	if up {
		fmt.Println("applying migrations...")
	} else {
		fmt.Println("rolling back...")
	}
	// Get up/down migration methods
	v := reflect.ValueOf(&M{})
	numMethods := v.NumMethod()
	stamps := make([]int, 0, numMethods)
	ups := make(map[int]reflect.Method)
	downs := make(map[int]reflect.Method)
	for i := 0; i < numMethods; i++ {
		method := v.Type().Method(i)
		chunks := strings.Split(method.Name, "_")
		if l := len(chunks); l >= 3 {
			ts, _ := strconv.Atoi(chunks[l-2])
			direction := chunks[l-1]
			if strings.ToLower(direction) == "up" {
				ups[ts] = method
				stamps = append(stamps, ts)
			} else {
				downs[ts] = method
			}
		}
	}
	sort.Ints(stamps)
	// Open hood
	hd, err := hood.Load(
		path.Join(wd, "db", "config.json"),
		os.Getenv("HOOD_ENV"),
	)
	if err != nil {
		panic(err)
	}
	hd.Log = true
	// Check migration table
	err = hd.CreateTableIfNotExists(&Migrations{})
	if err != nil {
		panic(err)
	}
	var rows []Migrations
	err = hd.Find(&rows)
	if err != nil {
		panic(err)
	}
	info := Migrations{}
	if len(rows) > 0 {
		info = rows[0]
	}
	runCount := 0
	for i, ts := range stamps {
		if up {
			if ts > info.Current {
				tx := hd.Begin()
				tx.Log = verbose
				method := ups[ts]
				method.Func.Call([]reflect.Value{v, reflect.ValueOf(tx)})
				info.Current = ts
				tx.Save(&info)
				err = tx.Commit()
				if err != nil {
					panic(err)
				} else {
					runCount++
					fmt.Printf("applied %s\n", method.Name)
				}
			}
		} else {
			if info.Current == ts {
				tx := hd.Begin()
				tx.Log = verbose
				method := downs[ts]
				method.Func.Call([]reflect.Value{v, reflect.ValueOf(tx)})
				if i > 0 {
					info.Current = stamps[i-1]
				} else {
					info.Current = 0
				}
				tx.Save(&info)
				err = tx.Commit()
				if err != nil {
					panic(err)
				} else {
					runCount++
					fmt.Printf("rolled back %s\n", method.Name)
					break
				}
			}
		}
	}
	if up {
		fmt.Printf("applied %d migrations\n", runCount)
	} else {
		fmt.Printf("rolled back %d migrations\n", runCount)
	}
	fmt.Println("generating new schema...")
	dry := hood.Dry()
	for _, ts := range stamps {
		if ts <= info.Current {
			method := ups[ts]
			method.Func.Call([]reflect.Value{v, reflect.ValueOf(dry)})
		}
	}
	schema := fmt.Sprintf(
		"package db\n\nimport (\n\t\"github.com/eaigner/hood\"\n)\n\n%s",
		dry.SchemaDefinition(),
	)
	schemaPath := path.Join(wd, "db", "schema.go")
	err = ioutil.WriteFile(schemaPath, []byte(schema), 0666)
	if err != nil {
		panic(err)
	}
	err = exec.Command("go", "fmt", schemaPath).Run()
	if err != nil {
		panic(err)
	}
	fmt.Printf("wrote schema %s\n", schemaPath)
	fmt.Println("done.")
}
<|endoftext|>


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

// TODO(adg,andybons): make the HTML pages prettier

package main

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

	"upspin.io/client"
	"upspin.io/errors"
	"upspin.io/log"
	"upspin.io/path"
	"upspin.io/upspin"
)

type web struct {
	cfg upspin.Config
	cli upspin.Client
}

func newWeb(cfg upspin.Config) http.Handler {
	return &web{
		cfg: cfg,
		cli: client.New(cfg),
	}
}

func (s *web) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path == "/" {
		fmt.Fprintln(w, "Hello, upspin")
		return
	}

	urlName := upspin.PathName(strings.TrimPrefix(r.URL.Path, "/"))
	p, err := path.Parse(urlName)
	if err != nil {
		http.Error(w, "Parse: "+err.Error(), http.StatusBadRequest)
		return
	}

	// The server user can always see its own tree,
	// so prevent access entirely from the web interface.
	if p.User() == s.cfg.UserName() {
		code := http.StatusForbidden
		http.Error(w, http.StatusText(code), code)
		return
	}

	// If the parsed path differs from the requested path, redirect.
	name := p.Path()
	if name != urlName {
		http.Redirect(w, r, "/"+string(name), http.StatusFound)
		return
	}

	des, err := s.cli.Glob(string(name))
	if errors.Match(errors.E(errors.Private), err) || errors.Match(errors.E(errors.Permission), err) {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	} else if err != nil {
		http.Error(w, "Glob: "+err.Error(), http.StatusInternalServerError)
		return
	}
	if len(des) == 0 {
		code := http.StatusNotFound
		http.Error(w, http.StatusText(code), code)
		return
	}

	if len(des) > 1 || des[0].IsDir() {
		// Display glob listing or directory contents.
		var d dirTemplateData
		if len(des) > 1 {
			d.Glob = name
			d.Content = des
		} else {
			d.Dir = des[0]
			d.Content, err = s.cli.Glob(string(name) + "/*")
			if err != nil {
				// TODO(adg): use correct status code for 'information withheld'
				http.Error(w, "Glob: "+err.Error(), http.StatusInternalServerError)
				return
			}
			if p.NElem() > 0 {
				d.Parent = p.Drop(1).Path()
			}
		}
		if err := dirTemplate.Execute(w, d); err != nil {
			log.Error.Printf("rendering directory template: %v", err)
		}
		return
	}

	// Serve the file.
	data, err := s.cli.Get(name)
	if err != nil {
		// TODO(adg): use correct status code for 'information withheld'
		http.Error(w, "Get: "+err.Error(), http.StatusInternalServerError)
		return
	}
	w.Write(data)
}

type dirTemplateData struct {
	// One and only one of these must be set.
	Dir  *upspin.DirEntry
	Glob upspin.PathName

	Parent  upspin.PathName
	Content []*upspin.DirEntry
}

var templateFuncs = template.FuncMap{
	"shortname": func(name upspin.PathName) upspin.PathName {
		parent := path.DropPath(name, 1)
		if name == parent {
			return name
		}
		if !strings.HasSuffix(string(parent), "/") {
			parent += "/"
		}
		return upspin.PathName(strings.TrimPrefix(string(name), string(parent)))
	},
}

var dirTemplate = template.Must(template.New("dir").Funcs(templateFuncs).Parse(`
{{with .Dir}}

Index of {{.Name}}

{{end}}
{{with .Glob}}

Matches for {{.}}

{{end}}

{{with .Parent}}

../

{{end}}
{{range .Content}}

{{shortname .Name}}{{if .IsDir}}/{{end}}

{{end}}

`))
<commit_msg>cmd/upspinserver: fix the remaining HTTP response codes<commit_after>// Copyright 2016 The Upspin Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// TODO(adg,andybons): make the HTML pages prettier

package main

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

	"upspin.io/client"
	"upspin.io/errors"
	"upspin.io/log"
	"upspin.io/path"
	"upspin.io/upspin"
)

type web struct {
	cfg upspin.Config
	cli upspin.Client
}

func newWeb(cfg upspin.Config) http.Handler {
	return &web{
		cfg: cfg,
		cli: client.New(cfg),
	}
}

func (s *web) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path == "/" {
		fmt.Fprintln(w, "Hello, upspin")
		return
	}

	urlName := upspin.PathName(strings.TrimPrefix(r.URL.Path, "/"))
	p, err := path.Parse(urlName)
	if err != nil {
		http.Error(w, "Parse: "+err.Error(), http.StatusBadRequest)
		return
	}

	// The server user can always see its own tree,
	// so prevent access entirely from the web interface.
	if p.User() == s.cfg.UserName() {
		code := http.StatusForbidden
		http.Error(w, http.StatusText(code), code)
		return
	}

	// If the parsed path differs from the requested path, redirect.
	name := p.Path()
	if name != urlName {
		http.Redirect(w, r, "/"+string(name), http.StatusFound)
		return
	}

	des, err := s.cli.Glob(string(name))
	if err != nil {
		httpError(w, err)
		return
	}
	if len(des) == 0 {
		http.Error(w, "Not found", http.StatusNotFound)
		return
	}

	if len(des) > 1 || des[0].IsDir() {
		// Display glob listing or directory contents.
		var d dirTemplateData
		if len(des) > 1 {
			d.Glob = name
			d.Content = des
		} else {
			d.Dir = des[0]
			d.Content, err = s.cli.Glob(string(name) + "/*")
			if err != nil {
				httpError(w, err)
				return
			}
			if p.NElem() > 0 {
				d.Parent = p.Drop(1).Path()
			}
		}
		if err := dirTemplate.Execute(w, d); err != nil {
			log.Error.Printf("rendering directory template: %v", err)
		}
		return
	}

	// Serve the file.
	data, err := s.cli.Get(name)
	if err != nil {
		httpError(w, err)
		return
	}
	w.Write(data)
}

func httpError(w http.ResponseWriter, err error) {
	switch {
	case errors.Match(errors.E(errors.Private), err),
		errors.Match(errors.E(errors.Permission), err):
		http.Error(w, "Forbidden", http.StatusForbidden)
	default:
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

type dirTemplateData struct {
	// One and only one of these must be set.
	Dir  *upspin.DirEntry
	Glob upspin.PathName

	Parent  upspin.PathName
	Content []*upspin.DirEntry
}

var templateFuncs = template.FuncMap{
	"shortname": func(name upspin.PathName) upspin.PathName {
		parent := path.DropPath(name, 1)
		if name == parent {
			return name
		}
		if !strings.HasSuffix(string(parent), "/") {
			parent += "/"
		}
		return upspin.PathName(strings.TrimPrefix(string(name), string(parent)))
	},
}

var dirTemplate = template.Must(template.New("dir").Funcs(templateFuncs).Parse(`
{{with .Dir}}

Index of {{.Name}}

{{end}}
{{with .Glob}}

Matches for {{.}}

{{end}}

{{with .Parent}}

../

{{end}}
{{range .Content}}

{{shortname .Name}}{{if .IsDir}}/{{end}}

{{end}}

`))
<|endoftext|>


<commit_before>package differ

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

	"github.com/boltdb/bolt"
	"github.com/containerd/containerd/archive"
	"github.com/containerd/containerd/archive/compression"
	"github.com/containerd/containerd/content"
	"github.com/containerd/containerd/errdefs"
	"github.com/containerd/containerd/images"
	"github.com/containerd/containerd/metadata"
	"github.com/containerd/containerd/mount"
	"github.com/containerd/containerd/plugin"
	digest "github.com/opencontainers/go-digest"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/pkg/errors"
	"golang.org/x/net/context"
)

func init() {
	plugin.Register(&plugin.Registration{
		Type: plugin.DiffPlugin,
		ID:   "walking",
		Requires: []plugin.PluginType{
			plugin.ContentPlugin,
			plugin.MetadataPlugin,
		},
		Init: func(ic *plugin.InitContext) (interface{}, error) {
			c, err := ic.Get(plugin.ContentPlugin)
			if err != nil {
				return nil, err
			}
			md, err := ic.Get(plugin.MetadataPlugin)
			if err != nil {
				return nil, err
			}
			return newWalkingDiff(metadata.NewContentStore(md.(*bolt.DB), c.(content.Store)))
		},
	})
}

type walkingDiff struct {
	store content.Store
}

var emptyDesc = ocispec.Descriptor{}

func newWalkingDiff(store content.Store) (plugin.Differ, error) {
	return &walkingDiff{
		store: store,
	}, nil
}

func (s *walkingDiff) Apply(ctx context.Context, desc ocispec.Descriptor, mounts []mount.Mount) (ocispec.Descriptor, error) {
	var isCompressed bool
	switch desc.MediaType {
	case ocispec.MediaTypeImageLayer, images.MediaTypeDockerSchema2Layer:
	case ocispec.MediaTypeImageLayerGzip, images.MediaTypeDockerSchema2LayerGzip:
		isCompressed = true
	default:
		// Still apply all generic media types *.tar[.+]gzip and *.tar
		if strings.HasSuffix(desc.MediaType, ".tar.gzip") || strings.HasSuffix(desc.MediaType, ".tar+gzip") {
			isCompressed = true
		} else if !strings.HasSuffix(desc.MediaType, ".tar") {
			return emptyDesc, errors.Wrapf(errdefs.ErrNotSupported, "unsupported diff media type: %v", desc.MediaType)
		}
	}

	dir, err := ioutil.TempDir("", "extract-")
	if err != nil {
		return emptyDesc, errors.Wrap(err, "failed to create temporary directory")
	}
	defer os.RemoveAll(dir)

	if err := mount.MountAll(mounts, dir); err != nil {
		return emptyDesc, errors.Wrap(err, "failed to mount")
	}
	defer mount.Unmount(dir, 0)

	ra, err := s.store.ReaderAt(ctx, desc.Digest)
	if err != nil {
		return emptyDesc, errors.Wrap(err, "failed to get reader from content store")
	}
	defer ra.Close()

	r := content.NewReader(ra)
	if isCompressed {
		ds, err := compression.DecompressStream(r)
		if err != nil {
			return emptyDesc, err
		}
		defer ds.Close()
		r = ds
	}

	digester := digest.Canonical.Digester()
	rc := &readCounter{
		r: io.TeeReader(r, digester.Hash()),
	}

	if _, err := archive.Apply(ctx, dir, rc); err != nil {
		return emptyDesc, err
	}

	// Read any trailing data
	if _, err := io.Copy(ioutil.Discard, rc); err != nil {
		return emptyDesc, err
	}

	return ocispec.Descriptor{
		MediaType: ocispec.MediaTypeImageLayer,
		Size:      rc.c,
		Digest:    digester.Digest(),
	}, nil
}

func (s *walkingDiff) DiffMounts(ctx context.Context, lower, upper []mount.Mount, media, ref string) (ocispec.Descriptor, error) {
	var isCompressed bool
	switch media {
	case ocispec.MediaTypeImageLayer:
	case ocispec.MediaTypeImageLayerGzip:
		isCompressed = true
	case "":
		media = ocispec.MediaTypeImageLayerGzip
		isCompressed = true
	default:
		return emptyDesc, errors.Wrapf(errdefs.ErrNotSupported, "unsupported diff media type: %v", media)
	}
	aDir, err := ioutil.TempDir("", "left-")
	if err != nil {
		return emptyDesc, errors.Wrap(err, "failed to create temporary directory")
	}
	defer os.RemoveAll(aDir)

	bDir, err := ioutil.TempDir("", "right-")
	if err != nil {
		return emptyDesc, errors.Wrap(err, "failed to create temporary directory")
	}
	defer os.RemoveAll(bDir)

	if err := mount.MountAll(lower, aDir); err != nil {
		return emptyDesc, errors.Wrap(err, "failed to mount")
	}
	defer mount.Unmount(aDir, 0)

	if err := mount.MountAll(upper, bDir); err != nil {
		return emptyDesc, errors.Wrap(err, "failed to mount")
	}
	defer mount.Unmount(bDir, 0)

	cw, err := s.store.Writer(ctx, ref, 0, "")
	if err != nil {
		return emptyDesc, errors.Wrap(err, "failed to open writer")
	}

	var opts []content.Opt
	if isCompressed {
		dgstr := digest.SHA256.Digester()
		compressed, err := compression.CompressStream(cw, compression.Gzip)
		if err != nil {
			return emptyDesc, errors.Wrap(err, "failed to get compressed stream")
		}
		err = archive.WriteDiff(ctx, io.MultiWriter(compressed, dgstr.Hash()), aDir, bDir)
		compressed.Close()
		if err != nil {
			return emptyDesc, errors.Wrap(err, "failed to write compressed diff")
		}
		opts = append(opts, content.WithLabels(map[string]string{
			"containerd.io/uncompressed": dgstr.Digest().String(),
		}))
	} else {
		if err = archive.WriteDiff(ctx, cw, aDir, bDir); err != nil {
			return emptyDesc, errors.Wrap(err, "failed to write diff")
		}
	}

	dgst := cw.Digest()
	if err := cw.Commit(ctx, 0, dgst, opts...); err != nil {
		return emptyDesc, errors.Wrap(err, "failed to commit")
	}

	info, err := s.store.Info(ctx, dgst)
	if err != nil {
		return emptyDesc, errors.Wrap(err, "failed to get info from content store")
	}

	return ocispec.Descriptor{
		MediaType: media,
		Size:      info.Size,
		Digest:    info.Digest,
	}, nil
}

type readCounter struct {
	r io.Reader
	c int64
}

func (rc *readCounter) Read(p []byte) (n int, err error) {
	n, err = rc.r.Read(p)
	rc.c += int64(n)
	return
}
<commit_msg>differ: expose newWalkingDiff() for standalone buildkit<commit_after>package differ

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

	"github.com/boltdb/bolt"
	"github.com/containerd/containerd/archive"
	"github.com/containerd/containerd/archive/compression"
	"github.com/containerd/containerd/content"
	"github.com/containerd/containerd/errdefs"
	"github.com/containerd/containerd/images"
	"github.com/containerd/containerd/metadata"
	"github.com/containerd/containerd/mount"
	"github.com/containerd/containerd/plugin"
	digest "github.com/opencontainers/go-digest"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/pkg/errors"
	"golang.org/x/net/context"
)

func init() {
	plugin.Register(&plugin.Registration{
		Type: plugin.DiffPlugin,
		ID:   "walking",
		Requires: []plugin.PluginType{
			plugin.ContentPlugin,
			plugin.MetadataPlugin,
		},
		Init: func(ic *plugin.InitContext) (interface{}, error) {
			c, err := ic.Get(plugin.ContentPlugin)
			if err != nil {
				return nil, err
			}
			md, err := ic.Get(plugin.MetadataPlugin)
			if err != nil {
				return nil, err
			}
			return NewWalkingDiff(metadata.NewContentStore(md.(*bolt.DB), c.(content.Store)))
		},
	})
}

type walkingDiff struct {
	store content.Store
}

var emptyDesc = ocispec.Descriptor{}

// NewWalkingDiff is a generic implementation of plugin.Differ.
// NewWalkingDiff is expected to work with any filesystem.
func NewWalkingDiff(store content.Store) (plugin.Differ, error) {
	return &walkingDiff{
		store: store,
	}, nil
}

// Apply applies the content associated with the provided digests onto the
// provided mounts. Archive content will be extracted and decompressed if
// necessary.
func (s *walkingDiff) Apply(ctx context.Context, desc ocispec.Descriptor, mounts []mount.Mount) (ocispec.Descriptor, error) {
	var isCompressed bool
	switch desc.MediaType {
	case ocispec.MediaTypeImageLayer, images.MediaTypeDockerSchema2Layer:
	case ocispec.MediaTypeImageLayerGzip, images.MediaTypeDockerSchema2LayerGzip:
		isCompressed = true
	default:
		// Still apply all generic media types *.tar[.+]gzip and *.tar
		if strings.HasSuffix(desc.MediaType, ".tar.gzip") || strings.HasSuffix(desc.MediaType, ".tar+gzip") {
			isCompressed = true
		} else if !strings.HasSuffix(desc.MediaType, ".tar") {
			return emptyDesc, errors.Wrapf(errdefs.ErrNotSupported, "unsupported diff media type: %v", desc.MediaType)
		}
	}

	dir, err := ioutil.TempDir("", "extract-")
	if err != nil {
		return emptyDesc, errors.Wrap(err, "failed to create temporary directory")
	}
	defer os.RemoveAll(dir)

	if err := mount.MountAll(mounts, dir); err != nil {
		return emptyDesc, errors.Wrap(err, "failed to mount")
	}
	defer mount.Unmount(dir, 0)

	ra, err := s.store.ReaderAt(ctx, desc.Digest)
	if err != nil {
		return emptyDesc, errors.Wrap(err, "failed to get reader from content store")
	}
	defer ra.Close()

	r := content.NewReader(ra)
	if isCompressed {
		ds, err := compression.DecompressStream(r)
		if err != nil {
			return emptyDesc, err
		}
		defer ds.Close()
		r = ds
	}

	digester := digest.Canonical.Digester()
	rc := &readCounter{
		r: io.TeeReader(r, digester.Hash()),
	}

	if _, err := archive.Apply(ctx, dir, rc); err != nil {
		return emptyDesc, err
	}

	// Read any trailing data
	if _, err := io.Copy(ioutil.Discard, rc); err != nil {
		return emptyDesc, err
	}

	return ocispec.Descriptor{
		MediaType: ocispec.MediaTypeImageLayer,
		Size:      rc.c,
		Digest:    digester.Digest(),
	}, nil
}

// DiffMounts creates a diff between the given mounts and uploads the result
// to the content store.
func (s *walkingDiff) DiffMounts(ctx context.Context, lower, upper []mount.Mount, media, ref string) (ocispec.Descriptor, error) {
	var isCompressed bool
	switch media {
	case ocispec.MediaTypeImageLayer:
	case ocispec.MediaTypeImageLayerGzip:
		isCompressed = true
	case "":
		media = ocispec.MediaTypeImageLayerGzip
		isCompressed = true
	default:
		return emptyDesc, errors.Wrapf(errdefs.ErrNotSupported, "unsupported diff media type: %v", media)
	}
	aDir, err := ioutil.TempDir("", "left-")
	if err != nil {
		return emptyDesc, errors.Wrap(err, "failed to create temporary directory")
	}
	defer os.RemoveAll(aDir)

	bDir, err := ioutil.TempDir("", "right-")
	if err != nil {
		return emptyDesc, errors.Wrap(err, "failed to create temporary directory")
	}
	defer os.RemoveAll(bDir)

	if err := mount.MountAll(lower, aDir); err != nil {
		return emptyDesc, errors.Wrap(err, "failed to mount")
	}
	defer mount.Unmount(aDir, 0)

	if err := mount.MountAll(upper, bDir); err != nil {
		return emptyDesc, errors.Wrap(err, "failed to mount")
	}
	defer mount.Unmount(bDir, 0)

	cw, err := s.store.Writer(ctx, ref, 0, "")
	if err != nil {
		return emptyDesc, errors.Wrap(err, "failed to open writer")
	}

	var opts []content.Opt
	if isCompressed {
		dgstr := digest.SHA256.Digester()
		compressed, err := compression.CompressStream(cw, compression.Gzip)
		if err != nil {
			return emptyDesc, errors.Wrap(err, "failed to get compressed stream")
		}
		err = archive.WriteDiff(ctx, io.MultiWriter(compressed, dgstr.Hash()), aDir, bDir)
		compressed.Close()
		if err != nil {
			return emptyDesc, errors.Wrap(err, "failed to write compressed diff")
		}
		opts = append(opts, content.WithLabels(map[string]string{
			"containerd.io/uncompressed": dgstr.Digest().String(),
		}))
	} else {
		if err = archive.WriteDiff(ctx, cw, aDir, bDir); err != nil {
			return emptyDesc, errors.Wrap(err, "failed to write diff")
		}
	}

	dgst := cw.Digest()
	if err := cw.Commit(ctx, 0, dgst, opts...); err != nil {
		return emptyDesc, errors.Wrap(err, "failed to commit")
	}

	info, err := s.store.Info(ctx, dgst)
	if err != nil {
		return emptyDesc, errors.Wrap(err, "failed to get info from content store")
	}

	return ocispec.Descriptor{
		MediaType: media,
		Size:      info.Size,
		Digest:    info.Digest,
	}, nil
}

type readCounter struct {
	r io.Reader
	c int64
}

func (rc *readCounter) Read(p []byte) (n int, err error) {
	n, err = rc.r.Read(p)
	rc.c += int64(n)
	return
}
<|endoftext|>


<commit_before>package digest

import (
	"bytes"
	"crypto/sha256"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"regexp"
	"strings"

	"github.com/docker/docker/pkg/tarsum"
)

const (
	// DigestTarSumV1EmptyTar is the digest for the empty tar file.
	DigestTarSumV1EmptyTar = "tarsum.v1+sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
)

// Digest allows simple protection of hex formatted digest strings, prefixed
// by their algorithm. Strings of type Digest have some guarantee of being in
// the correct format and it provides quick access to the components of a
// digest string.
//
// The following is an example of the contents of Digest types:
//
// 	sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc
//
// More important for this code base, this type is compatible with tarsum
// digests. For example, the following would be a valid Digest:
//
// 	tarsum+sha256:e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b
//
// This allows to abstract the digest behind this type and work only in those
// terms.
type Digest string

// NewDigest returns a Digest from alg and a hash.Hash object.
func NewDigest(alg string, h hash.Hash) Digest {
	return Digest(fmt.Sprintf("%s:%x", alg, h.Sum(nil)))
}

// NewDigestFromHex returns a Digest from alg and a the hex encoded digest.
func NewDigestFromHex(alg, hex string) Digest {
	return Digest(fmt.Sprintf("%s:%s", alg, hex))
}

// DigestRegexp matches valid digest types.
var DigestRegexp = regexp.MustCompile(`[a-zA-Z0-9-_+.]+:[a-zA-Z0-9-_+.=]+`)

var (
	// ErrDigestInvalidFormat returned when digest format invalid.
	ErrDigestInvalidFormat = fmt.Errorf("invalid checksum digest format")

	// ErrDigestUnsupported returned when the digest algorithm is unsupported by registry.
	ErrDigestUnsupported = fmt.Errorf("unsupported digest algorithm")
)

// ParseDigest parses s and returns the validated digest object. An error will
// be returned if the format is invalid.
func ParseDigest(s string) (Digest, error) {
	d := Digest(s)

	return d, d.Validate()
}

// FromReader returns the most valid digest for the underlying content.
func FromReader(rd io.Reader) (Digest, error) {
	h := sha256.New()

	if _, err := io.Copy(h, rd); err != nil {
		return "", err
	}

	return NewDigest("sha256", h), nil
}

// FromTarArchive produces a tarsum digest from reader rd.
func FromTarArchive(rd io.Reader) (Digest, error) {
	ts, err := tarsum.NewTarSum(rd, true, tarsum.Version1)
	if err != nil {
		return "", err
	}

	if _, err := io.Copy(ioutil.Discard, ts); err != nil {
		return "", err
	}

	d, err := ParseDigest(ts.Sum(nil))
	if err != nil {
		return "", err
	}

	return d, nil
}

// FromBytes digests the input and returns a Digest.
func FromBytes(p []byte) (Digest, error) {
	return FromReader(bytes.NewReader(p))
}

// Validate checks that the contents of d is a valid digest, returning an
// error if not.
func (d Digest) Validate() error {
	s := string(d)
	// Common case will be tarsum
	_, err := ParseTarSum(s)
	if err == nil {
		return nil
	}

	// Continue on for general parser

	i := strings.Index(s, ":")
	if i < 0 {
		return ErrDigestInvalidFormat
	}

	// case: "sha256:" with no hex.
	if i+1 == len(s) {
		return ErrDigestInvalidFormat
	}

	switch s[:i] {
	case "sha256", "sha384", "sha512":
		break
	default:
		return ErrDigestUnsupported
	}

	// TODO(stevvooe): Use DigestRegexp to validate digest here.

	return nil
}

// Algorithm returns the algorithm portion of the digest. This will panic if
// the underlying digest is not in a valid format.
func (d Digest) Algorithm() string {
	return string(d[:d.sepIndex()])
}

// Hex returns the hex digest portion of the digest. This will panic if the
// underlying digest is not in a valid format.
func (d Digest) Hex() string {
	return string(d[d.sepIndex()+1:])
}

func (d Digest) String() string {
	return string(d)
}

func (d Digest) sepIndex() int {
	i := strings.Index(string(d), ":")

	if i < 0 {
		panic("invalid digest: " + d)
	}

	return i
}
<commit_msg>:func Validate in digest doesn't filter no-hex data<commit_after>package digest

import (
	"bytes"
	"crypto/sha256"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"regexp"
	"strings"

	"github.com/docker/docker/pkg/tarsum"
)

const (
	// DigestTarSumV1EmptyTar is the digest for the empty tar file.
	DigestTarSumV1EmptyTar = "tarsum.v1+sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
)

// Digest allows simple protection of hex formatted digest strings, prefixed
// by their algorithm. Strings of type Digest have some guarantee of being in
// the correct format and it provides quick access to the components of a
// digest string.
//
// The following is an example of the contents of Digest types:
//
// 	sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc
//
// More important for this code base, this type is compatible with tarsum
// digests. For example, the following would be a valid Digest:
//
// 	tarsum+sha256:e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b
//
// This allows to abstract the digest behind this type and work only in those
// terms.
type Digest string

// NewDigest returns a Digest from alg and a hash.Hash object.
func NewDigest(alg string, h hash.Hash) Digest {
	return Digest(fmt.Sprintf("%s:%x", alg, h.Sum(nil)))
}

// NewDigestFromHex returns a Digest from alg and a the hex encoded digest.
func NewDigestFromHex(alg, hex string) Digest {
	return Digest(fmt.Sprintf("%s:%s", alg, hex))
}

// DigestRegexp matches valid digest types.
var DigestRegexp = regexp.MustCompile(`[a-zA-Z0-9-_+.]+:[a-zA-Z0-9-_+.=]+`)

var (
	// ErrDigestInvalidFormat returned when digest format invalid.
	ErrDigestInvalidFormat = fmt.Errorf("invalid checksum digest format")

	// ErrDigestUnsupported returned when the digest algorithm is unsupported by registry.
	ErrDigestUnsupported = fmt.Errorf("unsupported digest algorithm")
)

// ParseDigest parses s and returns the validated digest object. An error will
// be returned if the format is invalid.
func ParseDigest(s string) (Digest, error) {
	d := Digest(s)

	return d, d.Validate()
}

// FromReader returns the most valid digest for the underlying content.
func FromReader(rd io.Reader) (Digest, error) {
	h := sha256.New()

	if _, err := io.Copy(h, rd); err != nil {
		return "", err
	}

	return NewDigest("sha256", h), nil
}

// FromTarArchive produces a tarsum digest from reader rd.
func FromTarArchive(rd io.Reader) (Digest, error) {
	ts, err := tarsum.NewTarSum(rd, true, tarsum.Version1)
	if err != nil {
		return "", err
	}

	if _, err := io.Copy(ioutil.Discard, ts); err != nil {
		return "", err
	}

	d, err := ParseDigest(ts.Sum(nil))
	if err != nil {
		return "", err
	}

	return d, nil
}

// FromBytes digests the input and returns a Digest.
func FromBytes(p []byte) (Digest, error) {
	return FromReader(bytes.NewReader(p))
}

// Validate checks that the contents of d is a valid digest, returning an
// error if not.
func (d Digest) Validate() error {
	s := string(d)
	// Common case will be tarsum
	_, err := ParseTarSum(s)
	if err == nil {
		return nil
	}

	// Continue on for general parser

	if !DigestRegexp.MatchString(s) {
		return ErrDigestInvalidFormat
	}

	i := strings.Index(s, ":")
	if i < 0 {
		return ErrDigestInvalidFormat
	}

	// case: "sha256:" with no hex.
	if i+1 == len(s) {
		return ErrDigestInvalidFormat
	}

	switch s[:i] {
	case "sha256", "sha384", "sha512":
		break
	default:
		return ErrDigestUnsupported
	}

	return nil
}

// Algorithm returns the algorithm portion of the digest. This will panic if
// the underlying digest is not in a valid format.
func (d Digest) Algorithm() string {
	return string(d[:d.sepIndex()])
}

// Hex returns the hex digest portion of the digest. This will panic if the
// underlying digest is not in a valid format.
func (d Digest) Hex() string {
	return string(d[d.sepIndex()+1:])
}

func (d Digest) String() string {
	return string(d)
}

func (d Digest) sepIndex() int {
	i := strings.Index(string(d), ":")

	if i < 0 {
		panic("invalid digest: " + d)
	}

	return i
}
<|endoftext|>


<commit_before>// Copyright 2012 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/app"
	"github.com/globocom/tsuru/db"
	ttesting "github.com/globocom/tsuru/testing"
	"labix.org/v2/mgo"
	. "launchpad.net/gocheck"
	"testing"
)

func Test(t *testing.T) { TestingT(t) }

type S struct {
	session     *mgo.Session
	tmpdir      string
	instances   []string
	provisioner *ttesting.FakeProvisioner
}

var _ = Suite(&S{})

func (s *S) SetUpSuite(c *C) {
	var err error
	c.Assert(err, IsNil)
	db.Session, err = db.Open("127.0.0.1:27017", "tsuru_collector_test")
	c.Assert(err, IsNil)
	s.provisioner = ttesting.NewFakeProvisioner()
	app.Provisioner = s.provisioner
	config.Set("queue-server", "127.0.0.1:0")
}

func (s *S) TearDownSuite(c *C) {
	db.Session.Apps().Database.DropDatabase()
	db.Session.Close()
}

func (s *S) TearDownTest(c *C) {
	_, err := db.Session.Apps().RemoveAll(nil)
	c.Assert(err, IsNil)
}
<commit_msg>collector/tests: Reset FakeProvisioner on TearDownTest<commit_after>// Copyright 2012 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/app"
	"github.com/globocom/tsuru/db"
	ttesting "github.com/globocom/tsuru/testing"
	"labix.org/v2/mgo"
	. "launchpad.net/gocheck"
	"testing"
)

func Test(t *testing.T) { TestingT(t) }

type S struct {
	session     *mgo.Session
	tmpdir      string
	instances   []string
	provisioner *ttesting.FakeProvisioner
}

var _ = Suite(&S{})

func (s *S) SetUpSuite(c *C) {
	var err error
	c.Assert(err, IsNil)
	db.Session, err = db.Open("127.0.0.1:27017", "tsuru_collector_test")
	c.Assert(err, IsNil)
	s.provisioner = ttesting.NewFakeProvisioner()
	app.Provisioner = s.provisioner
	config.Set("queue-server", "127.0.0.1:0")
}

func (s *S) TearDownSuite(c *C) {
	db.Session.Apps().Database.DropDatabase()
	db.Session.Close()
}

func (s *S) TearDownTest(c *C) {
	_, err := db.Session.Apps().RemoveAll(nil)
	c.Assert(err, IsNil)
	s.provisioner.Reset()
}
<|endoftext|>