<commit_before>package util

import (
	"archive/tar"
	"archive/zip"
	"bytes"
	"compress/bzip2"
	"compress/gzip"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"path/filepath"
	"regexp"
)

type CompressionType string

const (
	Zip CompressionType = "zip"
	Tar                 = "tar"
)

func RemoteDecompress(uri string, pattern *regexp.Regexp, compressType CompressionType) ([]byte, error) {
	switch compressType {
	case Zip:
		return remoteUnzip(uri, pattern)
	case Tar:
		return remoteUntar(uri, pattern)
	}
	return nil, fmt.Errorf("Unrecognized compression type: %s", compressType)
}

func remoteUntar(uri string, pattern *regexp.Regexp) ([]byte, error) {
	resp, err := http.Get(uri)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var decompressed io.Reader
	if filepath.Ext(uri) == ".bz2" {
		decompressed = bzip2.NewReader(resp.Body)
	} else {
		decompressed, err = gzip.NewReader(resp.Body)
		if err != nil {
			return nil, err
		}
	}

	tr := tar.NewReader(decompressed)
	var data []byte
	matched := false
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			break
		}

		if pattern.MatchString(hdr.Name) {
			buf := bytes.NewBuffer(make([]byte, 0, hdr.Size))
			io.Copy(buf, tr)
			data = append(data, buf.Bytes()...)
			matched = true
		}
	}
	if !matched {
		return nil, fmt.Errorf("No file matched pattern %+v", pattern)
	}

	return data, nil
}

func remoteUnzip(uri string, pattern *regexp.Regexp) ([]byte, error) {
	resp, err := http.Get(uri)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

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

	zr, err := zip.NewReader(bytes.NewReader(zipdata), resp.ContentLength)
	if err != nil {
		return nil, err
	}

	var data []byte
	matched := false
	for _, file := range zr.File {
		if pattern.MatchString(file.Name) {
			fr, err := file.Open()
			if err != nil {
				return nil, err
			}
			defer fr.Close()
			filedata, err := ioutil.ReadAll(fr)
			if err != nil {
				return nil, err
			}
			data = append(data, filedata...)
			matched = true
		}
	}
	if !matched {
		return nil, fmt.Errorf("No file matched pattern %+v", pattern)
	}

	return data, nil
}
<commit_msg>handle malformed tarballs<commit_after>package util

import (
	"archive/tar"
	"archive/zip"
	"bytes"
	"compress/bzip2"
	"compress/gzip"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"path/filepath"
	"regexp"
)

type CompressionType string

const (
	Zip CompressionType = "zip"
	Tar                 = "tar"
)

func RemoteDecompress(uri string, pattern *regexp.Regexp, compressType CompressionType) ([]byte, error) {
	switch compressType {
	case Zip:
		return remoteUnzip(uri, pattern)
	case Tar:
		return remoteUntar(uri, pattern)
	}
	return nil, fmt.Errorf("Unrecognized compression type: %s", compressType)
}

func remoteUntar(uri string, pattern *regexp.Regexp) ([]byte, error) {
	resp, err := http.Get(uri)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var decompressed io.Reader
	if filepath.Ext(uri) == ".bz2" {
		decompressed = bzip2.NewReader(resp.Body)
	} else {
		decompressed, err = gzip.NewReader(resp.Body)
		if err != nil {
			return nil, err
		}
	}

	tr := tar.NewReader(decompressed)
	var data []byte
	matched := false
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			break
		} else if hdr == nil {
			return nil, fmt.Errorf("Error untarring %s: nil header (may be malformed)", uri)
		}

		if pattern.MatchString(hdr.Name) {
			buf := bytes.NewBuffer(make([]byte, 0, hdr.Size))
			io.Copy(buf, tr)
			data = append(data, buf.Bytes()...)
			matched = true
		}
	}
	if !matched {
		return nil, fmt.Errorf("No file matched pattern %+v", pattern)
	}

	return data, nil
}

func remoteUnzip(uri string, pattern *regexp.Regexp) ([]byte, error) {
	resp, err := http.Get(uri)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

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

	zr, err := zip.NewReader(bytes.NewReader(zipdata), resp.ContentLength)
	if err != nil {
		return nil, err
	}

	var data []byte
	matched := false
	for _, file := range zr.File {
		if file == nil {
			return nil, fmt.Errorf("Error unzipping %s: nil file (may be malformed)", uri)
		}

		if pattern.MatchString(file.Name) {
			fr, err := file.Open()
			if err != nil {
				return nil, err
			}
			defer fr.Close()
			filedata, err := ioutil.ReadAll(fr)
			if err != nil {
				return nil, err
			}
			data = append(data, filedata...)
			matched = true
		}
	}
	if !matched {
		return nil, fmt.Errorf("No file matched pattern %+v", pattern)
	}

	return data, nil
}
<|endoftext|>


<commit_before>// Package util contains utility functions
package util

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"errors"
	"fmt"
	"strconv"
	"time"
)

func GenerateCredentials(username, password, rawPem []byte) (cred string, err error) {
	unixStr := strconv.FormatInt(time.Now().Unix(), 10)

	userBase64 := base64.StdEncoding.EncodeToString(username)
	passBase64 := base64.StdEncoding.EncodeToString(password)
	timeBase64 := base64.StdEncoding.EncodeToString([]byte(unixStr))

	formated := fmt.Sprintf("%s:%s:%s", userBase64, passBase64, timeBase64)

	block, _ := pem.Decode(rawPem)
	if block == nil {
		err = errors.New("Could not Decode PEM")
		return
	}

	pubKeyVal, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return
	}

	rsaPubKey, ok := pubKeyVal.(*rsa.PublicKey)
	if !ok {
		err = errors.New("Could not make DER to an RSA PublicKey")
		return
	}

	encr, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPubKey, []byte(formated))
	if err != nil {
		return
	}

	cred = base64.StdEncoding.EncodeToString(encr)
	return
}
<commit_msg>Proper use milliseconds in credentials<commit_after>// Package util contains utility functions
package util

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"errors"
	"fmt"
	"strconv"
	"time"
)

func GenerateCredentials(username, password, rawPem []byte) (cred string, err error) {
	ms := time.Now().Unix() * 1000
	unixStr := strconv.FormatInt(ms, 10)

	userBase64 := base64.StdEncoding.EncodeToString(username)
	passBase64 := base64.StdEncoding.EncodeToString(password)
	timeBase64 := base64.StdEncoding.EncodeToString([]byte(unixStr))

	formated := fmt.Sprintf("%s:%s:%s", userBase64, passBase64, timeBase64)

	block, _ := pem.Decode(rawPem)
	if block == nil {
		err = errors.New("Could not Decode PEM")
		return
	}

	pubKeyVal, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return
	}

	rsaPubKey, ok := pubKeyVal.(*rsa.PublicKey)
	if !ok {
		err = errors.New("Could not make DER to an RSA PublicKey")
		return
	}

	encr, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPubKey, []byte(formated))
	if err != nil {
		return
	}

	cred = base64.StdEncoding.EncodeToString(encr)
	return
}
<|endoftext|>


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

// Package util contains utility functions related to systemd that applications
// can use to check things like whether systemd is running.  Note that some of
// these functions attempt to manually load systemd libraries at runtime rather
// than linking against them.
package util

// #cgo LDFLAGS: -ldl
// #include <stdlib.h>
// #include <dlfcn.h>
// #include <sys/types.h>
//
// int
// my_sd_pid_get_owner_uid(void *f, pid_t pid, uid_t *uid)
// {
//   int (*sd_pid_get_owner_uid)(pid_t, uid_t *);
//
//   sd_pid_get_owner_uid = (int (*)(pid_t, uid_t *))f;
//   return sd_pid_get_owner_uid(pid, uid);
// }
//
// int
// my_sd_pid_get_slice(void *f, pid_t pid, char **slice)
// {
//   int (*sd_pid_get_slice)(pid_t, char **);
//
//   sd_pid_get_slice = (int (*)(pid_t, char **))f;
//   return sd_pid_get_slice(pid, slice);
// }
//
import "C"
import (
	"fmt"
	"os"
	"syscall"
	"unsafe"
)

// getHandle tries to get a handle to a systemd library (.so), attempting to
// access it by several different names and returning the first that is
// successfully opened. Callers are responsible for closing the handler.
// Returns nil if no library can be found.
func getHandle() (unsafe.Pointer, string) {
	for _, name := range []string{
		// systemd < 209
		"libsystemd-login.so",
		"libsystemd-login.so.0",

		// systemd >= 209 merged libsystemd-login into libsystemd proper
		"libsystemd.so",
		"libsystemd.so.0",
	} {
		libname := C.CString(name)
		defer C.free(unsafe.Pointer(libname))
		handle := C.dlopen(libname, C.RTLD_LAZY)
		if handle != nil {
			return handle, name
		}
	}
	return nil, ""
}

// GetRunningSlice attempts to retrieve the name of the systemd slice in which
// the current process is running.
func GetRunningSlice() (slice string, err error) {
	handle, libname := getHandle()
	if handle == nil {
		err = fmt.Errorf("error opening libsystemd-login.so")
		return
	}
	defer func() {
		if r := C.dlclose(handle); r != 0 {
			err = fmt.Errorf("error closing %v", libname)
		}
	}()

	sym := C.CString("sd_pid_get_slice")
	defer C.free(unsafe.Pointer(sym))
	sd_pid_get_slice := C.dlsym(handle, sym)
	if sd_pid_get_slice == nil {
		err = fmt.Errorf("error resolving sd_pid_get_slice function")
		return
	}

	var s string
	sl := C.CString(s)
	defer C.free(unsafe.Pointer(sl))

	ret := C.my_sd_pid_get_slice(sd_pid_get_slice, 0, &sl)
	if ret < 0 {
		err = fmt.Errorf("error calling sd_pid_get_slice: %v", syscall.Errno(-ret))
		return
	}

	slice = C.GoString(sl)
	return
}

// RunningFromSystemService detects whether the current process has been invoked
// from a system service. The condition for this is whether the process is
// _not_ a user process. User processes are those running in session scopes or
// under per-user `systemd --user` instances
func RunningFromSystemService() (ret bool, err error) {
	handle, libname := getHandle()
	if handle == nil {
		// can't open libsystemd so we assume systemd is not
		// installed and we're not running from a unit file
		ret = false
		return
	}
	defer func() {
		if r := C.dlclose(handle); r != 0 {
			err = fmt.Errorf("error closing %v", libname)
		}
	}()

	sym := C.CString("sd_pid_get_owner_uid")
	defer C.free(unsafe.Pointer(sym))
	sd_pid_get_owner_uid := C.dlsym(handle, sym)
	if sd_pid_get_owner_uid == nil {
		err = fmt.Errorf("error resolving sd_pid_get_owner_uid function")
		return
	}

	var uid C.uid_t
	errno := C.my_sd_pid_get_owner_uid(sd_pid_get_owner_uid, 0, &uid)
	serrno := syscall.Errno(-errno)
	// when we're running from a unit file, sd_pid_get_owner_uid returns
	// ENOENT (systemd <220) or ENXIO (systemd >=220)
	switch {
	case errno >= 0:
		ret = false
		return
	case serrno == syscall.ENOENT, serrno == syscall.ENXIO:
		ret = true
		return
	default:
		err = fmt.Errorf("error calling sd_pid_get_owner_uid: %v", syscall.Errno(-errno))
		return
	}
}

// IsRunningSystemd checks whether the host was booted with systemd as its init
// system. This functions similar to systemd's `sd_booted(3)`: internally, it
// checks whether /run/systemd/system/ exists and is a directory.
// http://www.freedesktop.org/software/systemd/man/sd_booted.html
func IsRunningSystemd() bool {
	fi, err := os.Lstat("/run/systemd/system")
	if err != nil {
		return false
	}
	return fi.IsDir()
}
<commit_msg>util: rework getHandle interface and add caveats<commit_after>// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package util contains utility functions related to systemd that applications
// can use to check things like whether systemd is running.  Note that some of
// these functions attempt to manually load systemd libraries at runtime rather
// than linking against them.
package util

// #cgo LDFLAGS: -ldl
// #include <stdlib.h>
// #include <dlfcn.h>
// #include <sys/types.h>
//
// int
// my_sd_pid_get_owner_uid(void *f, pid_t pid, uid_t *uid)
// {
//   int (*sd_pid_get_owner_uid)(pid_t, uid_t *);
//
//   sd_pid_get_owner_uid = (int (*)(pid_t, uid_t *))f;
//   return sd_pid_get_owner_uid(pid, uid);
// }
//
// int
// my_sd_pid_get_slice(void *f, pid_t pid, char **slice)
// {
//   int (*sd_pid_get_slice)(pid_t, char **);
//
//   sd_pid_get_slice = (int (*)(pid_t, char **))f;
//   return sd_pid_get_slice(pid, slice);
// }
//
import "C"
import (
	"errors"
	"fmt"
	"os"
	"syscall"
	"unsafe"
)

// libHandle represents an open handle to the systemd C library
type libHandle struct {
	handle  unsafe.Pointer
	libname string
}

func (h *libHandle) Close() error {
	if r := C.dlclose(h.handle); r != 0 {
		return fmt.Errorf("error closing %v: %d", h.libname, r)
	}
	return nil
}

// getHandle tries to get a handle to a systemd library (.so), attempting to
// access it by several different names and returning the first that is
// successfully opened. Callers are responsible for closing the handler.
// If no library can be successfully opened, an error is returned.
func getHandle() (*libHandle, error) {
	for _, name := range []string{
		// systemd < 209
		"libsystemd-login.so",
		"libsystemd-login.so.0",

		// systemd >= 209 merged libsystemd-login into libsystemd proper
		"libsystemd.so",
		"libsystemd.so.0",
	} {
		libname := C.CString(name)
		defer C.free(unsafe.Pointer(libname))
		handle := C.dlopen(libname, C.RTLD_LAZY)
		if handle != nil {
			h := &libHandle{
				handle:  handle,
				libname: name,
			}
			return h, nil
		}
	}
	return nil, errors.New("unable to open a handle to libsystemd")
}

// GetRunningSlice attempts to retrieve the name of the systemd slice in which
// the current process is running.
// This function is a wrapper around the libsystemd C library; if it cannot be
// opened, an error is returned.
func GetRunningSlice() (slice string, err error) {
	var h *libHandle
	h, err = getHandle()
	if err != nil {
		return
	}
	defer func() {
		if err1 := h.Close(); err1 != nil {
			err = err1
		}
	}()

	sym := C.CString("sd_pid_get_slice")
	defer C.free(unsafe.Pointer(sym))
	sd_pid_get_slice := C.dlsym(h.handle, sym)
	if sd_pid_get_slice == nil {
		err = fmt.Errorf("error resolving sd_pid_get_slice function")
		return
	}

	var s string
	sl := C.CString(s)
	defer C.free(unsafe.Pointer(sl))

	ret := C.my_sd_pid_get_slice(sd_pid_get_slice, 0, &sl)
	if ret < 0 {
		err = fmt.Errorf("error calling sd_pid_get_slice: %v", syscall.Errno(-ret))
		return
	}

	return C.GoString(sl), nil
}

// RunningFromSystemService tries to detect whether the current process has
// been invoked from a system service. The condition for this is whether the
// process is _not_ a user process. User processes are those running in session
// scopes or under per-user `systemd --user` instances.
//
// This function is a wrapper around the libsystemd C library, which results in
// the following caveats:
//   1) An error will be returned if this is unable to successfully open a
//      handle to the library for any reason (e.g. it cannot be found)
//   2) Since the implementation of sessions in systemd relies on the
//     `pam_systemd` module, this function can result in false positives if that
//      module (or PAM itself) is not present or properly configured on the system
func RunningFromSystemService() (ret bool, err error) {
	var h *libHandle
	h, err = getHandle()
	if err != nil {
		return
	}
	defer func() {
		if err1 := h.Close(); err1 != nil {
			err = err1
		}
	}()

	sym := C.CString("sd_pid_get_owner_uid")
	defer C.free(unsafe.Pointer(sym))
	sd_pid_get_owner_uid := C.dlsym(h.handle, sym)
	if sd_pid_get_owner_uid == nil {
		err = fmt.Errorf("error resolving sd_pid_get_owner_uid function")
		return
	}

	var uid C.uid_t
	errno := C.my_sd_pid_get_owner_uid(sd_pid_get_owner_uid, 0, &uid)
	serrno := syscall.Errno(-errno)
	// when we're running from a unit file, sd_pid_get_owner_uid returns
	// ENOENT (systemd <220) or ENXIO (systemd >=220)
	switch {
	case errno >= 0:
		ret = false
		return
	case serrno == syscall.ENOENT, serrno == syscall.ENXIO:
		ret = true
		return
	default:
		err = fmt.Errorf("error calling sd_pid_get_owner_uid: %v", syscall.Errno(-errno))
		return
	}
}

// IsRunningSystemd checks whether the host was booted with systemd as its init
// system. This functions similar to systemd's `sd_booted(3)`: internally, it
// checks whether /run/systemd/system/ exists and is a directory.
// http://www.freedesktop.org/software/systemd/man/sd_booted.html
func IsRunningSystemd() bool {
	fi, err := os.Lstat("/run/systemd/system")
	if err != nil {
		return false
	}
	return fi.IsDir()
}
<|endoftext|>


<commit_before>package util

func DeleteEmpty(s []string) []string {
	var r []string
	for _, str := range s {
		if str != "" {
			r = append(r, str)
		}
	}
	return r
}
<commit_msg>Add util function<commit_after>package util

import (
	"fmt"
	"time"
)

func DeleteEmpty(s []string) []string {
	var r []string
	for _, str := range s {
		if str != "" {
			r = append(r, str)
		}
	}
	return r
}

func ShortDate(date *time.Time) string {
	now := time.Now()
	ret := fmt.Sprintf("%02d시 %02d분", date.Hour(), date.Minute())
	need := 0
	if now.Year() != date.Year() {
		need = 3
	} else if now.Month() != date.Month() {
		need = 2
	} else if now.Day() != date.Day() {
		need = 1
	}
	if need >= 1 {
		ret = fmt.Sprintf("%d일 %s", now.Day(), ret)
	}
	if need >= 2 {
		ret = fmt.Sprintf("%d월 %s", now.Month(), ret)
	}
	if need >= 3 {
		ret = fmt.Sprintf("%d년 %s", now.Year(), ret)
	}
	return ret
}
<|endoftext|>


<commit_before>package doc

import (
	"errors"
	"net/url"
	"path/filepath"
	"strings"

	"sourcegraph.com/sourcegraph/repo"
	"sourcegraph.com/sourcegraph/vcsfs"
)

type ReadmeFormatter interface {
	GetFormattedReadme(repo *repo.Repository) (string, error)
}

type OnlineReadmeFormatter struct {
	VCSFS vcsfs.Service
}

var ErrNoReadme = errors.New("no readme found in repository")

// GetFormattedReadme returns repo's HTML-formatted readme, or an empty string
// and ErrNoReadme if the repository has no README.
func (s *OnlineReadmeFormatter) GetFormattedReadme(repo *repo.Repository) (formattedReadme string, err error) {
	cloneURL, err := url.Parse(repo.CloneURL)
	if err != nil {
		return "", err
	}
	src, path, err := s.VCSFS.GetFirstExistingFile(repo.VCS, cloneURL, repo.RevSpecOrDefault(), readmeNames)
	if err != nil {
		return "", ErrNoReadme
	}
	return ToHTML(readmeFormats[strings.ToLower(filepath.Ext(path))], string(src))
}

type MockReadmeFormatter struct {
	GetFormattedReadme_ func(repo *repo.Repository) (string, error)
}

var _ ReadmeFormatter = MockReadmeFormatter{}

func (s MockReadmeFormatter) GetFormattedReadme(repo *repo.Repository) (string, error) {
	if s.GetFormattedReadme_ == nil {
		return "", nil
	}
	return s.GetFormattedReadme_(repo)
}

var readmeNames = []string{
	"README.md",
	"README.rst",
	"ReadMe.md",
	"Readme.md",
	"readme.md",
	"README.markdown",
	"ReadMe.markdown",
	"readme.markdown",
	"README",
	"ReadMe",
	"Readme",
	"readme",
	"README.rdoc",
	"README.txt",
	"ReadMe.txt",
	"readme.txt",
	"ReadMe.rst",
	"Readme.rst",
	"readme.rst",
}

var readmeFormats = map[string]Format{
	".md":       Markdown,
	".markdown": Markdown,
	".mdown":    Markdown,
	".rdoc":     Markdown, // TODO(sqs): actually implement RDoc
	".txt":      Text,
	".text":     Text,
	"":          Text,
	".ascii":    Text,
	".rst":      ReStructuredText,
}
<commit_msg>Simplify repository DB code<commit_after>package doc

import (
	"errors"
	"net/url"
	"path/filepath"
	"strings"

	"sourcegraph.com/sourcegraph/repo"
	"sourcegraph.com/sourcegraph/vcsfs"
)

type ReadmeFormatter interface {
	GetFormattedReadme(repo *repo.Repository) (string, error)
}

type OnlineReadmeFormatter struct {
	VCSFS vcsfs.Service
}

var ErrNoReadme = errors.New("no readme found in repository")

// GetFormattedReadme returns repo's HTML-formatted readme, or an empty string
// and ErrNoReadme if the repository has no README.
func (s *OnlineReadmeFormatter) GetFormattedReadme(repo *repo.Repository) (formattedReadme string, err error) {
	cloneURL, err := url.Parse(repo.CloneURL)
	if err != nil {
		return "", err
	}
	src, path, err := s.VCSFS.GetFirstExistingFile(string(repo.VCS), cloneURL, repo.DefaultBranch, readmeNames)
	if err != nil {
		return "", ErrNoReadme
	}
	return ToHTML(readmeFormats[strings.ToLower(filepath.Ext(path))], string(src))
}

type MockReadmeFormatter struct {
	GetFormattedReadme_ func(repo *repo.Repository) (string, error)
}

var _ ReadmeFormatter = MockReadmeFormatter{}

func (s MockReadmeFormatter) GetFormattedReadme(repo *repo.Repository) (string, error) {
	if s.GetFormattedReadme_ == nil {
		return "", nil
	}
	return s.GetFormattedReadme_(repo)
}

var readmeNames = []string{
	"README.md",
	"README.rst",
	"ReadMe.md",
	"Readme.md",
	"readme.md",
	"README.markdown",
	"ReadMe.markdown",
	"readme.markdown",
	"README",
	"ReadMe",
	"Readme",
	"readme",
	"README.rdoc",
	"README.txt",
	"ReadMe.txt",
	"readme.txt",
	"ReadMe.rst",
	"Readme.rst",
	"readme.rst",
}

var readmeFormats = map[string]Format{
	".md":       Markdown,
	".markdown": Markdown,
	".mdown":    Markdown,
	".rdoc":     Markdown, // TODO(sqs): actually implement RDoc
	".txt":      Text,
	".text":     Text,
	"":          Text,
	".ascii":    Text,
	".rst":      ReStructuredText,
}
<|endoftext|>


<commit_before>
package money

import (
	"github.com/reiver/go-numeric"

	"errors"
	"fmt"
	"strconv"
	"strings"
)

// ParseCAD converts a string to a CAD.
func ParseCAD(str string) (CAD, error) {
	cents, err := parseDollarsAndCents(str)
	return CAD(cents), err
}

// ParseUSD converts a string to a USD.
func ParseUSD(str string) (USD, error) {
	cents, err := parseDollarsAndCents(str)
	return USD(cents), err
}

func parseDollarsAndCents(str string) (int64, error) {

	// Trim leading and ending whitespace.
	str = strings.TrimSpace(str)

	// If resulting string is empty, return an error.
	if "" == str {
//@TODO: Make better error.
		return 0, errors.New("Nothing in the string.")
	}

	// Convert to runes.
	runes := []rune(str)

	// Check if it begins with a negative symbol.
	// (I.e., a hyphen.)
	//
	// If it does have a negative symbol we
	// truncate the rune slice by removing
	// the first character (i.e., removing
	// the negative symbol).
	hasNegativeSymbol := false
	if '-' == runes[0] {
		hasNegativeSymbol = true
		runes = runes[1:]
	}
	if 1 > len(runes) {
//@TODO: Make better error.
		return 0, fmt.Errorf("Parse error on %q.", str)
	}

	// Check if it begins with a dollar symbol
	// or ends with a cents symbol.
	hasDollarSymbol := false
	hasCentsSymbol := false

	switch runes[0] {
	case '$',     // normal dollar sign
	'\uFE69',     // small dollar sign
	'\uFF04',     // full-width dollar sign
	'\U0001F4B2': // heavy dollar sign
		hasDollarSymbol = true
		runes = runes[1:]
	}
	if !hasDollarSymbol {
		switch runes[0] {
		case '\u00A2', // cent sign
		     '\uFFE0': // full-width cent sign
			hasCentsSymbol = true
			runes = runes[:len(runes)-1]
		}
	}
	if 1 > len(runes) {
//@TODO: Make better error.
		return 0, fmt.Errorf("Parse error on %q.", str)
	}

//@TODO: This is a bit hacky. This was added to make it so could parse things
//       like "84.27". I.e., no dollar or cent symbol.
//       Make this better later.
	if !hasDollarSymbol && !hasCentsSymbol {
		hasDollarSymbol = true
		for i:=0; i<len(runes); i++ {
			if r := runes[i]; !numeric.IsNumeric(r) && '.' != r && ',' != r {
				hasDollarSymbol = false
			}
		}
	}

	switch {
	case hasDollarSymbol:
		cents, err := parseDollars(runes)
		if hasNegativeSymbol {
			cents = -1 * cents
		}
		return cents, err
	case hasCentsSymbol:
		cents, err := parseCents(runes)
		if hasNegativeSymbol {
			cents = -1 * cents
		}
		return cents, err
	default:
//@TODO: Make better error.
		return 0, fmt.Errorf("Parse error on %q.", str)
	}
}

func parseDollars(runes []rune) (int64, error) {

	// Money is stored in cents not dollars.
	// So if the string (which we converted to []rune elsewhere)
	// has a decimal point (either "." or ",") in it then we deal
	// with that situation.
	//
	// So, for example:
	//
	//	"12345.67" -> "1234567"
	//
	//	"12345,67" -> "1234567"
	//
	//	"12,345.67" -> "12,34567"
	//
	//	"12.345,67" -> "12.34567"
	//
	//	"12345" -> "1234500"
	//
	//	"0.10" -> "010"
	//
	//	"0,10" -> "010"
    //
    //  "0,1"  -> "010"
	//
	// After that then if the decimal point is a dot (".") then we remove comma (",") separators.
	// Alternatively, if the decimal point is a comma (",") then we remove dot (".") separators.
	//
	// So, for example:
	//
	//	"12345.67" -> "1234567" -> "1234567"
	//
	//	"12345,67" -> "1234567" -> "1234567"
	//
	//	"12,345.67" -> "12,34567" -> "1234567"
	//
	//	"12.345,67" -> "12.34567" -> "12.34567"
	//
	//	"12345" -> "1234500" -> "1234500"
	//
	//	"0.10" -> "010" -> "010"
	//
	//	"0,10" -> "010" -> "010"
	//
	//  "0.1" ->  "010"  -> "010"

	if hasSingleDecimalPlace := 2 <= len(runes) && ('.' == runes[len(runes)-2] || ',' == runes[len(runes)-2]); hasSingleDecimalPlace {
		runes = append(runes, '0')
	}

	if hasDotDecimalPoint := 3 <= len(runes) && '.' == runes[len(runes)-3]; hasDotDecimalPoint {

		i := len(runes)-3

		runes = append(runes[:i], runes[i+1:]...)

//@TODO: This is not the proper way to remove the separator ",".
		for ii:=0; ii<len(runes); ii++ {

			if ',' == runes[ii] {
				runes = append(runes[:ii], runes[1+ii:]...)
			}
		}
	} else if hasCommaDecimalPoint := 3 <= len(runes) && ',' == runes[len(runes)-3]; hasCommaDecimalPoint {

		i := len(runes)-3

		runes = append(runes[:i], runes[i+1:]...)

//@TODO: This is not the proper way to remove the separator ".".
		for ii:=0; ii<len(runes); ii++ {

			if '.' == runes[ii] {
				runes = append(runes[:ii], runes[1+ii:]...)
			}
		}
	} else {

		if 4 <= len(runes) && ',' == runes[len(runes)-4] {
//@TODO: This is not the proper way to remove the separator ",".
			for ii:=0; ii<len(runes); ii++ {

				if ',' == runes[ii] {
					runes = append(runes[:ii], runes[1+ii:]...)
				}
			}

		} else if 4 <= len(runes) && '.' == runes[len(runes)-4] {
//@TODO: This is not the proper way to remove the separator ".".
			for ii:=0; ii<len(runes); ii++ {

				if '.' == runes[ii] {
					runes = append(runes[:ii], runes[1+ii:]...)
				}
			}
		}

		runes = append(runes, '0', '0')
	}

	// Return.
	return parseCents(runes)
}

func parseCents(runes []rune) (int64, error) {

	// Convert the string into an int64.
	// And then convert that int64 into money.
	const base = 10
	const bitSize = 64
	if i, err := strconv.ParseInt(string(runes), base, bitSize); nil != err {
		return 0, err
	} else {
		return i, nil
	}

}
<commit_msg>MustParseCAD and MustParseUSD<commit_after>
package money

import (
	"github.com/reiver/go-numeric"

	"errors"
	"fmt"
	"strconv"
	"strings"
)

// MustParseCAD converts a string to a CAD, but panic()s if there is an error.
func MustParseCAD(str string) CAD {
	cad, err := ParseCAD(str)
	if nil != err {
		panic(err)
	}

	return cad
}

// MustParseUSD converts a string to a USD, but panic()s if there is an error.
func MustParseUSD(str string) USD {
	usd, err := ParseUSD(str)
	if nil != err {
		panic(err)
	}

	return usd
}

// ParseCAD converts a string to a CAD.
func ParseCAD(str string) (CAD, error) {
	cents, err := parseDollarsAndCents(str)
	return CAD(cents), err
}

// ParseUSD converts a string to a USD.
func ParseUSD(str string) (USD, error) {
	cents, err := parseDollarsAndCents(str)
	return USD(cents), err
}

func parseDollarsAndCents(str string) (int64, error) {

	// Trim leading and ending whitespace.
	str = strings.TrimSpace(str)

	// If resulting string is empty, return an error.
	if "" == str {
//@TODO: Make better error.
		return 0, errors.New("Nothing in the string.")
	}

	// Convert to runes.
	runes := []rune(str)

	// Check if it begins with a negative symbol.
	// (I.e., a hyphen.)
	//
	// If it does have a negative symbol we
	// truncate the rune slice by removing
	// the first character (i.e., removing
	// the negative symbol).
	hasNegativeSymbol := false
	if '-' == runes[0] {
		hasNegativeSymbol = true
		runes = runes[1:]
	}
	if 1 > len(runes) {
//@TODO: Make better error.
		return 0, fmt.Errorf("Parse error on %q.", str)
	}

	// Check if it begins with a dollar symbol
	// or ends with a cents symbol.
	hasDollarSymbol := false
	hasCentsSymbol := false

	switch runes[0] {
	case '$',     // normal dollar sign
	'\uFE69',     // small dollar sign
	'\uFF04',     // full-width dollar sign
	'\U0001F4B2': // heavy dollar sign
		hasDollarSymbol = true
		runes = runes[1:]
	}
	if !hasDollarSymbol {
		switch runes[0] {
		case '\u00A2', // cent sign
		     '\uFFE0': // full-width cent sign
			hasCentsSymbol = true
			runes = runes[:len(runes)-1]
		}
	}
	if 1 > len(runes) {
//@TODO: Make better error.
		return 0, fmt.Errorf("Parse error on %q.", str)
	}

//@TODO: This is a bit hacky. This was added to make it so could parse things
//       like "84.27". I.e., no dollar or cent symbol.
//       Make this better later.
	if !hasDollarSymbol && !hasCentsSymbol {
		hasDollarSymbol = true
		for i:=0; i<len(runes); i++ {
			if r := runes[i]; !numeric.IsNumeric(r) && '.' != r && ',' != r {
				hasDollarSymbol = false
			}
		}
	}

	switch {
	case hasDollarSymbol:
		cents, err := parseDollars(runes)
		if hasNegativeSymbol {
			cents = -1 * cents
		}
		return cents, err
	case hasCentsSymbol:
		cents, err := parseCents(runes)
		if hasNegativeSymbol {
			cents = -1 * cents
		}
		return cents, err
	default:
//@TODO: Make better error.
		return 0, fmt.Errorf("Parse error on %q.", str)
	}
}

func parseDollars(runes []rune) (int64, error) {

	// Money is stored in cents not dollars.
	// So if the string (which we converted to []rune elsewhere)
	// has a decimal point (either "." or ",") in it then we deal
	// with that situation.
	//
	// So, for example:
	//
	//	"12345.67" -> "1234567"
	//
	//	"12345,67" -> "1234567"
	//
	//	"12,345.67" -> "12,34567"
	//
	//	"12.345,67" -> "12.34567"
	//
	//	"12345" -> "1234500"
	//
	//	"0.10" -> "010"
	//
	//	"0,10" -> "010"
    //
    //  "0,1"  -> "010"
	//
	// After that then if the decimal point is a dot (".") then we remove comma (",") separators.
	// Alternatively, if the decimal point is a comma (",") then we remove dot (".") separators.
	//
	// So, for example:
	//
	//	"12345.67" -> "1234567" -> "1234567"
	//
	//	"12345,67" -> "1234567" -> "1234567"
	//
	//	"12,345.67" -> "12,34567" -> "1234567"
	//
	//	"12.345,67" -> "12.34567" -> "12.34567"
	//
	//	"12345" -> "1234500" -> "1234500"
	//
	//	"0.10" -> "010" -> "010"
	//
	//	"0,10" -> "010" -> "010"
	//
	//  "0.1" ->  "010"  -> "010"

	if hasSingleDecimalPlace := 2 <= len(runes) && ('.' == runes[len(runes)-2] || ',' == runes[len(runes)-2]); hasSingleDecimalPlace {
		runes = append(runes, '0')
	}

	if hasDotDecimalPoint := 3 <= len(runes) && '.' == runes[len(runes)-3]; hasDotDecimalPoint {

		i := len(runes)-3

		runes = append(runes[:i], runes[i+1:]...)

//@TODO: This is not the proper way to remove the separator ",".
		for ii:=0; ii<len(runes); ii++ {

			if ',' == runes[ii] {
				runes = append(runes[:ii], runes[1+ii:]...)
			}
		}
	} else if hasCommaDecimalPoint := 3 <= len(runes) && ',' == runes[len(runes)-3]; hasCommaDecimalPoint {

		i := len(runes)-3

		runes = append(runes[:i], runes[i+1:]...)

//@TODO: This is not the proper way to remove the separator ".".
		for ii:=0; ii<len(runes); ii++ {

			if '.' == runes[ii] {
				runes = append(runes[:ii], runes[1+ii:]...)
			}
		}
	} else {

		if 4 <= len(runes) && ',' == runes[len(runes)-4] {
//@TODO: This is not the proper way to remove the separator ",".
			for ii:=0; ii<len(runes); ii++ {

				if ',' == runes[ii] {
					runes = append(runes[:ii], runes[1+ii:]...)
				}
			}

		} else if 4 <= len(runes) && '.' == runes[len(runes)-4] {
//@TODO: This is not the proper way to remove the separator ".".
			for ii:=0; ii<len(runes); ii++ {

				if '.' == runes[ii] {
					runes = append(runes[:ii], runes[1+ii:]...)
				}
			}
		}

		runes = append(runes, '0', '0')
	}

	// Return.
	return parseCents(runes)
}

func parseCents(runes []rune) (int64, error) {

	// Convert the string into an int64.
	// And then convert that int64 into money.
	const base = 10
	const bitSize = 64
	if i, err := strconv.ParseInt(string(runes), base, bitSize); nil != err {
		return 0, err
	} else {
		return i, nil
	}

}
<|endoftext|>


<commit_before>package plugins

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	"github.com/grafana/grafana/pkg/log"
	"github.com/grafana/grafana/pkg/setting"
	"github.com/hashicorp/go-version"
)

var (
	httpClient http.Client = http.Client{Timeout: time.Duration(10 * time.Second)}
)

type GrafanaNetPlugin struct {
	Slug    string `json:"slug"`
	Version string `json:"version"`
}

type GithubLatest struct {
	Stable  string `json:"stable"`
	Testing string `json:"testing"`
}

func StartPluginUpdateChecker() {
	if !setting.CheckForUpdates {
		return
	}

	// do one check directly
	go checkForUpdates()

	ticker := time.NewTicker(time.Minute * 10)
	for {
		select {
		case <-ticker.C:
			checkForUpdates()
		}
	}
}

func getAllExternalPluginSlugs() string {
	var result []string
	for _, plug := range Plugins {
		if plug.IsCorePlugin {
			continue
		}

		result = append(result, plug.Id)
	}

	return strings.Join(result, ",")
}

func checkForUpdates() {
	log.Trace("Checking for updates")

	pluginSlugs := getAllExternalPluginSlugs()
	resp, err := httpClient.Get("https://grafana.com/api/plugins/versioncheck?slugIn=" + pluginSlugs + "&grafanaVersion=" + setting.BuildVersion)

	if err != nil {
		log.Trace("Failed to get plugins repo from grafana.net, %v", err.Error())
		return
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Trace("Update check failed, reading response from grafana.com, %v", err.Error())
		return
	}

	gNetPlugins := []GrafanaNetPlugin{}
	err = json.Unmarshal(body, &gNetPlugins)
	if err != nil {
		log.Trace("Failed to unmarshal plugin repo, reading response from grafana.com, %v", err.Error())
		return
	}

	for _, plug := range Plugins {
		for _, gplug := range gNetPlugins {
			if gplug.Slug == plug.Id {
				plug.GrafanaNetVersion = gplug.Version

				plugVersion, err1 := version.NewVersion(plug.Info.Version)
				gplugVersion, err2 := version.NewVersion(gplug.Version)

				if err1 != nil || err2 != nil {
					plug.GrafanaNetHasUpdate = plug.Info.Version != plug.GrafanaNetVersion
				} else {
					plug.GrafanaNetHasUpdate = plugVersion.LessThan(gplugVersion)
				}
			}
		}
	}

	resp2, err := httpClient.Get("https://raw.githubusercontent.com/grafana/grafana/master/latest.json")
	if err != nil {
		log.Trace("Failed to get latest.json repo from github: %v", err.Error())
		return
	}

	defer resp2.Body.Close()
	body, err = ioutil.ReadAll(resp2.Body)
	if err != nil {
		log.Trace("Update check failed, reading response from github.com, %v", err.Error())
		return
	}

	var githubLatest GithubLatest
	err = json.Unmarshal(body, &githubLatest)
	if err != nil {
		log.Trace("Failed to unmarshal github latest, reading response from github: %v", err.Error())
		return
	}

	if strings.Contains(setting.BuildVersion, "-") {
		GrafanaLatestVersion = githubLatest.Testing
		GrafanaHasUpdate = !strings.HasPrefix(setting.BuildVersion, githubLatest.Testing)
	} else {
		GrafanaLatestVersion = githubLatest.Stable
		GrafanaHasUpdate = githubLatest.Stable != setting.BuildVersion
	}

	currVersion, err1 := version.NewVersion(setting.BuildVersion)
	latestVersion, err2 := version.NewVersion(GrafanaLatestVersion)

	if err1 == nil && err2 == nil {
		GrafanaHasUpdate = currVersion.LessThan(latestVersion)
	}
}
<commit_msg>Fix urls in plugin update_checker logs<commit_after>package plugins

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	"github.com/grafana/grafana/pkg/log"
	"github.com/grafana/grafana/pkg/setting"
	"github.com/hashicorp/go-version"
)

var (
	httpClient http.Client = http.Client{Timeout: time.Duration(10 * time.Second)}
)

type GrafanaNetPlugin struct {
	Slug    string `json:"slug"`
	Version string `json:"version"`
}

type GithubLatest struct {
	Stable  string `json:"stable"`
	Testing string `json:"testing"`
}

func StartPluginUpdateChecker() {
	if !setting.CheckForUpdates {
		return
	}

	// do one check directly
	go checkForUpdates()

	ticker := time.NewTicker(time.Minute * 10)
	for {
		select {
		case <-ticker.C:
			checkForUpdates()
		}
	}
}

func getAllExternalPluginSlugs() string {
	var result []string
	for _, plug := range Plugins {
		if plug.IsCorePlugin {
			continue
		}

		result = append(result, plug.Id)
	}

	return strings.Join(result, ",")
}

func checkForUpdates() {
	log.Trace("Checking for updates")

	pluginSlugs := getAllExternalPluginSlugs()
	resp, err := httpClient.Get("https://grafana.com/api/plugins/versioncheck?slugIn=" + pluginSlugs + "&grafanaVersion=" + setting.BuildVersion)

	if err != nil {
		log.Trace("Failed to get plugins repo from grafana.com, %v", err.Error())
		return
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Trace("Update check failed, reading response from grafana.com, %v", err.Error())
		return
	}

	gNetPlugins := []GrafanaNetPlugin{}
	err = json.Unmarshal(body, &gNetPlugins)
	if err != nil {
		log.Trace("Failed to unmarshal plugin repo, reading response from grafana.com, %v", err.Error())
		return
	}

	for _, plug := range Plugins {
		for _, gplug := range gNetPlugins {
			if gplug.Slug == plug.Id {
				plug.GrafanaNetVersion = gplug.Version

				plugVersion, err1 := version.NewVersion(plug.Info.Version)
				gplugVersion, err2 := version.NewVersion(gplug.Version)

				if err1 != nil || err2 != nil {
					plug.GrafanaNetHasUpdate = plug.Info.Version != plug.GrafanaNetVersion
				} else {
					plug.GrafanaNetHasUpdate = plugVersion.LessThan(gplugVersion)
				}
			}
		}
	}

	resp2, err := httpClient.Get("https://raw.githubusercontent.com/grafana/grafana/master/latest.json")
	if err != nil {
		log.Trace("Failed to get latest.json repo from github.com: %v", err.Error())
		return
	}

	defer resp2.Body.Close()
	body, err = ioutil.ReadAll(resp2.Body)
	if err != nil {
		log.Trace("Update check failed, reading response from github.com, %v", err.Error())
		return
	}

	var githubLatest GithubLatest
	err = json.Unmarshal(body, &githubLatest)
	if err != nil {
		log.Trace("Failed to unmarshal github.com latest, reading response from github.com: %v", err.Error())
		return
	}

	if strings.Contains(setting.BuildVersion, "-") {
		GrafanaLatestVersion = githubLatest.Testing
		GrafanaHasUpdate = !strings.HasPrefix(setting.BuildVersion, githubLatest.Testing)
	} else {
		GrafanaLatestVersion = githubLatest.Stable
		GrafanaHasUpdate = githubLatest.Stable != setting.BuildVersion
	}

	currVersion, err1 := version.NewVersion(setting.BuildVersion)
	latestVersion, err2 := version.NewVersion(GrafanaLatestVersion)

	if err1 == nil && err2 == nil {
		GrafanaHasUpdate = currVersion.LessThan(latestVersion)
	}
}
<|endoftext|>


<commit_before>package ics

import (
	"fmt"
	"io/ioutil"
	"regexp"
	// "strings"
	// "errors"
	// "fmt"
	// "io"
	// "net/http"
	// "os"
	"sync"
	// "time"
)

type Parser struct {
	inputChan chan string
	errChan   chan error
}

// creates new parser and chan for calendar
func New() chan string {
	p := new(Parser)
	p.inputChan = make(chan string)
	p.errChan = make(chan error)

	//  init only once the WaitGroup
	o.Do(func() {
		Wg = new(sync.WaitGroup)
		// fmt.Println(Wg)
	})

	go func(input chan string) {
		// fmt.Println("Goroute")
		for {
			link := <-input
			Wg.Add(1)
			go func(link string) {
				iCalContent, err := p.getICal(link)
				if err != nil {
					p.errChan <- err
					return
				}
				p.parseICalContent(iCalContent)
			}(link)
		}
	}(p.inputChan)
	// p.wg.Wait()
	return p.inputChan
}

//  get the data from the calendar
func (p *Parser) getICal(url string) (string, error) {
	fileName, errDownload := downloadFromUrl(url)

	if errDownload != nil {
		return "", errDownload
	}

	fileContent, errReadFile := ioutil.ReadFile(fileName)
	if errReadFile != nil {
		return "", errReadFile
	}
	return fmt.Sprintf("%s", fileContent), nil
}

// parses the iCal formated string
func (p *Parser) parseICalContent(iCalContent string) {
	ical := NewCalendar()
	ical.SetName(p.parseICalName(iCalContent))
	ical.SetDesc(p.parseICalDesc(iCalContent))
	fmt.Println(ical.name)
	fmt.Println(ical.description)
	Wg.Done()
}

// parses the iCal Name
func (p *Parser) parseICalName(iCalContent string) string {
	re, _ := regexp.Compile(`X-WR-CALNAME:.*?\n`)
	result := re.Find(stringToByte(iCalContent))
	return trimField(fmt.Sprintf("%s", result), "X-WR-CALNAME:")
}

// parses the iCal description
func (p *Parser) parseICalDesc(iCalContent string) string {
	re, _ := regexp.Compile(`X-WR-CALDESC:.*?\n`)
	result := re.Find(stringToByte(iCalContent))
	return trimField(fmt.Sprintf("%s", result), "X-WR-CALDESC:")
}
<commit_msg>NewParser return fix + Get<type>Chan funcs<commit_after>package ics

import (
	"fmt"
	"io/ioutil"
	"regexp"
	// "strings"
	// "errors"
	// "fmt"
	// "io"
	// "net/http"
	// "os"
	"sync"
	// "time"
)

type Parser struct {
	inputChan  chan string
	outputChan chan Event
	errChan    chan error
}

// creates new parser
func New() chan string {
	p := new(Parser)
	p.inputChan = make(chan string)
	p.outputChan = make(chan Event)
	p.errChan = make(chan error)

	//  init only once the WaitGroup
	o.Do(func() {
		Wg = new(sync.WaitGroup)
		// fmt.Println(Wg)
	})

	go func(input chan string) {
		// fmt.Println("Goroute")
		for {
			link := <-input
			Wg.Add(1)
			go func(link string) {
				iCalContent, err := p.getICal(link)
				if err != nil {
					p.errChan <- err
					return
				}
				p.parseICalContent(iCalContent)
			}(link)
		}
	}(p.inputChan)
	// p.wg.Wait()
	// return p.inputChan
	return p
}

//  returns the chan for calendar urls
func (p *Parser) GetInputChan() chan string {
	return p.inputChan
}

// returns the chan where will be received events
func (p *Parser) GetOutputChan() chan Event {
	return p.outputChan
}

//  get the data from the calendar
func (p *Parser) getICal(url string) (string, error) {
	fileName, errDownload := downloadFromUrl(url)

	if errDownload != nil {
		return "", errDownload
	}

	fileContent, errReadFile := ioutil.ReadFile(fileName)
	if errReadFile != nil {
		return "", errReadFile
	}
	return fmt.Sprintf("%s", fileContent), nil
}

// parses the iCal formated string
func (p *Parser) parseICalContent(iCalContent string) {
	ical := NewCalendar()
	ical.SetName(p.parseICalName(iCalContent))
	ical.SetDesc(p.parseICalDesc(iCalContent))
	fmt.Println(ical.name)
	fmt.Println(ical.description)
	Wg.Done()
}

// parses the iCal Name
func (p *Parser) parseICalName(iCalContent string) string {
	re, _ := regexp.Compile(`X-WR-CALNAME:.*?\n`)
	result := re.Find(stringToByte(iCalContent))
	return trimField(fmt.Sprintf("%s", result), "X-WR-CALNAME:")
}

// parses the iCal description
func (p *Parser) parseICalDesc(iCalContent string) string {
	re, _ := regexp.Compile(`X-WR-CALDESC:.*?\n`)
	result := re.Find(stringToByte(iCalContent))
	return trimField(fmt.Sprintf("%s", result), "X-WR-CALDESC:")
}
<|endoftext|>


<commit_before>// Package utils contains various supplementary functions and data structures.
// This file cli.go contains functions for very simple console interface.
package utils

import (
	"bufio"
	"fmt"
	"os"
	"runtime"
	"sort"
	"strconv"
	"strings"
)

// ShowBanner function shows application's greeting banner.
func ShowBanner(rev string) {
	fmt.Printf("Get IE tool. Build rev %s.\n", rev)
}

// YesNoConfirmation function shows Yes/No choice. N is default choice for now.
func YesNoConfirmation(msg string) {
	reader := bufio.NewReader(os.Stdin)
	defer fmt.Println()
	fmt.Printf("%s [y/N]: ", msg)
	text, _ := reader.ReadString('\n')

	if strings.HasPrefix(strings.ToLower(strings.TrimSpace(text)), "y") {
		fmt.Println("Confirmed. Continue operations")
	} else {
		fmt.Println("Cancelled. Exiting..")
		os.Exit(1)
	}
}

// EnterToContinue function shows press ENTER confirmation for a give message.
func EnterToContinue(msg string) {
	reader := bufio.NewReader(os.Stdin)
	if runtime.GOOS == "darwin" {
		fmt.Printf("%s\nPress ENTER to continue CMD-C to abort.\n", msg)
	} else {
		fmt.Printf("%s\nPress ENTER to continue CTRL-C to abort.\n", msg)
	}
	reader.ReadString('\n')
}

// SelectOption function shows simple selection 'menu'.
func SelectOption(choices ChoiceGroups, groupMsg, groupName string, defaultChoiceFunc DefaultChoice) string {
	reader := bufio.NewReader(os.Stdin)
	defer fmt.Println()

	sortedChoices := choices[groupName]
	sort.Sort(sortedChoices)
	defaultChoice := defaultChoiceFunc(sortedChoices)
	for choice, option := range sortedChoices {
		fmt.Println(choice, option)
	}
	for {
		fmt.Printf("%s [%d]: ", groupMsg, defaultChoice)
		text, _ := reader.ReadString('\n')
		if strings.TrimSpace(text) == "" {
			return sortedChoices[defaultChoice]
		}
		selected, err := strconv.Atoi(strings.TrimSpace(text))
		if err != nil {
			continue
		}
		if selected < 0 || selected > len(sortedChoices) {
			continue
		}
		return sortedChoices[selected]
	}
}

// ConfirmUsersChoice shows options selected by a user.
func ConfirmUsersChoice(userChoice UserChoice) {
	fmt.Println("Platform:", userChoice.Spec.Platform)
	fmt.Println("Hypervisor:", userChoice.Spec.Hypervisor)
	fmt.Println("Browser and OS:", userChoice.Spec.BrowserOs)
	fmt.Println("Download path:", userChoice.DownloadPath)
	YesNoConfirmation("Confirm your selection")
}

// ShowHypervisorWarning function shows hypervisor specific warnings if any.
func ShowHypervisorWarning(hypervisor string) {
	switch hypervisor {
	case "HyperV":
		EnterToContinue("WARNING: For HyperV you must run this tool as Administrator.")
	case "VMware":
		if runtime.GOOS == "darwin" {
			EnterToContinue("WARNING: At least VMware Fusion must be isntalled to run this tool correctly.")
		} else {
			EnterToContinue("WARNING: At least VMware Workstation must be isntalled to run this tool correctly.")
		}
	case "VirtualBox":
		if runtime.GOOS == "windows" {
			EnterToContinue("WARNING: VirtualBox could fail to run selected VM if Hyper-V is also installed.")
		}
	case "VPC":
		EnterToContinue("WARNING: VPC (Virtual-PC) is obsolete.")
	}
}
<commit_msg>Added warning message for Parallels, fixed several typos<commit_after>// Package utils contains various supplementary functions and data structures.
// This file cli.go contains functions for very simple console interface.
package utils

import (
	"bufio"
	"fmt"
	"os"
	"runtime"
	"sort"
	"strconv"
	"strings"
)

// ShowBanner function shows application's greeting banner.
func ShowBanner(rev string) {
	fmt.Printf("Get IE tool. Build rev %s.\n", rev)
}

// YesNoConfirmation function shows Yes/No choice. N is default choice for now.
func YesNoConfirmation(msg string) {
	reader := bufio.NewReader(os.Stdin)
	defer fmt.Println()
	fmt.Printf("%s [y/N]: ", msg)
	text, _ := reader.ReadString('\n')

	if strings.HasPrefix(strings.ToLower(strings.TrimSpace(text)), "y") {
		fmt.Println("Confirmed. Continue operations")
	} else {
		fmt.Println("Cancelled. Exiting..")
		os.Exit(1)
	}
}

// EnterToContinue function shows press ENTER confirmation for a give message.
func EnterToContinue(msg string) {
	reader := bufio.NewReader(os.Stdin)
	if runtime.GOOS == "darwin" {
		fmt.Printf("%s\nPress ENTER to continue CMD-C to abort.\n", msg)
	} else {
		fmt.Printf("%s\nPress ENTER to continue CTRL-C to abort.\n", msg)
	}
	reader.ReadString('\n')
}

// SelectOption function shows simple selection 'menu'.
func SelectOption(choices ChoiceGroups, groupMsg, groupName string, defaultChoiceFunc DefaultChoice) string {
	reader := bufio.NewReader(os.Stdin)
	defer fmt.Println()

	sortedChoices := choices[groupName]
	sort.Sort(sortedChoices)
	defaultChoice := defaultChoiceFunc(sortedChoices)
	for choice, option := range sortedChoices {
		fmt.Println(choice, option)
	}
	for {
		fmt.Printf("%s [%d]: ", groupMsg, defaultChoice)
		text, _ := reader.ReadString('\n')
		if strings.TrimSpace(text) == "" {
			return sortedChoices[defaultChoice]
		}
		selected, err := strconv.Atoi(strings.TrimSpace(text))
		if err != nil {
			continue
		}
		if selected < 0 || selected > len(sortedChoices) {
			continue
		}
		return sortedChoices[selected]
	}
}

// ConfirmUsersChoice shows options selected by a user.
func ConfirmUsersChoice(userChoice UserChoice) {
	fmt.Println("Platform:", userChoice.Spec.Platform)
	fmt.Println("Hypervisor:", userChoice.Spec.Hypervisor)
	fmt.Println("Browser and OS:", userChoice.Spec.BrowserOs)
	fmt.Println("Download path:", userChoice.DownloadPath)
	YesNoConfirmation("Confirm your selection")
}

// ShowHypervisorWarning function shows hypervisor specific warnings if any.
func ShowHypervisorWarning(hypervisor string) {
	switch hypervisor {
	case "HyperV":
		EnterToContinue("WARNING: For HyperV you must run this tool as Administrator.")
	case "VMware":
		if runtime.GOOS == "darwin" {
			EnterToContinue("WARNING: At least VMware Fusion must be installed to run this tool correctly.")
		} else {
			EnterToContinue("WARNING: At least VMware Workstation must be installed to run this tool correctly.")
			EnterToContinue("WARNING: VMware hypervisor isn't compatible with Hyper-V hypervisor.")
		}
	case "Parallels":
			EnterToContinue("WARNING: Parallels Desktop for Mac Pro or Business Edition must be installed to run this tool correctly.")
	case "VirtualBox":
		if runtime.GOOS == "windows" {
			EnterToContinue("WARNING: VirtualBox could fail to run selected VM if Hyper-V is also installed.")
		}
	case "VPC":
		EnterToContinue("WARNING: VPC (Virtual-PC) is obsolete.")
	}
}
<|endoftext|>


<commit_before>package system // import "github.com/docker/docker/pkg/system"

import (
	"os"
	"regexp"
	"syscall"
	"unsafe"

	"golang.org/x/sys/windows"
)

// SddlAdministratorsLocalSystem is local administrators plus NT AUTHORITY\System.
const SddlAdministratorsLocalSystem = "D:P(A;OICI;GA;;;BA)(A;OICI;GA;;;SY)"

// volumePath is a regular expression to check if a path is a Windows
// volume path (e.g., "\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}"
// or "\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}\").
var volumePath = regexp.MustCompile(`^\\\\\?\\Volume{[a-z0-9-]+}\\?$`)

// MkdirAllWithACL is a custom version of os.MkdirAll modified for use on Windows
// so that it is both volume path aware, and can create a directory with
// an appropriate SDDL defined ACL.
func MkdirAllWithACL(path string, _ os.FileMode, sddl string) error {
	return mkdirall(path, true, sddl)
}

// MkdirAll is a custom version of os.MkdirAll that is volume path aware for
// Windows. It can be used as a drop-in replacement for os.MkdirAll.
func MkdirAll(path string, _ os.FileMode) error {
	return mkdirall(path, false, "")
}

// mkdirall is a custom version of os.MkdirAll modified for use on Windows
// so that it is both volume path aware, and can create a directory with
// a DACL.
func mkdirall(path string, applyACL bool, sddl string) error {
	if volumePath.MatchString(path) {
		return nil
	}

	// The rest of this method is largely copied from os.MkdirAll and should be kept
	// as-is to ensure compatibility.

	// Fast path: if we can tell whether path is a directory or file, stop with success or error.
	dir, err := os.Stat(path)
	if err == nil {
		if dir.IsDir() {
			return nil
		}
		return &os.PathError{
			Op:   "mkdir",
			Path: path,
			Err:  syscall.ENOTDIR,
		}
	}

	// Slow path: make sure parent exists and then call Mkdir for path.
	i := len(path)
	for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator.
		i--
	}

	j := i
	for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element.
		j--
	}

	if j > 1 {
		// Create parent
		err = mkdirall(path[0:j-1], false, sddl)
		if err != nil {
			return err
		}
	}

	// Parent now exists; invoke os.Mkdir or mkdirWithACL and use its result.
	if applyACL {
		err = mkdirWithACL(path, sddl)
	} else {
		err = os.Mkdir(path, 0)
	}

	if err != nil {
		// Handle arguments like "foo/." by
		// double-checking that directory doesn't exist.
		dir, err1 := os.Lstat(path)
		if err1 == nil && dir.IsDir() {
			return nil
		}
		return err
	}
	return nil
}

// mkdirWithACL creates a new directory. If there is an error, it will be of
// type *PathError. .
//
// This is a modified and combined version of os.Mkdir and windows.Mkdir
// in golang to cater for creating a directory am ACL permitting full
// access, with inheritance, to any subfolder/file for Built-in Administrators
// and Local System.
func mkdirWithACL(name string, sddl string) error {
	sa := windows.SecurityAttributes{Length: 0}
	sd, err := windows.SecurityDescriptorFromString(sddl)
	if err != nil {
		return &os.PathError{Op: "mkdir", Path: name, Err: err}
	}
	sa.Length = uint32(unsafe.Sizeof(sa))
	sa.InheritHandle = 1
	sa.SecurityDescriptor = sd

	namep, err := windows.UTF16PtrFromString(name)
	if err != nil {
		return &os.PathError{Op: "mkdir", Path: name, Err: err}
	}

	e := windows.CreateDirectory(namep, &sa)
	if e != nil {
		return &os.PathError{Op: "mkdir", Path: name, Err: e}
	}
	return nil
}
<commit_msg>pkg/system: create SecurityAttribute only once (Windows)<commit_after>package system // import "github.com/docker/docker/pkg/system"

import (
	"os"
	"regexp"
	"syscall"
	"unsafe"

	"golang.org/x/sys/windows"
)

// SddlAdministratorsLocalSystem is local administrators plus NT AUTHORITY\System.
const SddlAdministratorsLocalSystem = "D:P(A;OICI;GA;;;BA)(A;OICI;GA;;;SY)"

// volumePath is a regular expression to check if a path is a Windows
// volume path (e.g., "\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}"
// or "\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}\").
var volumePath = regexp.MustCompile(`^\\\\\?\\Volume{[a-z0-9-]+}\\?$`)

// MkdirAllWithACL is a custom version of os.MkdirAll modified for use on Windows
// so that it is both volume path aware, and can create a directory with
// an appropriate SDDL defined ACL.
func MkdirAllWithACL(path string, _ os.FileMode, sddl string) error {
	sa, err := makeSecurityAttributes(sddl)
	if err != nil {
		return &os.PathError{Op: "mkdirall", Path: path, Err: err}
	}
	return mkdirall(path, sa)
}

// MkdirAll is a custom version of os.MkdirAll that is volume path aware for
// Windows. It can be used as a drop-in replacement for os.MkdirAll.
func MkdirAll(path string, _ os.FileMode) error {
	return mkdirall(path, nil)
}

// mkdirall is a custom version of os.MkdirAll modified for use on Windows
// so that it is both volume path aware, and can create a directory with
// a DACL.
func mkdirall(path string, perm *windows.SecurityAttributes) error {
	if volumePath.MatchString(path) {
		return nil
	}

	// The rest of this method is largely copied from os.MkdirAll and should be kept
	// as-is to ensure compatibility.

	// Fast path: if we can tell whether path is a directory or file, stop with success or error.
	dir, err := os.Stat(path)
	if err == nil {
		if dir.IsDir() {
			return nil
		}
		return &os.PathError{
			Op:   "mkdir",
			Path: path,
			Err:  syscall.ENOTDIR,
		}
	}

	// Slow path: make sure parent exists and then call Mkdir for path.
	i := len(path)
	for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator.
		i--
	}

	j := i
	for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element.
		j--
	}

	if j > 1 {
		// Create parent
		err = mkdirall(path[0:j-1], perm)
		if err != nil {
			return err
		}
	}

	// Parent now exists; invoke os.Mkdir or mkdirWithACL and use its result.
	err = mkdirWithACL(path, perm)
	if err != nil {
		// Handle arguments like "foo/." by
		// double-checking that directory doesn't exist.
		dir, err1 := os.Lstat(path)
		if err1 == nil && dir.IsDir() {
			return nil
		}
		return err
	}
	return nil
}

// mkdirWithACL creates a new directory. If there is an error, it will be of
// type *PathError. .
//
// This is a modified and combined version of os.Mkdir and windows.Mkdir
// in golang to cater for creating a directory am ACL permitting full
// access, with inheritance, to any subfolder/file for Built-in Administrators
// and Local System.
func mkdirWithACL(name string, sa *windows.SecurityAttributes) error {
	if sa == nil {
		return os.Mkdir(name, 0)
	}

	namep, err := windows.UTF16PtrFromString(name)
	if err != nil {
		return &os.PathError{Op: "mkdir", Path: name, Err: err}
	}

	err = windows.CreateDirectory(namep, sa)
	if err != nil {
		return &os.PathError{Op: "mkdir", Path: name, Err: err}
	}
	return nil
}

func makeSecurityAttributes(sddl string) (*windows.SecurityAttributes, error) {
	var sa windows.SecurityAttributes
	sa.Length = uint32(unsafe.Sizeof(sa))
	sa.InheritHandle = 1
	var err error
	sa.SecurityDescriptor, err = windows.SecurityDescriptorFromString(sddl)
	if err != nil {
		return nil, err
	}
	return &sa, nil
}
<|endoftext|>


<commit_before>package influxdb

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"path"

	"golang.org/x/net/context/ctxhttp"

	"github.com/grafana/grafana/pkg/log"
	"github.com/grafana/grafana/pkg/setting"
	"github.com/grafana/grafana/pkg/tsdb"
)

type InfluxDBExecutor struct {
	*tsdb.DataSourceInfo
	QueryParser    *InfluxdbQueryParser
	ResponseParser *ResponseParser
}

func NewInfluxDBExecutor(dsInfo *tsdb.DataSourceInfo) tsdb.Executor {
	return &InfluxDBExecutor{
		DataSourceInfo: dsInfo,
		QueryParser:    &InfluxdbQueryParser{},
		ResponseParser: &ResponseParser{},
	}
}

var (
	glog       log.Logger
	HttpClient *http.Client
)

func init() {
	glog = log.New("tsdb.influxdb")
	tsdb.RegisterExecutor("influxdb", NewInfluxDBExecutor)

	HttpClient = tsdb.GetDefaultClient()
}

func (e *InfluxDBExecutor) Execute(ctx context.Context, queries tsdb.QuerySlice, context *tsdb.QueryContext) *tsdb.BatchResult {
	result := &tsdb.BatchResult{}

	query, err := e.getQuery(queries, context)
	if err != nil {
		return result.WithError(err)
	}

	rawQuery, err := query.Build(context)
	if err != nil {
		return result.WithError(err)
	}

	if setting.Env == setting.DEV {
		glog.Debug("Influxdb query", "raw query", rawQuery)
	}

	req, err := e.createRequest(rawQuery)
	if err != nil {
		return result.WithError(err)
	}

	resp, err := ctxhttp.Do(ctx, HttpClient, req)
	if err != nil {
		return result.WithError(err)
	}

	if resp.StatusCode/100 != 2 {
		return result.WithError(fmt.Errorf("Influxdb returned statuscode invalid status code: %v", resp.Status))
	}

	var response Response
	dec := json.NewDecoder(resp.Body)
	defer resp.Body.Close()
	dec.UseNumber()
	err = dec.Decode(&response)

	if err != nil {
		return result.WithError(err)
	}

	if response.Err != nil {
		return result.WithError(response.Err)
	}

	result.QueryResults = make(map[string]*tsdb.QueryResult)
	result.QueryResults["A"] = e.ResponseParser.Parse(&response, query)

	return result
}

func (e *InfluxDBExecutor) getQuery(queries tsdb.QuerySlice, context *tsdb.QueryContext) (*Query, error) {
	for _, v := range queries {

		query, err := e.QueryParser.Parse(v.Model, e.DataSourceInfo)
		if err != nil {
			return nil, err
		}

		return query, nil
	}

	return nil, fmt.Errorf("query request contains no queries")
}

func (e *InfluxDBExecutor) createRequest(query string) (*http.Request, error) {
	u, _ := url.Parse(e.Url)
	u.Path = path.Join(u.Path, "query")

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

	params := req.URL.Query()
	params.Set("q", query)
	params.Set("db", e.Database)
	params.Set("epoch", "s")
	req.URL.RawQuery = params.Encode()

	req.Header.Set("User-Agent", "Grafana")

	if e.BasicAuth {
		req.SetBasicAuth(e.BasicAuthUser, e.BasicAuthPassword)
	}

	if e.User != "" {
		req.SetBasicAuth(e.User, e.Password)
	}

	glog.Debug("Influxdb request", "url", req.URL.String())
	return req, nil
}
<commit_msg>fix(influxdb): align tsdb.influxdb with dataproxy<commit_after>package influxdb

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"path"

	"golang.org/x/net/context/ctxhttp"

	"github.com/grafana/grafana/pkg/log"
	"github.com/grafana/grafana/pkg/setting"
	"github.com/grafana/grafana/pkg/tsdb"
)

type InfluxDBExecutor struct {
	*tsdb.DataSourceInfo
	QueryParser    *InfluxdbQueryParser
	ResponseParser *ResponseParser
}

func NewInfluxDBExecutor(dsInfo *tsdb.DataSourceInfo) tsdb.Executor {
	return &InfluxDBExecutor{
		DataSourceInfo: dsInfo,
		QueryParser:    &InfluxdbQueryParser{},
		ResponseParser: &ResponseParser{},
	}
}

var (
	glog       log.Logger
	HttpClient *http.Client
)

func init() {
	glog = log.New("tsdb.influxdb")
	tsdb.RegisterExecutor("influxdb", NewInfluxDBExecutor)

	HttpClient = tsdb.GetDefaultClient()
}

func (e *InfluxDBExecutor) Execute(ctx context.Context, queries tsdb.QuerySlice, context *tsdb.QueryContext) *tsdb.BatchResult {
	result := &tsdb.BatchResult{}

	query, err := e.getQuery(queries, context)
	if err != nil {
		return result.WithError(err)
	}

	rawQuery, err := query.Build(context)
	if err != nil {
		return result.WithError(err)
	}

	if setting.Env == setting.DEV {
		glog.Debug("Influxdb query", "raw query", rawQuery)
	}

	req, err := e.createRequest(rawQuery)
	if err != nil {
		return result.WithError(err)
	}

	resp, err := ctxhttp.Do(ctx, HttpClient, req)
	if err != nil {
		return result.WithError(err)
	}

	if resp.StatusCode/100 != 2 {
		return result.WithError(fmt.Errorf("Influxdb returned statuscode invalid status code: %v", resp.Status))
	}

	var response Response
	dec := json.NewDecoder(resp.Body)
	defer resp.Body.Close()
	dec.UseNumber()
	err = dec.Decode(&response)

	if err != nil {
		return result.WithError(err)
	}

	if response.Err != nil {
		return result.WithError(response.Err)
	}

	result.QueryResults = make(map[string]*tsdb.QueryResult)
	result.QueryResults["A"] = e.ResponseParser.Parse(&response, query)

	return result
}

func (e *InfluxDBExecutor) getQuery(queries tsdb.QuerySlice, context *tsdb.QueryContext) (*Query, error) {
	for _, v := range queries {

		query, err := e.QueryParser.Parse(v.Model, e.DataSourceInfo)
		if err != nil {
			return nil, err
		}

		return query, nil
	}

	return nil, fmt.Errorf("query request contains no queries")
}

func (e *InfluxDBExecutor) createRequest(query string) (*http.Request, error) {
	u, _ := url.Parse(e.Url)
	u.Path = path.Join(u.Path, "query")

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

	params := req.URL.Query()
	params.Set("q", query)
	params.Set("db", e.Database)
	params.Set("epoch", "s")
	req.URL.RawQuery = params.Encode()

	req.Header.Set("User-Agent", "Grafana")

	if e.BasicAuth {
		req.SetBasicAuth(e.BasicAuthUser, e.BasicAuthPassword)
	}

	if !e.BasicAuth && e.User != "" {
		req.SetBasicAuth(e.User, e.Password)
	}

	glog.Debug("Influxdb request", "url", req.URL.String())
	return req, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2018 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 naming

import (
	"fmt"
	"regexp"
	goruntime "runtime"
	"runtime/debug"
	"strconv"
	"strings"
)

// GetNameFromCallsite walks back through the call stack until we find a caller from outside of the ignoredPackages
// it returns back a shortpath/filename:line to aid in identification of this reflector when it starts logging
func GetNameFromCallsite(ignoredPackages ...string) string {
	name := "????"
	const maxStack = 10
	for i := 1; i < maxStack; i++ {
		_, file, line, ok := goruntime.Caller(i)
		if !ok {
			file, line, ok = extractStackCreator()
			if !ok {
				break
			}
			i += maxStack
		}
		if hasPackage(file, append(ignoredPackages, "/runtime/asm_")) {
			continue
		}

		file = trimPackagePrefix(file)
		name = fmt.Sprintf("%s:%d", file, line)
		break
	}
	return name
}

// hasPackage returns true if the file is in one of the ignored packages.
func hasPackage(file string, ignoredPackages []string) bool {
	for _, ignoredPackage := range ignoredPackages {
		if strings.Contains(file, ignoredPackage) {
			return true
		}
	}
	return false
}

// trimPackagePrefix reduces duplicate values off the front of a package name.
func trimPackagePrefix(file string) string {
	if l := strings.LastIndex(file, "/vendor/"); l >= 0 {
		return file[l+len("/vendor/"):]
	}
	if l := strings.LastIndex(file, "/src/"); l >= 0 {
		return file[l+5:]
	}
	if l := strings.LastIndex(file, "/pkg/"); l >= 0 {
		return file[l+1:]
	}
	return file
}

var stackCreator = regexp.MustCompile(`(?m)^created by (.*)\n\s+(.*):(\d+) \+0x[[:xdigit:]]+$`)

// extractStackCreator retrieves the goroutine file and line that launched this stack. Returns false
// if the creator cannot be located.
// TODO: Go does not expose this via runtime https://github.com/golang/go/issues/11440
func extractStackCreator() (string, int, bool) {
	stack := debug.Stack()
	matches := stackCreator.FindStringSubmatch(string(stack))
	if matches == nil || len(matches) != 4 {
		return "", 0, false
	}
	line, err := strconv.Atoi(matches[3])
	if err != nil {
		return "", 0, false
	}
	return matches[2], line, true
}
<commit_msg>Remove unnecessary judgment<commit_after>/*
Copyright 2018 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 naming

import (
	"fmt"
	"regexp"
	goruntime "runtime"
	"runtime/debug"
	"strconv"
	"strings"
)

// GetNameFromCallsite walks back through the call stack until we find a caller from outside of the ignoredPackages
// it returns back a shortpath/filename:line to aid in identification of this reflector when it starts logging
func GetNameFromCallsite(ignoredPackages ...string) string {
	name := "????"
	const maxStack = 10
	for i := 1; i < maxStack; i++ {
		_, file, line, ok := goruntime.Caller(i)
		if !ok {
			file, line, ok = extractStackCreator()
			if !ok {
				break
			}
			i += maxStack
		}
		if hasPackage(file, append(ignoredPackages, "/runtime/asm_")) {
			continue
		}

		file = trimPackagePrefix(file)
		name = fmt.Sprintf("%s:%d", file, line)
		break
	}
	return name
}

// hasPackage returns true if the file is in one of the ignored packages.
func hasPackage(file string, ignoredPackages []string) bool {
	for _, ignoredPackage := range ignoredPackages {
		if strings.Contains(file, ignoredPackage) {
			return true
		}
	}
	return false
}

// trimPackagePrefix reduces duplicate values off the front of a package name.
func trimPackagePrefix(file string) string {
	if l := strings.LastIndex(file, "/vendor/"); l >= 0 {
		return file[l+len("/vendor/"):]
	}
	if l := strings.LastIndex(file, "/src/"); l >= 0 {
		return file[l+5:]
	}
	if l := strings.LastIndex(file, "/pkg/"); l >= 0 {
		return file[l+1:]
	}
	return file
}

var stackCreator = regexp.MustCompile(`(?m)^created by (.*)\n\s+(.*):(\d+) \+0x[[:xdigit:]]+$`)

// extractStackCreator retrieves the goroutine file and line that launched this stack. Returns false
// if the creator cannot be located.
// TODO: Go does not expose this via runtime https://github.com/golang/go/issues/11440
func extractStackCreator() (string, int, bool) {
	stack := debug.Stack()
	matches := stackCreator.FindStringSubmatch(string(stack))
	if len(matches) != 4 {
		return "", 0, false
	}
	line, err := strconv.Atoi(matches[3])
	if err != nil {
		return "", 0, false
	}
	return matches[2], line, true
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"encoding/hex"
	"flag"
	"fmt"
	"hash/crc32"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"time"

	"github.com/tarm/serial"
	"gopkg.in/readline.v1"
)

var (
	rlInstance *readline.Instance
	conn       *serial.Port
	serIn      = make(chan []byte)
	outBound   = make(chan string)
	progress   = make(chan bool, 1)
	incLevel   = make(chan int)

	port    = flag.String("p", "", "serial port (required: /dev/tty* or COM*)")
	baud    = flag.Int("b", 115200, "baud rate")
	upload  = flag.String("u", "", "upload the specified firmware, then quit")
	expand  = flag.String("e", "", "expand specified file to stdout, then quit")
	verbose = flag.Bool("v", false, "verbose output, for debugging only")
	capture = flag.String("c", "", "a file where captured output is appended")
	timeout = flag.Duration("t", 500*time.Millisecond, "serial echo timeout")
)

func main() {
	flag.Parse()
	var err error

	// expansion does not use the serial port, it just expands include lines
	if *expand != "" {
		expandFile()
		return
	}

	if *port == "" || flag.NArg() > 0 {
		flag.PrintDefaults()
		os.Exit(1)
	}
	config := serial.Config{Name: *port, Baud: *baud}
	if *upload != "" {
		config.Parity = serial.ParityEven
	}
	conn, err = serial.OpenPort(&config)
	check(err)
	//defer conn.Close()
	fmt.Println("Connected to:", *port)

	go serialInput() // feed the serIn channel

	// firmware upload uses serial in a different way, needs to quit when done
	if *upload != "" {
		firmwareUpload()
		return
	}

	rlInstance, err = readline.NewEx(&readline.Config{
		UniqueEditLine: true,
	})
	check(err)
	defer rlInstance.Close()

	go serialExchange()

	for {
		line, err := rlInstance.Readline()
		if err != nil { // io.EOF, readline.ErrInterrupt
			break
		}
		parseAndSend(line)
	}
}

func parseAndSend(line string) {
	if strings.HasPrefix(line, "include ") {
		for _, fname := range strings.Split(line[8:], " ") {
			doInclude(fname)
		}
	} else {
		outBound <- line
		<-progress
	}
}

func check(err error) {
	if err != nil {
		if rlInstance != nil {
			rlInstance.Close()
		}
		log.Fatal(err)
	}
}

func serialInput() {
	var f *os.File
	if *capture != "" {
		var err error
		opts := os.O_WRONLY | os.O_APPEND | os.O_CREATE
		f, err = os.OpenFile(*capture, opts, 0666)
		check(err)
		defer f.Close()
	}
	for {
		buf := make([]byte, 100)
		n, err := conn.Read(buf)
		check(err)
		if n == 0 {
			close(serIn)
			return
		}
		if f != nil {
			f.Write(buf[:n])
		}
		serIn <- buf[:n]
	}
}

func readWithTimeout() []byte {
	select {
	case data := <-serIn:
		return data
	case <-time.After(*timeout):
		return nil
	}
}

func serialExchange() {
	depth := 0
	for {
		select {

		case data := <-serIn:
			if len(data) == 0 {
				return
			}
			fmt.Print(string(data))

		case line := <-outBound:
			immediate := depth == 0
			// the task here is to omit "normal" output for included lines,
			// i.e. lines which only generate an echo, a space, and " ok.\n"
			// everything else should be echoed in full, including the input
			if len(line) > 0 {
				serialSend(line)
				prefix, matched := expectEcho(line, false, func(s string) {
					fmt.Print(s) // called to flush pending serial input lines
				})
				fmt.Print(prefix)
				if matched && immediate {
					fmt.Print(line)
					line = ""
				}
			}
			// now that the echo is done, send a CR and wait for the prompt
			serialSend("\r")
			prompt := " ok.\n"
			prefix, matched := expectEcho(prompt, immediate, func(s string) {
				fmt.Print(line + s) // show original command first
				line = ""
			})
			if !matched {
				prompt = ""
			}
			if immediate || prefix != " " || !matched {
				fmt.Print(line + prefix + prompt)
			}
			// signal to sender that this request has been processed
			progress <- matched

		case n := <-incLevel:
			depth += n
		}
	}
}

func expectEcho(match string, immed bool, flusher func(string)) (string, bool) {
	var collected []byte
	for {
		data := readWithTimeout()
		collected = append(collected, data...)
		if bytes.HasSuffix(collected, []byte(match)) {
			bytesBefore := len(collected) - len(match)
			return string(collected[:bytesBefore]), true
		}
		if immed || len(data) == 0 {
			return string(collected), false
		}
		if n := bytes.LastIndexByte(collected, '\n'); n >= 0 {
			flusher(string(collected[:n+1]))
			collected = collected[n+1:]
		}
	}
}

func serialSend(data string) {
	_, err := conn.Write([]byte(data))
	check(err)
}

func doInclude(fname string) {
	if fname == "" {
		return // silently ignore empty files
	}

	incLevel <- +1
	defer func() { incLevel <- -1 }()

	lineNum := 0
	fmt.Printf("\\       >>> include %s\n", fname)
	defer func() {
		fmt.Printf("\\       <<<<<<<<<<< %s (%d lines)\n", fname, lineNum)
	}()

	f, err := os.Open(fname)
	if err != nil {
		fmt.Println(err)
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := scanner.Text()
		lineNum++

		s := strings.TrimLeft(line, " ")
		if s == "" || strings.HasPrefix(s, "\\ ") {
			if len(*expand) == 0 {
				continue // don't send empty or comment-only lines
			}
		}

		parseAndSend(line)
	}
}

func expandFile() {
	go func() {
		for line := range outBound {
			fmt.Println(line)
			progress <- true
		}
	}()

	go func() {
		for range incLevel {
		}
	}()

	for _, fname := range strings.Split(*expand, ",") {
		doInclude(fname)
	}
}

func hexToBin(data []byte) []byte {
	var bin []byte
	for _, line := range strings.Split(string(data), "\n") {
		if strings.HasSuffix(line, "\r") {
			line = line[:len(line)-1]
		}
		if len(line) == 0 {
			continue
		}
		if line[0] != ':' || len(line) < 11 {
			fmt.Println("Not ihex format:", line)
			os.Exit(1)
		}
		bytes, err := hex.DecodeString(line[1:])
		check(err)
		if bytes[3] != 0x00 {
			continue
		}
		offset := (int(bytes[1]) << 8) + int(bytes[2])
		length := bytes[0]
		for offset < len(bin) {
			bin = append(bin, 0xFF)
		}
		bin = append(bin, bytes[4:4+length]...)
	}
	return bin
}

func firmwareUpload() {
	f, err := os.Open(*upload)
	if err != nil {
		fmt.Println(err)
	}
	defer f.Close()

	data, err := ioutil.ReadAll(f)
	check(err)

	// convert to binary if first bytes look like they are in hex format
	tag := ""
	if len(data) > 11 && data[0] == ':' {
		_, err = hex.DecodeString(string(data[1:11]))
		if err == nil {
			data = hexToBin(data)
			tag = " (converted from Intel HEX)"
		}
	}

	fmt.Printf("        File: %s\n", *upload)
	fmt.Printf("       Count: %d bytes%s\n", len(data), tag)
	fmt.Printf("    Checksum: %08x hex\n", crc32.ChecksumIEEE(data))

	uploadSTM32(data)
}
<commit_msg>flush pending input on startup<commit_after>package main

import (
	"bufio"
	"bytes"
	"encoding/hex"
	"flag"
	"fmt"
	"hash/crc32"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"time"

	"github.com/tarm/serial"
	"gopkg.in/readline.v1"
)

var (
	rlInstance *readline.Instance
	conn       *serial.Port
	serIn      = make(chan []byte)
	outBound   = make(chan string)
	progress   = make(chan bool, 1)
	incLevel   = make(chan int)

	port    = flag.String("p", "", "serial port (required: /dev/tty* or COM*)")
	baud    = flag.Int("b", 115200, "baud rate")
	upload  = flag.String("u", "", "upload the specified firmware, then quit")
	expand  = flag.String("e", "", "expand specified file to stdout, then quit")
	verbose = flag.Bool("v", false, "verbose output, for debugging only")
	capture = flag.String("c", "", "a file where captured output is appended")
	timeout = flag.Duration("t", 500*time.Millisecond, "serial echo timeout")
)

func main() {
	flag.Parse()
	var err error

	// expansion does not use the serial port, it just expands include lines
	if *expand != "" {
		expandFile()
		return
	}

	if *port == "" || flag.NArg() > 0 {
		flag.PrintDefaults()
		os.Exit(1)
	}
	config := serial.Config{Name: *port, Baud: *baud}
	if *upload != "" {
		config.Parity = serial.ParityEven
	}
	conn, err = serial.OpenPort(&config)
	check(err)
	//defer conn.Close()
	fmt.Println("Connected to:", *port)

	go serialInput() // feed the serIn channel

	// firmware upload uses serial in a different way, needs to quit when done
	if *upload != "" {
		firmwareUpload()
		return
	}

	rlInstance, err = readline.NewEx(&readline.Config{
		UniqueEditLine: true,
	})
	check(err)
	defer rlInstance.Close()

	go serialExchange()

	conn.Flush()
	readWithTimeout()  // get rid of partial pending data
	for {
		line, err := rlInstance.Readline()
		if err != nil { // io.EOF, readline.ErrInterrupt
			break
		}
		parseAndSend(line)
	}
}

func parseAndSend(line string) {
	if strings.HasPrefix(line, "include ") {
		for _, fname := range strings.Split(line[8:], " ") {
			doInclude(fname)
		}
	} else {
		outBound <- line
		<-progress
	}
}

func check(err error) {
	if err != nil {
		if rlInstance != nil {
			rlInstance.Close()
		}
		log.Fatal(err)
	}
}

func serialInput() {
	var f *os.File
	if *capture != "" {
		var err error
		opts := os.O_WRONLY | os.O_APPEND | os.O_CREATE
		f, err = os.OpenFile(*capture, opts, 0666)
		check(err)
		defer f.Close()
	}
	for {
		buf := make([]byte, 600)
		n, err := conn.Read(buf)
		check(err)
		if n == 0 {
			close(serIn)
			return
		}
		if f != nil {
			f.Write(buf[:n])
		}
		serIn <- buf[:n]
	}
}

func readWithTimeout() []byte {
	select {
	case data := <-serIn:
		return data
	case <-time.After(*timeout):
		return nil
	}
}

func serialExchange() {
	depth := 0
	for {
		select {

		case data := <-serIn:
			if len(data) == 0 {
				return
			}
			fmt.Print(string(data))

		case line := <-outBound:
			immediate := depth == 0
			// the task here is to omit "normal" output for included lines,
			// i.e. lines which only generate an echo, a space, and " ok.\n"
			// everything else should be echoed in full, including the input
			if len(line) > 0 {
				serialSend(line)
				prefix, matched := expectEcho(line, false, func(s string) {
					fmt.Print(s) // called to flush pending serial input lines
				})
				fmt.Print(prefix)
				if matched && immediate {
					fmt.Print(line)
					line = ""
				}
			}
			// now that the echo is done, send a CR and wait for the prompt
			serialSend("\r")
			prompt := " ok.\n"
			prefix, matched := expectEcho(prompt, immediate, func(s string) {
				fmt.Print(line + s) // show original command first
				line = ""
			})
			if !matched {
				prompt = ""
			}
			if immediate || prefix != " " || !matched {
				fmt.Print(line + prefix + prompt)
			}
			// signal to sender that this request has been processed
			progress <- matched

		case n := <-incLevel:
			depth += n
		}
	}
}

func expectEcho(match string, immed bool, flusher func(string)) (string, bool) {
	var collected []byte
	for {
		data := readWithTimeout()
		collected = append(collected, data...)
		if bytes.HasSuffix(collected, []byte(match)) {
			bytesBefore := len(collected) - len(match)
			return string(collected[:bytesBefore]), true
		}
		if immed || len(data) == 0 {
			return string(collected), false
		}
		if n := bytes.LastIndexByte(collected, '\n'); n >= 0 {
			flusher(string(collected[:n+1]))
			collected = collected[n+1:]
		}
	}
}

func serialSend(data string) {
	_, err := conn.Write([]byte(data))
	check(err)
}

func doInclude(fname string) {
	if fname == "" {
		return // silently ignore empty files
	}

	incLevel <- +1
	defer func() { incLevel <- -1 }()

	lineNum := 0
	fmt.Printf("\\       >>> include %s\n", fname)
	defer func() {
		fmt.Printf("\\       <<<<<<<<<<< %s (%d lines)\n", fname, lineNum)
	}()

	f, err := os.Open(fname)
	if err != nil {
		fmt.Println(err)
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := scanner.Text()
		lineNum++

		s := strings.TrimLeft(line, " ")
		if s == "" || strings.HasPrefix(s, "\\ ") {
			if len(*expand) == 0 {
				continue // don't send empty or comment-only lines
			}
		}

		parseAndSend(line)
	}
}

func expandFile() {
	go func() {
		for line := range outBound {
			fmt.Println(line)
			progress <- true
		}
	}()

	go func() {
		for range incLevel {
		}
	}()

	for _, fname := range strings.Split(*expand, ",") {
		doInclude(fname)
	}
}

func hexToBin(data []byte) []byte {
	var bin []byte
	for _, line := range strings.Split(string(data), "\n") {
		if strings.HasSuffix(line, "\r") {
			line = line[:len(line)-1]
		}
		if len(line) == 0 {
			continue
		}
		if line[0] != ':' || len(line) < 11 {
			fmt.Println("Not ihex format:", line)
			os.Exit(1)
		}
		bytes, err := hex.DecodeString(line[1:])
		check(err)
		if bytes[3] != 0x00 {
			continue
		}
		offset := (int(bytes[1]) << 8) + int(bytes[2])
		length := bytes[0]
		for offset < len(bin) {
			bin = append(bin, 0xFF)
		}
		bin = append(bin, bytes[4:4+length]...)
	}
	return bin
}

func firmwareUpload() {
	f, err := os.Open(*upload)
	if err != nil {
		fmt.Println(err)
	}
	defer f.Close()

	data, err := ioutil.ReadAll(f)
	check(err)

	// convert to binary if first bytes look like they are in hex format
	tag := ""
	if len(data) > 11 && data[0] == ':' {
		_, err = hex.DecodeString(string(data[1:11]))
		if err == nil {
			data = hexToBin(data)
			tag = " (converted from Intel HEX)"
		}
	}

	fmt.Printf("        File: %s\n", *upload)
	fmt.Printf("       Count: %d bytes%s\n", len(data), tag)
	fmt.Printf("    Checksum: %08x hex\n", crc32.ChecksumIEEE(data))

	uploadSTM32(data)
}
<|endoftext|>


<commit_before>package checkers

import (
	"testing"

	"github.com/cl0ne/go-checkers/point"
)

func TestNewBoard(t *testing.T) {
	uselessBoard := NewBoard(0)
	if uselessBoard == nil {
		t.Error("Zero-sized boards aren't very useful, but got nil.")
	}
	if uselessBoard.Size() != 0 {
		t.Error("Zero-sized board after creation got size of", uselessBoard.Size())
	}

	invalidBoard := NewBoard(-1)
	if invalidBoard != nil {
		t.Error("Boards of negative size not allowed, got size of", invalidBoard.Size())
	}

	board8x8 := NewBoard(8)
	if board8x8 == nil {
		t.Error("Can't create 8x8 board got nil.")
	}
	if board8x8.Size() != 8 {
		t.Error("Size of created 8x8 board is", board8x8.Size())
	}
}

func TestBoardOperations(t *testing.T) {
	board := NewBoard(8)
	t.Run("IsEmpty", func(t *testing.T) {
		checker := newChecker(3, 3, true)
		p := point.Point{X: 3, Y: 3}
		board.placeChecker(p.X, p.Y, &checker)
		if board.IsEmpty(p.X, p.Y) {
			t.Error("Cell", p, "shouldn't be empty.")
		}
		p.X, p.Y = 4, 6
		if !board.IsEmpty(p.X, p.Y) {
			t.Error("Cell", p, "should be empty.")
		}
	})

	t.Run("ContainsPos", func(t *testing.T) {
		point := point.Point{X: 7, Y: 8}
		contains := board.ContainsPos(7, 8)
		if contains {
			t.Error("Cell", point, "is outside of the board.")
		}
		point.X, point.Y = 3, 2
		contains = board.ContainsPos(3, 2)
		if !contains {
			t.Error("Cell", point, "is within the board.")
		}
	})

	whiteCell := point.Point{X: 2, Y: 1}
	blackCell := point.Point{X: 4, Y: 0}

	t.Run("IsBlackSquare", func(t *testing.T) {
		if !board.IsBlackSquare(blackCell) {
			t.Error("Cell", blackCell, "must be black.")
		}
		if board.IsBlackSquare(whiteCell) {
			t.Error("Cell", whiteCell, "must be white.")
		}
	})

	t.Run("IsWhiteSquare", func(t *testing.T) {
		if !board.IsWhiteSquare(whiteCell) {
			t.Error("Cell", whiteCell, "must be white.")
		}
		if board.IsWhiteSquare(blackCell) {
			t.Error("Cell", blackCell, "must be black.")
		}
	})

	t.Run("TakeChecker", func(t *testing.T) {
		p := point.Point{X: 2, Y: 2}
		checker := newChecker(p.X, p.Y, true)
		board.placeChecker(p.X, p.Y, &checker)
		c := board.takeChecker(p.X, p.Y)
		if c == nil {
			t.Error("Can't take checker at", p, ": cell is empty.")
		}
	})

	t.Run("GetChecker", func(t *testing.T) {
		p := point.Point{X: 2, Y: 4}
		checker := newChecker(p.X, p.Y, false)
		board.placeChecker(p.X, p.Y, &checker)
		c := board.GetChecker(p.X, p.Y)
		if c == nil {
			t.Error("Checker at", p, "is missing.")
		}
		p.X, p.Y = 5, 5
		c = board.GetChecker(p.X, p.Y)
		if c != nil {
			t.Error("Cell", p, "should be empty")
		}
	})

	t.Run("MoveChecker", func(t *testing.T) {
		from := point.Point{X: 3, Y: 4}
    checker := newChecker(from.X, from.Y, true)
		to := point.Point{X: 4, Y: 3}
    board.placeChecker(from.X, from.Y, &checker)
		board.moveChecker(from, to)
		c := board.GetChecker(3, 4)
		if c != nil {
			t.Error("Checker wasn't moved from", from, "to", to)
		}
	})
}
<commit_msg>Fix bugs on tests of moving checkers<commit_after>package checkers

import (
	"testing"

	"github.com/cl0ne/go-checkers/point"
)

func TestNewBoard(t *testing.T) {
	uselessBoard := NewBoard(0)
	if uselessBoard == nil {
		t.Error("Zero-sized boards aren't very useful, but got nil.")
	}
	if uselessBoard.Size() != 0 {
		t.Error("Zero-sized board after creation got size of", uselessBoard.Size())
	}

	invalidBoard := NewBoard(-1)
	if invalidBoard != nil {
		t.Error("Boards of negative size not allowed, got size of", invalidBoard.Size())
	}

	board8x8 := NewBoard(8)
	if board8x8 == nil {
		t.Error("Can't create 8x8 board got nil.")
	}
	if board8x8.Size() != 8 {
		t.Error("Size of created 8x8 board is", board8x8.Size())
	}
}

func TestBoardOperations(t *testing.T) {
	board := NewBoard(8)
	t.Run("IsEmpty", func(t *testing.T) {
		checker := newChecker(3, 3, true)
		p := point.Point{X: 3, Y: 3}
		board.placeChecker(p.X, p.Y, &checker)
		if board.IsEmpty(p.X, p.Y) {
			t.Error("Cell", p, "shouldn't be empty.")
		}
		p.X, p.Y = 4, 6
		if !board.IsEmpty(p.X, p.Y) {
			t.Error("Cell", p, "should be empty.")
		}
	})

	t.Run("ContainsPos", func(t *testing.T) {
		point := point.Point{X: 7, Y: 8}
		contains := board.ContainsPos(7, 8)
		if contains {
			t.Error("Cell", point, "is outside of the board.")
		}
		point.X, point.Y = 3, 2
		contains = board.ContainsPos(3, 2)
		if !contains {
			t.Error("Cell", point, "is within the board.")
		}
	})

	whiteCell := point.Point{X: 2, Y: 1}
	blackCell := point.Point{X: 4, Y: 0}

	t.Run("IsBlackSquare", func(t *testing.T) {
		if !board.IsBlackSquare(blackCell) {
			t.Error("Cell", blackCell, "must be black.")
		}
		if board.IsBlackSquare(whiteCell) {
			t.Error("Cell", whiteCell, "must be white.")
		}
	})

	t.Run("IsWhiteSquare", func(t *testing.T) {
		if !board.IsWhiteSquare(whiteCell) {
			t.Error("Cell", whiteCell, "must be white.")
		}
		if board.IsWhiteSquare(blackCell) {
			t.Error("Cell", blackCell, "must be black.")
		}
	})

	t.Run("TakeChecker", func(t *testing.T) {
		p := point.Point{X: 2, Y: 2}
		checker := newChecker(p.X, p.Y, true)
		board.placeChecker(p.X, p.Y, &checker)
		c := board.takeChecker(p.X, p.Y)
		if c == nil {
			t.Error("Can't take checker at", p, ": cell is empty.")
		}
	})

	t.Run("GetChecker", func(t *testing.T) {
		p := point.Point{X: 2, Y: 4}
		checker := newChecker(p.X, p.Y, false)
		board.placeChecker(p.X, p.Y, &checker)
		c := board.GetChecker(p.X, p.Y)
		if c == nil {
			t.Error("Checker at", p, "is missing.")
		}
		p.X, p.Y = 5, 5
		c = board.GetChecker(p.X, p.Y)
		if c != nil {
			t.Error("Cell", p, "should be empty")
		}
	})

	t.Run("MoveChecker", func(t *testing.T) {
		from := point.Point{X: 3, Y: 4}
    checker := newChecker(from.X, from.Y, true)
		to := point.Point{X: 4, Y: 3}
    board.placeChecker(from.X, from.Y, &checker)
		board.moveChecker(from, to)
		if !board.IsEmpty(from.X, from.Y) {
			t.Error("Checker wasn't moved from", from, "to", to)
		}
	})
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"os/exec"
)

func main() {
	_, err := exec.LookPath("npm")
	if err != nil {
		fmt.Println("FATAL ERROR: could not find NPM\n" +
			"SEE: https://nodejs.org/ for installation instructions...")
		return
	}
	_, err = exec.LookPath("polymer")
	if err != nil {
		fmt.Println("FATAL ERROR: could not find Polymer CLI\n" +
			"SEE: https://polymer-library.polymer-project.org/3.0/docs/tools/polymer-cli for installation instructions...")
		return
	}
	err = os.Chdir("./public")
	if err != nil {
		fmt.Printf("FATAL ERROR: could not descend into ./public folder: %v\n", err)
		return
	}
	fmt.Println("*** INSTALLING WEBCOMPONENTS ***")
	cmd := exec.Command("npm", "install")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err = cmd.Run()
	if err != nil {
		fmt.Printf("FATAL ERROR: could not fetch webcomponents: %v", err)
		return
	}
	fmt.Println("*** SUCCESS ***")
	err = os.Chdir("../")
	if err != nil {
		fmt.Printf("FATAL ERROR: could not return to the main folder: %v\n", err)
		return
	}
	fmt.Println("*** BUILDING POLYMER SOURCES ***")
	cmd = exec.Command("polymer", "build")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err = cmd.Run()
	if err != nil {
		fmt.Printf("FATAL ERROR: could not build Polymer sources: %v", err)
		return
	}
	fmt.Println("*** SUCCESS ***")
}
<commit_msg>custom polymer cli<commit_after>package main

import (
	"fmt"
	"os"
	"os/exec"
)

func main() {
	_, err := exec.LookPath("npm")
	if err != nil {
		fmt.Println("FATAL ERROR: could not find NPM\n" +
			"SEE: https://nodejs.org/ for installation instructions...")
		return
	}
	_, err = os.Stat("./node_modules/.bin/polymer")
	if err != nil {
		fmt.Println("ERROR: Could not find Polymer CLI")
		fmt.Println("*** INSTALLING POLYMER-CLI ***")
		cmd := exec.Command("npm", "install", "--prefix=./", "polymer-cli")
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err := cmd.Run()
		if err != nil {
			fmt.Printf("FATAL ERROR: Could not install Polymer-CLI: %v\n", err)
			return
		}
		fmt.Println("*** SUCCESS ***")
	}
	err = os.Chdir("./public")
	if err != nil {
		fmt.Printf("FATAL ERROR: could not descend into ./public folder: %v\n", err)
		return
	}
	fmt.Println("*** INSTALLING WEBCOMPONENTS ***")
	cmd := exec.Command("npm", "install")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err = cmd.Run()
	if err != nil {
		fmt.Printf("FATAL ERROR: could not fetch webcomponents: %v", err)
		return
	}
	fmt.Println("*** SUCCESS ***")
	err = os.Chdir("../")
	if err != nil {
		fmt.Printf("FATAL ERROR: could not return to the main folder: %v\n", err)
		return
	}
	fmt.Println("*** BUILDING POLYMER SOURCES ***")
	cmd = exec.Command("./node_modules/.bin/polymer", "build")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err = cmd.Run()
	if err != nil {
		fmt.Printf("FATAL ERROR: could not build Polymer sources: %v", err)
		return
	}
	fmt.Println("*** SUCCESS ***")
}
<|endoftext|>