<commit_before>package zoom // Use this file for /user endpoints

import "fmt"

const (
	listUsersPath      = "/users"
	getUserPath        = "/users/%s"
	getUserByEmailPath = "/user/getbyemail"
)

// ListUsersResponse contains the response from a call to ListUsers
type ListUsersResponse struct {
	TotalRecords int    `json:"total_records"`
	PageCount    int    `json:"page_count"`
	PageNumber   int    `json:"page_number"`
	PageSize     int    `json:"page_size"`
	Users        []User `json:"users"`
}

// ListUsersOptions contains options for ListUsers
type ListUsersOptions struct {
	PageSize   int         `url:"page_size"`
	PageNumber int         `url:"page_number"`
	Status     *UserStatus `url:"status,omitempty"`
}

// ListUsers calls /user/list, listing all users, using the default client
func ListUsers(opts ...ListUsersOptions) (ListUsersResponse, error) {
	return defaultClient.ListUsers(opts...)
}

// ListUsers calls /user/list, listing all users, using client c
func (c *Client) ListUsers(opts ...ListUsersOptions) (ListUsersResponse, error) {
	var ret = ListUsersResponse{}
	return ret, requestV2(c, Get, listUsersPath, opts, nil, &ret)
}

// GetUserOpts contains options for GetUser
type GetUserOpts struct {
	EmailOrID string
	LoginType *UserLoginType `url:"login_type,omitempty"` // use pointer so it can be null
}

// GetUser calls /users/{userId}, searching for a user by ID or email, using the default client
func GetUser(opts GetUserOpts) (User, error) {
	return defaultClient.GetUser(opts)
}

// GetUser calls /users/{userId}, searching for a user by ID or email, using a specific client
func (c *Client) GetUser(opts GetUserOpts) (User, error) {
	var ret = User{}
	return ret, requestV2(c, Get, fmt.Sprintf(getUserPath, opts.EmailOrID), opts, nil, &ret)
}
<commit_msg>Remove reference to deprecated method<commit_after>package zoom // Use this file for /user endpoints

import "fmt"

const (
	listUsersPath = "/users"
	getUserPath   = "/users/%s"
)

// ListUsersResponse contains the response from a call to ListUsers
type ListUsersResponse struct {
	TotalRecords int    `json:"total_records"`
	PageCount    int    `json:"page_count"`
	PageNumber   int    `json:"page_number"`
	PageSize     int    `json:"page_size"`
	Users        []User `json:"users"`
}

// ListUsersOptions contains options for ListUsers
type ListUsersOptions struct {
	PageSize   int         `url:"page_size"`
	PageNumber int         `url:"page_number"`
	Status     *UserStatus `url:"status,omitempty"`
}

// ListUsers calls /user/list, listing all users, using the default client
func ListUsers(opts ...ListUsersOptions) (ListUsersResponse, error) {
	return defaultClient.ListUsers(opts...)
}

// ListUsers calls /user/list, listing all users, using client c
func (c *Client) ListUsers(opts ...ListUsersOptions) (ListUsersResponse, error) {
	var ret = ListUsersResponse{}
	return ret, requestV2(c, Get, listUsersPath, opts, nil, &ret)
}

// GetUserOpts contains options for GetUser
type GetUserOpts struct {
	EmailOrID string
	LoginType *UserLoginType `url:"login_type,omitempty"` // use pointer so it can be null
}

// GetUser calls /users/{userId}, searching for a user by ID or email, using the default client
func GetUser(opts GetUserOpts) (User, error) {
	return defaultClient.GetUser(opts)
}

// GetUser calls /users/{userId}, searching for a user by ID or email, using a specific client
func (c *Client) GetUser(opts GetUserOpts) (User, error) {
	var ret = User{}
	return ret, requestV2(c, Get, fmt.Sprintf(getUserPath, opts.EmailOrID), opts, nil, &ret)
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors.

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

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

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

package healthz

import (
	"errors"
	"fmt"
	"net/http"
	"net/http/httptest"
	"net/url"
	"reflect"
	"strings"
	"testing"

	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apiserver/pkg/endpoints/metrics"
	"k8s.io/component-base/metrics/legacyregistry"
	"k8s.io/component-base/metrics/testutil"
)

func TestInstallHandler(t *testing.T) {
	mux := http.NewServeMux()
	InstallHandler(mux)
	req, err := http.NewRequest("GET", "http://example.com/healthz", nil)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	w := httptest.NewRecorder()
	mux.ServeHTTP(w, req)
	if w.Code != http.StatusOK {
		t.Errorf("expected %v, got %v", http.StatusOK, w.Code)
	}
	c := w.Header().Get("Content-Type")
	if c != "text/plain; charset=utf-8" {
		t.Errorf("expected %v, got %v", "text/plain", c)
	}
	if w.Body.String() != "ok" {
		t.Errorf("expected %v, got %v", "ok", w.Body.String())
	}
}

func TestInstallPathHandler(t *testing.T) {
	mux := http.NewServeMux()
	InstallPathHandler(mux, "/healthz/test")
	InstallPathHandler(mux, "/healthz/ready")
	req, err := http.NewRequest("GET", "http://example.com/healthz/test", nil)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	w := httptest.NewRecorder()
	mux.ServeHTTP(w, req)
	if w.Code != http.StatusOK {
		t.Errorf("expected %v, got %v", http.StatusOK, w.Code)
	}
	c := w.Header().Get("Content-Type")
	if c != "text/plain; charset=utf-8" {
		t.Errorf("expected %v, got %v", "text/plain", c)
	}
	if w.Body.String() != "ok" {
		t.Errorf("expected %v, got %v", "ok", w.Body.String())
	}

	req, err = http.NewRequest("GET", "http://example.com/healthz/ready", nil)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	w = httptest.NewRecorder()
	mux.ServeHTTP(w, req)
	if w.Code != http.StatusOK {
		t.Errorf("expected %v, got %v", http.StatusOK, w.Code)
	}
	c = w.Header().Get("Content-Type")
	if c != "text/plain; charset=utf-8" {
		t.Errorf("expected %v, got %v", "text/plain", c)
	}
	if w.Body.String() != "ok" {
		t.Errorf("expected %v, got %v", "ok", w.Body.String())
	}

}

func testMultipleChecks(path string, t *testing.T) {
	tests := []struct {
		path             string
		expectedResponse string
		expectedStatus   int
		addBadCheck      bool
	}{
		{"?verbose", "[+]ping ok\nhealthz check passed\n", http.StatusOK, false},
		{"?exclude=dontexist", "ok", http.StatusOK, false},
		{"?exclude=bad", "ok", http.StatusOK, true},
		{"?verbose=true&exclude=bad", "[+]ping ok\n[+]bad excluded: ok\nhealthz check passed\n", http.StatusOK, true},
		{"?verbose=true&exclude=dontexist", "[+]ping ok\nwarn: some health checks cannot be excluded: no matches for \"dontexist\"\nhealthz check passed\n", http.StatusOK, false},
		{"/ping", "ok", http.StatusOK, false},
		{"", "ok", http.StatusOK, false},
		{"?verbose", "[+]ping ok\n[-]bad failed: reason withheld\nhealthz check failed\n", http.StatusInternalServerError, true},
		{"/ping", "ok", http.StatusOK, true},
		{"/bad", "internal server error: this will fail\n", http.StatusInternalServerError, true},
		{"", "[+]ping ok\n[-]bad failed: reason withheld\nhealthz check failed\n", http.StatusInternalServerError, true},
	}

	for i, test := range tests {
		mux := http.NewServeMux()
		checks := []HealthChecker{PingHealthz}
		if test.addBadCheck {
			checks = append(checks, NamedCheck("bad", func(_ *http.Request) error {
				return errors.New("this will fail")
			}))
		}
		if path == "" {
			InstallHandler(mux, checks...)
			path = "/healthz"
		} else {
			InstallPathHandler(mux, path, checks...)
		}
		req, err := http.NewRequest("GET", fmt.Sprintf("http://example.com%s%v", path, test.path), nil)
		if err != nil {
			t.Fatalf("case[%d] Unexpected error: %v", i, err)
		}
		w := httptest.NewRecorder()
		mux.ServeHTTP(w, req)
		if w.Code != test.expectedStatus {
			t.Errorf("case[%d] Expected: %v, got: %v", i, test.expectedStatus, w.Code)
		}
		c := w.Header().Get("Content-Type")
		if c != "text/plain; charset=utf-8" {
			t.Errorf("case[%d] Expected: %v, got: %v", i, "text/plain", c)
		}
		if w.Body.String() != test.expectedResponse {
			t.Errorf("case[%d] Expected:\n%v\ngot:\n%v\n", i, test.expectedResponse, w.Body.String())
		}
	}
}

func TestMultipleChecks(t *testing.T) {
	testMultipleChecks("", t)
}

func TestMultiplePathChecks(t *testing.T) {
	testMultipleChecks("/ready", t)
}

func TestCheckerNames(t *testing.T) {
	n1 := "n1"
	n2 := "n2"
	c1 := &healthzCheck{name: n1}
	c2 := &healthzCheck{name: n2}

	testCases := []struct {
		desc string
		have []HealthChecker
		want []string
	}{
		{"no checker", []HealthChecker{}, []string{}},
		{"one checker", []HealthChecker{c1}, []string{n1}},
		{"other checker", []HealthChecker{c2}, []string{n2}},
		{"checker order", []HealthChecker{c1, c2}, []string{n1, n2}},
		{"different checker order", []HealthChecker{c2, c1}, []string{n2, n1}},
	}

	for _, tc := range testCases {
		result := checkerNames(tc.have...)
		t.Run(tc.desc, func(t *testing.T) {
			if !reflect.DeepEqual(tc.want, result) {
				t.Errorf("want %#v, got %#v", tc.want, result)
			}
		})
	}
}

func TestFormatQuoted(t *testing.T) {
	n1 := "n1"
	n2 := "n2"
	testCases := []struct {
		desc     string
		names    []string
		expected string
	}{
		{"empty", []string{}, ""},
		{"single name", []string{n1}, "\"n1\""},
		{"two names", []string{n1, n2}, "\"n1\",\"n2\""},
		{"two names, reverse order", []string{n2, n1}, "\"n2\",\"n1\""},
	}
	for _, tc := range testCases {
		result := formatQuoted(tc.names...)
		t.Run(tc.desc, func(t *testing.T) {
			if result != tc.expected {
				t.Errorf("expected %#v, got %#v", tc.expected, result)
			}
		})
	}
}

func TestGetExcludedChecks(t *testing.T) {
	type args struct {
		r *http.Request
	}
	tests := []struct {
		name string
		r    *http.Request
		want sets.String
	}{
		{"Should have no excluded health checks",
			createGetRequestWithUrl("/healthz?verbose=true"),
			sets.NewString(),
		},
		{"Should extract out the ping health check",
			createGetRequestWithUrl("/healthz?exclude=ping"),
			sets.NewString("ping"),
		},
		{"Should extract out ping and log health check",
			createGetRequestWithUrl("/healthz?exclude=ping&exclude=log"),
			sets.NewString("ping", "log"),
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := getExcludedChecks(tt.r); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("getExcludedChecks() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestMetrics(t *testing.T) {
	mux := http.NewServeMux()
	InstallHandler(mux)
	InstallLivezHandler(mux)
	InstallReadyzHandler(mux)
	metrics.Register()
	metrics.Reset()

	paths := []string{"/healthz", "/livez", "/readyz"}
	for _, path := range paths {
		req, err := http.NewRequest("GET", fmt.Sprintf("http://example.com%s", path), nil)
		if err != nil {
			t.Errorf("%v", err)
		}
		mux.ServeHTTP(httptest.NewRecorder(), req)
	}

	expected := strings.NewReader(`
        # HELP apiserver_request_total [ALPHA] Counter of apiserver requests broken out for each verb, dry run value, group, version, resource, scope, component, client, and HTTP response contentType and code.
        # TYPE apiserver_request_total counter
        apiserver_request_total{client="unknown",code="200",component="",contentType="text/plain; charset=utf-8",dry_run="",group="",resource="",scope="",subresource="/healthz",verb="GET",version=""} 1
        apiserver_request_total{client="unknown",code="200",component="",contentType="text/plain; charset=utf-8",dry_run="",group="",resource="",scope="",subresource="/livez",verb="GET",version=""} 1
        apiserver_request_total{client="unknown",code="200",component="",contentType="text/plain; charset=utf-8",dry_run="",group="",resource="",scope="",subresource="/readyz",verb="GET",version=""} 1
`)
	if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, expected, "apiserver_request_total"); err != nil {
		t.Error(err)
	}
}

func createGetRequestWithUrl(rawUrlString string) *http.Request {
	url, _ := url.Parse(rawUrlString)
	return &http.Request{
		Method: http.MethodGet,
		Proto:  "HTTP/1.1",
		URL:    url,
	}
}
<commit_msg>remove client label from healthz metric test<commit_after>/*
Copyright 2014 The Kubernetes Authors.

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

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

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

package healthz

import (
	"errors"
	"fmt"
	"net/http"
	"net/http/httptest"
	"net/url"
	"reflect"
	"strings"
	"testing"

	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apiserver/pkg/endpoints/metrics"
	"k8s.io/component-base/metrics/legacyregistry"
	"k8s.io/component-base/metrics/testutil"
)

func TestInstallHandler(t *testing.T) {
	mux := http.NewServeMux()
	InstallHandler(mux)
	req, err := http.NewRequest("GET", "http://example.com/healthz", nil)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	w := httptest.NewRecorder()
	mux.ServeHTTP(w, req)
	if w.Code != http.StatusOK {
		t.Errorf("expected %v, got %v", http.StatusOK, w.Code)
	}
	c := w.Header().Get("Content-Type")
	if c != "text/plain; charset=utf-8" {
		t.Errorf("expected %v, got %v", "text/plain", c)
	}
	if w.Body.String() != "ok" {
		t.Errorf("expected %v, got %v", "ok", w.Body.String())
	}
}

func TestInstallPathHandler(t *testing.T) {
	mux := http.NewServeMux()
	InstallPathHandler(mux, "/healthz/test")
	InstallPathHandler(mux, "/healthz/ready")
	req, err := http.NewRequest("GET", "http://example.com/healthz/test", nil)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	w := httptest.NewRecorder()
	mux.ServeHTTP(w, req)
	if w.Code != http.StatusOK {
		t.Errorf("expected %v, got %v", http.StatusOK, w.Code)
	}
	c := w.Header().Get("Content-Type")
	if c != "text/plain; charset=utf-8" {
		t.Errorf("expected %v, got %v", "text/plain", c)
	}
	if w.Body.String() != "ok" {
		t.Errorf("expected %v, got %v", "ok", w.Body.String())
	}

	req, err = http.NewRequest("GET", "http://example.com/healthz/ready", nil)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	w = httptest.NewRecorder()
	mux.ServeHTTP(w, req)
	if w.Code != http.StatusOK {
		t.Errorf("expected %v, got %v", http.StatusOK, w.Code)
	}
	c = w.Header().Get("Content-Type")
	if c != "text/plain; charset=utf-8" {
		t.Errorf("expected %v, got %v", "text/plain", c)
	}
	if w.Body.String() != "ok" {
		t.Errorf("expected %v, got %v", "ok", w.Body.String())
	}

}

func testMultipleChecks(path string, t *testing.T) {
	tests := []struct {
		path             string
		expectedResponse string
		expectedStatus   int
		addBadCheck      bool
	}{
		{"?verbose", "[+]ping ok\nhealthz check passed\n", http.StatusOK, false},
		{"?exclude=dontexist", "ok", http.StatusOK, false},
		{"?exclude=bad", "ok", http.StatusOK, true},
		{"?verbose=true&exclude=bad", "[+]ping ok\n[+]bad excluded: ok\nhealthz check passed\n", http.StatusOK, true},
		{"?verbose=true&exclude=dontexist", "[+]ping ok\nwarn: some health checks cannot be excluded: no matches for \"dontexist\"\nhealthz check passed\n", http.StatusOK, false},
		{"/ping", "ok", http.StatusOK, false},
		{"", "ok", http.StatusOK, false},
		{"?verbose", "[+]ping ok\n[-]bad failed: reason withheld\nhealthz check failed\n", http.StatusInternalServerError, true},
		{"/ping", "ok", http.StatusOK, true},
		{"/bad", "internal server error: this will fail\n", http.StatusInternalServerError, true},
		{"", "[+]ping ok\n[-]bad failed: reason withheld\nhealthz check failed\n", http.StatusInternalServerError, true},
	}

	for i, test := range tests {
		mux := http.NewServeMux()
		checks := []HealthChecker{PingHealthz}
		if test.addBadCheck {
			checks = append(checks, NamedCheck("bad", func(_ *http.Request) error {
				return errors.New("this will fail")
			}))
		}
		if path == "" {
			InstallHandler(mux, checks...)
			path = "/healthz"
		} else {
			InstallPathHandler(mux, path, checks...)
		}
		req, err := http.NewRequest("GET", fmt.Sprintf("http://example.com%s%v", path, test.path), nil)
		if err != nil {
			t.Fatalf("case[%d] Unexpected error: %v", i, err)
		}
		w := httptest.NewRecorder()
		mux.ServeHTTP(w, req)
		if w.Code != test.expectedStatus {
			t.Errorf("case[%d] Expected: %v, got: %v", i, test.expectedStatus, w.Code)
		}
		c := w.Header().Get("Content-Type")
		if c != "text/plain; charset=utf-8" {
			t.Errorf("case[%d] Expected: %v, got: %v", i, "text/plain", c)
		}
		if w.Body.String() != test.expectedResponse {
			t.Errorf("case[%d] Expected:\n%v\ngot:\n%v\n", i, test.expectedResponse, w.Body.String())
		}
	}
}

func TestMultipleChecks(t *testing.T) {
	testMultipleChecks("", t)
}

func TestMultiplePathChecks(t *testing.T) {
	testMultipleChecks("/ready", t)
}

func TestCheckerNames(t *testing.T) {
	n1 := "n1"
	n2 := "n2"
	c1 := &healthzCheck{name: n1}
	c2 := &healthzCheck{name: n2}

	testCases := []struct {
		desc string
		have []HealthChecker
		want []string
	}{
		{"no checker", []HealthChecker{}, []string{}},
		{"one checker", []HealthChecker{c1}, []string{n1}},
		{"other checker", []HealthChecker{c2}, []string{n2}},
		{"checker order", []HealthChecker{c1, c2}, []string{n1, n2}},
		{"different checker order", []HealthChecker{c2, c1}, []string{n2, n1}},
	}

	for _, tc := range testCases {
		result := checkerNames(tc.have...)
		t.Run(tc.desc, func(t *testing.T) {
			if !reflect.DeepEqual(tc.want, result) {
				t.Errorf("want %#v, got %#v", tc.want, result)
			}
		})
	}
}

func TestFormatQuoted(t *testing.T) {
	n1 := "n1"
	n2 := "n2"
	testCases := []struct {
		desc     string
		names    []string
		expected string
	}{
		{"empty", []string{}, ""},
		{"single name", []string{n1}, "\"n1\""},
		{"two names", []string{n1, n2}, "\"n1\",\"n2\""},
		{"two names, reverse order", []string{n2, n1}, "\"n2\",\"n1\""},
	}
	for _, tc := range testCases {
		result := formatQuoted(tc.names...)
		t.Run(tc.desc, func(t *testing.T) {
			if result != tc.expected {
				t.Errorf("expected %#v, got %#v", tc.expected, result)
			}
		})
	}
}

func TestGetExcludedChecks(t *testing.T) {
	type args struct {
		r *http.Request
	}
	tests := []struct {
		name string
		r    *http.Request
		want sets.String
	}{
		{"Should have no excluded health checks",
			createGetRequestWithUrl("/healthz?verbose=true"),
			sets.NewString(),
		},
		{"Should extract out the ping health check",
			createGetRequestWithUrl("/healthz?exclude=ping"),
			sets.NewString("ping"),
		},
		{"Should extract out ping and log health check",
			createGetRequestWithUrl("/healthz?exclude=ping&exclude=log"),
			sets.NewString("ping", "log"),
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := getExcludedChecks(tt.r); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("getExcludedChecks() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestMetrics(t *testing.T) {
	mux := http.NewServeMux()
	InstallHandler(mux)
	InstallLivezHandler(mux)
	InstallReadyzHandler(mux)
	metrics.Register()
	metrics.Reset()

	paths := []string{"/healthz", "/livez", "/readyz"}
	for _, path := range paths {
		req, err := http.NewRequest("GET", fmt.Sprintf("http://example.com%s", path), nil)
		if err != nil {
			t.Errorf("%v", err)
		}
		mux.ServeHTTP(httptest.NewRecorder(), req)
	}

	expected := strings.NewReader(`
        # HELP apiserver_request_total [ALPHA] Counter of apiserver requests broken out for each verb, dry run value, group, version, resource, scope, component, and HTTP response contentType and code.
        # TYPE apiserver_request_total counter
        apiserver_request_total{code="200",component="",contentType="text/plain; charset=utf-8",dry_run="",group="",resource="",scope="",subresource="/healthz",verb="GET",version=""} 1
        apiserver_request_total{code="200",component="",contentType="text/plain; charset=utf-8",dry_run="",group="",resource="",scope="",subresource="/livez",verb="GET",version=""} 1
        apiserver_request_total{code="200",component="",contentType="text/plain; charset=utf-8",dry_run="",group="",resource="",scope="",subresource="/readyz",verb="GET",version=""} 1
`)
	if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, expected, "apiserver_request_total"); err != nil {
		t.Error(err)
	}
}

func createGetRequestWithUrl(rawUrlString string) *http.Request {
	url, _ := url.Parse(rawUrlString)
	return &http.Request{
		Method: http.MethodGet,
		Proto:  "HTTP/1.1",
		URL:    url,
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"bytes"
	"strings"
	"time"
	"io/ioutil"
	"regexp"
	"log"
	"sync"
)

var (
	photoRe = regexp.MustCompile(`(?i)^[^\.].*\.(dng|cr2|jpg|jpeg|arw|orf)$`)
	videoRe = regexp.MustCompile(`(?i)^[^\.].*\.(mov|mp4|wmv|avi)$`)
)
func IsDirectory(name string) (isDir bool, err error) {
	info, err := os.Stat(name)
	if err != nil {
		return false, err
	}
	return info.IsDir(), nil
}

func GetExifData(file string) (map[string]string, error) {
	cmd := exec.Command("exiftool", file)

	var out bytes.Buffer
	cmd.Stdout = &out

	if err := cmd.Run(); err != nil {
		return nil, err
	}

	tags := make(map[string]string)

	data := strings.Trim(out.String(), " \r\n")
	lines := strings.Split(data, "\n")

	for _, line := range lines {
		k, v := strings.Replace(strings.TrimSpace(line[0:32]), " ", "", -1), strings.TrimSpace(line[33:])
		tags[k] = v
	}

	return tags, nil
}

func GetDateDirPath(exif map[string]string) (string, error) {
	t, err := time.Parse("2006:01:02 15:04:05", exif["Date/TimeOriginal"])
	if err == nil {
		return t.Format("2006/01/02"), nil
	}

	t, err = time.Parse("2006:01:02 15:04:05", exif["CreateDate"])
	if err == nil {
		return t.Format("2006/01/02"), nil
	}

	return "", err
}

func MoveFile(src, dst string, option *Option) (error) {
	if !option.Force {
		_, err := os.Stat(dst)
		if err != nil {
			return err
		}
	}

	inputFile, err := os.Open(src)
	if err != nil {
			return fmt.Errorf("Couldn't open source file: %s", err)
	}
	outputFile, err := os.Create(dst)
	if err != nil {
			inputFile.Close()
			return fmt.Errorf("Couldn't open dest file: %s", err)
	}
	defer outputFile.Close()
	_, err = io.Copy(outputFile, inputFile)
	inputFile.Close()
	if err != nil {
			return fmt.Errorf("Writing to output file failed: %s", err)
	}
	// The copy was successful, so now delete the original file
	err = os.Remove(src)
	if err != nil {
			return fmt.Errorf("Failed removing original file: %s", err)
	}
	return nil
}

func IsIgnoreFile(name string, option *Option) (bool) {
	if name == "." || name == ".." {
		return true
	}

	for _, v := range option.Excludes {
		if name == v {
			return true
		}
	}

	return false
}

func GetFileNum(from string, option *Option) (int, error) {
	fileInfos, readErr := ioutil.ReadDir(from + "/")
	if readErr != nil {
		return 0, readErr
	}

	num := 0
	for _, fileInfo := range fileInfos {
		name := (fileInfo).Name()
		if IsIgnoreFile(name, option) {
			continue
		}

		filePath := from + "/" + name
		isDir, err := IsDirectory(filePath)
		if err != nil {
			return 0, err
		}

		if isDir {
			if option.Recursive {
				subNum, subErr := GetFileNum(from + "/" + name, option)
				if subErr != nil {
					return 0, subErr
				}
				num += subNum
			}
		} else {
			if photoRe.MatchString(name) || videoRe.MatchString(name) {
				num += 1
			}
		}
	}

	return num, nil
}

func TransferFile(name, filePath, dir string, option *Option) {
	exif, _ := GetExifData(filePath)
	if option.Verbose {
		log.Println(exif)
	}
	dateDirPath, dateDirPathErr := GetDateDirPath(exif)
	if dateDirPathErr != nil {
		if option.SkipInvalidData {
			log.Printf("skip %s. Can't get date dir path.", filePath)
			return
		} else {
			log.Fatal(dateDirPathErr)
		}
	}

	dstDir := option.To + "/" + dir + "/" + dateDirPath + "/"
	if option.DryRun == false {
		mkdirErr := os.MkdirAll(dstDir, 0755)
		if mkdirErr != nil {
			log.Fatal(mkdirErr)
		}
	}

	dstPath := dstDir + name
	log.Printf("%s -> %s", filePath, dstPath)

	if option.DryRun == false {
		moveErr := MoveFile(filePath, dstPath, option)
		if moveErr != nil {
			log.Fatal(moveErr)
		}
	}
}

func Transfer(wg *sync.WaitGroup, ch chan int, from string, option *Option) {
	fileInfos, readErr := ioutil.ReadDir(from + "/")
	if readErr != nil {
		log.Fatal(readErr)
	}

	for _, fileInfo := range fileInfos {
		wg.Add(1)
		go func(fileInfo os.FileInfo) {
			defer wg.Done()
			ch <- 1

			name := (fileInfo).Name()
			if IsIgnoreFile(name, option) {
				<-ch
				return
			}

			filePath := from + "/" + name
			isDir, err := IsDirectory(filePath)
			if err != nil {
				log.Fatal(err)
			}

			if isDir {
				if option.Recursive {
					Transfer(wg, ch, filePath, option)
				}
			} else {
				if photoRe.MatchString(name) {
					TransferFile(name, filePath, option.PhotoDir, option)
				} else if videoRe.MatchString(name) {
					TransferFile(name, filePath, option.VideoDir, option)
				}
			}

			<-ch
		}(fileInfo)
	}
}
<commit_msg>reformat<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"sync"
	"time"
)

var (
	photoRe = regexp.MustCompile(`(?i)^[^\.].*\.(dng|cr2|jpg|jpeg|arw|orf)$`)
	videoRe = regexp.MustCompile(`(?i)^[^\.].*\.(mov|mp4|wmv|avi)$`)
)

func IsDirectory(name string) (isDir bool, err error) {
	info, err := os.Stat(name)
	if err != nil {
		return false, err
	}
	return info.IsDir(), nil
}

func GetExifData(file string) (map[string]string, error) {
	cmd := exec.Command("exiftool", file)

	var out bytes.Buffer
	cmd.Stdout = &out

	if err := cmd.Run(); err != nil {
		return nil, err
	}

	tags := make(map[string]string)

	data := strings.Trim(out.String(), " \r\n")
	lines := strings.Split(data, "\n")

	for _, line := range lines {
		k, v := strings.Replace(strings.TrimSpace(line[0:32]), " ", "", -1), strings.TrimSpace(line[33:])
		tags[k] = v
	}

	return tags, nil
}

func GetDateDirPath(exif map[string]string) (string, error) {
	t, err := time.Parse("2006:01:02 15:04:05", exif["Date/TimeOriginal"])
	if err == nil {
		return t.Format("2006/01/02"), nil
	}

	t, err = time.Parse("2006:01:02 15:04:05", exif["CreateDate"])
	if err == nil {
		return t.Format("2006/01/02"), nil
	}

	return "", err
}

func MoveFile(src, dst string, option *Option) error {
	if !option.Force {
		_, err := os.Stat(dst)
		if err != nil {
			return err
		}
	}

	inputFile, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("Couldn't open source file: %s", err)
	}
	outputFile, err := os.Create(dst)
	if err != nil {
		inputFile.Close()
		return fmt.Errorf("Couldn't open dest file: %s", err)
	}
	defer outputFile.Close()
	_, err = io.Copy(outputFile, inputFile)
	inputFile.Close()
	if err != nil {
		return fmt.Errorf("Writing to output file failed: %s", err)
	}
	// The copy was successful, so now delete the original file
	err = os.Remove(src)
	if err != nil {
		return fmt.Errorf("Failed removing original file: %s", err)
	}
	return nil
}

func IsIgnoreFile(name string, option *Option) bool {
	if name == "." || name == ".." {
		return true
	}

	for _, v := range option.Excludes {
		if name == v {
			return true
		}
	}

	return false
}

func GetFileNum(from string, option *Option) (int, error) {
	fileInfos, readErr := ioutil.ReadDir(from + "/")
	if readErr != nil {
		return 0, readErr
	}

	num := 0
	for _, fileInfo := range fileInfos {
		name := (fileInfo).Name()
		if IsIgnoreFile(name, option) {
			continue
		}

		filePath := from + "/" + name
		isDir, err := IsDirectory(filePath)
		if err != nil {
			return 0, err
		}

		if isDir {
			if option.Recursive {
				subNum, subErr := GetFileNum(from+"/"+name, option)
				if subErr != nil {
					return 0, subErr
				}
				num += subNum
			}
		} else {
			if photoRe.MatchString(name) || videoRe.MatchString(name) {
				num += 1
			}
		}
	}

	return num, nil
}

func TransferFile(name, filePath, dir string, option *Option) {
	exif, _ := GetExifData(filePath)
	if option.Verbose {
		log.Println(exif)
	}
	dateDirPath, dateDirPathErr := GetDateDirPath(exif)
	if dateDirPathErr != nil {
		if option.SkipInvalidData {
			log.Printf("skip %s. Can't get date dir path.", filePath)
			return
		} else {
			log.Fatal(dateDirPathErr)
		}
	}

	dstDir := option.To + "/" + dir + "/" + dateDirPath + "/"
	if option.DryRun == false {
		mkdirErr := os.MkdirAll(dstDir, 0755)
		if mkdirErr != nil {
			log.Fatal(mkdirErr)
		}
	}

	dstPath := dstDir + name
	log.Printf("%s -> %s", filePath, dstPath)

	if option.DryRun == false {
		moveErr := MoveFile(filePath, dstPath, option)
		if moveErr != nil {
			log.Fatal(moveErr)
		}
	}
}

func Transfer(wg *sync.WaitGroup, ch chan int, from string, option *Option) {
	fileInfos, readErr := ioutil.ReadDir(from + "/")
	if readErr != nil {
		log.Fatal(readErr)
	}

	for _, fileInfo := range fileInfos {
		wg.Add(1)
		go func(fileInfo os.FileInfo) {
			defer wg.Done()
			ch <- 1

			name := (fileInfo).Name()
			if IsIgnoreFile(name, option) {
				<-ch
				return
			}

			filePath := from + "/" + name
			isDir, err := IsDirectory(filePath)
			if err != nil {
				log.Fatal(err)
			}

			if isDir {
				if option.Recursive {
					Transfer(wg, ch, filePath, option)
				}
			} else {
				if photoRe.MatchString(name) {
					TransferFile(name, filePath, option.PhotoDir, option)
				} else if videoRe.MatchString(name) {
					TransferFile(name, filePath, option.VideoDir, option)
				}
			}

			<-ch
		}(fileInfo)
	}
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2012 Matthias S. Benkmann

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA  02110-1301, USA.
*/

// Various re-usable utility functions.
package util

import (
         "io"
         "fmt"
         "net"
         "time"
         "bytes"
         "crypto/md5"
       )

// Returns the md5sum of its argument as a string of hex digits.
func Md5sum(s string) string {
  md5 := md5.New()
  io.WriteString(md5, s)
  return fmt.Sprintf("%x",md5.Sum(nil))
}

// Number of consecutive short writes before WriteAll() will give up
// ATTENTION! The wait time between tries increases exponetially, so don't
// blindly increase this number.
const write_all_max_tries = 8

// Writes data to w, with automatic handling of short writes.
// A short write error will only be returned if multiple attempts
// failed in a row.
func WriteAll(w io.Writer, data []byte) (n int, err error) {
  // Yeah, I know. Other people just ignore the issue of
  // short writes. That's why their code fails more often than mine :-P
  tries := write_all_max_tries
  var bytes_written int
  for n = 0; n < len(data); {
    bytes_written, err = w.Write(data[n:])
    n += bytes_written

    if err != nil && err != io.ErrShortWrite {
      return n, err
    }

    if bytes_written == 0 {
      tries--
      if tries <= 0 {
        if err == nil {
          err = io.ErrShortWrite
        }
        return n, err
      }

      // The first time we don't sleep. The 2nd time we sleep 1ms. The 3rd time 2ms.
      // The 4th time 4ms. Then 8ms, 16ms, 32ms, 64ms,...
      var wait time.Duration = (1 << (write_all_max_tries-2)) >> uint(tries)
      time.Sleep(wait * time.Millisecond)

    } else {
      tries = write_all_max_tries  // every time we succeed at writing we start tries again
    }
  }

  return n, nil
}

// Opens a connection to target (e.g. "foo.example.com:20081"), sends msg followed
// by \r\n and then closes the connection.
// If timeout >= 0, then the connection will be terminated after at most this duration.
func SendLnTo(target string, msg string, timeout time.Duration) {
  conn, err := net.Dial("tcp", target)
  if err != nil {
    Log(0, "ERROR! Dial: %v", err)
    return
  }
  defer conn.Close()
  SendLn(conn, msg, timeout)
}

// Sends strings via connection conn, followed by "\r\n"
// If timeout >= 0, then the connection will be terminated after at most this duration.
func SendLn(conn net.Conn, s string, timeout time.Duration) {
  sendbuf := make([]byte, len(s)+2)
  copy(sendbuf, s)
  sendbuf[len(s)]='\r'
  sendbuf[len(s)+1]='\n'

  if timeout >= 0 {
    conn.SetWriteDeadline(time.Now().Add(timeout))
  }
  _, err := WriteAll(conn, sendbuf)
  if err != nil {
    Log(0, "ERROR! WriteAll: %v", err)
  }
}

// Reads from the connection until \n is seen (or timeout or error) and
// returns the first line with trailing \n and \r removed.
// If timeout >= 0, then the connection will be terminated after at most this duration.
func ReadLn(conn net.Conn, timeout time.Duration) string {
  var buf = make([]byte, 65536)
  i := 0
  n := 1

  if timeout >= 0 {
    conn.SetReadDeadline(time.Now().Add(timeout))
  }
  var err error
  for n != 0 {
    n, err = conn.Read(buf[i:])
    if err != nil && err != io.EOF {
      Log(0, "ERROR! Read: %v", err)
    }
    if err == io.EOF && i != 0 {
      Log(0, "ERROR! Incomplete message (i.e. not terminated by \"\\n\") of %v bytes", i)
    }

    i += n

    if i == len(buf) {
      buf_new := make([]byte, len(buf)+65536)
      copy(buf_new, buf)
      buf = buf_new
    }

    // Find complete line terminated by '\n' and return it
    eol := bytes.IndexByte(buf[0:i], '\n')

    if eol >= 0 {
      for ; eol >= 0 && (buf[eol] == '\n' || buf[eol] == '\r') ; { eol-- }
      return string(buf[0:eol+1])
    }
  }

  return ""
}
<commit_msg>add panic handlers to goroutines to make go-susi more robust<commit_after>/*
Copyright (c) 2012 Matthias S. Benkmann

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA  02110-1301, USA.
*/

// Various re-usable utility functions.
package util

import (
         "io"
         "fmt"
         "net"
         "time"
         "bytes"
         "crypto/md5"
         "runtime/debug"
       )

// Returns the md5sum of its argument as a string of hex digits.
func Md5sum(s string) string {
  md5 := md5.New()
  io.WriteString(md5, s)
  return fmt.Sprintf("%x",md5.Sum(nil))
}

// Number of consecutive short writes before WriteAll() will give up
// ATTENTION! The wait time between tries increases exponetially, so don't
// blindly increase this number.
const write_all_max_tries = 8

// Calls g wrapped in a panic handler that logs the panic and recovers from it.
// Example:
//   go util.WithPanicHandler(foobar)
//   go util.WithPanicHandler(func(){ Send_foreign_job_updates(server, jobs) })
func WithPanicHandler(g func()) {
  defer func() {
    if x := recover(); x != nil {
      Log(0, "PANIC! %v\n%v", x, string(debug.Stack()))
    }
  }()
  g()
}

// Writes data to w, with automatic handling of short writes.
// A short write error will only be returned if multiple attempts
// failed in a row.
func WriteAll(w io.Writer, data []byte) (n int, err error) {
  // Yeah, I know. Other people just ignore the issue of
  // short writes. That's why their code fails more often than mine :-P
  tries := write_all_max_tries
  var bytes_written int
  for n = 0; n < len(data); {
    bytes_written, err = w.Write(data[n:])
    n += bytes_written

    if err != nil && err != io.ErrShortWrite {
      return n, err
    }

    if bytes_written == 0 {
      tries--
      if tries <= 0 {
        if err == nil {
          err = io.ErrShortWrite
        }
        return n, err
      }

      // The first time we don't sleep. The 2nd time we sleep 1ms. The 3rd time 2ms.
      // The 4th time 4ms. Then 8ms, 16ms, 32ms, 64ms,...
      var wait time.Duration = (1 << (write_all_max_tries-2)) >> uint(tries)
      time.Sleep(wait * time.Millisecond)

    } else {
      tries = write_all_max_tries  // every time we succeed at writing we start tries again
    }
  }

  return n, nil
}

// Opens a connection to target (e.g. "foo.example.com:20081"), sends msg followed
// by \r\n and then closes the connection.
// If timeout >= 0, then the connection will be terminated after at most this duration.
func SendLnTo(target string, msg string, timeout time.Duration) {
  conn, err := net.Dial("tcp", target)
  if err != nil {
    Log(0, "ERROR! Dial: %v", err)
    return
  }
  defer conn.Close()
  SendLn(conn, msg, timeout)
}

// Sends strings via connection conn, followed by "\r\n"
// If timeout >= 0, then the connection will be terminated after at most this duration.
func SendLn(conn net.Conn, s string, timeout time.Duration) {
  sendbuf := make([]byte, len(s)+2)
  copy(sendbuf, s)
  sendbuf[len(s)]='\r'
  sendbuf[len(s)+1]='\n'

  if timeout >= 0 {
    conn.SetWriteDeadline(time.Now().Add(timeout))
  }
  _, err := WriteAll(conn, sendbuf)
  if err != nil {
    Log(0, "ERROR! WriteAll: %v", err)
  }
}

// Reads from the connection until \n is seen (or timeout or error) and
// returns the first line with trailing \n and \r removed.
// If timeout >= 0, then the connection will be terminated after at most this duration.
func ReadLn(conn net.Conn, timeout time.Duration) string {
  var buf = make([]byte, 65536)
  i := 0
  n := 1

  if timeout >= 0 {
    conn.SetReadDeadline(time.Now().Add(timeout))
  }
  var err error
  for n != 0 {
    n, err = conn.Read(buf[i:])
    if err != nil && err != io.EOF {
      Log(0, "ERROR! Read: %v", err)
    }
    if err == io.EOF && i != 0 {
      Log(0, "ERROR! Incomplete message (i.e. not terminated by \"\\n\") of %v bytes", i)
    }

    i += n

    if i == len(buf) {
      buf_new := make([]byte, len(buf)+65536)
      copy(buf_new, buf)
      buf = buf_new
    }

    // Find complete line terminated by '\n' and return it
    eol := bytes.IndexByte(buf[0:i], '\n')

    if eol >= 0 {
      for ; eol >= 0 && (buf[eol] == '\n' || buf[eol] == '\r') ; { eol-- }
      return string(buf[0:eol+1])
    }
  }

  return ""
}
<|endoftext|>


<commit_before>package store

import (
	"reflect"
	"time"

	"github.com/mxk/go-sqlite/sqlite3"
)

// TypeMap is a convenience type to reduce typing.
type TypeMap map[string]interface{}

// Interface is the data interface for the database.
type Interface interface {
	// Get returns a TypeMap of column name -> *type.
	Get() TypeMap
	// Key returns the column name of the primary key.
	Key() string
}

// InterfaceTable is an extension of Interface which allows a custom table name.
type InterfaceTable interface {
	Interface
	// TableName returns the custom table name for the type.
	TableName() string
}

type sort struct {
	Interface
	sortBy string
	asc    bool
}

func Sort(data []Interface, sortBy string, asc bool) []Interface {
	if len(data) > 0 {
		data[0] = sort{data[0], sortBy, asc}
	}
	return data
}

type statement struct {
	*sqlite3.Stmt
	vars []string
}

func (s statement) Vars(t map[string]interface{}) []interface{} {
	r := make([]interface{}, len(s.vars))
	for i, v := range s.vars {
		r[i] = t[v]
	}
	return r
}

func tableName(t Interface) string {
	if s, ok := t.(sort); ok {
		t = s.Interface
	}
	if it, ok := t.(InterfaceTable); ok {
		return it.TableName()
	}
	name := reflect.TypeOf(t).String()
	if name[0] == '*' {
		name = name[1:]
	}
	return name
}

func getType(i interface{}) string {
	switch i.(type) {
	case *bool, *int, *int64, *time.Time:
		return "INTEGER"
	case *float64:
		return "FLOAT"
	case *string:
		return "TEXT"
	case *[]byte:
		return "BLOB"
	}
	return ""
}

func unPointers(is []interface{}) []interface{} {
	for n := range is {
		is[n] = unPointer(is[n])
	}
	return is
}

func unPointer(i interface{}) interface{} {
	switch v := i.(type) {
	case *bool:
		return *v
	case *int:
		return *v
	case *int64:
		return *v
	case *float64:
		return *v
	case *string:
		return *v
	case *[]byte:
		return *v
	default:
		return nil
	}
}
<commit_msg>Added comment<commit_after>package store

import (
	"reflect"
	"time"

	"github.com/mxk/go-sqlite/sqlite3"
)

// TypeMap is a convenience type to reduce typing.
type TypeMap map[string]interface{}

// Interface is the data interface for the database.
type Interface interface {
	// Get returns a TypeMap of column name -> *type.
	Get() TypeMap
	// Key returns the column name of the primary key.
	Key() string
}

// InterfaceTable is an extension of Interface which allows a custom table name.
type InterfaceTable interface {
	Interface
	// TableName returns the custom table name for the type.
	TableName() string
}

type sort struct {
	Interface
	sortBy string
	asc    bool
}

// Sort provides a way to sort the data by a specific column
func Sort(data []Interface, sortBy string, asc bool) []Interface {
	if len(data) > 0 {
		data[0] = sort{data[0], sortBy, asc}
	}
	return data
}

type statement struct {
	*sqlite3.Stmt
	vars []string
}

func (s statement) Vars(t map[string]interface{}) []interface{} {
	r := make([]interface{}, len(s.vars))
	for i, v := range s.vars {
		r[i] = t[v]
	}
	return r
}

func tableName(t Interface) string {
	if s, ok := t.(sort); ok {
		t = s.Interface
	}
	if it, ok := t.(InterfaceTable); ok {
		return it.TableName()
	}
	name := reflect.TypeOf(t).String()
	if name[0] == '*' {
		name = name[1:]
	}
	return name
}

func getType(i interface{}) string {
	switch i.(type) {
	case *bool, *int, *int64, *time.Time:
		return "INTEGER"
	case *float64:
		return "FLOAT"
	case *string:
		return "TEXT"
	case *[]byte:
		return "BLOB"
	}
	return ""
}

func unPointers(is []interface{}) []interface{} {
	for n := range is {
		is[n] = unPointer(is[n])
	}
	return is
}

func unPointer(i interface{}) interface{} {
	switch v := i.(type) {
	case *bool:
		return *v
	case *int:
		return *v
	case *int64:
		return *v
	case *float64:
		return *v
	case *string:
		return *v
	case *[]byte:
		return *v
	default:
		return nil
	}
}
<|endoftext|>


<commit_before>package gg

import (
	"fmt"
	"image"
	"image/draw"
	"image/png"
	"io/ioutil"
	"math"
	"os"
	"strings"

	"github.com/golang/freetype/raster"
	"github.com/golang/freetype/truetype"

	"golang.org/x/image/font"
	"golang.org/x/image/math/fixed"
)

func Radians(degrees float64) float64 {
	return degrees * math.Pi / 180
}

func Degrees(radians float64) float64 {
	return radians * 180 / math.Pi
}

func LoadPNG(path string) (image.Image, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	return png.Decode(file)
}

func SavePNG(path string, im image.Image) error {
	file, err := os.Create(path)
	if err != nil {
		return err
	}
	defer file.Close()
	return png.Encode(file, im)
}

func imageToRGBA(src image.Image) *image.RGBA {
	dst := image.NewRGBA(src.Bounds())
	draw.Draw(dst, dst.Rect, src, image.ZP, draw.Src)
	return dst
}

func parseHexColor(x string) (r, g, b, a int) {
	x = strings.TrimPrefix(x, "#")
	a = 255
	if len(x) == 3 {
		format := "%1x%1x%1x"
		fmt.Sscanf(x, format, &r, &g, &b)
		r |= r << 4
		g |= g << 4
		b |= b << 4
	}
	if len(x) == 6 {
		format := "%02x%02x%02x"
		fmt.Sscanf(x, format, &r, &g, &b)
	}
	if len(x) == 8 {
		format := "%02x%02x%02x%02x"
		fmt.Sscanf(x, format, &r, &g, &b, &a)
	}
	return
}

func fixp(x, y float64) fixed.Point26_6 {
	return fixed.Point26_6{fixed.Int26_6(x * 64), fixed.Int26_6(y * 64)}
}

func fix(x float64) fixed.Int26_6 {
	return fixed.Int26_6(x * 64)
}

func unfix(x fixed.Int26_6) float64 {
	const shift, mask = 6, 1<<6 - 1
	if x >= 0 {
		return float64(x>>shift) + float64(x&mask)/64
	}
	x = -x
	if x >= 0 {
		return -(float64(x>>shift) + float64(x&mask)/64)
	}
	return 0
}

func loadFontFace(path string, points float64) font.Face {
	fontBytes, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	f, err := truetype.Parse(fontBytes)
	if err != nil {
		panic(err)
	}
	return truetype.NewFace(f, &truetype.Options{
		Size: points,
		// Hinting: font.HintingFull,
	})
}

func flattenPath(p raster.Path) [][]Point {
	var result [][]Point
	var path []Point
	var cx, cy float64
	for i := 0; i < len(p); {
		switch p[i] {
		case 0:
			if len(path) > 0 {
				result = append(result, path)
				path = nil
			}
			x := unfix(p[i+1])
			y := unfix(p[i+2])
			path = append(path, Point{x, y})
			cx, cy = x, y
			i += 4
		case 1:
			x := unfix(p[i+1])
			y := unfix(p[i+2])
			path = append(path, Point{x, y})
			cx, cy = x, y
			i += 4
		case 2:
			x1 := unfix(p[i+1])
			y1 := unfix(p[i+2])
			x2 := unfix(p[i+3])
			y2 := unfix(p[i+4])
			points := QuadraticBezier(cx, cy, x1, y1, x2, y2)
			path = append(path, points...)
			cx, cy = x2, y2
			i += 6
		case 3:
			x1 := unfix(p[i+1])
			y1 := unfix(p[i+2])
			x2 := unfix(p[i+3])
			y2 := unfix(p[i+4])
			x3 := unfix(p[i+5])
			y3 := unfix(p[i+6])
			points := CubicBezier(cx, cy, x1, y1, x2, y2, x3, y3)
			path = append(path, points...)
			cx, cy = x3, y3
			i += 8
		default:
			panic("bad path")
		}
	}
	if len(path) > 0 {
		result = append(result, path)
	}
	return result
}

func dashPath(paths [][]Point, dashes []float64) [][]Point {
	var result [][]Point
	if len(dashes) == 0 {
		return paths
	}
	if len(dashes) == 1 {
		dashes = append(dashes, dashes[0])
	}
	for _, path := range paths {
		if len(path) < 2 {
			continue
		}
		previous := path[0]
		pathIndex := 1
		dashIndex := 0
		segmentLength := 0.0
		var segment []Point
		segment = append(segment, previous)
		for pathIndex < len(path) {
			dashLength := dashes[dashIndex]
			point := path[pathIndex]
			d := previous.Distance(point)
			maxd := dashLength - segmentLength
			if d > maxd {
				t := maxd / d
				p := previous.Interpolate(point, t)
				segment = append(segment, p)
				if dashIndex%2 == 0 && len(segment) > 1 {
					result = append(result, segment)
				}
				segment = nil
				segment = append(segment, p)
				segmentLength = 0
				previous = p
				dashIndex = (dashIndex + 1) % len(dashes)
			} else {
				segment = append(segment, point)
				previous = point
				segmentLength += d
				pathIndex++
			}
		}
		if dashIndex%2 == 0 && len(segment) > 1 {
			result = append(result, segment)
		}
	}
	return result
}

func rasterPath(paths [][]Point) raster.Path {
	var result raster.Path
	for _, path := range paths {
		var previous fixed.Point26_6
		for i, point := range path {
			f := point.Fixed()
			if i == 0 {
				result.Start(f)
			} else {
				dx := f.X - previous.X
				dy := f.Y - previous.Y
				if dx < 0 {
					dx = -dx
				}
				if dy < 0 {
					dy = -dy
				}
				if dx+dy > 4 {
					// TODO: this is a hack for cases where two points are
					// too close - causes rendering issues with joins / caps
					result.Add1(f)
				}
			}
			previous = f
		}
	}
	return result
}

func dashed(path raster.Path, dashes []float64) raster.Path {
	return rasterPath(dashPath(flattenPath(path), dashes))
}
<commit_msg>refactor<commit_after>package gg

import (
	"fmt"
	"image"
	"image/draw"
	"image/png"
	"io/ioutil"
	"math"
	"os"
	"strings"

	"github.com/golang/freetype/raster"
	"github.com/golang/freetype/truetype"

	"golang.org/x/image/font"
	"golang.org/x/image/math/fixed"
)

func Radians(degrees float64) float64 {
	return degrees * math.Pi / 180
}

func Degrees(radians float64) float64 {
	return radians * 180 / math.Pi
}

func LoadPNG(path string) (image.Image, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	return png.Decode(file)
}

func SavePNG(path string, im image.Image) error {
	file, err := os.Create(path)
	if err != nil {
		return err
	}
	defer file.Close()
	return png.Encode(file, im)
}

func imageToRGBA(src image.Image) *image.RGBA {
	dst := image.NewRGBA(src.Bounds())
	draw.Draw(dst, dst.Rect, src, image.ZP, draw.Src)
	return dst
}

func parseHexColor(x string) (r, g, b, a int) {
	x = strings.TrimPrefix(x, "#")
	a = 255
	if len(x) == 3 {
		format := "%1x%1x%1x"
		fmt.Sscanf(x, format, &r, &g, &b)
		r |= r << 4
		g |= g << 4
		b |= b << 4
	}
	if len(x) == 6 {
		format := "%02x%02x%02x"
		fmt.Sscanf(x, format, &r, &g, &b)
	}
	if len(x) == 8 {
		format := "%02x%02x%02x%02x"
		fmt.Sscanf(x, format, &r, &g, &b, &a)
	}
	return
}

func fixp(x, y float64) fixed.Point26_6 {
	return fixed.Point26_6{fix(x), fix(y)}
}

func fix(x float64) fixed.Int26_6 {
	return fixed.Int26_6(x * 64)
}

func unfix(x fixed.Int26_6) float64 {
	const shift, mask = 6, 1<<6 - 1
	if x >= 0 {
		return float64(x>>shift) + float64(x&mask)/64
	}
	x = -x
	if x >= 0 {
		return -(float64(x>>shift) + float64(x&mask)/64)
	}
	return 0
}

func loadFontFace(path string, points float64) font.Face {
	fontBytes, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	f, err := truetype.Parse(fontBytes)
	if err != nil {
		panic(err)
	}
	return truetype.NewFace(f, &truetype.Options{
		Size: points,
		// Hinting: font.HintingFull,
	})
}

func flattenPath(p raster.Path) [][]Point {
	var result [][]Point
	var path []Point
	var cx, cy float64
	for i := 0; i < len(p); {
		switch p[i] {
		case 0:
			if len(path) > 0 {
				result = append(result, path)
				path = nil
			}
			x := unfix(p[i+1])
			y := unfix(p[i+2])
			path = append(path, Point{x, y})
			cx, cy = x, y
			i += 4
		case 1:
			x := unfix(p[i+1])
			y := unfix(p[i+2])
			path = append(path, Point{x, y})
			cx, cy = x, y
			i += 4
		case 2:
			x1 := unfix(p[i+1])
			y1 := unfix(p[i+2])
			x2 := unfix(p[i+3])
			y2 := unfix(p[i+4])
			points := QuadraticBezier(cx, cy, x1, y1, x2, y2)
			path = append(path, points...)
			cx, cy = x2, y2
			i += 6
		case 3:
			x1 := unfix(p[i+1])
			y1 := unfix(p[i+2])
			x2 := unfix(p[i+3])
			y2 := unfix(p[i+4])
			x3 := unfix(p[i+5])
			y3 := unfix(p[i+6])
			points := CubicBezier(cx, cy, x1, y1, x2, y2, x3, y3)
			path = append(path, points...)
			cx, cy = x3, y3
			i += 8
		default:
			panic("bad path")
		}
	}
	if len(path) > 0 {
		result = append(result, path)
	}
	return result
}

func dashPath(paths [][]Point, dashes []float64) [][]Point {
	var result [][]Point
	if len(dashes) == 0 {
		return paths
	}
	if len(dashes) == 1 {
		dashes = append(dashes, dashes[0])
	}
	for _, path := range paths {
		if len(path) < 2 {
			continue
		}
		previous := path[0]
		pathIndex := 1
		dashIndex := 0
		segmentLength := 0.0
		var segment []Point
		segment = append(segment, previous)
		for pathIndex < len(path) {
			dashLength := dashes[dashIndex]
			point := path[pathIndex]
			d := previous.Distance(point)
			maxd := dashLength - segmentLength
			if d > maxd {
				t := maxd / d
				p := previous.Interpolate(point, t)
				segment = append(segment, p)
				if dashIndex%2 == 0 && len(segment) > 1 {
					result = append(result, segment)
				}
				segment = nil
				segment = append(segment, p)
				segmentLength = 0
				previous = p
				dashIndex = (dashIndex + 1) % len(dashes)
			} else {
				segment = append(segment, point)
				previous = point
				segmentLength += d
				pathIndex++
			}
		}
		if dashIndex%2 == 0 && len(segment) > 1 {
			result = append(result, segment)
		}
	}
	return result
}

func rasterPath(paths [][]Point) raster.Path {
	var result raster.Path
	for _, path := range paths {
		var previous fixed.Point26_6
		for i, point := range path {
			f := point.Fixed()
			if i == 0 {
				result.Start(f)
			} else {
				dx := f.X - previous.X
				dy := f.Y - previous.Y
				if dx < 0 {
					dx = -dx
				}
				if dy < 0 {
					dy = -dy
				}
				if dx+dy > 4 {
					// TODO: this is a hack for cases where two points are
					// too close - causes rendering issues with joins / caps
					result.Add1(f)
				}
			}
			previous = f
		}
	}
	return result
}

func dashed(path raster.Path, dashes []float64) raster.Path {
	return rasterPath(dashPath(flattenPath(path), dashes))
}
<|endoftext|>


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

// +build ignore

package main

import (
	"image"
	"image/color"

	"code.google.com/p/go-tour-french/pic"
)

type Image struct {
	Height, Width int
}

func (m Image) ColorModel() color.Model {
	return color.RGBAModel
}

func (m Image) Bounds() image.Rectangle {
	return image.Rect(0, 0, m.Height, m.Width)
}

func (m Image) At(x, y int) color.Color {
	c := uint8(x ^ y)
	return color.RGBA{c, c, 255, 255}
}

func main() {
	m := Image{256, 256}
	pic.ShowImage(m)
}
<commit_msg>Update imports from googlecode to github<commit_after>// Copyright 2012 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build ignore

package main

import (
	"image"
	"image/color"

	"github.com/dupoxy/go-tour-fr/pic"
)

type Image struct {
	Height, Width int
}

func (m Image) ColorModel() color.Model {
	return color.RGBAModel
}

func (m Image) Bounds() image.Rectangle {
	return image.Rect(0, 0, m.Height, m.Width)
}

func (m Image) At(x, y int) color.Color {
	c := uint8(x ^ y)
	return color.RGBA{c, c, 255, 255}
}

func main() {
	m := Image{256, 256}
	pic.ShowImage(m)
}
<|endoftext|>


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

package uuid

import (
	"bytes"
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"io"
	"strings"
)

// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
// 4122.
type UUID []byte

// A Version represents a UUIDs version.
type Version byte

// A Variant represents a UUIDs variant.
type Variant byte

// Constants returned by Variant.
const (
	Invalid   = Variant(iota) // Invalid UUID
	RFC4122                   // The variant specified in RFC4122
	Reserved                  // Reserved, NCS backward compatibility.
	Microsoft                 // Reserved, Microsoft Corporation backward compatibility.
	Future                    // Reserved for future definition.
)

var rander = rand.Reader // random function

// New returns a new random (version 4) UUID as a string.  It is a convenience
// function for NewRandom().String().
func New() string {
	return NewRandom().String()
}

// Parse decodes s into a UUID or returns nil.  Both the UUID form of
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded.
func Parse(s string) UUID {
	if len(s) == 36+9 {
		if strings.ToLower(s[:9]) != "urn:uuid:" {
			return nil
		}
		s = s[9:]
	} else if len(s) != 36 {
		return nil
	}
	if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
		return nil
	}
	var uuid [16]byte
	for i, x := range [16]int{
		0, 2, 4, 6,
		9, 11,
		14, 16,
		19, 21,
		24, 26, 28, 30, 32, 34} {
		if v, ok := xtob(s[x:]); !ok {
			return nil
		} else {
			uuid[i] = v
		}
	}
	return uuid[:]
}

// Equal returns true if uuid1 and uuid2 are equal.
func Equal(uuid1, uuid2 UUID) bool {
	return bytes.Equal(uuid1, uuid2)
}

// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// , or "" if uuid is invalid.
func (uuid UUID) String() string {
	if uuid == nil || len(uuid) != 16 {
		return ""
	}
	var buf [36]byte
	hex.Encode(buf[:], uuid[:4])
	buf[8] = '-'
	hex.Encode(buf[9:13], uuid[4:6])
	buf[13] = '-'
	hex.Encode(buf[14:18], uuid[6:8])
	buf[18] = '-'
	hex.Encode(buf[19:23], uuid[8:10])
	buf[23] = '-'
	hex.Encode(buf[24:], uuid[10:])
	return string(buf[:])
}

// URN returns the RFC 2141 URN form of uuid,
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,  or "" if uuid is invalid.
func (uuid UUID) URN() string {
	if uuid == nil || len(uuid) != 16 {
		return ""
	}
	var buf [36 + 9]byte
	copy(buf[:], "urn:uuid:")
	_buf := buf[9:]
	hex.Encode(_buf[:], uuid[:4])
	_buf[8] = '-'
	hex.Encode(_buf[9:13], uuid[4:6])
	_buf[13] = '-'
	hex.Encode(_buf[14:18], uuid[6:8])
	_buf[18] = '-'
	hex.Encode(_buf[19:23], uuid[8:10])
	_buf[23] = '-'
	hex.Encode(_buf[24:], uuid[10:])
	return string(buf[:])
}

// Variant returns the variant encoded in uuid.  It returns Invalid if
// uuid is invalid.
func (uuid UUID) Variant() Variant {
	if len(uuid) != 16 {
		return Invalid
	}
	switch {
	case (uuid[8] & 0xc0) == 0x80:
		return RFC4122
	case (uuid[8] & 0xe0) == 0xc0:
		return Microsoft
	case (uuid[8] & 0xe0) == 0xe0:
		return Future
	default:
		return Reserved
	}
	panic("unreachable")
}

// Version returns the verison of uuid.  It returns false if uuid is not
// valid.
func (uuid UUID) Version() (Version, bool) {
	if len(uuid) != 16 {
		return 0, false
	}
	return Version(uuid[6] >> 4), true
}

func (v Version) String() string {
	if v > 15 {
		return fmt.Sprintf("BAD_VERSION_%d", v)
	}
	return fmt.Sprintf("VERSION_%d", v)
}

func (v Variant) String() string {
	switch v {
	case RFC4122:
		return "RFC4122"
	case Reserved:
		return "Reserved"
	case Microsoft:
		return "Microsoft"
	case Future:
		return "Future"
	case Invalid:
		return "Invalid"
	}
	return fmt.Sprintf("BadVariant%d", int(v))
}

// SetRand sets the random number generator to r, which implents io.Reader.
// If r.Read returns an error when the package requests random data then
// a panic will be issued.
//
// Calling SetRand with nil sets the random number generator to the default
// generator.
func SetRand(r io.Reader) {
	if r == nil {
		rander = rand.Reader
		return
	}
	rander = r
}
<commit_msg>remove redundant nil checks in UUID.String() and UUID.URN()<commit_after>// Copyright 2011 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
	"bytes"
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"io"
	"strings"
)

// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
// 4122.
type UUID []byte

// A Version represents a UUIDs version.
type Version byte

// A Variant represents a UUIDs variant.
type Variant byte

// Constants returned by Variant.
const (
	Invalid   = Variant(iota) // Invalid UUID
	RFC4122                   // The variant specified in RFC4122
	Reserved                  // Reserved, NCS backward compatibility.
	Microsoft                 // Reserved, Microsoft Corporation backward compatibility.
	Future                    // Reserved for future definition.
)

var rander = rand.Reader // random function

// New returns a new random (version 4) UUID as a string.  It is a convenience
// function for NewRandom().String().
func New() string {
	return NewRandom().String()
}

// Parse decodes s into a UUID or returns nil.  Both the UUID form of
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded.
func Parse(s string) UUID {
	if len(s) == 36+9 {
		if strings.ToLower(s[:9]) != "urn:uuid:" {
			return nil
		}
		s = s[9:]
	} else if len(s) != 36 {
		return nil
	}
	if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
		return nil
	}
	var uuid [16]byte
	for i, x := range [16]int{
		0, 2, 4, 6,
		9, 11,
		14, 16,
		19, 21,
		24, 26, 28, 30, 32, 34} {
		if v, ok := xtob(s[x:]); !ok {
			return nil
		} else {
			uuid[i] = v
		}
	}
	return uuid[:]
}

// Equal returns true if uuid1 and uuid2 are equal.
func Equal(uuid1, uuid2 UUID) bool {
	return bytes.Equal(uuid1, uuid2)
}

// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// , or "" if uuid is invalid.
func (uuid UUID) String() string {
	if len(uuid) != 16 {
		return ""
	}
	var buf [36]byte
	hex.Encode(buf[:], uuid[:4])
	buf[8] = '-'
	hex.Encode(buf[9:13], uuid[4:6])
	buf[13] = '-'
	hex.Encode(buf[14:18], uuid[6:8])
	buf[18] = '-'
	hex.Encode(buf[19:23], uuid[8:10])
	buf[23] = '-'
	hex.Encode(buf[24:], uuid[10:])
	return string(buf[:])
}

// URN returns the RFC 2141 URN form of uuid,
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,  or "" if uuid is invalid.
func (uuid UUID) URN() string {
	if len(uuid) != 16 {
		return ""
	}
	var buf [36 + 9]byte
	copy(buf[:], "urn:uuid:")
	_buf := buf[9:]
	hex.Encode(_buf[:], uuid[:4])
	_buf[8] = '-'
	hex.Encode(_buf[9:13], uuid[4:6])
	_buf[13] = '-'
	hex.Encode(_buf[14:18], uuid[6:8])
	_buf[18] = '-'
	hex.Encode(_buf[19:23], uuid[8:10])
	_buf[23] = '-'
	hex.Encode(_buf[24:], uuid[10:])
	return string(buf[:])
}

// Variant returns the variant encoded in uuid.  It returns Invalid if
// uuid is invalid.
func (uuid UUID) Variant() Variant {
	if len(uuid) != 16 {
		return Invalid
	}
	switch {
	case (uuid[8] & 0xc0) == 0x80:
		return RFC4122
	case (uuid[8] & 0xe0) == 0xc0:
		return Microsoft
	case (uuid[8] & 0xe0) == 0xe0:
		return Future
	default:
		return Reserved
	}
	panic("unreachable")
}

// Version returns the verison of uuid.  It returns false if uuid is not
// valid.
func (uuid UUID) Version() (Version, bool) {
	if len(uuid) != 16 {
		return 0, false
	}
	return Version(uuid[6] >> 4), true
}

func (v Version) String() string {
	if v > 15 {
		return fmt.Sprintf("BAD_VERSION_%d", v)
	}
	return fmt.Sprintf("VERSION_%d", v)
}

func (v Variant) String() string {
	switch v {
	case RFC4122:
		return "RFC4122"
	case Reserved:
		return "Reserved"
	case Microsoft:
		return "Microsoft"
	case Future:
		return "Future"
	case Invalid:
		return "Invalid"
	}
	return fmt.Sprintf("BadVariant%d", int(v))
}

// SetRand sets the random number generator to r, which implents io.Reader.
// If r.Read returns an error when the package requests random data then
// a panic will be issued.
//
// Calling SetRand with nil sets the random number generator to the default
// generator.
func SetRand(r io.Reader) {
	if r == nil {
		rander = rand.Reader
		return
	}
	rander = r
}
<|endoftext|>


<commit_before>package events

import (
	"crypto/sha256"
	"errors"
	"fmt"
	"time"
	"unicode/utf8"
)

type Event struct {
	ID             string    `gorm:"size:64;primary_key";json:"id"`
	Name           string    `gorm:"index"`
	TTL            int64     `gorm:"index"`
	AuthUserSource string    `gorm:"index"`
	CreatedAt      time.Time `gorm:"index"`
	ExpiresAt      time.Time `gorm:"index"`
	Description    string
	Source         string
	Processed      bool
	Expired        bool
	Status         uint8
}

// Generate UUID (SHA256) with event infos
func (e *Event) Gen256Sum() {
	eventBytes := []byte(e.Name + e.Source + e.Description + string(e.TTL) + e.CreatedAt.String() + string(e.Status))
	h := sha256.New()
	h.Write(eventBytes)
	e.ID = fmt.Sprintf("%x", h.Sum(nil))
}

// Add TTL to timestamp and calculate event expiration date
func (e *Event) GenExpiredAt() {
	if e.IsExpirable() {
		e.ExpiresAt = e.CreatedAt.Add(time.Duration(e.TTL) * time.Second)
	}
}

// IsExpirable return true if event has TTL, success status and CreatedAt
func (e Event) IsExpirable() bool {
	return e.TTL > 0 && e.Status == 0 && !e.CreatedAt.IsZero()
}

// Check if event is well formed
func (e *Event) Check() error {
	if utf8.RuneCountInString(e.ID) != 64 {
		return errors.New("Bad SHA256 sum")
	} else if utf8.RuneCountInString(e.Name) <= 0 {
		return errors.New("name cannot be blank")
	}
	return nil
}

// Fail sets event to fail status
func (e *Event) Fail() {
	e.Status = 1
}

// Success sets event to Success status
func (e *Event) Success() {
	e.Status = 0
}

// isSuccess return true if event is in success status
func (e Event) isSuccess() bool {
	return e.Status == 0
}
<commit_msg>fix failing event error with mysql strict compat<commit_after>package events

import (
	"crypto/sha256"
	"errors"
	"fmt"
	"time"
	"unicode/utf8"
)

type Event struct {
	ID             string    `gorm:"size:64;primary_key";json:"id"`
	Name           string    `gorm:"index"`
	TTL            int64     `gorm:"index"`
	AuthUserSource string    `gorm:"index"`
	CreatedAt      time.Time `gorm:"index"`
	ExpiresAt      time.Time `gorm:"index"`
	Description    string
	Source         string
	Processed      bool
	Expired        bool
	Status         uint8
}

// Generate UUID (SHA256) with event infos
func (e *Event) Gen256Sum() {
	eventBytes := []byte(e.Name + e.Source + e.Description + string(e.TTL) + e.CreatedAt.String() + string(e.Status))
	h := sha256.New()
	h.Write(eventBytes)
	e.ID = fmt.Sprintf("%x", h.Sum(nil))
}

// Add TTL to timestamp and calculate event expiration date
func (e *Event) GenExpiredAt() {
	// Default to time.Now for mysql 5.7 strict mode
	e.ExpiresAt = time.Now()

	// Else, calculate the time this event will expires
	if e.IsExpirable() {
		e.ExpiresAt = e.CreatedAt.Add(time.Duration(e.TTL) * time.Second)
	}
}

// IsExpirable return true if event has TTL, success status and CreatedAt
func (e Event) IsExpirable() bool {
	return e.TTL > 0 && e.Status == 0 && !e.CreatedAt.IsZero()
}

// Check if event is well formed
func (e *Event) Check() error {
	if utf8.RuneCountInString(e.ID) != 64 {
		return errors.New("Bad SHA256 sum")
	} else if utf8.RuneCountInString(e.Name) <= 0 {
		return errors.New("name cannot be blank")
	}
	return nil
}

// Fail sets event to fail status
func (e *Event) Fail() {
	e.Status = 1
}

// Success sets event to Success status
func (e *Event) Success() {
	e.Status = 0
}

// isSuccess return true if event is in success status
func (e Event) isSuccess() bool {
	return e.Status == 0
}
<|endoftext|>


<commit_before>package main

const (
	VERSION         = "1.34"
	DATABASE_DIR    = "database"
	RELEASE_URL     = "https://github.com/Seklfreak/discord-image-downloader-go/releases/latest"
	RELEASE_API_URL = "https://api.github.com/repos/Seklfreak/discord-image-downloader-go/releases/latest"
	IMGUR_CLIENT_ID = "a39473314df3f59"

	DEFAULT_CONFIG_FILE = "config.ini"

	discordEmojiBaseUrl = "https://cdn.discordapp.com/emojis/"
)
<commit_msg>version bump<commit_after>package main

const (
	VERSION         = "1.35"
	DATABASE_DIR    = "database"
	RELEASE_URL     = "https://github.com/Seklfreak/discord-image-downloader-go/releases/latest"
	RELEASE_API_URL = "https://api.github.com/repos/Seklfreak/discord-image-downloader-go/releases/latest"
	IMGUR_CLIENT_ID = "a39473314df3f59"

	DEFAULT_CONFIG_FILE = "config.ini"

	discordEmojiBaseUrl = "https://cdn.discordapp.com/emojis/"
)
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
)

// A map for Puppet Versions JSON
type PuppetVersions map[string]interface{}

// A map for Production Versions JSON
type ProductionVersions map[string]interface{}

// Our bare page
type Page struct {
	Title string
	Body  []byte
	Pv    PuppetVersions
	Prodv ProductionVersions
}

func puppetversions(url string) (PuppetVersions, error) {
	// Get response and handle any errors on return
	resp, err := http.Get(url)
	defer resp.Body.Close()
	if err != nil {
		log.Println(err)
		return nil, err
	}

	// Read JSON from request
	jsonDataFromHttp, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	// Unmarshel the JSON to our struct
	var v PuppetVersions
	err = json.Unmarshal(jsonDataFromHttp, &v)
	if err != nil {
		return nil, err
	}

	return v, nil
}

func productionversions(url string) (ProductionVersions, error) {
	resp, err := http.Get(url)
	defer resp.Body.Close()
	if err != nil {
		log.Println(err)
		return nil, err
	}

	jsonDataFromHttp, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	//available_services := make(map[string]interface{})
	var v ProductionVersions
	err = json.Unmarshal(jsonDataFromHttp, &v)
	if err != nil {
		return nil, err
	}

	log.Println("AVAILABLE SERVICES: ", v)

	return v, nil
}

func loadPage(title string) (*Page, error) {
	// Get the versions from the puppet master
	log.Println("Getting Puppet Versions - Make sure VPN is on!")
	pv, err := puppetversions("http://puppet.ec2.srcclr.com:1015/versions")
	if err != nil {
		log.Println("Failed to get Puppet Versions from http://puppet.ec2.srcclr.com:1015/versions\n")
		log.Println(err)
	}

	// Get running versions
	log.Println("Getting available services...")
	prv, err := productionversions("http://localhost:3000/services")
	if err != nil {
		log.Println("Failed getting production versions")
	}

	filename := title + ".html"
	body, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	log.Println("VERSIONS\n")
	log.Println("%v", pv["scm_agent_version_production"])

	return &Page{
			Title: title,
			Body:  body,
			Pv:    pv,
			Prodv: prv,
		},
		nil
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
	log.Println("Loading page view...")
	title := "versionctl"
	p, err := loadPage(title)
	if err != nil {
		p = &Page{Title: title}
	}

	// Parse the template, execute and write it to stdout for good measure
	log.Println("Parsing go template...")
	t, _ := template.ParseFiles("versionctl.html")
	t.Execute(w, p)
	log.Println("Serving:\n", string(p.Title), string(p.Body))
}

func main() {
	log.Println("Starting vctl...")
	http.HandleFunc("/", viewHandler)
	http.ListenAndServe(":9000", nil)
}
<commit_msg>getting available<commit_after>package main

import (
	"encoding/json"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
)

// A map for Puppet Versions JSON
type PuppetVersions map[string]interface{}

// A map for Production Versions JSON
type ProductionVersions map[string]interface{}

// Our bare page
type Page struct {
	Title string
	Body  []byte
	Pv    PuppetVersions
	Prodv ProductionVersions
}

func puppetversions(url string) (PuppetVersions, error) {
	// Get response and handle any errors on return
	resp, err := http.Get(url)
	defer resp.Body.Close()
	if err != nil {
		log.Println(err)
		return nil, err
	}

	// Read JSON from request
	jsonDataFromHttp, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	// Unmarshel the JSON to our struct
	var v PuppetVersions
	err = json.Unmarshal(jsonDataFromHttp, &v)
	if err != nil {
		return nil, err
	}

	return v, nil
}

func getServices(url string) (map[string]interface{}, error) {
	resp, err := http.Get(url)
	defer resp.Body.Close()
	if err != nil {
		log.Println(err)
		return nil, err
	}

	jsonDataFromHttp, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	available_services := make(map[string]interface{})

	err = json.Unmarshal(jsonDataFromHttp, &available_services)
	if err != nil {
		return nil, err
	}

	log.Println("AVAILABLE SERVICES for ", url, ":\n", available_services)

	return available_services, nil
}

func loadPage(title string) (*Page, error) {
	// Get the versions from the puppet master
	log.Println("Getting Puppet Versions - Make sure VPN is on!")
	pv, err := puppetversions("http://puppet.ec2.srcclr.com:1015/versions")
	if err != nil {
		log.Println("Failed to get Puppet Versions from http://puppet.ec2.srcclr.com:1015/versions\n")
		log.Println(err)
	}

	// Get running versions
	log.Println("Getting available services...")
	prv, err := getServices("http://localhost:3000/services")
	if err != nil {
		log.Println("Failed getting production versions")
	}

	filename := title + ".html"
	body, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	log.Println("Puppet Versions: ", pv)

	return &Page{
			Title: title,
			Body:  body,
			Pv:    pv,
			Prodv: prv,
		},
		nil
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
	log.Println("Loading page view...")
	title := "versionctl"
	p, err := loadPage(title)
	if err != nil {
		p = &Page{Title: title}
	}

	// Parse the template, execute and write it to stdout for good measure
	log.Println("Parsing go template...")
	t, _ := template.ParseFiles("versionctl.html")
	t.Execute(w, p)
	log.Println("Serving:\n", string(p.Title), string(p.Body))
}

func main() {
	log.Println("Starting vctl...")
	http.HandleFunc("/", viewHandler)
	http.ListenAndServe(":9000", nil)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"os"
	"sort"
	"strings"

	"github.com/Masterminds/semver"
	"github.com/codegangsta/cli"
)

const name = "vert"
const version = "0.1.0"
const description = `Version Tester. Compare versions.

Vert is a tool for comparing two version strings, or comparing a version string
to a version range.

	$ vert ">1.0.0" 1.1.0
	1.1.0

	$ vert "<1.0.0" 1.1.0
	   # No output because nothing matched.

	$ vert -f "<1.0.0" 1.1.0
	1.1.0   # -f returns all failures, rather than matches.

	$ vert ">1.0.0" 1.1.0 1.1.1 1.2.3 0.1.1
	1.1.0
	1.1.1
	1.2.3

Vert can also convert a Git version to a SemVer 2 version.

	$ vert -g ">1" v1.10.0-123-g0239788                                                                                1 ↵
	1.10.0+123.g0239788

Note that it assigns the git commit count and hash to the build metadata, not
to a pre-release tag.

See below for information about how to determine the number of failed tests.

EXIT CODES:

vert returns exit codes based on the number of failed matches. There are a few
reserved exit codes:

- 128: The command was not called correctly.
- 256: A version failed to parse, and comparisons could not continue. This will
  occur if the original constraint version cannot be parsed. If any
  subsequent version fails to parse, it will simply be counted as a failure.

Any other error codes indicate the number of failed tests. For example:

	$ vert 1.2.3 1.2.3 1.2.4 1.2.5
	1.2.3
	$ echo $?
	2   # <-- Two tests failed.

BASE VERSIONS:

The base version may be in any of the following formats:

- An exact semantic version number
	- 1.2.3
	- v1.2.3
	- 1.2.3-alpha.1+10212015
- A semantic version range
	- *
	- !=1.0.0
	- >=1.2.3
	- >1.2.3,<1.3.2
	- ~1.2.0
	- ^2.3

VERSIONS:

Other than the base version, all other supplied versions must follow the
SemVer 2 spec. Examples:

	- 1.2.3
	- v1.2.3
	- 1.2.3-alpha.1+10212015
	- v1.2.3-alpha.1+10212015
	- 1 (equivalent to 1.0.0)
`

func main() {
	app := cli.NewApp()
	app.Name = name
	app.Usage = description
	app.Action = func(c *cli.Context) { res := run(c); os.Exit(res) }
	app.Version = version
	app.ArgsUsage = "BASE VERSION [VERSION [VERSION [...]]"
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "failed,f",
			Usage: "Show the versions that failed rather than the ones that passed.",
		},
		cli.BoolFlag{
			Name:  "sort,s",
			Usage: "Sort the versions before printing. Without this, versions are returned in the order they were tested.",
		},
		cli.BoolFlag{
			Name:  "git,g",
			Usage: "Assume that (non-base) versions are in Git `git describe --tags` version format, and convert to SemVer.",
		},
	}
	app.Run(os.Args)
}

// context describes the relevant portion of a cli.Context.
//
// This abstraction makes mocking easy.
type context interface {
	Bool(string) bool
	Args() cli.Args
}

// run handles all of the flags and then runs the main action.
func run(c context) int {
	args := c.Args()
	if len(args) < 2 {
		perr("Not enough arguments")
		return 128
	}

	if c.Bool("git") {
		for i := 1; i < len(args); i++ {
			nv, err := git2semver(args[i])
			if err != nil {
				perr("Not a recognize git version: %s", args[i])
				continue
			}
			args[i] = nv.String()
		}
	}

	pass, fail, code := compare(args[0], args[1:])

	out := pass
	if c.Bool("failed") {
		out = fail
	}

	if c.Bool("sort") {
		sort.Sort(semver.Collection(out))
	}

	pvers(out)
	return code
}

// compare compiles a base version comparator, and then compares all cases to it.
//
// It retuns an array of versions that passed, and an array of versions that failed.
func compare(base string, cases []string) ([]*semver.Version, []*semver.Version, int) {
	passed, failed := []*semver.Version{}, []*semver.Version{}

	constraint, err := semver.NewConstraint(base)
	if err != nil {
		perr("Could not parse constraint %s", base)
		return passed, failed, 256
	}

	for _, t := range cases {
		ver, err := semver.NewVersion(t)
		if err != nil {
			failed = append(failed, ver)
			perr("Failed to parse %s", t)
			continue
		}
		if constraint.Check(ver) {
			passed = append(passed, ver)
			continue
		}
		failed = append(failed, ver)
	}

	return passed, failed, len(failed)
}

var stdout io.Writer = os.Stdout
var stderr io.Writer = os.Stderr

// pvers prints a list of versions to standard out.
func pvers(vers []*semver.Version) {
	for _, v := range vers {
		fmt.Fprintln(stdout, v.String())
	}
}

// pout prints to stdout.
func pout(msg string, args ...interface{}) {
	fmt.Fprintf(stdout, msg, args...)
	fmt.Fprintln(stdout)
}

// perr prints to stderr.
func perr(msg string, args ...interface{}) {
	fmt.Fprintf(stderr, msg, args...)
	fmt.Fprintln(stderr)
}

// git2semver converts a Git version to a SemVer 2 version
//
// This assumes that the base tag is a semver tag.
//
// v1.2.3-3-afeee becomes 1.2.3+3.afeee
func git2semver(ver string) (*semver.Version, error) {
	va := strings.Split(ver, "-")
	target := va[0]
	if len(va) > 1 {
		md := strings.Join(va[1:], ".")
		target += "+" + md
	}
	return semver.NewVersion(target)
}
<commit_msg>Updating the exit code to be in range (255 max)<commit_after>package main

import (
	"fmt"
	"io"
	"os"
	"sort"
	"strings"

	"github.com/Masterminds/semver"
	"github.com/codegangsta/cli"
)

const name = "vert"
const version = "0.1.0"
const description = `Version Tester. Compare versions.

Vert is a tool for comparing two version strings, or comparing a version string
to a version range.

	$ vert ">1.0.0" 1.1.0
	1.1.0

	$ vert "<1.0.0" 1.1.0
	   # No output because nothing matched.

	$ vert -f "<1.0.0" 1.1.0
	1.1.0   # -f returns all failures, rather than matches.

	$ vert ">1.0.0" 1.1.0 1.1.1 1.2.3 0.1.1
	1.1.0
	1.1.1
	1.2.3

Vert can also convert a Git version to a SemVer 2 version.

	$ vert -g ">1" v1.10.0-123-g0239788                                                                                1 ↵
	1.10.0+123.g0239788

Note that it assigns the git commit count and hash to the build metadata, not
to a pre-release tag.

See below for information about how to determine the number of failed tests.

EXIT CODES:

vert returns exit codes based on the number of failed matches. There are a few
reserved exit codes:

- 128: The command was not called correctly.
- 256: A version failed to parse, and comparisons could not continue. This will
  occur if the original constraint version cannot be parsed. If any
  subsequent version fails to parse, it will simply be counted as a failure.

Any other error codes indicate the number of failed tests. For example:

	$ vert 1.2.3 1.2.3 1.2.4 1.2.5
	1.2.3
	$ echo $?
	2   # <-- Two tests failed.

BASE VERSIONS:

The base version may be in any of the following formats:

- An exact semantic version number
	- 1.2.3
	- v1.2.3
	- 1.2.3-alpha.1+10212015
- A semantic version range
	- *
	- !=1.0.0
	- >=1.2.3
	- >1.2.3,<1.3.2
	- ~1.2.0
	- ^2.3

VERSIONS:

Other than the base version, all other supplied versions must follow the
SemVer 2 spec. Examples:

	- 1.2.3
	- v1.2.3
	- 1.2.3-alpha.1+10212015
	- v1.2.3-alpha.1+10212015
	- 1 (equivalent to 1.0.0)
`

func main() {
	app := cli.NewApp()
	app.Name = name
	app.Usage = description
	app.Action = func(c *cli.Context) { res := run(c); os.Exit(res) }
	app.Version = version
	app.ArgsUsage = "BASE VERSION [VERSION [VERSION [...]]"
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "failed,f",
			Usage: "Show the versions that failed rather than the ones that passed.",
		},
		cli.BoolFlag{
			Name:  "sort,s",
			Usage: "Sort the versions before printing. Without this, versions are returned in the order they were tested.",
		},
		cli.BoolFlag{
			Name:  "git,g",
			Usage: "Assume that (non-base) versions are in Git `git describe --tags` version format, and convert to SemVer.",
		},
	}
	app.Run(os.Args)
}

// context describes the relevant portion of a cli.Context.
//
// This abstraction makes mocking easy.
type context interface {
	Bool(string) bool
	Args() cli.Args
}

// run handles all of the flags and then runs the main action.
func run(c context) int {
	args := c.Args()
	if len(args) < 2 {
		perr("Not enough arguments")
		return 128
	}

	if c.Bool("git") {
		for i := 1; i < len(args); i++ {
			nv, err := git2semver(args[i])
			if err != nil {
				perr("Not a recognize git version: %s", args[i])
				continue
			}
			args[i] = nv.String()
		}
	}

	pass, fail, code := compare(args[0], args[1:])

	out := pass
	if c.Bool("failed") {
		out = fail
	}

	if c.Bool("sort") {
		sort.Sort(semver.Collection(out))
	}

	pvers(out)
	return code
}

// compare compiles a base version comparator, and then compares all cases to it.
//
// It retuns an array of versions that passed, and an array of versions that failed.
func compare(base string, cases []string) ([]*semver.Version, []*semver.Version, int) {
	passed, failed := []*semver.Version{}, []*semver.Version{}

	constraint, err := semver.NewConstraint(base)
	if err != nil {
		perr("Could not parse constraint %s", base)
		return passed, failed, 128
	}

	for _, t := range cases {
		ver, err := semver.NewVersion(t)
		if err != nil {
			failed = append(failed, ver)
			perr("Failed to parse %s", t)
			continue
		}
		if constraint.Check(ver) {
			passed = append(passed, ver)
			continue
		}
		failed = append(failed, ver)
	}

	return passed, failed, len(failed)
}

var stdout io.Writer = os.Stdout
var stderr io.Writer = os.Stderr

// pvers prints a list of versions to standard out.
func pvers(vers []*semver.Version) {
	for _, v := range vers {
		fmt.Fprintln(stdout, v.String())
	}
}

// pout prints to stdout.
func pout(msg string, args ...interface{}) {
	fmt.Fprintf(stdout, msg, args...)
	fmt.Fprintln(stdout)
}

// perr prints to stderr.
func perr(msg string, args ...interface{}) {
	fmt.Fprintf(stderr, msg, args...)
	fmt.Fprintln(stderr)
}

// git2semver converts a Git version to a SemVer 2 version
//
// This assumes that the base tag is a semver tag.
//
// v1.2.3-3-afeee becomes 1.2.3+3.afeee
func git2semver(ver string) (*semver.Version, error) {
	va := strings.Split(ver, "-")
	target := va[0]
	if len(va) > 1 {
		md := strings.Join(va[1:], ".")
		target += "+" + md
	}
	return semver.NewVersion(target)
}
<|endoftext|>