<commit_before>package labreserved

import (
	"log"
	"testing"
)

var testBlobId = 7357

func TestBlobSet(t *testing.T) {

	if testing.Short() {
		return
	}

	testStr := `{
  		"id": "xxxx",
  		"version": "v1.0",
  		"name": "Our team #10 blob",
  		"content": "Wooot",
  		"tag": ""
		}`

	err := PostBlob(testBlobId, testStr)
	if err != nil {
		t.Error(err)
	}

	blob, err := GetBlob(testBlobId)
	if err != nil {
		t.Error(err)
	}
	if testing.Verbose() {
		log.Println("Got decoded blob content: ", string(blob))
	}

	if blob != testStr {
		t.Errorf("blob(%s) doesn't match (%s)", blob, testStr)
	}

}
<commit_msg>make blob test use accurately formatted data<commit_after>package labreserved

import (
	"log"
	"testing"
)

var testBlobId = 7357

func TestBlobSet(t *testing.T) {

	if testing.Short() {
		return
	}

	testStr := `{
		"server11": {
			"description": "from booo!",
			"name": "server11",
			"reservations": [
			{
				"begin": "2016-09-06T00:09:04.032-04:00",
				"hoursheld": 3,
				"username": "tom"
			},
			{
				"begin": "2016-09-06T00:09:04.032-04:00",
				"hoursheld": 3,
				"username": "tom"
			}
			]
		},
		"server12": {
			"description": "from booo!",
			"name": "server12",
			"reservations": [
			{
				"begin": "2016-09-06T00:09:04.032-04:00",
				"hoursheld": 3,
				"username": "tom"
			}
			]
		},
		"server13": {
			"description": "from booo!",
			"name": "server13"
		},
		"server9": {
			"description": "from jasmine",
			"name": "server9"
		}
	} `

	err := PostBlob(testBlobId, testStr)
	if err != nil {
		t.Error(err)
	}

	blob, err := GetBlob(testBlobId)
	if err != nil {
		t.Error(err)
	}
	if testing.Verbose() {
		log.Println("Got decoded blob content: ", string(blob))
	}

	if blob != testStr {
		t.Errorf("blob(%s) doesn't match (%s)", blob, testStr)
	}

}
<|endoftext|>


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

package prober

import (
	"context"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"math/big"
	"net"
	"os"
	"testing"
	"time"

	"github.com/go-kit/log"

	"github.com/prometheus/client_golang/prometheus"
	dto "github.com/prometheus/client_model/go"
)

// Check if expected results are in the registry
func checkRegistryResults(expRes map[string]float64, mfs []*dto.MetricFamily, t *testing.T) {
	res := make(map[string]float64)
	for i := range mfs {
		res[mfs[i].GetName()] = mfs[i].Metric[0].GetGauge().GetValue()
	}
	for k, v := range expRes {
		val, ok := res[k]
		if !ok {
			t.Fatalf("Expected metric %v not found in returned metrics", k)
		}
		if val != v {
			t.Fatalf("Expected: %v: %v, got: %v: %v", k, v, k, val)
		}
	}
}

// Check if expected labels are in the registry
func checkRegistryLabels(expRes map[string]map[string]string, mfs []*dto.MetricFamily, t *testing.T) {
	results := make(map[string]map[string]string)
	for _, mf := range mfs {
		result := make(map[string]string)
		for _, metric := range mf.Metric {
			for _, l := range metric.GetLabel() {
				result[l.GetName()] = l.GetValue()
			}
		}
		results[mf.GetName()] = result
	}

	for metric, labelValues := range expRes {
		if _, ok := results[metric]; !ok {
			t.Fatalf("Expected metric %v not found in returned metrics", metric)
		}
		for name, exp := range labelValues {
			val, ok := results[metric][name]
			if !ok {
				t.Fatalf("Expected label %v for metric %v not found in returned metrics", val, name)
			}
			if val != exp {
				t.Fatalf("Expected: %v{%q=%q}, got: %v{%q=%q}", metric, name, exp, metric, name, val)
			}
		}
	}
}

func generateCertificateTemplate(expiry time.Time, IPAddressSAN bool) *x509.Certificate {
	template := &x509.Certificate{
		BasicConstraintsValid: true,
		SubjectKeyId:          []byte{1},
		SerialNumber:          big.NewInt(1),
		Subject: pkix.Name{
			Organization: []string{"Example Org"},
		},
		NotBefore:   time.Now(),
		NotAfter:    expiry,
		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
		KeyUsage:    x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
	}

	template.DNSNames = append(template.DNSNames, "localhost")
	if IPAddressSAN {
		template.IPAddresses = append(template.IPAddresses, net.ParseIP("127.0.0.1"))
		template.IPAddresses = append(template.IPAddresses, net.ParseIP("::1"))
	}

	return template
}

func generateCertificate(template, parent *x509.Certificate, publickey *rsa.PublicKey, privatekey *rsa.PrivateKey) (*x509.Certificate, []byte) {
	derCert, err := x509.CreateCertificate(rand.Reader, template, template, publickey, privatekey)
	if err != nil {
		panic(fmt.Sprintf("Error signing test-certificate: %s", err))
	}
	cert, err := x509.ParseCertificate(derCert)
	if err != nil {
		panic(fmt.Sprintf("Error parsing test-certificate: %s", err))
	}
	pemCert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derCert})
	return cert, pemCert

}

func generateSignedCertificate(template, parentCert *x509.Certificate, parentKey *rsa.PrivateKey) (*x509.Certificate, []byte, *rsa.PrivateKey) {
	privatekey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		panic(fmt.Sprintf("Error creating rsa key: %s", err))
	}
	cert, pemCert := generateCertificate(template, parentCert, &privatekey.PublicKey, parentKey)
	return cert, pemCert, privatekey
}

func generateSelfSignedCertificate(template *x509.Certificate) (*x509.Certificate, []byte, *rsa.PrivateKey) {
	privatekey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		panic(fmt.Sprintf("Error creating rsa key: %s", err))
	}
	publickey := &privatekey.PublicKey

	cert, pemCert := generateCertificate(template, template, publickey, privatekey)
	return cert, pemCert, privatekey
}

func generateSelfSignedCertificateWithPrivateKey(template *x509.Certificate, privatekey *rsa.PrivateKey) (*x509.Certificate, []byte) {
	publickey := &privatekey.PublicKey
	cert, pemCert := generateCertificate(template, template, publickey, privatekey)
	return cert, pemCert
}

func TestChooseProtocol(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping network dependent test")
	}
	ctx := context.Background()
	registry := prometheus.NewPedanticRegistry()
	w := log.NewSyncWriter(os.Stderr)
	logger := log.NewLogfmtLogger(w)

	ip, _, err := chooseProtocol(ctx, "ip4", true, "ipv6.google.com", registry, logger)
	if err != nil {
		t.Error(err)
	}
	if ip == nil || ip.IP.To4() != nil {
		t.Error("with fallback it should answer")
	}

	registry = prometheus.NewPedanticRegistry()

	ip, _, err = chooseProtocol(ctx, "ip4", false, "ipv6.google.com", registry, logger)
	if err != nil && err.Error() != "address ipv6.google.com: no suitable address found" {
		t.Error(err)
	} else if err == nil {
		t.Error("should set error")
	}
	if ip != nil {
		t.Error("without fallback it should not answer")
	}
}

func checkMetrics(expected map[string]map[string]map[string]struct{}, mfs []*dto.MetricFamily, t *testing.T) {
	type (
		valueValidation struct {
			found bool
		}
		labelValidation struct {
			found  bool
			values map[string]valueValidation
		}
		metricValidation struct {
			found  bool
			labels map[string]labelValidation
		}
	)

	foundMetrics := map[string]metricValidation{}

	for mname, labels := range expected {
		var mv metricValidation
		if labels != nil {
			mv.labels = map[string]labelValidation{}
			for lname, values := range labels {
				var lv labelValidation
				if values != nil {
					lv.values = map[string]valueValidation{}
					for vname := range values {
						lv.values[vname] = valueValidation{}
					}
				}
				mv.labels[lname] = lv
			}
		}
		foundMetrics[mname] = mv
	}

	for _, mf := range mfs {
		info, wanted := foundMetrics[mf.GetName()]
		if !wanted {
			continue
		}
		info.found = true
		for _, metric := range mf.GetMetric() {
			if info.labels == nil {
				continue
			}
			for _, lp := range metric.Label {
				if label, labelWanted := info.labels[lp.GetName()]; labelWanted {
					label.found = true
					if label.values != nil {
						if value, wanted := label.values[lp.GetValue()]; !wanted {
							t.Fatalf("Unexpected label %s=%s", lp.GetName(), lp.GetValue())
						} else if value.found {
							t.Fatalf("Label %s=%s duplicated", lp.GetName(), lp.GetValue())
						}
						label.values[lp.GetValue()] = valueValidation{found: true}
					}
					info.labels[lp.GetName()] = label
				}
			}
		}
		foundMetrics[mf.GetName()] = info
	}

	for mname, m := range foundMetrics {
		if !m.found {
			t.Fatalf("metric %s wanted, not found", mname)
		}
		for lname, label := range m.labels {
			if !label.found {
				t.Fatalf("metric %s, label %s wanted, not found", mname, lname)
			}
			for vname, value := range label.values {
				if !value.found {
					t.Fatalf("metric %s, label %s, value %s wanted, not found", mname, lname, vname)
				}
			}
		}
	}
}
<commit_msg>Fixup chooseProtocol test.<commit_after>// Copyright 2016 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package prober

import (
	"context"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"math/big"
	"net"
	"os"
	"testing"
	"time"

	"github.com/go-kit/log"

	"github.com/prometheus/client_golang/prometheus"
	dto "github.com/prometheus/client_model/go"
)

// Check if expected results are in the registry
func checkRegistryResults(expRes map[string]float64, mfs []*dto.MetricFamily, t *testing.T) {
	res := make(map[string]float64)
	for i := range mfs {
		res[mfs[i].GetName()] = mfs[i].Metric[0].GetGauge().GetValue()
	}
	for k, v := range expRes {
		val, ok := res[k]
		if !ok {
			t.Fatalf("Expected metric %v not found in returned metrics", k)
		}
		if val != v {
			t.Fatalf("Expected: %v: %v, got: %v: %v", k, v, k, val)
		}
	}
}

// Check if expected labels are in the registry
func checkRegistryLabels(expRes map[string]map[string]string, mfs []*dto.MetricFamily, t *testing.T) {
	results := make(map[string]map[string]string)
	for _, mf := range mfs {
		result := make(map[string]string)
		for _, metric := range mf.Metric {
			for _, l := range metric.GetLabel() {
				result[l.GetName()] = l.GetValue()
			}
		}
		results[mf.GetName()] = result
	}

	for metric, labelValues := range expRes {
		if _, ok := results[metric]; !ok {
			t.Fatalf("Expected metric %v not found in returned metrics", metric)
		}
		for name, exp := range labelValues {
			val, ok := results[metric][name]
			if !ok {
				t.Fatalf("Expected label %v for metric %v not found in returned metrics", val, name)
			}
			if val != exp {
				t.Fatalf("Expected: %v{%q=%q}, got: %v{%q=%q}", metric, name, exp, metric, name, val)
			}
		}
	}
}

func generateCertificateTemplate(expiry time.Time, IPAddressSAN bool) *x509.Certificate {
	template := &x509.Certificate{
		BasicConstraintsValid: true,
		SubjectKeyId:          []byte{1},
		SerialNumber:          big.NewInt(1),
		Subject: pkix.Name{
			Organization: []string{"Example Org"},
		},
		NotBefore:   time.Now(),
		NotAfter:    expiry,
		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
		KeyUsage:    x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
	}

	template.DNSNames = append(template.DNSNames, "localhost")
	if IPAddressSAN {
		template.IPAddresses = append(template.IPAddresses, net.ParseIP("127.0.0.1"))
		template.IPAddresses = append(template.IPAddresses, net.ParseIP("::1"))
	}

	return template
}

func generateCertificate(template, parent *x509.Certificate, publickey *rsa.PublicKey, privatekey *rsa.PrivateKey) (*x509.Certificate, []byte) {
	derCert, err := x509.CreateCertificate(rand.Reader, template, template, publickey, privatekey)
	if err != nil {
		panic(fmt.Sprintf("Error signing test-certificate: %s", err))
	}
	cert, err := x509.ParseCertificate(derCert)
	if err != nil {
		panic(fmt.Sprintf("Error parsing test-certificate: %s", err))
	}
	pemCert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derCert})
	return cert, pemCert

}

func generateSignedCertificate(template, parentCert *x509.Certificate, parentKey *rsa.PrivateKey) (*x509.Certificate, []byte, *rsa.PrivateKey) {
	privatekey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		panic(fmt.Sprintf("Error creating rsa key: %s", err))
	}
	cert, pemCert := generateCertificate(template, parentCert, &privatekey.PublicKey, parentKey)
	return cert, pemCert, privatekey
}

func generateSelfSignedCertificate(template *x509.Certificate) (*x509.Certificate, []byte, *rsa.PrivateKey) {
	privatekey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		panic(fmt.Sprintf("Error creating rsa key: %s", err))
	}
	publickey := &privatekey.PublicKey

	cert, pemCert := generateCertificate(template, template, publickey, privatekey)
	return cert, pemCert, privatekey
}

func generateSelfSignedCertificateWithPrivateKey(template *x509.Certificate, privatekey *rsa.PrivateKey) (*x509.Certificate, []byte) {
	publickey := &privatekey.PublicKey
	cert, pemCert := generateCertificate(template, template, publickey, privatekey)
	return cert, pemCert
}

func TestChooseProtocol(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping network dependent test")
	}
	ctx := context.Background()
	registry := prometheus.NewPedanticRegistry()
	w := log.NewSyncWriter(os.Stderr)
	logger := log.NewLogfmtLogger(w)

	ip, _, err := chooseProtocol(ctx, "ip4", true, "ipv6.google.com", registry, logger)
	if err != nil {
		t.Error(err)
	}
	if ip == nil || ip.IP.To4() != nil {
		t.Error("with fallback it should answer")
	}

	registry = prometheus.NewPedanticRegistry()

	ip, _, err = chooseProtocol(ctx, "ip4", false, "ipv6.google.com", registry, logger)
	if err != nil && !err.(*net.DNSError).IsNotFound {
		t.Error(err)
	} else if err == nil {
		t.Error("should set error")
	}
	if ip != nil {
		t.Error("without fallback it should not answer")
	}
}

func checkMetrics(expected map[string]map[string]map[string]struct{}, mfs []*dto.MetricFamily, t *testing.T) {
	type (
		valueValidation struct {
			found bool
		}
		labelValidation struct {
			found  bool
			values map[string]valueValidation
		}
		metricValidation struct {
			found  bool
			labels map[string]labelValidation
		}
	)

	foundMetrics := map[string]metricValidation{}

	for mname, labels := range expected {
		var mv metricValidation
		if labels != nil {
			mv.labels = map[string]labelValidation{}
			for lname, values := range labels {
				var lv labelValidation
				if values != nil {
					lv.values = map[string]valueValidation{}
					for vname := range values {
						lv.values[vname] = valueValidation{}
					}
				}
				mv.labels[lname] = lv
			}
		}
		foundMetrics[mname] = mv
	}

	for _, mf := range mfs {
		info, wanted := foundMetrics[mf.GetName()]
		if !wanted {
			continue
		}
		info.found = true
		for _, metric := range mf.GetMetric() {
			if info.labels == nil {
				continue
			}
			for _, lp := range metric.Label {
				if label, labelWanted := info.labels[lp.GetName()]; labelWanted {
					label.found = true
					if label.values != nil {
						if value, wanted := label.values[lp.GetValue()]; !wanted {
							t.Fatalf("Unexpected label %s=%s", lp.GetName(), lp.GetValue())
						} else if value.found {
							t.Fatalf("Label %s=%s duplicated", lp.GetName(), lp.GetValue())
						}
						label.values[lp.GetValue()] = valueValidation{found: true}
					}
					info.labels[lp.GetName()] = label
				}
			}
		}
		foundMetrics[mf.GetName()] = info
	}

	for mname, m := range foundMetrics {
		if !m.found {
			t.Fatalf("metric %s wanted, not found", mname)
		}
		for lname, label := range m.labels {
			if !label.found {
				t.Fatalf("metric %s, label %s wanted, not found", mname, lname)
			}
			for vname, value := range label.values {
				if !value.found {
					t.Fatalf("metric %s, label %s, value %s wanted, not found", mname, lname, vname)
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>package products

import (
	"time"
)

// Product represents a software product within the system for identification
// across multiple sources
type Product struct {
	ID         int           `json:"id" xml:"id"`
	Name       string        `json:"name" xml:"name"`
	Org        string        `json:"org" xml:"org"`
	Version    string        `json:"version" xml:"version"`
	Up         string        `json:"up" xml:"up"`
	Edition    string        `json:"edition" xml:"edition"`
	Aliases    interface{}   `json:"aliases" xml:"aliases"`
	CreatedAt  time.Time     `json:"created_at" xml:"created_at"`
	UpdatedAt  time.Time     `json:"updated_at" xml:"updated_at"`
	Title      string        `json:"title" xml:"title"`
	References []interface{} `json:"references" xml:"references"`
	Part       string        `json:"part" xml:"part"`
	Language   string        `json:"language" xml:"language"`
	ExternalID string        `json:"external_id" xml:"external_id"`
	Sources    []Source      `json:"source" xml:"source"`
}

// Source represents information about where the product data came from
type Source struct {
	ID           int       `json:"id" xml:"id"`
	Name         string    `json:"name" xml:"name"`
	Description  string    `json:"description" xml:"description"`
	CreatedAt    time.Time `json:"created_at" xml:"created_at"`
	UpdatedAt    time.Time `json:"updated_at" xml:"updated_at"`
	Attribution  string    `json:"attribution" xml:"attribution"`
	License      string    `json:"license" xml:"license"`
	CopyrightURL string    `json:"copyright_url" xml:"copyright_url"`
}

// ProductSearchResult represents information about a product as well as
// other info, like Git repository, committer counts, etc
type ProductSearchResult struct {
	Product   Product `json:"product" xml:"product"`
	Github    Github  `json:"github,omitempty" xml:"github,omitempty"`
	MeanScore float64 `json:"mean_score" xml:"mean_score"`
	Scores    []ProductSearchScore
}

// ProductSearchScore represents the TF;IDF score for a given search result
// and a given search term
type ProductSearchScore struct {
	Term  string  `json:"term" xml:"term"`
	Score float64 `json:"score" xml:"term"`
}

// Github represents information from Github about a given repository
type Github struct {
	URI            string `json:"uri" xml:"uri"`
	CommitterCount uint   `json:"committer_count" xml:"committer_count"`
}
<commit_msg>adding json,xml tags to Scores element on ProductSearchResult<commit_after>package products

import (
	"time"
)

// Product represents a software product within the system for identification
// across multiple sources
type Product struct {
	ID         int           `json:"id" xml:"id"`
	Name       string        `json:"name" xml:"name"`
	Org        string        `json:"org" xml:"org"`
	Version    string        `json:"version" xml:"version"`
	Up         string        `json:"up" xml:"up"`
	Edition    string        `json:"edition" xml:"edition"`
	Aliases    interface{}   `json:"aliases" xml:"aliases"`
	CreatedAt  time.Time     `json:"created_at" xml:"created_at"`
	UpdatedAt  time.Time     `json:"updated_at" xml:"updated_at"`
	Title      string        `json:"title" xml:"title"`
	References []interface{} `json:"references" xml:"references"`
	Part       string        `json:"part" xml:"part"`
	Language   string        `json:"language" xml:"language"`
	ExternalID string        `json:"external_id" xml:"external_id"`
	Sources    []Source      `json:"source" xml:"source"`
}

// Source represents information about where the product data came from
type Source struct {
	ID           int       `json:"id" xml:"id"`
	Name         string    `json:"name" xml:"name"`
	Description  string    `json:"description" xml:"description"`
	CreatedAt    time.Time `json:"created_at" xml:"created_at"`
	UpdatedAt    time.Time `json:"updated_at" xml:"updated_at"`
	Attribution  string    `json:"attribution" xml:"attribution"`
	License      string    `json:"license" xml:"license"`
	CopyrightURL string    `json:"copyright_url" xml:"copyright_url"`
}

// ProductSearchResult represents information about a product as well as
// other info, like Git repository, committer counts, etc
type ProductSearchResult struct {
	Product   Product              `json:"product" xml:"product"`
	Github    Github               `json:"github,omitempty" xml:"github,omitempty"`
	MeanScore float64              `json:"mean_score" xml:"mean_score"`
	Scores    []ProductSearchScore `json:"scores" "xml:"scores"`
}

// ProductSearchScore represents the TF;IDF score for a given search result
// and a given search term
type ProductSearchScore struct {
	Term  string  `json:"term" xml:"term"`
	Score float64 `json:"score" xml:"term"`
}

// Github represents information from Github about a given repository
type Github struct {
	URI            string `json:"uri" xml:"uri"`
	CommitterCount uint   `json:"committer_count" xml:"committer_count"`
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
)

const validFilenameExtension = ".md"
const couldNotFindPostErrorMessage = "Could not find post"

type BlogPostFilter func(post *BlogPost, index int, stop *bool) bool
type BlogPosts []*BlogPost

func (b BlogPosts) Len() int {
	return len(b)
}

func (b BlogPosts) Swap(i, j int) {
	b[i], b[j] = b[j], b[i]
}

func (b BlogPosts) Less(i, j int) bool {

	// We use "After" instead of "Before" to get posts in descending order
	return b[i].Metadata.Date.After(b[j].Metadata.Date)
}

func (b BlogPosts) Filter(filter BlogPostFilter) BlogPosts {
	filteredPosts := BlogPosts{}

	stop := new(bool)
	*stop = false

	for index, post := range b {
		if filter(post, index, stop) {
			filteredPosts = append(filteredPosts, post)
		}

		if *stop {
			break
		}
	}

	return filteredPosts
}

func (b BlogPosts) FilteredPosts(term string, start int, count int) (BlogPosts, int) {
	var filteredPosts BlogPosts

	if len(term) > 0 {
		filteredPosts = b.Filter(func(post *BlogPost, index int, stop *bool) bool {
			return post.ContainsTerm(term)
		})
	} else {
		filteredPosts = b
	}

	if start > len(filteredPosts) {
		return BlogPosts{}, 0
	}

	if start+count > len(filteredPosts) {
		count = len(filteredPosts) - start
	}

	return filteredPosts[start : start+count], len(filteredPosts)
}

func (b BlogPosts) PostWithUrl(url string) (*BlogPost, error) {
	for _, post := range b {
		if post.Url == url {
			return post, nil
		}
	}

	err := errors.New(couldNotFindPostErrorMessage)

	return nil, err
}

func (b BlogPosts) PostsWithTag(tag string, start int, count int) (BlogPosts, int) {

	filteredPosts := b.Filter(func(post *BlogPost, index int, stop *bool) bool {
		return post.ContainsTag(tag)
	})

	if start > len(filteredPosts) {
		return BlogPosts{}, 0
	}

	if start+count > len(filteredPosts) {
		count = len(filteredPosts) - start
	}

	return filteredPosts[start : start+count], len(filteredPosts)
}

func (b BlogPosts) PostWithId(id int) (*BlogPost, error) {
	for _, post := range b {
		if post.Metadata.Id == id {
			return post, nil
		}
	}

	err := errors.New(couldNotFindPostErrorMessage)

	return nil, err
}
<commit_msg>Removed unnecessary heap-allocated bool.<commit_after>package main

import (
	"errors"
)

const validFilenameExtension = ".md"
const couldNotFindPostErrorMessage = "Could not find post"

type BlogPostFilter func(post *BlogPost, index int, stop *bool) bool
type BlogPosts []*BlogPost

func (b BlogPosts) Len() int {
	return len(b)
}

func (b BlogPosts) Swap(i, j int) {
	b[i], b[j] = b[j], b[i]
}

func (b BlogPosts) Less(i, j int) bool {

	// We use "After" instead of "Before" to get posts in descending order
	return b[i].Metadata.Date.After(b[j].Metadata.Date)
}

func (b BlogPosts) Filter(filter BlogPostFilter) BlogPosts {
	filteredPosts := BlogPosts{}

	stop := false

	for index, post := range b {
		if filter(post, index, &stop) {
			filteredPosts = append(filteredPosts, post)
		}

		if stop {
			break
		}
	}

	return filteredPosts
}

func (b BlogPosts) FilteredPosts(term string, start int, count int) (BlogPosts, int) {
	var filteredPosts BlogPosts

	if len(term) > 0 {
		filteredPosts = b.Filter(func(post *BlogPost, index int, stop *bool) bool {
			return post.ContainsTerm(term)
		})
	} else {
		filteredPosts = b
	}

	if start > len(filteredPosts) {
		return BlogPosts{}, 0
	}

	if start+count > len(filteredPosts) {
		count = len(filteredPosts) - start
	}

	return filteredPosts[start : start+count], len(filteredPosts)
}

func (b BlogPosts) PostWithUrl(url string) (*BlogPost, error) {
	for _, post := range b {
		if post.Url == url {
			return post, nil
		}
	}

	err := errors.New(couldNotFindPostErrorMessage)

	return nil, err
}

func (b BlogPosts) PostsWithTag(tag string, start int, count int) (BlogPosts, int) {

	filteredPosts := b.Filter(func(post *BlogPost, index int, stop *bool) bool {
		return post.ContainsTag(tag)
	})

	if start > len(filteredPosts) {
		return BlogPosts{}, 0
	}

	if start+count > len(filteredPosts) {
		count = len(filteredPosts) - start
	}

	return filteredPosts[start : start+count], len(filteredPosts)
}

func (b BlogPosts) PostWithId(id int) (*BlogPost, error) {
	for _, post := range b {
		if post.Metadata.Id == id {
			return post, nil
		}
	}

	err := errors.New(couldNotFindPostErrorMessage)

	return nil, err
}
<|endoftext|>


<commit_before>// Copyright 2017 The Bazel 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.

package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"time"
)

var Version = "Development"

var overrideableStartupFlags []string = []string{
	"--bazelrc",
}

var overrideableBazelFlags []string = []string{
	"--action_env",
	"--announce_rc",
	"--config=",
	"--curses=no",
	"--define",
	"--features=",
	"--keep_going",
	"-k",
	"--nostamp",
	"--output_groups=",
	"--override_repository",
	"--repo_env",
	"--runs_per_test",
	"--stamp",
	"--strategy",
	"--test_arg",
	"--test_env",
	"--test_filter",
	"--test_output=",
	"--test_timeout",
}

var debounceDuration = flag.Duration("debounce", 100*time.Millisecond, "Debounce duration")
var logToFile = flag.String("log_to_file", "-", "Log iBazel stderr to a file instead of os.Stderr")

func usage() {
	fmt.Fprintf(os.Stderr, `iBazel - Version %s

A file watcher for Bazel. Whenever a source file used in a specified
target, run, build, or test the specified targets.

Usage:

ibazel build|test|run [flags] targets...

Example:

ibazel test //path/to/my/testing:target
ibazel test //path/to/my/testing/targets/...
ibazel run //path/to/my/runnable:target -- --arguments --for_your=binary
ibazel build //path/to/my/buildable:target

Supported Bazel startup flags:
  %s

Supported Bazel command flags:
  %s

To add to this list, edit
https://github.com/bazelbuild/bazel-watcher/blob/master/ibazel/main.go

iBazel flags:
`, Version, strings.Join(overrideableStartupFlags, "\n  "), strings.Join(overrideableBazelFlags, "\n  "))
	flag.PrintDefaults()
}

func isOverrideable(arg string, overrideables []string) bool {
	for _, overrideable := range overrideables {
		if strings.HasPrefix(arg, overrideable) {
			return true
		}
	}
	return false
}

func isOverrideableStartupFlag(arg string) bool {
	return isOverrideable(arg, overrideableStartupFlags)
}

func isOverrideableBazelFlag(arg string) bool {
	return isOverrideable(arg, overrideableBazelFlags)
}

func parseArgs(in []string) (targets, startupArgs, bazelArgs, args []string) {
	afterDoubleDash := false
	for _, arg := range in {
		if afterDoubleDash {
			// Put it in the extra args section if we are after a double dash.
			args = append(args, arg)
		} else {
			// Check to see if this token is a double dash.
			if arg == "--" {
				afterDoubleDash = true
				continue
			}

			// Check to see if this startup option or command flag is on the bazel whitelist of flags.
			if isOverrideableStartupFlag(arg) {
				startupArgs = append(startupArgs, arg)
			} else if isOverrideableBazelFlag(arg) {
				bazelArgs = append(bazelArgs, arg)
			} else {
				// If none of those things then it's probably a target.
				targets = append(targets, arg)
			}
		}
	}
	return
}

// main entrypoint for IBazel.
func main() {
	flag.Usage = usage
	flag.Parse()

	if *logToFile != "-" {
		var err error
		logFile, err := os.OpenFile(*logToFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
		if err != nil {
			panic(err)
		}
		os.Stderr = logFile
	}

	if len(flag.Args()) < 2 {
		usage()
		return
	}

	command := strings.ToLower(flag.Args()[0])
	args := flag.Args()[1:]

	i, err := New()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error creating iBazel: %s\n", err)
		os.Exit(1)
	}
	i.SetDebounceDuration(*debounceDuration)
	defer i.Cleanup()

	// increase the number of files that this process can
	// have open.
	err = setUlimit()
	if err != nil {
		fmt.Fprint(os.Stderr, "error setting higher file descriptor limit for this process: ", err)
	}

	handle(i, command, args)
}

func handle(i *IBazel, command string, args []string) {
	targets, startupArgs, bazelArgs, args := parseArgs(args)
	i.SetStartupArgs(startupArgs)
	i.SetBazelArgs(bazelArgs)

	switch command {
	case "build":
		i.Build(targets...)
	case "test":
		i.Test(targets...)
	case "run":
		// Run only takes one argument
		i.Run(targets[0], args)
	default:
		fmt.Fprintf(os.Stderr, "Asked me to perform %s. I don't know how to do that.", command)
		usage()
		return
	}
}
<commit_msg>Add --test_tag_filters= to overrideable flags (#281)<commit_after>// Copyright 2017 The Bazel 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.

package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"time"
)

var Version = "Development"

var overrideableStartupFlags []string = []string{
	"--bazelrc",
}

var overrideableBazelFlags []string = []string{
	"--action_env",
	"--announce_rc",
	"--config=",
	"--curses=no",
	"--define",
	"--features=",
	"--keep_going",
	"-k",
	"--nostamp",
	"--output_groups=",
	"--override_repository",
	"--repo_env",
	"--runs_per_test",
	"--stamp",
	"--strategy",
	"--test_arg",
	"--test_env",
	"--test_filter",
	"--test_output=",
	"--test_tag_filters=",
	"--test_timeout",
}

var debounceDuration = flag.Duration("debounce", 100*time.Millisecond, "Debounce duration")
var logToFile = flag.String("log_to_file", "-", "Log iBazel stderr to a file instead of os.Stderr")

func usage() {
	fmt.Fprintf(os.Stderr, `iBazel - Version %s

A file watcher for Bazel. Whenever a source file used in a specified
target, run, build, or test the specified targets.

Usage:

ibazel build|test|run [flags] targets...

Example:

ibazel test //path/to/my/testing:target
ibazel test //path/to/my/testing/targets/...
ibazel run //path/to/my/runnable:target -- --arguments --for_your=binary
ibazel build //path/to/my/buildable:target

Supported Bazel startup flags:
  %s

Supported Bazel command flags:
  %s

To add to this list, edit
https://github.com/bazelbuild/bazel-watcher/blob/master/ibazel/main.go

iBazel flags:
`, Version, strings.Join(overrideableStartupFlags, "\n  "), strings.Join(overrideableBazelFlags, "\n  "))
	flag.PrintDefaults()
}

func isOverrideable(arg string, overrideables []string) bool {
	for _, overrideable := range overrideables {
		if strings.HasPrefix(arg, overrideable) {
			return true
		}
	}
	return false
}

func isOverrideableStartupFlag(arg string) bool {
	return isOverrideable(arg, overrideableStartupFlags)
}

func isOverrideableBazelFlag(arg string) bool {
	return isOverrideable(arg, overrideableBazelFlags)
}

func parseArgs(in []string) (targets, startupArgs, bazelArgs, args []string) {
	afterDoubleDash := false
	for _, arg := range in {
		if afterDoubleDash {
			// Put it in the extra args section if we are after a double dash.
			args = append(args, arg)
		} else {
			// Check to see if this token is a double dash.
			if arg == "--" {
				afterDoubleDash = true
				continue
			}

			// Check to see if this startup option or command flag is on the bazel whitelist of flags.
			if isOverrideableStartupFlag(arg) {
				startupArgs = append(startupArgs, arg)
			} else if isOverrideableBazelFlag(arg) {
				bazelArgs = append(bazelArgs, arg)
			} else {
				// If none of those things then it's probably a target.
				targets = append(targets, arg)
			}
		}
	}
	return
}

// main entrypoint for IBazel.
func main() {
	flag.Usage = usage
	flag.Parse()

	if *logToFile != "-" {
		var err error
		logFile, err := os.OpenFile(*logToFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
		if err != nil {
			panic(err)
		}
		os.Stderr = logFile
	}

	if len(flag.Args()) < 2 {
		usage()
		return
	}

	command := strings.ToLower(flag.Args()[0])
	args := flag.Args()[1:]

	i, err := New()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error creating iBazel: %s\n", err)
		os.Exit(1)
	}
	i.SetDebounceDuration(*debounceDuration)
	defer i.Cleanup()

	// increase the number of files that this process can
	// have open.
	err = setUlimit()
	if err != nil {
		fmt.Fprint(os.Stderr, "error setting higher file descriptor limit for this process: ", err)
	}

	handle(i, command, args)
}

func handle(i *IBazel, command string, args []string) {
	targets, startupArgs, bazelArgs, args := parseArgs(args)
	i.SetStartupArgs(startupArgs)
	i.SetBazelArgs(bazelArgs)

	switch command {
	case "build":
		i.Build(targets...)
	case "test":
		i.Test(targets...)
	case "run":
		// Run only takes one argument
		i.Run(targets[0], args)
	default:
		fmt.Fprintf(os.Stderr, "Asked me to perform %s. I don't know how to do that.", command)
		usage()
		return
	}
}
<|endoftext|>


<commit_before>package progress

import (
	"image/color"
	"io"
	"strconv"

	"github.com/MJKWoolnough/gopherjs/xjs"

	"honnef.co/go/js/dom"
)

type ProgressBar struct {
	*dom.HTMLCanvasElement
	percent                int
	ctx                    *dom.CanvasRenderingContext2D
	width, height          int
	foreground, background string
}

func (p *ProgressBar) Percent(i int) {
	if i != p.percent {
		p.percent = i
		p.draw()
	}
}

func (p *ProgressBar) draw() {
	p.ctx.FillStyle = p.background
	p.ctx.FillRect(0, 0, p.width, p.height)
	p.ctx.FillStyle = p.foreground
	p.ctx.FillRect(0, 0, p.width*p.percent/100, p.height)
}

func New(fore, back color.Color, width, height int) *ProgressBar {
	c := xjs.CreateElement("canvas").(*dom.HTMLCanvasElement)
	c.SetAttribute("width", strconv.Itoa(width))
	c.SetAttribute("height", strconv.Itoa(height))
	r, g, b, _ := fore.RGBA()
	foreground := "rgb(" + strconv.Itoa(int(r>>8)) + ", " + strconv.Itoa(int(g>>8)) + ", " + strconv.Itoa(int(b>>8)) + ")"
	r, g, b, _ = back.RGBA()
	background := "rgb(" + strconv.Itoa(int(r>>8)) + ", " + strconv.Itoa(int(g>>8)) + ", " + strconv.Itoa(int(b>>8)) + ")"
	pb := &ProgressBar{
		HTMLCanvasElement: c,
		ctx:               c.GetContext2d(),
		width:             width,
		height:            height,
		foreground:        foreground,
		background:        background,
	}
	pb.draw()
	return pb
}

type ProgressReader struct {
	*ProgressBar
	io.Reader
	offset, size int
}

func (p *ProgressBar) Reader(r io.Reader, size int) *ProgressReader {
	return &ProgressReader{p, r, 0, size}
}

func (pr *ProgressReader) Read(p []byte) (int, error) {
	n, err := pr.Reader.Read(p)
	pr.offset += n
	pr.Percent(100 * pr.offset / pr.size)
	return n, err
}

func (pr *ProgressReader) Len() int {
	return int(pr.size)
}
<commit_msg>Used Width and Height struct members to avoid type conversions<commit_after>package progress

import (
	"image/color"
	"io"
	"strconv"

	"github.com/MJKWoolnough/gopherjs/xjs"

	"honnef.co/go/js/dom"
)

type ProgressBar struct {
	*dom.HTMLCanvasElement
	percent                int
	ctx                    *dom.CanvasRenderingContext2D
	width, height          int
	foreground, background string
}

func (p *ProgressBar) Percent(i int) {
	if i != p.percent {
		p.percent = i
		p.draw()
	}
}

func (p *ProgressBar) draw() {
	p.ctx.FillStyle = p.background
	p.ctx.FillRect(0, 0, p.width, p.height)
	p.ctx.FillStyle = p.foreground
	p.ctx.FillRect(0, 0, p.width*p.percent/100, p.height)
}

func New(fore, back color.Color, width, height int) *ProgressBar {
	c := xjs.CreateElement("canvas").(*dom.HTMLCanvasElement)
	c.Width = width
	c.Height = height
	r, g, b, _ := fore.RGBA()
	foreground := "rgb(" + strconv.Itoa(int(r>>8)) + ", " + strconv.Itoa(int(g>>8)) + ", " + strconv.Itoa(int(b>>8)) + ")"
	r, g, b, _ = back.RGBA()
	background := "rgb(" + strconv.Itoa(int(r>>8)) + ", " + strconv.Itoa(int(g>>8)) + ", " + strconv.Itoa(int(b>>8)) + ")"
	pb := &ProgressBar{
		HTMLCanvasElement: c,
		ctx:               c.GetContext2d(),
		width:             width,
		height:            height,
		foreground:        foreground,
		background:        background,
	}
	pb.draw()
	return pb
}

type ProgressReader struct {
	*ProgressBar
	io.Reader
	offset, size int
}

func (p *ProgressBar) Reader(r io.Reader, size int) *ProgressReader {
	return &ProgressReader{p, r, 0, size}
}

func (pr *ProgressReader) Read(p []byte) (int, error) {
	n, err := pr.Reader.Read(p)
	pr.offset += n
	pr.Percent(100 * pr.offset / pr.size)
	return n, err
}

func (pr *ProgressReader) Len() int {
	return int(pr.size)
}
<|endoftext|>


<commit_before>package reporting

import "testing"

func TestPrint(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const expected = "Hello, World!"

	printer.Print(expected)

	if file.buffer != expected {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintPreservesEncodedStrings(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const expected = "= -> %3D"
	printer.Print(expected)

	if file.buffer != expected {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintln(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const expected = "Hello, World!"

	printer.Println(expected)

	if file.buffer != expected+"\n" {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintlnPreservesEncodedStrings(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const expected = "= -> %3D"
	printer.Println(expected)

	if file.buffer != expected+"\n" {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintIndented(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const message = "Hello, World!\nGoodbye, World!"
	const expected = "  Hello, World!\n  Goodbye, World!"

	printer.Indent()
	printer.Print(message)

	if file.buffer != expected {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintDedented(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const expected = "Hello, World!\nGoodbye, World!"

	printer.Indent()
	printer.Dedent()
	printer.Print(expected)

	if file.buffer != expected {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintlnIndented(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const message = "Hello, World!\nGoodbye, World!"
	const expected = "  Hello, World!\n  Goodbye, World!\n"

	printer.Indent()
	printer.Println(message)

	if file.buffer != expected {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintlnDedented(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const expected = "Hello, World!\nGoodbye, World!"

	printer.Indent()
	printer.Dedent()
	printer.Println(expected)

	if file.buffer != expected+"\n" {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestDedentTooFarShouldNotPanic(t *testing.T) {
	defer func() {
		if r := recover(); r != nil {
			t.Error("Should not have panicked!")
		}
	}()
	file := newMemoryFile()
	printer := NewPrinter(file)

	printer.Dedent()

	t.Log("Getting to this point without panicking means we passed.")
}

func TestInsert(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)

	printer.Indent()
	printer.Print("Hi")
	printer.Insert(" there")
	printer.Dedent()

	expected := "  Hi there"
	if file.buffer != expected {
		t.Errorf("Should have written '%s' but instead wrote '%s'.", expected, file.buffer)
	}
}

type memoryFile struct {
	buffer string
}

func (self *memoryFile) Write(p []byte) (n int, err error) {
	self.buffer += string(p)
	return len(p), nil
}

func newMemoryFile() *memoryFile {
	return new(memoryFile)
}
<commit_msg>Coverage for printer.<commit_after>package reporting

import "testing"

func TestPrint(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const expected = "Hello, World!"

	printer.Print(expected)

	if file.buffer != expected {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintFormat(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	template := "Hi, %s"
	name := "Ralph"
	expected := "Hi, Ralph"

	printer.Print(template, name)

	if file.buffer != expected {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintPreservesEncodedStrings(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const expected = "= -> %3D"
	printer.Print(expected)

	if file.buffer != expected {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintln(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const expected = "Hello, World!"

	printer.Println(expected)

	if file.buffer != expected+"\n" {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintlnFormat(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	template := "Hi, %s"
	name := "Ralph"
	expected := "Hi, Ralph\n"

	printer.Println(template, name)

	if file.buffer != expected {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintlnPreservesEncodedStrings(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const expected = "= -> %3D"
	printer.Println(expected)

	if file.buffer != expected+"\n" {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintIndented(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const message = "Hello, World!\nGoodbye, World!"
	const expected = "  Hello, World!\n  Goodbye, World!"

	printer.Indent()
	printer.Print(message)

	if file.buffer != expected {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintDedented(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const expected = "Hello, World!\nGoodbye, World!"

	printer.Indent()
	printer.Dedent()
	printer.Print(expected)

	if file.buffer != expected {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintlnIndented(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const message = "Hello, World!\nGoodbye, World!"
	const expected = "  Hello, World!\n  Goodbye, World!\n"

	printer.Indent()
	printer.Println(message)

	if file.buffer != expected {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestPrintlnDedented(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)
	const expected = "Hello, World!\nGoodbye, World!"

	printer.Indent()
	printer.Dedent()
	printer.Println(expected)

	if file.buffer != expected+"\n" {
		t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer)
	}
}

func TestDedentTooFarShouldNotPanic(t *testing.T) {
	defer func() {
		if r := recover(); r != nil {
			t.Error("Should not have panicked!")
		}
	}()
	file := newMemoryFile()
	printer := NewPrinter(file)

	printer.Dedent()

	t.Log("Getting to this point without panicking means we passed.")
}

func TestInsert(t *testing.T) {
	file := newMemoryFile()
	printer := NewPrinter(file)

	printer.Indent()
	printer.Print("Hi")
	printer.Insert(" there")
	printer.Dedent()

	expected := "  Hi there"
	if file.buffer != expected {
		t.Errorf("Should have written '%s' but instead wrote '%s'.", expected, file.buffer)
	}
}

type memoryFile struct {
	buffer string
}

func (self *memoryFile) Write(p []byte) (n int, err error) {
	self.buffer += string(p)
	return len(p), nil
}

func newMemoryFile() *memoryFile {
	return new(memoryFile)
}
<|endoftext|>


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

// TODO(thockin): This whole pkg is pretty linux-centric.  As soon as we have
// an alternate platform, we will need to abstract further.
package mount

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

type FileType string

const (
	// Default mount command if mounter path is not specified
	defaultMountCommand           = "mount"
	MountsInGlobalPDPath          = "mounts"
	FileTypeDirectory    FileType = "Directory"
	FileTypeFile         FileType = "File"
	FileTypeSocket       FileType = "Socket"
	FileTypeCharDev      FileType = "CharDevice"
	FileTypeBlockDev     FileType = "BlockDevice"
)

type Interface interface {
	// Mount mounts source to target as fstype with given options.
	Mount(source string, target string, fstype string, options []string) error
	// Unmount unmounts given target.
	Unmount(target string) error
	// List returns a list of all mounted filesystems.  This can be large.
	// On some platforms, reading mounts is not guaranteed consistent (i.e.
	// it could change between chunked reads). This is guaranteed to be
	// consistent.
	List() ([]MountPoint, error)
	// IsMountPointMatch determines if the mountpoint matches the dir
	IsMountPointMatch(mp MountPoint, dir string) bool
	// IsNotMountPoint determines if a directory is a mountpoint.
	// It should return ErrNotExist when the directory does not exist.
	// IsNotMountPoint is more expensive than IsLikelyNotMountPoint.
	// IsNotMountPoint detects bind mounts in linux.
	// IsNotMountPoint enumerates all the mountpoints using List() and
	// the list of mountpoints may be large, then it uses
	// IsMountPointMatch to evaluate whether the directory is a mountpoint
	IsNotMountPoint(file string) (bool, error)
	// IsLikelyNotMountPoint uses heuristics to determine if a directory
	// is a mountpoint.
	// It should return ErrNotExist when the directory does not exist.
	// IsLikelyNotMountPoint does NOT properly detect all mountpoint types
	// most notably linux bind mounts.
	IsLikelyNotMountPoint(file string) (bool, error)
	// DeviceOpened determines if the device is in use elsewhere
	// on the system, i.e. still mounted.
	DeviceOpened(pathname string) (bool, error)
	// PathIsDevice determines if a path is a device.
	PathIsDevice(pathname string) (bool, error)
	// GetDeviceNameFromMount finds the device name by checking the mount path
	// to get the global mount path which matches its plugin directory
	GetDeviceNameFromMount(mountPath, pluginDir string) (string, error)
	// MakeRShared checks that given path is on a mount with 'rshared' mount
	// propagation. If not, it bind-mounts the path as rshared.
	MakeRShared(path string) error
	// GetFileType checks for file/directory/socket/block/character devices.
	// Will operate in the host mount namespace if kubelet is running in a container
	GetFileType(pathname string) (FileType, error)
	// MakeFile creates an empty file.
	// Will operate in the host mount namespace if kubelet is running in a container
	MakeFile(pathname string) error
	// MakeDir creates a new directory.
	// Will operate in the host mount namespace if kubelet is running in a container
	MakeDir(pathname string) error
	// SafeMakeDir creates subdir within given base. It makes sure that the
	// created directory does not escape given base directory mis-using
	// symlinks. Note that the function makes sure that it creates the directory
	// somewhere under the base, nothing else. E.g. if the directory already
	// exists, it may exist outside of the base due to symlinks.
	// This method should be used if the directory to create is inside volume
	// that's under user control. User must not be able to use symlinks to
	// escape the volume to create directories somewhere else.
	SafeMakeDir(subdir string, base string, perm os.FileMode) error
	// Will operate in the host mount namespace if kubelet is running in a container.
	// Error is returned on any other error than "file not found".
	ExistsPath(pathname string) (bool, error)
	// EvalHostSymlinks returns the path name after evaluating symlinks.
	// Will operate in the host mount namespace if kubelet is running in a container.
	EvalHostSymlinks(pathname string) (string, error)
	// CleanSubPaths removes any bind-mounts created by PrepareSafeSubpath in given
	// pod volume directory.
	CleanSubPaths(podDir string, volumeName string) error
	// PrepareSafeSubpath does everything that's necessary to prepare a subPath
	// that's 1) inside given volumePath and 2) immutable after this call.
	//
	// newHostPath - location of prepared subPath. It should be used instead of
	// hostName when running the container.
	// cleanupAction - action to run when the container is running or it failed to start.
	//
	// CleanupAction must be called immediately after the container with given
	// subpath starts. On the other hand, Interface.CleanSubPaths must be called
	// when the pod finishes.
	PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error)
	// GetMountRefs finds all mount references to the path, returns a
	// list of paths. Path could be a mountpoint path, device or a normal
	// directory (for bind mount).
	GetMountRefs(pathname string) ([]string, error)
	// GetFSGroup returns FSGroup of the path.
	GetFSGroup(pathname string) (int64, error)
	// GetSELinuxSupport returns true if given path is on a mount that supports
	// SELinux.
	GetSELinuxSupport(pathname string) (bool, error)
	// GetMode returns permissions of the path.
	GetMode(pathname string) (os.FileMode, error)
}

type Subpath struct {
	// index of the VolumeMount for this container
	VolumeMountIndex int
	// Full path to the subpath directory on the host
	Path string
	// name of the volume that is a valid directory name.
	VolumeName string
	// Full path to the volume path
	VolumePath string
	// Path to the pod's directory, including pod UID
	PodDir string
	// Name of the container
	ContainerName string
}

// Exec executes command where mount utilities are. This can be either the host,
// container where kubelet runs or even a remote pod with mount utilities.
// Usual pkg/util/exec interface is not used because kubelet.RunInContainer does
// not provide stdin/stdout/stderr streams.
type Exec interface {
	// Run executes a command and returns its stdout + stderr combined in one
	// stream.
	Run(cmd string, args ...string) ([]byte, error)
}

// Compile-time check to ensure all Mounter implementations satisfy
// the mount interface
var _ Interface = &Mounter{}

// This represents a single line in /proc/mounts or /etc/fstab.
type MountPoint struct {
	Device string
	Path   string
	Type   string
	Opts   []string
	Freq   int
	Pass   int
}

// SafeFormatAndMount probes a device to see if it is formatted.
// Namely it checks to see if a file system is present. If so it
// mounts it otherwise the device is formatted first then mounted.
type SafeFormatAndMount struct {
	Interface
	Exec
}

// FormatAndMount formats the given disk, if needed, and mounts it.
// That is if the disk is not formatted and it is not being mounted as
// read-only it will format it first then mount it. Otherwise, if the
// disk is already formatted or it is being mounted as read-only, it
// will be mounted without formatting.
func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string, fstype string, options []string) error {
	return mounter.formatAndMount(source, target, fstype, options)
}

// getMountRefsByDev finds all references to the device provided
// by mountPath; returns a list of paths.
// Note that mountPath should be path after the evaluation of any symblolic links.
func getMountRefsByDev(mounter Interface, mountPath string) ([]string, error) {
	mps, err := mounter.List()
	if err != nil {
		return nil, err
	}

	// Finding the device mounted to mountPath
	diskDev := ""
	for i := range mps {
		if mountPath == mps[i].Path {
			diskDev = mps[i].Device
			break
		}
	}

	// Find all references to the device.
	var refs []string
	for i := range mps {
		if mps[i].Device == diskDev || mps[i].Device == mountPath {
			if mps[i].Path != mountPath {
				refs = append(refs, mps[i].Path)
			}
		}
	}
	return refs, nil
}

// GetDeviceNameFromMount: given a mnt point, find the device from /proc/mounts
// returns the device name, reference count, and error code
func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, error) {
	mps, err := mounter.List()
	if err != nil {
		return "", 0, err
	}

	// Find the device name.
	// FIXME if multiple devices mounted on the same mount path, only the first one is returned
	device := ""
	// If mountPath is symlink, need get its target path.
	slTarget, err := filepath.EvalSymlinks(mountPath)
	if err != nil {
		slTarget = mountPath
	}
	for i := range mps {
		if mps[i].Path == slTarget {
			device = mps[i].Device
			break
		}
	}

	// Find all references to the device.
	refCount := 0
	for i := range mps {
		if mps[i].Device == device {
			refCount++
		}
	}
	return device, refCount, nil
}

// isNotMountPoint implements Mounter.IsNotMountPoint and is shared by mounter
// implementations.
func isNotMountPoint(mounter Interface, file string) (bool, error) {
	// IsLikelyNotMountPoint provides a quick check
	// to determine whether file IS A mountpoint
	notMnt, notMntErr := mounter.IsLikelyNotMountPoint(file)
	if notMntErr != nil && os.IsPermission(notMntErr) {
		// We were not allowed to do the simple stat() check, e.g. on NFS with
		// root_squash. Fall back to /proc/mounts check below.
		notMnt = true
		notMntErr = nil
	}
	if notMntErr != nil {
		return notMnt, notMntErr
	}
	// identified as mountpoint, so return this fact
	if notMnt == false {
		return notMnt, nil
	}

	// Resolve any symlinks in file, kernel would do the same and use the resolved path in /proc/mounts
	resolvedFile, err := mounter.EvalHostSymlinks(file)
	if err != nil {
		return true, err
	}

	// check all mountpoints since IsLikelyNotMountPoint
	// is not reliable for some mountpoint types
	mountPoints, mountPointsErr := mounter.List()
	if mountPointsErr != nil {
		return notMnt, mountPointsErr
	}
	for _, mp := range mountPoints {
		if mounter.IsMountPointMatch(mp, resolvedFile) {
			notMnt = false
			break
		}
	}
	return notMnt, nil
}

// isBind detects whether a bind mount is being requested and makes the remount options to
// use in case of bind mount, due to the fact that bind mount doesn't respect mount options.
// The list equals:
//   options - 'bind' + 'remount' (no duplicate)
func isBind(options []string) (bool, []string, []string) {
	// Because we have an FD opened on the subpath bind mount, the "bind" option
	// needs to be included, otherwise the mount target will error as busy if you
	// remount as readonly.
	//
	// As a consequence, all read only bind mounts will no longer change the underlying
	// volume mount to be read only.
	bindRemountOpts := []string{"bind", "remount"}
	bind := false
	bindOpts := []string{"bind"}

	// _netdev is a userspace mount option and does not automatically get added when
	// bind mount is created and hence we must carry it over.
	if checkForNetDev(options) {
		bindOpts = append(bindOpts, "_netdev")
	}

	for _, option := range options {
		switch option {
		case "bind":
			bind = true
			break
		case "remount":
			break
		default:
			bindRemountOpts = append(bindRemountOpts, option)
		}
	}

	return bind, bindOpts, bindRemountOpts
}

func checkForNetDev(options []string) bool {
	for _, option := range options {
		if option == "_netdev" {
			return true
		}
	}
	return false
}

// TODO: this is a workaround for the unmount device issue caused by gci mounter.
// In GCI cluster, if gci mounter is used for mounting, the container started by mounter
// script will cause additional mounts created in the container. Since these mounts are
// irrelevant to the original mounts, they should be not considered when checking the
// mount references. Current solution is to filter out those mount paths that contain
// the string of original mount path.
// Plan to work on better approach to solve this issue.

func HasMountRefs(mountPath string, mountRefs []string) bool {
	count := 0
	for _, ref := range mountRefs {
		if !strings.Contains(ref, mountPath) {
			count = count + 1
		}
	}
	return count > 0
}

// PathWithinBase checks if give path is within given base directory.
func PathWithinBase(fullPath, basePath string) bool {
	rel, err := filepath.Rel(basePath, fullPath)
	if err != nil {
		return false
	}
	if startsWithBackstep(rel) {
		// Needed to escape the base path
		return false
	}
	return true
}

// startsWithBackstep checks if the given path starts with a backstep segment
func startsWithBackstep(rel string) bool {
	// normalize to / and check for ../
	return rel == ".." || strings.HasPrefix(filepath.ToSlash(rel), "../")
}

// getFileType checks for file/directory/socket and block/character devices
func getFileType(pathname string) (FileType, error) {
	var pathType FileType
	info, err := os.Stat(pathname)
	if os.IsNotExist(err) {
		return pathType, fmt.Errorf("path %q does not exist", pathname)
	}
	// err in call to os.Stat
	if err != nil {
		return pathType, err
	}

	// checks whether the mode is the target mode
	isSpecificMode := func(mode, targetMode os.FileMode) bool {
		return mode&targetMode == targetMode
	}

	mode := info.Mode()
	if mode.IsDir() {
		return FileTypeDirectory, nil
	} else if mode.IsRegular() {
		return FileTypeFile, nil
	} else if isSpecificMode(mode, os.ModeSocket) {
		return FileTypeSocket, nil
	} else if isSpecificMode(mode, os.ModeDevice) {
		if isSpecificMode(mode, os.ModeCharDevice) {
			return FileTypeCharDev, nil
		}
		return FileTypeBlockDev, nil
	}

	return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
}
<commit_msg>migrate the rest reference of pkg/util/exec to k8s.io/utils/exec<commit_after>/*
Copyright 2014 The Kubernetes 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.
*/

// TODO(thockin): This whole pkg is pretty linux-centric.  As soon as we have
// an alternate platform, we will need to abstract further.
package mount

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

type FileType string

const (
	// Default mount command if mounter path is not specified
	defaultMountCommand           = "mount"
	MountsInGlobalPDPath          = "mounts"
	FileTypeDirectory    FileType = "Directory"
	FileTypeFile         FileType = "File"
	FileTypeSocket       FileType = "Socket"
	FileTypeCharDev      FileType = "CharDevice"
	FileTypeBlockDev     FileType = "BlockDevice"
)

type Interface interface {
	// Mount mounts source to target as fstype with given options.
	Mount(source string, target string, fstype string, options []string) error
	// Unmount unmounts given target.
	Unmount(target string) error
	// List returns a list of all mounted filesystems.  This can be large.
	// On some platforms, reading mounts is not guaranteed consistent (i.e.
	// it could change between chunked reads). This is guaranteed to be
	// consistent.
	List() ([]MountPoint, error)
	// IsMountPointMatch determines if the mountpoint matches the dir
	IsMountPointMatch(mp MountPoint, dir string) bool
	// IsNotMountPoint determines if a directory is a mountpoint.
	// It should return ErrNotExist when the directory does not exist.
	// IsNotMountPoint is more expensive than IsLikelyNotMountPoint.
	// IsNotMountPoint detects bind mounts in linux.
	// IsNotMountPoint enumerates all the mountpoints using List() and
	// the list of mountpoints may be large, then it uses
	// IsMountPointMatch to evaluate whether the directory is a mountpoint
	IsNotMountPoint(file string) (bool, error)
	// IsLikelyNotMountPoint uses heuristics to determine if a directory
	// is a mountpoint.
	// It should return ErrNotExist when the directory does not exist.
	// IsLikelyNotMountPoint does NOT properly detect all mountpoint types
	// most notably linux bind mounts.
	IsLikelyNotMountPoint(file string) (bool, error)
	// DeviceOpened determines if the device is in use elsewhere
	// on the system, i.e. still mounted.
	DeviceOpened(pathname string) (bool, error)
	// PathIsDevice determines if a path is a device.
	PathIsDevice(pathname string) (bool, error)
	// GetDeviceNameFromMount finds the device name by checking the mount path
	// to get the global mount path which matches its plugin directory
	GetDeviceNameFromMount(mountPath, pluginDir string) (string, error)
	// MakeRShared checks that given path is on a mount with 'rshared' mount
	// propagation. If not, it bind-mounts the path as rshared.
	MakeRShared(path string) error
	// GetFileType checks for file/directory/socket/block/character devices.
	// Will operate in the host mount namespace if kubelet is running in a container
	GetFileType(pathname string) (FileType, error)
	// MakeFile creates an empty file.
	// Will operate in the host mount namespace if kubelet is running in a container
	MakeFile(pathname string) error
	// MakeDir creates a new directory.
	// Will operate in the host mount namespace if kubelet is running in a container
	MakeDir(pathname string) error
	// SafeMakeDir creates subdir within given base. It makes sure that the
	// created directory does not escape given base directory mis-using
	// symlinks. Note that the function makes sure that it creates the directory
	// somewhere under the base, nothing else. E.g. if the directory already
	// exists, it may exist outside of the base due to symlinks.
	// This method should be used if the directory to create is inside volume
	// that's under user control. User must not be able to use symlinks to
	// escape the volume to create directories somewhere else.
	SafeMakeDir(subdir string, base string, perm os.FileMode) error
	// Will operate in the host mount namespace if kubelet is running in a container.
	// Error is returned on any other error than "file not found".
	ExistsPath(pathname string) (bool, error)
	// EvalHostSymlinks returns the path name after evaluating symlinks.
	// Will operate in the host mount namespace if kubelet is running in a container.
	EvalHostSymlinks(pathname string) (string, error)
	// CleanSubPaths removes any bind-mounts created by PrepareSafeSubpath in given
	// pod volume directory.
	CleanSubPaths(podDir string, volumeName string) error
	// PrepareSafeSubpath does everything that's necessary to prepare a subPath
	// that's 1) inside given volumePath and 2) immutable after this call.
	//
	// newHostPath - location of prepared subPath. It should be used instead of
	// hostName when running the container.
	// cleanupAction - action to run when the container is running or it failed to start.
	//
	// CleanupAction must be called immediately after the container with given
	// subpath starts. On the other hand, Interface.CleanSubPaths must be called
	// when the pod finishes.
	PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error)
	// GetMountRefs finds all mount references to the path, returns a
	// list of paths. Path could be a mountpoint path, device or a normal
	// directory (for bind mount).
	GetMountRefs(pathname string) ([]string, error)
	// GetFSGroup returns FSGroup of the path.
	GetFSGroup(pathname string) (int64, error)
	// GetSELinuxSupport returns true if given path is on a mount that supports
	// SELinux.
	GetSELinuxSupport(pathname string) (bool, error)
	// GetMode returns permissions of the path.
	GetMode(pathname string) (os.FileMode, error)
}

type Subpath struct {
	// index of the VolumeMount for this container
	VolumeMountIndex int
	// Full path to the subpath directory on the host
	Path string
	// name of the volume that is a valid directory name.
	VolumeName string
	// Full path to the volume path
	VolumePath string
	// Path to the pod's directory, including pod UID
	PodDir string
	// Name of the container
	ContainerName string
}

// Exec executes command where mount utilities are. This can be either the host,
// container where kubelet runs or even a remote pod with mount utilities.
// Usual k8s.io/utils/exec interface is not used because kubelet.RunInContainer does
// not provide stdin/stdout/stderr streams.
type Exec interface {
	// Run executes a command and returns its stdout + stderr combined in one
	// stream.
	Run(cmd string, args ...string) ([]byte, error)
}

// Compile-time check to ensure all Mounter implementations satisfy
// the mount interface
var _ Interface = &Mounter{}

// This represents a single line in /proc/mounts or /etc/fstab.
type MountPoint struct {
	Device string
	Path   string
	Type   string
	Opts   []string
	Freq   int
	Pass   int
}

// SafeFormatAndMount probes a device to see if it is formatted.
// Namely it checks to see if a file system is present. If so it
// mounts it otherwise the device is formatted first then mounted.
type SafeFormatAndMount struct {
	Interface
	Exec
}

// FormatAndMount formats the given disk, if needed, and mounts it.
// That is if the disk is not formatted and it is not being mounted as
// read-only it will format it first then mount it. Otherwise, if the
// disk is already formatted or it is being mounted as read-only, it
// will be mounted without formatting.
func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string, fstype string, options []string) error {
	return mounter.formatAndMount(source, target, fstype, options)
}

// getMountRefsByDev finds all references to the device provided
// by mountPath; returns a list of paths.
// Note that mountPath should be path after the evaluation of any symblolic links.
func getMountRefsByDev(mounter Interface, mountPath string) ([]string, error) {
	mps, err := mounter.List()
	if err != nil {
		return nil, err
	}

	// Finding the device mounted to mountPath
	diskDev := ""
	for i := range mps {
		if mountPath == mps[i].Path {
			diskDev = mps[i].Device
			break
		}
	}

	// Find all references to the device.
	var refs []string
	for i := range mps {
		if mps[i].Device == diskDev || mps[i].Device == mountPath {
			if mps[i].Path != mountPath {
				refs = append(refs, mps[i].Path)
			}
		}
	}
	return refs, nil
}

// GetDeviceNameFromMount: given a mnt point, find the device from /proc/mounts
// returns the device name, reference count, and error code
func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, error) {
	mps, err := mounter.List()
	if err != nil {
		return "", 0, err
	}

	// Find the device name.
	// FIXME if multiple devices mounted on the same mount path, only the first one is returned
	device := ""
	// If mountPath is symlink, need get its target path.
	slTarget, err := filepath.EvalSymlinks(mountPath)
	if err != nil {
		slTarget = mountPath
	}
	for i := range mps {
		if mps[i].Path == slTarget {
			device = mps[i].Device
			break
		}
	}

	// Find all references to the device.
	refCount := 0
	for i := range mps {
		if mps[i].Device == device {
			refCount++
		}
	}
	return device, refCount, nil
}

// isNotMountPoint implements Mounter.IsNotMountPoint and is shared by mounter
// implementations.
func isNotMountPoint(mounter Interface, file string) (bool, error) {
	// IsLikelyNotMountPoint provides a quick check
	// to determine whether file IS A mountpoint
	notMnt, notMntErr := mounter.IsLikelyNotMountPoint(file)
	if notMntErr != nil && os.IsPermission(notMntErr) {
		// We were not allowed to do the simple stat() check, e.g. on NFS with
		// root_squash. Fall back to /proc/mounts check below.
		notMnt = true
		notMntErr = nil
	}
	if notMntErr != nil {
		return notMnt, notMntErr
	}
	// identified as mountpoint, so return this fact
	if notMnt == false {
		return notMnt, nil
	}

	// Resolve any symlinks in file, kernel would do the same and use the resolved path in /proc/mounts
	resolvedFile, err := mounter.EvalHostSymlinks(file)
	if err != nil {
		return true, err
	}

	// check all mountpoints since IsLikelyNotMountPoint
	// is not reliable for some mountpoint types
	mountPoints, mountPointsErr := mounter.List()
	if mountPointsErr != nil {
		return notMnt, mountPointsErr
	}
	for _, mp := range mountPoints {
		if mounter.IsMountPointMatch(mp, resolvedFile) {
			notMnt = false
			break
		}
	}
	return notMnt, nil
}

// isBind detects whether a bind mount is being requested and makes the remount options to
// use in case of bind mount, due to the fact that bind mount doesn't respect mount options.
// The list equals:
//   options - 'bind' + 'remount' (no duplicate)
func isBind(options []string) (bool, []string, []string) {
	// Because we have an FD opened on the subpath bind mount, the "bind" option
	// needs to be included, otherwise the mount target will error as busy if you
	// remount as readonly.
	//
	// As a consequence, all read only bind mounts will no longer change the underlying
	// volume mount to be read only.
	bindRemountOpts := []string{"bind", "remount"}
	bind := false
	bindOpts := []string{"bind"}

	// _netdev is a userspace mount option and does not automatically get added when
	// bind mount is created and hence we must carry it over.
	if checkForNetDev(options) {
		bindOpts = append(bindOpts, "_netdev")
	}

	for _, option := range options {
		switch option {
		case "bind":
			bind = true
			break
		case "remount":
			break
		default:
			bindRemountOpts = append(bindRemountOpts, option)
		}
	}

	return bind, bindOpts, bindRemountOpts
}

func checkForNetDev(options []string) bool {
	for _, option := range options {
		if option == "_netdev" {
			return true
		}
	}
	return false
}

// TODO: this is a workaround for the unmount device issue caused by gci mounter.
// In GCI cluster, if gci mounter is used for mounting, the container started by mounter
// script will cause additional mounts created in the container. Since these mounts are
// irrelevant to the original mounts, they should be not considered when checking the
// mount references. Current solution is to filter out those mount paths that contain
// the string of original mount path.
// Plan to work on better approach to solve this issue.

func HasMountRefs(mountPath string, mountRefs []string) bool {
	count := 0
	for _, ref := range mountRefs {
		if !strings.Contains(ref, mountPath) {
			count = count + 1
		}
	}
	return count > 0
}

// PathWithinBase checks if give path is within given base directory.
func PathWithinBase(fullPath, basePath string) bool {
	rel, err := filepath.Rel(basePath, fullPath)
	if err != nil {
		return false
	}
	if startsWithBackstep(rel) {
		// Needed to escape the base path
		return false
	}
	return true
}

// startsWithBackstep checks if the given path starts with a backstep segment
func startsWithBackstep(rel string) bool {
	// normalize to / and check for ../
	return rel == ".." || strings.HasPrefix(filepath.ToSlash(rel), "../")
}

// getFileType checks for file/directory/socket and block/character devices
func getFileType(pathname string) (FileType, error) {
	var pathType FileType
	info, err := os.Stat(pathname)
	if os.IsNotExist(err) {
		return pathType, fmt.Errorf("path %q does not exist", pathname)
	}
	// err in call to os.Stat
	if err != nil {
		return pathType, err
	}

	// checks whether the mode is the target mode
	isSpecificMode := func(mode, targetMode os.FileMode) bool {
		return mode&targetMode == targetMode
	}

	mode := info.Mode()
	if mode.IsDir() {
		return FileTypeDirectory, nil
	} else if mode.IsRegular() {
		return FileTypeFile, nil
	} else if isSpecificMode(mode, os.ModeSocket) {
		return FileTypeSocket, nil
	} else if isSpecificMode(mode, os.ModeDevice) {
		if isSpecificMode(mode, os.ModeCharDevice) {
			return FileTypeCharDev, nil
		}
		return FileTypeBlockDev, nil
	}

	return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
}
<|endoftext|>


<commit_before>// +build !windows,!plan9

package bolt

import (
	"os"
	"syscall"
	"time"
	"unsafe"
)

// flock acquires an advisory lock on a file descriptor.
func flock(f *os.File, timeout time.Duration) error {
	var t time.Time
	for {
		// If we're beyond our timeout then return an error.
		// This can only occur after we've attempted a flock once.
		if t.IsZero() {
			t = time.Now()
		} else if timeout > 0 && time.Since(t) > timeout {
			return ErrTimeout
		}

		// Otherwise attempt to obtain an exclusive lock.
		err := syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
		if err == nil {
			return nil
		} else if err != syscall.EWOULDBLOCK {
			return err
		}

		// Wait for a bit and try again.
		time.Sleep(50 * time.Millisecond)
	}
}

// funlock releases an advisory lock on a file descriptor.
func funlock(f *os.File) error {
	return syscall.Flock(int(f.Fd()), syscall.LOCK_UN)
}

// mmap memory maps a DB's data file.
func mmap(db *DB, sz int) error {
	b, err := syscall.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED)
	if err != nil {
		return err
	}

	// Save the original byte slice and convert to a byte array pointer.
	db.dataref = b
	db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0]))
	db.datasz = sz
	return nil
}

// munmap unmaps a DB's data file from memory.
func munmap(db *DB) error {
	// Ignore the unmap if we have no mapped data.
	if db.dataref == nil {
		return nil
	}

	// Unmap using the original byte slice.
	err := syscall.Munmap(db.dataref)
	db.dataref = nil
	db.data = nil
	db.datasz = 0
	return err
}
<commit_msg>Add truncate() and sync() on resize.<commit_after>// +build !windows,!plan9

package bolt

import (
	"fmt"
	"os"
	"syscall"
	"time"
	"unsafe"
)

// flock acquires an advisory lock on a file descriptor.
func flock(f *os.File, timeout time.Duration) error {
	var t time.Time
	for {
		// If we're beyond our timeout then return an error.
		// This can only occur after we've attempted a flock once.
		if t.IsZero() {
			t = time.Now()
		} else if timeout > 0 && time.Since(t) > timeout {
			return ErrTimeout
		}

		// Otherwise attempt to obtain an exclusive lock.
		err := syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
		if err == nil {
			return nil
		} else if err != syscall.EWOULDBLOCK {
			return err
		}

		// Wait for a bit and try again.
		time.Sleep(50 * time.Millisecond)
	}
}

// funlock releases an advisory lock on a file descriptor.
func funlock(f *os.File) error {
	return syscall.Flock(int(f.Fd()), syscall.LOCK_UN)
}

// mmap memory maps a DB's data file.
func mmap(db *DB, sz int) error {
	// Truncate and fsync to ensure file size metadata is flushed.
	// https://github.com/boltdb/bolt/issues/284
	if err := db.file.Truncate(int64(sz)); err != nil {
		return fmt.Errorf("file resize error: %s", err)
	}
	if err := db.file.Sync(); err != nil {
		return fmt.Errorf("file sync error: %s", err)
	}

	// Map the data file to memory.
	b, err := syscall.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED)
	if err != nil {
		return err
	}

	// Save the original byte slice and convert to a byte array pointer.
	db.dataref = b
	db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0]))
	db.datasz = sz
	return nil
}

// munmap unmaps a DB's data file from memory.
func munmap(db *DB) error {
	// Ignore the unmap if we have no mapped data.
	if db.dataref == nil {
		return nil
	}

	// Unmap using the original byte slice.
	err := syscall.Munmap(db.dataref)
	db.dataref = nil
	db.data = nil
	db.datasz = 0
	return err
}
<|endoftext|>


<commit_before>package sudoku

// Sudoku has one rule - no value can be repeated horizontally, vertically,
// or in the same section. This gives rise to a few simple rules - and those
// rules are applied across each cluster - without even knowning the orientation
// of the cluster.
//
// In order to make solving possible however, that one rule is enforced with
// the following rules:
//
// 1) If all cells are solved, that cluster is solved.
// 2) If any cell is solved, it has no possibles.
// 3) If any cell is solved, that value is not possible in other cells.
// 4) If any cell only has one possible value, that is that cell's value.
// 5) If any x cells have x possible values, those values are not possible
//  outside of those cells - those values are constrained to those cells.
// 6) If any value only has one possible cell, that is that cell's value.
// 7) If any x values have x possible cells, those cells only have those
//  possible values - those cells are constrained to those values.
//
// Additional Helper functions are included and explained later.

// indexedCLuster is a datatype for an index for the values of the cluster.
// Each possible value is a key in the map. THe value of each key is an array of
// possible locations for that value - the index and order are not defined,
// instead the values of the array are the indexes of possible cells in for that
// value.
type intArray []int
type indexedCluster map[int]intArray

func indexCluster(in []cell) (out indexedCluster) {
	for id, each := range in {
		for onePossible, _ := range each.possible {
			out[onePossible] = append(out[onePossible], id)
		}
	}
	return out
}

// A helper function to determine the number of cells hit by working across a
// number of values.
func valuesCost(markedVals []int, index indexedCluster, cluseter []cell) (int) {
	var neededCells map[int]bool
	for _, value := range markedVals{
		for oneCell, _ := range index[value]{
			neededCells[oneCell] = true
		}
	}
	return len(neededCells)
}

// A helper function to determine the number of valus hit given a specific set
// of cells.
func cellsCost(markedCells []int, cluster []cell) (int) {
	var neededValues map[int]bool
	for _, cellPos := range markedCells {
		for possibleValue, _ := range cluster[cellPos].possible {
			neededValues[possibleValue] = true
		}
	}
	return len(neededValues)
}

// This covers rule 1 from above:
// 1) If all cells are solved, that cluster is solved.
func clusterSolved(cluster []cell, u chan cell) (solved bool) {
	solved = true
	for _, each := range cluster {
		if each.actual ==0 {
			solved = false
		} else if len(each.possible) > 0 {
			solved = false
		}
	}
	return solved
}

// This covers rule 2 from above:
// 2) If any cell is solved, it has no possibles.
func solvedNoPossible(cluster []cell, u chan cell) (changed bool) {
	for _, each := range cluster {
		if each.actual == 0 {
			continue
		}
		if len(each.possible) > 0 {
			changed = true
			u <- cell{
				location: each.location,
				possible: each.possible,
			}
		}
	}
	return changed
}

// Removes known values from other possibles in the same cluster
// Covers rule 3 from above:
// 3) If any cell is solved, that value is not possible in other cells.
func eliminateKnowns(workingCluster []cell, u chan cell) bool {
	var solved map[int]bool
	var remove map[int]bool
	var changed bool

	// Loop thru and find all solved values.
	for _, each := range workingCluster {
		if each.actual != 0 {
			solved[each.actual] = true
		}
	}

	for _, each := range workingCluster {
		for i, potential := range each.possible {
			if potential && solved[i] {
				remove[i] = true
			}
		}
		if len(remove) > 0 {
			// send back removal of possibles & reset
			changed = true
			u <- cell{
				location: each.location,
				possible: remove,
			}
			remove = map[int]bool{}
		}
	}
	return changed
}

// This covers the 4th rule from above:
// 4) If any cell only has one possible value, that is that cell's value.
func singleValueSolver(cluster []cell, u chan cell) (changed bool) {
	for _, workingCell := range cluster {
		// if the cell is already solved, skip this.
		if workingCell.actual != 0 {
			continue
		}

		// if there is more than one possible value for this cell, you should be good
		if len(workingCell.possible) > 1 {
			continue
		}

		// should never happen - probably #TODO# to catch this
		if len(workingCell.possible) < 1 {
			panic("Found an unsolved cell with no possible values")
		}

		changed = true

		// this empty for loop will set value to each key in the map
		// since there's one key, it gives me that one key
		var key int
		for key, _ = range workingCell.possible {
		}

		// send back an update for this cell
		u <- cell{
			location: workingCell.location,
			actual:   key,
		}
	}
	return changed
}

// This covers rule 6 from above:
// 6) If any value only has one possible cell, that is that cell's value.
func singleCellSolver(index indexedCluster, workingCluster []cell, u chan cell) (changed bool) {
	for val, section := range index {
		if len(section) < 1 {
			// something went terribly wrong here - #TODO# add panic catch?
			panic("Found an unsolved cell with no possible values")
		} else if len(section) == 1 {
			u <- cell{
				location: workingCluster[section[0]].location,
				actual:   val,
			}
			changed = true
		}
	}
	return changed
}

func additionalCost(addVal int, markedVals map[int]bool, index indexedCluster) int {
	// skip this one if it's already marked
	if markedVals[addVal] {
		return -1
	}
	var newCols map[int]bool
	// for target, _ := range index[addVal].targets {
	for target, _ := range index[addVal] {
		newCols[target] = true
	}
	for preIndexed, _ := range markedVals {
		// for target, _ := range index[preIndexed].targets {
		for target, _ := range index[preIndexed] {
			delete(newCols, target)
		}
	}
	return len(newCols)
}

// Given certain premarked values, searches an index to find the next value to
// mark while staying under the given budget. If something is found to match
// the required values under the squares budget, changes are made.
func findPairsChild(markedVals map[int]bool, budget, required int, index indexedCluster, workingCluster []cell, u chan cell) (changed bool) {
	for possibleVal, locations := range index {
		if markedVals[possibleVal] {
			// this cell is already on the list, so skip it
			continue
		}
		// if len(locations.targets) > budget {
		if len(locations) > budget {
			// adding this cell will never fit in the budget, so skip it
			continue
		}
		// you can't add anything, so return false
		if budget < 1 {
			return false
		}
		if deduction := additionalCost(possibleVal, markedVals, index); deduction < budget {
			markedValsCopy := markedVals
			markedValsCopy[possibleVal] = true
			// if you already have the hit, mark it
			if required >= len(markedValsCopy) {
				if processSquares() {

				}

			}

			// if you need to go down recursively, do it
			if findPairsChild(makredValsCopy, budget-deduction, required, index, workingCluster) {
				return true
			}
		}
	}
}

// func findPairs(index indexedCluster, workingCluster []cell, u chan cell) (changed bool) {
// 	searchCount := 2

// 	localIndex := index
// 	for searchCount < len(index) {
// 		for val, valIndex := range localIndex {
// 			if len(valIndex.targets) <= searchCount {
// 				localIndex := index
// 				// this could be a first in a pair
// 				// probalby use something recursive to find the second match? idk

// 			}
// 		}
// 	}
// }

// func cheapestAddition(markedVals map[int]bool, index indexedCluster)(int, int){
// 	var markedCells map[int]bool
// 	for k, v :=
// }
<commit_msg>added a recursive function to cover rule #5<commit_after>package sudoku

// Sudoku has one rule - no value can be repeated horizontally, vertically,
// or in the same section. This gives rise to a few simple rules - and those
// rules are applied across each cluster - without even knowning the orientation
// of the cluster.
//
// In order to make solving possible however, that one rule is enforced with
// the following rules:
//
// 1) If all cells are solved, that cluster is solved.
// 2) If any cell is solved, it has no possibles.
// 3) If any cell is solved, that value is not possible in other cells.
// 4) If any cell only has one possible value, that is that cell's value.
// 5) If any x cells have x possible values, those values are not possible
//  outside of those cells - those values are constrained to those cells.
// 6) If any value only has one possible cell, that is that cell's value.
// 7) If any x values have x possible cells, those cells only have those
//  possible values - those cells are constrained to those values.
//
// Additional Helper functions are included and explained later.

// indexedCLuster is a datatype for an index for the values of the cluster.
// Each possible value is a key in the map. THe value of each key is an array of
// possible locations for that value - the index and order are not defined,
// instead the values of the array are the indexes of possible cells in for that
// value.
type intArray []int
type indexedCluster map[int]intArray

func indexCluster(in []cell) (out indexedCluster) {
	for id, each := range in {
		for onePossible, _ := range each.possible {
			out[onePossible] = append(out[onePossible], id)
		}
	}
	return out
}

// A helper function to determine the number of cells hit by working across a
// number of values.
func valuesCost(markedVals map[int]bool, index indexedCluster, cluseter []cell) int {
	var neededCells map[int]bool
	for value, _ := range markedVals {
		for oneCell, _ := range index[value] {
			neededCells[oneCell] = true
		}
	}
	return len(neededCells)
}

// This covers rule 1 from above:
// 1) If all cells are solved, that cluster is solved.
func clusterSolved(cluster []cell, u chan cell) (solved bool) {
	solved = true
	for _, each := range cluster {
		if each.actual == 0 {
			solved = false
		} else if len(each.possible) > 0 {
			solved = false
		}
	}
	return solved
}

// This covers rule 2 from above:
// 2) If any cell is solved, it has no possibles.
func solvedNoPossible(cluster []cell, u chan cell) (changed bool) {
	for _, each := range cluster {
		if each.actual == 0 {
			continue
		}
		if len(each.possible) > 0 {
			changed = true
			u <- cell{
				location: each.location,
				possible: each.possible,
			}
		}
	}
	return changed
}

// Removes known values from other possibles in the same cluster
// Covers rule 3 from above:
// 3) If any cell is solved, that value is not possible in other cells.
func eliminateKnowns(workingCluster []cell, u chan cell) bool {
	var solved map[int]bool
	var remove map[int]bool
	var changed bool

	// Loop thru and find all solved values.
	for _, each := range workingCluster {
		if each.actual != 0 {
			solved[each.actual] = true
		}
	}

	for _, each := range workingCluster {
		for i, potential := range each.possible {
			if potential && solved[i] {
				remove[i] = true
			}
		}
		if len(remove) > 0 {
			// send back removal of possibles & reset
			changed = true
			u <- cell{
				location: each.location,
				possible: remove,
			}
			remove = map[int]bool{}
		}
	}
	return changed
}

// This covers the 4th rule from above:
// 4) If any cell only has one possible value, that is that cell's value.
func singleValueSolver(cluster []cell, u chan cell) (changed bool) {
	for _, workingCell := range cluster {
		// if the cell is already solved, skip this.
		if workingCell.actual != 0 {
			continue
		}

		// if there is more than one possible value for this cell, you should be good
		if len(workingCell.possible) > 1 {
			continue
		}

		// should never happen - probably #TODO# to catch this
		if len(workingCell.possible) < 1 {
			panic("Found an unsolved cell with no possible values")
		}

		changed = true

		// this empty for loop will set value to each key in the map
		// since there's one key, it gives me that one key
		var key int
		for key, _ = range workingCell.possible {
		}

		// send back an update for this cell
		u <- cell{
			location: workingCell.location,
			actual:   key,
		}
	}
	return changed
}

// A helper function to determine the number of valus hit given a specific set
// of cells.
func cellsCost(markedCells map[int]bool, cluster []cell) int {
	var neededValues map[int]bool
	for cellPos, _ := range markedCells {
		for possibleValue, _ := range cluster[cellPos].possible {
			neededValues[possibleValue] = true
		}
	}
	return len(neededValues)
}

func cellLimiterChild(limit int, markedCells map[int]bool, cluster []cell, u chan cell) (changed bool) {
	valueCount := cellsCost(markedCells, cluster)
	// you have overspent - it's a no-go
	if len(markedCells) > limit {
		return false
	}

	// you have room to add more cells
	if len(markedCells) < limit {
		if valueCount < len(markedCells) {
			// #TODO# probably fix this? rework into error?
			panic("less possible values than squares to fill")
		}
		if valueCount > len(markedCells) {
			// you need to try adding each other cell
			for idCell, oneCell := range cluster {
				if oneCell.actual != 0 {
					continue
				}
				if markedCells[idCell] {
					// this cell is already in the map, skip
					continue
				}

				// decend down into looking at that cell
				childMarkedCells := markedCells // #TODO# map copy
				childMarkedCells[idCell] = true
				if cellLimiterChild(limit, childMarkedCells, cluster, u) {
					// if you got true from the child, pass it on
					return true
				}
			}
		}
	}

	// did you fill the cells? if so, mark it
	if valueCount == len(markedCells) {
		// it's a match - so remove values
		for idCell, oneCell := range cluster {
			if oneCell.actual != 0 {
				// already solved
				continue
			}
			if markedCells[idCell] {
				// this cell is a part of the list - no exclusions needed
				continue
			}
			remove := map[int]bool{}
			for potential, _ := range oneCell.possible {
				if markedCells[idCell] {
					// this possibility exists in the map - need to remove it
					remove[potential] = true
				}
			}
			if len(remove) > 0 {
				changed = true
				u <- cell{
					location: oneCell.location,
					possible: remove,
				}
			}
		}
	}
	return changed
}

// This covers rule 5:
// 5) If any x cells have x possible values, those values are not possible
//  outside of those cells - those values are constrained to those cells.
func cellLimiter(cluster []cell, u chan cell) (changed bool) {
	upperBound := len(cluster)
	for _, eachCell := range cluster{
		if eachCell.actual != 0{
			upperBound--
		}
	}
	for i :=2; i <= upperBound; i++ {
		if cellLimiterChild(i, map[int]bool{}, cluster, u) {
			changed = true
		}
	}
	return changed
}

// This covers rule 6 from above:
// 6) If any value only has one possible cell, that is that cell's value.
func singleCellSolver(index indexedCluster, workingCluster []cell, u chan cell) (changed bool) {
	for val, section := range index {
		if len(section) < 1 {
			// something went terribly wrong here - #TODO# add panic catch?
			panic("Found an unsolved cell with no possible values")
		} else if len(section) == 1 {
			u <- cell{
				location: workingCluster[section[0]].location,
				actual:   val,
			}
			changed = true
		}
	}
	return changed
}

func additionalCost(addVal int, markedVals map[int]bool, index indexedCluster) int {
	// skip this one if it's already marked
	if markedVals[addVal] {
		return -1
	}
	var newCols map[int]bool
	// for target, _ := range index[addVal].targets {
	for target, _ := range index[addVal] {
		newCols[target] = true
	}
	for preIndexed, _ := range markedVals {
		// for target, _ := range index[preIndexed].targets {
		for target, _ := range index[preIndexed] {
			delete(newCols, target)
		}
	}
	return len(newCols)
}

// Given certain premarked values, searches an index to find the next value to
// mark while staying under the given budget. If something is found to match
// the required values under the squares budget, changes are made.
func findPairsChild(markedVals map[int]bool, budget, required int, index indexedCluster, workingCluster []cell, u chan cell) (changed bool) {
	for possibleVal, locations := range index {
		if markedVals[possibleVal] {
			// this cell is already on the list, so skip it
			continue
		}
		// if len(locations.targets) > budget {
		if len(locations) > budget {
			// adding this cell will never fit in the budget, so skip it
			continue
		}
		// you can't add anything, so return false
		if budget < 1 {
			return false
		}
		if deduction := additionalCost(possibleVal, markedVals, index); deduction < budget {
			markedValsCopy := markedVals // #TODO# map copy
			markedValsCopy[possibleVal] = true
			// if you already have the hit, mark it
			if required >= len(markedValsCopy) {
				if processSquares() {

				}

			}

			// if you need to go down recursively, do it
			if findPairsChild(makredValsCopy, budget-deduction, required, index, workingCluster) {
				return true
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math/big"

	"github.com/conformal/btcec"
	"github.com/conformal/btcutil"
)

func main() {
	// Print header
	fmt.Printf("%64s %34s %34s\n", "Private", "Public", "Public Compressed")

	// Initialise big numbers with small numbers
	count, one := big.NewInt(0), big.NewInt(1)

	// Create a slice to pad our count to 32 bytes
	padded := make([]byte, 32)

	// Loop forever because we're never going to hit the end anyway
	for {
		// Increment our counter
		count.Add(count, one)

		// Copy count value's bytes to padded slice
		copy(padded[32-len(count.Bytes()):], count.Bytes())

		// Get public key
		_, public := btcec.PrivKeyFromBytes(btcec.S256(), padded)

		// Get compressed and uncompressed addresses
		caddr, _ := btcutil.NewAddressPubKey(public.SerializeCompressed(), 0xd9b4bef9)
		uaddr, _ := btcutil.NewAddressPubKey(public.SerializeUncompressed(), 0xd9b4bef9)

		// Print keys
		fmt.Printf("%x %34s %34s\n", padded, uaddr.EncodeAddress(), caddr.EncodeAddress())
	}
}
<commit_msg>Fixes #1<commit_after>package main

import (
	"fmt"
	"math/big"

	"github.com/conformal/btcec"
	"github.com/conformal/btcutil"
	"github.com/conformal/btcnet"
)

func main() {
	// Print header
	fmt.Printf("%64s %34s %34s\n", "Private", "Public", "Public Compressed")

	// Initialise big numbers with small numbers
	count, one := big.NewInt(0), big.NewInt(1)

	// Create a slice to pad our count to 32 bytes
	padded := make([]byte, 32)

	// Loop forever because we're never going to hit the end anyway
	for {
		// Increment our counter
		count.Add(count, one)

		// Copy count value's bytes to padded slice
		copy(padded[32-len(count.Bytes()):], count.Bytes())

		// Get public key
		_, public := btcec.PrivKeyFromBytes(btcec.S256(), padded)

		// Get compressed and uncompressed addresses
		caddr, _ := btcutil.NewAddressPubKey(public.SerializeCompressed(), &btcnet.MainNetParams)
		uaddr, _ := btcutil.NewAddressPubKey(public.SerializeUncompressed(), &btcnet.MainNetParams)

		// Print keys
		fmt.Printf("%x %34s %34s\n", padded, uaddr.EncodeAddress(), caddr.EncodeAddress())
	}
}
<|endoftext|>