<commit_before>package main

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"time"

	_ "github.com/k0kubun/pp"
	"srcd.works/go-git.v4"
	"srcd.works/go-git.v4/plumbing"
)

type Installer interface {
	Initialize(config *Config) error
	Install(urls []string) error
}

type Config struct {
	Username       string
	Password       string
	Endpoint       string
	ApiVersion     string
	PollSeconds    int
	TimeoutSeconds int
	PackageFile    string
	IsCloneOnly    bool
	Directory      string
}

type SalesforceInstaller struct {
	Config *Config
	Client *ForceClient
	logger *Logger
}

func NewSalesforceInstaller(logger *Logger) *SalesforceInstaller {
	return &SalesforceInstaller{
		logger: logger,
	}
}

func (i *SalesforceInstaller) Initialize(config *Config) (err error) {
	i.Config = config
	if i.Config.IsCloneOnly {
		return nil
	}
	if i.Config.Username == "" {
		return errors.New("Username is required")
	}
	if i.Config.Password == "" {
		return errors.New("Password is required")
	}

	if !i.Config.IsCloneOnly {
		err = i.setClient()
	}
	if err != nil {
		return err
	}
	if i.Config.Directory == "" {
		if i.Config.IsCloneOnly {
			dir, err := os.Getwd()
			if err != nil {
				return err
			}
			i.Config.Directory = dir
		} else {
			i.Config.Directory = os.TempDir()
		}
	}
	return nil
}

func (i *SalesforceInstaller) setClient() error {
	i.Client = NewForceClient(i.Config.Endpoint, i.Config.ApiVersion)
	err := i.Client.Login(i.Config.Username, i.Config.Password)
	if err != nil {
		return err
	}
	return nil
}

func (i *SalesforceInstaller) Install(urls []string) error {
	for _, url := range urls {
		uri, dir, target_dir, branch := extractInstallParameter(url)

		err := i.installToSalesforce(uri, dir, target_dir, branch)
		if err != nil {
			return err
		}
	}
	return nil
}

func (i *SalesforceInstaller) installToSalesforce(url string, directory string, targetDirectory string, branch string) error {
	cloneDir := filepath.Join(i.Config.Directory, directory)
	i.logger.Info("Clone repository from " + url + " (branch: " + branch + ")")
	err := i.cloneFromRemoteRepository(cloneDir, url, branch, false)
	if err != nil {
		return err
	}
	if i.Config.IsCloneOnly {
		return nil
	}
	defer cleanTempDirectory(cloneDir)
	targetDirAbsPath := filepath.Join(cloneDir, targetDirectory)
	i.loadDependencies(targetDirAbsPath)
	err = i.deployToSalesforce(targetDirAbsPath)
	if err != nil {
		return err
	}
	return nil
}

func (i *SalesforceInstaller) cloneFromRemoteRepository(directory string, url string, paramBranch string, retry bool) (err error) {
	branch := "master"
	if paramBranch != "" {
		branch = paramBranch
	}
	_, err = git.PlainClone(directory, false, &git.CloneOptions{
		URL:           url,
		ReferenceName: plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", branch)),
		SingleBranch:  true,
	})
	if err != nil {
		if err.Error() != "repository already exists" {
			return
		}
		if retry == true {
			return
		}
		i.logger.Warningf("repository non empty: %s", directory)
		i.logger.Infof("remove directory: %s", directory)
		err = cleanTempDirectory(directory)
		if err != nil {
			return
		}
		err = i.cloneFromRemoteRepository(directory, url, paramBranch, true)
	}
	return
}

func (i *SalesforceInstaller) deployToSalesforce(directory string) error {
	buf, err := zipDirectory(directory)
	if err != nil {
		return err
	}

	response, err := i.Client.Deploy(buf.Bytes())
	if err != nil {
		return err
	}

	err = i.checkDeployStatus(response.Result.Id)
	if err != nil {
		return err
	}
	i.logger.Info("Deploy is successful")

	return nil
}

func (i *SalesforceInstaller) checkDeployStatus(resultId *ID) error {
	totalTime := 0
	for {
		time.Sleep(time.Duration(i.Config.PollSeconds) * time.Second)
		i.logger.Info("Check Deploy Result...")

		response, err := i.Client.CheckDeployStatus(resultId)
		if err != nil {
			return err
		}
		if response.Result.Done {
			return nil
		}
		if i.Config.TimeoutSeconds != 0 {
			totalTime += i.Config.PollSeconds
			if totalTime > i.Config.TimeoutSeconds {
				i.logger.Error("Deploy is timeout. Please check release status for the deployment")
				return nil
			}
		}
	}
}

func (i *SalesforceInstaller) loadDependencies(cloneDir string) error {
	targetFile := filepath.Join(cloneDir, "package.yml")
	_, err := os.Stat(targetFile)
	if err != nil {
		return nil
	}
	urls := []string{}
	packageFile, err := readPackageFile(targetFile)
	if err != nil {
		return err
	}
	for _, pkg := range packageFile.Packages {
		url, err := convertToUrl(pkg)
		if err != nil {
			return err
		}
		urls = append(urls, url)
	}
	return i.Install(urls)
}
<commit_msg>Mod log message<commit_after>package main

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"time"

	_ "github.com/k0kubun/pp"
	"srcd.works/go-git.v4"
	"srcd.works/go-git.v4/plumbing"
)

type Installer interface {
	Initialize(config *Config) error
	Install(urls []string) error
}

type Config struct {
	Username       string
	Password       string
	Endpoint       string
	ApiVersion     string
	PollSeconds    int
	TimeoutSeconds int
	PackageFile    string
	IsCloneOnly    bool
	Directory      string
}

type SalesforceInstaller struct {
	Config *Config
	Client *ForceClient
	logger *Logger
	urlStack []string
}

func NewSalesforceInstaller(logger *Logger) *SalesforceInstaller {
	return &SalesforceInstaller{
		logger: logger,
		urlStack: []string{},
	}
}

func (i *SalesforceInstaller) Initialize(config *Config) (err error) {
	i.Config = config
	if i.Config.IsCloneOnly {
		return nil
	}
	if i.Config.Username == "" {
		return errors.New("Username is required")
	}
	if i.Config.Password == "" {
		return errors.New("Password is required")
	}

	if !i.Config.IsCloneOnly {
		err = i.setClient()
	}
	if err != nil {
		return err
	}
	if i.Config.Directory == "" {
		if i.Config.IsCloneOnly {
			dir, err := os.Getwd()
			if err != nil {
				return err
			}
			i.Config.Directory = dir
		} else {
			i.Config.Directory = os.TempDir()
		}
	}
	return nil
}

func (i *SalesforceInstaller) setClient() error {
	i.Client = NewForceClient(i.Config.Endpoint, i.Config.ApiVersion)
	err := i.Client.Login(i.Config.Username, i.Config.Password)
	if err != nil {
		return err
	}
	return nil
}

func (i *SalesforceInstaller) Install(urls []string) error {
	for _, url := range urls {
		uri, dir, target_dir, branch := extractInstallParameter(url)

		err := i.installToSalesforce(uri, dir, target_dir, branch)
		if err != nil {
			return err
		}
	}
	return nil
}

func (i *SalesforceInstaller) installToSalesforce(url string, directory string, targetDirectory string, branch string) error {
	cloneDir := filepath.Join(i.Config.Directory, directory)
	i.addUrlStack(url)
	defer i.popUrlStack()
	i.logger.Info("Clone repository from " + url + " (branch: " + branch + ")")
	err := i.cloneFromRemoteRepository(cloneDir, url, branch, false)
	if err != nil {
		return err
	}
	if i.Config.IsCloneOnly {
		return nil
	}
	defer cleanTempDirectory(cloneDir)
	targetDirAbsPath := filepath.Join(cloneDir, targetDirectory)
	err = i.loadDependencies(targetDirAbsPath)
	if err != nil {
		return err
	}
	err = i.deployToSalesforce(targetDirAbsPath)
	if err != nil {
		return err
	}
	return nil
}

func (i *SalesforceInstaller) cloneFromRemoteRepository(directory string, url string, paramBranch string, retry bool) (err error) {
	branch := "master"
	if paramBranch != "" {
		branch = paramBranch
	}
	_, err = git.PlainClone(directory, false, &git.CloneOptions{
		URL:           url,
		ReferenceName: plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", branch)),
		SingleBranch:  true,
	})
	if err != nil {
		if err.Error() != "repository already exists" {
			return
		}
		if retry == true {
			return
		}
		i.logger.Warningf("repository non empty: %s", directory)
		i.logger.Infof("remove directory: %s", directory)
		err = cleanTempDirectory(directory)
		if err != nil {
			return
		}
		err = i.cloneFromRemoteRepository(directory, url, paramBranch, true)
	}
	return
}

func (i *SalesforceInstaller) deployToSalesforce(directory string) error {
	buf, err := zipDirectory(directory)
	if err != nil {
		return err
	}

	response, err := i.Client.Deploy(buf.Bytes())
	if err != nil {
		return err
	}

	err = i.checkDeployStatus(response.Result.Id)
	if err != nil {
		return err
	}
	i.logger.Infof("%s: Deploy is successful", i.getTopStack())

	return nil
}

func (i *SalesforceInstaller) checkDeployStatus(resultId *ID) error {
	totalTime := 0
	for {
		time.Sleep(time.Duration(i.Config.PollSeconds) * time.Second)
		i.logger.Infof("%s: Check Deploy Result...", i.getTopStack())

		response, err := i.Client.CheckDeployStatus(resultId)
		if err != nil {
			return err
		}
		if response.Result.Done {
			return nil
		}
		if i.Config.TimeoutSeconds != 0 {
			totalTime += i.Config.PollSeconds
			if totalTime > i.Config.TimeoutSeconds {
				i.logger.Errorf("%s: Deploy is timeout. Please check release status for the deployment", i.getTopStack())
				return nil
			}
		}
	}
}

func (i *SalesforceInstaller) loadDependencies(cloneDir string) error {
	targetFile := filepath.Join(cloneDir, "package.yml")
	_, err := os.Stat(targetFile)
	if err != nil {
		return nil
	}
	urls := []string{}
	packageFile, err := readPackageFile(targetFile)
	if err != nil {
		return err
	}
	for _, pkg := range packageFile.Packages {
		url, err := convertToUrl(pkg)
		if err != nil {
			return err
		}
		urls = append(urls, url)
	}
	return i.Install(urls)
}

func (i *SalesforceInstaller) addUrlStack(url string) error {
	i.urlStack = append(i.urlStack, url)
	return nil
}

func (i *SalesforceInstaller) getTopStack() string {
	return i.urlStack[len(i.urlStack)-1]
}

func (i *SalesforceInstaller) popUrlStack() {
	i.urlStack = i.urlStack[:len(i.urlStack)-1]
}<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"errors"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
)

// check checks if there whas an error and do panic if it was
func check(e error) {
	if e != nil {
		panic(e)
	}
}

// doHTTPReq executes a particullar http request
func doHTTPReq(req *http.Request) ([]byte, string, error) {
	req.Header.Set("User-Agent", userAgent)
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return []byte{}, "", err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return []byte{}, "", err
	}

	if resp.StatusCode == http.StatusForbidden {
		return []byte{}, resp.Header.Get("Content-type"), errors.New(string(body))
	}

	return body, resp.Header.Get("Content-type"), nil
}

// Executes HTTP GET request
func httpGet(urlPath string) ([]byte, string, error) {
	req, err := http.NewRequest("GET", urlPath, nil)
	if err != nil {
		return []byte{}, "", err
	}
	return doHTTPReq(req)
}

// httpPost executes HTTP POST with file content
func httpPost(urlPath string, filePath string) (string, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return "", err
	}
	defer file.Close()

	body := &bytes.Buffer{}
	io.Copy(body, file)

	req, err := http.NewRequest("POST", urlPath, body)
	if err != nil {
		return "", err
	}

	req.Header.Set("Content-Type", "text/plain")

	resp, _, err := doHTTPReq(req)
	return string(resp), err
}

// removeStuf trims spaces, removes new lines and code tag from a string
func removeStuf(s string) string {
	res := strings.Replace(s, "\n", "", -1)
	res = strings.Replace(res, "", "", -1)
	res = strings.Replace(res, "", "", -1)
	res = strings.TrimSpace(res)

	return res
}

// generate func of custom spaces indentation
func generateListIndentation(spaces int) func() string {
	return func() string {
		return strings.Repeat(" ", spaces)
	}
}

// Public

// EscapeSpecChars Escapes special characters
func EscapeSpecChars(s string) string {
	specChar := []string{"\\", "`", "*", "_", "{", "}", "#", "+", "-", ".", "!"}
	res := s

	for _, c := range specChar {
		res = strings.Replace(res, c, "\\"+c, -1)
	}
	return res
}

// ConvertMd2Html Sends Markdown to the github converter
// and returns html
func ConvertMd2Html(localpath string, token string) (string, error) {
	url := "https://api.github.com/markdown/raw"
	if token != "" {
		url += "?access_token=" + token
	}
	return httpPost(url, localpath)
}
<commit_msg>Pass token via header. Fixes #23<commit_after>package main

import (
	"bytes"
	"errors"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
)

// check checks if there whas an error and do panic if it was
func check(e error) {
	if e != nil {
		panic(e)
	}
}

// doHTTPReq executes a particullar http request
func doHTTPReq(req *http.Request) ([]byte, string, error) {
	req.Header.Set("User-Agent", userAgent)
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return []byte{}, "", err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return []byte{}, "", err
	}

	if resp.StatusCode == http.StatusForbidden {
		return []byte{}, resp.Header.Get("Content-type"), errors.New(string(body))
	}

	return body, resp.Header.Get("Content-type"), nil
}

// Executes HTTP GET request
func httpGet(urlPath string) ([]byte, string, error) {
	req, err := http.NewRequest("GET", urlPath, nil)
	if err != nil {
		return []byte{}, "", err
	}
	return doHTTPReq(req)
}

// httpPost executes HTTP POST with file content
func httpPost(urlPath, filePath, token string) (string, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return "", err
	}
	defer file.Close()

	body := &bytes.Buffer{}
	io.Copy(body, file)

	req, err := http.NewRequest("POST", urlPath, body)
	if err != nil {
		return "", err
	}

	if token != "" {
		req.Header.Add("Authorization", "token "+token)
	}
	req.Header.Set("Content-Type", "text/plain;charset=utf-8")

	resp, _, err := doHTTPReq(req)
	return string(resp), err
}

// removeStuf trims spaces, removes new lines and code tag from a string
func removeStuf(s string) string {
	res := strings.Replace(s, "\n", "", -1)
	res = strings.Replace(res, "", "", -1)
	res = strings.Replace(res, "", "", -1)
	res = strings.TrimSpace(res)

	return res
}

// generate func of custom spaces indentation
func generateListIndentation(spaces int) func() string {
	return func() string {
		return strings.Repeat(" ", spaces)
	}
}

// Public

// EscapeSpecChars Escapes special characters
func EscapeSpecChars(s string) string {
	specChar := []string{"\\", "`", "*", "_", "{", "}", "#", "+", "-", ".", "!"}
	res := s

	for _, c := range specChar {
		res = strings.Replace(res, c, "\\"+c, -1)
	}
	return res
}

// ConvertMd2Html Sends Markdown to the github converter
// and returns html
func ConvertMd2Html(localpath string, token string) (string, error) {
	url := "https://api.github.com/markdown/raw"
	return httpPost(url, localpath, token)
}
<|endoftext|>


<commit_before>package sdl

// #include "SDL.h"
import "C"

import (
	"image"
	"image/color"
	"unsafe"
)

// Surface is a rectangular array of pixels.
type Surface struct {
	s C.SDL_Surface
}

// PixelFormat returns the surface's pixel format.
func (surface *Surface) PixelFormat() *PixelFormat {
	return &PixelFormat{
		Format:        PixelFormatEnum(surface.s.format.format),
		BitsPerPixel:  uint8(surface.s.format.BitsPerPixel),
		BytesPerPixel: uint8(surface.s.format.BytesPerPixel),
		Rmask:         uint32(surface.s.format.Rmask),
		Gmask:         uint32(surface.s.format.Gmask),
		Bmask:         uint32(surface.s.format.Bmask),
		Amask:         uint32(surface.s.format.Amask),
	}
}

// Size returns the surface's width and height.
func (surface *Surface) Size() Point {
	return Point{int(surface.s.w), int(surface.s.h)}
}

// PixelData locks the surface and returns a PixelData value,
// which can be used to access and modify the surface's pixels.
// The returned PixelData must be closed before the surface can be
// used again.
func (surface *Surface) PixelData() (PixelData, error) {
	if result := C.SDL_LockSurface(&surface.s); result < 0 {
		return PixelData{}, GetError()
	}
	return PixelData{s: &surface.s}, nil
}

// Destroy destroys the surface.  The surface should not be used after
// a call to Destroy.
func (surface *Surface) Destroy() {
	C.SDL_FreeSurface(&surface.s)
}

// PixelData is a mutable view of a surface's pixels.  The data is only
// available while a surface is locked, so pixel data should be closed to
// allow the surface to be used again.
//
// PixelData implements the image.Image and draw.Image interfaces.
// See: http://golang.org/pkg/image/#Image and http://golang.org/pkg/image/draw/#Image.
type PixelData struct {
	s *C.SDL_Surface
}

// Expand out a component of a color from a pixel representing the color.
// TODO(adam): unit tests
func expandColor(pixel uint32, mask C.Uint32, shift, loss C.Uint8) uint8 {
	temp := pixel & uint32(mask)
	temp = temp >> uint8(shift)
	return uint8(temp << uint8(loss))
}

// Takes a uintptr to the pixel data from an SDL Surface and returns a pointer to the particular
// pixel referenced by parameters.
// Pitch is the number of bytes that make up one horizontal row (same as the field in SDL_Surface)
func getPixelPointer(pixels uintptr, x, y, bytesPerPixel, pitch int) unsafe.Pointer {
	offset := x*bytesPerPixel + y*pitch
	return unsafe.Pointer(pixels + uintptr(offset))
}

// At returns the pixel at the given position.
func (pix PixelData) At(x, y int) color.Color {
	format := pix.s.format
	bytesPerPixel := int(format.BytesPerPixel)

	ptr := getPixelPointer(uintptr(pix.s.pixels), x, y, bytesPerPixel, int(pix.s.pitch))
	pixel := *(*uint32)(ptr)

	// TODO(adam): not necesarily NRGBA (which would be an entirely different codepath)
	var col color.NRGBA

	switch bytesPerPixel {
	case 1:
		// TODO(adam): look up the color in color palette
	case 2, 3, 4:
		col.R = expandColor(pixel, format.Rmask, format.Rshift, format.Rloss)
		col.G = expandColor(pixel, format.Gmask, format.Gshift, format.Gloss)
		col.B = expandColor(pixel, format.Bmask, format.Bshift, format.Bloss)
		// If the alpha mask is 0, there's no alpha component, so set it to 1
		if format.Amask == 0 {
			col.A = 1
		} else {
			col.A = expandColor(pixel, format.Amask, format.Ashift, format.Aloss)
		}
	}

	return col
}

// ColorModel returns the color model of the pixel data.
func (pix PixelData) ColorModel() color.Model {
	// TODO(adam): this is a guess
	return color.NRGBAModel
}

// Bounds returns a rectangle of (0,0) => (w,h).
func (pix PixelData) Bounds() image.Rectangle {
	return image.Rectangle{image.Point{0, 0}, image.Point{int(pix.s.w), int(pix.s.h)}}
}

// Collapse a component of the color into a pointer at a pixel representing the color.
// TODO(adam): unit tests
func collapseColor(pixel *uint32, color uint8, shift, loss C.Uint8) {
	temp := uint32(color >> uint8(loss))
	temp = temp << uint8(shift)
	*pixel = *pixel & temp
}

// Set sets the color at an x, y position in the PixelData to a given color.
func (pix PixelData) Set(x, y int, c color.Color) {
	format := pix.s.format
	bytesPerPixel := int(format.BytesPerPixel)

	switch bytesPerPixel {
	case 1:
		// TODO(adam): look up the color in color palette
	case 2, 3, 4:
		// if necessary, convert color model to NRGBA
		col := pix.ColorModel().Convert(c).(color.NRGBA)

		// put that in a uint32 that I can slap into the void* of pixel data (also helper function?)
		var pixel *uint32
		collapseColor(pixel, col.R, format.Rshift, format.Rloss)
		collapseColor(pixel, col.G, format.Gshift, format.Gloss)
		collapseColor(pixel, col.B, format.Bshift, format.Bloss)
		// If the alpha mask is 0, there's no alpha component, so set it to 1
		if format.Amask == 0 {
			col.A = 1
		}
		collapseColor(pixel, col.A, format.Ashift, format.Aloss)

		// get pixel offset that's (x, y)
		ptr := getPixelPointer(uintptr(pix.s.pixels), x, y, bytesPerPixel, int(pix.s.pitch))

		// slap it in
		*(*uint32)(ptr) = *pixel
	}
}

// Destroy unlocks the underlying surface.  pix should not be used after
// calling Destroy.
func (pix PixelData) Destroy() {
	C.SDL_UnlockSurface(pix.s)
}
<commit_msg>Make getPixelPointer safer (fixes #21)<commit_after>package sdl

// #include "SDL.h"
import "C"

import (
	"image"
	"image/color"
	"unsafe"
)

// Surface is a rectangular array of pixels.
type Surface struct {
	s C.SDL_Surface
}

// PixelFormat returns the surface's pixel format.
func (surface *Surface) PixelFormat() *PixelFormat {
	return &PixelFormat{
		Format:        PixelFormatEnum(surface.s.format.format),
		BitsPerPixel:  uint8(surface.s.format.BitsPerPixel),
		BytesPerPixel: uint8(surface.s.format.BytesPerPixel),
		Rmask:         uint32(surface.s.format.Rmask),
		Gmask:         uint32(surface.s.format.Gmask),
		Bmask:         uint32(surface.s.format.Bmask),
		Amask:         uint32(surface.s.format.Amask),
	}
}

// Size returns the surface's width and height.
func (surface *Surface) Size() Point {
	return Point{int(surface.s.w), int(surface.s.h)}
}

// PixelData locks the surface and returns a PixelData value,
// which can be used to access and modify the surface's pixels.
// The returned PixelData must be closed before the surface can be
// used again.
func (surface *Surface) PixelData() (PixelData, error) {
	if result := C.SDL_LockSurface(&surface.s); result < 0 {
		return PixelData{}, GetError()
	}
	return PixelData{s: &surface.s}, nil
}

// Destroy destroys the surface.  The surface should not be used after
// a call to Destroy.
func (surface *Surface) Destroy() {
	C.SDL_FreeSurface(&surface.s)
}

// PixelData is a mutable view of a surface's pixels.  The data is only
// available while a surface is locked, so pixel data should be closed to
// allow the surface to be used again.
//
// PixelData implements the image.Image and draw.Image interfaces.
// See: http://golang.org/pkg/image/#Image and http://golang.org/pkg/image/draw/#Image.
type PixelData struct {
	s *C.SDL_Surface
}

// Expand out a component of a color from a pixel representing the color.
// TODO(adam): unit tests
func expandColor(pixel uint32, mask C.Uint32, shift, loss C.Uint8) uint8 {
	temp := pixel & uint32(mask)
	temp = temp >> uint8(shift)
	return uint8(temp << uint8(loss))
}

// getPixelPointer returns the address of the pixel at (x, y) relative
// to a base pointer.  pitch is the number of bytes in a horizontal row.
func getPixelPointer(pixels unsafe.Pointer, x, y int, bytesPerPixel, pitch uintptr) unsafe.Pointer {
	offset := uintptr(x)*bytesPerPixel + uintptr(y)*pitch
	return unsafe.Pointer(uintptr(pixels) + offset)
}

// At returns the pixel at the given position.
func (pix PixelData) At(x, y int) color.Color {
	format := pix.s.format
	bytesPerPixel := uintptr(format.BytesPerPixel)

	ptr := getPixelPointer(pix.s.pixels, x, y, bytesPerPixel, uintptr(pix.s.pitch))
	pixel := *(*uint32)(ptr)

	// TODO(adam): not necesarily NRGBA (which would be an entirely different codepath)
	var col color.NRGBA

	switch bytesPerPixel {
	case 1:
		// TODO(adam): look up the color in color palette
	case 2, 3, 4:
		col.R = expandColor(pixel, format.Rmask, format.Rshift, format.Rloss)
		col.G = expandColor(pixel, format.Gmask, format.Gshift, format.Gloss)
		col.B = expandColor(pixel, format.Bmask, format.Bshift, format.Bloss)
		// If the alpha mask is 0, there's no alpha component, so set it to 1
		if format.Amask == 0 {
			col.A = 1
		} else {
			col.A = expandColor(pixel, format.Amask, format.Ashift, format.Aloss)
		}
	}

	return col
}

// ColorModel returns the color model of the pixel data.
func (pix PixelData) ColorModel() color.Model {
	// TODO(adam): this is a guess
	return color.NRGBAModel
}

// Bounds returns a rectangle of (0,0) => (w,h).
func (pix PixelData) Bounds() image.Rectangle {
	return image.Rectangle{image.Point{0, 0}, image.Point{int(pix.s.w), int(pix.s.h)}}
}

// Collapse a component of the color into a pointer at a pixel representing the color.
// TODO(adam): unit tests
func collapseColor(pixel *uint32, color uint8, shift, loss C.Uint8) {
	temp := uint32(color >> uint8(loss))
	temp = temp << uint8(shift)
	*pixel = *pixel & temp
}

// Set sets the color at an x, y position in the PixelData to a given color.
func (pix PixelData) Set(x, y int, c color.Color) {
	format := pix.s.format
	bytesPerPixel := uintptr(format.BytesPerPixel)

	switch bytesPerPixel {
	case 1:
		// TODO(adam): look up the color in color palette
	case 2, 3, 4:
		// if necessary, convert color model to NRGBA
		col := pix.ColorModel().Convert(c).(color.NRGBA)

		// put that in a uint32 that I can slap into the void* of pixel data (also helper function?)
		var pixel *uint32
		collapseColor(pixel, col.R, format.Rshift, format.Rloss)
		collapseColor(pixel, col.G, format.Gshift, format.Gloss)
		collapseColor(pixel, col.B, format.Bshift, format.Bloss)
		// If the alpha mask is 0, there's no alpha component, so set it to 1
		if format.Amask == 0 {
			col.A = 1
		}
		collapseColor(pixel, col.A, format.Ashift, format.Aloss)

		// get pixel offset that's (x, y)
		ptr := getPixelPointer(pix.s.pixels, x, y, bytesPerPixel, uintptr(pix.s.pitch))

		// slap it in
		*(*uint32)(ptr) = *pixel
	}
}

// Destroy unlocks the underlying surface.  pix should not be used after
// calling Destroy.
func (pix PixelData) Destroy() {
	C.SDL_UnlockSurface(pix.s)
}
<|endoftext|>


<commit_before>package gitlab

import (
	"net/http"
	"testing"

	"github.com/stretchr/testify/require"
)

func TestSearchService_Users(t *testing.T) {
	mux, server, client := setup(t)
	defer teardown(server)

	mux.HandleFunc("/api/v4/search", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "GET")
		mustWriteHTTPResponse(t, w, "testdata/search_users.json")
	})

	opts := &SearchOptions{PerPage: 2}
	users, _, err := client.Search.Users("doe", opts)

	require.NoError(t, err)

	want := []*User{{
		ID:        1,
		Username:  "user1",
		Name:      "John Doe1",
		State:     "active",
		AvatarURL: "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon",
	}}
	require.Equal(t, want, users)
}

func TestSearchService_UsersByGroup(t *testing.T) {
	mux, server, client := setup(t)
	defer teardown(server)

	mux.HandleFunc("/api/v4/groups/3/-/search", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "GET")
		mustWriteHTTPResponse(t, w, "testdata/search_users.json")
	})

	opts := &SearchOptions{PerPage: 2}
	users, _, err := client.Search.UsersByGroup("3", "doe", opts)

	require.NoError(t, err)

	want := []*User{{
		ID:        1,
		Username:  "user1",
		Name:      "John Doe1",
		State:     "active",
		AvatarURL: "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon",
	}}
	require.Equal(t, want, users)
}

func TestSearchService_UsersByProject(t *testing.T) {
	mux, server, client := setup(t)
	defer teardown(server)

	mux.HandleFunc("/api/v4/projects/6/-/search", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "GET")
		mustWriteHTTPResponse(t, w, "testdata/search_users.json")
	})

	opts := &SearchOptions{PerPage: 2}
	users, _, err := client.Search.UsersByProject("6", "doe", opts)

	require.NoError(t, err)

	want := []*User{{
		ID:        1,
		Username:  "user1",
		Name:      "John Doe1",
		State:     "active",
		AvatarURL: "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon",
	}}
	require.Equal(t, want, users)
}
<commit_msg>Update tests.<commit_after>package gitlab

import (
	"net/http"
	"testing"

	"github.com/stretchr/testify/require"
)

func TestSearchService_Users(t *testing.T) {
	mux, server, client := setup(t)
	defer teardown(server)

	mux.HandleFunc("/api/v4/search", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "GET")
		mustWriteHTTPResponse(t, w, "testdata/search_users.json")
	})

	opts := &SearchOptions{PerPage: 2}
	users, _, err := client.Search.Users("doe", opts)

	require.NoError(t, err)

	want := []*User{{
		ID:        1,
		Username:  "user1",
		Name:      "John Doe1",
		State:     "active",
		AvatarURL: "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon",
		WebURL:    "http://localhost/user1",
	}}
	require.Equal(t, want, users)
}

func TestSearchService_UsersByGroup(t *testing.T) {
	mux, server, client := setup(t)
	defer teardown(server)

	mux.HandleFunc("/api/v4/groups/3/-/search", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "GET")
		mustWriteHTTPResponse(t, w, "testdata/search_users.json")
	})

	opts := &SearchOptions{PerPage: 2}
	users, _, err := client.Search.UsersByGroup("3", "doe", opts)

	require.NoError(t, err)

	want := []*User{{
		ID:        1,
		Username:  "user1",
		Name:      "John Doe1",
		State:     "active",
		AvatarURL: "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon",
		WebURL:    "http://localhost/user1",
	}}
	require.Equal(t, want, users)
}

func TestSearchService_UsersByProject(t *testing.T) {
	mux, server, client := setup(t)
	defer teardown(server)

	mux.HandleFunc("/api/v4/projects/6/-/search", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "GET")
		mustWriteHTTPResponse(t, w, "testdata/search_users.json")
	})

	opts := &SearchOptions{PerPage: 2}
	users, _, err := client.Search.UsersByProject("6", "doe", opts)

	require.NoError(t, err)

	want := []*User{{
		ID:        1,
		Username:  "user1",
		Name:      "John Doe1",
		State:     "active",
		AvatarURL: "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon",
		WebURL:    "http://localhost/user1",
	}}
	require.Equal(t, want, users)
}
<|endoftext|>


<commit_before>//  Copyright (c) 2015 Rackspace
//
//  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 proxyserver

import (
	"flag"
	"fmt"
	"net/http"
	"strings"

	"github.com/troubling/hummingbird/client"
	"github.com/troubling/hummingbird/common"
	"github.com/troubling/hummingbird/common/conf"
	"github.com/troubling/hummingbird/common/ring"
	"github.com/troubling/hummingbird/common/srv"
	"github.com/troubling/hummingbird/proxyserver/middleware"

	"github.com/justinas/alice"
	"go.uber.org/zap"
)

type ProxyServer struct {
	logger            srv.LowLevelLogger
	logLevel          zap.AtomicLevel
	mc                ring.MemcacheRing
	proxyDirectClient *client.ProxyDirectClient
}

func (server *ProxyServer) Finalize() {
}

func (server *ProxyServer) GetHandler(config conf.Config) http.Handler {
	router := srv.NewRouter()
	router.Get("/loglevel", server.logLevel)
	router.Put("/loglevel", server.logLevel)
	router.Get("/v1/:account/:container/*obj", http.HandlerFunc(server.ObjectGetHandler))
	router.Head("/v1/:account/:container/*obj", http.HandlerFunc(server.ObjectHeadHandler))
	router.Put("/v1/:account/:container/*obj", http.HandlerFunc(server.ObjectPutHandler))
	router.Delete("/v1/:account/:container/*obj", http.HandlerFunc(server.ObjectDeleteHandler))

	router.Get("/v1/:account/:container", http.HandlerFunc(server.ContainerGetHandler))
	router.Get("/v1/:account/:container/", http.HandlerFunc(server.ContainerGetHandler))
	router.Head("/v1/:account/:container", http.HandlerFunc(server.ContainerHeadHandler))
	router.Head("/v1/:account/:container/", http.HandlerFunc(server.ContainerHeadHandler))
	router.Put("/v1/:account/:container", http.HandlerFunc(server.ContainerPutHandler))
	router.Put("/v1/:account/:container/", http.HandlerFunc(server.ContainerPutHandler))
	router.Delete("/v1/:account/:container", http.HandlerFunc(server.ContainerDeleteHandler))
	router.Delete("/v1/:account/:container/", http.HandlerFunc(server.ContainerDeleteHandler))
	router.Post("/v1/:account/:container", http.HandlerFunc(server.ContainerPostHandler))
	router.Post("/v1/:account/:container/", http.HandlerFunc(server.ContainerPostHandler))

	router.Get("/v1/:account", http.HandlerFunc(server.AccountGetHandler))
	router.Get("/v1/:account/", http.HandlerFunc(server.AccountGetHandler))
	router.Head("/v1/:account", http.HandlerFunc(server.AccountHeadHandler))
	router.Head("/v1/:account/", http.HandlerFunc(server.AccountHeadHandler))
	router.Put("/v1/:account", http.HandlerFunc(server.AccountPutHandler))
	router.Put("/v1/:account/", http.HandlerFunc(server.AccountPutHandler))
	router.Delete("/v1/:account", http.HandlerFunc(server.AccountDeleteHandler))
	router.Delete("/v1/:account/", http.HandlerFunc(server.AccountDeleteHandler))
	router.Post("/v1/:account", http.HandlerFunc(server.AccountPostHandler))
	router.Post("/v1/:account/", http.HandlerFunc(server.AccountPostHandler))

	tempAuth := config.GetBool("proxy-server", "tempauth_enabled", true)
	var middlewares []struct {
		construct func(config conf.Section) (func(http.Handler) http.Handler, error)
		section   string
	}
	// TODO: make this all dynamical and stuff
	if tempAuth {
		middlewares = []struct {
			construct func(config conf.Section) (func(http.Handler) http.Handler, error)
			section   string
		}{
			{middleware.NewCatchError, "filter:catch_errors"},
			{middleware.NewHealthcheck, "filter:healthcheck"},
			{middleware.NewRequestLogger, "filter:proxy-logging"},
			{middleware.NewFormPost, "filter:formpost"},
			{middleware.NewTempURL, "filter:tempurl"},
			{middleware.NewTempAuth, "filter:tempauth"},
			{middleware.NewRatelimiter, "filter:ratelimit"},
			//{middleware.NewStaticWeb, "filter:staticweb"},
			{middleware.NewCopyMiddleware, "filter:copy"},
			{middleware.NewXlo, "fliter:slo"},
		}
	} else {
		middlewares = []struct {
			construct func(config conf.Section) (func(http.Handler) http.Handler, error)
			section   string
		}{
			{middleware.NewCatchError, "filter:catch_errors"},
			{middleware.NewHealthcheck, "filter:healthcheck"},
			{middleware.NewRequestLogger, "filter:proxy-logging"},
			{middleware.NewFormPost, "filter:formpost"},
			{middleware.NewTempURL, "filter:tempurl"},
			{middleware.NewAuthToken, "filter:authtoken"},
			{middleware.NewKeystoneAuth, "filter:keystoneauth"},
			{middleware.NewRatelimiter, "filter:ratelimit"},
			//{middleware.NewStaticWeb, "filter:staticweb"},
			{middleware.NewCopyMiddleware, "filter:copy"},
			{middleware.NewXlo, "filter:slo"},
		}
	}
	pipeline := alice.New(middleware.NewContext(server.mc, server.logger, server.proxyDirectClient))
	for _, m := range middlewares {
		mid, err := m.construct(config.GetSection(m.section))
		if err != nil {
			// TODO: propagate error upwards instead of panicking
			panic("Unable to construct middleware")
		}
		pipeline = pipeline.Append(mid)
	}
	return pipeline.Then(router)
}

func GetServer(serverconf conf.Config, flags *flag.FlagSet) (string, int, srv.Server, srv.LowLevelLogger, error) {
	var err error
	server := &ProxyServer{}
	server.mc, err = ring.NewMemcacheRingFromConfig(serverconf)
	if err != nil {
		return "", 0, nil, nil, err
	}

	bindIP := serverconf.GetDefault("DEFAULT", "bind_ip", "0.0.0.0")
	bindPort := serverconf.GetInt("DEFAULT", "bind_port", 8080)

	logLevelString := serverconf.GetDefault("proxy-server", "log_level", "INFO")
	server.logLevel = zap.NewAtomicLevel()
	server.logLevel.UnmarshalText([]byte(strings.ToLower(logLevelString)))

	if server.logger, err = srv.SetupLogger("proxy-server", &server.logLevel, flags); err != nil {
		return "", 0, nil, nil, fmt.Errorf("Error setting up logger: %v", err)
	}
	policies := conf.LoadPolicies()
	server.proxyDirectClient, err = client.NewProxyDirectClient(policies)
	if err != nil {
		return "", 0, nil, nil, fmt.Errorf("Error setting up proxyDirectClient: %v", err)
	}
	info := map[string]interface{}{
		"version":          common.Version,
		"strict_cors_mode": true,
		"policies":         policies.GetPolicyInfo(),
	}
	for k, v := range DEFAULT_CONSTRAINTS {
		info[k] = v
	}
	middleware.RegisterInfo("swift", info)
	return bindIP, int(bindPort), server, server.logger, nil
}
<commit_msg>Revert "remove staticweb for a bit"<commit_after>//  Copyright (c) 2015 Rackspace
//
//  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 proxyserver

import (
	"flag"
	"fmt"
	"net/http"
	"strings"

	"github.com/troubling/hummingbird/client"
	"github.com/troubling/hummingbird/common"
	"github.com/troubling/hummingbird/common/conf"
	"github.com/troubling/hummingbird/common/ring"
	"github.com/troubling/hummingbird/common/srv"
	"github.com/troubling/hummingbird/proxyserver/middleware"

	"github.com/justinas/alice"
	"go.uber.org/zap"
)

type ProxyServer struct {
	logger            srv.LowLevelLogger
	logLevel          zap.AtomicLevel
	mc                ring.MemcacheRing
	proxyDirectClient *client.ProxyDirectClient
}

func (server *ProxyServer) Finalize() {
}

func (server *ProxyServer) GetHandler(config conf.Config) http.Handler {
	router := srv.NewRouter()
	router.Get("/loglevel", server.logLevel)
	router.Put("/loglevel", server.logLevel)
	router.Get("/v1/:account/:container/*obj", http.HandlerFunc(server.ObjectGetHandler))
	router.Head("/v1/:account/:container/*obj", http.HandlerFunc(server.ObjectHeadHandler))
	router.Put("/v1/:account/:container/*obj", http.HandlerFunc(server.ObjectPutHandler))
	router.Delete("/v1/:account/:container/*obj", http.HandlerFunc(server.ObjectDeleteHandler))

	router.Get("/v1/:account/:container", http.HandlerFunc(server.ContainerGetHandler))
	router.Get("/v1/:account/:container/", http.HandlerFunc(server.ContainerGetHandler))
	router.Head("/v1/:account/:container", http.HandlerFunc(server.ContainerHeadHandler))
	router.Head("/v1/:account/:container/", http.HandlerFunc(server.ContainerHeadHandler))
	router.Put("/v1/:account/:container", http.HandlerFunc(server.ContainerPutHandler))
	router.Put("/v1/:account/:container/", http.HandlerFunc(server.ContainerPutHandler))
	router.Delete("/v1/:account/:container", http.HandlerFunc(server.ContainerDeleteHandler))
	router.Delete("/v1/:account/:container/", http.HandlerFunc(server.ContainerDeleteHandler))
	router.Post("/v1/:account/:container", http.HandlerFunc(server.ContainerPostHandler))
	router.Post("/v1/:account/:container/", http.HandlerFunc(server.ContainerPostHandler))

	router.Get("/v1/:account", http.HandlerFunc(server.AccountGetHandler))
	router.Get("/v1/:account/", http.HandlerFunc(server.AccountGetHandler))
	router.Head("/v1/:account", http.HandlerFunc(server.AccountHeadHandler))
	router.Head("/v1/:account/", http.HandlerFunc(server.AccountHeadHandler))
	router.Put("/v1/:account", http.HandlerFunc(server.AccountPutHandler))
	router.Put("/v1/:account/", http.HandlerFunc(server.AccountPutHandler))
	router.Delete("/v1/:account", http.HandlerFunc(server.AccountDeleteHandler))
	router.Delete("/v1/:account/", http.HandlerFunc(server.AccountDeleteHandler))
	router.Post("/v1/:account", http.HandlerFunc(server.AccountPostHandler))
	router.Post("/v1/:account/", http.HandlerFunc(server.AccountPostHandler))

	tempAuth := config.GetBool("proxy-server", "tempauth_enabled", true)
	var middlewares []struct {
		construct func(config conf.Section) (func(http.Handler) http.Handler, error)
		section   string
	}
	// TODO: make this all dynamical and stuff
	if tempAuth {
		middlewares = []struct {
			construct func(config conf.Section) (func(http.Handler) http.Handler, error)
			section   string
		}{
			{middleware.NewCatchError, "filter:catch_errors"},
			{middleware.NewHealthcheck, "filter:healthcheck"},
			{middleware.NewRequestLogger, "filter:proxy-logging"},
			{middleware.NewFormPost, "filter:formpost"},
			{middleware.NewTempURL, "filter:tempurl"},
			{middleware.NewTempAuth, "filter:tempauth"},
			{middleware.NewRatelimiter, "filter:ratelimit"},
			{middleware.NewStaticWeb, "filter:staticweb"},
			{middleware.NewCopyMiddleware, "filter:copy"},
			{middleware.NewXlo, "fliter:slo"},
		}
	} else {
		middlewares = []struct {
			construct func(config conf.Section) (func(http.Handler) http.Handler, error)
			section   string
		}{
			{middleware.NewCatchError, "filter:catch_errors"},
			{middleware.NewHealthcheck, "filter:healthcheck"},
			{middleware.NewRequestLogger, "filter:proxy-logging"},
			{middleware.NewFormPost, "filter:formpost"},
			{middleware.NewTempURL, "filter:tempurl"},
			{middleware.NewAuthToken, "filter:authtoken"},
			{middleware.NewKeystoneAuth, "filter:keystoneauth"},
			{middleware.NewRatelimiter, "filter:ratelimit"},
			{middleware.NewStaticWeb, "filter:staticweb"},
			{middleware.NewCopyMiddleware, "filter:copy"},
			{middleware.NewXlo, "filter:slo"},
		}
	}
	pipeline := alice.New(middleware.NewContext(server.mc, server.logger, server.proxyDirectClient))
	for _, m := range middlewares {
		mid, err := m.construct(config.GetSection(m.section))
		if err != nil {
			// TODO: propagate error upwards instead of panicking
			panic("Unable to construct middleware")
		}
		pipeline = pipeline.Append(mid)
	}
	return pipeline.Then(router)
}

func GetServer(serverconf conf.Config, flags *flag.FlagSet) (string, int, srv.Server, srv.LowLevelLogger, error) {
	var err error
	server := &ProxyServer{}
	server.mc, err = ring.NewMemcacheRingFromConfig(serverconf)
	if err != nil {
		return "", 0, nil, nil, err
	}

	bindIP := serverconf.GetDefault("DEFAULT", "bind_ip", "0.0.0.0")
	bindPort := serverconf.GetInt("DEFAULT", "bind_port", 8080)

	logLevelString := serverconf.GetDefault("proxy-server", "log_level", "INFO")
	server.logLevel = zap.NewAtomicLevel()
	server.logLevel.UnmarshalText([]byte(strings.ToLower(logLevelString)))

	if server.logger, err = srv.SetupLogger("proxy-server", &server.logLevel, flags); err != nil {
		return "", 0, nil, nil, fmt.Errorf("Error setting up logger: %v", err)
	}
	policies := conf.LoadPolicies()
	server.proxyDirectClient, err = client.NewProxyDirectClient(policies)
	if err != nil {
		return "", 0, nil, nil, fmt.Errorf("Error setting up proxyDirectClient: %v", err)
	}
	info := map[string]interface{}{
		"version":          common.Version,
		"strict_cors_mode": true,
		"policies":         policies.GetPolicyInfo(),
	}
	for k, v := range DEFAULT_CONSTRAINTS {
		info[k] = v
	}
	middleware.RegisterInfo("swift", info)
	return bindIP, int(bindPort), server, server.logger, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2017 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 main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/sirupsen/logrus"
	"sigs.k8s.io/yaml"

	prowapi "k8s.io/test-infra/prow/apis/prowjobs/v1"
	"k8s.io/test-infra/prow/config"
	"k8s.io/test-infra/prow/config/secret"
	prowflagutil "k8s.io/test-infra/prow/flagutil"
	"k8s.io/test-infra/prow/github"
	"k8s.io/test-infra/prow/pjutil"
)

type options struct {
	jobName       string
	configPath    string
	jobConfigPath string

	baseRef    string
	baseSha    string
	pullNumber int
	pullSha    string
	pullAuthor string
	org        string
	repo       string

	local bool

	github       prowflagutil.GitHubOptions
	githubClient githubClient
	pullRequest  *github.PullRequest
}

func (o *options) getPullRequest() (*github.PullRequest, error) {
	if o.pullRequest != nil {
		return o.pullRequest, nil
	}
	pr, err := o.githubClient.GetPullRequest(o.org, o.repo, o.pullNumber)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch PullRequest from GitHub: %v", err)
	}
	o.pullRequest = pr
	return pr, nil
}

func (o *options) defaultPR(pjs *prowapi.ProwJobSpec) error {
	if pjs.Refs.Pulls[0].Number == 0 {
		fmt.Fprint(os.Stderr, "PR Number: ")
		var pullNumber int
		fmt.Scanln(&pullNumber)
		pjs.Refs.Pulls[0].Number = pullNumber
		o.pullNumber = pullNumber
	}
	if pjs.Refs.Pulls[0].Author == "" {
		pr, err := o.getPullRequest()
		if err != nil {
			return err
		}
		pjs.Refs.Pulls[0].Author = pr.User.Login
	}
	if pjs.Refs.Pulls[0].SHA == "" {
		pr, err := o.getPullRequest()
		if err != nil {
			return err
		}
		pjs.Refs.Pulls[0].SHA = pr.Head.SHA
	}
	return nil
}

func (o *options) defaultBaseRef(pjs *prowapi.ProwJobSpec) error {
	if pjs.Refs == nil {
		return nil
	}
	if pjs.Refs.BaseRef == "" {
		if o.pullNumber != 0 {
			pr, err := o.getPullRequest()
			if err != nil {
				return err
			}
			pjs.Refs.BaseRef = pr.Base.Ref
		} else {
			fmt.Fprint(os.Stderr, "Base ref (e.g. master): ")
			fmt.Scanln(&pjs.Refs.BaseRef)
		}
	}
	if pjs.Refs.BaseSHA == "" {
		if o.pullNumber != 0 {
			pr, err := o.getPullRequest()
			if err != nil {
				return err
			}
			pjs.Refs.BaseSHA = pr.Base.SHA
		} else {
			baseSHA, err := o.githubClient.GetRef(o.org, o.repo, fmt.Sprintf("heads/%s", pjs.Refs.BaseRef))
			if err != nil {
				logrus.Fatalf("failed to get base sha: %v", err)
				return err
			}
			pjs.Refs.BaseSHA = baseSHA
		}
	}
	return nil
}

type githubClient interface {
	GetPullRequest(org, repo string, number int) (*github.PullRequest, error)
	GetRef(org, repo, ref string) (string, error)
}

func (o *options) Validate() error {
	if o.jobName == "" {
		return errors.New("required flag --job was unset")
	}

	if o.configPath == "" {
		return errors.New("required flag --config-path was unset")
	}

	if err := o.github.Validate(false); err != nil {
		return err
	}

	return nil
}

func gatherOptions() options {
	var o options
	fs := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
	fs.StringVar(&o.jobName, "job", "", "Job to run.")
	fs.BoolVar(&o.local, "local", false, "Print help for running locally")
	fs.StringVar(&o.configPath, "config-path", "", "Path to config.yaml.")
	fs.StringVar(&o.jobConfigPath, "job-config-path", "", "Path to prow job configs.")
	fs.StringVar(&o.baseRef, "base-ref", "", "Git base ref under test")
	fs.StringVar(&o.baseSha, "base-sha", "", "Git base SHA under test")
	fs.IntVar(&o.pullNumber, "pull-number", 0, "Git pull number under test")
	fs.StringVar(&o.pullSha, "pull-sha", "", "Git pull SHA under test")
	fs.StringVar(&o.pullAuthor, "pull-author", "", "Git pull author under test")
	o.github.AddFlagsWithoutDefaultGitHubTokenPath(fs)
	fs.Parse(os.Args[1:])
	return o
}

func main() {
	o := gatherOptions()
	if err := o.Validate(); err != nil {
		logrus.WithError(err).Fatalf("Bad flags")
	}

	conf, err := config.Load(o.configPath, o.jobConfigPath)
	if err != nil {
		logrus.WithError(err).Fatal("Error loading config")
	}

	var secretAgent *secret.Agent
	if o.github.TokenPath != "" {
		secretAgent = &secret.Agent{}
		if err := secretAgent.Start([]string{o.github.TokenPath}); err != nil {
			logrus.WithError(err).Fatal("Failed to start secret agent")
		}
	}
	o.githubClient, err = o.github.GitHubClient(secretAgent, false)
	if err != nil {
		logrus.WithError(err).Fatal("Failed to get GitHub client")
	}

	var pjs prowapi.ProwJobSpec
	var labels map[string]string
	var annotations map[string]string
	var found bool
	var needsBaseRef bool
	var needsPR bool
	for fullRepoName, ps := range conf.Presubmits {
		org, repo, err := splitRepoName(fullRepoName)
		if err != nil {
			logrus.WithError(err).Warnf("Invalid repo name %s.", fullRepoName)
			continue
		}
		for _, p := range ps {
			if p.Name == o.jobName {
				pjs = pjutil.PresubmitSpec(p, prowapi.Refs{
					Org:     org,
					Repo:    repo,
					BaseRef: o.baseRef,
					BaseSHA: o.baseSha,
					Pulls: []prowapi.Pull{{
						Author: o.pullAuthor,
						Number: o.pullNumber,
						SHA:    o.pullSha,
					}},
				})
				labels = p.Labels
				annotations = p.Annotations
				found = true
				needsBaseRef = true
				needsPR = true
				o.org = org
				o.repo = repo
			}
		}
	}
	for fullRepoName, ps := range conf.Postsubmits {
		org, repo, err := splitRepoName(fullRepoName)
		if err != nil {
			logrus.WithError(err).Warnf("Invalid repo name %s.", fullRepoName)
			continue
		}
		for _, p := range ps {
			if p.Name == o.jobName {
				pjs = pjutil.PostsubmitSpec(p, prowapi.Refs{
					Org:     org,
					Repo:    repo,
					BaseRef: o.baseRef,
					BaseSHA: o.baseSha,
				})
				labels = p.Labels
				annotations = p.Annotations
				found = true
				needsBaseRef = true
				o.org = org
				o.repo = repo
			}
		}
	}
	for _, p := range conf.Periodics {
		if p.Name == o.jobName {
			pjs = pjutil.PeriodicSpec(p)
			labels = p.Labels
			annotations = p.Annotations
			found = true
		}
	}
	if !found {
		logrus.Fatalf("Job %s not found.", o.jobName)
	}
	if needsPR {
		if err := o.defaultPR(&pjs); err != nil {
			logrus.WithError(err).Fatal("Failed to default PR")
		}
	}
	if needsBaseRef {
		if err := o.defaultBaseRef(&pjs); err != nil {
			logrus.WithError(err).Fatal("Failed to default base ref")
		}
	}
	pj := pjutil.NewProwJob(pjs, labels, annotations)
	b, err := yaml.Marshal(&pj)
	if err != nil {
		logrus.WithError(err).Fatal("Error marshalling YAML.")
	}
	fmt.Print(string(b))
	if o.local {
		logrus.Info("Use 'bazel run //prow/cmd/phaino' to run this job locally in docker")
	}
}

func splitRepoName(repo string) (string, string, error) {
	s := strings.SplitN(repo, "/", 2)
	if len(s) != 2 {
		return "", "", fmt.Errorf("repo %s cannot be split into org/repo", repo)
	}
	return s[0], s[1], nil
}
<commit_msg>mkpj: get org/repo from generated job spec<commit_after>/*
Copyright 2017 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 main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/sirupsen/logrus"
	"sigs.k8s.io/yaml"

	prowapi "k8s.io/test-infra/prow/apis/prowjobs/v1"
	"k8s.io/test-infra/prow/config"
	"k8s.io/test-infra/prow/config/secret"
	prowflagutil "k8s.io/test-infra/prow/flagutil"
	"k8s.io/test-infra/prow/github"
	"k8s.io/test-infra/prow/pjutil"
)

type options struct {
	jobName       string
	configPath    string
	jobConfigPath string

	baseRef    string
	baseSha    string
	pullNumber int
	pullSha    string
	pullAuthor string
	org        string
	repo       string

	local bool

	github       prowflagutil.GitHubOptions
	githubClient githubClient
	pullRequest  *github.PullRequest
}

func (o *options) getPullRequest() (*github.PullRequest, error) {
	if o.pullRequest != nil {
		return o.pullRequest, nil
	}
	pr, err := o.githubClient.GetPullRequest(o.org, o.repo, o.pullNumber)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch PullRequest from GitHub: %v", err)
	}
	o.pullRequest = pr
	return pr, nil
}

func (o *options) defaultPR(pjs *prowapi.ProwJobSpec) error {
	if pjs.Refs.Pulls[0].Number == 0 {
		fmt.Fprint(os.Stderr, "PR Number: ")
		var pullNumber int
		fmt.Scanln(&pullNumber)
		pjs.Refs.Pulls[0].Number = pullNumber
		o.pullNumber = pullNumber
	}
	if pjs.Refs.Pulls[0].Author == "" {
		pr, err := o.getPullRequest()
		if err != nil {
			return err
		}
		pjs.Refs.Pulls[0].Author = pr.User.Login
	}
	if pjs.Refs.Pulls[0].SHA == "" {
		pr, err := o.getPullRequest()
		if err != nil {
			return err
		}
		pjs.Refs.Pulls[0].SHA = pr.Head.SHA
	}
	return nil
}

func (o *options) defaultBaseRef(pjs *prowapi.ProwJobSpec) error {
	if pjs.Refs == nil {
		return nil
	}
	if pjs.Refs.BaseRef == "" {
		if o.pullNumber != 0 {
			pr, err := o.getPullRequest()
			if err != nil {
				return err
			}
			pjs.Refs.BaseRef = pr.Base.Ref
		} else {
			fmt.Fprint(os.Stderr, "Base ref (e.g. master): ")
			fmt.Scanln(&pjs.Refs.BaseRef)
		}
	}
	if pjs.Refs.BaseSHA == "" {
		if o.pullNumber != 0 {
			pr, err := o.getPullRequest()
			if err != nil {
				return err
			}
			pjs.Refs.BaseSHA = pr.Base.SHA
		} else {
			baseSHA, err := o.githubClient.GetRef(o.org, o.repo, fmt.Sprintf("heads/%s", pjs.Refs.BaseRef))
			if err != nil {
				logrus.Fatalf("failed to get base sha: %v", err)
				return err
			}
			pjs.Refs.BaseSHA = baseSHA
		}
	}
	return nil
}

type githubClient interface {
	GetPullRequest(org, repo string, number int) (*github.PullRequest, error)
	GetRef(org, repo, ref string) (string, error)
}

func (o *options) Validate() error {
	if o.jobName == "" {
		return errors.New("required flag --job was unset")
	}

	if o.configPath == "" {
		return errors.New("required flag --config-path was unset")
	}

	if err := o.github.Validate(false); err != nil {
		return err
	}

	return nil
}

func gatherOptions() options {
	var o options
	fs := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
	fs.StringVar(&o.jobName, "job", "", "Job to run.")
	fs.BoolVar(&o.local, "local", false, "Print help for running locally")
	fs.StringVar(&o.configPath, "config-path", "", "Path to config.yaml.")
	fs.StringVar(&o.jobConfigPath, "job-config-path", "", "Path to prow job configs.")
	fs.StringVar(&o.baseRef, "base-ref", "", "Git base ref under test")
	fs.StringVar(&o.baseSha, "base-sha", "", "Git base SHA under test")
	fs.IntVar(&o.pullNumber, "pull-number", 0, "Git pull number under test")
	fs.StringVar(&o.pullSha, "pull-sha", "", "Git pull SHA under test")
	fs.StringVar(&o.pullAuthor, "pull-author", "", "Git pull author under test")
	o.github.AddFlagsWithoutDefaultGitHubTokenPath(fs)
	fs.Parse(os.Args[1:])
	return o
}

func main() {
	o := gatherOptions()
	if err := o.Validate(); err != nil {
		logrus.WithError(err).Fatalf("Bad flags")
	}

	conf, err := config.Load(o.configPath, o.jobConfigPath)
	if err != nil {
		logrus.WithError(err).Fatal("Error loading config")
	}

	var secretAgent *secret.Agent
	if o.github.TokenPath != "" {
		secretAgent = &secret.Agent{}
		if err := secretAgent.Start([]string{o.github.TokenPath}); err != nil {
			logrus.WithError(err).Fatal("Failed to start secret agent")
		}
	}
	o.githubClient, err = o.github.GitHubClient(secretAgent, false)
	if err != nil {
		logrus.WithError(err).Fatal("Failed to get GitHub client")
	}

	var pjs prowapi.ProwJobSpec
	var labels map[string]string
	var annotations map[string]string
	var found bool
	var needsBaseRef bool
	var needsPR bool
	for fullRepoName, ps := range conf.Presubmits {
		org, repo, err := splitRepoName(fullRepoName)
		if err != nil {
			logrus.WithError(err).Warnf("Invalid repo name %s.", fullRepoName)
			continue
		}
		for _, p := range ps {
			if p.Name == o.jobName {
				pjs = pjutil.PresubmitSpec(p, prowapi.Refs{
					Org:     org,
					Repo:    repo,
					BaseRef: o.baseRef,
					BaseSHA: o.baseSha,
					Pulls: []prowapi.Pull{{
						Author: o.pullAuthor,
						Number: o.pullNumber,
						SHA:    o.pullSha,
					}},
				})
				labels = p.Labels
				annotations = p.Annotations
				found = true
				needsBaseRef = true
				needsPR = true
			}
		}
	}
	for fullRepoName, ps := range conf.Postsubmits {
		org, repo, err := splitRepoName(fullRepoName)
		if err != nil {
			logrus.WithError(err).Warnf("Invalid repo name %s.", fullRepoName)
			continue
		}
		for _, p := range ps {
			if p.Name == o.jobName {
				pjs = pjutil.PostsubmitSpec(p, prowapi.Refs{
					Org:     org,
					Repo:    repo,
					BaseRef: o.baseRef,
					BaseSHA: o.baseSha,
				})
				labels = p.Labels
				annotations = p.Annotations
				found = true
				needsBaseRef = true
			}
		}
	}
	for _, p := range conf.Periodics {
		if p.Name == o.jobName {
			pjs = pjutil.PeriodicSpec(p)
			labels = p.Labels
			annotations = p.Annotations
			found = true
		}
	}
	if !found {
		logrus.Fatalf("Job %s not found.", o.jobName)
	}
	if pjs.Refs != nil {
		o.org = pjs.Refs.Org
		o.repo = pjs.Refs.Repo
	}
	if needsPR {
		if err := o.defaultPR(&pjs); err != nil {
			logrus.WithError(err).Fatal("Failed to default PR")
		}
	}
	if needsBaseRef {
		if err := o.defaultBaseRef(&pjs); err != nil {
			logrus.WithError(err).Fatal("Failed to default base ref")
		}
	}
	pj := pjutil.NewProwJob(pjs, labels, annotations)
	b, err := yaml.Marshal(&pj)
	if err != nil {
		logrus.WithError(err).Fatal("Error marshalling YAML.")
	}
	fmt.Print(string(b))
	if o.local {
		logrus.Info("Use 'bazel run //prow/cmd/phaino' to run this job locally in docker")
	}
}

func splitRepoName(repo string) (string, string, error) {
	s := strings.SplitN(repo, "/", 2)
	if len(s) != 2 {
		return "", "", fmt.Errorf("repo %s cannot be split into org/repo", repo)
	}
	return s[0], s[1], nil
}
<|endoftext|>


<commit_before>package main

import (
	"time"

	log "github.com/Sirupsen/logrus"
)

// Runner is the main entry point for the job runner goroutine.
func Runner(c *Context) {
	for {
		select {
		case <-time.After(time.Duration(c.Poll) * time.Millisecond):
			Claim(c)
		}
	}
}

// Claim acquires the oldest single pending job and launches a goroutine to execute its command in
// a new container.
func Claim(c *Context) {
	job, err := c.ClaimJob()
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Error("Unable to claim a job.")
		return
	}
	if job == nil {
		// Nothing to claim.
		return
	}

	log.WithFields(log.Fields{
		"jid": job.JID,
	}).Info("Launching a new job.")

	go Execute(c, job)
}

// Execute launches a container to process the submitted job. It passes any provided stdin data
// to the container and consumes stdout and stderr, updating Mongo as it runs. Once completed, it
// acquires the job's result from its configured source and marks the job as finished.
func Execute(c *Context, job *SubmittedJob) {
	job.StartedAt = StoreTime(time.Now())
	if err := c.UpdateJob(job); err != nil {
		log.WithFields(log.Fields{
			"jid":   job.JID,
			"error": err,
		}).Error("Unable to update job start timestamp.")
		return
	}

	log.WithFields(log.Fields{
		"jid":     job.JID,
		"command": job.Command,
	}).Info("Hey look I'm executing a job!")

	job.FinishedAt = StoreTime(time.Now())
	job.Status = StatusDone
	if err := c.UpdateJob(job); err != nil {
		log.WithFields(log.Fields{
			"jid":   job.JID,
			"error": err,
		}).Error(`Unable to update job status to "done".`)
		return
	}
}
<commit_msg>Connect to Docker.<commit_after>package main

import (
	"time"

	log "github.com/Sirupsen/logrus"
	docker "github.com/fsouza/go-dockerclient"
)

// Runner is the main entry point for the job runner goroutine.
func Runner(c *Context) {
	client, err := docker.NewClient(c.DockerHost)
	if err != nil {
		log.WithFields(log.Fields{
			"docker host": c.DockerHost,
			"error":       err,
		}).Fatal("Unable to connect to Docker.")
		return
	}

	for {
		select {
		case <-time.After(time.Duration(c.Poll) * time.Millisecond):
			Claim(c, client)
		}
	}
}

// Claim acquires the oldest single pending job and launches a goroutine to execute its command in
// a new container.
func Claim(c *Context, client *docker.Client) {
	job, err := c.ClaimJob()
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Error("Unable to claim a job.")
		return
	}
	if job == nil {
		// Nothing to claim.
		return
	}

	log.WithFields(log.Fields{
		"jid": job.JID,
	}).Info("Launching a new job.")

	go Execute(c, client, job)
}

// Execute launches a container to process the submitted job. It passes any provided stdin data
// to the container and consumes stdout and stderr, updating Mongo as it runs. Once completed, it
// acquires the job's result from its configured source and marks the job as finished.
func Execute(c *Context, client *docker.Client, job *SubmittedJob) {
	job.StartedAt = StoreTime(time.Now())
	if err := c.UpdateJob(job); err != nil {
		log.WithFields(log.Fields{
			"jid":   job.JID,
			"error": err,
		}).Error("Unable to update job start timestamp.")
		return
	}

	log.WithFields(log.Fields{
		"jid":     job.JID,
		"command": job.Command,
	}).Info("Hey look I'm executing a job!")

	job.FinishedAt = StoreTime(time.Now())
	job.Status = StatusDone
	if err := c.UpdateJob(job); err != nil {
		log.WithFields(log.Fields{
			"jid":   job.JID,
			"error": err,
		}).Error(`Unable to update job status to "done".`)
		return
	}
}
<|endoftext|>


<commit_before>package socks

import (
	"io"
	"sync"
	"time"

	"v2ray.com/core/app"
	"v2ray.com/core/app/dispatcher"
	"v2ray.com/core/common/buf"
	"v2ray.com/core/common/bufio"
	"v2ray.com/core/common/errors"
	"v2ray.com/core/common/log"
	v2net "v2ray.com/core/common/net"
	"v2ray.com/core/common/protocol"
	"v2ray.com/core/common/signal"
	"v2ray.com/core/proxy"
	"v2ray.com/core/transport/internet"
	"v2ray.com/core/transport/internet/udp"
)

// Server is a SOCKS 5 proxy server
type Server struct {
	tcpMutex         sync.RWMutex
	udpMutex         sync.RWMutex
	accepting        bool
	packetDispatcher dispatcher.PacketDispatcher
	config           *ServerConfig
	tcpListener      *internet.TCPHub
	udpHub           *udp.Hub
	udpAddress       v2net.Destination
	udpServer        *udp.Server
	meta             *proxy.InboundHandlerMeta
}

// NewServer creates a new Server object.
func NewServer(config *ServerConfig, space app.Space, meta *proxy.InboundHandlerMeta) *Server {
	s := &Server{
		config: config,
		meta:   meta,
	}
	space.OnInitialize(func() error {
		s.packetDispatcher = dispatcher.FromSpace(space)
		if s.packetDispatcher == nil {
			return errors.New("Socks|Server: Dispatcher is not found in the space.")
		}
		return nil
	})
	return s
}

// Port implements InboundHandler.Port().
func (v *Server) Port() v2net.Port {
	return v.meta.Port
}

// Close implements InboundHandler.Close().
func (v *Server) Close() {
	v.accepting = false
	if v.tcpListener != nil {
		v.tcpMutex.Lock()
		v.tcpListener.Close()
		v.tcpListener = nil
		v.tcpMutex.Unlock()
	}
	if v.udpHub != nil {
		v.udpMutex.Lock()
		v.udpHub.Close()
		v.udpHub = nil
		v.udpMutex.Unlock()
	}
}

// Start implements InboundHandler.Start().
func (v *Server) Start() error {
	if v.accepting {
		return nil
	}

	listener, err := internet.ListenTCP(
		v.meta.Address,
		v.meta.Port,
		v.handleConnection,
		v.meta.StreamSettings)
	if err != nil {
		log.Error("Socks: failed to listen on ", v.meta.Address, ":", v.meta.Port, ": ", err)
		return err
	}
	v.accepting = true
	v.tcpMutex.Lock()
	v.tcpListener = listener
	v.tcpMutex.Unlock()
	if v.config.UdpEnabled {
		v.listenUDP()
	}
	return nil
}

func (v *Server) handleConnection(connection internet.Connection) {
	defer connection.Close()

	connection.SetReusable(false)

	timedReader := v2net.NewTimeOutReader(16 /* seconds, for handshake */, connection)
	reader := bufio.NewReader(timedReader)

	session := &ServerSession{
		config: v.config,
		meta:   v.meta,
	}

	clientAddr := v2net.DestinationFromAddr(connection.RemoteAddr())

	request, err := session.Handshake(reader, connection)
	if err != nil {
		log.Access(clientAddr, "", log.AccessRejected, err)
		log.Info("Socks|Server: Failed to read request: ", err)
		return
	}

	if request.Command == protocol.RequestCommandTCP {
		dest := request.Destination()
		session := &proxy.SessionInfo{
			Source:      clientAddr,
			Destination: dest,
			Inbound:     v.meta,
		}
		log.Info("Socks|Server: TCP Connect request to ", dest)
		log.Access(clientAddr, dest, log.AccessAccepted, "")

		timedReader.SetTimeOut(v.config.Timeout)
		v.transport(reader, connection, session)
		return
	}

	if request.Command == protocol.RequestCommandUDP {
		v.handleUDP()
		return
	}
}

func (v *Server) handleUDP() error {
	// The TCP connection closes after v method returns. We need to wait until
	// the client closes it.
	// TODO: get notified from UDP part
	<-time.After(5 * time.Minute)

	return nil
}

func (v *Server) transport(reader io.Reader, writer io.Writer, session *proxy.SessionInfo) {
	ray := v.packetDispatcher.DispatchToOutbound(session)
	input := ray.InboundInput()
	output := ray.InboundOutput()

	requestDone := signal.ExecuteAsync(func() error {
		defer input.Close()

		v2reader := buf.NewReader(reader)
		if err := buf.PipeUntilEOF(v2reader, input); err != nil {
			log.Info("Socks|Server: Failed to transport all TCP request: ", err)
			return err
		}
		return nil
	})

	responseDone := signal.ExecuteAsync(func() error {
		defer output.ForceClose()

		v2writer := buf.NewWriter(writer)
		if err := buf.PipeUntilEOF(output, v2writer); err != nil {
			log.Info("Socks|Server: Failed to transport all TCP response: ", err)
			return err
		}
		return nil

	})

	if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil {
		log.Info("Socks|Server: Connection ends with ", err)
	}
}

type ServerFactory struct{}

func (v *ServerFactory) StreamCapability() v2net.NetworkList {
	return v2net.NetworkList{
		Network: []v2net.Network{v2net.Network_TCP},
	}
}

func (v *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) {
	return NewServer(rawConfig.(*ServerConfig), space, meta), nil
}
<commit_msg>fix link warnings<commit_after>package socks

import (
	"io"
	"sync"
	"time"

	"v2ray.com/core/app"
	"v2ray.com/core/app/dispatcher"
	"v2ray.com/core/common/buf"
	"v2ray.com/core/common/bufio"
	"v2ray.com/core/common/errors"
	"v2ray.com/core/common/log"
	v2net "v2ray.com/core/common/net"
	"v2ray.com/core/common/protocol"
	"v2ray.com/core/common/signal"
	"v2ray.com/core/proxy"
	"v2ray.com/core/transport/internet"
	"v2ray.com/core/transport/internet/udp"
)

// Server is a SOCKS 5 proxy server
type Server struct {
	tcpMutex         sync.RWMutex
	udpMutex         sync.RWMutex
	accepting        bool
	packetDispatcher dispatcher.PacketDispatcher
	config           *ServerConfig
	tcpListener      *internet.TCPHub
	udpHub           *udp.Hub
	udpAddress       v2net.Destination
	udpServer        *udp.Server
	meta             *proxy.InboundHandlerMeta
}

// NewServer creates a new Server object.
func NewServer(config *ServerConfig, space app.Space, meta *proxy.InboundHandlerMeta) *Server {
	s := &Server{
		config: config,
		meta:   meta,
	}
	space.OnInitialize(func() error {
		s.packetDispatcher = dispatcher.FromSpace(space)
		if s.packetDispatcher == nil {
			return errors.New("Socks|Server: Dispatcher is not found in the space.")
		}
		return nil
	})
	return s
}

// Port implements InboundHandler.Port().
func (v *Server) Port() v2net.Port {
	return v.meta.Port
}

// Close implements InboundHandler.Close().
func (v *Server) Close() {
	v.accepting = false
	if v.tcpListener != nil {
		v.tcpMutex.Lock()
		v.tcpListener.Close()
		v.tcpListener = nil
		v.tcpMutex.Unlock()
	}
	if v.udpHub != nil {
		v.udpMutex.Lock()
		v.udpHub.Close()
		v.udpHub = nil
		v.udpMutex.Unlock()
	}
}

// Start implements InboundHandler.Start().
func (v *Server) Start() error {
	if v.accepting {
		return nil
	}

	listener, err := internet.ListenTCP(
		v.meta.Address,
		v.meta.Port,
		v.handleConnection,
		v.meta.StreamSettings)
	if err != nil {
		log.Error("Socks: failed to listen on ", v.meta.Address, ":", v.meta.Port, ": ", err)
		return err
	}
	v.accepting = true
	v.tcpMutex.Lock()
	v.tcpListener = listener
	v.tcpMutex.Unlock()
	if v.config.UdpEnabled {
		if err := v.listenUDP(); err != nil {
			return err
		}
	}
	return nil
}

func (v *Server) handleConnection(connection internet.Connection) {
	defer connection.Close()

	connection.SetReusable(false)

	timedReader := v2net.NewTimeOutReader(16 /* seconds, for handshake */, connection)
	reader := bufio.NewReader(timedReader)

	session := &ServerSession{
		config: v.config,
		meta:   v.meta,
	}

	clientAddr := v2net.DestinationFromAddr(connection.RemoteAddr())

	request, err := session.Handshake(reader, connection)
	if err != nil {
		log.Access(clientAddr, "", log.AccessRejected, err)
		log.Info("Socks|Server: Failed to read request: ", err)
		return
	}

	if request.Command == protocol.RequestCommandTCP {
		dest := request.Destination()
		session := &proxy.SessionInfo{
			Source:      clientAddr,
			Destination: dest,
			Inbound:     v.meta,
		}
		log.Info("Socks|Server: TCP Connect request to ", dest)
		log.Access(clientAddr, dest, log.AccessAccepted, "")

		timedReader.SetTimeOut(v.config.Timeout)
		v.transport(reader, connection, session)
		return
	}

	if request.Command == protocol.RequestCommandUDP {
		v.handleUDP()
		return
	}
}

func (v *Server) handleUDP() {
	// The TCP connection closes after v method returns. We need to wait until
	// the client closes it.
	// TODO: get notified from UDP part
	<-time.After(5 * time.Minute)
}

func (v *Server) transport(reader io.Reader, writer io.Writer, session *proxy.SessionInfo) {
	ray := v.packetDispatcher.DispatchToOutbound(session)
	input := ray.InboundInput()
	output := ray.InboundOutput()

	requestDone := signal.ExecuteAsync(func() error {
		defer input.Close()

		v2reader := buf.NewReader(reader)
		if err := buf.PipeUntilEOF(v2reader, input); err != nil {
			log.Info("Socks|Server: Failed to transport all TCP request: ", err)
			return err
		}
		return nil
	})

	responseDone := signal.ExecuteAsync(func() error {
		defer output.ForceClose()

		v2writer := buf.NewWriter(writer)
		if err := buf.PipeUntilEOF(output, v2writer); err != nil {
			log.Info("Socks|Server: Failed to transport all TCP response: ", err)
			return err
		}
		return nil

	})

	if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil {
		log.Info("Socks|Server: Connection ends with ", err)
	}
}

type ServerFactory struct{}

func (v *ServerFactory) StreamCapability() v2net.NetworkList {
	return v2net.NetworkList{
		Network: []v2net.Network{v2net.Network_TCP},
	}
}

func (v *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) {
	return NewServer(rawConfig.(*ServerConfig), space, meta), nil
}
<|endoftext|>


<commit_before>package main

import (
    "flag"
    "fmt"
    "github.com/howeyc/fsnotify"
    "github.com/remogatto/application"
    "log"
    "os"
    "os/exec"
    "regexp"
    "sync"
    "syscall"
    "time"
)

const (
    // Multiple events that occur for the same file in this
    // time windows will be discarded.
    DISCARD_TIME = 1 * time.Second
    RERUN_TIME   = 2 * time.Second
)

var (
    events  map[string]*eventOnFile
    rwMutex sync.RWMutex
)

// eventOnFile stores informations about events occured on a file
type eventOnFile struct {
    fsnotifyEvent *fsnotify.FileEvent
    time          time.Time
}

func addEvent(event *eventOnFile) *eventOnFile {
    rwMutex.Lock()
    events[event.fsnotifyEvent.Name] = event
    rwMutex.Unlock()
    return event
}

func getEvent(filename string) *eventOnFile {
    rwMutex.RLock()
    event, ok := events[filename]
    rwMutex.RUnlock()
    if ok {
        return event
    }
    return nil
}

// sigterm is a type for handling a SIGTERM signal.
type sigterm struct {
    hitCounter byte
    watchDir   string
}

func (h *sigterm) HandleSignal(s os.Signal) {
    switch ss := s.(type) {
    case syscall.Signal:
        switch ss {
        case syscall.SIGTERM, syscall.SIGINT:
            if h.hitCounter > 0 {
                application.Exit()
                return
            }
            application.Printf("Hit CTRL-C again to exit otherwise tests will be re-runned in %s.", RERUN_TIME)
            h.hitCounter++
            go func() {
                time.Sleep(RERUN_TIME)
                execGoTest(h.watchDir)
                h.hitCounter = 0
            }()
        }
    }
}

// watchLoop watches for changes in the folder
type watcherLoop struct {
    pause, terminate chan int
    watchDir         string
}

func newWatcherLoop(watchDir string) *watcherLoop {
    return &watcherLoop{make(chan int), make(chan int), watchDir}
}

func (l *watcherLoop) Pause() chan int {
    return l.pause
}

func (l *watcherLoop) Terminate() chan int {
    return l.terminate
}

func (l *watcherLoop) Run() {
    // Run the tests for the first time.
    execGoTest(l.watchDir)

    watcher, err := fsnotify.NewWatcher()
    err = watcher.Watch(l.watchDir)
    if err != nil {
        application.Fatal(err.Error())
    }
    application.Printf("Start watching path %s", l.watchDir)
    for {
        select {
        case <-l.pause:
            l.pause <- 0
        case <-l.terminate:
            watcher.Close()
            l.terminate <- 0
            return
        case ev := <-watcher.Event:
            if ev.IsModify() {
                if matches(ev.Name, ".*\\.go$") {
                    if application.Verbose {
                        application.Logf("Event %s occured for file %s", ev, ev.Name)
                    }
                    // check if the same event was
                    // registered for the same
                    // file in the acceptable
                    // TIME_DISCARD time window
                    event := getEvent(ev.Name)
                    if event == nil {
                        event = addEvent(&eventOnFile{ev, time.Now()})
                        application.Logf("Run the tests")
                        execGoTest(l.watchDir)
                    } else if time.Now().Sub(event.time) > DISCARD_TIME {
                        event.time = time.Now()
                        application.Logf("Run the tests")
                        execGoTest(l.watchDir)
                    } else {
                        if application.Verbose {
                            application.Logf("Event %s was discarded for file %s", ev, ev.Name)
                        }
                    }
                }
            }
        case err := <-watcher.Error:
            application.Fatal(err.Error())
        }
    }
}

func usage() {
    fmt.Fprintf(os.Stderr, "PrettyAutoTest continously watches for changes in folder and re-run the tests\n\n")
    fmt.Fprintf(os.Stderr, "Usage:\n\n")
    fmt.Fprintf(os.Stderr, "\tprettyautotest [options]\n\n")
    fmt.Fprintf(os.Stderr, "Options are:\n\n")
    flag.PrintDefaults()
}

// Returns whether 's' matches 'pattern'
func matches(s, pattern string) bool {
    return regexp.MustCompile(pattern).MatchString(s)
}

func execGoTest(path string) {
    cmd := exec.Command("go", "test", "./...")
    cmd.Dir = path
    out, err := cmd.CombinedOutput()
    if err != nil {
        log.Println(err)
    }
    fmt.Print(string(out))
}

func init() {
    events = make(map[string]*eventOnFile, 0)
}

func main() {
    watchDir := flag.String("watchdir", "./", "Directory to watch for changes")
    verbose := flag.Bool("verbose", false, "Verbose mode")
    help := flag.Bool("help", false, "Show usage")
    flag.Usage = usage
    flag.Parse()
    application.Verbose = *verbose
    if *help {
        usage()
        return
    }
    application.Register("Watcher Loop", newWatcherLoop(*watchDir))
    application.InstallSignalHandler(&sigterm{watchDir: *watchDir})
    exitCh := make(chan bool)
    application.Run(exitCh)
    <-exitCh
}
<commit_msg>watch a folder and its subfolders<commit_after>package main

import (
    "flag"
    "fmt"
    "github.com/howeyc/fsnotify"
    "github.com/remogatto/application"
    "log"
    "os"
    "os/exec"
    "path/filepath"
    "regexp"
    "sync"
    "syscall"
    "time"
)

const (
    // Multiple events that occur for the same file in this
    // time windows will be discarded.
    DISCARD_TIME = 1 * time.Second
    RERUN_TIME   = 2 * time.Second
)

var (
    events  map[string]*eventOnFile
    rwMutex sync.RWMutex
)

// eventOnFile stores informations about events occured on a file
type eventOnFile struct {
    fsnotifyEvent *fsnotify.FileEvent
    time          time.Time
}

func addEvent(event *eventOnFile) *eventOnFile {
    rwMutex.Lock()
    events[event.fsnotifyEvent.Name] = event
    rwMutex.Unlock()
    return event
}

func getEvent(filename string) *eventOnFile {
    rwMutex.RLock()
    event, ok := events[filename]
    rwMutex.RUnlock()
    if ok {
        return event
    }
    return nil
}

// sigterm is a type for handling a SIGTERM signal.
type sigterm struct {
    hitCounter byte
    watchDir   string
}

func (h *sigterm) HandleSignal(s os.Signal) {
    switch ss := s.(type) {
    case syscall.Signal:
        switch ss {
        case syscall.SIGTERM, syscall.SIGINT:
            if h.hitCounter > 0 {
                application.Exit()
                return
            }
            application.Printf("Hit CTRL-C again to exit otherwise tests will be re-runned in %s.", RERUN_TIME)
            h.hitCounter++
            go func() {
                time.Sleep(RERUN_TIME)
                execGoTest(h.watchDir)
                h.hitCounter = 0
            }()
        }
    }
}

// watchLoop watches for changes in the folder
type watcherLoop struct {
    pause, terminate chan int
    watchDir         string
}

func newWatcherLoop(watchDir string) *watcherLoop {
    return &watcherLoop{make(chan int), make(chan int), watchDir}
}

func (l *watcherLoop) Pause() chan int {
    return l.pause
}

func (l *watcherLoop) Terminate() chan int {
    return l.terminate
}

func (l *watcherLoop) Run() {
    // Run the tests for the first time.
    execGoTest(l.watchDir)

    watcher, err := fsnotify.NewWatcher()

    for _, folder := range folders(l.watchDir) {
        err = watcher.Watch(folder)
        if err != nil {
            application.Fatal(err.Error())
        }
        application.Printf("Start watching path %s", folder)
    }

    for {
        select {
        case <-l.pause:
            l.pause <- 0
        case <-l.terminate:
            watcher.Close()
            l.terminate <- 0
            return
        case ev := <-watcher.Event:
            if ev.IsModify() {
                if matches(ev.Name, ".*\\.go$") {
                    if application.Verbose {
                        application.Logf("Event %s occured for file %s", ev, ev.Name)
                    }
                    // check if the same event was
                    // registered for the same
                    // file in the acceptable
                    // TIME_DISCARD time window
                    event := getEvent(ev.Name)
                    if event == nil {
                        event = addEvent(&eventOnFile{ev, time.Now()})
                        application.Logf("Run the tests")
                        execGoTest(l.watchDir)
                    } else if time.Now().Sub(event.time) > DISCARD_TIME {
                        event.time = time.Now()
                        application.Logf("Run the tests")
                        execGoTest(l.watchDir)
                    } else {
                        if application.Verbose {
                            application.Logf("Event %s was discarded for file %s", ev, ev.Name)
                        }
                    }
                }
            }
        case err := <-watcher.Error:
            application.Fatal(err.Error())
        }
    }
}

func usage() {
    fmt.Fprintf(os.Stderr, "PrettyAutoTest continously watches for changes in folder and re-run the tests\n\n")
    fmt.Fprintf(os.Stderr, "Usage:\n\n")
    fmt.Fprintf(os.Stderr, "\tprettyautotest [options]\n\n")
    fmt.Fprintf(os.Stderr, "Options are:\n\n")
    flag.PrintDefaults()
}

// Returns whether 's' matches 'pattern'
func matches(s, pattern string) bool {
    return regexp.MustCompile(pattern).MatchString(s)
}

func execGoTest(path string) {
    cmd := exec.Command("go", "test", "./...")
    cmd.Dir = path
    out, err := cmd.CombinedOutput()
    if err != nil {
        log.Println(err)
    }
    fmt.Print(string(out))
}

func init() {
    events = make(map[string]*eventOnFile, 0)
}

// returns a slice of subfolders (recursive), including the folder passed in
func folders(path string) (paths []string) {
    filepath.Walk(path, func(newPath string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }

        if info.IsDir() {
            name := info.Name()
            // skip folders that begin with a dot
            hidden := filepath.HasPrefix(name, ".") && name != "." && name != ".."
            if hidden {
                return filepath.SkipDir
            } else {
                paths = append(paths, newPath)
            }
        }
        return nil
    })
    return paths
}

func main() {
    watchDir := flag.String("watchdir", "./", "Directory to watch for changes")
    verbose := flag.Bool("verbose", false, "Verbose mode")
    help := flag.Bool("help", false, "Show usage")
    flag.Usage = usage
    flag.Parse()

    application.Verbose = *verbose
    if *help {
        usage()
        return
    }
    application.Register("Watcher Loop", newWatcherLoop(*watchDir))
    application.InstallSignalHandler(&sigterm{watchDir: *watchDir})
    exitCh := make(chan bool)
    application.Run(exitCh)
    <-exitCh
}
<|endoftext|>


<commit_before>/*
Copyright 2018, Cossack Labs Limited

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 filesystem

import (
	"github.com/cossacklabs/acra/keystore"
	"github.com/cossacklabs/themis/gothemis/keys"
	"io/ioutil"
	"path/filepath"
)

// TranslatorFileSystemKeyStore stores AcraTranslator keys configuration
type TranslatorFileSystemKeyStore struct {
	*KeyStore
	directory string
	encryptor keystore.KeyEncryptor
}

// NewTranslatorFileSystemKeyStore creates new TranslatorFileSystemKeyStore
func NewTranslatorFileSystemKeyStore(directory string, encryptor keystore.KeyEncryptor, cacheSize int) (*TranslatorFileSystemKeyStore, error) {
	fsKeystore, err := NewFileSystemKeyStoreWithCacheSize(directory, encryptor, cacheSize)
	if err != nil {
		return nil, err
	}
	return &TranslatorFileSystemKeyStore{KeyStore: fsKeystore, directory: directory, encryptor: encryptor}, nil
}

// CheckIfPrivateKeyExists checks if Keystore has Translator transport private key for establishing Secure Session connection,
// returns true if key exists in fs.
func (store *TranslatorFileSystemKeyStore) CheckIfPrivateKeyExists(id []byte) (bool, error) {
	_, err := ioutil.ReadFile(filepath.Join(store.directory, getTranslatorKeyFilename(id)))
	if err != nil {
		return false, err
	}
	return true, nil
}

// GetPrivateKey reads and decrypts Translator transport private key for establishing Secure Session connection.
func (store *TranslatorFileSystemKeyStore) GetPrivateKey(id []byte) (*keys.PrivateKey, error) {
	keyData, err := ioutil.ReadFile(filepath.Join(store.directory, getTranslatorKeyFilename(id)))
	if err != nil {
		return nil, err
	}

	var privateKey []byte
	if privateKey, err = store.encryptor.Decrypt(keyData, id); err != nil {
		return nil, err
	}
	return &keys.PrivateKey{Value: privateKey}, nil
}

// GetPeerPublicKey returns other party transport public key.
func (store *TranslatorFileSystemKeyStore) GetPeerPublicKey(id []byte) (*keys.PublicKey, error) {
	filename := getConnectorKeyFilename(id)
	key, err := ioutil.ReadFile(filepath.Join(store.directory, getPublicKeyFilename([]byte(filename))))
	if err != nil {
		return nil, err
	}
	return &keys.PublicKey{Value: key}, nil
}
<commit_msg>add general constructor for translator's keystore<commit_after>/*
Copyright 2018, Cossack Labs Limited

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 filesystem

import (
	"github.com/cossacklabs/acra/keystore"
	"github.com/cossacklabs/themis/gothemis/keys"
	"io/ioutil"
	"path/filepath"
)

// TranslatorFileSystemKeyStore stores AcraTranslator keys configuration
type TranslatorFileSystemKeyStore struct {
	*KeyStore
	directory string
	encryptor keystore.KeyEncryptor
}

// NewTranslatorFileSystemKeyStoreFromServerStore create TranslatorKeyStore which inherit KeyStore
func NewTranslatorFileSystemKeyStoreFromServerStore(directory string, encryptor keystore.KeyEncryptor, store *KeyStore)(*TranslatorFileSystemKeyStore, error){
	return &TranslatorFileSystemKeyStore{KeyStore: store, directory: directory, encryptor: encryptor}, nil
}

// NewTranslatorFileSystemKeyStore creates new TranslatorFileSystemKeyStore
func NewTranslatorFileSystemKeyStore(directory string, encryptor keystore.KeyEncryptor, cacheSize int) (*TranslatorFileSystemKeyStore, error) {
	fsKeystore, err := NewFileSystemKeyStoreWithCacheSize(directory, encryptor, cacheSize)
	if err != nil {
		return nil, err
	}
	return &TranslatorFileSystemKeyStore{KeyStore: fsKeystore, directory: directory, encryptor: encryptor}, nil
}

// CheckIfPrivateKeyExists checks if Keystore has Translator transport private key for establishing Secure Session connection,
// returns true if key exists in fs.
func (store *TranslatorFileSystemKeyStore) CheckIfPrivateKeyExists(id []byte) (bool, error) {
	_, err := ioutil.ReadFile(filepath.Join(store.directory, getTranslatorKeyFilename(id)))
	if err != nil {
		return false, err
	}
	return true, nil
}

// GetPrivateKey reads and decrypts Translator transport private key for establishing Secure Session connection.
func (store *TranslatorFileSystemKeyStore) GetPrivateKey(id []byte) (*keys.PrivateKey, error) {
	keyData, err := ioutil.ReadFile(filepath.Join(store.directory, getTranslatorKeyFilename(id)))
	if err != nil {
		return nil, err
	}

	var privateKey []byte
	if privateKey, err = store.encryptor.Decrypt(keyData, id); err != nil {
		return nil, err
	}
	return &keys.PrivateKey{Value: privateKey}, nil
}

// GetPeerPublicKey returns other party transport public key.
func (store *TranslatorFileSystemKeyStore) GetPeerPublicKey(id []byte) (*keys.PublicKey, error) {
	filename := getConnectorKeyFilename(id)
	key, err := ioutil.ReadFile(filepath.Join(store.directory, getPublicKeyFilename([]byte(filename))))
	if err != nil {
		return nil, err
	}
	return &keys.PublicKey{Value: key}, nil
}
<|endoftext|>


<commit_before>package assert

import (
	"errors"
	"fmt"
	"reflect"
)

func NotNull(message string, value interface{}) error {
	if value == nil {
		return errors.New(fmt.Sprintf("%s, expect not null value", message))
	}
	return nil
}

func Null(message string, value interface{}) error {
	if value != nil {
		return errors.New(fmt.Sprintf("%s, expect null value", message))
	}
	return nil
}

func EqualsString(message string, expected string, value string) error {
	if expected != value {
		return errors.New(fmt.Sprintf("%s, expected '%s' but got '%s'", message, expected, value))
	}
	return nil
}

func EqualsInt(message string, expected int, value int) error {
	if expected != value {
		return errors.New(fmt.Sprintf("%s, expected %d but got %d", message, expected, value))
	}
	return nil
}

func True(message string, value bool) error {
	if value != true {
		return errors.New(fmt.Sprintf("%s, expected true but got false", message))
	}
	return nil
}

func False(message string, value bool) error {
	if value != false {
		return errors.New(fmt.Sprintf("%s, expected false but got true", message))
	}
	return nil
}

func Implements(message string, expected interface{}, value interface{}) error {
	expectedType := reflect.TypeOf(expected).Elem()
	valueType := reflect.TypeOf(value)
	if !valueType.Implements(expectedType) {
		return errors.New(fmt.Sprintf("%s, expected type '%s' but got '%s'", message, expectedType.Name(), valueType.Elem().Name()))
	}
	return nil
}

func Length(message string, expectedLength int, arrayLength int) error {
	if expectedLength != arrayLength {
		return errors.New(fmt.Sprintf("%s, expected array length %d but got %d", message, expectedLength, arrayLength))
	}
	return nil
}
<commit_msg>add doc for Implements<commit_after>package assert

import (
	"errors"
	"fmt"
	"reflect"
)

func NotNull(message string, value interface{}) error {
	if value == nil {
		return errors.New(fmt.Sprintf("%s, expect not null value", message))
	}
	return nil
}

func Null(message string, value interface{}) error {
	if value != nil {
		return errors.New(fmt.Sprintf("%s, expect null value", message))
	}
	return nil
}

func EqualsString(message string, expected string, value string) error {
	if expected != value {
		return errors.New(fmt.Sprintf("%s, expected '%s' but got '%s'", message, expected, value))
	}
	return nil
}

func EqualsInt(message string, expected int, value int) error {
	if expected != value {
		return errors.New(fmt.Sprintf("%s, expected %d but got %d", message, expected, value))
	}
	return nil
}

func True(message string, value bool) error {
	if value != true {
		return errors.New(fmt.Sprintf("%s, expected true but got false", message))
	}
	return nil
}

func False(message string, value bool) error {
	if value != false {
		return errors.New(fmt.Sprintf("%s, expected false but got true", message))
	}
	return nil
}

//    var value := ...
//    var expected *InterfaceName
//    err := assert.Implements("should of type InterfaceName", expected, value)
//    if err != nil {
//      t.Error(err)
//    }
func Implements(message string, expected interface{}, value interface{}) error {
	expectedType := reflect.TypeOf(expected).Elem()
	valueType := reflect.TypeOf(value)
	if !valueType.Implements(expectedType) {
		return errors.New(fmt.Sprintf("%s, expected type '%s' but got '%s'", message, expectedType.Name(), valueType.Elem().Name()))
	}
	return nil
}

func Length(message string, expectedLength int, arrayLength int) error {
	if expectedLength != arrayLength {
		return errors.New(fmt.Sprintf("%s, expected array length %d but got %d", message, expectedLength, arrayLength))
	}
	return nil
}
<|endoftext|>