<commit_before>package main

import (
	"github.com/cad-san/ikaring"

	"bufio"
	"context"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/signal"
	"os/user"
	"path/filepath"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/bgentry/speakeasy"
	"github.com/jessevdk/go-flags"
	"github.com/mattn/go-colorable"
)

type option struct {
	Stage  stageCmd  `command:"stage"  description:"display stage schedule"`
	Rank   rankCmd   `command:"rank"   description:"display ranking with friends"`
	Friend friendCmd `command:"friend" description:"display friend list"`
}
type stageCmd struct{}
type rankCmd struct{}
type friendCmd struct{}

const (
	Red   = "\x1b[31;1m"
	Green = "\x1b[32;1m"
	Blue  = "\x1b[34;1m"
	Pink  = "\x1b[35;1m"
	White = "\x1b[37;1m"
	End   = "\x1b[0m"
)

const timeoutTime = time.Second * 5

var (
	stdout = colorable.NewColorableStdout()
)

func getCacheFile() (string, error) {
	me, err := user.Current()
	if err != nil {
		return "", err
	}
	return filepath.Join(me.HomeDir, ".ikaring.session"), nil
}

func readSession(path string) (string, error) {
	buff, err := ioutil.ReadFile(path)
	if err != nil {
		return "", err
	}
	return strings.TrimSpace(string(buff)), nil
}

func writeSession(path string, session string) error {
	return ioutil.WriteFile(path, []byte(session), 600)
}

func getAccount(r io.Reader) (string, string, error) {
	scanner := bufio.NewScanner(r)
	for {
		fmt.Print("User: ")
		if scanner.Scan() {
			break
		}
	}
	username := scanner.Text()
	password, err := speakeasy.Ask("Password: ")
	return username, password, err
}

func login(ctx context.Context, client *ikaring.IkaClient) error {
	path, err := getCacheFile()
	if err != nil {
		return err
	}

	session, err := readSession(path)
	if err == nil && len(session) > 0 {
		client.SetSession(session)
		return nil // already authorized
	}

	username, password, err := getAccount(os.Stdin)
	session, err = client.Login(ctx, username, password)
	if err != nil {
		return err
	}

	if len(session) <= 0 {
		return errors.New("login failure")
	}
	writeSession(path, session)
	return nil
}

func (c *stageCmd) Execute(args []string) error {
	client, err := ikaring.CreateClient()
	if err != nil {
		return err
	}

	ctx, cancel := context.WithTimeout(context.Background(), timeoutTime)
	handle, doneCh := newSignalHandler(cancel)

	wg := &sync.WaitGroup{}
	wg.Add(1)
	go handle(wg)

	if err = login(ctx, client); err != nil {
		return err
	}

	info, err := client.GetStageInfo(ctx)
	if err != nil {
		return err
	}

	if info.FesSchedules != nil {
		for _, s := range *info.FesSchedules {
			fmt.Printf("%v\n", s)
		}
	}

	if info.Schedules != nil {
		for _, s := range *info.Schedules {
			fmt.Printf("%v\n", s)
		}
	}
	doneCh <- struct{}{}
	wg.Wait()
	return nil
}

func (c *rankCmd) Execute(args []string) error {
	client, err := ikaring.CreateClient()
	if err != nil {
		return err
	}

	ctx, cancel := context.WithTimeout(context.Background(), timeoutTime)
	handle, doneCh := newSignalHandler(cancel)

	wg := &sync.WaitGroup{}
	wg.Add(1)
	go handle(wg)

	if err = login(ctx, client); err != nil {
		return err
	}

	info, err := client.GetRanking(ctx)
	if err != nil {
		return err
	}

	if len(info.Regular) > 0 {
		fmt.Println(Green + "レギュラーマッチ" + End)
		for _, p := range info.Regular {
			fmt.Printf("\t[%d] %3d %s (%s)\n", p.Rank, p.Score, p.Name, p.Weapon)
		}
	}

	if len(info.Gachi) > 0 {
		fmt.Println(Pink + "ガチマッチ" + End)
		for _, p := range info.Gachi {
			fmt.Printf("\t[%d] %3d %s (%s)\n", p.Rank, p.Score, p.Name, p.Weapon)
		}
	}

	if len(info.Festival) > 0 {
		fmt.Println(Blue + "フェス" + End)
		for _, p := range info.Festival {
			top100 := ""
			if p.Top100 {
				top100 = Red + "百ケツ!\t" + End
			} else {
				top100 = "\t"
			}
			fmt.Fprintf(stdout, "%s[%d] %3d %s(%s)\n", top100, p.Rank, p.Score, p.Name, p.Weapon)
		}
	}

	doneCh <- struct{}{}
	wg.Wait()
	return nil
}

func (c *friendCmd) Execute(args []string) error {
	client, err := ikaring.CreateClient()
	if err != nil {
		return err
	}

	ctx, cancel := context.WithTimeout(context.Background(), timeoutTime)
	handle, doneCh := newSignalHandler(cancel)

	wg := &sync.WaitGroup{}
	wg.Add(1)
	go handle(wg)

	if err = login(ctx, client); err != nil {
		return err
	}

	list, err := client.GetFriendList(ctx)
	if err != nil {
		return err
	}

	if len(list) == 0 {
		fmt.Println("フレンドはオフラインです")
	}

	for _, f := range list {
		fmt.Printf("%s\n", f.Name)
		fmt.Printf("\t%s\n", f.Mode)
	}
	doneCh <- struct{}{}
	wg.Wait()
	return nil
}

func newSignalHandler(cancel context.CancelFunc) (func(*sync.WaitGroup), chan struct{}) {
	doneCh := make(chan struct{}, 1)
	handler := func(wg *sync.WaitGroup) {
		defer wg.Done()

		// catch Ctrl+C signal
		sigCh := make(chan os.Signal, 1)
		signal.Notify(sigCh,
			syscall.SIGTERM,
			os.Interrupt)
		defer signal.Stop(sigCh)

		for {
			select {
			case <-sigCh:
				cancel()
				fmt.Printf("signal catch\n")
				return
			case <-doneCh:
				return
			}
		}
	}
	return handler, doneCh
}

func main() {
	var opts option
	parser := flags.NewParser(&opts, flags.Default)
	parser.Name = "ikaring"
	parser.SubcommandsOptional = true

	_, err := parser.Parse()

	if len(os.Args) == 1 {
		parser.WriteHelp(os.Stdout)
		return
	}
	if err != nil {
		os.Exit(1)
	}
}
<commit_msg>fix for login timeout<commit_after>package main

import (
	"github.com/cad-san/ikaring"

	"bufio"
	"context"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/signal"
	"os/user"
	"path/filepath"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/bgentry/speakeasy"
	"github.com/jessevdk/go-flags"
	"github.com/mattn/go-colorable"
)

type option struct {
	Stage  stageCmd  `command:"stage"  description:"display stage schedule"`
	Rank   rankCmd   `command:"rank"   description:"display ranking with friends"`
	Friend friendCmd `command:"friend" description:"display friend list"`
}
type stageCmd struct{}
type rankCmd struct{}
type friendCmd struct{}

const (
	Red   = "\x1b[31;1m"
	Green = "\x1b[32;1m"
	Blue  = "\x1b[34;1m"
	Pink  = "\x1b[35;1m"
	White = "\x1b[37;1m"
	End   = "\x1b[0m"
)

const loginTimeout = time.Second * 30
const timeoutTime = time.Second * 5

var (
	stdout = colorable.NewColorableStdout()
)

func getCacheFile() (string, error) {
	me, err := user.Current()
	if err != nil {
		return "", err
	}
	return filepath.Join(me.HomeDir, ".ikaring.session"), nil
}

func readSession(path string) (string, error) {
	buff, err := ioutil.ReadFile(path)
	if err != nil {
		return "", err
	}
	return strings.TrimSpace(string(buff)), nil
}

func writeSession(path string, session string) error {
	return ioutil.WriteFile(path, []byte(session), 600)
}

func getAccount(r io.Reader) (string, string, error) {
	scanner := bufio.NewScanner(r)
	for {
		fmt.Print(Red + "User: " + End)
		if scanner.Scan() {
			break
		}
	}
	username := scanner.Text()
	password, err := speakeasy.Ask(Red + "Password: " + End)
	return username, password, err
}

func login(client *ikaring.IkaClient) error {
	path, err := getCacheFile()
	if err != nil {
		return err
	}

	session, err := readSession(path)
	if err == nil && len(session) > 0 {
		client.SetSession(session)
		return nil // already authorized
	}

	username, password, err := getAccount(os.Stdin)

	ctx, cancel := context.WithTimeout(context.Background(), loginTimeout)
	handle, doneCh := newSignalHandler(cancel)

	wg := &sync.WaitGroup{}
	wg.Add(1)
	go handle(wg)

	session, err = client.Login(ctx, username, password)
	if err != nil {
		return err
	}

	if len(session) <= 0 {
		return errors.New("login failure")
	}

	doneCh <- struct{}{}
	wg.Wait()

	writeSession(path, session)
	return nil
}

func (c *stageCmd) Execute(args []string) error {
	client, err := ikaring.CreateClient()
	if err != nil {
		return err
	}

	if err = login(client); err != nil {
		return err
	}

	ctx, cancel := context.WithTimeout(context.Background(), timeoutTime)
	handle, doneCh := newSignalHandler(cancel)

	wg := &sync.WaitGroup{}
	wg.Add(1)
	go handle(wg)

	info, err := client.GetStageInfo(ctx)
	if err != nil {
		return err
	}

	if info.FesSchedules != nil {
		for _, s := range *info.FesSchedules {
			fmt.Printf("%v\n", s)
		}
	}

	if info.Schedules != nil {
		for _, s := range *info.Schedules {
			fmt.Printf("%v\n", s)
		}
	}
	doneCh <- struct{}{}
	wg.Wait()
	return nil
}

func (c *rankCmd) Execute(args []string) error {
	client, err := ikaring.CreateClient()
	if err != nil {
		return err
	}

	if err = login(client); err != nil {
		return err
	}

	ctx, cancel := context.WithTimeout(context.Background(), timeoutTime)
	handle, doneCh := newSignalHandler(cancel)

	wg := &sync.WaitGroup{}
	wg.Add(1)
	go handle(wg)

	info, err := client.GetRanking(ctx)
	if err != nil {
		return err
	}

	if len(info.Regular) > 0 {
		fmt.Println(Green + "レギュラーマッチ" + End)
		for _, p := range info.Regular {
			fmt.Printf("\t[%d] %3d %s (%s)\n", p.Rank, p.Score, p.Name, p.Weapon)
		}
	}

	if len(info.Gachi) > 0 {
		fmt.Println(Pink + "ガチマッチ" + End)
		for _, p := range info.Gachi {
			fmt.Printf("\t[%d] %3d %s (%s)\n", p.Rank, p.Score, p.Name, p.Weapon)
		}
	}

	if len(info.Festival) > 0 {
		fmt.Println(Blue + "フェス" + End)
		for _, p := range info.Festival {
			top100 := ""
			if p.Top100 {
				top100 = Red + "百ケツ!\t" + End
			} else {
				top100 = "\t"
			}
			fmt.Fprintf(stdout, "%s[%d] %3d %s(%s)\n", top100, p.Rank, p.Score, p.Name, p.Weapon)
		}
	}

	doneCh <- struct{}{}
	wg.Wait()
	return nil
}

func (c *friendCmd) Execute(args []string) error {
	client, err := ikaring.CreateClient()
	if err != nil {
		return err
	}

	if err = login(client); err != nil {
		return err
	}

	ctx, cancel := context.WithTimeout(context.Background(), timeoutTime)
	handle, doneCh := newSignalHandler(cancel)

	wg := &sync.WaitGroup{}
	wg.Add(1)
	go handle(wg)

	list, err := client.GetFriendList(ctx)
	if err != nil {
		return err
	}

	if len(list) == 0 {
		fmt.Println("フレンドはオフラインです")
	}

	for _, f := range list {
		fmt.Printf("%s\n", f.Name)
		fmt.Printf("\t%s\n", f.Mode)
	}
	doneCh <- struct{}{}
	wg.Wait()
	return nil
}

func newSignalHandler(cancel context.CancelFunc) (func(*sync.WaitGroup), chan struct{}) {
	doneCh := make(chan struct{}, 1)
	handler := func(wg *sync.WaitGroup) {
		defer wg.Done()

		// catch Ctrl+C signal
		sigCh := make(chan os.Signal, 1)
		signal.Notify(sigCh,
			syscall.SIGTERM,
			os.Interrupt)
		defer signal.Stop(sigCh)

		for {
			select {
			case <-sigCh:
				cancel()
				fmt.Printf("signal catch\n")
				return
			case <-doneCh:
				return
			}
		}
	}
	return handler, doneCh
}

func main() {
	var opts option
	parser := flags.NewParser(&opts, flags.Default)
	parser.Name = "ikaring"
	parser.SubcommandsOptional = true

	_, err := parser.Parse()

	if len(os.Args) == 1 {
		parser.WriteHelp(os.Stdout)
		return
	}
	if err != nil {
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 Google 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.

// imageproxy starts an HTTP server that proxies requests for remote images.
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strings"

	"github.com/gregjones/httpcache"
	"github.com/gregjones/httpcache/diskcache"
	"github.com/peterbourgon/diskv"
	"willnorris.com/go/imageproxy"
)

// goxc values
var (
	// VERSION is the version string for imageproxy.
	VERSION = "HEAD"

	// BUILD_DATE is the timestamp of when imageproxy was built.
	BUILD_DATE string
)

var addr = flag.String("addr", "localhost:8080", "TCP address to listen on")
var whitelist = flag.String("whitelist", "", "comma separated list of allowed remote hosts")
var baseURL = flag.String("baseURL", "", "default base URL for relative remote URLs")
var cacheDir = flag.String("cacheDir", "", "directory to use for file cache")
var cacheSize = flag.Uint64("cacheSize", 100, "maximum size of file cache (in MB)")
var signatureKey = flag.String("signatureKey", "", "HMAC key used in calculating request signatures")
var version = flag.Bool("version", false, "print version information")

func main() {
	flag.Parse()

	if *version {
		fmt.Printf("%v\nBuild: %v\n", VERSION, BUILD_DATE)
		return
	}

	var c httpcache.Cache
	if *cacheDir != "" {
		d := diskv.New(diskv.Options{
			BasePath:     *cacheDir,
			CacheSizeMax: *cacheSize * 1024 * 1024,
		})
		c = diskcache.NewWithDiskv(d)
	} else {
		c = httpcache.NewMemoryCache()
	}

	p := imageproxy.NewProxy(nil, c)
	if *whitelist != "" {
		p.Whitelist = strings.Split(*whitelist, ",")
	}
	if *signatureKey != "" {
		key := []byte(*signatureKey)
		if strings.HasPrefix(*signatureKey, "@") {
			file := strings.TrimPrefix(*signatureKey, "@")
			var err error
			key, err = ioutil.ReadFile(file)
			if err != nil {
				log.Fatalf("error reading signature file: %v", err)
			}
		}
		p.SignatureKey = key
	}
	if *baseURL != "" {
		var err error
		p.DefaultBaseURL, err = url.Parse(*baseURL)
		if err != nil {
			log.Fatalf("error parsing baseURL: %v", err)
		}
	}

	server := &http.Server{
		Addr:    *addr,
		Handler: p,
	}

	fmt.Printf("imageproxy (version %v) listening on %s\n", VERSION, server.Addr)
	err := server.ListenAndServe()
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>allowing cache size of 0<commit_after>// Copyright 2013 Google 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.

// imageproxy starts an HTTP server that proxies requests for remote images.
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strings"

	"github.com/gregjones/httpcache"
	"github.com/gregjones/httpcache/diskcache"
	"github.com/peterbourgon/diskv"
	"willnorris.com/go/imageproxy"
)

// goxc values
var (
	// VERSION is the version string for imageproxy.
	VERSION = "HEAD"

	// BUILD_DATE is the timestamp of when imageproxy was built.
	BUILD_DATE string
)

var addr = flag.String("addr", "localhost:8080", "TCP address to listen on")
var whitelist = flag.String("whitelist", "", "comma separated list of allowed remote hosts")
var baseURL = flag.String("baseURL", "", "default base URL for relative remote URLs")
var cacheDir = flag.String("cacheDir", "", "directory to use for file cache")
var cacheSize = flag.Uint64("cacheSize", 100, "maximum size of file cache (in MB)")
var signatureKey = flag.String("signatureKey", "", "HMAC key used in calculating request signatures")
var version = flag.Bool("version", false, "print version information")

func main() {
	flag.Parse()

	if *version {
		fmt.Printf("%v\nBuild: %v\n", VERSION, BUILD_DATE)
		return
	}

	var c httpcache.Cache
	if *cacheDir != "" {
		d := diskv.New(diskv.Options{
			BasePath:     *cacheDir,
			CacheSizeMax: *cacheSize * 1024 * 1024,
		})
		c = diskcache.NewWithDiskv(d)
	} else if *cacheSize != 0 {
		c = httpcache.NewMemoryCache()
	}

	p := imageproxy.NewProxy(nil, c)
	if *whitelist != "" {
		p.Whitelist = strings.Split(*whitelist, ",")
	}
	if *signatureKey != "" {
		key := []byte(*signatureKey)
		if strings.HasPrefix(*signatureKey, "@") {
			file := strings.TrimPrefix(*signatureKey, "@")
			var err error
			key, err = ioutil.ReadFile(file)
			if err != nil {
				log.Fatalf("error reading signature file: %v", err)
			}
		}
		p.SignatureKey = key
	}
	if *baseURL != "" {
		var err error
		p.DefaultBaseURL, err = url.Parse(*baseURL)
		if err != nil {
			log.Fatalf("error parsing baseURL: %v", err)
		}
	}

	server := &http.Server{
		Addr:    *addr,
		Handler: p,
	}

	fmt.Printf("imageproxy (version %v) listening on %s\n", VERSION, server.Addr)
	err := server.ListenAndServe()
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>package internal

import (
	"encoding/json"
	"os"

	"github.com/ready-steady/adhier"
	"github.com/ready-steady/simulation/temperature/numeric"
)

// Config is a configuration of the problem.
type Config struct {
	Inherit string

	System        SystemConfig        // Platform and application
	Probability   ProbabilityConfig   // Probability model
	Target        TargetConfig        // Quantity of interest
	Interpolation InterpolationConfig // Interpolation
	Assessment    AssessmentConfig    // Assessment

	// A flag indicating that diagnostic information should be displayed.
	Verbose bool
}

// SystemConfig is a configuration of the system.
type SystemConfig struct {
	// A TGFF file describing the platform and application to analyze.
	Specification string

	numeric.Config
}

// ProbabilityConfig is a configuration of the probability model.
type ProbabilityConfig struct {
	// The indices of the tasks whose execution times should be considered as
	// uncertain; if empty, the parameter is set to all tasks.
	TaskIndex []uint
	// The multiplier used to calculate the maximal delay of a task.
	MaxDelay float64 // ∈ [0, 1)
	// The marginal distributions of tasks’ delays.
	Marginal string
	// The strength of correlations between tasks.
	CorrLength float64 // > 0
	// The portion of the variance to be preserved when reducing the number of
	// stochastic dimensions.
	VarThreshold float64 // ∈ (0, 1]
}

// TargetConfig is a configuration of the quantity of interest.
type TargetConfig struct {
	// The name of the quantity. The options are “end-to-end-delay,”
	// “total-energy,” and “temperature-profile.”
	Name string

	// The error tolerance.
	Tolerance float64
	// The patter that is replicated onto a surplus in order to identify the
	// elements that should be used for the error estimation.
	Stencil []bool

	// The indices of the cores that should be considered; if empty, the
	// parameter is set to all cores.
	CoreIndex []uint
	// The time step of temperature profiles.
	TimeStep float64
	// The fraction of the application’s span that should be considered; if
	// empty, the parameter is set to the entire span [0, 1].
	TimeFraction []float64

	// A flag indicating that diagnostic information should be displayed.
	Verbose bool
}

// InterpolationConfig is a configuration of the interpolation algorithm.
type InterpolationConfig struct {
	// The quadrature rule to use, which is either “closed” or “open.”
	Rule string

	adhier.Config
}

// AssessmentConfig is a configuration of the assessment procedure.
type AssessmentConfig struct {
	// The seed for random number generation.
	Seed int
	// The number of samples to take.
	Samples uint
}

func NewConfig(path string) (*Config, error) {
	paths := []string{path}
	for {
		config := Config{}
		if err := populate(&config, path); err != nil {
			return nil, err
		}

		if len(config.Inherit) > 0 {
			path = config.Inherit
			paths = append([]string{path}, paths...)
			continue
		}

		break
	}

	config := DefaultConfig()
	for _, path := range paths {
		if err := populate(config, path); err != nil {
			return nil, err
		}
	}

	return config, nil
}

func DefaultConfig() *Config {
	config := &Config{}

	func(c *SystemConfig) {
		c.Ambience = 45 + 273.15
	}(&config.System)

	func(c *TargetConfig) {
		c.Stencil = []bool{true, false}
	}(&config.Target)

	func(c *InterpolationConfig) {
		c.Rule = "open"
		c.MinLevel = 1
		c.MaxLevel = 10
	}(&config.Interpolation)

	func(c *AssessmentConfig) {
		c.Seed = 1
		c.Samples = 10000
	}(&config.Assessment)

	return config
}

func populate(config *Config, path string) error {
	file, err := os.Open(path)
	if err != nil {
		return err
	}
	defer file.Close()

	decoder := json.NewDecoder(file)

	return decoder.Decode(config)
}
<commit_msg>Change the units of temperature to Celsius<commit_after>package internal

import (
	"encoding/json"
	"os"

	"github.com/ready-steady/adhier"
	"github.com/ready-steady/simulation/temperature/numeric"
)

// Config is a configuration of the problem.
type Config struct {
	Inherit string

	System        SystemConfig        // Platform and application
	Probability   ProbabilityConfig   // Probability model
	Target        TargetConfig        // Quantity of interest
	Interpolation InterpolationConfig // Interpolation
	Assessment    AssessmentConfig    // Assessment

	// A flag indicating that diagnostic information should be displayed.
	Verbose bool
}

// SystemConfig is a configuration of the system.
type SystemConfig struct {
	// A TGFF file describing the platform and application to analyze.
	Specification string

	numeric.Config
}

// ProbabilityConfig is a configuration of the probability model.
type ProbabilityConfig struct {
	// The indices of the tasks whose execution times should be considered as
	// uncertain; if empty, the parameter is set to all tasks.
	TaskIndex []uint
	// The multiplier used to calculate the maximal delay of a task.
	MaxDelay float64 // ∈ [0, 1)
	// The marginal distributions of tasks’ delays.
	Marginal string
	// The strength of correlations between tasks.
	CorrLength float64 // > 0
	// The portion of the variance to be preserved when reducing the number of
	// stochastic dimensions.
	VarThreshold float64 // ∈ (0, 1]
}

// TargetConfig is a configuration of the quantity of interest.
type TargetConfig struct {
	// The name of the quantity. The options are “end-to-end-delay,”
	// “total-energy,” and “temperature-profile.”
	Name string

	// The error tolerance.
	Tolerance float64
	// The patter that is replicated onto a surplus in order to identify the
	// elements that should be used for the error estimation.
	Stencil []bool

	// The indices of the cores that should be considered; if empty, the
	// parameter is set to all cores.
	CoreIndex []uint
	// The time step of temperature profiles.
	TimeStep float64
	// The fraction of the application’s span that should be considered; if
	// empty, the parameter is set to the entire span [0, 1].
	TimeFraction []float64

	// A flag indicating that diagnostic information should be displayed.
	Verbose bool
}

// InterpolationConfig is a configuration of the interpolation algorithm.
type InterpolationConfig struct {
	// The quadrature rule to use, which is either “closed” or “open.”
	Rule string

	adhier.Config
}

// AssessmentConfig is a configuration of the assessment procedure.
type AssessmentConfig struct {
	// The seed for random number generation.
	Seed int
	// The number of samples to take.
	Samples uint
}

func NewConfig(path string) (*Config, error) {
	paths := []string{path}
	for {
		config := Config{}
		if err := populate(&config, path); err != nil {
			return nil, err
		}

		if len(config.Inherit) > 0 {
			path = config.Inherit
			paths = append([]string{path}, paths...)
			continue
		}

		break
	}

	config := DefaultConfig()
	for _, path := range paths {
		if err := populate(config, path); err != nil {
			return nil, err
		}
	}

	return config, nil
}

func DefaultConfig() *Config {
	config := &Config{}

	func(c *SystemConfig) {
		c.Ambience = 45
	}(&config.System)

	func(c *TargetConfig) {
		c.Stencil = []bool{true, false}
	}(&config.Target)

	func(c *InterpolationConfig) {
		c.Rule = "open"
		c.MinLevel = 1
		c.MaxLevel = 10
	}(&config.Interpolation)

	func(c *AssessmentConfig) {
		c.Seed = 1
		c.Samples = 10000
	}(&config.Assessment)

	return config
}

func populate(config *Config, path string) error {
	file, err := os.Open(path)
	if err != nil {
		return err
	}
	defer file.Close()

	decoder := json.NewDecoder(file)

	return decoder.Decode(config)
}
<|endoftext|>


<commit_before>// jsonfmt formats JSON files in place.
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/tidwall/pretty"
)

func formatJSON(filename string, bePretty bool) error {
	in, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}
	var out []byte
	if bePretty {
		out = pretty.Pretty(in)
	} else {
		var jsn interface{}
		if err := json.Unmarshal(in, &jsn); err != nil {
			return err
		}
		out, err = json.MarshalIndent(jsn, "", "  ")
		if err != nil {
			return err
		}
	}
	fp, err := ioutil.TempFile("", "jsonfmt")
	if err != nil {
		return err
	}
	if _, err := fmt.Fprintln(fp, string(out)); err != nil {
		fp.Close()
		return err
	}
	if err := fp.Close(); err != nil {
		return err
	}
	return os.Rename(fp.Name(), filename)
}

func fatal(err error) {
	fmt.Fprintf(os.Stderr, "%s: error: %s\n", os.Args[0], err)
	os.Exit(1)
}

func usage() {
	fmt.Fprintf(os.Stderr, "usage: %s JSON_file\n", os.Args[0])
	os.Exit(2)
}

func main() {
	bePretty := flag.Bool("p", false, "Use pretty printer")
	flag.Parse()
	if flag.NArg() > 1 {
		usage()
	}
	if err := formatJSON(flag.Arg(0), *bePretty); err != nil {
		fatal(err)
	}
}
<commit_msg>jsonfmt: rename accross file systems<commit_after>// jsonfmt formats JSON files in place.
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"

	"github.com/tidwall/pretty"
)

func renameAccrossFilesystem(src, dst string) error {
	// open source file
	s, err := os.Open(src)
	if err != nil {
		return err
	}
	defer s.Close()
	// get mode of source file
	fi, err := s.Stat()
	if err != nil {
		return err
	}
	// make sure source file is a regular file
	if !fi.Mode().IsRegular() {
		return fmt.Errorf("source file '%s' is not a regular file", src)
	}
	mode := fi.Mode() & os.ModePerm // only keep standard UNIX permission bits
	// create destination file
	d, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, mode)
	if err != nil {
		return err
	}
	defer d.Close()
	// copy content
	if _, err := io.Copy(d, s); err != nil {
		return err
	}
	// remove src file
	defer os.Remove(src)
	return nil
}

func formatJSON(filename string, bePretty bool) error {
	in, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}
	var out []byte
	if bePretty {
		out = pretty.Pretty(in)
	} else {
		var jsn interface{}
		if err := json.Unmarshal(in, &jsn); err != nil {
			return err
		}
		out, err = json.MarshalIndent(jsn, "", "  ")
		if err != nil {
			return err
		}
	}
	fp, err := ioutil.TempFile("", "jsonfmt")
	if err != nil {
		return err
	}
	if _, err := fmt.Fprintln(fp, string(out)); err != nil {
		fp.Close()
		return err
	}
	if err := fp.Close(); err != nil {
		return err
	}
	err = os.Rename(fp.Name(), filename)
	if err != nil {
		err = renameAccrossFilesystem(fp.Name(), filename)
	}
	return err
}

func fatal(err error) {
	fmt.Fprintf(os.Stderr, "%s: error: %s\n", os.Args[0], err)
	os.Exit(1)
}

func usage() {
	fmt.Fprintf(os.Stderr, "usage: %s JSON_file\n", os.Args[0])
	os.Exit(2)
}

func main() {
	bePretty := flag.Bool("p", false, "Use pretty printer")
	flag.Parse()
	if flag.NArg() > 1 {
		usage()
	}
	if err := formatJSON(flag.Arg(0), *bePretty); err != nil {
		fatal(err)
	}
}
<|endoftext|>


<commit_before>package jira

import (
	"github.com/coryb/oreo"
	logging "gopkg.in/op/go-logging.v1"
)

var log = logging.MustGetLogger("jira")

const VERSION = "1.0.2"

type Jira struct {
	Endpoint string     `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
	UA       HttpClient `json:"-" yaml:"-"`
}

func NewJira(endpoint string) *Jira {
	return &Jira{
		Endpoint: endpoint,
		UA:       oreo.New(),
	}
}
<commit_msg>version bump<commit_after>package jira

import (
	"github.com/coryb/oreo"
	logging "gopkg.in/op/go-logging.v1"
)

var log = logging.MustGetLogger("jira")

const VERSION = "1.0.3"

type Jira struct {
	Endpoint string     `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
	UA       HttpClient `json:"-" yaml:"-"`
}

func NewJira(endpoint string) *Jira {
	return &Jira{
		Endpoint: endpoint,
		UA:       oreo.New(),
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"net/http"
	"os"
	"sync"
	"syscall"
	"time"

	_ "expvar"
	_ "net/http/pprof"

	"github.com/funkygao/gafka/cmd/kateway/meta"
	"github.com/funkygao/gafka/cmd/kateway/meta/zkmeta"
	"github.com/funkygao/gafka/cmd/kateway/store"
	"github.com/funkygao/gafka/cmd/kateway/store/dumb"
	"github.com/funkygao/gafka/cmd/kateway/store/kafka"
	"github.com/funkygao/gafka/ctx"
	"github.com/funkygao/gafka/registry"
	"github.com/funkygao/gafka/registry/zk"
	"github.com/funkygao/golib/ratelimiter"
	"github.com/funkygao/golib/signal"
	"github.com/funkygao/golib/timewheel"
	log "github.com/funkygao/log4go"
)

// Gateway is a distributed kafka Pub/Sub HTTP endpoint.
type Gateway struct {
	id        string
	startedAt time.Time
	zone      string

	certFile string
	keyFile  string

	pubPeersLock sync.RWMutex
	pubPeers     []string // cluster of kateway pub

	pubServer *pubServer
	subServer *subServer
	manServer *manServer

	guard *guard
	timer *timewheel.TimeWheel

	shutdownOnce sync.Once
	shutdownCh   chan struct{}
	wg           sync.WaitGroup

	leakyBuckets *ratelimiter.LeakyBuckets // TODO

	pubMetrics *pubMetrics
	subMetrics *subMetrics
	svrMetrics *serverMetrics
}

func NewGateway(id string, metaRefreshInterval time.Duration) *Gateway {
	this := &Gateway{
		id:           id,
		zone:         options.zone,
		shutdownCh:   make(chan struct{}),
		leakyBuckets: ratelimiter.NewLeakyBuckets(1000*60, time.Minute),
		certFile:     options.certFile,
		keyFile:      options.keyFile,
		pubPeers:     make([]string, 0, 20),
	}

	registry.Default = zk.New(options.zone, id, this.InstanceInfo())

	metaConf := zkmeta.DefaultConfig(options.zone)
	metaConf.Refresh = metaRefreshInterval
	meta.Default = zkmeta.New(metaConf)
	this.guard = newGuard(this)
	this.timer = timewheel.NewTimeWheel(time.Second, 120)

	this.manServer = newManServer(options.manHttpAddr, options.manHttpsAddr,
		options.maxClients, this)
	this.svrMetrics = NewServerMetrics(options.reporterInterval)

	if options.pubHttpAddr != "" || options.pubHttpsAddr != "" {
		this.pubServer = newPubServer(options.pubHttpAddr, options.pubHttpsAddr,
			options.maxClients, this)
		this.pubMetrics = NewPubMetrics()

		switch options.store {
		case "kafka":
			store.DefaultPubStore = kafka.NewPubStore(
				options.pubPoolCapcity, options.maxPubRetries, options.pubPoolIdleTimeout,
				&this.wg, options.debug, options.dryRun)

		case "dumb":
			store.DefaultPubStore = dumb.NewPubStore(&this.wg, options.debug)
		}
	}

	if options.subHttpAddr != "" || options.subHttpsAddr != "" {
		this.subServer = newSubServer(options.subHttpAddr, options.subHttpsAddr,
			options.maxClients, this)
		this.subMetrics = NewSubMetrics()

		switch options.store {
		case "kafka":
			store.DefaultSubStore = kafka.NewSubStore(&this.wg,
				this.subServer.closedConnCh, options.debug)

		case "dumb":
			store.DefaultSubStore = dumb.NewSubStore(&this.wg,
				this.subServer.closedConnCh, options.debug)

		}
	}

	return this
}

func (this *Gateway) InstanceInfo() []byte {
	var s map[string]string = make(map[string]string)
	s["host"] = ctx.Hostname()
	s["id"] = this.id
	s["zone"] = options.zone
	s["man"] = options.manHttpAddr
	s["sman"] = options.manHttpsAddr
	s["pub"] = options.pubHttpAddr
	s["spub"] = options.pubHttpsAddr
	s["sub"] = options.subHttpAddr
	s["ssub"] = options.subHttpsAddr
	s["debug"] = options.debugHttpAddr
	d, _ := json.Marshal(s)
	return d
}

func (this *Gateway) Start() (err error) {
	signal.RegisterSignalsHandler(func(sig os.Signal) {
		this.Stop()
	}, syscall.SIGINT, syscall.SIGUSR2)

	this.startedAt = time.Now()

	startRuntimeMetrics(options.reporterInterval)

	meta.Default.Start()
	log.Trace("meta store started")

	this.guard.Start()
	log.Trace("guard started")

	this.buildRouting()
	this.manServer.Start()

	if options.debugHttpAddr != "" {
		log.Info("debug http server ready on %s", options.debugHttpAddr)

		go http.ListenAndServe(options.debugHttpAddr, nil)
	}

	if this.pubServer != nil {
		if err := store.DefaultPubStore.Start(); err != nil {
			panic(err)
		}
		log.Trace("pub store[%s] started", store.DefaultPubStore.Name())

		this.pubServer.Start()
	}
	if this.subServer != nil {
		if err := store.DefaultSubStore.Start(); err != nil {
			panic(err)
		}
		log.Trace("sub store[%s] started", store.DefaultSubStore.Name())

		this.subServer.Start()
	}

	// the last thing is to register: notify others
	if registry.Default != nil {
		if err := registry.Default.Register(); err != nil {
			panic(err)
		}
	}

	log.Info("gateway[%s:%s] ready", ctx.Hostname(), this.id)

	return nil
}

func (this *Gateway) Stop() {
	this.shutdownOnce.Do(func() {
		log.Info("stopping kateway...")

		close(this.shutdownCh)
	})

}

func (this *Gateway) ServeForever() {
	select {
	case <-this.shutdownCh:
		// the 1st thing is to deregister
		if registry.Default != nil {
			if err := registry.Default.Deregister(); err != nil {
				log.Error("Deregister: %v", err)
			}
		}

		log.Info("Deregister done, waiting for components shutdown...")
		this.wg.Wait()

		if store.DefaultPubStore != nil {
			store.DefaultPubStore.Stop()
		}
		if store.DefaultSubStore != nil {
			store.DefaultSubStore.Stop()
		}

		log.Info("all components shutdown complete")

		meta.Default.Stop()
		this.timer.Stop()
	}

}
<commit_msg>each kateway will register with ver and buildId<commit_after>package main

import (
	"encoding/json"
	"net/http"
	"os"
	"sync"
	"syscall"
	"time"

	_ "expvar"
	_ "net/http/pprof"

	"github.com/funkygao/gafka"
	"github.com/funkygao/gafka/cmd/kateway/meta"
	"github.com/funkygao/gafka/cmd/kateway/meta/zkmeta"
	"github.com/funkygao/gafka/cmd/kateway/store"
	"github.com/funkygao/gafka/cmd/kateway/store/dumb"
	"github.com/funkygao/gafka/cmd/kateway/store/kafka"
	"github.com/funkygao/gafka/ctx"
	"github.com/funkygao/gafka/registry"
	"github.com/funkygao/gafka/registry/zk"
	"github.com/funkygao/golib/ratelimiter"
	"github.com/funkygao/golib/signal"
	"github.com/funkygao/golib/timewheel"
	log "github.com/funkygao/log4go"
)

// Gateway is a distributed kafka Pub/Sub HTTP endpoint.
type Gateway struct {
	id        string
	startedAt time.Time
	zone      string

	certFile string
	keyFile  string

	pubPeersLock sync.RWMutex
	pubPeers     []string // cluster of kateway pub

	pubServer *pubServer
	subServer *subServer
	manServer *manServer

	guard *guard
	timer *timewheel.TimeWheel

	shutdownOnce sync.Once
	shutdownCh   chan struct{}
	wg           sync.WaitGroup

	leakyBuckets *ratelimiter.LeakyBuckets // TODO

	pubMetrics *pubMetrics
	subMetrics *subMetrics
	svrMetrics *serverMetrics
}

func NewGateway(id string, metaRefreshInterval time.Duration) *Gateway {
	this := &Gateway{
		id:           id,
		zone:         options.zone,
		shutdownCh:   make(chan struct{}),
		leakyBuckets: ratelimiter.NewLeakyBuckets(1000*60, time.Minute),
		certFile:     options.certFile,
		keyFile:      options.keyFile,
		pubPeers:     make([]string, 0, 20),
	}

	registry.Default = zk.New(options.zone, id, this.InstanceInfo())

	metaConf := zkmeta.DefaultConfig(options.zone)
	metaConf.Refresh = metaRefreshInterval
	meta.Default = zkmeta.New(metaConf)
	this.guard = newGuard(this)
	this.timer = timewheel.NewTimeWheel(time.Second, 120)

	this.manServer = newManServer(options.manHttpAddr, options.manHttpsAddr,
		options.maxClients, this)
	this.svrMetrics = NewServerMetrics(options.reporterInterval)

	if options.pubHttpAddr != "" || options.pubHttpsAddr != "" {
		this.pubServer = newPubServer(options.pubHttpAddr, options.pubHttpsAddr,
			options.maxClients, this)
		this.pubMetrics = NewPubMetrics()

		switch options.store {
		case "kafka":
			store.DefaultPubStore = kafka.NewPubStore(
				options.pubPoolCapcity, options.maxPubRetries, options.pubPoolIdleTimeout,
				&this.wg, options.debug, options.dryRun)

		case "dumb":
			store.DefaultPubStore = dumb.NewPubStore(&this.wg, options.debug)
		}
	}

	if options.subHttpAddr != "" || options.subHttpsAddr != "" {
		this.subServer = newSubServer(options.subHttpAddr, options.subHttpsAddr,
			options.maxClients, this)
		this.subMetrics = NewSubMetrics()

		switch options.store {
		case "kafka":
			store.DefaultSubStore = kafka.NewSubStore(&this.wg,
				this.subServer.closedConnCh, options.debug)

		case "dumb":
			store.DefaultSubStore = dumb.NewSubStore(&this.wg,
				this.subServer.closedConnCh, options.debug)

		}
	}

	return this
}

func (this *Gateway) InstanceInfo() []byte {
	var s map[string]string = make(map[string]string)
	s["host"] = ctx.Hostname()
	s["id"] = this.id
	s["ver"] = gafka.Version
	s["build"] = gafka.BuildId
	s["zone"] = options.zone
	s["man"] = options.manHttpAddr
	s["sman"] = options.manHttpsAddr
	s["pub"] = options.pubHttpAddr
	s["spub"] = options.pubHttpsAddr
	s["sub"] = options.subHttpAddr
	s["ssub"] = options.subHttpsAddr
	s["debug"] = options.debugHttpAddr
	d, _ := json.Marshal(s)
	return d
}

func (this *Gateway) Start() (err error) {
	signal.RegisterSignalsHandler(func(sig os.Signal) {
		this.Stop()
	}, syscall.SIGINT, syscall.SIGUSR2)

	this.startedAt = time.Now()

	startRuntimeMetrics(options.reporterInterval)

	meta.Default.Start()
	log.Trace("meta store started")

	this.guard.Start()
	log.Trace("guard started")

	this.buildRouting()
	this.manServer.Start()

	if options.debugHttpAddr != "" {
		log.Info("debug http server ready on %s", options.debugHttpAddr)

		go http.ListenAndServe(options.debugHttpAddr, nil)
	}

	if this.pubServer != nil {
		if err := store.DefaultPubStore.Start(); err != nil {
			panic(err)
		}
		log.Trace("pub store[%s] started", store.DefaultPubStore.Name())

		this.pubServer.Start()
	}
	if this.subServer != nil {
		if err := store.DefaultSubStore.Start(); err != nil {
			panic(err)
		}
		log.Trace("sub store[%s] started", store.DefaultSubStore.Name())

		this.subServer.Start()
	}

	// the last thing is to register: notify others
	if registry.Default != nil {
		if err := registry.Default.Register(); err != nil {
			panic(err)
		}
	}

	log.Info("gateway[%s:%s] ready", ctx.Hostname(), this.id)

	return nil
}

func (this *Gateway) Stop() {
	this.shutdownOnce.Do(func() {
		log.Info("stopping kateway...")

		close(this.shutdownCh)
	})

}

func (this *Gateway) ServeForever() {
	select {
	case <-this.shutdownCh:
		// the 1st thing is to deregister
		if registry.Default != nil {
			if err := registry.Default.Deregister(); err != nil {
				log.Error("Deregister: %v", err)
			}
		}

		log.Info("Deregister done, waiting for components shutdown...")
		this.wg.Wait()

		if store.DefaultPubStore != nil {
			store.DefaultPubStore.Stop()
		}
		if store.DefaultSubStore != nil {
			store.DefaultSubStore.Stop()
		}

		log.Info("all components shutdown complete")

		meta.Default.Stop()
		this.timer.Stop()
	}

}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"runtime"
	"strings"

	"github.com/sourcegraph/makex"
)

var file = flag.String("f", "Makefile", "path to Makefile")
var cwd = flag.String("C", "", "change to this directory before doing anything")
var dryRun = flag.Bool("n", false, "dry run (don't actually run any commands)")
var jobs = flag.Int("j", runtime.GOMAXPROCS(0), "number of jobs to run in parallel")
var expand = flag.Bool("x", true, "expand globs in makefile prereqs")

func main() {
	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, `makex is an experimental, incomplete implementation of make in Go.

Usage:

        makex [options] [target] ...

If no targets are specified, the first target that appears in the makefile is
used.

The options are:
`)
		flag.PrintDefaults()
		os.Exit(1)
	}

	flag.Parse()
	conf := makex.Default
	conf.ParallelJobs = *jobs

	data, err := ioutil.ReadFile(*file)
	if err != nil {
		conf.Log.Fatal(err)
	}

	if *cwd != "" {
		err := os.Chdir(*cwd)
		if err != nil {
			conf.Log.Fatal(err)
		}
	}

	mf, err := makex.Parse(data)
	if err != nil {
		conf.Log.Fatal(err)
	}

	goals := flag.Args()
	if len(goals) == 0 {
		// Find the first rule that doesn't begin with a ".".
		for _, rule := range mf.Rules {
			target := rule.Target()
			if !strings.HasPrefix(target, ".") {
				goals = []string{target}
				break
			}
		}
	}

	if *expand {
		mf, err = conf.Expand(mf)
		if err != nil {
			log.Fatal(err)
		}
	}

	mk := conf.NewMaker(mf, goals...)

	targetSets, err := mk.TargetSetsNeedingBuild()
	if err != nil {
		conf.Log.Fatal(err)
	}

	if len(targetSets) == 0 {
		fmt.Println("Nothing to do.")
	}

	if *dryRun {
		for i, targetSet := range targetSets {
			if i != 0 {
				fmt.Println()
			}
			fmt.Printf("========= TARGET SET %d (%d targets)\n", i, len(targetSet))
			for _, target := range targetSet {
				fmt.Println(" - ", target)
			}
		}
		return
	}

	err = mk.Run()
	if err != nil {
		conf.Log.Fatal(err)
	}
}
<commit_msg>Clarify default target<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"runtime"
	"strings"

	"github.com/sourcegraph/makex"
)

var file = flag.String("f", "Makefile", "path to Makefile")
var cwd = flag.String("C", "", "change to this directory before doing anything")
var dryRun = flag.Bool("n", false, "dry run (don't actually run any commands)")
var jobs = flag.Int("j", runtime.GOMAXPROCS(0), "number of jobs to run in parallel")
var expand = flag.Bool("x", true, "expand globs in makefile prereqs")

func main() {
	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, `makex is an experimental, incomplete implementation of make in Go.

Usage:

        makex [options] [target] ...

If no targets are specified, the first target that appears in the makefile (not
beginning with ".") is used.

The options are:
`)
		flag.PrintDefaults()
		os.Exit(1)
	}

	flag.Parse()
	conf := makex.Default
	conf.ParallelJobs = *jobs

	data, err := ioutil.ReadFile(*file)
	if err != nil {
		conf.Log.Fatal(err)
	}

	if *cwd != "" {
		err := os.Chdir(*cwd)
		if err != nil {
			conf.Log.Fatal(err)
		}
	}

	mf, err := makex.Parse(data)
	if err != nil {
		conf.Log.Fatal(err)
	}

	goals := flag.Args()
	if len(goals) == 0 {
		// Find the first rule that doesn't begin with a ".".
		for _, rule := range mf.Rules {
			target := rule.Target()
			if !strings.HasPrefix(target, ".") {
				goals = []string{target}
				break
			}
		}
	}

	if *expand {
		mf, err = conf.Expand(mf)
		if err != nil {
			log.Fatal(err)
		}
	}

	mk := conf.NewMaker(mf, goals...)

	targetSets, err := mk.TargetSetsNeedingBuild()
	if err != nil {
		conf.Log.Fatal(err)
	}

	if len(targetSets) == 0 {
		fmt.Println("Nothing to do.")
	}

	if *dryRun {
		for i, targetSet := range targetSets {
			if i != 0 {
				fmt.Println()
			}
			fmt.Printf("========= TARGET SET %d (%d targets)\n", i, len(targetSet))
			for _, target := range targetSet {
				fmt.Println(" - ", target)
			}
		}
		return
	}

	err = mk.Run()
	if err != nil {
		conf.Log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>//
// Copyright 2017, Arkbriar
//
// 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 gitlab

import (
	"bytes"
	"fmt"
	"io"
	"time"
)

// JobsService handles communication with the ci builds related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/jobs.html
type JobsService struct {
	client *Client
}

// Job represents a ci build.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/jobs.html
type Job struct {
	Commit        *Commit    `json:"commit"`
	CreatedAt     *time.Time `json:"created_at"`
	Coverage      float64    `json:"coverage"`
	ArtifactsFile struct {
		Filename string `json:"filename"`
		Size     int    `json:"size"`
	} `json:"artifacts_file"`
	FinishedAt *time.Time `json:"finished_at"`
	ID         int        `json:"id"`
	Name       string     `json:"name"`
	Pipeline   struct {
		ID     int    `json:"id"`
		Ref    string `json:"ref"`
		Sha    string `json:"sha"`
		Status string `json:"status"`
	} `json:"pipeline"`
	Ref    string `json:"ref"`
	Runner struct {
		ID          int    `json:"id"`
		Description string `json:"description"`
		Active      bool   `json:"active"`
		IsShared    bool   `json:"is_shared"`
		Name        string `json:"name"`
	} `json:"runner"`
	Stage     string     `json:"stage"`
	StartedAt *time.Time `json:"started_at"`
	Status    string     `json:"status"`
	Tag       bool       `json:"tag"`
	User      *User      `json:"user"`
	WebURL    string     `json:"web_url"`
}

// ListJobsOptions are options for two list apis
type ListJobsOptions struct {
	ListOptions
	Scope []BuildStateValue `url:"scope[],omitempty" json:"scope,omitempty"`
}

// ListProjectJobs gets a list of jobs in a project.
//
// The scope of jobs to show, one or array of: created, pending, running,
// failed, success, canceled, skipped; showing all jobs if none provided
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#list-project-jobs
func (s *JobsService) ListProjectJobs(pid interface{}, opts *ListJobsOptions, options ...OptionFunc) ([]Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs", pathEscape(project))

	req, err := s.client.NewRequest("GET", u, opts, options)
	if err != nil {
		return nil, nil, err
	}

	var jobs []Job
	resp, err := s.client.Do(req, &jobs)
	if err != nil {
		return nil, resp, err
	}

	return jobs, resp, err
}

// ListPipelineJobs gets a list of jobs for specific pipeline in a
// project. If the pipeline ID is not found, it will respond with 404.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#list-pipeline-jobs
func (s *JobsService) ListPipelineJobs(pid interface{}, pipelineID int, opts *ListJobsOptions, options ...OptionFunc) ([]*Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines/%d/jobs", pathEscape(project), pipelineID)

	req, err := s.client.NewRequest("GET", u, opts, options)
	if err != nil {
		return nil, nil, err
	}

	var jobs []*Job
	resp, err := s.client.Do(req, &jobs)
	if err != nil {
		return nil, resp, err
	}

	return jobs, resp, err
}

// GetJob gets a single job of a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#get-a-single-job
func (s *JobsService) GetJob(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d", pathEscape(project), jobID)

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	job := new(Job)
	resp, err := s.client.Do(req, job)
	if err != nil {
		return nil, resp, err
	}

	return job, resp, err
}

// GetJobArtifacts get jobs artifacts of a project
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#get-job-artifacts
func (s *JobsService) GetJobArtifacts(pid interface{}, jobID int, options ...OptionFunc) (io.Reader, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d/artifacts", pathEscape(project), jobID)

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	artifactsBuf := new(bytes.Buffer)
	resp, err := s.client.Do(req, artifactsBuf)
	if err != nil {
		return nil, resp, err
	}

	return artifactsBuf, resp, err
}

// DownloadArtifactsFileOptions represents the available DownloadArtifactsFile()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#download-the-artifacts-file
type DownloadArtifactsFileOptions struct {
	Job *string `url:"job" json:"job"`
}

// DownloadArtifactsFile download the artifacts file from the given
// reference name and job provided the job finished successfully.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#download-the-artifacts-file
func (s *JobsService) DownloadArtifactsFile(pid interface{}, refName string, opt *DownloadArtifactsFileOptions, options ...OptionFunc) (io.Reader, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/artifacts/%s/download", pathEscape(project), refName)

	req, err := s.client.NewRequest("GET", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	artifactsBuf := new(bytes.Buffer)
	resp, err := s.client.Do(req, artifactsBuf)
	if err != nil {
		return nil, resp, err
	}

	return artifactsBuf, resp, err
}

// DownloadSingleArtifactsFile download a file from the artifacts from the
// given reference name and job provided the job finished successfully.
// Only a single file is going to be extracted from the archive and streamed
// to a client.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#download-a-single-artifact-file
func (s *JobsService) DownloadSingleArtifactsFile(pid interface{}, jobID int, artifactPath string, options ...OptionFunc) (io.Reader, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}

	u := fmt.Sprintf(
		"projects/%s/jobs/%d/artifacts/%s",
		pathEscape(project),
		jobID,
		artifactPath,
	)

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	artifactBuf := new(bytes.Buffer)
	resp, err := s.client.Do(req, artifactBuf)
	if err != nil {
		return nil, resp, err
	}

	return artifactBuf, resp, err
}

// GetTraceFile gets a trace of a specific job of a project
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#get-a-trace-file
func (s *JobsService) GetTraceFile(pid interface{}, jobID int, options ...OptionFunc) (io.Reader, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d/trace", pathEscape(project), jobID)

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	traceBuf := new(bytes.Buffer)
	resp, err := s.client.Do(req, traceBuf)
	if err != nil {
		return nil, resp, err
	}

	return traceBuf, resp, err
}

// CancelJob cancels a single job of a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#cancel-a-job
func (s *JobsService) CancelJob(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d/cancel", pathEscape(project), jobID)

	req, err := s.client.NewRequest("POST", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	job := new(Job)
	resp, err := s.client.Do(req, job)
	if err != nil {
		return nil, resp, err
	}

	return job, resp, err
}

// RetryJob retries a single job of a project
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#retry-a-job
func (s *JobsService) RetryJob(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d/retry", pathEscape(project), jobID)

	req, err := s.client.NewRequest("POST", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	job := new(Job)
	resp, err := s.client.Do(req, job)
	if err != nil {
		return nil, resp, err
	}

	return job, resp, err
}

// EraseJob erases a single job of a project, removes a job
// artifacts and a job trace.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#erase-a-job
func (s *JobsService) EraseJob(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d/erase", pathEscape(project), jobID)

	req, err := s.client.NewRequest("POST", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	job := new(Job)
	resp, err := s.client.Do(req, job)
	if err != nil {
		return nil, resp, err
	}

	return job, resp, err
}

// KeepArtifacts prevents artifacts from being deleted when
// expiration is set.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#keep-artifacts
func (s *JobsService) KeepArtifacts(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d/artifacts/keep", pathEscape(project), jobID)

	req, err := s.client.NewRequest("POST", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	job := new(Job)
	resp, err := s.client.Do(req, job)
	if err != nil {
		return nil, resp, err
	}

	return job, resp, err
}

// PlayJob triggers a manual action to start a job.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#play-a-job
func (s *JobsService) PlayJob(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d/play", pathEscape(project), jobID)

	req, err := s.client.NewRequest("POST", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	job := new(Job)
	resp, err := s.client.Do(req, job)
	if err != nil {
		return nil, resp, err
	}

	return job, resp, err
}
<commit_msg>Add Duration to Job resource<commit_after>//
// Copyright 2017, Arkbriar
//
// 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 gitlab

import (
	"bytes"
	"fmt"
	"io"
	"time"
)

// JobsService handles communication with the ci builds related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/jobs.html
type JobsService struct {
	client *Client
}

// Job represents a ci build.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/jobs.html
type Job struct {
	Commit        *Commit    `json:"commit"`
	CreatedAt     *time.Time `json:"created_at"`
	Coverage      float64    `json:"coverage"`
	ArtifactsFile struct {
		Filename string `json:"filename"`
		Size     int    `json:"size"`
	} `json:"artifacts_file"`
	FinishedAt *time.Time `json:"finished_at"`
	ID         int        `json:"id"`
	Name       string     `json:"name"`
	Pipeline   struct {
		ID     int    `json:"id"`
		Ref    string `json:"ref"`
		Sha    string `json:"sha"`
		Status string `json:"status"`
	} `json:"pipeline"`
	Ref    string `json:"ref"`
	Runner struct {
		ID          int    `json:"id"`
		Description string `json:"description"`
		Active      bool   `json:"active"`
		IsShared    bool   `json:"is_shared"`
		Name        string `json:"name"`
	} `json:"runner"`
	Stage     string     `json:"stage"`
	StartedAt *time.Time `json:"started_at"`
	Status    string     `json:"status"`
	Tag       bool       `json:"tag"`
	User      *User      `json:"user"`
	WebURL    string     `json:"web_url"`
	Duration  float64    `json:"duration"`
}

// ListJobsOptions are options for two list apis
type ListJobsOptions struct {
	ListOptions
	Scope []BuildStateValue `url:"scope[],omitempty" json:"scope,omitempty"`
}

// ListProjectJobs gets a list of jobs in a project.
//
// The scope of jobs to show, one or array of: created, pending, running,
// failed, success, canceled, skipped; showing all jobs if none provided
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#list-project-jobs
func (s *JobsService) ListProjectJobs(pid interface{}, opts *ListJobsOptions, options ...OptionFunc) ([]Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs", pathEscape(project))

	req, err := s.client.NewRequest("GET", u, opts, options)
	if err != nil {
		return nil, nil, err
	}

	var jobs []Job
	resp, err := s.client.Do(req, &jobs)
	if err != nil {
		return nil, resp, err
	}

	return jobs, resp, err
}

// ListPipelineJobs gets a list of jobs for specific pipeline in a
// project. If the pipeline ID is not found, it will respond with 404.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#list-pipeline-jobs
func (s *JobsService) ListPipelineJobs(pid interface{}, pipelineID int, opts *ListJobsOptions, options ...OptionFunc) ([]*Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines/%d/jobs", pathEscape(project), pipelineID)

	req, err := s.client.NewRequest("GET", u, opts, options)
	if err != nil {
		return nil, nil, err
	}

	var jobs []*Job
	resp, err := s.client.Do(req, &jobs)
	if err != nil {
		return nil, resp, err
	}

	return jobs, resp, err
}

// GetJob gets a single job of a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#get-a-single-job
func (s *JobsService) GetJob(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d", pathEscape(project), jobID)

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	job := new(Job)
	resp, err := s.client.Do(req, job)
	if err != nil {
		return nil, resp, err
	}

	return job, resp, err
}

// GetJobArtifacts get jobs artifacts of a project
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#get-job-artifacts
func (s *JobsService) GetJobArtifacts(pid interface{}, jobID int, options ...OptionFunc) (io.Reader, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d/artifacts", pathEscape(project), jobID)

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	artifactsBuf := new(bytes.Buffer)
	resp, err := s.client.Do(req, artifactsBuf)
	if err != nil {
		return nil, resp, err
	}

	return artifactsBuf, resp, err
}

// DownloadArtifactsFileOptions represents the available DownloadArtifactsFile()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#download-the-artifacts-file
type DownloadArtifactsFileOptions struct {
	Job *string `url:"job" json:"job"`
}

// DownloadArtifactsFile download the artifacts file from the given
// reference name and job provided the job finished successfully.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#download-the-artifacts-file
func (s *JobsService) DownloadArtifactsFile(pid interface{}, refName string, opt *DownloadArtifactsFileOptions, options ...OptionFunc) (io.Reader, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/artifacts/%s/download", pathEscape(project), refName)

	req, err := s.client.NewRequest("GET", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	artifactsBuf := new(bytes.Buffer)
	resp, err := s.client.Do(req, artifactsBuf)
	if err != nil {
		return nil, resp, err
	}

	return artifactsBuf, resp, err
}

// DownloadSingleArtifactsFile download a file from the artifacts from the
// given reference name and job provided the job finished successfully.
// Only a single file is going to be extracted from the archive and streamed
// to a client.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#download-a-single-artifact-file
func (s *JobsService) DownloadSingleArtifactsFile(pid interface{}, jobID int, artifactPath string, options ...OptionFunc) (io.Reader, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}

	u := fmt.Sprintf(
		"projects/%s/jobs/%d/artifacts/%s",
		pathEscape(project),
		jobID,
		artifactPath,
	)

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	artifactBuf := new(bytes.Buffer)
	resp, err := s.client.Do(req, artifactBuf)
	if err != nil {
		return nil, resp, err
	}

	return artifactBuf, resp, err
}

// GetTraceFile gets a trace of a specific job of a project
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#get-a-trace-file
func (s *JobsService) GetTraceFile(pid interface{}, jobID int, options ...OptionFunc) (io.Reader, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d/trace", pathEscape(project), jobID)

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	traceBuf := new(bytes.Buffer)
	resp, err := s.client.Do(req, traceBuf)
	if err != nil {
		return nil, resp, err
	}

	return traceBuf, resp, err
}

// CancelJob cancels a single job of a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#cancel-a-job
func (s *JobsService) CancelJob(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d/cancel", pathEscape(project), jobID)

	req, err := s.client.NewRequest("POST", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	job := new(Job)
	resp, err := s.client.Do(req, job)
	if err != nil {
		return nil, resp, err
	}

	return job, resp, err
}

// RetryJob retries a single job of a project
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#retry-a-job
func (s *JobsService) RetryJob(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d/retry", pathEscape(project), jobID)

	req, err := s.client.NewRequest("POST", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	job := new(Job)
	resp, err := s.client.Do(req, job)
	if err != nil {
		return nil, resp, err
	}

	return job, resp, err
}

// EraseJob erases a single job of a project, removes a job
// artifacts and a job trace.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#erase-a-job
func (s *JobsService) EraseJob(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d/erase", pathEscape(project), jobID)

	req, err := s.client.NewRequest("POST", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	job := new(Job)
	resp, err := s.client.Do(req, job)
	if err != nil {
		return nil, resp, err
	}

	return job, resp, err
}

// KeepArtifacts prevents artifacts from being deleted when
// expiration is set.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#keep-artifacts
func (s *JobsService) KeepArtifacts(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d/artifacts/keep", pathEscape(project), jobID)

	req, err := s.client.NewRequest("POST", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	job := new(Job)
	resp, err := s.client.Do(req, job)
	if err != nil {
		return nil, resp, err
	}

	return job, resp, err
}

// PlayJob triggers a manual action to start a job.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/jobs.html#play-a-job
func (s *JobsService) PlayJob(pid interface{}, jobID int, options ...OptionFunc) (*Job, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/jobs/%d/play", pathEscape(project), jobID)

	req, err := s.client.NewRequest("POST", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	job := new(Job)
	resp, err := s.client.Do(req, job)
	if err != nil {
		return nil, resp, err
	}

	return job, resp, err
}
<|endoftext|>


<commit_before>// +build debug

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"os"

	"github.com/juju/errors"
	"github.com/restic/restic"
	"github.com/restic/restic/backend"
	"github.com/restic/restic/pack"
	"github.com/restic/restic/repository"
)

type CmdDump struct {
	global *GlobalOptions
}

func init() {
	_, err := parser.AddCommand("dump",
		"dump data structures",
		"The dump command dumps data structures from a repository as JSON documents",
		&CmdDump{global: &globalOpts})
	if err != nil {
		panic(err)
	}
}

func (cmd CmdDump) Usage() string {
	return "[index|snapshots|trees|all]"
}

func prettyPrintJSON(wr io.Writer, item interface{}) error {
	buf, err := json.MarshalIndent(item, "", "  ")
	if err != nil {
		return err
	}

	_, err = wr.Write(append(buf, '\n'))
	return err
}

func printSnapshots(repo *repository.Repository, wr io.Writer) error {
	done := make(chan struct{})
	defer close(done)

	for id := range repo.List(backend.Snapshot, done) {
		snapshot, err := restic.LoadSnapshot(repo, id)
		if err != nil {
			fmt.Fprintf(os.Stderr, "LoadSnapshot(%v): %v", id.Str(), err)
			continue
		}

		fmt.Fprintf(wr, "snapshot_id: %v\n", id)

		err = prettyPrintJSON(wr, snapshot)
		if err != nil {
			return err
		}
	}

	return nil
}

func printTrees(repo *repository.Repository, wr io.Writer) error {
	done := make(chan struct{})
	defer close(done)

	trees := []backend.ID{}

	for blob := range repo.Index().Each(done) {
		if blob.Type != pack.Tree {
			continue
		}

		trees = append(trees, blob.ID)
	}

	for _, id := range trees {
		tree, err := restic.LoadTree(repo, id)
		if err != nil {
			fmt.Fprintf(os.Stderr, "LoadTree(%v): %v", id.Str(), err)
			continue
		}

		fmt.Fprintf(wr, "tree_id: %v\n", id)

		prettyPrintJSON(wr, tree)
	}

	return nil
}

func (cmd CmdDump) Execute(args []string) error {
	if len(args) != 1 {
		return fmt.Errorf("type not specified, Usage: %s", cmd.Usage())
	}

	repo, err := cmd.global.OpenRepository()
	if err != nil {
		return err
	}

	lock, err := lockRepo(repo)
	defer unlockRepo(lock)
	if err != nil {
		return err
	}

	err = repo.LoadIndex()
	if err != nil {
		return err
	}

	tpe := args[0]

	switch tpe {
	case "index":
		return repo.Index().Dump(os.Stdout)
	case "snapshots":
		return printSnapshots(repo, os.Stdout)
	case "trees":
		return printTrees(repo, os.Stdout)
	case "all":
		fmt.Printf("snapshots:\n")
		err := printSnapshots(repo, os.Stdout)
		if err != nil {
			return err
		}

		fmt.Printf("\ntrees:\n")

		err = printTrees(repo, os.Stdout)
		if err != nil {
			return err
		}

		fmt.Printf("\nindex:\n")

		err = repo.Index().Dump(os.Stdout)
		if err != nil {
			return err
		}

		return nil
	default:
		return errors.Errorf("no such type %q", tpe)
	}
}
<commit_msg>Dump individual indexes<commit_after>// +build debug

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"os"

	"github.com/juju/errors"
	"github.com/restic/restic"
	"github.com/restic/restic/backend"
	"github.com/restic/restic/pack"
	"github.com/restic/restic/repository"
)

type CmdDump struct {
	global *GlobalOptions

	repo *repository.Repository
}

func init() {
	_, err := parser.AddCommand("dump",
		"dump data structures",
		"The dump command dumps data structures from a repository as JSON documents",
		&CmdDump{global: &globalOpts})
	if err != nil {
		panic(err)
	}
}

func (cmd CmdDump) Usage() string {
	return "[index|snapshots|trees|all]"
}

func prettyPrintJSON(wr io.Writer, item interface{}) error {
	buf, err := json.MarshalIndent(item, "", "  ")
	if err != nil {
		return err
	}

	_, err = wr.Write(append(buf, '\n'))
	return err
}

func printSnapshots(repo *repository.Repository, wr io.Writer) error {
	done := make(chan struct{})
	defer close(done)

	for id := range repo.List(backend.Snapshot, done) {
		snapshot, err := restic.LoadSnapshot(repo, id)
		if err != nil {
			fmt.Fprintf(os.Stderr, "LoadSnapshot(%v): %v", id.Str(), err)
			continue
		}

		fmt.Fprintf(wr, "snapshot_id: %v\n", id)

		err = prettyPrintJSON(wr, snapshot)
		if err != nil {
			return err
		}
	}

	return nil
}

func printTrees(repo *repository.Repository, wr io.Writer) error {
	done := make(chan struct{})
	defer close(done)

	trees := []backend.ID{}

	for blob := range repo.Index().Each(done) {
		if blob.Type != pack.Tree {
			continue
		}

		trees = append(trees, blob.ID)
	}

	for _, id := range trees {
		tree, err := restic.LoadTree(repo, id)
		if err != nil {
			fmt.Fprintf(os.Stderr, "LoadTree(%v): %v", id.Str(), err)
			continue
		}

		fmt.Fprintf(wr, "tree_id: %v\n", id)

		prettyPrintJSON(wr, tree)
	}

	return nil
}

func (cmd CmdDump) DumpIndexes() error {
	done := make(chan struct{})
	defer close(done)

	for id := range cmd.repo.List(backend.Index, done) {
		fmt.Printf("index_id: %v\n", id)

		idx, err := repository.LoadIndex(cmd.repo, id.String())
		if err != nil {
			return err
		}

		err = idx.Dump(os.Stdout)
		if err != nil {
			return err
		}
	}

	return nil
}

func (cmd CmdDump) Execute(args []string) error {
	if len(args) != 1 {
		return fmt.Errorf("type not specified, Usage: %s", cmd.Usage())
	}

	repo, err := cmd.global.OpenRepository()
	if err != nil {
		return err
	}
	cmd.repo = repo

	lock, err := lockRepo(repo)
	defer unlockRepo(lock)
	if err != nil {
		return err
	}

	err = repo.LoadIndex()
	if err != nil {
		return err
	}

	tpe := args[0]

	switch tpe {
	case "index":
		return repo.Index().Dump(os.Stdout)
	case "indexes":
		return cmd.DumpIndexes()
	case "snapshots":
		return printSnapshots(repo, os.Stdout)
	case "trees":
		return printTrees(repo, os.Stdout)
	case "all":
		fmt.Printf("snapshots:\n")
		err := printSnapshots(repo, os.Stdout)
		if err != nil {
			return err
		}

		fmt.Printf("\ntrees:\n")

		err = printTrees(repo, os.Stdout)
		if err != nil {
			return err
		}

		fmt.Printf("\nindexes:\n")
		err = cmd.DumpIndexes()
		if err != nil {
			return err
		}

		fmt.Printf("\nindex:\n")

		err = repo.Index().Dump(os.Stdout)
		if err != nil {
			return err
		}

		return nil
	default:
		return errors.Errorf("no such type %q", tpe)
	}
}
<|endoftext|>


<commit_before>/*
 *
 * k6 - a next-generation load testing tool
 * Copyright (C) 2018 Load Impact
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package cmd

import (
	"os"
	"regexp"
	"strings"

	"github.com/loadimpact/k6/lib"
	"github.com/pkg/errors"
	"github.com/spf13/pflag"
)

var userEnvVarName = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)

func parseEnvKeyValue(kv string) (string, string) {
	if idx := strings.IndexRune(kv, '='); idx != -1 {
		return kv[:idx], kv[idx+1:]
	}
	return kv, ""
}

func collectEnv() map[string]string {
	env := make(map[string]string)
	for _, kv := range os.Environ() {
		k, v := parseEnvKeyValue(kv)
		env[k] = v
	}
	return env
}

func runtimeOptionFlagSet(includeSysEnv bool) *pflag.FlagSet {
	flags := pflag.NewFlagSet("", 0)
	flags.SortFlags = false
	flags.Bool("include-system-env-vars", includeSysEnv, "pass the real system environment variables to the runtime")
	flags.StringArrayP("env", "e", nil, "add/override environment variable with `VAR=value`")
	return flags
}

func getRuntimeOptions(flags *pflag.FlagSet) (lib.RuntimeOptions, error) {
	opts := lib.RuntimeOptions{
		IncludeSystemEnvVars: getNullBool(flags, "include-system-env-vars"),
		Env:                  make(map[string]string),
	}

	// If enabled, gather the actual system environment variables
	if opts.IncludeSystemEnvVars.Bool {
		opts.Env = collectEnv()
	}

	// Set/overwrite environment variables with custom user-supplied values
	envVars, err := flags.GetStringArray("env")
	if err != nil {
		return opts, err
	}

	for _, kv := range envVars {
		k, v := parseEnvKeyValue(kv)
		// Allow only alphanumeric ASCII variable names for now
		if !userEnvVarName.MatchString(k) {
			return opts, errors.Errorf("Invalid environment variable name '%s'", k)
		}
		opts.Env[k] = v
	}

	return opts, nil
}
<commit_msg>feat(cmd): expose compatibility mode option to CLI<commit_after>/*
 *
 * k6 - a next-generation load testing tool
 * Copyright (C) 2018 Load Impact
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package cmd

import (
	"os"
	"regexp"
	"strings"

	"github.com/loadimpact/k6/lib"
	"github.com/pkg/errors"
	"github.com/spf13/pflag"
	"gopkg.in/guregu/null.v3"
)

var userEnvVarName = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)

func parseEnvKeyValue(kv string) (string, string) {
	if idx := strings.IndexRune(kv, '='); idx != -1 {
		return kv[:idx], kv[idx+1:]
	}
	return kv, ""
}

func collectEnv() map[string]string {
	env := make(map[string]string)
	for _, kv := range os.Environ() {
		k, v := parseEnvKeyValue(kv)
		env[k] = v
	}
	return env
}

func runtimeOptionFlagSet(includeSysEnv bool) *pflag.FlagSet {
	flags := pflag.NewFlagSet("", 0)
	flags.SortFlags = false
	flags.Bool("include-system-env-vars", includeSysEnv, "pass the real system environment variables to the runtime")
	flags.String("compatibility-mode", "extended",
		`JavaScript compiler compatibility mode, "extended" or "base"
base: pure Golang JS VM supporting ES5.1+
extended: base + Babel with ES2015 preset + core.js v2,
          slower and memory consuming but with greater JS support
`)
	flags.StringArrayP("env", "e", nil, "add/override environment variable with `VAR=value`")
	return flags
}

func getRuntimeOptions(flags *pflag.FlagSet) (lib.RuntimeOptions, error) {
	opts := lib.RuntimeOptions{
		IncludeSystemEnvVars: getNullBool(flags, "include-system-env-vars"),
		CompatibilityMode:    getNullString(flags, "compatibility-mode"),
		Env:                  make(map[string]string),
	}

	// If enabled, gather the actual system environment variables
	if opts.IncludeSystemEnvVars.Bool {
		opts.Env = collectEnv()
	}

	// Set/overwrite environment variables with custom user-supplied values
	envVars, err := flags.GetStringArray("env")
	if err != nil {
		return opts, err
	}

	for _, kv := range envVars {
		k, v := parseEnvKeyValue(kv)
		// Allow only alphanumeric ASCII variable names for now
		if !userEnvVarName.MatchString(k) {
			return opts, errors.Errorf("Invalid environment variable name '%s'", k)
		}
		opts.Env[k] = v
	}

	// Fallback to env
	compatMode := opts.Env["K6_COMPATIBILITY_MODE"]
	if !opts.CompatibilityMode.Valid && compatMode != "" {
		opts.CompatibilityMode = null.StringFrom(compatMode)
	}

	return opts, nil
}
<|endoftext|>


<commit_before>package sdp

import (
	"fmt"
	"time"
)

// Constants for SDP attributes used in JSEP
const (
	AttrKeyIdentity        = "identity"
	AttrKeyGroup           = "group"
	AttrKeySsrc            = "ssrc"
	AttrKeySsrcGroup       = "ssrc-group"
	AttrKeyMsidSemantic    = "msid-semantic"
	AttrKeyConnectionSetup = "setup"
	AttrKeyMID             = "mid"
	AttrKeyICELite         = "ice-lite"
	AttrKeyRtcpMux         = "rtcp-mux"
	AttrKeyRtcpRsize       = "rtcp-rsize"
)

// Constants for semantic tokens used in JSEP
const (
	SemanticTokenLipSynchronization     = "LS"
	SemanticTokenFlowIdentification     = "FID"
	SemanticTokenForwardErrorCorrection = "FEC"
	SemanticTokenWebRTCMediaStreams     = "WMS"
)

// API to match draft-ietf-rtcweb-jsep
// Move to webrtc or its own package?

// NewJSEPSessionDescription creates a new SessionDescription with
// some settings that are required by the JSEP spec.
func NewJSEPSessionDescription(fingerprint string, identity bool) *SessionDescription {
	d := &SessionDescription{
		ProtocolVersion: 0,
		Origin: fmt.Sprintf(
			"- %d %d IN IP4 0.0.0.0",
			newSessionID(),
			time.Now().Unix(),
		),
		SessionName: "-",
		Timing:      []string{"0 0"},
		Attributes: []string{
			//	"ice-options:trickle", // TODO: implement trickle ICE
			"fingerprint:sha-256 " + fingerprint,
		},
	}

	if identity {
		d.WithPropertyAttribute(AttrKeyIdentity)
	}

	return d
}

// WithPropertyAttribute adds a property attribute 'a=key' to the session description
func (d *SessionDescription) WithPropertyAttribute(key string) *SessionDescription {
	d.Attributes = append(d.Attributes, key)
	return d
}

// WithValueAttribute adds a value attribute 'a=key:value' to the session description
func (d *SessionDescription) WithValueAttribute(key, value string) *SessionDescription {
	d.Attributes = append(d.Attributes, fmt.Sprintf("%s:%s", key, value))
	return d
}

// WithMedia adds a media description to the session description
func (d *SessionDescription) WithMedia(md *MediaDescription) *SessionDescription {
	d.MediaDescriptions = append(d.MediaDescriptions, md)
	return d
}

// NewJSEPMediaDescription creates a new MediaDescription with
// some settings that are required by the JSEP spec.
func NewJSEPMediaDescription(typ string, codecPrefs []string) *MediaDescription {
	// TODO: handle codecPrefs
	d := &MediaDescription{
		MediaName:      fmt.Sprintf("%s 9 UDP/TLS/RTP/SAVPF", typ), // TODO: other transports?
		ConnectionData: "IN IP4 0.0.0.0",
		Attributes:     []string{},
	}
	return d
}

// WithPropertyAttribute adds a property attribute 'a=key' to the media description
func (d *MediaDescription) WithPropertyAttribute(key string) *MediaDescription {
	d.Attributes = append(d.Attributes, key)
	return d
}

// WithValueAttribute adds a value attribute 'a=key:value' to the media description
func (d *MediaDescription) WithValueAttribute(key, value string) *MediaDescription {
	d.Attributes = append(d.Attributes, fmt.Sprintf("%s:%s", key, value))
	return d
}

// WithICECredentials adds ICE credentials to the media description
func (d *MediaDescription) WithICECredentials(username, password string) *MediaDescription {
	return d.
		WithValueAttribute("ice-ufrag", username).
		WithValueAttribute("ice-pwd", password)
}

// WithCodec adds codec information to the media description
func (d *MediaDescription) WithCodec(payloadType uint8, name string, clockrate uint32, channels uint16, fmtp string) *MediaDescription {
	d.MediaName = fmt.Sprintf("%s %d", d.MediaName, payloadType)
	rtpmap := fmt.Sprintf("%d %s/%d", payloadType, name, clockrate)
	if channels > 0 {
		rtpmap = rtpmap + fmt.Sprintf("/%d", channels)
	}
	d.WithValueAttribute("rtpmap", rtpmap)
	if fmtp != "" {
		d.WithValueAttribute("fmtp", fmt.Sprintf("%d %s", payloadType, fmtp))
	}
	return d
}

// WithMediaSource adds media source information to the media description
func (d *MediaDescription) WithMediaSource(ssrc uint32, cname, streamLabel, label string) *MediaDescription {
	return d.
		WithValueAttribute("ssrc", fmt.Sprintf("%d cname:%s", ssrc, cname)). // Deprecated but not pased out?
		WithValueAttribute("ssrc", fmt.Sprintf("%d msid:%s %s", ssrc, streamLabel, label)).
		WithValueAttribute("ssrc", fmt.Sprintf("%d mslabel:%s", ssrc, streamLabel)). // Deprecated but not pased out?
		WithValueAttribute("ssrc", fmt.Sprintf("%d label:%s", ssrc, label))          // Deprecated but not pased out?
}

// WithCandidate adds an ICE candidate to the media description
func (d *MediaDescription) WithCandidate(id int, transport string, basePriority uint16, ip string, port int, typ string) *MediaDescription {
	return d.
		WithValueAttribute("candidate",
			fmt.Sprintf("%scandidate %d %s %d %s %d typ %s", transport, id, transport, basePriority, ip, port, typ))
}
<commit_msg>api: fix typos<commit_after>package sdp

import (
	"fmt"
	"time"
)

// Constants for SDP attributes used in JSEP
const (
	AttrKeyIdentity        = "identity"
	AttrKeyGroup           = "group"
	AttrKeySsrc            = "ssrc"
	AttrKeySsrcGroup       = "ssrc-group"
	AttrKeyMsidSemantic    = "msid-semantic"
	AttrKeyConnectionSetup = "setup"
	AttrKeyMID             = "mid"
	AttrKeyICELite         = "ice-lite"
	AttrKeyRtcpMux         = "rtcp-mux"
	AttrKeyRtcpRsize       = "rtcp-rsize"
)

// Constants for semantic tokens used in JSEP
const (
	SemanticTokenLipSynchronization     = "LS"
	SemanticTokenFlowIdentification     = "FID"
	SemanticTokenForwardErrorCorrection = "FEC"
	SemanticTokenWebRTCMediaStreams     = "WMS"
)

// API to match draft-ietf-rtcweb-jsep
// Move to webrtc or its own package?

// NewJSEPSessionDescription creates a new SessionDescription with
// some settings that are required by the JSEP spec.
func NewJSEPSessionDescription(fingerprint string, identity bool) *SessionDescription {
	d := &SessionDescription{
		ProtocolVersion: 0,
		Origin: fmt.Sprintf(
			"- %d %d IN IP4 0.0.0.0",
			newSessionID(),
			time.Now().Unix(),
		),
		SessionName: "-",
		Timing:      []string{"0 0"},
		Attributes: []string{
			//	"ice-options:trickle", // TODO: implement trickle ICE
			"fingerprint:sha-256 " + fingerprint,
		},
	}

	if identity {
		d.WithPropertyAttribute(AttrKeyIdentity)
	}

	return d
}

// WithPropertyAttribute adds a property attribute 'a=key' to the session description
func (d *SessionDescription) WithPropertyAttribute(key string) *SessionDescription {
	d.Attributes = append(d.Attributes, key)
	return d
}

// WithValueAttribute adds a value attribute 'a=key:value' to the session description
func (d *SessionDescription) WithValueAttribute(key, value string) *SessionDescription {
	d.Attributes = append(d.Attributes, fmt.Sprintf("%s:%s", key, value))
	return d
}

// WithMedia adds a media description to the session description
func (d *SessionDescription) WithMedia(md *MediaDescription) *SessionDescription {
	d.MediaDescriptions = append(d.MediaDescriptions, md)
	return d
}

// NewJSEPMediaDescription creates a new MediaDescription with
// some settings that are required by the JSEP spec.
func NewJSEPMediaDescription(codecType string, codecPrefs []string) *MediaDescription {
	// TODO: handle codecPrefs
	d := &MediaDescription{
		MediaName:      fmt.Sprintf("%s 9 UDP/TLS/RTP/SAVPF", codecType), // TODO: other transports?
		ConnectionData: "IN IP4 0.0.0.0",
		Attributes:     []string{},
	}
	return d
}

// WithPropertyAttribute adds a property attribute 'a=key' to the media description
func (d *MediaDescription) WithPropertyAttribute(key string) *MediaDescription {
	d.Attributes = append(d.Attributes, key)
	return d
}

// WithValueAttribute adds a value attribute 'a=key:value' to the media description
func (d *MediaDescription) WithValueAttribute(key, value string) *MediaDescription {
	d.Attributes = append(d.Attributes, fmt.Sprintf("%s:%s", key, value))
	return d
}

// WithICECredentials adds ICE credentials to the media description
func (d *MediaDescription) WithICECredentials(username, password string) *MediaDescription {
	return d.
		WithValueAttribute("ice-ufrag", username).
		WithValueAttribute("ice-pwd", password)
}

// WithCodec adds codec information to the media description
func (d *MediaDescription) WithCodec(payloadType uint8, name string, clockrate uint32, channels uint16, fmtp string) *MediaDescription {
	d.MediaName = fmt.Sprintf("%s %d", d.MediaName, payloadType)
	rtpmap := fmt.Sprintf("%d %s/%d", payloadType, name, clockrate)
	if channels > 0 {
		rtpmap = rtpmap + fmt.Sprintf("/%d", channels)
	}
	d.WithValueAttribute("rtpmap", rtpmap)
	if fmtp != "" {
		d.WithValueAttribute("fmtp", fmt.Sprintf("%d %s", payloadType, fmtp))
	}
	return d
}

// WithMediaSource adds media source information to the media description
func (d *MediaDescription) WithMediaSource(ssrc uint32, cname, streamLabel, label string) *MediaDescription {
	return d.
		WithValueAttribute("ssrc", fmt.Sprintf("%d cname:%s", ssrc, cname)). // Deprecated but not pased out?
		WithValueAttribute("ssrc", fmt.Sprintf("%d msid:%s %s", ssrc, streamLabel, label)).
		WithValueAttribute("ssrc", fmt.Sprintf("%d mslabel:%s", ssrc, streamLabel)). // Deprecated but not pased out?
		WithValueAttribute("ssrc", fmt.Sprintf("%d label:%s", ssrc, label))          // Deprecated but not pased out?
}

// WithCandidate adds an ICE candidate to the media description
func (d *MediaDescription) WithCandidate(id int, transport string, basePriority uint16, ip string, port int, typ string) *MediaDescription {
	return d.
		WithValueAttribute("candidate",
			fmt.Sprintf("%scandidate %d %s %d %s %d typ %s", transport, id, transport, basePriority, ip, port, typ))
}
<|endoftext|>