<commit_before>package main

import (
    "encoding/json"
    "flag"
    "io"
    "io/ioutil"
    "image"
    "image/jpeg"
    "image/png"
    "fmt"
    "html/template"
    "net/http"
    "os"
    "path/filepath"
    "strconv"
    "strings"
    "code.google.com/p/graphics-go/graphics"
    "github.com/elazarl/go-bindata-assetfs"
)

type SelectableFile struct {
    Name string
    Selected bool
}

var address = flag.String("address", "0.0.0.0", "server address")
var port = flag.String("port", "4000", "server port")
var cache = flag.String("cache", "cache", "folder for resized images")

var folder = flag.String("images", "images", "folder with images")
var selected string
var files []SelectableFile

func ListFolder() {
    files = []SelectableFile{}
    raw, _ := ioutil.ReadDir(*folder)
    noneSelected := true
    for _, f := range raw {
        ext := strings.ToLower(filepath.Ext(f.Name()))
        if ext == ".png" || ext == ".jpg" || ext == ".jpeg" {
            name := filepath.Join("/", *folder, f.Name())
            isSelected := false
            if name == selected {
                isSelected = true
                noneSelected = false
            }
            files = append(files, SelectableFile{name, isSelected})
        }
    }

    if noneSelected && len(files) > 0 {
        selected = files[0].Name
        files[0].Selected = true
    }
}

func GetImages(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path == "/images/" {
        ListFolder()

        jsonData, err := json.MarshalIndent(files, "", "    ")
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }

        w.Header().Set("Content-Type", "application/json")
        if len(files) == 0 {
            w.Write([]byte("[]"))
        } else {
            w.Write(jsonData)
        }
    } else {
        filename := r.URL.Path[1:]

        absFilename, err := filepath.Abs(filename)
        if err != nil {
            fmt.Printf("Error: %s\n", err.Error())
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        wd, _ := os.Getwd()
        if !strings.HasPrefix(absFilename, wd) {
            w.WriteHeader(http.StatusBadRequest)
            return
        }

        if r.Method == "GET" {
            width, err1 := strconv.Atoi(r.URL.Query().Get("width"))
            height, err2 := strconv.Atoi(r.URL.Query().Get("height"))

            if err1 == nil && err2 == nil && width > 0 && height > 0 {
                ext := filepath.Ext(filename)
                resizedFilename := strings.TrimRight(filepath.Base(filename), ext)
                resizedFilename += "_" + strconv.Itoa(width)
                resizedFilename += "_" + strconv.Itoa(height)
                resizedFilename += ext

                resizedFilename = filepath.Join(*cache, resizedFilename)

                if _, err := os.Stat(resizedFilename); os.IsNotExist(err) {
                    fSrc, err := os.Open(filename)
                    if err != nil {
                        fmt.Printf("Error: %s\n", err.Error())
                        http.Error(w, err.Error(), http.StatusInternalServerError)
                        return
                    }
                    defer fSrc.Close()

                    src, _, err := image.Decode(fSrc)
                    if err != nil {
                        fmt.Printf("Error: %s\n", err.Error())
                        http.Error(w, err.Error(), http.StatusInternalServerError)
                        return
                    }

                    dst := image.NewRGBA(image.Rect(0, 0, width, height))

                    graphics.Thumbnail(dst, src)

                    fDst, err := os.Create(resizedFilename)
                    if err != nil {
                        fmt.Printf("Error: %s\n", err.Error())
                        http.Error(w, err.Error(), http.StatusInternalServerError)
                        return
                    }
                    defer fDst.Close()

                    if ext == ".png" {
                        png.Encode(fDst, dst)
                    } else {
                        jpeg.Encode(fDst, dst, &jpeg.Options{jpeg.DefaultQuality})
                    }
                    filename = resizedFilename
                } else {
                    filename = resizedFilename
                }
            }

            http.ServeFile(w, r, filename)

            fmt.Printf("Serving image %s\n", filename)

        } else if r.Method == "DELETE" {
            // TODO: remove cached resized versions of the image
            if err := os.Remove(filename); err != nil {
                fmt.Printf("Error: %s\n", err.Error())
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }

            fmt.Printf("Removed %s\n", filename)

            w.WriteHeader(http.StatusNoContent)
        }
    }
}

func SelectImage(w http.ResponseWriter, r *http.Request) {
    jsonDoc, err := ioutil.ReadAll(r.Body);
    if err != nil {
        fmt.Printf("Error: %s\n", err.Error())
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    selectedFile := SelectableFile{}
    if err := json.Unmarshal(jsonDoc, &selectedFile); err != nil {
        fmt.Printf("Error: %s\n", err.Error())
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    fmt.Printf("Selected %s\n", selectedFile.Name)

    for _, file := range files {
        if file.Name == selectedFile.Name {
            selected = selectedFile.Name
            ListFolder()

            w.WriteHeader(http.StatusNoContent)
            return
        }
    }

    w.WriteHeader(http.StatusBadRequest)
}

func UploadImage(w http.ResponseWriter, r *http.Request) {
    file, header, err := r.FormFile("file")
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    defer file.Close()

    out, err := os.Create(filepath.Join(*folder, header.Filename))
    if err != nil {
        fmt.Printf("Error: %s\n", err.Error())
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    defer out.Close()

    _, err = io.Copy(out, file)
    if err != nil {
        fmt.Printf("Error: %s\n", err.Error())
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    fmt.Printf("Uploaded %s\n", header.Filename)

    w.WriteHeader(http.StatusNoContent)
}

func Screen(w http.ResponseWriter, r *http.Request) {
    if r.Header.Get("Content-Type") == "application/json" {
        jsonData, err := json.MarshalIndent(SelectableFile{selected, true}, "", "    ")
        if err != nil {
            fmt.Printf("Error: %s\n", err.Error())
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        w.Write(jsonData)
    } else {
        data, err := Asset("static/screen.html")
        if err != nil {
            fmt.Printf("Error: %s\n", err.Error())
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }

        t := template.New("screen")
        t, _ = t.Parse(string(data[:]))
        t.Execute(w, selected)
    }
}

func main() {
    flag.Parse()

    os.Mkdir(*cache, 0755)
    os.Mkdir(*folder, 0755)
    ListFolder()

    http.HandleFunc("/images/", GetImages)
    http.HandleFunc("/select", SelectImage)
    http.HandleFunc("/upload", UploadImage)
    http.HandleFunc("/screen", Screen)

    http.Handle("/", http.FileServer(&assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, Prefix: "static"}))

    fmt.Printf("Starting server at: http://%s:%s/ \n", *address, *port)
    err := http.ListenAndServe(*address + ":" + *port, nil)
    if err != nil {
        panic("ListenAndServe: " + err.Error())
    }
}
<commit_msg>Fixed filepaths in windows.<commit_after>package main

import (
    "encoding/json"
    "flag"
    "io"
    "io/ioutil"
    "image"
    "image/jpeg"
    "image/png"
    "fmt"
    "html/template"
    "net/http"
    "os"
    "path/filepath"
    "strconv"
    "strings"
    "code.google.com/p/graphics-go/graphics"
    "github.com/elazarl/go-bindata-assetfs"
)

type SelectableFile struct {
    Name string
    Selected bool
}

var address = flag.String("address", "0.0.0.0", "server address")
var port = flag.String("port", "4000", "server port")
var cache = flag.String("cache", "cache", "folder for resized images")

var folder = flag.String("images", "images", "folder with images")
var selected string
var files []SelectableFile

func ListFolder() {
    files = []SelectableFile{}
    raw, _ := ioutil.ReadDir(*folder)
    noneSelected := true
    for _, f := range raw {
        ext := strings.ToLower(filepath.Ext(f.Name()))
        if ext == ".png" || ext == ".jpg" || ext == ".jpeg" {
            name := filepath.ToSlash(filepath.Join("/", *folder, f.Name()))
            isSelected := false
            if name == selected {
                isSelected = true
                noneSelected = false
            }
            files = append(files, SelectableFile{name, isSelected})
        }
    }

    if noneSelected && len(files) > 0 {
        selected = files[0].Name
        files[0].Selected = true
    }
}

func GetImages(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path == "/images/" {
        ListFolder()

        jsonData, err := json.MarshalIndent(files, "", "    ")
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }

        w.Header().Set("Content-Type", "application/json")
        if len(files) == 0 {
            w.Write([]byte("[]"))
        } else {
            w.Write(jsonData)
        }
    } else {
        filename := filepath.FromSlash(r.URL.Path[1:])

        absFilename, err := filepath.Abs(filename)
        if err != nil {
            fmt.Printf("Error: %s\n", err.Error())
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        wd, _ := os.Getwd()
        if !strings.HasPrefix(absFilename, wd) {
            w.WriteHeader(http.StatusBadRequest)
            return
        }

        if r.Method == "GET" {
            width, err1 := strconv.Atoi(r.URL.Query().Get("width"))
            height, err2 := strconv.Atoi(r.URL.Query().Get("height"))

            if err1 == nil && err2 == nil && width > 0 && height > 0 {
                ext := filepath.Ext(filename)
                resizedFilename := strings.TrimRight(filepath.Base(filename), ext)
                resizedFilename += "_" + strconv.Itoa(width)
                resizedFilename += "_" + strconv.Itoa(height)
                resizedFilename += ext

                resizedFilename = filepath.Join(*cache, resizedFilename)

                if _, err := os.Stat(resizedFilename); os.IsNotExist(err) {
                    fSrc, err := os.Open(filename)
                    if err != nil {
                        fmt.Printf("Error: %s\n", err.Error())
                        http.Error(w, err.Error(), http.StatusInternalServerError)
                        return
                    }
                    defer fSrc.Close()

                    src, _, err := image.Decode(fSrc)
                    if err != nil {
                        fmt.Printf("Error: %s\n", err.Error())
                        http.Error(w, err.Error(), http.StatusInternalServerError)
                        return
                    }

                    dst := image.NewRGBA(image.Rect(0, 0, width, height))

                    graphics.Thumbnail(dst, src)

                    fDst, err := os.Create(resizedFilename)
                    if err != nil {
                        fmt.Printf("Error: %s\n", err.Error())
                        http.Error(w, err.Error(), http.StatusInternalServerError)
                        return
                    }
                    defer fDst.Close()

                    if ext == ".png" {
                        png.Encode(fDst, dst)
                    } else {
                        jpeg.Encode(fDst, dst, &jpeg.Options{jpeg.DefaultQuality})
                    }
                    filename = resizedFilename
                } else {
                    filename = resizedFilename
                }
            }

            http.ServeFile(w, r, filename)

            fmt.Printf("Serving image %s\n", filename)

        } else if r.Method == "DELETE" {
            // TODO: remove cached resized versions of the image
            if err := os.Remove(filename); err != nil {
                fmt.Printf("Error: %s\n", err.Error())
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }

            fmt.Printf("Removed %s\n", filename)

            w.WriteHeader(http.StatusNoContent)
        }
    }
}

func SelectImage(w http.ResponseWriter, r *http.Request) {
    jsonDoc, err := ioutil.ReadAll(r.Body);
    if err != nil {
        fmt.Printf("Error: %s\n", err.Error())
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    selectedFile := SelectableFile{}
    if err := json.Unmarshal(jsonDoc, &selectedFile); err != nil {
        fmt.Printf("Error: %s\n", err.Error())
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    fmt.Printf("Selected %s\n", selectedFile.Name)

    for _, file := range files {
        if file.Name == selectedFile.Name {
            selected = selectedFile.Name
            ListFolder()

            w.WriteHeader(http.StatusNoContent)
            return
        }
    }

    w.WriteHeader(http.StatusBadRequest)
}

func UploadImage(w http.ResponseWriter, r *http.Request) {
    file, header, err := r.FormFile("file")
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    defer file.Close()

    out, err := os.Create(filepath.Join(*folder, header.Filename))
    if err != nil {
        fmt.Printf("Error: %s\n", err.Error())
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    defer out.Close()

    _, err = io.Copy(out, file)
    if err != nil {
        fmt.Printf("Error: %s\n", err.Error())
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    fmt.Printf("Uploaded %s\n", header.Filename)

    w.WriteHeader(http.StatusNoContent)
}

func Screen(w http.ResponseWriter, r *http.Request) {
    if r.Header.Get("Content-Type") == "application/json" {
        jsonData, err := json.MarshalIndent(SelectableFile{selected, true}, "", "    ")
        if err != nil {
            fmt.Printf("Error: %s\n", err.Error())
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        w.Write(jsonData)
    } else {
        data, err := Asset("static/screen.html")
        if err != nil {
            fmt.Printf("Error: %s\n", err.Error())
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }

        t := template.New("screen")
        t, _ = t.Parse(string(data[:]))
        t.Execute(w, selected)
    }
}

func main() {
    flag.Parse()

    os.Mkdir(*cache, 0755)
    os.Mkdir(*folder, 0755)
    ListFolder()

    http.HandleFunc("/images/", GetImages)
    http.HandleFunc("/select", SelectImage)
    http.HandleFunc("/upload", UploadImage)
    http.HandleFunc("/screen", Screen)

    http.Handle("/", http.FileServer(&assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, Prefix: "static"}))

    fmt.Printf("Starting server at: http://%s:%s/ \n", *address, *port)
    err := http.ListenAndServe(*address + ":" + *port, nil)
    if err != nil {
        panic("ListenAndServe: " + err.Error())
    }
}
<|endoftext|>


<commit_before>package cioutil

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

	"github.com/garyburd/go-oauth/oauth"
	"github.com/pkg/errors"
)

// ClientRequest defines information that can be used to make a request
type ClientRequest struct {
	Method       string
	Path         string
	FormValues   interface{}
	QueryValues  interface{}
	UserID       string
	AccountLabel string
}

// DoFormRequest makes the actual request
func (cio Cio) DoFormRequest(request ClientRequest, result interface{}) error {

	// Construct the url
	cioURL := cio.Host + request.Path + QueryString(request.QueryValues)

	// Construct the body
	bodyValues := FormValues(request.FormValues)
	bodyString := bodyValues.Encode()

	// Before-Request Hook Function (logging)
	if cio.PreRequestHook != nil {
		cio.PreRequestHook(request.UserID, request.AccountLabel, request.Method, cioURL, redactBodyValues(bodyValues))
	}

	var (
		statusCode int
		resBody    string
		err        error
	)

	for i := 1; ; i++ {
		statusCode, resBody, err = cio.createAndSendRequest(request, cioURL, bodyString, bodyValues, result)
		// After-Request Hook Function (logging)
		if cio.PostRequestShouldRetryHook == nil || !cio.PostRequestShouldRetryHook(i, request.UserID, request.AccountLabel, request.Method, cioURL, statusCode, resBody, err) {
			break
		}
		time.Sleep(time.Duration(i*i*i) * time.Second) // Exponential backoff
	}

	return err
}

// createAndSendRequest creates the body io.Reader, the *http.Request, and sends the request, logging the response.
// Returns the status code, the response body, and any error
func (cio Cio) createAndSendRequest(request ClientRequest, cioURL string, bodyString string, bodyValues url.Values, result interface{}) (int, string, error) {

	var bodyReader io.Reader
	if len(bodyString) > 0 {
		bodyReader = bytes.NewReader([]byte(bodyString))
	}

	// Construct the request
	httpReq, err := cio.createRequest(request, cioURL, bodyReader, bodyValues)
	if err != nil {
		return 0, "", err
	}

	// Send the request
	return cio.sendRequest(httpReq, result, cioURL)
}

// createRequest creates the *http.Request object
func (cio Cio) createRequest(request ClientRequest, cioURL string, bodyReader io.Reader, bodyValues url.Values) (*http.Request, error) {
	// Construct the request
	httpReq, err := http.NewRequest(request.Method, cioURL, bodyReader)
	if err != nil {
		return httpReq, RequestError{errors.Wrap(err, "CIO: Failed to form request"), ErrorMetaData{Method: request.Method, URL: cioURL}}
	}

	// oAuth signature
	var client oauth.Client
	client.Credentials = oauth.Credentials{Token: cio.apiKey, Secret: cio.apiSecret}

	// Add headers
	httpReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	httpReq.Header.Set("Accept", "application/json")
	httpReq.Header.Set("Accept-Charset", "utf-8")
	httpReq.Header.Set("User-Agent", "Golang CIO Library")
	httpReq.Header.Set("Authorization", client.AuthorizationHeader(nil, request.Method, httpReq.URL, bodyValues))

	return httpReq, nil
}

// sendRequest sends the *http.Request, and returns the status code, the response body, and any error
func (cio Cio) sendRequest(httpReq *http.Request, result interface{}, cioURL string) (int, string, error) {
	// Create the HTTP client
	httpClient := &http.Client{
		Transport: http.DefaultTransport,
		Timeout:   cio.RequestTimeout,
	}

	// Make the request
	res, err := httpClient.Do(httpReq)
	if err != nil {
		return 0, "", RequestError{errors.Wrap(err, "CIO: Failed to make request"), ErrorMetaData{Method: httpReq.Method, URL: cioURL}}
	}

	// Parse the response
	defer func() {
		if closeErr := res.Body.Close(); closeErr != nil && cio.ResponseBodyCloseErrorHook != nil {
			cio.ResponseBodyCloseErrorHook(closeErr) // Logging
		}
	}()

	resBody, err := ioutil.ReadAll(res.Body)
	resBodyString := string(resBody)
	if err != nil {
		return res.StatusCode, resBodyString, RequestError{errors.Wrap(err, "CIO: Could not read response"), ErrorMetaData{Method: httpReq.Method, URL: cioURL, StatusCode: res.StatusCode, Payload: resBodyString}}
	}

	// Unmarshal result
	err = json.Unmarshal(resBody, &result)

	// Return own error if Status Code >= 400
	if res.StatusCode >= 400 {
		return res.StatusCode, resBodyString, RequestError{errors.New("CIO: Status Code >= 400"), ErrorMetaData{Method: httpReq.Method, URL: cioURL, StatusCode: res.StatusCode, Payload: resBodyString}}
	}

	// Return Unmarshal error (if any) if Status Code is < 400
	if err != nil {
		return res.StatusCode, resBodyString, RequestError{errors.Wrap(err, "CIO: Could not unmarshal payload"), ErrorMetaData{Method: httpReq.Method, URL: cioURL, StatusCode: res.StatusCode, Payload: resBodyString}}
	}
	return res.StatusCode, resBodyString, nil
}

// redactBodyValues returns a copy of the body values redacted
func redactBodyValues(bodyValues url.Values) url.Values {

	// Copy url.Values
	redactedValues := url.Values{}
	for k, v := range bodyValues {
		redactedValues[k] = v
	}

	// Redact sensitive information
	if val := redactedValues.Get("password"); len(val) > 0 {
		redactedValues.Set("password", "redacted")
	}
	if val := redactedValues.Get("provider_refresh_token"); len(val) > 0 {
		redactedValues.Set("provider_refresh_token", "redacted")
	}
	if val := redactedValues.Get("provider_consumer_key"); len(val) > 0 {
		redactedValues.Set("provider_consumer_key", "redacted")
	}
	if val := redactedValues.Get("provider_consumer_secret"); len(val) > 0 {
		redactedValues.Set("provider_consumer_secret", "redacted")
	}

	return redactedValues
}
<commit_msg>hardcoded max attempts<commit_after>package cioutil

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

	"github.com/garyburd/go-oauth/oauth"
	"github.com/pkg/errors"
)

// ClientRequest defines information that can be used to make a request
type ClientRequest struct {
	Method       string
	Path         string
	FormValues   interface{}
	QueryValues  interface{}
	UserID       string
	AccountLabel string
}

// DoFormRequest makes the actual request
func (cio Cio) DoFormRequest(request ClientRequest, result interface{}) error {

	// Construct the url
	cioURL := cio.Host + request.Path + QueryString(request.QueryValues)

	// Construct the body
	bodyValues := FormValues(request.FormValues)
	bodyString := bodyValues.Encode()

	// Before-Request Hook Function (logging)
	if cio.PreRequestHook != nil {
		cio.PreRequestHook(request.UserID, request.AccountLabel, request.Method, cioURL, redactBodyValues(bodyValues))
	}

	var (
		statusCode int
		resBody    string
		err        error
	)

	for i := 1; i <= 10; i++ {
		statusCode, resBody, err = cio.createAndSendRequest(request, cioURL, bodyString, bodyValues, result)
		// After-Request Hook Function (logging)
		if cio.PostRequestShouldRetryHook == nil || !cio.PostRequestShouldRetryHook(i, request.UserID, request.AccountLabel, request.Method, cioURL, statusCode, resBody, err) {
			break
		}
		time.Sleep(time.Duration(i*i*i) * time.Second) // Exponential backoff
	}

	return err
}

// createAndSendRequest creates the body io.Reader, the *http.Request, and sends the request, logging the response.
// Returns the status code, the response body, and any error
func (cio Cio) createAndSendRequest(request ClientRequest, cioURL string, bodyString string, bodyValues url.Values, result interface{}) (int, string, error) {

	var bodyReader io.Reader
	if len(bodyString) > 0 {
		bodyReader = bytes.NewReader([]byte(bodyString))
	}

	// Construct the request
	httpReq, err := cio.createRequest(request, cioURL, bodyReader, bodyValues)
	if err != nil {
		return 0, "", err
	}

	// Send the request
	return cio.sendRequest(httpReq, result, cioURL)
}

// createRequest creates the *http.Request object
func (cio Cio) createRequest(request ClientRequest, cioURL string, bodyReader io.Reader, bodyValues url.Values) (*http.Request, error) {
	// Construct the request
	httpReq, err := http.NewRequest(request.Method, cioURL, bodyReader)
	if err != nil {
		return httpReq, RequestError{errors.Wrap(err, "CIO: Failed to form request"), ErrorMetaData{Method: request.Method, URL: cioURL}}
	}

	// oAuth signature
	var client oauth.Client
	client.Credentials = oauth.Credentials{Token: cio.apiKey, Secret: cio.apiSecret}

	// Add headers
	httpReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	httpReq.Header.Set("Accept", "application/json")
	httpReq.Header.Set("Accept-Charset", "utf-8")
	httpReq.Header.Set("User-Agent", "Golang CIO Library")
	httpReq.Header.Set("Authorization", client.AuthorizationHeader(nil, request.Method, httpReq.URL, bodyValues))

	return httpReq, nil
}

// sendRequest sends the *http.Request, and returns the status code, the response body, and any error
func (cio Cio) sendRequest(httpReq *http.Request, result interface{}, cioURL string) (int, string, error) {
	// Create the HTTP client
	httpClient := &http.Client{
		Transport: http.DefaultTransport,
		Timeout:   cio.RequestTimeout,
	}

	// Make the request
	res, err := httpClient.Do(httpReq)
	if err != nil {
		return 0, "", RequestError{errors.Wrap(err, "CIO: Failed to make request"), ErrorMetaData{Method: httpReq.Method, URL: cioURL}}
	}

	// Parse the response
	defer func() {
		if closeErr := res.Body.Close(); closeErr != nil && cio.ResponseBodyCloseErrorHook != nil {
			cio.ResponseBodyCloseErrorHook(closeErr) // Logging
		}
	}()

	resBody, err := ioutil.ReadAll(res.Body)
	resBodyString := string(resBody)
	if err != nil {
		return res.StatusCode, resBodyString, RequestError{errors.Wrap(err, "CIO: Could not read response"), ErrorMetaData{Method: httpReq.Method, URL: cioURL, StatusCode: res.StatusCode, Payload: resBodyString}}
	}

	// Unmarshal result
	err = json.Unmarshal(resBody, &result)

	// Return own error if Status Code >= 400
	if res.StatusCode >= 400 {
		return res.StatusCode, resBodyString, RequestError{errors.New("CIO: Status Code >= 400"), ErrorMetaData{Method: httpReq.Method, URL: cioURL, StatusCode: res.StatusCode, Payload: resBodyString}}
	}

	// Return Unmarshal error (if any) if Status Code is < 400
	if err != nil {
		return res.StatusCode, resBodyString, RequestError{errors.Wrap(err, "CIO: Could not unmarshal payload"), ErrorMetaData{Method: httpReq.Method, URL: cioURL, StatusCode: res.StatusCode, Payload: resBodyString}}
	}
	return res.StatusCode, resBodyString, nil
}

// redactBodyValues returns a copy of the body values redacted
func redactBodyValues(bodyValues url.Values) url.Values {

	// Copy url.Values
	redactedValues := url.Values{}
	for k, v := range bodyValues {
		redactedValues[k] = v
	}

	// Redact sensitive information
	if val := redactedValues.Get("password"); len(val) > 0 {
		redactedValues.Set("password", "redacted")
	}
	if val := redactedValues.Get("provider_refresh_token"); len(val) > 0 {
		redactedValues.Set("provider_refresh_token", "redacted")
	}
	if val := redactedValues.Get("provider_consumer_key"); len(val) > 0 {
		redactedValues.Set("provider_consumer_key", "redacted")
	}
	if val := redactedValues.Get("provider_consumer_secret"); len(val) > 0 {
		redactedValues.Set("provider_consumer_secret", "redacted")
	}

	return redactedValues
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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 render

import (
	"bytes"
	"fmt"
	"io"
	"path"
	"sort"
	"strconv"
	"strings"

	"github.com/googlecodelabs/tools/claat/types"
)

// MD renders nodes as markdown for the target env.
func MD(env string, nodes ...types.Node) (string, error) {
	var buf bytes.Buffer
	if err := WriteMD(&buf, env, nodes...); err != nil {
		return "", err
	}
	return buf.String(), nil
}

// WriteMD does the same as MD but outputs rendered markup to w.
func WriteMD(w io.Writer, env string, nodes ...types.Node) error {
	mw := mdWriter{w: w, env: env}
	return mw.write(nodes...)
}

type mdWriter struct {
	w         io.Writer // output writer
	env       string    // target environment
	err       error     // error during any writeXxx methods
	lineStart bool
}

func (mw *mdWriter) writeBytes(b []byte) {
	if mw.err != nil {
		return
	}
	mw.lineStart = len(b) > 0 && b[len(b)-1] == '\n'
	_, mw.err = mw.w.Write(b)
}

func (mw *mdWriter) writeString(s string) {
	mw.writeBytes([]byte(s))
}

func (mw *mdWriter) space() {
	if !mw.lineStart {
		mw.writeString(" ")
	}
}

func (mw *mdWriter) newBlock() {
	if !mw.lineStart {
		mw.writeBytes(newLine)
	}
	mw.writeBytes(newLine)
}

func (mw *mdWriter) matchEnv(v []string) bool {
	if len(v) == 0 || mw.env == "" {
		return true
	}
	i := sort.SearchStrings(v, mw.env)
	return i < len(v) && v[i] == mw.env
}

func (mw *mdWriter) write(nodes ...types.Node) error {
	for _, n := range nodes {
		if !mw.matchEnv(n.Env()) {
			continue
		}
		switch n := n.(type) {
		case *types.TextNode:
			mw.text(n)
		case *types.ImageNode:
			mw.image(n)
		case *types.URLNode:
			mw.url(n)
		case *types.ButtonNode:
			mw.write(n.Content.Nodes...)
		case *types.CodeNode:
			mw.code(n)
		case *types.ListNode:
			mw.list(n)
		case *types.ImportNode:
			if len(n.Content.Nodes) == 0 {
				break
			}
			mw.write(n.Content.Nodes...)
		case *types.ItemsListNode:
			mw.itemsList(n)
		//case *types.GridNode:
		//	mw.grid(n)
		case *types.InfoboxNode:
			mw.infobox(n)
		//case *types.SurveyNode:
		//	mw.survey(n)
		case *types.HeaderNode:
			mw.header(n)
		case *types.YouTubeNode:
			mw.youtube(n)
		}
		if mw.err != nil {
			return mw.err
		}
	}
	return nil
}

func (mw *mdWriter) text(n *types.TextNode) {
	if n.Bold {
		mw.writeString("**")
	}
	if n.Italic {
		mw.writeString(" *")
	}
	if n.Code {
		mw.writeString("`")
	}
	mw.writeString(n.Value)
	if n.Code {
		mw.writeString("`")
	}
	if n.Italic {
		mw.writeString("* ")
	}
	if n.Bold {
		mw.writeString("**")
	}
}

func (mw *mdWriter) image(n *types.ImageNode) {
	mw.space()
	mw.writeString(" 0 {
		mw.writeString(fmt.Sprintf(" width=\"%.2f\" ", n.Width))
	}

	mw.writeString("/>")
}

func (mw *mdWriter) url(n *types.URLNode) {
	mw.space()
	if n.URL != "" {
		mw.writeString("[")
	}
	for _, cn := range n.Content.Nodes {
		if t, ok := cn.(*types.TextNode); ok {
			mw.writeString(t.Value)
		}
	}
	if n.URL != "" {
		mw.writeString("](")
		mw.writeString(n.URL)
		mw.writeString(")")
	}
}

func (mw *mdWriter) code(n *types.CodeNode) {
	mw.newBlock()
	defer mw.writeBytes(newLine)
	if n.Term {
		var buf bytes.Buffer
		const prefix = "    "
		lineStart := true
		for _, r := range n.Value {
			if lineStart {
				buf.WriteString(prefix)
			}
			buf.WriteRune(r)
			lineStart = r == '\n'
		}
		mw.writeBytes(buf.Bytes())
		return
	}
	mw.writeString("```")
	mw.writeString(n.Lang)
	mw.writeBytes(newLine)
	mw.writeString(n.Value)
	if !mw.lineStart {
		mw.writeBytes(newLine)
	}
	mw.writeString("```")
}

func (mw *mdWriter) list(n *types.ListNode) {
	if n.Block() == true {
		mw.newBlock()
	}
	mw.write(n.Nodes...)
	if !mw.lineStart {
		mw.writeBytes(newLine)
	}
}

func (mw *mdWriter) itemsList(n *types.ItemsListNode) {
	mw.newBlock()
	for i, item := range n.Items {
		s := "* "
		if n.Type() == types.NodeItemsList && n.Start > 0 {
			s = strconv.Itoa(i+n.Start) + ". "
		}
		mw.writeString(s)
		mw.write(item.Nodes...)
		if !mw.lineStart {
			mw.writeBytes(newLine)
		}
	}
}

func (mw *mdWriter) infobox(n *types.InfoboxNode) {
	// TODO: This should use the "detail item" syntax so that it can be pure MD and not HTML
	// kind
	// : <content>
	//
	// The main issue is that when you do write(n.Content.Nodes...) it always adds two newlines
	// at the beginning. This is because the gdoc parser parses info boxes as a list node
	// followed by a text node, and the list node is an md block unto itself, resulting in two
	// newlines being added to the output before the text.
	mw.newBlock()
	mw.writeString(`<aside class="`)
	class := "positive"
	if n.Kind == types.InfoboxNegative {
		class = "negative"
	}
	mw.writeString(class)
	mw.writeString(`">`)
	mw.write(n.Content.Nodes...)
	mw.writeString("")
}

func (mw *mdWriter) header(n *types.HeaderNode) {
	mw.newBlock()
	mw.writeString(strings.Repeat("#", n.Level+1))
	mw.writeString(" ")
	mw.write(n.Content.Nodes...)
	if !mw.lineStart {
		mw.writeBytes(newLine)
	}
}

func (mw *mdWriter) youtube(n *types.YouTubeNode) {
	mw.newBlock()
	mw.writeString(fmt.Sprintf(`<video id="%s"></video>`, n.VideoID))
}
<commit_msg>Fixes incorrect markdown button rendering.<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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 render

import (
	"bytes"
	"fmt"
	"io"
	"path"
	"sort"
	"strconv"
	"strings"

	"github.com/googlecodelabs/tools/claat/types"
)

// MD renders nodes as markdown for the target env.
func MD(env string, nodes ...types.Node) (string, error) {
	var buf bytes.Buffer
	if err := WriteMD(&buf, env, nodes...); err != nil {
		return "", err
	}
	return buf.String(), nil
}

// WriteMD does the same as MD but outputs rendered markup to w.
func WriteMD(w io.Writer, env string, nodes ...types.Node) error {
	mw := mdWriter{w: w, env: env}
	return mw.write(nodes...)
}

type mdWriter struct {
	w         io.Writer // output writer
	env       string    // target environment
	err       error     // error during any writeXxx methods
	lineStart bool
}

func (mw *mdWriter) writeBytes(b []byte) {
	if mw.err != nil {
		return
	}
	mw.lineStart = len(b) > 0 && b[len(b)-1] == '\n'
	_, mw.err = mw.w.Write(b)
}

func (mw *mdWriter) writeString(s string) {
	mw.writeBytes([]byte(s))
}

func (mw *mdWriter) space() {
	if !mw.lineStart {
		mw.writeString(" ")
	}
}

func (mw *mdWriter) newBlock() {
	if !mw.lineStart {
		mw.writeBytes(newLine)
	}
	mw.writeBytes(newLine)
}

func (mw *mdWriter) matchEnv(v []string) bool {
	if len(v) == 0 || mw.env == "" {
		return true
	}
	i := sort.SearchStrings(v, mw.env)
	return i < len(v) && v[i] == mw.env
}

func (mw *mdWriter) write(nodes ...types.Node) error {
	for _, n := range nodes {
		if !mw.matchEnv(n.Env()) {
			continue
		}
		switch n := n.(type) {
		case *types.TextNode:
			mw.text(n)
		case *types.ImageNode:
			mw.image(n)
		case *types.URLNode:
			mw.url(n)
		case *types.ButtonNode:
			mw.write(n.Content.Nodes...)
		case *types.CodeNode:
			mw.code(n)
		case *types.ListNode:
			mw.list(n)
		case *types.ImportNode:
			if len(n.Content.Nodes) == 0 {
				break
			}
			mw.write(n.Content.Nodes...)
		case *types.ItemsListNode:
			mw.itemsList(n)
		//case *types.GridNode:
		//	mw.grid(n)
		case *types.InfoboxNode:
			mw.infobox(n)
		//case *types.SurveyNode:
		//	mw.survey(n)
		case *types.HeaderNode:
			mw.header(n)
		case *types.YouTubeNode:
			mw.youtube(n)
		}
		if mw.err != nil {
			return mw.err
		}
	}
	return nil
}

func (mw *mdWriter) text(n *types.TextNode) {
	if n.Bold {
		mw.writeString("**")
	}
	if n.Italic {
		mw.writeString(" *")
	}
	if n.Code {
		mw.writeString("`")
	}
	mw.writeString(n.Value)
	if n.Code {
		mw.writeString("`")
	}
	if n.Italic {
		mw.writeString("* ")
	}
	if n.Bold {
		mw.writeString("**")
	}
}

func (mw *mdWriter) image(n *types.ImageNode) {
	mw.space()
	mw.writeString(" 0 {
		mw.writeString(fmt.Sprintf(" width=\"%.2f\" ", n.Width))
	}

	mw.writeString("/>")
}

func (mw *mdWriter) url(n *types.URLNode) {
	mw.space()
	if n.URL != "" {
		// Look-ahead for button syntax.
		if _, ok := n.Content.Nodes[0].(*types.ButtonNode); ok {
			mw.writeString("<button>")
		}
		mw.writeString("[")
	}
	mw.write(n.Content.Nodes...)
	if n.URL != "" {
		mw.writeString("](")
		mw.writeString(n.URL)
		mw.writeString(")")
		if _, ok := n.Content.Nodes[0].(*types.ButtonNode); ok {
			// Look-ahead for button syntax.
			mw.writeString("</button>")
		}
	}
}

func (mw *mdWriter) code(n *types.CodeNode) {
	mw.newBlock()
	defer mw.writeBytes(newLine)
	if n.Term {
		var buf bytes.Buffer
		const prefix = "    "
		lineStart := true
		for _, r := range n.Value {
			if lineStart {
				buf.WriteString(prefix)
			}
			buf.WriteRune(r)
			lineStart = r == '\n'
		}
		mw.writeBytes(buf.Bytes())
		return
	}
	mw.writeString("```")
	mw.writeString(n.Lang)
	mw.writeBytes(newLine)
	mw.writeString(n.Value)
	if !mw.lineStart {
		mw.writeBytes(newLine)
	}
	mw.writeString("```")
}

func (mw *mdWriter) list(n *types.ListNode) {
	if n.Block() == true {
		mw.newBlock()
	}
	mw.write(n.Nodes...)
	if !mw.lineStart {
		mw.writeBytes(newLine)
	}
}

func (mw *mdWriter) itemsList(n *types.ItemsListNode) {
	mw.newBlock()
	for i, item := range n.Items {
		s := "* "
		if n.Type() == types.NodeItemsList && n.Start > 0 {
			s = strconv.Itoa(i+n.Start) + ". "
		}
		mw.writeString(s)
		mw.write(item.Nodes...)
		if !mw.lineStart {
			mw.writeBytes(newLine)
		}
	}
}

func (mw *mdWriter) infobox(n *types.InfoboxNode) {
	// TODO: This should use the "detail item" syntax so that it can be pure MD and not HTML
	// kind
	// : <content>
	//
	// The main issue is that when you do write(n.Content.Nodes...) it always adds two newlines
	// at the beginning. This is because the gdoc parser parses info boxes as a list node
	// followed by a text node, and the list node is an md block unto itself, resulting in two
	// newlines being added to the output before the text.
	mw.newBlock()
	mw.writeString(`<aside class="`)
	class := "positive"
	if n.Kind == types.InfoboxNegative {
		class = "negative"
	}
	mw.writeString(class)
	mw.writeString(`">`)
	mw.write(n.Content.Nodes...)
	mw.writeString("")
}

func (mw *mdWriter) header(n *types.HeaderNode) {
	mw.newBlock()
	mw.writeString(strings.Repeat("#", n.Level+1))
	mw.writeString(" ")
	mw.write(n.Content.Nodes...)
	if !mw.lineStart {
		mw.writeBytes(newLine)
	}
}

func (mw *mdWriter) youtube(n *types.YouTubeNode) {
	mw.newBlock()
	mw.writeString(fmt.Sprintf(`<video id="%s"></video>`, n.VideoID))
}
<|endoftext|>


<commit_before>/*
   Copyright 2014 Outbrain 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 sqlutils

import (
	"database/sql"
	"errors"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/outbrain/golib/log"
	"strconv"
	"strings"
)

// RowMap represents one row in a result set. Its objective is to allow
// for easy, typed getters by column name.
type RowMap map[string]sql.NullString

// RowData is the result of a single row, in positioned array format
type RowData []sql.NullString

// ResultData is an ordered row set of RowData
type ResultData []RowData

var EmptyResultData = ResultData{}

func (this *RowMap) GetString(key string) string {
	return (*this)[key].String
}

func (this *RowMap) GetInt64(key string) int64 {
	res, _ := strconv.ParseInt(this.GetString(key), 10, 0)
	return res
}

func (this *RowMap) GetNullInt64(key string) sql.NullInt64 {
	i, err := strconv.ParseInt(this.GetString(key), 10, 0)
	if err == nil {
		return sql.NullInt64{Int64: i, Valid: true}
	} else {
		return sql.NullInt64{Valid: false}
	}
}

func (this *RowMap) GetInt(key string) int {
	res, _ := strconv.Atoi(this.GetString(key))
	return res
}

func (this *RowMap) GetIntD(key string, def int) int {
	res, err := strconv.Atoi(this.GetString(key))
	if err != nil {
		return def
	}
	return res
}

func (this *RowMap) GetUint(key string) uint {
	res, _ := strconv.Atoi(this.GetString(key))
	return uint(res)
}

func (this *RowMap) GetBool(key string) bool {
	return this.GetInt(key) != 0
}

// knownDBs is a DB cache by uri
var knownDBs map[string]*sql.DB = make(map[string]*sql.DB)

// GetDB returns a DB instance based on uri.
// bool result indicates whether the DB was returned from cache; err
func GetDB(mysql_uri string) (*sql.DB, bool, error) {

	var exists bool
	if _, exists = knownDBs[mysql_uri]; !exists {
		if db, err := sql.Open("mysql", mysql_uri); err == nil {
			knownDBs[mysql_uri] = db
		} else {
			return db, exists, err
		}
	}
	return knownDBs[mysql_uri], exists, nil
}

// RowToArray is a convenience function, typically not called directly, which maps a
// single read database row into a NullString
func RowToArray(rows *sql.Rows, columns []string) []sql.NullString {
	buff := make([]interface{}, len(columns))
	data := make([]sql.NullString, len(columns))
	for i, _ := range buff {
		buff[i] = &data[i]
	}
	rows.Scan(buff...)
	return data
}

// ScanRowsToArrays is a convenience function, typically not called directly, which maps rows
// already read from the databse into arrays of NullString
func ScanRowsToArrays(rows *sql.Rows, on_row func([]sql.NullString) error) error {
	columns, _ := rows.Columns()
	for rows.Next() {
		arr := RowToArray(rows, columns)

		err := on_row(arr)
		if err != nil {
			return err
		}
	}
	return nil
}

// ScanRowsToMaps is a convenience function, typically not called directly, which maps rows
// already read from the databse into RowMap entries.
func ScanRowsToMaps(rows *sql.Rows, on_row func(RowMap) error) error {
	columns, _ := rows.Columns()
	err := ScanRowsToArrays(rows, func(arr []sql.NullString) error {
		m := make(map[string]sql.NullString)
		for k, data_col := range arr {
			m[columns[k]] = data_col
		}
		err := on_row(m)
		if err != nil {
			return err
		}
		return nil
	})
	return err
}

// QueryRowsMap is a convenience function allowing querying a result set while poviding a callback
// function activated per read row.
func QueryRowsMap(db *sql.DB, query string, on_row func(RowMap) error) error {
	var err error
	defer func() {
		if derr := recover(); derr != nil {
			err = errors.New(fmt.Sprintf("QueryRowsMap unexpected error: %+v", derr))
		}
	}()

	rows, err := db.Query(query)
	defer rows.Close()
	if err != nil && err != sql.ErrNoRows {
		return log.Errore(err)
	}
	err = ScanRowsToMaps(rows, on_row)
	return err
}

// QueryResultData returns a raw array of rows
func QueryResultData(db *sql.DB, query string) (ResultData, error) {
	var err error
	defer func() {
		if derr := recover(); derr != nil {
			err = errors.New(fmt.Sprintf("QueryRowsMap unexpected error: %+v", derr))
		}
	}()

	rows, err := db.Query(query)
	defer rows.Close()
	if err != nil && err != sql.ErrNoRows {
		return EmptyResultData, log.Errore(err)
	}
	resultData := ResultData{}
	err = ScanRowsToArrays(rows, func(rowData []sql.NullString) error {
		resultData = append(resultData, rowData)
		return nil
	})
	return resultData, err
}

// ExecQuery executes given query using given args on given DB. It will safele prepare, execute and close
// the statement.
func execInternal(silent bool, db *sql.DB, query string, args ...interface{}) (sql.Result, error) {
	var err error
	defer func() {
		if derr := recover(); derr != nil {
			err = errors.New(fmt.Sprintf("QueryRowsMap unexpected error: %+v", derr))
		}
	}()

	stmt, err := db.Prepare(query)
	if err != nil {
		return nil, err
	}
	defer stmt.Close()
	var res sql.Result
	res, err = stmt.Exec(args...)
	if err != nil && !silent {
		log.Errore(err)
	}
	return res, err
}

// Exec executes given query using given args on given DB. It will safele prepare, execute and close
// the statement.
func Exec(db *sql.DB, query string, args ...interface{}) (sql.Result, error) {
	return execInternal(false, db, query, args...)
}

// ExecSilently acts like Exec but does not report any error
func ExecSilently(db *sql.DB, query string, args ...interface{}) (sql.Result, error) {
	return execInternal(true, db, query, args...)
}

func InClauseStringValues(terms []string) string {
	quoted := []string{}
	for _, s := range terms {
		quoted = append(quoted, fmt.Sprintf("'%s'", strings.Replace(s, ",", "''", -1)))
	}
	return strings.Join(quoted, ", ")
}
<commit_msg>Added CellData, added JSON marshalling<commit_after>/*
   Copyright 2014 Outbrain 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 sqlutils

import (
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/outbrain/golib/log"
	"strconv"
	"strings"
)

// RowMap represents one row in a result set. Its objective is to allow
// for easy, typed getters by column name.
type RowMap map[string]sql.NullString

// Cell data is the result of a single (atomic) column in a single row
type CellData sql.NullString

//
func (this *CellData) MarshalJSON() ([]byte, error) {
	if this.Valid {
		return json.Marshal(this.String)
	} else {
		return json.Marshal(nil)
	}
}

// RowData is the result of a single row, in positioned array format
type RowData []sql.NullString

// ResultData is an ordered row set of RowData
type ResultData []RowData

var EmptyResultData = ResultData{}

func (this *RowMap) GetString(key string) string {
	return (*this)[key].String
}

func (this *RowMap) GetInt64(key string) int64 {
	res, _ := strconv.ParseInt(this.GetString(key), 10, 0)
	return res
}

func (this *RowMap) GetNullInt64(key string) sql.NullInt64 {
	i, err := strconv.ParseInt(this.GetString(key), 10, 0)
	if err == nil {
		return sql.NullInt64{Int64: i, Valid: true}
	} else {
		return sql.NullInt64{Valid: false}
	}
}

func (this *RowMap) GetInt(key string) int {
	res, _ := strconv.Atoi(this.GetString(key))
	return res
}

func (this *RowMap) GetIntD(key string, def int) int {
	res, err := strconv.Atoi(this.GetString(key))
	if err != nil {
		return def
	}
	return res
}

func (this *RowMap) GetUint(key string) uint {
	res, _ := strconv.Atoi(this.GetString(key))
	return uint(res)
}

func (this *RowMap) GetBool(key string) bool {
	return this.GetInt(key) != 0
}

// knownDBs is a DB cache by uri
var knownDBs map[string]*sql.DB = make(map[string]*sql.DB)

// GetDB returns a DB instance based on uri.
// bool result indicates whether the DB was returned from cache; err
func GetDB(mysql_uri string) (*sql.DB, bool, error) {

	var exists bool
	if _, exists = knownDBs[mysql_uri]; !exists {
		if db, err := sql.Open("mysql", mysql_uri); err == nil {
			knownDBs[mysql_uri] = db
		} else {
			return db, exists, err
		}
	}
	return knownDBs[mysql_uri], exists, nil
}

// RowToArray is a convenience function, typically not called directly, which maps a
// single read database row into a NullString
func RowToArray(rows *sql.Rows, columns []string) []sql.NullString {
	buff := make([]interface{}, len(columns))
	data := make([]sql.NullString, len(columns))
	for i, _ := range buff {
		buff[i] = &data[i]
	}
	rows.Scan(buff...)
	return data
}

// ScanRowsToArrays is a convenience function, typically not called directly, which maps rows
// already read from the databse into arrays of NullString
func ScanRowsToArrays(rows *sql.Rows, on_row func([]sql.NullString) error) error {
	columns, _ := rows.Columns()
	for rows.Next() {
		arr := RowToArray(rows, columns)

		err := on_row(arr)
		if err != nil {
			return err
		}
	}
	return nil
}

// ScanRowsToMaps is a convenience function, typically not called directly, which maps rows
// already read from the databse into RowMap entries.
func ScanRowsToMaps(rows *sql.Rows, on_row func(RowMap) error) error {
	columns, _ := rows.Columns()
	err := ScanRowsToArrays(rows, func(arr []sql.NullString) error {
		m := make(map[string]sql.NullString)
		for k, data_col := range arr {
			m[columns[k]] = data_col
		}
		err := on_row(m)
		if err != nil {
			return err
		}
		return nil
	})
	return err
}

// QueryRowsMap is a convenience function allowing querying a result set while poviding a callback
// function activated per read row.
func QueryRowsMap(db *sql.DB, query string, on_row func(RowMap) error) error {
	var err error
	defer func() {
		if derr := recover(); derr != nil {
			err = errors.New(fmt.Sprintf("QueryRowsMap unexpected error: %+v", derr))
		}
	}()

	rows, err := db.Query(query)
	defer rows.Close()
	if err != nil && err != sql.ErrNoRows {
		return log.Errore(err)
	}
	err = ScanRowsToMaps(rows, on_row)
	return err
}

// QueryResultData returns a raw array of rows
func QueryResultData(db *sql.DB, query string) (ResultData, error) {
	var err error
	defer func() {
		if derr := recover(); derr != nil {
			err = errors.New(fmt.Sprintf("QueryRowsMap unexpected error: %+v", derr))
		}
	}()

	rows, err := db.Query(query)
	defer rows.Close()
	if err != nil && err != sql.ErrNoRows {
		return EmptyResultData, log.Errore(err)
	}
	resultData := ResultData{}
	err = ScanRowsToArrays(rows, func(rowData []sql.NullString) error {
		resultData = append(resultData, rowData)
		return nil
	})
	return resultData, err
}

// ExecQuery executes given query using given args on given DB. It will safele prepare, execute and close
// the statement.
func execInternal(silent bool, db *sql.DB, query string, args ...interface{}) (sql.Result, error) {
	var err error
	defer func() {
		if derr := recover(); derr != nil {
			err = errors.New(fmt.Sprintf("QueryRowsMap unexpected error: %+v", derr))
		}
	}()

	stmt, err := db.Prepare(query)
	if err != nil {
		return nil, err
	}
	defer stmt.Close()
	var res sql.Result
	res, err = stmt.Exec(args...)
	if err != nil && !silent {
		log.Errore(err)
	}
	return res, err
}

// Exec executes given query using given args on given DB. It will safele prepare, execute and close
// the statement.
func Exec(db *sql.DB, query string, args ...interface{}) (sql.Result, error) {
	return execInternal(false, db, query, args...)
}

// ExecSilently acts like Exec but does not report any error
func ExecSilently(db *sql.DB, query string, args ...interface{}) (sql.Result, error) {
	return execInternal(true, db, query, args...)
}

func InClauseStringValues(terms []string) string {
	quoted := []string{}
	for _, s := range terms {
		quoted = append(quoted, fmt.Sprintf("'%s'", strings.Replace(s, ",", "''", -1)))
	}
	return strings.Join(quoted, ", ")
}
<|endoftext|>


<commit_before>// +build linux

package unshare

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"runtime"
	"strconv"
	"strings"
	"syscall"

	"github.com/containers/buildah/util"
	"github.com/containers/storage/pkg/reexec"
	"github.com/opencontainers/runtime-spec/specs-go"
	"github.com/pkg/errors"
)

// Cmd wraps an exec.Cmd created by the reexec package in unshare(), and
// handles setting ID maps and other related settings by triggering
// initialization code in the child.
type Cmd struct {
	*exec.Cmd
	UnshareFlags               int
	UseNewuidmap               bool
	UidMappings                []specs.LinuxIDMapping
	UseNewgidmap               bool
	GidMappings                []specs.LinuxIDMapping
	GidMappingsEnableSetgroups bool
	Setsid                     bool
	Setpgrp                    bool
	Ctty                       *os.File
	OOMScoreAdj                *int
	Hook                       func(pid int) error
}

// Command creates a new Cmd which can be customized.
func Command(args ...string) *Cmd {
	cmd := reexec.Command(args...)
	return &Cmd{
		Cmd: cmd,
	}
}

func (c *Cmd) Start() error {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	// Set an environment variable to tell the child to synchronize its startup.
	if c.Env == nil {
		c.Env = os.Environ()
	}
	c.Env = append(c.Env, fmt.Sprintf("_Buildah-unshare=%d", c.UnshareFlags))

	// Please the libpod "rootless" package to find the expected env variables.
	c.Env = append(c.Env, "_LIBPOD_USERNS_CONFIGURED=done")
	c.Env = append(c.Env, fmt.Sprintf("_LIBPOD_ROOTLESS_UID=%d", os.Geteuid()))

	// Create the pipe for reading the child's PID.
	pidRead, pidWrite, err := os.Pipe()
	if err != nil {
		return errors.Wrapf(err, "error creating pid pipe")
	}
	c.Env = append(c.Env, fmt.Sprintf("_Buildah-pid-pipe=%d", len(c.ExtraFiles)+3))
	c.ExtraFiles = append(c.ExtraFiles, pidWrite)

	// Create the pipe for letting the child know to proceed.
	continueRead, continueWrite, err := os.Pipe()
	if err != nil {
		pidRead.Close()
		pidWrite.Close()
		return errors.Wrapf(err, "error creating pid pipe")
	}
	c.Env = append(c.Env, fmt.Sprintf("_Buildah-continue-pipe=%d", len(c.ExtraFiles)+3))
	c.ExtraFiles = append(c.ExtraFiles, continueRead)

	// Pass along other instructions.
	if c.Setsid {
		c.Env = append(c.Env, "_Buildah-setsid=1")
	}
	if c.Setpgrp {
		c.Env = append(c.Env, "_Buildah-setpgrp=1")
	}
	if c.Ctty != nil {
		c.Env = append(c.Env, fmt.Sprintf("_Buildah-ctty=%d", len(c.ExtraFiles)+3))
		c.ExtraFiles = append(c.ExtraFiles, c.Ctty)
	}

	// Make sure we clean up our pipes.
	defer func() {
		if pidRead != nil {
			pidRead.Close()
		}
		if pidWrite != nil {
			pidWrite.Close()
		}
		if continueRead != nil {
			continueRead.Close()
		}
		if continueWrite != nil {
			continueWrite.Close()
		}
	}()

	// Start the new process.
	err = c.Cmd.Start()
	if err != nil {
		return err
	}

	// Close the ends of the pipes that the parent doesn't need.
	continueRead.Close()
	continueRead = nil
	pidWrite.Close()
	pidWrite = nil

	// Read the child's PID from the pipe.
	pidString := ""
	b := new(bytes.Buffer)
	io.Copy(b, pidRead)
	pidString = b.String()
	pid, err := strconv.Atoi(pidString)
	if err != nil {
		fmt.Fprintf(continueWrite, "error parsing PID %q: %v", pidString, err)
		return errors.Wrapf(err, "error parsing PID %q", pidString)
	}
	pidString = fmt.Sprintf("%d", pid)

	// If we created a new user namespace, set any specified mappings.
	if c.UnshareFlags&syscall.CLONE_NEWUSER != 0 {
		// Always set "setgroups".
		setgroups, err := os.OpenFile(fmt.Sprintf("/proc/%s/setgroups", pidString), os.O_TRUNC|os.O_WRONLY, 0)
		if err != nil {
			fmt.Fprintf(continueWrite, "error opening setgroups: %v", err)
			return errors.Wrapf(err, "error opening /proc/%s/setgroups", pidString)
		}
		defer setgroups.Close()
		if c.GidMappingsEnableSetgroups {
			if _, err := fmt.Fprintf(setgroups, "allow"); err != nil {
				fmt.Fprintf(continueWrite, "error writing \"allow\" to setgroups: %v", err)
				return errors.Wrapf(err, "error opening \"allow\" to /proc/%s/setgroups", pidString)
			}
		} else {
			if _, err := fmt.Fprintf(setgroups, "deny"); err != nil {
				fmt.Fprintf(continueWrite, "error writing \"deny\" to setgroups: %v", err)
				return errors.Wrapf(err, "error writing \"deny\" to /proc/%s/setgroups", pidString)
			}
		}

		if len(c.UidMappings) == 0 || len(c.GidMappings) == 0 {
			uidmap, gidmap, err := util.GetHostIDMappings("")
			if err != nil {
				fmt.Fprintf(continueWrite, "error reading ID mappings in parent: %v", err)
				return errors.Wrapf(err, "error reading ID mappings in parent")
			}
			if len(c.UidMappings) == 0 {
				c.UidMappings = uidmap
				for i := range c.UidMappings {
					c.UidMappings[i].HostID = c.UidMappings[i].ContainerID
				}
			}
			if len(c.GidMappings) == 0 {
				c.GidMappings = gidmap
				for i := range c.GidMappings {
					c.GidMappings[i].HostID = c.GidMappings[i].ContainerID
				}
			}
		}

		if len(c.GidMappings) > 0 {
			// Build the GID map, since writing to the proc file has to be done all at once.
			g := new(bytes.Buffer)
			for _, m := range c.GidMappings {
				fmt.Fprintf(g, "%d %d %d\n", m.ContainerID, m.HostID, m.Size)
			}
			// Set the GID map.
			if c.UseNewgidmap {
				cmd := exec.Command("newgidmap", append([]string{pidString}, strings.Fields(strings.Replace(g.String(), "\n", " ", -1))...)...)
				g.Reset()
				cmd.Stdout = g
				cmd.Stderr = g
				err := cmd.Run()
				if err != nil {
					fmt.Fprintf(continueWrite, "error running newgidmap: %v: %s", err, g.String())
					return errors.Wrapf(err, "error running newgidmap: %s", g.String())
				}
			} else {
				gidmap, err := os.OpenFile(fmt.Sprintf("/proc/%s/gid_map", pidString), os.O_TRUNC|os.O_WRONLY, 0)
				if err != nil {
					fmt.Fprintf(continueWrite, "error opening /proc/%s/gid_map: %v", pidString, err)
					return errors.Wrapf(err, "error opening /proc/%s/gid_map", pidString)
				}
				defer gidmap.Close()
				if _, err := fmt.Fprintf(gidmap, "%s", g.String()); err != nil {
					fmt.Fprintf(continueWrite, "error writing %q to /proc/%s/gid_map: %v", g.String(), pidString, err)
					return errors.Wrapf(err, "error writing %q to /proc/%s/gid_map", g.String(), pidString)
				}
			}
		}

		if len(c.UidMappings) > 0 {
			// Build the UID map, since writing to the proc file has to be done all at once.
			u := new(bytes.Buffer)
			for _, m := range c.UidMappings {
				fmt.Fprintf(u, "%d %d %d\n", m.ContainerID, m.HostID, m.Size)
			}
			// Set the GID map.
			if c.UseNewuidmap {
				cmd := exec.Command("newuidmap", append([]string{pidString}, strings.Fields(strings.Replace(u.String(), "\n", " ", -1))...)...)
				u.Reset()
				cmd.Stdout = u
				cmd.Stderr = u
				err := cmd.Run()
				if err != nil {
					fmt.Fprintf(continueWrite, "error running newuidmap: %v: %s", err, u.String())
					return errors.Wrapf(err, "error running newuidmap: %s", u.String())
				}
			} else {
				uidmap, err := os.OpenFile(fmt.Sprintf("/proc/%s/uid_map", pidString), os.O_TRUNC|os.O_WRONLY, 0)
				if err != nil {
					fmt.Fprintf(continueWrite, "error opening /proc/%s/uid_map: %v", pidString, err)
					return errors.Wrapf(err, "error opening /proc/%s/uid_map", pidString)
				}
				defer uidmap.Close()
				if _, err := fmt.Fprintf(uidmap, "%s", u.String()); err != nil {
					fmt.Fprintf(continueWrite, "error writing %q to /proc/%s/uid_map: %v", u.String(), pidString, err)
					return errors.Wrapf(err, "error writing %q to /proc/%s/uid_map", u.String(), pidString)
				}
			}
		}
	}

	if c.OOMScoreAdj != nil {
		oomScoreAdj, err := os.OpenFile(fmt.Sprintf("/proc/%s/oom_score_adj", pidString), os.O_TRUNC|os.O_WRONLY, 0)
		if err != nil {
			fmt.Fprintf(continueWrite, "error opening oom_score_adj: %v", err)
			return errors.Wrapf(err, "error opening /proc/%s/oom_score_adj", pidString)
		}
		defer oomScoreAdj.Close()
		if _, err := fmt.Fprintf(oomScoreAdj, "%d\n", *c.OOMScoreAdj); err != nil {
			fmt.Fprintf(continueWrite, "error writing \"%d\" to oom_score_adj: %v", c.OOMScoreAdj, err)
			return errors.Wrapf(err, "error writing \"%d\" to /proc/%s/oom_score_adj", c.OOMScoreAdj, pidString)
		}
	}
	// Run any additional setup that we want to do before the child starts running proper.
	if c.Hook != nil {
		if err = c.Hook(pid); err != nil {
			fmt.Fprintf(continueWrite, "hook error: %v", err)
			return err
		}
	}

	return nil
}

func (c *Cmd) Run() error {
	if err := c.Start(); err != nil {
		return err
	}
	return c.Wait()
}

func (c *Cmd) CombinedOutput() ([]byte, error) {
	return nil, errors.New("unshare: CombinedOutput() not implemented")
}

func (c *Cmd) Output() ([]byte, error) {
	return nil, errors.New("unshare: Output() not implemented")
}
<commit_msg>unshare: do not set rootless mode if euid=0<commit_after>// +build linux

package unshare

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"runtime"
	"strconv"
	"strings"
	"syscall"

	"github.com/containers/buildah/util"
	"github.com/containers/storage/pkg/reexec"
	"github.com/opencontainers/runtime-spec/specs-go"
	"github.com/pkg/errors"
)

// Cmd wraps an exec.Cmd created by the reexec package in unshare(), and
// handles setting ID maps and other related settings by triggering
// initialization code in the child.
type Cmd struct {
	*exec.Cmd
	UnshareFlags               int
	UseNewuidmap               bool
	UidMappings                []specs.LinuxIDMapping
	UseNewgidmap               bool
	GidMappings                []specs.LinuxIDMapping
	GidMappingsEnableSetgroups bool
	Setsid                     bool
	Setpgrp                    bool
	Ctty                       *os.File
	OOMScoreAdj                *int
	Hook                       func(pid int) error
}

// Command creates a new Cmd which can be customized.
func Command(args ...string) *Cmd {
	cmd := reexec.Command(args...)
	return &Cmd{
		Cmd: cmd,
	}
}

func (c *Cmd) Start() error {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	// Set an environment variable to tell the child to synchronize its startup.
	if c.Env == nil {
		c.Env = os.Environ()
	}
	c.Env = append(c.Env, fmt.Sprintf("_Buildah-unshare=%d", c.UnshareFlags))

	// Please the libpod "rootless" package to find the expected env variables.
	if os.Geteuid() != 0 {
		c.Env = append(c.Env, "_LIBPOD_USERNS_CONFIGURED=done")
		c.Env = append(c.Env, fmt.Sprintf("_LIBPOD_ROOTLESS_UID=%d", os.Geteuid()))
	}

	// Create the pipe for reading the child's PID.
	pidRead, pidWrite, err := os.Pipe()
	if err != nil {
		return errors.Wrapf(err, "error creating pid pipe")
	}
	c.Env = append(c.Env, fmt.Sprintf("_Buildah-pid-pipe=%d", len(c.ExtraFiles)+3))
	c.ExtraFiles = append(c.ExtraFiles, pidWrite)

	// Create the pipe for letting the child know to proceed.
	continueRead, continueWrite, err := os.Pipe()
	if err != nil {
		pidRead.Close()
		pidWrite.Close()
		return errors.Wrapf(err, "error creating pid pipe")
	}
	c.Env = append(c.Env, fmt.Sprintf("_Buildah-continue-pipe=%d", len(c.ExtraFiles)+3))
	c.ExtraFiles = append(c.ExtraFiles, continueRead)

	// Pass along other instructions.
	if c.Setsid {
		c.Env = append(c.Env, "_Buildah-setsid=1")
	}
	if c.Setpgrp {
		c.Env = append(c.Env, "_Buildah-setpgrp=1")
	}
	if c.Ctty != nil {
		c.Env = append(c.Env, fmt.Sprintf("_Buildah-ctty=%d", len(c.ExtraFiles)+3))
		c.ExtraFiles = append(c.ExtraFiles, c.Ctty)
	}

	// Make sure we clean up our pipes.
	defer func() {
		if pidRead != nil {
			pidRead.Close()
		}
		if pidWrite != nil {
			pidWrite.Close()
		}
		if continueRead != nil {
			continueRead.Close()
		}
		if continueWrite != nil {
			continueWrite.Close()
		}
	}()

	// Start the new process.
	err = c.Cmd.Start()
	if err != nil {
		return err
	}

	// Close the ends of the pipes that the parent doesn't need.
	continueRead.Close()
	continueRead = nil
	pidWrite.Close()
	pidWrite = nil

	// Read the child's PID from the pipe.
	pidString := ""
	b := new(bytes.Buffer)
	io.Copy(b, pidRead)
	pidString = b.String()
	pid, err := strconv.Atoi(pidString)
	if err != nil {
		fmt.Fprintf(continueWrite, "error parsing PID %q: %v", pidString, err)
		return errors.Wrapf(err, "error parsing PID %q", pidString)
	}
	pidString = fmt.Sprintf("%d", pid)

	// If we created a new user namespace, set any specified mappings.
	if c.UnshareFlags&syscall.CLONE_NEWUSER != 0 {
		// Always set "setgroups".
		setgroups, err := os.OpenFile(fmt.Sprintf("/proc/%s/setgroups", pidString), os.O_TRUNC|os.O_WRONLY, 0)
		if err != nil {
			fmt.Fprintf(continueWrite, "error opening setgroups: %v", err)
			return errors.Wrapf(err, "error opening /proc/%s/setgroups", pidString)
		}
		defer setgroups.Close()
		if c.GidMappingsEnableSetgroups {
			if _, err := fmt.Fprintf(setgroups, "allow"); err != nil {
				fmt.Fprintf(continueWrite, "error writing \"allow\" to setgroups: %v", err)
				return errors.Wrapf(err, "error opening \"allow\" to /proc/%s/setgroups", pidString)
			}
		} else {
			if _, err := fmt.Fprintf(setgroups, "deny"); err != nil {
				fmt.Fprintf(continueWrite, "error writing \"deny\" to setgroups: %v", err)
				return errors.Wrapf(err, "error writing \"deny\" to /proc/%s/setgroups", pidString)
			}
		}

		if len(c.UidMappings) == 0 || len(c.GidMappings) == 0 {
			uidmap, gidmap, err := util.GetHostIDMappings("")
			if err != nil {
				fmt.Fprintf(continueWrite, "error reading ID mappings in parent: %v", err)
				return errors.Wrapf(err, "error reading ID mappings in parent")
			}
			if len(c.UidMappings) == 0 {
				c.UidMappings = uidmap
				for i := range c.UidMappings {
					c.UidMappings[i].HostID = c.UidMappings[i].ContainerID
				}
			}
			if len(c.GidMappings) == 0 {
				c.GidMappings = gidmap
				for i := range c.GidMappings {
					c.GidMappings[i].HostID = c.GidMappings[i].ContainerID
				}
			}
		}

		if len(c.GidMappings) > 0 {
			// Build the GID map, since writing to the proc file has to be done all at once.
			g := new(bytes.Buffer)
			for _, m := range c.GidMappings {
				fmt.Fprintf(g, "%d %d %d\n", m.ContainerID, m.HostID, m.Size)
			}
			// Set the GID map.
			if c.UseNewgidmap {
				cmd := exec.Command("newgidmap", append([]string{pidString}, strings.Fields(strings.Replace(g.String(), "\n", " ", -1))...)...)
				g.Reset()
				cmd.Stdout = g
				cmd.Stderr = g
				err := cmd.Run()
				if err != nil {
					fmt.Fprintf(continueWrite, "error running newgidmap: %v: %s", err, g.String())
					return errors.Wrapf(err, "error running newgidmap: %s", g.String())
				}
			} else {
				gidmap, err := os.OpenFile(fmt.Sprintf("/proc/%s/gid_map", pidString), os.O_TRUNC|os.O_WRONLY, 0)
				if err != nil {
					fmt.Fprintf(continueWrite, "error opening /proc/%s/gid_map: %v", pidString, err)
					return errors.Wrapf(err, "error opening /proc/%s/gid_map", pidString)
				}
				defer gidmap.Close()
				if _, err := fmt.Fprintf(gidmap, "%s", g.String()); err != nil {
					fmt.Fprintf(continueWrite, "error writing %q to /proc/%s/gid_map: %v", g.String(), pidString, err)
					return errors.Wrapf(err, "error writing %q to /proc/%s/gid_map", g.String(), pidString)
				}
			}
		}

		if len(c.UidMappings) > 0 {
			// Build the UID map, since writing to the proc file has to be done all at once.
			u := new(bytes.Buffer)
			for _, m := range c.UidMappings {
				fmt.Fprintf(u, "%d %d %d\n", m.ContainerID, m.HostID, m.Size)
			}
			// Set the GID map.
			if c.UseNewuidmap {
				cmd := exec.Command("newuidmap", append([]string{pidString}, strings.Fields(strings.Replace(u.String(), "\n", " ", -1))...)...)
				u.Reset()
				cmd.Stdout = u
				cmd.Stderr = u
				err := cmd.Run()
				if err != nil {
					fmt.Fprintf(continueWrite, "error running newuidmap: %v: %s", err, u.String())
					return errors.Wrapf(err, "error running newuidmap: %s", u.String())
				}
			} else {
				uidmap, err := os.OpenFile(fmt.Sprintf("/proc/%s/uid_map", pidString), os.O_TRUNC|os.O_WRONLY, 0)
				if err != nil {
					fmt.Fprintf(continueWrite, "error opening /proc/%s/uid_map: %v", pidString, err)
					return errors.Wrapf(err, "error opening /proc/%s/uid_map", pidString)
				}
				defer uidmap.Close()
				if _, err := fmt.Fprintf(uidmap, "%s", u.String()); err != nil {
					fmt.Fprintf(continueWrite, "error writing %q to /proc/%s/uid_map: %v", u.String(), pidString, err)
					return errors.Wrapf(err, "error writing %q to /proc/%s/uid_map", u.String(), pidString)
				}
			}
		}
	}

	if c.OOMScoreAdj != nil {
		oomScoreAdj, err := os.OpenFile(fmt.Sprintf("/proc/%s/oom_score_adj", pidString), os.O_TRUNC|os.O_WRONLY, 0)
		if err != nil {
			fmt.Fprintf(continueWrite, "error opening oom_score_adj: %v", err)
			return errors.Wrapf(err, "error opening /proc/%s/oom_score_adj", pidString)
		}
		defer oomScoreAdj.Close()
		if _, err := fmt.Fprintf(oomScoreAdj, "%d\n", *c.OOMScoreAdj); err != nil {
			fmt.Fprintf(continueWrite, "error writing \"%d\" to oom_score_adj: %v", c.OOMScoreAdj, err)
			return errors.Wrapf(err, "error writing \"%d\" to /proc/%s/oom_score_adj", c.OOMScoreAdj, pidString)
		}
	}
	// Run any additional setup that we want to do before the child starts running proper.
	if c.Hook != nil {
		if err = c.Hook(pid); err != nil {
			fmt.Fprintf(continueWrite, "hook error: %v", err)
			return err
		}
	}

	return nil
}

func (c *Cmd) Run() error {
	if err := c.Start(); err != nil {
		return err
	}
	return c.Wait()
}

func (c *Cmd) CombinedOutput() ([]byte, error) {
	return nil, errors.New("unshare: CombinedOutput() not implemented")
}

func (c *Cmd) Output() ([]byte, error) {
	return nil, errors.New("unshare: Output() not implemented")
}
<|endoftext|>


<commit_before>// Copyright 2015 Intuit, Inc.  All rights reserved.
// Use of this source code is governed the MIT license
// that can be found in the LICENSE file.

package amicache

import (
	"context"
	"net/http"
	"reflect"
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
	"github.com/aws/aws-sdk-go/service/sts"
	"github.com/aws/aws-sdk-go/service/sts/stsiface"
	"github.com/go-kit/kit/log"
)

// mockSTSClient mock.
type mockSTSClient struct {
	stsiface.STSAPI

	// Callbacks for API endpoints. Add more as needed.
	// The default implementations return empty values and nil errors.
	assumeRole func(*sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error)
}

// AssumeRole mock.
func (m *mockSTSClient) AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) {
	if m.assumeRole == nil {
		return &sts.AssumeRoleOutput{}, nil
	}
	return m.assumeRole(input)
}

// mockEC2Client mock.
type mockEC2Client struct {
	ec2iface.EC2API

	// Callbacks for API endpoints. Add more as needed.
	// The default implementations return empty values and nil errors.
	describeImages         func(*ec2.DescribeImagesInput) (*ec2.DescribeImagesOutput, error)
	describeImageAttribute func(*ec2.DescribeImageAttributeInput) (*ec2.DescribeImageAttributeOutput, error)
}

// DescribeImages mock.
func (m *mockEC2Client) DescribeImages(input *ec2.DescribeImagesInput) (*ec2.DescribeImagesOutput, error) {
	if m.describeImages == nil {
		return &ec2.DescribeImagesOutput{}, nil
	}
	return m.describeImages(input)
}

// DescribeImageAttribute mock.
func (m *mockEC2Client) DescribeImageAttribute(input *ec2.DescribeImageAttributeInput) (*ec2.DescribeImageAttributeOutput, error) {
	if m.describeImageAttribute == nil {
		return &ec2.DescribeImageAttributeOutput{}, nil
	}
	return m.describeImageAttribute(input)
}

// Creates a new cache with a single AMI.
func newMockCache(opts ...Option) *Cache {
	svc := &mockSTSClient{
		assumeRole: func(*sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) {
			return &sts.AssumeRoleOutput{
				Credentials: &sts.Credentials{
					AccessKeyId:     aws.String("foo"),
					SecretAccessKey: aws.String("bar"),
					SessionToken:    aws.String("baz"),
				},
			}, nil
		},
	}

	c := New(svc, "foo", []string{"111122223333"}, opts...)

	c.ec2Svc = func(*session.Session, string, int) ec2iface.EC2API {
		return &mockEC2Client{
			describeImages: func(*ec2.DescribeImagesInput) (*ec2.DescribeImagesOutput, error) {
				return &ec2.DescribeImagesOutput{
					Images: []*ec2.Image{
						{
							Name:               aws.String("test-ami-1"),
							Description:        aws.String("Test AMI 1"),
							VirtualizationType: aws.String("hvm"),
							CreationDate:       aws.String("2017-11-29T16:00:00.000Z"),
							ImageId:            aws.String("ami-1a2b3c4d"),
							Tags: []*ec2.Tag{{
								Key:   aws.String(StateTag),
								Value: aws.String("available"),
							}},
						},
					},
				}, nil
			},
			describeImageAttribute: func(*ec2.DescribeImageAttributeInput) (*ec2.DescribeImageAttributeOutput, error) {
				return &ec2.DescribeImageAttributeOutput{
					LaunchPermissions: []*ec2.LaunchPermission{
						{UserId: aws.String("111111111111")},
						{UserId: aws.String("111111111112")},
					},
				}, nil
			},
		}
	}

	return c
}

func TestCacheOptions(t *testing.T) {
	c := New(
		nil,
		"foo",
		[]string{"foo"},
		Regions("us-west-1"),
		TTL(15*time.Minute),
		MaxConcurrentRequests(1),
		MaxRequestRetries(1),
		HTTPClient(http.DefaultClient),
		Logger(log.NewNopLogger()),
	)

	if want, got := map[string]struct{}{"us-west-1": struct{}{}}, c.regions; !reflect.DeepEqual(want, got) {
		t.Errorf("Bad Regions Map - want: %v, got: %v", want, got)
	}

	if want, got := []string{"us-west-1"}, c.Regions(); !reflect.DeepEqual(want, got) {
		t.Errorf("Bad Regions Slice - want: %v, got: %v", want, got)
	}

	if want, got := 15*time.Minute, c.ttl; want != got {
		t.Errorf("Bad TTL - want: %s, got: %s", want, got)
	}

	if want, got := 1, c.maxRequests; want != got {
		t.Errorf("Bad MaxConcurrentRequests - want: %d, got: %d", want, got)
	}

	if want, got := 1, c.maxRetries; want != got {
		t.Errorf("Bad MaxRequestRetries - want: %d, got: %d", want, got)
	}

	if want, got := http.DefaultClient, c.httpClient; want != got {
		t.Errorf("Bad HTTPClient - want: %v, got: %v", want, got)
	}

	if want, got := log.NewNopLogger(), c.logger; want != got {
		t.Errorf("Bad Logger - want: %T, got: %T", want, got)
	}
}

func TestMinTTL(t *testing.T) {
	c := New(nil, "foo", []string{"foo"}, TTL(time.Second))
	if want, got := minCacheTTL, c.ttl; want != got {
		t.Errorf("want: %s, got: %s", want, got)
	}
}

func TestCacheIsRunning(t *testing.T) {
	c := newMockCache()

	go func() { c.Run(context.Background()) }()

	<-c.Warmed()

	if want, got := true, c.isRunning(); want != got {
		t.Errorf("want: %t, got: %t", want, got)
	}

	if want, got := errCacheRunning, c.Run(context.Background()); want != got {
		t.Errorf("want: %v, got: %v", want, got)
	}

	c.Stop()

	if want, got := false, c.isRunning(); want != got {
		t.Errorf("want: %t, got: %t", want, got)
	}
}

func TestCacheStopped(t *testing.T) {
	c := newMockCache()
	errCh := make(chan error)

	go func() { errCh <- c.Run(context.Background()) }()

	<-c.Warmed()
	c.Stop()

	if want, got := errCacheStopped, <-errCh; want != got {
		t.Errorf("want: %s, got: %s", want, got)
	}
}

func TestCacheContextCanceled(t *testing.T) {
	c := newMockCache()
	errCh := make(chan error)
	ctx, cancel := context.WithCancel(context.Background())

	go func() { errCh <- c.Run(ctx) }()

	<-c.Warmed()
	cancel()

	if want, got := context.Canceled, <-errCh; want != got {
		t.Errorf("want: %s, got: %s", want, got)
	}
}

func TestImages(t *testing.T) {
	c := newMockCache(Regions("us-west-1"))
	defer c.Stop()

	go func() { c.Run(context.Background()) }()

	<-c.Warmed()

	images, err := c.Images("us-west-1")
	if err != nil {
		t.Fatal(err)
	}

	if want, got := 1, len(images); want != got {
		t.Errorf("want: %d image(s), got: %d image(s)", want, got)
	}

	if want, got := 2, len(images[0].launchPerms); want != got {
		t.Errorf("want: %d perms, got: %d perms", want, got)
	}

	_, err = c.Images("us-foo-1")

	if want, got := "unknown or unsupported region: us-foo-1", err.Error(); want != got {
		t.Errorf("\n\twant err: %q\n\t got err: %q", want, got)
	}
}

func TestFilteredImages(t *testing.T) {
	c := newMockCache(Regions("us-west-1"))
	defer c.Stop()

	go func() { c.Run(context.Background()) }()

	<-c.Warmed()

	images, err := c.FilterImages("us-west-1", NewFilter(FilterByImageID("ami-1a2b3c4d")))
	if err != nil {
		t.Fatal(err)
	}

	if want, got := 1, len(images); want != got {
		t.Errorf("want: %d image(s), got: %d image(s)", want, got)
	}

	images, err = c.FilterImages("us-west-1", NewFilter(FilterByImageID("foo")))
	if err != nil {
		t.Fatal(err)
	}

	if want, got := 0, len(images); want != got {
		t.Errorf("want: %d image(s), got: %d image(s)", want, got)
	}

	_, err = c.FilterImages("us-foo-1", nil)

	if want, got := "unknown or unsupported region: us-foo-1", err.Error(); want != got {
		t.Errorf("\n\twant err: %q\n\t got err: %q", want, got)
	}
}

func TestPoolSize(t *testing.T) {
	tests := []struct {
		name    string
		max     int
		queue   int
		percent float64
		want    int
	}{
		{"min_workers", 10, 1, 0.05, 1},
		{"2_workers", 10, 42, 0.05, 2},
		{"5_workers", 10, 108, 0.05, 5},
		{"max_workers", 2, 1000, 0.05, 2},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := poolSize(tt.max, tt.queue, tt.percent); tt.want != got {
				t.Errorf("want: %d, got: %d", tt.want, got)
			}
		})
	}
}
<commit_msg>amicache/cache_test: Added TestAWSError<commit_after>// Copyright 2015 Intuit, Inc.  All rights reserved.
// Use of this source code is governed the MIT license
// that can be found in the LICENSE file.

package amicache

import (
	"context"
	"errors"
	"net/http"
	"reflect"
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
	"github.com/aws/aws-sdk-go/service/sts"
	"github.com/aws/aws-sdk-go/service/sts/stsiface"
	"github.com/go-kit/kit/log"
)

// mockSTSClient mock.
type mockSTSClient struct {
	stsiface.STSAPI

	// Callbacks for API endpoints. Add more as needed.
	// The default implementations return empty values and nil errors.
	assumeRole func(*sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error)
}

// AssumeRole mock.
func (m *mockSTSClient) AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) {
	if m.assumeRole == nil {
		return &sts.AssumeRoleOutput{}, nil
	}
	return m.assumeRole(input)
}

// mockEC2Client mock.
type mockEC2Client struct {
	ec2iface.EC2API

	// Callbacks for API endpoints. Add more as needed.
	// The default implementations return empty values and nil errors.
	describeImages         func(*ec2.DescribeImagesInput) (*ec2.DescribeImagesOutput, error)
	describeImageAttribute func(*ec2.DescribeImageAttributeInput) (*ec2.DescribeImageAttributeOutput, error)
}

// DescribeImages mock.
func (m *mockEC2Client) DescribeImages(input *ec2.DescribeImagesInput) (*ec2.DescribeImagesOutput, error) {
	if m.describeImages == nil {
		return &ec2.DescribeImagesOutput{}, nil
	}
	return m.describeImages(input)
}

// DescribeImageAttribute mock.
func (m *mockEC2Client) DescribeImageAttribute(input *ec2.DescribeImageAttributeInput) (*ec2.DescribeImageAttributeOutput, error) {
	if m.describeImageAttribute == nil {
		return &ec2.DescribeImageAttributeOutput{}, nil
	}
	return m.describeImageAttribute(input)
}

// Creates a new cache with a single AMI.
func newMockCache(opts ...Option) *Cache {
	svc := &mockSTSClient{
		assumeRole: func(*sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) {
			return &sts.AssumeRoleOutput{
				Credentials: &sts.Credentials{
					AccessKeyId:     aws.String("foo"),
					SecretAccessKey: aws.String("bar"),
					SessionToken:    aws.String("baz"),
				},
			}, nil
		},
	}

	c := New(svc, "foo", []string{"111122223333"}, opts...)

	c.ec2Svc = func(*session.Session, string, int) ec2iface.EC2API {
		return &mockEC2Client{
			describeImages: func(*ec2.DescribeImagesInput) (*ec2.DescribeImagesOutput, error) {
				return &ec2.DescribeImagesOutput{
					Images: []*ec2.Image{
						{
							Name:               aws.String("test-ami-1"),
							Description:        aws.String("Test AMI 1"),
							VirtualizationType: aws.String("hvm"),
							CreationDate:       aws.String("2017-11-29T16:00:00.000Z"),
							ImageId:            aws.String("ami-1a2b3c4d"),
							Tags: []*ec2.Tag{{
								Key:   aws.String(StateTag),
								Value: aws.String("available"),
							}},
						},
					},
				}, nil
			},
			describeImageAttribute: func(*ec2.DescribeImageAttributeInput) (*ec2.DescribeImageAttributeOutput, error) {
				return &ec2.DescribeImageAttributeOutput{
					LaunchPermissions: []*ec2.LaunchPermission{
						{UserId: aws.String("111111111111")},
						{UserId: aws.String("111111111112")},
					},
				}, nil
			},
		}
	}

	return c
}

func TestCacheOptions(t *testing.T) {
	c := New(
		nil,
		"foo",
		[]string{"foo"},
		Regions("us-west-1"),
		TTL(15*time.Minute),
		MaxConcurrentRequests(1),
		MaxRequestRetries(1),
		HTTPClient(http.DefaultClient),
		Logger(log.NewNopLogger()),
	)

	if want, got := map[string]struct{}{"us-west-1": struct{}{}}, c.regions; !reflect.DeepEqual(want, got) {
		t.Errorf("Bad Regions Map - want: %v, got: %v", want, got)
	}

	if want, got := []string{"us-west-1"}, c.Regions(); !reflect.DeepEqual(want, got) {
		t.Errorf("Bad Regions Slice - want: %v, got: %v", want, got)
	}

	if want, got := 15*time.Minute, c.ttl; want != got {
		t.Errorf("Bad TTL - want: %s, got: %s", want, got)
	}

	if want, got := 1, c.maxRequests; want != got {
		t.Errorf("Bad MaxConcurrentRequests - want: %d, got: %d", want, got)
	}

	if want, got := 1, c.maxRetries; want != got {
		t.Errorf("Bad MaxRequestRetries - want: %d, got: %d", want, got)
	}

	if want, got := http.DefaultClient, c.httpClient; want != got {
		t.Errorf("Bad HTTPClient - want: %v, got: %v", want, got)
	}

	if want, got := log.NewNopLogger(), c.logger; want != got {
		t.Errorf("Bad Logger - want: %T, got: %T", want, got)
	}
}

func TestMinTTL(t *testing.T) {
	c := New(nil, "foo", []string{"foo"}, TTL(time.Second))
	if want, got := minCacheTTL, c.ttl; want != got {
		t.Errorf("want: %s, got: %s", want, got)
	}
}

func TestCacheIsRunning(t *testing.T) {
	c := newMockCache()

	go func() { c.Run(context.Background()) }()

	<-c.Warmed()

	if want, got := true, c.isRunning(); want != got {
		t.Errorf("want: %t, got: %t", want, got)
	}

	if want, got := errCacheRunning, c.Run(context.Background()); want != got {
		t.Errorf("want: %v, got: %v", want, got)
	}

	c.Stop()

	if want, got := false, c.isRunning(); want != got {
		t.Errorf("want: %t, got: %t", want, got)
	}
}

func TestCacheStopped(t *testing.T) {
	c := newMockCache()
	errCh := make(chan error)

	go func() { errCh <- c.Run(context.Background()) }()

	<-c.Warmed()
	c.Stop()

	if want, got := errCacheStopped, <-errCh; want != got {
		t.Errorf("want: %s, got: %s", want, got)
	}
}

func TestCacheContextCanceled(t *testing.T) {
	c := newMockCache()
	errCh := make(chan error)
	ctx, cancel := context.WithCancel(context.Background())

	go func() { errCh <- c.Run(ctx) }()

	<-c.Warmed()
	cancel()

	if want, got := context.Canceled, <-errCh; want != got {
		t.Errorf("want: %s, got: %s", want, got)
	}
}

func TestImages(t *testing.T) {
	c := newMockCache(Regions("us-west-1"))
	defer c.Stop()

	go func() { c.Run(context.Background()) }()

	<-c.Warmed()

	images, err := c.Images("us-west-1")
	if err != nil {
		t.Fatal(err)
	}

	if want, got := 1, len(images); want != got {
		t.Errorf("want: %d image(s), got: %d image(s)", want, got)
	}

	if want, got := 2, len(images[0].launchPerms); want != got {
		t.Errorf("want: %d perms, got: %d perms", want, got)
	}

	_, err = c.Images("us-foo-1")

	if want, got := "unknown or unsupported region: us-foo-1", err.Error(); want != got {
		t.Errorf("\n\twant err: %q\n\t got err: %q", want, got)
	}
}

func TestFilteredImages(t *testing.T) {
	c := newMockCache(Regions("us-west-1"))
	defer c.Stop()

	go func() { c.Run(context.Background()) }()

	<-c.Warmed()

	images, err := c.FilterImages("us-west-1", NewFilter(FilterByImageID("ami-1a2b3c4d")))
	if err != nil {
		t.Fatal(err)
	}

	if want, got := 1, len(images); want != got {
		t.Errorf("want: %d image(s), got: %d image(s)", want, got)
	}

	images, err = c.FilterImages("us-west-1", NewFilter(FilterByImageID("foo")))
	if err != nil {
		t.Fatal(err)
	}

	if want, got := 0, len(images); want != got {
		t.Errorf("want: %d image(s), got: %d image(s)", want, got)
	}

	_, err = c.FilterImages("us-foo-1", nil)

	if want, got := "unknown or unsupported region: us-foo-1", err.Error(); want != got {
		t.Errorf("\n\twant err: %q\n\t got err: %q", want, got)
	}
}

func TestPoolSize(t *testing.T) {
	tests := []struct {
		name    string
		max     int
		queue   int
		percent float64
		want    int
	}{
		{"min_workers", 10, 1, 0.05, 1},
		{"2_workers", 10, 42, 0.05, 2},
		{"5_workers", 10, 108, 0.05, 5},
		{"max_workers", 2, 1000, 0.05, 2},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := poolSize(tt.max, tt.queue, tt.percent); tt.want != got {
				t.Errorf("want: %d, got: %d", tt.want, got)
			}
		})
	}
}

type mockAWSErr struct{}

func (mockAWSErr) Error() string   { return "foo" }
func (mockAWSErr) Code() string    { return "42" }
func (mockAWSErr) Message() string { return "foobar" }
func (mockAWSErr) OrigErr() error  { return errors.New("o.g. foo") }

func TestAWSError(t *testing.T) {
	tests := []struct {
		name string
		err  error
		want string
	}{
		{"awsError", &mockAWSErr{}, "foobar"},
		{"error", errors.New("foobar"), "foobar"},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := awsError(tt.err).Error(); tt.want != got {
				t.Errorf("want: %v, got: %v", tt.want, got)
			}
		})
	}
}
<|endoftext|>


<commit_before>package plugins

import (
	"github.com/GeertJohan/go.rice/embedded"
	"time"
)

func init() {

	// define files
	file2 := &embedded.EmbeddedFile{
		Filename:    `hugo.js`,
		FileModTime: time.Unix(1501319450, 0),
		Content:     string("'use strict';\n\n(function () {\n  if (window.plugins === undefined || window.plugins === null) {\n    window.plugins = []\n  }\n\n  let regenerate = function (data, url) {\n    url = data.api.removePrefix(url)\n\n    return new Promise((resolve, reject) => {\n      let request = new window.XMLHttpRequest()\n      request.open('POST', `${data.store.state.baseURL}/api/hugo${url}`, true)\n      request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\n      request.setRequestHeader('Regenerate', 'true')\n\n      request.onload = () => {\n        if (request.status === 200) {\n          resolve()\n        } else {\n          reject(request.responseText)\n        }\n      }\n\n      request.onerror = (error) => reject(error)\n      request.send()\n    })\n  }\n\n  let newArchetype = function (data, url, type) {\n    url = data.api.removePrefix(url)\n\n    return new Promise((resolve, reject) => {\n      let request = new window.XMLHttpRequest()\n      request.open('POST', `${data.store.state.baseURL}/api/hugo${url}`, true)\n      request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\n      request.setRequestHeader('Archetype', encodeURIComponent(type))\n\n      request.onload = () => {\n        if (request.status === 200) {\n          resolve(request.getResponseHeader('Location'))\n        } else {\n          reject(request.responseText)\n        }\n      }\n\n      request.onerror = (error) => reject(error)\n      request.send()\n    })\n  }\n\n  let schedule = function (data, file, date) {\n    file = data.api.removePrefix(file)\n\n    return new Promise((resolve, reject) => {\n      let request = new window.XMLHttpRequest()\n      request.open('POST', `${data.store.state.baseURL}/api/hugo${file}`, true)\n      request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\n      request.setRequestHeader('Schedule', date)\n\n      request.onload = () => {\n        if (request.status === 200) {\n          resolve(request.getResponseHeader('Location'))\n        } else {\n          reject(request.responseText)\n        }\n      }\n\n      request.onerror = (error) => reject(error)\n      request.send()\n    })\n  }\n\n  window.plugins.push({\n    name: 'hugo',\n    credits: 'With a flavour of Hugo.',\n    header: {\n      visible: [\n        {\n          if: function (data, route) {\n            return (data.store.state.req.kind === 'editor' &&\n              !data.store.state.loading &&\n              data.store.state.user.allowEdit &\n              data.store.state.user.permissions.allowPublish)\n          },\n          click: function (event, data, route) {\n            event.preventDefault()\n            document.getElementById('save-button').click()\n            // TODO: wait for save to finish?\n            data.buttons.loading('publish')\n\n            regenerate(data, route.path)\n              .then(() => {\n                data.buttons.done('publish')\n                data.store.commit('showSuccess', 'Post published!')\n                data.store.commit('setReload', true)\n              })\n              .catch((error) => {\n                data.buttons.done('publish')\n                data.store.commit('showError', error)\n              })\n          },\n          id: 'publish-button',\n          icon: 'send',\n          name: 'Publish'\n        }\n      ],\n      hidden: [\n        {\n          if: function (data, route) {\n            return (data.store.state.req.kind === 'editor' &&\n              !data.store.state.loading &&\n              data.store.state.req.metadata !== undefined &&\n              data.store.state.req.metadata !== null &&\n              data.store.state.user.permissions.allowPublish)\n          },\n          click: function (event, data, route) {\n            document.getElementById('save-button').click()\n            data.store.commit('showHover', 'schedule')\n          },\n          id: 'schedule-button',\n          icon: 'alarm',\n          name: 'Schedule'\n        }\n      ]\n    },\n    sidebar: [\n      {\n        click: function (event, data, route) {\n          data.router.push({ path: '/files/settings' })\n        },\n        icon: 'settings',\n        name: 'Hugo Settings'\n      },\n      {\n        click: function (event, data, route) {\n          data.store.commit('showHover', 'new-archetype')\n        },\n        if: function (data, route) {\n          return data.store.state.user.allowNew\n        },\n        icon: 'merge_type',\n        name: 'Hugo New'\n      } /* ,\n      {\n        click: function (event, data, route) {\n          console.log('evt')\n        },\n        icon: 'remove_red_eye',\n        name: 'Preview'\n      } */\n    ],\n    prompts: [\n      {\n        name: 'new-archetype',\n        title: 'New file',\n        description: 'Create a new post based on an archetype. Your file will be created on content folder.',\n        inputs: [\n          {\n            type: 'text',\n            name: 'file',\n            placeholder: 'File name'\n          },\n          {\n            type: 'text',\n            name: 'archetype',\n            placeholder: 'Archetype'\n          }\n        ],\n        ok: 'Create',\n        submit: function (event, data, route) {\n          event.preventDefault()\n\n          let file = event.currentTarget.querySelector('[name=\"file\"]').value\n          let type = event.currentTarget.querySelector('[name=\"archetype\"]').value\n          if (type === '') type = 'default'\n\n          data.store.commit('closeHovers')\n\n          newArchetype(data, '/' + file, type)\n            .then((url) => {\n              data.router.push({ path: url })\n            })\n            .catch(error => {\n              data.store.commit('showError', error)\n            })\n        }\n      },\n      {\n        name: 'schedule',\n        title: 'Schedule',\n        description: 'Pick a date and time to schedule the publication of this post.',\n        inputs: [\n          {\n            type: 'datetime-local',\n            name: 'date',\n            placeholder: 'Date'\n          }\n        ],\n        ok: 'Schedule',\n        submit: function (event, data, route) {\n          event.preventDefault()\n          data.buttons.loading('schedule')\n\n          let date = event.currentTarget.querySelector('[name=\"date\"]').value\n          if (date === '') {\n            data.buttons.done('schedule')\n            data.store.commit('showError', 'The date must not be empty.')\n            return\n          }\n\n          schedule(data, route.path, date)\n            .then(() => {\n              data.buttons.done('schedule')\n              data.store.commit('showSuccess', 'Post scheduled!')\n            })\n            .catch((error) => {\n              data.buttons.done('schedule')\n              data.store.commit('showError', error)\n            })\n        }\n      }\n    ]\n  })\n})()\n"),
	}

	// define dirs
	dir1 := &embedded.EmbeddedDir{
		Filename:   ``,
		DirModTime: time.Unix(1501318911, 0),
		ChildFiles: []*embedded.EmbeddedFile{
			file2, // hugo.js

		},
	}

	// link ChildDirs
	dir1.ChildDirs = []*embedded.EmbeddedDir{}

	// register embeddedBox
	embedded.RegisterEmbeddedBox(`./assets/`, &embedded.EmbeddedBox{
		Name: `./assets/`,
		Time: time.Unix(1501318911, 0),
		Dirs: map[string]*embedded.EmbeddedDir{
			"": dir1,
		},
		Files: map[string]*embedded.EmbeddedFile{
			"hugo.js": file2,
		},
	})
}
<commit_msg>Deploy assets Sat Jul 29 14:28:14 GMTST 2017<commit_after><|endoftext|>


<commit_before><commit_msg>solve 451 by hashmap<commit_after><|endoftext|>