<commit_before>/*
Copyright 2014 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

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

import (
	"path/filepath"
)

type FileType string

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

type Interface interface {
	// Mount mounts source to target as fstype with given options.
	Mount(source string, target string, fstype string, options []string) error
	// Unmount unmounts given target.
	Unmount(target string) error
	// List returns a list of all mounted filesystems.  This can be large.
	// On some platforms, reading mounts is not guaranteed consistent (i.e.
	// it could change between chunked reads). This is guaranteed to be
	// consistent.
	List() ([]MountPoint, error)
	// IsMountPointMatch determines if the mountpoint matches the dir
	IsMountPointMatch(mp MountPoint, dir string) bool
	// IsNotMountPoint determines if a directory is a mountpoint.
	// It should return ErrNotExist when the directory does not exist.
	// IsNotMountPoint is more expensive than IsLikelyNotMountPoint.
	// IsNotMountPoint detects bind mounts in linux.
	// IsNotMountPoint enumerates all the mountpoints using List() and
	// the list of mountpoints may be large, then it uses
	// IsMountPointMatch to evaluate whether the directory is a mountpoint
	IsNotMountPoint(file string) (bool, error)
	// IsLikelyNotMountPoint uses heuristics to determine if a directory
	// is a mountpoint.
	// It should return ErrNotExist when the directory does not exist.
	// IsLikelyNotMountPoint does NOT properly detect all mountpoint types
	// most notably linux bind mounts.
	IsLikelyNotMountPoint(file string) (bool, error)
	// DeviceOpened determines if the device is in use elsewhere
	// on the system, i.e. still mounted.
	DeviceOpened(pathname string) (bool, error)
	// PathIsDevice determines if a path is a device.
	PathIsDevice(pathname string) (bool, error)
	// GetDeviceNameFromMount finds the device name by checking the mount path
	// to get the global mount path which matches its plugin directory
	GetDeviceNameFromMount(mountPath, pluginDir string) (string, error)
	// MakeRShared checks that given path is on a mount with 'rshared' mount
	// propagation. If not, it bind-mounts the path as rshared.
	MakeRShared(path string) error
	// GetFileType checks for file/directory/socket/block/character devices.
	// Will operate in the host mount namespace if kubelet is running in a container
	GetFileType(pathname string) (FileType, error)
	// MakeFile creates an empty file.
	// Will operate in the host mount namespace if kubelet is running in a container
	MakeFile(pathname string) error
	// MakeDir creates a new directory.
	// Will operate in the host mount namespace if kubelet is running in a container
	MakeDir(pathname string) error
	// ExistsPath checks whether the path exists.
	// Will operate in the host mount namespace if kubelet is running in a container
	ExistsPath(pathname string) bool
}

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

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

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

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

// FormatAndMount formats the given disk, if needed, and mounts it.
// That is if the disk is not formatted and it is not being mounted as
// read-only it will format it first then mount it. Otherwise, if the
// disk is already formatted or it is being mounted as read-only, it
// will be mounted without formatting.
func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string, fstype string, options []string) error {
	// Don't attempt to format if mounting as readonly. Go straight to mounting.
	for _, option := range options {
		if option == "ro" {
			return mounter.Interface.Mount(source, target, fstype, options)
		}
	}
	return mounter.formatAndMount(source, target, fstype, options)
}

// GetMountRefsByDev finds all references to the device provided
// by mountPath; returns a list of paths.
func GetMountRefsByDev(mounter Interface, mountPath string) ([]string, error) {
	mps, err := mounter.List()
	if err != nil {
		return nil, err
	}
	slTarget, err := filepath.EvalSymlinks(mountPath)
	if err != nil {
		slTarget = mountPath
	}

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

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

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

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

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

// IsNotMountPoint determines if a directory is a mountpoint.
// It should return ErrNotExist when the directory does not exist.
// This method uses the List() of all mountpoints
// It is more extensive than IsLikelyNotMountPoint
// and it detects bind mounts in linux
func IsNotMountPoint(mounter Interface, file string) (bool, error) {
	// IsLikelyNotMountPoint provides a quick check
	// to determine whether file IS A mountpoint
	notMnt, notMntErr := mounter.IsLikelyNotMountPoint(file)
	if notMntErr != nil {
		return notMnt, notMntErr
	}
	// identified as mountpoint, so return this fact
	if notMnt == false {
		return notMnt, nil
	}
	// check all mountpoints since IsLikelyNotMountPoint
	// is not reliable for some mountpoint types
	mountPoints, mountPointsErr := mounter.List()
	if mountPointsErr != nil {
		return notMnt, mountPointsErr
	}
	for _, mp := range mountPoints {
		if mounter.IsMountPointMatch(mp, file) {
			notMnt = false
			break
		}
	}
	return notMnt, nil
}

// isBind detects whether a bind mount is being requested and makes the remount options to
// use in case of bind mount, due to the fact that bind mount doesn't respect mount options.
// The list equals:
//   options - 'bind' + 'remount' (no duplicate)
func isBind(options []string) (bool, []string) {
	bindRemountOpts := []string{"remount"}
	bind := false

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

	return bind, bindRemountOpts
}
<commit_msg>Fixed TearDown of NFS with root squash.<commit_after>/*
Copyright 2014 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

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

import (
	"os"
	"path/filepath"
)

type FileType string

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

type Interface interface {
	// Mount mounts source to target as fstype with given options.
	Mount(source string, target string, fstype string, options []string) error
	// Unmount unmounts given target.
	Unmount(target string) error
	// List returns a list of all mounted filesystems.  This can be large.
	// On some platforms, reading mounts is not guaranteed consistent (i.e.
	// it could change between chunked reads). This is guaranteed to be
	// consistent.
	List() ([]MountPoint, error)
	// IsMountPointMatch determines if the mountpoint matches the dir
	IsMountPointMatch(mp MountPoint, dir string) bool
	// IsNotMountPoint determines if a directory is a mountpoint.
	// It should return ErrNotExist when the directory does not exist.
	// IsNotMountPoint is more expensive than IsLikelyNotMountPoint.
	// IsNotMountPoint detects bind mounts in linux.
	// IsNotMountPoint enumerates all the mountpoints using List() and
	// the list of mountpoints may be large, then it uses
	// IsMountPointMatch to evaluate whether the directory is a mountpoint
	IsNotMountPoint(file string) (bool, error)
	// IsLikelyNotMountPoint uses heuristics to determine if a directory
	// is a mountpoint.
	// It should return ErrNotExist when the directory does not exist.
	// IsLikelyNotMountPoint does NOT properly detect all mountpoint types
	// most notably linux bind mounts.
	IsLikelyNotMountPoint(file string) (bool, error)
	// DeviceOpened determines if the device is in use elsewhere
	// on the system, i.e. still mounted.
	DeviceOpened(pathname string) (bool, error)
	// PathIsDevice determines if a path is a device.
	PathIsDevice(pathname string) (bool, error)
	// GetDeviceNameFromMount finds the device name by checking the mount path
	// to get the global mount path which matches its plugin directory
	GetDeviceNameFromMount(mountPath, pluginDir string) (string, error)
	// MakeRShared checks that given path is on a mount with 'rshared' mount
	// propagation. If not, it bind-mounts the path as rshared.
	MakeRShared(path string) error
	// GetFileType checks for file/directory/socket/block/character devices.
	// Will operate in the host mount namespace if kubelet is running in a container
	GetFileType(pathname string) (FileType, error)
	// MakeFile creates an empty file.
	// Will operate in the host mount namespace if kubelet is running in a container
	MakeFile(pathname string) error
	// MakeDir creates a new directory.
	// Will operate in the host mount namespace if kubelet is running in a container
	MakeDir(pathname string) error
	// ExistsPath checks whether the path exists.
	// Will operate in the host mount namespace if kubelet is running in a container
	ExistsPath(pathname string) bool
}

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

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

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

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

// FormatAndMount formats the given disk, if needed, and mounts it.
// That is if the disk is not formatted and it is not being mounted as
// read-only it will format it first then mount it. Otherwise, if the
// disk is already formatted or it is being mounted as read-only, it
// will be mounted without formatting.
func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string, fstype string, options []string) error {
	// Don't attempt to format if mounting as readonly. Go straight to mounting.
	for _, option := range options {
		if option == "ro" {
			return mounter.Interface.Mount(source, target, fstype, options)
		}
	}
	return mounter.formatAndMount(source, target, fstype, options)
}

// GetMountRefsByDev finds all references to the device provided
// by mountPath; returns a list of paths.
func GetMountRefsByDev(mounter Interface, mountPath string) ([]string, error) {
	mps, err := mounter.List()
	if err != nil {
		return nil, err
	}
	slTarget, err := filepath.EvalSymlinks(mountPath)
	if err != nil {
		slTarget = mountPath
	}

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

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

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

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

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

// IsNotMountPoint determines if a directory is a mountpoint.
// It should return ErrNotExist when the directory does not exist.
// This method uses the List() of all mountpoints
// It is more extensive than IsLikelyNotMountPoint
// and it detects bind mounts in linux
func IsNotMountPoint(mounter Interface, file string) (bool, error) {
	// IsLikelyNotMountPoint provides a quick check
	// to determine whether file IS A mountpoint
	notMnt, notMntErr := mounter.IsLikelyNotMountPoint(file)
	if notMntErr != nil && os.IsPermission(notMntErr) {
		// We were not allowed to do the simple stat() check, e.g. on NFS with
		// root_squash. Fall back to /proc/mounts check below.
		notMnt = true
		notMntErr = nil
	}
	if notMntErr != nil {
		return notMnt, notMntErr
	}
	// identified as mountpoint, so return this fact
	if notMnt == false {
		return notMnt, nil
	}
	// check all mountpoints since IsLikelyNotMountPoint
	// is not reliable for some mountpoint types
	mountPoints, mountPointsErr := mounter.List()
	if mountPointsErr != nil {
		return notMnt, mountPointsErr
	}
	for _, mp := range mountPoints {
		if mounter.IsMountPointMatch(mp, file) {
			notMnt = false
			break
		}
	}
	return notMnt, nil
}

// isBind detects whether a bind mount is being requested and makes the remount options to
// use in case of bind mount, due to the fact that bind mount doesn't respect mount options.
// The list equals:
//   options - 'bind' + 'remount' (no duplicate)
func isBind(options []string) (bool, []string) {
	bindRemountOpts := []string{"remount"}
	bind := false

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

	return bind, bindRemountOpts
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"

	"github.com/muesli/goefa"
)

func main() {
	efa := goefa.EFA{}

	station_id := flag.String("stop", "Königsplatz", "id or (part of the) stop name")
	max_results := flag.Int("results", 5, "how many results to show")
	flag.StringVar(&efa.BaseURL, "baseurl", "http://efa.avv-augsburg.de/avv/", "base-url for EFA API")
	flag.Parse()

/*	if result.Stop.State != "identified" {
		panic("Stop does not exist or name is not unique!")
	}
	fmt.Printf("Selected stop: %s (%d)\n\n",
		result.Stop.IdfdStop.StopName,
		result.Stop.IdfdStop.StopID)*/

	departures, err := efa.Departures(*station_id, *max_results)
	if err != nil {
		panic("Stop does not exist or name is not unique!")
	}
	for _, departure := range departures {
		plu := " "
		if departure.Countdown != 1 {
			plu = "s"
		}

		fmt.Printf("Route %-5s due in %-2d minute%s --> %s\n",
			departure.ServingLine.Number,
			departure.Countdown,
			plu,
			departure.ServingLine.Direction)
	}
}
<commit_msg>* Unpanic in app.<commit_after>package main

import (
	"flag"
	"fmt"

	"github.com/muesli/goefa"
)

func main() {
	efa := goefa.EFA{}

	station_id := flag.String("stop", "Königsplatz", "id or (part of the) stop name")
	max_results := flag.Int("results", 5, "how many results to show")
	flag.StringVar(&efa.BaseURL, "baseurl", "http://efa.avv-augsburg.de/avv/", "base-url for EFA API")
	flag.Parse()

/*	if result.Stop.State != "identified" {
		fmt.Println("Stop does not exist or name is not unique!")
	}
	fmt.Printf("Selected stop: %s (%d)\n\n",
		result.Stop.IdfdStop.StopName,
		result.Stop.IdfdStop.StopID)*/

	departures, err := efa.Departures(*station_id, *max_results)
	if err != nil {
		fmt.Println("Stop does not exist or name is not unique!")
	}
	for _, departure := range departures {
		plu := " "
		if departure.Countdown != 1 {
			plu = "s"
		}

		fmt.Printf("Route %-5s due in %-2d minute%s --> %s\n",
			departure.ServingLine.Number,
			departure.Countdown,
			plu,
			departure.ServingLine.Direction)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/hex"
	"flag"
	"http"
	"io/ioutil"
	"json"
	"log"
	"os"
	"path"
	"sort"
	"template"
	"time"
	"url"
)

type Configuration struct {
	UpdateInterval int64
	Feeds          []FeedInfo
}

type FeedInfo struct {
	Name    string
	URL     string
	MainURL string
	Type    string
}

type Feed struct {
	Info  FeedInfo
	ID    string
	Items map[string]*Item
}

type Item struct {
	Feed    *Feed `json:"-"`
	Title   string
	GUID    string
	URL     string
	Date    time.Time
	Desc    string
	Content string
	Read    bool
	ID      string
}

type TemplateData struct {
	Config *Configuration
	Feeds  *map[string]*Feed
	Unread []*Item
}

const (
	DoUpdate = iota
	GetContent
)

var (
	Config Configuration
	Feeds  map[string]*Feed

	page_template template.Template
	client        http.Client
	updates       chan int
	content       chan string
)

type FeedReader interface {

}

func main() {
	flag.Parse()

	updates = make(chan int)
	content = make(chan string)

	InitTemplate()
	ReadConfig()
	InitCache()
	go HandleUpdates()
	updates <- DoUpdate
	go RunHTTPServer()

	ticks := time.Tick(1e9 * Config.UpdateInterval)
	for {
		go ReadFeeds()
		<-ticks
	}
}

func InitTemplate() {
	log.Print("Initializing Page Template")
	page_template.Parse(page_template_string)
}

func ReadConfig() {
	log.Print("Reading Config")
	// Read config from ~/.munchrc
	file, err := os.Open(path.Join(os.Getenv("HOME"), ".munchrc"))
	if err != nil {
		log.Fatal(err.Error())
	}
	decoder := json.NewDecoder(file)
	err = decoder.Decode(&Config)
	if err != nil {
		log.Fatal(err.Error())
	}
}

func InitCache() {
	Feeds = make(map[string]*Feed)
	// Ensure the cache directory exists
	cachePath := path.Join(os.Getenv("HOME"), ".munch.d", "cache")
	os.MkdirAll(cachePath, 0700)
	// For each feed
	for _, info := range Config.Feeds {
		name := info.Name
		fPath := path.Join(cachePath, name)
		file, _ := os.Open(fPath)
		feed := &Feed{}
		if file != nil {
			log.Print("Loading: ", name)
			decoder := json.NewDecoder(file)
			err := decoder.Decode(feed)
			if err != nil {
				log.Fatal(err.Error())
			}
			for _, item := range feed.Items {
				item.Feed = feed
			}
			feed.Info = info
			Feeds[name] = feed
		} else {
			log.Print("New Feed: ", name)
			feed.Info = info
			feed.ID = hex.EncodeToString([]byte(name))
			feed.Items = make(map[string]*Item)
			Feeds[name] = feed
		}
		if feed.Info.MainURL == "" {
			u, err := url.Parse(feed.Info.URL)
			if err != nil {
				panic(err)
			}
			feed.Info.MainURL = "http://" + u.Host
		}
	}
}

func HandleUpdates() {
	pageBuffer := new(bytes.Buffer)
	tmplData := TemplateData{}
	tmplData.Feeds = &Feeds
	tmplData.Config = &Config
	err := page_template.Execute(pageBuffer, tmplData)
	if err != nil {
		log.Print("ERROR: ", err.Error())
	}
	for u := range updates {
		switch u {
		case DoUpdate:
			tmplData.Unread = getUnread(tmplData.Feeds)
			pageBuffer = new(bytes.Buffer)
			err = page_template.Execute(pageBuffer, tmplData)
			if err != nil {
				log.Print("ERROR: ", err.Error())
			}
			writeCache()
		case GetContent:
			content <- pageBuffer.String()
		default:
			panic("Undefined request to updater")
		}
	}
}

type ItemList []*Item

func (is ItemList) Len() int {
	return len(is)
}

func (is ItemList) Less(i, j int) bool {
	a := is[i]
	b := is[j]
	return a.Date.Seconds() > b.Date.Seconds()
}

func (is ItemList) Swap(i, j int) {
	is[i], is[j] = is[j], is[i]
}

func getUnread(feeds *map[string]*Feed) []*Item {
	items := ItemList{}
	for _, feed := range *feeds {
		for _, item := range feed.Items {
			if !item.Read {
				items = append(items, item)
			}
		}
	}
	sort.Sort(items)
	return items
}

func writeCache() {
	cachePath := path.Join(os.Getenv("HOME"), ".munch.d", "cache")
	os.MkdirAll(cachePath, 0700)
	for _, info := range Config.Feeds {
		name := info.Name
		fPath := path.Join(cachePath, name)
		js, err := json.MarshalIndent(Feeds[name], "", "  ")
		if err != nil {
			log.Print("ERR: ", err)
			continue
		}
		err = ioutil.WriteFile(fPath, []byte(js), 0600)
		if err != nil {
			log.Print("ERR: ", err)
			continue
		}
	}
}

func ReadFeeds() {
	log.Print("Updating feeds")
	for _, feed := range Feeds {
		switch feed.Info.Type {
		case "RSS":
			readRSS(feed)
		case "Atom":
			readAtom(feed)
		case "RDF":
			readRDF(feed)
			log.Print("RDF feeds unsupported")
		default:
			log.Print("Ignoring unknown feed of type ", feed.Info.Type)
		}
	}
	log.Print("Done")
}

// TODO handle this gracefully
func readFeed(feed Feed, reader FeedReader) {

}
<commit_msg>Adding version number<commit_after>package main

import (
	"bytes"
	"encoding/hex"
	"flag"
	"http"
	"io/ioutil"
	"json"
	"log"
	"os"
	"path"
	"sort"
	"template"
	"time"
	"url"
)

const (
	version = `0.1`
)

type Configuration struct {
	UpdateInterval int64
	Feeds          []FeedInfo
}

type FeedInfo struct {
	Name    string
	URL     string
	MainURL string
	Type    string
}

type Feed struct {
	Info  FeedInfo
	ID    string
	Items map[string]*Item
}

type Item struct {
	Feed    *Feed `json:"-"`
	Title   string
	GUID    string
	URL     string
	Date    time.Time
	Desc    string
	Content string
	Read    bool
	ID      string
}

type TemplateData struct {
	Config *Configuration
	Feeds  *map[string]*Feed
	Unread []*Item
}

const (
	DoUpdate = iota
	GetContent
)

var (
	Config Configuration
	Feeds  map[string]*Feed

	page_template template.Template
	client        http.Client
	updates       chan int
	content       chan string
)

type FeedReader interface {

}

func main() {
	flag.Parse()

	updates = make(chan int)
	content = make(chan string)

	InitTemplate()
	ReadConfig()
	InitCache()
	go HandleUpdates()
	updates <- DoUpdate
	go RunHTTPServer()

	ticks := time.Tick(1e9 * Config.UpdateInterval)
	for {
		go ReadFeeds()
		<-ticks
	}
}

func InitTemplate() {
	log.Print("Initializing Page Template")
	page_template.Parse(page_template_string)
}

func ReadConfig() {
	log.Print("Reading Config")
	// Read config from ~/.munchrc
	file, err := os.Open(path.Join(os.Getenv("HOME"), ".munchrc"))
	if err != nil {
		log.Fatal(err.Error())
	}
	decoder := json.NewDecoder(file)
	err = decoder.Decode(&Config)
	if err != nil {
		log.Fatal(err.Error())
	}
}

func InitCache() {
	Feeds = make(map[string]*Feed)
	// Ensure the cache directory exists
	cachePath := path.Join(os.Getenv("HOME"), ".munch.d", "cache")
	os.MkdirAll(cachePath, 0700)
	// For each feed
	for _, info := range Config.Feeds {
		name := info.Name
		fPath := path.Join(cachePath, name)
		file, _ := os.Open(fPath)
		feed := &Feed{}
		if file != nil {
			log.Print("Loading: ", name)
			decoder := json.NewDecoder(file)
			err := decoder.Decode(feed)
			if err != nil {
				log.Fatal(err.Error())
			}
			for _, item := range feed.Items {
				item.Feed = feed
			}
			feed.Info = info
			Feeds[name] = feed
		} else {
			log.Print("New Feed: ", name)
			feed.Info = info
			feed.ID = hex.EncodeToString([]byte(name))
			feed.Items = make(map[string]*Item)
			Feeds[name] = feed
		}
		if feed.Info.MainURL == "" {
			u, err := url.Parse(feed.Info.URL)
			if err != nil {
				panic(err)
			}
			feed.Info.MainURL = "http://" + u.Host
		}
	}
}

func HandleUpdates() {
	pageBuffer := new(bytes.Buffer)
	tmplData := TemplateData{}
	tmplData.Feeds = &Feeds
	tmplData.Config = &Config
	err := page_template.Execute(pageBuffer, tmplData)
	if err != nil {
		log.Print("ERROR: ", err.Error())
	}
	for u := range updates {
		switch u {
		case DoUpdate:
			tmplData.Unread = getUnread(tmplData.Feeds)
			pageBuffer = new(bytes.Buffer)
			err = page_template.Execute(pageBuffer, tmplData)
			if err != nil {
				log.Print("ERROR: ", err.Error())
			}
			writeCache()
		case GetContent:
			content <- pageBuffer.String()
		default:
			panic("Undefined request to updater")
		}
	}
}

type ItemList []*Item

func (is ItemList) Len() int {
	return len(is)
}

func (is ItemList) Less(i, j int) bool {
	a := is[i]
	b := is[j]
	return a.Date.Seconds() > b.Date.Seconds()
}

func (is ItemList) Swap(i, j int) {
	is[i], is[j] = is[j], is[i]
}

func getUnread(feeds *map[string]*Feed) []*Item {
	items := ItemList{}
	for _, feed := range *feeds {
		for _, item := range feed.Items {
			if !item.Read {
				items = append(items, item)
			}
		}
	}
	sort.Sort(items)
	return items
}

func writeCache() {
	cachePath := path.Join(os.Getenv("HOME"), ".munch.d", "cache")
	os.MkdirAll(cachePath, 0700)
	for _, info := range Config.Feeds {
		name := info.Name
		fPath := path.Join(cachePath, name)
		js, err := json.MarshalIndent(Feeds[name], "", "  ")
		if err != nil {
			log.Print("ERR: ", err)
			continue
		}
		err = ioutil.WriteFile(fPath, []byte(js), 0600)
		if err != nil {
			log.Print("ERR: ", err)
			continue
		}
	}
}

func ReadFeeds() {
	log.Print("Updating feeds")
	for _, feed := range Feeds {
		switch feed.Info.Type {
		case "RSS":
			readRSS(feed)
		case "Atom":
			readAtom(feed)
		case "RDF":
			readRDF(feed)
			log.Print("RDF feeds unsupported")
		default:
			log.Print("Ignoring unknown feed of type ", feed.Info.Type)
		}
	}
	log.Print("Done")
}

// TODO handle this gracefully
func readFeed(feed Feed, reader FeedReader) {

}
<|endoftext|>


<commit_before>package mq

import (
	"errors"

	"github.com/iron-io/go.iron/api"
	"github.com/iron-io/go.iron/config"
)

type Queue struct {
	Settings config.Settings
	Name     string
}

type QueueInfo struct {
	TotalMessages int    `json:"total_messages"`
	Name          string `json:"queuename"`
	Size          int    `json:"size"`
}

type Message struct {
	Id   string `json:"id,omitempty"`
	Body string `json:"body"`
	// Timeout is the amount of time in seconds allowed for processing the
	// message.
	Timeout int64 `json:"timeout,omitempty"`
	// Delay is the amount of time in seconds to wait before adding the message
	// to the queue.
	Delay int64 `json:"delay,omitempty"`
	q     Queue
}

func New(queueName string) *Queue {
	return &Queue{Settings: config.Config("iron_mq"), Name: queueName}
}

func (q Queue) queues(s ...string) *api.URL { return api.Action(q.Settings, "queues", s...) }

func (q Queue) ListQueues(page, perPage int) (queues []Queue, err error) {
	out := []struct {
		Id         string
		Project_id string
		Name       string
	}{}

	err = q.queues().
		QueryAdd("page", "%d", page).
		QueryAdd("per_page", "%d", perPage).
		Req("GET", nil, &out)
	if err != nil {
		return
	}

	queues = make([]Queue, 0, len(out))
	for _, item := range out {
		queues = append(queues, Queue{
			Settings: q.Settings,
			Name:     item.Name,
		})
	}

	return
}

func (q Queue) Info() (QueueInfo, error) {
	qi := QueueInfo{}
	err := q.queues(q.Name).Req("GET", nil, &qi)
	return qi, err
}

func (q Queue) PushString(body string) (id string, err error) {
	ids, err := q.PushStrings(body)
	if err != nil {
		return
	}
	return ids[0], nil
}

// Push adds one or more messages to the end of the queue using IronMQ's defaults:
//	timeout - 60 seconds
//	delay - none
//
// Identical to PushMessages with Message{Timeout: 60, Delay: 0}
func (q Queue) PushStrings(bodies ...string) (ids []string, err error) {
	msgs := make([]*Message, 0, len(bodies))
	for _, body := range bodies {
		msgs = append(msgs, &Message{Body: body})
	}

	return q.PushMessages(msgs...)
}

func (q Queue) PushMessage(msg *Message) (id string, err error) {
	ids, err := q.PushMessages(msg)
	if err != nil {
		return
	}
	return ids[0], nil
}

func (q Queue) PushMessages(msgs ...*Message) (ids []string, err error) {
	in := struct {
		Messages []*Message `json:"messages"`
	}{Messages: msgs}

	out := struct {
		IDs []string `json:"ids"`
		Msg string   `json:"msg"`
	}{}

	err = q.queues(q.Name, "messages").Req("POST", &in, &out)
	return out.IDs, err
}

// Get reserves a message from the queue.
// The message will not be deleted, but will be reserved until the timeout
// expires. If the timeout expires before the message is deleted, the message
// will be placed back onto the queue.
// As a result, be sure to Delete a message after you're done with it.
func (q Queue) Get() (msg *Message, err error) {
	msgs, err := q.GetN(1)
	if err != nil {
		return
	}

	if len(msgs) > 0 {
		msg = msgs[0]
	} else {
		err = errors.New("Couldn't get a single message")
	}

	return
}

func (q Queue) GetN(n int) (msgs []*Message, err error) {
	out := struct {
		Messages []*Message `json:"messages"`
	}{}

	err = q.queues(q.Name, "messages").
		QueryAdd("n", "%d", n).
		Req("GET", nil, &out)
	if err != nil {
		return
	}

	for _, msg := range out.Messages {
		msg.q = q
	}

	return out.Messages, nil
}

func (q Queue) Clear() (err error) {
	return q.queues(q.Name, "clear").Req("POST", nil, nil)
}

func (q Queue) DeleteMessage(msgId string) (err error) {
	return q.queues(q.Name, "messages", msgId).Req("DELETE", nil, nil)
}

func (m Message) Delete() (err error) {
	return m.q.DeleteMessage(m.Id)
}
<commit_msg>Support for message release and touch<commit_after>package mq

import (
	"errors"

	"github.com/iron-io/go.iron/api"
	"github.com/iron-io/go.iron/config"
)

type Queue struct {
	Settings config.Settings
	Name     string
}

type QueueInfo struct {
	TotalMessages int    `json:"total_messages"`
	Name          string `json:"queuename"`
	Size          int    `json:"size"`
}

type Message struct {
	Id   string `json:"id,omitempty"`
	Body string `json:"body"`
	// Timeout is the amount of time in seconds allowed for processing the
	// message.
	Timeout int64 `json:"timeout,omitempty"`
	// Delay is the amount of time in seconds to wait before adding the message
	// to the queue.
	Delay int64 `json:"delay,omitempty"`
	q     Queue
}

func New(queueName string) *Queue {
	return &Queue{Settings: config.Config("iron_mq"), Name: queueName}
}

func (q Queue) queues(s ...string) *api.URL { return api.Action(q.Settings, "queues", s...) }

func (q Queue) ListQueues(page, perPage int) (queues []Queue, err error) {
	out := []struct {
		Id         string
		Project_id string
		Name       string
	}{}

	err = q.queues().
		QueryAdd("page", "%d", page).
		QueryAdd("per_page", "%d", perPage).
		Req("GET", nil, &out)
	if err != nil {
		return
	}

	queues = make([]Queue, 0, len(out))
	for _, item := range out {
		queues = append(queues, Queue{
			Settings: q.Settings,
			Name:     item.Name,
		})
	}

	return
}

func (q Queue) Info() (QueueInfo, error) {
	qi := QueueInfo{}
	err := q.queues(q.Name).Req("GET", nil, &qi)
	return qi, err
}

func (q Queue) PushString(body string) (id string, err error) {
	ids, err := q.PushStrings(body)
	if err != nil {
		return
	}
	return ids[0], nil
}

// Push adds one or more messages to the end of the queue using IronMQ's defaults:
//	timeout - 60 seconds
//	delay - none
//
// Identical to PushMessages with Message{Timeout: 60, Delay: 0}
func (q Queue) PushStrings(bodies ...string) (ids []string, err error) {
	msgs := make([]*Message, 0, len(bodies))
	for _, body := range bodies {
		msgs = append(msgs, &Message{Body: body})
	}

	return q.PushMessages(msgs...)
}

func (q Queue) PushMessage(msg *Message) (id string, err error) {
	ids, err := q.PushMessages(msg)
	if err != nil {
		return
	}
	return ids[0], nil
}

func (q Queue) PushMessages(msgs ...*Message) (ids []string, err error) {
	in := struct {
		Messages []*Message `json:"messages"`
	}{Messages: msgs}

	out := struct {
		IDs []string `json:"ids"`
		Msg string   `json:"msg"`
	}{}

	err = q.queues(q.Name, "messages").Req("POST", &in, &out)
	return out.IDs, err
}

// Get reserves a message from the queue.
// The message will not be deleted, but will be reserved until the timeout
// expires. If the timeout expires before the message is deleted, the message
// will be placed back onto the queue.
// As a result, be sure to Delete a message after you're done with it.
func (q Queue) Get() (msg *Message, err error) {
	msgs, err := q.GetN(1)
	if err != nil {
		return
	}

	if len(msgs) > 0 {
		msg = msgs[0]
	} else {
		err = errors.New("Couldn't get a single message")
	}

	return
}

// get N messages
func (q Queue) GetN(n int) (msgs []*Message, err error) {
	out := struct {
		Messages []*Message `json:"messages"`
	}{}

	err = q.queues(q.Name, "messages").
		QueryAdd("n", "%d", n).
		Req("GET", nil, &out)
	if err != nil {
		return
	}

	for _, msg := range out.Messages {
		msg.q = q
	}

	return out.Messages, nil
}

// Delete all messages in the queue
func (q Queue) Clear() (err error) {
	return q.queues(q.Name, "clear").Req("POST", nil, nil)
}

// Delete message from queue
func (q Queue) DeleteMessage(msgId string) (err error) {
	return q.queues(q.Name, "messages", msgId).Req("DELETE", nil, nil)
}

// Reset timeout of message to keep it reserved
func (q Queue) TouchMessage(msgId string) (err error) {
	return q.queues(q.Name, "messages", msgId, "touch").Req("POST", nil, nil)
}

// Put message back in the queue
func (q Queue) ReleaseMessage(msgId string) (err error) {
	return q.queues(q.Name, "messages", msgId, "release").Req("POST", nil, nil)
}

// Delete message from queue
func (m Message) Delete() (err error) {
	return m.q.DeleteMessage(m.Id)
}

// Reset timeout of message to keep it reserved
func (m Message) Touch() (err error) {
	return m.q.TouchMessage(m.Id)
}

// Put message back in the queue
func (m Message) Release() (err error) {
	return m.q.Release(m.Id)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"database/sql"
	"flag"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"io/ioutil"
	"net"
	"os"
	"os/exec"

	"github.com/writeas/nerds/store"
)

var (
	banner    []byte
	outDir    string
	staticDir string
	debugging bool
	rsyncHost string
	db        *sql.DB
)

const (
	colBlue   = "\033[0;34m"
	colGreen  = "\033[0;32m"
	colBGreen = "\033[1;32m"
	colCyan   = "\033[0;36m"
	colBRed   = "\033[1;31m"
	colBold   = "\033[1;37m"
	noCol     = "\033[0m"

	hr = "————————————————————————————————————————————————————————————————————————————————"
)

func main() {
	// Get any arguments
	outDirPtr := flag.String("o", "/var/write", "Directory where text files will be stored.")
	staticDirPtr := flag.String("s", "./static", "Directory where required static files exist.")
	rsyncHostPtr := flag.String("h", "", "Hostname of the server to rsync saved files to.")
	portPtr := flag.Int("p", 2323, "Port to listen on.")
	debugPtr := flag.Bool("debug", false, "Enables garrulous debug logging.")
	flag.Parse()

	outDir = *outDirPtr
	staticDir = *staticDirPtr
	rsyncHost = *rsyncHostPtr
	debugging = *debugPtr

	fmt.Print("\nCONFIG:\n")
	fmt.Printf("Output directory  : %s\n", outDir)
	fmt.Printf("Static directory  : %s\n", staticDir)
	fmt.Printf("rsync host        : %s\n", rsyncHost)
	fmt.Printf("Debugging enabled : %t\n\n", debugging)

	fmt.Print("Initializing...")
	var err error
	banner, err = ioutil.ReadFile(staticDir + "/banner.txt")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("DONE")

	// Connect to database
	dbUser := os.Getenv("WA_USER")
	dbPassword := os.Getenv("WA_PASSWORD")
	dbName := os.Getenv("WA_DB")
	dbHost := os.Getenv("WA_HOST")

	if outDir == "" && (dbUser == "" || dbPassword == "" || dbName == "") {
		// Ensure parameters needed for storage (file or database) are given
		fmt.Println("Database user, password, or database name not set.")
		return
	}

	if outDir == "" {
		fmt.Print("Connecting to database...")
		db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?charset=utf8mb4", dbUser, dbPassword, dbHost, dbName))
		if err != nil {
			fmt.Printf("\n%s\n", err)
			return
		}
		defer db.Close()
		fmt.Println("CONNECTED")
	}

	ln, err := net.Listen("tcp", fmt.Sprintf(":%d", *portPtr))
	if err != nil {
		panic(err)
	}
	fmt.Printf("Listening on localhost:%d\n", *portPtr)

	for {
		conn, err := ln.Accept()
		if err != nil {
			fmt.Println(err)
			continue
		}

		go handleConnection(conn)
	}
}

func output(c net.Conn, m string) bool {
	_, err := c.Write([]byte(m))
	if err != nil {
		c.Close()
		return false
	}
	return true
}

func outputBytes(c net.Conn, m []byte) bool {
	_, err := c.Write(m)
	if err != nil {
		c.Close()
		return false
	}
	return true
}

func handleConnection(c net.Conn) {
	outputBytes(c, banner)
	output(c, fmt.Sprintf("\n%sWelcome to write.as!%s\n", colBGreen, noCol))
	output(c, fmt.Sprintf("If this is freaking you out, you can get notified of the %sbrowser-based%s launch\ninstead at https://write.as.\n\n", colBold, noCol))

	waitForEnter(c)

	c.Close()

	fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}

func waitForEnter(c net.Conn) {
	b := make([]byte, 4)

	output(c, fmt.Sprintf("%sPress Enter to continue...%s\n", colBRed, noCol))
	for {
		n, err := c.Read(b)

		if debugging {
			fmt.Print(b[0:n])
			fmt.Printf("\n%d: %s\n", n, b[0:n])
		}

		if bytes.IndexRune(b[0:n], '\n') > -1 {
			break
		}
		if err != nil || n == 0 {
			c.Close()
			break
		}
	}

	output(c, fmt.Sprintf("Enter anything you like.\nPress %sCtrl-D%s to publish and quit.\n%s\n", colBold, noCol, hr))
	readInput(c)
}

func checkExit(b []byte, n int) bool {
	return n > 0 && bytes.IndexRune(b[0:n], '\n') == -1
}

func readInput(c net.Conn) {
	defer c.Close()

	b := make([]byte, 4096)

	var post bytes.Buffer

	for {
		n, err := c.Read(b)
		post.Write(b[0:n])

		if debugging {
			fmt.Print(b[0:n])
			fmt.Printf("\n%d: %s\n", n, b[0:n])
		}

		if checkExit(b, n) {
			friendlyId := store.GenerateFriendlyRandomString(store.FriendlyIdLen)
			editToken := store.Generate62RandomString(32)

			if outDir == "" {
				_, err := db.Exec("INSERT INTO posts (id, content, modify_token, text_appearance) VALUES (?, ?, ?, 'mono')", friendlyId, post.Bytes(), editToken)
				if err != nil {
					fmt.Printf("There was an error saving: %s\n", err)
					output(c, "Something went terribly wrong, sorry. Try again later?\n\n")
					break
				}
				output(c, fmt.Sprintf("\n%s\nPosted! View at %shttps://write.as/%s%s", hr, colBlue, friendlyId, noCol))
			} else {
				output(c, fmt.Sprintf("\n%s\nPosted to %shttp://nerds.write.as/%s%s", hr, colBlue, friendlyId, noCol))

				if rsyncHost != "" {
					output(c, "\nPosting to secure site...")
					exec.Command("rsync", "-ptgou", outDir+"/"+friendlyId, rsyncHost+":").Run()
					output(c, fmt.Sprintf("\nPosted! View at %shttps://write.as/%s%s", colBlue, friendlyId, noCol))
				}
			}

			output(c, "\nSee you later.\n\n")
			break
		}

		if err != nil || n == 0 {
			break
		}
	}
}
<commit_msg>Add links to welcome text<commit_after>package main

import (
	"bytes"
	"database/sql"
	"flag"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"io/ioutil"
	"net"
	"os"
	"os/exec"

	"github.com/writeas/nerds/store"
)

var (
	banner    []byte
	outDir    string
	staticDir string
	debugging bool
	rsyncHost string
	db        *sql.DB
)

const (
	colBlue   = "\033[0;34m"
	colGreen  = "\033[0;32m"
	colBGreen = "\033[1;32m"
	colCyan   = "\033[0;36m"
	colBRed   = "\033[1;31m"
	colBold   = "\033[1;37m"
	noCol     = "\033[0m"

	hr = "————————————————————————————————————————————————————————————————————————————————"
)

func main() {
	// Get any arguments
	outDirPtr := flag.String("o", "/var/write", "Directory where text files will be stored.")
	staticDirPtr := flag.String("s", "./static", "Directory where required static files exist.")
	rsyncHostPtr := flag.String("h", "", "Hostname of the server to rsync saved files to.")
	portPtr := flag.Int("p", 2323, "Port to listen on.")
	debugPtr := flag.Bool("debug", false, "Enables garrulous debug logging.")
	flag.Parse()

	outDir = *outDirPtr
	staticDir = *staticDirPtr
	rsyncHost = *rsyncHostPtr
	debugging = *debugPtr

	fmt.Print("\nCONFIG:\n")
	fmt.Printf("Output directory  : %s\n", outDir)
	fmt.Printf("Static directory  : %s\n", staticDir)
	fmt.Printf("rsync host        : %s\n", rsyncHost)
	fmt.Printf("Debugging enabled : %t\n\n", debugging)

	fmt.Print("Initializing...")
	var err error
	banner, err = ioutil.ReadFile(staticDir + "/banner.txt")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("DONE")

	// Connect to database
	dbUser := os.Getenv("WA_USER")
	dbPassword := os.Getenv("WA_PASSWORD")
	dbName := os.Getenv("WA_DB")
	dbHost := os.Getenv("WA_HOST")

	if outDir == "" && (dbUser == "" || dbPassword == "" || dbName == "") {
		// Ensure parameters needed for storage (file or database) are given
		fmt.Println("Database user, password, or database name not set.")
		return
	}

	if outDir == "" {
		fmt.Print("Connecting to database...")
		db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?charset=utf8mb4", dbUser, dbPassword, dbHost, dbName))
		if err != nil {
			fmt.Printf("\n%s\n", err)
			return
		}
		defer db.Close()
		fmt.Println("CONNECTED")
	}

	ln, err := net.Listen("tcp", fmt.Sprintf(":%d", *portPtr))
	if err != nil {
		panic(err)
	}
	fmt.Printf("Listening on localhost:%d\n", *portPtr)

	for {
		conn, err := ln.Accept()
		if err != nil {
			fmt.Println(err)
			continue
		}

		go handleConnection(conn)
	}
}

func output(c net.Conn, m string) bool {
	_, err := c.Write([]byte(m))
	if err != nil {
		c.Close()
		return false
	}
	return true
}

func outputBytes(c net.Conn, m []byte) bool {
	_, err := c.Write(m)
	if err != nil {
		c.Close()
		return false
	}
	return true
}

func handleConnection(c net.Conn) {
	outputBytes(c, banner)
	output(c, fmt.Sprintf("\n%sWelcome to write.as!%s\n", colBGreen, noCol))
	output(c, fmt.Sprintf("Our telnet server is open source! https://github.com/writeas/nerds\nOptionally post with %scURL%s: http://cmd.write.as\nOr use our cross-platform %scommand-line client%s: https://write.as/cli.html\nWe won't judge if you crawl back to the GUI: https://write.as/apps\n\n", colBold, noCol, colBold, noCol))

	waitForEnter(c)

	c.Close()

	fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}

func waitForEnter(c net.Conn) {
	b := make([]byte, 4)

	output(c, fmt.Sprintf("%sPress Enter to continue...%s\n", colBRed, noCol))
	for {
		n, err := c.Read(b)

		if debugging {
			fmt.Print(b[0:n])
			fmt.Printf("\n%d: %s\n", n, b[0:n])
		}

		if bytes.IndexRune(b[0:n], '\n') > -1 {
			break
		}
		if err != nil || n == 0 {
			c.Close()
			break
		}
	}

	output(c, fmt.Sprintf("Enter anything you like.\nPress %sCtrl-D%s to publish and quit.\n%s\n", colBold, noCol, hr))
	readInput(c)
}

func checkExit(b []byte, n int) bool {
	return n > 0 && bytes.IndexRune(b[0:n], '\n') == -1
}

func readInput(c net.Conn) {
	defer c.Close()

	b := make([]byte, 4096)

	var post bytes.Buffer

	for {
		n, err := c.Read(b)
		post.Write(b[0:n])

		if debugging {
			fmt.Print(b[0:n])
			fmt.Printf("\n%d: %s\n", n, b[0:n])
		}

		if checkExit(b, n) {
			friendlyId := store.GenerateFriendlyRandomString(store.FriendlyIdLen)
			editToken := store.Generate62RandomString(32)

			if outDir == "" {
				_, err := db.Exec("INSERT INTO posts (id, content, modify_token, text_appearance) VALUES (?, ?, ?, 'mono')", friendlyId, post.Bytes(), editToken)
				if err != nil {
					fmt.Printf("There was an error saving: %s\n", err)
					output(c, "Something went terribly wrong, sorry. Try again later?\n\n")
					break
				}
				output(c, fmt.Sprintf("\n%s\nPosted! View at %shttps://write.as/%s%s", hr, colBlue, friendlyId, noCol))
			} else {
				output(c, fmt.Sprintf("\n%s\nPosted to %shttp://nerds.write.as/%s%s", hr, colBlue, friendlyId, noCol))

				if rsyncHost != "" {
					output(c, "\nPosting to secure site...")
					exec.Command("rsync", "-ptgou", outDir+"/"+friendlyId, rsyncHost+":").Run()
					output(c, fmt.Sprintf("\nPosted! View at %shttps://write.as/%s%s", colBlue, friendlyId, noCol))
				}
			}

			output(c, "\nSee you later.\n\n")
			break
		}

		if err != nil || n == 0 {
			break
		}
	}
}
<|endoftext|>


<commit_before>package main

import(
  "encoding/json"
  "database/sql"
  _ "github.com/go-sql-driver/mysql"
  "github.com/spf13/viper"
  "github.com/chapani/sue"
  "gopkg.in/couchbase/gocb.v1"
)

// fetches data from mysql and adds to couchbase
func mysqlHandler (vp *viper.Viper, cbBucket *gocb.Bucket) (int, interface{}) {

  // get user name from config.toml
  user := vp.GetString("mysql.user")
  if user == "" {
    return 0, "MySQL connection failed: user is missing"
  }

  // get password
  password := vp.GetString("mysql.password")
  if password == "" {
    return 0, "MySQL connection failed: password is missing"
  }

  // get database name
  dbname := vp.GetString("mysql.dbname")
  if dbname == "" {
    return 0, "MySQL connection failed: database name is missing"
  }

  // connect to database
  db, err := sql.Open("mysql", user + ":" + password + "@/" + dbname)
  if err != nil {
    return 0, err.Error()
  }
  defer db.Close()

  // number of added documents
  count := 0

  // query.sql array from config.toml
  var queries []map[string]interface{}
  vp.UnmarshalKey("query", &queries)

  // loop over sql queries
  for i := range queries {

    query := queries[i]

    // fetch data from database
    rows, err := db.Query(query["sql"].(string))
    if err != nil {
      return 0, err.Error()
    }

    // get column names
    columns, err := rows.Columns()
    if err != nil {
      return 0, err.Error()
    }

    // make a slice for the values
    values := make([]sql.RawBytes, len(columns))
    scanArgs := make([]interface{}, len(values))
    for i := range values {
      scanArgs[i] = &values[i]
    }

    // fetch rows
    for rows.Next() {
      err = rows.Scan(scanArgs...)
      if err != nil {
        return 0, err.Error()
      }

      // add field values to document
      var value interface{}
      doc := map[string]interface{}{}
      for i, col := range values {
        if col == nil {
          value = "NULL"
        } else {
          value = col
        }
        doc[columns[i]] = value
      }

      // add additional field values
      if props, ok := query["props"].(map[string]interface{}); ok {
        for propKey, propValue := range props {
          doc[propKey] = propValue
        }
      }

      // convert doc to json and upsert into couchbase
      jsonDoc, _ := json.Marshal(doc)
      _, err := upsert(cbBucket, sue.New2(), jsonDoc)
      if err != nil {
        return 0, err
      }

      count++
    }
    if err = rows.Err(); err != nil {
      return 0, err.Error()
    }
  }
  return count, nil
}
<commit_msg>added string convertion for sql.rawBytes<commit_after>package main

import(
  "encoding/json"
  "database/sql"
  _ "github.com/go-sql-driver/mysql"
  "github.com/spf13/viper"
  "github.com/chapani/sue"
  "gopkg.in/couchbase/gocb.v1"
)

// fetches data from mysql and adds to couchbase
func mysqlHandler (vp *viper.Viper, cbBucket *gocb.Bucket) (int, interface{}) {

  // get user name from config.toml
  user := vp.GetString("mysql.user")
  if user == "" {
    return 0, "MySQL connection failed: user is missing"
  }

  // get password
  password := vp.GetString("mysql.password")
  if password == "" {
    return 0, "MySQL connection failed: password is missing"
  }

  // get database name
  dbname := vp.GetString("mysql.dbname")
  if dbname == "" {
    return 0, "MySQL connection failed: database name is missing"
  }

  // connect to database
  db, err := sql.Open("mysql", user + ":" + password + "@/" + dbname)
  if err != nil {
    return 0, err.Error()
  }
  defer db.Close()

  // number of added documents
  count := 0

  // query.sql array from config.toml
  var queries []map[string]interface{}
  vp.UnmarshalKey("query", &queries)

  // loop over sql queries
  for i := range queries {

    query := queries[i]

    // fetch data from database
    rows, err := db.Query(query["sql"].(string))
    if err != nil {
      return 0, err.Error()
    }

    // get column names
    columns, err := rows.Columns()
    if err != nil {
      return 0, err.Error()
    }

    // make a slice for the values
    values := make([]sql.RawBytes, len(columns))
    scanArgs := make([]interface{}, len(values))
    for i := range values {
      scanArgs[i] = &values[i]
    }

    // fetch rows
    for rows.Next() {
      err = rows.Scan(scanArgs...)
      if err != nil {
        return 0, err.Error()
      }

      // add field values to document
      var value interface{}
      doc := map[string]interface{}{}
      for i, col := range values {
        if col == nil {
          value = "NULL"
        } else {
          value = string(col)
        }
        doc[columns[i]] = value
      }

      // add additional field values
      if props, ok := query["props"].(map[string]interface{}); ok {
        for propKey, propValue := range props {
          doc[propKey] = propValue
        }
      }

      // convert doc to json and upsert into couchbase
      jsonDoc, _ := json.Marshal(doc)
      _, err := upsert(cbBucket, sue.New2(), jsonDoc)
      if err != nil {
        return 0, err
      }

      count++
    }
    if err = rows.Err(); err != nil {
      return 0, err.Error()
    }
  }
  return count, nil
}
<|endoftext|>


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

package newrelicexporter

import (
	"errors"
	"fmt"
	"math"
	"strings"
	"time"

	"github.com/newrelic/newrelic-telemetry-sdk-go/telemetry"
	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/consumer/pdata"
	tracetranslator "go.opentelemetry.io/collector/translator/trace"
)

const (
	unitAttrKey               = "unit"
	descriptionAttrKey        = "description"
	collectorNameKey          = "collector.name"
	collectorVersionKey       = "collector.version"
	instrumentationNameKey    = "instrumentation.name"
	instrumentationVersionKey = "instrumentation.version"
	statusCodeKey             = "otel.status_code"
	statusDescriptionKey      = "otel.status_description"
	spanKindKey               = "span.kind"
	spanIDKey                 = "span.id"
	traceIDKey                = "trace.id"
	logSeverityTextKey        = "log.level"
	logSeverityNumKey         = "log.levelNum"
)

type transformer struct {
	OverrideAttributes map[string]interface{}
	details            *exportMetadata
}

func newTransformer(startInfo *component.ApplicationStartInfo, details *exportMetadata) *transformer {
	overrideAttributes := make(map[string]interface{})
	if startInfo != nil {
		overrideAttributes[collectorNameKey] = startInfo.ExeName
		if startInfo.Version != "" {
			overrideAttributes[collectorVersionKey] = startInfo.Version
		}
	}

	return &transformer{OverrideAttributes: overrideAttributes, details: details}
}

func (t *transformer) CommonAttributes(resource pdata.Resource, lib pdata.InstrumentationLibrary) map[string]interface{} {
	resourceAttrs := resource.Attributes()
	commonAttrs := tracetranslator.AttributeMapToMap(resourceAttrs)
	t.TrackAttributes(attributeLocationResource, resourceAttrs)

	if n := lib.Name(); n != "" {
		commonAttrs[instrumentationNameKey] = n
		if v := lib.Version(); v != "" {
			commonAttrs[instrumentationVersionKey] = v
		}
	}

	for k, v := range t.OverrideAttributes {
		commonAttrs[k] = v
	}

	return commonAttrs
}

var (
	errInvalidSpanID  = errors.New("SpanID is invalid")
	errInvalidTraceID = errors.New("TraceID is invalid")
)

func (t *transformer) Span(span pdata.Span) (telemetry.Span, error) {
	startTime := span.StartTimestamp().AsTime()
	sp := telemetry.Span{
		// HexString validates the IDs, it will be an empty string if invalid.
		ID:         span.SpanID().HexString(),
		TraceID:    span.TraceID().HexString(),
		ParentID:   span.ParentSpanID().HexString(),
		Name:       span.Name(),
		Timestamp:  startTime,
		Duration:   span.EndTimestamp().AsTime().Sub(startTime),
		Attributes: t.SpanAttributes(span),
		Events:     t.SpanEvents(span),
	}

	spanMetadataKey := spanStatsKey{
		hasEvents: sp.Events != nil,
		hasLinks:  span.Links().Len() > 0,
	}
	t.details.spanMetadataCount[spanMetadataKey]++

	if sp.ID == "" {
		return sp, errInvalidSpanID
	}
	if sp.TraceID == "" {
		return sp, errInvalidTraceID
	}

	return sp, nil
}

func (t *transformer) Log(log pdata.LogRecord) (telemetry.Log, error) {
	var message string

	if bodyString := log.Body().StringVal(); bodyString != "" {
		message = bodyString
	} else {
		message = log.Name()
	}

	logAttrs := log.Attributes()
	attrs := make(map[string]interface{}, logAttrs.Len()+5)

	for k, v := range tracetranslator.AttributeMapToMap(logAttrs) {
		// Only include attribute if not an override attribute
		if _, isOverrideKey := t.OverrideAttributes[k]; !isOverrideKey {
			attrs[k] = v
		}
	}
	t.TrackAttributes(attributeLocationLog, logAttrs)

	attrs["name"] = log.Name()
	if !log.TraceID().IsEmpty() {
		attrs[traceIDKey] = log.TraceID().HexString()
	}

	if !log.SpanID().IsEmpty() {
		attrs[spanIDKey] = log.SpanID().HexString()
	}

	if log.SeverityText() != "" {
		attrs[logSeverityTextKey] = log.SeverityText()
	}

	if log.SeverityNumber() != 0 {
		attrs[logSeverityNumKey] = int32(log.SeverityNumber())
	}

	return telemetry.Log{
		Message:    message,
		Timestamp:  log.Timestamp().AsTime(),
		Attributes: attrs,
	}, nil
}

func (t *transformer) SpanAttributes(span pdata.Span) map[string]interface{} {
	spanAttrs := span.Attributes()
	length := spanAttrs.Len()

	var hasStatusCode, hasStatusDesc bool
	s := span.Status()
	if s.Code() != pdata.StatusCodeUnset {
		hasStatusCode = true
		length++
		if s.Message() != "" {
			hasStatusDesc = true
			length++
		}
	}

	validSpanKind := span.Kind() != pdata.SpanKindUNSPECIFIED
	if validSpanKind {
		length++
	}

	attrs := make(map[string]interface{}, length)

	if hasStatusCode {
		code := strings.TrimPrefix(span.Status().Code().String(), "STATUS_CODE_")
		attrs[statusCodeKey] = code
	}
	if hasStatusDesc {
		attrs[statusDescriptionKey] = span.Status().Message()
	}

	// Add span kind if it is set
	if validSpanKind {
		kind := strings.TrimPrefix(span.Kind().String(), "SPAN_KIND_")
		attrs[spanKindKey] = strings.ToLower(kind)
	}

	for k, v := range tracetranslator.AttributeMapToMap(spanAttrs) {
		// Only include attribute if not an override attribute
		if _, isOverrideKey := t.OverrideAttributes[k]; !isOverrideKey {
			attrs[k] = v
		}
	}
	t.TrackAttributes(attributeLocationSpan, spanAttrs)

	return attrs
}

// SpanEvents transforms the recorded events of span into New Relic tracing events.
func (t *transformer) SpanEvents(span pdata.Span) []telemetry.Event {
	length := span.Events().Len()
	if length == 0 {
		return nil
	}

	events := make([]telemetry.Event, length)

	for i := 0; i < length; i++ {
		event := span.Events().At(i)
		eventAttrs := event.Attributes()
		events[i] = telemetry.Event{
			EventType:  event.Name(),
			Timestamp:  event.Timestamp().AsTime(),
			Attributes: tracetranslator.AttributeMapToMap(eventAttrs),
		}
		t.TrackAttributes(attributeLocationSpanEvent, eventAttrs)
	}
	return events
}

type errUnsupportedMetricType struct {
	metricType    string
	metricName    string
	numDataPoints int
}

func (e errUnsupportedMetricType) Error() string {
	return fmt.Sprintf("unsupported metric %v (%v)", e.metricName, e.metricType)
}

func (t *transformer) Metric(m pdata.Metric) ([]telemetry.Metric, error) {
	var output []telemetry.Metric
	baseAttributes := t.BaseMetricAttributes(m)

	dataType := m.DataType()
	k := metricStatsKey{MetricType: dataType}

	switch dataType {
	case pdata.MetricDataTypeIntGauge:
		t.details.metricMetadataCount[k]++
		// "StartTimestampUnixNano" is ignored for all data points.
		gauge := m.IntGauge()
		points := gauge.DataPoints()
		output = make([]telemetry.Metric, 0, points.Len())
		for l := 0; l < points.Len(); l++ {
			point := points.At(l)
			attributes := t.MetricAttributes(baseAttributes, point.LabelsMap())

			nrMetric := telemetry.Gauge{
				Name:       m.Name(),
				Attributes: attributes,
				Value:      float64(point.Value()),
				Timestamp:  point.Timestamp().AsTime(),
			}
			output = append(output, nrMetric)
		}
	case pdata.MetricDataTypeDoubleGauge:
		t.details.metricMetadataCount[k]++
		// "StartTimestampUnixNano" is ignored for all data points.
		gauge := m.DoubleGauge()
		points := gauge.DataPoints()
		output = make([]telemetry.Metric, 0, points.Len())
		for l := 0; l < points.Len(); l++ {
			point := points.At(l)
			attributes := t.MetricAttributes(baseAttributes, point.LabelsMap())

			nrMetric := telemetry.Gauge{
				Name:       m.Name(),
				Attributes: attributes,
				Value:      point.Value(),
				Timestamp:  point.Timestamp().AsTime(),
			}
			output = append(output, nrMetric)
		}
	case pdata.MetricDataTypeIntSum:
		// aggregation_temporality describes if the aggregator reports delta changes
		// since last report time, or cumulative changes since a fixed start time.
		sum := m.IntSum()
		temporality := sum.AggregationTemporality()
		k.MetricTemporality = temporality
		t.details.metricMetadataCount[k]++

		if temporality != pdata.AggregationTemporalityDelta {
			return nil, &errUnsupportedMetricType{metricType: k.MetricType.String(), metricName: m.Name(), numDataPoints: sum.DataPoints().Len()}
		}

		points := sum.DataPoints()
		output = make([]telemetry.Metric, 0, points.Len())
		for l := 0; l < points.Len(); l++ {
			point := points.At(l)
			attributes := t.MetricAttributes(baseAttributes, point.LabelsMap())

			nrMetric := telemetry.Count{
				Name:       m.Name(),
				Attributes: attributes,
				Value:      float64(point.Value()),
				Timestamp:  point.StartTimestamp().AsTime(),
				Interval:   time.Duration(point.Timestamp() - point.StartTimestamp()),
			}
			output = append(output, nrMetric)
		}
	case pdata.MetricDataTypeDoubleSum:
		sum := m.DoubleSum()
		temporality := sum.AggregationTemporality()
		k.MetricTemporality = temporality
		t.details.metricMetadataCount[k]++

		if temporality != pdata.AggregationTemporalityDelta {
			return nil, &errUnsupportedMetricType{metricType: k.MetricType.String(), metricName: m.Name(), numDataPoints: sum.DataPoints().Len()}
		}

		points := sum.DataPoints()
		output = make([]telemetry.Metric, 0, points.Len())
		for l := 0; l < points.Len(); l++ {
			point := points.At(l)
			attributes := t.MetricAttributes(baseAttributes, point.LabelsMap())

			nrMetric := telemetry.Count{
				Name:       m.Name(),
				Attributes: attributes,
				Value:      point.Value(),
				Timestamp:  point.StartTimestamp().AsTime(),
				Interval:   time.Duration(point.Timestamp() - point.StartTimestamp()),
			}
			output = append(output, nrMetric)
		}
	case pdata.MetricDataTypeIntHistogram:
		t.details.metricMetadataCount[k]++
		hist := m.IntHistogram()
		return nil, &errUnsupportedMetricType{metricType: k.MetricType.String(), metricName: m.Name(), numDataPoints: hist.DataPoints().Len()}
	case pdata.MetricDataTypeHistogram:
		t.details.metricMetadataCount[k]++
		hist := m.Histogram()
		return nil, &errUnsupportedMetricType{metricType: k.MetricType.String(), metricName: m.Name(), numDataPoints: hist.DataPoints().Len()}
	case pdata.MetricDataTypeSummary:
		t.details.metricMetadataCount[k]++
		summary := m.Summary()
		points := summary.DataPoints()
		output = make([]telemetry.Metric, 0, points.Len())
		name := m.Name()
		for l := 0; l < points.Len(); l++ {
			point := points.At(l)
			quantiles := point.QuantileValues()
			minQuantile := math.NaN()
			maxQuantile := math.NaN()

			if quantiles.Len() > 0 {
				quantileA := quantiles.At(0)
				if quantileA.Quantile() == 0 {
					minQuantile = quantileA.Value()
				}
				if quantiles.Len() > 1 {
					quantileB := quantiles.At(quantiles.Len() - 1)
					if quantileB.Quantile() == 1 {
						maxQuantile = quantileB.Value()
					}
				} else if quantileA.Quantile() == 1 {
					maxQuantile = quantileA.Value()
				}
			}

			attributes := t.MetricAttributes(baseAttributes, point.LabelsMap())
			nrMetric := telemetry.Summary{
				Name:       name,
				Attributes: attributes,
				Count:      float64(point.Count()),
				Sum:        point.Sum(),
				Min:        minQuantile,
				Max:        maxQuantile,
				Timestamp:  point.StartTimestamp().AsTime(),
				Interval:   time.Duration(point.Timestamp() - point.StartTimestamp()),
			}

			output = append(output, nrMetric)
		}
	default:
		t.details.metricMetadataCount[k]++
	}
	return output, nil
}

func (t *transformer) BaseMetricAttributes(metric pdata.Metric) map[string]interface{} {
	length := 0

	if metric.Unit() != "" {
		length++
	}

	if metric.Description() != "" {
		length++
	}

	attrs := make(map[string]interface{}, length)

	if metric.Unit() != "" {
		attrs[unitAttrKey] = metric.Unit()
	}

	if metric.Description() != "" {
		attrs[descriptionAttrKey] = metric.Description()
	}
	return attrs
}

func (t *transformer) MetricAttributes(baseAttributes map[string]interface{}, attrMap pdata.StringMap) map[string]interface{} {
	rawMap := make(map[string]interface{}, len(baseAttributes)+attrMap.Len())
	for k, v := range baseAttributes {
		rawMap[k] = v
	}
	attrMap.ForEach(func(k string, v string) {
		// Only include attribute if not an override attribute
		if _, isOverrideKey := t.OverrideAttributes[k]; !isOverrideKey {
			rawMap[k] = v
		}
	})

	return rawMap
}

func (t *transformer) TrackAttributes(location attributeLocation, attributeMap pdata.AttributeMap) {
	attributeMap.ForEach(func(k string, v pdata.AttributeValue) {
		statsKey := attributeStatsKey{location: location, attributeType: v.Type()}
		t.details.attributeMetadataCount[statsKey]++
	})
}
<commit_msg>Fix build from ForEach -> Range (#3174)<commit_after>// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package newrelicexporter

import (
	"errors"
	"fmt"
	"math"
	"strings"
	"time"

	"github.com/newrelic/newrelic-telemetry-sdk-go/telemetry"
	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/consumer/pdata"
	tracetranslator "go.opentelemetry.io/collector/translator/trace"
)

const (
	unitAttrKey               = "unit"
	descriptionAttrKey        = "description"
	collectorNameKey          = "collector.name"
	collectorVersionKey       = "collector.version"
	instrumentationNameKey    = "instrumentation.name"
	instrumentationVersionKey = "instrumentation.version"
	statusCodeKey             = "otel.status_code"
	statusDescriptionKey      = "otel.status_description"
	spanKindKey               = "span.kind"
	spanIDKey                 = "span.id"
	traceIDKey                = "trace.id"
	logSeverityTextKey        = "log.level"
	logSeverityNumKey         = "log.levelNum"
)

type transformer struct {
	OverrideAttributes map[string]interface{}
	details            *exportMetadata
}

func newTransformer(startInfo *component.ApplicationStartInfo, details *exportMetadata) *transformer {
	overrideAttributes := make(map[string]interface{})
	if startInfo != nil {
		overrideAttributes[collectorNameKey] = startInfo.ExeName
		if startInfo.Version != "" {
			overrideAttributes[collectorVersionKey] = startInfo.Version
		}
	}

	return &transformer{OverrideAttributes: overrideAttributes, details: details}
}

func (t *transformer) CommonAttributes(resource pdata.Resource, lib pdata.InstrumentationLibrary) map[string]interface{} {
	resourceAttrs := resource.Attributes()
	commonAttrs := tracetranslator.AttributeMapToMap(resourceAttrs)
	t.TrackAttributes(attributeLocationResource, resourceAttrs)

	if n := lib.Name(); n != "" {
		commonAttrs[instrumentationNameKey] = n
		if v := lib.Version(); v != "" {
			commonAttrs[instrumentationVersionKey] = v
		}
	}

	for k, v := range t.OverrideAttributes {
		commonAttrs[k] = v
	}

	return commonAttrs
}

var (
	errInvalidSpanID  = errors.New("SpanID is invalid")
	errInvalidTraceID = errors.New("TraceID is invalid")
)

func (t *transformer) Span(span pdata.Span) (telemetry.Span, error) {
	startTime := span.StartTimestamp().AsTime()
	sp := telemetry.Span{
		// HexString validates the IDs, it will be an empty string if invalid.
		ID:         span.SpanID().HexString(),
		TraceID:    span.TraceID().HexString(),
		ParentID:   span.ParentSpanID().HexString(),
		Name:       span.Name(),
		Timestamp:  startTime,
		Duration:   span.EndTimestamp().AsTime().Sub(startTime),
		Attributes: t.SpanAttributes(span),
		Events:     t.SpanEvents(span),
	}

	spanMetadataKey := spanStatsKey{
		hasEvents: sp.Events != nil,
		hasLinks:  span.Links().Len() > 0,
	}
	t.details.spanMetadataCount[spanMetadataKey]++

	if sp.ID == "" {
		return sp, errInvalidSpanID
	}
	if sp.TraceID == "" {
		return sp, errInvalidTraceID
	}

	return sp, nil
}

func (t *transformer) Log(log pdata.LogRecord) (telemetry.Log, error) {
	var message string

	if bodyString := log.Body().StringVal(); bodyString != "" {
		message = bodyString
	} else {
		message = log.Name()
	}

	logAttrs := log.Attributes()
	attrs := make(map[string]interface{}, logAttrs.Len()+5)

	for k, v := range tracetranslator.AttributeMapToMap(logAttrs) {
		// Only include attribute if not an override attribute
		if _, isOverrideKey := t.OverrideAttributes[k]; !isOverrideKey {
			attrs[k] = v
		}
	}
	t.TrackAttributes(attributeLocationLog, logAttrs)

	attrs["name"] = log.Name()
	if !log.TraceID().IsEmpty() {
		attrs[traceIDKey] = log.TraceID().HexString()
	}

	if !log.SpanID().IsEmpty() {
		attrs[spanIDKey] = log.SpanID().HexString()
	}

	if log.SeverityText() != "" {
		attrs[logSeverityTextKey] = log.SeverityText()
	}

	if log.SeverityNumber() != 0 {
		attrs[logSeverityNumKey] = int32(log.SeverityNumber())
	}

	return telemetry.Log{
		Message:    message,
		Timestamp:  log.Timestamp().AsTime(),
		Attributes: attrs,
	}, nil
}

func (t *transformer) SpanAttributes(span pdata.Span) map[string]interface{} {
	spanAttrs := span.Attributes()
	length := spanAttrs.Len()

	var hasStatusCode, hasStatusDesc bool
	s := span.Status()
	if s.Code() != pdata.StatusCodeUnset {
		hasStatusCode = true
		length++
		if s.Message() != "" {
			hasStatusDesc = true
			length++
		}
	}

	validSpanKind := span.Kind() != pdata.SpanKindUNSPECIFIED
	if validSpanKind {
		length++
	}

	attrs := make(map[string]interface{}, length)

	if hasStatusCode {
		code := strings.TrimPrefix(span.Status().Code().String(), "STATUS_CODE_")
		attrs[statusCodeKey] = code
	}
	if hasStatusDesc {
		attrs[statusDescriptionKey] = span.Status().Message()
	}

	// Add span kind if it is set
	if validSpanKind {
		kind := strings.TrimPrefix(span.Kind().String(), "SPAN_KIND_")
		attrs[spanKindKey] = strings.ToLower(kind)
	}

	for k, v := range tracetranslator.AttributeMapToMap(spanAttrs) {
		// Only include attribute if not an override attribute
		if _, isOverrideKey := t.OverrideAttributes[k]; !isOverrideKey {
			attrs[k] = v
		}
	}
	t.TrackAttributes(attributeLocationSpan, spanAttrs)

	return attrs
}

// SpanEvents transforms the recorded events of span into New Relic tracing events.
func (t *transformer) SpanEvents(span pdata.Span) []telemetry.Event {
	length := span.Events().Len()
	if length == 0 {
		return nil
	}

	events := make([]telemetry.Event, length)

	for i := 0; i < length; i++ {
		event := span.Events().At(i)
		eventAttrs := event.Attributes()
		events[i] = telemetry.Event{
			EventType:  event.Name(),
			Timestamp:  event.Timestamp().AsTime(),
			Attributes: tracetranslator.AttributeMapToMap(eventAttrs),
		}
		t.TrackAttributes(attributeLocationSpanEvent, eventAttrs)
	}
	return events
}

type errUnsupportedMetricType struct {
	metricType    string
	metricName    string
	numDataPoints int
}

func (e errUnsupportedMetricType) Error() string {
	return fmt.Sprintf("unsupported metric %v (%v)", e.metricName, e.metricType)
}

func (t *transformer) Metric(m pdata.Metric) ([]telemetry.Metric, error) {
	var output []telemetry.Metric
	baseAttributes := t.BaseMetricAttributes(m)

	dataType := m.DataType()
	k := metricStatsKey{MetricType: dataType}

	switch dataType {
	case pdata.MetricDataTypeIntGauge:
		t.details.metricMetadataCount[k]++
		// "StartTimestampUnixNano" is ignored for all data points.
		gauge := m.IntGauge()
		points := gauge.DataPoints()
		output = make([]telemetry.Metric, 0, points.Len())
		for l := 0; l < points.Len(); l++ {
			point := points.At(l)
			attributes := t.MetricAttributes(baseAttributes, point.LabelsMap())

			nrMetric := telemetry.Gauge{
				Name:       m.Name(),
				Attributes: attributes,
				Value:      float64(point.Value()),
				Timestamp:  point.Timestamp().AsTime(),
			}
			output = append(output, nrMetric)
		}
	case pdata.MetricDataTypeDoubleGauge:
		t.details.metricMetadataCount[k]++
		// "StartTimestampUnixNano" is ignored for all data points.
		gauge := m.DoubleGauge()
		points := gauge.DataPoints()
		output = make([]telemetry.Metric, 0, points.Len())
		for l := 0; l < points.Len(); l++ {
			point := points.At(l)
			attributes := t.MetricAttributes(baseAttributes, point.LabelsMap())

			nrMetric := telemetry.Gauge{
				Name:       m.Name(),
				Attributes: attributes,
				Value:      point.Value(),
				Timestamp:  point.Timestamp().AsTime(),
			}
			output = append(output, nrMetric)
		}
	case pdata.MetricDataTypeIntSum:
		// aggregation_temporality describes if the aggregator reports delta changes
		// since last report time, or cumulative changes since a fixed start time.
		sum := m.IntSum()
		temporality := sum.AggregationTemporality()
		k.MetricTemporality = temporality
		t.details.metricMetadataCount[k]++

		if temporality != pdata.AggregationTemporalityDelta {
			return nil, &errUnsupportedMetricType{metricType: k.MetricType.String(), metricName: m.Name(), numDataPoints: sum.DataPoints().Len()}
		}

		points := sum.DataPoints()
		output = make([]telemetry.Metric, 0, points.Len())
		for l := 0; l < points.Len(); l++ {
			point := points.At(l)
			attributes := t.MetricAttributes(baseAttributes, point.LabelsMap())

			nrMetric := telemetry.Count{
				Name:       m.Name(),
				Attributes: attributes,
				Value:      float64(point.Value()),
				Timestamp:  point.StartTimestamp().AsTime(),
				Interval:   time.Duration(point.Timestamp() - point.StartTimestamp()),
			}
			output = append(output, nrMetric)
		}
	case pdata.MetricDataTypeDoubleSum:
		sum := m.DoubleSum()
		temporality := sum.AggregationTemporality()
		k.MetricTemporality = temporality
		t.details.metricMetadataCount[k]++

		if temporality != pdata.AggregationTemporalityDelta {
			return nil, &errUnsupportedMetricType{metricType: k.MetricType.String(), metricName: m.Name(), numDataPoints: sum.DataPoints().Len()}
		}

		points := sum.DataPoints()
		output = make([]telemetry.Metric, 0, points.Len())
		for l := 0; l < points.Len(); l++ {
			point := points.At(l)
			attributes := t.MetricAttributes(baseAttributes, point.LabelsMap())

			nrMetric := telemetry.Count{
				Name:       m.Name(),
				Attributes: attributes,
				Value:      point.Value(),
				Timestamp:  point.StartTimestamp().AsTime(),
				Interval:   time.Duration(point.Timestamp() - point.StartTimestamp()),
			}
			output = append(output, nrMetric)
		}
	case pdata.MetricDataTypeIntHistogram:
		t.details.metricMetadataCount[k]++
		hist := m.IntHistogram()
		return nil, &errUnsupportedMetricType{metricType: k.MetricType.String(), metricName: m.Name(), numDataPoints: hist.DataPoints().Len()}
	case pdata.MetricDataTypeHistogram:
		t.details.metricMetadataCount[k]++
		hist := m.Histogram()
		return nil, &errUnsupportedMetricType{metricType: k.MetricType.String(), metricName: m.Name(), numDataPoints: hist.DataPoints().Len()}
	case pdata.MetricDataTypeSummary:
		t.details.metricMetadataCount[k]++
		summary := m.Summary()
		points := summary.DataPoints()
		output = make([]telemetry.Metric, 0, points.Len())
		name := m.Name()
		for l := 0; l < points.Len(); l++ {
			point := points.At(l)
			quantiles := point.QuantileValues()
			minQuantile := math.NaN()
			maxQuantile := math.NaN()

			if quantiles.Len() > 0 {
				quantileA := quantiles.At(0)
				if quantileA.Quantile() == 0 {
					minQuantile = quantileA.Value()
				}
				if quantiles.Len() > 1 {
					quantileB := quantiles.At(quantiles.Len() - 1)
					if quantileB.Quantile() == 1 {
						maxQuantile = quantileB.Value()
					}
				} else if quantileA.Quantile() == 1 {
					maxQuantile = quantileA.Value()
				}
			}

			attributes := t.MetricAttributes(baseAttributes, point.LabelsMap())
			nrMetric := telemetry.Summary{
				Name:       name,
				Attributes: attributes,
				Count:      float64(point.Count()),
				Sum:        point.Sum(),
				Min:        minQuantile,
				Max:        maxQuantile,
				Timestamp:  point.StartTimestamp().AsTime(),
				Interval:   time.Duration(point.Timestamp() - point.StartTimestamp()),
			}

			output = append(output, nrMetric)
		}
	default:
		t.details.metricMetadataCount[k]++
	}
	return output, nil
}

func (t *transformer) BaseMetricAttributes(metric pdata.Metric) map[string]interface{} {
	length := 0

	if metric.Unit() != "" {
		length++
	}

	if metric.Description() != "" {
		length++
	}

	attrs := make(map[string]interface{}, length)

	if metric.Unit() != "" {
		attrs[unitAttrKey] = metric.Unit()
	}

	if metric.Description() != "" {
		attrs[descriptionAttrKey] = metric.Description()
	}
	return attrs
}

func (t *transformer) MetricAttributes(baseAttributes map[string]interface{}, attrMap pdata.StringMap) map[string]interface{} {
	rawMap := make(map[string]interface{}, len(baseAttributes)+attrMap.Len())
	for k, v := range baseAttributes {
		rawMap[k] = v
	}
	attrMap.Range(func(k string, v string) bool {
		// Only include attribute if not an override attribute
		if _, isOverrideKey := t.OverrideAttributes[k]; !isOverrideKey {
			rawMap[k] = v
		}
		return true
	})

	return rawMap
}

func (t *transformer) TrackAttributes(location attributeLocation, attributeMap pdata.AttributeMap) {
	attributeMap.Range(func(k string, v pdata.AttributeValue) bool {
		statsKey := attributeStatsKey{location: location, attributeType: v.Type()}
		t.details.attributeMetadataCount[statsKey]++
		return true
	})
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"testing"
	"net/http"
)

var edgeHostName = flag.String("edge", "www.gov.uk", "Hostname of edge")

// Should redirect from HTTP to HTTPS without hitting origin.
func TestProtocolRedirect(t *testing.T) {
	sourceUrl := fmt.Sprintf("http://%s/", *edgeHostName)
	destUrl := fmt.Sprintf("https://%s/", *edgeHostName)

	client := &http.Transport{}
	req, _ := http.NewRequest("GET", sourceUrl, nil)
	resp, err := client.RoundTrip(req)

	if err != nil {
		t.Error(err)
	}
	if resp.StatusCode != 301 {
		t.Errorf("Status code expected 301, got %s", resp.StatusCode)
	}
	if d := resp.Header.Get("Location"); d != destUrl {
		t.Errorf("Location header expected %s, got %s", destUrl, d)
	}

	t.Error("Not implemented test to confirm that it doesn't hit origin")
}

// Should create an X-Forwarded-For header containing the client's IP.
func TestHeaderCreateXFF(t *testing.T) {
	t.Error("Not implemented")
}

// Should append client's IP to existing X-Forwarded-For header.
func TestHeaderAppendXFF(t *testing.T) {
	t.Error("Not implemented")
}

// Should create a True-Client-IP header containing the client's IP
// address, discarding the value provided in the original request.
func TestHeaderUnspoofableClientIP(t *testing.T) {
	t.Error("Not implemented")
}

// Should not modify Host header from original request.
func TestHeaderHostUnmodified(t *testing.T) {
	t.Error("Not implemented")
}
<commit_msg>Empty test for restrict PURGE.<commit_after>package main

import (
	"flag"
	"fmt"
	"testing"
	"net/http"
)

var edgeHostName = flag.String("edge", "www.gov.uk", "Hostname of edge")

// Should redirect from HTTP to HTTPS without hitting origin.
func TestProtocolRedirect(t *testing.T) {
	sourceUrl := fmt.Sprintf("http://%s/", *edgeHostName)
	destUrl := fmt.Sprintf("https://%s/", *edgeHostName)

	client := &http.Transport{}
	req, _ := http.NewRequest("GET", sourceUrl, nil)
	resp, err := client.RoundTrip(req)

	if err != nil {
		t.Error(err)
	}
	if resp.StatusCode != 301 {
		t.Errorf("Status code expected 301, got %s", resp.StatusCode)
	}
	if d := resp.Header.Get("Location"); d != destUrl {
		t.Errorf("Location header expected %s, got %s", destUrl, d)
	}

	t.Error("Not implemented test to confirm that it doesn't hit origin")
}

// Should return 403 for PURGE requests from IPs not in the whitelist.
func TestRestrictPurgeRequests(t *testing.T) {
	t.Error("Not implemented")
}

// Should create an X-Forwarded-For header containing the client's IP.
func TestHeaderCreateXFF(t *testing.T) {
	t.Error("Not implemented")
}

// Should append client's IP to existing X-Forwarded-For header.
func TestHeaderAppendXFF(t *testing.T) {
	t.Error("Not implemented")
}

// Should create a True-Client-IP header containing the client's IP
// address, discarding the value provided in the original request.
func TestHeaderUnspoofableClientIP(t *testing.T) {
	t.Error("Not implemented")
}

// Should not modify Host header from original request.
func TestHeaderHostUnmodified(t *testing.T) {
	t.Error("Not implemented")
}
<|endoftext|>


<commit_before>package evolve

type Table interface {
	Name() string
	Columns() []*Column
	Column(name string) *Column

	Primary(name string) *fluentColumn
	String(name string, size int) *fluentColumn
	DateTime(name string) *fluentColumn
}

func NewTable(name string) Table {
	return &table{
		name: name,
	}
}

type table struct {
	name    string
	columns []*Column
}

func (t *table) Name() string {
	return t.name
}

func (t *table) Columns() []*Column {
	return t.columns
}

// Return the column with the specified name.  Returns nil if the column isn't found.
func (t *table) Column(name string) *Column {
	for _, column := range t.columns {
		if column.Name == name {
			return column
		}
	}

	return nil
}

func (t *table) Primary(name string) *fluentColumn {
	column := &Column{
		Name:      name,
		Type:      COLUMN_TYPE_UNSIGNED_INTEGER,
		Size:      0,
		AllowNull: false,
		IsPrimary: true,
	}

	t.columns = append(t.columns, column)

	return newFluentColumn(column)
}

func (t *table) String(name string, size int) *fluentColumn {
	column := &Column{
		Name:      name,
		Type:      COLUMN_TYPE_STRING,
		Size:      size,
		AllowNull: true,
		IsPrimary: false,
	}

	t.columns = append(t.columns, column)

	return newFluentColumn(column)
}

func (t *table) DateTime(name string) *fluentColumn {
	column := &Column{
		Name:      name,
		Type:      COLUMN_TYPE_DATE_TIME,
		Size:      0,
		AllowNull: true,
		IsPrimary: false,
	}

	t.columns = append(t.columns, column)

	return newFluentColumn(column)
}
<commit_msg>Set AutoIncrement values when creating columns<commit_after>package evolve

type Table interface {
	Name() string
	Columns() []*Column
	Column(name string) *Column

	Primary(name string) *fluentColumn
	String(name string, size int) *fluentColumn
	DateTime(name string) *fluentColumn
}

func NewTable(name string) Table {
	return &table{
		name: name,
	}
}

type table struct {
	name    string
	columns []*Column
}

func (t *table) Name() string {
	return t.name
}

func (t *table) Columns() []*Column {
	return t.columns
}

// Return the column with the specified name.  Returns nil if the column isn't found.
func (t *table) Column(name string) *Column {
	for _, column := range t.columns {
		if column.Name == name {
			return column
		}
	}

	return nil
}

func (t *table) Primary(name string) *fluentColumn {
	column := &Column{
		Name:          name,
		Type:          COLUMN_TYPE_UNSIGNED_INTEGER,
		Size:          0,
		AllowNull:     false,
		IsPrimary:     true,
		AutoIncrement: true,
	}

	t.columns = append(t.columns, column)

	return newFluentColumn(column)
}

func (t *table) String(name string, size int) *fluentColumn {
	column := &Column{
		Name:          name,
		Type:          COLUMN_TYPE_STRING,
		Size:          size,
		AllowNull:     true,
		IsPrimary:     false,
		AutoIncrement: false,
	}

	t.columns = append(t.columns, column)

	return newFluentColumn(column)
}

func (t *table) DateTime(name string) *fluentColumn {
	column := &Column{
		Name:          name,
		Type:          COLUMN_TYPE_DATE_TIME,
		Size:          0,
		AllowNull:     true,
		IsPrimary:     false,
		AutoIncrement: false,
	}

	t.columns = append(t.columns, column)

	return newFluentColumn(column)
}
<|endoftext|>


<commit_before>package yorm

import (
	"reflect"
	"strings"
	"time"
)

type tableSetter struct {
	table    string
	dests    []interface{}
	columns  []*column
	pkColumn *column
}

var (
	//TimeType time's reflect type.
	TimeType = reflect.TypeOf(time.Time{})

	// one struct reflect to a table query setter
	tableMap = map[reflect.Value]*tableSetter{}
)

func newTableSetter(ri reflect.Value) (*tableSetter, error) {
	if q, ok := tableMap[ri]; ok {
		return q, nil
	}
	if ri.Kind() != reflect.Ptr || ri.IsNil() {
		return nil, ErrNotSupported
	}
	q := new(tableSetter)
	defer func() {
		tableMap[ri] = q
	}()
	table, cs := structToTable(reflect.Indirect(ri).Interface())
	var err error
	q.pkColumn, err = findPkColumn(cs)
	if q.pkColumn == nil {
		return nil, err
	}
	q.table = table
	q.columns = cs
	q.dests = make([]interface{}, len(cs))
	for k, v := range cs {
		q.dests[k] = newPtrInterface(v.typ)
	}
	return q, nil
}

func findPkColumn(cs []*column) (*column, error) {
	var c *column
	var idColumn *column
	isPk := false

	for _, v := range cs {
		if strings.ToLower(v.name) == "id" {
			idColumn = v
		}
		if v.isPK {
			if isPk {
				return c, ErrDuplicatePkColumn
			}
			isPk = true
			c = v
		}
	}
	if c == nil {
		c = idColumn
	}
	if c == nil {
		return nil, ErrNonePkColumn
	}
	return c, nil
}

func newPtrInterface(t reflect.Type) interface{} {
	k := t.Kind()
	var ti interface{}
	switch k {
	case reflect.Int:
		ti = new(int)
	case reflect.Int64:
		ti = new(int64)
	case reflect.String:
		ti = new(string)
	case reflect.Float32:
		ti = new(float32)
	case reflect.Float64:
		ti = new(float64)
	case reflect.Struct:
		switch t {
		case TimeType:
			ti = new(string)
		}
	}
	return ti
}

func scanValue(sc sqlScanner, q *tableSetter, st reflect.Value) error {
	err := sc.Scan(q.dests...)
	if err != nil {
		return err
	}
	for idx, c := range q.columns {
		// different assign func here
		switch c.typ.Kind() {
		case reflect.Int:
			st.Field(c.fieldNum).SetInt(int64(*(q.dests[idx].(*int))))
		case reflect.Int64:
			st.Field(c.fieldNum).SetInt(int64(*(q.dests[idx].(*int64))))
		case reflect.String:
			st.Field(c.fieldNum).SetString(string(*(q.dests[idx].(*string))))
		case reflect.Float32:
			st.Field(c.fieldNum).SetFloat(float64(*(q.dests[idx].(*float32))))
		case reflect.Float64:
			st.Field(c.fieldNum).SetFloat(float64(*(q.dests[idx].(*float64))))
		case reflect.Struct:
			switch c.typ {
			case TimeType:
				timeStr := string(*(q.dests[idx].(*string)))
				var layout string
				if len(timeStr) == 10 {
					layout = "2006-01-02"
				}
				if len(timeStr) == 19 {
					layout = "2006-01-02 15:04:05"
				}
				timeTime, err := time.ParseInLocation(layout, timeStr, time.Local)
				if timeTime.IsZero() {
					return err
				}
				st.Field(c.fieldNum).Set(reflect.ValueOf(timeTime))
			}
		}
	}
	return nil
}
<commit_msg>more detail about err<commit_after>package yorm

import (
	"reflect"
	"strings"
	"time"
)

type tableSetter struct {
	table    string
	dests    []interface{}
	columns  []*column
	pkColumn *column
}

var (
	//TimeType time's reflect type.
	TimeType = reflect.TypeOf(time.Time{})

	// one struct reflect to a table query setter
	tableMap = map[reflect.Value]*tableSetter{}
)

func newTableSetter(ri reflect.Value) (*tableSetter, error) {
	if q, ok := tableMap[ri]; ok {
		return q, nil
	}
	if ri.Kind() != reflect.Ptr {
		return nil, ErrNonPtr
	}
	if ri.IsNil() {
		return nil, ErrNotSupported
	}
	q := new(tableSetter)
	defer func() {
		tableMap[ri] = q
	}()
	table, cs := structToTable(reflect.Indirect(ri).Interface())
	var err error
	q.pkColumn, err = findPkColumn(cs)
	if q.pkColumn == nil {
		return nil, err
	}
	q.table = table
	q.columns = cs
	q.dests = make([]interface{}, len(cs))
	for k, v := range cs {
		q.dests[k] = newPtrInterface(v.typ)
	}
	return q, nil
}

func findPkColumn(cs []*column) (*column, error) {
	var c *column
	var idColumn *column
	isPk := false

	for _, v := range cs {
		if strings.ToLower(v.name) == "id" {
			idColumn = v
		}
		if v.isPK {
			if isPk {
				return c, ErrDuplicatePkColumn
			}
			isPk = true
			c = v
		}
	}
	if c == nil {
		c = idColumn
	}
	if c == nil {
		return nil, ErrNonePkColumn
	}
	return c, nil
}

func newPtrInterface(t reflect.Type) interface{} {
	k := t.Kind()
	var ti interface{}
	switch k {
	case reflect.Int:
		ti = new(int)
	case reflect.Int64:
		ti = new(int64)
	case reflect.String:
		ti = new(string)
	case reflect.Float32:
		ti = new(float32)
	case reflect.Float64:
		ti = new(float64)
	case reflect.Struct:
		switch t {
		case TimeType:
			ti = new(string)
		}
	}
	return ti
}

func scanValue(sc sqlScanner, q *tableSetter, st reflect.Value) error {
	err := sc.Scan(q.dests...)
	if err != nil {
		return err
	}
	for idx, c := range q.columns {
		// different assign func here
		switch c.typ.Kind() {
		case reflect.Int:
			st.Field(c.fieldNum).SetInt(int64(*(q.dests[idx].(*int))))
		case reflect.Int64:
			st.Field(c.fieldNum).SetInt(int64(*(q.dests[idx].(*int64))))
		case reflect.String:
			st.Field(c.fieldNum).SetString(string(*(q.dests[idx].(*string))))
		case reflect.Float32:
			st.Field(c.fieldNum).SetFloat(float64(*(q.dests[idx].(*float32))))
		case reflect.Float64:
			st.Field(c.fieldNum).SetFloat(float64(*(q.dests[idx].(*float64))))
		case reflect.Struct:
			switch c.typ {
			case TimeType:
				timeStr := string(*(q.dests[idx].(*string)))
				var layout string
				if len(timeStr) == 10 {
					layout = "2006-01-02"
				}
				if len(timeStr) == 19 {
					layout = "2006-01-02 15:04:05"
				}
				timeTime, err := time.ParseInLocation(layout, timeStr, time.Local)
				if timeTime.IsZero() {
					return err
				}
				st.Field(c.fieldNum).Set(reflect.ValueOf(timeTime))
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/codegangsta/cli"
)

func execProgram(program string, input string) string {
	var stdout bytes.Buffer
	cmd := exec.Command(program)
	cmd.Stdin = strings.NewReader(input)
	cmd.Stdout = &stdout

	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}

	return stdout.String()
}

func urlPath(programPath string) string {
	return "/" + strings.TrimSuffix(filepath.Base(programPath), filepath.Ext(programPath))
}

func serve(programPath) http.Handler {
	return func(w http.ResponseWriter, r *http.Request) {
		buf := new(bytes.Buffer)
		buf.ReadFrom(r.Body)

		stdout := execProgram(programPath, buf.String())
		io.WriteString(w, stdout)
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "nigit"
	app.Version = "0.1-alpha"
	app.Usage = "Expose any Program as HTTP API"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "port",
			Value:  "8000",
			Usage:  "HTTP port",
			EnvVar: "PORT",
		},
	}

	app.Action = func(c *cli.Context) {
		if !c.Args().Present() {
			fmt.Println("Please provide the names of the scripts to run under nigit")
			os.Exit(1)
		}
		fmt.Println("Serve from port " + c.GlobalString("port"))

		for _, program := range c.Args() {
			programPath, err := filepath.Abs(program)
			if err != nil {
				fmt.Printf("Cannot get path of %s\n", program)
				os.Exit(2)
			}

			programPath, err = exec.LookPath(programPath)
			if err != nil {
				fmt.Printf("Executable program %s not found\n", program)
				os.Exit(3)
			}

			fmt.Printf("%s -> %s\n", urlPath(programPath), program)
			http.HandleFunc(urlPath(programPath), serve)
		}
		http.ListenAndServe(":"+c.GlobalString("port"), nil)
	}

	app.Run(os.Args)
}
<commit_msg>Implement content negotiation<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/codegangsta/cli"
)

func execProgram(program string, env []string, input string) string {
	var stdout bytes.Buffer
	cmd := exec.Command(program)
	cmd.Stdin = strings.NewReader(input)
	cmd.Env = env
	cmd.Stdout = &stdout

	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}

	return stdout.String()
}

func urlPath(programPath string) string {
	return "/" + strings.TrimSuffix(filepath.Base(programPath), filepath.Ext(programPath))
}

func serveText(programPath string, w http.ResponseWriter, r *http.Request) {
	env := os.Environ()
	for k, v := range r.Form {
		env = append(env, fmt.Sprintf("%s=%s", strings.ToUpper(k), v))
	}

	buf := new(bytes.Buffer)
	buf.ReadFrom(r.Body)

	stdout := execProgram(programPath, env, buf.String())

	w.Header().Set("Content-Type", "text/plain")
	io.WriteString(w, stdout)
}

func serve(programPath string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

		accept := r.Header.Get("Accept")
		switch accept {
		case "application/json":
			w.Header().Set("Content-Type", "application/json")
		default:
			serveText(programPath, w, r)
		}
	})
}

func logRequests(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Printf("%s %s\n", r.Method, r.URL)
		handler.ServeHTTP(w, r)
	})
}

func main() {
	app := cli.NewApp()
	app.Name = "nigit"
	app.Version = "0.1-alpha"
	app.Usage = "Expose any Program as HTTP API"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "port",
			Value:  "8000",
			Usage:  "HTTP port",
			EnvVar: "PORT",
		},
	}

	app.Action = func(c *cli.Context) {
		if !c.Args().Present() {
			fmt.Println("Please provide the names of the scripts to run under nigit")
			os.Exit(1)
		}
		fmt.Println("Serve from port " + c.GlobalString("port"))

		for _, program := range c.Args() {
			programPath, err := filepath.Abs(program)
			if err != nil {
				fmt.Printf("Cannot get path of %s\n", program)
				os.Exit(2)
			}

			programPath, err = exec.LookPath(programPath)
			if err != nil {
				fmt.Printf("Executable program %s not found\n", program)
				os.Exit(3)
			}

			fmt.Printf("Handle %s -> %s\n", urlPath(programPath), program)
			http.Handle(urlPath(programPath), serve(programPath))
		}
		http.ListenAndServe(":"+c.GlobalString("port"), logRequests(http.DefaultServeMux))
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import "fmt"
import "os"

import "github.com/go-redis/redis"
import "github.com/joho/godotenv"

//import "github.com/stianeikeland/go-rpio"

func main() {
	godotenv.Load()

	redisChannelName := os.Getenv("UNSPEAK_CHANNEL_SPOKEN")
	redisAddress := os.Getenv("UNSPEAK_REDIS_ADDRESS")

	done := make(chan bool)
	msg := make(chan string)

	go pinWorker(msg)
	go redisWorker(redisAddress, redisChannelName, msg, done)

	//Wait until we are Done...
	<-done

	fmt.Println("Exiting")
}

func redisWorker(redisAddress string, redisChannelName string, msg chan<- string, done chan<- bool) {
	client := redis.NewClient(&redis.Options{
		Addr:     redisAddress,
		Password: "", // no password set
		DB:       0,  // use default DB
	})
	defer client.Close()

	pubsub := client.Subscribe(redisChannelName)
	defer pubsub.Close()

	for {
		message, err := pubsub.ReceiveMessage()
		if err != nil {
			break
		}
		msg <- message.Payload
	}
	close(msg)
	done <- true
}

func pinWorker(msg <-chan string) {

	// err := rpio.Open(); err != nil {
	// 	fmt.Println(err)
	// 	os.Exit(1)
	// }

	// defer rpio.Close();

	//pin := rpio.Pin(10);
	for message := range msg {
		//At this point we should increment the counter
		//pin.Toggle();
		fmt.Println(message)
	}
}
<commit_msg>Replaced tabs with spaces in dis-incrementer.go Also uncommented the go-rpio calls<commit_after>package main

import "fmt"
import "os"

import "github.com/go-redis/redis"
import "github.com/joho/godotenv"

import "github.com/stianeikeland/go-rpio"

func main() {
    godotenv.Load()

    redisChannelName := os.Getenv("UNSPEAK_CHANNEL_SPOKEN")
    redisAddress := os.Getenv("UNSPEAK_REDIS_ADDRESS")

    done := make(chan bool)
    msg := make(chan string)

    go pinWorker(msg)
    go redisWorker(redisAddress, redisChannelName, msg, done)

    //Wait until we are Done...
    <-done

    fmt.Println("Exiting")
}

func redisWorker(redisAddress string, redisChannelName string, msg chan<- string, done chan<- bool) {
    client := redis.NewClient(&redis.Options{
        Addr:     redisAddress,
        Password: "", // no password set
        DB:       0,  // use default DB
    })
    defer client.Close()

    pubsub := client.Subscribe(redisChannelName)
    defer pubsub.Close()

    for {
        message, err := pubsub.ReceiveMessage()
        if err != nil {
            break
        }
        msg <- message.Payload
    }
    close(msg)
    done <- true
}

func pinWorker(msg <-chan string) {

    err := rpio.Open()

    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    defer rpio.Close();

    //pin := rpio.Pin(10);
    for message := range msg {
    //At this point we should increment the counter
    //pin.Toggle();
        fmt.Println(message)
    }
}
<|endoftext|>


<commit_before>package clauseset

import (
	//"davisputnam/clause"
	//"davisputnam/literal"
	"testing"
)

func TestCopy(t *testing.T) {
	//TODO

}
<commit_msg>fixed tests for ClauseSet.Copy()<commit_after>package clauseset

import (
	"davisputnam/clause"
	"testing"
)

func TestCopy(t *testing.T) {
	_, one, two, _ := clause.ConstructTestClauses()

	//case0 -- empty ClauseSet, don't change
	cs := ClauseSet{}
	copy := cs.Copy()

	if !Equals(cs, copy) {
		t.Errorf("original (%q) != copy (%q)", cs, copy)
	}

	//case1 -- empty ClauseSet, chagne copy
	cs = ClauseSet{}
	copy = cs.Copy()
	copy.Append(one)

	if Equals(cs, copy) {
		t.Errorf("original (%q) == Copy().Append(%q) (%q)", cs, one, copy)
	}

	//case2 -- 1 thing in ClauseSet, don't change
	cs = ClauseSet{}
	cs.Append(two)
	copy = cs.Copy()

	if !Equals(cs, copy) {
		t.Errorf("original (%q) != copy (%q)", cs, copy)
	}

	//case3 -- 1 thing in ClauseSet, chagne copy
	cs = ClauseSet{}
	cs.Append(two)
	copy = cs.Copy()
	copy.Append(one)

	if Equals(cs, copy) {
		t.Errorf("original (%q) == Copy().Append(%q, %q) (%q)", cs, one, two, copy)
	}

}
<|endoftext|>