<commit_before>// +build !windows,!darwin,!plan9
// this is manual but either this or the opposite (listing all valid systems) really are the only ways to do it; proposals for a 'unix' tag were rejected (https://code.google.com/p/go/issues/detail?id=6325)

// 16 february 2014

package ui

import (
	"fmt"
	"unsafe"
)

// #include "gtk_unix.h"
// static inline void gtkSetComboBoxArbitrarilyResizeable(GtkWidget *w)
// {
// 	/* we can safely assume that the cell renderers of a GtkComboBoxText are a single GtkCellRendererText by default */
// 	/* thanks mclasen and tristan in irc.gimp.net/#gtk+ */
// 	GtkCellLayout *cbox = (GtkCellLayout *) w;
// 	GList *renderer;
//
// 	renderer = gtk_cell_layout_get_cells(cbox);
// 	g_object_set(renderer->data,
// 		"ellipsize-set", TRUE,		/* with no ellipsizing or wrapping, the combobox won't resize */
// 		"ellipsize", PANGO_ELLIPSIZE_END,
// 		"width-chars", 0,
// 		NULL);
// 	g_list_free(renderer);
// }
import "C"

var gtkStyles = []byte(
	// this first one is for ProgressBar so we can arbitrarily resize it
	// min-horizontal-bar-width is a style property; we do it through CSS
	// thanks tristan in irc.gimp.net/#gtk+
	`* {
	-GtkProgressBar-min-horizontal-bar-width: 1;
}
` +
	// on some themes, such as oxygen-gtk, GtkLayout draws a solid-color background, not the window background (as GtkFixed and GtkDrawingArea do)
	// this CSS fixes it
	// thanks to drahnr and ptomato in http://stackoverflow.com/questions/22940588/how-do-i-really-make-a-gtk-3-gtklayout-transparent-draw-theme-background
	// this has now been reported to the Oyxgen maintainers (https://bugs.kde.org/show_bug.cgi?id=333983); I'm not sure if I'll remove this or not when that's fixed (only if it breaks other styles... I *think* it breaks elementary OS? need to check again)
	`GtkLayout {
	background-color: transparent;
}
` +
	"\000")

func gtk_init() error {
	var err *C.GError = nil		// redundant in Go, but let's explicitly assign it anyway

	// gtk_init_with_args() gives us error info (thanks chpe in irc.gimp.net/#gtk+)
	// don't worry about GTK+'s command-line arguments; they're also available as environment variables (thanks mclasen in irc.gimp.net/#gtk+)
	result := C.gtk_init_with_args(nil, nil, nil, nil, nil, &err)
	if result == C.FALSE {
		return fmt.Errorf("error actually initilaizing GTK+: %s", fromgstr(err.message))
	}

	// now apply our custom program-global styles
	provider := C.gtk_css_provider_new();
	if C.gtk_css_provider_load_from_data(provider, (*C.gchar)(unsafe.Pointer(&gtkStyles[0])), -1, &err) == C.FALSE {
		return fmt.Errorf("error applying package ui's custom program-global styles to GTK+: %v", fromgstr(err.message))
	}
	// GDK (at least as far back as GTK+ 3.4, but officially documented as of 3.10) merges all screens into one big one, so we don't need to worry about multimonitor
	// thanks to baedert and mclasen in irc.gimp.net/#gtk+
	C.gtk_style_context_add_provider_for_screen(C.gdk_screen_get_default(),
		(*C.GtkStyleProvider)(unsafe.Pointer(provider)),
		C.GTK_STYLE_PROVIDER_PRIORITY_USER)

	return nil
}

func gtk_main_quit() {
	C.gtk_main_quit()
}

func gtk_window_new() *C.GtkWidget {
	return C.gtk_window_new(C.GTK_WINDOW_TOPLEVEL)
}

func gtk_widget_show(widget *C.GtkWidget) {
	C.gtk_widget_show_all(widget)
}

func gtk_widget_hide(widget *C.GtkWidget) {
	C.gtk_widget_hide(widget)
}

func gtk_window_set_title(window *C.GtkWidget, title string) {
	ctitle := C.CString(title)
	defer C.free(unsafe.Pointer(ctitle))
	C.gtk_window_set_title(togtkwindow(window), togstr(ctitle))
}

func gtk_window_get_title(window *C.GtkWidget) string {
	return fromgstr(C.gtk_window_get_title(togtkwindow(window)))
}

func gtk_window_resize(window *C.GtkWidget, width int, height int) {
	C.gtk_window_resize(togtkwindow(window), C.gint(width), C.gint(height))
}

func gtk_window_get_size(window *C.GtkWidget) (int, int) {
	var width, height C.gint

	C.gtk_window_get_size(togtkwindow(window), &width, &height)
	return int(width), int(height)
}

// this should allow us to resize the window arbitrarily
// thanks to Company in irc.gimp.net/#gtk+
func gtkNewWindowLayout() *C.GtkWidget {
	layout := C.gtk_layout_new(nil, nil)
	scrollarea := C.gtk_scrolled_window_new((*C.GtkAdjustment)(nil), (*C.GtkAdjustment)(nil))
	C.gtk_container_add((*C.GtkContainer)(unsafe.Pointer(scrollarea)), layout)
	// never show scrollbars; we're just doing this to allow arbitrary resizes
	C.gtk_scrolled_window_set_policy((*C.GtkScrolledWindow)(unsafe.Pointer(scrollarea)),
		C.GTK_POLICY_NEVER, C.GTK_POLICY_NEVER)
	return scrollarea
}

func gtk_container_add(container *C.GtkWidget, widget *C.GtkWidget) {
	C.gtk_container_add(togtkcontainer(container), widget)
}

func gtkAddWidgetToLayout(container *C.GtkWidget, widget *C.GtkWidget) {
	layout := C.gtk_bin_get_child((*C.GtkBin)(unsafe.Pointer(container)))
	C.gtk_container_add((*C.GtkContainer)(unsafe.Pointer(layout)), widget)
}

func gtkMoveWidgetInLayout(container *C.GtkWidget, widget *C.GtkWidget, x int, y int) {
	layout := C.gtk_bin_get_child((*C.GtkBin)(unsafe.Pointer(container)))
	C.gtk_layout_move((*C.GtkLayout)(unsafe.Pointer(layout)), widget,
		C.gint(x), C.gint(y))
}

func gtk_widget_set_size_request(widget *C.GtkWidget, width int, height int) {
	C.gtk_widget_set_size_request(widget, C.gint(width), C.gint(height))
}

func gtk_button_new() *C.GtkWidget {
	return C.gtk_button_new()
}

func gtk_button_set_label(button *C.GtkWidget, label string) {
	clabel := C.CString(label)
	defer C.free(unsafe.Pointer(clabel))
	C.gtk_button_set_label(togtkbutton(button), togstr(clabel))
}

func gtk_button_get_label(button *C.GtkWidget) string {
	return fromgstr(C.gtk_button_get_label(togtkbutton(button)))
}

func gtk_check_button_new() *C.GtkWidget {
	return C.gtk_check_button_new()
}

func gtk_toggle_button_get_active(widget *C.GtkWidget) bool {
	return fromgbool(C.gtk_toggle_button_get_active(togtktogglebutton(widget)))
}

func gtk_combo_box_text_new() *C.GtkWidget {
	w := C.gtk_combo_box_text_new()
	C.gtkSetComboBoxArbitrarilyResizeable(w)
	return w
}

func gtk_combo_box_text_new_with_entry() *C.GtkWidget {
	w := C.gtk_combo_box_text_new_with_entry()
	// we need to set the entry's width-chars to achieve the arbitrary sizing we want
	// thanks to tristan in irc.gimp.net/#gtk+
	// in my tests, this is sufficient to get the effect we want; setting the cell renderer isn't necessary like it is with an entry-less combobox
	entry := togtkentry(C.gtk_bin_get_child((*C.GtkBin)(unsafe.Pointer(w))))
	C.gtk_entry_set_width_chars(entry, 0)
	return w
}

func gtk_combo_box_text_get_active_text(widget *C.GtkWidget) string {
	return fromgstr(C.gtk_combo_box_text_get_active_text(togtkcombobox(widget)))
}

func gtk_combo_box_text_append_text(widget *C.GtkWidget, text string) {
	ctext := C.CString(text)
	defer C.free(unsafe.Pointer(ctext))
	C.gtk_combo_box_text_append_text(togtkcombobox(widget), togstr(ctext))
}

func gtk_combo_box_text_insert_text(widget *C.GtkWidget, index int, text string) {
	ctext := C.CString(text)
	defer C.free(unsafe.Pointer(ctext))
	C.gtk_combo_box_text_insert_text(togtkcombobox(widget), C.gint(index), togstr(ctext))
}

func gtk_combo_box_get_active(widget *C.GtkWidget) int {
	cb := (*C.GtkComboBox)(unsafe.Pointer(widget))
	return int(C.gtk_combo_box_get_active(cb))
}

func gtk_combo_box_text_remove(widget *C.GtkWidget, index int) {
	C.gtk_combo_box_text_remove(togtkcombobox(widget), C.gint(index))
}

func gtkComboBoxLen(widget *C.GtkWidget) int {
	cb := (*C.GtkComboBox)(unsafe.Pointer(widget))
	model := C.gtk_combo_box_get_model(cb)
	// this is the same as with a Listbox so
	return gtkTreeModelListLen(model)
}

func gtk_entry_new() *C.GtkWidget {
	e := C.gtk_entry_new()
	// allows the GtkEntry to be resized with the window smaller than what it thinks the size should be
	// thanks to Company in irc.gimp.net/#gtk+
	C.gtk_entry_set_width_chars(togtkentry(e), 0)
	return e
}

func gtkPasswordEntryNew() *C.GtkWidget {
	e := gtk_entry_new()
	C.gtk_entry_set_visibility(togtkentry(e), C.FALSE)
	return e
}

func gtk_entry_set_text(widget *C.GtkWidget, text string) {
	ctext := C.CString(text)
	defer C.free(unsafe.Pointer(ctext))
	C.gtk_entry_set_text(togtkentry(widget), togstr(ctext))
}

func gtk_entry_get_text(widget *C.GtkWidget) string {
	return fromgstr(C.gtk_entry_get_text(togtkentry(widget)))
}

var _emptystring = [1]C.gchar{0}
var emptystring = &_emptystring[0]

func gtk_label_new() *C.GtkWidget {
	label := C.gtk_label_new(emptystring)
	C.gtk_label_set_line_wrap(togtklabel(label), C.FALSE)			// turn off line wrap
	// don't call gtk_label_set_line_wrap_mode(); there's no "wrap none" value there anyway
	C.gtk_label_set_ellipsize(togtklabel(label), C.PANGO_ELLIPSIZE_NONE)		// turn off ellipsizing; this + line wrapping above will guarantee cutoff as documented
	// there's a function gtk_label_set_justify() that indicates GTK_JUSTIFY_LEFT is the default
	// but this actually is NOT the control justification, just the multi-line justification
	// so we need to do THIS instead
	// this will also valign to the top
	// thanks to mclasen in irc.gimp.net/#gtk+
	C.gtk_misc_set_alignment((*C.GtkMisc)(unsafe.Pointer(label)), 0, 0)
	return label
}

func gtk_label_set_text(widget *C.GtkWidget, text string) {
	ctext := C.CString(text)
	defer C.free(unsafe.Pointer(ctext))
	C.gtk_label_set_text(togtklabel(widget), togstr(ctext))
}

func gtk_label_get_text(widget *C.GtkWidget) string {
	return fromgstr(C.gtk_label_get_text(togtklabel(widget)))
}

func gtk_widget_get_preferred_size(widget *C.GtkWidget) (minWidth int, minHeight int, natWidth int, natHeight int) {
	var minimum, natural C.GtkRequisition

	C.gtk_widget_get_preferred_size(widget, &minimum, &natural)
	return int(minimum.width), int(minimum.height),
		int(natural.width), int(natural.height)
}

func gtk_progress_bar_new() *C.GtkWidget {
	return C.gtk_progress_bar_new()
}

func gtk_progress_bar_set_fraction(w *C.GtkWidget, percent int) {
	p := C.gdouble(percent) / 100
	C.gtk_progress_bar_set_fraction(togtkprogressbar(w), p)
}

func gtk_progress_bar_pulse(w *C.GtkWidget) {
	C.gtk_progress_bar_pulse(togtkprogressbar(w))
}
<commit_msg>More go fmt.<commit_after>// +build !windows,!darwin,!plan9
// this is manual but either this or the opposite (listing all valid systems) really are the only ways to do it; proposals for a 'unix' tag were rejected (https://code.google.com/p/go/issues/detail?id=6325)

// 16 february 2014

package ui

import (
	"fmt"
	"unsafe"
)

// #include "gtk_unix.h"
// static inline void gtkSetComboBoxArbitrarilyResizeable(GtkWidget *w)
// {
// 	/* we can safely assume that the cell renderers of a GtkComboBoxText are a single GtkCellRendererText by default */
// 	/* thanks mclasen and tristan in irc.gimp.net/#gtk+ */
// 	GtkCellLayout *cbox = (GtkCellLayout *) w;
// 	GList *renderer;
//
// 	renderer = gtk_cell_layout_get_cells(cbox);
// 	g_object_set(renderer->data,
// 		"ellipsize-set", TRUE,		/* with no ellipsizing or wrapping, the combobox won't resize */
// 		"ellipsize", PANGO_ELLIPSIZE_END,
// 		"width-chars", 0,
// 		NULL);
// 	g_list_free(renderer);
// }
import "C"

var gtkStyles = []byte(
	// this first one is for ProgressBar so we can arbitrarily resize it
	// min-horizontal-bar-width is a style property; we do it through CSS
	// thanks tristan in irc.gimp.net/#gtk+
	`* {
	-GtkProgressBar-min-horizontal-bar-width: 1;
}
` +
		// on some themes, such as oxygen-gtk, GtkLayout draws a solid-color background, not the window background (as GtkFixed and GtkDrawingArea do)
		// this CSS fixes it
		// thanks to drahnr and ptomato in http://stackoverflow.com/questions/22940588/how-do-i-really-make-a-gtk-3-gtklayout-transparent-draw-theme-background
		// this has now been reported to the Oyxgen maintainers (https://bugs.kde.org/show_bug.cgi?id=333983); I'm not sure if I'll remove this or not when that's fixed (only if it breaks other styles... I *think* it breaks elementary OS? need to check again)
		`GtkLayout {
	background-color: transparent;
}
` +
		"\000")

func gtk_init() error {
	var err *C.GError = nil // redundant in Go, but let's explicitly assign it anyway

	// gtk_init_with_args() gives us error info (thanks chpe in irc.gimp.net/#gtk+)
	// don't worry about GTK+'s command-line arguments; they're also available as environment variables (thanks mclasen in irc.gimp.net/#gtk+)
	result := C.gtk_init_with_args(nil, nil, nil, nil, nil, &err)
	if result == C.FALSE {
		return fmt.Errorf("error actually initilaizing GTK+: %s", fromgstr(err.message))
	}

	// now apply our custom program-global styles
	provider := C.gtk_css_provider_new()
	if C.gtk_css_provider_load_from_data(provider, (*C.gchar)(unsafe.Pointer(&gtkStyles[0])), -1, &err) == C.FALSE {
		return fmt.Errorf("error applying package ui's custom program-global styles to GTK+: %v", fromgstr(err.message))
	}
	// GDK (at least as far back as GTK+ 3.4, but officially documented as of 3.10) merges all screens into one big one, so we don't need to worry about multimonitor
	// thanks to baedert and mclasen in irc.gimp.net/#gtk+
	C.gtk_style_context_add_provider_for_screen(C.gdk_screen_get_default(),
		(*C.GtkStyleProvider)(unsafe.Pointer(provider)),
		C.GTK_STYLE_PROVIDER_PRIORITY_USER)

	return nil
}

func gtk_main_quit() {
	C.gtk_main_quit()
}

func gtk_window_new() *C.GtkWidget {
	return C.gtk_window_new(C.GTK_WINDOW_TOPLEVEL)
}

func gtk_widget_show(widget *C.GtkWidget) {
	C.gtk_widget_show_all(widget)
}

func gtk_widget_hide(widget *C.GtkWidget) {
	C.gtk_widget_hide(widget)
}

func gtk_window_set_title(window *C.GtkWidget, title string) {
	ctitle := C.CString(title)
	defer C.free(unsafe.Pointer(ctitle))
	C.gtk_window_set_title(togtkwindow(window), togstr(ctitle))
}

func gtk_window_get_title(window *C.GtkWidget) string {
	return fromgstr(C.gtk_window_get_title(togtkwindow(window)))
}

func gtk_window_resize(window *C.GtkWidget, width int, height int) {
	C.gtk_window_resize(togtkwindow(window), C.gint(width), C.gint(height))
}

func gtk_window_get_size(window *C.GtkWidget) (int, int) {
	var width, height C.gint

	C.gtk_window_get_size(togtkwindow(window), &width, &height)
	return int(width), int(height)
}

// this should allow us to resize the window arbitrarily
// thanks to Company in irc.gimp.net/#gtk+
func gtkNewWindowLayout() *C.GtkWidget {
	layout := C.gtk_layout_new(nil, nil)
	scrollarea := C.gtk_scrolled_window_new((*C.GtkAdjustment)(nil), (*C.GtkAdjustment)(nil))
	C.gtk_container_add((*C.GtkContainer)(unsafe.Pointer(scrollarea)), layout)
	// never show scrollbars; we're just doing this to allow arbitrary resizes
	C.gtk_scrolled_window_set_policy((*C.GtkScrolledWindow)(unsafe.Pointer(scrollarea)),
		C.GTK_POLICY_NEVER, C.GTK_POLICY_NEVER)
	return scrollarea
}

func gtk_container_add(container *C.GtkWidget, widget *C.GtkWidget) {
	C.gtk_container_add(togtkcontainer(container), widget)
}

func gtkAddWidgetToLayout(container *C.GtkWidget, widget *C.GtkWidget) {
	layout := C.gtk_bin_get_child((*C.GtkBin)(unsafe.Pointer(container)))
	C.gtk_container_add((*C.GtkContainer)(unsafe.Pointer(layout)), widget)
}

func gtkMoveWidgetInLayout(container *C.GtkWidget, widget *C.GtkWidget, x int, y int) {
	layout := C.gtk_bin_get_child((*C.GtkBin)(unsafe.Pointer(container)))
	C.gtk_layout_move((*C.GtkLayout)(unsafe.Pointer(layout)), widget,
		C.gint(x), C.gint(y))
}

func gtk_widget_set_size_request(widget *C.GtkWidget, width int, height int) {
	C.gtk_widget_set_size_request(widget, C.gint(width), C.gint(height))
}

func gtk_button_new() *C.GtkWidget {
	return C.gtk_button_new()
}

func gtk_button_set_label(button *C.GtkWidget, label string) {
	clabel := C.CString(label)
	defer C.free(unsafe.Pointer(clabel))
	C.gtk_button_set_label(togtkbutton(button), togstr(clabel))
}

func gtk_button_get_label(button *C.GtkWidget) string {
	return fromgstr(C.gtk_button_get_label(togtkbutton(button)))
}

func gtk_check_button_new() *C.GtkWidget {
	return C.gtk_check_button_new()
}

func gtk_toggle_button_get_active(widget *C.GtkWidget) bool {
	return fromgbool(C.gtk_toggle_button_get_active(togtktogglebutton(widget)))
}

func gtk_combo_box_text_new() *C.GtkWidget {
	w := C.gtk_combo_box_text_new()
	C.gtkSetComboBoxArbitrarilyResizeable(w)
	return w
}

func gtk_combo_box_text_new_with_entry() *C.GtkWidget {
	w := C.gtk_combo_box_text_new_with_entry()
	// we need to set the entry's width-chars to achieve the arbitrary sizing we want
	// thanks to tristan in irc.gimp.net/#gtk+
	// in my tests, this is sufficient to get the effect we want; setting the cell renderer isn't necessary like it is with an entry-less combobox
	entry := togtkentry(C.gtk_bin_get_child((*C.GtkBin)(unsafe.Pointer(w))))
	C.gtk_entry_set_width_chars(entry, 0)
	return w
}

func gtk_combo_box_text_get_active_text(widget *C.GtkWidget) string {
	return fromgstr(C.gtk_combo_box_text_get_active_text(togtkcombobox(widget)))
}

func gtk_combo_box_text_append_text(widget *C.GtkWidget, text string) {
	ctext := C.CString(text)
	defer C.free(unsafe.Pointer(ctext))
	C.gtk_combo_box_text_append_text(togtkcombobox(widget), togstr(ctext))
}

func gtk_combo_box_text_insert_text(widget *C.GtkWidget, index int, text string) {
	ctext := C.CString(text)
	defer C.free(unsafe.Pointer(ctext))
	C.gtk_combo_box_text_insert_text(togtkcombobox(widget), C.gint(index), togstr(ctext))
}

func gtk_combo_box_get_active(widget *C.GtkWidget) int {
	cb := (*C.GtkComboBox)(unsafe.Pointer(widget))
	return int(C.gtk_combo_box_get_active(cb))
}

func gtk_combo_box_text_remove(widget *C.GtkWidget, index int) {
	C.gtk_combo_box_text_remove(togtkcombobox(widget), C.gint(index))
}

func gtkComboBoxLen(widget *C.GtkWidget) int {
	cb := (*C.GtkComboBox)(unsafe.Pointer(widget))
	model := C.gtk_combo_box_get_model(cb)
	// this is the same as with a Listbox so
	return gtkTreeModelListLen(model)
}

func gtk_entry_new() *C.GtkWidget {
	e := C.gtk_entry_new()
	// allows the GtkEntry to be resized with the window smaller than what it thinks the size should be
	// thanks to Company in irc.gimp.net/#gtk+
	C.gtk_entry_set_width_chars(togtkentry(e), 0)
	return e
}

func gtkPasswordEntryNew() *C.GtkWidget {
	e := gtk_entry_new()
	C.gtk_entry_set_visibility(togtkentry(e), C.FALSE)
	return e
}

func gtk_entry_set_text(widget *C.GtkWidget, text string) {
	ctext := C.CString(text)
	defer C.free(unsafe.Pointer(ctext))
	C.gtk_entry_set_text(togtkentry(widget), togstr(ctext))
}

func gtk_entry_get_text(widget *C.GtkWidget) string {
	return fromgstr(C.gtk_entry_get_text(togtkentry(widget)))
}

var _emptystring = [1]C.gchar{0}
var emptystring = &_emptystring[0]

func gtk_label_new() *C.GtkWidget {
	label := C.gtk_label_new(emptystring)
	C.gtk_label_set_line_wrap(togtklabel(label), C.FALSE) // turn off line wrap
	// don't call gtk_label_set_line_wrap_mode(); there's no "wrap none" value there anyway
	C.gtk_label_set_ellipsize(togtklabel(label), C.PANGO_ELLIPSIZE_NONE) // turn off ellipsizing; this + line wrapping above will guarantee cutoff as documented
	// there's a function gtk_label_set_justify() that indicates GTK_JUSTIFY_LEFT is the default
	// but this actually is NOT the control justification, just the multi-line justification
	// so we need to do THIS instead
	// this will also valign to the top
	// thanks to mclasen in irc.gimp.net/#gtk+
	C.gtk_misc_set_alignment((*C.GtkMisc)(unsafe.Pointer(label)), 0, 0)
	return label
}

func gtk_label_set_text(widget *C.GtkWidget, text string) {
	ctext := C.CString(text)
	defer C.free(unsafe.Pointer(ctext))
	C.gtk_label_set_text(togtklabel(widget), togstr(ctext))
}

func gtk_label_get_text(widget *C.GtkWidget) string {
	return fromgstr(C.gtk_label_get_text(togtklabel(widget)))
}

func gtk_widget_get_preferred_size(widget *C.GtkWidget) (minWidth int, minHeight int, natWidth int, natHeight int) {
	var minimum, natural C.GtkRequisition

	C.gtk_widget_get_preferred_size(widget, &minimum, &natural)
	return int(minimum.width), int(minimum.height),
		int(natural.width), int(natural.height)
}

func gtk_progress_bar_new() *C.GtkWidget {
	return C.gtk_progress_bar_new()
}

func gtk_progress_bar_set_fraction(w *C.GtkWidget, percent int) {
	p := C.gdouble(percent) / 100
	C.gtk_progress_bar_set_fraction(togtkprogressbar(w), p)
}

func gtk_progress_bar_pulse(w *C.GtkWidget) {
	C.gtk_progress_bar_pulse(togtkprogressbar(w))
}
<|endoftext|>


<commit_before>package gubled

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/alexflint/go-arg"
	"github.com/caarlos0/env"
	"github.com/smancke/guble/gcm"
	"github.com/smancke/guble/metrics"
	"github.com/smancke/guble/server"
	"github.com/smancke/guble/server/auth"
	"github.com/smancke/guble/server/rest"
	"github.com/smancke/guble/server/webserver"
	"github.com/smancke/guble/server/websocket"
	"github.com/smancke/guble/store"

	"expvar"
	"os"
	"os/signal"
	"path"
	"runtime"
	"syscall"
)

var logger = log.WithFields(log.Fields{
	"app":    "guble",
	"module": "gubled",
	"env":    "TBD"})

const (
	healthEndpointPrefix = "/_health"
)

type Args struct {
	Listen      string `arg:"-l,help: [Host:]Port the address to listen on (:8080)" env:"GUBLE_LISTEN"`
	LogInfo     bool   `arg:"--log-info,help: Log on INFO level (false)" env:"GUBLE_LOG_INFO"`
	LogDebug    bool   `arg:"--log-debug,help: Log on DEBUG level (false)" env:"GUBLE_LOG_DEBUG"`
	StoragePath string `arg:"--storage-path,help: The path for storing messages and key value data if 'file' is enabled (/var/lib/guble)" env:"GUBLE_STORAGE_PATH"`
	KVBackend   string `arg:"--kv-backend,help: The storage backend for the key value store to use: file|memory (file)" env:"GUBLE_KV_BACKEND"`
	MSBackend   string `arg:"--ms-backend,help: The message storage backend : file|memory (file)" env:"GUBLE_MS_BACKEND"`
	GcmEnable   bool   `arg:"--gcm-enable: Enable the Google Cloud Messaging Connector (false)" env:"GUBLE_GCM_ENABLE"`
	GcmApiKey   string `arg:"--gcm-api-key: The Google API Key for Google Cloud Messaging" env:"GUBLE_GCM_API_KEY"`
	GcmWorkers  int    `arg:"--gcm-workers: The number of workers handling traffic with Google Cloud Messaging (default: GOMAXPROCS)" env:"GUBLE_GCM_WORKERS"`
	Health      string `arg:"--health: The health endpoint (default: /_health; value for disabling it: \"\" )" env:"GUBLE_HEALTH_ENDPOINT"`
	Metrics     string `arg:"--metrics: The metrics endpoint (disabled by default; a possible value for enabling it: /_metrics )" env:"GUBLE_METRICS_ENDPOINT"`
}

var ValidateStoragePath = func(args Args) error {
	if args.KVBackend == "file" || args.MSBackend == "file" {
		testfile := path.Join(args.StoragePath, "write-test-file")
		f, err := os.Create(testfile)
		if err != nil {
			logger.WithFields(log.Fields{
				"storage_Path": args.StoragePath,
				"err":          err,
			}).Error("Storage path not present/writeable.")

			if args.StoragePath == "/var/lib/guble" {
				logger.WithFields(log.Fields{
					"storage_Path": args.StoragePath,
					"err":          err,
				}).Error("Use --storage-path=<path> to override the default location, or create the directory with RW rights.")
			}
			return err
		}
		f.Close()
		os.Remove(testfile)
	}
	return nil
}

var CreateKVStore = func(args Args) store.KVStore {
	switch args.KVBackend {
	case "memory":
		return store.NewMemoryKVStore()
	case "file":
		db := store.NewSqliteKVStore(path.Join(args.StoragePath, "kv-store.db"), true)
		if err := db.Open(); err != nil {
			logger.WithField("err", err).Panic("Could not open db connection")

		}
		return db
	default:
		panic(fmt.Errorf("Unknown key-value backend: %q", args.KVBackend))
	}
}

var CreateMessageStore = func(args Args) store.MessageStore {
	switch args.MSBackend {
	case "none", "":
		return store.NewDummyMessageStore(store.NewMemoryKVStore())
	case "file":
		logger.WithField("storage_Path", args.StoragePath).Info("Using FileMessageStore in directory")

		return store.NewFileMessageStore(args.StoragePath)
	default:
		panic(fmt.Errorf("Unknown message-store backend: %q", args.MSBackend))
	}
}

var CreateModules = func(router server.Router, args Args) []interface{} {
	modules := make([]interface{}, 0, 3)

	if wsHandler, err := websocket.NewWSHandler(router, "/stream/"); err != nil {
		logger.WithField("err", err).Error("Error loading WSHandler module:")
	} else {
		modules = append(modules, wsHandler)
	}

	modules = append(modules, rest.NewRestMessageAPI(router, "/api/"))

	if args.GcmEnable {
		if args.GcmApiKey == "" {
			logger.Panic("GCM API Key has to be provided, if GCM is enabled")

		}

		logger.Info("Google cloud messaging: enabled")

		logger.WithField("args.GcmWOrkers", args.GcmWorkers).Debug("Workers")

		if gcm, err := gcm.NewGCMConnector(router, "/gcm/", args.GcmApiKey, args.GcmWorkers); err != nil {
			logger.WithField("err", err).Error("Error loading GCMConnector:")
		} else {
			modules = append(modules, gcm)
		}
	} else {
		logger.Info("Google cloud messaging: disabled")
	}

	return modules
}

func Main() {
	defer func() {
		if p := recover(); p != nil {
			logger.Fatal("Fatal error in gubled after recover")
		}
	}()

	args := loadArgs()
	if args.LogInfo {
		log.SetLevel(log.InfoLevel)
	}
	if args.LogDebug {
		log.SetLevel(log.DebugLevel)
	}

	if err := ValidateStoragePath(args); err != nil {
		logger.Fatal("Fatal error in gubled in validation for storage path")
	}

	service := StartService(args)

	waitForTermination(func() {
		err := service.Stop()
		if err != nil {
			logger.WithField("err", err).Error("Error when stopping service")
		}
	})
}

func StartService(args Args) *server.Service {
	accessManager := auth.NewAllowAllAccessManager(true)
	messageStore := CreateMessageStore(args)
	kvStore := CreateKVStore(args)

	router := server.NewRouter(accessManager, messageStore, kvStore)
	webserver := webserver.New(args.Listen)

	service := server.NewService(router, webserver).HealthEndpointPrefix(args.Health).MetricsEndpointPrefix(args.Metrics)

	service.RegisterModules(CreateModules(router, args)...)

	if err := service.Start(); err != nil {
		if err := service.Stop(); err != nil {
			logger.WithField("err", err).Error("Error when stopping service after Start() failed")
		}
		logger.WithField("err", err).Fatal("Service could not be started")
	}
	expvar.Publish("guble.args", expvar.Func(func() interface{} {
		return args
	}))

	return service
}

func loadArgs() Args {
	args := Args{
		Listen:      ":8080",
		KVBackend:   "file",
		MSBackend:   "file",
		StoragePath: "/var/lib/guble",
		GcmWorkers:  runtime.GOMAXPROCS(0),
		Health:      healthEndpointPrefix,
	}

	env.Parse(&args)
	arg.MustParse(&args)
	return args
}

func waitForTermination(callback func()) {
	signalC := make(chan os.Signal)
	signal.Notify(signalC, syscall.SIGINT, syscall.SIGTERM)

	logger.Infof("Got signal '%v' .. exiting gracefully now", <-signalC)

	callback()
	metrics.LogOnDebugLevel()
	logger.Info("Exit gracefully now")
	os.Exit(0)
}
<commit_msg>Small refactoring<commit_after>package gubled

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/alexflint/go-arg"
	"github.com/caarlos0/env"
	"github.com/smancke/guble/gcm"
	"github.com/smancke/guble/metrics"
	"github.com/smancke/guble/server"
	"github.com/smancke/guble/server/auth"
	"github.com/smancke/guble/server/rest"
	"github.com/smancke/guble/server/webserver"
	"github.com/smancke/guble/server/websocket"
	"github.com/smancke/guble/store"

	"expvar"
	"os"
	"os/signal"
	"path"
	"runtime"
	"syscall"
)

var logger = log.WithFields(log.Fields{
	"app":    "guble",
	"module": "gubled",
	"env":    "TBD"})

const (
	healthEndpointPrefix = "/_health"
)

type Args struct {
	Listen      string `arg:"-l,help: [Host:]Port the address to listen on (:8080)" env:"GUBLE_LISTEN"`
	LogInfo     bool   `arg:"--log-info,help: Log on INFO level (false)" env:"GUBLE_LOG_INFO"`
	LogDebug    bool   `arg:"--log-debug,help: Log on DEBUG level (false)" env:"GUBLE_LOG_DEBUG"`
	StoragePath string `arg:"--storage-path,help: The path for storing messages and key value data if 'file' is enabled (/var/lib/guble)" env:"GUBLE_STORAGE_PATH"`
	KVBackend   string `arg:"--kv-backend,help: The storage backend for the key value store to use: file|memory (file)" env:"GUBLE_KV_BACKEND"`
	MSBackend   string `arg:"--ms-backend,help: The message storage backend : file|memory (file)" env:"GUBLE_MS_BACKEND"`
	GcmEnable   bool   `arg:"--gcm-enable: Enable the Google Cloud Messaging Connector (false)" env:"GUBLE_GCM_ENABLE"`
	GcmApiKey   string `arg:"--gcm-api-key: The Google API Key for Google Cloud Messaging" env:"GUBLE_GCM_API_KEY"`
	GcmWorkers  int    `arg:"--gcm-workers: The number of workers handling traffic with Google Cloud Messaging (default: GOMAXPROCS)" env:"GUBLE_GCM_WORKERS"`
	Health      string `arg:"--health: The health endpoint (default: /_health; value for disabling it: \"\" )" env:"GUBLE_HEALTH_ENDPOINT"`
	Metrics     string `arg:"--metrics: The metrics endpoint (disabled by default; a possible value for enabling it: /_metrics )" env:"GUBLE_METRICS_ENDPOINT"`
}

var ValidateStoragePath = func(args Args) error {
	if args.KVBackend == "file" || args.MSBackend == "file" {
		testfile := path.Join(args.StoragePath, "write-test-file")
		f, err := os.Create(testfile)
		if err != nil {
			logger.WithFields(log.Fields{
				"storagePath": args.StoragePath,
				"err":         err,
			}).Error("Storage path not present/writeable.")

			if args.StoragePath == "/var/lib/guble" {
				logger.WithFields(log.Fields{
					"storagePath": args.StoragePath,
					"err":         err,
				}).Error("Use --storage-path=<path> to override the default location, or create the directory with RW rights.")
			}
			return err
		}
		f.Close()
		os.Remove(testfile)
	}
	return nil
}

var CreateKVStore = func(args Args) store.KVStore {
	switch args.KVBackend {
	case "memory":
		return store.NewMemoryKVStore()
	case "file":
		db := store.NewSqliteKVStore(path.Join(args.StoragePath, "kv-store.db"), true)
		if err := db.Open(); err != nil {
			logger.WithField("err", err).Panic("Could not open db connection")

		}
		return db
	default:
		panic(fmt.Errorf("Unknown key-value backend: %q", args.KVBackend))
	}
}

var CreateMessageStore = func(args Args) store.MessageStore {
	switch args.MSBackend {
	case "none", "":
		return store.NewDummyMessageStore(store.NewMemoryKVStore())
	case "file":
		logger.WithField("storagePath", args.StoragePath).Info("Using FileMessageStore in directory")

		return store.NewFileMessageStore(args.StoragePath)
	default:
		panic(fmt.Errorf("Unknown message-store backend: %q", args.MSBackend))
	}
}

var CreateModules = func(router server.Router, args Args) []interface{} {
	modules := make([]interface{}, 0, 3)

	if wsHandler, err := websocket.NewWSHandler(router, "/stream/"); err != nil {
		logger.WithField("err", err).Error("Error loading WSHandler module:")
	} else {
		modules = append(modules, wsHandler)
	}

	modules = append(modules, rest.NewRestMessageAPI(router, "/api/"))

	if args.GcmEnable {
		if args.GcmApiKey == "" {
			logger.Panic("GCM API Key has to be provided, if GCM is enabled")

		}

		logger.Info("Google cloud messaging: enabled")

		logger.WithField("args.GcmWOrkers", args.GcmWorkers).Debug("Workers")

		if gcm, err := gcm.NewGCMConnector(router, "/gcm/", args.GcmApiKey, args.GcmWorkers); err != nil {
			logger.WithField("err", err).Error("Error loading GCMConnector:")
		} else {
			modules = append(modules, gcm)
		}
	} else {
		logger.Info("Google cloud messaging: disabled")
	}

	return modules
}

func Main() {
	defer func() {
		if p := recover(); p != nil {
			logger.Fatal("Fatal error in gubled after recover")
		}
	}()

	args := loadArgs()
	if args.LogInfo {
		log.SetLevel(log.InfoLevel)
	}
	if args.LogDebug {
		log.SetLevel(log.DebugLevel)
	}

	if err := ValidateStoragePath(args); err != nil {
		logger.Fatal("Fatal error in gubled in validation for storage path")
	}

	service := StartService(args)

	waitForTermination(func() {
		err := service.Stop()
		if err != nil {
			logger.WithField("err", err).Error("Error when stopping service")
		}
	})
}

func StartService(args Args) *server.Service {
	accessManager := auth.NewAllowAllAccessManager(true)
	messageStore := CreateMessageStore(args)
	kvStore := CreateKVStore(args)

	router := server.NewRouter(accessManager, messageStore, kvStore)
	webserver := webserver.New(args.Listen)

	service := server.NewService(router, webserver).HealthEndpointPrefix(args.Health).MetricsEndpointPrefix(args.Metrics)

	service.RegisterModules(CreateModules(router, args)...)

	if err := service.Start(); err != nil {
		if err := service.Stop(); err != nil {
			logger.WithField("err", err).Error("Error when stopping service after Start() failed")
		}
		logger.WithField("err", err).Fatal("Service could not be started")
	}
	expvar.Publish("guble.args", expvar.Func(func() interface{} {
		return args
	}))

	return service
}

func loadArgs() Args {
	args := Args{
		Listen:      ":8080",
		KVBackend:   "file",
		MSBackend:   "file",
		StoragePath: "/var/lib/guble",
		GcmWorkers:  runtime.GOMAXPROCS(0),
		Health:      healthEndpointPrefix,
	}

	env.Parse(&args)
	arg.MustParse(&args)
	return args
}

func waitForTermination(callback func()) {
	signalC := make(chan os.Signal)
	signal.Notify(signalC, syscall.SIGINT, syscall.SIGTERM)

	logger.Infof("Got signal '%v' .. exiting gracefully now", <-signalC)

	callback()
	metrics.LogOnDebugLevel()
	logger.Info("Exit gracefully now")
	os.Exit(0)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"github.com/swdunlop/tarantula-go"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"mime"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"time"
)

func main() {
	flag.Usage = func() {
		println("livefire option ... path ...")
		flag.PrintDefaults()
		println()
		println("File Handling:")
		println("  .css: wrapped with a
{{end}}{{range .JS}}

{{end}}{{range .HTML}}
  {{.}}
{{end}}`))
<commit_msg>moved livefire to docopt-go<commit_after>package main

import (
	"fmt"
	"github.com/swdunlop/docopt-go"
	"github.com/swdunlop/tarantula-go"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"mime"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"time"
)

var USAGE = `
USAGE:
    livefire [options] FILE...

OPTIONS:
    -b ADDR   where the http server should listen [default: 127.0.0.1:8080]
    -t TITLE  title for the generated html page [default: Livefire Exercise]
    -f URL    HTTP server for any unrecognized paths

Livefire serves a number of local files on the command line and
constructs skeleton HTML page around them that will
automatically refresh when any of the files change according to
the operating system.  The composition of this file depends on
the extension of the files provided on the command line:

    .css   wrapped with a
{{end}}{{range .JS}}

{{end}}{{range .HTML}}
  {{.}}
{{end}}`))
<|endoftext|>


<commit_before>package formatters

import (
	"fmt"
	"strings"

	"github.com/stilvoid/please/common"
)

func wrapObj(in interface{}) string {
	out := formatBashInternal(in)
	out = strings.Replace(out, "\\", "\\\\", -1)
	out = strings.Replace(out, "\"", "\\\"", -1)
	out = strings.Replace(out, "`", "\\`", -1)
	out = strings.Replace(out, "\n", "\\n", -1)
	out = strings.Replace(out, "$", "\\$", -1)
	out = fmt.Sprintf("\"%s\"", out)

	return out
}

func formatBashInternal(in interface{}) string {
	if in == nil {
		return ""
	}

	switch v := in.(type) {
	case map[string]interface{}:
		keys := common.SortedKeys(v)

		parts := make([]string, len(v))

		for i, key := range keys {
			parts[i] = fmt.Sprintf("[%s]=%s", key, wrapObj(v[key.(string)]))
		}

		return fmt.Sprintf("(%s)", strings.Join(parts, " "))
	default:
		return fmt.Sprint(in)
	}
}

func formatBash(in interface{}) (string, error) {
	in = common.ArraysToMaps(in)
	in = common.ForceStringKeys(in)

	return formatBashInternal(in), nil
}
<commit_msg>Improve performance of bash formatter<commit_after>package formatters

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/stilvoid/please/common"
)

func wrapObj(in string) string {
	out := strings.Replace(in, `\`, `\\`, -1)
	out = strings.Replace(out, `"`, `\"`, -1)
	out = strings.Replace(out, "`", "\\`", -1)
	out = strings.Replace(out, "\n", `\n`, -1)
	out = strings.Replace(out, `$`, `\$`, -1)

	return "\"" + out + "\""
}

func formatBashInternal(in interface{}, buf *bytes.Buffer) {
	if in == nil {
		return
	}

	switch v := in.(type) {
	case map[string]interface{}:
		keys := common.SortedKeys(v)

		buf.WriteByte('(')

		for i, key := range keys {
			var innerBuf bytes.Buffer

			formatBashInternal(v[key.(string)], &innerBuf)

			buf.WriteByte('[')
			buf.WriteString(key.(string))
			buf.WriteString("]=")
			buf.WriteString(wrapObj(innerBuf.String()))

			if i != len(keys)-1 {
				buf.WriteByte(' ')
			}
		}

		buf.WriteByte(')')
	default:
		buf.WriteString(fmt.Sprint(in))
	}
}

func formatBash(in interface{}) (string, error) {
	in = common.ArraysToMaps(in)
	in = common.ForceStringKeys(in)

	var buf bytes.Buffer

	formatBashInternal(in, &buf)

	return buf.String(), nil
}
<|endoftext|>


<commit_before>package street

import (
	"context"
	"errors"
	"io/ioutil"
	"net/http"
	"net/url"
	"testing"

	"github.com/smartystreets/assertions/should"
	"github.com/smartystreets/gunit"
	sdk "github.com/smartystreets/smartystreets-go-sdk"
)

func TestClientFixture(t *testing.T) {
	gunit.Run(new(ClientFixture), t)
}

type ClientFixture struct {
	*gunit.Fixture

	sender *FakeSender
	client *Client
	batch  *Batch
}

func (f *ClientFixture) Setup() {
	f.sender = &FakeSender{}
	f.client = NewClient(f.sender)
	f.batch = NewBatch()
}

func (f *ClientFixture) TestSingleAddressBatchWithContext_SentInQueryStringAsGET() {
	f.sender.response = `[{"input_index": 0, "input_id": "42"}]`
	input := &Lookup{InputID: "42"}
	f.batch.Append(input)

	ctx := context.WithValue(context.Background(), "key", "value")
	err := f.client.SendBatchWithContext(ctx, f.batch)

	f.So(err, should.BeNil)
	f.So(f.sender.request, should.NotBeNil)
	f.So(f.sender.request.Method, should.Equal, "GET")
	f.So(f.sender.request.URL.Path, should.Equal, "/street-address")
	f.So(f.sender.requestBody, should.BeNil)
	f.So(f.sender.request.ContentLength, should.Equal, 0)
	f.So(f.sender.request.URL.String(), should.StartWith, verifyURL)
	f.So(f.sender.request.URL.Query(), should.Resemble, url.Values{"input_id": {"42"}})
	f.So(f.sender.request.Context(), should.Resemble, ctx)
}

func (f *ClientFixture) TestAddressBatchSerializedAndSent__ResponseCandidatesIncorporatedIntoBatch() {
	f.sender.response = `[
		{"input_index": 0, "input_id": "42"},
		{"input_index": 2, "input_id": "44"},
		{"input_index": 2, "input_id": "44", "candidate_index": 1}
	]`
	input0 := &Lookup{InputID: "42"}
	input1 := &Lookup{InputID: "43"}
	input2 := &Lookup{InputID: "44"}
	f.batch.Append(input0)
	f.batch.Append(input1)
	f.batch.Append(input2)

	err := f.client.SendBatch(f.batch)

	f.So(err, should.BeNil)
	f.So(f.sender.request, should.NotBeNil)
	f.So(f.sender.request.Method, should.Equal, "POST")
	f.So(f.sender.request.URL.Path, should.Equal, "/street-address")
	f.So(f.sender.request.ContentLength, should.Equal, len(f.sender.requestBody))
	f.So(string(f.sender.requestBody), should.Equal, `[{"input_id":"42"},{"input_id":"43"},{"input_id":"44"}]`)
	f.So(f.sender.request.URL.String(), should.Equal, verifyURL)

	f.So(input0.Results, should.Resemble, []*Candidate{{InputID: "42"}})
	f.So(input1.Results, should.BeEmpty)
	f.So(input2.Results, should.Resemble, []*Candidate{{InputID: "44", InputIndex: 2}, {InputID: "44", InputIndex: 2, CandidateIndex: 1}})
}

func (f *ClientFixture) TestNilBatchNOP() {
	err := f.client.SendBatch(nil)
	f.So(err, should.BeNil)
	f.So(f.sender.request, should.BeNil)
}

func (f *ClientFixture) TestEmptyBatch_NOP() {
	err := f.client.SendBatch(new(Batch))
	f.So(err, should.BeNil)
	f.So(f.sender.request, should.BeNil)
}

func (f *ClientFixture) TestSenderErrorPreventsDeserialization() {
	f.sender.err = errors.New("GOPHERS!")
	f.sender.response = `[
		{"input_index": 0, "input_id": "42"},
		{"input_index": 2, "input_id": "44"},
		{"input_index": 2, "input_id": "44", "candidate_index": 1}
	]` // would be deserialized if not for the err (above)

	input := new(Lookup)
	f.batch.Append(input)

	err := f.client.SendBatch(f.batch)

	f.So(err, should.NotBeNil)
	f.So(input.Results, should.BeEmpty)
}

func (f *ClientFixture) TestDeserializationErrorPreventsDeserialization() {
	f.sender.response = `I can't haz JSON`
	input := new(Lookup)
	f.batch.Append(input)

	err := f.client.SendBatch(f.batch)

	f.So(err, should.NotBeNil)
	f.So(input.Results, should.BeEmpty)
}

func (f *ClientFixture) TestNullCandidatesWithinResponseArrayAreIgnoredAfterDeserialization() {
	f.sender.response = `[null]`
	lookup := new(Lookup)
	f.batch.Append(lookup)
	f.So(func() { f.client.SendBatch(f.batch) }, should.NotPanic)
	f.So(lookup.Results, should.BeEmpty)
}

func (f *ClientFixture) TestOutOfRangeCandidatesWithinResponseArrayAreIgnoredAfterDeserialization() {
	f.sender.response = `[{"input_index": 9999999}]`
	lookup := new(Lookup)
	f.batch.Append(lookup)
	f.So(func() { f.client.SendBatch(f.batch) }, should.NotPanic)
	f.So(lookup.Results, should.BeEmpty)
}

func (f *ClientFixture) TestFullJSONResponseDeserialization() {
	f.sender.response = `[
  {
	"input_id": "blah",
    "input_index": 0,
    "candidate_index": 4242,
	"addressee": "John Smith",
    "delivery_line_1": "3214 N University Ave # 409",
    "delivery_line_2": "blah blah",
    "last_line": "Provo UT 84604-4405",
    "delivery_point_barcode": "846044405140",
    "components": {
      "primary_number": "3214",
      "street_predirection": "N",
      "street_postdirection": "Q",
      "street_name": "University",
      "street_suffix": "Ave",
      "secondary_number": "409",
      "secondary_designator": "#",
      "extra_secondary_number": "410",
      "extra_secondary_designator": "Apt",
      "pmb_number": "411",
      "pmb_designator": "Box",
      "city_name": "Provo",
      "default_city_name": "Provo",
      "state_abbreviation": "UT",
      "zipcode": "84604",
      "plus4_code": "4405",
      "delivery_point": "14",
      "delivery_point_check_digit": "0",
      "urbanization": "urbanization"
    },
    "metadata": {
      "record_type": "S",
      "zip_type": "Standard",
      "county_fips": "49049",
      "county_name": "Utah",
      "carrier_route": "C016",
      "congressional_district": "03",
	  "building_default_indicator": "hi",
      "rdi": "Commercial",
      "elot_sequence": "0016",
      "elot_sort": "A",
      "latitude": 40.27658,
      "longitude": -111.65759,
      "coordinate_license": 1,
      "precision": "Rooftop",
      "time_zone": "Mountain",
      "utc_offset": -7,
      "dst": true,
	  "ews_match": true
    },
    "analysis": {
      "dpv_match_code": "S",
      "dpv_footnotes": "AACCRR",
      "dpv_cmra": "Y",
      "dpv_vacant": "N",
      "dpv_no_stat": "N",
      "active": "Y",
      "footnotes": "footnotes",
      "lacslink_code": "lacslink_code",
      "lacslink_indicator": "lacslink_indicator",
      "suitelink_match": true
    }
  }
]`
	lookup := new(Lookup)
	f.batch.Append(lookup)
	err := f.client.SendBatch(f.batch)
	f.So(err, should.BeNil)
	f.So(lookup.Results, should.Resemble, []*Candidate{
		{
			InputID:              "blah",
			InputIndex:           0,
			CandidateIndex:       4242,
			Addressee:            "John Smith",
			DeliveryLine1:        "3214 N University Ave # 409",
			DeliveryLine2:        "blah blah",
			LastLine:             "Provo UT 84604-4405",
			DeliveryPointBarcode: "846044405140",
			Components: Components{
				PrimaryNumber:            "3214",
				StreetPredirection:       "N",
				StreetName:               "University",
				StreetPostdirection:      "Q",
				StreetSuffix:             "Ave",
				SecondaryNumber:          "409",
				SecondaryDesignator:      "#",
				ExtraSecondaryNumber:     "410",
				ExtraSecondaryDesignator: "Apt",
				PMBNumber:                "411",
				PMBDesignator:            "Box",
				CityName:                 "Provo",
				DefaultCityName:          "Provo",
				StateAbbreviation:        "UT",
				ZIPCode:                  "84604",
				Plus4Code:                "4405",
				DeliveryPoint:            "14",
				DeliveryPointCheckDigit:  "0",
				Urbanization:             "urbanization",
			},
			Metadata: Metadata{
				RecordType:               "S",
				ZIPType:                  "Standard",
				CountyFIPS:               "49049",
				CountyName:               "Utah",
				CarrierRoute:             "C016",
				CongressionalDistrict:    "03",
				BuildingDefaultIndicator: "hi",
				RDI:                      "Commercial",
				ELOTSequence:             "0016",
				ELOTSort:                 "A",
				Latitude:                 40.27658,
				Longitude:                -111.65759,
				CoordinateLicense:        sdk.CoordinateLicenseSmartyStreetsProprietary,
				Precision:                "Rooftop",
				TimeZone:                 "Mountain",
				UTCOffset:                -7,
				DST:                      true,
				EWSMatch:                 true,
			},
			Analysis: Analysis{
				DPVMatchCode:      "S",
				DPVFootnotes:      "AACCRR",
				DPVCMRACode:       "Y",
				DPVVacantCode:     "N",
				DPVNoStat:         "N",
				Active:            "Y",
				Footnotes:         "footnotes",
				LACSLinkCode:      "lacslink_code",
				LACSLinkIndicator: "lacslink_indicator",
				SuiteLinkMatch:    true,
				EWSMatch:          false,
			},
		},
	})
}

/*////////////////////////////////////////////////////////////////////////*/

type FakeSender struct {
	callCount int

	request     *http.Request
	requestBody []byte

	response string
	err      error
}

func (f *FakeSender) Send(request *http.Request) ([]byte, error) {
	f.callCount++
	f.request = request
	if request != nil && request.Body != nil {
		f.requestBody, _ = ioutil.ReadAll(request.Body)
	}
	return []byte(f.response), f.err
}
<commit_msg>Tests for analysis updates.<commit_after>package street

import (
	"context"
	"errors"
	"io/ioutil"
	"net/http"
	"net/url"
	"testing"

	"github.com/smartystreets/assertions/should"
	"github.com/smartystreets/gunit"
	sdk "github.com/smartystreets/smartystreets-go-sdk"
)

func TestClientFixture(t *testing.T) {
	gunit.Run(new(ClientFixture), t)
}

type ClientFixture struct {
	*gunit.Fixture

	sender *FakeSender
	client *Client
	batch  *Batch
}

func (f *ClientFixture) Setup() {
	f.sender = &FakeSender{}
	f.client = NewClient(f.sender)
	f.batch = NewBatch()
}

func (f *ClientFixture) TestSingleAddressBatchWithContext_SentInQueryStringAsGET() {
	f.sender.response = `[{"input_index": 0, "input_id": "42"}]`
	input := &Lookup{InputID: "42"}
	f.batch.Append(input)

	ctx := context.WithValue(context.Background(), "key", "value")
	err := f.client.SendBatchWithContext(ctx, f.batch)

	f.So(err, should.BeNil)
	f.So(f.sender.request, should.NotBeNil)
	f.So(f.sender.request.Method, should.Equal, "GET")
	f.So(f.sender.request.URL.Path, should.Equal, "/street-address")
	f.So(f.sender.requestBody, should.BeNil)
	f.So(f.sender.request.ContentLength, should.Equal, 0)
	f.So(f.sender.request.URL.String(), should.StartWith, verifyURL)
	f.So(f.sender.request.URL.Query(), should.Resemble, url.Values{"input_id": {"42"}})
	f.So(f.sender.request.Context(), should.Resemble, ctx)
}

func (f *ClientFixture) TestAddressBatchSerializedAndSent__ResponseCandidatesIncorporatedIntoBatch() {
	f.sender.response = `[
		{"input_index": 0, "input_id": "42"},
		{"input_index": 2, "input_id": "44"},
		{"input_index": 2, "input_id": "44", "candidate_index": 1}
	]`
	input0 := &Lookup{InputID: "42"}
	input1 := &Lookup{InputID: "43"}
	input2 := &Lookup{InputID: "44"}
	f.batch.Append(input0)
	f.batch.Append(input1)
	f.batch.Append(input2)

	err := f.client.SendBatch(f.batch)

	f.So(err, should.BeNil)
	f.So(f.sender.request, should.NotBeNil)
	f.So(f.sender.request.Method, should.Equal, "POST")
	f.So(f.sender.request.URL.Path, should.Equal, "/street-address")
	f.So(f.sender.request.ContentLength, should.Equal, len(f.sender.requestBody))
	f.So(string(f.sender.requestBody), should.Equal, `[{"input_id":"42"},{"input_id":"43"},{"input_id":"44"}]`)
	f.So(f.sender.request.URL.String(), should.Equal, verifyURL)

	f.So(input0.Results, should.Resemble, []*Candidate{{InputID: "42"}})
	f.So(input1.Results, should.BeEmpty)
	f.So(input2.Results, should.Resemble, []*Candidate{{InputID: "44", InputIndex: 2}, {InputID: "44", InputIndex: 2, CandidateIndex: 1}})
}

func (f *ClientFixture) TestNilBatchNOP() {
	err := f.client.SendBatch(nil)
	f.So(err, should.BeNil)
	f.So(f.sender.request, should.BeNil)
}

func (f *ClientFixture) TestEmptyBatch_NOP() {
	err := f.client.SendBatch(new(Batch))
	f.So(err, should.BeNil)
	f.So(f.sender.request, should.BeNil)
}

func (f *ClientFixture) TestSenderErrorPreventsDeserialization() {
	f.sender.err = errors.New("GOPHERS!")
	f.sender.response = `[
		{"input_index": 0, "input_id": "42"},
		{"input_index": 2, "input_id": "44"},
		{"input_index": 2, "input_id": "44", "candidate_index": 1}
	]` // would be deserialized if not for the err (above)

	input := new(Lookup)
	f.batch.Append(input)

	err := f.client.SendBatch(f.batch)

	f.So(err, should.NotBeNil)
	f.So(input.Results, should.BeEmpty)
}

func (f *ClientFixture) TestDeserializationErrorPreventsDeserialization() {
	f.sender.response = `I can't haz JSON`
	input := new(Lookup)
	f.batch.Append(input)

	err := f.client.SendBatch(f.batch)

	f.So(err, should.NotBeNil)
	f.So(input.Results, should.BeEmpty)
}

func (f *ClientFixture) TestNullCandidatesWithinResponseArrayAreIgnoredAfterDeserialization() {
	f.sender.response = `[null]`
	lookup := new(Lookup)
	f.batch.Append(lookup)
	f.So(func() { f.client.SendBatch(f.batch) }, should.NotPanic)
	f.So(lookup.Results, should.BeEmpty)
}

func (f *ClientFixture) TestOutOfRangeCandidatesWithinResponseArrayAreIgnoredAfterDeserialization() {
	f.sender.response = `[{"input_index": 9999999}]`
	lookup := new(Lookup)
	f.batch.Append(lookup)
	f.So(func() { f.client.SendBatch(f.batch) }, should.NotPanic)
	f.So(lookup.Results, should.BeEmpty)
}

func (f *ClientFixture) TestFullJSONResponseDeserialization() {
	f.sender.response = `[
  {
	"input_id": "blah",
    "input_index": 0,
    "candidate_index": 4242,
	"addressee": "John Smith",
    "delivery_line_1": "3214 N University Ave # 409",
    "delivery_line_2": "blah blah",
    "last_line": "Provo UT 84604-4405",
    "delivery_point_barcode": "846044405140",
    "components": {
      "primary_number": "3214",
      "street_predirection": "N",
      "street_postdirection": "Q",
      "street_name": "University",
      "street_suffix": "Ave",
      "secondary_number": "409",
      "secondary_designator": "#",
      "extra_secondary_number": "410",
      "extra_secondary_designator": "Apt",
      "pmb_number": "411",
      "pmb_designator": "Box",
      "city_name": "Provo",
      "default_city_name": "Provo",
      "state_abbreviation": "UT",
      "zipcode": "84604",
      "plus4_code": "4405",
      "delivery_point": "14",
      "delivery_point_check_digit": "0",
      "urbanization": "urbanization"
    },
    "metadata": {
      "record_type": "S",
      "zip_type": "Standard",
      "county_fips": "49049",
      "county_name": "Utah",
      "carrier_route": "C016",
      "congressional_district": "03",
	  "building_default_indicator": "hi",
      "rdi": "Commercial",
      "elot_sequence": "0016",
      "elot_sort": "A",
      "latitude": 40.27658,
      "longitude": -111.65759,
      "coordinate_license": 1,
      "precision": "Rooftop",
      "time_zone": "Mountain",
      "utc_offset": -7,
      "dst": true,
	  "ews_match": true
    },
    "analysis": {
      "dpv_match_code": "S",
      "dpv_footnotes": "AACCRR",
      "dpv_cmra": "Y",
      "dpv_vacant": "N",
      "dpv_no_stat": "N",
      "active": "Y",
      "footnotes": "footnotes",
      "lacslink_code": "lacslink_code",
      "lacslink_indicator": "lacslink_indicator",
      "suitelink_match": true,
      "match_mode": "match_mode",
      "match_details": "match_details"
    }
  }
]`
	lookup := new(Lookup)
	f.batch.Append(lookup)
	err := f.client.SendBatch(f.batch)
	f.So(err, should.BeNil)
	f.So(lookup.Results, should.Resemble, []*Candidate{
		{
			InputID:              "blah",
			InputIndex:           0,
			CandidateIndex:       4242,
			Addressee:            "John Smith",
			DeliveryLine1:        "3214 N University Ave # 409",
			DeliveryLine2:        "blah blah",
			LastLine:             "Provo UT 84604-4405",
			DeliveryPointBarcode: "846044405140",
			Components: Components{
				PrimaryNumber:            "3214",
				StreetPredirection:       "N",
				StreetName:               "University",
				StreetPostdirection:      "Q",
				StreetSuffix:             "Ave",
				SecondaryNumber:          "409",
				SecondaryDesignator:      "#",
				ExtraSecondaryNumber:     "410",
				ExtraSecondaryDesignator: "Apt",
				PMBNumber:                "411",
				PMBDesignator:            "Box",
				CityName:                 "Provo",
				DefaultCityName:          "Provo",
				StateAbbreviation:        "UT",
				ZIPCode:                  "84604",
				Plus4Code:                "4405",
				DeliveryPoint:            "14",
				DeliveryPointCheckDigit:  "0",
				Urbanization:             "urbanization",
			},
			Metadata: Metadata{
				RecordType:               "S",
				ZIPType:                  "Standard",
				CountyFIPS:               "49049",
				CountyName:               "Utah",
				CarrierRoute:             "C016",
				CongressionalDistrict:    "03",
				BuildingDefaultIndicator: "hi",
				RDI:                      "Commercial",
				ELOTSequence:             "0016",
				ELOTSort:                 "A",
				Latitude:                 40.27658,
				Longitude:                -111.65759,
				CoordinateLicense:        sdk.CoordinateLicenseSmartyStreetsProprietary,
				Precision:                "Rooftop",
				TimeZone:                 "Mountain",
				UTCOffset:                -7,
				DST:                      true,
				EWSMatch:                 true,
			},
			Analysis: Analysis{
				DPVMatchCode:      "S",
				DPVFootnotes:      "AACCRR",
				DPVCMRACode:       "Y",
				DPVVacantCode:     "N",
				DPVNoStat:         "N",
				Active:            "Y",
				Footnotes:         "footnotes",
				LACSLinkCode:      "lacslink_code",
				LACSLinkIndicator: "lacslink_indicator",
				SuiteLinkMatch:    true,
				EWSMatch:          false,
				MatchMode:         "match_mode",
				MatchDetails:      "match_details",
			},
		},
	})
}

/*////////////////////////////////////////////////////////////////////////*/

type FakeSender struct {
	callCount int

	request     *http.Request
	requestBody []byte

	response string
	err      error
}

func (f *FakeSender) Send(request *http.Request) ([]byte, error) {
	f.callCount++
	f.request = request
	if request != nil && request.Body != nil {
		f.requestBody, _ = ioutil.ReadAll(request.Body)
	}
	return []byte(f.response), f.err
}
<|endoftext|>


<commit_before>package lua

import "testing"

func TestPushFStringPointer(t *testing.T) {
	l := NewState()
	l.PushFString("%p %s", l, "test")
}
<commit_msg>Improve unit test.<commit_after>package lua

import (
	"regexp"
	"testing"
)

// https://github.com/Shopify/go-lua/pull/63
func TestPushFStringPointer(t *testing.T) {
	l := NewState()
	l.PushFString("%p %s", l, "test")

	actual := CheckString(l, -1)
	ok, err := regexp.MatchString("0x[0-9a-f]+ test", actual)
	if !ok {
		t.Error("regex did not match")
	} else if err != nil {
		t.Errorf("regex error: %s", err.Error())
	}
}
<|endoftext|>


<commit_before>package dioder

import (
	"image/color"
	"reflect"
	"testing"
)

var piBlasterFile = "/dev/pi-blaster"

func TestNew(t *testing.T) {
	d := New(Pins{}, "")

	if reflect.TypeOf(d).String() != "dioder.Dioder" {
		t.Errorf("Got wrong dioder.Dioder object: %s", reflect.TypeOf(d))
	}
}

func TestDioderGetCurrentColor(t *testing.T) {
	dioder := New(Pins{"18", "17", "4"}, "/dev/pi-blaster")

	colorSet := dioder.GetCurrentColor()

	if colorSet.A != 0 {
		t.Error("Opacity is not 0")
	}

	if colorSet.R != 0 {
		t.Error("Red is not 0")
	}

	if colorSet.G != 0 {
		t.Error("Green is not 0")
	}

	if colorSet.B != 0 {
		t.Error("Blue is not 0")
	}
}

func TestDioderPinConfiguration(t *testing.T) {
	pinConfiguration := Pins{"18", "17", "4"}

	dioder := New(pinConfiguration, "/dev/pi-blaster")

	if dioder.PinConfiguration != pinConfiguration {
		t.Errorf("Pins are not correctly configured. Gave %s, got %s", pinConfiguration, dioder.PinConfiguration)
	}

	if dioder.PiBlaster != "/dev/pi-blaster" {
		t.Errorf("Pi-Blaster file wrong configured. Gave /dev/pi-blaster, got %s", dioder.PiBlaster)
	}
}

func TestDioderSetAll(t *testing.T) {
	d := New(Pins{}, "/dev/pi-blaster")

	d.SetAll(color.RGBA{})

	if d.ColorConfiguration.A != 0 {
		t.Error("Opacity is not correct")
	}

	if d.ColorConfiguration.R != 0 {
		t.Error("Red is not correct")
	}

	if d.ColorConfiguration.G != 0 {
		t.Error("Green is not correct")
	}

	if d.ColorConfiguration.B != 0 {
		t.Error("Blue is not correct")
	}
}

func TestDioderSetPins(t *testing.T) {
	d := New(Pins{"1", "2", "3"}, "/dev/pi-blaster")

	if d.PinConfiguration.Blue != "3" {
		t.Error("Blue pin is not correct")
	}

	if d.PinConfiguration.Green != "2" {
		t.Error("Green pin is not correct")
	}

	if d.PinConfiguration.Red != "1" {
		t.Error("Red pin is not correct")
	}
}
<commit_msg>Added tests for TurnOn() and TurnOff()<commit_after>package dioder

import (
	"image/color"
	"reflect"
	"testing"
)

var piBlasterFile = "/dev/pi-blaster"

func TestNew(t *testing.T) {
	d := New(Pins{}, "")

	if reflect.TypeOf(d).String() != "dioder.Dioder" {
		t.Errorf("Got wrong dioder.Dioder object: %s", reflect.TypeOf(d))
	}
}

func TestDioderGetCurrentColor(t *testing.T) {
	dioder := New(Pins{"18", "17", "4"}, piBlasterFile)

	colorSet := dioder.GetCurrentColor()

	if colorSet.A != 0 {
		t.Error("Opacity is not 0")
	}

	if colorSet.R != 0 {
		t.Error("Red is not 0")
	}

	if colorSet.G != 0 {
		t.Error("Green is not 0")
	}

	if colorSet.B != 0 {
		t.Error("Blue is not 0")
	}
}

func TestDioderPinConfiguration(t *testing.T) {
	pinConfiguration := Pins{"18", "17", "4"}

	dioder := New(pinConfiguration, piBlasterFile)

	if dioder.PinConfiguration != pinConfiguration {
		t.Errorf("Pins are not correctly configured. Gave %s, got %s", pinConfiguration, dioder.PinConfiguration)
	}

	if dioder.PiBlaster != "/dev/pi-blaster" {
		t.Errorf("Pi-Blaster file wrong configured. Gave /dev/pi-blaster, got %s", dioder.PiBlaster)
	}
}

func TestDioderSetAll(t *testing.T) {
	d := New(Pins{}, "/dev/pi-blaster")

	d.SetAll(color.RGBA{})

	if d.ColorConfiguration.A != 0 {
		t.Error("Opacity is not correct")
	}

	if d.ColorConfiguration.R != 0 {
		t.Error("Red is not correct")
	}

	if d.ColorConfiguration.G != 0 {
		t.Error("Green is not correct")
	}

	if d.ColorConfiguration.B != 0 {
		t.Error("Blue is not correct")
	}
}

func TestDioderSetPins(t *testing.T) {
	d := New(Pins{"1", "2", "3"}, piBlasterFile)

	if d.PinConfiguration.Blue != "3" {
		t.Error("Blue pin is not correct")
	}

	if d.PinConfiguration.Green != "2" {
		t.Error("Green pin is not correct")
	}

	if d.PinConfiguration.Red != "1" {
		t.Error("Red pin is not correct")
	}
}

func TestDidoerTurnOff(t *testing.T) {
	d := New(Pins{"1", "2", "3"}, piBlasterFile)

	configuration := d.ColorConfiguration

	d.TurnOff()

	if d.ColorConfiguration != configuration {
		t.Errorf("Didn't saved the current settings, had %d - got %d", configuration, d.ColorConfiguration)
	}
}

func TestDioderTurnOn(t *testing.T) {
	d := New(Pins{"1", "2", "3"}, piBlasterFile)

	d.TurnOff()
	d.TurnOn()

	if d.ColorConfiguration.A != 255 {
		t.Errorf("Value for opacity is wrong. Expected 0, got %d", d.ColorConfiguration.A)
	}
	if d.ColorConfiguration.R != 255 {
		t.Errorf("Value for red is wrong. Expected 0, got %d", d.ColorConfiguration.R)
	}
	if d.ColorConfiguration.G != 255 {
		t.Errorf("Value for green is wrong. Expected 0, got %d", d.ColorConfiguration.G)
	}
	if d.ColorConfiguration.B != 255 {
		t.Errorf("Value for blue is wrong. Expected 0, got %d", d.ColorConfiguration.B)
	}
}
<|endoftext|>


<commit_before>package main

import (
	. "github.com/conclave/pcduino/core"
)

func init() {
	Init()
	setup()
}

func main() {
	for {
		loop()
	}
}

func setup() {
}

func loop() {
	Delay(100)
}
<commit_msg>update test/linker_tilt_test<commit_after>package main

import (
	. "github.com/conclave/pcduino/core"
)

func init() {
	Init()
	setup()
}

func main() {
	for {
		loop()
	}
}

var ledPin byte = 0
var switchPin byte = 1
var val byte

func setup() {
	println("Tilt sensor test code!")
	println("Using I/O_0=Drive LED, I/O_1=Sensor output.")
	PinMode(ledPin, OUTPUT)
	PinMode(switchPin, INPUT)
}

func loop() {
	val = DigitalRead(switchPin)
	if val == HIGH {
		DigitalWrite(ledPin, HIGH)
	} else {
		DigitalWrite(ledPin, LOW)
	}
}
<|endoftext|>


<commit_before>package gin

import (
	"fmt"
	"log"
	"os"
	"time"
)

func ErrorLogger() HandlerFunc {
	return func(c *Context) {
		c.Next()

		if len(c.Errors) > 0 {
			// -1 status code = do not change current one
			c.JSON(-1, c.Errors)
		}
	}
}

var (
	green  = string([]byte{27, 91, 57, 55, 59, 52, 50, 109})
	white  = string([]byte{27, 91, 57, 48, 59, 52, 55, 109})
	yellow = string([]byte{27, 91, 57, 55, 59, 52, 51, 109})
	red    = string([]byte{27, 91, 57, 55, 59, 52, 49, 109})
	reset  = string([]byte{27, 91, 48, 109})
)

func Logger() HandlerFunc {
	logger := log.New(os.Stdout, "", 0)
	return func(c *Context) {
		// Start timer
		start := time.Now()

		// Process request
		c.Next()

		var color string
		code := c.Writer.Status()
		switch {
		case code >= 200 && code <= 299:
			color = green
		case code >= 300 && code <= 399:
			color = white
		case code >= 400 && code <= 499:
			color = yellow
		default:
			color = red
		}
		latency := time.Since(start)
		logger.Printf("[GIN] %v |%s %3d %s| %12v | %3.1f%% | %3s | %s\n",
			time.Now().Format("2006/01/02 - 15:04:05"),
			color, c.Writer.Status(), reset,
			latency,
			c.Engine.CacheStress()*100,
			c.Req.Method, c.Req.URL.Path,
		)

		// Calculate resolution time
		if len(c.Errors) > 0 {
			fmt.Println(c.Errors.String())
		}
	}
}
<commit_msg>Adds source IP in built-in logger<commit_after>package gin

import (
	"log"
	"os"
	"time"
)

func ErrorLogger() HandlerFunc {
	return func(c *Context) {
		c.Next()

		if len(c.Errors) > 0 {
			// -1 status code = do not change current one
			c.JSON(-1, c.Errors)
		}
	}
}

var (
	green  = string([]byte{27, 91, 57, 55, 59, 52, 50, 109})
	white  = string([]byte{27, 91, 57, 48, 59, 52, 55, 109})
	yellow = string([]byte{27, 91, 57, 55, 59, 52, 51, 109})
	red    = string([]byte{27, 91, 57, 55, 59, 52, 49, 109})
	reset  = string([]byte{27, 91, 48, 109})
)

func Logger() HandlerFunc {
	stdlogger := log.New(os.Stdout, "", 0)
	//errlogger := log.New(os.Stderr, "", 0)

	return func(c *Context) {
		// Start timer
		start := time.Now()

		// Process request
		c.Next()

		// save the IP of the requester
		requester := c.Req.Header.Get("X-Real-IP")
		// if the requester-header is empty, check the forwarded-header
		if requester == "" {
			requester = c.Req.Header.Get("X-Forwarded-For")
		}

		// if the requester is still empty, use the hard-coded address from the socket
		if requester == "" {
			requester = c.Req.RemoteAddr
		}

		var color string
		code := c.Writer.Status()
		switch {
		case code >= 200 && code <= 299:
			color = green
		case code >= 300 && code <= 399:
			color = white
		case code >= 400 && code <= 499:
			color = yellow
		default:
			color = red
		}
		latency := time.Since(start)
		stdlogger.Printf("[GIN] %v |%s %3d %s| %12v | %3.1f%% | %s %4s %s\n",
			time.Now().Format("2006/01/02 - 15:04:05"),
			color, c.Writer.Status(), reset,
			latency,
			c.Engine.CacheStress()*100,
			requester,
			c.Req.Method, c.Req.URL.Path,
		)

		// Calculate resolution time
		if len(c.Errors) > 0 {
			stdlogger.Println(c.Errors.String())
		}
	}
}
<|endoftext|>


<commit_before>// Credit to logrus project. Much of the code here is modified from the TextFormatter

package canoe

import (
	"bytes"
	"fmt"
	"github.com/sirupsen/logrus"
	"os"
	"runtime"
	"sort"
	"strings"
	"time"
)

var DefaultLogger = &logrus.Logger{
	Out: os.Stderr,
	Formatter: &TextFormatter{
		Prefix:        "canoe",
		FullTimestamp: true,
	},
	Level: logrus.InfoLevel,
}

const (
	nocolor = 0
	red     = 31
	green   = 32
	yellow  = 33
	blue    = 34
	gray    = 37
)

var (
	baseTimestamp time.Time
	isTerminal    bool
)

func init() {
	baseTimestamp = time.Now()
	isTerminal = logrus.IsTerminal()
}

func miniTS() int {
	return int(time.Since(baseTimestamp) / time.Second)
}

type TextFormatter struct {
	// String that all logs are prefixed with
	Prefix string

	// Set to true to bypass checking for a TTY before outputting colors.
	ForceColors bool

	// Force disabling colors.
	DisableColors bool

	// Disable timestamp logging. useful when output is redirected to logging
	// system that already adds timestamps.
	DisableTimestamp bool

	// Enable logging the full timestamp when a TTY is attached instead of just
	// the time passed since beginning of execution.
	FullTimestamp bool

	// TimestampFormat to use for display when a full timestamp is printed
	TimestampFormat string

	// The fields are sorted by default for a consistent output. For applications
	// that log extremely frequently and don't use the JSON formatter this may not
	// be desired.
	DisableSorting bool
}

func prefixFieldClashes(data logrus.Fields) {
	if t, ok := data["time"]; ok {
		data["fields.time"] = t
	}

	if m, ok := data["msg"]; ok {
		data["fields.msg"] = m
	}

	if l, ok := data["level"]; ok {
		data["fields.level"] = l
	}
}
func (f *TextFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	var keys []string = make([]string, 0, len(entry.Data))
	for k := range entry.Data {
		keys = append(keys, k)
	}

	if !f.DisableSorting {
		sort.Strings(keys)
	}

	b := &bytes.Buffer{}

	prefixFieldClashes(entry.Data)

	isColorTerminal := isTerminal && (runtime.GOOS != "windows")
	isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors

	b.WriteString(f.Prefix)

	timestampFormat := f.TimestampFormat
	if timestampFormat == "" {
		timestampFormat = logrus.DefaultTimestampFormat
	}
	if isColored {
		f.printColored(b, entry, keys, timestampFormat)
	} else {
		if !f.DisableTimestamp {
			f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat))
		}
		f.appendKeyValue(b, "level", entry.Level.String())
		if entry.Message != "" {
			f.appendKeyValue(b, "msg", entry.Message)
		}
		for _, key := range keys {
			f.appendKeyValue(b, key, entry.Data[key])
		}
	}

	b.WriteByte('\n')
	return b.Bytes(), nil
}

func (f *TextFormatter) printColored(b *bytes.Buffer, entry *logrus.Entry, keys []string, timestampFormat string) {
	var levelColor int
	switch entry.Level {
	case logrus.DebugLevel:
		levelColor = gray
	case logrus.WarnLevel:
		levelColor = yellow
	case logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel:
		levelColor = red
	default:
		levelColor = blue
	}

	levelText := strings.ToUpper(entry.Level.String())[0:4]

	if !f.FullTimestamp {
		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
	} else {
		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message)
	}
	for _, k := range keys {
		v := entry.Data[k]
		fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%+v", levelColor, k, v)
	}
}

func needsQuoting(text string) bool {
	for _, ch := range text {
		if !((ch >= 'a' && ch <= 'z') ||
			(ch >= 'A' && ch <= 'Z') ||
			(ch >= '0' && ch <= '9') ||
			ch == '-' || ch == '.') {
			return true
		}
	}
	return false
}

func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {

	b.WriteString(key)
	b.WriteByte('=')

	switch value := value.(type) {
	case string:
		if !needsQuoting(value) {
			b.WriteString(value)
		} else {
			fmt.Fprintf(b, "%q", value)
		}
	case error:
		errmsg := value.Error()
		if !needsQuoting(errmsg) {
			b.WriteString(errmsg)
		} else {
			fmt.Fprintf(b, "%q", value)
		}
	default:
		fmt.Fprint(b, value)
	}

	b.WriteByte(' ')
}
<commit_msg>get logger passing golint<commit_after>// Credit to logrus project. Much of the code here is modified from the TextFormatter

package canoe

import (
	"bytes"
	"fmt"
	"github.com/sirupsen/logrus"
	"os"
	"runtime"
	"sort"
	"strings"
	"time"
)

// DefaultLogger gives a default logger for canoe
var DefaultLogger = &logrus.Logger{
	Out: os.Stderr,
	Formatter: &textFormatter{
		Prefix:        "canoe",
		FullTimestamp: true,
	},
	Level: logrus.InfoLevel,
}

const (
	nocolor = 0
	red     = 31
	green   = 32
	yellow  = 33
	blue    = 34
	gray    = 37
)

var (
	baseTimestamp time.Time
	isTerminal    bool
)

func init() {
	baseTimestamp = time.Now()
	isTerminal = logrus.IsTerminal()
}

func miniTS() int {
	return int(time.Since(baseTimestamp) / time.Second)
}

//
type textFormatter struct {
	// String that all logs are prefixed with
	Prefix string

	// Set to true to bypass checking for a TTY before outputting colors.
	ForceColors bool

	// Force disabling colors.
	DisableColors bool

	// Disable timestamp logging. useful when output is redirected to logging
	// system that already adds timestamps.
	DisableTimestamp bool

	// Enable logging the full timestamp when a TTY is attached instead of just
	// the time passed since beginning of execution.
	FullTimestamp bool

	// TimestampFormat to use for display when a full timestamp is printed
	TimestampFormat string

	// The fields are sorted by default for a consistent output. For applications
	// that log extremely frequently and don't use the JSON formatter this may not
	// be desired.
	DisableSorting bool
}

func prefixFieldClashes(data logrus.Fields) {
	if t, ok := data["time"]; ok {
		data["fields.time"] = t
	}

	if m, ok := data["msg"]; ok {
		data["fields.msg"] = m
	}

	if l, ok := data["level"]; ok {
		data["fields.level"] = l
	}
}
func (f *textFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	var keys = make([]string, 0, len(entry.Data))
	for k := range entry.Data {
		keys = append(keys, k)
	}

	if !f.DisableSorting {
		sort.Strings(keys)
	}

	b := &bytes.Buffer{}

	prefixFieldClashes(entry.Data)

	isColorTerminal := isTerminal && (runtime.GOOS != "windows")
	isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors

	b.WriteString(f.Prefix)

	timestampFormat := f.TimestampFormat
	if timestampFormat == "" {
		timestampFormat = logrus.DefaultTimestampFormat
	}
	if isColored {
		f.printColored(b, entry, keys, timestampFormat)
	} else {
		if !f.DisableTimestamp {
			f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat))
		}
		f.appendKeyValue(b, "level", entry.Level.String())
		if entry.Message != "" {
			f.appendKeyValue(b, "msg", entry.Message)
		}
		for _, key := range keys {
			f.appendKeyValue(b, key, entry.Data[key])
		}
	}

	b.WriteByte('\n')
	return b.Bytes(), nil
}

func (f *textFormatter) printColored(b *bytes.Buffer, entry *logrus.Entry, keys []string, timestampFormat string) {
	var levelColor int
	switch entry.Level {
	case logrus.DebugLevel:
		levelColor = gray
	case logrus.WarnLevel:
		levelColor = yellow
	case logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel:
		levelColor = red
	default:
		levelColor = blue
	}

	levelText := strings.ToUpper(entry.Level.String())[0:4]

	if !f.FullTimestamp {
		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
	} else {
		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message)
	}
	for _, k := range keys {
		v := entry.Data[k]
		fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%+v", levelColor, k, v)
	}
}

func needsQuoting(text string) bool {
	for _, ch := range text {
		if !((ch >= 'a' && ch <= 'z') ||
			(ch >= 'A' && ch <= 'Z') ||
			(ch >= '0' && ch <= '9') ||
			ch == '-' || ch == '.') {
			return true
		}
	}
	return false
}

func (f *textFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {

	b.WriteString(key)
	b.WriteByte('=')

	switch value := value.(type) {
	case string:
		if !needsQuoting(value) {
			b.WriteString(value)
		} else {
			fmt.Fprintf(b, "%q", value)
		}
	case error:
		errmsg := value.Error()
		if !needsQuoting(errmsg) {
			b.WriteString(errmsg)
		} else {
			fmt.Fprintf(b, "%q", value)
		}
	default:
		fmt.Fprint(b, value)
	}

	b.WriteByte(' ')
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strconv"
	"strings"
)

// may just setup a global logger, and change output during runtime...
// http://codereview.stackexchange.com/a/59733

var logf *os.File
var logger *log.Logger

func initLoggerWriter(w io.Writer) {
	logger = log.New(w, "", log.Lshortfile|log.LstdFlags)
	logger.Println("initializing logger")
}

func initLogger() {
	if conf.out.logFile != "" && conf.out.printDebug {
		logf, err := os.OpenFile(conf.out.logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			fmt.Printf("error opening log file: %s, %v", conf.out.logFile, err)
			os.Exit(1)
		}

		initLoggerWriter(io.MultiWriter(logf, os.Stdout))
		return
	}

	if conf.out.logFile != "" {
		logf, err := os.OpenFile(conf.out.logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			fmt.Printf("error opening log file: %s, %v", conf.out.logFile, err)
			os.Exit(1)
		}

		initLoggerWriter(logf)
		return
	}

	if conf.out.printDebug {
		initLoggerWriter(os.Stdout)
		return
	}

	initLoggerWriter(ioutil.Discard)
}

func closeLogger() {
	if logf == nil {
		return
	}

	logf.Close()
}

type Color struct {
	Name string
	ID   int
}

var colors = []*Color{
	{"c", 0}, {"bold", 1}, {"black", 30}, {"red", 31}, {"green", 32}, {"yellow", 33},
	{"blue", 34}, {"magenta", 35}, {"cyan", 36}, {"white", 37}, {"gray", 90},
	{"lightred", 91}, {"lightgreen", 92}, {"lightyellow", 93}, {"lightblue", 94},
	{"lightmagenta", 95}, {"lightcyan", 96}, {"lightgray", 97},
}

func FmtColor(format *string, shouldStrip bool) {
	for _, clr := range colors {
		if shouldStrip {
			*format = strings.Replace(*format, "{"+clr.Name+"}", "", -1)
		} else {
			*format = strings.Replace(*format, "{"+clr.Name+"}", "\x1b["+strconv.Itoa(clr.ID)+"m", -1)
		}
	}

	if !shouldStrip {
		*format = *format + "\x1b[0;m"
	}

	return
}

type Output struct{}

// Printf interprets []*Color{} escape codes and prints them to stdout
func (o Output) Printf(format string, a ...interface{}) (n int, err error) {
	if conf.out.ignoreStd {
		return 0, nil
	}

	str := fmt.Sprintf(format, a...)
	FmtColor(&str, conf.out.noColors)

	return fmt.Print(str)
}

// Println interprets []*Color{} escape codes and prints them to stdout
func (o Output) Println(a ...interface{}) (n int, err error) {
	if conf.out.ignoreStd {
		return 0, nil
	}

	str := fmt.Sprintln(a...)
	FmtColor(&str, conf.out.noColors)
	return fmt.Print(str)
}

// Fatalf interprets []*Color{} escape codes and prints them to stdout
func (o Output) Fatalf(format string, a ...interface{}) {
	// print to regular stdout
	if !conf.out.ignoreStd {
		str := fmt.Sprintf(fmt.Sprintf("{bold}{red}error:{c} %s\n", format), a...)
		FmtColor(&str, conf.out.noColors)
		fmt.Print(str)
	}

	logger.Fatalf(format, a...)
}
<commit_msg>add Output.Fatal(), and StripColor()<commit_after>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strconv"
	"strings"
)

// may just setup a global logger, and change output during runtime...
// http://codereview.stackexchange.com/a/59733

var logf *os.File
var logger *log.Logger

func initLoggerWriter(w io.Writer) {
	logger = log.New(w, "", log.Lshortfile|log.LstdFlags)
	logger.Println("initializing logger")
}

func initLogger() {
	if conf.out.logFile != "" && conf.out.printDebug {
		logf, err := os.OpenFile(conf.out.logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			fmt.Printf("error opening log file: %s, %v", conf.out.logFile, err)
			os.Exit(1)
		}

		initLoggerWriter(io.MultiWriter(logf, os.Stdout))
		return
	}

	if conf.out.logFile != "" {
		logf, err := os.OpenFile(conf.out.logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			fmt.Printf("error opening log file: %s, %v", conf.out.logFile, err)
			os.Exit(1)
		}

		initLoggerWriter(logf)
		return
	}

	if conf.out.printDebug {
		initLoggerWriter(os.Stdout)
		return
	}

	initLoggerWriter(ioutil.Discard)
}

func closeLogger() {
	if logf == nil {
		return
	}

	logf.Close()
}

type Color struct {
	Name string
	ID   int
}

var colors = []*Color{
	{"c", 0}, {"bold", 1}, {"black", 30}, {"red", 31}, {"green", 32}, {"yellow", 33},
	{"blue", 34}, {"magenta", 35}, {"cyan", 36}, {"white", 37}, {"gray", 90},
	{"lightred", 91}, {"lightgreen", 92}, {"lightyellow", 93}, {"lightblue", 94},
	{"lightmagenta", 95}, {"lightcyan", 96}, {"lightgray", 97},
}

func StripColor(format *string) {
	for _, clr := range colors {
		*format = strings.Replace(*format, "{"+clr.Name+"}", "", -1)
	}
}

func FmtColor(format *string, shouldStrip bool) {
	if shouldStrip {
		StripColor(format)

		return
	}

	for _, clr := range colors {
		*format = strings.Replace(*format, "{"+clr.Name+"}", "\x1b["+strconv.Itoa(clr.ID)+"m", -1)
	}

	*format = *format + "\x1b[0;m"
}

type Output struct{}

// Printf interprets []*Color{} escape codes and prints them to stdout
func (o Output) Printf(format string, a ...interface{}) (n int, err error) {
	if conf.out.ignoreStd {
		return 0, nil
	}

	str := fmt.Sprintf(format, a...)
	FmtColor(&str, conf.out.noColors)

	return fmt.Print(str)
}

// Println interprets []*Color{} escape codes and prints them to stdout
func (o Output) Println(a ...interface{}) (n int, err error) {
	if conf.out.ignoreStd {
		return 0, nil
	}

	str := fmt.Sprintln(a...)
	FmtColor(&str, conf.out.noColors)
	return fmt.Print(str)
}

// Fatalf interprets []*Color{} escape codes and prints them to stdout/logger, and exits
func (o Output) Fatalf(format string, a ...interface{}) {
	// print to regular stdout
	if !conf.out.ignoreStd {
		str := fmt.Sprintf(fmt.Sprintf("{bold}{red}error:{c} %s\n", format), a...)
		FmtColor(&str, conf.out.noColors)
		fmt.Print(str)
	}

	// strip color from format
	StripColor(&format)
	logger.Fatalf("error: "+format, a...)
}

// Fatal interprets []*Color{} escape codes and prints them to stdout
func (o Output) Fatal(a ...interface{}) {
	// print to regular stdout
	if !conf.out.ignoreStd {
		str := fmt.Sprintf("{bold}{red}error:{c} %s", fmt.Sprintln(a...))
		FmtColor(&str, conf.out.noColors)
		fmt.Print(str)
	}

	str := fmt.Sprintln(a...)

	logger.Fatal("error: " + str)
}
<|endoftext|>


<commit_before>package httplog

import (
	"fmt"
	"github.com/dustin/go-humanize"
	"github.com/miolini/datacounter"
	"io"
	"net/http"
	"os"
	"time"
)

// FormatterFunc user defined formatter func
type FormatterFunc func(w io.Writer, r *http.Request, sentBytes uint64, elapsedTime time.Duration)

// DefaultFormatter default formatter func
var DefaultFormatter FormatterFunc = func(w io.Writer, r *http.Request, sentBytes uint64, elapsedTime time.Duration) {
	fmt.Fprintf(w, "%s [%.2fms %s] %s %s\n", time.Now().String(), elapsedTime.Seconds()*1000, humanize.Bytes(sentBytes), r.Method, r.URL.Path)
}

// Logger simple func for wrapping http.Handler and log to stderr
func Logger(h http.Handler) http.Handler {
	return LoggerWithWriterAndFormatter(h, os.Stderr, DefaultFormatter)
}

// LoggerWithFormatter wrapping func with user defined formatter
func LoggerWithFormatter(h http.Handler, formatter FormatterFunc) http.Handler {
	return LoggerWithWriterAndFormatter(h, os.Stderr, formatter)
}

// LoggerWithWriter func for wrapping http.Handler and user defined output io.Writer
func LoggerWithWriter(h http.Handler, w io.Writer) http.Handler {
	return LoggerWithWriterAndFormatter(h, w, DefaultFormatter)
}

// LoggerWithWriterAndFormatter func for wrapping http.Handler and user defined output io.Writer and FormatterFunc
func LoggerWithWriterAndFormatter(h http.Handler, lw io.Writer, formatter FormatterFunc) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		wcounter := datacounter.NewResponseWriterCounter(w)
		defer func(t time.Time) {
			formatter(lw, r, wcounter.Count(), time.Since(t))
		}(time.Now())
		h.ServeHTTP(wcounter, r)
	})
}
<commit_msg>change time layout<commit_after>package httplog

import (
	"fmt"
	"github.com/dustin/go-humanize"
	"github.com/miolini/datacounter"
	"io"
	"net/http"
	"os"
	"time"
)

// FormatterFunc user defined formatter func
type FormatterFunc func(w io.Writer, r *http.Request, sentBytes uint64, elapsedTime time.Duration)

// DefaultFormatter default formatter func
var DefaultFormatter FormatterFunc = func(w io.Writer, r *http.Request, sentBytes uint64, elapsedTime time.Duration) {
	fmt.Fprintf(w, "%s [%.2fms %s] %s %s\n", time.Now().Format("2005-Mo-2 15:04:05"),
		elapsedTime.Seconds()*1000, humanize.Bytes(sentBytes), r.Method, r.URL.Path)
}

// Logger simple func for wrapping http.Handler and log to stderr
func Logger(h http.Handler) http.Handler {
	return LoggerWithWriterAndFormatter(h, os.Stderr, DefaultFormatter)
}

// LoggerWithFormatter wrapping func with user defined formatter
func LoggerWithFormatter(h http.Handler, formatter FormatterFunc) http.Handler {
	return LoggerWithWriterAndFormatter(h, os.Stderr, formatter)
}

// LoggerWithWriter func for wrapping http.Handler and user defined output io.Writer
func LoggerWithWriter(h http.Handler, w io.Writer) http.Handler {
	return LoggerWithWriterAndFormatter(h, w, DefaultFormatter)
}

// LoggerWithWriterAndFormatter func for wrapping http.Handler and user defined output io.Writer and FormatterFunc
func LoggerWithWriterAndFormatter(h http.Handler, lw io.Writer, formatter FormatterFunc) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		wcounter := datacounter.NewResponseWriterCounter(w)
		defer func(t time.Time) {
			formatter(lw, r, wcounter.Count(), time.Since(t))
		}(time.Now())
		h.ServeHTTP(wcounter, r)
	})
}
<|endoftext|>


<commit_before>package allocationstore

import (
	"os"
	"sync"
	"time"

	"github.com/cloudfoundry-incubator/executor"
	"github.com/pivotal-golang/clock"
	"github.com/pivotal-golang/lager"
	"github.com/tedsuo/ifrit"
)

type AllocationStore struct {
	allocated    map[string]executor.Container
	clock        clock.Clock
	eventEmitter EventEmitter
	lock         sync.RWMutex
}

func NewAllocationStore(clock clock.Clock, eventEmitter EventEmitter) *AllocationStore {
	return &AllocationStore{
		allocated:    map[string]executor.Container{},
		clock:        clock,
		eventEmitter: eventEmitter,
	}
}

func (a *AllocationStore) List() []executor.Container {
	a.lock.RLock()
	defer a.lock.RUnlock()

	containers := make([]executor.Container, 0, len(a.allocated))

	for key := range a.allocated {
		containers = append(containers, a.allocated[key].Copy())
	}

	return containers
}

func (a *AllocationStore) Lookup(guid string) (executor.Container, error) {
	a.lock.RLock()
	defer a.lock.RUnlock()

	return a.lookup(guid)
}

func (a *AllocationStore) Allocate(logger lager.Logger, req *executor.AllocationRequest) (executor.Container, error) {
	a.lock.Lock()
	defer a.lock.Unlock()

	if _, err := a.lookup(req.Guid); err == nil {
		logger.Error("failed-allocating-container", err)
		return executor.Container{}, executor.ErrContainerGuidNotAvailable
	}

	logger.Debug("allocating-container", lager.Data{"allocation-request": req})

	a.allocated[req.Guid] = executor.NewReservedContainerFromAllocationRequest(req, a.clock.Now().UnixNano())

	a.eventEmitter.Emit(executor.NewContainerReservedEvent(a.allocated[req.Guid]))

	return a.allocated[req.Guid].Copy(), nil
}

func (a *AllocationStore) Initialize(logger lager.Logger, req *executor.RunRequest) error {
	a.lock.Lock()
	defer a.lock.Unlock()

	container, err := a.lookup(req.Guid)
	if err != nil {
		logger.Error("failed-initializing-container", err)
		return err
	}
	logger.Debug("initializing-container", lager.Data{"guid": req.Guid})

	if container.State != executor.StateReserved {
		logger.Error(
			"failed-initializing-container",
			executor.ErrInvalidTransition,
			lager.Data{
				"current_state":  container.State,
				"expected_state": executor.StateReserved,
			},
		)
		return executor.ErrInvalidTransition
	}

	container.State = executor.StateInitializing
	container.RunInfo = req.RunInfo
	container.Tags.Add(req.Tags)
	a.allocated[container.Guid] = container

	return nil
}

func (a *AllocationStore) Fail(logger lager.Logger, guid string, reason string) (executor.Container, error) {
	a.lock.Lock()
	defer a.lock.Unlock()

	container, err := a.lookup(guid)
	if err != nil {
		logger.Error("failed-completing-container", err)
		return executor.Container{}, err
	}

	if container.State == executor.StateCompleted {
		logger.Error(
			"failed-completing-container",
			executor.ErrInvalidTransition,
			lager.Data{
				"current_state":  container.State,
				"expected_state": executor.StateInitializing,
			},
		)
		return executor.Container{}, executor.ErrInvalidTransition
	}

	logger.Debug("marking-container-completed-with-failure-reason", lager.Data{
		"guid":           guid,
		"failure_reason": reason,
	})

	container.State = executor.StateCompleted
	container.RunResult = executor.ContainerRunResult{
		Failed:        true,
		FailureReason: reason,
	}
	a.allocated[guid] = container

	a.eventEmitter.Emit(executor.NewContainerCompleteEvent(container))

	return container, nil
}

func (a *AllocationStore) Deallocate(logger lager.Logger, guid string) bool {
	a.lock.Lock()
	defer a.lock.Unlock()

	_, allocated := a.allocated[guid]
	if !allocated {
		logger.Debug("container-already-deallocated", lager.Data{"guid": guid})
		return false
	}

	logger.Debug("deallocating-container", lager.Data{"guid": guid})

	delete(a.allocated, guid)

	return true
}

func (a *AllocationStore) lookup(guid string) (executor.Container, error) {
	container, found := a.allocated[guid]
	if !found {
		return executor.Container{}, executor.ErrContainerNotFound
	}

	return container, nil
}

func (a *AllocationStore) RegistryPruner(logger lager.Logger, expirationTime time.Duration) ifrit.Runner {
	logger = logger.Session("allocation-store-pruner")

	return ifrit.RunFunc(func(signals <-chan os.Signal, ready chan<- struct{}) error {
		ticker := a.clock.NewTicker(expirationTime / 2)
		defer ticker.Stop()

		close(ready)

		for {
			select {
			case <-signals:
				logger.Info("exiting-pruning-loop")
				return nil

			case <-ticker.C():
				logger.Debug("checking-for-expired-containers")
				expiredAllocations := []string{}

				a.lock.Lock()

				for guid, container := range a.allocated {
					if container.State != executor.StateReserved {
						// only prune reserved containers
						continue
					}

					lifespan := a.clock.Now().Sub(time.Unix(0, container.AllocatedAt))

					if lifespan >= expirationTime {
						logger.Info("reserved-container-expired", lager.Data{"guid": guid, "lifespan": lifespan})
						expiredAllocations = append(expiredAllocations, guid)
					}
				}

				if len(expiredAllocations) > 0 {
					logger.Info("reaping-expired-allocations", lager.Data{"num-reaped": len(expiredAllocations)})
				} else {
					logger.Info("no-expired-allocations-found")
				}

				for _, guid := range expiredAllocations {
					logger.Info("deleting-expired-container", lager.Data{"guid": guid})
					delete(a.allocated, guid)
				}

				a.lock.Unlock()
			}
		}

		return nil
	})
}
<commit_msg>Log when finishing allocating a container<commit_after>package allocationstore

import (
	"os"
	"sync"
	"time"

	"github.com/cloudfoundry-incubator/executor"
	"github.com/pivotal-golang/clock"
	"github.com/pivotal-golang/lager"
	"github.com/tedsuo/ifrit"
)

type AllocationStore struct {
	allocated    map[string]executor.Container
	clock        clock.Clock
	eventEmitter EventEmitter
	lock         sync.RWMutex
}

func NewAllocationStore(clock clock.Clock, eventEmitter EventEmitter) *AllocationStore {
	return &AllocationStore{
		allocated:    map[string]executor.Container{},
		clock:        clock,
		eventEmitter: eventEmitter,
	}
}

func (a *AllocationStore) List() []executor.Container {
	a.lock.RLock()
	defer a.lock.RUnlock()

	containers := make([]executor.Container, 0, len(a.allocated))

	for key := range a.allocated {
		containers = append(containers, a.allocated[key].Copy())
	}

	return containers
}

func (a *AllocationStore) Lookup(guid string) (executor.Container, error) {
	a.lock.RLock()
	defer a.lock.RUnlock()

	return a.lookup(guid)
}

func (a *AllocationStore) Allocate(logger lager.Logger, req *executor.AllocationRequest) (executor.Container, error) {
	a.lock.Lock()
	defer a.lock.Unlock()

	if _, err := a.lookup(req.Guid); err == nil {
		logger.Error("failed-allocating-container", err)
		return executor.Container{}, executor.ErrContainerGuidNotAvailable
	}

	logger.Debug("allocating-container", lager.Data{"allocation-request": req})
	defer logger.Debug("finished-allocating-container", lager.Data{"allocation-request": req})

	a.allocated[req.Guid] = executor.NewReservedContainerFromAllocationRequest(req, a.clock.Now().UnixNano())

	a.eventEmitter.Emit(executor.NewContainerReservedEvent(a.allocated[req.Guid]))

	return a.allocated[req.Guid].Copy(), nil
}

func (a *AllocationStore) Initialize(logger lager.Logger, req *executor.RunRequest) error {
	a.lock.Lock()
	defer a.lock.Unlock()

	container, err := a.lookup(req.Guid)
	if err != nil {
		logger.Error("failed-initializing-container", err)
		return err
	}
	logger.Debug("initializing-container", lager.Data{"guid": req.Guid})

	if container.State != executor.StateReserved {
		logger.Error(
			"failed-initializing-container",
			executor.ErrInvalidTransition,
			lager.Data{
				"current_state":  container.State,
				"expected_state": executor.StateReserved,
			},
		)
		return executor.ErrInvalidTransition
	}

	container.State = executor.StateInitializing
	container.RunInfo = req.RunInfo
	container.Tags.Add(req.Tags)
	a.allocated[container.Guid] = container

	return nil
}

func (a *AllocationStore) Fail(logger lager.Logger, guid string, reason string) (executor.Container, error) {
	a.lock.Lock()
	defer a.lock.Unlock()

	container, err := a.lookup(guid)
	if err != nil {
		logger.Error("failed-completing-container", err)
		return executor.Container{}, err
	}

	if container.State == executor.StateCompleted {
		logger.Error(
			"failed-completing-container",
			executor.ErrInvalidTransition,
			lager.Data{
				"current_state":  container.State,
				"expected_state": executor.StateInitializing,
			},
		)
		return executor.Container{}, executor.ErrInvalidTransition
	}

	logger.Debug("marking-container-completed-with-failure-reason", lager.Data{
		"guid":           guid,
		"failure_reason": reason,
	})

	container.State = executor.StateCompleted
	container.RunResult = executor.ContainerRunResult{
		Failed:        true,
		FailureReason: reason,
	}
	a.allocated[guid] = container

	a.eventEmitter.Emit(executor.NewContainerCompleteEvent(container))

	return container, nil
}

func (a *AllocationStore) Deallocate(logger lager.Logger, guid string) bool {
	a.lock.Lock()
	defer a.lock.Unlock()

	_, allocated := a.allocated[guid]
	if !allocated {
		logger.Debug("container-already-deallocated", lager.Data{"guid": guid})
		return false
	}

	logger.Debug("deallocating-container", lager.Data{"guid": guid})

	delete(a.allocated, guid)

	return true
}

func (a *AllocationStore) lookup(guid string) (executor.Container, error) {
	container, found := a.allocated[guid]
	if !found {
		return executor.Container{}, executor.ErrContainerNotFound
	}

	return container, nil
}

func (a *AllocationStore) RegistryPruner(logger lager.Logger, expirationTime time.Duration) ifrit.Runner {
	logger = logger.Session("allocation-store-pruner")

	return ifrit.RunFunc(func(signals <-chan os.Signal, ready chan<- struct{}) error {
		ticker := a.clock.NewTicker(expirationTime / 2)
		defer ticker.Stop()

		close(ready)

		for {
			select {
			case <-signals:
				logger.Info("exiting-pruning-loop")
				return nil

			case <-ticker.C():
				logger.Debug("checking-for-expired-containers")
				expiredAllocations := []string{}

				a.lock.Lock()

				for guid, container := range a.allocated {
					if container.State != executor.StateReserved {
						// only prune reserved containers
						continue
					}

					lifespan := a.clock.Now().Sub(time.Unix(0, container.AllocatedAt))

					if lifespan >= expirationTime {
						logger.Info("reserved-container-expired", lager.Data{"guid": guid, "lifespan": lifespan})
						expiredAllocations = append(expiredAllocations, guid)
					}
				}

				if len(expiredAllocations) > 0 {
					logger.Info("reaping-expired-allocations", lager.Data{"num-reaped": len(expiredAllocations)})
				} else {
					logger.Info("no-expired-allocations-found")
				}

				for _, guid := range expiredAllocations {
					logger.Info("deleting-expired-container", lager.Data{"guid": guid})
					delete(a.allocated, guid)
				}

				a.lock.Unlock()
			}
		}

		return nil
	})
}
<|endoftext|>


<commit_before>package main

import (
	"os"

	"github.com/docker/docker/cli/config"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
)

// filled in at compile time
var gitCommit = ""

const (
	version = "2.0.1-dev"
	usage   = "registry client to inspect and push multi-platform OCI & Docker v2 images"
)

func main() {
	if err := runApplication(); err != nil {
		logrus.Errorf("manifest-tool failed with error: %v", err)
		os.Exit(1)
	}
	os.Exit(0)
}

func runApplication() error {
	app := cli.NewApp()
	app.Name = os.Args[0]
	app.Version = version + " (commit: " + gitCommit + ")"
	app.Usage = usage
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "debug",
			Usage: "enable debug output",
		},
		cli.BoolFlag{
			Name:  "insecure",
			Usage: "allow insecure registry communication",
		},
		cli.BoolFlag{
			Name:  "plain-http",
			Usage: "allow registry communication over plain http",
		},
		cli.StringFlag{
			Name:  "username",
			Value: "",
			Usage: "registry username",
		},
		cli.StringFlag{
			Name:  "password",
			Value: "",
			Usage: "registry password",
		},
		cli.StringFlag{
			Name:  "docker-cfg",
			Value: config.Dir(),
			Usage: "Docker's cli config for auth",
		},
	}
	app.Before = func(c *cli.Context) error {
		if c.GlobalBool("debug") {
			logrus.SetLevel(logrus.DebugLevel)
		} else {
			logrus.SetLevel(logrus.WarnLevel)
		}
		return nil
	}
	// currently support inspect and pushml
	app.Commands = []cli.Command{
		inspectCmd,
		pushCmd,
	}

	return app.Run(os.Args)
}
<commit_msg>Prepare patch release v2.0.1<commit_after>package main

import (
	"os"

	"github.com/docker/docker/cli/config"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
)

// filled in at compile time
var gitCommit = ""

const (
	version = "2.0.1"
	usage   = "registry client to inspect and push multi-platform OCI & Docker v2 images"
)

func main() {
	if err := runApplication(); err != nil {
		logrus.Errorf("manifest-tool failed with error: %v", err)
		os.Exit(1)
	}
	os.Exit(0)
}

func runApplication() error {
	app := cli.NewApp()
	app.Name = os.Args[0]
	app.Version = version + " (commit: " + gitCommit + ")"
	app.Usage = usage
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "debug",
			Usage: "enable debug output",
		},
		cli.BoolFlag{
			Name:  "insecure",
			Usage: "allow insecure registry communication",
		},
		cli.BoolFlag{
			Name:  "plain-http",
			Usage: "allow registry communication over plain http",
		},
		cli.StringFlag{
			Name:  "username",
			Value: "",
			Usage: "registry username",
		},
		cli.StringFlag{
			Name:  "password",
			Value: "",
			Usage: "registry password",
		},
		cli.StringFlag{
			Name:  "docker-cfg",
			Value: config.Dir(),
			Usage: "Docker's cli config for auth",
		},
	}
	app.Before = func(c *cli.Context) error {
		if c.GlobalBool("debug") {
			logrus.SetLevel(logrus.DebugLevel)
		} else {
			logrus.SetLevel(logrus.WarnLevel)
		}
		return nil
	}
	// currently support inspect and pushml
	app.Commands = []cli.Command{
		inspectCmd,
		pushCmd,
	}

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