<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package binaryprefix

import (
	"errors"
	"strconv"
)

const (
	_          = iota // ignore first value by assigning to blank identifier
	GB float64 = 1 << (10 * iota)
	TB
	PB
	EB
	ZB
	YB
)

func getValues(size string) (string, float64, error) {
	d := size[len(size)-2:]
	s := size[:len(size)-2]
	f, err := strconv.ParseFloat(s, 64)
	return d, f, err
}

// GetMB ...
func GetMB(size string) (int, error) {
	d, s, err := getValues(size)
	if err != nil {
		return 0, err
	}
	switch d {
	case "MB":
		return int(s), nil
	case "GB":
		return int(s * GB), nil
	case "TB":
		return int(s * TB), nil
	case "PB":
		return int(s * PB), nil
	case "EB":
		return int(s * EB), nil
	case "ZB":
		return int(s * ZB), nil
	case "YB":
		return int(s * YB), nil
	}
	err = errors.New("Unknown Denomination")
	return 0, err
}
<commit_msg>Added docs to all exported functions<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package binaryprefix

import (
	"errors"
	"strconv"
)

const (
	_          = iota // ignore first value by assigning to blank identifier
	GB float64 = 1 << (10 * iota)
	TB
	PB
	EB
	ZB
	YB
)

func getValues(size string) (string, float64, error) {
	d := size[len(size)-2:]
	s := size[:len(size)-2]
	f, err := strconv.ParseFloat(s, 64)
	return d, f, err
}

// GetMB gets number of megabytes as an integer given a string formatted
// following the binary prefix convention.
// https://en.wikipedia.org/wiki/Binary_prefix
//
func GetMB(size string) (int, error) {
	d, s, err := getValues(size)
	if err != nil {
		return 0, err
	}
	switch d {
	case "MB":
		return int(s), nil
	case "GB":
		return int(s * GB), nil
	case "TB":
		return int(s * TB), nil
	case "PB":
		return int(s * PB), nil
	case "EB":
		return int(s * EB), nil
	case "ZB":
		return int(s * ZB), nil
	case "YB":
		return int(s * YB), nil
	}
	err = errors.New("Unknown Denomination")
	return 0, err
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/hex"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io"
	"net/http"
	"time"

	"strconv"
	"sync"

	"crypto/sha256"

	"airdispat.ch/crypto"
	"airdispat.ch/identity"
	"airdispat.ch/message"
	"airdispat.ch/server"
	"airdispat.ch/tracker"
	"code.google.com/p/go-uuid/uuid"
)

// Start the Dispatcher
func main() {
	var (
		me      = flag.String("me", "", "Location of the server.")
		keyFile = flag.String("keyfile", "", "Location of file to get keys from.")
		apiKey  = flag.String("apikey", "", "NYTimes Newswire API Key.")

		port = flag.Int("port", 1024, "Port to run server on.")

		registerAt = flag.String("registerAt", "", "Tracker to Register Server At.")
		registerAs = flag.String("registerAs", "", "Alais for tracker.")
	)
	flag.Parse()

	mel := &NewsDispatcher{
		Me:         *me,
		KeyFile:    *keyFile,
		APIKey:     *apiKey,
		TrackerURL: *registerAt,
		Alias:      *registerAs,
	}
	err := mel.Run(*port)
	if err != nil {
		fmt.Println("Error Starting Server", err)
	}
}

type NewsDispatcher struct {
	// Basic Properties
	Me      string
	KeyFile string
	Key     *identity.Identity

	APIKey string

	// Tracker Properties
	TrackerURL string
	Alias      string

	Fetcher *newsFetcher

	// Import Logging and Such
	server.BasicServer
}

// Run will start the server with the specified database model.
func (m *NewsDispatcher) Run(port int) error {
	// Load the Server Keys
	loadedKey, err := identity.LoadKeyFromFile(m.KeyFile)
	if err != nil {
		loadedKey, err = identity.CreateIdentity()
		if err != nil {
			return err
		}
		if m.KeyFile != "" {
			err = loadedKey.SaveKeyToFile(m.KeyFile)
			if err != nil {
				return err
			}
		}
	}
	m.LogMessage("Loaded Address", loadedKey.Address.String())
	m.LogMessage("Loaded Encryption Key", hex.EncodeToString(crypto.RSAToBytes(loadedKey.Address.EncryptionKey)))

	loadedKey.SetLocation(m.Me)
	err = (&tracker.Router{
		URL:    m.TrackerURL,
		Origin: loadedKey,
	}).Register(loadedKey, m.Alias, nil)
	if err != nil {
		return err
	}

	m.Key = loadedKey

	m.Fetcher = &newsFetcher{
		News:      make(map[string]*newsItem),
		Images:    make(map[string]*newsImage),
		API:       m.APIKey,
		newsLock:  &sync.RWMutex{},
		imageLock: &sync.RWMutex{},
	}
	go m.Fetcher.StartFetch()

	// Create the AirDispatch Server
	adServer := server.Server{
		LocationName: m.Me,
		Key:          loadedKey,
		Delegate:     m,
		Handlers:     nil,
	}

	return adServer.StartServer(fmt.Sprintf("%d", port))
}

type newsFetcher struct {
	Latest *newsItem
	News   map[string]*newsItem
	Images map[string]*newsImage
	API    string

	newsLock  *sync.RWMutex
	imageLock *sync.RWMutex
}

type newsItem struct {
	ID        string
	Headline  string
	Image     string
	URL       string
	Published time.Time
}

func (n *newsItem) ToDispatch(from *identity.Identity, to *identity.Address, latest bool) (*message.EncryptedMessage, error) {
	name := n.ID
	if latest {
		name = "latest"
	}

	mail := message.CreateMail(from.Address, n.Published, name, to)
	mail.Components.AddComponent(message.CreateStringComponent("airdispat.ch/news/headline", n.Headline))
	mail.Components.AddComponent(message.CreateStringComponent("airdispat.ch/news/image", n.Image))
	mail.Components.AddComponent(message.CreateStringComponent("airdispat.ch/news/url", n.URL))
	mail.Components.AddComponent(message.CreateStringComponent("airdispat.ch/news/source", "nytimes"))

	signed, err := message.SignMessage(mail, from)
	if err != nil {
		return nil, err
	}

	return signed.UnencryptedMessage(to)
}

type newsImage struct {
	ID   string
	URL  string
	Hash []byte
}

type fakeCloser struct{ io.Reader }

func (f fakeCloser) Close() error { return nil }

func (n *newsImage) ToDispatch(from *identity.Identity, to *identity.Address) (*message.EncryptedMessage, io.ReadCloser, error) {
	if n == nil {
		return nil, nil, nil
	}

	resp, err := http.Get(string(n.URL))
	if err != nil {
		return nil, nil, err
	}

	length, err := strconv.Atoi(resp.Header.Get("Content-Length"))
	if err != nil {
		return nil, nil, err
	}

	reader := resp.Body
	hash := n.Hash

	if hash == nil {
		if length > 1e7 {
			return nil, nil, errors.New("Not setup to handle large images yet.")
		}

		b := &bytes.Buffer{}
		hasher := sha256.New()

		_, err = io.Copy(
			io.MultiWriter(b, hasher),
			resp.Body,
		)
		if err != nil {
			return nil, nil, err
		}

		hash := hasher.Sum(nil)
		reader = fakeCloser{
			Reader: b,
		}

		n.Hash = hash
	}

	dataMsg, encReader, err := message.CreateDataMessage(
		hash,
		uint64(length),
		"airdispat.ch/news/image",
		n.ID,
		"news",
		reader,
		message.CreateHeader(from.Address, to),
	)
	if err != nil {
		return nil, nil, err
	}

	signed, err := message.SignMessage(dataMsg, from)
	if err != nil {
		return nil, nil, err
	}

	encMsg, err := signed.UnencryptedMessage(to)
	if err != nil {
		return nil, nil, err
	}

	return encMsg, encReader, nil
}

type jsonNews struct {
	Section           string    `json:"section"`
	Subsection        string    `json:"subsection"`
	Title             string    `json:"title"`
	URL               string    `json:"url"`
	ThumbnailStandard string    `json:"thumnail_standard"`
	ItemType          string    `json:"item_type"`
	PublishedDate     time.Time `json:"published_date"`
}

func (m *newsFetcher) StartFetch() {
	fetchChan := time.Tick(time.Minute)

	for {
		t := <-fetchChan
		fmt.Println("Fetching News", t)
		m.FetchNews()
	}
}

func (m *newsFetcher) FetchNews() {
	resp, err := http.Get("http://api.nytimes.com/svc/news/v3/content/all/all/.json?api-key=" + m.API)
	if err != nil {
		fmt.Println("Got error getting news", err)
		return
	}
	defer resp.Body.Close()

	dec := json.NewDecoder(resp.Body)

	j := make([]*jsonNews, 0)
	err = dec.Decode(&j)
	if err != nil {
		fmt.Println("Got error translating news", err)
	}

	m.newsLock.RLock()
	latestDate := m.Latest.Published
	m.newsLock.RUnlock()

	populatedLatest := false
	for _, v := range j {
		// Check to see if we can add it.
		if v.Section != "Sports" && v.ItemType != "blog" && v.ThumbnailStandard != "" && v.PublishedDate.After(latestDate) {
			// Create the News Item
			n := &newsItem{
				ID:        uuid.NewRandom().String(),
				Headline:  v.Title,
				URL:       v.URL,
				Image:     uuid.NewRandom().String(),
				Published: v.PublishedDate,
			}

			// Create the News Image
			i := &newsImage{
				ID:  n.Image,
				URL: v.ThumbnailStandard,
			}

			m.newsLock.Lock()
			// Populate Fields!
			m.News[n.ID] = n

			// Populate Latest!
			if !populatedLatest {
				m.Latest = n
				populatedLatest = true
			}

			m.newsLock.Unlock()

			m.imageLock.Lock()
			m.Images[n.Image] = i
			m.imageLock.Unlock()
		}
	}
}

func (m *newsFetcher) GetNewsItem(name string, from *identity.Identity, to *identity.Address) *message.EncryptedMessage {
	m.newsLock.RLock()
	defer m.newsLock.RUnlock()

	data, ok := m.News[name]

	if !ok {
		return nil
	}

	msg, err := data.ToDispatch(from, to, false)
	if err != nil {
		fmt.Println("Error marshalling News Story to Dispatch", err)
		return nil
	}

	return msg
}

func (m *newsFetcher) GetLatestNewsItem(from *identity.Identity, to *identity.Address) *message.EncryptedMessage {
	m.newsLock.RLock()
	defer m.newsLock.RUnlock()

	data := m.Latest

	if data == nil {
		return nil
	}

	msg, err := data.ToDispatch(from, to, true)
	if err != nil {
		fmt.Println("Error marshalling News Story to Dispatch", err)
		return nil
	}

	return msg
}

func (m *newsFetcher) GetData(name string, from *identity.Identity, to *identity.Address) (*message.EncryptedMessage, io.ReadCloser) {
	m.imageLock.RLock()
	defer m.imageLock.RUnlock()

	data, ok := m.Images[name]

	if !ok {
		return nil, nil
	}

	msg, r, err := data.ToDispatch(from, to)
	if err != nil {
		fmt.Println("Error marshalling News Story to Dispatch", err)
		return nil, nil
	}

	return msg, r
}

// SaveMessageDescription is not implemented on this server.
func (m *NewsDispatcher) SaveMessageDescription(desc *message.EncryptedMessage) {}

// RetrieveMessageListForUser is not implemented on this server.
func (m *NewsDispatcher) RetrieveMessageListForUser(since uint64, author *identity.Address, forAddr *identity.Address) []*message.EncryptedMessage {
	return nil
}

func (m *NewsDispatcher) RetrieveDataForUser(id string, author *identity.Address, forAddr *identity.Address) (*message.EncryptedMessage, io.ReadCloser) {
	return m.Fetcher.GetData(id, m.Key, forAddr)
}

func (m *NewsDispatcher) RetrieveMessageForUser(id string, author *identity.Address, forAddr *identity.Address) *message.EncryptedMessage {
	if id == "latest" {
		return m.Fetcher.GetLatestNewsItem(m.Key, forAddr)
	}

	return m.Fetcher.GetNewsItem(id, m.Key, forAddr)
}
<commit_msg>Fixed Errors in News Dispatcher<commit_after>package main

import (
	"bytes"
	"encoding/hex"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io"
	"net/http"
	"time"

	"strconv"
	"sync"

	"crypto/sha256"

	"airdispat.ch/crypto"
	"airdispat.ch/identity"
	"airdispat.ch/message"
	"airdispat.ch/server"
	"airdispat.ch/tracker"
	"code.google.com/p/go-uuid/uuid"
)

// Start the Dispatcher
func main() {
	var (
		me      = flag.String("me", "", "Location of the server.")
		keyFile = flag.String("keyfile", "", "Location of file to get keys from.")
		apiKey  = flag.String("apikey", "", "NYTimes Newswire API Key.")

		port = flag.Int("port", 1024, "Port to run server on.")

		registerAt = flag.String("registerAt", "", "Tracker to Register Server At.")
		registerAs = flag.String("registerAs", "", "Alais for tracker.")
	)
	flag.Parse()

	mel := &NewsDispatcher{
		Me:         *me,
		KeyFile:    *keyFile,
		APIKey:     *apiKey,
		TrackerURL: *registerAt,
		Alias:      *registerAs,
	}
	err := mel.Run(*port)
	if err != nil {
		fmt.Println("Error Starting Server", err)
	}
}

type NewsDispatcher struct {
	// Basic Properties
	Me      string
	KeyFile string
	Key     *identity.Identity

	APIKey string

	// Tracker Properties
	TrackerURL string
	Alias      string

	Fetcher *newsFetcher

	// Import Logging and Such
	server.BasicServer
}

// Run will start the server with the specified database model.
func (m *NewsDispatcher) Run(port int) error {
	// Load the Server Keys
	loadedKey, err := identity.LoadKeyFromFile(m.KeyFile)
	if err != nil {
		loadedKey, err = identity.CreateIdentity()
		if err != nil {
			return err
		}
		if m.KeyFile != "" {
			err = loadedKey.SaveKeyToFile(m.KeyFile)
			if err != nil {
				return err
			}
		}
	}
	m.LogMessage("Loaded Address", loadedKey.Address.String())
	m.LogMessage("Loaded Encryption Key", hex.EncodeToString(crypto.RSAToBytes(loadedKey.Address.EncryptionKey)))

	loadedKey.SetLocation(m.Me)
	err = (&tracker.Router{
		URL:    m.TrackerURL,
		Origin: loadedKey,
	}).Register(loadedKey, m.Alias, nil)
	if err != nil {
		return err
	}

	m.Key = loadedKey

	m.Fetcher = &newsFetcher{
		News:      make(map[string]*newsItem),
		Images:    make(map[string]*newsImage),
		API:       m.APIKey,
		newsLock:  &sync.RWMutex{},
		imageLock: &sync.RWMutex{},
	}
	go m.Fetcher.StartFetch()

	// Create the AirDispatch Server
	adServer := server.Server{
		LocationName: m.Me,
		Key:          loadedKey,
		Delegate:     m,
		Handlers:     nil,
	}

	return adServer.StartServer(fmt.Sprintf("%d", port))
}

type newsFetcher struct {
	Latest *newsItem
	News   map[string]*newsItem
	Images map[string]*newsImage
	API    string

	newsLock  *sync.RWMutex
	imageLock *sync.RWMutex
}

type newsItem struct {
	ID        string
	Headline  string
	Image     string
	URL       string
	Published time.Time
}

func (n *newsItem) ToDispatch(from *identity.Identity, to *identity.Address, latest bool) (*message.EncryptedMessage, error) {
	name := n.ID
	if latest {
		name = "latest"
	}

	mail := message.CreateMail(from.Address, n.Published, name, to)
	mail.Components.AddComponent(message.CreateStringComponent("airdispat.ch/news/headline", n.Headline))
	mail.Components.AddComponent(message.CreateStringComponent("airdispat.ch/news/image", n.Image))
	mail.Components.AddComponent(message.CreateStringComponent("airdispat.ch/news/url", n.URL))
	mail.Components.AddComponent(message.CreateStringComponent("airdispat.ch/news/source", "nytimes"))

	signed, err := message.SignMessage(mail, from)
	if err != nil {
		return nil, err
	}

	return signed.UnencryptedMessage(to)
}

type newsImage struct {
	ID   string
	URL  string
	Hash []byte
}

type fakeCloser struct{ io.Reader }

func (f fakeCloser) Close() error { return nil }

func (n *newsImage) ToDispatch(from *identity.Identity, to *identity.Address) (*message.EncryptedMessage, io.ReadCloser, error) {
	if n == nil {
		return nil, nil, nil
	}

	resp, err := http.Get(string(n.URL))
	if err != nil {
		return nil, nil, err
	}

	length, err := strconv.Atoi(resp.Header.Get("Content-Length"))
	if err != nil {
		return nil, nil, err
	}

	reader := resp.Body
	hash := n.Hash

	if hash == nil {
		if length > 1e7 {
			return nil, nil, errors.New("Not setup to handle large images yet.")
		}

		b := &bytes.Buffer{}
		hasher := sha256.New()

		_, err = io.Copy(
			io.MultiWriter(b, hasher),
			resp.Body,
		)
		if err != nil {
			return nil, nil, err
		}

		hash := hasher.Sum(nil)
		reader = fakeCloser{
			Reader: b,
		}

		n.Hash = hash
	}

	dataMsg, encReader, err := message.CreateDataMessage(
		hash,
		uint64(length),
		"airdispat.ch/news/image",
		n.ID,
		"news",
		reader,
		message.CreateHeader(from.Address, to),
	)
	if err != nil {
		return nil, nil, err
	}

	signed, err := message.SignMessage(dataMsg, from)
	if err != nil {
		return nil, nil, err
	}

	encMsg, err := signed.UnencryptedMessage(to)
	if err != nil {
		return nil, nil, err
	}

	return encMsg, encReader, nil
}

type jsonTimes struct {
	Results []*jsonNews `json:"results"`
}

type jsonNews struct {
	Section           string    `json:"section"`
	Subsection        string    `json:"subsection"`
	Title             string    `json:"title"`
	URL               string    `json:"url"`
	ThumbnailStandard string    `json:"thumbnail_standard"`
	ItemType          string    `json:"item_type"`
	PublishedDate     time.Time `json:"published_date"`
}

func (m *newsFetcher) StartFetch() {
	fetchChan := time.Tick(time.Minute)

	for {
		t := <-fetchChan
		fmt.Println("Fetching News", t)
		m.FetchNews()
	}
}

func (m *newsFetcher) FetchNews() {
	resp, err := http.Get("http://api.nytimes.com/svc/news/v3/content/all/all/.json?api-key=" + m.API)
	if err != nil {
		fmt.Println("Got error getting news", err)
		return
	}
	defer resp.Body.Close()

	dec := json.NewDecoder(resp.Body)

	// j := make([]*jsonNews, 0)
	t := &jsonTimes{}
	err = dec.Decode(t)
	if err != nil {
		fmt.Println("Got error translating news", err)
		return
	}
	j := t.Results

	var latestDate time.Time

	if m.Latest != nil {
		m.newsLock.RLock()
		latestDate = m.Latest.Published
		m.newsLock.RUnlock()
	}

	populatedLatest := false
	for _, v := range j {
		// Check to see if we can add it.
		// fmt.Println(v)
		if v.Section != "Sports" && v.ItemType == "Article" && v.ThumbnailStandard != "" && v.PublishedDate.After(latestDate) {
			fmt.Println("Found a news story!")
			// Create the News Item
			n := &newsItem{
				ID:        uuid.NewRandom().String(),
				Headline:  v.Title,
				URL:       v.URL,
				Image:     uuid.NewRandom().String(),
				Published: v.PublishedDate,
			}

			// Create the News Image
			i := &newsImage{
				ID:  n.Image,
				URL: v.ThumbnailStandard,
			}

			m.newsLock.Lock()
			// Populate Fields!
			m.News[n.ID] = n

			// Populate Latest!
			if !populatedLatest {
				m.Latest = n
				populatedLatest = true
			}

			m.newsLock.Unlock()

			m.imageLock.Lock()
			m.Images[n.Image] = i
			m.imageLock.Unlock()
		}
	}

	fmt.Println("Finished Fetching News.")
}

func (m *newsFetcher) GetNewsItem(name string, from *identity.Identity, to *identity.Address) *message.EncryptedMessage {
	m.newsLock.RLock()
	defer m.newsLock.RUnlock()

	data, ok := m.News[name]

	if !ok {
		return nil
	}

	msg, err := data.ToDispatch(from, to, false)
	if err != nil {
		fmt.Println("Error marshalling News Story to Dispatch", err)
		return nil
	}

	return msg
}

func (m *newsFetcher) GetLatestNewsItem(from *identity.Identity, to *identity.Address) *message.EncryptedMessage {
	m.newsLock.RLock()
	defer m.newsLock.RUnlock()

	data := m.Latest

	if data == nil {
		fmt.Println("No latest news yet.")
		return nil
	}

	msg, err := data.ToDispatch(from, to, true)
	if err != nil {
		fmt.Println("Error marshalling News Story to Dispatch", err)
		return nil
	}

	return msg
}

func (m *newsFetcher) GetData(name string, from *identity.Identity, to *identity.Address) (*message.EncryptedMessage, io.ReadCloser) {
	m.imageLock.RLock()
	defer m.imageLock.RUnlock()

	data, ok := m.Images[name]

	if !ok {
		return nil, nil
	}

	msg, r, err := data.ToDispatch(from, to)
	if err != nil {
		fmt.Println("Error marshalling News Story to Dispatch", err)
		return nil, nil
	}

	return msg, r
}

// SaveMessageDescription is not implemented on this server.
func (m *NewsDispatcher) SaveMessageDescription(desc *message.EncryptedMessage) {}

// RetrieveMessageListForUser is not implemented on this server.
func (m *NewsDispatcher) RetrieveMessageListForUser(since uint64, author *identity.Address, forAddr *identity.Address) []*message.EncryptedMessage {
	return nil
}

func (m *NewsDispatcher) RetrieveDataForUser(id string, author *identity.Address, forAddr *identity.Address) (*message.EncryptedMessage, io.ReadCloser) {
	return m.Fetcher.GetData(id, m.Key, forAddr)
}

func (m *NewsDispatcher) RetrieveMessageForUser(id string, author *identity.Address, forAddr *identity.Address) *message.EncryptedMessage {
	if id == "latest" {
		return m.Fetcher.GetLatestNewsItem(m.Key, forAddr)
	}

	return m.Fetcher.GetNewsItem(id, m.Key, forAddr)
}
<|endoftext|>


<commit_before>package main

import (
	"archive/zip"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"

	. "github.com/dvyukov/go-fuzz/go-fuzz-defs"
)

var (
	flagOut        = flag.String("o", "", "output file")
	flagFunc       = flag.String("func", "Fuzz", "entry function")
	flagWork       = flag.Bool("work", false, "don't remove working directory")
	flagInstrument = flag.String("instrument", "", "instrument a single file (for debugging)")

	workdir string
)

const (
	mainPkg = "go-fuzz-main"
)

// Copies the package with all dependent packages into a temp dir,
// instruments Go source files there and builds setting GOROOT to the temp dir.
func main() {
	flag.Parse()
	if *flagInstrument != "" {
		f := tempFile()
		instrument("pkg", "pkg/file.go", *flagInstrument, f, nil, nil, nil)
		fmt.Println(string(readFile(f)))
		os.Exit(0)
	}
	if len(flag.Args()) != 1 || len(flag.Arg(0)) == 0 {
		failf("usage: go-fuzz-build pkg")
	}
	GOROOT := os.Getenv("GOROOT")
	if GOROOT == "" {
		out, err := exec.Command("go", "env", "GOROOT").CombinedOutput()
		if err != nil || len(out) == 0 {
			failf("GOROOT is not set and failed to locate it: 'go env GOROOT' returned '%s' (%v)", out, err)
		}
		GOROOT = strings.Trim(string(out), "\n\t ")
	}
	pkg := flag.Arg(0)
	if pkg[0] == '.' {
		failf("relative import paths are not supported, please specify full package name")
	}

	// To produce error messages (this is much faster and gives correct line numbers).
	testNormalBuild(pkg)

	deps := make(map[string]bool)
	for _, p := range goListList(pkg, "Deps") {
		deps[p] = true
	}
	deps[pkg] = true
	// These packages are used by go-fuzz-dep, so we need to copy them regardless.
	deps["runtime"] = true
	deps["syscall"] = true
	deps["time"] = true
	deps["errors"] = true
	deps["unsafe"] = true
	deps["sync"] = true
	deps["sync/atomic"] = true
	if runtime.GOOS == "windows" {
		// syscall depends on unicode/utf16.
		// Cross-compilation is not implemented.
		deps["unicode/utf16"] = true
	}

	lits := make(map[Literal]struct{})
	var blocks, sonar []CoverBlock
	coverBin := buildInstrumentedBinary(pkg, deps, lits, &blocks, nil)
	sonarBin := buildInstrumentedBinary(pkg, deps, nil, nil, &sonar)
	metaData := createMeta(lits, blocks, sonar)
	defer func() {
		os.Remove(coverBin)
		os.Remove(sonarBin)
		os.Remove(metaData)
	}()

	if *flagOut == "" {
		*flagOut = goListProps(pkg, "Name")[0] + "-fuzz.zip"
	}
	outf, err := os.Create(*flagOut)
	if err != nil {
		failf("failed to create output file: %v", err)
	}
	zipw := zip.NewWriter(outf)
	zipFile := func(name, datafile string) {
		w, err := zipw.Create(name)
		if err != nil {
			failf("failed to create zip file: %v", err)
		}
		if _, err := w.Write(readFile(datafile)); err != nil {
			failf("failed to write to zip file: %v", err)
		}
	}
	zipFile("cover.exe", coverBin)
	zipFile("sonar.exe", sonarBin)
	zipFile("metadata", metaData)
	if err := zipw.Close(); err != nil {
		failf("failed to close zip file: %v", err)
	}
	if err := outf.Close(); err != nil {
		failf("failed to close out file: %v", err)
	}
}

func testNormalBuild(pkg string) {
	var err error
	workdir, err = ioutil.TempDir("", "go-fuzz-build")
	if err != nil {
		failf("failed to create temp dir: %v", err)
	}
	if *flagWork {
		fmt.Printf("workdir: %v\n", workdir)
	} else {
		defer os.RemoveAll(workdir)
	}
	defer func() {
		workdir = ""
	}()
	createFuzzMain(pkg)
	cmd := exec.Command("go", "build", "-tags", "gofuzz", "-o", filepath.Join(workdir, "bin"), mainPkg)
	cmd.Env = append([]string{"GOPATH=" + workdir + string(os.PathListSeparator) + os.Getenv("GOPATH")}, os.Environ()...)
	if out, err := cmd.CombinedOutput(); err != nil {
		failf("failed to execute go build: %v\n%v", err, string(out))
	}
}

func createMeta(lits map[Literal]struct{}, blocks []CoverBlock, sonar []CoverBlock) string {
	meta := MetaData{Blocks: blocks, Sonar: sonar}
	for k := range lits {
		meta.Literals = append(meta.Literals, k)
	}
	data, err := json.Marshal(meta)
	if err != nil {
		failf("failed to serialize meta information: %v", err)
	}
	f := tempFile()
	writeFile(f, data)
	return f
}

func buildInstrumentedBinary(pkg string, deps map[string]bool, lits map[Literal]struct{}, blocks *[]CoverBlock, sonar *[]CoverBlock) string {
	var err error
	workdir, err = ioutil.TempDir("", "go-fuzz-build")
	if err != nil {
		failf("failed to create temp dir: %v", err)
	}
	if *flagWork {
		fmt.Printf("workdir: %v\n", workdir)
	} else {
		defer func() {
			os.RemoveAll(workdir)
			workdir = ""
		}()
	}

	if deps["runtime/cgo"] {
		// Trick go command into thinking that it has up-to-date sources for cmd/cgo.
		cgoDir := filepath.Join(workdir, "src", "cmd", "cgo")
		if err := os.MkdirAll(cgoDir, 0700); err != nil {
			failf("failed to create temp dir: %v", err)
		}
		src := "// +build never\npackage main\n"
		writeFile(filepath.Join(cgoDir, "fake.go"), []byte(src))
	}
	copyDir(filepath.Join(GOROOT, "pkg", "tool"), filepath.Join(workdir, "pkg", "tool"), true, nil)
	if _, err := os.Stat(filepath.Join(GOROOT, "pkg", "include")); err == nil {
		copyDir(filepath.Join(GOROOT, "pkg", "include"), filepath.Join(workdir, "pkg", "include"), true, nil)
	} else {
		// Cross-compilation is not implemented.
		copyDir(filepath.Join(GOROOT, "pkg", runtime.GOOS+"_"+runtime.GOARCH), filepath.Join(workdir, "pkg", runtime.GOOS+"_"+runtime.GOARCH), true, nil)
	}
	for p := range deps {
		clonePackage(workdir, p, lits, blocks, sonar)
	}
	createFuzzMain(pkg)

	outf := tempFile() + ".exe"
	cmd := exec.Command("go", "build", "-tags", "gofuzz", "-o", outf, mainPkg)
	for _, v := range os.Environ() {
		if strings.HasPrefix(v, "GOROOT") {
			continue
		}
		cmd.Env = append(cmd.Env, v)
	}
	cmd.Env = append(cmd.Env, "GOROOT="+workdir)
	if out, err := cmd.CombinedOutput(); err != nil {
		failf("failed to execute go build: %v\n%v", err, string(out))
	}
	return outf
}

func createFuzzMain(pkg string) {
	if err := os.MkdirAll(filepath.Join(workdir, "src", mainPkg), 0700); err != nil {
		failf("failed to create temp dir: %v", err)
	}
	src := fmt.Sprintf(mainSrc, pkg, *flagFunc)
	writeFile(filepath.Join(workdir, "src", mainPkg, "main.go"), []byte(src))
}

func clonePackage(workdir, pkg string, lits map[Literal]struct{}, blocks *[]CoverBlock, sonar *[]CoverBlock) {
	dir := goListProps(pkg, "Dir")[0]
	if !strings.HasSuffix(filepath.ToSlash(dir), pkg) {
		failf("package dir '%v' does not end with import path '%v'", dir, pkg)
	}
	newDir := filepath.Join(workdir, "src", pkg)
	copyDir(dir, newDir, false, isSourceFile)
	ignore := map[string]bool{
		"runtime":       true, // lots of non-determinism and irrelevant code paths (e.g. different paths in mallocgc, chans and maps)
		"unsafe":        true, // nothing to see here (also creates import cycle with go-fuzz-dep)
		"errors":        true, // nothing to see here (also creates import cycle with go-fuzz-dep)
		"syscall":       true, // creates import cycle with go-fuzz-dep (and probably nothing to see here)
		"sync":          true, // non-deterministic and not interesting (also creates import cycle with go-fuzz-dep)
		"sync/atomic":   true, // not interesting (also creates import cycle with go-fuzz-dep)
		"time":          true, // creates import cycle with go-fuzz-dep
		"runtime/cgo":   true, // why would we instrument it?
		"runtime/pprof": true, // why would we instrument it?
		"runtime/race":  true, // why would we instrument it?
	}
	if runtime.GOOS == "windows" {
		// syscall depends on unicode/utf16.
		// Cross-compilation is not implemented.
		ignore["unicode/utf16"] = true
	}
	nolits := map[string]bool{
		"math":    true,
		"os":      true,
		"unicode": true,
	}
	if ignore[pkg] {
		return
	}
	if nolits[pkg] {
		lits = nil
	}
	files, err := ioutil.ReadDir(newDir)
	if err != nil {
		failf("failed to scan dir '%v': %v", dir, err)
	}
	for _, f := range files {
		if f.IsDir() {
			continue
		}
		if !strings.HasSuffix(f.Name(), ".go") {
			continue
		}
		fn := filepath.Join(newDir, f.Name())
		newFn := fn + ".cover"
		instrument(pkg, filepath.Join(pkg, f.Name()), fn, newFn, lits, blocks, sonar)
		os.Remove(fn)
		err := os.Rename(newFn, fn)
		if err != nil {
			failf("failed to rename file: %v", err)
		}
	}
}

func copyDir(dir, newDir string, rec bool, pred func(string) bool) {
	if err := os.MkdirAll(newDir, 0700); err != nil {
		failf("failed to create temp dir: %v", err)
	}
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		failf("failed to scan dir '%v': %v", dir, err)
	}
	for _, f := range files {
		if f.IsDir() {
			if rec {
				copyDir(filepath.Join(dir, f.Name()), filepath.Join(newDir, f.Name()), rec, pred)
			}
			continue
		}
		if pred != nil && !pred(f.Name()) {
			continue
		}
		data := readFile(filepath.Join(dir, f.Name()))
		writeFile(filepath.Join(newDir, f.Name()), data)
	}
}

func goListList(pkg, what string) []string {
	templ := fmt.Sprintf("{{range .%v}}{{.}}|{{end}}", what)
	out, err := exec.Command("go", "list", "-tags", "gofuzz", "-f", templ, pkg).CombinedOutput()
	if err != nil {
		failf("failed to execute 'go list -f \"%v\" %v': %v\n%v", templ, pkg, err, string(out))
	}
	if len(out) < 2 {
		failf("go list output is empty")
	}
	out = out[:len(out)-2]
	return strings.Split(string(out), "|")
}

func goListProps(pkg string, props ...string) []string {
	templ := ""
	for _, p := range props {
		templ += fmt.Sprintf("{{.%v}}|", p)
	}
	out, err := exec.Command("go", "list", "-tags", "gofuzz", "-f", templ, pkg).CombinedOutput()
	if err != nil {
		failf("failed to execute 'go list -f \"%v\" %v': %v\n%v", templ, pkg, err, string(out))
	}
	if len(out) == 0 {
		failf("go list output is empty")
	}
	out = out[:len(out)-1]
	return strings.Split(string(out), "|")
}

func failf(str string, args ...interface{}) {
	if !*flagWork && workdir != "" {
		os.RemoveAll(workdir)
	}
	fmt.Fprintf(os.Stderr, str+"\n", args...)
	os.Exit(1)
}

func tempFile() string {
	outf, err := ioutil.TempFile("", "go-fuzz")
	if err != nil {
		failf("failed to create temp file: %v", err)
	}
	outf.Close()
	return outf.Name()
}

func readFile(name string) []byte {
	data, err := ioutil.ReadFile(name)
	if err != nil {
		failf("failed to read temp file: %v", err)
	}
	return data
}

func writeFile(name string, data []byte) {
	if err := ioutil.WriteFile(name, data, 0700); err != nil {
		failf("failed to write temp file: %v", err)
	}
}

func isSourceFile(f string) bool {
	return (strings.HasSuffix(f, ".go") && !strings.HasSuffix(f, "_test.go")) ||
		strings.HasSuffix(f, ".s") ||
		strings.HasSuffix(f, ".S") ||
		strings.HasSuffix(f, ".c") ||
		strings.HasSuffix(f, ".h") ||
		strings.HasSuffix(f, ".cxx") ||
		strings.HasSuffix(f, ".cpp") ||
		strings.HasSuffix(f, ".c++") ||
		strings.HasSuffix(f, ".cc")
}

func isHeaderFile(f string) bool {
	return strings.HasSuffix(f, ".h")
}

var mainSrc = `
package main

import (
	target "%v"
	dep "github.com/dvyukov/go-fuzz/go-fuzz-dep"
)

func main() {
	dep.Main(target.%v)
}
`
<commit_msg>fix code after merge<commit_after>package main

import (
	"archive/zip"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"

	. "github.com/dvyukov/go-fuzz/go-fuzz-defs"
)

var (
	flagOut        = flag.String("o", "", "output file")
	flagFunc       = flag.String("func", "Fuzz", "entry function")
	flagWork       = flag.Bool("work", false, "don't remove working directory")
	flagInstrument = flag.String("instrument", "", "instrument a single file (for debugging)")

	workdir string
	GOROOT  string
)

const (
	mainPkg = "go-fuzz-main"
)

// Copies the package with all dependent packages into a temp dir,
// instruments Go source files there and builds setting GOROOT to the temp dir.
func main() {
	flag.Parse()
	if *flagInstrument != "" {
		f := tempFile()
		instrument("pkg", "pkg/file.go", *flagInstrument, f, nil, nil, nil)
		fmt.Println(string(readFile(f)))
		os.Exit(0)
	}
	if len(flag.Args()) != 1 || len(flag.Arg(0)) == 0 {
		failf("usage: go-fuzz-build pkg")
	}
	GOROOT = os.Getenv("GOROOT")
	if GOROOT == "" {
		out, err := exec.Command("go", "env", "GOROOT").CombinedOutput()
		if err != nil || len(out) == 0 {
			failf("GOROOT is not set and failed to locate it: 'go env GOROOT' returned '%s' (%v)", out, err)
		}
		GOROOT = strings.Trim(string(out), "\n\t ")
	}
	pkg := flag.Arg(0)
	if pkg[0] == '.' {
		failf("relative import paths are not supported, please specify full package name")
	}

	// To produce error messages (this is much faster and gives correct line numbers).
	testNormalBuild(pkg)

	deps := make(map[string]bool)
	for _, p := range goListList(pkg, "Deps") {
		deps[p] = true
	}
	deps[pkg] = true
	// These packages are used by go-fuzz-dep, so we need to copy them regardless.
	deps["runtime"] = true
	deps["syscall"] = true
	deps["time"] = true
	deps["errors"] = true
	deps["unsafe"] = true
	deps["sync"] = true
	deps["sync/atomic"] = true
	if runtime.GOOS == "windows" {
		// syscall depends on unicode/utf16.
		// Cross-compilation is not implemented.
		deps["unicode/utf16"] = true
	}

	lits := make(map[Literal]struct{})
	var blocks, sonar []CoverBlock
	coverBin := buildInstrumentedBinary(pkg, deps, lits, &blocks, nil)
	sonarBin := buildInstrumentedBinary(pkg, deps, nil, nil, &sonar)
	metaData := createMeta(lits, blocks, sonar)
	defer func() {
		os.Remove(coverBin)
		os.Remove(sonarBin)
		os.Remove(metaData)
	}()

	if *flagOut == "" {
		*flagOut = goListProps(pkg, "Name")[0] + "-fuzz.zip"
	}
	outf, err := os.Create(*flagOut)
	if err != nil {
		failf("failed to create output file: %v", err)
	}
	zipw := zip.NewWriter(outf)
	zipFile := func(name, datafile string) {
		w, err := zipw.Create(name)
		if err != nil {
			failf("failed to create zip file: %v", err)
		}
		if _, err := w.Write(readFile(datafile)); err != nil {
			failf("failed to write to zip file: %v", err)
		}
	}
	zipFile("cover.exe", coverBin)
	zipFile("sonar.exe", sonarBin)
	zipFile("metadata", metaData)
	if err := zipw.Close(); err != nil {
		failf("failed to close zip file: %v", err)
	}
	if err := outf.Close(); err != nil {
		failf("failed to close out file: %v", err)
	}
}

func testNormalBuild(pkg string) {
	var err error
	workdir, err = ioutil.TempDir("", "go-fuzz-build")
	if err != nil {
		failf("failed to create temp dir: %v", err)
	}
	if *flagWork {
		fmt.Printf("workdir: %v\n", workdir)
	} else {
		defer os.RemoveAll(workdir)
	}
	defer func() {
		workdir = ""
	}()
	createFuzzMain(pkg)
	cmd := exec.Command("go", "build", "-tags", "gofuzz", "-o", filepath.Join(workdir, "bin"), mainPkg)
	cmd.Env = append([]string{"GOPATH=" + workdir + string(os.PathListSeparator) + os.Getenv("GOPATH")}, os.Environ()...)
	if out, err := cmd.CombinedOutput(); err != nil {
		failf("failed to execute go build: %v\n%v", err, string(out))
	}
}

func createMeta(lits map[Literal]struct{}, blocks []CoverBlock, sonar []CoverBlock) string {
	meta := MetaData{Blocks: blocks, Sonar: sonar}
	for k := range lits {
		meta.Literals = append(meta.Literals, k)
	}
	data, err := json.Marshal(meta)
	if err != nil {
		failf("failed to serialize meta information: %v", err)
	}
	f := tempFile()
	writeFile(f, data)
	return f
}

func buildInstrumentedBinary(pkg string, deps map[string]bool, lits map[Literal]struct{}, blocks *[]CoverBlock, sonar *[]CoverBlock) string {
	var err error
	workdir, err = ioutil.TempDir("", "go-fuzz-build")
	if err != nil {
		failf("failed to create temp dir: %v", err)
	}
	if *flagWork {
		fmt.Printf("workdir: %v\n", workdir)
	} else {
		defer func() {
			os.RemoveAll(workdir)
			workdir = ""
		}()
	}

	if deps["runtime/cgo"] {
		// Trick go command into thinking that it has up-to-date sources for cmd/cgo.
		cgoDir := filepath.Join(workdir, "src", "cmd", "cgo")
		if err := os.MkdirAll(cgoDir, 0700); err != nil {
			failf("failed to create temp dir: %v", err)
		}
		src := "// +build never\npackage main\n"
		writeFile(filepath.Join(cgoDir, "fake.go"), []byte(src))
	}
	copyDir(filepath.Join(GOROOT, "pkg", "tool"), filepath.Join(workdir, "pkg", "tool"), true, nil)
	if _, err := os.Stat(filepath.Join(GOROOT, "pkg", "include")); err == nil {
		copyDir(filepath.Join(GOROOT, "pkg", "include"), filepath.Join(workdir, "pkg", "include"), true, nil)
	} else {
		// Cross-compilation is not implemented.
		copyDir(filepath.Join(GOROOT, "pkg", runtime.GOOS+"_"+runtime.GOARCH), filepath.Join(workdir, "pkg", runtime.GOOS+"_"+runtime.GOARCH), true, nil)
	}
	for p := range deps {
		clonePackage(workdir, p, lits, blocks, sonar)
	}
	createFuzzMain(pkg)

	outf := tempFile() + ".exe"
	cmd := exec.Command("go", "build", "-tags", "gofuzz", "-o", outf, mainPkg)
	for _, v := range os.Environ() {
		if strings.HasPrefix(v, "GOROOT") {
			continue
		}
		cmd.Env = append(cmd.Env, v)
	}
	cmd.Env = append(cmd.Env, "GOROOT="+workdir)
	if out, err := cmd.CombinedOutput(); err != nil {
		failf("failed to execute go build: %v\n%v", err, string(out))
	}
	return outf
}

func createFuzzMain(pkg string) {
	if err := os.MkdirAll(filepath.Join(workdir, "src", mainPkg), 0700); err != nil {
		failf("failed to create temp dir: %v", err)
	}
	src := fmt.Sprintf(mainSrc, pkg, *flagFunc)
	writeFile(filepath.Join(workdir, "src", mainPkg, "main.go"), []byte(src))
}

func clonePackage(workdir, pkg string, lits map[Literal]struct{}, blocks *[]CoverBlock, sonar *[]CoverBlock) {
	dir := goListProps(pkg, "Dir")[0]
	if !strings.HasSuffix(filepath.ToSlash(dir), pkg) {
		failf("package dir '%v' does not end with import path '%v'", dir, pkg)
	}
	newDir := filepath.Join(workdir, "src", pkg)
	copyDir(dir, newDir, false, isSourceFile)
	ignore := map[string]bool{
		"runtime":       true, // lots of non-determinism and irrelevant code paths (e.g. different paths in mallocgc, chans and maps)
		"unsafe":        true, // nothing to see here (also creates import cycle with go-fuzz-dep)
		"errors":        true, // nothing to see here (also creates import cycle with go-fuzz-dep)
		"syscall":       true, // creates import cycle with go-fuzz-dep (and probably nothing to see here)
		"sync":          true, // non-deterministic and not interesting (also creates import cycle with go-fuzz-dep)
		"sync/atomic":   true, // not interesting (also creates import cycle with go-fuzz-dep)
		"time":          true, // creates import cycle with go-fuzz-dep
		"runtime/cgo":   true, // why would we instrument it?
		"runtime/pprof": true, // why would we instrument it?
		"runtime/race":  true, // why would we instrument it?
	}
	if runtime.GOOS == "windows" {
		// syscall depends on unicode/utf16.
		// Cross-compilation is not implemented.
		ignore["unicode/utf16"] = true
	}
	nolits := map[string]bool{
		"math":    true,
		"os":      true,
		"unicode": true,
	}
	if ignore[pkg] {
		return
	}
	if nolits[pkg] {
		lits = nil
	}
	files, err := ioutil.ReadDir(newDir)
	if err != nil {
		failf("failed to scan dir '%v': %v", dir, err)
	}
	for _, f := range files {
		if f.IsDir() {
			continue
		}
		if !strings.HasSuffix(f.Name(), ".go") {
			continue
		}
		fn := filepath.Join(newDir, f.Name())
		newFn := fn + ".cover"
		instrument(pkg, filepath.Join(pkg, f.Name()), fn, newFn, lits, blocks, sonar)
		os.Remove(fn)
		err := os.Rename(newFn, fn)
		if err != nil {
			failf("failed to rename file: %v", err)
		}
	}
}

func copyDir(dir, newDir string, rec bool, pred func(string) bool) {
	if err := os.MkdirAll(newDir, 0700); err != nil {
		failf("failed to create temp dir: %v", err)
	}
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		failf("failed to scan dir '%v': %v", dir, err)
	}
	for _, f := range files {
		if f.IsDir() {
			if rec {
				copyDir(filepath.Join(dir, f.Name()), filepath.Join(newDir, f.Name()), rec, pred)
			}
			continue
		}
		if pred != nil && !pred(f.Name()) {
			continue
		}
		data := readFile(filepath.Join(dir, f.Name()))
		writeFile(filepath.Join(newDir, f.Name()), data)
	}
}

func goListList(pkg, what string) []string {
	templ := fmt.Sprintf("{{range .%v}}{{.}}|{{end}}", what)
	out, err := exec.Command("go", "list", "-tags", "gofuzz", "-f", templ, pkg).CombinedOutput()
	if err != nil {
		failf("failed to execute 'go list -f \"%v\" %v': %v\n%v", templ, pkg, err, string(out))
	}
	if len(out) < 2 {
		failf("go list output is empty")
	}
	out = out[:len(out)-2]
	return strings.Split(string(out), "|")
}

func goListProps(pkg string, props ...string) []string {
	templ := ""
	for _, p := range props {
		templ += fmt.Sprintf("{{.%v}}|", p)
	}
	out, err := exec.Command("go", "list", "-tags", "gofuzz", "-f", templ, pkg).CombinedOutput()
	if err != nil {
		failf("failed to execute 'go list -f \"%v\" %v': %v\n%v", templ, pkg, err, string(out))
	}
	if len(out) == 0 {
		failf("go list output is empty")
	}
	out = out[:len(out)-1]
	return strings.Split(string(out), "|")
}

func failf(str string, args ...interface{}) {
	if !*flagWork && workdir != "" {
		os.RemoveAll(workdir)
	}
	fmt.Fprintf(os.Stderr, str+"\n", args...)
	os.Exit(1)
}

func tempFile() string {
	outf, err := ioutil.TempFile("", "go-fuzz")
	if err != nil {
		failf("failed to create temp file: %v", err)
	}
	outf.Close()
	return outf.Name()
}

func readFile(name string) []byte {
	data, err := ioutil.ReadFile(name)
	if err != nil {
		failf("failed to read temp file: %v", err)
	}
	return data
}

func writeFile(name string, data []byte) {
	if err := ioutil.WriteFile(name, data, 0700); err != nil {
		failf("failed to write temp file: %v", err)
	}
}

func isSourceFile(f string) bool {
	return (strings.HasSuffix(f, ".go") && !strings.HasSuffix(f, "_test.go")) ||
		strings.HasSuffix(f, ".s") ||
		strings.HasSuffix(f, ".S") ||
		strings.HasSuffix(f, ".c") ||
		strings.HasSuffix(f, ".h") ||
		strings.HasSuffix(f, ".cxx") ||
		strings.HasSuffix(f, ".cpp") ||
		strings.HasSuffix(f, ".c++") ||
		strings.HasSuffix(f, ".cc")
}

func isHeaderFile(f string) bool {
	return strings.HasSuffix(f, ".h")
}

var mainSrc = `
package main

import (
	target "%v"
	dep "github.com/dvyukov/go-fuzz/go-fuzz-dep"
)

func main() {
	dep.Main(target.%v)
}
`
<|endoftext|>


<commit_before>package bowling

import (
	"fmt"
	"log"
)

type Game struct {
	frames []*Frame
	rolls  []int
}

func NewGame() *Game {
	return &Game{}
}

func (g *Game) Roll(pins int) error {
	g.rolls = append(g.rolls, pins)
	return nil
}

func (g *Game) parseFrames() {
	g.frames = []*Frame{}
	for _, roll := range g.rolls {
		if len(g.frames) == 0 {
			isComplete := roll == 10
			g.frames = append(g.frames, &Frame{roll, 0, isComplete})
		} else if !g.lastFrame().isComplete {
			g.lastFrame().rollTwo = roll
			g.lastFrame().isComplete = true
		} else {
			isComplete := roll == 10
			g.frames = append(g.frames, &Frame{roll, 0, isComplete})
		}
	}
}

func (g *Game) Score() (score int, err error) {
	g.parseFrames()
	fmt.Printf("rolls: %v\nframes: %v\n", g.rolls, g.frames)
	for i, frame := range g.frames {
		score += frame.score(g.frames[i+1:])
	}
	return score, nil
}

func (g *Game) lastFrame() *Frame {
	return g.frames[len(g.frames)-1]
}

type Frame struct {
	rollOne    int
	rollTwo    int
	isComplete bool
}

func (f *Frame) String() string {
	return fmt.Sprintf("[%d, %d]", f.rollOne, f.rollTwo)
}

func (f *Frame) score(nextFrames []*Frame) int {
	if f.isOpenFrame() {
		return f.rollOne + f.rollTwo
	}
	nextFrame := nextFrames[0]
	nextRoll := nextFrame.rollOne
	nextNextRoll := nextFrame.rollTwo
	if f.isSpare() {
		return 10 + nextRoll
	}
	if f.isStrike() {
		return 10 + nextRoll + nextNextRoll
	}
	log.Fatalf("frame %v is not an open frame, spare, or strike", f)
	return 0
}

func (f *Frame) isStrike() bool {
	return isStrike(f.rollOne)
}

func (f *Frame) isSpare() bool {
	return !f.isStrike() && f.rollOne+f.rollTwo == 10
}

func (f *Frame) isOpenFrame() bool {
	return !f.isStrike() && !f.isSpare()
}

func isStrike(roll int) bool {
	return roll == 10
}
<commit_msg>Pass a spare in the last frame gets a one roll bonus that is counted once<commit_after>package bowling

import (
	"fmt"
	"log"
)

type Game struct {
	frames []*Frame
	rolls  []int
}

func NewGame() *Game {
	return &Game{}
}

func (g *Game) Roll(pins int) error {
	g.rolls = append(g.rolls, pins)
	return nil
}

func (g *Game) parseFrames() {
	g.frames = []*Frame{}
	for _, roll := range g.rolls {
		if len(g.frames) == 0 {
			isComplete := roll == 10
			g.frames = append(g.frames, &Frame{roll, 0, isComplete})
		} else if !g.lastFrame().isComplete {
			g.lastFrame().rollTwo = roll
			g.lastFrame().isComplete = true
		} else {
			isComplete := roll == 10
			g.frames = append(g.frames, &Frame{roll, 0, isComplete})
		}
	}
}

func (g *Game) Score() (score int, err error) {
	g.parseFrames()
	fmt.Printf("rolls: %v\nframes: %v\n", g.rolls, g.frames)
	for i, frame := range g.frames[0:10] {
		score += frame.score(g.frames[i+1:])
	}
	return score, nil
}

func (g *Game) lastFrame() *Frame {
	return g.frames[len(g.frames)-1]
}

type Frame struct {
	rollOne    int
	rollTwo    int
	isComplete bool
}

func (f *Frame) String() string {
	return fmt.Sprintf("[%d, %d]", f.rollOne, f.rollTwo)
}

func (f *Frame) score(nextFrames []*Frame) int {
	if f.isOpenFrame() {
		return f.rollOne + f.rollTwo
	}
	nextFrame := nextFrames[0]
	nextRoll := nextFrame.rollOne
	nextNextRoll := nextFrame.rollTwo
	if f.isSpare() {
		return 10 + nextRoll
	}
	if f.isStrike() {
		return 10 + nextRoll + nextNextRoll
	}
	log.Fatalf("frame %v is not an open frame, spare, or strike", f)
	return 0
}

func (f *Frame) isStrike() bool {
	return isStrike(f.rollOne)
}

func (f *Frame) isSpare() bool {
	return !f.isStrike() && f.rollOne+f.rollTwo == 10
}

func (f *Frame) isOpenFrame() bool {
	return !f.isStrike() && !f.isSpare()
}

func isStrike(roll int) bool {
	return roll == 10
}
<|endoftext|>


<commit_before>package graph

import (
	"container/heap"
	"github.com/twmb/algoimpl/go/graph/lite"
	"math/rand"
	"time"
)

const (
	unseen = iota
	seen
	queued = 1 << 30 // assume that no weight will be > 2^30
)

// O(V + E). It does not matter to traverse back
// on a bidirectional edge, because any vertex dfs is
// recursing on is marked as visited and won't be visited
// again anyway.
func (g *Graph) dfs(node *node, finishList *[]Node) {
	node.state = seen
	for _, edge := range node.edges {
		if edge.end.state == unseen {
			edge.end.parent = node
			g.dfs(edge.end, finishList)
		}
	}
	*finishList = append(*finishList, node.container)
}

func (g *Graph) dfsReversedEdges(node *node, finishList *[]Node) {
	node.state = seen
	for _, edge := range node.reversedEdges {
		if edge.end.state == unseen {
			edge.end.parent = node
			g.dfsReversedEdges(edge.end, finishList)
		}
	}
	*finishList = append(*finishList, node.container)
}

// Topologically sorts a directed acyclic graph.
// If the graph is cyclic, the sort order will change
// based on which node the sort starts on. O(V+E) complexity.
func (g *Graph) TopologicalSort() []Node {
	sorted := make([]Node, 0, len(g.nodes))
	// sort preorder (first jacket, then shirt)
	for _, node := range g.nodes {
		if node.state == unseen {
			g.dfs(node, &sorted)
		}
	}
	// now make post order for correct sort (jacket follows shirt). O(V)
	length := len(sorted)
	for i := 0; i < length/2; i++ {
		sorted[i], sorted[length-i-1] = sorted[length-i-1], sorted[i]
	}
	return sorted
}

// Returns reversed copy of the directed graph g. O(V+E) complexity.
// This function can be used to copy an undirected graph.
func (g *Graph) Reverse() *Graph {
	reversed := New(Directed)
	if g.kind == Undirected {
		reversed = New(Undirected)
	}
	// O(V)
	for _ = range g.nodes {
		reversed.MakeNode()
	}
	// O(V + E)
	for _, node := range g.nodes {
		for _, edge := range node.edges {
			reversed.MakeEdge(reversed.nodes[edge.end.index].container, reversed.nodes[node.index].container)
		}
	}
	return reversed
}

// Returns a slice of strongly connected nodes on a directed graph.
// If passed an undirected graph, returns nil.
// The returned components have reversed, nonexclusive edges.
// For example, if this is passed the graph
//     a->b, c
//     b->a, c
//     c
// will return components
//     [[c->a, b], [b->a], [a->b]]
// where -> represents the edges that the node contains.
// O(V+E) complexity.
func (g *Graph) StronglyConnectedComponents() [][]Node {
	if g.kind == Undirected {
		return nil
	}
	components := make([][]Node, 0)
	finishOrder := g.TopologicalSort()
	for i := range finishOrder {
		finishOrder[i].node.state = unseen
	}
	for _, sink := range finishOrder {
		if g.nodes[sink.node.index].state == unseen {
			component := make([]Node, 0)
			g.dfsReversedEdges(g.nodes[sink.node.index], &component)
			components = append(components, component)
		}
	}
	return components
}

func (g *Graph) RandMinimumCut(iterations int) []Edge {
	// copy a graph into mock nodes and edges
	// so that I can collapse nodes / edges without losing
	// the true spanning edge's start and end
	rand.Seed(time.Now().Unix())
	var minLiteEdges []lite.Edge
	for iteration := 0; iteration < iterations; iteration++ {

		gLite := lite.NewGraph(len(g.nodes))
		for i := range g.nodes {
			for _, edge := range g.nodes[i].edges {
				gLite[i].Edges = append(gLite[i].Edges, lite.Edge{End: edge.end.index, S: g.nodes[i], E: edge.end})
			}
		}

		for len(gLite) > 2 {
			randNodeI := rand.Intn(len(gLite))
			randNode := gLite[randNodeI]

			randEdgeI := rand.Intn(len(randNode.Edges))
			randEdge := randNode.Edges[randEdgeI]

			removeNodeI := randEdge.End

			finalRandNodeI := randNodeI
			if randNodeI > removeNodeI {
				finalRandNodeI-- // the final index of randNode will be back one
			}

			// every edge on rand node pointing to remove node is removed (will form loop when collapsed)
			shift := 0
			for e := range gLite[randNodeI].Edges {
				if gLite[randNodeI].Edges[e].End == removeNodeI {
					shift++
					continue
				}
				if gLite[randNodeI].Edges[e].End > removeNodeI {
					gLite[randNodeI].Edges[e].End--
				}
				gLite[randNodeI].Edges[e-shift] = gLite[randNodeI].Edges[e]
			}
			gLite[randNodeI].Edges = gLite[randNodeI].Edges[:len(gLite[randNodeI].Edges)-shift]

			// everything on every other node pointing to removeNode should now point to randNode
			for n := range gLite {
				if n == removeNodeI || n == randNodeI {
					continue
				}
				for e := range gLite[n].Edges {
					// if the current edge on the current node points to the removal node
					if gLite[n].Edges[e].End == removeNodeI {
						// point it to the final randNode position
						gLite[n].Edges[e].End = finalRandNodeI
					} else if gLite[n].Edges[e].End > removeNodeI {
						// or, if the edge points to something AFTER the removal node, decrement that edge's end
						gLite[n].Edges[e].End--
					}
				}
			}
			numAppended := 0
			// everything removeNode points to, randNode should now point to
			for e := range gLite[removeNodeI].Edges {
				if gLite[removeNodeI].Edges[e].End != randNodeI {
					if gLite[removeNodeI].Edges[e].End > removeNodeI {
						gLite[removeNodeI].Edges[e].End--
					}
					gLite[randNodeI].Edges = append(gLite[randNodeI].Edges, gLite[removeNodeI].Edges[e])
					numAppended++
				}
			}
			// shift all nodes after the remove node back one
			gLite = append(gLite[:removeNodeI], gLite[removeNodeI+1:]...)
		}
		if iteration == 0 || len(gLite[0].Edges) < len(minLiteEdges) {
			minLiteEdges = make([]lite.Edge, len(gLite[0].Edges))
			copy(minLiteEdges, gLite[0].Edges)
		}
	}

	minCut := make([]Edge, len(minLiteEdges))
	for i := range minLiteEdges {
		start := minLiteEdges[i].S.(*node)
		end := minLiteEdges[i].E.(*node)
		minCut[i] = Edge{Weight: g.edgeWeightBetween(start, end), Start: start.container, End: end.container, Kind: g.kind}
	}
	return minCut
}

// This function will return the edges corresponding to the
// minimum spanning tree in the graph based off of the edge's weight values.
func (g *Graph) MinimumSpanningTree() []Edge {
	// create priority queue for vertices
	nodesBase := nodeSlice(make([]*node, 0))
	nodes := &nodesBase
	heap.Init(nodes)
	for _, node := range g.nodes[1:] {
		node.state = 1<<30 - 1 // bit 31 is for queue testing
		node.state |= queued
		heap.Push(nodes, node)
	}
	g.nodes[0].state = 0
	heap.Push(nodes, g.nodes[0]) // now add root element

	for nodes.Len() > 0 {
		min := heap.Pop(nodes).(*node)
		for _, edge := range min.edges {
			v := edge.end // get the other side of the edge
			if nodes.QueueContains(v) && edge.weight < (v.state & ^queued) {
				v.parent = min
				heap.Remove(nodes, v.data)     // remove it
				v.state = edge.weight | queued // update state, add queue bit
				heap.Push(nodes, v)            // add it back in, WORD, O(lg n) update key time!
			}
		}
	}

	mst := make([]Edge, 0)
	for i := range g.nodes {
		if g.nodes[i].parent != nil {
			mst = append(mst, Edge{Weight: g.edgeWeightBetween(g.nodes[i], g.nodes[i].parent), Start: g.nodes[i].container,
				End: g.nodes[i].parent.container, Kind: g.kind})
		}
	}

	return mst
}

// only called when the graph is guaranteed to have an edge
// between the two nodes
func (g *Graph) edgeWeightBetween(v, u *node) int {
	for _, edge := range u.edges {
		// one of the two is always u
		if edge.end == v {
			return edge.weight
		}
	}
	return 0
}

type nodeSlice []*node

func (n *nodeSlice) Push(x interface{}) {
	p := x.(*node)
	p.data = len(*n) // index into heap
	*n = append(*n, x.(*node))
}
func (n *nodeSlice) Pop() interface{} {
	rNode := (*n)[len(*n)-1]
	rNode.state &= ^queued
	*n = (*n)[0 : len(*n)-1]
	return rNode
}
func (n nodeSlice) Len() int {
	return len(n)
}
func (n nodeSlice) Less(i, j int) bool {
	return n[i].state & ^queued < n[j].state & ^queued
}
func (n nodeSlice) Swap(i, j int) {
	n[j].data, n[i].data = n[i].data, n[j].data // swap data containing indices
	n[j], n[i] = n[i], n[j]
}
func (n nodeSlice) QueueContains(node *node) bool { // extend heap interface
	return node.state&queued > 0
}
<commit_msg>sped up random min cut significantly - uses single edge slice<commit_after>package graph

import (
	"container/heap"
	"github.com/twmb/algoimpl/go/graph/lite"
	"math/rand"
	"time"
)

const (
	unseen = iota
	seen
	queued = 1 << 30 // assume that no weight will be > 2^30
)

// O(V + E). It does not matter to traverse back
// on a bidirectional edge, because any vertex dfs is
// recursing on is marked as visited and won't be visited
// again anyway.
func (g *Graph) dfs(node *node, finishList *[]Node) {
	node.state = seen
	for _, edge := range node.edges {
		if edge.end.state == unseen {
			edge.end.parent = node
			g.dfs(edge.end, finishList)
		}
	}
	*finishList = append(*finishList, node.container)
}

func (g *Graph) dfsReversedEdges(node *node, finishList *[]Node) {
	node.state = seen
	for _, edge := range node.reversedEdges {
		if edge.end.state == unseen {
			edge.end.parent = node
			g.dfsReversedEdges(edge.end, finishList)
		}
	}
	*finishList = append(*finishList, node.container)
}

// Topologically sorts a directed acyclic graph.
// If the graph is cyclic, the sort order will change
// based on which node the sort starts on. O(V+E) complexity.
func (g *Graph) TopologicalSort() []Node {
	sorted := make([]Node, 0, len(g.nodes))
	// sort preorder (first jacket, then shirt)
	for _, node := range g.nodes {
		if node.state == unseen {
			g.dfs(node, &sorted)
		}
	}
	// now make post order for correct sort (jacket follows shirt). O(V)
	length := len(sorted)
	for i := 0; i < length/2; i++ {
		sorted[i], sorted[length-i-1] = sorted[length-i-1], sorted[i]
	}
	return sorted
}

// Returns reversed copy of the directed graph g. O(V+E) complexity.
// This function can be used to copy an undirected graph.
func (g *Graph) Reverse() *Graph {
	reversed := New(Directed)
	if g.kind == Undirected {
		reversed = New(Undirected)
	}
	// O(V)
	for _ = range g.nodes {
		reversed.MakeNode()
	}
	// O(V + E)
	for _, node := range g.nodes {
		for _, edge := range node.edges {
			reversed.MakeEdge(reversed.nodes[edge.end.index].container, reversed.nodes[node.index].container)
		}
	}
	return reversed
}

// Returns a slice of strongly connected nodes on a directed graph.
// If passed an undirected graph, returns nil.
// The returned components have reversed, nonexclusive edges.
// For example, if this is passed the graph
//     a->b, c
//     b->a, c
//     c
// will return components
//     [[c->a, b], [b->a], [a->b]]
// where -> represents the edges that the node contains.
// O(V+E) complexity.
func (g *Graph) StronglyConnectedComponents() [][]Node {
	if g.kind == Undirected {
		return nil
	}
	components := make([][]Node, 0)
	finishOrder := g.TopologicalSort()
	for i := range finishOrder {
		finishOrder[i].node.state = unseen
	}
	for _, sink := range finishOrder {
		if g.nodes[sink.node.index].state == unseen {
			component := make([]Node, 0)
			g.dfsReversedEdges(g.nodes[sink.node.index], &component)
			components = append(components, component)
		}
	}
	return components
}

func (g *Graph) RandMinimumCut(iterations int) []Edge {
	// make a lite slice of the edges and shuffle for random edge removal order
	rand.Seed(time.Now().Unix())
	var baseAllEdges []lite.Edge
	nodecount := 0
	for n := range g.nodes {
		nodecount++
		for _, edge := range g.nodes[n].edges {
			if g.kind == Undirected && n < edge.end.index {
				continue
			}
			baseAllEdges = append(baseAllEdges, lite.Edge{Start: n, End: edge.end.index, S: g.nodes[n], E: edge})
		}
	}

	originalNodeCount := nodecount
	allEdgesOnce := make([]lite.Edge, len(baseAllEdges))

	var minCutLite []lite.Edge

	// reuse lite edges as opposed to rebuild every iteration
	for iter := 0; iter < iterations; iter++ {
		nodecount = originalNodeCount
		allEdges := allEdgesOnce
		copy(allEdges, baseAllEdges)
		shuffle(allEdges)
		for nodecount > 2 {
			// remove first edge, keep the start node, collapse the end node
			// anything that points to the collapsing node now points to the keep node
			// anything that starts at the collapsing node now starts at the keep node
			keep := allEdges[len(allEdges)-1].Start
			remove := allEdges[len(allEdges)-1].End // deleting this node
			allEdges = allEdges[:len(allEdges)-1]
			for e := 0; e < len(allEdges); e++ {
				if allEdges[e].Start == remove {
					allEdges[e].Start = keep
				}
				if allEdges[e].End == remove {
					allEdges[e].End = keep
				}
				// remove the node if it self looped
				if allEdges[e].Start == allEdges[e].End {
					allEdges[e] = allEdges[len(allEdges)-1]
					allEdges = allEdges[:len(allEdges)-1]
					e--
				}
			}

			nodecount--
		}

		if iter == 0 || len(allEdges) < len(minCutLite) {
			minCutLite = make([]lite.Edge, len(allEdges))
			copy(minCutLite, allEdges)
		}
	}

	minCut := make([]Edge, len(minCutLite))
	for i := range minCutLite {
		start := minCutLite[i].S.(*node)
		edge := minCutLite[i].E.(edge)
		minCut[i] = Edge{Weight: edge.weight, Start: start.container, End: edge.end.container, Kind: g.kind}
	}
	return minCut
}

// Fischer-Yates shuffle
func shuffle(edges []lite.Edge) {
	for i := len(edges) - 1; i > 0; i-- {
		j := rand.Intn(i)
		edges[j], edges[i] = edges[i], edges[j]
	}
}

// This function will return the edges corresponding to the
// minimum spanning tree in the graph based off of the edge's weight values.
func (g *Graph) MinimumSpanningTree() []Edge {
	// create priority queue for vertices
	nodesBase := nodeSlice(make([]*node, 0))
	nodes := &nodesBase
	heap.Init(nodes)
	for _, node := range g.nodes[1:] {
		node.state = 1<<30 - 1 // bit 31 is for queue testing
		node.state |= queued
		heap.Push(nodes, node)
	}
	g.nodes[0].state = 0
	heap.Push(nodes, g.nodes[0]) // now add root element

	for nodes.Len() > 0 {
		min := heap.Pop(nodes).(*node)
		for _, edge := range min.edges {
			v := edge.end // get the other side of the edge
			if nodes.QueueContains(v) && edge.weight < (v.state & ^queued) {
				v.parent = min
				heap.Remove(nodes, v.data)     // remove it
				v.state = edge.weight | queued // update state, add queue bit
				heap.Push(nodes, v)            // add it back in, WORD, O(lg n) update key time!
			}
		}
	}

	mst := make([]Edge, 0)
	for i := range g.nodes {
		if g.nodes[i].parent != nil {
			mst = append(mst, Edge{Weight: g.edgeWeightBetween(g.nodes[i], g.nodes[i].parent), Start: g.nodes[i].container,
				End: g.nodes[i].parent.container, Kind: g.kind})
		}
	}

	return mst
}

// only called when the graph is guaranteed to have an edge
// between the two nodes
func (g *Graph) edgeWeightBetween(v, u *node) int {
	for _, edge := range u.edges {
		// one of the two is always u
		if edge.end == v {
			return edge.weight
		}
	}
	return 0
}

type nodeSlice []*node

func (n *nodeSlice) Push(x interface{}) {
	p := x.(*node)
	p.data = len(*n) // index into heap
	*n = append(*n, x.(*node))
}
func (n *nodeSlice) Pop() interface{} {
	rNode := (*n)[len(*n)-1]
	rNode.state &= ^queued
	*n = (*n)[0 : len(*n)-1]
	return rNode
}
func (n nodeSlice) Len() int {
	return len(n)
}
func (n nodeSlice) Less(i, j int) bool {
	return n[i].state & ^queued < n[j].state & ^queued
}
func (n nodeSlice) Swap(i, j int) {
	n[j].data, n[i].data = n[i].data, n[j].data // swap data containing indices
	n[j], n[i] = n[i], n[j]
}
func (n nodeSlice) QueueContains(node *node) bool { // extend heap interface
	return node.state&queued > 0
}
<|endoftext|>


<commit_before>package notificator

import (
	"os/exec"
	"runtime"
	"fmt"
	"strings"
	"strconv"
)

type Options struct {
	DefaultIcon string
	AppName     string
}

const (
	UR_NORMAL   =	"normal"
	UR_CRITICAL	=	"critical"
)

type notifier interface {
	push(title string, text string, iconPath string) *exec.Cmd
	pushCritical(title string, text string, iconPath string) *exec.Cmd
}

type Notificator struct {
	notifier    notifier
	defaultIcon string
}

func (n Notificator) Push(title string, text string, iconPath string, urgency string) error {
	icon := n.defaultIcon

	if iconPath != "" {
		icon = iconPath
	}

	if urgency == UR_CRITICAL {
		return n.notifier.pushCritical(title, text, icon).Run()
	}

	return n.notifier.push(title, text, icon).Run()

}

type osxNotificator struct {
	AppName string
}

func (o osxNotificator) push(title string, text string, iconPath string) *exec.Cmd {

	// Checks if terminal-notifier exists, and is accessible.

	term_notif := CheckTermNotif()
	os_version_check := CheckMacOSVersion()

  // if terminal-notifier exists, use it.
	// else, fall back to osascript. (Mavericks and later.)

	if term_notif == true {
		return exec.Command("terminal-notifier", "-title", o.AppName, "-message", text, "-subtitle", title)
	} else if os_version_check == true {
		notification := fmt.Sprintf("display notification \"%s\" with title \"%s\" subtitle \"%s\"", text, o.AppName, title)
		return exec.Command("osascript", "-e", notification)
	}

	// finally falls back to growlnotify.

  return exec.Command("growlnotify", "-n", o.AppName, "--image", iconPath, "-m", title)
}

// Causes the notification to stick around until clicked.
func (o osxNotificator) pushCritical(title string, text string, iconPath string) *exec.Cmd {

  // same function as above...

	term_notif := CheckTermNotif()
	os_version_check := CheckMacOSVersion()

	if term_notif == true {
		// timeout set to 30 seconds, to show the importance of the notification
		return exec.Command("terminal-notifier", "-title", o.AppName, "-message", title, "-subtitle", title ,"-timeout", "30")
	} else if os_version_check == true {
		notification := fmt.Sprintf("display notification \"%s\" with title \"%s\" subtitle \"%s\"", text, o.AppName, title)
		return exec.Command("osascript", "-e", notification)
	}

  return exec.Command("growlnotify", "-n", o.AppName, "--image", iconPath, "-m", title)

}

type linuxNotificator struct{}

func (l linuxNotificator) push(title string, text string, iconPath string) *exec.Cmd {
	return exec.Command("notify-send", "-i", iconPath, title, text)
}

// Causes the notification to stick around until clicked.
func (l linuxNotificator) pushCritical(title string, text string, iconPath string) *exec.Cmd {
	return exec.Command("notify-send", "-i", iconPath, title, text, "-u", "critical")
}

type windowsNotificator struct{}

func (w windowsNotificator) push(title string, text string, iconPath string) *exec.Cmd {
	return exec.Command("growlnotify", "/i:", iconPath, "/t:", title, text)
}

// Causes the notification to stick around until clicked.
func (w windowsNotificator) pushCritical(title string, text string, iconPath string) *exec.Cmd {
	return exec.Command("notify-send", "-i", iconPath, title, text, "/s", "true", "/p", "2")
}

func New(o Options) *Notificator {

	var Notifier notifier

	switch runtime.GOOS {

	case "darwin":
		Notifier = osxNotificator{AppName: o.AppName}
	case "linux":
		Notifier = linuxNotificator{}
	case "windows":
		Notifier = windowsNotificator{}

	}

	return &Notificator{notifier: Notifier, defaultIcon: o.DefaultIcon}
}

// Helper function for macOS

func CheckTermNotif() bool {
	// Checks if terminal-notifier exists, and is accessible.

	check_term_notif := exec.Command("which", "terminal-notifier");
	err := check_term_notif.Start()

  if err != nil {
		return false
	} else {
		err = check_term_notif.Wait()
		if err != nil {
			return false
		}
	}
	// no error, so return true. (terminal-notifier exists)
  return true
}

func CheckMacOSVersion() bool {
	// Checks if the version of macOS is 10.9 or Higher (osascript support for notifications.)

	cmd := exec.Command("sw_vers", "-productVersion");
	check, _ := cmd.Output()

	version := strings.Split(string(check), ".")

  // semantic versioning of macOS

	major, _ := strconv.Atoi(version[0])
	minor, _ := strconv.Atoi(version[1])

	if major < 10 {
    return false
	} else if major == 10 && minor < 9 {
    return false
	} else {
		return true
	}
}
<commit_msg>Gofmt<commit_after>package notificator

import (
	"fmt"
	"os/exec"
	"runtime"
	"strconv"
	"strings"
)

type Options struct {
	DefaultIcon string
	AppName     string
}

const (
	UR_NORMAL   = "normal"
	UR_CRITICAL = "critical"
)

type notifier interface {
	push(title string, text string, iconPath string) *exec.Cmd
	pushCritical(title string, text string, iconPath string) *exec.Cmd
}

type Notificator struct {
	notifier    notifier
	defaultIcon string
}

func (n Notificator) Push(title string, text string, iconPath string, urgency string) error {
	icon := n.defaultIcon

	if iconPath != "" {
		icon = iconPath
	}

	if urgency == UR_CRITICAL {
		return n.notifier.pushCritical(title, text, icon).Run()
	}

	return n.notifier.push(title, text, icon).Run()

}

type osxNotificator struct {
	AppName string
}

func (o osxNotificator) push(title string, text string, iconPath string) *exec.Cmd {

	// Checks if terminal-notifier exists, and is accessible.

	term_notif := CheckTermNotif()
	os_version_check := CheckMacOSVersion()

	// if terminal-notifier exists, use it.
	// else, fall back to osascript. (Mavericks and later.)

	if term_notif == true {
		return exec.Command("terminal-notifier", "-title", o.AppName, "-message", text, "-subtitle", title)
	} else if os_version_check == true {
		notification := fmt.Sprintf("display notification \"%s\" with title \"%s\" subtitle \"%s\"", text, o.AppName, title)
		return exec.Command("osascript", "-e", notification)
	}

	// finally falls back to growlnotify.

	return exec.Command("growlnotify", "-n", o.AppName, "--image", iconPath, "-m", title)
}

// Causes the notification to stick around until clicked.
func (o osxNotificator) pushCritical(title string, text string, iconPath string) *exec.Cmd {

	// same function as above...

	term_notif := CheckTermNotif()
	os_version_check := CheckMacOSVersion()

	if term_notif == true {
		// timeout set to 30 seconds, to show the importance of the notification
		return exec.Command("terminal-notifier", "-title", o.AppName, "-message", title, "-subtitle", title, "-timeout", "30")
	} else if os_version_check == true {
		notification := fmt.Sprintf("display notification \"%s\" with title \"%s\" subtitle \"%s\"", text, o.AppName, title)
		return exec.Command("osascript", "-e", notification)
	}

	return exec.Command("growlnotify", "-n", o.AppName, "--image", iconPath, "-m", title)

}

type linuxNotificator struct{}

func (l linuxNotificator) push(title string, text string, iconPath string) *exec.Cmd {
	return exec.Command("notify-send", "-i", iconPath, title, text)
}

// Causes the notification to stick around until clicked.
func (l linuxNotificator) pushCritical(title string, text string, iconPath string) *exec.Cmd {
	return exec.Command("notify-send", "-i", iconPath, title, text, "-u", "critical")
}

type windowsNotificator struct{}

func (w windowsNotificator) push(title string, text string, iconPath string) *exec.Cmd {
	return exec.Command("growlnotify", "/i:", iconPath, "/t:", title, text)
}

// Causes the notification to stick around until clicked.
func (w windowsNotificator) pushCritical(title string, text string, iconPath string) *exec.Cmd {
	return exec.Command("notify-send", "-i", iconPath, title, text, "/s", "true", "/p", "2")
}

func New(o Options) *Notificator {

	var Notifier notifier

	switch runtime.GOOS {

	case "darwin":
		Notifier = osxNotificator{AppName: o.AppName}
	case "linux":
		Notifier = linuxNotificator{}
	case "windows":
		Notifier = windowsNotificator{}

	}

	return &Notificator{notifier: Notifier, defaultIcon: o.DefaultIcon}
}

// Helper function for macOS

func CheckTermNotif() bool {
	// Checks if terminal-notifier exists, and is accessible.

	check_term_notif := exec.Command("which", "terminal-notifier")
	err := check_term_notif.Start()

	if err != nil {
		return false
	} else {
		err = check_term_notif.Wait()
		if err != nil {
			return false
		}
	}
	// no error, so return true. (terminal-notifier exists)
	return true
}

func CheckMacOSVersion() bool {
	// Checks if the version of macOS is 10.9 or Higher (osascript support for notifications.)

	cmd := exec.Command("sw_vers", "-productVersion")
	check, _ := cmd.Output()

	version := strings.Split(string(check), ".")

	// semantic versioning of macOS

	major, _ := strconv.Atoi(version[0])
	minor, _ := strconv.Atoi(version[1])

	if major < 10 {
		return false
	} else if major == 10 && minor < 9 {
		return false
	} else {
		return true
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"net/http"
	"os/exec"
	"text/template"

	"github.com/AlexanderThaller/logger"
	"github.com/juju/errgo"
)

type Page interface {
	Template() string
}

func WriteTemplateHTML(w http.ResponseWriter, r *http.Request, page Page) {
	template := template.New("templatehtmlpage")
	template.Parse(page.Template())

	buffer := bytes.NewBufferString("")
	err := template.Execute(buffer, page)
	if err != nil {
		fmt.Fprintf(w, "Error: %s", errgo.Details(err))
		return
	}

	output, err := StringToAsciiDoctor(buffer.String())
	if err != nil {
		fmt.Fprintf(w, "Error: %s", errgo.Details(err))
		return
	}

	fmt.Fprintf(w, output)
}

func StringToAsciiDoctor(input string) (string, error) {
	l := logger.New(Name, "StringToAsciiDoctor")
	l.SetLevel(logger.Debug)

	l.Debug("Starting command")
	command := exec.Command("asciidoctor", "-")

	l.Debug("Opening pipe to command")
	pipe, err := command.StdinPipe()
	if err != nil {
		return "", err
	}

	l.Debug("Writing to pipe")
	_, err = pipe.Write([]byte(input))
	if err != nil {
		return "", err
	}
	pipe.Close()

	l.Debug("Reading output")
	output, err := command.CombinedOutput()
	if err != nil {
		err = errgo.New("problem while getting raw snapshots: " + err.Error() +
			" - " + string(output))

		return "", err
	}

	l.Debug("Returning output")
	return string(output), nil
}

type RootPage struct {
	Projects []string
}

const TemplatePageRoot = `= Lablog -- Projects

[cols="4*", options="header"]
|===
|Project
|Notes
|Todos
|Tracks

{{ range .Projects }}
|{{ . }}
|link:/notes/{{ . }}[Notes]
|link:/todos/{{ . }}[Todos]
|link:/tracks/{{ . }}[Tracks]
{{ end }}
|===`

func (page RootPage) Template() string {
	return TemplatePageRoot
}

type PageNotes struct {
	Project string
	Notes   []Note
}

func (page PageNotes) Template() string {
	buffer := bytes.NewBufferString("")

	err := FormatNotes(buffer, page.Project, "Notes", page.Notes, 1)
	if err != nil {
		fmt.Fprintf(buffer, "Error: %s", errgo.Details(err))
		return buffer.String()
	}

	return buffer.String()
}
<commit_msg>will now use WriteString to write the string to the pipe instead of converting to a byte.<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"os/exec"
	"text/template"

	"github.com/AlexanderThaller/logger"
	"github.com/juju/errgo"
)

type Page interface {
	Template() string
}

func WriteTemplateHTML(w http.ResponseWriter, r *http.Request, page Page) {
	template := template.New("templatehtmlpage")
	template.Parse(page.Template())

	buffer := bytes.NewBufferString("")
	err := template.Execute(buffer, page)
	if err != nil {
		fmt.Fprintf(w, "Error: %s", errgo.Details(err))
		return
	}

	output, err := StringToAsciiDoctor(buffer.String())
	if err != nil {
		fmt.Fprintf(w, "Error: %s", errgo.Details(err))
		return
	}

	fmt.Fprintf(w, output)
}

func StringToAsciiDoctor(input string) (string, error) {
	l := logger.New(Name, "StringToAsciiDoctor")
	l.SetLevel(logger.Debug)

	l.Debug("Starting command")
	command := exec.Command("asciidoctor", "-")

	l.Debug("Opening pipe to command")
	pipe, err := command.StdinPipe()
	if err != nil {
		return "", err
	}

	l.Debug("Writing to pipe")
	_, err = io.WriteString(pipe, input)
	if err != nil {
		return "", errgo.Notef(err, "can not write to pipe")
	}
	l.Debug("Finished writing to pipe")
	pipe.Close()

	l.Debug("Reading output")
	output, err := command.CombinedOutput()
	if err != nil {
		err = errgo.New("problem while getting raw snapshots: " + err.Error() +
			" - " + string(output))

		return "", err
	}

	l.Debug("Returning output")
	return string(output), nil
}

type RootPage struct {
	Projects []string
}

const TemplatePageRoot = `= Lablog -- Projects

[cols="4*", options="header"]
|===
|Project
|Notes
|Todos
|Tracks

{{ range .Projects }}
|{{ . }}
|link:/notes/{{ . }}[Notes]
|link:/todos/{{ . }}[Todos]
|link:/tracks/{{ . }}[Tracks]
{{ end }}
|===`

func (page RootPage) Template() string {
	return TemplatePageRoot
}

type PageNotes struct {
	Project string
	Notes   []Note
}

func (page PageNotes) Template() string {
	buffer := bytes.NewBufferString("")

	err := FormatNotes(buffer, page.Project, "Notes", page.Notes, 1)
	if err != nil {
		fmt.Fprintf(buffer, "Error: %s", errgo.Details(err))
		return buffer.String()
	}

	return buffer.String()
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2019 IBM, Inc.
 *
 * 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 ofthe 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 specificlanguage governing permissions and
 * limitations under the License.
 *
 */

package main

import (
	"github.com/skydive-project/skydive/contrib/exporters/core"
	awsflowlogs "github.com/skydive-project/skydive/contrib/exporters/awsflowlogs/mod"
	secadvisor "github.com/skydive-project/skydive/contrib/exporters/secadvisor/mod"
)

func main() {
	core.Main("/etc/skydive/allinone.yml")
}

func init() {
	core.EncoderHandlers.Register("secadvisor", secadvisor.NewEncode, false)
	core.TransformerHandlers.Register("awsflowlogs", awsflowlogs.NewTransform, false)
	core.TransformerHandlers.Register("vpclogs", secadvisor.NewTransform, false)
}
<commit_msg>exporter/allinone: Register logstatus mangler<commit_after>/*
 * Copyright (C) 2019 IBM, Inc.
 *
 * 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 ofthe 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 specificlanguage governing permissions and
 * limitations under the License.
 *
 */

package main

import (
	"github.com/skydive-project/skydive/contrib/exporters/core"
	awsflowlogs "github.com/skydive-project/skydive/contrib/exporters/awsflowlogs/mod"
	secadvisor "github.com/skydive-project/skydive/contrib/exporters/secadvisor/mod"
)

func main() {
	core.Main("/etc/skydive/allinone.yml")
}

func init() {
	core.ManglerHandlers.Register("logstatus", secadvisor.NewMangleLogStatus, false)
	core.EncoderHandlers.Register("secadvisor", secadvisor.NewEncode, false)
	core.TransformerHandlers.Register("awsflowlogs", awsflowlogs.NewTransform, false)
	core.TransformerHandlers.Register("vpclogs", secadvisor.NewTransform, false)
}
<|endoftext|>


<commit_before>package xlsx

import (
	"fmt"
	"regexp"
	"text/template"
	"time"
)

// Templates for the various XML content in XLST files
var (
	TemplateContentTypes          *template.Template
	TemplateRelationships         *template.Template
	TemplateWorkbook              *template.Template
	TemplateWorkbookRelationships *template.Template
	TemplateStyles                *template.Template
	TemplateStringLookups         *template.Template
	TemplateSheetStart            *template.Template
	TemplateSheetEnd              *template.Template
	TemplateApp                   *template.Template
	TemplateCore                  *template.Template
)

// Template function for integer addition. This is useful to convert between
// zero-based and one-based array offsets within templates
func plus(i int, n int) string {
	return fmt.Sprintf("%d", i+n)
}

// Template function for time formatting
func timeFormat(t time.Time) string {
	return t.Format(time.RFC3339)
}

func init() {
	re := regexp.MustCompile("\n[\t\n\f\r ]*")
	funcMap := template.FuncMap{"plus": plus, "timeFormat": timeFormat}

	TemplateContentTypes = template.Must(template.New("templateContentTypes").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateContentTypes, "")))
	TemplateRelationships = template.Must(template.New("templateRelationships").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateRelationships, "")))
	TemplateWorkbook = template.Must(template.New("templateWorkbook").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateWorkbook, "")))
	TemplateWorkbookRelationships = template.Must(template.New("templateWorkbookRelationships").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateWorkbookRelationships, "")))
	TemplateStyles = template.Must(template.New("templateStyles").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateStyles, "")))
	TemplateStringLookups = template.Must(template.New("templateStringLookups").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateStringLookups, "")))
	TemplateSheetStart = template.Must(template.New("templateSheetStart").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateSheetStart, "")))
	TemplateSheetEnd = template.Must(template.New("templateSheetEnd").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateSheetEnd, "")))
	TemplateApp = template.Must(template.New("templateApp").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateApp, "")))
	TemplateCore = template.Must(template.New("templateCore").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateCore, "")))
}

const templateContentTypes = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
      <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
      <Default Extension="xml" ContentType="application/xml"/>
      <Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
      <Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>
      <Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
      <Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>
      <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
      <Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
  </Types>`

const templateRelationships = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
      <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
      <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
      <Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
  </Relationships>`

const templateWorkbook = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
      <fileVersion appName="xl" lastEdited="5" lowestEdited="5" rupBuild="9303"/>
      <workbookPr defaultThemeVersion="124226"/>
      <bookViews>
          <workbookView xWindow="480" yWindow="60" windowWidth="18195" windowHeight="8505"/>
      </bookViews>
      <sheets>
          <sheet name="{{.Title}}" sheetId="1" r:id="rId1"/>
      </sheets>
      <calcPr calcId="145621"/>
  </workbook>`

const templateWorkbookRelationships = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
      <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>
      <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>
      <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
  </Relationships>`

const templateStyles = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  `

const templateStringLookups = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="{{len .}}" uniqueCount="{{len .}}">
{{range .}}<si><t>{{.}}</t></si>{{end}}
</sst>`

const templateSheetStart = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">
            <sheetViews>
        <sheetView workbookViewId="0"/>
      </sheetViews>
      <sheetFormatPr defaultRowHeight="15" x14ac:dyDescent="0.25"/>
        <cols>
          {{range $i, $e := .Cols}}
          <col min="{{plus $i 1}}" max="{{plus $i 1}}" width="{{$e.Width}}" customWidth="1" style="1"/>
          {{end}}
        </cols>
      <sheetData>`

const templateSheetEnd = `
 </sheetData>
 <dimension ref="{{.Start}}:{{.End}}"/>
   </worksheet>`

const templateApp = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
  <Application>None</Application>
  <DocSecurity>0</DocSecurity>
  <ScaleCrop>false</ScaleCrop>
  <HeadingPairs>
    <vt:vector size="2" baseType="variant">
      <vt:variant>
        <vt:lpstr>Worksheets</vt:lpstr>
      </vt:variant>
      <vt:variant>
        <vt:i4>1</vt:i4>
      </vt:variant>
    </vt:vector>
  </HeadingPairs>
  <TitlesOfParts>
    <vt:vector size="1" baseType="lpstr">
      <vt:lpstr>{{.Title}}</vt:lpstr>
    </vt:vector>
  </TitlesOfParts>
  <LinksUpToDate>false</LinksUpToDate>
  <SharedDoc>false</SharedDoc>
  <HyperlinksChanged>false</HyperlinksChanged>
</Properties>`

const templateCore = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <dc:creator>{{.CreatedBy}}</dc:creator>
    <cp:lastModifiedBy>{{.ModifiedBy}}</cp:lastModifiedBy>
    <dcterms:created xsi:type="dcterms:W3CDTF">{{timeFormat .CreatedAt}}</dcterms:created>
    <dcterms:modified xsi:type="dcterms:W3CDTF">{{timeFormat .ModifiedAt}}</dcterms:modified>
  </cp:coreProperties>`
<commit_msg>Remove templating for sheet end<commit_after>package xlsx

import (
	"fmt"
	"regexp"
	"text/template"
	"time"
)

// Templates for the various XML content in XLST files
var (
	TemplateContentTypes          *template.Template
	TemplateRelationships         *template.Template
	TemplateWorkbook              *template.Template
	TemplateWorkbookRelationships *template.Template
	TemplateStyles                *template.Template
	TemplateStringLookups         *template.Template
	TemplateSheetStart            *template.Template
	TemplateApp                   *template.Template
	TemplateCore                  *template.Template
)

// Template function for integer addition. This is useful to convert between
// zero-based and one-based array offsets within templates
func plus(i int, n int) string {
	return fmt.Sprintf("%d", i+n)
}

// Template function for time formatting
func timeFormat(t time.Time) string {
	return t.Format(time.RFC3339)
}

func init() {
	re := regexp.MustCompile("\n[\t\n\f\r ]*")
	funcMap := template.FuncMap{"plus": plus, "timeFormat": timeFormat}

	TemplateContentTypes = template.Must(template.New("templateContentTypes").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateContentTypes, "")))
	TemplateRelationships = template.Must(template.New("templateRelationships").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateRelationships, "")))
	TemplateWorkbook = template.Must(template.New("templateWorkbook").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateWorkbook, "")))
	TemplateWorkbookRelationships = template.Must(template.New("templateWorkbookRelationships").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateWorkbookRelationships, "")))
	TemplateStyles = template.Must(template.New("templateStyles").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateStyles, "")))
	TemplateStringLookups = template.Must(template.New("templateStringLookups").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateStringLookups, "")))
	TemplateSheetStart = template.Must(template.New("templateSheetStart").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateSheetStart, "")))
	TemplateApp = template.Must(template.New("templateApp").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateApp, "")))
	TemplateCore = template.Must(template.New("templateCore").Funcs(funcMap).Parse(re.ReplaceAllLiteralString(templateCore, "")))
}

const templateContentTypes = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
      <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
      <Default Extension="xml" ContentType="application/xml"/>
      <Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
      <Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>
      <Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
      <Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>
      <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
      <Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
  </Types>`

const templateRelationships = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
      <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
      <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
      <Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
  </Relationships>`

const templateWorkbook = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
      <fileVersion appName="xl" lastEdited="5" lowestEdited="5" rupBuild="9303"/>
      <workbookPr defaultThemeVersion="124226"/>
      <bookViews>
          <workbookView xWindow="480" yWindow="60" windowWidth="18195" windowHeight="8505"/>
      </bookViews>
      <sheets>
          <sheet name="{{.Title}}" sheetId="1" r:id="rId1"/>
      </sheets>
      <calcPr calcId="145621"/>
  </workbook>`

const templateWorkbookRelationships = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
      <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>
      <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>
      <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
  </Relationships>`

const templateStyles = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  `

const templateStringLookups = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="{{len .}}" uniqueCount="{{len .}}">
{{range .}}<si><t>{{.}}</t></si>{{end}}
</sst>`

const templateSheetStart = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">
            <sheetViews>
        <sheetView workbookViewId="0"/>
      </sheetViews>
      <sheetFormatPr defaultRowHeight="15" x14ac:dyDescent="0.25"/>
        <cols>
          {{range $i, $e := .Cols}}
          <col min="{{plus $i 1}}" max="{{plus $i 1}}" width="{{$e.Width}}" customWidth="1" style="1"/>
          {{end}}
        </cols>
      <sheetData>`

const templateApp = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
  <Application>None</Application>
  <DocSecurity>0</DocSecurity>
  <ScaleCrop>false</ScaleCrop>
  <HeadingPairs>
    <vt:vector size="2" baseType="variant">
      <vt:variant>
        <vt:lpstr>Worksheets</vt:lpstr>
      </vt:variant>
      <vt:variant>
        <vt:i4>1</vt:i4>
      </vt:variant>
    </vt:vector>
  </HeadingPairs>
  <TitlesOfParts>
    <vt:vector size="1" baseType="lpstr">
      <vt:lpstr>{{.Title}}</vt:lpstr>
    </vt:vector>
  </TitlesOfParts>
  <LinksUpToDate>false</LinksUpToDate>
  <SharedDoc>false</SharedDoc>
  <HyperlinksChanged>false</HyperlinksChanged>
</Properties>`

const templateCore = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <dc:creator>{{.CreatedBy}}</dc:creator>
    <cp:lastModifiedBy>{{.ModifiedBy}}</cp:lastModifiedBy>
    <dcterms:created xsi:type="dcterms:W3CDTF">{{timeFormat .CreatedAt}}</dcterms:created>
    <dcterms:modified xsi:type="dcterms:W3CDTF">{{timeFormat .ModifiedAt}}</dcterms:modified>
  </cp:coreProperties>`
<|endoftext|>


<commit_before>package main

import (
    "fmt"
    "github.com/fuzxxl/nfc/2.0/nfc"
    "github.com/fuzxxl/freefare/0.3/freefare"
//    "code.google.com/p/go-sqlite/go1/sqlite3"
    "time"
)

func heartbeat() {
    for {
        time.Sleep(2000 * time.Millisecond)
        fmt.Println("Dunka-dunk")
    }
}

func main() {
    d, err := nfc.Open("");
    if err != nil {
        panic(err);
    }

    go heartbeat()
    // mainlopp
    for {
        // Poll for tags
        var tags []freefare.Tag
        for {
            tags, err = freefare.GetTags(d);
            if err != nil {
                panic(err);
            }
            if len(tags) > 0 {
                break;
            }
            time.Sleep(100 * time.Millisecond)
            //fmt.Println("...polling")
        }
        for i := 0; i < len(tags); i++ {
            tag := tags[i]
            uidstr := tag.UID()
            fmt.Println("Found tag", uidstr);
            // TODO: Check tag
            // TODO: do not rediscover same tag at every iteration (ie track state somehow)
        }
    }
}
<commit_msg>check the tag<commit_after>package main

import (
    "fmt"
    "github.com/fuzxxl/nfc/2.0/nfc"
    "github.com/fuzxxl/freefare/0.3/freefare"
    "code.google.com/p/go-sqlite/go1/sqlite3"
    "time"
)

func heartbeat() {
    for {
        time.Sleep(2000 * time.Millisecond)
        fmt.Println("Dunka-dunk")
    }
}

func main() {
    d, err := nfc.Open("");
    if err != nil {
        panic(err);
    }

    c, err := sqlite3.Open("keys.db")
    if err != nil {
        panic(err);
    }
    row := make(sqlite3.RowMap)

    go heartbeat()
    // mainlopp
    for {
        // Poll for tags
        var tags []freefare.Tag
        for {
            tags, err = freefare.GetTags(d);
            if err != nil {
                panic(err);
            }
            if len(tags) > 0 {
                break;
            }
            time.Sleep(100 * time.Millisecond)
            //fmt.Println("...polling")
        }
        valid_found := false
        for i := 0; i < len(tags); i++ {
            tag := tags[i]
            uidstr := tag.UID()
            fmt.Println("Found tag", uidstr);
            sql := "SELECT rowid, * FROM keys where uid=?"
            for s, err := c.Query(sql, uidstr); err == nil; err = s.Next() {
                var rowid int64
                s.Scan(&rowid, row)     // Assigns 1st column to rowid, the rest to row
                fmt.Println(rowid, row)
                valid_found = true
            }
        }
        if valid_found {
            // TODO: run relay in subroutine
            fmt.Println("Access GRANTED")
        } else {
            fmt.Println("Access DENIED")
        }
        // Wait a moment before continuing with fast polling
        time.Sleep(500 * time.Millisecond)
    }
}
<|endoftext|>