<commit_before>package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"
)

var (
	urlRE      = regexp.MustCompile(`https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9]{1,6}\b([-a-zA-Z0-9!@:%_\+.~#?&\/\/=$]*)`)
	skipStatus = flag.String("a", "", "-a 500,400")
	timeout    = flag.Duration("t", 10*time.Second, "-t 10s or -t 1h")
	whitelist  = flag.String("w", "", "-w server1.com,server2.com")
)

var (
	errorColor    = "\033[1;31m%d\033[0m"
	errorStrColor = "\033[1;31m%s\033[0m"
	okColor       = "\033[1;32m%d\033[0m"
	debugColor    = "\033[1;36m%d\033[0m"
)

type response struct {
	URL      string
	Response *http.Response
	Err      error
}

func main() {
	flag.Parse()

	args := flag.Args()
	if len(args) == 0 {
		log.Fatal("filename is required")
	}

	// read file
	file, err := os.ReadFile(args[0])
	if err != nil {
		log.Fatalf("error on reading file: %v", err)
	}

	// validate skipStatus
	var skipped []int
	if len(*skipStatus) > 0 {
		splitted := strings.Split(*skipStatus, ",")
		for _, item := range splitted {
			val, err := strconv.Atoi(item)
			if err != nil {
				log.Fatalf("could not parse skip status value: %v \n", err)
			}
			skipped = append(skipped, val)
		}
	}

	// validate whitelist
	var whitelisted []string
	if len(*whitelist) > 0 {
		whitelisted = strings.Split(*whitelist, ",")
	}

	matches := urlRE.FindAllString(string(file), -1)
	client := &http.Client{
		Timeout: *timeout,
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		},
	}

	results := make(chan *response)

	// producer
	counter := 0
	for _, url := range matches {
		u := url
		if isInStr(url, whitelisted) {
			continue
		}
		counter++
		go worker(u, results, client)
	}
	fmt.Printf("Found %d URIs\n", len(matches))

	totalErrors := 0
	for counter > 0 {
		resp := <-results
		counter--
		if resp.Err != nil && resp.Response == nil {
			fmt.Printf("[%s] %s\n", fmt.Sprintf(errorStrColor, "ERROR"), resp.Err.Error())
			totalErrors++
			continue
		}

		shouldSkipURL := len(skipped) > 0 && isIn(resp.Response.StatusCode, skipped)
		statusColor := okColor
		if resp.Response.StatusCode > 400 && !shouldSkipURL {
			statusColor = errorColor
			totalErrors++
		} else if shouldSkipURL {
			statusColor = debugColor
		}

		fmt.Printf("[%s] %s \n", fmt.Sprintf(statusColor, resp.Response.StatusCode), resp.URL)
	}

	if totalErrors > 0 {
		fmt.Printf("Total Errors: %s \n", fmt.Sprintf(errorColor, totalErrors))
		os.Exit(1)
	}
}

func worker(url string, results chan<- *response, client *http.Client) {
	response := &response{
		URL: url,
	}
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		response.Err = err
		return
	}

	resp, err := client.Do(req)
	if err != nil {
		response.Err = err
		results <- response
		return
	}
	defer resp.Body.Close()

	response.Response = resp
	results <- response
}

func isIn(item int, items []int) bool {
	for _, i := range items {
		if i == item {
			return true
		}
	}
	return false
}

func isInStr(item string, items []string) bool {
	for _, i := range items {
		if i == item {
			return true
		}
	}
	return false
}
<commit_msg>adding substring check for whitelist<commit_after>package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"
)

var (
	urlRE      = regexp.MustCompile(`https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9]{1,6}\b([-a-zA-Z0-9!@:%_\+.~#?&\/\/=$]*)`)
	skipStatus = flag.String("a", "", "-a 500,400")
	timeout    = flag.Duration("t", 10*time.Second, "-t 10s or -t 1h")
	whitelist  = flag.String("w", "", "-w server1.com,server2.com")
)

var (
	errorColor    = "\033[1;31m%d\033[0m"
	errorStrColor = "\033[1;31m%s\033[0m"
	okColor       = "\033[1;32m%d\033[0m"
	debugColor    = "\033[1;36m%d\033[0m"
)

type response struct {
	URL      string
	Response *http.Response
	Err      error
}

func main() {
	flag.Parse()

	args := flag.Args()
	if len(args) == 0 {
		log.Fatal("filename is required")
	}

	// read file
	file, err := os.ReadFile(args[0])
	if err != nil {
		log.Fatalf("error on reading file: %v", err)
	}

	// validate skipStatus
	var skipped []int
	if len(*skipStatus) > 0 {
		splitted := strings.Split(*skipStatus, ",")
		for _, item := range splitted {
			val, err := strconv.Atoi(item)
			if err != nil {
				log.Fatalf("could not parse skip status value: %v \n", err)
			}
			skipped = append(skipped, val)
		}
	}

	// validate whitelist
	var whitelisted []string
	if len(*whitelist) > 0 {
		whitelisted = strings.Split(*whitelist, ",")
	}

	matches := urlRE.FindAllString(string(file), -1)
	client := &http.Client{
		Timeout: *timeout,
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		},
	}

	results := make(chan *response)

	// producer
	counter := 0
	for _, url := range matches {
		u := url
		if isInStr(url, whitelisted) {
			continue
		}
		counter++
		go worker(u, results, client)
	}
	fmt.Printf("Found %d URIs\n", len(matches))

	totalErrors := 0
	for counter > 0 {
		resp := <-results
		counter--
		if resp.Err != nil && resp.Response == nil {
			fmt.Printf("[%s] %s\n", fmt.Sprintf(errorStrColor, "ERROR"), resp.Err.Error())
			totalErrors++
			continue
		}

		shouldSkipURL := len(skipped) > 0 && isIn(resp.Response.StatusCode, skipped)
		statusColor := okColor
		if resp.Response.StatusCode > 400 && !shouldSkipURL {
			statusColor = errorColor
			totalErrors++
		} else if shouldSkipURL {
			statusColor = debugColor
		}

		fmt.Printf("[%s] %s \n", fmt.Sprintf(statusColor, resp.Response.StatusCode), resp.URL)
	}

	if totalErrors > 0 {
		fmt.Printf("Total Errors: %s \n", fmt.Sprintf(errorColor, totalErrors))
		os.Exit(1)
	}
}

func worker(url string, results chan<- *response, client *http.Client) {
	response := &response{
		URL: url,
	}
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		response.Err = err
		return
	}

	resp, err := client.Do(req)
	if err != nil {
		response.Err = err
		results <- response
		return
	}
	defer resp.Body.Close()

	response.Response = resp
	results <- response
}

func isIn(item int, items []int) bool {
	for _, i := range items {
		if i == item {
			return true
		}
	}
	return false
}

func isInStr(item string, items []string) bool {
	for _, i := range items {
		if strings.Contains(item, i) {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/gonuts/commander"
	"github.com/gonuts/flag"
)

func hwaf_make_cmd_version() *commander.Command {
	cmd := &commander.Command{
		Run:       hwaf_run_cmd_version,
		UsageLine: "version",
		Short:     "print version and exit",
		Long: `
print version and exit.

ex:
 $ hwaf version
 hwaf-20130814 (ae3197b)
`,
		Flag: *flag.NewFlagSet("hwaf-version", flag.ExitOnError),
	}
	return cmd
}

func hwaf_run_cmd_version(cmd *commander.Command, args []string) {
	fmt.Printf("hwaf-20130814 (ae3197b)\n")
}

// EOF
<commit_msg>version: 20130814<commit_after>package main

import (
	"fmt"

	"github.com/gonuts/commander"
	"github.com/gonuts/flag"
)

func hwaf_make_cmd_version() *commander.Command {
	cmd := &commander.Command{
		Run:       hwaf_run_cmd_version,
		UsageLine: "version",
		Short:     "print version and exit",
		Long: `
print version and exit.

ex:
 $ hwaf version
 hwaf-20130814 (990d7df)
`,
		Flag: *flag.NewFlagSet("hwaf-version", flag.ExitOnError),
	}
	return cmd
}

func hwaf_run_cmd_version(cmd *commander.Command, args []string) {
	fmt.Printf("hwaf-20130814 (990d7df)\n")
}

// EOF
<|endoftext|>


<commit_before><commit_msg>lets switch to install the 4.x distro of the software<commit_after><|endoftext|>


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

package containermatcher

import (
	"fmt"
	"path/filepath"

	"github.com/richardlehane/siegfried/internal/priority"
	"github.com/richardlehane/siegfried/internal/siegreader"
	"github.com/richardlehane/siegfried/pkg/config"
	"github.com/richardlehane/siegfried/pkg/core"
)

func (m Matcher) Identify(n string, b *siegreader.Buffer, hints ...core.Hint) (chan core.Result, error) {
	res := make(chan core.Result)
	// check trigger
	buf, err := b.Slice(0, 8)
	if err != nil {
		close(res)
		return res, nil
	}
	divhints := m.divideHints(hints)
	for i, c := range m {
		if c.trigger(buf) {
			rdr, err := c.rdr(b)
			if err != nil {
				close(res)
				return res, err
			}
			go c.identify(n, rdr, res, divhints[i]...)
			return res, nil
		}
	}
	// nothing ... move on
	close(res)
	return res, nil
}

// ranges allows referencing a container hit back to a specific container matcher (used by divideHints)
// returns running number / matcher index / identifier index
func (m Matcher) ranges() [][3]int {
	var l int
	for _, c := range m {
		l += len(c.startIndexes)
	}
	ret := make([][3]int, l)
	var prev, this, idx, jdx int
	for i := range ret {
		prev = this
		this = m[idx].startIndexes[jdx]
		ret[i] = [3]int{prev + this, idx, jdx}
		idx++
		if idx >= len(m) {
			jdx++
			idx = 0
		}
	}
	return ret
}

func findID(id int, rng [][3]int) (int, int) {
	var idx int
	for idx = range rng {
		if rng[idx][0] >= id {
			if idx > 0 {
				idx--
			}
			break
		}
	}
	return rng[idx][1], rng[idx][2]
}

func (m Matcher) divideHints(hints []core.Hint) [][]core.Hint {
	ret := make([][]core.Hint, len(m))
	for i := range ret {
		ret[i] = make([]core.Hint, len(hints))
	}
	rng := m.ranges()
	for i, h := range hints {
		if len(h.Pivot) == 0 {
			continue
		}
		for _, p := range h.Pivot {
			midx, iidx := findID(p, rng)
			if ret[midx][i].Pivot == nil {
				ret[midx][i].Pivot = make([]int, 0, len(h.Pivot))
			}
			ret[midx][i].Pivot = append(ret[midx][i].Pivot, p-m[midx].startIndexes[iidx])
		}
	}
	return ret
}

type identifier struct {
	partsMatched [][]hit // hits for parts
	ruledOut     []bool  // mark additional signatures as negatively matched
	waitSet      *priority.WaitSet
	hits         []hit // shared buffer of hits used when matching
	result       bool
}

func (c *ContainerMatcher) newIdentifier(numParts int, hints ...core.Hint) *identifier {
	return &identifier{
		make([][]hit, numParts),
		make([]bool, numParts),
		c.priorities.WaitSet(hints...),
		make([]hit, 0, 1),
		false,
	}
}

func (c *ContainerMatcher) identify(n string, rdr Reader, res chan core.Result, hints ...core.Hint) {
	// safe to call on a nil matcher (i.e. container matching switched off)
	if c == nil {
		close(res)
		return
	}
	id := c.newIdentifier(len(c.parts), hints...)
	var err error
	for err = rdr.Next(); err == nil; err = rdr.Next() {
		ct, ok := c.nameCTest[rdr.Name()]
		if !ok {
			continue
		}
		if config.Debug() {
			fmt.Fprintf(config.Out(), "{Name match - %s (container %d))}\n", rdr.Name(), c.conType)
		}
		// name has matched, let's test the CTests
		// ct.identify will generate a slice of hits which pass to
		// processHits which will return true if we can stop
		if c.processHits(ct.identify(c, id, rdr, rdr.Name()), id, ct, rdr.Name(), res) {
			break
		}
	}
	// send a default hit if no result and extension matches
	if c.extension != "" && !id.result && filepath.Ext(n) == "."+c.extension {
		res <- defaultHit(-1 - int(c.conType))
	}
	close(res)
}

func (ct *cTest) identify(c *ContainerMatcher, id *identifier, rdr Reader, name string) []hit {
	// reset hits
	id.hits = id.hits[:0]
	for _, h := range ct.satisfied {
		if id.waitSet.Check(h) {
			id.hits = append(id.hits, hit{h, name, "name only"})
		}
	}
	if ct.unsatisfied != nil && !rdr.IsDir() {
		buf, _ := rdr.SetSource(c.entryBufs) // NOTE: an error is ignored here.
		bmc, _ := ct.bm.Identify("", buf)
		for r := range bmc {
			h := ct.unsatisfied[r.Index()]
			if id.waitSet.Check(h) && id.checkHits(h) {
				id.hits = append(id.hits, hit{h, name, r.Basis()})
			}
		}
		rdr.Close()
		c.entryBufs.Put(buf)
	}
	return id.hits
}

// process the hits from the ctest: adding hits to the parts matched, checking priorities
// return true if satisfied and can quit
func (c *ContainerMatcher) processHits(hits []hit, id *identifier, ct *cTest, name string, res chan core.Result) bool {
	// if there are no hits, rule out any sigs in the ctest
	if len(hits) == 0 {
		for _, v := range ct.satisfied {
			id.ruledOut[v] = true
		}
		for _, v := range ct.unsatisfied {
			id.ruledOut[v] = true
		}
		return false
	}
	for _, h := range hits {
		id.partsMatched[h.id] = append(id.partsMatched[h.id], h)
		if len(id.partsMatched[h.id]) == c.parts[h.id] {
			if id.waitSet.Check(h.id) {
				idx, _ := c.priorities.Index(h.id)
				res <- toResult(c.startIndexes[idx], id.partsMatched[h.id]) // send a Result here
				id.result = true                                            // mark id as having a result (for zip default)
				// set a priority list and return early if can
				if id.waitSet.Put(h.id) {
					return true
				}
			}
		}
	}
	// if nothing ruled out by this test, then we must continue
	if len(hits) == len(ct.satisfied)+len(ct.unsatisfied) {
		return false
	}
	// we can rule some possible matches out...
	for _, v := range ct.satisfied {
		if len(id.partsMatched[v]) == 0 || id.partsMatched[v][len(id.partsMatched[v])-1].name != name {
			id.ruledOut[v] = true
		}
	}
	for _, v := range ct.unsatisfied {
		if len(id.partsMatched[v]) == 0 || id.partsMatched[v][len(id.partsMatched[v])-1].name != name {
			id.ruledOut[v] = true
		}
	}
	// if we haven't got a waitList yet, then we should return false
	waitingOn := id.waitSet.WaitingOn()
	if waitingOn == nil {
		return false
	}
	// loop over the wait list, seeing if they are all ruled out
	for _, v := range waitingOn {
		if !id.ruledOut[v] {
			return false
		}
	}
	return true
}

// eliminate duplicate hits - must do this since rely on number of matches for each sig as test for full match
func (id *identifier) checkHits(i int) bool {
	for _, h := range id.hits {
		if i == h.id {
			return false
		}
	}
	return true
}

func toResult(i int, h []hit) result {
	if len(h) == 0 {
		return result(h)
	}
	h[0].id += i
	return result(h)
}

type result []hit

func (r result) Index() int {
	if len(r) == 0 {
		return -1
	}
	return r[0].id
}

func (r result) Basis() string {
	var basis string
	for i, v := range r {
		if i < 1 {
			basis += "container "
		} else {
			basis += "; "
		}
		basis += "name " + v.name
		if len(v.basis) > 0 {
			basis += " with " + v.basis
		}
	}
	return basis
}

type hit struct {
	id    int
	name  string
	basis string
}

type defaultHit int

func (d defaultHit) Index() int {
	return int(d)
}

func (d defaultHit) Basis() string {
	return "container match with trigger and default extension"
}
<commit_msg>fixes #126<commit_after>// Copyright 2014 Richard Lehane. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package containermatcher

import (
	"fmt"
	"path/filepath"

	"github.com/richardlehane/siegfried/internal/priority"
	"github.com/richardlehane/siegfried/internal/siegreader"
	"github.com/richardlehane/siegfried/pkg/config"
	"github.com/richardlehane/siegfried/pkg/core"
)

func (m Matcher) Identify(n string, b *siegreader.Buffer, hints ...core.Hint) (chan core.Result, error) {
	res := make(chan core.Result)
	// check trigger
	buf, err := b.Slice(0, 8)
	if err != nil {
		close(res)
		return res, nil
	}
	divhints := m.divideHints(hints)
	for i, c := range m {
		if c.trigger(buf) {
			rdr, err := c.rdr(b)
			if err != nil {
				close(res)
				return res, err
			}
			go c.identify(n, rdr, res, divhints[i]...)
			return res, nil
		}
	}
	// nothing ... move on
	close(res)
	return res, nil
}

// ranges allows referencing a container hit back to a specific container matcher (used by divideHints)
// returns running number / matcher index / identifier index
func (m Matcher) ranges() [][3]int {
	var l int
	for _, c := range m {
		l += len(c.startIndexes)
	}
	ret := make([][3]int, l)
	var prev, this, idx, jdx int
	for i := range ret {
		prev = this
		this = m[idx].startIndexes[jdx]
		ret[i] = [3]int{prev + this, idx, jdx}
		idx++
		if idx >= len(m) {
			jdx++
			idx = 0
		}
	}
	return ret
}

func findID(id int, rng [][3]int) (int, int) {
	var idx int
	for idx = range rng {
		if rng[idx][0] > id {
			if idx > 0 {
				idx--
			}
			break
		}
	}
	return rng[idx][1], rng[idx][2]
}

func (m Matcher) divideHints(hints []core.Hint) [][]core.Hint {
	ret := make([][]core.Hint, len(m))
	for i := range ret {
		ret[i] = make([]core.Hint, len(hints))
	}
	rng := m.ranges()
	for i, h := range hints {
		if len(h.Pivot) == 0 {
			continue
		}
		for _, p := range h.Pivot {
			midx, iidx := findID(p, rng)
			if ret[midx][i].Pivot == nil {
				ret[midx][i].Pivot = make([]int, 0, len(h.Pivot))
			}
			ret[midx][i].Pivot = append(ret[midx][i].Pivot, p-m[midx].startIndexes[iidx])
		}
	}
	return ret
}

type identifier struct {
	partsMatched [][]hit // hits for parts
	ruledOut     []bool  // mark additional signatures as negatively matched
	waitSet      *priority.WaitSet
	hits         []hit // shared buffer of hits used when matching
	result       bool
}

func (c *ContainerMatcher) newIdentifier(numParts int, hints ...core.Hint) *identifier {
	return &identifier{
		make([][]hit, numParts),
		make([]bool, numParts),
		c.priorities.WaitSet(hints...),
		make([]hit, 0, 1),
		false,
	}
}

func (c *ContainerMatcher) identify(n string, rdr Reader, res chan core.Result, hints ...core.Hint) {
	// safe to call on a nil matcher (i.e. container matching switched off)
	if c == nil {
		close(res)
		return
	}
	id := c.newIdentifier(len(c.parts), hints...)
	var err error
	for err = rdr.Next(); err == nil; err = rdr.Next() {
		ct, ok := c.nameCTest[rdr.Name()]
		if !ok {
			continue
		}
		if config.Debug() {
			fmt.Fprintf(config.Out(), "{Name match - %s (container %d))}\n", rdr.Name(), c.conType)
		}
		// name has matched, let's test the CTests
		// ct.identify will generate a slice of hits which pass to
		// processHits which will return true if we can stop
		if c.processHits(ct.identify(c, id, rdr, rdr.Name()), id, ct, rdr.Name(), res) {
			break
		}
	}
	// send a default hit if no result and extension matches
	if c.extension != "" && !id.result && filepath.Ext(n) == "."+c.extension {
		res <- defaultHit(-1 - int(c.conType))
	}
	close(res)
}

func (ct *cTest) identify(c *ContainerMatcher, id *identifier, rdr Reader, name string) []hit {
	// reset hits
	id.hits = id.hits[:0]
	for _, h := range ct.satisfied {
		if id.waitSet.Check(h) {
			id.hits = append(id.hits, hit{h, name, "name only"})
		}
	}
	if ct.unsatisfied != nil && !rdr.IsDir() {
		buf, _ := rdr.SetSource(c.entryBufs) // NOTE: an error is ignored here.
		bmc, _ := ct.bm.Identify("", buf)
		for r := range bmc {
			h := ct.unsatisfied[r.Index()]
			if id.waitSet.Check(h) && id.checkHits(h) {
				id.hits = append(id.hits, hit{h, name, r.Basis()})
			}
		}
		rdr.Close()
		c.entryBufs.Put(buf)
	}
	return id.hits
}

// process the hits from the ctest: adding hits to the parts matched, checking priorities
// return true if satisfied and can quit
func (c *ContainerMatcher) processHits(hits []hit, id *identifier, ct *cTest, name string, res chan core.Result) bool {
	// if there are no hits, rule out any sigs in the ctest
	if len(hits) == 0 {
		for _, v := range ct.satisfied {
			id.ruledOut[v] = true
		}
		for _, v := range ct.unsatisfied {
			id.ruledOut[v] = true
		}
		return false
	}
	for _, h := range hits {
		id.partsMatched[h.id] = append(id.partsMatched[h.id], h)
		if len(id.partsMatched[h.id]) == c.parts[h.id] {
			if id.waitSet.Check(h.id) {
				idx, _ := c.priorities.Index(h.id)
				res <- toResult(c.startIndexes[idx], id.partsMatched[h.id]) // send a Result here
				id.result = true                                            // mark id as having a result (for zip default)
				// set a priority list and return early if can
				if id.waitSet.Put(h.id) {
					return true
				}
			}
		}
	}
	// if nothing ruled out by this test, then we must continue
	if len(hits) == len(ct.satisfied)+len(ct.unsatisfied) {
		return false
	}
	// we can rule some possible matches out...
	for _, v := range ct.satisfied {
		if len(id.partsMatched[v]) == 0 || id.partsMatched[v][len(id.partsMatched[v])-1].name != name {
			id.ruledOut[v] = true
		}
	}
	for _, v := range ct.unsatisfied {
		if len(id.partsMatched[v]) == 0 || id.partsMatched[v][len(id.partsMatched[v])-1].name != name {
			id.ruledOut[v] = true
		}
	}
	// if we haven't got a waitList yet, then we should return false
	waitingOn := id.waitSet.WaitingOn()
	if waitingOn == nil {
		return false
	}
	// loop over the wait list, seeing if they are all ruled out
	for _, v := range waitingOn {
		if !id.ruledOut[v] {
			return false
		}
	}
	return true
}

// eliminate duplicate hits - must do this since rely on number of matches for each sig as test for full match
func (id *identifier) checkHits(i int) bool {
	for _, h := range id.hits {
		if i == h.id {
			return false
		}
	}
	return true
}

func toResult(i int, h []hit) result {
	if len(h) == 0 {
		return result(h)
	}
	h[0].id += i
	return result(h)
}

type result []hit

func (r result) Index() int {
	if len(r) == 0 {
		return -1
	}
	return r[0].id
}

func (r result) Basis() string {
	var basis string
	for i, v := range r {
		if i < 1 {
			basis += "container "
		} else {
			basis += "; "
		}
		basis += "name " + v.name
		if len(v.basis) > 0 {
			basis += " with " + v.basis
		}
	}
	return basis
}

type hit struct {
	id    int
	name  string
	basis string
}

type defaultHit int

func (d defaultHit) Index() int {
	return int(d)
}

func (d defaultHit) Basis() string {
	return "container match with trigger and default extension"
}
<|endoftext|>


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

// +build dragonfly freebsd linux netbsd openbsd solaris
// +build !js
// +build !android

package devicescale

import (
	"encoding/xml"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
)

type xmlBool bool

func (b *xmlBool) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var s string
	if err := d.DecodeElement(&s, &start); err != nil {
		return err
	}
	*b = xmlBool(s == "yes")
	return nil
}

func cinnamonScaleFromXML() (float64, error) {
	type cinnamonMonitors struct {
		XMLName       xml.Name `xml:"monitors"`
		Version       string   `xml:"version,attr"`
		Configuration []struct {
			BaseScale float64 `xml:"base_scale"`
			Output    []struct {
				Scale   float64 `xml:"scale"`
				Primary xmlBool `xml:"primary"`
			} `xml:"output"`
		} `xml:"configuration"`
	}

	home, err := os.UserHomeDir()
	if err != nil {
		return 0, err
	}
	f, err := os.Open(filepath.Join(home, ".config", "cinnamon-monitors.xml"))
	if err != nil {
		return 0, err
	}
	defer f.Close()

	d := xml.NewDecoder(f)

	var monitors cinnamonMonitors
	if err = d.Decode(&monitors); err != nil {
		return 0, err
	}

	// TODO: Choose the correct configuration.
	c := monitors.Configuration[0]
	for _, v := range c.Output {
		// TODO: Get the monitor at the specified position.
		if v.Primary && v.Scale != 0.0 {
			return c.BaseScale * v.Scale, nil
		}
	}
	return c.BaseScale, nil
}

func cinnamonScale() float64 {
	if s, err := cinnamonScaleFromXML(); err == nil && s > 0 {
		return s
	}

	out, err := exec.Command("gsettings", "get", "org.cinnamon.desktop.interface", "scaling-factor").Output()
	if err != nil {
		if err == exec.ErrNotFound {
			return 0
		}
		if _, ok := err.(*exec.ExitError); ok {
			return 0
		}
		panic(err)
	}
	m := gsettingsRe.FindStringSubmatch(string(out))
	s, err := strconv.Atoi(m[1])
	if err != nil {
		return 0
	}
	return float64(s)
}
<commit_msg>devicescale: Choose the correct Cinnamon monitor configuration<commit_after>// Copyright 2020 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build dragonfly freebsd linux netbsd openbsd solaris
// +build !js
// +build !android

package devicescale

import (
	"encoding/xml"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"

	"github.com/hajimehoshi/ebiten/internal/glfw"
)

type xmlBool bool

func (b *xmlBool) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var s string
	if err := d.DecodeElement(&s, &start); err != nil {
		return err
	}
	*b = xmlBool(s == "yes")
	return nil
}

type cinnamonMonitors struct {
	XMLName       xml.Name                        `xml:"monitors"`
	Version       string                          `xml:"version,attr"`
	Configuration []cinnamonMonitorsConfiguration `xml:"configuration"`
}

type cinnamonMonitorsConfiguration struct {
	BaseScale float64 `xml:"base_scale"`
	Output    []struct {
		X       int     `xml:"x"`
		Y       int     `xml:"y"`
		Width   int     `xml:"width"`
		Height  int     `xml:"height"`
		Scale   float64 `xml:"scale"`
		Primary xmlBool `xml:"primary"`
	} `xml:"output"`
}

func (c *cinnamonMonitorsConfiguration) matchesWithGLFWMonitors(monitors []*glfw.Monitor) bool {
	type area struct {
		X, Y, Width, Height int
	}
	areas := map[area]struct{}{}

	for _, o := range c.Output {
		if o.Width == 0 || o.Height == 0 {
			continue
		}
		areas[area{
			X:      o.X,
			Y:      o.Y,
			Width:  o.Width,
			Height: o.Height,
		}] = struct{}{}
	}

	if len(areas) != len(monitors) {
		return false
	}

	for _, m := range monitors {
		x, y := m.GetPos()
		v := m.GetVideoMode()
		a := area{
			X:      x,
			Y:      y,
			Width:  v.Width,
			Height: v.Height,
		}
		if _, ok := areas[a]; !ok {
			return false
		}
	}
	return true
}

func cinnamonScaleFromXML() (float64, error) {
	home, err := os.UserHomeDir()
	if err != nil {
		return 0, err
	}
	f, err := os.Open(filepath.Join(home, ".config", "cinnamon-monitors.xml"))
	if err != nil {
		return 0, err
	}
	defer f.Close()

	d := xml.NewDecoder(f)

	var monitors cinnamonMonitors
	if err = d.Decode(&monitors); err != nil {
		return 0, err
	}

	for _, c := range monitors.Configuration {
		if !c.matchesWithGLFWMonitors(glfw.GetMonitors()) {
			continue
		}
		for _, v := range c.Output {
			// TODO: Get the monitor at the specified position.
			if v.Primary && v.Scale != 0.0 {
				return c.BaseScale * v.Scale, nil
			}
		}
	}
	return 0, nil
}

func cinnamonScale() float64 {
	if s, err := cinnamonScaleFromXML(); err == nil && s > 0 {
		return s
	}

	out, err := exec.Command("gsettings", "get", "org.cinnamon.desktop.interface", "scaling-factor").Output()
	if err != nil {
		if err == exec.ErrNotFound {
			return 0
		}
		if _, ok := err.(*exec.ExitError); ok {
			return 0
		}
		panic(err)
	}
	m := gsettingsRe.FindStringSubmatch(string(out))
	s, err := strconv.Atoi(m[1])
	if err != nil {
		return 0
	}
	return float64(s)
}
<|endoftext|>


<commit_before>package common

import (
	"fmt"
	"log"
	"os/exec"
	"strings"

	"github.com/skeswa/gophr/common/models"
)

var (
	folderName              string
	gitHubRemoteOrigin      = "git@github.com:gophr-pm/%s.git"
	navigateToPackageFolder = "cd /tmp/%s"
)

var (
	initalizeRepo    = "cd /tmp && mkdir %s && cd %s && git init"
	createBranch     = "%s && git checkout -b %s"
	setRemoteCommand = "%s && git remote add origin %s"
	fetchRepoArchive = "%s && wget https://github.com/%s/%s/archive/%s.zip"
	unzipRepoArchive = "%s && unzip %s.zip && rm %s.zip"
	addFiles         = "%s && git add . "
	commitFiles      = "%s && git commit -m \" %s \""
	pushFiles        = "%s && git push --set-upstream origin %s"
)

//  SubVersionPackageModel TODO (@Shikkic): Possibly add Channel as a param
func SubVersionPackageModel(packageModel *models.PackageModel, ref string) {
	// Set working folderName for package
	folderName = BuildNewGitHubRepoName(packageModel)

	// Instantiate New Github Request Service
	log.Println("Initializing gitHub component")
	gitHubRequestService := NewGitHubRequestService()

	log.Printf("Creating new Github repo for %s/%s at %s",
		*packageModel.Author,
		*packageModel.Repo,
		ref,
	)
	err := gitHubRequestService.CreateNewGitHubRepo(*packageModel)
	log.Printf("%s", err)

	log.Printf("Initializing folder and initializing git repo for %s \n", folderName)
	err = initializeRepoCMD(packageModel)
	checkError(err, folderName)

	log.Printf("Creating branch %s \n", buildGitHubBranch(ref))
	err = createBranchCMD(packageModel, ref)
	checkError(err, folderName)

	log.Printf("Setting remote branch url %s \n", buildGitHubBranch(ref))
	err = setRemoteCMD(packageModel, ref)
	checkError(err, folderName)

	log.Printf("Fetching github archive for %s/%s with tag %s \n",
		*packageModel.Author,
		*packageModel.Repo,
		ref,
	)
	err = fetchArchiveCMD(packageModel, ref)
	checkError(err, folderName)

	log.Printf("Fetching github archive for %s/%s with tag %s \n",
		*packageModel.Author,
		*packageModel.Repo,
		ref,
	)
	err = unzipArchiveCMD(packageModel, ref)
	checkError(err, folderName)

	// TODO subverisoning
	// Create array of all sub-dependencies

	log.Println("Adding unarchived repo data to branch")
	err = addFilesCMD()
	checkError(err, folderName)

	log.Println("Commiting repo data to branch")
	err = commitFilesCMD(packageModel)
	checkError(err, folderName)

	log.Printf("Pushing files to branch %s \n", buildRemoteURL(packageModel, ref))
	err = pushFilesCMD(packageModel, ref)
	checkError(err, folderName)

	cleanUpExitHook(folderName)
}

func initializeRepoCMD(packageModel *models.PackageModel) error {
	log.Println("Initializing folder and repo commmand")
	cmd := fmt.Sprintf(initalizeRepo, folderName, folderName)
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s \n", out)
	return err
}

func createBranchCMD(packageModel *models.PackageModel, ref string) error {
	log.Println("Initializing folder and repo commmand")
	navigateFolderCMD := fmt.Sprintf(navigateToPackageFolder, folderName)
	cmd := fmt.Sprintf(createBranch, navigateFolderCMD, buildGitHubBranch(ref))
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s \n", out)
	return err
}

func setRemoteCMD(packageModel *models.PackageModel, ref string) error {
	log.Println("Initializing folder and repo commmand")
	navigateFolderCMD := fmt.Sprintf(navigateToPackageFolder, folderName)
	remoteURL := buildRemoteURL(packageModel, ref)
	cmd := fmt.Sprintf(setRemoteCommand, navigateFolderCMD, remoteURL)
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s \n", out)
	return err
}
func fetchArchiveCMD(packageModel *models.PackageModel, ref string) error {
	log.Println("Fetching and Unzipping Archive for tag")
	navigateFolderCMD := fmt.Sprintf(navigateToPackageFolder, folderName)

	cmd := fmt.Sprintf(fetchRepoArchive, navigateFolderCMD, *packageModel.Author, *packageModel.Repo, ref)
	log.Printf("%s FETCH ARCHIVE COMMAND", cmd)
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s \n", out)

	return err
}

func unzipArchiveCMD(packageModel *models.PackageModel, ref string) error {
	log.Println("Fetching and Unzipping Archive for tag")
	navigateFolderCMD := fmt.Sprintf(navigateToPackageFolder, folderName)
	cmd := fmt.Sprintf(unzipRepoArchive, navigateFolderCMD, ref, ref)
	log.Printf("%s UNZIP ARCHIVE COMMAND", cmd)
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s \n", out)

	return err
}

func addFilesCMD() error {
	navigateFolderCMD := fmt.Sprintf(navigateToPackageFolder, folderName)
	cmd := fmt.Sprintf(addFiles, navigateFolderCMD)
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s \n", out)

	return err
}

// TODO add version
func commitFilesCMD(packageModel *models.PackageModel) error {
	navigateFolderCMD := fmt.Sprintf(navigateToPackageFolder, folderName)
	commitMessage := fmt.Sprintf("Created Versin Repo of %s / %s @ %s", *packageModel.Author, *packageModel.Repo, "1.0")
	cmd := fmt.Sprintf(commitFiles, navigateFolderCMD, commitMessage)
	log.Println(cmd)
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s \n", out)

	return err
}

func pushFilesCMD(packageModel *models.PackageModel, ref string) error {
	navigateFolderCMD := fmt.Sprintf(navigateToPackageFolder, folderName)
	cmd := fmt.Sprintf(pushFiles, navigateFolderCMD, buildGitHubBranch(ref))
	log.Println(cmd)
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s 		\n", out)
	return err
}

// Helper functions

func buildRemoteURL(packageModel *models.PackageModel, ref string) string {
	repoName := BuildNewGitHubRepoName(packageModel)
	remoteURL := fmt.Sprintf(gitHubRemoteOrigin, repoName)
	return remoteURL
}

func buildGitHubBranch(ref string) string {
	repoHash := ref[:len(ref)-1]
	return repoHash
}

// Exit Hook to clean up files
func cleanUpExitHook(folderName string) {
	log.Printf("Exit hook initiated deleting folder %s \n", folderName)
	if strings.ContainsAny(folderName, "/") == true {
		cmd := fmt.Sprintf("cd /tmp && rm -rf %s", folderName)
		out, err := exec.Command("sh", "-c", cmd).Output()
		if err != nil {
			log.Println("Could not properly engage exit hook")
			log.Fatalln(err)
		}
		log.Printf("Output: %s", out)
	} else {
		log.Println("Cowardly refusing to initiate exit hook. Will not rm -rf folder names that contains any leading '/'")
	}
}

// Check Error and Engage Exit Hook if fatal error occured
func checkError(err error, folderName string) {
	if err != nil {
		cleanUpExitHook(folderName)
		log.Fatalf("Error occured %s \n", err)
	}
}
<commit_msg>sub version removes unzip into dir<commit_after>package common

import (
	"fmt"
	"log"
	"os/exec"
	"strings"

	"github.com/skeswa/gophr/common/models"
)

var (
	folderName              string
	gitHubRemoteOrigin      = "git@github.com:gophr-pm/%s.git"
	navigateToPackageFolder = "cd /tmp/%s"
)

var (
	initalizeRepo    = "cd /tmp && mkdir %s && cd %s && git init"
	createBranch     = "%s && git checkout -b %s"
	setRemoteCommand = "%s && git remote add origin %s"
	fetchRepoArchive = "%s && wget https://github.com/%s/%s/archive/%s.zip"
	unzipRepoArchive = "%s && unzip -j %s.zip && rm %s.zip"
	addFiles         = "%s && git add . "
	commitFiles      = "%s && git commit -m \" %s \""
	pushFiles        = "%s && git push --set-upstream origin %s"
)

//  SubVersionPackageModel TODO (@Shikkic): Possibly add Channel as a param
func SubVersionPackageModel(packageModel *models.PackageModel, ref string) {
	// Set working folderName for package
	folderName = BuildNewGitHubRepoName(packageModel)

	// Instantiate New Github Request Service
	log.Println("Initializing gitHub component")
	gitHubRequestService := NewGitHubRequestService()

	log.Printf("Creating new Github repo for %s/%s at %s",
		*packageModel.Author,
		*packageModel.Repo,
		ref,
	)
	err := gitHubRequestService.CreateNewGitHubRepo(*packageModel)
	log.Printf("%s", err)

	log.Printf("Initializing folder and initializing git repo for %s \n", folderName)
	err = initializeRepoCMD(packageModel)
	checkError(err, folderName)

	log.Printf("Creating branch %s \n", buildGitHubBranch(ref))
	err = createBranchCMD(packageModel, ref)
	checkError(err, folderName)

	log.Printf("Setting remote branch url %s \n", buildGitHubBranch(ref))
	err = setRemoteCMD(packageModel, ref)
	checkError(err, folderName)

	log.Printf("Fetching github archive for %s/%s with tag %s \n",
		*packageModel.Author,
		*packageModel.Repo,
		ref,
	)
	err = fetchArchiveCMD(packageModel, ref)
	checkError(err, folderName)

	log.Printf("Fetching github archive for %s/%s with tag %s \n",
		*packageModel.Author,
		*packageModel.Repo,
		ref,
	)
	err = unzipArchiveCMD(packageModel, ref)
	checkError(err, folderName)

	// TODO subverisoning
	// Create array of all sub-dependencies

	log.Println("Adding unarchived repo data to branch")
	err = addFilesCMD()
	checkError(err, folderName)

	log.Println("Commiting repo data to branch")
	err = commitFilesCMD(packageModel, ref)
	checkError(err, folderName)

	log.Printf("Pushing files to branch %s \n", buildRemoteURL(packageModel, ref))
	err = pushFilesCMD(packageModel, ref)
	checkError(err, folderName)

	cleanUpExitHook(folderName)
}

func initializeRepoCMD(packageModel *models.PackageModel) error {
	log.Println("Initializing folder and repo commmand")
	cmd := fmt.Sprintf(initalizeRepo, folderName, folderName)
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s \n", out)
	return err
}

func createBranchCMD(packageModel *models.PackageModel, ref string) error {
	log.Println("Initializing folder and repo commmand")
	navigateFolderCMD := fmt.Sprintf(navigateToPackageFolder, folderName)
	cmd := fmt.Sprintf(createBranch, navigateFolderCMD, buildGitHubBranch(ref))
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s \n", out)
	return err
}

func setRemoteCMD(packageModel *models.PackageModel, ref string) error {
	log.Println("Initializing folder and repo commmand")
	navigateFolderCMD := fmt.Sprintf(navigateToPackageFolder, folderName)
	remoteURL := buildRemoteURL(packageModel, ref)
	cmd := fmt.Sprintf(setRemoteCommand, navigateFolderCMD, remoteURL)
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s \n", out)
	return err
}
func fetchArchiveCMD(packageModel *models.PackageModel, ref string) error {
	log.Println("Fetching and Unzipping Archive for tag")
	navigateFolderCMD := fmt.Sprintf(navigateToPackageFolder, folderName)

	cmd := fmt.Sprintf(fetchRepoArchive, navigateFolderCMD, *packageModel.Author, *packageModel.Repo, ref)
	log.Printf("%s FETCH ARCHIVE COMMAND", cmd)
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s \n", out)

	return err
}

func unzipArchiveCMD(packageModel *models.PackageModel, ref string) error {
	log.Println("Fetching and Unzipping Archive for tag")
	navigateFolderCMD := fmt.Sprintf(navigateToPackageFolder, folderName)
	cmd := fmt.Sprintf(unzipRepoArchive, navigateFolderCMD, ref, ref)
	log.Printf("%s UNZIP ARCHIVE COMMAND", cmd)
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s \n", out)

	return err
}

func addFilesCMD() error {
	navigateFolderCMD := fmt.Sprintf(navigateToPackageFolder, folderName)
	cmd := fmt.Sprintf(addFiles, navigateFolderCMD)
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s \n", out)

	return err
}

// TODO add version
func commitFilesCMD(packageModel *models.PackageModel, ref string) error {
	navigateFolderCMD := fmt.Sprintf(navigateToPackageFolder, folderName)
	commitMessage := fmt.Sprintf("Gophr versioned repo of %s / %s @ %s", *packageModel.Author, *packageModel.Repo, ref)
	cmd := fmt.Sprintf(commitFiles, navigateFolderCMD, commitMessage)
	log.Println(cmd)
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s \n", out)

	return err
}

func pushFilesCMD(packageModel *models.PackageModel, ref string) error {
	navigateFolderCMD := fmt.Sprintf(navigateToPackageFolder, folderName)
	cmd := fmt.Sprintf(pushFiles, navigateFolderCMD, buildGitHubBranch(ref))
	log.Println(cmd)
	out, err := exec.Command("sh", "-c", cmd).Output()
	log.Printf("Output: %s 		\n", out)
	return err
}

// Helper functions

func buildRemoteURL(packageModel *models.PackageModel, ref string) string {
	repoName := BuildNewGitHubRepoName(packageModel)
	remoteURL := fmt.Sprintf(gitHubRemoteOrigin, repoName)
	return remoteURL
}

func buildGitHubBranch(ref string) string {
	repoHash := ref[:len(ref)-1]
	return repoHash
}

// Exit Hook to clean up files
func cleanUpExitHook(folderName string) {
	log.Printf("Exit hook initiated deleting folder %s \n", folderName)
	if strings.ContainsAny(folderName, "/") == true {
		cmd := fmt.Sprintf("cd /tmp && rm -rf %s", folderName)
		out, err := exec.Command("sh", "-c", cmd).Output()
		if err != nil {
			log.Println("Could not properly engage exit hook")
			log.Fatalln(err)
		}
		log.Printf("Output: %s", out)
	} else {
		log.Println("Cowardly refusing to initiate exit hook. Will not rm -rf folder names that contains any leading '/'")
	}
}

// Check Error and Engage Exit Hook if fatal error occured
func checkError(err error, folderName string) {
	if err != nil {
		cleanUpExitHook(folderName)
		log.Fatalf("Error occured %s \n", err)
	}
}
<|endoftext|>


<commit_before>package object

import (
	"fmt"
	"sort"

	"gopkg.in/src-d/go-git.v4/plumbing"
	"gopkg.in/src-d/go-git.v4/plumbing/storer"
)

// errIsReachable is thrown when first commit is an ancestor of the second
var errIsReachable = fmt.Errorf("first is reachable from second")

// MergeBase mimics the behavior of `git merge-base actual other`, returning the
// best common ancestor between the actual and the passed one.
// The best common ancestors can not be reached from other common ancestors.
func (c *Commit) MergeBase(other *Commit) ([]*Commit, error) {
	// use sortedByCommitDateDesc strategy
	sorted := sortByCommitDateDesc(c, other)
	newer := sorted[0]
	older := sorted[1]

	newerHistory, err := ancestorsIndex(older, newer)
	if err == errIsReachable {
		return []*Commit{older}, nil
	}

	if err != nil {
		return nil, err
	}

	var res []*Commit
	inNewerHistory := isInIndexCommitFilter(newerHistory)
	resIter := NewFilterCommitIter(older, &inNewerHistory, &inNewerHistory)
	err = resIter.ForEach(func(commit *Commit) error {
		res = append(res, commit)
		return nil
	})

	return Independents(res)
}

// IsAncestor returns true if the actual commit is ancestor of the passed one.
// It returns an error if the history is not transversable
// It mimics the behavior of `git merge --is-ancestor actual other`
func (c *Commit) IsAncestor(other *Commit) (bool, error) {
	found := false
	iter := NewCommitPreorderIter(other, nil, nil)
	err := iter.ForEach(func(comm *Commit) error {
		if comm.Hash != c.Hash {
			return nil
		}

		found = true
		return storer.ErrStop
	})

	return found, err
}

// ancestorsIndex returns a map with the ancestors of the starting commit if the
// excluded one is not one of them. It returns errIsReachable if the excluded commit
// is ancestor of the starting, or another error if the history is not traversable.
func ancestorsIndex(excluded, starting *Commit) (map[plumbing.Hash]struct{}, error) {
	if excluded.Hash.String() == starting.Hash.String() {
		return nil, errIsReachable
	}

	startingHistory := map[plumbing.Hash]struct{}{}
	startingIter := NewCommitIterBSF(starting, nil, nil)
	err := startingIter.ForEach(func(commit *Commit) error {
		if commit.Hash == excluded.Hash {
			return errIsReachable
		}

		startingHistory[commit.Hash] = struct{}{}
		return nil
	})

	if err != nil {
		return nil, err
	}

	return startingHistory, nil
}

// Independents returns a subset of the passed commits, that are not reachable the others
// It mimics the behavior of `git merge-base --independent commit...`.
func Independents(commits []*Commit) ([]*Commit, error) {
	// use sortedByCommitDateDesc strategy
	candidates := sortByCommitDateDesc(commits...)
	candidates = removeDuplicated(candidates)

	seen := map[plumbing.Hash]struct{}{}
	var isLimit CommitFilter = func(commit *Commit) bool {
		_, ok := seen[commit.Hash]
		return ok
	}

	if len(candidates) < 2 {
		return candidates, nil
	}

	pos := 0
	for {
		from := candidates[pos]
		others := remove(candidates, from)
		fromHistoryIter := NewFilterCommitIter(from, nil, &isLimit)
		err := fromHistoryIter.ForEach(func(fromAncestor *Commit) error {
			for _, other := range others {
				if fromAncestor.Hash == other.Hash {
					candidates = remove(candidates, other)
					others = remove(others, other)
				}
			}

			if len(candidates) == 1 {
				return storer.ErrStop
			}

			seen[fromAncestor.Hash] = struct{}{}
			return nil
		})

		if err != nil {
			return nil, err
		}

		nextPos := indexOf(candidates, from) + 1
		if nextPos >= len(candidates) {
			break
		}

		pos = nextPos
	}

	return candidates, nil
}

// sortByCommitDateDesc returns the passed commits, sorted by `committer.When desc`
//
// Following this strategy, it is tried to reduce the time needed when walking
// the history from one commit to reach the others. It is assumed that ancestors
// use to be committed before its descendant;
// That way `Independents(A^, A)` will be processed as being `Independents(A, A^)`;
// so starting by `A` it will be reached `A^` way sooner than walking from `A^`
// to the initial commit, and then from `A` to `A^`.
func sortByCommitDateDesc(commits ...*Commit) []*Commit {
	sorted := make([]*Commit, len(commits))
	copy(sorted, commits)
	sort.Slice(sorted, func(i, j int) bool {
		return sorted[i].Committer.When.After(sorted[j].Committer.When)
	})

	return sorted
}

// indexOf returns the first position where target was found in the passed commits
func indexOf(commits []*Commit, target *Commit) int {
	for i, commit := range commits {
		if target.Hash == commit.Hash {
			return i
		}
	}

	return -1
}

// remove returns the passed commits excluding the commit toDelete
func remove(commits []*Commit, toDelete *Commit) []*Commit {
	res := make([]*Commit, len(commits))
	j := 0
	for _, commit := range commits {
		if commit.Hash == toDelete.Hash {
			continue
		}

		res[j] = commit
		j++
	}

	return res[:j]
}

// removeDuplicated removes duplicated commits from the passed slice of commits
func removeDuplicated(commits []*Commit) []*Commit {
	seen := make(map[plumbing.Hash]struct{}, len(commits))
	res := make([]*Commit, len(commits))
	j := 0
	for _, commit := range commits {
		if _, ok := seen[commit.Hash]; ok {
			continue
		}

		seen[commit.Hash] = struct{}{}
		res[j] = commit
		j++
	}

	return res[:j]
}

// isInIndexCommitFilter returns a commitFilter that returns true
// if the commit is in the passed index.
func isInIndexCommitFilter(index map[plumbing.Hash]struct{}) CommitFilter {
	return func(c *Commit) bool {
		_, ok := index[c.Hash]
		return ok
	}
}
<commit_msg>plumbing/object: don't assign err from ForEach loop<commit_after>package object

import (
	"fmt"
	"sort"

	"gopkg.in/src-d/go-git.v4/plumbing"
	"gopkg.in/src-d/go-git.v4/plumbing/storer"
)

// errIsReachable is thrown when first commit is an ancestor of the second
var errIsReachable = fmt.Errorf("first is reachable from second")

// MergeBase mimics the behavior of `git merge-base actual other`, returning the
// best common ancestor between the actual and the passed one.
// The best common ancestors can not be reached from other common ancestors.
func (c *Commit) MergeBase(other *Commit) ([]*Commit, error) {
	// use sortedByCommitDateDesc strategy
	sorted := sortByCommitDateDesc(c, other)
	newer := sorted[0]
	older := sorted[1]

	newerHistory, err := ancestorsIndex(older, newer)
	if err == errIsReachable {
		return []*Commit{older}, nil
	}

	if err != nil {
		return nil, err
	}

	var res []*Commit
	inNewerHistory := isInIndexCommitFilter(newerHistory)
	resIter := NewFilterCommitIter(older, &inNewerHistory, &inNewerHistory)
	_ = resIter.ForEach(func(commit *Commit) error {
		res = append(res, commit)
		return nil
	})

	return Independents(res)
}

// IsAncestor returns true if the actual commit is ancestor of the passed one.
// It returns an error if the history is not transversable
// It mimics the behavior of `git merge --is-ancestor actual other`
func (c *Commit) IsAncestor(other *Commit) (bool, error) {
	found := false
	iter := NewCommitPreorderIter(other, nil, nil)
	err := iter.ForEach(func(comm *Commit) error {
		if comm.Hash != c.Hash {
			return nil
		}

		found = true
		return storer.ErrStop
	})

	return found, err
}

// ancestorsIndex returns a map with the ancestors of the starting commit if the
// excluded one is not one of them. It returns errIsReachable if the excluded commit
// is ancestor of the starting, or another error if the history is not traversable.
func ancestorsIndex(excluded, starting *Commit) (map[plumbing.Hash]struct{}, error) {
	if excluded.Hash.String() == starting.Hash.String() {
		return nil, errIsReachable
	}

	startingHistory := map[plumbing.Hash]struct{}{}
	startingIter := NewCommitIterBSF(starting, nil, nil)
	err := startingIter.ForEach(func(commit *Commit) error {
		if commit.Hash == excluded.Hash {
			return errIsReachable
		}

		startingHistory[commit.Hash] = struct{}{}
		return nil
	})

	if err != nil {
		return nil, err
	}

	return startingHistory, nil
}

// Independents returns a subset of the passed commits, that are not reachable the others
// It mimics the behavior of `git merge-base --independent commit...`.
func Independents(commits []*Commit) ([]*Commit, error) {
	// use sortedByCommitDateDesc strategy
	candidates := sortByCommitDateDesc(commits...)
	candidates = removeDuplicated(candidates)

	seen := map[plumbing.Hash]struct{}{}
	var isLimit CommitFilter = func(commit *Commit) bool {
		_, ok := seen[commit.Hash]
		return ok
	}

	if len(candidates) < 2 {
		return candidates, nil
	}

	pos := 0
	for {
		from := candidates[pos]
		others := remove(candidates, from)
		fromHistoryIter := NewFilterCommitIter(from, nil, &isLimit)
		err := fromHistoryIter.ForEach(func(fromAncestor *Commit) error {
			for _, other := range others {
				if fromAncestor.Hash == other.Hash {
					candidates = remove(candidates, other)
					others = remove(others, other)
				}
			}

			if len(candidates) == 1 {
				return storer.ErrStop
			}

			seen[fromAncestor.Hash] = struct{}{}
			return nil
		})

		if err != nil {
			return nil, err
		}

		nextPos := indexOf(candidates, from) + 1
		if nextPos >= len(candidates) {
			break
		}

		pos = nextPos
	}

	return candidates, nil
}

// sortByCommitDateDesc returns the passed commits, sorted by `committer.When desc`
//
// Following this strategy, it is tried to reduce the time needed when walking
// the history from one commit to reach the others. It is assumed that ancestors
// use to be committed before its descendant;
// That way `Independents(A^, A)` will be processed as being `Independents(A, A^)`;
// so starting by `A` it will be reached `A^` way sooner than walking from `A^`
// to the initial commit, and then from `A` to `A^`.
func sortByCommitDateDesc(commits ...*Commit) []*Commit {
	sorted := make([]*Commit, len(commits))
	copy(sorted, commits)
	sort.Slice(sorted, func(i, j int) bool {
		return sorted[i].Committer.When.After(sorted[j].Committer.When)
	})

	return sorted
}

// indexOf returns the first position where target was found in the passed commits
func indexOf(commits []*Commit, target *Commit) int {
	for i, commit := range commits {
		if target.Hash == commit.Hash {
			return i
		}
	}

	return -1
}

// remove returns the passed commits excluding the commit toDelete
func remove(commits []*Commit, toDelete *Commit) []*Commit {
	res := make([]*Commit, len(commits))
	j := 0
	for _, commit := range commits {
		if commit.Hash == toDelete.Hash {
			continue
		}

		res[j] = commit
		j++
	}

	return res[:j]
}

// removeDuplicated removes duplicated commits from the passed slice of commits
func removeDuplicated(commits []*Commit) []*Commit {
	seen := make(map[plumbing.Hash]struct{}, len(commits))
	res := make([]*Commit, len(commits))
	j := 0
	for _, commit := range commits {
		if _, ok := seen[commit.Hash]; ok {
			continue
		}

		seen[commit.Hash] = struct{}{}
		res[j] = commit
		j++
	}

	return res[:j]
}

// isInIndexCommitFilter returns a commitFilter that returns true
// if the commit is in the passed index.
func isInIndexCommitFilter(index map[plumbing.Hash]struct{}) CommitFilter {
	return func(c *Commit) bool {
		_, ok := index[c.Hash]
		return ok
	}
}
<|endoftext|>


<commit_before>package aws

import (
	"errors"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
	"github.com/docker/libmachete/provisioners/api"
	"sort"
	"time"
)

// Builder is a ProvisionerBuilder for AWS.
type Builder struct {
}

// Build creates an AWS provisioner.
func (a Builder) Build(params map[string]string) (api.Provisioner, error) {
	region := params["REGION"]
	if region == "" {
		return nil, errors.New("REGION must be specified")
	}

	accessKey := params["ACCESS_KEY"]
	secretKey := params["SECRET_KEY"]
	sessionToken := params["SESSION_TOKEN"]
	var awsCredentials *credentials.Credentials
	if (accessKey == "" || secretKey == "") && sessionToken == "" {
		// Fall back to shared credentials
		awsCredentials = credentials.NewSharedCredentials("", "")
	} else {
		awsCredentials =
			credentials.NewStaticCredentials(accessKey, secretKey, sessionToken)
	}

	client := CreateClient(region, awsCredentials, 5)

	return New(client), nil
}

type provisioner struct {
	client        ec2iface.EC2API
	sleepFunction func(time.Duration)
}

// New creates a new AWS provisioner that will use the provided EC2 API implementation.
func New(client ec2iface.EC2API) api.Provisioner {
	return &provisioner{client: client, sleepFunction: time.Sleep}
}

// CreateClient creates the actual EC2 API client.
func CreateClient(region string, awsCredentials *credentials.Credentials, retryCount int) ec2iface.EC2API {
	return ec2.New(session.New(aws.NewConfig().
		WithRegion(region).
		WithCredentials(awsCredentials).
		WithLogger(getLogger()).
		WithLogLevel(aws.LogDebugWithHTTPBody).
		WithMaxRetries(retryCount)))
}

func getInstanceSync(client ec2iface.EC2API, instanceID string) (*ec2.Instance, error) {
	result, err := client.DescribeInstances(&ec2.DescribeInstancesInput{
		InstanceIds: []*string{&instanceID},
	})
	if err != nil {
		return nil, err
	}
	if len(result.Reservations) != 1 || len(result.Reservations[0].Instances) != 1 {
		return nil, &ErrUnexpectedResponse{}
	}
	return result.Reservations[0].Instances[0], nil
}

func tagSync(client ec2iface.EC2API, request CreateInstanceRequest, instance *ec2.Instance) error {
	tags := []*ec2.Tag{}

	// Gather the tag keys in sorted order, to provide predictable tag order.  This is
	// particularly useful for tests.
	var keys []string
	for k := range request.Tags {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	for _, k := range keys {
		key := k
		value := request.Tags[key]
		tags = append(tags, &ec2.Tag{
			Key:   &key,
			Value: &value,
		})
	}

	_, err := client.CreateTags(&ec2.CreateTagsInput{
		Resources: []*string{instance.InstanceId},
		Tags:      tags,
	})
	return err
}

func createInstanceSync(
	client ec2iface.EC2API,
	request CreateInstanceRequest) (*ec2.Instance, error) {

	reservation, err := client.RunInstances(&ec2.RunInstancesInput{
		ImageId:  &request.ImageID,
		MinCount: aws.Int64(1),
		MaxCount: aws.Int64(1),
		Placement: &ec2.Placement{
			AvailabilityZone: &request.AvailabilityZone,
		},
		KeyName:      &request.KeyName,
		InstanceType: &request.InstanceType,
		NetworkInterfaces: []*ec2.InstanceNetworkInterfaceSpecification{{
			DeviceIndex:              aws.Int64(0), // eth0
			Groups:                   makePointerSlice(request.SecurityGroupIds),
			SubnetId:                 &request.SubnetID,
			AssociatePublicIpAddress: &request.AssociatePublicIPAddress,
			DeleteOnTermination:      &request.DeleteOnTermination,
		}},
		Monitoring: &ec2.RunInstancesMonitoringEnabled{
			Enabled: &request.Monitoring,
		},
		IamInstanceProfile: &ec2.IamInstanceProfileSpecification{
			Name: &request.IamInstanceProfile,
		},
		EbsOptimized: &request.EbsOptimized,
		BlockDeviceMappings: []*ec2.BlockDeviceMapping{
			{
				DeviceName: &request.BlockDeviceName,
				Ebs: &ec2.EbsBlockDevice{
					VolumeSize:          &request.RootSize,
					VolumeType:          &request.VolumeType,
					DeleteOnTermination: &request.DeleteOnTermination,
				},
			},
		},
	})

	if err != nil {
		return nil, err
	}

	if reservation == nil || len(reservation.Instances) != 1 {
		return nil, &ErrUnexpectedResponse{}
	}
	return reservation.Instances[0], nil
}

func (p *provisioner) blockUntilInstanceInState(instanceID string, instanceState string) error {
	return WaitUntil(p.sleepFunction, 30, 10*time.Second,
		func() (bool, error) {
			inst, err := getInstanceSync(p.client, instanceID)
			return inst != nil && *inst.State.Name == instanceState, err
		})
}

func (p *provisioner) NewRequestInstance() api.MachineRequest {
	return new(CreateInstanceRequest)
}

func (p *provisioner) CreateInstance(
	req api.MachineRequest) (<-chan api.CreateInstanceEvent, error) {

	request, is := req.(*CreateInstanceRequest)
	if !is {
		return nil, &ErrInvalidRequest{}
	}

	if err := request.Validate(); err != nil {
		return nil, err
	}

	events := make(chan api.CreateInstanceEvent)
	go func() {
		defer close(events)

		events <- api.CreateInstanceEvent{Type: api.CreateInstanceStarted}

		instance, err := createInstanceSync(p.client, *request)
		if err != nil {
			events <- api.CreateInstanceEvent{
				Error: err,
				Type:  api.CreateInstanceError,
			}
			return
		}

		err = p.blockUntilInstanceInState(*instance.InstanceId, ec2.InstanceStateNameRunning)
		if err != nil {
			events <- api.CreateInstanceEvent{
				Error: err,
				Type:  api.CreateInstanceError,
			}
			return
		}

		err = tagSync(p.client, *request, instance)
		if err != nil {
			events <- api.CreateInstanceEvent{
				Error: err,
				Type:  api.CreateInstanceError,
			}
			return
		}
		events <- api.CreateInstanceEvent{
			Type:       api.CreateInstanceCompleted,
			InstanceID: *instance.InstanceId,
		}
	}()

	return events, nil
}

func destroyInstanceSync(client ec2iface.EC2API, instanceID string) error {
	result, err := client.TerminateInstances(&ec2.TerminateInstancesInput{
		InstanceIds: []*string{&instanceID}})

	if err != nil {
		return err
	}

	if len(result.TerminatingInstances) == 1 {
		return nil
	}

	// There was no match for the instance ID.
	return &ErrInvalidRequest{}
}

func (p *provisioner) DestroyInstance(instanceID string) (<-chan api.DestroyInstanceEvent, error) {
	events := make(chan api.DestroyInstanceEvent)

	go func() {
		defer close(events)

		events <- api.DestroyInstanceEvent{Type: api.DestroyInstanceStarted}

		err := destroyInstanceSync(p.client, instanceID)
		if err != nil {
			events <- api.DestroyInstanceEvent{
				Type:  api.DestroyInstanceError,
				Error: err}
			return
		}

		err = p.blockUntilInstanceInState(instanceID, ec2.InstanceStateNameTerminated)
		if err != nil {
			events <- api.DestroyInstanceEvent{
				Error: err,
				Type:  api.DestroyInstanceError,
			}
			return
		}

		events <- api.DestroyInstanceEvent{Type: api.DestroyInstanceCompleted}
	}()

	return events, nil
}
<commit_msg>Use chained credentials for AWS. (#40)<commit_after>package aws

import (
	"errors"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
	"github.com/docker/libmachete/provisioners/api"
	"sort"
	"time"
)

// Builder is a ProvisionerBuilder for AWS.
type Builder struct {
}

// Build creates an AWS provisioner.
func (a Builder) Build(params map[string]string) (api.Provisioner, error) {
	region := params["REGION"]
	if region == "" {
		return nil, errors.New("REGION must be specified")
	}

	accessKey := params["ACCESS_KEY"]
	secretKey := params["SECRET_KEY"]
	sessionToken := params["SESSION_TOKEN"]

	awsCredentials := credentials.NewChainCredentials([]credentials.Provider{
		&credentials.StaticProvider{Value: credentials.Value{
			AccessKeyID:     accessKey,
			SecretAccessKey: secretKey,
			SessionToken:    sessionToken,
		}},
		&credentials.EnvProvider{},
		&credentials.SharedCredentialsProvider{},
		&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(session.New())},
	})

	client := CreateClient(region, awsCredentials, 5)

	return New(client), nil
}

type provisioner struct {
	client        ec2iface.EC2API
	sleepFunction func(time.Duration)
}

// New creates a new AWS provisioner that will use the provided EC2 API implementation.
func New(client ec2iface.EC2API) api.Provisioner {
	return &provisioner{client: client, sleepFunction: time.Sleep}
}

// CreateClient creates the actual EC2 API client.
func CreateClient(region string, awsCredentials *credentials.Credentials, retryCount int) ec2iface.EC2API {
	return ec2.New(session.New(aws.NewConfig().
		WithRegion(region).
		WithCredentials(awsCredentials).
		WithLogger(getLogger()).
		WithLogLevel(aws.LogDebugWithHTTPBody).
		WithMaxRetries(retryCount)))
}

func getInstanceSync(client ec2iface.EC2API, instanceID string) (*ec2.Instance, error) {
	result, err := client.DescribeInstances(&ec2.DescribeInstancesInput{
		InstanceIds: []*string{&instanceID},
	})
	if err != nil {
		return nil, err
	}
	if len(result.Reservations) != 1 || len(result.Reservations[0].Instances) != 1 {
		return nil, &ErrUnexpectedResponse{}
	}
	return result.Reservations[0].Instances[0], nil
}

func tagSync(client ec2iface.EC2API, request CreateInstanceRequest, instance *ec2.Instance) error {
	tags := []*ec2.Tag{}

	// Gather the tag keys in sorted order, to provide predictable tag order.  This is
	// particularly useful for tests.
	var keys []string
	for k := range request.Tags {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	for _, k := range keys {
		key := k
		value := request.Tags[key]
		tags = append(tags, &ec2.Tag{
			Key:   &key,
			Value: &value,
		})
	}

	_, err := client.CreateTags(&ec2.CreateTagsInput{
		Resources: []*string{instance.InstanceId},
		Tags:      tags,
	})
	return err
}

func createInstanceSync(
	client ec2iface.EC2API,
	request CreateInstanceRequest) (*ec2.Instance, error) {

	reservation, err := client.RunInstances(&ec2.RunInstancesInput{
		ImageId:  &request.ImageID,
		MinCount: aws.Int64(1),
		MaxCount: aws.Int64(1),
		Placement: &ec2.Placement{
			AvailabilityZone: &request.AvailabilityZone,
		},
		KeyName:      &request.KeyName,
		InstanceType: &request.InstanceType,
		NetworkInterfaces: []*ec2.InstanceNetworkInterfaceSpecification{{
			DeviceIndex:              aws.Int64(0), // eth0
			Groups:                   makePointerSlice(request.SecurityGroupIds),
			SubnetId:                 &request.SubnetID,
			AssociatePublicIpAddress: &request.AssociatePublicIPAddress,
			DeleteOnTermination:      &request.DeleteOnTermination,
		}},
		Monitoring: &ec2.RunInstancesMonitoringEnabled{
			Enabled: &request.Monitoring,
		},
		IamInstanceProfile: &ec2.IamInstanceProfileSpecification{
			Name: &request.IamInstanceProfile,
		},
		EbsOptimized: &request.EbsOptimized,
		BlockDeviceMappings: []*ec2.BlockDeviceMapping{
			{
				DeviceName: &request.BlockDeviceName,
				Ebs: &ec2.EbsBlockDevice{
					VolumeSize:          &request.RootSize,
					VolumeType:          &request.VolumeType,
					DeleteOnTermination: &request.DeleteOnTermination,
				},
			},
		},
	})

	if err != nil {
		return nil, err
	}

	if reservation == nil || len(reservation.Instances) != 1 {
		return nil, &ErrUnexpectedResponse{}
	}
	return reservation.Instances[0], nil
}

func (p *provisioner) blockUntilInstanceInState(instanceID string, instanceState string) error {
	return WaitUntil(p.sleepFunction, 30, 10*time.Second,
		func() (bool, error) {
			inst, err := getInstanceSync(p.client, instanceID)
			return inst != nil && *inst.State.Name == instanceState, err
		})
}

func (p *provisioner) NewRequestInstance() api.MachineRequest {
	return new(CreateInstanceRequest)
}

func (p *provisioner) CreateInstance(
	req api.MachineRequest) (<-chan api.CreateInstanceEvent, error) {

	request, is := req.(*CreateInstanceRequest)
	if !is {
		return nil, &ErrInvalidRequest{}
	}

	if err := request.Validate(); err != nil {
		return nil, err
	}

	events := make(chan api.CreateInstanceEvent)
	go func() {
		defer close(events)

		events <- api.CreateInstanceEvent{Type: api.CreateInstanceStarted}

		instance, err := createInstanceSync(p.client, *request)
		if err != nil {
			events <- api.CreateInstanceEvent{
				Error: err,
				Type:  api.CreateInstanceError,
			}
			return
		}

		err = p.blockUntilInstanceInState(*instance.InstanceId, ec2.InstanceStateNameRunning)
		if err != nil {
			events <- api.CreateInstanceEvent{
				Error: err,
				Type:  api.CreateInstanceError,
			}
			return
		}

		err = tagSync(p.client, *request, instance)
		if err != nil {
			events <- api.CreateInstanceEvent{
				Error: err,
				Type:  api.CreateInstanceError,
			}
			return
		}
		events <- api.CreateInstanceEvent{
			Type:       api.CreateInstanceCompleted,
			InstanceID: *instance.InstanceId,
		}
	}()

	return events, nil
}

func destroyInstanceSync(client ec2iface.EC2API, instanceID string) error {
	result, err := client.TerminateInstances(&ec2.TerminateInstancesInput{
		InstanceIds: []*string{&instanceID}})

	if err != nil {
		return err
	}

	if len(result.TerminatingInstances) == 1 {
		return nil
	}

	// There was no match for the instance ID.
	return &ErrInvalidRequest{}
}

func (p *provisioner) DestroyInstance(instanceID string) (<-chan api.DestroyInstanceEvent, error) {
	events := make(chan api.DestroyInstanceEvent)

	go func() {
		defer close(events)

		events <- api.DestroyInstanceEvent{Type: api.DestroyInstanceStarted}

		err := destroyInstanceSync(p.client, instanceID)
		if err != nil {
			events <- api.DestroyInstanceEvent{
				Type:  api.DestroyInstanceError,
				Error: err}
			return
		}

		err = p.blockUntilInstanceInState(instanceID, ec2.InstanceStateNameTerminated)
		if err != nil {
			events <- api.DestroyInstanceEvent{
				Error: err,
				Type:  api.DestroyInstanceError,
			}
			return
		}

		events <- api.DestroyInstanceEvent{Type: api.DestroyInstanceCompleted}
	}()

	return events, nil
}
<|endoftext|>


<commit_before>package daemon

import (
    "github.com/BluePecker/JwtAuth/daemon/service"
    "github.com/BluePecker/JwtAuth/service/router"
    "github.com/BluePecker/JwtAuth/service/router/token"
    "fmt"
    "github.com/kataras/iris"
    "github.com/kataras/iris/core/netutil"
    "github.com/BluePecker/JwtAuth/service/router/version"
)

func (d *Daemon) Shadow(ch chan struct{}) error {
    d.shadow = &service.Shadow{
        Routes: []router.Router{version.NewRouter(d)},
    }
    Listener, err := netutil.UNIX(d.Options.SockFile, 0666)
    if err != nil {
        return nil
    }
    return d.shadow.New(ch, iris.Listener(Listener))
}

func (d *Daemon) Rosiness(ch chan struct{}) error {
    d.rosiness = &service.Rosiness{
        Routes:[]router.Router{token.NewRouter(d)},
    }
    Addr := fmt.Sprintf("%s:%d", d.Options.Host, d.Options.Port)
    var runner iris.Runner
    if d.Options.TLS.Cert != "" && d.Options.TLS.Key != "" {
        runner = iris.TLS(Addr, d.Options.TLS.Cert, d.Options.TLS.Key)
    } else {
        runner = iris.Addr(Addr)
    }
    return d.rosiness.New(ch, runner)
}<commit_msg>add route<commit_after>package daemon

import (
	"github.com/BluePecker/JwtAuth/daemon/service"
	"github.com/BluePecker/JwtAuth/service/router"
	"fmt"
	"github.com/kataras/iris"
	"github.com/kataras/iris/core/netutil"
	"github.com/BluePecker/JwtAuth/service/router/token"
	"github.com/BluePecker/JwtAuth/service/router/version"
	"github.com/BluePecker/JwtAuth/service/router/signal"
)

func (d *Daemon) Shadow(ch chan struct{}) error {
	d.shadow = &service.Shadow{
		Routes: []router.Router{version.NewRouter(d), signal.NewRouter(d)},
	}
	Listener, err := netutil.UNIX(d.Options.SockFile, 0666)
	if err != nil {
		return nil
	}
	return d.shadow.New(ch, iris.Listener(Listener))
}

func (d *Daemon) Rosiness(ch chan struct{}) error {
	d.rosiness = &service.Rosiness{
		Routes: []router.Router{token.NewRouter(d)},
	}
	Addr := fmt.Sprintf("%s:%d", d.Options.Host, d.Options.Port)
	var runner iris.Runner
	if d.Options.TLS.Cert != "" && d.Options.TLS.Key != "" {
		runner = iris.TLS(Addr, d.Options.TLS.Cert, d.Options.TLS.Key)
	} else {
		runner = iris.Addr(Addr)
	}
	return d.rosiness.New(ch, runner)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

type mapInfo struct {
	start int64
	end   int64
}

// mappedAddresses gives the stack and heap addresses for a given pid
func mappedAdresses(pid uint) ([]mapInfo, error) {

	path := filepath.Join("/proc", fmt.Sprintf("%d", pid), "maps")
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	res := make([]mapInfo, 0)
	scanner := bufio.NewScanner(f)
	name, err := nameByPID(pid)
	if err != nil {
		return nil, err
	}
	goals := []string{"[heap]", "[stack]", name} // we want to look into the binary memory, its heap and its stack

	for scanner.Scan() {
		line := scanner.Text()

		items := strings.Split(line, " ")
		if len(items) <= 1 {
			continue
		}
		if stringInSlice(items[len(items)-1], goals) {
			fields := strings.Split(items[0], "-")
			start, _ := strconv.ParseInt(fields[0], 16, 64)
			end, _ := strconv.ParseInt(fields[1], 16, 64)
			info := mapInfo{start: start, end: end}
			res = append(res, info)
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return res, nil
}

func stringInSlice(a string, list []string) bool {
	for _, b := range list {
		if a == b {
			return true
		}
	}
	return false
}

func MemoryGrep(pid uint, str []byte) (bool, error) {
	maps, err := mappedAdresses(pid)
	path := filepath.Join("/proc", fmt.Sprintf("%d", pid), "mem")
	f, err := os.Open(path)
	if err != nil {
		return false, err
	}
	defer f.Close()

	res := false
	for _, region := range maps {
		found, err := searchString(str, region, f)
		if err != nil {
			return false, err
		}
		res = res || found
	}
	return res, nil
}

func nameByPID(pid uint) (string, error) {
	// inside /proc/[pid]/stat is the name of the binary between parentheses as second word
	// should be pathByPID (because we need to compare with the full path)
	path := filepath.Join("/proc", fmt.Sprintf("%d", pid), "stat")
	f, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer f.Close()
	scanner := bufio.NewScanner(f)
	scanner.Split(bufio.ScanWords)

	scanner.Scan() // discard first word
	scanner.Scan()

	res := scanner.Text()
	res = strings.TrimPrefix(res, "(")
	res = strings.TrimSuffix(res, ")")

	return res, nil
}

func searchString(str []byte, region mapInfo, memory *os.File) (bool, error) {
	buf := make([]byte, len(str))
	for pos := region.start; pos < region.end-int64(len(str)); pos++ {
		_, err := memory.ReadAt(buf, pos)
		if err != nil {
			return false, err
		}
		if areEqual(str, buf) {
			return true, nil
		}
	}
	return false, nil
}

func areEqual(s1 []byte, s2 []byte) bool {
	for index, _ := range s1 {
		if s1[index] != s2[index] {
			return false
		}
	}
	return true
}

// test main
func main() {
	var pid uint
	var str []byte
	fmt.Scanf("%d", &pid)
	name, _ := nameByPID(pid)
	fmt.Println(name)

	fmt.Scanf("%s", &str)
	res, err := MemoryGrep(pid, str)
	if err != nil {
		fmt.Println("Error", err)
	}
	if res {
		fmt.Println("Encontrado")
	}
}
<commit_msg>Grep Mem Linux WIP<commit_after>package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

type mapInfo struct {
	start int64
	end   int64
}

type memManagerData struct {
	pos int64
	buf []byte
	memory *os.File
}

//TODO: write memManager
//initializeMemManager returns the memManagerData structure needed to make the subsecuent calls to readAtMemManager
func initializeMemManager(region mapInfo, memory *os.File, length uint) (memManagerData, error){
	res := memManagerData{pos: 0, buf: , memory: memory}
}

//readAtMemManager
func readAtMemManager(memManagerData, buf []byte, pos uint){

}

// mappedAddresses gives the stack and heap addresses for a given pid
func mappedAdresses(pid uint) ([]mapInfo, error) {

	path := filepath.Join("/proc", fmt.Sprintf("%d", pid), "maps")
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	res := make([]mapInfo, 0)
	scanner := bufio.NewScanner(f)
	name, err := nameByPID(pid)
	if err != nil {
		return nil, err
	}
	goals := []string{"[heap]", "[stack]", name} // we want to look into the binary memory, its heap and its stack

	for scanner.Scan() {
		line := scanner.Text()

		items := strings.Split(line, " ")
		if len(items) <= 1 {
			continue
		}
		if stringInSlice(items[len(items)-1], goals) {
			fields := strings.Split(items[0], "-")
			start, _ := strconv.ParseInt(fields[0], 16, 64)
			end, _ := strconv.ParseInt(fields[1], 16, 64)
			info := mapInfo{start: start, end: end}
			res = append(res, info)
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return res, nil
}

func stringInSlice(a string, list []string) bool {
	for _, b := range list {
		if a == b {
			return true
		}
	}
	return false
}

func MemoryGrep(pid uint, str []byte) (bool, error) {
	maps, err := mappedAdresses(pid)
	path := filepath.Join("/proc", fmt.Sprintf("%d", pid), "mem")
	f, err := os.Open(path)
	if err != nil {
		return false, err
	}
	defer f.Close()

	res := false
	for _, region := range maps {
		found, err := searchString(str, region, f)
		if err != nil {
			return false, err
		}
		res = res || found
	}
	return res, nil
}

func nameByPID(pid uint) (string, error) {
	// inside /proc/[pid]/stat is the name of the binary between parentheses as second word
	// should be pathByPID (because we need to compare with the full path)
	path := filepath.Join("/proc", fmt.Sprintf("%d", pid), "stat")
	f, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer f.Close()
	scanner := bufio.NewScanner(f)
	scanner.Split(bufio.ScanWords)

	scanner.Scan() // discard first word
	scanner.Scan()

	res := scanner.Text()
	res = strings.TrimPrefix(res, "(")
	res = strings.TrimSuffix(res, ")")

	return res, nil
}

func searchString(str []byte, region mapInfo, memory *os.File) (bool, error) {
	length = int64(math.Min(512, len(str))) // our buffer will be 512 bytes long unless the string we're looking for is bigger
	buf := make([]byte, length)
	mmanager := initializeMemManager(region, memory, len(str))
	pos = region.start
	for pos < region.end-length {
		_, err := readAtMemManager(mmanager, buf, pos)
		if err != nil {
			return false, err
		}
		if areEqual(str, buf) {
			return true, nil
		}
		pos += length
	}
	return false, nil
}

func areEqual(s1 []byte, s2 []byte) bool {
	for index, _ := range s1 {
		if s1[index] != s2[index] {
			return false
		}
	}
	return true
}

// test main
func main() {
	var pid uint
	var str []byte
	fmt.Scanf("%d", &pid)
	name, _ := nameByPID(pid)
	fmt.Println(name)

	fmt.Scanf("%s", &str)
	res, err := MemoryGrep(pid, str)
	if err != nil {
		fmt.Println("Error", err)
	}
	if res {
		fmt.Println("Encontrado")
	}
}
<|endoftext|>


<commit_before>package collector

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"strconv"
	"strings"

	"github.com/boynux/squid-exporter/types"
)

/*CacheObjectClient holds information about squid manager */
type CacheObjectClient struct {
	hostname string
	port     int
	headers  map[string]string
}

/*SquidClient provides functionality to fetch squid metrics */
type SquidClient interface {
	GetCounters() (types.Counters, error)
}

const (
	requestProtocol = "GET cache_object://localhost/%s HTTP/1.0"
)

/*NewCacheObjectClient initializes a new cache client */
func NewCacheObjectClient(hostname string, port int) *CacheObjectClient {
	return &CacheObjectClient{
		hostname,
		port,
		map[string]string{},
	}
}

/*GetCounters fetches counters from squid cache manager */
func (c *CacheObjectClient) GetCounters() (types.Counters, error) {
	conn, err := connect(c.hostname, c.port)

	if err != nil {
		return types.Counters{}, err
	}

	r, err := get(conn, "counters")

	var counters types.Counters

	// TODO: Move to another func
	reader := bufio.NewReader(r.Body)

	for {
		line, err := reader.ReadString('\n')

		if err == io.EOF {
			break
		}
		if err != nil {
			return nil, err
		}

		c, err := decodeCounterStrings(line)
		if err != nil {
			log.Println(err)
		} else {
			counters = append(counters, c)
		}
	}

	return counters, err
}

func connect(hostname string, port int) (net.Conn, error) {
	return net.Dial("tcp", fmt.Sprintf("%s:%d", hostname, port))
}

func get(conn net.Conn, path string) (*http.Response, error) {
	rBody := []string{
		fmt.Sprintf(requestProtocol, path),
		"Host: localhost",
		"User-Agent: squidclient/3.5.12",
		"Accept: */*",
		"\r\n",
	}

	request := strings.Join(rBody, "\r\n")

	fmt.Fprintf(conn, request)
	return http.ReadResponse(bufio.NewReader(conn), nil)
}

func decodeCounterStrings(line string) (types.Counter, error) {
	if equal := strings.Index(line, "="); equal >= 0 {
		if key := strings.TrimSpace(line[:equal]); len(key) > 0 {
			value := ""
			if len(line) > equal {
				value = strings.TrimSpace(line[equal+1:])
			}

			if i, err := strconv.ParseFloat(value, 64); err == nil {
				return types.Counter{key, i}, nil
			}
		}
	}

	return types.Counter{}, errors.New("could not parse line")
}
<commit_msg>Fix sample_time parsing issue<commit_after>package collector

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"strconv"
	"strings"

	"github.com/boynux/squid-exporter/types"
)

/*CacheObjectClient holds information about squid manager */
type CacheObjectClient struct {
	hostname string
	port     int
	headers  map[string]string
}

/*SquidClient provides functionality to fetch squid metrics */
type SquidClient interface {
	GetCounters() (types.Counters, error)
}

const (
	requestProtocol = "GET cache_object://localhost/%s HTTP/1.0"
)

/*NewCacheObjectClient initializes a new cache client */
func NewCacheObjectClient(hostname string, port int) *CacheObjectClient {
	return &CacheObjectClient{
		hostname,
		port,
		map[string]string{},
	}
}

/*GetCounters fetches counters from squid cache manager */
func (c *CacheObjectClient) GetCounters() (types.Counters, error) {
	conn, err := connect(c.hostname, c.port)

	if err != nil {
		return types.Counters{}, err
	}

	r, err := get(conn, "counters")

	var counters types.Counters

	// TODO: Move to another func
	reader := bufio.NewReader(r.Body)

	for {
		line, err := reader.ReadString('\n')

		if err == io.EOF {
			break
		}
		if err != nil {
			return nil, err
		}

		c, err := decodeCounterStrings(line)
		if err != nil {
			log.Println(err)
		} else {
			counters = append(counters, c)
		}
	}

	return counters, err
}

func connect(hostname string, port int) (net.Conn, error) {
	return net.Dial("tcp", fmt.Sprintf("%s:%d", hostname, port))
}

func get(conn net.Conn, path string) (*http.Response, error) {
	rBody := []string{
		fmt.Sprintf(requestProtocol, path),
		"Host: localhost",
		"User-Agent: squidclient/3.5.12",
		"Accept: */*",
		"\r\n",
	}

	request := strings.Join(rBody, "\r\n")

	fmt.Fprintf(conn, request)
	return http.ReadResponse(bufio.NewReader(conn), nil)
}

func decodeCounterStrings(line string) (types.Counter, error) {
	if equal := strings.Index(line, "="); equal >= 0 {
		if key := strings.TrimSpace(line[:equal]); len(key) > 0 {
			value := ""
			if len(line) > equal {
				value = strings.TrimSpace(line[equal+1:])
			}

			// Remove additional formating string from `sample_time`
			if slices := strings.Split(value, " "); len(slices) > 0 {
				value = slices[0]
			}

			if i, err := strconv.ParseFloat(value, 64); err == nil {
				return types.Counter{key, i}, nil
			}
		}
	}

	return types.Counter{}, errors.New("could not parse line: " + line)
}
<|endoftext|>