<commit_before>/*
 * This file is part of the KubeVirt project
 *
 * 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.
 *
 * Copyright 2017 Red Hat, Inc.
 *
 */

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"time"

	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	flag "github.com/spf13/pflag"
	k8sv1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/fields"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/client-go/kubernetes/scheme"
	k8coresv1 "k8s.io/client-go/kubernetes/typed/core/v1"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/tools/record"

	v1 "kubevirt.io/kubevirt/pkg/api/v1"
	"kubevirt.io/kubevirt/pkg/certificates"
	"kubevirt.io/kubevirt/pkg/controller"
	inotifyinformer "kubevirt.io/kubevirt/pkg/inotify-informer"
	"kubevirt.io/kubevirt/pkg/kubecli"
	"kubevirt.io/kubevirt/pkg/log"
	_ "kubevirt.io/kubevirt/pkg/monitoring/client/prometheus"    // import for prometheus metrics
	_ "kubevirt.io/kubevirt/pkg/monitoring/reflector/prometheus" // import for prometheus metrics
	_ "kubevirt.io/kubevirt/pkg/monitoring/workqueue/prometheus" // import for prometheus metrics
	"kubevirt.io/kubevirt/pkg/service"
	"kubevirt.io/kubevirt/pkg/util"
	virthandler "kubevirt.io/kubevirt/pkg/virt-handler"
	virtcache "kubevirt.io/kubevirt/pkg/virt-handler/cache"
	virtlauncher "kubevirt.io/kubevirt/pkg/virt-launcher"
	virt_api "kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/api"
)

const (
	defaultWatchdogTimeout = 15 * time.Second

	// Default port that virt-handler listens on.
	defaultPort = 8185

	// Default address that virt-handler listens on.
	defaultHost = "0.0.0.0"

	hostOverride = ""

	podIpAddress = ""

	virtShareDir = "/var/run/kubevirt"

	// This value is derived from default MaxPods in Kubelet Config
	maxDevices = 110
)

type virtHandlerApp struct {
	service.ServiceListen
	HostOverride            string
	PodIpAddress            string
	VirtShareDir            string
	WatchdogTimeoutDuration time.Duration
	MaxDevices              int
}

var _ service.Service = &virtHandlerApp{}

func (app *virtHandlerApp) Run() {
	// HostOverride should default to os.Hostname(), to make sure we handle errors ensure it here.
	if app.HostOverride == "" {
		defaultHostName, err := os.Hostname()
		if err != nil {
			panic(err)
		}
		app.HostOverride = defaultHostName
	}

	if app.PodIpAddress == "" {
		panic(fmt.Errorf("no pod ip detected"))
	}

	logger := log.Log
	logger.V(1).Level(log.INFO).Log("hostname", app.HostOverride)

	// Create event recorder
	virtCli, err := kubecli.GetKubevirtClient()
	if err != nil {
		panic(err)
	}
	broadcaster := record.NewBroadcaster()
	broadcaster.StartRecordingToSink(&k8coresv1.EventSinkImpl{Interface: virtCli.CoreV1().Events(k8sv1.NamespaceAll)})
	// Scheme is used to create an ObjectReference from an Object (e.g. VirtualMachineInstance) during Event creation
	recorder := broadcaster.NewRecorder(scheme.Scheme, k8sv1.EventSource{Component: "virt-handler", Host: app.HostOverride})

	if err != nil {
		panic(err)
	}

	vmiSourceLabel, err := labels.Parse(fmt.Sprintf(v1.NodeNameLabel+" in (%s)", app.HostOverride))
	if err != nil {
		panic(err)
	}
	vmiTargetLabel, err := labels.Parse(fmt.Sprintf(v1.MigrationTargetNodeNameLabel+" in (%s)", app.HostOverride))
	if err != nil {
		panic(err)
	}

	// Wire VirtualMachineInstance controller

	vmSourceSharedInformer := cache.NewSharedIndexInformer(
		controller.NewListWatchFromClient(virtCli.RestClient(), "virtualmachineinstances", k8sv1.NamespaceAll, fields.Everything(), vmiSourceLabel),
		&v1.VirtualMachineInstance{},
		0,
		cache.Indexers{},
	)

	vmTargetSharedInformer := cache.NewSharedIndexInformer(
		controller.NewListWatchFromClient(virtCli.RestClient(), "virtualmachineinstances", k8sv1.NamespaceAll, fields.Everything(), vmiTargetLabel),
		&v1.VirtualMachineInstance{},
		0,
		cache.Indexers{},
	)

	// Wire Domain controller
	domainSharedInformer, err := virtcache.NewSharedInformer(app.VirtShareDir, int(app.WatchdogTimeoutDuration.Seconds()), recorder, vmSourceSharedInformer.GetStore())
	if err != nil {
		panic(err)
	}

	virtlauncher.InitializeSharedDirectories(app.VirtShareDir)

	gracefulShutdownInformer := cache.NewSharedIndexInformer(
		inotifyinformer.NewFileListWatchFromClient(
			virtlauncher.GracefulShutdownTriggerDir(app.VirtShareDir)),
		&virt_api.Domain{},
		0,
		cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})

	vmController := virthandler.NewController(
		recorder,
		virtCli,
		app.HostOverride,
		app.PodIpAddress,
		app.VirtShareDir,
		vmSourceSharedInformer,
		vmTargetSharedInformer,
		domainSharedInformer,
		gracefulShutdownInformer,
		int(app.WatchdogTimeoutDuration.Seconds()),
		maxDevices,
	)

	certsDirectory, err := ioutil.TempDir("", "certsdir")
	if err != nil {
		panic(err)
	}
	defer os.RemoveAll(certsDirectory)
	namespace, err := util.GetNamespace()
	if err != nil {
		glog.Fatalf("Error searching for namespace: %v", err)
	}
	certStore, err := certificates.GenerateSelfSignedCert(certsDirectory, "virt-handler", namespace)
	if err != nil {
		glog.Fatalf("unable to generate certificates: %v", err)
	}
	// Bootstrapping. From here on the startup order matters
	stop := make(chan struct{})
	defer close(stop)
	go vmController.Run(3, stop)

	http.Handle("/metrics", promhttp.Handler())
	err = http.ListenAndServeTLS(app.ServiceListen.Address(), certStore.CurrentPath(), certStore.CurrentPath(), nil)
	if err != nil {
		log.Log.Reason(err).Error("Serving prometheus failed.")
		panic(err)
	}
}

func (app *virtHandlerApp) AddFlags() {
	app.InitFlags()

	app.BindAddress = defaultHost
	app.Port = defaultPort

	app.AddCommonFlags()

	flag.StringVar(&app.HostOverride, "hostname-override", hostOverride,
		"Name under which the node is registered in Kubernetes, where this virt-handler instance is running on")

	flag.StringVar(&app.PodIpAddress, "pod-ip-address", podIpAddress,
		"The pod ip address")

	flag.StringVar(&app.VirtShareDir, "kubevirt-share-dir", virtShareDir,
		"Shared directory between virt-handler and virt-launcher")

	flag.DurationVar(&app.WatchdogTimeoutDuration, "watchdog-timeout", defaultWatchdogTimeout,
		"Watchdog file timeout")

	// TODO: the Device Plugin API does not allow for infinitely available (shared) devices
	// so the current approach is to register an arbitrary number.
	// This should be deprecated if the API allows for shared resources in the future
	flag.IntVar(&app.MaxDevices, "max-devices", maxDevices,
		"Number of devices to register with Kubernetes device plugin framework")
}

func main() {
	app := &virtHandlerApp{}
	service.Setup(app)
	log.InitializeLogging("virt-handler")
	app.Run()
}
<commit_msg>Fix max devices for virt-handler device plugins<commit_after>/*
 * This file is part of the KubeVirt project
 *
 * 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.
 *
 * Copyright 2017 Red Hat, Inc.
 *
 */

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"time"

	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	flag "github.com/spf13/pflag"
	k8sv1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/fields"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/client-go/kubernetes/scheme"
	k8coresv1 "k8s.io/client-go/kubernetes/typed/core/v1"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/tools/record"

	v1 "kubevirt.io/kubevirt/pkg/api/v1"
	"kubevirt.io/kubevirt/pkg/certificates"
	"kubevirt.io/kubevirt/pkg/controller"
	inotifyinformer "kubevirt.io/kubevirt/pkg/inotify-informer"
	"kubevirt.io/kubevirt/pkg/kubecli"
	"kubevirt.io/kubevirt/pkg/log"
	_ "kubevirt.io/kubevirt/pkg/monitoring/client/prometheus"    // import for prometheus metrics
	_ "kubevirt.io/kubevirt/pkg/monitoring/reflector/prometheus" // import for prometheus metrics
	_ "kubevirt.io/kubevirt/pkg/monitoring/workqueue/prometheus" // import for prometheus metrics
	"kubevirt.io/kubevirt/pkg/service"
	"kubevirt.io/kubevirt/pkg/util"
	virthandler "kubevirt.io/kubevirt/pkg/virt-handler"
	virtcache "kubevirt.io/kubevirt/pkg/virt-handler/cache"
	virtlauncher "kubevirt.io/kubevirt/pkg/virt-launcher"
	virt_api "kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/api"
)

const (
	defaultWatchdogTimeout = 15 * time.Second

	// Default port that virt-handler listens on.
	defaultPort = 8185

	// Default address that virt-handler listens on.
	defaultHost = "0.0.0.0"

	hostOverride = ""

	podIpAddress = ""

	virtShareDir = "/var/run/kubevirt"

	// This value is derived from default MaxPods in Kubelet Config
	maxDevices = 110
)

type virtHandlerApp struct {
	service.ServiceListen
	HostOverride            string
	PodIpAddress            string
	VirtShareDir            string
	WatchdogTimeoutDuration time.Duration
	MaxDevices              int
}

var _ service.Service = &virtHandlerApp{}

func (app *virtHandlerApp) Run() {
	// HostOverride should default to os.Hostname(), to make sure we handle errors ensure it here.
	if app.HostOverride == "" {
		defaultHostName, err := os.Hostname()
		if err != nil {
			panic(err)
		}
		app.HostOverride = defaultHostName
	}

	if app.PodIpAddress == "" {
		panic(fmt.Errorf("no pod ip detected"))
	}

	logger := log.Log
	logger.V(1).Level(log.INFO).Log("hostname", app.HostOverride)

	// Create event recorder
	virtCli, err := kubecli.GetKubevirtClient()
	if err != nil {
		panic(err)
	}
	broadcaster := record.NewBroadcaster()
	broadcaster.StartRecordingToSink(&k8coresv1.EventSinkImpl{Interface: virtCli.CoreV1().Events(k8sv1.NamespaceAll)})
	// Scheme is used to create an ObjectReference from an Object (e.g. VirtualMachineInstance) during Event creation
	recorder := broadcaster.NewRecorder(scheme.Scheme, k8sv1.EventSource{Component: "virt-handler", Host: app.HostOverride})

	if err != nil {
		panic(err)
	}

	vmiSourceLabel, err := labels.Parse(fmt.Sprintf(v1.NodeNameLabel+" in (%s)", app.HostOverride))
	if err != nil {
		panic(err)
	}
	vmiTargetLabel, err := labels.Parse(fmt.Sprintf(v1.MigrationTargetNodeNameLabel+" in (%s)", app.HostOverride))
	if err != nil {
		panic(err)
	}

	// Wire VirtualMachineInstance controller

	vmSourceSharedInformer := cache.NewSharedIndexInformer(
		controller.NewListWatchFromClient(virtCli.RestClient(), "virtualmachineinstances", k8sv1.NamespaceAll, fields.Everything(), vmiSourceLabel),
		&v1.VirtualMachineInstance{},
		0,
		cache.Indexers{},
	)

	vmTargetSharedInformer := cache.NewSharedIndexInformer(
		controller.NewListWatchFromClient(virtCli.RestClient(), "virtualmachineinstances", k8sv1.NamespaceAll, fields.Everything(), vmiTargetLabel),
		&v1.VirtualMachineInstance{},
		0,
		cache.Indexers{},
	)

	// Wire Domain controller
	domainSharedInformer, err := virtcache.NewSharedInformer(app.VirtShareDir, int(app.WatchdogTimeoutDuration.Seconds()), recorder, vmSourceSharedInformer.GetStore())
	if err != nil {
		panic(err)
	}

	virtlauncher.InitializeSharedDirectories(app.VirtShareDir)

	gracefulShutdownInformer := cache.NewSharedIndexInformer(
		inotifyinformer.NewFileListWatchFromClient(
			virtlauncher.GracefulShutdownTriggerDir(app.VirtShareDir)),
		&virt_api.Domain{},
		0,
		cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})

	vmController := virthandler.NewController(
		recorder,
		virtCli,
		app.HostOverride,
		app.PodIpAddress,
		app.VirtShareDir,
		vmSourceSharedInformer,
		vmTargetSharedInformer,
		domainSharedInformer,
		gracefulShutdownInformer,
		int(app.WatchdogTimeoutDuration.Seconds()),
		app.MaxDevices,
	)

	certsDirectory, err := ioutil.TempDir("", "certsdir")
	if err != nil {
		panic(err)
	}
	defer os.RemoveAll(certsDirectory)
	namespace, err := util.GetNamespace()
	if err != nil {
		glog.Fatalf("Error searching for namespace: %v", err)
	}
	certStore, err := certificates.GenerateSelfSignedCert(certsDirectory, "virt-handler", namespace)
	if err != nil {
		glog.Fatalf("unable to generate certificates: %v", err)
	}
	// Bootstrapping. From here on the startup order matters
	stop := make(chan struct{})
	defer close(stop)
	go vmController.Run(3, stop)

	http.Handle("/metrics", promhttp.Handler())
	err = http.ListenAndServeTLS(app.ServiceListen.Address(), certStore.CurrentPath(), certStore.CurrentPath(), nil)
	if err != nil {
		log.Log.Reason(err).Error("Serving prometheus failed.")
		panic(err)
	}
}

func (app *virtHandlerApp) AddFlags() {
	app.InitFlags()

	app.BindAddress = defaultHost
	app.Port = defaultPort

	app.AddCommonFlags()

	flag.StringVar(&app.HostOverride, "hostname-override", hostOverride,
		"Name under which the node is registered in Kubernetes, where this virt-handler instance is running on")

	flag.StringVar(&app.PodIpAddress, "pod-ip-address", podIpAddress,
		"The pod ip address")

	flag.StringVar(&app.VirtShareDir, "kubevirt-share-dir", virtShareDir,
		"Shared directory between virt-handler and virt-launcher")

	flag.DurationVar(&app.WatchdogTimeoutDuration, "watchdog-timeout", defaultWatchdogTimeout,
		"Watchdog file timeout")

	// TODO: the Device Plugin API does not allow for infinitely available (shared) devices
	// so the current approach is to register an arbitrary number.
	// This should be deprecated if the API allows for shared resources in the future
	flag.IntVar(&app.MaxDevices, "max-devices", maxDevices,
		"Number of devices to register with Kubernetes device plugin framework")
}

func main() {
	app := &virtHandlerApp{}
	service.Setup(app)
	log.InitializeLogging("virt-handler")
	app.Run()
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 J. Hartsfield

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// Package inboxer is a Go library for checking email using the google Gmail
// API.
package inboxer

// SCOPE:
// TODO:
// channels and go routines
// Mark as read/unread/important/spam
// Get emails by label
// Get emails by query
//
// tests
// Watch inbox
// DOCS
// README.md
// how-to: add client credentials (for readme)
// Get Previews/snippet (put in docs)
//
// WORKS:
// Get emails by date
// Get emails by sender
// Get emails by recipient
// Get emails by subject
// Get emails by mailing-list
// Get emails by thread-topic
// Get labels
// Check for unread messages
// Convert date to human readable format
// Get Body
//
// DONE:
// LICENSE

import (
	"encoding/base64"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	gmail "google.golang.org/api/gmail/v1"
)

// GetBody gets, decodes, and returns the body of the email. It returns an
// error if decoding goes wrong. mimeType is used to indicate whether you want
// the plain text or html encoding ("text/html", "text/plain").
func GetBody(msg *gmail.Message, mimeType string) (string, error) {
	for _, v := range msg.Payload.Parts {
		if v.MimeType == "multipart/alternative" {
			for _, l := range v.Parts {
				if l.MimeType == mimeType && l.Body.Size >= 1 {
					dec, err := decodeEmailBody(l.Body.Data)
					if err != nil {
						return "", err
					}
					return dec, nil
				}
			}
		}
		if v.MimeType == mimeType && v.Body.Size >= 1 {
			dec, err := decodeEmailBody(v.Body.Data)
			if err != nil {
				return "", err
			}
			return dec, nil
		}
	}
	return "", errors.New("Couldn't Read Body")
}

// CheckForUnreadByLabel checks for unread mail maching the speciified label.
// NOTE: When checking your inbox for unread messages, it's not uncommon for
// it return thousands of unread messages that you don't know about. To see them
// in gmail, search your mail for "label:unread". For CheckForUnreadByLabel to
// work properly you need to mark all mail as read either through gmail or
// through the MarkAllAsRead() function found in this library.
func CheckForUnreadByLabel(srv *gmail.Service, label string) (int64, error) {
	inbox, err := srv.Users.Labels.Get("me", label).Do()
	if err != nil {
		return -1, err
	}

	// fmt.Println(label.MessagesUnread)
	if inbox.MessagesUnread == 0 && inbox.ThreadsUnread == 0 {
		return 0, nil
	}

	return inbox.MessagesUnread + inbox.ThreadsUnread, nil
}

// CheckForUnread checks for mail labeled "UNREAD".
// NOTE: When checking your inbox for unread messages, it's not uncommon for
// it return thousands of unread messages that you don't know about. To see them
// in gmail, search your mail for "label:unread". For CheckForUnread to
// work properly you need to mark all mail as read either through gmail or
// through the MarkAllAsRead() function found in this library.
func CheckForUnread(srv *gmail.Service) (int64, error) {
	inbox, err := srv.Users.Labels.Get("me", "UNREAD").Do()
	if err != nil {
		return -1, err
	}

	// fmt.Println(label.MessagesUnread)
	if inbox.MessagesUnread == 0 && inbox.ThreadsUnread == 0 {
		return 0, nil
	}

	return inbox.MessagesUnread + inbox.ThreadsUnread, nil
}

// GetLabels gets a list of the labels used in the users inbox.
func GetLabels(srv *gmail.Service) (*gmail.ListLabelsResponse, error) {
	return srv.Users.Labels.List("me").Do()
}

// HasLabel takes a label and an email and checks if that email has that label
func HasLabel(label string, msg *gmail.Message) bool {
	for _, v := range msg.LabelIds {
		if v == strings.ToUpper(label) {
			return true
		}
	}
	return false
}

// Query queries the inbox for a string following the search style of the gmail
// online mailbox.
// example:
// "in:sent after:2017/01/01 before:2017/01/30"
func Query(srv *gmail.Service, query string) []*gmail.Message {
	inbox, err := srv.Users.Messages.List("me").Q(query).Do()
	if err != nil {
		fmt.Println(err)
	}
	return getById(srv, inbox)
}

// PartialMetadata stores email metadata. Some fields may sound redundant, but
// infact have different contexts. Some are slices of string because the ones
// that have multiple values are still being sorted from those that don't.
type PartialMetadata struct {
	// Sender is the entity that originally created and sent the message
	Sender string
	// From is the entitiy that sent the message to you (e.g. googlegroups). Most
	// of the time this information is only relevant to mailing lists.
	From string
	// Subject is the email subject
	Subject string
	// Mailing list contains the name of the mailing list that the email was
	// posted to, if any.
	MailingList string
	// CC is the "carbon copy" list of addresses
	CC []string
	// To is the recipient of the email.
	To []string
	// ThreadTopic contains the topic of the thread (e.g. google groups threads)
	ThreadTopic []string
	// DeliveredTo is who the email was sent to. This can contain multiple
	// addresses if the email was forwarded.
	DeliveredTo []string
}

// GetPartialMetadata gets some of the useful metadata from the headers.
func GetPartialMetadata(msg *gmail.Message) *PartialMetadata {
	info := &PartialMetadata{}
	for _, v := range msg.Payload.Headers {
		switch v.Name {
		case "Sender":
			info.Sender = v.Value
		case "From":
			info.From = v.Value
		case "Subject":
			info.Subject = v.Value
		case "Mailing-list":
			info.MailingList = v.Value
		case "CC":
			info.CC = append(info.CC, v.Value)
		case "To":
			info.To = append(info.To, v.Value)
		case "Thread-Topic":
			info.ThreadTopic = append(info.ThreadTopic, v.Value)
		case "Delivered-To":
			info.DeliveredTo = append(info.DeliveredTo, v.Value)
		}
	}
	return info
}

// decodeEmailBody is used to decode the email body by converting from
// URLEncoded base64 to a string.
func decodeEmailBody(data string) (string, error) {
	decoded, err := base64.URLEncoding.DecodeString(data)
	if err != nil {
		fmt.Println("decode error:", err)
		return "", err
	}
	return string(decoded), nil
}

// ReceivedTime converts parses and converts a unix time stamp into a human
// readable format ().
func ReceivedTime(datetime int64) time.Time {
	conv := strconv.FormatInt(datetime, 10)
	// Remove trailing zeros.
	conv = conv[:len(conv)-3]
	tc, err := strconv.ParseInt(conv, 10, 64)
	if err != nil {
		fmt.Println(err)
	}
	return time.Unix(tc, 0)
}

func getById(srv *gmail.Service, msgs *gmail.ListMessagesResponse) []*gmail.Message {
	var msgSlice []*gmail.Message
	for _, v := range msgs.Messages {
		msg, _ := srv.Users.Messages.Get("me", v.Id).Do()
		msgSlice = append(msgSlice, msg)
	}
	return msgSlice
}

// GetMessages gets and returns gmail messages
func GetMessages(srv *gmail.Service, howMany uint) ([]*gmail.Message, error) {
	var msgSlice []*gmail.Message

	// Get the messages
	msgs, err := srv.Users.Messages.List("me").MaxResults(int64(howMany)).Do()
	if err != nil {
		return msgSlice, err
	}

	return getById(srv, msgs), nil
}

// func watchInbox() {
// 	req := &gmail.WatchRequest{
// 		LabelFilterAction: "include",
// 		LabelIds:          []string{"UNREAD"},
// 		TopicName:         "gmailmsg",
// 	}

// 	wr, _ := srv.Users.Watch("me", req).Do()
// 	fmt.Println(wr.ForceSendFields)
// }
<commit_msg>moving functions around<commit_after>// Copyright (c) 2017 J. Hartsfield

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// Package inboxer is a Go library for checking email using the google Gmail
// API.
package inboxer

// SCOPE:
// TODO:
// channels and go routines
// Mark as read/unread/important/spam
// check/return errors
//
//
// tests
// Watch inbox
// DOCS
// README.md
// how-to: add client credentials (for readme)
// Get Previews/snippet (put in docs)
//
// WORKS:
// Get emails by query
// Get email metadata
// Get email main body
// Get labels
// Check for unread messages
// Convert date to human readable format
//
// DONE:
// LICENSE

import (
	"encoding/base64"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	gmail "google.golang.org/api/gmail/v1"
)

// GetBody gets, decodes, and returns the body of the email. It returns an
// error if decoding goes wrong. mimeType is used to indicate whether you want
// the plain text or html encoding ("text/html", "text/plain").
func GetBody(msg *gmail.Message, mimeType string) (string, error) {
	for _, v := range msg.Payload.Parts {
		if v.MimeType == "multipart/alternative" {
			for _, l := range v.Parts {
				if l.MimeType == mimeType && l.Body.Size >= 1 {
					dec, err := decodeEmailBody(l.Body.Data)
					if err != nil {
						return "", err
					}
					return dec, nil
				}
			}
		}
		if v.MimeType == mimeType && v.Body.Size >= 1 {
			dec, err := decodeEmailBody(v.Body.Data)
			if err != nil {
				return "", err
			}
			return dec, nil
		}
	}
	return "", errors.New("Couldn't Read Body")
}

// HasLabel takes an email and a label and checks if that email has that label
func HasLabel(msg *gmail.Message, label string) bool {
	for _, v := range msg.LabelIds {
		if v == strings.ToUpper(label) {
			return true
		}
	}
	return false
}

// PartialMetadata stores email metadata. Some fields may sound redundant, but
// infact have different contexts. Some are slices of string because the ones
// that have multiple values are still being sorted from those that don't.
type PartialMetadata struct {
	// Sender is the entity that originally created and sent the message
	Sender string
	// From is the entitiy that sent the message to you (e.g. googlegroups). Most
	// of the time this information is only relevant to mailing lists.
	From string
	// Subject is the email subject
	Subject string
	// Mailing list contains the name of the mailing list that the email was
	// posted to, if any.
	MailingList string
	// CC is the "carbon copy" list of addresses
	CC []string
	// To is the recipient of the email.
	To []string
	// ThreadTopic contains the topic of the thread (e.g. google groups threads)
	ThreadTopic []string
	// DeliveredTo is who the email was sent to. This can contain multiple
	// addresses if the email was forwarded.
	DeliveredTo []string
}

// GetPartialMetadata gets some of the useful metadata from the headers.
func GetPartialMetadata(msg *gmail.Message) *PartialMetadata {
	info := &PartialMetadata{}
	for _, v := range msg.Payload.Headers {
		switch v.Name {
		case "Sender":
			info.Sender = v.Value
		case "From":
			info.From = v.Value
		case "Subject":
			info.Subject = v.Value
		case "Mailing-list":
			info.MailingList = v.Value
		case "CC":
			info.CC = append(info.CC, v.Value)
		case "To":
			info.To = append(info.To, v.Value)
		case "Thread-Topic":
			info.ThreadTopic = append(info.ThreadTopic, v.Value)
		case "Delivered-To":
			info.DeliveredTo = append(info.DeliveredTo, v.Value)
		}
	}
	return info
}

// decodeEmailBody is used to decode the email body by converting from
// URLEncoded base64 to a string.
func decodeEmailBody(data string) (string, error) {
	decoded, err := base64.URLEncoding.DecodeString(data)
	if err != nil {
		fmt.Println("decode error:", err)
		return "", err
	}
	return string(decoded), nil
}

// ReceivedTime parses and converts a unix time stamp into a human readable
// format ().
func ReceivedTime(datetime int64) time.Time {
	conv := strconv.FormatInt(datetime, 10)
	// Remove trailing zeros.
	conv = conv[:len(conv)-3]
	tc, err := strconv.ParseInt(conv, 10, 64)
	if err != nil {
		fmt.Println(err)
	}
	return time.Unix(tc, 0)
}

// Query queries the inbox for a string following the search style of the gmail
// online mailbox.
// example:
// "in:sent after:2017/01/01 before:2017/01/30"
func Query(srv *gmail.Service, query string) []*gmail.Message {
	inbox, err := srv.Users.Messages.List("me").Q(query).Do()
	if err != nil {
		fmt.Println(err)
	}
	return getById(srv, inbox)
}

// getById gets emails individually by ID. This is neccessary because this is
// how the gmail API is set up apparently (but why?).
//
func getById(srv *gmail.Service, msgs *gmail.ListMessagesResponse) []*gmail.Message {
	var msgSlice []*gmail.Message
	for _, v := range msgs.Messages {
		msg, _ := srv.Users.Messages.Get("me", v.Id).Do()
		msgSlice = append(msgSlice, msg)
	}
	return msgSlice
}

// GetMessages gets and returns gmail messages
func GetMessages(srv *gmail.Service, howMany uint) ([]*gmail.Message, error) {
	var msgSlice []*gmail.Message

	// Get the messages
	msgs, err := srv.Users.Messages.List("me").MaxResults(int64(howMany)).Do()
	if err != nil {
		return msgSlice, err
	}

	return getById(srv, msgs), nil
}

// CheckForUnreadByLabel checks for unread mail maching the speciified label.
// NOTE: When checking your inbox for unread messages, it's not uncommon for
// it return thousands of unread messages that you don't know about. To see them
// in gmail, search your mail for "label:unread". For CheckForUnreadByLabel to
// work properly you need to mark all mail as read either through gmail or
// through the MarkAllAsRead() function found in this library.
func CheckForUnreadByLabel(srv *gmail.Service, label string) (int64, error) {
	inbox, err := srv.Users.Labels.Get("me", label).Do()
	if err != nil {
		return -1, err
	}

	// fmt.Println(label.MessagesUnread)
	if inbox.MessagesUnread == 0 && inbox.ThreadsUnread == 0 {
		return 0, nil
	}

	return inbox.MessagesUnread + inbox.ThreadsUnread, nil
}

// CheckForUnread checks for mail labeled "UNREAD".
// NOTE: When checking your inbox for unread messages, it's not uncommon for
// it return thousands of unread messages that you don't know about. To see them
// in gmail, search your mail for "label:unread". For CheckForUnread to
// work properly you need to mark all mail as read either through gmail or
// through the MarkAllAsRead() function found in this library.
func CheckForUnread(srv *gmail.Service) (int64, error) {
	inbox, err := srv.Users.Labels.Get("me", "UNREAD").Do()
	if err != nil {
		return -1, err
	}

	// fmt.Println(label.MessagesUnread)
	if inbox.MessagesUnread == 0 && inbox.ThreadsUnread == 0 {
		return 0, nil
	}

	return inbox.MessagesUnread + inbox.ThreadsUnread, nil
}

// GetLabels gets a list of the labels used in the users inbox.
func GetLabels(srv *gmail.Service) (*gmail.ListLabelsResponse, error) {
	return srv.Users.Labels.List("me").Do()
}

// func watchInbox() {
// 	req := &gmail.WatchRequest{
// 		LabelFilterAction: "include",
// 		LabelIds:          []string{"UNREAD"},
// 		TopicName:         "gmailmsg",
// 	}

// 	wr, _ := srv.Users.Watch("me", req).Do()
// 	fmt.Println(wr.ForceSendFields)
// }
<|endoftext|>


<commit_before>// Copyright 2015-2017 trivago GmbH
//
// 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 core

import (
	"strconv"
	"strings"
)

var versionString string

// GetVersionString return a symantic version string
func GetVersionString() string {
	return versionString
}

// GetVersionNumber return a symantic based version number
func GetVersionNumber() int64 {
	parts := strings.Split(versionString, ".")
	multiplier := int64(100 * 100) // major, minor, patch
	version := int64(0)
	for i, subVerString := range parts {
		if i == 3 {
			break // done
		}
		subVer, err := strconv.Atoi(subVerString)
		if err != nil {
			break // cannot parse
		}
		version += int64(subVer) * multiplier
		multiplier /= 100

	}
	return version
}
<commit_msg>valid version for builds without make<commit_after>// Copyright 2015-2017 trivago GmbH
//
// 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 core

import (
	"strconv"
	"strings"
)

var versionString string

// GetVersionString return a symantic version string
func GetVersionString() string {
	if len(versionString) == 0 {
		return "0.0.0-non_make_build"
	}
	return versionString
}

// GetVersionNumber return a symantic based version number
func GetVersionNumber() int64 {
	parts := strings.Split(GetVersionString(), ".")
	multiplier := int64(100 * 100) // major, minor, patch
	version := int64(0)
	for i, subVerString := range parts {
		if i == 3 {
			break // done
		}
		subVer, err := strconv.Atoi(subVerString)
		if err != nil {
			break // cannot parse
		}
		version += int64(subVer) * multiplier
		multiplier /= 100

	}
	return version
}
<|endoftext|>


<commit_before>package controllers

import (
	"fmt"
	"github.com/astaxie/beego"
	"strconv"
	"strings"
	"time"

	"github.com/shwinpiocess/cc/models"
	"github.com/shwinpiocess/cc/utils"
)

type MainController struct {
	BaseController
}

func (this *MainController) Index() {
	fmt.Println("this.firstApp=", this.firstApp)
	if this.firstApp {
		this.TplName = "app/help.html"
	} else {
		fmt.Println("2222222222222")
	}
}

// 登录
func (this *MainController) Login() {
	if this.userId > 0 {
		fmt.Println("登录userid=", this.userId)
		this.redirect("/")
	}

	beego.ReadFromRequest(&this.Controller)
	if this.isPost() {
		username := strings.TrimSpace(this.GetString("username"))
		password := strings.TrimSpace(this.GetString("password"))
		remember := this.GetString("remember")
		if username != "" && password != "" {
			user, err := models.GetUserByName(username)
			errMsg := ""
			if err != nil || user.Password != utils.Md5([]byte(password+user.Salt)) {
				errMsg = "账号或密码错误"
			} else if user.Status == -1 {
				errMsg = "该账号已禁用"
			} else {
				user.LastIp = this.getClientIP()
				user.LastLogin = time.Now().Unix()
				models.UpdateUser(user)

				authkey := utils.Md5([]byte(this.getClientIP() + "|" + user.Password + user.Salt))

				if remember == "yes" {
					this.Ctx.SetCookie("auth", strconv.Itoa(user.Id)+"|"+authkey, 7*86400)
				} else {
					this.Ctx.SetCookie("auth", strconv.Itoa(user.Id)+"|"+authkey)
				}
				fmt.Println(this.Data)
				this.redirect(beego.URLFor("AppController.Index"))
			}
			fmt.Println(errMsg)
		}

	}

	fmt.Println("登录嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻")
	this.TplName = "main/login.html"
}

// 退出登录
func (this *MainController) Logout() {
	this.Ctx.SetCookie("auth", "")
	this.redirect(beego.URLFor("MainController.Login"))
}
<commit_msg>清除调试信息<commit_after>package controllers

import (
	"fmt"
	"github.com/astaxie/beego"
	"strconv"
	"strings"
	"time"

	"github.com/shwinpiocess/cc/models"
	"github.com/shwinpiocess/cc/utils"
)

type MainController struct {
	BaseController
}

func (this *MainController) Index() {
	fmt.Println("this.firstApp=", this.firstApp)
	if this.firstApp {
		this.TplName = "app/help.html"
	} else {
		this.TplName = "index.html"
	}
}

// 登录
func (this *MainController) Login() {
	if this.userId > 0 {
		fmt.Println("登录userid=", this.userId)
		this.redirect("/")
	}

	beego.ReadFromRequest(&this.Controller)
	if this.isPost() {
		username := strings.TrimSpace(this.GetString("username"))
		password := strings.TrimSpace(this.GetString("password"))
		remember := this.GetString("remember")
		if username != "" && password != "" {
			user, err := models.GetUserByName(username)
			errMsg := ""
			if err != nil || user.Password != utils.Md5([]byte(password+user.Salt)) {
				errMsg = "账号或密码错误"
			} else if user.Status == -1 {
				errMsg = "该账号已禁用"
			} else {
				user.LastIp = this.getClientIP()
				user.LastLogin = time.Now().Unix()
				models.UpdateUser(user)

				authkey := utils.Md5([]byte(this.getClientIP() + "|" + user.Password + user.Salt))

				if remember == "yes" {
					this.Ctx.SetCookie("auth", strconv.Itoa(user.Id)+"|"+authkey, 7*86400)
				} else {
					this.Ctx.SetCookie("auth", strconv.Itoa(user.Id)+"|"+authkey)
				}
				fmt.Println(this.Data)
				this.redirect(beego.URLFor("AppController.Index"))
			}
			fmt.Println(errMsg)
		}

	}

	fmt.Println("登录嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻")
	this.TplName = "main/login.html"
}

// 退出登录
func (this *MainController) Logout() {
	this.Ctx.SetCookie("auth", "")
	this.redirect(beego.URLFor("MainController.Login"))
}
<|endoftext|>


<commit_before>package forceleave

import (
	"flag"
	"fmt"

	"github.com/hashicorp/consul/command/flags"
	"github.com/mitchellh/cli"
)

func New(ui cli.Ui) *cmd {
	c := &cmd{UI: ui}
	c.init()
	return c
}

type cmd struct {
	UI    cli.Ui
	flags *flag.FlagSet
	http  *flags.HTTPFlags
	help  string
}

func (c *cmd) init() {
	c.flags = flag.NewFlagSet("", flag.ContinueOnError)
	c.http = &flags.HTTPFlags{}
	flags.Merge(c.flags, c.http.ClientFlags())
	flags.Merge(c.flags, c.http.ServerFlags())
	c.help = flags.Usage(help, c.flags, c.http.ClientFlags(), c.http.ServerFlags())
}

func (c *cmd) Run(args []string) int {
	if err := c.flags.Parse(args); err != nil {
		return 1
	}

	nodes := c.flags.Args()
	if len(nodes) != 1 {
		c.UI.Error("A single node name must be specified to force leave.")
		c.UI.Error("")
		c.UI.Error(c.Help())
		return 1
	}

	client, err := c.http.APIClient()
	if err != nil {
		c.UI.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
		return 1
	}

	err = client.Agent().ForceLeave(nodes[0])
	if err != nil {
		c.UI.Error(fmt.Sprintf("Error force leaving: %s", err))
		return 1
	}

	return 0
}

func (c *cmd) Synopsis() string {
	return synopsis
}

func (c *cmd) Help() string {
	return c.help
}

const synopsis = "Forces a member of the cluster to enter the \"left\" state"
const help = `
Usage: consul force-leave [options] name

  Forces a member of a Consul cluster to enter the "left" state. Note
  that if the member is still actually alive, it will eventually rejoin
  the cluster. This command is most useful for cleaning out "failed" nodes
  that are never coming back. If you do not force leave a failed node,
  Consul will attempt to reconnect to those failed nodes for some period of
  time before eventually reaping them.
`
<commit_msg>commands: drop http server flags from force-leave command<commit_after>package forceleave

import (
	"flag"
	"fmt"

	"github.com/hashicorp/consul/command/flags"
	"github.com/mitchellh/cli"
)

func New(ui cli.Ui) *cmd {
	c := &cmd{UI: ui}
	c.init()
	return c
}

type cmd struct {
	UI    cli.Ui
	flags *flag.FlagSet
	http  *flags.HTTPFlags
	help  string
}

func (c *cmd) init() {
	c.flags = flag.NewFlagSet("", flag.ContinueOnError)
	c.http = &flags.HTTPFlags{}
	flags.Merge(c.flags, c.http.ClientFlags())
	c.help = flags.Usage(help, c.flags, c.http.ClientFlags(), nil)
}

func (c *cmd) Run(args []string) int {
	if err := c.flags.Parse(args); err != nil {
		return 1
	}

	nodes := c.flags.Args()
	if len(nodes) != 1 {
		c.UI.Error("A single node name must be specified to force leave.")
		c.UI.Error("")
		c.UI.Error(c.Help())
		return 1
	}

	client, err := c.http.APIClient()
	if err != nil {
		c.UI.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
		return 1
	}

	err = client.Agent().ForceLeave(nodes[0])
	if err != nil {
		c.UI.Error(fmt.Sprintf("Error force leaving: %s", err))
		return 1
	}

	return 0
}

func (c *cmd) Synopsis() string {
	return synopsis
}

func (c *cmd) Help() string {
	return c.help
}

const synopsis = "Forces a member of the cluster to enter the \"left\" state"
const help = `
Usage: consul force-leave [options] name

  Forces a member of a Consul cluster to enter the "left" state. Note
  that if the member is still actually alive, it will eventually rejoin
  the cluster. This command is most useful for cleaning out "failed" nodes
  that are never coming back. If you do not force leave a failed node,
  Consul will attempt to reconnect to those failed nodes for some period of
  time before eventually reaping them.
`
<|endoftext|>


<commit_before>package commands

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"time"

	"github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"

	b58 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58"

	cmds "github.com/jbenet/go-ipfs/commands"
	"github.com/jbenet/go-ipfs/peer"
	kb "github.com/jbenet/go-ipfs/routing/kbucket"
	u "github.com/jbenet/go-ipfs/util"
)

const offlineIdErrorMessage = `ID command fails when run without daemon, we are working to fix this.
In the meantime, please run the daemon if you want to use 'ipfs id':

    ipfs daemon &
    ipfs id QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
`

type IdOutput struct {
	ID              string
	PublicKey       string
	Addresses       []string
	AgentVersion    string
	ProtocolVersion string
}

var idCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Show IPFS Node ID info",
		ShortDescription: `
Prints out information about the specified peer,
if no peer is specified, prints out local peers info.
`,
	},
	Arguments: []cmds.Argument{
		cmds.StringArg("peerid", false, false, "peer.ID of node to look up"),
	},
	Run: func(req cmds.Request) (interface{}, error) {
		node, err := req.Context().GetNode()
		if err != nil {
			return nil, err
		}

		if len(req.Arguments()) == 0 {
			return printPeer(node.Identity)
		}

		pid := req.Arguments()[0]

		id := peer.ID(b58.Decode(pid))
		if len(id) == 0 {
			return nil, cmds.ClientError("Invalid peer id")
		}

		ctx, _ := context.WithTimeout(context.TODO(), time.Second*5)
		if node.Routing == nil {
			return nil, errors.New(offlineIdErrorMessage)
		}

		p, err := node.Routing.FindPeer(ctx, id)
		if err == kb.ErrLookupFailure {
			return nil, errors.New(offlineIdErrorMessage)
		}
		if err != nil {
			return nil, err
		}
		return printPeer(p)
	},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: func(res cmds.Response) ([]byte, error) {
			val, ok := res.Output().(*IdOutput)
			if !ok {
				return nil, u.ErrCast()
			}

			return json.MarshalIndent(val, "", "\t")
		},
	},
	Type: &IdOutput{},
}

func printPeer(p peer.Peer) (interface{}, error) {
	if p == nil {
		return nil, errors.New("Attempted to print nil peer!")
	}
	info := new(IdOutput)

	info.ID = p.ID().String()
	if p.PubKey() == nil {
		return nil, errors.New(`peer publickey not populated on offline runs,
please run the daemon to use ipfs id!`)
	}
	pkb, err := p.PubKey().Bytes()
	if err != nil {
		return nil, err
	}
	info.PublicKey = base64.StdEncoding.EncodeToString(pkb)
	for _, a := range p.Addresses() {
		info.Addresses = append(info.Addresses, a.String())
	}

	agent, protocol := p.GetVersions()
	info.AgentVersion = agent
	info.ProtocolVersion = protocol

	return info, nil
}
<commit_msg>fix for #381<commit_after>package commands

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"time"

	"github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"

	b58 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58"

	cmds "github.com/jbenet/go-ipfs/commands"
	"github.com/jbenet/go-ipfs/peer"
	kb "github.com/jbenet/go-ipfs/routing/kbucket"
	u "github.com/jbenet/go-ipfs/util"
)

const offlineIdErrorMessage = `ID command fails when run without daemon, we are working to fix this.
In the meantime, please run the daemon if you want to use 'ipfs id':

    ipfs daemon &
    ipfs id QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
`

type IdOutput struct {
	ID              string
	PublicKey       string
	Addresses       []string
	AgentVersion    string
	ProtocolVersion string
}

var idCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Show IPFS Node ID info",
		ShortDescription: `
Prints out information about the specified peer,
if no peer is specified, prints out local peers info.
`,
	},
	Arguments: []cmds.Argument{
		cmds.StringArg("peerid", false, false, "peer.ID of node to look up"),
	},
	Run: func(req cmds.Request) (interface{}, error) {
		node, err := req.Context().GetNode()
		if err != nil {
			return nil, err
		}

		if len(req.Arguments()) == 0 {
			return printPeer(node.Identity)
		}

		pid := req.Arguments()[0]

		id := peer.ID(b58.Decode(pid))
		if len(id) == 0 {
			return nil, cmds.ClientError("Invalid peer id")
		}

		ctx, _ := context.WithTimeout(context.TODO(), time.Second*5)
		if node.Routing == nil {
			return nil, errors.New(offlineIdErrorMessage)
		}

		p, err := node.Routing.FindPeer(ctx, id)
		if err == kb.ErrLookupFailure {
			log.Error("what? no.")
			return nil, errors.New(offlineIdErrorMessage)
		}
		if err != nil {
			return nil, err
		}
		return printPeer(p)
	},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: func(res cmds.Response) ([]byte, error) {
			val, ok := res.Output().(*IdOutput)
			if !ok {
				return nil, u.ErrCast()
			}

			return json.MarshalIndent(val, "", "\t")
		},
	},
	Type: &IdOutput{},
}

func printPeer(p peer.Peer) (interface{}, error) {
	if p == nil {
		return nil, errors.New("Attempted to print nil peer!")
	}
	info := new(IdOutput)

	info.ID = p.ID().String()
	if p.PubKey() != nil {
		pkb, err := p.PubKey().Bytes()
		if err != nil {
			return nil, err
		}
		info.PublicKey = base64.StdEncoding.EncodeToString(pkb)
	}
	for _, a := range p.Addresses() {
		info.Addresses = append(info.Addresses, a.String())
	}

	agent, protocol := p.GetVersions()
	info.AgentVersion = agent
	info.ProtocolVersion = protocol

	return info, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2016 Crunchy Data Solutions, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

import (
	"github.com/crunchydata/crunchy-proxy/admin"
	"github.com/crunchydata/crunchy-proxy/config"
	"github.com/crunchydata/crunchy-proxy/proxy"
	"github.com/golang/glog"
	"os"
	"os/signal"
	"syscall"
)

func main() {
	//get the Config
	config.ReadConfig()

	glog.Infoln("main starting...")

	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
	go func() {
		sig := <-sigs
		glog.Infoln(sig)
		glog.Infoln("caught signal, cleaning up and exiting...")
		os.Exit(0)
	}()

	go admin.StartHealthcheck()
	config.Cfg.SetupAdapters()
	config.Cfg.PrintNodeInfo()

	go admin.Initialize()

	if config.Cfg.Pool.Enabled {
		proxy.SetupPools()
	}

	proxy.ListenAndServe()

}
<commit_msg>Minor whitespace update.<commit_after>/*
Copyright 2016 Crunchy Data Solutions, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

import (
	"github.com/crunchydata/crunchy-proxy/admin"
	"github.com/crunchydata/crunchy-proxy/config"
	"github.com/crunchydata/crunchy-proxy/proxy"
	"github.com/golang/glog"
	"os"
	"os/signal"
	"syscall"
)

func main() {
	//get the Config
	config.ReadConfig()

	glog.Infoln("main starting...")

	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
	go func() {
		sig := <-sigs
		glog.Infoln(sig)
		glog.Infoln("caught signal, cleaning up and exiting...")
		os.Exit(0)
	}()

	go admin.StartHealthcheck()

	config.Cfg.SetupAdapters()
	config.Cfg.PrintNodeInfo()

	go admin.Initialize()

	if config.Cfg.Pool.Enabled {
		proxy.SetupPools()
	}

	proxy.ListenAndServe()

}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"github.com/fatih/color"
	"gopkg.in/fsnotify.v1"
)

// some systems say `foo' and some say 'foo'
var prereqDebugLine = regexp.MustCompile(`Prerequisite .([^']+)' is (older|newer) than target .([^']+)'.`)

var watchFailedColor = color.New(color.FgMagenta, color.Bold)
var changeColor = color.New(color.FgYellow, color.Bold)
var makingColor = color.New(color.FgBlue, color.Bold)
var makeSucceededColor = color.New(color.FgGreen, color.Bold)
var makeFailedColor = color.New(color.FgRed, color.Bold)

type Harry struct {
	MakeArgs []string

	watcher *fsnotify.Watcher
}

func newHarry(makeArgs []string) *Harry {
	return &Harry{
		MakeArgs: makeArgs,
	}
}

func (harry *Harry) MakeMyDay() {
	for {
		shouldMake, err := harry.watchForRemake()
		if err != nil {
			watchFailedColor.Printf("failed to watch (%s); waiting 1s...\n", err)
			time.Sleep(time.Second)
			continue
		}

		if shouldMake {
			harry.remake()
		}

		harry.wait()
	}
}

func (harry *Harry) watchForRemake() (bool, error) {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return false, fmt.Errorf("failed to construct watcher: %s", err)
	}

	harry.watcher = watcher

	err = watcher.Add("Makefile")
	if err != nil {
		return false, fmt.Errorf("failed to watch Makefile for changes: %s", err)
	}

	detectArgs := []string{"--dry-run", "--debug=v", "--no-builtin-rules"}
	detect := exec.Command("make", append(detectArgs, harry.MakeArgs...)...)

	detectOut, err := detect.StdoutPipe()
	if err != nil {
		return false, fmt.Errorf("failed to construct stdout pipe: %s", err)
	}

	outBuf := bufio.NewReader(detectOut)

	err = detect.Start()
	if err != nil {
		return false, fmt.Errorf("failed spawning 'make' to determine prerequisites: %s", err)
	}

	shouldMake, err := harry.watchPrereqs(outBuf)
	if err != nil {
		return false, fmt.Errorf("failed to watch prerequisites: %s", err)
	}

	err = detect.Wait()
	if err != nil {
		return false, fmt.Errorf("failed to determine prerequisites: %s", err)
	}

	return shouldMake, nil
}

func (harry *Harry) remake() {
	makingColor.Printf("running make %s\n", strings.Join(harry.MakeArgs, " "))

	remake := exec.Command("make", harry.MakeArgs...)
	remake.Stdout = os.Stdout
	remake.Stderr = os.Stderr

	err := remake.Run()
	if err != nil {
		makeFailedColor.Println("make failed")
	} else {
		makeSucceededColor.Println("make succeeded")
	}
}

func (harry *Harry) wait() {
	defer harry.watcher.Close()

	for {
		select {
		case <-harry.watcher.Events:
			return
		case err := <-harry.watcher.Errors:
			watchFailedColor.Printf("encountered error while watching: %s\n", err)
		}
	}
}

func (harry *Harry) watchPrereqs(out *bufio.Reader) (bool, error) {
	var shouldMake bool

	watched := map[string]bool{}

	for {
		line, err := out.ReadString('\n')
		if err == io.EOF {
			return shouldMake, nil
		}

		if err != nil {
			return false, err
		}

		matches := prereqDebugLine.FindStringSubmatch(line)
		if matches == nil {
			continue
		}

		prereq := matches[1]

		if matches[2] == "newer" {
			changeColor.Printf("detected change in '%s'\n", prereq)
			shouldMake = true
		}

		parentDir := filepath.Dir(prereq)

		err = harry.watch(watched, parentDir)
		if err != nil {
			return false, err
		}
	}
}

func (harry *Harry) watch(watched map[string]bool, path string) error {
	if watched[path] {
		return nil
	}

	err := harry.watcher.Add(path)
	if err != nil {
		return err
	}

	watched[path] = true

	return nil
}
<commit_msg>prevent deadlock<commit_after>package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"github.com/fatih/color"
	"gopkg.in/fsnotify.v1"
)

// some systems say `foo' and some say 'foo'
var prereqDebugLine = regexp.MustCompile(`Prerequisite .([^']+)' is (older|newer) than target .([^']+)'.`)

var watchFailedColor = color.New(color.FgMagenta, color.Bold)
var changeColor = color.New(color.FgYellow, color.Bold)
var makingColor = color.New(color.FgBlue, color.Bold)
var makeSucceededColor = color.New(color.FgGreen, color.Bold)
var makeFailedColor = color.New(color.FgRed, color.Bold)

type Harry struct {
	MakeArgs []string

	watcher *fsnotify.Watcher
}

func newHarry(makeArgs []string) *Harry {
	return &Harry{
		MakeArgs: makeArgs,
	}
}

func (harry *Harry) MakeMyDay() {
	for {
		shouldMake, err := harry.watchForRemake()
		if err != nil {
			watchFailedColor.Printf("failed to watch (%s); waiting 1s...\n", err)
			time.Sleep(time.Second)
			continue
		}

		if shouldMake {
			harry.remake()
		}

		harry.wait()
	}
}

func (harry *Harry) watchForRemake() (bool, error) {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return false, fmt.Errorf("failed to construct watcher: %s", err)
	}

	harry.watcher = watcher

	err = watcher.Add("Makefile")
	if err != nil {
		return false, fmt.Errorf("failed to watch Makefile for changes: %s", err)
	}

	detectArgs := []string{"--dry-run", "--debug=v", "--no-builtin-rules"}
	detect := exec.Command("make", append(detectArgs, harry.MakeArgs...)...)

	detectOut, err := detect.StdoutPipe()
	if err != nil {
		return false, fmt.Errorf("failed to construct stdout pipe: %s", err)
	}

	outBuf := bufio.NewReader(detectOut)

	err = detect.Start()
	if err != nil {
		return false, fmt.Errorf("failed spawning 'make' to determine prerequisites: %s", err)
	}

	shouldMake, err := harry.watchPrereqs(outBuf)
	if err != nil {
		return false, fmt.Errorf("failed to watch prerequisites: %s", err)
	}

	err = detect.Wait()
	if err != nil {
		return false, fmt.Errorf("failed to determine prerequisites: %s", err)
	}

	return shouldMake, nil
}

func (harry *Harry) remake() {
	makingColor.Printf("running make %s\n", strings.Join(harry.MakeArgs, " "))

	remake := exec.Command("make", harry.MakeArgs...)
	remake.Stdout = os.Stdout
	remake.Stderr = os.Stderr

	err := remake.Run()
	if err != nil {
		makeFailedColor.Println("make failed")
	} else {
		makeSucceededColor.Println("make succeeded")
	}
}

func (harry *Harry) wait() {
	errs := harry.watcher.Errors

	for {
		select {
		case _, ok := <-harry.watcher.Events:
			if ok {
				// closing must be asynchronous to prevent deadlock
				go harry.watcher.Close()
			} else {
				return
			}

		case err, ok := <-errs:
			if ok {
				watchFailedColor.Printf("encountered error while watching: %s\n", err)
			} else {
				errs = nil
			}
		}
	}
}

func (harry *Harry) watchPrereqs(out *bufio.Reader) (bool, error) {
	var shouldMake bool

	watched := map[string]bool{}

	for {
		line, err := out.ReadString('\n')
		if err == io.EOF {
			return shouldMake, nil
		}

		if err != nil {
			return false, err
		}

		matches := prereqDebugLine.FindStringSubmatch(line)
		if matches == nil {
			continue
		}

		prereq := matches[1]

		if matches[2] == "newer" {
			changeColor.Printf("detected change in '%s'\n", prereq)
			shouldMake = true
		}

		parentDir := filepath.Dir(prereq)

		err = harry.watch(watched, parentDir)
		if err != nil {
			return false, err
		}
	}
}

func (harry *Harry) watch(watched map[string]bool, path string) error {
	if watched[path] {
		return nil
	}

	err := harry.watcher.Add(path)
	if err != nil {
		return err
	}

	watched[path] = true

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"github.com/fatih/color"
	"gopkg.in/fsnotify.v1"
)

var prereqDebugLine = regexp.MustCompile(`Prerequisite '([^']+)' is (older|newer) than target '([^']+)'.`)

var watchFailedColor = color.New(color.FgMagenta, color.Bold)
var changeColor = color.New(color.FgYellow, color.Bold)
var makingColor = color.New(color.FgBlue, color.Bold)
var makeSucceededColor = color.New(color.FgGreen, color.Bold)
var makeFailedColor = color.New(color.FgRed, color.Bold)

type Harry struct {
	MakeArgs []string

	watcher *fsnotify.Watcher
}

func newHarry(makeArgs []string) *Harry {
	return &Harry{
		MakeArgs: makeArgs,
	}
}

func (harry *Harry) MakeMyDay() {
	for {
		shouldMake, err := harry.watchForRemake()
		if err != nil {
			watchFailedColor.Printf("failed to watch (%s); waiting 1s...\n", err)
			time.Sleep(time.Second)
			continue
		}

		if shouldMake {
			harry.remake()
		}

		harry.wait()
	}
}

func (harry *Harry) watchForRemake() (bool, error) {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return false, fmt.Errorf("failed to construct watcher: %s", err)
	}

	harry.watcher = watcher

	err = watcher.Add("Makefile")
	if err != nil {
		return false, fmt.Errorf("failed to watch Makefile for changes: %s", err)
	}

	detectArgs := []string{"--dry-run", "--debug=v", "--no-builtin-rules"}
	detect := exec.Command("make", append(detectArgs, harry.MakeArgs...)...)

	detectOut, err := detect.StdoutPipe()
	if err != nil {
		return false, fmt.Errorf("failed to construct stdout pipe: %s", err)
	}

	outBuf := bufio.NewReader(detectOut)

	err = detect.Start()
	if err != nil {
		return false, fmt.Errorf("failed spawning 'make' to determine prerequisites: %s", err)
	}

	shouldMake, err := harry.watchPrereqs(outBuf)
	if err != nil {
		return false, fmt.Errorf("failed to watch prerequisites: %s", err)
	}

	err = detect.Wait()
	if err != nil {
		return false, fmt.Errorf("failed to determine prerequisites: %s", err)
	}

	return shouldMake, nil
}

func (harry *Harry) remake() {
	makingColor.Printf("running make %s\n", strings.Join(harry.MakeArgs, " "))

	remake := exec.Command("make", harry.MakeArgs...)
	remake.Stdout = os.Stdout
	remake.Stderr = os.Stderr

	err := remake.Run()
	if err != nil {
		makeFailedColor.Println("make failed")
	} else {
		makeSucceededColor.Println("make succeeded")
	}
}

func (harry *Harry) wait() {
	defer harry.watcher.Close()

	for {
		select {
		case <-harry.watcher.Events:
			return
		case err := <-harry.watcher.Errors:
			watchFailedColor.Printf("encountered error while watching: %s\n", err)
		}
	}
}

func (harry *Harry) watchPrereqs(out *bufio.Reader) (bool, error) {
	var shouldMake bool

	watched := map[string]bool{}

	for {
		line, err := out.ReadString('\n')
		if err == io.EOF {
			return shouldMake, nil
		}

		if err != nil {
			return false, err
		}

		matches := prereqDebugLine.FindStringSubmatch(line)
		if matches == nil {
			continue
		}

		prereq := matches[1]

		if matches[2] == "newer" {
			changeColor.Printf("detected change in '%s'\n", prereq)
			shouldMake = true
		}

		parentDir := filepath.Dir(prereq)

		err = harry.watch(watched, parentDir)
		if err != nil {
			return false, err
		}
	}
}

func (harry *Harry) watch(watched map[string]bool, path string) error {
	if watched[path] {
		return nil
	}

	err := harry.watcher.Add(path)
	if err != nil {
		return err
	}

	watched[path] = true

	return nil
}
<commit_msg>fix parsing BSD make output<commit_after>package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"github.com/fatih/color"
	"gopkg.in/fsnotify.v1"
)

// some systems say `foo' and some say 'foo'
var prereqDebugLine = regexp.MustCompile(`Prerequisite .([^']+)' is (older|newer) than target .([^']+)'.`)

var watchFailedColor = color.New(color.FgMagenta, color.Bold)
var changeColor = color.New(color.FgYellow, color.Bold)
var makingColor = color.New(color.FgBlue, color.Bold)
var makeSucceededColor = color.New(color.FgGreen, color.Bold)
var makeFailedColor = color.New(color.FgRed, color.Bold)

type Harry struct {
	MakeArgs []string

	watcher *fsnotify.Watcher
}

func newHarry(makeArgs []string) *Harry {
	return &Harry{
		MakeArgs: makeArgs,
	}
}

func (harry *Harry) MakeMyDay() {
	for {
		shouldMake, err := harry.watchForRemake()
		if err != nil {
			watchFailedColor.Printf("failed to watch (%s); waiting 1s...\n", err)
			time.Sleep(time.Second)
			continue
		}

		if shouldMake {
			harry.remake()
		}

		harry.wait()
	}
}

func (harry *Harry) watchForRemake() (bool, error) {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return false, fmt.Errorf("failed to construct watcher: %s", err)
	}

	harry.watcher = watcher

	err = watcher.Add("Makefile")
	if err != nil {
		return false, fmt.Errorf("failed to watch Makefile for changes: %s", err)
	}

	detectArgs := []string{"--dry-run", "--debug=v", "--no-builtin-rules"}
	detect := exec.Command("make", append(detectArgs, harry.MakeArgs...)...)

	detectOut, err := detect.StdoutPipe()
	if err != nil {
		return false, fmt.Errorf("failed to construct stdout pipe: %s", err)
	}

	outBuf := bufio.NewReader(detectOut)

	err = detect.Start()
	if err != nil {
		return false, fmt.Errorf("failed spawning 'make' to determine prerequisites: %s", err)
	}

	shouldMake, err := harry.watchPrereqs(outBuf)
	if err != nil {
		return false, fmt.Errorf("failed to watch prerequisites: %s", err)
	}

	err = detect.Wait()
	if err != nil {
		return false, fmt.Errorf("failed to determine prerequisites: %s", err)
	}

	return shouldMake, nil
}

func (harry *Harry) remake() {
	makingColor.Printf("running make %s\n", strings.Join(harry.MakeArgs, " "))

	remake := exec.Command("make", harry.MakeArgs...)
	remake.Stdout = os.Stdout
	remake.Stderr = os.Stderr

	err := remake.Run()
	if err != nil {
		makeFailedColor.Println("make failed")
	} else {
		makeSucceededColor.Println("make succeeded")
	}
}

func (harry *Harry) wait() {
	defer harry.watcher.Close()

	for {
		select {
		case <-harry.watcher.Events:
			return
		case err := <-harry.watcher.Errors:
			watchFailedColor.Printf("encountered error while watching: %s\n", err)
		}
	}
}

func (harry *Harry) watchPrereqs(out *bufio.Reader) (bool, error) {
	var shouldMake bool

	watched := map[string]bool{}

	for {
		line, err := out.ReadString('\n')
		if err == io.EOF {
			return shouldMake, nil
		}

		if err != nil {
			return false, err
		}

		matches := prereqDebugLine.FindStringSubmatch(line)
		if matches == nil {
			continue
		}

		prereq := matches[1]

		if matches[2] == "newer" {
			changeColor.Printf("detected change in '%s'\n", prereq)
			shouldMake = true
		}

		parentDir := filepath.Dir(prereq)

		err = harry.watch(watched, parentDir)
		if err != nil {
			return false, err
		}
	}
}

func (harry *Harry) watch(watched map[string]bool, path string) error {
	if watched[path] {
		return nil
	}

	err := harry.watcher.Add(path)
	if err != nil {
		return err
	}

	watched[path] = true

	return nil
}
<|endoftext|>


<commit_before>package hb

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
)

const (
	defaultBaseURL = "http://hummingbird.me/"
)

type auth struct {
	Username string `json:"username"`
	Email    string `json:"email"`
	Password string `json:"password"`
}

// Client manages communication with the Hummingbird API.
type Client struct {
	client *http.Client

	BaseURL *url.URL

	User  *UserService
	Anime *AnimeService
}

// NewClient returns a new Hummingbird API client.
func NewClient(httpClient *http.Client) *Client {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}
	baseURL, _ := url.Parse(defaultBaseURL)

	c := &Client{client: httpClient, BaseURL: baseURL}

	c.User = &UserService{client: c}
	c.Anime = &AnimeService{client: c}
	return c
}

// NewRequest creates an API request. A relative URL can be provided in urlStr,
// in which case it is resolved relative to the BaseURL of the Client.
// Relative URLs should always be specified without a preceding slash. If body
// is passed as an argument, then it will be encoded to JSON and used as the
// request body.
func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) {
	url, err := url.Parse(urlStr)
	if err != nil {
		return nil, err
	}

	u := c.BaseURL.ResolveReference(url)

	var buf io.ReadWriter
	if body != nil {
		buf = new(bytes.Buffer)
		err := json.NewEncoder(buf).Encode(body)
		if err != nil {
			return nil, fmt.Errorf("cannot encode body: %v", err)
		}
	}

	req, err := http.NewRequest(method, u.String(), buf)
	if err != nil {
		return nil, err
	}

	req.Header.Add("Content-Type", "application/json")

	return req, nil
}

// Do sends an API request and returns the API response. If an API error has
// occurred both the response and the error will be returned in case the caller
// wishes to further inspect the response. If v is passed as an argument, then
// the API response is JSON decoded and stored to v.
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	err = checkResponse(resp)
	if err != nil {
		return resp, err
	}

	if v != nil {
		err = json.NewDecoder(resp.Body).Decode(v)
	}
	return resp, err
}

// checkResponse checks the API response for errors. A response is considered an
// error if it has status code outside the 200 range. API error responses are
// expected to have a JSON response body that maps to ErrorResponse. Other
// response bodies are ignored.
func checkResponse(r *http.Response) error {
	if c := r.StatusCode; 200 <= c && c <= 299 {
		return nil
	}
	errorResponse := &ErrorResponse{Response: r}
	body, err := ioutil.ReadAll(r.Body)
	if err == nil && body != nil {
		json.Unmarshal(body, errorResponse)
	}
	return errorResponse
}

// ErrorResponse represents a Hummingbird API error response.
type ErrorResponse struct {
	Response *http.Response
	Message  string `json:"error"`
}

func (r *ErrorResponse) Error() string {
	return fmt.Sprintf("%v %v: %v %v", r.Response.Request.Method, r.Response.Request.URL,
		r.Response.StatusCode, r.Message)
}
<commit_msg>change default base URL to use https<commit_after>package hb

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
)

const (
	defaultBaseURL = "https://hummingbird.me/"
)

type auth struct {
	Username string `json:"username"`
	Email    string `json:"email"`
	Password string `json:"password"`
}

// Client manages communication with the Hummingbird API.
type Client struct {
	client *http.Client

	BaseURL *url.URL

	User  *UserService
	Anime *AnimeService
}

// NewClient returns a new Hummingbird API client.
func NewClient(httpClient *http.Client) *Client {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}
	baseURL, _ := url.Parse(defaultBaseURL)

	c := &Client{client: httpClient, BaseURL: baseURL}

	c.User = &UserService{client: c}
	c.Anime = &AnimeService{client: c}
	return c
}

// NewRequest creates an API request. A relative URL can be provided in urlStr,
// in which case it is resolved relative to the BaseURL of the Client.
// Relative URLs should always be specified without a preceding slash. If body
// is passed as an argument, then it will be encoded to JSON and used as the
// request body.
func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) {
	url, err := url.Parse(urlStr)
	if err != nil {
		return nil, err
	}

	u := c.BaseURL.ResolveReference(url)

	var buf io.ReadWriter
	if body != nil {
		buf = new(bytes.Buffer)
		err := json.NewEncoder(buf).Encode(body)
		if err != nil {
			return nil, fmt.Errorf("cannot encode body: %v", err)
		}
	}

	req, err := http.NewRequest(method, u.String(), buf)
	if err != nil {
		return nil, err
	}

	req.Header.Add("Content-Type", "application/json")

	return req, nil
}

// Do sends an API request and returns the API response. If an API error has
// occurred both the response and the error will be returned in case the caller
// wishes to further inspect the response. If v is passed as an argument, then
// the API response is JSON decoded and stored to v.
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	err = checkResponse(resp)
	if err != nil {
		return resp, err
	}

	if v != nil {
		err = json.NewDecoder(resp.Body).Decode(v)
	}
	return resp, err
}

// checkResponse checks the API response for errors. A response is considered an
// error if it has status code outside the 200 range. API error responses are
// expected to have a JSON response body that maps to ErrorResponse. Other
// response bodies are ignored.
func checkResponse(r *http.Response) error {
	if c := r.StatusCode; 200 <= c && c <= 299 {
		return nil
	}
	errorResponse := &ErrorResponse{Response: r}
	body, err := ioutil.ReadAll(r.Body)
	if err == nil && body != nil {
		json.Unmarshal(body, errorResponse)
	}
	return errorResponse
}

// ErrorResponse represents a Hummingbird API error response.
type ErrorResponse struct {
	Response *http.Response
	Message  string `json:"error"`
}

func (r *ErrorResponse) Error() string {
	return fmt.Sprintf("%v %v: %v %v", r.Response.Request.Method, r.Response.Request.URL,
		r.Response.StatusCode, r.Message)
}
<|endoftext|>


<commit_before>package main

import "fmt"

<<<<<<< HEAD
 func main() {
   fmt.Println("Hello")
+	fmt.Println("bye forever")
+ fmt.Println("Whoops, I'm back!")
 }
=======
func main() {
	fmt.Println("Hello")
	fmt.Println("Is it me you're looking for?")
	fmt.Println("bye forever")
}
>>>>>>> origin/master
<commit_msg>yolo-endringer<commit_after>package main

import "fmt"

 func main() {
   fmt.Println("Hello")
fmt.Println("bye forever")
fmt.Println("Whoops, I'm back!")

	fmt.Println("Hello")
	fmt.Println("Is it me you're looking for?")
	fmt.Println("bye forever")
}
<|endoftext|>


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

package docker

import (
	"encoding/json"
	"errors"
	"github.com/dotcloud/docker"
	"io"
	"net/http"
)

// Error returned when the image does not exist.
var ErrNoSuchImage = errors.New("No such image")

// ListImages returns the list of available images in the server.
//
// See http://goo.gl/5ZfHk for more details.
func (c *Client) ListImages(all bool) ([]docker.APIImages, error) {
	path := "/images/json?all="
	if all {
		path += "1"
	} else {
		path += "0"
	}
	body, _, err := c.do("GET", path, nil)
	if err != nil {
		return nil, err
	}
	var images []docker.APIImages
	err = json.Unmarshal(body, &images)
	if err != nil {
		return nil, err
	}
	return images, nil
}

// RemoveImage removes an image by its name or ID.
//
// See http://goo.gl/J2FNF for more details.
func (c *Client) RemoveImage(name string) error {
	_, status, err := c.do("DELETE", "/images/"+name, nil)
	if status == http.StatusNotFound {
		return ErrNoSuchImage
	}
	return err
}

// InspectImage returns an image by its name or ID.
//
// See http://goo.gl/dqGQO for more details.
func (c *Client) InspectImage(name string) (*docker.Image, error) {
	body, status, err := c.do("GET", "/images/"+name+"/json", nil)
	if status == http.StatusNotFound {
		return nil, ErrNoSuchImage
	}
	if err != nil {
		return nil, err
	}
	var image docker.Image
	err = json.Unmarshal(body, &image)
	if err != nil {
		return nil, err
	}
	return &image, nil
}

// PushImageOptions options to use in the PushImage method.
type PushImageOptions struct {
	// Name or ID of the image
	Name string

	// Registry server to push the image
	Registry string
}

// PushImage pushes an image to a remote registry, logging progress to w.
//
// See http://goo.gl/Hx3CB for more details.
func (c *Client) PushImage(opts PushImageOptions, w io.Writer) error {
	if opts.Name == "" {
		return ErrNoSuchImage
	}
	name := opts.Name
	opts.Name = ""
	path := "/images/" + name + "/push?" + queryString(&opts)
	return c.stream("POST", path, nil, w)
}

// PullImageOptions present the set of options available for pulling an image
// from a registry.
//
// See http://goo.gl/JSltN for more details.
type PullImageOptions struct {
	Repository string `qs:"fromImage"`
	Registry   string
}

// PullImage pulls an image from a remote registry, logging progress to w.
//
// See http://goo.gl/JSltN for more details.
func (c *Client) PullImage(opts PullImageOptions, w io.Writer) error {
	if opts.Repository == "" {
		return ErrNoSuchImage
	}
	path := "/images/create?" + queryString(&opts)
	return c.stream("POST", path, nil, w)
}
<commit_msg>image: fix documentation<commit_after>// Copyright 2013 Francisco Souza. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package docker

import (
	"encoding/json"
	"errors"
	"github.com/dotcloud/docker"
	"io"
	"net/http"
)

// Error returned when the image does not exist.
var ErrNoSuchImage = errors.New("No such image")

// ListImages returns the list of available images in the server.
//
// See http://goo.gl/5ZfHk for more details.
func (c *Client) ListImages(all bool) ([]docker.APIImages, error) {
	path := "/images/json?all="
	if all {
		path += "1"
	} else {
		path += "0"
	}
	body, _, err := c.do("GET", path, nil)
	if err != nil {
		return nil, err
	}
	var images []docker.APIImages
	err = json.Unmarshal(body, &images)
	if err != nil {
		return nil, err
	}
	return images, nil
}

// RemoveImage removes an image by its name or ID.
//
// See http://goo.gl/J2FNF for more details.
func (c *Client) RemoveImage(name string) error {
	_, status, err := c.do("DELETE", "/images/"+name, nil)
	if status == http.StatusNotFound {
		return ErrNoSuchImage
	}
	return err
}

// InspectImage returns an image by its name or ID.
//
// See http://goo.gl/dqGQO for more details.
func (c *Client) InspectImage(name string) (*docker.Image, error) {
	body, status, err := c.do("GET", "/images/"+name+"/json", nil)
	if status == http.StatusNotFound {
		return nil, ErrNoSuchImage
	}
	if err != nil {
		return nil, err
	}
	var image docker.Image
	err = json.Unmarshal(body, &image)
	if err != nil {
		return nil, err
	}
	return &image, nil
}

// PushImageOptions options to use in the PushImage method.
type PushImageOptions struct {
	// Name of the image
	Name string

	// Registry server to push the image
	Registry string
}

// PushImage pushes an image to a remote registry, logging progress to w.
//
// See http://goo.gl/Hx3CB for more details.
func (c *Client) PushImage(opts PushImageOptions, w io.Writer) error {
	if opts.Name == "" {
		return ErrNoSuchImage
	}
	name := opts.Name
	opts.Name = ""
	path := "/images/" + name + "/push?" + queryString(&opts)
	return c.stream("POST", path, nil, w)
}

// PullImageOptions present the set of options available for pulling an image
// from a registry.
//
// See http://goo.gl/JSltN for more details.
type PullImageOptions struct {
	Repository string `qs:"fromImage"`
	Registry   string
}

// PullImage pulls an image from a remote registry, logging progress to w.
//
// See http://goo.gl/JSltN for more details.
func (c *Client) PullImage(opts PullImageOptions, w io.Writer) error {
	if opts.Repository == "" {
		return ErrNoSuchImage
	}
	path := "/images/create?" + queryString(&opts)
	return c.stream("POST", path, nil, w)
}
<|endoftext|>


<commit_before>// Copyright 2014 Hajime Hoshi
//
// 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 ebiten

import (
	"errors"
	"fmt"
	"image"
	"image/color"
	"runtime"
	"sync"

	"github.com/hajimehoshi/ebiten/internal/graphics"
	"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
)

var imageM sync.Mutex

var (
	imageCommandQueue = []func() error{}
)

func execBufferedImageCommands() error {
	imageM.Lock()
	defer imageM.Unlock()
	for _, f := range imageCommandQueue {
		if err := f(); err != nil {
			return err
		}
	}
	imageCommandQueue = nil
	return nil
}

// Image represents an image.
// The pixel format is alpha-premultiplied.
// Image implements image.Image.
type Image struct {
	framebuffer *graphics.Framebuffer
	texture     *graphics.Texture
	disposed    bool
	pixels      []uint8
	width       int
	height      int
}

// Size returns the size of the image.
//
// This function is concurrent-safe.
func (i *Image) Size() (width, height int) {
	return i.width, i.height
}

// Clear resets the pixels of the image into 0.
//
// This function is concurrent-safe.
func (i *Image) Clear() (err error) {
	imageM.Lock()
	defer imageM.Unlock()
	return i.clear()
}

func (i *Image) clear() (err error) {
	return i.fill(color.Transparent)
}

// Fill fills the image with a solid color.
//
// This function is concurrent-safe.
func (i *Image) Fill(clr color.Color) (err error) {
	imageM.Lock()
	defer imageM.Unlock()
	return i.fill(clr)
}

func (i *Image) fill(clr color.Color) (err error) {
	f := func() error {
		if i.isDisposed() {
			return errors.New("ebiten: image is already disposed")
		}
		i.pixels = nil
		return i.framebuffer.Fill(glContext, clr)
	}
	if imageCommandQueue != nil {
		imageCommandQueue = append(imageCommandQueue, f)
		return
	}
	return f()

}

// DrawImage draws the given image on the receiver image.
//
// This method accepts the options.
// The parts of the given image at the parts of the destination.
// After determining parts to draw, this applies the geometry matrix and the color matrix.
//
// Here are the default values:
//     ImageParts:    (0, 0) - (source width, source height) to (0, 0) - (source width, source height)
//                    (i.e. the whole source image)
//     GeoM:          Identity matrix
//     ColorM:        Identity matrix (that changes no colors)
//     CompositeMode: CompositeModeSourceOver (regular alpha blending)
//
// Be careful that this method is potentially slow.
// It would be better if you could call this method fewer times.
//
// This function is concurrent-safe.
func (i *Image) DrawImage(image *Image, options *DrawImageOptions) (err error) {
	// Calculate vertices before locking because the user can do anything in
	// options.ImageParts interface without deadlock (e.g. Call Image functions).
	if options == nil {
		options = &DrawImageOptions{}
	}
	parts := options.ImageParts
	if parts == nil {
		// Check options.Parts for backward-compatibility.
		dparts := options.Parts
		if dparts != nil {
			parts = imageParts(dparts)
		} else {
			parts = &wholeImage{image.width, image.height}
		}
	}
	quads := &textureQuads{parts: parts, width: image.width, height: image.height}
	// TODO: Reuse one vertices instead of making here, but this would need locking.
	vertices := make([]int16, parts.Len()*16)
	n := quads.vertices(vertices)
	if n == 0 {
		return nil
	}

	imageM.Lock()
	defer imageM.Unlock()
	if i == image {
		return errors.New("ebiten: Image.DrawImage: image should be different from the receiver")
	}
	f := func() error {
		if i.isDisposed() {
			return errors.New("ebiten: image is already disposed")
		}
		i.pixels = nil
		m := opengl.CompositeMode(options.CompositeMode)
		return i.framebuffer.DrawTexture(glContext, image.texture, vertices[:16*n], &options.GeoM, &options.ColorM, m)
	}
	if imageCommandQueue != nil {
		imageCommandQueue = append(imageCommandQueue, f)
		return nil
	}
	return f()
}

// Bounds returns the bounds of the image.
//
// This function is concurrent-safe.
func (i *Image) Bounds() image.Rectangle {
	return image.Rect(0, 0, i.width, i.height)
}

// ColorModel returns the color model of the image.
//
// This function is concurrent-safe.
func (i *Image) ColorModel() color.Model {
	return color.RGBAModel
}

// At returns the color of the image at (x, y).
//
// This method loads pixels from VRAM to system memory if necessary.
//
// This method can't be called before the main loop (ebiten.Run) starts (as of version 1.4.0-alpha).
//
// This function is concurrent-safe.
func (i *Image) At(x, y int) color.Color {
	// TODO: What if At is called internaly (like from image parts?)
	imageM.Lock()
	defer imageM.Unlock()
	if imageCommandQueue != nil {
		panic("ebiten: At can't be called when the GL context is not initialized")
	}
	if i.isDisposed() {
		return color.Transparent
	}
	if i.pixels == nil {
		var err error
		i.pixels, err = i.framebuffer.Pixels(glContext)
		if err != nil {
			panic(err)
		}
	}
	w := int(graphics.NextPowerOf2Int32(int32(i.width)))
	idx := 4*x + 4*y*w
	r, g, b, a := i.pixels[idx], i.pixels[idx+1], i.pixels[idx+2], i.pixels[idx+3]
	return color.RGBA{r, g, b, a}
}

// Dispose disposes the image data. After disposing, the image becomes invalid.
// This is useful to save memory.
//
// The behavior of any functions for a disposed image is undefined.
//
// This function is concurrent-safe.
func (i *Image) Dispose() error {
	imageM.Lock()
	defer imageM.Unlock()
	f := func() error {
		if i.isDisposed() {
			return errors.New("ebiten: image is already disposed")
		}
		if i.framebuffer != nil {
			if err := i.framebuffer.Dispose(glContext); err != nil {
				return err
			}
			i.framebuffer = nil
		}
		if i.texture != nil {
			if err := i.texture.Dispose(glContext); err != nil {
				return err
			}
			i.texture = nil
		}
		i.disposed = true
		i.pixels = nil
		runtime.SetFinalizer(i, nil)
		return nil
	}
	if imageCommandQueue != nil {
		imageCommandQueue = append(imageCommandQueue, f)
		return nil
	}
	return f()
}

func (i *Image) isDisposed() bool {
	return i.disposed
}

// ReplacePixels replaces the pixels of the image with p.
//
// The given p must represent RGBA pre-multiplied alpha values. len(p) must equal to 4 * (image width) * (image height).
//
// This function may be slow (as for implementation, this calls glTexSubImage2D).
//
// This function is concurrent-safe.
func (i *Image) ReplacePixels(p []uint8) error {
	imageM.Lock()
	defer imageM.Unlock()
	if l := 4 * i.width * i.height; len(p) != l {
		return fmt.Errorf("ebiten: p's length must be %d", l)
	}
	f := func() error {
		// Don't set i.pixels here because i.pixels is used not every time.
		i.pixels = nil
		if i.isDisposed() {
			return errors.New("ebiten: image is already disposed")
		}
		return i.framebuffer.ReplacePixels(glContext, i.texture, p)
	}
	if imageCommandQueue != nil {
		imageCommandQueue = append(imageCommandQueue, f)
		return nil
	}
	return f()
}

// A DrawImageOptions represents options to render an image on an image.
type DrawImageOptions struct {
	ImageParts    ImageParts
	GeoM          GeoM
	ColorM        ColorM
	CompositeMode CompositeMode

	// Deprecated (as of 1.1.0-alpha): Use ImageParts instead.
	Parts []ImagePart
}

// NewImage returns an empty image.
//
// NewImage generates a new texture and a new framebuffer.
// Be careful that image objects will never be released
// even though nothing refers the image object and GC works.
// It is because there is no way to define finalizers for Go objects if you use GopherJS.
//
// This function is concurrent-safe.
func NewImage(width, height int, filter Filter) (*Image, error) {
	imageM.Lock()
	defer imageM.Unlock()
	image := &Image{
		width:  width,
		height: height,
	}
	f := func() error {
		texture, err := graphics.NewTexture(glContext, width, height, glFilter(glContext, filter))
		if err != nil {
			return err
		}
		framebuffer, err := graphics.NewFramebufferFromTexture(glContext, texture)
		if err != nil {
			// TODO: texture should be removed here?
			return err
		}
		image.framebuffer = framebuffer
		image.texture = texture
		runtime.SetFinalizer(image, (*Image).Dispose)
		if err := image.framebuffer.Fill(glContext, color.Transparent); err != nil {
			return err
		}
		return nil
	}
	if imageCommandQueue != nil {
		imageCommandQueue = append(imageCommandQueue, f)
		return image, nil
	}
	if err := f(); err != nil {
		return nil, err
	}
	return image, nil
}

// NewImageFromImage creates a new image with the given image (img).
//
// NewImageFromImage generates a new texture and a new framebuffer.
// Be careful that image objects will never be released
// even though nothing refers the image object and GC works.
// It is because there is no way to define finalizers for Go objects if you use GopherJS.
//
// This function is concurrent-safe.
func NewImageFromImage(img image.Image, filter Filter) (*Image, error) {
	imageM.Lock()
	defer imageM.Unlock()
	size := img.Bounds().Size()
	w, h := size.X, size.Y
	image := &Image{
		width:  w,
		height: h,
	}
	f := func() error {
		texture, err := graphics.NewTextureFromImage(glContext, img, glFilter(glContext, filter))
		if err != nil {
			return err
		}
		framebuffer, err := graphics.NewFramebufferFromTexture(glContext, texture)
		if err != nil {
			// TODO: texture should be removed here?
			return err
		}
		image.framebuffer = framebuffer
		image.texture = texture
		runtime.SetFinalizer(image, (*Image).Dispose)
		return nil
	}
	if imageCommandQueue != nil {
		imageCommandQueue = append(imageCommandQueue, f)
		return image, nil
	}
	if err := f(); err != nil {
		return nil, err
	}
	return image, nil
}
<commit_msg>graphics: Kinder panic messages<commit_after>// Copyright 2014 Hajime Hoshi
//
// 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 ebiten

import (
	"errors"
	"fmt"
	"image"
	"image/color"
	"runtime"
	"sync"

	"github.com/hajimehoshi/ebiten/internal/graphics"
	"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
)

var imageM sync.Mutex

var (
	imageCommandQueue = []func() error{}
)

func execBufferedImageCommands() error {
	imageM.Lock()
	defer imageM.Unlock()
	for _, f := range imageCommandQueue {
		if err := f(); err != nil {
			return err
		}
	}
	imageCommandQueue = nil
	return nil
}

// Image represents an image.
// The pixel format is alpha-premultiplied.
// Image implements image.Image.
type Image struct {
	framebuffer *graphics.Framebuffer
	texture     *graphics.Texture
	disposed    bool
	pixels      []uint8
	width       int
	height      int
}

// Size returns the size of the image.
//
// This function is concurrent-safe.
func (i *Image) Size() (width, height int) {
	return i.width, i.height
}

// Clear resets the pixels of the image into 0.
//
// This function is concurrent-safe.
func (i *Image) Clear() (err error) {
	imageM.Lock()
	defer imageM.Unlock()
	return i.clear()
}

func (i *Image) clear() (err error) {
	return i.fill(color.Transparent)
}

// Fill fills the image with a solid color.
//
// This function is concurrent-safe.
func (i *Image) Fill(clr color.Color) (err error) {
	imageM.Lock()
	defer imageM.Unlock()
	return i.fill(clr)
}

func (i *Image) fill(clr color.Color) (err error) {
	f := func() error {
		if i.isDisposed() {
			return errors.New("ebiten: image is already disposed")
		}
		i.pixels = nil
		return i.framebuffer.Fill(glContext, clr)
	}
	if imageCommandQueue != nil {
		imageCommandQueue = append(imageCommandQueue, f)
		return
	}
	return f()

}

// DrawImage draws the given image on the receiver image.
//
// This method accepts the options.
// The parts of the given image at the parts of the destination.
// After determining parts to draw, this applies the geometry matrix and the color matrix.
//
// Here are the default values:
//     ImageParts:    (0, 0) - (source width, source height) to (0, 0) - (source width, source height)
//                    (i.e. the whole source image)
//     GeoM:          Identity matrix
//     ColorM:        Identity matrix (that changes no colors)
//     CompositeMode: CompositeModeSourceOver (regular alpha blending)
//
// Be careful that this method is potentially slow.
// It would be better if you could call this method fewer times.
//
// This function is concurrent-safe.
func (i *Image) DrawImage(image *Image, options *DrawImageOptions) (err error) {
	// Calculate vertices before locking because the user can do anything in
	// options.ImageParts interface without deadlock (e.g. Call Image functions).
	if options == nil {
		options = &DrawImageOptions{}
	}
	parts := options.ImageParts
	if parts == nil {
		// Check options.Parts for backward-compatibility.
		dparts := options.Parts
		if dparts != nil {
			parts = imageParts(dparts)
		} else {
			parts = &wholeImage{image.width, image.height}
		}
	}
	quads := &textureQuads{parts: parts, width: image.width, height: image.height}
	// TODO: Reuse one vertices instead of making here, but this would need locking.
	vertices := make([]int16, parts.Len()*16)
	n := quads.vertices(vertices)
	if n == 0 {
		return nil
	}

	imageM.Lock()
	defer imageM.Unlock()
	if i == image {
		return errors.New("ebiten: Image.DrawImage: image should be different from the receiver")
	}
	f := func() error {
		if i.isDisposed() {
			return errors.New("ebiten: image is already disposed")
		}
		i.pixels = nil
		m := opengl.CompositeMode(options.CompositeMode)
		return i.framebuffer.DrawTexture(glContext, image.texture, vertices[:16*n], &options.GeoM, &options.ColorM, m)
	}
	if imageCommandQueue != nil {
		imageCommandQueue = append(imageCommandQueue, f)
		return nil
	}
	return f()
}

// Bounds returns the bounds of the image.
//
// This function is concurrent-safe.
func (i *Image) Bounds() image.Rectangle {
	return image.Rect(0, 0, i.width, i.height)
}

// ColorModel returns the color model of the image.
//
// This function is concurrent-safe.
func (i *Image) ColorModel() color.Model {
	return color.RGBAModel
}

// At returns the color of the image at (x, y).
//
// This method loads pixels from VRAM to system memory if necessary.
//
// This method can't be called before the main loop (ebiten.Run) starts (as of version 1.4.0-alpha).
//
// This function is concurrent-safe.
func (i *Image) At(x, y int) color.Color {
	// TODO: What if At is called internaly (like from image parts?)
	imageM.Lock()
	defer imageM.Unlock()
	if imageCommandQueue != nil {
		panic("ebiten: At can't be called when the GL context is not initialized (this panic happens as of version 1.4.0-alpha)")
	}
	if i.isDisposed() {
		return color.Transparent
	}
	if i.pixels == nil {
		var err error
		i.pixels, err = i.framebuffer.Pixels(glContext)
		if err != nil {
			panic(err)
		}
	}
	w := int(graphics.NextPowerOf2Int32(int32(i.width)))
	idx := 4*x + 4*y*w
	r, g, b, a := i.pixels[idx], i.pixels[idx+1], i.pixels[idx+2], i.pixels[idx+3]
	return color.RGBA{r, g, b, a}
}

// Dispose disposes the image data. After disposing, the image becomes invalid.
// This is useful to save memory.
//
// The behavior of any functions for a disposed image is undefined.
//
// This function is concurrent-safe.
func (i *Image) Dispose() error {
	imageM.Lock()
	defer imageM.Unlock()
	f := func() error {
		if i.isDisposed() {
			return errors.New("ebiten: image is already disposed")
		}
		if i.framebuffer != nil {
			if err := i.framebuffer.Dispose(glContext); err != nil {
				return err
			}
			i.framebuffer = nil
		}
		if i.texture != nil {
			if err := i.texture.Dispose(glContext); err != nil {
				return err
			}
			i.texture = nil
		}
		i.disposed = true
		i.pixels = nil
		runtime.SetFinalizer(i, nil)
		return nil
	}
	if imageCommandQueue != nil {
		imageCommandQueue = append(imageCommandQueue, f)
		return nil
	}
	return f()
}

func (i *Image) isDisposed() bool {
	return i.disposed
}

// ReplacePixels replaces the pixels of the image with p.
//
// The given p must represent RGBA pre-multiplied alpha values. len(p) must equal to 4 * (image width) * (image height).
//
// This function may be slow (as for implementation, this calls glTexSubImage2D).
//
// This function is concurrent-safe.
func (i *Image) ReplacePixels(p []uint8) error {
	imageM.Lock()
	defer imageM.Unlock()
	if l := 4 * i.width * i.height; len(p) != l {
		return fmt.Errorf("ebiten: p's length must be %d", l)
	}
	f := func() error {
		// Don't set i.pixels here because i.pixels is used not every time.
		i.pixels = nil
		if i.isDisposed() {
			return errors.New("ebiten: image is already disposed")
		}
		return i.framebuffer.ReplacePixels(glContext, i.texture, p)
	}
	if imageCommandQueue != nil {
		imageCommandQueue = append(imageCommandQueue, f)
		return nil
	}
	return f()
}

// A DrawImageOptions represents options to render an image on an image.
type DrawImageOptions struct {
	ImageParts    ImageParts
	GeoM          GeoM
	ColorM        ColorM
	CompositeMode CompositeMode

	// Deprecated (as of 1.1.0-alpha): Use ImageParts instead.
	Parts []ImagePart
}

// NewImage returns an empty image.
//
// NewImage generates a new texture and a new framebuffer.
// Be careful that image objects will never be released
// even though nothing refers the image object and GC works.
// It is because there is no way to define finalizers for Go objects if you use GopherJS.
//
// This function is concurrent-safe.
func NewImage(width, height int, filter Filter) (*Image, error) {
	imageM.Lock()
	defer imageM.Unlock()
	image := &Image{
		width:  width,
		height: height,
	}
	f := func() error {
		texture, err := graphics.NewTexture(glContext, width, height, glFilter(glContext, filter))
		if err != nil {
			return err
		}
		framebuffer, err := graphics.NewFramebufferFromTexture(glContext, texture)
		if err != nil {
			// TODO: texture should be removed here?
			return err
		}
		image.framebuffer = framebuffer
		image.texture = texture
		runtime.SetFinalizer(image, (*Image).Dispose)
		if err := image.framebuffer.Fill(glContext, color.Transparent); err != nil {
			return err
		}
		return nil
	}
	if imageCommandQueue != nil {
		imageCommandQueue = append(imageCommandQueue, f)
		return image, nil
	}
	if err := f(); err != nil {
		return nil, err
	}
	return image, nil
}

// NewImageFromImage creates a new image with the given image (img).
//
// NewImageFromImage generates a new texture and a new framebuffer.
// Be careful that image objects will never be released
// even though nothing refers the image object and GC works.
// It is because there is no way to define finalizers for Go objects if you use GopherJS.
//
// This function is concurrent-safe.
func NewImageFromImage(img image.Image, filter Filter) (*Image, error) {
	imageM.Lock()
	defer imageM.Unlock()
	size := img.Bounds().Size()
	w, h := size.X, size.Y
	image := &Image{
		width:  w,
		height: h,
	}
	f := func() error {
		texture, err := graphics.NewTextureFromImage(glContext, img, glFilter(glContext, filter))
		if err != nil {
			return err
		}
		framebuffer, err := graphics.NewFramebufferFromTexture(glContext, texture)
		if err != nil {
			// TODO: texture should be removed here?
			return err
		}
		image.framebuffer = framebuffer
		image.texture = texture
		runtime.SetFinalizer(image, (*Image).Dispose)
		return nil
	}
	if imageCommandQueue != nil {
		imageCommandQueue = append(imageCommandQueue, f)
		return image, nil
	}
	if err := f(); err != nil {
		return nil, err
	}
	return image, nil
}
<|endoftext|>


<commit_before>package signals

import (
	"image"
	"image/color"
	"image/color/palette"
)

// Depiction of a Signal, implements Depictor
type Depiction struct {
	Signal
	size                     image.Rectangle
	pixelsPerUnitX           int
	belowColour, aboveColour color.Color
}

// makes a Depiction of a LimitedSignal, scaled to pxMaxx x pxMaxy pixels and sets its colours.
func NewDepiction(s LimitedSignal, pxMaxX, pxMaxY int, c1, c2 color.Color) Depiction {
	return Depiction{s, image.Rect(0, -pxMaxY/2, pxMaxX, pxMaxY/2), int(int64(pxMaxX) * int64(unitX) / int64(s.MaxX())), c1, c2}
}

func (i Depiction) Bounds() image.Rectangle {
	return i.size
}

func (i Depiction) At(xp, yp int) color.Color {
	if i.property(x(xp)*unitX/x(i.pixelsPerUnitX)-x(i.size.Min.X)) <= unitY/y(i.size.Max.Y)*y(yp)-y(i.size.Min.Y) {
		return i.aboveColour
	}
	return i.belowColour
}

// a Depictor is an image.Image without a colormodel, so is more general.
// embedded in one of the helper wrappers gets you an image.Image.
// (this and the wrappers might be moved, in a later version of this package, to their own package.)
type Depictor interface {
	Bounds() image.Rectangle
	At(x, y int) color.Color
}

// RGBA depiction wrapper
type RGBAImage struct {
	Depictor
}

func (i RGBAImage) ColorModel() color.Model { return color.RGBAModel }

// gray depiction wrapper.
type GrayImage struct {
	Depictor
}

func (i GrayImage) ColorModel() color.Model { return color.GrayModel }

// plan9 paletted, depiction wrapper.
type Plan9PalettedImage struct {
	Depictor
}

func (i Plan9PalettedImage) ColorModel() color.Model { return color.Palette(palette.Plan9) }

// WebSafe paletted, depiction wrapper.
type WebSafePalettedImage struct {
	Depictor
}

func (i WebSafePalettedImage) ColorModel() color.Model { return color.Palette(palette.WebSafe) }
<commit_msg>comment<commit_after>package signals

import (
	"image"
	"image/color"
	"image/color/palette"
)

// simple visual Depiction of a Signal, implements Depictor
type Depiction struct {
	Signal
	size                     image.Rectangle
	pixelsPerUnitX           int
	below, above color.Color
}

// makes a Depiction of a LimitedSignal, scaled to pxMaxx by pxMaxy pixels and sets the colours for above and below the value.
func NewDepiction(s LimitedSignal, pxMaxX, pxMaxY int, below, above color.Color) Depiction {
	return Depiction{s, image.Rect(0, -pxMaxY/2, pxMaxX, pxMaxY/2), int(int64(pxMaxX) * int64(unitX) / int64(s.MaxX())), below, above}
}

func (i Depiction) Bounds() image.Rectangle {
	return i.size
}

func (i Depiction) At(xp, yp int) color.Color {
	if i.property(x(xp)*unitX/x(i.pixelsPerUnitX)-x(i.size.Min.X)) <= unitY/y(i.size.Max.Y)*y(yp)-y(i.size.Min.Y) {
		return i.above
	}
	return i.below
}

// a Depictor is an image.Image without a colormodel, so is more general.
// embedded in one of the helper wrappers gets you an image.Image.
// (this and the wrappers might be moved, in a later version of this package, to their own package.)
type Depictor interface {
	Bounds() image.Rectangle
	At(x, y int) color.Color
}

// RGBA depiction wrapper
type RGBAImage struct {
	Depictor
}

func (i RGBAImage) ColorModel() color.Model { return color.RGBAModel }

// gray depiction wrapper.
type GrayImage struct {
	Depictor
}

func (i GrayImage) ColorModel() color.Model { return color.GrayModel }

// plan9 paletted, depiction wrapper.
type Plan9PalettedImage struct {
	Depictor
}

func (i Plan9PalettedImage) ColorModel() color.Model { return color.Palette(palette.Plan9) }

// WebSafe paletted, depiction wrapper.
type WebSafePalettedImage struct {
	Depictor
}

func (i WebSafePalettedImage) ColorModel() color.Model { return color.Palette(palette.WebSafe) }
<|endoftext|>