<commit_before>package bridge

import (
	"fmt"
	"net"

	"github.com/docker/docker/pkg/iptables"
	"github.com/docker/libnetwork/netutils"
)

// DockerChain: DOCKER iptable chain name
const (
	DockerChain = "DOCKER"
)

func setupIPTables(config *Configuration, i *bridgeInterface) error {
	// Sanity check.
	if config.EnableIPTables == false {
		return ipTableCfgError(config.BridgeName)
	}

	addrv4, _, err := netutils.GetIfaceAddr(config.BridgeName)
	if err != nil {
		return fmt.Errorf("Failed to setup IP tables, cannot acquire Interface address: %s", err.Error())
	}
	if err = setupIPTablesInternal(config.BridgeName, addrv4, config.EnableICC, config.EnableIPMasquerade, true); err != nil {
		return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
	}

	_, err = iptables.NewChain(DockerChain, config.BridgeName, iptables.Nat)
	if err != nil {
		return fmt.Errorf("Failed to create NAT chain: %s", err.Error())
	}

	chain, err := iptables.NewChain(DockerChain, config.BridgeName, iptables.Filter)
	if err != nil {
		return fmt.Errorf("Failed to create FILTER chain: %s", err.Error())
	}

	portMapper.SetIptablesChain(chain)

	return nil
}

type iptRule struct {
	table   iptables.Table
	chain   string
	preArgs []string
	args    []string
}

func setupIPTablesInternal(bridgeIface string, addr net.Addr, icc, ipmasq, enable bool) error {

	var (
		address = addr.String()
		natRule = iptRule{table: iptables.Nat, chain: "POSTROUTING", preArgs: []string{"-t", "nat"}, args: []string{"-s", address, "!", "-o", bridgeIface, "-j", "MASQUERADE"}}
		outRule = iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", bridgeIface, "!", "-o", bridgeIface, "-j", "ACCEPT"}}
		inRule  = iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-o", bridgeIface, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}}
	)

	// Set NAT.
	if ipmasq {
		if err := programChainRule(natRule, "NAT", enable); err != nil {
			return err
		}
	}

	// Set Inter Container Communication.
	if err := setIcc(bridgeIface, icc, enable); err != nil {
		return err
	}

	// Set Accept on all non-intercontainer outgoing packets.
	if err := programChainRule(outRule, "ACCEPT NON_ICC OUTGOING", enable); err != nil {
		return err
	}

	// Set Accept on incoming packets for existing connections.
	if err := programChainRule(inRule, "ACCEPT INCOMING", enable); err != nil {
		return err
	}

	return nil
}

func programChainRule(rule iptRule, ruleDescr string, insert bool) error {
	var (
		prefix    []string
		operation string
		condition bool
		doesExist = iptables.Exists(rule.table, rule.chain, rule.args...)
	)

	if insert {
		condition = !doesExist
		prefix = []string{"-I", rule.chain}
		operation = "enable"
	} else {
		condition = doesExist
		prefix = []string{"-D", rule.chain}
		operation = "disable"
	}
	if rule.preArgs != nil {
		prefix = append(rule.preArgs, prefix...)
	}

	if condition {
		if output, err := iptables.Raw(append(prefix, rule.args...)...); err != nil {
			return fmt.Errorf("Unable to %s %s rule: %s", operation, ruleDescr, err.Error())
		} else if len(output) != 0 {
			return &iptables.ChainError{Chain: rule.chain, Output: output}
		}
	}

	return nil
}

func setIcc(bridgeIface string, iccEnable, insert bool) error {
	var (
		table      = iptables.Filter
		chain      = "FORWARD"
		args       = []string{"-i", bridgeIface, "-o", bridgeIface, "-j"}
		acceptArgs = append(args, "ACCEPT")
		dropArgs   = append(args, "DROP")
	)

	if insert {
		if !iccEnable {
			iptables.Raw(append([]string{"-D", chain}, acceptArgs...)...)

			if !iptables.Exists(table, chain, dropArgs...) {
				if output, err := iptables.Raw(append([]string{"-I", chain}, dropArgs...)...); err != nil {
					return fmt.Errorf("Unable to prevent intercontainer communication: %s", err.Error())
				} else if len(output) != 0 {
					return fmt.Errorf("Error disabling intercontainer communication: %s", output)
				}
			}
		} else {
			iptables.Raw(append([]string{"-D", chain}, dropArgs...)...)

			if !iptables.Exists(table, chain, acceptArgs...) {
				if output, err := iptables.Raw(append([]string{"-I", chain}, acceptArgs...)...); err != nil {
					return fmt.Errorf("Unable to allow intercontainer communication: %s", err.Error())
				} else if len(output) != 0 {
					return fmt.Errorf("Error enabling intercontainer communication: %s", output)
				}
			}
		}
	} else {
		// Remove any ICC rule.
		if !iccEnable {
			if iptables.Exists(table, chain, dropArgs...) {
				iptables.Raw(append([]string{"-D", chain}, dropArgs...)...)
			}
		} else {
			if iptables.Exists(table, chain, acceptArgs...) {
				iptables.Raw(append([]string{"-D", chain}, acceptArgs...)...)
			}
		}
	}

	return nil
}
<commit_msg>Port PR #11526 to libnetwork<commit_after>package bridge

import (
	"fmt"
	"net"

	"github.com/docker/docker/pkg/iptables"
	"github.com/docker/libnetwork/netutils"
)

// DockerChain: DOCKER iptable chain name
const (
	DockerChain = "DOCKER"
)

func setupIPTables(config *Configuration, i *bridgeInterface) error {
	// Sanity check.
	if config.EnableIPTables == false {
		return ipTableCfgError(config.BridgeName)
	}

	addrv4, _, err := netutils.GetIfaceAddr(config.BridgeName)
	if err != nil {
		return fmt.Errorf("Failed to setup IP tables, cannot acquire Interface address: %s", err.Error())
	}
	if err = setupIPTablesInternal(config.BridgeName, addrv4, config.EnableICC, config.EnableIPMasquerade, true); err != nil {
		return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
	}

	_, err = iptables.NewChain(DockerChain, config.BridgeName, iptables.Nat)
	if err != nil {
		return fmt.Errorf("Failed to create NAT chain: %s", err.Error())
	}

	chain, err := iptables.NewChain(DockerChain, config.BridgeName, iptables.Filter)
	if err != nil {
		return fmt.Errorf("Failed to create FILTER chain: %s", err.Error())
	}

	portMapper.SetIptablesChain(chain)

	return nil
}

type iptRule struct {
	table   iptables.Table
	chain   string
	preArgs []string
	args    []string
}

func setupIPTablesInternal(bridgeIface string, addr net.Addr, icc, ipmasq, enable bool) error {

	var (
		address = addr.String()
		natRule = iptRule{table: iptables.Nat, chain: "POSTROUTING", preArgs: []string{"-t", "nat"}, args: []string{"-s", address, "!", "-o", bridgeIface, "-j", "MASQUERADE"}}
		outRule = iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", bridgeIface, "!", "-o", bridgeIface, "-j", "ACCEPT"}}
		inRule  = iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-o", bridgeIface, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}}
	)

	// Set NAT.
	if ipmasq {
		if err := programChainRule(natRule, "NAT", enable); err != nil {
			return err
		}
	}

	// Set Inter Container Communication.
	if err := setIcc(bridgeIface, icc, enable); err != nil {
		return err
	}

	// Set Accept on all non-intercontainer outgoing packets.
	if err := programChainRule(outRule, "ACCEPT NON_ICC OUTGOING", enable); err != nil {
		return err
	}

	// Set Accept on incoming packets for existing connections.
	if err := programChainRule(inRule, "ACCEPT INCOMING", enable); err != nil {
		return err
	}

	return nil
}

func programChainRule(rule iptRule, ruleDescr string, insert bool) error {
	var (
		prefix    []string
		operation string
		condition bool
		doesExist = iptables.Exists(rule.table, rule.chain, rule.args...)
	)

	if insert {
		condition = !doesExist
		prefix = []string{"-I", rule.chain}
		operation = "enable"
	} else {
		condition = doesExist
		prefix = []string{"-D", rule.chain}
		operation = "disable"
	}
	if rule.preArgs != nil {
		prefix = append(rule.preArgs, prefix...)
	}

	if condition {
		if output, err := iptables.Raw(append(prefix, rule.args...)...); err != nil {
			return fmt.Errorf("Unable to %s %s rule: %s", operation, ruleDescr, err.Error())
		} else if len(output) != 0 {
			return &iptables.ChainError{Chain: rule.chain, Output: output}
		}
	}

	return nil
}

func setIcc(bridgeIface string, iccEnable, insert bool) error {
	var (
		table      = iptables.Filter
		chain      = "FORWARD"
		args       = []string{"-i", bridgeIface, "-o", bridgeIface, "-j"}
		acceptArgs = append(args, "ACCEPT")
		dropArgs   = append(args, "DROP")
	)

	if insert {
		if !iccEnable {
			iptables.Raw(append([]string{"-D", chain}, acceptArgs...)...)

			if !iptables.Exists(table, chain, dropArgs...) {
				if output, err := iptables.Raw(append([]string{"-A", chain}, dropArgs...)...); err != nil {
					return fmt.Errorf("Unable to prevent intercontainer communication: %s", err.Error())
				} else if len(output) != 0 {
					return fmt.Errorf("Error disabling intercontainer communication: %s", output)
				}
			}
		} else {
			iptables.Raw(append([]string{"-D", chain}, dropArgs...)...)

			if !iptables.Exists(table, chain, acceptArgs...) {
				if output, err := iptables.Raw(append([]string{"-A", chain}, acceptArgs...)...); err != nil {
					return fmt.Errorf("Unable to allow intercontainer communication: %s", err.Error())
				} else if len(output) != 0 {
					return fmt.Errorf("Error enabling intercontainer communication: %s", output)
				}
			}
		}
	} else {
		// Remove any ICC rule.
		if !iccEnable {
			if iptables.Exists(table, chain, dropArgs...) {
				iptables.Raw(append([]string{"-D", chain}, dropArgs...)...)
			}
		} else {
			if iptables.Exists(table, chain, acceptArgs...) {
				iptables.Raw(append([]string{"-D", chain}, acceptArgs...)...)
			}
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"os"

	"github.com/bborbe/log"
	"github.com/bborbe/monitoring/configuration"
	"github.com/bborbe/monitoring/runner"
	"github.com/bborbe/monitoring/runner/all"
	"github.com/bborbe/monitoring/runner/hierarchy"
)

var logger = log.DefaultLogger

func main() {
	defer logger.Close()
	logLevelPtr := flag.String("loglevel", log.LogLevelToString(log.ERROR), "one of OFF,TRACE,DEBUG,INFO,WARN,ERROR")
	modePtr := flag.String("mode", "", "mode (all|hierachy)")
	flag.Parse()
	logger.SetLevelThreshold(log.LogStringToLevel(*logLevelPtr))
	logger.Debugf("set log level to %s", *logLevelPtr)

	var r runner.Runner
	if "all" == *modePtr {
		logger.Debug("runner = all")
		r = all.New()
	} else {
		logger.Debug("runner = hierarchy")
		r = hierarchy.New()
	}
	c := configuration.New()
	writer := os.Stdout
	err := do(writer, r, c)
	if err != nil {
		logger.Fatal(err)
		os.Exit(1)
	}
	logger.Debug("done")
}

func do(writer io.Writer, r runner.Runner, c configuration.Configuration) error {
	var err error
	fmt.Fprintf(writer, "check started\n")
	results := r.Run(c)
	for result := range results {
		if result.Success() {
			fmt.Fprintf(writer, "[OK]   %s\n", result.Message())
		} else {
			fmt.Fprintf(writer, "[FAIL] %s - %v\n", result.Message(), result.Error())
		}
	}
	fmt.Fprintf(writer, "check finished\n")
	return err
}
<commit_msg>add logger close on error<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"os"

	"github.com/bborbe/log"
	"github.com/bborbe/monitoring/configuration"
	"github.com/bborbe/monitoring/runner"
	"github.com/bborbe/monitoring/runner/all"
	"github.com/bborbe/monitoring/runner/hierarchy"
)

var logger = log.DefaultLogger

func main() {
	defer logger.Close()
	logLevelPtr := flag.String("loglevel", log.LogLevelToString(log.ERROR), "one of OFF,TRACE,DEBUG,INFO,WARN,ERROR")
	modePtr := flag.String("mode", "", "mode (all|hierachy)")
	flag.Parse()
	logger.SetLevelThreshold(log.LogStringToLevel(*logLevelPtr))
	logger.Debugf("set log level to %s", *logLevelPtr)

	var r runner.Runner
	if "all" == *modePtr {
		logger.Debug("runner = all")
		r = all.New()
	} else {
		logger.Debug("runner = hierarchy")
		r = hierarchy.New()
	}
	c := configuration.New()
	writer := os.Stdout
	err := do(writer, r, c)
	if err != nil {
		logger.Fatal(err)
		logger.Close()
		os.Exit(1)
	}
	logger.Debug("done")
}

func do(writer io.Writer, r runner.Runner, c configuration.Configuration) error {
	var err error
	fmt.Fprintf(writer, "check started\n")
	results := r.Run(c)
	for result := range results {
		if result.Success() {
			fmt.Fprintf(writer, "[OK]   %s\n", result.Message())
		} else {
			fmt.Fprintf(writer, "[FAIL] %s - %v\n", result.Message(), result.Error())
		}
	}
	fmt.Fprintf(writer, "check finished\n")
	return err
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package fft

import (
	"math"
	"testing"

	"github.com/mjibson/go-dsp/dsputils"
)

const (
	sqrt2_2 = math.Sqrt2 / 2
)

type fftTest struct {
	in  []float64
	out []complex128
}

var fftTests = []fftTest{
	// impulse responses
	fftTest{
		[]float64{1},
		[]complex128{complex(1, 0)},
	},
	fftTest{
		[]float64{1, 0},
		[]complex128{complex(1, 0), complex(1, 0)},
	},
	fftTest{
		[]float64{1, 0, 0, 0},
		[]complex128{complex(1, 0), complex(1, 0), complex(1, 0), complex(1, 0)},
	},
	fftTest{
		[]float64{1, 0, 0, 0, 0, 0, 0, 0},
		[]complex128{
			complex(1, 0),
			complex(1, 0),
			complex(1, 0),
			complex(1, 0),
			complex(1, 0),
			complex(1, 0),
			complex(1, 0),
			complex(1, 0)},
	},

	// shifted impulse response
	fftTest{
		[]float64{0, 1},
		[]complex128{complex(1, 0), complex(-1, 0)},
	},
	fftTest{
		[]float64{0, 1, 0, 0},
		[]complex128{complex(1, 0), complex(0, -1), complex(-1, 0), complex(0, 1)},
	},
	fftTest{
		[]float64{0, 1, 0, 0, 0, 0, 0, 0},
		[]complex128{
			complex(1, 0),
			complex(sqrt2_2, -sqrt2_2),
			complex(0, -1),
			complex(-sqrt2_2, -sqrt2_2),
			complex(-1, 0),
			complex(-sqrt2_2, sqrt2_2),
			complex(0, 1),
			complex(sqrt2_2, sqrt2_2)},
	},

	// other
	fftTest{
		[]float64{1, 2, 3, 4},
		[]complex128{
			complex(10, 0),
			complex(-2, 2),
			complex(-2, 0),
			complex(-2, -2)},
	},
	fftTest{
		[]float64{1, 3, 5, 7},
		[]complex128{
			complex(16, 0),
			complex(-4, 4),
			complex(-4, 0),
			complex(-4, -4)},
	},
	fftTest{
		[]float64{1, 2, 3, 4, 5, 6, 7, 8},
		[]complex128{
			complex(36, 0),
			complex(-4, 9.65685425),
			complex(-4, 4),
			complex(-4, 1.65685425),
			complex(-4, 0),
			complex(-4, -1.65685425),
			complex(-4, -4),
			complex(-4, -9.65685425)},
	},

	// non power of 2 lengths
	fftTest{
		[]float64{1, 0, 0, 0, 0},
		[]complex128{
			complex(1, 0),
			complex(1, 0),
			complex(1, 0),
			complex(1, 0),
			complex(1, 0)},
	},
	fftTest{
		[]float64{1, 2, 3},
		[]complex128{
			complex(6, 0),
			complex(-1.5, 0.8660254),
			complex(-1.5, -0.8660254)},
	},
	fftTest{
		[]float64{1, 1, 1},
		[]complex128{
			complex(3, 0),
			complex(0, 0),
			complex(0, 0)},
	},
}

type fft2Test struct {
	in  [][]float64
	out [][]complex128
}

var fft2Tests = []fft2Test{
	fft2Test{
		[][]float64{{1, 2, 3}, {3, 4, 5}},
		[][]complex128{
			{complex(18, 0), complex(-3, 1.73205081), complex(-3, -1.73205081)},
			{complex(-6, 0), complex(0, 0), complex(0, 0)}},
	},
	fft2Test{
		[][]float64{{0.1, 0.2, 0.3, 0.4, 0.5}, {1, 2, 3, 4, 5}, {3, 2, 1, 0, -1}},
		[][]complex128{
			{complex(21.5, 0), complex(-0.25, 0.34409548), complex(-0.25, 0.08122992), complex(-0.25, -0.08122992), complex(-0.25, -0.34409548)},
			{complex(-8.5, -8.66025404), complex(5.70990854, 4.6742225), complex(1.15694356, 4.41135694), complex(-1.65694356, 4.24889709), complex(-6.20990854, 3.98603154)},
			{complex(-8.5, 8.66025404), complex(-6.20990854, -3.98603154), complex(-1.65694356, -4.24889709), complex(1.15694356, -4.41135694), complex(5.70990854, -4.6742225)}},
	},
}

type fftnTest struct {
	in  []float64
	dim []int
	out []complex128
}

var fftnTests = []fftnTest{
	fftnTest{
		[]float64{4, 2, 3, 8, 5, 6, 7, 2, 13, 24, 13, 17},
		[]int{2, 2, 3},
		[]complex128{
			complex(104, 0), complex(12.5, 14.72243186), complex(12.5, -14.72243186),
			complex(-42, 0), complex(-10.5, 6.06217783), complex(-10.5, -6.06217783),

			complex(-48, 0), complex(-4.5, -11.25833025), complex(-4.5, 11.25833025),
			complex(22, 0), complex(8.5, -6.06217783), complex(8.5, 6.06217783)},
	},
}

type reverseBitsTest struct {
	in  uint
	sz  uint
	out uint
}

var reverseBitsTests = []reverseBitsTest{
	reverseBitsTest{0, 1, 0},
	reverseBitsTest{1, 2, 2},
	reverseBitsTest{1, 4, 8},
	reverseBitsTest{2, 4, 4},
	reverseBitsTest{3, 4, 12},
}

func TestFFT(t *testing.T) {
	for _, ft := range fftTests {
		v := FFTReal(ft.in)
		if !dsputils.PrettyCloseC(v, ft.out) {
			t.Error("FFT error\ninput:", ft.in, "\noutput:", v, "\nexpected:", ft.out)
		}

		vi := IFFT(ft.out)
		if !dsputils.PrettyCloseC(vi, dsputils.ToComplex(ft.in)) {
			t.Error("IFFT error\ninput:", ft.out, "\noutput:", vi, "\nexpected:", dsputils.ToComplex(ft.in))
		}
	}
}

func TestFFT2(t *testing.T) {
	for _, ft := range fft2Tests {
		v := FFT2Real(ft.in)
		if !dsputils.PrettyClose2(v, ft.out) {
			t.Error("FFT2 error\ninput:", ft.in, "\noutput:", v, "\nexpected:", ft.out)
		}

		vi := IFFT2(ft.out)
		if !dsputils.PrettyClose2(vi, dsputils.ToComplex2(ft.in)) {
			t.Error("IFFT2 error\ninput:", ft.out, "\noutput:", vi, "\nexpected:", dsputils.ToComplex2(ft.in))
		}
	}
}

func TestFFTN(t *testing.T) {
	for _, ft := range fftnTests {
		m := dsputils.MakeMatrix(dsputils.ToComplex(ft.in), ft.dim)
		o := dsputils.MakeMatrix(ft.out, ft.dim)
		v := FFTN(m)
		if !v.PrettyClose(o) {
			t.Error("FFTN error\ninput:", m, "\noutput:", v, "\nexpected:", o)
		}

		vi := IFFTN(o)
		if !vi.PrettyClose(m) {
			t.Error("IFFTN error\ninput:", o, "\noutput:", vi, "\nexpected:", m)
		}
	}
}

func BenchmarkFFT(b *testing.B) {
	b.StopTimer()

	N := 1 << 15
	a := make([]complex128, N)
	for i := 0; i < N; i++ {
		a[i] = complex(float64(i)/float64(N), 0)
	}

	getRadix2Factors(N)

	b.StartTimer()

	for i := 0; i < b.N; i++ {
		FFT(a)
	}
}

func TestReverseBits(t *testing.T) {
	for _, rt := range reverseBitsTests {
		v := reverseBits(rt.in, rt.sz)

		if v != rt.out {
			t.Error("reverse bits error\ninput:", rt.in, "\nsize:", rt.sz, "\noutput:", v, "\nexpected:", rt.out)
		}
	}
}
<commit_msg>Document how to run the benchmark - I always forget<commit_after>/*
 * Copyright (c) 2011 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package fft

import (
	"math"
	"testing"

	"github.com/mjibson/go-dsp/dsputils"
)

const (
	sqrt2_2 = math.Sqrt2 / 2
)

type fftTest struct {
	in  []float64
	out []complex128
}

var fftTests = []fftTest{
	// impulse responses
	fftTest{
		[]float64{1},
		[]complex128{complex(1, 0)},
	},
	fftTest{
		[]float64{1, 0},
		[]complex128{complex(1, 0), complex(1, 0)},
	},
	fftTest{
		[]float64{1, 0, 0, 0},
		[]complex128{complex(1, 0), complex(1, 0), complex(1, 0), complex(1, 0)},
	},
	fftTest{
		[]float64{1, 0, 0, 0, 0, 0, 0, 0},
		[]complex128{
			complex(1, 0),
			complex(1, 0),
			complex(1, 0),
			complex(1, 0),
			complex(1, 0),
			complex(1, 0),
			complex(1, 0),
			complex(1, 0)},
	},

	// shifted impulse response
	fftTest{
		[]float64{0, 1},
		[]complex128{complex(1, 0), complex(-1, 0)},
	},
	fftTest{
		[]float64{0, 1, 0, 0},
		[]complex128{complex(1, 0), complex(0, -1), complex(-1, 0), complex(0, 1)},
	},
	fftTest{
		[]float64{0, 1, 0, 0, 0, 0, 0, 0},
		[]complex128{
			complex(1, 0),
			complex(sqrt2_2, -sqrt2_2),
			complex(0, -1),
			complex(-sqrt2_2, -sqrt2_2),
			complex(-1, 0),
			complex(-sqrt2_2, sqrt2_2),
			complex(0, 1),
			complex(sqrt2_2, sqrt2_2)},
	},

	// other
	fftTest{
		[]float64{1, 2, 3, 4},
		[]complex128{
			complex(10, 0),
			complex(-2, 2),
			complex(-2, 0),
			complex(-2, -2)},
	},
	fftTest{
		[]float64{1, 3, 5, 7},
		[]complex128{
			complex(16, 0),
			complex(-4, 4),
			complex(-4, 0),
			complex(-4, -4)},
	},
	fftTest{
		[]float64{1, 2, 3, 4, 5, 6, 7, 8},
		[]complex128{
			complex(36, 0),
			complex(-4, 9.65685425),
			complex(-4, 4),
			complex(-4, 1.65685425),
			complex(-4, 0),
			complex(-4, -1.65685425),
			complex(-4, -4),
			complex(-4, -9.65685425)},
	},

	// non power of 2 lengths
	fftTest{
		[]float64{1, 0, 0, 0, 0},
		[]complex128{
			complex(1, 0),
			complex(1, 0),
			complex(1, 0),
			complex(1, 0),
			complex(1, 0)},
	},
	fftTest{
		[]float64{1, 2, 3},
		[]complex128{
			complex(6, 0),
			complex(-1.5, 0.8660254),
			complex(-1.5, -0.8660254)},
	},
	fftTest{
		[]float64{1, 1, 1},
		[]complex128{
			complex(3, 0),
			complex(0, 0),
			complex(0, 0)},
	},
}

type fft2Test struct {
	in  [][]float64
	out [][]complex128
}

var fft2Tests = []fft2Test{
	fft2Test{
		[][]float64{{1, 2, 3}, {3, 4, 5}},
		[][]complex128{
			{complex(18, 0), complex(-3, 1.73205081), complex(-3, -1.73205081)},
			{complex(-6, 0), complex(0, 0), complex(0, 0)}},
	},
	fft2Test{
		[][]float64{{0.1, 0.2, 0.3, 0.4, 0.5}, {1, 2, 3, 4, 5}, {3, 2, 1, 0, -1}},
		[][]complex128{
			{complex(21.5, 0), complex(-0.25, 0.34409548), complex(-0.25, 0.08122992), complex(-0.25, -0.08122992), complex(-0.25, -0.34409548)},
			{complex(-8.5, -8.66025404), complex(5.70990854, 4.6742225), complex(1.15694356, 4.41135694), complex(-1.65694356, 4.24889709), complex(-6.20990854, 3.98603154)},
			{complex(-8.5, 8.66025404), complex(-6.20990854, -3.98603154), complex(-1.65694356, -4.24889709), complex(1.15694356, -4.41135694), complex(5.70990854, -4.6742225)}},
	},
}

type fftnTest struct {
	in  []float64
	dim []int
	out []complex128
}

var fftnTests = []fftnTest{
	fftnTest{
		[]float64{4, 2, 3, 8, 5, 6, 7, 2, 13, 24, 13, 17},
		[]int{2, 2, 3},
		[]complex128{
			complex(104, 0), complex(12.5, 14.72243186), complex(12.5, -14.72243186),
			complex(-42, 0), complex(-10.5, 6.06217783), complex(-10.5, -6.06217783),

			complex(-48, 0), complex(-4.5, -11.25833025), complex(-4.5, 11.25833025),
			complex(22, 0), complex(8.5, -6.06217783), complex(8.5, 6.06217783)},
	},
}

type reverseBitsTest struct {
	in  uint
	sz  uint
	out uint
}

var reverseBitsTests = []reverseBitsTest{
	reverseBitsTest{0, 1, 0},
	reverseBitsTest{1, 2, 2},
	reverseBitsTest{1, 4, 8},
	reverseBitsTest{2, 4, 4},
	reverseBitsTest{3, 4, 12},
}

func TestFFT(t *testing.T) {
	for _, ft := range fftTests {
		v := FFTReal(ft.in)
		if !dsputils.PrettyCloseC(v, ft.out) {
			t.Error("FFT error\ninput:", ft.in, "\noutput:", v, "\nexpected:", ft.out)
		}

		vi := IFFT(ft.out)
		if !dsputils.PrettyCloseC(vi, dsputils.ToComplex(ft.in)) {
			t.Error("IFFT error\ninput:", ft.out, "\noutput:", vi, "\nexpected:", dsputils.ToComplex(ft.in))
		}
	}
}

func TestFFT2(t *testing.T) {
	for _, ft := range fft2Tests {
		v := FFT2Real(ft.in)
		if !dsputils.PrettyClose2(v, ft.out) {
			t.Error("FFT2 error\ninput:", ft.in, "\noutput:", v, "\nexpected:", ft.out)
		}

		vi := IFFT2(ft.out)
		if !dsputils.PrettyClose2(vi, dsputils.ToComplex2(ft.in)) {
			t.Error("IFFT2 error\ninput:", ft.out, "\noutput:", vi, "\nexpected:", dsputils.ToComplex2(ft.in))
		}
	}
}

func TestFFTN(t *testing.T) {
	for _, ft := range fftnTests {
		m := dsputils.MakeMatrix(dsputils.ToComplex(ft.in), ft.dim)
		o := dsputils.MakeMatrix(ft.out, ft.dim)
		v := FFTN(m)
		if !v.PrettyClose(o) {
			t.Error("FFTN error\ninput:", m, "\noutput:", v, "\nexpected:", o)
		}

		vi := IFFTN(o)
		if !vi.PrettyClose(m) {
			t.Error("IFFTN error\ninput:", o, "\noutput:", vi, "\nexpected:", m)
		}
	}
}

// run with: go test -test.bench="."
func BenchmarkFFT(b *testing.B) {
	b.StopTimer()

	N := 1 << 15
	a := make([]complex128, N)
	for i := 0; i < N; i++ {
		a[i] = complex(float64(i)/float64(N), 0)
	}

	getRadix2Factors(N)

	b.StartTimer()

	for i := 0; i < b.N; i++ {
		FFT(a)
	}
}

func TestReverseBits(t *testing.T) {
	for _, rt := range reverseBitsTests {
		v := reverseBits(rt.in, rt.sz)

		if v != rt.out {
			t.Error("reverse bits error\ninput:", rt.in, "\nsize:", rt.sz, "\noutput:", v, "\nexpected:", rt.out)
		}
	}
}
<|endoftext|>


<commit_before>package file

import (
	"fmt"
	"regexp"
	"strconv"
)

var appVersion = "1.0.0"

// GetAppVersion return app version
func GetAppVersion() string {
	return appVersion
}

// getAppDbVersion return app version recorded in database
func getAppDbVersion() (string, error) {
	var version string

	res, err := db.Query("select id from version")

	if err != nil {
		return "", fmt.Errorf("Can't retrieve database app version")
	}

	res.Next()

	err = res.Scan(&version)

	return version, err
}

// HasMajorVersionEqualFrom check if major version in given version is equal to app version
func HasMajorVersionEqualFrom() (bool, error) {
	re := regexp.MustCompile(`^(\d)\.(\d)\.(\d)(?:(?:\-|\+).*)?`)

	dbVer, err := getAppDbVersion()

	if err != nil {
		return false, err
	}

	dbVerComp := re.FindStringSubmatch(dbVer)
	appVerComp := re.FindStringSubmatch(appVersion)

	if len(dbVerComp) != 4 {
		return false, fmt.Errorf("Wrong version format : %s, must follows semver", dbVer)
	}

	appVerMajor, err := strconv.Atoi(appVerComp[1])

	if err != nil {
		return false, err
	}

	verMajor, err := strconv.Atoi(dbVerComp[1])

	if err != nil {
		return false, err
	}

	if verMajor == appVerMajor {
		return true, nil
	}

	return false, fmt.Errorf("Database version : %s and app version : %s don't have same major version", dbVer, appVersion)
}
<commit_msg>feat(version) : 2.0.0<commit_after>package file

import (
	"fmt"
	"regexp"
	"strconv"
)

var appVersion = "2.0.0"

// GetAppVersion return app version
func GetAppVersion() string {
	return appVersion
}

// getAppDbVersion return app version recorded in database
func getAppDbVersion() (string, error) {
	var version string

	res, err := db.Query("select id from version")

	if err != nil {
		return "", fmt.Errorf("Can't retrieve database app version")
	}

	res.Next()

	err = res.Scan(&version)

	return version, err
}

// HasMajorVersionEqualFrom check if major version in given version is equal to app version
func HasMajorVersionEqualFrom() (bool, error) {
	re := regexp.MustCompile(`^(\d)\.(\d)\.(\d)(?:(?:\-|\+).*)?`)

	dbVer, err := getAppDbVersion()

	if err != nil {
		return false, err
	}

	dbVerComp := re.FindStringSubmatch(dbVer)
	appVerComp := re.FindStringSubmatch(appVersion)

	if len(dbVerComp) != 4 {
		return false, fmt.Errorf("Wrong version format : %s, must follows semver", dbVer)
	}

	appVerMajor, err := strconv.Atoi(appVerComp[1])

	if err != nil {
		return false, err
	}

	verMajor, err := strconv.Atoi(dbVerComp[1])

	if err != nil {
		return false, err
	}

	if verMajor == appVerMajor {
		return true, nil
	}

	return false, fmt.Errorf("Database version : %s and app version : %s don't have same major version", dbVer, appVersion)
}
<|endoftext|>


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

package main

import (
	"bytes"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"
)

// A Dir describes a directory holding code by specifying
// the expected import path and the file system directory.
type Dir struct {
	importPath string // import path for that dir
	dir        string // file system directory
}

// Dirs is a structure for scanning the directory tree.
// Its Next method returns the next Go source directory it finds.
// Although it can be used to scan the tree multiple times, it
// only walks the tree once, caching the data it finds.
type Dirs struct {
	scan   chan Dir // Directories generated by walk.
	hist   []Dir    // History of reported Dirs.
	offset int      // Counter for Next.
}

var dirs Dirs

// dirsInit starts the scanning of package directories in GOROOT and GOPATH. Any
// extra paths passed to it are included in the channel.
func dirsInit(extra ...Dir) {
	dirs.hist = make([]Dir, 0, 1000)
	dirs.hist = append(dirs.hist, extra...)
	dirs.scan = make(chan Dir)
	go dirs.walk(codeRoots())
}

// Reset puts the scan back at the beginning.
func (d *Dirs) Reset() {
	d.offset = 0
}

// Next returns the next directory in the scan. The boolean
// is false when the scan is done.
func (d *Dirs) Next() (Dir, bool) {
	if d.offset < len(d.hist) {
		dir := d.hist[d.offset]
		d.offset++
		return dir, true
	}
	dir, ok := <-d.scan
	if !ok {
		return Dir{}, false
	}
	d.hist = append(d.hist, dir)
	d.offset++
	return dir, ok
}

// walk walks the trees in GOROOT and GOPATH.
func (d *Dirs) walk(roots []Dir) {
	for _, root := range roots {
		d.bfsWalkRoot(root)
	}
	close(d.scan)
}

// bfsWalkRoot walks a single directory hierarchy in breadth-first lexical order.
// Each Go source directory it finds is delivered on d.scan.
func (d *Dirs) bfsWalkRoot(root Dir) {
	root.dir = filepath.Clean(root.dir) // because filepath.Join will do it anyway

	// this is the queue of directories to examine in this pass.
	this := []string{}
	// next is the queue of directories to examine in the next pass.
	next := []string{root.dir}

	for len(next) > 0 {
		this, next = next, this[0:0]
		for _, dir := range this {
			fd, err := os.Open(dir)
			if err != nil {
				log.Print(err)
				continue
			}
			entries, err := fd.Readdir(0)
			fd.Close()
			if err != nil {
				log.Print(err)
				continue
			}
			hasGoFiles := false
			for _, entry := range entries {
				name := entry.Name()
				// For plain files, remember if this directory contains any .go
				// source files, but ignore them otherwise.
				if !entry.IsDir() {
					if !hasGoFiles && strings.HasSuffix(name, ".go") {
						hasGoFiles = true
					}
					continue
				}
				// Entry is a directory.

				// The go tool ignores directories starting with ., _, or named "testdata".
				if name[0] == '.' || name[0] == '_' || name == "testdata" {
					continue
				}
				// Ignore vendor when using modules.
				if usingModules && name == "vendor" {
					continue
				}
				// Remember this (fully qualified) directory for the next pass.
				next = append(next, filepath.Join(dir, name))
			}
			if hasGoFiles {
				// It's a candidate.
				importPath := root.importPath
				if len(dir) > len(root.dir) {
					if importPath != "" {
						importPath += "/"
					}
					importPath += filepath.ToSlash(dir[len(root.dir)+1:])
				}
				d.scan <- Dir{importPath, dir}
			}
		}

	}
}

var testGOPATH = false // force GOPATH use for testing

// codeRoots returns the code roots to search for packages.
// In GOPATH mode this is GOROOT/src and GOPATH/src, with empty import paths.
// In module mode, this is each module root, with an import path set to its module path.
func codeRoots() []Dir {
	codeRootsCache.once.Do(func() {
		codeRootsCache.roots = findCodeRoots()
	})
	return codeRootsCache.roots
}

var codeRootsCache struct {
	once  sync.Once
	roots []Dir
}

var usingModules bool

func findCodeRoots() []Dir {
	list := []Dir{{"", filepath.Join(buildCtx.GOROOT, "src")}}

	if !testGOPATH {
		// Check for use of modules by 'go env GOMOD',
		// which reports a go.mod file path if modules are enabled.
		stdout, _ := exec.Command("go", "env", "GOMOD").Output()
		usingModules = bytes.Contains(stdout, []byte("go.mod"))
	}

	if !usingModules {
		for _, root := range splitGopath() {
			list = append(list, Dir{"", filepath.Join(root, "src")})
		}
		return list
	}

	// Find module root directories from go list.
	// Eventually we want golang.org/x/tools/go/packages
	// to handle the entire file system search and become go/packages,
	// but for now enumerating the module roots lets us fit modules
	// into the current code with as few changes as possible.
	cmd := exec.Command("go", "list", "-m", "-f={{.Path}}\t{{.Dir}}", "all")
	cmd.Stderr = os.Stderr
	out, _ := cmd.Output()
	for _, line := range strings.Split(string(out), "\n") {
		i := strings.Index(line, "\t")
		if i < 0 {
			continue
		}
		path, dir := line[:i], line[i+1:]
		if dir != "" {
			list = append(list, Dir{path, dir})
		}
	}

	return list
}
<commit_msg>cmd/doc: treat any non-empty GOMOD as module mode<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"
)

// A Dir describes a directory holding code by specifying
// the expected import path and the file system directory.
type Dir struct {
	importPath string // import path for that dir
	dir        string // file system directory
}

// Dirs is a structure for scanning the directory tree.
// Its Next method returns the next Go source directory it finds.
// Although it can be used to scan the tree multiple times, it
// only walks the tree once, caching the data it finds.
type Dirs struct {
	scan   chan Dir // Directories generated by walk.
	hist   []Dir    // History of reported Dirs.
	offset int      // Counter for Next.
}

var dirs Dirs

// dirsInit starts the scanning of package directories in GOROOT and GOPATH. Any
// extra paths passed to it are included in the channel.
func dirsInit(extra ...Dir) {
	dirs.hist = make([]Dir, 0, 1000)
	dirs.hist = append(dirs.hist, extra...)
	dirs.scan = make(chan Dir)
	go dirs.walk(codeRoots())
}

// Reset puts the scan back at the beginning.
func (d *Dirs) Reset() {
	d.offset = 0
}

// Next returns the next directory in the scan. The boolean
// is false when the scan is done.
func (d *Dirs) Next() (Dir, bool) {
	if d.offset < len(d.hist) {
		dir := d.hist[d.offset]
		d.offset++
		return dir, true
	}
	dir, ok := <-d.scan
	if !ok {
		return Dir{}, false
	}
	d.hist = append(d.hist, dir)
	d.offset++
	return dir, ok
}

// walk walks the trees in GOROOT and GOPATH.
func (d *Dirs) walk(roots []Dir) {
	for _, root := range roots {
		d.bfsWalkRoot(root)
	}
	close(d.scan)
}

// bfsWalkRoot walks a single directory hierarchy in breadth-first lexical order.
// Each Go source directory it finds is delivered on d.scan.
func (d *Dirs) bfsWalkRoot(root Dir) {
	root.dir = filepath.Clean(root.dir) // because filepath.Join will do it anyway

	// this is the queue of directories to examine in this pass.
	this := []string{}
	// next is the queue of directories to examine in the next pass.
	next := []string{root.dir}

	for len(next) > 0 {
		this, next = next, this[0:0]
		for _, dir := range this {
			fd, err := os.Open(dir)
			if err != nil {
				log.Print(err)
				continue
			}
			entries, err := fd.Readdir(0)
			fd.Close()
			if err != nil {
				log.Print(err)
				continue
			}
			hasGoFiles := false
			for _, entry := range entries {
				name := entry.Name()
				// For plain files, remember if this directory contains any .go
				// source files, but ignore them otherwise.
				if !entry.IsDir() {
					if !hasGoFiles && strings.HasSuffix(name, ".go") {
						hasGoFiles = true
					}
					continue
				}
				// Entry is a directory.

				// The go tool ignores directories starting with ., _, or named "testdata".
				if name[0] == '.' || name[0] == '_' || name == "testdata" {
					continue
				}
				// Ignore vendor when using modules.
				if usingModules && name == "vendor" {
					continue
				}
				// Remember this (fully qualified) directory for the next pass.
				next = append(next, filepath.Join(dir, name))
			}
			if hasGoFiles {
				// It's a candidate.
				importPath := root.importPath
				if len(dir) > len(root.dir) {
					if importPath != "" {
						importPath += "/"
					}
					importPath += filepath.ToSlash(dir[len(root.dir)+1:])
				}
				d.scan <- Dir{importPath, dir}
			}
		}

	}
}

var testGOPATH = false // force GOPATH use for testing

// codeRoots returns the code roots to search for packages.
// In GOPATH mode this is GOROOT/src and GOPATH/src, with empty import paths.
// In module mode, this is each module root, with an import path set to its module path.
func codeRoots() []Dir {
	codeRootsCache.once.Do(func() {
		codeRootsCache.roots = findCodeRoots()
	})
	return codeRootsCache.roots
}

var codeRootsCache struct {
	once  sync.Once
	roots []Dir
}

var usingModules bool

func findCodeRoots() []Dir {
	list := []Dir{{"", filepath.Join(buildCtx.GOROOT, "src")}}

	if !testGOPATH {
		// Check for use of modules by 'go env GOMOD',
		// which reports a go.mod file path if modules are enabled.
		stdout, _ := exec.Command("go", "env", "GOMOD").Output()
		usingModules = len(bytes.TrimSpace(stdout)) > 0
	}

	if !usingModules {
		for _, root := range splitGopath() {
			list = append(list, Dir{"", filepath.Join(root, "src")})
		}
		return list
	}

	// Find module root directories from go list.
	// Eventually we want golang.org/x/tools/go/packages
	// to handle the entire file system search and become go/packages,
	// but for now enumerating the module roots lets us fit modules
	// into the current code with as few changes as possible.
	cmd := exec.Command("go", "list", "-m", "-f={{.Path}}\t{{.Dir}}", "all")
	cmd.Stderr = os.Stderr
	out, _ := cmd.Output()
	for _, line := range strings.Split(string(out), "\n") {
		i := strings.Index(line, "\t")
		if i < 0 {
			continue
		}
		path, dir := line[:i], line[i+1:]
		if dir != "" {
			list = append(list, Dir{path, dir})
		}
	}

	return list
}
<|endoftext|>


<commit_before>package flatten

import (
	"encoding/json"
	"reflect"
	"strings"
	"testing"
	"unicode"
)

func TestFlatten(t *testing.T) {
	cases := []struct {
		test   string
		want   map[string]interface{}
		prefix string
		style  SeparatorStyle
	}{
		{
			`{
				"foo": {
					"jim":"bean"
				},
				"fee": "bar",
				"n1": {
					"alist": [
						"a",
						"b",
						"c",
						{
							"d": "other",
							"e": "another"
						}
					]
				},
				"number": 1.4567,
				"bool":   true
			}`,
			map[string]interface{}{
				"foo.jim":      "bean",
				"fee":          "bar",
				"n1.alist.0":   "a",
				"n1.alist.1":   "b",
				"n1.alist.2":   "c",
				"n1.alist.3.d": "other",
				"n1.alist.3.e": "another",
				"number":       1.4567,
				"bool":         true,
			},
			"",
			DOT_STYLE,
		},
		{
			`{
				"foo": {
					"jim":"bean"
				},
				"fee": "bar",
				"n1": {
					"alist": [
					"a",
					"b",
					"c",
					{
						"d": "other",
						"e": "another"
					}
					]
				}
			}`,
			map[string]interface{}{
				"foo[jim]":        "bean",
				"fee":             "bar",
				"n1[alist][0]":    "a",
				"n1[alist][1]":    "b",
				"n1[alist][2]":    "c",
				"n1[alist][3][d]": "other",
				"n1[alist][3][e]": "another",
			},
			"",
			RAILS_STYLE,
		},
		{
			`{ "a": { "b": "c" }, "e": "f" }`,
			map[string]interface{}{
				"p:a.b": "c",
				"p:e":   "f",
			},
			"p:",
			DOT_STYLE,
		},
	}

	for i, test := range cases {
		var m interface{}
		err := json.Unmarshal([]byte(test.test), &m)
		if err != nil {
			t.Errorf("%d: failed to unmarshal test: %v", i+1, err)
		}
		got, err := Flatten(m.(map[string]interface{}), test.prefix, test.style)
		if err != nil {
			t.Errorf("%d: failed to flatten: %v", i+1, err)
		}
		if !reflect.DeepEqual(got, test.want) {
			t.Errorf("%d: mismatch, got: %v want: %v", i+1, got, test.want)
		}
	}
}

func TestFlattenString(t *testing.T) {
	cases := []struct {
		test   string
		want   string
		prefix string
		style  SeparatorStyle
	}{
		{
			`{ "a": "b" }`,
			`{ "a": "b" }`,
			"",
			DOT_STYLE,
		},
		{
			`{ "number": 1.4567, "bool": true, "a": { "b" : { "c" : { "d" : "e" } } } }`,
			`{ "number": 1.4567, "bool": true, "a.b.c.d": "e" }`,
			"",
			DOT_STYLE,
		},
	}

	for i, test := range cases {
		got, err := FlattenString(test.test, test.prefix, test.style)
		if err != nil {
			t.Errorf("%d: failed to flatten: %v", i+1, err)
		}

		nixws := func(r rune) rune {
			if unicode.IsSpace(r) {
				return -1
			}
			return r
		}

		if got != strings.Map(nixws, test.want) {
			t.Errorf("%d: mismatch, got: %v want: %v", i+1, got, test.want)
		}
	}
}
<commit_msg>Order test for lexicographic marshal ordering.<commit_after>package flatten

import (
	"encoding/json"
	"reflect"
	"strings"
	"testing"
	"unicode"
)

func TestFlatten(t *testing.T) {
	cases := []struct {
		test   string
		want   map[string]interface{}
		prefix string
		style  SeparatorStyle
	}{
		{
			`{
				"foo": {
					"jim":"bean"
				},
				"fee": "bar",
				"n1": {
					"alist": [
						"a",
						"b",
						"c",
						{
							"d": "other",
							"e": "another"
						}
					]
				},
				"number": 1.4567,
				"bool":   true
			}`,
			map[string]interface{}{
				"foo.jim":      "bean",
				"fee":          "bar",
				"n1.alist.0":   "a",
				"n1.alist.1":   "b",
				"n1.alist.2":   "c",
				"n1.alist.3.d": "other",
				"n1.alist.3.e": "another",
				"number":       1.4567,
				"bool":         true,
			},
			"",
			DOT_STYLE,
		},
		{
			`{
				"foo": {
					"jim":"bean"
				},
				"fee": "bar",
				"n1": {
					"alist": [
					"a",
					"b",
					"c",
					{
						"d": "other",
						"e": "another"
					}
					]
				}
			}`,
			map[string]interface{}{
				"foo[jim]":        "bean",
				"fee":             "bar",
				"n1[alist][0]":    "a",
				"n1[alist][1]":    "b",
				"n1[alist][2]":    "c",
				"n1[alist][3][d]": "other",
				"n1[alist][3][e]": "another",
			},
			"",
			RAILS_STYLE,
		},
		{
			`{ "a": { "b": "c" }, "e": "f" }`,
			map[string]interface{}{
				"p:a.b": "c",
				"p:e":   "f",
			},
			"p:",
			DOT_STYLE,
		},
	}

	for i, test := range cases {
		var m interface{}
		err := json.Unmarshal([]byte(test.test), &m)
		if err != nil {
			t.Errorf("%d: failed to unmarshal test: %v", i+1, err)
		}
		got, err := Flatten(m.(map[string]interface{}), test.prefix, test.style)
		if err != nil {
			t.Errorf("%d: failed to flatten: %v", i+1, err)
		}
		if !reflect.DeepEqual(got, test.want) {
			t.Errorf("%d: mismatch, got: %v want: %v", i+1, got, test.want)
		}
	}
}

func TestFlattenString(t *testing.T) {
	cases := []struct {
		test   string
		want   string
		prefix string
		style  SeparatorStyle
	}{
		{
			`{ "a": "b" }`,
			`{ "a": "b" }`,
			"",
			DOT_STYLE,
		},
		{
			`{ "a": { "b" : { "c" : { "d" : "e" } } }, "number": 1.4567, "bool": true }`,
			`{ "a.b.c.d": "e", "bool": true, "number": 1.4567 }`,
			"",
			DOT_STYLE,
		},
	}

	for i, test := range cases {
		got, err := FlattenString(test.test, test.prefix, test.style)
		if err != nil {
			t.Errorf("%d: failed to flatten: %v", i+1, err)
		}

		nixws := func(r rune) rune {
			if unicode.IsSpace(r) {
				return -1
			}
			return r
		}

		if got != strings.Map(nixws, test.want) {
			t.Errorf("%d: mismatch, got: %v want: %v", i+1, got, test.want)
		}
	}
}
<|endoftext|>


<commit_before>/*
Package gexec provides support for testing external processes.
*/

// untested sections: 1

package gexec

import (
	"io"
	"os"
	"os/exec"
	"sync"
	"syscall"

	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
)

const INVALID_EXIT_CODE = 254

type Session struct {
	//The wrapped command
	Command *exec.Cmd

	//A *gbytes.Buffer connected to the command's stdout
	Out *gbytes.Buffer

	//A *gbytes.Buffer connected to the command's stderr
	Err *gbytes.Buffer

	//A channel that will close when the command exits
	Exited <-chan struct{}

	lock     *sync.Mutex
	exitCode int
}

/*
Start starts the passed-in *exec.Cmd command.  It wraps the command in a *gexec.Session.

The session pipes the command's stdout and stderr to two *gbytes.Buffers available as properties on the session: session.Out and session.Err.
These buffers can be used with the gbytes.Say matcher to match against unread output:

	Expect(session.Out).Should(gbytes.Say("foo-out"))
	Expect(session.Err).Should(gbytes.Say("foo-err"))

In addition, Session satisfies the gbytes.BufferProvider interface and provides the stdout *gbytes.Buffer.  This allows you to replace the first line, above, with:

	Expect(session).Should(gbytes.Say("foo-out"))

When outWriter and/or errWriter are non-nil, the session will pipe stdout and/or stderr output both into the session *gybtes.Buffers and to the passed-in outWriter/errWriter.
This is useful for capturing the process's output or logging it to screen.  In particular, when using Ginkgo it can be convenient to direct output to the GinkgoWriter:

	session, err := Start(command, GinkgoWriter, GinkgoWriter)

This will log output when running tests in verbose mode, but - otherwise - will only log output when a test fails.

The session wrapper is responsible for waiting on the *exec.Cmd command.  You *should not* call command.Wait() yourself.
Instead, to assert that the command has exited you can use the gexec.Exit matcher:

	Expect(session).Should(gexec.Exit())

When the session exits it closes the stdout and stderr gbytes buffers.  This will short circuit any
Eventuallys waiting for the buffers to Say something.
*/
func Start(command *exec.Cmd, outWriter io.Writer, errWriter io.Writer) (*Session, error) {
	exited := make(chan struct{})

	session := &Session{
		Command:  command,
		Out:      gbytes.NewBuffer(),
		Err:      gbytes.NewBuffer(),
		Exited:   exited,
		lock:     &sync.Mutex{},
		exitCode: -1,
	}

	var commandOut, commandErr io.Writer

	commandOut, commandErr = session.Out, session.Err

	if outWriter != nil {
		commandOut = io.MultiWriter(commandOut, outWriter)
	}

	if errWriter != nil {
		commandErr = io.MultiWriter(commandErr, errWriter)
	}

	command.Stdout = commandOut
	command.Stderr = commandErr

	err := command.Start()
	if err == nil {
		go session.monitorForExit(exited)
		trackedSessionsMutex.Lock()
		defer trackedSessionsMutex.Unlock()
		trackedSessions = append(trackedSessions, session)
	}

	return session, err
}

/*
Buffer implements the gbytes.BufferProvider interface and returns s.Out
This allows you to make gbytes.Say matcher assertions against stdout without having to reference .Out:

	Eventually(session).Should(gbytes.Say("foo"))
*/
func (s *Session) Buffer() *gbytes.Buffer {
	return s.Out
}

/*
ExitCode returns the wrapped command's exit code.  If the command hasn't exited yet, ExitCode returns -1.

To assert that the command has exited it is more convenient to use the Exit matcher:

	Eventually(s).Should(gexec.Exit())

When the process exits because it has received a particular signal, the exit code will be 128+signal-value
(See http://www.tldp.org/LDP/abs/html/exitcodes.html and http://man7.org/linux/man-pages/man7/signal.7.html)

*/
func (s *Session) ExitCode() int {
	s.lock.Lock()
	defer s.lock.Unlock()
	return s.exitCode
}

/*
Wait waits until the wrapped command exits.  It can be passed an optional timeout.
If the command does not exit within the timeout, Wait will trigger a test failure.

Wait returns the session, making it possible to chain:

	session.Wait().Out.Contents()

will wait for the command to exit then return the entirety of Out's contents.

Wait uses eventually under the hood and accepts the same timeout/polling intervals that eventually does.
*/
func (s *Session) Wait(timeout ...interface{}) *Session {
	EventuallyWithOffset(1, s, timeout...).Should(Exit())
	return s
}

/*
Kill sends the running command a SIGKILL signal.  It does not wait for the process to exit.

If the command has already exited, Kill returns silently.

The session is returned to enable chaining.
*/
func (s *Session) Kill() *Session {
	return s.Signal(syscall.SIGKILL)
}

/*
Interrupt sends the running command a SIGINT signal.  It does not wait for the process to exit.

If the command has already exited, Interrupt returns silently.

The session is returned to enable chaining.
*/
func (s *Session) Interrupt() *Session {
	return s.Signal(syscall.SIGINT)
}

/*
Terminate sends the running command a SIGTERM signal.  It does not wait for the process to exit.

If the command has already exited, Terminate returns silently.

The session is returned to enable chaining.
*/
func (s *Session) Terminate() *Session {
	return s.Signal(syscall.SIGTERM)
}

/*
Signal sends the running command the passed in signal.  It does not wait for the process to exit.

If the command has already exited, Signal returns silently.

The session is returned to enable chaining.
*/
func (s *Session) Signal(signal os.Signal) *Session {
	if s.processIsAlive() {
		s.Command.Process.Signal(signal)
	}
	return s
}

func (s *Session) monitorForExit(exited chan<- struct{}) {
	err := s.Command.Wait()
	s.lock.Lock()
	s.Out.Close()
	s.Err.Close()
	status := s.Command.ProcessState.Sys().(syscall.WaitStatus)
	if status.Signaled() {
		s.exitCode = 128 + int(status.Signal())
	} else {
		exitStatus := status.ExitStatus()
		if exitStatus == -1 && err != nil {
			s.exitCode = INVALID_EXIT_CODE
		}
		s.exitCode = exitStatus
	}
	s.lock.Unlock()

	close(exited)
}

func (s *Session) processIsAlive() bool {
	return s.ExitCode() == -1 && s.Command.Process != nil
}

var trackedSessions = []*Session{}
var trackedSessionsMutex = &sync.Mutex{}

/*
Kill sends a SIGKILL signal to all the processes started by Run, and waits for them to exit.
The timeout specified is applied to each process killed.

If any of the processes already exited, KillAndWait returns silently.
*/
func KillAndWait(timeout ...interface{}) {
	trackedSessionsMutex.Lock()
	defer trackedSessionsMutex.Unlock()
	for _, session := range trackedSessions {
		session.Kill().Wait(timeout...)
	}
	trackedSessions = []*Session{}
}

/*
Kill sends a SIGTERM signal to all the processes started by Run, and waits for them to exit.
The timeout specified is applied to each process killed.

If any of the processes already exited, TerminateAndWait returns silently.
*/
func TerminateAndWait(timeout ...interface{}) {
	trackedSessionsMutex.Lock()
	defer trackedSessionsMutex.Unlock()
	for _, session := range trackedSessions {
		session.Terminate().Wait(timeout...)
	}
}

/*
Kill sends a SIGKILL signal to all the processes started by Run.
It does not wait for the processes to exit.

If any of the processes already exited, Kill returns silently.
*/
func Kill() {
	trackedSessionsMutex.Lock()
	defer trackedSessionsMutex.Unlock()
	for _, session := range trackedSessions {
		session.Kill()
	}
}

/*
Terminate sends a SIGTERM signal to all the processes started by Run.
It does not wait for the processes to exit.

If any of the processes already exited, Terminate returns silently.
*/
func Terminate() {
	trackedSessionsMutex.Lock()
	defer trackedSessionsMutex.Unlock()
	for _, session := range trackedSessions {
		session.Terminate()
	}
}

/*
Signal sends the passed in signal to all the processes started by Run.
It does not wait for the processes to exit.

If any of the processes already exited, Signal returns silently.
*/
func Signal(signal os.Signal) {
	trackedSessionsMutex.Lock()
	defer trackedSessionsMutex.Unlock()
	for _, session := range trackedSessions {
		session.Signal(signal)
	}
}

/*
Interrupt sends the SIGINT signal to all the processes started by Run.
It does not wait for the processes to exit.

If any of the processes already exited, Interrupt returns silently.
*/
func Interrupt() {
	trackedSessionsMutex.Lock()
	defer trackedSessionsMutex.Unlock()
	for _, session := range trackedSessions {
		session.Interrupt()
	}
}
<commit_msg>fix broken call to Eventually<commit_after>/*
Package gexec provides support for testing external processes.
*/

// untested sections: 1

package gexec

import (
	"io"
	"os"
	"os/exec"
	"sync"
	"syscall"

	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
)

const INVALID_EXIT_CODE = 254

type Session struct {
	//The wrapped command
	Command *exec.Cmd

	//A *gbytes.Buffer connected to the command's stdout
	Out *gbytes.Buffer

	//A *gbytes.Buffer connected to the command's stderr
	Err *gbytes.Buffer

	//A channel that will close when the command exits
	Exited <-chan struct{}

	lock     *sync.Mutex
	exitCode int
}

/*
Start starts the passed-in *exec.Cmd command.  It wraps the command in a *gexec.Session.

The session pipes the command's stdout and stderr to two *gbytes.Buffers available as properties on the session: session.Out and session.Err.
These buffers can be used with the gbytes.Say matcher to match against unread output:

	Expect(session.Out).Should(gbytes.Say("foo-out"))
	Expect(session.Err).Should(gbytes.Say("foo-err"))

In addition, Session satisfies the gbytes.BufferProvider interface and provides the stdout *gbytes.Buffer.  This allows you to replace the first line, above, with:

	Expect(session).Should(gbytes.Say("foo-out"))

When outWriter and/or errWriter are non-nil, the session will pipe stdout and/or stderr output both into the session *gybtes.Buffers and to the passed-in outWriter/errWriter.
This is useful for capturing the process's output or logging it to screen.  In particular, when using Ginkgo it can be convenient to direct output to the GinkgoWriter:

	session, err := Start(command, GinkgoWriter, GinkgoWriter)

This will log output when running tests in verbose mode, but - otherwise - will only log output when a test fails.

The session wrapper is responsible for waiting on the *exec.Cmd command.  You *should not* call command.Wait() yourself.
Instead, to assert that the command has exited you can use the gexec.Exit matcher:

	Expect(session).Should(gexec.Exit())

When the session exits it closes the stdout and stderr gbytes buffers.  This will short circuit any
Eventuallys waiting for the buffers to Say something.
*/
func Start(command *exec.Cmd, outWriter io.Writer, errWriter io.Writer) (*Session, error) {
	exited := make(chan struct{})

	session := &Session{
		Command:  command,
		Out:      gbytes.NewBuffer(),
		Err:      gbytes.NewBuffer(),
		Exited:   exited,
		lock:     &sync.Mutex{},
		exitCode: -1,
	}

	var commandOut, commandErr io.Writer

	commandOut, commandErr = session.Out, session.Err

	if outWriter != nil {
		commandOut = io.MultiWriter(commandOut, outWriter)
	}

	if errWriter != nil {
		commandErr = io.MultiWriter(commandErr, errWriter)
	}

	command.Stdout = commandOut
	command.Stderr = commandErr

	err := command.Start()
	if err == nil {
		go session.monitorForExit(exited)
		trackedSessionsMutex.Lock()
		defer trackedSessionsMutex.Unlock()
		trackedSessions = append(trackedSessions, session)
	}

	return session, err
}

/*
Buffer implements the gbytes.BufferProvider interface and returns s.Out
This allows you to make gbytes.Say matcher assertions against stdout without having to reference .Out:

	Eventually(session).Should(gbytes.Say("foo"))
*/
func (s *Session) Buffer() *gbytes.Buffer {
	return s.Out
}

/*
ExitCode returns the wrapped command's exit code.  If the command hasn't exited yet, ExitCode returns -1.

To assert that the command has exited it is more convenient to use the Exit matcher:

	Eventually(s).Should(gexec.Exit())

When the process exits because it has received a particular signal, the exit code will be 128+signal-value
(See http://www.tldp.org/LDP/abs/html/exitcodes.html and http://man7.org/linux/man-pages/man7/signal.7.html)

*/
func (s *Session) ExitCode() int {
	s.lock.Lock()
	defer s.lock.Unlock()
	return s.exitCode
}

/*
Wait waits until the wrapped command exits.  It can be passed an optional timeout.
If the command does not exit within the timeout, Wait will trigger a test failure.

Wait returns the session, making it possible to chain:

	session.Wait().Out.Contents()

will wait for the command to exit then return the entirety of Out's contents.

Wait uses eventually under the hood and accepts the same timeout/polling intervals that eventually does.
*/
func (s *Session) Wait(timeout ...interface{}) *Session {
	args := []any{s}
	args = append(args, timeout...)
	EventuallyWithOffset(1, args...).Should(Exit())
	return s
}

/*
Kill sends the running command a SIGKILL signal.  It does not wait for the process to exit.

If the command has already exited, Kill returns silently.

The session is returned to enable chaining.
*/
func (s *Session) Kill() *Session {
	return s.Signal(syscall.SIGKILL)
}

/*
Interrupt sends the running command a SIGINT signal.  It does not wait for the process to exit.

If the command has already exited, Interrupt returns silently.

The session is returned to enable chaining.
*/
func (s *Session) Interrupt() *Session {
	return s.Signal(syscall.SIGINT)
}

/*
Terminate sends the running command a SIGTERM signal.  It does not wait for the process to exit.

If the command has already exited, Terminate returns silently.

The session is returned to enable chaining.
*/
func (s *Session) Terminate() *Session {
	return s.Signal(syscall.SIGTERM)
}

/*
Signal sends the running command the passed in signal.  It does not wait for the process to exit.

If the command has already exited, Signal returns silently.

The session is returned to enable chaining.
*/
func (s *Session) Signal(signal os.Signal) *Session {
	if s.processIsAlive() {
		s.Command.Process.Signal(signal)
	}
	return s
}

func (s *Session) monitorForExit(exited chan<- struct{}) {
	err := s.Command.Wait()
	s.lock.Lock()
	s.Out.Close()
	s.Err.Close()
	status := s.Command.ProcessState.Sys().(syscall.WaitStatus)
	if status.Signaled() {
		s.exitCode = 128 + int(status.Signal())
	} else {
		exitStatus := status.ExitStatus()
		if exitStatus == -1 && err != nil {
			s.exitCode = INVALID_EXIT_CODE
		}
		s.exitCode = exitStatus
	}
	s.lock.Unlock()

	close(exited)
}

func (s *Session) processIsAlive() bool {
	return s.ExitCode() == -1 && s.Command.Process != nil
}

var trackedSessions = []*Session{}
var trackedSessionsMutex = &sync.Mutex{}

/*
Kill sends a SIGKILL signal to all the processes started by Run, and waits for them to exit.
The timeout specified is applied to each process killed.

If any of the processes already exited, KillAndWait returns silently.
*/
func KillAndWait(timeout ...interface{}) {
	trackedSessionsMutex.Lock()
	defer trackedSessionsMutex.Unlock()
	for _, session := range trackedSessions {
		session.Kill().Wait(timeout...)
	}
	trackedSessions = []*Session{}
}

/*
Kill sends a SIGTERM signal to all the processes started by Run, and waits for them to exit.
The timeout specified is applied to each process killed.

If any of the processes already exited, TerminateAndWait returns silently.
*/
func TerminateAndWait(timeout ...interface{}) {
	trackedSessionsMutex.Lock()
	defer trackedSessionsMutex.Unlock()
	for _, session := range trackedSessions {
		session.Terminate().Wait(timeout...)
	}
}

/*
Kill sends a SIGKILL signal to all the processes started by Run.
It does not wait for the processes to exit.

If any of the processes already exited, Kill returns silently.
*/
func Kill() {
	trackedSessionsMutex.Lock()
	defer trackedSessionsMutex.Unlock()
	for _, session := range trackedSessions {
		session.Kill()
	}
}

/*
Terminate sends a SIGTERM signal to all the processes started by Run.
It does not wait for the processes to exit.

If any of the processes already exited, Terminate returns silently.
*/
func Terminate() {
	trackedSessionsMutex.Lock()
	defer trackedSessionsMutex.Unlock()
	for _, session := range trackedSessions {
		session.Terminate()
	}
}

/*
Signal sends the passed in signal to all the processes started by Run.
It does not wait for the processes to exit.

If any of the processes already exited, Signal returns silently.
*/
func Signal(signal os.Signal) {
	trackedSessionsMutex.Lock()
	defer trackedSessionsMutex.Unlock()
	for _, session := range trackedSessions {
		session.Signal(signal)
	}
}

/*
Interrupt sends the SIGINT signal to all the processes started by Run.
It does not wait for the processes to exit.

If any of the processes already exited, Interrupt returns silently.
*/
func Interrupt() {
	trackedSessionsMutex.Lock()
	defer trackedSessionsMutex.Unlock()
	for _, session := range trackedSessions {
		session.Interrupt()
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors 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.
*/

// git-sync is a command that pull a git repository to a local directory.

package main // import "k8s.io/contrib/git-sync"

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"strconv"
	"strings"
	"time"
)

var flRepo = flag.String("repo", envString("GIT_SYNC_REPO", ""), "git repo url")
var flBranch = flag.String("branch", envString("GIT_SYNC_BRANCH", "master"), "git branch")
var flRev = flag.String("rev", envString("GIT_SYNC_BRANCH", "HEAD"), "git rev")
var flDest = flag.String("dest", envString("GIT_SYNC_DEST", ""), "destination path")
var flWait = flag.Int("wait", envInt("GIT_SYNC_WAIT", 0), "number of seconds to wait before exit")

func envString(key, def string) string {
	if env := os.Getenv(key); env != "" {
		return env
	}
	return def
}

func envInt(key string, def int) int {
	if env := os.Getenv(key); env != "" {
		val, err := strconv.Atoi(env)
		if err != nil {
			log.Printf("invalid value for %q: using default: %q", key, def)
			return def
		}
		return val
	}
	return def
}

const usage = "usage: GIT_SYNC_REPO= GIT_SYNC_DEST= [GIT_SYNC_BRANCH= GIT_SYNC_WAIT=] git-sync -repo GIT_REPO_URL -dest PATH [-branch -wait]"

func main() {
	flag.Parse()
	if *flRepo == "" || *flDest == "" {
		flag.Usage()
		log.Fatal(usage)
	}
	if _, err := exec.LookPath("git"); err != nil {
		log.Fatalf("required git executable not found: %v", err)
	}
	for {
		if err := syncRepo(*flRepo, *flDest, *flBranch, *flRev); err != nil {
			log.Fatalf("error syncing repo: %v", err)
		}
		log.Printf("wait %d seconds", *flWait)
		time.Sleep(time.Duration(*flWait) * time.Second)
		log.Println("done")
	}
}

// syncRepo syncs the branch of a given repository to the destination at the given rev.
func syncRepo(repo, dest, branch, rev string) error {
	gitRepoPath := path.Join(dest, ".git")
	_, err := os.Stat(gitRepoPath)
	switch {
	case os.IsNotExist(err):
		// clone repo
		cmd := exec.Command("git", "clone", "--no-checkout", "-b", branch, repo, dest)
		output, err := cmd.CombinedOutput()
		if err != nil {
			return fmt.Errorf("error cloning repo %q: %v: %s", strings.Join(cmd.Args, " "), err, string(output))
		}
		log.Printf("clone %q: %s", repo, string(output))
	case err != nil:
		return fmt.Errorf("error checking if repo exist %q: %v", gitRepoPath, err)
	}

	// fetch branch
	cmd := exec.Command("git", "fetch", "origin", branch)
	cmd.Dir = dest
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("error running command %q: %v: %s", strings.Join(cmd.Args, " "), err, string(output))
	}
	log.Printf("fetch %q: %s", branch, string(output))

	// reset working copy
	cmd = exec.Command("git", "reset", "--hard", rev)
	cmd.Dir = dest
	output, err = cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("error running command %q : %v: %s", strings.Join(cmd.Args, " "), err, string(output))
	}
	log.Printf("reset %q: %v", rev, string(output))
	return nil
}
<commit_msg>Fixed incorrect environment variable<commit_after>/*
Copyright 2014 The Kubernetes Authors 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.
*/

// git-sync is a command that pull a git repository to a local directory.

package main // import "k8s.io/contrib/git-sync"

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"strconv"
	"strings"
	"time"
)

var flRepo = flag.String("repo", envString("GIT_SYNC_REPO", ""), "git repo url")
var flBranch = flag.String("branch", envString("GIT_SYNC_BRANCH", "master"), "git branch")
var flRev = flag.String("rev", envString("GIT_SYNC_REV", "HEAD"), "git rev")
var flDest = flag.String("dest", envString("GIT_SYNC_DEST", ""), "destination path")
var flWait = flag.Int("wait", envInt("GIT_SYNC_WAIT", 0), "number of seconds to wait before exit")

func envString(key, def string) string {
	if env := os.Getenv(key); env != "" {
		return env
	}
	return def
}

func envInt(key string, def int) int {
	if env := os.Getenv(key); env != "" {
		val, err := strconv.Atoi(env)
		if err != nil {
			log.Printf("invalid value for %q: using default: %q", key, def)
			return def
		}
		return val
	}
	return def
}

const usage = "usage: GIT_SYNC_REPO= GIT_SYNC_DEST= [GIT_SYNC_BRANCH= GIT_SYNC_WAIT=] git-sync -repo GIT_REPO_URL -dest PATH [-branch -wait]"

func main() {
	flag.Parse()
	if *flRepo == "" || *flDest == "" {
		flag.Usage()
		log.Fatal(usage)
	}
	if _, err := exec.LookPath("git"); err != nil {
		log.Fatalf("required git executable not found: %v", err)
	}
	for {
		if err := syncRepo(*flRepo, *flDest, *flBranch, *flRev); err != nil {
			log.Fatalf("error syncing repo: %v", err)
		}
		log.Printf("wait %d seconds", *flWait)
		time.Sleep(time.Duration(*flWait) * time.Second)
		log.Println("done")
	}
}

// syncRepo syncs the branch of a given repository to the destination at the given rev.
func syncRepo(repo, dest, branch, rev string) error {
	gitRepoPath := path.Join(dest, ".git")
	_, err := os.Stat(gitRepoPath)
	switch {
	case os.IsNotExist(err):
		// clone repo
		cmd := exec.Command("git", "clone", "--no-checkout", "-b", branch, repo, dest)
		output, err := cmd.CombinedOutput()
		if err != nil {
			return fmt.Errorf("error cloning repo %q: %v: %s", strings.Join(cmd.Args, " "), err, string(output))
		}
		log.Printf("clone %q: %s", repo, string(output))
	case err != nil:
		return fmt.Errorf("error checking if repo exist %q: %v", gitRepoPath, err)
	}

	// fetch branch
	cmd := exec.Command("git", "fetch", "origin", branch)
	cmd.Dir = dest
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("error running command %q: %v: %s", strings.Join(cmd.Args, " "), err, string(output))
	}
	log.Printf("fetch %q: %s", branch, string(output))

	// reset working copy
	cmd = exec.Command("git", "reset", "--hard", rev)
	cmd.Dir = dest
	output, err = cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("error running command %q : %v: %s", strings.Join(cmd.Args, " "), err, string(output))
	}
	log.Printf("reset %q: %v", rev, string(output))
	return nil
}
<|endoftext|>


<commit_before>package github

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"os/signal"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"

	"github.com/github/hub/ui"
	"github.com/github/hub/utils"
	"github.com/mitchellh/go-homedir"
	"golang.org/x/crypto/ssh/terminal"
)

type yamlHost struct {
	User       string `yaml:"user"`
	OAuthToken string `yaml:"oauth_token"`
	Protocol   string `yaml:"protocol"`
	UnixSocket string `yaml:"unix_socket,omitempty"`
}

type Host struct {
	Host        string `toml:"host"`
	User        string `toml:"user"`
	AccessToken string `toml:"access_token"`
	Protocol    string `toml:"protocol"`
	UnixSocket  string `toml:"unix_socket,omitempty"`
}

type Config struct {
	Hosts []*Host `toml:"hosts"`
}

func (c *Config) PromptForHost(host string) (h *Host, err error) {
	token := c.DetectToken()
	tokenFromEnv := token != ""

	if host != GitHubHost {
		if _, e := url.Parse("https://" + host); e != nil {
			err = fmt.Errorf("invalid hostname: %q", host)
			return
		}
	}

	h = c.Find(host)
	if h != nil {
		if h.User == "" {
			utils.Check(CheckWriteable(configsFile()))
			// User is missing from the config: this is a broken config probably
			// because it was created with an old (broken) version of hub. Let's fix
			// it now. See issue #1007 for details.
			user := c.PromptForUser(host)
			if user == "" {
				utils.Check(fmt.Errorf("missing user"))
			}
			h.User = user
			err := newConfigService().Save(configsFile(), c)
			utils.Check(err)
		}
		if tokenFromEnv {
			h.AccessToken = token
		} else {
			return
		}
	} else {
		h = &Host{
			Host:        host,
			AccessToken: token,
			Protocol:    "https",
		}
		c.Hosts = append(c.Hosts, h)
	}

	client := NewClientWithHost(h)

	if !tokenFromEnv {
		utils.Check(CheckWriteable(configsFile()))
		err = c.authorizeClient(client, host)
		if err != nil {
			return
		}
	}

	userFromEnv := os.Getenv("GITHUB_USER")
	repoFromEnv := os.Getenv("GITHUB_REPOSITORY")
	if userFromEnv == "" && repoFromEnv != "" {
		repoParts := strings.SplitN(repoFromEnv, "/", 2)
		if len(repoParts) > 0 {
			userFromEnv = repoParts[0]
		}
	}
	if tokenFromEnv && userFromEnv != "" {
		h.User = userFromEnv
	} else {
		var currentUser *User
		currentUser, err = client.CurrentUser()
		if err != nil {
			return
		}
		h.User = currentUser.Login
	}

	if !tokenFromEnv {
		err = newConfigService().Save(configsFile(), c)
	}

	return
}

func (c *Config) authorizeClient(client *Client, host string) (err error) {
	user := c.PromptForUser(host)
	pass := c.PromptForPassword(host, user)

	var code, token string
	for {
		token, err = client.FindOrCreateToken(user, pass, code)
		if err == nil {
			break
		}

		if ae, ok := err.(*errorInfo); ok && strings.HasPrefix(ae.Response.Header.Get("X-GitHub-OTP"), "required;") {
			if code != "" {
				ui.Errorln("warning: invalid two-factor code")
			}
			code = c.PromptForOTP()
		} else {
			break
		}
	}

	if err == nil {
		client.Host.AccessToken = token
	}

	return
}

func (c *Config) DetectToken() string {
	return os.Getenv("GITHUB_TOKEN")
}

func (c *Config) PromptForUser(host string) (user string) {
	user = os.Getenv("GITHUB_USER")
	if user != "" {
		return
	}

	ui.Printf("%s username: ", host)
	user = c.scanLine()

	return
}

func (c *Config) PromptForPassword(host, user string) (pass string) {
	pass = os.Getenv("GITHUB_PASSWORD")
	if pass != "" {
		return
	}

	ui.Printf("%s password for %s (never stored): ", host, user)
	if ui.IsTerminal(os.Stdin) {
		if password, err := getPassword(); err == nil {
			pass = password
		}
	} else {
		pass = c.scanLine()
	}

	return
}

func (c *Config) PromptForOTP() string {
	fmt.Print("two-factor authentication code: ")
	return c.scanLine()
}

func (c *Config) scanLine() string {
	var line string
	scanner := bufio.NewScanner(os.Stdin)
	if scanner.Scan() {
		line = scanner.Text()
	}
	utils.Check(scanner.Err())

	return line
}

func getPassword() (string, error) {
	stdin := 0 // syscall.Stdin
	initialTermState, err := terminal.GetState(stdin)
	if err != nil {
		return "", err
	}

	c := make(chan os.Signal)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		s := <-c
		terminal.Restore(stdin, initialTermState)
		switch sig := s.(type) {
		case syscall.Signal:
			if int(sig) == 2 {
				fmt.Println("^C")
			}
		}
		os.Exit(1)
	}()

	passBytes, err := terminal.ReadPassword(stdin)
	if err != nil {
		return "", err
	}

	signal.Stop(c)
	fmt.Print("\n")
	return string(passBytes), nil
}

func (c *Config) Find(host string) *Host {
	for _, h := range c.Hosts {
		if h.Host == host {
			return h
		}
	}

	return nil
}

func (c *Config) selectHost() *Host {
	options := len(c.Hosts)

	if options == 1 {
		return c.Hosts[0]
	}

	prompt := "Select host:\n"
	for idx, host := range c.Hosts {
		prompt += fmt.Sprintf(" %d. %s\n", idx+1, host.Host)
	}
	prompt += fmt.Sprint("> ")

	ui.Printf(prompt)
	index := c.scanLine()
	i, err := strconv.Atoi(index)
	if err != nil || i < 1 || i > options {
		utils.Check(fmt.Errorf("Error: must enter a number [1-%d]", options))
	}

	return c.Hosts[i-1]
}

var defaultConfigsFile string

func configsFile() string {
	if configFromEnv := os.Getenv("HUB_CONFIG"); configFromEnv != "" {
		return configFromEnv
	}
	if defaultConfigsFile == "" {
		var err error
		defaultConfigsFile, err = determineConfigLocation()
		utils.Check(err)
	}
	return defaultConfigsFile
}

func homeConfig() (string, error) {
	if home, err := homedir.Dir(); err != nil {
		return "", err
	} else {
		return filepath.Join(home, ".config"), nil
	}
}

func determineConfigLocation() (string, error) {
	var err error

	xdgHome := os.Getenv("XDG_CONFIG_HOME")
	configDir := xdgHome
	if configDir == "" {
		if configDir, err = homeConfig(); err != nil {
			return "", err
		}
	}

	xdgDirs := os.Getenv("XDG_CONFIG_DIRS")
	if xdgDirs == "" {
		xdgDirs = "/etc/xdg"
	}
	searchDirs := append([]string{configDir}, strings.Split(xdgDirs, ":")...)

	for _, dir := range searchDirs {
		filename := filepath.Join(dir, "hub")
		if _, err := os.Stat(filename); err == nil {
			return filename, nil
		}
	}

	configFile := filepath.Join(configDir, "hub")

	if configDir == xdgHome {
		if homeDir, _ := homeConfig(); homeDir != "" {
			legacyConfig := filepath.Join(homeDir, "hub")
			if _, err = os.Stat(legacyConfig); err == nil {
				ui.Errorf("Notice: config file found but not respected at: %s\n", legacyConfig)
				ui.Errorf("You might want to move it to `%s' to avoid re-authenticating.\n", configFile)
			}
		}
	}

	return configFile, nil
}

var currentConfig *Config
var configLoadedFrom = ""

func CurrentConfig() *Config {
	filename := configsFile()
	if configLoadedFrom != filename {
		currentConfig = &Config{}
		newConfigService().Load(filename, currentConfig)
		configLoadedFrom = filename
	}

	return currentConfig
}

func (c *Config) DefaultHost() (host *Host, err error) {
	if GitHubHostEnv != "" {
		host, err = c.PromptForHost(GitHubHostEnv)
	} else if len(c.Hosts) > 0 {
		host = c.selectHost()
		// HACK: forces host to inherit GITHUB_TOKEN if applicable
		host, err = c.PromptForHost(host.Host)
	} else {
		host, err = c.PromptForHost(DefaultGitHubHost())
	}

	return
}

func (c *Config) DefaultHostNoPrompt() (*Host, error) {
	if GitHubHostEnv != "" {
		return c.PromptForHost(GitHubHostEnv)
	} else if len(c.Hosts) > 0 {
		host := c.Hosts[0]
		// HACK: forces host to inherit GITHUB_TOKEN if applicable
		return c.PromptForHost(host.Host)
	} else {
		return c.PromptForHost(GitHubHost)
	}
}

// CheckWriteable checks if config file is writeable. This should
// be called before asking for credentials and only if current
// operation needs to update the file. See issue #1314 for details.
func CheckWriteable(filename string) error {
	// Check if file exists already. if it doesn't, we will delete it after
	// checking for writeabilty
	fileExistsAlready := false

	if _, err := os.Stat(filename); err == nil {
		fileExistsAlready = true
	}

	err := os.MkdirAll(filepath.Dir(filename), 0771)
	if err != nil {
		return err
	}

	w, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
	if err != nil {
		return err
	}
	w.Close()

	if !fileExistsAlready {
		err := os.Remove(filename)
		if err != nil {
			return err
		}
	}
	return nil
}

// Public for testing purpose
func CreateTestConfigs(user, token string) *Config {
	f, _ := ioutil.TempFile("", "test-config")
	os.Setenv("HUB_CONFIG", f.Name())

	host := &Host{
		User:        "jingweno",
		AccessToken: "123",
		Host:        GitHubHost,
	}

	c := &Config{Hosts: []*Host{host}}
	err := newConfigService().Save(f.Name(), c)
	if err != nil {
		panic(err)
	}

	return c
}
<commit_msg>[auth] Fix password prompt on Windows<commit_after>package github

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"os/signal"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"

	"github.com/github/hub/ui"
	"github.com/github/hub/utils"
	"github.com/mitchellh/go-homedir"
	"golang.org/x/crypto/ssh/terminal"
)

type yamlHost struct {
	User       string `yaml:"user"`
	OAuthToken string `yaml:"oauth_token"`
	Protocol   string `yaml:"protocol"`
	UnixSocket string `yaml:"unix_socket,omitempty"`
}

type Host struct {
	Host        string `toml:"host"`
	User        string `toml:"user"`
	AccessToken string `toml:"access_token"`
	Protocol    string `toml:"protocol"`
	UnixSocket  string `toml:"unix_socket,omitempty"`
}

type Config struct {
	Hosts []*Host `toml:"hosts"`
}

func (c *Config) PromptForHost(host string) (h *Host, err error) {
	token := c.DetectToken()
	tokenFromEnv := token != ""

	if host != GitHubHost {
		if _, e := url.Parse("https://" + host); e != nil {
			err = fmt.Errorf("invalid hostname: %q", host)
			return
		}
	}

	h = c.Find(host)
	if h != nil {
		if h.User == "" {
			utils.Check(CheckWriteable(configsFile()))
			// User is missing from the config: this is a broken config probably
			// because it was created with an old (broken) version of hub. Let's fix
			// it now. See issue #1007 for details.
			user := c.PromptForUser(host)
			if user == "" {
				utils.Check(fmt.Errorf("missing user"))
			}
			h.User = user
			err := newConfigService().Save(configsFile(), c)
			utils.Check(err)
		}
		if tokenFromEnv {
			h.AccessToken = token
		} else {
			return
		}
	} else {
		h = &Host{
			Host:        host,
			AccessToken: token,
			Protocol:    "https",
		}
		c.Hosts = append(c.Hosts, h)
	}

	client := NewClientWithHost(h)

	if !tokenFromEnv {
		utils.Check(CheckWriteable(configsFile()))
		err = c.authorizeClient(client, host)
		if err != nil {
			return
		}
	}

	userFromEnv := os.Getenv("GITHUB_USER")
	repoFromEnv := os.Getenv("GITHUB_REPOSITORY")
	if userFromEnv == "" && repoFromEnv != "" {
		repoParts := strings.SplitN(repoFromEnv, "/", 2)
		if len(repoParts) > 0 {
			userFromEnv = repoParts[0]
		}
	}
	if tokenFromEnv && userFromEnv != "" {
		h.User = userFromEnv
	} else {
		var currentUser *User
		currentUser, err = client.CurrentUser()
		if err != nil {
			return
		}
		h.User = currentUser.Login
	}

	if !tokenFromEnv {
		err = newConfigService().Save(configsFile(), c)
	}

	return
}

func (c *Config) authorizeClient(client *Client, host string) (err error) {
	user := c.PromptForUser(host)
	pass := c.PromptForPassword(host, user)

	var code, token string
	for {
		token, err = client.FindOrCreateToken(user, pass, code)
		if err == nil {
			break
		}

		if ae, ok := err.(*errorInfo); ok && strings.HasPrefix(ae.Response.Header.Get("X-GitHub-OTP"), "required;") {
			if code != "" {
				ui.Errorln("warning: invalid two-factor code")
			}
			code = c.PromptForOTP()
		} else {
			break
		}
	}

	if err == nil {
		client.Host.AccessToken = token
	}

	return
}

func (c *Config) DetectToken() string {
	return os.Getenv("GITHUB_TOKEN")
}

func (c *Config) PromptForUser(host string) (user string) {
	user = os.Getenv("GITHUB_USER")
	if user != "" {
		return
	}

	ui.Printf("%s username: ", host)
	user = c.scanLine()

	return
}

func (c *Config) PromptForPassword(host, user string) (pass string) {
	pass = os.Getenv("GITHUB_PASSWORD")
	if pass != "" {
		return
	}

	ui.Printf("%s password for %s (never stored): ", host, user)
	if ui.IsTerminal(os.Stdin) {
		if password, err := getPassword(); err == nil {
			pass = password
		}
	} else {
		pass = c.scanLine()
	}

	return
}

func (c *Config) PromptForOTP() string {
	fmt.Print("two-factor authentication code: ")
	return c.scanLine()
}

func (c *Config) scanLine() string {
	var line string
	scanner := bufio.NewScanner(os.Stdin)
	if scanner.Scan() {
		line = scanner.Text()
	}
	utils.Check(scanner.Err())

	return line
}

func getPassword() (string, error) {
	stdin := int(syscall.Stdin)
	initialTermState, err := terminal.GetState(stdin)
	if err != nil {
		return "", err
	}

	c := make(chan os.Signal)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		s := <-c
		terminal.Restore(stdin, initialTermState)
		switch sig := s.(type) {
		case syscall.Signal:
			if int(sig) == 2 {
				fmt.Println("^C")
			}
		}
		os.Exit(1)
	}()

	passBytes, err := terminal.ReadPassword(stdin)
	if err != nil {
		return "", err
	}

	signal.Stop(c)
	fmt.Print("\n")
	return string(passBytes), nil
}

func (c *Config) Find(host string) *Host {
	for _, h := range c.Hosts {
		if h.Host == host {
			return h
		}
	}

	return nil
}

func (c *Config) selectHost() *Host {
	options := len(c.Hosts)

	if options == 1 {
		return c.Hosts[0]
	}

	prompt := "Select host:\n"
	for idx, host := range c.Hosts {
		prompt += fmt.Sprintf(" %d. %s\n", idx+1, host.Host)
	}
	prompt += fmt.Sprint("> ")

	ui.Printf(prompt)
	index := c.scanLine()
	i, err := strconv.Atoi(index)
	if err != nil || i < 1 || i > options {
		utils.Check(fmt.Errorf("Error: must enter a number [1-%d]", options))
	}

	return c.Hosts[i-1]
}

var defaultConfigsFile string

func configsFile() string {
	if configFromEnv := os.Getenv("HUB_CONFIG"); configFromEnv != "" {
		return configFromEnv
	}
	if defaultConfigsFile == "" {
		var err error
		defaultConfigsFile, err = determineConfigLocation()
		utils.Check(err)
	}
	return defaultConfigsFile
}

func homeConfig() (string, error) {
	if home, err := homedir.Dir(); err != nil {
		return "", err
	} else {
		return filepath.Join(home, ".config"), nil
	}
}

func determineConfigLocation() (string, error) {
	var err error

	xdgHome := os.Getenv("XDG_CONFIG_HOME")
	configDir := xdgHome
	if configDir == "" {
		if configDir, err = homeConfig(); err != nil {
			return "", err
		}
	}

	xdgDirs := os.Getenv("XDG_CONFIG_DIRS")
	if xdgDirs == "" {
		xdgDirs = "/etc/xdg"
	}
	searchDirs := append([]string{configDir}, strings.Split(xdgDirs, ":")...)

	for _, dir := range searchDirs {
		filename := filepath.Join(dir, "hub")
		if _, err := os.Stat(filename); err == nil {
			return filename, nil
		}
	}

	configFile := filepath.Join(configDir, "hub")

	if configDir == xdgHome {
		if homeDir, _ := homeConfig(); homeDir != "" {
			legacyConfig := filepath.Join(homeDir, "hub")
			if _, err = os.Stat(legacyConfig); err == nil {
				ui.Errorf("Notice: config file found but not respected at: %s\n", legacyConfig)
				ui.Errorf("You might want to move it to `%s' to avoid re-authenticating.\n", configFile)
			}
		}
	}

	return configFile, nil
}

var currentConfig *Config
var configLoadedFrom = ""

func CurrentConfig() *Config {
	filename := configsFile()
	if configLoadedFrom != filename {
		currentConfig = &Config{}
		newConfigService().Load(filename, currentConfig)
		configLoadedFrom = filename
	}

	return currentConfig
}

func (c *Config) DefaultHost() (host *Host, err error) {
	if GitHubHostEnv != "" {
		host, err = c.PromptForHost(GitHubHostEnv)
	} else if len(c.Hosts) > 0 {
		host = c.selectHost()
		// HACK: forces host to inherit GITHUB_TOKEN if applicable
		host, err = c.PromptForHost(host.Host)
	} else {
		host, err = c.PromptForHost(DefaultGitHubHost())
	}

	return
}

func (c *Config) DefaultHostNoPrompt() (*Host, error) {
	if GitHubHostEnv != "" {
		return c.PromptForHost(GitHubHostEnv)
	} else if len(c.Hosts) > 0 {
		host := c.Hosts[0]
		// HACK: forces host to inherit GITHUB_TOKEN if applicable
		return c.PromptForHost(host.Host)
	} else {
		return c.PromptForHost(GitHubHost)
	}
}

// CheckWriteable checks if config file is writeable. This should
// be called before asking for credentials and only if current
// operation needs to update the file. See issue #1314 for details.
func CheckWriteable(filename string) error {
	// Check if file exists already. if it doesn't, we will delete it after
	// checking for writeabilty
	fileExistsAlready := false

	if _, err := os.Stat(filename); err == nil {
		fileExistsAlready = true
	}

	err := os.MkdirAll(filepath.Dir(filename), 0771)
	if err != nil {
		return err
	}

	w, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
	if err != nil {
		return err
	}
	w.Close()

	if !fileExistsAlready {
		err := os.Remove(filename)
		if err != nil {
			return err
		}
	}
	return nil
}

// Public for testing purpose
func CreateTestConfigs(user, token string) *Config {
	f, _ := ioutil.TempFile("", "test-config")
	os.Setenv("HUB_CONFIG", f.Name())

	host := &Host{
		User:        "jingweno",
		AccessToken: "123",
		Host:        GitHubHost,
	}

	c := &Config{Hosts: []*Host{host}}
	err := newConfigService().Save(f.Name(), c)
	if err != nil {
		panic(err)
	}

	return c
}
<|endoftext|>


<commit_before>// Copyright 2017 Jeff Foley. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package format

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/OWASP/Amass/net"
	"github.com/OWASP/Amass/requests"
	"github.com/fatih/color"
)

// Banner is the ASCII art logo used within help output.
const Banner = `
        .+++:.            :                             .+++.
      +W@@@@@@8        &+W@#               o8W8:      +W@@@@@@#.   oW@@@W#+
     &@#+   .o@##.    .@@@o@W.o@@o       :@@#&W8o    .@#:  .:oW+  .@#+++&#&
    +@&        &@&     #@8 +@W@&8@+     :@W.   +@8   +@:          .@8
    8@          @@     8@o  8@8  WW    .@W      W@+  .@W.          o@#:
    WW          &@o    &@:  o@+  o@+   #@.      8@o   +W@#+.        +W@8:
    #@          :@W    &@+  &@+   @8  :@o       o@o     oW@@W+        oW@8
    o@+          @@&   &@+  &@+   #@  &@.      .W@W       .+#@&         o@W.
     WW         +@W@8. &@+  :&    o@+ #@      :@W&@&         &@:  ..     :@o
     :@W:      o@# +Wo &@+        :W: +@W&o++o@W. &@&  8@#o+&@W.  #@:    o@+
      :W@@WWWW@@8       +              :&W@@@@&    &W  .o#@@W&.   :W@WWW@@&
        +o&&&&+.                                                    +oooo.
`

const (
	// Version is used to display the current version of Amass.
	Version = "v3.1.6"

	// Author is used to display the Amass Project Team.
	Author = "OWASP Amass Project - @owaspamass"

	// Description is the slogan for the Amass Project.
	Description = "In-depth Attack Surface Mapping and Asset Discovery"
)

var (
	// Colors used to ease the reading of program output
	y      = color.New(color.FgHiYellow)
	g      = color.New(color.FgHiGreen)
	r      = color.New(color.FgHiRed)
	b      = color.New(color.FgHiBlue)
	fgR    = color.New(color.FgRed)
	fgY    = color.New(color.FgYellow)
	yellow = color.New(color.FgHiYellow).SprintFunc()
	green  = color.New(color.FgHiGreen).SprintFunc()
	blue   = color.New(color.FgHiBlue).SprintFunc()
)

// ASNSummaryData stores information related to discovered ASs and netblocks.
type ASNSummaryData struct {
	Name      string
	Netblocks map[string]int
}

// UpdateSummaryData updates the summary maps using the provided requests.Output data.
func UpdateSummaryData(output *requests.Output, tags map[string]int, asns map[int]*ASNSummaryData) {
	tags[output.Tag]++

	for _, addr := range output.Addresses {
		data, found := asns[addr.ASN]
		if !found {
			asns[addr.ASN] = &ASNSummaryData{
				Name:      addr.Description,
				Netblocks: make(map[string]int),
			}
			data = asns[addr.ASN]
		}
		// Increment how many IPs were in this netblock
		data.Netblocks[addr.Netblock.String()]++
	}
}

// PrintEnumerationSummary outputs the summary information utilized by the command-line tools.
func PrintEnumerationSummary(total int, tags map[string]int, asns map[int]*ASNSummaryData, demo bool) {
	pad := func(num int, chr string) {
		for i := 0; i < num; i++ {
			b.Fprint(color.Error, chr)
		}
	}

	fmt.Fprintln(color.Error)
	// Print the header information
	title := "OWASP Amass "
	site := "https://github.com/OWASP/Amass"
	b.Fprint(color.Error, title+Version)
	num := 80 - (len(title) + len(Version) + len(site))
	pad(num, " ")
	b.Fprintf(color.Error, "%s\n", site)
	pad(8, "----------")
	fmt.Fprintf(color.Error, "\n%s%s", yellow(strconv.Itoa(total)), green(" names discovered - "))
	// Print the stats using tag information
	num, length := 1, len(tags)
	for k, v := range tags {
		fmt.Fprintf(color.Error, "%s: %s", green(k), yellow(strconv.Itoa(v)))
		if num < length {
			g.Fprint(color.Error, ", ")
		}
		num++
	}
	fmt.Fprintln(color.Error)

	if len(asns) == 0 {
		return
	}
	// Another line gets printed
	pad(8, "----------")
	fmt.Fprintln(color.Error)
	// Print the ASN and netblock information
	for asn, data := range asns {
		asnstr := strconv.Itoa(asn)
		datastr := data.Name

		if demo && asn > 0 {
			asnstr = censorString(asnstr, 0, len(asnstr))
			datastr = censorString(datastr, 0, len(datastr))
		}

		fmt.Fprintf(color.Error, "%s%s %s %s\n",
			blue("ASN: "), yellow(asnstr), green("-"), green(datastr))

		for cidr, ips := range data.Netblocks {
			countstr := strconv.Itoa(ips)
			cidrstr := cidr

			if demo {
				cidrstr = censorNetBlock(cidrstr)
			}

			countstr = fmt.Sprintf("\t%-4s", countstr)
			cidrstr = fmt.Sprintf("\t%-18s", cidrstr)

			fmt.Fprintf(color.Error, "%s%s %s\n",
				yellow(cidrstr), yellow(countstr), blue("Subdomain Name(s)"))
		}
	}
}

// PrintBanner outputs the Amass banner the same for all tools.
func PrintBanner() {
	y := color.New(color.FgHiYellow)
	r := color.New(color.FgHiRed)
	rightmost := 76

	pad := func(num int) {
		for i := 0; i < num; i++ {
			fmt.Fprint(color.Error, " ")
		}
	}
	r.Fprintln(color.Error, Banner)
	pad(rightmost - len(Version))
	y.Fprintln(color.Error, Version)
	pad(rightmost - len(Author))
	y.Fprintln(color.Error, Author)
	pad(rightmost - len(Description))
	y.Fprintf(color.Error, "%s\n\n\n", Description)
}

func censorDomain(input string) string {
	return censorString(input, strings.Index(input, "."), len(input))
}

func censorIP(input string) string {
	return censorString(input, 0, strings.LastIndex(input, "."))
}

func censorNetBlock(input string) string {
	return censorString(input, 0, strings.Index(input, "/"))
}

func censorString(input string, start, end int) string {
	runes := []rune(input)
	for i := start; i < end; i++ {
		if runes[i] == '.' ||
			runes[i] == '/' ||
			runes[i] == '-' ||
			runes[i] == ' ' {
			continue
		}
		runes[i] = 'x'
	}
	return string(runes)
}

// OutputLineParts returns the parts of a line to be printed for a requests.Output.
func OutputLineParts(out *requests.Output, src, addrs, demo bool) (source, name, ips string) {
	if src {
		source = fmt.Sprintf("%-18s", "["+out.Source+"] ")
	}
	if addrs {
		for i, a := range out.Addresses {
			if i != 0 {
				ips += ","
			}
			if demo {
				ips += censorIP(a.Address.String())
			} else {
				ips += a.Address.String()
			}
		}
		if ips == "" {
			ips = "N/A"
		}
	}
	name = out.Name
	if demo {
		name = censorDomain(name)
	}
	return
}

// DesiredAddrTypes removes undesired address types from the AddressInfo slice.
func DesiredAddrTypes(addrs []requests.AddressInfo, ipv4, ipv6 bool) []requests.AddressInfo {
	if !ipv4 && !ipv6 {
		return addrs
	}

	var keep []requests.AddressInfo
	for _, addr := range addrs {
		if net.IsIPv4(addr.Address) && !ipv4 {
			continue
		} else if net.IsIPv6(addr.Address) && !ipv6 {
			continue
		}
		keep = append(keep, addr)
	}
	return keep
}
<commit_msg>v3.1.7 release<commit_after>// Copyright 2017 Jeff Foley. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package format

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/OWASP/Amass/net"
	"github.com/OWASP/Amass/requests"
	"github.com/fatih/color"
)

// Banner is the ASCII art logo used within help output.
const Banner = `
        .+++:.            :                             .+++.
      +W@@@@@@8        &+W@#               o8W8:      +W@@@@@@#.   oW@@@W#+
     &@#+   .o@##.    .@@@o@W.o@@o       :@@#&W8o    .@#:  .:oW+  .@#+++&#&
    +@&        &@&     #@8 +@W@&8@+     :@W.   +@8   +@:          .@8
    8@          @@     8@o  8@8  WW    .@W      W@+  .@W.          o@#:
    WW          &@o    &@:  o@+  o@+   #@.      8@o   +W@#+.        +W@8:
    #@          :@W    &@+  &@+   @8  :@o       o@o     oW@@W+        oW@8
    o@+          @@&   &@+  &@+   #@  &@.      .W@W       .+#@&         o@W.
     WW         +@W@8. &@+  :&    o@+ #@      :@W&@&         &@:  ..     :@o
     :@W:      o@# +Wo &@+        :W: +@W&o++o@W. &@&  8@#o+&@W.  #@:    o@+
      :W@@WWWW@@8       +              :&W@@@@&    &W  .o#@@W&.   :W@WWW@@&
        +o&&&&+.                                                    +oooo.
`

const (
	// Version is used to display the current version of Amass.
	Version = "v3.1.7"

	// Author is used to display the Amass Project Team.
	Author = "OWASP Amass Project - @owaspamass"

	// Description is the slogan for the Amass Project.
	Description = "In-depth Attack Surface Mapping and Asset Discovery"
)

var (
	// Colors used to ease the reading of program output
	y      = color.New(color.FgHiYellow)
	g      = color.New(color.FgHiGreen)
	r      = color.New(color.FgHiRed)
	b      = color.New(color.FgHiBlue)
	fgR    = color.New(color.FgRed)
	fgY    = color.New(color.FgYellow)
	yellow = color.New(color.FgHiYellow).SprintFunc()
	green  = color.New(color.FgHiGreen).SprintFunc()
	blue   = color.New(color.FgHiBlue).SprintFunc()
)

// ASNSummaryData stores information related to discovered ASs and netblocks.
type ASNSummaryData struct {
	Name      string
	Netblocks map[string]int
}

// UpdateSummaryData updates the summary maps using the provided requests.Output data.
func UpdateSummaryData(output *requests.Output, tags map[string]int, asns map[int]*ASNSummaryData) {
	tags[output.Tag]++

	for _, addr := range output.Addresses {
		data, found := asns[addr.ASN]
		if !found {
			asns[addr.ASN] = &ASNSummaryData{
				Name:      addr.Description,
				Netblocks: make(map[string]int),
			}
			data = asns[addr.ASN]
		}
		// Increment how many IPs were in this netblock
		data.Netblocks[addr.Netblock.String()]++
	}
}

// PrintEnumerationSummary outputs the summary information utilized by the command-line tools.
func PrintEnumerationSummary(total int, tags map[string]int, asns map[int]*ASNSummaryData, demo bool) {
	pad := func(num int, chr string) {
		for i := 0; i < num; i++ {
			b.Fprint(color.Error, chr)
		}
	}

	fmt.Fprintln(color.Error)
	// Print the header information
	title := "OWASP Amass "
	site := "https://github.com/OWASP/Amass"
	b.Fprint(color.Error, title+Version)
	num := 80 - (len(title) + len(Version) + len(site))
	pad(num, " ")
	b.Fprintf(color.Error, "%s\n", site)
	pad(8, "----------")
	fmt.Fprintf(color.Error, "\n%s%s", yellow(strconv.Itoa(total)), green(" names discovered - "))
	// Print the stats using tag information
	num, length := 1, len(tags)
	for k, v := range tags {
		fmt.Fprintf(color.Error, "%s: %s", green(k), yellow(strconv.Itoa(v)))
		if num < length {
			g.Fprint(color.Error, ", ")
		}
		num++
	}
	fmt.Fprintln(color.Error)

	if len(asns) == 0 {
		return
	}
	// Another line gets printed
	pad(8, "----------")
	fmt.Fprintln(color.Error)
	// Print the ASN and netblock information
	for asn, data := range asns {
		asnstr := strconv.Itoa(asn)
		datastr := data.Name

		if demo && asn > 0 {
			asnstr = censorString(asnstr, 0, len(asnstr))
			datastr = censorString(datastr, 0, len(datastr))
		}

		fmt.Fprintf(color.Error, "%s%s %s %s\n",
			blue("ASN: "), yellow(asnstr), green("-"), green(datastr))

		for cidr, ips := range data.Netblocks {
			countstr := strconv.Itoa(ips)
			cidrstr := cidr

			if demo {
				cidrstr = censorNetBlock(cidrstr)
			}

			countstr = fmt.Sprintf("\t%-4s", countstr)
			cidrstr = fmt.Sprintf("\t%-18s", cidrstr)

			fmt.Fprintf(color.Error, "%s%s %s\n",
				yellow(cidrstr), yellow(countstr), blue("Subdomain Name(s)"))
		}
	}
}

// PrintBanner outputs the Amass banner the same for all tools.
func PrintBanner() {
	y := color.New(color.FgHiYellow)
	r := color.New(color.FgHiRed)
	rightmost := 76

	pad := func(num int) {
		for i := 0; i < num; i++ {
			fmt.Fprint(color.Error, " ")
		}
	}
	r.Fprintln(color.Error, Banner)
	pad(rightmost - len(Version))
	y.Fprintln(color.Error, Version)
	pad(rightmost - len(Author))
	y.Fprintln(color.Error, Author)
	pad(rightmost - len(Description))
	y.Fprintf(color.Error, "%s\n\n\n", Description)
}

func censorDomain(input string) string {
	return censorString(input, strings.Index(input, "."), len(input))
}

func censorIP(input string) string {
	return censorString(input, 0, strings.LastIndex(input, "."))
}

func censorNetBlock(input string) string {
	return censorString(input, 0, strings.Index(input, "/"))
}

func censorString(input string, start, end int) string {
	runes := []rune(input)
	for i := start; i < end; i++ {
		if runes[i] == '.' ||
			runes[i] == '/' ||
			runes[i] == '-' ||
			runes[i] == ' ' {
			continue
		}
		runes[i] = 'x'
	}
	return string(runes)
}

// OutputLineParts returns the parts of a line to be printed for a requests.Output.
func OutputLineParts(out *requests.Output, src, addrs, demo bool) (source, name, ips string) {
	if src {
		source = fmt.Sprintf("%-18s", "["+out.Source+"] ")
	}
	if addrs {
		for i, a := range out.Addresses {
			if i != 0 {
				ips += ","
			}
			if demo {
				ips += censorIP(a.Address.String())
			} else {
				ips += a.Address.String()
			}
		}
		if ips == "" {
			ips = "N/A"
		}
	}
	name = out.Name
	if demo {
		name = censorDomain(name)
	}
	return
}

// DesiredAddrTypes removes undesired address types from the AddressInfo slice.
func DesiredAddrTypes(addrs []requests.AddressInfo, ipv4, ipv6 bool) []requests.AddressInfo {
	if !ipv4 && !ipv6 {
		return addrs
	}

	var keep []requests.AddressInfo
	for _, addr := range addrs {
		if net.IsIPv4(addr.Address) && !ipv4 {
			continue
		} else if net.IsIPv6(addr.Address) && !ipv6 {
			continue
		}
		keep = append(keep, addr)
	}
	return keep
}
<|endoftext|>