<commit_before>package core

import (
	"bufio"
	"fmt"
	"github.com/grandcat/zeroconf"
	"gopkg.in/cheggaaa/pb.v1"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"path"
	"sync"
	"syscall"
	"time"
)

var (
	start     chan bool
	quit      chan bool
	wg        sync.WaitGroup
	file_path string
)

func RegisterZeroConf(hash string, port int, quit chan bool) {
	defer wg.Done()
	if server, err := zeroconf.Register(hash, "_figo._http._tcp", "local.", port, nil, nil); err != nil {
		panic(err)
	} else {
		<-quit
		server.Shutdown()
	}
}

func ServeHandler(w http.ResponseWriter, r *http.Request) {
	if file, err := os.Open(file_path); err != nil {
		panic(err)
	} else {
		start <- true
		w.Header().Set("Content-Type", "application/octet-stream")
		var datalen int
		if stat, err := file.Stat(); err != nil {
			panic(err)
		} else {
			datalen = int(stat.Size())
			w.Header().Add("Content-Length", fmt.Sprintf("%d", datalen))
			w.Header().Add("Content-Disposition", "inline; filename=\""+stat.Name()+"\"")
		}

		file_buf := bufio.NewReader(file)
		w_buf := bufio.NewWriter(w)

		bar := pb.New(datalen).SetUnits(pb.U_BYTES)
		bar.Start()
		bar_reader := bar.NewProxyReader(file_buf)
		io.Copy(w_buf, bar_reader)
		bar.Finish()
		quit <- true
	}
}

func Figos(name string, nick string) {
	log.SetOutput(ioutil.Discard)
	if nick == "" {
		nick = GetNick(4)
	}
	port := 44234
	// zeroconfQuit := make(chan bool)
	file_path = name
	allowed := []string{path.Base(file_path), nick}
	allowed_hash := GetHashes(allowed)
	zeroconfQuits := make([]chan bool, 2)
	defer wg.Wait()
	for i, hash := range allowed_hash {
		wg.Add(1)
		zeroconfQuits[i] = make(chan bool)
		go RegisterZeroConf(hash, port, zeroconfQuits[i])
	}
	if listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port)); err != nil {
		panic(err)
	} else {
		quit = make(chan bool)
		start = make(chan bool, 1)
		if fi, err := os.Stat(file_path); err != nil || !fi.Mode().IsRegular() {
			fmt.Println("Not valid file")
			os.Exit(1)
		}
		base_name := url.PathEscape(path.Base(file_path))
		http.HandleFunc(fmt.Sprintf("/%s", nick), ServeHandler)
		http.HandleFunc(fmt.Sprintf("/%s", url.PathEscape(base_name)), ServeHandler)
		go http.Serve(listener, nil)

		{
			timer := time.NewTimer(time.Second)
			select {
			case <-start:
			case <-timer.C:
				fmt.Println("Download using either of")
				fmt.Println("\tfigor", nick)
				fmt.Println("\tfigor", base_name)
			}
			timer.Stop()
		}

		sig := make(chan os.Signal, 1)
		signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
		select {
		case <-sig:
		case <-quit:
		}
		listener.Close()
		for _, quit := range zeroconfQuits {
			quit <- true
		}
	}
}
<commit_msg>optimized channel<commit_after>package core

import (
	"bufio"
	"fmt"
	"github.com/grandcat/zeroconf"
	"gopkg.in/cheggaaa/pb.v1"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"path"
	"sync"
	"syscall"
	"time"
)

var (
	start     chan bool
	quit      chan bool
	wg        sync.WaitGroup
	file_path string
)

func RegisterZeroConf(hash string, port int, quit chan bool) {
	defer wg.Done()
	if server, err := zeroconf.Register(hash, "_figo._http._tcp", "local.", port, nil, nil); err != nil {
		panic(err)
	} else {
		<-quit
		server.Shutdown()
	}
}

func ServeHandler(w http.ResponseWriter, r *http.Request) {
	if file, err := os.Open(file_path); err != nil {
		panic(err)
	} else {
		start <- true
		w.Header().Set("Content-Type", "application/octet-stream")
		var datalen int
		if stat, err := file.Stat(); err != nil {
			panic(err)
		} else {
			datalen = int(stat.Size())
			w.Header().Add("Content-Length", fmt.Sprintf("%d", datalen))
			w.Header().Add("Content-Disposition", "inline; filename=\""+stat.Name()+"\"")
		}

		file_buf := bufio.NewReader(file)
		w_buf := bufio.NewWriter(w)

		bar := pb.New(datalen).SetUnits(pb.U_BYTES)
		bar.Start()
		bar_reader := bar.NewProxyReader(file_buf)
		io.Copy(w_buf, bar_reader)
		bar.Finish()
		quit <- true
	}
}

func Figos(name string, nick string) {
	log.SetOutput(ioutil.Discard)
	if nick == "" {
		nick = GetNick(4)
	}
	port := 44234
	// zeroconfQuit := make(chan bool)
	file_path = name
	allowed := []string{path.Base(file_path), nick}
	allowed_hash := GetHashes(allowed)
	zeroconfQuits := make([]chan bool, 2)
	defer wg.Wait()
	for i, hash := range allowed_hash {
		wg.Add(1)
		zeroconfQuits[i] = make(chan bool)
		go RegisterZeroConf(hash, port, zeroconfQuits[i])
	}
	if listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port)); err != nil {
		panic(err)
	} else {
		quit = make(chan bool)
		start = make(chan bool)
		if fi, err := os.Stat(file_path); err != nil || !fi.Mode().IsRegular() {
			fmt.Println("Not valid file")
			os.Exit(1)
		}
		base_name := url.PathEscape(path.Base(file_path))
		http.HandleFunc(fmt.Sprintf("/%s", nick), ServeHandler)
		http.HandleFunc(fmt.Sprintf("/%s", url.PathEscape(base_name)), ServeHandler)
		go http.Serve(listener, nil)

		{
			timer := time.NewTimer(time.Second)
			select {
			case <-start:
			case <-timer.C:
				fmt.Println("Download using either of")
				fmt.Println("\tfigor", nick)
				fmt.Println("\tfigor", base_name)
				<-start
			}
			timer.Stop()
		}

		sig := make(chan os.Signal, 1)
		signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
		select {
		case <-sig:
		case <-quit:
		}
		listener.Close()
		for _, quit := range zeroconfQuits {
			quit <- true
		}
	}
}
<|endoftext|>


<commit_before>// Package migrate is imported by other Go code.
// It is the entry point to all migration functions.
package migrate

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/signal"
	"path"
	"strconv"
	"strings"

	"github.com/mattes/migrate/driver"
	"github.com/mattes/migrate/file"
	"github.com/mattes/migrate/migrate/direction"
	pipep "github.com/mattes/migrate/pipe"
)

// Up applies all available migrations
func Up(pipe chan interface{}, url, migrationsPath string) {
	d, files, version, err := initDriverAndReadMigrationFilesAndGetVersion(url, migrationsPath)
	if err != nil {
		go pipep.Close(pipe, err)
		return
	}

	applyMigrationFiles, err := files.ToLastFrom(version)
	if err != nil {
		if err2 := d.Close(); err2 != nil {
			pipe <- err2
		}
		go pipep.Close(pipe, err)
		return
	}

	if len(applyMigrationFiles) > 0 {
		for _, f := range applyMigrationFiles {
			pipe1 := pipep.New()
			go d.Migrate(f, pipe1)
			if ok := pipep.WaitAndRedirect(pipe1, pipe, handleInterrupts()); !ok {
				break
			}
		}
		if err := d.Close(); err != nil {
			pipe <- err
		}
		go pipep.Close(pipe, nil)
		return
	} else {
		if err := d.Close(); err != nil {
			pipe <- err
		}
		go pipep.Close(pipe, nil)
		return
	}
}

// UpSync is synchronous version of Up
func UpSync(url, migrationsPath string) (err []error, ok bool) {
	pipe := pipep.New()
	go Up(pipe, url, migrationsPath)
	err = pipep.ReadErrors(pipe)
	return err, len(err) == 0
}

// Down rolls back all migrations
func Down(pipe chan interface{}, url, migrationsPath string) {
	d, files, version, err := initDriverAndReadMigrationFilesAndGetVersion(url, migrationsPath)
	if err != nil {
		go pipep.Close(pipe, err)
		return
	}

	applyMigrationFiles, err := files.ToFirstFrom(version)
	if err != nil {
		if err2 := d.Close(); err2 != nil {
			pipe <- err2
		}
		go pipep.Close(pipe, err)
		return
	}

	if len(applyMigrationFiles) > 0 {
		for _, f := range applyMigrationFiles {
			pipe1 := pipep.New()
			go d.Migrate(f, pipe1)
			if ok := pipep.WaitAndRedirect(pipe1, pipe, handleInterrupts()); !ok {
				break
			}
		}
		if err2 := d.Close(); err2 != nil {
			pipe <- err2
		}
		go pipep.Close(pipe, nil)
		return
	} else {
		if err2 := d.Close(); err2 != nil {
			pipe <- err2
		}
		go pipep.Close(pipe, nil)
		return
	}
}

// DownSync is synchronous version of Down
func DownSync(url, migrationsPath string) (err []error, ok bool) {
	pipe := pipep.New()
	go Down(pipe, url, migrationsPath)
	err = pipep.ReadErrors(pipe)
	return err, len(err) == 0
}

// Redo rolls back the most recently applied migration, then runs it again.
func Redo(pipe chan interface{}, url, migrationsPath string) {
	pipe1 := pipep.New()
	go Migrate(pipe1, url, migrationsPath, -1)
	if ok := pipep.WaitAndRedirect(pipe1, pipe, handleInterrupts()); !ok {
		go pipep.Close(pipe, nil)
		return
	} else {
		go Migrate(pipe, url, migrationsPath, +1)
	}
}

// RedoSync is synchronous version of Redo
func RedoSync(url, migrationsPath string) (err []error, ok bool) {
	pipe := pipep.New()
	go Redo(pipe, url, migrationsPath)
	err = pipep.ReadErrors(pipe)
	return err, len(err) == 0
}

// Reset runs the down and up migration function
func Reset(pipe chan interface{}, url, migrationsPath string) {
	pipe1 := pipep.New()
	go Down(pipe1, url, migrationsPath)
	if ok := pipep.WaitAndRedirect(pipe1, pipe, handleInterrupts()); !ok {
		go pipep.Close(pipe, nil)
		return
	} else {
		go Up(pipe, url, migrationsPath)
	}
}

// ResetSync is synchronous version of Reset
func ResetSync(url, migrationsPath string) (err []error, ok bool) {
	pipe := pipep.New()
	go Reset(pipe, url, migrationsPath)
	err = pipep.ReadErrors(pipe)
	return err, len(err) == 0
}

// Migrate applies relative +n/-n migrations
func Migrate(pipe chan interface{}, url, migrationsPath string, relativeN int) {
	d, files, version, err := initDriverAndReadMigrationFilesAndGetVersion(url, migrationsPath)
	if err != nil {
		go pipep.Close(pipe, err)
		return
	}

	applyMigrationFiles, err := files.From(version, relativeN)
	if err != nil {
		if err2 := d.Close(); err2 != nil {
			pipe <- err2
		}
		go pipep.Close(pipe, err)
		return
	}

	if len(applyMigrationFiles) > 0 && relativeN != 0 {
		for _, f := range applyMigrationFiles {
			pipe1 := pipep.New()
			go d.Migrate(f, pipe1)
			if ok := pipep.WaitAndRedirect(pipe1, pipe, handleInterrupts()); !ok {
				break
			}
		}
		if err2 := d.Close(); err2 != nil {
			pipe <- err2
		}
		go pipep.Close(pipe, nil)
		return
	}
	if err2 := d.Close(); err2 != nil {
		pipe <- err2
	}
	go pipep.Close(pipe, nil)
	return
}

// MigrateSync is synchronous version of Migrate
func MigrateSync(url, migrationsPath string, relativeN int) (err []error, ok bool) {
	pipe := pipep.New()
	go Migrate(pipe, url, migrationsPath, relativeN)
	err = pipep.ReadErrors(pipe)
	return err, len(err) == 0
}

// Version returns the current migration version
func Version(url, migrationsPath string) (version uint64, err error) {
	d, err := driver.New(url)
	if err != nil {
		return 0, err
	}
	return d.Version()
}

// Create creates new migration files on disk
func Create(url, migrationsPath, name string) (*file.MigrationFile, error) {
	d, err := driver.New(url)
	if err != nil {
		return nil, err
	}
	files, err := file.ReadMigrationFiles(migrationsPath, file.FilenameRegex(d.FilenameExtension()))
	if err != nil {
		return nil, err
	}

	version := uint64(0)
	if len(files) > 0 {
		lastFile := files[len(files)-1]
		version = lastFile.Version
	}
	version += 1
	versionStr := strconv.FormatUint(version, 10)

	length := 4 // TODO(mattes) check existing files and try to guess length
	if len(versionStr)%length != 0 {
		versionStr = strings.Repeat("0", length-len(versionStr)%length) + versionStr
	}

	filenamef := "%s_%s.%s.%s"
	name = strings.Replace(name, " ", "_", -1)

	mfile := &file.MigrationFile{
		Version: version,
		UpFile: &file.File{
			Path:      migrationsPath,
			FileName:  fmt.Sprintf(filenamef, versionStr, name, "up", d.FilenameExtension()),
			Name:      name,
			Content:   []byte(""),
			Direction: direction.Up,
		},
		DownFile: &file.File{
			Path:      migrationsPath,
			FileName:  fmt.Sprintf(filenamef, versionStr, name, "down", d.FilenameExtension()),
			Name:      name,
			Content:   []byte(""),
			Direction: direction.Down,
		},
	}

	if err := ioutil.WriteFile(path.Join(mfile.UpFile.Path, mfile.UpFile.FileName), mfile.UpFile.Content, 0644); err != nil {
		return nil, err
	}
	if err := ioutil.WriteFile(path.Join(mfile.DownFile.Path, mfile.DownFile.FileName), mfile.DownFile.Content, 0644); err != nil {
		return nil, err
	}

	return mfile, nil
}

// initDriverAndReadMigrationFilesAndGetVersion is a small helper
// function that is common to most of the migration funcs
func initDriverAndReadMigrationFilesAndGetVersion(url, migrationsPath string) (driver.Driver, *file.MigrationFiles, uint64, error) {
	d, err := driver.New(url)
	if err != nil {
		return nil, nil, 0, err
	}
	files, err := file.ReadMigrationFiles(migrationsPath, file.FilenameRegex(d.FilenameExtension()))
	if err != nil {
		d.Close() // TODO what happens with errors from this func?
		return nil, nil, 0, err
	}
	version, err := d.Version()
	if err != nil {
		d.Close() // TODO what happens with errors from this func?
		return nil, nil, 0, err
	}
	return d, &files, version, nil
}

// NewPipe is a convenience function for pipe.New().
// This is helpful if the user just wants to import this package and nothing else.
func NewPipe() chan interface{} {
	return pipep.New()
}

// interrupts is an internal variable that holds the state of
// interrupt handling
var interrupts = true

// Graceful enables interrupts checking. Once the first ^C is received
// it will finish the currently running migration and abort execution
// of the next migration. If ^C is received twice, it will stop
// execution immediately.
func Graceful() {
	interrupts = true
}

// NonGraceful disables interrupts checking. The first received ^C will
// stop execution immediately.
func NonGraceful() {
	interrupts = false
}

// interrupts returns a signal channel if interrupts checking is
// enabled. nil otherwise.
func handleInterrupts() chan os.Signal {
	if interrupts {
		c := make(chan os.Signal, 1)
		signal.Notify(c, os.Interrupt)
		return c
	}
	return nil
}
<commit_msg>Support using different file stores for migration scripts<commit_after>// Package migrate is imported by other Go code.
// It is the entry point to all migration functions.
package migrate

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/signal"
	"path"
	"strconv"
	"strings"

	"github.com/mattes/migrate/driver"
	"github.com/mattes/migrate/file"
	"github.com/mattes/migrate/migrate/direction"
	pipep "github.com/mattes/migrate/pipe"
)

// Up applies all available migrations
func Up(pipe chan interface{}, url, migrationsPath string) {
	d, files, version, err := initDriverAndReadMigrationFilesAndGetVersion(url, migrationsPath)
	if err != nil {
		go pipep.Close(pipe, err)
		return
	}

	applyMigrationFiles, err := files.ToLastFrom(version)
	if err != nil {
		if err2 := d.Close(); err2 != nil {
			pipe <- err2
		}
		go pipep.Close(pipe, err)
		return
	}

	if len(applyMigrationFiles) > 0 {
		for _, f := range applyMigrationFiles {
			pipe1 := pipep.New()
			go d.Migrate(f, pipe1)
			if ok := pipep.WaitAndRedirect(pipe1, pipe, handleInterrupts()); !ok {
				break
			}
		}
		if err := d.Close(); err != nil {
			pipe <- err
		}
		go pipep.Close(pipe, nil)
		return
	} else {
		if err := d.Close(); err != nil {
			pipe <- err
		}
		go pipep.Close(pipe, nil)
		return
	}
}

// UpSync is synchronous version of Up
func UpSync(url, migrationsPath string) (err []error, ok bool) {
	pipe := pipep.New()
	go Up(pipe, url, migrationsPath)
	err = pipep.ReadErrors(pipe)
	return err, len(err) == 0
}

// Down rolls back all migrations
func Down(pipe chan interface{}, url, migrationsPath string) {
	d, files, version, err := initDriverAndReadMigrationFilesAndGetVersion(url, migrationsPath)
	if err != nil {
		go pipep.Close(pipe, err)
		return
	}

	applyMigrationFiles, err := files.ToFirstFrom(version)
	if err != nil {
		if err2 := d.Close(); err2 != nil {
			pipe <- err2
		}
		go pipep.Close(pipe, err)
		return
	}

	if len(applyMigrationFiles) > 0 {
		for _, f := range applyMigrationFiles {
			pipe1 := pipep.New()
			go d.Migrate(f, pipe1)
			if ok := pipep.WaitAndRedirect(pipe1, pipe, handleInterrupts()); !ok {
				break
			}
		}
		if err2 := d.Close(); err2 != nil {
			pipe <- err2
		}
		go pipep.Close(pipe, nil)
		return
	} else {
		if err2 := d.Close(); err2 != nil {
			pipe <- err2
		}
		go pipep.Close(pipe, nil)
		return
	}
}

// DownSync is synchronous version of Down
func DownSync(url, migrationsPath string) (err []error, ok bool) {
	pipe := pipep.New()
	go Down(pipe, url, migrationsPath)
	err = pipep.ReadErrors(pipe)
	return err, len(err) == 0
}

// Redo rolls back the most recently applied migration, then runs it again.
func Redo(pipe chan interface{}, url, migrationsPath string) {
	pipe1 := pipep.New()
	go Migrate(pipe1, url, migrationsPath, -1)
	if ok := pipep.WaitAndRedirect(pipe1, pipe, handleInterrupts()); !ok {
		go pipep.Close(pipe, nil)
		return
	} else {
		go Migrate(pipe, url, migrationsPath, +1)
	}
}

// RedoSync is synchronous version of Redo
func RedoSync(url, migrationsPath string) (err []error, ok bool) {
	pipe := pipep.New()
	go Redo(pipe, url, migrationsPath)
	err = pipep.ReadErrors(pipe)
	return err, len(err) == 0
}

// Reset runs the down and up migration function
func Reset(pipe chan interface{}, url, migrationsPath string) {
	pipe1 := pipep.New()
	go Down(pipe1, url, migrationsPath)
	if ok := pipep.WaitAndRedirect(pipe1, pipe, handleInterrupts()); !ok {
		go pipep.Close(pipe, nil)
		return
	} else {
		go Up(pipe, url, migrationsPath)
	}
}

// ResetSync is synchronous version of Reset
func ResetSync(url, migrationsPath string) (err []error, ok bool) {
	pipe := pipep.New()
	go Reset(pipe, url, migrationsPath)
	err = pipep.ReadErrors(pipe)
	return err, len(err) == 0
}

// Migrate applies relative +n/-n migrations
func Migrate(pipe chan interface{}, url, migrationsPath string, relativeN int) {
	d, files, version, err := initDriverAndReadMigrationFilesAndGetVersion(url, migrationsPath)
	if err != nil {
		go pipep.Close(pipe, err)
		return
	}

	applyMigrationFiles, err := files.From(version, relativeN)
	if err != nil {
		if err2 := d.Close(); err2 != nil {
			pipe <- err2
		}
		go pipep.Close(pipe, err)
		return
	}

	if len(applyMigrationFiles) > 0 && relativeN != 0 {
		for _, f := range applyMigrationFiles {
			pipe1 := pipep.New()
			go d.Migrate(f, pipe1)
			if ok := pipep.WaitAndRedirect(pipe1, pipe, handleInterrupts()); !ok {
				break
			}
		}
		if err2 := d.Close(); err2 != nil {
			pipe <- err2
		}
		go pipep.Close(pipe, nil)
		return
	}
	if err2 := d.Close(); err2 != nil {
		pipe <- err2
	}
	go pipep.Close(pipe, nil)
	return
}

// MigrateSync is synchronous version of Migrate
func MigrateSync(url, migrationsPath string, relativeN int) (err []error, ok bool) {
	pipe := pipep.New()
	go Migrate(pipe, url, migrationsPath, relativeN)
	err = pipep.ReadErrors(pipe)
	return err, len(err) == 0
}

// Version returns the current migration version
func Version(url, migrationsPath string) (version uint64, err error) {
	d, err := driver.New(url)
	if err != nil {
		return 0, err
	}
	return d.Version()
}

// Create creates new migration files on disk
func Create(url, migrationsPath, name string) (*file.MigrationFile, error) {
	d, err := driver.New(url)
	if err != nil {
		return nil, err
	}
	files, err := file.ReadMigrationFilesFromStore(fileStore, migrationsPath,
		file.FilenameRegex(d.FilenameExtension()))
	if err != nil {
		return nil, err
	}

	version := uint64(0)
	if len(files) > 0 {
		lastFile := files[len(files)-1]
		version = lastFile.Version
	}
	version += 1
	versionStr := strconv.FormatUint(version, 10)

	length := 4 // TODO(mattes) check existing files and try to guess length
	if len(versionStr)%length != 0 {
		versionStr = strings.Repeat("0", length-len(versionStr)%length) + versionStr
	}

	filenamef := "%s_%s.%s.%s"
	name = strings.Replace(name, " ", "_", -1)

	mfile := &file.MigrationFile{
		Version: version,
		UpFile: &file.File{
			Path:      migrationsPath,
			FileName:  fmt.Sprintf(filenamef, versionStr, name, "up", d.FilenameExtension()),
			Name:      name,
			Content:   []byte(""),
			Direction: direction.Up,
		},
		DownFile: &file.File{
			Path:      migrationsPath,
			FileName:  fmt.Sprintf(filenamef, versionStr, name, "down", d.FilenameExtension()),
			Name:      name,
			Content:   []byte(""),
			Direction: direction.Down,
		},
	}

	if err := ioutil.WriteFile(path.Join(mfile.UpFile.Path, mfile.UpFile.FileName), mfile.UpFile.Content, 0644); err != nil {
		return nil, err
	}
	if err := ioutil.WriteFile(path.Join(mfile.DownFile.Path, mfile.DownFile.FileName), mfile.DownFile.Content, 0644); err != nil {
		return nil, err
	}

	return mfile, nil
}

// initDriverAndReadMigrationFilesAndGetVersion is a small helper
// function that is common to most of the migration funcs
func initDriverAndReadMigrationFilesAndGetVersion(url, migrationsPath string) (driver.Driver, *file.MigrationFiles, uint64, error) {
	d, err := driver.New(url)
	if err != nil {
		return nil, nil, 0, err
	}
	files, err := file.ReadMigrationFilesFromStore(fileStore, migrationsPath,
		file.FilenameRegex(d.FilenameExtension()))
	if err != nil {
		d.Close() // TODO what happens with errors from this func?
		return nil, nil, 0, err
	}
	version, err := d.Version()
	if err != nil {
		d.Close() // TODO what happens with errors from this func?
		return nil, nil, 0, err
	}
	return d, &files, version, nil
}

// NewPipe is a convenience function for pipe.New().
// This is helpful if the user just wants to import this package and nothing else.
func NewPipe() chan interface{} {
	return pipep.New()
}

// interrupts is an internal variable that holds the state of
// interrupt handling
var interrupts = true

// Graceful enables interrupts checking. Once the first ^C is received
// it will finish the currently running migration and abort execution
// of the next migration. If ^C is received twice, it will stop
// execution immediately.
func Graceful() {
	interrupts = true
}

// NonGraceful disables interrupts checking. The first received ^C will
// stop execution immediately.
func NonGraceful() {
	interrupts = false
}

// File store to read migration scripts from
var fileStore file.FileStore = &file.FSStore{}

// Read migration scripts from a given file store.
//
// In order to use bindata asset as a store:
// 	import "github.com/mattes/migrate/migrate"
// 	import "github.com/mattes/migrate/file"
// 	...
// 	migrate.UseStore(file.AssetStore{
// 		Asset: Asset,
// 		AssetDir: AssetDir,
// 	})
func UseStore(store file.FileStore) {
	fileStore = store
}

// interrupts returns a signal channel if interrupts checking is
// enabled. nil otherwise.
func handleInterrupts() chan os.Signal {
	if interrupts {
		c := make(chan os.Signal, 1)
		signal.Notify(c, os.Interrupt)
		return c
	}
	return nil
}
<|endoftext|>


<commit_before>// +build windows

package jibber_jabber

import (
	"errors"
	"syscall"
	"unsafe"
)

const LOCALE_NAME_MAX_LENGTH uint32 = 85

var SUPPORTED_LOCALES = map[uintptr]string{
	0x0407: "de-DE",
	0x0409: "en-US",
	0x0c0a: "es-ES", //or is it 0x040a
	0x040c: "fr-FR",
	0x0410: "it-IT",
	0x0411: "ja-JA",
	//0x0412: "ko_KO", - Will add support for Korean when nicksnyder/go-i18n supports Korean
	0x0416: "pt-BR",
	//0x0419: "ru_RU", - Will add support for Russian when nicksnyder/go-i18n supports Russian
	0x0804: "zh-CN",
	0x0c04: "zh-CK",
}

func getWindowsLocaleFrom(sysCall string) (locale string, err error) {
	buffer := make([]uint16, LOCALE_NAME_MAX_LENGTH)

	dll := syscall.MustLoadDLL("kernel32")
	proc := dll.MustFindProc(sysCall)
	r, _, dllError := proc.Call(uintptr(unsafe.Pointer(&buffer[0])), uintptr(LOCALE_NAME_MAX_LENGTH))
	if r == 0 {
		err = errors.New(COULD_NOT_DETECT_PACKAGE_ERROR_MESSAGE + ":\n" + dllError.Error())
		return
	}

	locale = syscall.UTF16ToString(buffer)

	return
}

func getAllWindowsLocaleFrom(sysCall string) (string, error) {
	dll, err := syscall.LoadDLL("kernel32")
	if err != nil {
		return "", errors.New("Could not find kernel32 dll")
	}

	proc, err := dll.FindProc(sysCall)
	if err != nil {
		return "", err
	}

	r, locale, dllError := proc.Call()
	if r == 0 {
		return "", errors.New(COULD_NOT_DETECT_PACKAGE_ERROR_MESSAGE + ":\n" + dllError.Error())
	}

	return SUPPORTED_LOCALES[locale], nil
}

func getWindowsLocale() (locale string, err error) {
	dll, err := syscall.LoadDLL("kernel32")
	if err != nil {
		return "", errors.New("Could not find kernel32 dll")
	}

	proc, err := dll.FindProc("IsWindowsVistaOrGreater")
	if err != nil {
		return "", err
	}

	r, isVistaOrGreater, dllError := proc.Call()
	if r == 0 {
		return "", errors.New("Could not determine if the version of Windows is Vista or later:\n" + dllError.Error())
	}

	if isVistaOrGreater == 1 {
		locale, err = getWindowsLocaleFrom("GetUserDefaultLocaleName")
		if err != nil {
			locale, err = getWindowsLocaleFrom("GetSystemDefaultLocaleName")
		}
	} else if isVistaOrGreater == 0 {
		locale, err = getAllWindowsLocaleFrom("GetUserDefaultLCID")
		if err != nil {
			locale, err = getAllWindowsLocaleFrom("GetSystemDefaultLCID")
		}
	} else {
		panic(fmt.Sprintf("we do not know what we are doing and the value is: %#v" + isVistaOrGreater))
	}
	return
}
func DetectIETF() (locale string, err error) {
	locale, err = getWindowsLocale()
	return
}

func DetectLanguage() (language string, err error) {
	windows_locale, err := getWindowsLocale()
	if err == nil {
		language, _ = splitLocale(windows_locale)
	}

	return
}

func DetectTerritory() (territory string, err error) {
	windows_locale, err := getWindowsLocale()
	if err == nil {
		_, territory = splitLocale(windows_locale)
	}

	return
}
<commit_msg>Yet another attempt to fix Windows<commit_after>// +build windows

package jibber_jabber

import (
	"errors"
	"fmt"
	"syscall"
	"unsafe"
)

const LOCALE_NAME_MAX_LENGTH uint32 = 85

var SUPPORTED_LOCALES = map[uintptr]string{
	0x0407: "de-DE",
	0x0409: "en-US",
	0x0c0a: "es-ES", //or is it 0x040a
	0x040c: "fr-FR",
	0x0410: "it-IT",
	0x0411: "ja-JA",
	//0x0412: "ko_KO", - Will add support for Korean when nicksnyder/go-i18n supports Korean
	0x0416: "pt-BR",
	//0x0419: "ru_RU", - Will add support for Russian when nicksnyder/go-i18n supports Russian
	0x0804: "zh-CN",
	0x0c04: "zh-CK",
}

func getWindowsLocaleFrom(sysCall string) (locale string, err error) {
	buffer := make([]uint16, LOCALE_NAME_MAX_LENGTH)

	dll := syscall.MustLoadDLL("kernel32")
	proc := dll.MustFindProc(sysCall)
	r, _, dllError := proc.Call(uintptr(unsafe.Pointer(&buffer[0])), uintptr(LOCALE_NAME_MAX_LENGTH))
	if r == 0 {
		err = errors.New(COULD_NOT_DETECT_PACKAGE_ERROR_MESSAGE + ":\n" + dllError.Error())
		return
	}

	locale = syscall.UTF16ToString(buffer)

	return
}

func getAllWindowsLocaleFrom(sysCall string) (string, error) {
	dll, err := syscall.LoadDLL("kernel32")
	if err != nil {
		return "", errors.New("Could not find kernel32 dll")
	}

	proc, err := dll.FindProc(sysCall)
	if err != nil {
		return "", err
	}

	r, locale, dllError := proc.Call()
	if r == 0 {
		return "", errors.New(COULD_NOT_DETECT_PACKAGE_ERROR_MESSAGE + ":\n" + dllError.Error())
	}

	return SUPPORTED_LOCALES[locale], nil
}

func getWindowsLocale() (locale string, err error) {
	dll, err := syscall.LoadDLL("kernel32")
	if err != nil {
		return "", errors.New("Could not find kernel32 dll")
	}

	proc, err := dll.FindProc("IsWindowsVistaOrGreater")
	if err != nil {
		return "", err
	}

	r, isVistaOrGreater, dllError := proc.Call()
	if r == 0 {
		return "", errors.New("Could not determine if the version of Windows is Vista or later:\n" + dllError.Error())
	}

	if isVistaOrGreater == 1 {
		locale, err = getWindowsLocaleFrom("GetUserDefaultLocaleName")
		if err != nil {
			locale, err = getWindowsLocaleFrom("GetSystemDefaultLocaleName")
		}
	} else if isVistaOrGreater == 0 {
		locale, err = getAllWindowsLocaleFrom("GetUserDefaultLCID")
		if err != nil {
			locale, err = getAllWindowsLocaleFrom("GetSystemDefaultLCID")
		}
	} else {
		panic(fmt.Sprintf("we do not know what we are doing and the value is: %s" + syscall.UTF16ToString(isVistaOrGreater)))
	}
	return
}
func DetectIETF() (locale string, err error) {
	locale, err = getWindowsLocale()
	return
}

func DetectLanguage() (language string, err error) {
	windows_locale, err := getWindowsLocale()
	if err == nil {
		language, _ = splitLocale(windows_locale)
	}

	return
}

func DetectTerritory() (territory string, err error) {
	windows_locale, err := getWindowsLocale()
	if err == nil {
		_, territory = splitLocale(windows_locale)
	}

	return
}
<|endoftext|>


<commit_before>package substring

import (
	"testing"
	"testing/quick"
)

func testAnyContainsAny(t *testing.T, f func([]string, []string) bool) {
	for _, td := range [][2][]string{
		{{""}, {""}},
		{{"hello"}, {""}},
		{{"b"}, {"b"}},
		{{"ab"}, {"b"}},
		{{"abc"}, {"b"}},
		{{"some", "more", "words"}, {"just", "one", "word"}},
		{{"some", "more", "words"}, {"really", "or", "fewer"}},
		{{"very very long and", "short"}, {"shorter", "longer", "y very l"}},
	} {
		if !f(td[0], td[1]) {
			t.Errorf("fail, %q contains %q", td[0], td[1])
		}
	}
	for _, td := range [][2][]string{
		{{}, {}},
		{{"some", "more", "words"}, {}},
		{{}, {"hello"}},
		{{}, {""}},
		{{""}, {"hello"}},
		{{"", "hello"}, {"HELLO"}},
		{{"some", "more", "words"}, {"no", "not", "really"}},
		{{"some", "short", "words"}, {"some longer", "patterns than that"}},
		{{"very very long and", "short"}, {"shorter", "longer", " very ly"}},
	} {
		if f(td[0], td[1]) {
			t.Errorf("fail, %q does not contain %q", td[0], td[1])
		}
	}
}

func TestAnyContainsAnyNaive(t *testing.T) {
	testAnyContainsAny(t, AnyContainsAnyNaive)
}

func testAgainstNaive(t *testing.T, f func([]string, []string) bool) {
	if err := quick.CheckEqual(f, AnyContainsAnyNaive, nil); err != nil {
		t.Error(err)
	}
}

func TestAnyContainsAnyRadix(t *testing.T) {
	testAnyContainsAny(t, AnyContainsAnyRadix)
}

func TestAnyContainsAnyRadixQuick(t *testing.T) {
	testAgainstNaive(t, AnyContainsAnyRadix)
}

func TestAnyContainsAnyKR(t *testing.T) {
	testAnyContainsAny(t, AnyContainsAnyKarpRabin)
}

func TestAnyContainsAnyKRQuick(t *testing.T) {
	testAgainstNaive(t, AnyContainsAnyKarpRabin)
}
<commit_msg>Starting on benchmarks.<commit_after>package substring

import (
	"math/rand"
	"strings"
	"testing"
	"testing/quick"
)

func testAnyContainsAny(t *testing.T, f func([]string, []string) bool) {
	for _, td := range [][2][]string{
		{{""}, {""}},
		{{"hello"}, {""}},
		{{"b"}, {"b"}},
		{{"ab"}, {"b"}},
		{{"abc"}, {"b"}},
		{{"some", "more", "words"}, {"just", "one", "word"}},
		{{"some", "more", "words"}, {"really", "or", "fewer"}},
		{{"very very long and", "short"}, {"shorter", "longer", "y very l"}},
	} {
		if !f(td[0], td[1]) {
			t.Errorf("fail, %q contains %q", td[0], td[1])
		}
	}
	for _, td := range [][2][]string{
		{{}, {}},
		{{"some", "more", "words"}, {}},
		{{}, {"hello"}},
		{{}, {""}},
		{{""}, {"hello"}},
		{{"", "hello"}, {"HELLO"}},
		{{"some", "more", "words"}, {"no", "not", "really"}},
		{{"some", "short", "words"}, {"some longer", "patterns than that"}},
		{{"very very long and", "short"}, {"shorter", "longer", " very ly"}},
	} {
		if f(td[0], td[1]) {
			t.Errorf("fail, %q does not contain %q", td[0], td[1])
		}
	}
}

func TestAnyContainsAnyNaive(t *testing.T) {
	testAnyContainsAny(t, AnyContainsAnyNaive)
}

func testAgainstNaive(t *testing.T, f func([]string, []string) bool) {
	if err := quick.CheckEqual(f, AnyContainsAnyNaive, nil); err != nil {
		t.Error(err)
	}
}

func TestAnyContainsAnyRadix(t *testing.T) {
	testAnyContainsAny(t, AnyContainsAnyRadix)
}

func TestAnyContainsAnyRadixQuick(t *testing.T) {
	testAgainstNaive(t, AnyContainsAnyRadix)
}

func TestAnyContainsAnyKR(t *testing.T) {
	testAnyContainsAny(t, AnyContainsAnyKarpRabin)
}

func TestAnyContainsAnyKRQuick(t *testing.T) {
	testAgainstNaive(t, AnyContainsAnyKarpRabin)
}

func makeBenchInputHard() string {
	tokens := [...]string{
		"", "
", "", "",
		"", "
", "", "",
		"hello", "world",
	}
	x := make([]byte, 0, 1<<20)
	for {
		i := rand.Intn(len(tokens))
		if len(x)+len(tokens[i]) >= 1<<20 {
			break
		}
		x = append(x, tokens[i]...)
	}
	return string(x)
}

var benchInputHard = makeBenchInputHard()

func benchmarkMatcherHard(b *testing.B, mm MatcherMaker) {
	m := mm([]string{"<>", "
", "hello world"})
	for i := 0; i < b.N; i++ {
		m.Matches(benchInputHard)
	}
}

func benchmarkMatcherHard2(b *testing.B, mm MatcherMaker) {
	m := mm([]string{
		"
a couple more
",
		"and longer",
		"
some way longer
",
		"
patterns than
",
		"the other case",
		"no idea if this makes a real difference",
		"though, no really",
		"we'll just have to see",
		"hello world hello world",
	})
	for i := 0; i < b.N; i++ {
		m.Matches(benchInputHard)
	}
}

func benchmarkMatcherHard3(b *testing.B, mm MatcherMaker) {
	m := mm([]string{
		"let's", "see", "what", "happens", "with", "lots",
		"of", "words", "that", "aren't", "just",
		"one", "letter", "each", "but", "THAT", "aren't",
		"really", "particularly", "long", "either", "such",
		"as", "hello world", "none", "that", "match",
	})
	for i := 0; i < b.N; i++ {
		m.Matches(benchInputHard)
	}
}

func benchmarkMatcherHard4(b *testing.B, mm MatcherMaker) {
	m := mm([]string{
		"xyz", "nothing", "matches", "xylophone", "man",
		"of", "in", "an", "any", "if", "it", "is", "don't", "really",
		"know", "what", "I'm", "doing", "here",
	})
	for i := 0; i < b.N; i++ {
		m.Matches(benchInputHard)
	}
}

func BenchmarkBruteHard(b *testing.B)     { benchmarkMatcherHard(b, MakeBrute) }
func BenchmarkRadixHard(b *testing.B)     { benchmarkMatcherHard(b, MakeRadix) }
func BenchmarkRabinKarpHard(b *testing.B) { benchmarkMatcherHard(b, MakeRabinKarp) }

func BenchmarkBruteHard2(b *testing.B)     { benchmarkMatcherHard2(b, MakeBrute) }
func BenchmarkRadixHard2(b *testing.B)     { benchmarkMatcherHard2(b, MakeRadix) }
func BenchmarkRabinKarpHard2(b *testing.B) { benchmarkMatcherHard2(b, MakeRabinKarp) }

func BenchmarkBruteHard3(b *testing.B)     { benchmarkMatcherHard3(b, MakeBrute) }
func BenchmarkRadixHard3(b *testing.B)     { benchmarkMatcherHard3(b, MakeRadix) }
func BenchmarkRabinKarpHard3(b *testing.B) { benchmarkMatcherHard3(b, MakeRabinKarp) }

func BenchmarkBruteHard4(b *testing.B)     { benchmarkMatcherHard4(b, MakeBrute) }
func BenchmarkRadixHard4(b *testing.B)     { benchmarkMatcherHard4(b, MakeRadix) }
func BenchmarkRabinKarpHard4(b *testing.B) { benchmarkMatcherHard4(b, MakeRabinKarp) }

var benchInputTorture = strings.Repeat("ABC", 1<<10) + "123" + strings.Repeat("ABC", 1<<10)
var benchNeedleTorture = strings.Repeat("ABC", 1<<10+1)
<|endoftext|>


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

// +build windows

package dokan

import (
	"testing"
	"time"
)

func testTimePacking(t *testing.T, t0 time.Time) {
	t1 := unpackTime(packTime(t0))
	if !t0.Equal(t1) {
		t.Fatal("Time pack+unpack not equal with original: %v => %v", t0, t1)
	}
}

func TestTimePacking(t *testing.T) {
	testTimePacking(t, time.Time{})
	testTimePacking(t, time.Now())
	testTimePacking(t, time.Unix(0, 0))
}

func TestCtxAlloc(t *testing.T) {
	ctx := allocCtx(0)
	ctx.Free()
}
<commit_msg>fix dokan test<commit_after>// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

// +build windows

package dokan

import (
	"testing"
	"time"
)

func testTimePacking(t *testing.T, t0 time.Time) {
	t1 := unpackTime(packTime(t0))
	if !t0.Equal(t1) {
		t.Fatalf("Time pack+unpack not equal with original: %v => %v", t0, t1)
	}
}

func TestTimePacking(t *testing.T) {
	testTimePacking(t, time.Time{})
	testTimePacking(t, time.Now())
	testTimePacking(t, time.Unix(0, 0))
}

func TestCtxAlloc(t *testing.T) {
	ctx := allocCtx(0)
	ctx.Free()
}
<|endoftext|>


<commit_before>package quickselect

import (
  "testing"
)

type TestData struct {
  Array []int
}

func (t TestData) Len() (int) {
  return len(t.Array)
}

func (t TestData) Less(i, j int) bool {
  return t.Array[i] < t.Array[j]
}

func (t TestData) Swap(i, j int) {
  t.Array[i], t.Array[j] = t.Array[j], t.Array[i]
}

func TestQuickSelectWithSimpleArray(t *testing.T) {
  fixture := TestData{[]int{50, 20, 30, 25, 45, 2, 6, 10, 3, 4, 5}}
  err := QuickSelect(fixture, 5)
  if err != nil {
    t.Errorf("Shouldn't have raised error: '%s'", err.Error())
  }

  smallestK := fixture.Array[:5]
  expectedK := []int{2,3,4,5,6}
  if !hasSameElements(smallestK, expectedK) {
    t.Errorf("Expected smallest K elements to be '%s', but got '%s'", expectedK, smallestK)
  }
}

func TestQuickSelectWithRepeatedElements(t *testing.T) {
  fixture := TestData{[]int{2, 10, 5, 3, 2, 6, 2, 6, 10, 3, 4, 5}}
  err := QuickSelect(fixture, 5)
  if err != nil {
    t.Errorf("Shouldn't have raised error: '%s'", err.Error())
  }

  smallestK := fixture.Array[:5]
  expectedK := []int{2,2,2,3,3}
  if !hasSameElements(smallestK, expectedK) {
    t.Errorf("Expected smallest K elements to be '%s', but got '%s'", expectedK, smallestK)
  }
}

func TestQuickSelectEmptyDataStructure(t *testing.T) {
  fixture := TestData{[]int{}}
  err := QuickSelect(fixture, 0)
  if err == nil {
    t.Errorf("Should have raised error on index outside of array length.")
  }

  err = QuickSelect(fixture, 5)
  if err == nil {
    t.Errorf("Should have raised error on index outside of array length.")
  }

  err = QuickSelect(fixture, -1)
  if err == nil {
    t.Errorf("Should have raised error on index outside of array length.")
  }
}

func TestIntSliceQuickSelect(t *testing.T) {
  fixtures := []struct {
    Array IntSlice
    ExpectedK []int
  }{
    {[]int{0, 14, 16, 29, 12, 2, 4, 4, 7, 29}, []int{0, 2, 4, 4}},
    {[]int{9, 3, 2, 18}, []int{9, 3, 2, 18}},
    {[]int{16, 29, -11, 25, 28, -14, 10, 4, 7, -27}, []int{-27, -11, -14, 4}},
  }

  for _, fixture := range fixtures {
    err := fixture.Array.QuickSelect(3)
    if err != nil {
      t.Errorf("Shouldn't have raised error: '%s'", err.Error())
    }

    resultK := fixture.Array[:4]
    if !hasSameElements(resultK, fixture.ExpectedK) {
      t.Errorf("Expected smallest K elements to be '%s', but got '%s'", fixture.ExpectedK, resultK)
    }
  }
}

func TestFloat64SliceQuickSelect(t *testing.T) {
  fixtures := []struct {
    Array Float64Slice
    ExpectedK []float64
  }{
    {[]float64{0.0, 14.3, 16.5, 29.7, 12.6, 2.4, 4.9, 4.2, 7.1, 29.3}, []float64{0.0, 2.4, 4.2, 4.9}},
    {[]float64{9.3, 3.3, 2.7, 18.5}, []float64{9.3, 3.3, 2.7, 18.5}},
    {[]float64{16.1, 29.3, -11.5, 25.3, 28.8, -14.7, 10.5, 4.4, 7.5, -27.9}, []float64{-27.9, -11.5, -14.7, 4.4}},
  }

  for _, fixture := range fixtures {
    err := fixture.Array.QuickSelect(3)
    if err != nil {
      t.Errorf("Shouldn't have raised error: '%s'", err.Error())
    }

    resultK := fixture.Array[:4]
    if !hasSameElementsFloat64(resultK, fixture.ExpectedK) {
      t.Errorf("Expected smallest K elements to be '%s', but got '%s'", fixture.ExpectedK, resultK)
    }
  }
}

func hasSameElements(array1, array2 []int) (bool) {
  elements := make(map[int]int)

  for _, elem1 := range array1 {
    elements[elem1]++
  }

  for _, elem2 := range array2 {
    elements[elem2]--
  }

  for _, count := range elements {
    if count != 0 {
      return false
    }
  }
  return true
}

func hasSameElementsFloat64(array1, array2 []float64) (bool) {
  elements := make(map[float64]int)

  for _, elem1 := range array1 {
    elements[elem1]++
  }

  for _, elem2 := range array2 {
    elements[elem2]--
  }

  for _, count := range elements {
    if count != 0 {
      return false
    }
  }
  return true
}
<commit_msg>Benchmarks for quickselect vs. sorting<commit_after>package quickselect

import (
  "testing"
  "sort"
)

type TestData struct {
  Array []int
}

func (t TestData) Len() (int) {
  return len(t.Array)
}

func (t TestData) Less(i, j int) bool {
  return t.Array[i] < t.Array[j]
}

func (t TestData) Swap(i, j int) {
  t.Array[i], t.Array[j] = t.Array[j], t.Array[i]
}

func TestQuickSelectWithSimpleArray(t *testing.T) {
  fixture := TestData{[]int{50, 20, 30, 25, 45, 2, 6, 10, 3, 4, 5}}
  err := QuickSelect(fixture, 5)
  if err != nil {
    t.Errorf("Shouldn't have raised error: '%s'", err.Error())
  }

  smallestK := fixture.Array[:5]
  expectedK := []int{2,3,4,5,6}
  if !hasSameElements(smallestK, expectedK) {
    t.Errorf("Expected smallest K elements to be '%s', but got '%s'", expectedK, smallestK)
  }
}

func TestQuickSelectWithRepeatedElements(t *testing.T) {
  fixture := TestData{[]int{2, 10, 5, 3, 2, 6, 2, 6, 10, 3, 4, 5}}
  err := QuickSelect(fixture, 5)
  if err != nil {
    t.Errorf("Shouldn't have raised error: '%s'", err.Error())
  }

  smallestK := fixture.Array[:5]
  expectedK := []int{2,2,2,3,3}
  if !hasSameElements(smallestK, expectedK) {
    t.Errorf("Expected smallest K elements to be '%s', but got '%s'", expectedK, smallestK)
  }
}

func TestQuickSelectEmptyDataStructure(t *testing.T) {
  fixture := TestData{[]int{}}
  err := QuickSelect(fixture, 0)
  if err == nil {
    t.Errorf("Should have raised error on index outside of array length.")
  }

  err = QuickSelect(fixture, 5)
  if err == nil {
    t.Errorf("Should have raised error on index outside of array length.")
  }

  err = QuickSelect(fixture, -1)
  if err == nil {
    t.Errorf("Should have raised error on index outside of array length.")
  }
}

func TestIntSliceQuickSelect(t *testing.T) {
  fixtures := []struct {
    Array IntSlice
    ExpectedK []int
  }{
    {[]int{0, 14, 16, 29, 12, 2, 4, 4, 7, 29}, []int{0, 2, 4, 4}},
    {[]int{9, 3, 2, 18}, []int{9, 3, 2, 18}},
    {[]int{16, 29, -11, 25, 28, -14, 10, 4, 7, -27}, []int{-27, -11, -14, 4}},
  }

  for _, fixture := range fixtures {
    err := fixture.Array.QuickSelect(3)
    if err != nil {
      t.Errorf("Shouldn't have raised error: '%s'", err.Error())
    }

    resultK := fixture.Array[:4]
    if !hasSameElements(resultK, fixture.ExpectedK) {
      t.Errorf("Expected smallest K elements to be '%s', but got '%s'", fixture.ExpectedK, resultK)
    }
  }
}

func TestFloat64SliceQuickSelect(t *testing.T) {
  fixtures := []struct {
    Array Float64Slice
    ExpectedK []float64
  }{
    {[]float64{0.0, 14.3, 16.5, 29.7, 12.6, 2.4, 4.9, 4.2, 7.1, 29.3}, []float64{0.0, 2.4, 4.2, 4.9}},
    {[]float64{9.3, 3.3, 2.7, 18.5}, []float64{9.3, 3.3, 2.7, 18.5}},
    {[]float64{16.1, 29.3, -11.5, 25.3, 28.8, -14.7, 10.5, 4.4, 7.5, -27.9}, []float64{-27.9, -11.5, -14.7, 4.4}},
  }

  for _, fixture := range fixtures {
    err := fixture.Array.QuickSelect(3)
    if err != nil {
      t.Errorf("Shouldn't have raised error: '%s'", err.Error())
    }

    resultK := fixture.Array[:4]
    if !hasSameElementsFloat64(resultK, fixture.ExpectedK) {
      t.Errorf("Expected smallest K elements to be '%s', but got '%s'", fixture.ExpectedK, resultK)
    }
  }
}

func hasSameElements(array1, array2 []int) (bool) {
  elements := make(map[int]int)

  for _, elem1 := range array1 {
    elements[elem1]++
  }

  for _, elem2 := range array2 {
    elements[elem2]--
  }

  for _, count := range elements {
    if count != 0 {
      return false
    }
  }
  return true
}

func hasSameElementsFloat64(array1, array2 []float64) (bool) {
  elements := make(map[float64]int)

  for _, elem1 := range array1 {
    elements[elem1]++
  }

  for _, elem2 := range array2 {
    elements[elem2]--
  }

  for _, count := range elements {
    if count != 0 {
      return false
    }
  }
  return true
}

func bench(b *testing.B, size, k int, quickselect bool) {
  b.StopTimer()
  data := make(IntSlice, size)
  x := ^uint32(0)
  for i := 0; i < b.N; i++ {
    for n := size - 3; n <= size+3; n++ {
      for i := 0; i < len(data); i++ {
        x += x
        x ^= 1
        if int32(x) < 0 {
          x ^= 0x88888eef
        }
        data[i] = int(x % uint32(n/5))
      }
      if quickselect {
        b.StartTimer()
        QuickSelect(data, k)
        b.StopTimer()
      } else {
        b.StartTimer()
        sort.Sort(data)
        b.StopTimer()
      }
    }
  }
}

// Benchmarks for QuickSelect
func BenchmarkQuickSelectSize1e2K1e1(b *testing.B) { bench(b, 1e2, 1e1, true) }
func BenchmarkQuickSelectSize1e4K1e1(b *testing.B) { bench(b, 1e4, 1e1, true) }
func BenchmarkQuickSelectSize1e6K1e1(b *testing.B) { bench(b, 1e6, 1e1, true) }
func BenchmarkQuickSelectSize1e8K1e1(b *testing.B) { bench(b, 1e8, 1e1, true) }
func BenchmarkQuickSelectSize1e4K1e2(b *testing.B) { bench(b, 1e4, 1e2, true) }
func BenchmarkQuickSelectSize1e6K1e2(b *testing.B) { bench(b, 1e6, 1e2, true) }
func BenchmarkQuickSelectSize1e8K1e2(b *testing.B) { bench(b, 1e8, 1e2, true) }
func BenchmarkQuickSelectSize1e6K1e4(b *testing.B) { bench(b, 1e6, 1e4, true) }
func BenchmarkQuickSelectSize1e8K1e4(b *testing.B) { bench(b, 1e8, 1e4, true) }
func BenchmarkQuickSelectSize1e8K1e6(b *testing.B) { bench(b, 1e8, 1e6, true) }

// Benchmarks for sorting
func BenchmarkSortSize1e2K1e1(b *testing.B) { bench(b, 1e2, 1e1, false) }
func BenchmarkSortSize1e4K1e1(b *testing.B) { bench(b, 1e4, 1e1, false) }
func BenchmarkSortSize1e6K1e1(b *testing.B) { bench(b, 1e6, 1e1, false) }
func BenchmarkSortSize1e8K1e1(b *testing.B) { bench(b, 1e8, 1e1, false) }
<|endoftext|>


<commit_before>package pixel

const fragmentShader = "\n" + `#version 460 core

//------------------------------------------------------------------------------

const uint cmdPicture    = 1;
const uint cmdPictureExt = 2;
const uint cmdPrint      = 3;
const uint cmdPoint      = 4;
const uint cmdPointList  = 5;
const uint cmdLine       = 6;

//------------------------------------------------------------------------------

in PerVertex {
	layout(location=0) flat uint Command;
	layout(location=1) flat uint Bin;
	layout(location=2) vec2 UV;
	layout(location=3) flat uint ColorIndex;
	layout(location=4) flat vec2 Orig;
	layout(location=5) flat float Slope;
	layout(location=6) flat bool Steep;
};

layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord;

//------------------------------------------------------------------------------

layout(binding = 1) uniform usampler2DArray Pictures;
layout(binding = 2) uniform usampler2DArray Fonts;

//------------------------------------------------------------------------------

out uint out_color;

//------------------------------------------------------------------------------

void main(void)
{
	float x, y;
	uint c = 0;
	switch (Command) {
	case cmdPicture:
		uint p = texelFetch(Pictures, ivec3(UV.x, UV.y, 0), 0).x;
		if (p == 0) {
			c = 0;
		} else {
			c = p;// + Tint;
			if (c > 255) {
				c -= 255;
			}
		}
		break;

	case cmdPrint:
		p = texelFetch(Fonts, ivec3(UV.x, UV.y, 0), 0).x;
		if (p == 0) {
			c = 0;
		} else {
			c = p + ColorIndex;
			if (c > 255) {
				c -= 255;
			}
		}
		break;

	case cmdPoint:
	case cmdPointList:
		c = ColorIndex;
		break;

	case cmdLine:
		x = gl_FragCoord.x - Orig.x;
		y = gl_FragCoord.y - Orig.y;
		if (Steep) {
			if (x == round(Slope*y)) {
				c = ColorIndex;
			}
		} else {
			if (y == round(Slope*x)) {
				c = ColorIndex;
			}
		}
		break;
	}

	if (c == 0) {
		discard;
	}

	out_color = c;
}
`

// Copyright (c) 2013-2018 Laurent Moussault. All rights reserved.
// Licensed under a simplified BSD license (see LICENSE file).
//------------------------------------------------------------------------------
<commit_msg>Fix use of Bin in pixel shader<commit_after>package pixel

const fragmentShader = "\n" + `#version 460 core

//------------------------------------------------------------------------------

const uint cmdPicture    = 1;
const uint cmdPictureExt = 2;
const uint cmdPrint      = 3;
const uint cmdPoint      = 4;
const uint cmdPointList  = 5;
const uint cmdLine       = 6;

//------------------------------------------------------------------------------

in PerVertex {
	layout(location=0) flat uint Command;
	layout(location=1) flat uint Bin;
	layout(location=2) vec2 UV;
	layout(location=3) flat uint ColorIndex;
	layout(location=4) flat vec2 Orig;
	layout(location=5) flat float Slope;
	layout(location=6) flat bool Steep;
};

layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord;

//------------------------------------------------------------------------------

layout(binding = 1) uniform usampler2DArray Pictures;
layout(binding = 2) uniform usampler2DArray Fonts;

//------------------------------------------------------------------------------

out uint out_color;

//------------------------------------------------------------------------------

void main(void)
{
	float x, y;
	uint c = 0;
	switch (Command) {
	case cmdPicture:
		uint p = texelFetch(Pictures, ivec3(UV.x, UV.y, Bin), 0).x;
		if (p == 0) {
			c = 0;
		} else {
			c = p;// + Tint;
			if (c > 255) {
				c -= 255;
			}
		}
		break;

	case cmdPrint:
		p = texelFetch(Fonts, ivec3(UV.x, UV.y, Bin), 0).x;
		if (p == 0) {
			c = 0;
		} else {
			c = p + ColorIndex;
			if (c > 255) {
				c -= 255;
			}
		}
		break;

	case cmdPoint:
	case cmdPointList:
		c = ColorIndex;
		break;

	case cmdLine:
		x = gl_FragCoord.x - Orig.x;
		y = gl_FragCoord.y - Orig.y;
		if (Steep) {
			if (x == round(Slope*y)) {
				c = ColorIndex;
			}
		} else {
			if (y == round(Slope*x)) {
				c = ColorIndex;
			}
		}
		break;
	}

	if (c == 0) {
		discard;
	}

	out_color = c;
}
`

// Copyright (c) 2013-2018 Laurent Moussault. All rights reserved.
// Licensed under a simplified BSD license (see LICENSE file).
//------------------------------------------------------------------------------
<|endoftext|>


<commit_before>// Copyright 2022 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package asset

import (
	"fmt"
	"strings"

	"github.com/google/syzkaller/dashboard/dashapi"
)

type Config struct {
	// Debug mode forces syz-ci upload artifacts on each syz-manager restart and also forces
	// it to produce more logs.
	Debug bool `json:"debug"`
	// Where to upload artifacts.
	// If "gs://bucket/" is specified, assets will be stored in the corresponding GCS bucket.
	// If "dummpy://" is specified, assets will not be actually stored anywhere. May be helpful
	// for debugging.
	UploadTo string `json:"upload_to"`
	// Perform asset deprecation from this instance. If several syz-ci's share a common stoage,
	// it make sense to enable derprecation only on one of them.
	DoDeprecation bool `json:"do_deprecation"`
	// Make assets publicly available (note that it also might require special configuration
	// on the storage backend's side).
	PublicAccess bool `json:"public_access"`
	// Which assets need to be uploaded.
	Assets map[dashapi.AssetType]TypeConfig `json:"assets"`
}

type TypeConfig struct {
	Never bool `json:"never"`
	// TODO: in future there'll also be `OnlyOn` and `NeverOn`, but so far we don't really need that.
	// TODO: here will also go compression settings, should we ever want to make it configurable.
}

func (tc *TypeConfig) Validate() error {
	return nil
}

func (c *Config) IsEnabled(assetType dashapi.AssetType) bool {
	return !c.Assets[assetType].Never
}

func (c *Config) IsEmpty() bool {
	return c == nil
}

func (c *Config) Validate() error {
	for assetType, cfg := range c.Assets {
		if GetTypeDescription(assetType) == nil {
			return fmt.Errorf("invalid asset type: %s", assetType)
		}
		if err := cfg.Validate(); err != nil {
			return fmt.Errorf("invalid config for %s: %w", assetType, err)
		}
	}
	if c.UploadTo == "" && len(c.Assets) != 0 {
		return fmt.Errorf("assets are specified, but upload_to is empty")
	}
	allowedFormats := []string{"gs://", "dummy://"}
	if c.UploadTo != "" {
		any := false
		for _, prefix := range allowedFormats {
			if strings.HasPrefix(c.UploadTo, prefix) {
				any = true
			}
		}
		if !any {
			return fmt.Errorf("the currently supported upload destinations are: %v", allowedFormats)
		}
	}
	return nil
}
<commit_msg>pkg/asset: update config documentation<commit_after>// Copyright 2022 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package asset

import (
	"fmt"
	"strings"

	"github.com/google/syzkaller/dashboard/dashapi"
)

type Config struct {
	// Debug mode forces syz-ci upload artifacts on each syz-manager restart and also forces
	// it to produce more logs.
	Debug bool `json:"debug"`
	// Where to upload artifacts.
	// If "gs://bucket/" is specified, assets will be stored in the corresponding GCS bucket.
	// If "dummy://" is specified, assets will not be actually stored anywhere. May be helpful
	// for debugging.
	UploadTo string `json:"upload_to"`
	// Perform asset deprecation from this instance. If several syz-ci's share a common stoage,
	// it make sense to enable derprecation only on one of them.
	DoDeprecation bool `json:"do_deprecation"`
	// Make assets publicly available (note that it also might require special configuration
	// on the storage backend's side).
	PublicAccess bool `json:"public_access"`
	// Some asset type-specific configurations. By default all asset types are enabled.
	Assets map[dashapi.AssetType]TypeConfig `json:"assets"`
}

type TypeConfig struct {
	Never bool `json:"never"`
	// TODO: in future there'll also be `OnlyOn` and `NeverOn`, but so far we don't really need that.
	// TODO: here will also go compression settings, should we ever want to make it configurable.
}

func (tc *TypeConfig) Validate() error {
	return nil
}

func (c *Config) IsEnabled(assetType dashapi.AssetType) bool {
	return !c.Assets[assetType].Never
}

func (c *Config) IsEmpty() bool {
	return c == nil
}

func (c *Config) Validate() error {
	for assetType, cfg := range c.Assets {
		if GetTypeDescription(assetType) == nil {
			return fmt.Errorf("invalid asset type: %s", assetType)
		}
		if err := cfg.Validate(); err != nil {
			return fmt.Errorf("invalid config for %s: %w", assetType, err)
		}
	}
	if c.UploadTo == "" && len(c.Assets) != 0 {
		return fmt.Errorf("assets are specified, but upload_to is empty")
	}
	allowedFormats := []string{"gs://", "dummy://"}
	if c.UploadTo != "" {
		any := false
		for _, prefix := range allowedFormats {
			if strings.HasPrefix(c.UploadTo, prefix) {
				any = true
			}
		}
		if !any {
			return fmt.Errorf("the currently supported upload destinations are: %v", allowedFormats)
		}
	}
	return nil
}
<|endoftext|>


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

package berglas

import (
	"context"
	"sort"

	"cloud.google.com/go/storage"
	"github.com/pkg/errors"
	"google.golang.org/api/iterator"
)

// ListResponse is the response from a list call.
type ListResponse struct {
	// Secrets are the list of secrets in the response.
	Secrets []*Secret
}

// secretList is a list of secrets
type secretList []*Secret

// Len is the number of elements in the collection.
func (s secretList) Len() int {
	return len(s)
}

// Less reports whether the element with
// index i should sort before the element with index j.
func (s secretList) Less(i, j int) bool {
	if s[i].Name == s[j].Name {
		return s[i].Generation > s[j].Generation
	}
	return s[i].Name > s[j].Name
}

// Swap swaps the elements with indexes i and j.
func (s secretList) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

// List is a top-level package function for listing secrets. This doesn't
// fetch the plaintext value of secrets.
func List(ctx context.Context, i *ListRequest) (*ListResponse, error) {
	client, err := New(ctx)
	if err != nil {
		return nil, err
	}
	return client.List(ctx, i)
}

// ListRequest is used as input to a list all secrets in a bucket.
type ListRequest struct {
	// Bucket is the name of the bucket where the secrets live.
	Bucket string

	// Prefix matches secret names to filter
	Prefix string

	// Generations indicates that all generations of secrets should be listed
	Generations bool
}

// List lists all secrets in the bucket. This doesn't fetch the plaintext value
// of secrets.
func (c *Client) List(
	ctx context.Context, i *ListRequest) (*ListResponse, error) {
	if i == nil {
		return nil, errors.New("missing request")
	}

	bucket := i.Bucket
	if bucket == "" {
		return nil, errors.New("missing bucket name")
	}

	allSecrets := map[string][]*storage.ObjectAttrs{}

	query := &storage.Query{
		Prefix:   i.Prefix,
		Versions: i.Generations,
	}

	// List all objects
	it := c.storageClient.
		Bucket(bucket).
		Objects(ctx, query)
	for {
		obj, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, errors.Wrap(err, "failed to list secrets")
		}

		// Only include items with metadata marking them as a secret
		if obj.Metadata != nil && obj.Metadata[MetadataIDKey] == "1" {
			allSecrets[obj.Name] = append(allSecrets[obj.Name], obj)
		}
	}

	var result secretList

	// list objects returns all generations even if the live object is gone.
	// filter on names which have not been deleted
	for _, secretAttrs := range allSecrets {
		foundLiveObject := false
		for _, obj := range secretAttrs {
			if obj.Deleted.IsZero() {
				foundLiveObject = true
				break
			}
		}

		if foundLiveObject {
			for _, attrs := range secretAttrs {
				result = append(result, secretFromAttrs(attrs, nil))
			}
		}
	}

	sort.Sort(result)

	return &ListResponse{
		Secrets: result,
	}, nil
}
<commit_msg>minor naming<commit_after>// Copyright 2019 The Berglas Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package berglas

import (
	"context"
	"sort"

	"cloud.google.com/go/storage"
	"github.com/pkg/errors"
	"google.golang.org/api/iterator"
)

// ListResponse is the response from a list call.
type ListResponse struct {
	// Secrets are the list of secrets in the response.
	Secrets []*Secret
}

// secretList is a list of secrets
type secretList []*Secret

// Len is the number of elements in the collection.
func (s secretList) Len() int {
	return len(s)
}

// Less reports whether the element with
// index i should sort before the element with index j.
func (s secretList) Less(i, j int) bool {
	if s[i].Name == s[j].Name {
		return s[i].Generation > s[j].Generation
	}
	return s[i].Name > s[j].Name
}

// Swap swaps the elements with indexes i and j.
func (s secretList) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

// List is a top-level package function for listing secrets. This doesn't
// fetch the plaintext value of secrets.
func List(ctx context.Context, i *ListRequest) (*ListResponse, error) {
	client, err := New(ctx)
	if err != nil {
		return nil, err
	}
	return client.List(ctx, i)
}

// ListRequest is used as input to a list all secrets in a bucket.
type ListRequest struct {
	// Bucket is the name of the bucket where the secrets live.
	Bucket string

	// Prefix matches secret names to filter
	Prefix string

	// Generations indicates that all generations of secrets should be listed
	Generations bool
}

// List lists all secrets in the bucket. This doesn't fetch the plaintext value
// of secrets.
func (c *Client) List(
	ctx context.Context, i *ListRequest) (*ListResponse, error) {
	if i == nil {
		return nil, errors.New("missing request")
	}

	bucket := i.Bucket
	if bucket == "" {
		return nil, errors.New("missing bucket name")
	}

	allObjects := map[string][]*storage.ObjectAttrs{}

	query := &storage.Query{
		Prefix:   i.Prefix,
		Versions: i.Generations,
	}

	// List all objects
	it := c.storageClient.
		Bucket(bucket).
		Objects(ctx, query)
	for {
		obj, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, errors.Wrap(err, "failed to list secrets")
		}

		// Only include items with metadata marking them as a secret
		if obj.Metadata != nil && obj.Metadata[MetadataIDKey] == "1" {
			allObjects[obj.Name] = append(allObjects[obj.Name], obj)
		}
	}

	var result secretList

	// list objects returns all generations even if the live object is gone.
	// filter on names which have not been deleted
	for _, objects := range allObjects {
		foundLiveObject := false
		for _, obj := range objects {
			if obj.Deleted.IsZero() {
				foundLiveObject = true
				break
			}
		}

		if foundLiveObject {
			for _, obj := range objects {
				result = append(result, secretFromAttrs(obj, nil))
			}
		}
	}

	sort.Sort(result)

	return &ListResponse{
		Secrets: result,
	}, nil
}
<|endoftext|>


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

package doc

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	mangen "github.com/cpuguy83/go-md2man/md2man"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

// GenManTree will generate a man page for this command and all descendants
// in the directory given. The header may be nil. This function may not work
// correctly if your command names have - in them. If you have `cmd` with two
// subcmds, `sub` and `sub-third`. And `sub` has a subcommand called `third`
// it is undefined which help output will be in the file `cmd-sub-third.1`.
func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error {
	if header == nil {
		header = &GenManHeader{}
	}
	for _, c := range cmd.Commands() {
		if !c.IsAvailableCommand() || c.IsHelpCommand() {
			continue
		}
		if err := GenManTree(c, header, dir); err != nil {
			return err
		}
	}
	section := "1"
	if header.Section != "" {
		section = header.Section
	}

	basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + "." + section
	filename := filepath.Join(dir, basename)
	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	headerCopy := *header
	return GenMan(cmd, &headerCopy, f)
}

// GenManHeader is a lot like the .TH header at the start of man pages. These
// include the title, section, date, source, and manual. We will use the
// current time if Date if unset and will use "Auto generated by spf13/cobra"
// if the Source is unset.
type GenManHeader struct {
	Title   string
	Section string
	Date    *time.Time
	date    string
	Source  string
	Manual  string
}

// GenMan will generate a man page for the given command and write it to
// w. The header argument may be nil, however obviously w may not.
func GenMan(cmd *cobra.Command, header *GenManHeader, w io.Writer) error {
	if header == nil {
		header = &GenManHeader{}
	}
	fillHeader(header, cmd.CommandPath())

	b := genMan(cmd, header)
	_, err := w.Write(mangen.Render(b))
	return err
}

func fillHeader(header *GenManHeader, name string) {
	if header.Title == "" {
		header.Title = strings.ToUpper(strings.Replace(name, " ", "\\-", -1))
	}
	if header.Section == "" {
		header.Section = "1"
	}
	if header.Date == nil {
		now := time.Now()
		header.Date = &now
	}
	header.date = (*header.Date).Format("Jan 2006")
	if header.Source == "" {
		header.Source = "Auto generated by spf13/cobra"
	}
}

func manPreamble(out io.Writer, header *GenManHeader, cmd *cobra.Command, dashedName string) {
	description := cmd.Long
	if len(description) == 0 {
		description = cmd.Short
	}

	fmt.Fprintf(out, `%% %s(%s)%s
%% %s
%% %s
# NAME
`, header.Title, header.Section, header.date, header.Source, header.Manual)
	fmt.Fprintf(out, "%s \\- %s\n\n", dashedName, cmd.Short)
	fmt.Fprintf(out, "# SYNOPSIS\n")
	fmt.Fprintf(out, "**%s**\n\n", cmd.UseLine())
	fmt.Fprintf(out, "# DESCRIPTION\n")
	fmt.Fprintf(out, "%s\n\n", description)
}

func manPrintFlags(out io.Writer, flags *pflag.FlagSet) {
	flags.VisitAll(func(flag *pflag.Flag) {
		if len(flag.Deprecated) > 0 || flag.Hidden {
			return
		}
		format := ""
		if len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 {
			format = fmt.Sprintf("**-%s**, **--%s**", flag.Shorthand, flag.Name)
		} else {
			format = fmt.Sprintf("**--%s**", flag.Name)
		}
		if len(flag.NoOptDefVal) > 0 {
			format = format + "["
		}
		if flag.Value.Type() == "string" {
			// put quotes on the value
			format = format + "=%q"
		} else {
			format = format + "=%s"
		}
		if len(flag.NoOptDefVal) > 0 {
			format = format + "]"
		}
		format = format + "\n\t%s\n\n"
		fmt.Fprintf(out, format, flag.DefValue, flag.Usage)
	})
}

func manPrintOptions(out io.Writer, command *cobra.Command) {
	flags := command.NonInheritedFlags()
	if flags.HasFlags() {
		fmt.Fprintf(out, "# OPTIONS\n")
		manPrintFlags(out, flags)
		fmt.Fprintf(out, "\n")
	}
	flags = command.InheritedFlags()
	if flags.HasFlags() {
		fmt.Fprintf(out, "# OPTIONS INHERITED FROM PARENT COMMANDS\n")
		manPrintFlags(out, flags)
		fmt.Fprintf(out, "\n")
	}
}

func genMan(cmd *cobra.Command, header *GenManHeader) []byte {
	// something like `rootcmd subcmd1 subcmd2`
	commandName := cmd.CommandPath()
	// something like `rootcmd-subcmd1-subcmd2`
	dashCommandName := strings.Replace(commandName, " ", "-", -1)

	buf := new(bytes.Buffer)

	manPreamble(buf, header, cmd, dashCommandName)
	manPrintOptions(buf, cmd)
	if len(cmd.Example) > 0 {
		fmt.Fprintf(buf, "# EXAMPLE\n")
		fmt.Fprintf(buf, "```\n%s\n```\n", cmd.Example)
	}
	if hasSeeAlso(cmd) {
		fmt.Fprintf(buf, "# SEE ALSO\n")
		seealsos := make([]string, 0)
		if cmd.HasParent() {
			parentPath := cmd.Parent().CommandPath()
			dashParentPath := strings.Replace(parentPath, " ", "-", -1)
			seealso := fmt.Sprintf("**%s(%s)**", dashParentPath, header.Section)
			seealsos = append(seealsos, seealso)
			cmd.VisitParents(func(c *cobra.Command) {
				if c.DisableAutoGenTag {
					cmd.DisableAutoGenTag = c.DisableAutoGenTag
				}
			})
		}
		children := cmd.Commands()
		sort.Sort(byName(children))
		for _, c := range children {
			if !c.IsAvailableCommand() || c.IsHelpCommand() {
				continue
			}
			seealso := fmt.Sprintf("**%s-%s(%s)**", dashCommandName, c.Name(), header.Section)
			seealsos = append(seealsos, seealso)
		}
		fmt.Fprintf(buf, "%s\n", strings.Join(seealsos, ", "))
	}
	if !cmd.DisableAutoGenTag {
		fmt.Fprintf(buf, "# HISTORY\n%s Auto generated by spf13/cobra\n", header.Date.Format("2-Jan-2006"))
	}
	return buf.Bytes()
}
<commit_msg>Cretea a new GenManTree function that takes an options struct.<commit_after>// Copyright 2015 Red Hat Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package doc

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	mangen "github.com/cpuguy83/go-md2man/md2man"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

// GenManTree will generate a man page for this command and all descendants
// in the directory given. The header may be nil. This function may not work
// correctly if your command names have - in them. If you have `cmd` with two
// subcmds, `sub` and `sub-third`. And `sub` has a subcommand called `third`
// it is undefined which help output will be in the file `cmd-sub-third.1`.
func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error {
	return GenManTreeFromOpts(cmd, GenManTreeOptions{
		Header:           header,
		Path:             dir,
		CommandSeparator: "_",
	})
}

// GenManTreeFromOpts generates a man page for the command and all descendants.
// The pages are written to the opts.Path directory.
func GenManTreeFromOpts(cmd *cobra.Command, opts GenManTreeOptions) error {
	header := opts.Header
	if header == nil {
		header = &GenManHeader{}
	}
	for _, c := range cmd.Commands() {
		if !c.IsAvailableCommand() || c.IsHelpCommand() {
			continue
		}
		if err := GenManTreeFromOpts(c, opts); err != nil {
			return err
		}
	}
	section := "1"
	if header.Section != "" {
		section = header.Section
	}

	separator := "_"
	if opts.CommandSeparator != "" {
		separator = opts.CommandSeparator
	}
	basename := strings.Replace(cmd.CommandPath(), " ", separator, -1)
	filename := filepath.Join(opts.Path, basename + "." + section)
	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	headerCopy := *header
	return GenMan(cmd, &headerCopy, f)
}

type GenManTreeOptions struct {
	Header           *GenManHeader
	Path             string
	CommandSeparator string
}

// GenManHeader is a lot like the .TH header at the start of man pages. These
// include the title, section, date, source, and manual. We will use the
// current time if Date if unset and will use "Auto generated by spf13/cobra"
// if the Source is unset.
type GenManHeader struct {
	Title   string
	Section string
	Date    *time.Time
	date    string
	Source  string
	Manual  string
}

// GenMan will generate a man page for the given command and write it to
// w. The header argument may be nil, however obviously w may not.
func GenMan(cmd *cobra.Command, header *GenManHeader, w io.Writer) error {
	if header == nil {
		header = &GenManHeader{}
	}
	fillHeader(header, cmd.CommandPath())

	b := genMan(cmd, header)
	_, err := w.Write(mangen.Render(b))
	return err
}

func fillHeader(header *GenManHeader, name string) {
	if header.Title == "" {
		header.Title = strings.ToUpper(strings.Replace(name, " ", "\\-", -1))
	}
	if header.Section == "" {
		header.Section = "1"
	}
	if header.Date == nil {
		now := time.Now()
		header.Date = &now
	}
	header.date = (*header.Date).Format("Jan 2006")
	if header.Source == "" {
		header.Source = "Auto generated by spf13/cobra"
	}
}

func manPreamble(out io.Writer, header *GenManHeader, cmd *cobra.Command, dashedName string) {
	description := cmd.Long
	if len(description) == 0 {
		description = cmd.Short
	}

	fmt.Fprintf(out, `%% %s(%s)%s
%% %s
%% %s
# NAME
`, header.Title, header.Section, header.date, header.Source, header.Manual)
	fmt.Fprintf(out, "%s \\- %s\n\n", dashedName, cmd.Short)
	fmt.Fprintf(out, "# SYNOPSIS\n")
	fmt.Fprintf(out, "**%s**\n\n", cmd.UseLine())
	fmt.Fprintf(out, "# DESCRIPTION\n")
	fmt.Fprintf(out, "%s\n\n", description)
}

func manPrintFlags(out io.Writer, flags *pflag.FlagSet) {
	flags.VisitAll(func(flag *pflag.Flag) {
		if len(flag.Deprecated) > 0 || flag.Hidden {
			return
		}
		format := ""
		if len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 {
			format = fmt.Sprintf("**-%s**, **--%s**", flag.Shorthand, flag.Name)
		} else {
			format = fmt.Sprintf("**--%s**", flag.Name)
		}
		if len(flag.NoOptDefVal) > 0 {
			format = format + "["
		}
		if flag.Value.Type() == "string" {
			// put quotes on the value
			format = format + "=%q"
		} else {
			format = format + "=%s"
		}
		if len(flag.NoOptDefVal) > 0 {
			format = format + "]"
		}
		format = format + "\n\t%s\n\n"
		fmt.Fprintf(out, format, flag.DefValue, flag.Usage)
	})
}

func manPrintOptions(out io.Writer, command *cobra.Command) {
	flags := command.NonInheritedFlags()
	if flags.HasFlags() {
		fmt.Fprintf(out, "# OPTIONS\n")
		manPrintFlags(out, flags)
		fmt.Fprintf(out, "\n")
	}
	flags = command.InheritedFlags()
	if flags.HasFlags() {
		fmt.Fprintf(out, "# OPTIONS INHERITED FROM PARENT COMMANDS\n")
		manPrintFlags(out, flags)
		fmt.Fprintf(out, "\n")
	}
}

func genMan(cmd *cobra.Command, header *GenManHeader) []byte {
	// something like `rootcmd-subcmd1-subcmd2`
	dashCommandName := strings.Replace(cmd.CommandPath(), " ", "-", -1)

	buf := new(bytes.Buffer)

	manPreamble(buf, header, cmd, dashCommandName)
	manPrintOptions(buf, cmd)
	if len(cmd.Example) > 0 {
		fmt.Fprintf(buf, "# EXAMPLE\n")
		fmt.Fprintf(buf, "```\n%s\n```\n", cmd.Example)
	}
	if hasSeeAlso(cmd) {
		fmt.Fprintf(buf, "# SEE ALSO\n")
		seealsos := make([]string, 0)
		if cmd.HasParent() {
			parentPath := cmd.Parent().CommandPath()
			dashParentPath := strings.Replace(parentPath, " ", "-", -1)
			seealso := fmt.Sprintf("**%s(%s)**", dashParentPath, header.Section)
			seealsos = append(seealsos, seealso)
			cmd.VisitParents(func(c *cobra.Command) {
				if c.DisableAutoGenTag {
					cmd.DisableAutoGenTag = c.DisableAutoGenTag
				}
			})
		}
		children := cmd.Commands()
		sort.Sort(byName(children))
		for _, c := range children {
			if !c.IsAvailableCommand() || c.IsHelpCommand() {
				continue
			}
			seealso := fmt.Sprintf("**%s-%s(%s)**", dashCommandName, c.Name(), header.Section)
			seealsos = append(seealsos, seealso)
		}
		fmt.Fprintf(buf, "%s\n", strings.Join(seealsos, ", "))
	}
	if !cmd.DisableAutoGenTag {
		fmt.Fprintf(buf, "# HISTORY\n%s Auto generated by spf13/cobra\n", header.Date.Format("2-Jan-2006"))
	}
	return buf.Bytes()
}
<|endoftext|>


<commit_before>package util

import (
	"errors"
	"fmt"
	"io"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/spf13/cobra"

	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/apimachinery"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	kapi "k8s.io/kubernetes/pkg/api"
	kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
)

// ErrExit is a marker interface for cli commands indicating that the response has been processed
var ErrExit = fmt.Errorf("exit directly")

var commaSepVarsPattern = regexp.MustCompile(".*=.*,.*=.*")

// ReplaceCommandName recursively processes the examples in a given command to change a hardcoded
// command name (like 'kubectl' to the appropriate target name). It returns c.
func ReplaceCommandName(from, to string, c *cobra.Command) *cobra.Command {
	c.Example = strings.Replace(c.Example, from, to, -1)
	for _, sub := range c.Commands() {
		ReplaceCommandName(from, to, sub)
	}
	return c
}

// GetDisplayFilename returns the absolute path of the filename as long as there was no error, otherwise it returns the filename as-is
func GetDisplayFilename(filename string) string {
	if absName, err := filepath.Abs(filename); err == nil {
		return absName
	}

	return filename
}

// ResolveResource returns the resource type and name of the resourceString.
// If the resource string has no specified type, defaultResource will be returned.
func ResolveResource(defaultResource schema.GroupResource, resourceString string, mapper meta.RESTMapper) (schema.GroupResource, string, error) {
	if mapper == nil {
		return schema.GroupResource{}, "", errors.New("mapper cannot be nil")
	}

	var name string
	parts := strings.Split(resourceString, "/")
	switch len(parts) {
	case 1:
		name = parts[0]
	case 2:
		name = parts[1]

		// Allow specifying the group the same way kubectl does, as "resource.group.name"
		groupResource := schema.ParseGroupResource(parts[0])
		// normalize resource case
		groupResource.Resource = strings.ToLower(groupResource.Resource)

		gvr, err := mapper.ResourceFor(groupResource.WithVersion(""))
		if err != nil {
			return schema.GroupResource{}, "", err
		}
		return gvr.GroupResource(), name, nil
	default:
		return schema.GroupResource{}, "", fmt.Errorf("invalid resource format: %s", resourceString)
	}

	return defaultResource, name, nil
}

// convertItemsForDisplay returns a new list that contains parallel elements that have been converted to the most preferred external version
func convertItemsForDisplay(objs []runtime.Object, preferredVersions ...schema.GroupVersion) ([]runtime.Object, error) {
	ret := []runtime.Object{}

	for i := range objs {
		obj := objs[i]
		kinds, _, err := kapi.Scheme.ObjectKinds(obj)
		if err != nil {
			return nil, err
		}

		// Gather all groups where the object kind is known.
		groups := []*apimachinery.GroupMeta{}
		for _, kind := range kinds {
			groupMeta, err := kapi.Registry.Group(kind.Group)
			if err != nil {
				return nil, err
			}
			groups = append(groups, groupMeta)
		}

		actualOutputVersion := schema.GroupVersion{}
		// Find the first preferred version that contains the object kind group.
		// If there are more groups for the given resource, prefer those that are first in the
		// list of preferred versions.
		for _, version := range preferredVersions {
			for _, group := range groups {
				if version.Group == group.GroupVersion.Group {
					for _, externalVersion := range group.GroupVersions {
						if version == externalVersion {
							actualOutputVersion = externalVersion
							break
						}
						if actualOutputVersion.Empty() {
							actualOutputVersion = externalVersion
						}
					}
				}
				if !actualOutputVersion.Empty() {
					break
				}
			}
			if !actualOutputVersion.Empty() {
				break
			}
		}

		convertedObject, err := kapi.Scheme.ConvertToVersion(obj, actualOutputVersion)
		if err != nil {
			return nil, err
		}

		ret = append(ret, convertedObject)
	}

	return ret, nil
}

// convertItemsForDisplayFromDefaultCommand returns a new list that contains parallel elements that have been converted to the most preferred external version
// TODO: move this function into the core factory PrintObjects method
// TODO: print-objects should have preferred output versions
func convertItemsForDisplayFromDefaultCommand(cmd *cobra.Command, objs []runtime.Object) ([]runtime.Object, error) {
	requested := kcmdutil.GetFlagString(cmd, "output-version")
	versions := []schema.GroupVersion{}
	for _, v := range strings.Split(requested, ",") {
		version, err := schema.ParseGroupVersion(v)
		if err != nil {
			return nil, err
		}
		versions = append(versions, version)
	}

	return convertItemsForDisplay(objs, versions...)
}

// VersionedPrintObject handles printing an object in the appropriate version by looking at 'output-version'
// on the command
func VersionedPrintObject(fn func(*cobra.Command, bool, meta.RESTMapper, runtime.Object, io.Writer) error, c *cobra.Command, mapper meta.RESTMapper, out io.Writer) func(runtime.Object) error {
	return func(obj runtime.Object) error {
		// TODO: fold into the core printer functionality (preferred output version)
		if list, ok := obj.(*kapi.List); ok {
			var err error
			if list.Items, err = convertItemsForDisplayFromDefaultCommand(c, list.Items); err != nil {
				return err
			}
		} else {
			result, err := convertItemsForDisplayFromDefaultCommand(c, []runtime.Object{obj})
			if err != nil {
				return err
			}
			obj = result[0]
		}
		return fn(c, false, mapper, obj, out)
	}
}

func WarnAboutCommaSeparation(errout io.Writer, values []string, flag string) {
	if errout == nil {
		return
	}
	for _, value := range values {
		if commaSepVarsPattern.MatchString(value) {
			fmt.Fprintf(errout, "warning: %s no longer accepts comma-separated lists of values. %q will be treated as a single key-value pair.\n", flag, value)
		}
	}
}
<commit_msg>fix newapp resource convert for extensions and apps groups<commit_after>package util

import (
	"errors"
	"fmt"
	"io"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/spf13/cobra"

	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/apimachinery"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	kapi "k8s.io/kubernetes/pkg/api"
	kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
)

// ErrExit is a marker interface for cli commands indicating that the response has been processed
var ErrExit = fmt.Errorf("exit directly")

var commaSepVarsPattern = regexp.MustCompile(".*=.*,.*=.*")

// ReplaceCommandName recursively processes the examples in a given command to change a hardcoded
// command name (like 'kubectl' to the appropriate target name). It returns c.
func ReplaceCommandName(from, to string, c *cobra.Command) *cobra.Command {
	c.Example = strings.Replace(c.Example, from, to, -1)
	for _, sub := range c.Commands() {
		ReplaceCommandName(from, to, sub)
	}
	return c
}

// GetDisplayFilename returns the absolute path of the filename as long as there was no error, otherwise it returns the filename as-is
func GetDisplayFilename(filename string) string {
	if absName, err := filepath.Abs(filename); err == nil {
		return absName
	}

	return filename
}

// ResolveResource returns the resource type and name of the resourceString.
// If the resource string has no specified type, defaultResource will be returned.
func ResolveResource(defaultResource schema.GroupResource, resourceString string, mapper meta.RESTMapper) (schema.GroupResource, string, error) {
	if mapper == nil {
		return schema.GroupResource{}, "", errors.New("mapper cannot be nil")
	}

	var name string
	parts := strings.Split(resourceString, "/")
	switch len(parts) {
	case 1:
		name = parts[0]
	case 2:
		name = parts[1]

		// Allow specifying the group the same way kubectl does, as "resource.group.name"
		groupResource := schema.ParseGroupResource(parts[0])
		// normalize resource case
		groupResource.Resource = strings.ToLower(groupResource.Resource)

		gvr, err := mapper.ResourceFor(groupResource.WithVersion(""))
		if err != nil {
			return schema.GroupResource{}, "", err
		}
		return gvr.GroupResource(), name, nil
	default:
		return schema.GroupResource{}, "", fmt.Errorf("invalid resource format: %s", resourceString)
	}

	return defaultResource, name, nil
}

// convertItemsForDisplay returns a new list that contains parallel elements that have been converted to the most preferred external version
func convertItemsForDisplay(objs []runtime.Object, preferredVersions ...schema.GroupVersion) ([]runtime.Object, error) {
	ret := []runtime.Object{}

	for i := range objs {
		obj := objs[i]
		kinds, _, err := kapi.Scheme.ObjectKinds(obj)
		if err != nil {
			return nil, err
		}

		// Gather all groups where the object kind is known.
		groups := []*apimachinery.GroupMeta{}
		for _, kind := range kinds {
			groupMeta, err := kapi.Registry.Group(kind.Group)
			if err != nil {
				return nil, err
			}
			groups = append(groups, groupMeta)
		}

		// if no preferred versions given, pass all group versions found.
		if len(preferredVersions) == 0 {
			defaultGroupVersions := []runtime.GroupVersioner{}
			for _, group := range groups {
				defaultGroupVersions = append(defaultGroupVersions, group.GroupVersion)
			}

			defaultGroupVersioners := runtime.GroupVersioners(defaultGroupVersions)
			convertedObject, err := kapi.Scheme.ConvertToVersion(obj, defaultGroupVersioners)
			if err != nil {
				return nil, err
			}
			ret = append(ret, convertedObject)
			continue
		}

		actualOutputVersion := schema.GroupVersion{}
		// Find the first preferred version that contains the object kind group.
		// If there are more groups for the given resource, prefer those that are first in the
		// list of preferred versions.
		for _, version := range preferredVersions {
			for _, group := range groups {
				if version.Group == group.GroupVersion.Group {
					for _, externalVersion := range group.GroupVersions {
						if version == externalVersion {
							actualOutputVersion = externalVersion
							break
						}
						if actualOutputVersion.Empty() {
							actualOutputVersion = externalVersion
						}
					}
				}
				if !actualOutputVersion.Empty() {
					break
				}
			}
			if !actualOutputVersion.Empty() {
				break
			}
		}

		// if no preferred version found in the list of given GroupVersions,
		// attempt to convert to first GroupVersion that satisfies a preferred version
		if len(actualOutputVersion.Version) == 0 {
			preferredVersioners := []runtime.GroupVersioner{}
			for _, gv := range preferredVersions {
				preferredVersions = append(preferredVersions, gv)
			}
			preferredVersioner := runtime.GroupVersioners(preferredVersioners)
			convertedObject, err := kapi.Scheme.ConvertToVersion(obj, preferredVersioner)
			if err != nil {
				return nil, err
			}

			ret = append(ret, convertedObject)
			continue
		}

		convertedObject, err := kapi.Scheme.ConvertToVersion(obj, actualOutputVersion)
		if err != nil {
			return nil, err
		}

		ret = append(ret, convertedObject)
	}

	return ret, nil
}

// convertItemsForDisplayFromDefaultCommand returns a new list that contains parallel elements that have been converted to the most preferred external version
// TODO: move this function into the core factory PrintObjects method
// TODO: print-objects should have preferred output versions
func convertItemsForDisplayFromDefaultCommand(cmd *cobra.Command, objs []runtime.Object) ([]runtime.Object, error) {
	requested := kcmdutil.GetFlagString(cmd, "output-version")
	versions := []schema.GroupVersion{}
	if len(requested) == 0 {
		return convertItemsForDisplay(objs, versions...)
	}

	for _, v := range strings.Split(requested, ",") {
		version, err := schema.ParseGroupVersion(v)
		if err != nil {
			return nil, err
		}
		versions = append(versions, version)
	}

	return convertItemsForDisplay(objs, versions...)
}

// VersionedPrintObject handles printing an object in the appropriate version by looking at 'output-version'
// on the command
func VersionedPrintObject(fn func(*cobra.Command, bool, meta.RESTMapper, runtime.Object, io.Writer) error, c *cobra.Command, mapper meta.RESTMapper, out io.Writer) func(runtime.Object) error {
	return func(obj runtime.Object) error {
		// TODO: fold into the core printer functionality (preferred output version)
		if list, ok := obj.(*kapi.List); ok {
			var err error
			if list.Items, err = convertItemsForDisplayFromDefaultCommand(c, list.Items); err != nil {
				return err
			}
		} else {
			result, err := convertItemsForDisplayFromDefaultCommand(c, []runtime.Object{obj})
			if err != nil {
				return err
			}
			obj = result[0]
		}
		return fn(c, false, mapper, obj, out)
	}
}

func WarnAboutCommaSeparation(errout io.Writer, values []string, flag string) {
	if errout == nil {
		return
	}
	for _, value := range values {
		if commaSepVarsPattern.MatchString(value) {
			fmt.Fprintf(errout, "warning: %s no longer accepts comma-separated lists of values. %q will be treated as a single key-value pair.\n", flag, value)
		}
	}
}
<|endoftext|>