<commit_before>package s3meta

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"encoding/xml"
	"errors"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
	"time"
)

type Bucket struct {
	Name   string // "com-awesome-dev-bucket"
	Base   string // ".s3.amazonaws.com/"
	Key    string
	Secret string
}

func (b *Bucket) HeadS3ObjectResponse(key string) (*http.Response, error) {
	fullPath := "http://" + b.Name + b.Base + key
	req, err := http.NewRequest("HEAD", fullPath, nil)
	if err != nil {
		return &http.Response{}, err
	}

	resp, err := b.authDoRequest(req)

	return resp, err
}

func (b *Bucket) HeadS3Object(key string) (bl bool, err error) {
	bl = false
	resp, err := b.HeadS3ObjectResponse(key)
	if err != nil {
		return
	}

	defer resp.Body.Close()
	if resp.StatusCode == 404 {
		return
	}

	if resp.StatusCode != 200 {
		err = errors.New(resp.Status)
		return
	}

	bl = true

	return
}

func (b *Bucket) HeadS3ObjectWithMetaData(key string) (bl bool, data map[string]string, err error) {
	bl = false
	resp, err := b.HeadS3ObjectResponse(key)
	if err != nil {
		return
	}

	defer resp.Body.Close()
	if resp.StatusCode == 404 {
		return
	}

	if resp.StatusCode != 200 {
		err = errors.New(resp.Status)
		return
	}

	bl = true
	data = extractMetaDataFrom(resp.Header)

	return
}

func (b *Bucket) GetS3ObjectResponse(key string) (*http.Response, error) {
	fullPath := "http://" + b.Name + b.Base + key
	req, err := http.NewRequest("GET", fullPath, nil)
	if err != nil {
		return &http.Response{}, err
	}
	resp, err := b.authDoRequest(req)

	return resp, err
}

// GetS3Object Get object from s3 bucket
func (b *Bucket) GetS3Object(key string) (string, error) {
	resp, err := b.GetS3ObjectResponse(key)
	if err != nil {
		return "", err
	}

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

	if resp.StatusCode != 200 {
		return "", errors.New(string(body))
	}

	return string(body), nil
}

func (b *Bucket) GetS3ObjectWithMetaData(key string) (str string, data map[string]string, err error) {
	resp, err := b.GetS3ObjectResponse(key)
	if err != nil {
		return
	}

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

	if resp.StatusCode != 200 {
		err = errors.New(string(body))
		return
	}

	str = string(body)
	data = extractMetaDataFrom(resp.Header)

	return
}

func (b *Bucket) GetS3BucketResponse(prefix string) (*http.Response, error) {
	fullPath := "http://" + b.Name + b.Base + "?prefix=" + prefix
	req, err := http.NewRequest("GET", fullPath, nil)
	if err != nil {
		return &http.Response{}, err
	}
	resp, err := b.authDoRequest(req)

	return resp, err
}

type BucketItem struct {
	Key          string
	LastModified time.Time
	Body         string
}

type ListBucketResult struct {
	Contents []BucketItem
}

func (b *Bucket) GetS3Bucket(prefix string) (result *ListBucketResult, err error) {
	resp, err := b.GetS3BucketResponse(prefix)
	if err != nil {
		return
	}

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

	if resp.StatusCode != 200 {
		err = errors.New(string(body))
		return
	}

	result = &ListBucketResult{}

	err = xml.Unmarshal(body, result)
	if err != nil {
		return
	}

	return
}

func (b *Bucket) PutS3ObjectResponse(key string, body []byte) (*http.Response, error) {
	fullPath := "http://" + b.Name + b.Base + key
	req, err := http.NewRequest("PUT", fullPath, nil)
	if err != nil {
		return &http.Response{}, err
	}

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

	req.Body = ioutil.NopCloser(bytes.NewReader(body))
	req.ContentLength = int64(len(body))

	return b.authDoRequest(req)
}

// PutObject from s3 bucket
func (b *Bucket) PutS3Object(key string, bs []byte) error {
	resp, err := b.PutS3ObjectResponse(key, bs)
	if err != nil {
		return err
	}

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

	if resp.StatusCode != 200 {
		return errors.New(resp.Status + string(body))
	}

	return nil
}

func (b *Bucket) PutS3ObjectMetaDataResponse(key string, body []byte, data map[string]string) (*http.Response, error) {
	fullPath := "http://" + b.Name + b.Base + key
	req, err := http.NewRequest("PUT", fullPath, nil)
	if err != nil {
		return &http.Response{}, err
	}

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

	for k, v := range data {
		req.Header.Add("x-amz-meta-"+k, v)
	}

	req.Body = ioutil.NopCloser(bytes.NewReader(body))
	req.ContentLength = int64(len(body))

	return b.authDoRequest(req)
}

// PutObject from s3 bucket
func (b *Bucket) PutS3ObjectWithMetaData(key string, bs []byte, data map[string]string) error {
	resp, err := b.PutS3ObjectMetaDataResponse(key, bs, data)
	if err != nil {
		return err
	}

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

	if resp.StatusCode != 200 {
		return errors.New(resp.Status + string(body))
	}

	return nil
}

func (b *Bucket) authDoRequest(request *http.Request) (*http.Response, error) {
	b.authRequest(request)

	return http.DefaultClient.Do(request)
}

// http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#ConstructingTheAuthenticationHeader
func (b *Bucket) authRequest(request *http.Request) {
	if request.Header.Get("Date") == "" {
		date := time.Now().UTC().Format(time.RFC1123Z)
		request.Header.Add("Date", date)
	}

	// canonicalizedResource needs uri without query
	url := *request.URL
	url.RawQuery = ""
	uri := url.RequestURI()

	canonicalizedResource := strings.Join([]string{
		"/",
		b.Name,
		uri,
	}, "")

	stringToSign := strings.Join([]string{
		request.Method, "\n\n", // no MD5
		request.Header.Get("Content-Type"), "\n",
		request.Header.Get("Date"), "\n",
		canonicalizedAmzHeaders(request.Header),
		canonicalizedResource,
	}, "")

	h := hmac.New(sha1.New, []byte(b.Secret))
	h.Write([]byte(stringToSign))

	signature := base64.StdEncoding.EncodeToString(h.Sum([]byte{}))

	request.Header.Add("Host", "http://"+b.Name+b.Base)
	request.Header.Add("Authorization", "AWS "+b.Key+":"+signature)

	return
}

// http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationConstructingCanonicalizedAmzHeaders
func canonicalizedAmzHeaders(headers http.Header) string {
	var keys []string
	for k, _ := range headers {
		k_lower := strings.ToLower(k)
		if strings.HasPrefix(k_lower, "x-amz-") {
			keys = append(keys, k)
		}
	}

	sort.Strings(keys)
	var buffer bytes.Buffer

	for _, k := range keys {
		buffer.WriteString(strings.ToLower(k) + ":" + headers.Get(k) + "\n")
	}

	return buffer.String()
}

func extractMetaDataFrom(headers http.Header) map[string]string {
	data := make(map[string]string)

	for k, _ := range headers {
		k_lower := strings.ToLower(k)
		if strings.HasPrefix(k_lower, "x-amz-meta-") {
			key := strings.TrimPrefix(k_lower, "x-amz-meta-")
			data[key] = headers.Get(k)
		}
	}

	return data
}
<commit_msg>documentation<commit_after>// Package s3meta an interface to Amazon's Simple Storage Solution with
// a focus on User Defined Meta data
package s3meta

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"encoding/xml"
	"errors"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
	"time"
)

// Bucket is representation of an S3 bucket.
type Bucket struct {
  // Name is the bucket name
  // Example: "com-awesome-dev-bucket"
  Name   string

  // Base is the URL base for the region
  // Example: ".s3.amazonaws.com/"
  Base   string

  // S3 Key
	Key    string
  // S3 Secret
	Secret string
}

func (b *Bucket) HeadS3ObjectResponse(key string) (*http.Response, error) {
	fullPath := "http://" + b.Name + b.Base + key
	req, err := http.NewRequest("HEAD", fullPath, nil)
	if err != nil {
		return &http.Response{}, err
	}

	resp, err := b.authDoRequest(req)

	return resp, err
}

func (b *Bucket) HeadS3Object(key string) (bl bool, err error) {
	bl = false
	resp, err := b.HeadS3ObjectResponse(key)
	if err != nil {
		return
	}

	defer resp.Body.Close()
	if resp.StatusCode == 404 {
		return
	}

	if resp.StatusCode != 200 {
		err = errors.New(resp.Status)
		return
	}

	bl = true

	return
}

func (b *Bucket) HeadS3ObjectWithMetaData(key string) (bl bool, data map[string]string, err error) {
	bl = false
	resp, err := b.HeadS3ObjectResponse(key)
	if err != nil {
		return
	}

	defer resp.Body.Close()
	if resp.StatusCode == 404 {
		return
	}

	if resp.StatusCode != 200 {
		err = errors.New(resp.Status)
		return
	}

	bl = true
	data = extractMetaDataFrom(resp.Header)

	return
}

func (b *Bucket) GetS3ObjectResponse(key string) (*http.Response, error) {
	fullPath := "http://" + b.Name + b.Base + key
	req, err := http.NewRequest("GET", fullPath, nil)
	if err != nil {
		return &http.Response{}, err
	}
	resp, err := b.authDoRequest(req)

	return resp, err
}

// GetS3Object Get object from s3 bucket
func (b *Bucket) GetS3Object(key string) (string, error) {
	resp, err := b.GetS3ObjectResponse(key)
	if err != nil {
		return "", err
	}

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

	if resp.StatusCode != 200 {
		return "", errors.New(string(body))
	}

	return string(body), nil
}

func (b *Bucket) GetS3ObjectWithMetaData(key string) (str string, data map[string]string, err error) {
	resp, err := b.GetS3ObjectResponse(key)
	if err != nil {
		return
	}

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

	if resp.StatusCode != 200 {
		err = errors.New(string(body))
		return
	}

	str = string(body)
	data = extractMetaDataFrom(resp.Header)

	return
}

func (b *Bucket) ListS3BucketObjectsResponse(prefix string) (*http.Response, error) {
	fullPath := "http://" + b.Name + b.Base + "?prefix=" + prefix
	req, err := http.NewRequest("GET", fullPath, nil)
	if err != nil {
		return &http.Response{}, err
	}
	resp, err := b.authDoRequest(req)

	return resp, err
}

type BucketItem struct {
	Key          string
	LastModified time.Time
	Body         string
}

type ListBucketResult struct {
	Contents []BucketItem
}

func (b *Bucket) ListS3BucketObjects(prefix string) (result *ListBucketResult, err error) {
	resp, err := b.ListS3BucketObjectsResponse(prefix)
	if err != nil {
		return
	}

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

	if resp.StatusCode != 200 {
		err = errors.New(string(body))
		return
	}

	result = &ListBucketResult{}

	err = xml.Unmarshal(body, result)
	if err != nil {
		return
	}

	return
}

func (b *Bucket) PutS3ObjectResponse(key string, body []byte) (*http.Response, error) {
	fullPath := "http://" + b.Name + b.Base + key
	req, err := http.NewRequest("PUT", fullPath, nil)
	if err != nil {
		return &http.Response{}, err
	}

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

	req.Body = ioutil.NopCloser(bytes.NewReader(body))
	req.ContentLength = int64(len(body))

	return b.authDoRequest(req)
}

// PutObject from s3 bucket
func (b *Bucket) PutS3Object(key string, bs []byte) error {
	resp, err := b.PutS3ObjectResponse(key, bs)
	if err != nil {
		return err
	}

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

	if resp.StatusCode != 200 {
		return errors.New(resp.Status + string(body))
	}

	return nil
}

func (b *Bucket) PutS3ObjectMetaDataResponse(key string, body []byte, data map[string]string) (*http.Response, error) {
	fullPath := "http://" + b.Name + b.Base + key
	req, err := http.NewRequest("PUT", fullPath, nil)
	if err != nil {
		return &http.Response{}, err
	}

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

	for k, v := range data {
		req.Header.Add("x-amz-meta-"+k, v)
	}

	req.Body = ioutil.NopCloser(bytes.NewReader(body))
	req.ContentLength = int64(len(body))

	return b.authDoRequest(req)
}

// PutObject from s3 bucket
func (b *Bucket) PutS3ObjectWithMetaData(key string, bs []byte, data map[string]string) error {
	resp, err := b.PutS3ObjectMetaDataResponse(key, bs, data)
	if err != nil {
		return err
	}

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

	if resp.StatusCode != 200 {
		return errors.New(resp.Status + string(body))
	}

	return nil
}

func (b *Bucket) authDoRequest(request *http.Request) (*http.Response, error) {
	b.authRequest(request)

	return http.DefaultClient.Do(request)
}

// http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#ConstructingTheAuthenticationHeader
func (b *Bucket) authRequest(request *http.Request) {
	if request.Header.Get("Date") == "" {
		date := time.Now().UTC().Format(time.RFC1123Z)
		request.Header.Add("Date", date)
	}

	// canonicalizedResource needs uri without query
	url := *request.URL
	url.RawQuery = ""
	uri := url.RequestURI()

	canonicalizedResource := strings.Join([]string{
		"/",
		b.Name,
		uri,
	}, "")

	stringToSign := strings.Join([]string{
		request.Method, "\n\n", // no MD5
		request.Header.Get("Content-Type"), "\n",
		request.Header.Get("Date"), "\n",
		canonicalizedAmzHeaders(request.Header),
		canonicalizedResource,
	}, "")

	h := hmac.New(sha1.New, []byte(b.Secret))
	h.Write([]byte(stringToSign))

	signature := base64.StdEncoding.EncodeToString(h.Sum([]byte{}))

	request.Header.Add("Host", "http://"+b.Name+b.Base)
	request.Header.Add("Authorization", "AWS "+b.Key+":"+signature)

	return
}

// http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationConstructingCanonicalizedAmzHeaders
func canonicalizedAmzHeaders(headers http.Header) string {
	var keys []string
	for k, _ := range headers {
		k_lower := strings.ToLower(k)
		if strings.HasPrefix(k_lower, "x-amz-") {
			keys = append(keys, k)
		}
	}

	sort.Strings(keys)
	var buffer bytes.Buffer

	for _, k := range keys {
		buffer.WriteString(strings.ToLower(k) + ":" + headers.Get(k) + "\n")
	}

	return buffer.String()
}

func extractMetaDataFrom(headers http.Header) map[string]string {
	data := make(map[string]string)

	for k, _ := range headers {
		k_lower := strings.ToLower(k)
		if strings.HasPrefix(k_lower, "x-amz-meta-") {
			key := strings.TrimPrefix(k_lower, "x-amz-meta-")
			data[key] = headers.Get(k)
		}
	}

	return data
}
<|endoftext|>


<commit_before>// Copyright 2014 Rana Ian. All rights reserved.
// Use of this source code is governed by The MIT License
// found in the accompanying LICENSE file.

package ora

/*
#include <oci.h>
#include <stdlib.h>
*/
import "C"
import (
	"container/list"
)

// Tx represents an Oracle transaction associated with a session.
//
// Implements the driver.Tx interface.
type Tx struct {
	id   uint64
	ses  *Ses
	elem *list.Element
}

// checkIsOpen validates that the session is open.
func (tx *Tx) checkIsOpen() error {
	if tx.ses != nil {
		return errNewF("Tx is closed (id %v)", tx.id)
	}
	return nil
}

func (tx *Tx) close() {
	if tx.ses != nil {
		tx.ses.txs.Remove(tx.elem)
		tx.ses = nil
		tx.elem = nil
	}
}

// Commit commits the transaction.
//
// Commit is a member of the driver.Tx interface.
func (tx *Tx) Commit() (err error) {
	if tx.checkIsOpen(); err != nil {
		return err
	}
	defer tx.close()
	r := C.OCITransCommit(
		tx.ses.srv.ocisvcctx,  //OCISvcCtx    *svchp,
		tx.ses.srv.env.ocierr, //OCIError     *errhp,
		C.OCI_DEFAULT)         //ub4          flags );
	if r == C.OCI_ERROR {
		return tx.ses.srv.env.ociError()
	}
	return nil
}

// Rollback rolls back a transaction.
//
// Rollback is a member of the driver.Tx interface.
func (tx *Tx) Rollback() (err error) {
	if tx.checkIsOpen(); err != nil {
		return err
	}
	defer tx.close()
	r := C.OCITransRollback(
		tx.ses.srv.ocisvcctx,  //OCISvcCtx    *svchp,
		tx.ses.srv.env.ocierr, //OCIError     *errhp,
		C.OCI_DEFAULT)         //ub4          flags );
	if r == C.OCI_ERROR {
		return tx.ses.srv.env.ociError()
	}
	return nil
}
<commit_msg>tx.Rollback: recover from panic<commit_after>// Copyright 2014 Rana Ian. All rights reserved.
// Use of this source code is governed by The MIT License
// found in the accompanying LICENSE file.

package ora

/*
#include <oci.h>
#include <stdlib.h>
*/
import "C"
import (
	"container/list"
	"fmt"
)

// Tx represents an Oracle transaction associated with a session.
//
// Implements the driver.Tx interface.
type Tx struct {
	id   uint64
	ses  *Ses
	elem *list.Element
}

// checkIsOpen validates that the session is open.
func (tx *Tx) checkIsOpen() error {
	if tx.ses != nil {
		return errNewF("Tx is closed (id %v)", tx.id)
	}
	return nil
}

func (tx *Tx) close() {
	if tx.ses != nil {
		tx.ses.txs.Remove(tx.elem)
		tx.ses = nil
		tx.elem = nil
	}
}

// Commit commits the transaction.
//
// Commit is a member of the driver.Tx interface.
func (tx *Tx) Commit() (err error) {
	if tx.checkIsOpen(); err != nil {
		return err
	}
	defer tx.close()
	r := C.OCITransCommit(
		tx.ses.srv.ocisvcctx,  //OCISvcCtx    *svchp,
		tx.ses.srv.env.ocierr, //OCIError     *errhp,
		C.OCI_DEFAULT)         //ub4          flags );
	if r == C.OCI_ERROR {
		return tx.ses.srv.env.ociError()
	}
	return nil
}

// Rollback rolls back a transaction.
//
// Rollback is a member of the driver.Tx interface.
func (tx *Tx) Rollback() (err error) {
	defer func() {
		if r := recover(); r != nil && err == nil {
			err = fmt.Errorf("%v", r)
		}
	}()
	if tx.checkIsOpen(); err != nil {
		return err
	}
	defer tx.close()
	r := C.OCITransRollback(
		tx.ses.srv.ocisvcctx,  //OCISvcCtx    *svchp,
		tx.ses.srv.env.ocierr, //OCIError     *errhp,
		C.OCI_DEFAULT)         //ub4          flags );
	if r == C.OCI_ERROR {
		return tx.ses.srv.env.ociError()
	}
	return nil
}
<|endoftext|>


<commit_before>package vxsv

import (
	"fmt"

	"github.com/nsf/termbox-go"
)

const MaxCellWidth = 20
const CellSeparator = " │ "
const RowIndicator = '»'

const HiliteFg = termbox.ColorBlack | termbox.AttrBold
const HiliteBg = termbox.ColorWhite

const HelpText = `Key Bindings:

vxsv is a modal viewer, meaning that actions are only valid in certain
contexts.

DEFAULT MODE
============

  Ctrl l          refresh screen
  Ctrl a          pan to beginning of line
  Ctrl e          pan to end of line
  <arrow keys>    scroll / pan control
  Ctrl r, /       enter ** FILTER MODE **
  [ENTER]         pop open dialog showing row in detail
  [SPACE]         scroll down one screen
  C               enter ** COLUMN SELECT MODE **
  R               enter ** ROW SELECT MODE **
  G               scroll to bottom
  g               scroll to top
  Z               toggle zebra stripes
  X               toggle expanding all columns
  ?               show this help dialog
  Ctrl c          exit

COLUMN SELECT MODE
==================

  <arrow keys>    select column
  Ctrl a          select first column
  Ctrl e          select last column
  <               sort by column, ascending
  >               sort by column, descending
  w               toggle collapsing this column
  x               toggle expanding this column
  a               line up decimal points for floats in this column
  .               toggle pinning this column
  |               pipe column values into shell, see ** SHELL COMMAND MODE **
  u               filter rows to unique values for this column
  s               show summary statistics for this column
  [ESC], Ctrl g   return to ** DEFAULT MODE **

FILTER MODE
===========

  Filter expressions can take two forms:

    1. Column filter: "column_name CMP value"
       * CMP is one of (==, !=, <, <=, >, >=)
       * Display rows where the given column's value for the
         row makes the comparison evaluate to true.

    2. Row filter: "filter_string"
       * Display rows where any column in the row matches the
         filter string.

  [ESC], Ctrl g   clear filter and return to previous mode
  Ctrl w, Ctrl u  clear entered filter expression
  [ENTER]         apply filter and return to previous mode

ROW SELECT MODE
===============

  <arrow keys>    select row
  [ENTER]         pop open expanded row dialog.

SHELL COMMAND MODE
==================
  Pipe selected column's values into an external process, setting the new value
  to the output of the process. Each value is printed on a new line, which will
  work with most standard unix pipe commands.

  Examples:
     jq -c '.foo.bar.baz' -       # extract json values from col with jq
     awk '{ println $1 * 100 }'   # multiply current col in each row by 100
     sed 's/1/true/g'             # simple remapping of values

  [ESC], Ctrl g   exit shell command mode and revert to original values
  Ctrl w, Ctrl u  clear entered shell command
  [ENTER]         run shell command and return to previous mode
`

type UI struct {
	handlers         []ModeHandler
	rowIdx           int // Selection control
	offsetX, offsetY int // Pan control
	filter           Filter
	filterMatches    []int
	zebraStripe      bool
	allExpanded      bool
	columns          []Column
	rows             [][]string
}

type Column struct {
	Name string

	// Display options
	Display   ColumnDisplay
	Pinned    bool
	Highlight bool
	Width     int

	Modified        bool
	ModifiedValues  []string
	ModifiedCommand string
}

type TabularData struct {
	Columns []Column
	Rows    [][]string
}

type ColumnDisplay int

const (
	ColumnDefault = iota
	ColumnCollapsed
	ColumnExpanded

	// TODO: Move this to the Modified attribute
	ColumnAligned
)

func (c *Column) toggleDisplay(mode ColumnDisplay) {
	if c.Display == mode {
		c.Display = ColumnDefault
	} else {
		c.Display = mode
	}
}

func (c Column) displayWidth() int {
	switch c.Display {
	case ColumnAligned:
		return clamp(c.Width, 16, c.Width)
	case ColumnCollapsed:
		return 1
	case ColumnExpanded:
		return c.Width
	case ColumnDefault:
		return clamp(c.Width, 1, MaxCellWidth)
	}

	panic("TODO: this is a bug")
}

// It is so dumb that go doesn't have this
func clamp(val, lo, hi int) int {
	if val <= lo {
		return lo
	} else if val >= hi {
		return hi
	}

	return val
}
func NewUI(data *TabularData) *UI {
	filterMatches := make([]int, len(data.Rows))

	for i, col := range data.Columns {
		col.Display = ColumnDefault
		col.Pinned = false
		col.Highlight = false
		col.Modified = false

		// Last column should open expanded
		if i == len(data.Columns)-1 {
			col.Display = ColumnExpanded
		}
	}

	for i := range data.Rows {
		filterMatches[i] = i
	}

	ui := &UI{
		offsetX:       0,
		offsetY:       0,
		rows:          data.Rows,
		columns:       data.Columns,
		zebraStripe:   false,
		allExpanded:   false,
		filter:        EmptyFilter{},
		filterMatches: filterMatches,
	}

	ui.switchToDefault()

	return ui
}

func (ui *UI) Init() error {
	if err := termbox.Init(); err != nil {
		return err
	}

	termbox.SetInputMode(termbox.InputEsc)
	return nil
}

func (ui *UI) Loop() {
	defer termbox.Close()

	ui.repaint()

eventloop:
	for {
		switch ev := termbox.PollEvent(); ev.Type {
		case termbox.EventKey:
			if ev.Key == termbox.KeyCtrlC {
				break eventloop
			}

			ui.activeHandler().HandleKey(ev)
		}

		ui.repaint()
	}
}

// Return indices of rows to display
func (ui *UI) filterRows() {
	rows := make([]int, 0, 100)

	for i := 0; i < len(ui.rows); i++ {
		if ui.filter.Matches(ui.getRow(i)) {
			rows = append(rows, i)
		}
	}

	ui.filterMatches = rows
}

func (ui *UI) repaint() {
	termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
	termbox.HideCursor()
	_, vh := ui.viewSize()

	const coldef = termbox.ColorDefault

	ui.writeColumns(-ui.offsetX, 0)

	for i := 0; i < vh; i++ {
		if i+ui.offsetY < len(ui.filterMatches) {
			row := ui.getRow(ui.filterMatches[i+ui.offsetY])
			ui.writeRow(-ui.offsetX, i+1, row)
		} else {
			writeLine(0, i+1, termbox.ColorDefault|termbox.AttrBold, termbox.ColorDefault, "~")
		}
	}

	ui.activeHandler().Repaint()
	termbox.Flush()
}

func (ui *UI) viewSize() (int, int) {
	width, height := termbox.Size()
	pinnedWidth := ui.pinnedWidth()

	return width - pinnedWidth, height - 2
}

func (ui *UI) pinnedWidth() (width int) {
	for _, col := range ui.columns {
		if col.Pinned {
			width += col.displayWidth()
			width += len(CellSeparator)
		}
	}

	return width
}

func (ui *UI) columnOffset(colIdx int) (offset int, width int) {
	offset = 0

	for i, col := range ui.columns {
		// Pinned columns should always be visible
		if i == colIdx {
			if !col.Pinned {
				break
			}

			return 0, col.Width
		}

		if !col.Pinned {
			width = col.displayWidth()
			offset += width
			offset += len(CellSeparator)
		}
	}

	return offset, width
}

func (ui *UI) recomputeColumnWidth(colIdx int) {
	width := len(ui.columns[colIdx].Name)

	for _, idx := range ui.filterMatches {
		row := ui.getRow(idx)
		if len(row[colIdx]) > width {
			width = len(row[colIdx])
		}
	}

	ui.columns[colIdx].Width = width
}

// Find the first visually displayed column
func (ui *UI) findFirstColumn() int {
	for i, col := range ui.columns {
		if col.Pinned {
			return i
		}
	}

	// If there are no pinned columns, just return first
	return 0
}

func (ui *UI) findNextColumn(current, direction int) int {
	isPinned := ui.columns[current].Pinned

	// if pinned, find the next pinned col, or vice versa for unpinned
	for i := current + direction; i >= 0 && i < len(ui.columns); i += direction {
		if ui.columns[i].Pinned == isPinned {
			return i
		}
	}

	// Don't fall off the end (would cause confusing behavior)
	if isPinned && direction < 0 || !isPinned && direction > 0 {
		return current
	}

	// we're crossing the pinned/unpinned boundary
	i := 0
	if direction < 0 {
		i = len(ui.columns) - 1
	}
	for ; i >= 0 && i < len(ui.columns); i += direction {
		if (isPinned && !ui.columns[i].Pinned) || (!isPinned && ui.columns[i].Pinned) {
			return i
		}
	}

	return current
}

func (ui *UI) activeHandler() ModeHandler {
	if len(ui.handlers) == 0 {
		ui.switchToDefault()
	}
	return ui.handlers[len(ui.handlers)-1]
}

func (ui *UI) switchToDefault() {
	ui.handlers = []ModeHandler{&HandlerDefault{ui}}
}

func (ui *UI) pushHandler(h ModeHandler) {
	ui.handlers = append(ui.handlers, h)
}

func (ui *UI) popHandler() {
	if len(ui.handlers) > 1 {
		ui.handlers = ui.handlers[:len(ui.handlers)-1]
	} else {
		ui.switchToDefault()
	}
}

func (ui *UI) pushErrorPopup(msg string, err error) {
	errMsg := fmt.Sprintf("Error: %s\n\n%v", msg, err)
	ui.pushHandler(NewPopup(ui, errMsg))
}

func (ui *UI) getRow(idx int) []string {
	row := make([]string, len(ui.columns))

	if idx < 0 || idx >= len(ui.rows) {
		panic(fmt.Errorf("Overflowed row bounds: %d [0, %d]", idx, len(ui.rows)))
	}

	origRow := ui.rows[idx]

	for i, col := range ui.columns {
		if col.Modified {
			row[i] = col.ModifiedValues[idx]
		} else {
			row[i] = origRow[i]
		}
	}

	return row
}
<commit_msg>Document ~, !~<commit_after>package vxsv

import (
	"fmt"

	"github.com/nsf/termbox-go"
)

const MaxCellWidth = 20
const CellSeparator = " │ "
const RowIndicator = '»'

const HiliteFg = termbox.ColorBlack | termbox.AttrBold
const HiliteBg = termbox.ColorWhite

const HelpText = `Key Bindings:

vxsv is a modal viewer, meaning that actions are only valid in certain
contexts.

DEFAULT MODE
============

  Ctrl l          refresh screen
  Ctrl a          pan to beginning of line
  Ctrl e          pan to end of line
  <arrow keys>    scroll / pan control
  Ctrl r, /       enter ** FILTER MODE **
  [ENTER]         pop open dialog showing row in detail
  [SPACE]         scroll down one screen
  C               enter ** COLUMN SELECT MODE **
  R               enter ** ROW SELECT MODE **
  G               scroll to bottom
  g               scroll to top
  Z               toggle zebra stripes
  X               toggle expanding all columns
  ?               show this help dialog
  Ctrl c          exit

COLUMN SELECT MODE
==================

  <arrow keys>    select column
  Ctrl a          select first column
  Ctrl e          select last column
  <               sort by column, ascending
  >               sort by column, descending
  w               toggle collapsing this column
  x               toggle expanding this column
  a               line up decimal points for floats in this column
  .               toggle pinning this column
  |               pipe column values into shell, see ** SHELL COMMAND MODE **
  u               filter rows to unique values for this column
  s               show summary statistics for this column
  [ESC], Ctrl g   return to ** DEFAULT MODE **

FILTER MODE
===========

  Filter expressions can take two forms:

    1. Column filter: "column_name CMP value"
       * CMP is one of (==, !=, <, <=, >, >=, ~, !~)
       * Display rows where the given column's value for the
         row makes the comparison evaluate to true.
       * Read '~' and '!~' as "matches" and "doesn't match",
         respectively.

    2. Row filter: "filter_string"
       * Display rows where any column in the row matches the
         filter string.

  [ESC], Ctrl g   clear filter and return to previous mode
  Ctrl w, Ctrl u  clear entered filter expression
  [ENTER]         apply filter and return to previous mode

ROW SELECT MODE
===============

  <arrow keys>    select row
  [ENTER]         pop open expanded row dialog.

SHELL COMMAND MODE
==================
  Pipe selected column's values into an external process, setting the new value
  to the output of the process. Each value is printed on a new line, which will
  work with most standard unix pipe commands.

  Examples:
     jq -c '.foo.bar.baz' -       # extract json values from col with jq
     awk '{ println $1 * 100 }'   # multiply current col in each row by 100
     sed 's/1/true/g'             # simple remapping of values

  [ESC], Ctrl g   exit shell command mode and revert to original values
  Ctrl w, Ctrl u  clear entered shell command
  [ENTER]         run shell command and return to previous mode
`

type UI struct {
	handlers         []ModeHandler
	rowIdx           int // Selection control
	offsetX, offsetY int // Pan control
	filter           Filter
	filterMatches    []int
	zebraStripe      bool
	allExpanded      bool
	columns          []Column
	rows             [][]string
}

type Column struct {
	Name string

	// Display options
	Display   ColumnDisplay
	Pinned    bool
	Highlight bool
	Width     int

	Modified        bool
	ModifiedValues  []string
	ModifiedCommand string
}

type TabularData struct {
	Columns []Column
	Rows    [][]string
}

type ColumnDisplay int

const (
	ColumnDefault = iota
	ColumnCollapsed
	ColumnExpanded

	// TODO: Move this to the Modified attribute
	ColumnAligned
)

func (c *Column) toggleDisplay(mode ColumnDisplay) {
	if c.Display == mode {
		c.Display = ColumnDefault
	} else {
		c.Display = mode
	}
}

func (c Column) displayWidth() int {
	switch c.Display {
	case ColumnAligned:
		return clamp(c.Width, 16, c.Width)
	case ColumnCollapsed:
		return 1
	case ColumnExpanded:
		return c.Width
	case ColumnDefault:
		return clamp(c.Width, 1, MaxCellWidth)
	}

	panic("TODO: this is a bug")
}

// It is so dumb that go doesn't have this
func clamp(val, lo, hi int) int {
	if val <= lo {
		return lo
	} else if val >= hi {
		return hi
	}

	return val
}
func NewUI(data *TabularData) *UI {
	filterMatches := make([]int, len(data.Rows))

	for i, col := range data.Columns {
		col.Display = ColumnDefault
		col.Pinned = false
		col.Highlight = false
		col.Modified = false

		// Last column should open expanded
		if i == len(data.Columns)-1 {
			col.Display = ColumnExpanded
		}
	}

	for i := range data.Rows {
		filterMatches[i] = i
	}

	ui := &UI{
		offsetX:       0,
		offsetY:       0,
		rows:          data.Rows,
		columns:       data.Columns,
		zebraStripe:   false,
		allExpanded:   false,
		filter:        EmptyFilter{},
		filterMatches: filterMatches,
	}

	ui.switchToDefault()

	return ui
}

func (ui *UI) Init() error {
	if err := termbox.Init(); err != nil {
		return err
	}

	termbox.SetInputMode(termbox.InputEsc)
	return nil
}

func (ui *UI) Loop() {
	defer termbox.Close()

	ui.repaint()

eventloop:
	for {
		switch ev := termbox.PollEvent(); ev.Type {
		case termbox.EventKey:
			if ev.Key == termbox.KeyCtrlC {
				break eventloop
			}

			ui.activeHandler().HandleKey(ev)
		}

		ui.repaint()
	}
}

// Return indices of rows to display
func (ui *UI) filterRows() {
	rows := make([]int, 0, 100)

	for i := 0; i < len(ui.rows); i++ {
		if ui.filter.Matches(ui.getRow(i)) {
			rows = append(rows, i)
		}
	}

	ui.filterMatches = rows
}

func (ui *UI) repaint() {
	termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
	termbox.HideCursor()
	_, vh := ui.viewSize()

	const coldef = termbox.ColorDefault

	ui.writeColumns(-ui.offsetX, 0)

	for i := 0; i < vh; i++ {
		if i+ui.offsetY < len(ui.filterMatches) {
			row := ui.getRow(ui.filterMatches[i+ui.offsetY])
			ui.writeRow(-ui.offsetX, i+1, row)
		} else {
			writeLine(0, i+1, termbox.ColorDefault|termbox.AttrBold, termbox.ColorDefault, "~")
		}
	}

	ui.activeHandler().Repaint()
	termbox.Flush()
}

func (ui *UI) viewSize() (int, int) {
	width, height := termbox.Size()
	pinnedWidth := ui.pinnedWidth()

	return width - pinnedWidth, height - 2
}

func (ui *UI) pinnedWidth() (width int) {
	for _, col := range ui.columns {
		if col.Pinned {
			width += col.displayWidth()
			width += len(CellSeparator)
		}
	}

	return width
}

func (ui *UI) columnOffset(colIdx int) (offset int, width int) {
	offset = 0

	for i, col := range ui.columns {
		// Pinned columns should always be visible
		if i == colIdx {
			if !col.Pinned {
				break
			}

			return 0, col.Width
		}

		if !col.Pinned {
			width = col.displayWidth()
			offset += width
			offset += len(CellSeparator)
		}
	}

	return offset, width
}

func (ui *UI) recomputeColumnWidth(colIdx int) {
	width := len(ui.columns[colIdx].Name)

	for _, idx := range ui.filterMatches {
		row := ui.getRow(idx)
		if len(row[colIdx]) > width {
			width = len(row[colIdx])
		}
	}

	ui.columns[colIdx].Width = width
}

// Find the first visually displayed column
func (ui *UI) findFirstColumn() int {
	for i, col := range ui.columns {
		if col.Pinned {
			return i
		}
	}

	// If there are no pinned columns, just return first
	return 0
}

func (ui *UI) findNextColumn(current, direction int) int {
	isPinned := ui.columns[current].Pinned

	// if pinned, find the next pinned col, or vice versa for unpinned
	for i := current + direction; i >= 0 && i < len(ui.columns); i += direction {
		if ui.columns[i].Pinned == isPinned {
			return i
		}
	}

	// Don't fall off the end (would cause confusing behavior)
	if isPinned && direction < 0 || !isPinned && direction > 0 {
		return current
	}

	// we're crossing the pinned/unpinned boundary
	i := 0
	if direction < 0 {
		i = len(ui.columns) - 1
	}
	for ; i >= 0 && i < len(ui.columns); i += direction {
		if (isPinned && !ui.columns[i].Pinned) || (!isPinned && ui.columns[i].Pinned) {
			return i
		}
	}

	return current
}

func (ui *UI) activeHandler() ModeHandler {
	if len(ui.handlers) == 0 {
		ui.switchToDefault()
	}
	return ui.handlers[len(ui.handlers)-1]
}

func (ui *UI) switchToDefault() {
	ui.handlers = []ModeHandler{&HandlerDefault{ui}}
}

func (ui *UI) pushHandler(h ModeHandler) {
	ui.handlers = append(ui.handlers, h)
}

func (ui *UI) popHandler() {
	if len(ui.handlers) > 1 {
		ui.handlers = ui.handlers[:len(ui.handlers)-1]
	} else {
		ui.switchToDefault()
	}
}

func (ui *UI) pushErrorPopup(msg string, err error) {
	errMsg := fmt.Sprintf("Error: %s\n\n%v", msg, err)
	ui.pushHandler(NewPopup(ui, errMsg))
}

func (ui *UI) getRow(idx int) []string {
	row := make([]string, len(ui.columns))

	if idx < 0 || idx >= len(ui.rows) {
		panic(fmt.Errorf("Overflowed row bounds: %d [0, %d]", idx, len(ui.rows)))
	}

	origRow := ui.rows[idx]

	for i, col := range ui.columns {
		if col.Modified {
			row[i] = col.ModifiedValues[idx]
		} else {
			row[i] = origRow[i]
		}
	}

	return row
}
<|endoftext|>


<commit_before>package main

func set(m map[int]int, n int) {
	for i := 0; i < n; i++ {
		m[i] = i
	}
}

func main() {
}
<commit_msg>rename initMap<commit_after>package main

func initMap(m map[int]int, n int) {
	for i := 0; i < n; i++ {
		m[i] = i
	}
}

func main() {}
<|endoftext|>


<commit_before>package merge

import "reflect"

// Merge will take two data sets and merge them together - returning a new data set
func Merge(base, override interface{}) interface{} {
	//reflect and recurse
	b := reflect.ValueOf(base)
	o := reflect.ValueOf(override)
	ret := mergeRecursive(b, o)

	return ret.Interface()
}

func mergeRecursive(base, override reflect.Value) reflect.Value {
	var result reflect.Value

	switch base.Kind() {
	case reflect.Ptr:
		switch base.Elem().Kind() {
		case reflect.Ptr:
			fallthrough
		case reflect.Interface:
			fallthrough
		case reflect.Struct:
			fallthrough
		case reflect.Map:
			// Pointers to complex types should recurse if they aren't nil
			if base.IsNil() {
				result = override
			} else if override.IsNil() {
				result = base
			} else {
				result = mergeRecursive(base.Elem(), override.Elem())
			}
		default:
			// Pointers to basic types should just override
			if isEmptyValue(override) {
				result = base
			} else {
				result = override
			}
		}
	case reflect.Interface:
		// Interfaces should just be unwrapped and recursed through
		result = mergeRecursive(base.Elem(), override.Elem())

	case reflect.Struct:
		// For structs we loop over fields and recurse
		// setup our result struct
		result = reflect.New(base.Type())
		for i, n := 0, base.NumField(); i < n; i++ {
			// We cant set private fields so don't recurse on them
			if result.Elem().Field(i).CanSet() {
				// get the merged value of each field
				newVal := mergeRecursive(base.Field(i), override.Field(i))

				//attempt to set that merged value on our result struct
				if result.Elem().Field(i).CanSet() && newVal.IsValid() {
					if newVal.Kind() == reflect.Ptr && result.Elem().Field(i).Kind() != reflect.Ptr {
						newVal = newVal.Elem()
					} else if result.Elem().Field(i).Kind() == reflect.Ptr && newVal.Kind() != reflect.Ptr && newVal.CanAddr() {
						newVal = newVal.Addr()
					}
					result.Elem().Field(i).Set(newVal)
				}
			}
		}

	case reflect.Map:
		// For Maps we copy the base data, and then replace it with merged data
		// We use two for loops to make sure all map keys from base and all keys from
		// override exist in the result just in case one of the maps is sparse.

		result = reflect.MakeMap(base.Type())
		// Copy from base first
		for _, key := range base.MapKeys() {
			result.SetMapIndex(key, base.MapIndex(key))
		}

		// Override with values from override if they exist
		if override.Kind() == reflect.Map {
			for _, key := range override.MapKeys() {
				overrideVal := override.MapIndex(key)
				baseVal := base.MapIndex(key)
				if !overrideVal.IsValid() {
					continue
				}

				// Merge the values and set in the result
				newVal := mergeRecursive(baseVal, overrideVal)
				if newVal.Kind() == reflect.Ptr {
					result.SetMapIndex(key, newVal.Elem())

				} else {
					result.SetMapIndex(key, newVal)
				}
			}
		}

	default:
		// These are all generic types
		// override will be taken for generic types if it is set
		if isEmptyValue(override) {
			result = base
		} else {
			result = override
		}
	}
	return result
}

// Copied From http://golang.org/src/encoding/json/encode.go
// Lines 280 - 296
func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	}
	return false
}
<commit_msg>Fix panic when a map contains pointers<commit_after>package merge

import "reflect"

// Merge will take two data sets and merge them together - returning a new data set
func Merge(base, override interface{}) interface{} {
	//reflect and recurse
	b := reflect.ValueOf(base)
	o := reflect.ValueOf(override)
	ret := mergeRecursive(b, o)

	return ret.Interface()
}

func mergeRecursive(base, override reflect.Value) reflect.Value {
	var result reflect.Value

	switch base.Kind() {
	case reflect.Ptr:
		switch base.Elem().Kind() {
		case reflect.Ptr:
			fallthrough
		case reflect.Interface:
			fallthrough
		case reflect.Struct:
			fallthrough
		case reflect.Map:
			// Pointers to complex types should recurse if they aren't nil
			if base.IsNil() {
				result = override
			} else if override.IsNil() {
				result = base
			} else {
				result = mergeRecursive(base.Elem(), override.Elem())
			}
		default:
			// Pointers to basic types should just override
			if isEmptyValue(override) {
				result = base
			} else {
				result = override
			}
		}
	case reflect.Interface:
		// Interfaces should just be unwrapped and recursed through
		result = mergeRecursive(base.Elem(), override.Elem())

	case reflect.Struct:
		// For structs we loop over fields and recurse
		// setup our result struct
		result = reflect.New(base.Type())
		for i, n := 0, base.NumField(); i < n; i++ {
			// We cant set private fields so don't recurse on them
			if result.Elem().Field(i).CanSet() {
				// get the merged value of each field
				newVal := mergeRecursive(base.Field(i), override.Field(i))

				//attempt to set that merged value on our result struct
				if result.Elem().Field(i).CanSet() && newVal.IsValid() {
					if newVal.Kind() == reflect.Ptr && result.Elem().Field(i).Kind() != reflect.Ptr {
						newVal = newVal.Elem()
					} else if result.Elem().Field(i).Kind() == reflect.Ptr && newVal.Kind() != reflect.Ptr && newVal.CanAddr() {
						newVal = newVal.Addr()
					}
					result.Elem().Field(i).Set(newVal)
				}
			}
		}

	case reflect.Map:
		// For Maps we copy the base data, and then replace it with merged data
		// We use two for loops to make sure all map keys from base and all keys from
		// override exist in the result just in case one of the maps is sparse.
		elementsAreValues := base.Type().Elem().Kind() != reflect.Ptr

		result = reflect.MakeMap(base.Type())
		// Copy from base first
		for _, key := range base.MapKeys() {
			result.SetMapIndex(key, base.MapIndex(key))
		}

		// Override with values from override if they exist
		if override.Kind() == reflect.Map {
			for _, key := range override.MapKeys() {
				overrideVal := override.MapIndex(key)
				baseVal := base.MapIndex(key)
				if !overrideVal.IsValid() {
					continue
				}

				// Merge the values and set in the result
				newVal := mergeRecursive(baseVal, overrideVal)
				if elementsAreValues && newVal.Kind() == reflect.Ptr {
					result.SetMapIndex(key, newVal.Elem())

				} else {
					result.SetMapIndex(key, newVal)
				}
			}
		}

	default:
		// These are all generic types
		// override will be taken for generic types if it is set
		if isEmptyValue(override) {
			result = base
		} else {
			result = override
		}
	}
	return result
}

// Copied From http://golang.org/src/encoding/json/encode.go
// Lines 280 - 296
func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"regexp"

	"github.com/kurin/wordsquares/trie"
)

var matcher = regexp.MustCompile("^[a-z]*$")

var (
	size = flag.Int("size", 2, "the word size to use")
	word = flag.String("word", "", "the word to start with")
	dict = flag.String("dictionary", "/usr/share/dict/words", "the dictionary to use")
)

func wordList(size int) ([]string, error) {
	var wl []string
	f, err := os.Open(*dict)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		if len(scanner.Text()) == size && matcher.MatchString(scanner.Text()) {
			wl = append(wl, scanner.Text())
		}
	}
	return wl, scanner.Err()
}

func makeSquare(words []string, t *trie.Trie) [][]string {
	c := len(words)
	if c == 0 {
		return nil
	}

	s := len(words[0])
	pfx := make([]byte, c)
	for i := 0; i < s; i++ {
		for j := 0; j < c; j++ {
			pfx[j] = words[j][i]
		}
		if !t.HasPrefix(string(pfx)) {
			return nil
		}
	}

	if s == c {
		rtn := make([]string, c)
		copy(rtn, words)
		return [][]string{rtn}
	}

	for i, word := range words {
		pfx[i] = byte(word[c])
	}
	tmp := make([]string, c+1)
	copy(tmp, words)
	var all [][]string
	for _, cand := range t.WithPrefix(string(pfx)) {
		tmp[c] = cand
		sq := makeSquare(tmp, t)
		for _, s := range sq {
			all = append(all, s)
		}
	}
	return all
}

func main() {
	flag.Parse()
	size := *size
	if *word != "" {
		size = len(*word)
	}
	wl, err := wordList(size)
	if err != nil {
		fmt.Println(err)
		return
	}

	t := &trie.Trie{}
	for _, w := range wl {
		t.Add(w)
	}
	if *word != "" {
		t.Add(*word)
		wSqs := makeSquare([]string{*word}, t)
		for _, sq := range wSqs {
			fmt.Println("---")
			for _, a := range sq {
				fmt.Println(a)
			}
		}
		return
	}
	for _, w := range wl {
		wSqs := makeSquare([]string{w}, t)
		for _, sq := range wSqs {
			fmt.Println("---")
			for _, a := range sq {
				fmt.Println(a)
			}
		}
	}
}
<commit_msg>Add support for "double" word squares.<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"regexp"

	"github.com/kurin/wordsquares/trie"
)

var matcher = regexp.MustCompile("^[a-z]*$")

var (
	size   = flag.Int("size", 2, "the word size to use")
	word   = flag.String("word", "", "the word to start with")
	dict   = flag.String("dictionary", "/usr/share/dict/words", "the dictionary to use")
	double = flag.Bool("double", false, "make a double word square")
)

func wordList(size int) ([]string, error) {
	var wl []string
	f, err := os.Open(*dict)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		if len(scanner.Text()) == size && matcher.MatchString(scanner.Text()) {
			wl = append(wl, scanner.Text())
		}
	}
	return wl, scanner.Err()
}

func hasChar(s []byte, b byte) bool {
	for _, c := range s {
		if b == c {
			return true
		}
	}
	return false
}

func makeDoubleSquare(t *trie.Trie, words []string) [][]string {
	c := len(words)
	if c == 0 {
		return nil
	}
	s := len(words[0])
	if c == s {
		rtn := make([]string, c)
		copy(rtn, words)
		return [][]string{rtn}
	}
	matcher := make([][]byte, s)
	pfx := make([]byte, c)
	for i := 0; i < s; i++ {
		imatch := make([]byte, c)
		for j := range words {
			pfx[j] = words[j][i]
		}
		cands := t.WithPrefix(string(pfx))
		for _, cand := range cands {
			r := cand[c]
			if !hasChar(imatch, r) {
				imatch = append(imatch, r)
			}
		}
		if len(imatch) == 0 {
			return nil
		}
		matcher[i] = imatch
	}
	cWords := t.Matches(matcher)
	next := make([]string, c+1)
	copy(next, words)
	var rtn [][]string
	for _, word := range cWords {
		next[c] = word
		sqs := makeDoubleSquare(t, next)
		for _, sq := range sqs {
			rtn = append(rtn, sq)
		}
	}
	return rtn
}

func makeSquare(t *trie.Trie, words []string) [][]string {
	c := len(words)
	if c == 0 {
		return nil
	}

	s := len(words[0])
	pfx := make([]byte, c)
	for i := 0; i < s; i++ {
		for j := 0; j < c; j++ {
			pfx[j] = words[j][i]
		}
		if !t.HasPrefix(string(pfx)) {
			return nil
		}
	}

	if s == c {
		rtn := make([]string, c)
		copy(rtn, words)
		return [][]string{rtn}
	}

	for i, word := range words {
		pfx[i] = byte(word[c])
	}
	tmp := make([]string, c+1)
	copy(tmp, words)
	var all [][]string
	for _, cand := range t.WithPrefix(string(pfx)) {
		tmp[c] = cand
		sq := makeSquare(t, tmp)
		for _, s := range sq {
			all = append(all, s)
		}
	}
	return all
}

func main() {
	flag.Parse()
	squareFunc := makeSquare
	if *double {
		squareFunc = makeDoubleSquare
	}
	size := *size
	if *word != "" {
		size = len(*word)
	}
	wl, err := wordList(size)
	if err != nil {
		fmt.Println(err)
		return
	}

	t := &trie.Trie{}
	for _, w := range wl {
		t.Add(w)
	}

	if *word != "" {
		t.Add(*word)
		wSqs := squareFunc(t, []string{*word})
		for _, sq := range wSqs {
			fmt.Println("---")
			for _, a := range sq {
				fmt.Println(a)
			}
		}
		return
	}
	for _, w := range wl {
		fmt.Fprintln(os.Stderr, w)
		wSqs := squareFunc(t, []string{w})
		for _, sq := range wSqs {
			fmt.Println("---")
			for _, a := range sq {
				fmt.Println(a)
			}
		}
	}
}
<|endoftext|>


<commit_before>/*
 * Minio Client, (C) 2015, 2016 Minio, 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 main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sync"
	"syscall"

	"github.com/fatih/color"
	"github.com/minio/cli"
	"github.com/minio/mc/pkg/console"
	"github.com/minio/minio/pkg/probe"
	"github.com/minio/pb"
)

// mirror specific flags.
var (
	mirrorFlags = []cli.Flag{
		cli.BoolFlag{
			Name:  "help, h",
			Usage: "Help of mirror.",
		},
		cli.BoolFlag{
			Name:  "force",
			Usage: "Force overwrite of an existing target(s).",
		},
		cli.BoolFlag{
			Name:  "fake",
			Usage: "Perform a fake mirror operation.",
		},
	}
)

//  Mirror folders recursively from a single source to many destinations
var mirrorCmd = cli.Command{
	Name:   "mirror",
	Usage:  "Mirror folders recursively from a single source to single destination.",
	Action: mainMirror,
	Flags:  append(mirrorFlags, globalFlags...),
	CustomHelpTemplate: `NAME:
   mc {{.Name}} - {{.Usage}}

USAGE:
   mc {{.Name}} [FLAGS] SOURCE TARGET

FLAGS:
  {{range .Flags}}{{.}}
  {{end}}
EXAMPLES:
   1. Mirror a bucket recursively from Minio cloud storage to a bucket on Amazon S3 cloud storage.
      $ mc {{.Name}} play/photos/2014 s3/backup-photos

   2. Mirror a local folder recursively to Amazon S3 cloud storage.
      $ mc {{.Name}} backup/ s3/archive

   3. Mirror a bucket from aliased Amazon S3 cloud storage to a folder on Windows.
      $ mc {{.Name}} s3\documents\2014\ C:\backup\2014

   4. Mirror a bucket from aliased Amazon S3 cloud storage to a local folder use '--force' to overwrite destination.
      $ mc {{.Name}} --force s3/miniocloud miniocloud-backup

   5. Fake mirror a bucket from Minio cloud storage to a bucket on Amazon S3 cloud storage.
      $ mc {{.Name}} --fake play/photos/2014 s3/backup-photos/2014

`,
}

// mirrorMessage container for file mirror messages
type mirrorMessage struct {
	Status string `json:"status"`
	Source string `json:"source"`
	Target string `json:"target"`
}

// String colorized mirror message
func (m mirrorMessage) String() string {
	return console.Colorize("Mirror", fmt.Sprintf("‘%s’ -> ‘%s’", m.Source, m.Target))
}

// JSON jsonified mirror message
func (m mirrorMessage) JSON() string {
	m.Status = "success"
	mirrorMessageBytes, e := json.Marshal(m)
	fatalIf(probe.NewError(e), "Unable to marshal into JSON.")

	return string(mirrorMessageBytes)
}

// mirrorStatMessage container for mirror accounting message
type mirrorStatMessage struct {
	Total       int64
	Transferred int64
	Speed       float64
}

// mirrorStatMessage mirror accounting message
func (c mirrorStatMessage) String() string {
	speedBox := pb.Format(int64(c.Speed)).To(pb.U_BYTES).String()
	if speedBox == "" {
		speedBox = "0 MB"
	} else {
		speedBox = speedBox + "/s"
	}
	message := fmt.Sprintf("Total: %s, Transferred: %s, Speed: %s", pb.Format(c.Total).To(pb.U_BYTES),
		pb.Format(c.Transferred).To(pb.U_BYTES), speedBox)
	return message
}

// doMirror - Mirror an object to multiple destination. mirrorURLs status contains a copy of sURLs and error if any.
func doMirror(sURLs mirrorURLs, progressReader *progressBar, accountingReader *accounter, isFake bool) mirrorURLs {
	if sURLs.Error != nil { // Errorneous sURLs passed.
		sURLs.Error = sURLs.Error.Trace()
		return sURLs
	}

	sourceAlias := sURLs.SourceAlias
	sourceURL := sURLs.SourceContent.URL
	targetAlias := sURLs.TargetAlias
	targetURL := sURLs.TargetContent.URL
	length := sURLs.SourceContent.Size

	if !globalQuiet && !globalJSON {
		progressReader = progressReader.SetCaption(sourceURL.String() + ": ")
	}

	var progress io.Reader
	if globalQuiet || globalJSON {
		sourcePath := filepath.ToSlash(filepath.Join(sourceAlias, sourceURL.Path))
		targetPath := filepath.ToSlash(filepath.Join(targetAlias, targetURL.Path))
		printMsg(mirrorMessage{
			Source: sourcePath,
			Target: targetPath,
		})
		if globalQuiet || globalJSON {
			progress = accountingReader
		}
	} else {
		// Set up progress bar.
		progress = progressReader.ProgressBar
	}

	if isFake {
		if !globalDebug && !globalJSON && !globalQuiet {
			progressReader.ProgressBar.Add64(sURLs.SourceContent.Size)
		}
		sURLs.Error = nil
		return sURLs
	}

	reader, err := getSourceStreamFromAlias(sourceAlias, sourceURL.String())
	if err != nil {
		sURLs.Error = err.Trace(sourceURL.String())
		return sURLs
	}

	_, err = putTargetStreamFromAlias(targetAlias, targetURL.String(), reader, length, progress)
	if err != nil {
		sURLs.Error = err.Trace(targetURL.String())
		return sURLs
	}

	sURLs.Error = nil // just for safety
	return sURLs
}

// doPrepareMirrorURLs scans the source URL and prepares a list of objects for mirroring.
func doPrepareMirrorURLs(session *sessionV6, isForce bool, isFake bool, trapCh <-chan bool) {
	sourceURL := session.Header.CommandArgs[0] // first one is source.
	targetURL := session.Header.CommandArgs[1]
	var totalBytes int64
	var totalObjects int

	// Create a session data file to store the processed URLs.
	dataFP := session.NewDataWriter()

	var scanBar scanBarFunc
	if !globalQuiet && !globalJSON { // set up progress bar
		scanBar = scanBarFactory()
	}

	URLsCh := prepareMirrorURLs(sourceURL, targetURL, isForce, isFake)
	done := false
	for !done {
		select {
		case sURLs, ok := <-URLsCh:
			if !ok { // Done with URL prepration
				done = true
				break
			}
			if sURLs.Error != nil {
				// Print in new line and adjust to top so that we don't print over the ongoing scan bar
				if !globalQuiet && !globalJSON {
					console.Eraseline()
				}
				errorIf(sURLs.Error.Trace(), "Unable to prepare URLs for mirroring.")
				break
			}
			if sURLs.isEmpty() {
				break
			}
			jsonData, e := json.Marshal(sURLs)
			if e != nil {
				session.Delete()
				fatalIf(probe.NewError(e), "Unable to marshal URLs into JSON.")
			}
			fmt.Fprintln(dataFP, string(jsonData))
			if !globalQuiet && !globalJSON {
				scanBar(sURLs.SourceContent.URL.String())
			}

			totalBytes += sURLs.SourceContent.Size
			totalObjects++
		case <-trapCh:
			// Print in new line and adjust to top so that we don't print over the ongoing scan bar
			if !globalQuiet && !globalJSON {
				console.Eraseline()
			}
			session.Delete() // If we are interrupted during the URL scanning, we drop the session.
			os.Exit(0)
		}
	}
	session.Header.TotalBytes = totalBytes
	session.Header.TotalObjects = totalObjects
	session.Save()
}

// Session'fied mirror command.
func doMirrorSession(session *sessionV6) {
	isForce := session.Header.CommandBoolFlags["force"]
	isFake := session.Header.CommandBoolFlags["fake"]

	// Initialize signal trap.
	trapCh := signalTrap(os.Interrupt, syscall.SIGTERM)

	if !session.HasData() {
		doPrepareMirrorURLs(session, isForce, isFake, trapCh)
	}

	// Enable accounting reader by default.
	accntReader := newAccounter(session.Header.TotalBytes)

	// Set up progress bar.
	var progressReader *progressBar
	if !globalQuiet && !globalJSON {
		progressReader = newProgressBar(session.Header.TotalBytes)
	}

	// Prepare URL scanner from session data file.
	urlScanner := bufio.NewScanner(session.NewDataReader())

	// isCopied returns true if an object has been already copied
	// or not. This is useful when we resume from a session.
	isCopied := isCopiedFactory(session.Header.LastCopied)

	// Wait on status of doMirror() operation.
	var statusCh = make(chan mirrorURLs)

	// Add a wait group for the below go-routine.
	var wg = new(sync.WaitGroup)
	wg.Add(1)

	// Go routine to monitor signal traps if any.
	go func() {
		defer wg.Done()
		for {
			select {
			case <-trapCh:
				// Receive interrupt notification.
				if !globalQuiet && !globalJSON {
					console.Eraseline()
				}
				session.CloseAndDie()
			case sURLs, ok := <-statusCh:
				// Status channel is closed, we should return.
				if !ok {
					return
				}
				if sURLs.Error == nil {
					session.Header.LastCopied = sURLs.SourceContent.URL.String()
					session.Save()
				} else {
					// Print in new line and adjust to top so that we
					// don't print over the ongoing progress bar.
					if !globalQuiet && !globalJSON {
						console.Eraseline()
					}
					errorIf(sURLs.Error.Trace(sURLs.SourceContent.URL.String()),
						fmt.Sprintf("Failed to copy ‘%s’.", sURLs.SourceContent.URL.String()))
					// For all non critical errors we can continue for the
					// remaining files.
					switch sURLs.Error.ToGoError().(type) {
					// Handle this specifically for filesystem related errors.
					case BrokenSymlink, TooManyLevelsSymlink, PathNotFound, PathInsufficientPermission:
						continue
					case BucketNameEmpty, ObjectMissing, ObjectAlreadyExists, BucketDoesNotExist, BucketInvalid:
						continue
					}
					// For critical errors we should exit. Session
					// can be resumed after the user figures out
					// the problem.
					session.CloseAndDie()
				}
			}
		}
	}()

	// Loop through all urls and mirror.
	for urlScanner.Scan() {
		var sURLs mirrorURLs
		// Unmarshal copyURLs from each line.
		json.Unmarshal([]byte(urlScanner.Text()), &sURLs)
		// Verify if previously copied, notify progress bar.
		if isCopied(sURLs.SourceContent.URL.String()) {
			isFake = true
		}
		statusCh <- doMirror(sURLs, progressReader, accntReader, isFake)
	}

	// Close the goroutine.
	close(statusCh)

	// Wait for the goroutines to finish.
	wg.Wait()

	if !globalQuiet && !globalJSON {
		if progressReader.ProgressBar.Get() > 0 {
			progressReader.ProgressBar.Finish()
		}
	} else {
		accntStat := accntReader.Stat()
		mrStatMessage := mirrorStatMessage{
			Total:       accntStat.Total,
			Transferred: accntStat.Transferred,
			Speed:       accntStat.Speed,
		}
		console.Println(console.Colorize("Mirror", mrStatMessage.String()))
	}
}

// Main entry point for mirror command.
func mainMirror(ctx *cli.Context) {
	// Set global flags from context.
	setGlobalsFromContext(ctx)

	// check 'mirror' cli arguments.
	checkMirrorSyntax(ctx)

	// Additional command speific theme customization.
	console.SetColor("Mirror", color.New(color.FgGreen, color.Bold))

	var e error
	session := newSessionV6()
	session.Header.CommandType = "mirror"
	session.Header.RootPath, e = os.Getwd()
	if e != nil {
		session.Delete()
		fatalIf(probe.NewError(e), "Unable to get current working folder.")
	}

	// Set command flags from context.
	isForce := ctx.Bool("force")
	isFake := ctx.Bool("fake")
	session.Header.CommandBoolFlags["force"] = isForce
	session.Header.CommandBoolFlags["fake"] = isFake

	// extract URLs.
	session.Header.CommandArgs = ctx.Args()
	doMirrorSession(session)
	session.Delete()
}
<commit_msg>mirror: Make sure isFake is set to false properly.<commit_after>/*
 * Minio Client, (C) 2015, 2016 Minio, 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 main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sync"
	"syscall"

	"github.com/fatih/color"
	"github.com/minio/cli"
	"github.com/minio/mc/pkg/console"
	"github.com/minio/minio/pkg/probe"
	"github.com/minio/pb"
)

// mirror specific flags.
var (
	mirrorFlags = []cli.Flag{
		cli.BoolFlag{
			Name:  "help, h",
			Usage: "Help of mirror.",
		},
		cli.BoolFlag{
			Name:  "force",
			Usage: "Force overwrite of an existing target(s).",
		},
		cli.BoolFlag{
			Name:  "fake",
			Usage: "Perform a fake mirror operation.",
		},
	}
)

//  Mirror folders recursively from a single source to many destinations
var mirrorCmd = cli.Command{
	Name:   "mirror",
	Usage:  "Mirror folders recursively from a single source to single destination.",
	Action: mainMirror,
	Flags:  append(mirrorFlags, globalFlags...),
	CustomHelpTemplate: `NAME:
   mc {{.Name}} - {{.Usage}}

USAGE:
   mc {{.Name}} [FLAGS] SOURCE TARGET

FLAGS:
  {{range .Flags}}{{.}}
  {{end}}
EXAMPLES:
   1. Mirror a bucket recursively from Minio cloud storage to a bucket on Amazon S3 cloud storage.
      $ mc {{.Name}} play/photos/2014 s3/backup-photos

   2. Mirror a local folder recursively to Amazon S3 cloud storage.
      $ mc {{.Name}} backup/ s3/archive

   3. Mirror a bucket from aliased Amazon S3 cloud storage to a folder on Windows.
      $ mc {{.Name}} s3\documents\2014\ C:\backup\2014

   4. Mirror a bucket from aliased Amazon S3 cloud storage to a local folder use '--force' to overwrite destination.
      $ mc {{.Name}} --force s3/miniocloud miniocloud-backup

   5. Fake mirror a bucket from Minio cloud storage to a bucket on Amazon S3 cloud storage.
      $ mc {{.Name}} --fake play/photos/2014 s3/backup-photos/2014

`,
}

// mirrorMessage container for file mirror messages
type mirrorMessage struct {
	Status string `json:"status"`
	Source string `json:"source"`
	Target string `json:"target"`
}

// String colorized mirror message
func (m mirrorMessage) String() string {
	return console.Colorize("Mirror", fmt.Sprintf("‘%s’ -> ‘%s’", m.Source, m.Target))
}

// JSON jsonified mirror message
func (m mirrorMessage) JSON() string {
	m.Status = "success"
	mirrorMessageBytes, e := json.Marshal(m)
	fatalIf(probe.NewError(e), "Unable to marshal into JSON.")

	return string(mirrorMessageBytes)
}

// mirrorStatMessage container for mirror accounting message
type mirrorStatMessage struct {
	Total       int64
	Transferred int64
	Speed       float64
}

// mirrorStatMessage mirror accounting message
func (c mirrorStatMessage) String() string {
	speedBox := pb.Format(int64(c.Speed)).To(pb.U_BYTES).String()
	if speedBox == "" {
		speedBox = "0 MB"
	} else {
		speedBox = speedBox + "/s"
	}
	message := fmt.Sprintf("Total: %s, Transferred: %s, Speed: %s", pb.Format(c.Total).To(pb.U_BYTES),
		pb.Format(c.Transferred).To(pb.U_BYTES), speedBox)
	return message
}

// doMirror - Mirror an object to multiple destination. mirrorURLs status contains a copy of sURLs and error if any.
func doMirror(sURLs mirrorURLs, progressReader *progressBar, accountingReader *accounter, isFake bool) mirrorURLs {
	if sURLs.Error != nil { // Errorneous sURLs passed.
		sURLs.Error = sURLs.Error.Trace()
		return sURLs
	}

	sourceAlias := sURLs.SourceAlias
	sourceURL := sURLs.SourceContent.URL
	targetAlias := sURLs.TargetAlias
	targetURL := sURLs.TargetContent.URL
	length := sURLs.SourceContent.Size

	if !globalQuiet && !globalJSON {
		progressReader = progressReader.SetCaption(sourceURL.String() + ": ")
	}

	var progress io.Reader
	if globalQuiet || globalJSON {
		sourcePath := filepath.ToSlash(filepath.Join(sourceAlias, sourceURL.Path))
		targetPath := filepath.ToSlash(filepath.Join(targetAlias, targetURL.Path))
		printMsg(mirrorMessage{
			Source: sourcePath,
			Target: targetPath,
		})
		if globalQuiet || globalJSON {
			progress = accountingReader
		}
	} else {
		// Set up progress bar.
		progress = progressReader.ProgressBar
	}

	if isFake {
		if !globalDebug && !globalJSON && !globalQuiet {
			progressReader.ProgressBar.Add64(sURLs.SourceContent.Size)
		}
		sURLs.Error = nil
		return sURLs
	}

	reader, err := getSourceStreamFromAlias(sourceAlias, sourceURL.String())
	if err != nil {
		sURLs.Error = err.Trace(sourceURL.String())
		return sURLs
	}

	_, err = putTargetStreamFromAlias(targetAlias, targetURL.String(), reader, length, progress)
	if err != nil {
		sURLs.Error = err.Trace(targetURL.String())
		return sURLs
	}

	sURLs.Error = nil // just for safety
	return sURLs
}

// doPrepareMirrorURLs scans the source URL and prepares a list of objects for mirroring.
func doPrepareMirrorURLs(session *sessionV6, isForce bool, isFake bool, trapCh <-chan bool) {
	sourceURL := session.Header.CommandArgs[0] // first one is source.
	targetURL := session.Header.CommandArgs[1]
	var totalBytes int64
	var totalObjects int

	// Create a session data file to store the processed URLs.
	dataFP := session.NewDataWriter()

	var scanBar scanBarFunc
	if !globalQuiet && !globalJSON { // set up progress bar
		scanBar = scanBarFactory()
	}

	URLsCh := prepareMirrorURLs(sourceURL, targetURL, isForce, isFake)
	done := false
	for !done {
		select {
		case sURLs, ok := <-URLsCh:
			if !ok { // Done with URL prepration
				done = true
				break
			}
			if sURLs.Error != nil {
				// Print in new line and adjust to top so that we don't print over the ongoing scan bar
				if !globalQuiet && !globalJSON {
					console.Eraseline()
				}
				errorIf(sURLs.Error.Trace(), "Unable to prepare URLs for mirroring.")
				break
			}
			if sURLs.isEmpty() {
				break
			}
			jsonData, e := json.Marshal(sURLs)
			if e != nil {
				session.Delete()
				fatalIf(probe.NewError(e), "Unable to marshal URLs into JSON.")
			}
			fmt.Fprintln(dataFP, string(jsonData))
			if !globalQuiet && !globalJSON {
				scanBar(sURLs.SourceContent.URL.String())
			}

			totalBytes += sURLs.SourceContent.Size
			totalObjects++
		case <-trapCh:
			// Print in new line and adjust to top so that we don't print over the ongoing scan bar
			if !globalQuiet && !globalJSON {
				console.Eraseline()
			}
			session.Delete() // If we are interrupted during the URL scanning, we drop the session.
			os.Exit(0)
		}
	}
	session.Header.TotalBytes = totalBytes
	session.Header.TotalObjects = totalObjects
	session.Save()
}

// Session'fied mirror command.
func doMirrorSession(session *sessionV6) {
	isForce := session.Header.CommandBoolFlags["force"]
	isFake := session.Header.CommandBoolFlags["fake"]

	// Initialize signal trap.
	trapCh := signalTrap(os.Interrupt, syscall.SIGTERM)

	if !session.HasData() {
		doPrepareMirrorURLs(session, isForce, isFake, trapCh)
	}

	// Enable accounting reader by default.
	accntReader := newAccounter(session.Header.TotalBytes)

	// Set up progress bar.
	var progressReader *progressBar
	if !globalQuiet && !globalJSON {
		progressReader = newProgressBar(session.Header.TotalBytes)
	}

	// Prepare URL scanner from session data file.
	urlScanner := bufio.NewScanner(session.NewDataReader())

	// isCopied returns true if an object has been already copied
	// or not. This is useful when we resume from a session.
	isCopied := isCopiedFactory(session.Header.LastCopied)

	// Wait on status of doMirror() operation.
	var statusCh = make(chan mirrorURLs)

	// Add a wait group for the below go-routine.
	var wg = new(sync.WaitGroup)
	wg.Add(1)

	// Go routine to monitor signal traps if any.
	go func() {
		defer wg.Done()
		for {
			select {
			case <-trapCh:
				// Receive interrupt notification.
				if !globalQuiet && !globalJSON {
					console.Eraseline()
				}
				session.CloseAndDie()
			case sURLs, ok := <-statusCh:
				// Status channel is closed, we should return.
				if !ok {
					return
				}
				if sURLs.Error == nil {
					session.Header.LastCopied = sURLs.SourceContent.URL.String()
					session.Save()
				} else {
					// Print in new line and adjust to top so that we
					// don't print over the ongoing progress bar.
					if !globalQuiet && !globalJSON {
						console.Eraseline()
					}
					errorIf(sURLs.Error.Trace(sURLs.SourceContent.URL.String()),
						fmt.Sprintf("Failed to copy ‘%s’.", sURLs.SourceContent.URL.String()))
					// For all non critical errors we can continue for the
					// remaining files.
					switch sURLs.Error.ToGoError().(type) {
					// Handle this specifically for filesystem related errors.
					case BrokenSymlink, TooManyLevelsSymlink, PathNotFound, PathInsufficientPermission:
						continue
					case BucketNameEmpty, ObjectMissing, ObjectAlreadyExists, BucketDoesNotExist, BucketInvalid:
						continue
					}
					// For critical errors we should exit. Session
					// can be resumed after the user figures out
					// the problem.
					session.CloseAndDie()
				}
			}
		}
	}()

	// Loop through all urls and mirror.
	for urlScanner.Scan() {
		var sURLs mirrorURLs
		// Unmarshal copyURLs from each line.
		json.Unmarshal([]byte(urlScanner.Text()), &sURLs)
		// Verify if previously copied, notify progress bar.
		if isCopied(sURLs.SourceContent.URL.String()) {
			isFake = true
		} else {
			isFake = false
		}
		statusCh <- doMirror(sURLs, progressReader, accntReader, isFake)
	}

	// Close the goroutine.
	close(statusCh)

	// Wait for the goroutines to finish.
	wg.Wait()

	if !globalQuiet && !globalJSON {
		if progressReader.ProgressBar.Get() > 0 {
			progressReader.ProgressBar.Finish()
		}
	} else {
		accntStat := accntReader.Stat()
		mrStatMessage := mirrorStatMessage{
			Total:       accntStat.Total,
			Transferred: accntStat.Transferred,
			Speed:       accntStat.Speed,
		}
		console.Println(console.Colorize("Mirror", mrStatMessage.String()))
	}
}

// Main entry point for mirror command.
func mainMirror(ctx *cli.Context) {
	// Set global flags from context.
	setGlobalsFromContext(ctx)

	// check 'mirror' cli arguments.
	checkMirrorSyntax(ctx)

	// Additional command speific theme customization.
	console.SetColor("Mirror", color.New(color.FgGreen, color.Bold))

	var e error
	session := newSessionV6()
	session.Header.CommandType = "mirror"
	session.Header.RootPath, e = os.Getwd()
	if e != nil {
		session.Delete()
		fatalIf(probe.NewError(e), "Unable to get current working folder.")
	}

	// Set command flags from context.
	isForce := ctx.Bool("force")
	isFake := ctx.Bool("fake")
	session.Header.CommandBoolFlags["force"] = isForce
	session.Header.CommandBoolFlags["fake"] = isFake

	// extract URLs.
	session.Header.CommandArgs = ctx.Args()
	doMirrorSession(session)
	session.Delete()
}
<|endoftext|>


<commit_before>package model

import (
	"fmt"
	"time"

	"github.com/Machiel/slugify"
	"github.com/asaskevich/govalidator"
	"github.com/jinzhu/gorm"
	"gopkg.in/guregu/null.v3"
)

// Builds is simply a collection of build structs.
type Builds []*Build

// Build represents a build model definition.
type Build struct {
	ID          int64      `json:"id" gorm:"primary_key"`
	Pack        *Pack      `json:"pack,omitempty"`
	PackID      int64      `json:"pack_id" sql:"index"`
	Minecraft   *Minecraft `json:"minecraft,omitempty"`
	MinecraftID null.Int   `json:"minecraft_id" sql:"index"`
	Forge       *Forge     `json:"forge,omitempty"`
	ForgeID     null.Int   `json:"forge_id" sql:"index"`
	Slug        string     `json:"slug"`
	Name        string     `json:"name"`
	MinJava     string     `json:"min_java"`
	MinMemory   string     `json:"min_memory"`
	Published   bool       `json:"published" sql:"default:false"`
	Hidden      bool       `json:"hidden" sql:"-"`
	Private     bool       `json:"private" sql:"default:false"`
	Public      bool       `json:"public" sql:"-"`
	CreatedAt   time.Time  `json:"created_at"`
	UpdatedAt   time.Time  `json:"updated_at"`
	Versions    Versions   `json:"versions,omitempty" gorm:"many2many:build_versions"`
}

// AfterFind invokes required after loading a record from the database.
func (u *Build) AfterFind(db *gorm.DB) {
	u.Hidden = !u.Published
	u.Public = !u.Private
}

// BeforeSave invokes required actions before persisting.
func (u *Build) BeforeSave(db *gorm.DB) (err error) {
	if u.Slug == "" {
		for i := 0; true; i++ {
			if i == 0 {
				u.Slug = slugify.Slugify(u.Name)
			} else {
				u.Slug = slugify.Slugify(
					fmt.Sprintf("%s-%d", u.Name, i),
				)
			}

			notFound := db.Where(
				"pack_id = ?",
				u.PackID,
			).Where(
				"slug = ?",
				u.Slug,
			).Not(
				"id",
				u.ID,
			).First(
				&Build{},
			).RecordNotFound()

			if notFound {
				break
			}
		}
	}

	return nil
}

// BeforeDelete invokes required actions before deletion.
func (u *Build) BeforeDelete(tx *gorm.DB) error {
	if err := tx.Model(u).Association("Versions").Clear().Error; err != nil {
		return err
	}

	return nil
}

// Validate does some validation to be able to store the record.
func (u *Build) Validate(db *gorm.DB) {
	if u.PackID == 0 {
		db.AddError(fmt.Errorf("A pack reference is required"))
	} else {
		res := db.Where(
			"id = ?",
			u.PackID,
		).First(
			&Pack{},
		)

		if res.RecordNotFound() {
			db.AddError(fmt.Errorf("Referenced pack does not exist"))
		}
	}

	if u.MinecraftID.Int64 > 0 {
		res := db.Where(
			"id = ?",
			u.MinecraftID,
		).First(
			&Minecraft{},
		)

		if res.RecordNotFound() {
			db.AddError(fmt.Errorf("Referenced minecraft does not exist"))
		}
	}

	if u.ForgeID.Int64 > 0 {
		res := db.Where(
			"id = ?",
			u.ForgeID,
		).First(
			&Forge{},
		)

		if res.RecordNotFound() {
			db.AddError(fmt.Errorf("Referenced forge does not exist"))
		}
	}

	if !govalidator.StringLength(u.Name, "2", "255") {
		db.AddError(fmt.Errorf("Name should be longer than 2 and shorter than 255"))
	}

	if u.Name != "" {
		notFound := db.Where(
			"pack_id = ?",
			u.PackID,
		).Where(
			"name = ?",
			u.Name,
		).Not(
			"id",
			u.ID,
		).First(
			&Build{},
		).RecordNotFound()

		if !notFound {
			db.AddError(fmt.Errorf("Name is already present"))
		}
	}
}
<commit_msg>Use the name as a slug for builds<commit_after>package model

import (
	"fmt"
	"time"

	"github.com/asaskevich/govalidator"
	"github.com/jinzhu/gorm"
	"gopkg.in/guregu/null.v3"
)

// Builds is simply a collection of build structs.
type Builds []*Build

// Build represents a build model definition.
type Build struct {
	ID          int64      `json:"id" gorm:"primary_key"`
	Pack        *Pack      `json:"pack,omitempty"`
	PackID      int64      `json:"pack_id" sql:"index"`
	Minecraft   *Minecraft `json:"minecraft,omitempty"`
	MinecraftID null.Int   `json:"minecraft_id" sql:"index"`
	Forge       *Forge     `json:"forge,omitempty"`
	ForgeID     null.Int   `json:"forge_id" sql:"index"`
	Slug        string     `json:"slug"`
	Name        string     `json:"name"`
	MinJava     string     `json:"min_java"`
	MinMemory   string     `json:"min_memory"`
	Published   bool       `json:"published" sql:"default:false"`
	Hidden      bool       `json:"hidden" sql:"-"`
	Private     bool       `json:"private" sql:"default:false"`
	Public      bool       `json:"public" sql:"-"`
	CreatedAt   time.Time  `json:"created_at"`
	UpdatedAt   time.Time  `json:"updated_at"`
	Versions    Versions   `json:"versions,omitempty" gorm:"many2many:build_versions"`
}

// AfterFind invokes required after loading a record from the database.
func (u *Build) AfterFind(db *gorm.DB) {
	u.Hidden = !u.Published
	u.Public = !u.Private
}

// BeforeSave invokes required actions before persisting.
func (u *Build) BeforeSave(db *gorm.DB) (err error) {
	if u.Slug == "" {
		for i := 0; true; i++ {
			if i == 0 {
				u.Slug = u.Name
			} else {
				u.Slug = fmt.Sprintf("%s-%d", u.Name, i)
			}

			notFound := db.Where(
				"pack_id = ?",
				u.PackID,
			).Where(
				"slug = ?",
				u.Slug,
			).Not(
				"id",
				u.ID,
			).First(
				&Build{},
			).RecordNotFound()

			if notFound {
				break
			}
		}
	}

	return nil
}

// BeforeDelete invokes required actions before deletion.
func (u *Build) BeforeDelete(tx *gorm.DB) error {
	if err := tx.Model(u).Association("Versions").Clear().Error; err != nil {
		return err
	}

	return nil
}

// Validate does some validation to be able to store the record.
func (u *Build) Validate(db *gorm.DB) {
	if u.PackID == 0 {
		db.AddError(fmt.Errorf("A pack reference is required"))
	} else {
		res := db.Where(
			"id = ?",
			u.PackID,
		).First(
			&Pack{},
		)

		if res.RecordNotFound() {
			db.AddError(fmt.Errorf("Referenced pack does not exist"))
		}
	}

	if u.MinecraftID.Int64 > 0 {
		res := db.Where(
			"id = ?",
			u.MinecraftID,
		).First(
			&Minecraft{},
		)

		if res.RecordNotFound() {
			db.AddError(fmt.Errorf("Referenced minecraft does not exist"))
		}
	}

	if u.ForgeID.Int64 > 0 {
		res := db.Where(
			"id = ?",
			u.ForgeID,
		).First(
			&Forge{},
		)

		if res.RecordNotFound() {
			db.AddError(fmt.Errorf("Referenced forge does not exist"))
		}
	}

	if !govalidator.StringLength(u.Name, "2", "255") {
		db.AddError(fmt.Errorf("Name should be longer than 2 and shorter than 255"))
	}

	if u.Name != "" {
		notFound := db.Where(
			"pack_id = ?",
			u.PackID,
		).Where(
			"name = ?",
			u.Name,
		).Not(
			"id",
			u.ID,
		).First(
			&Build{},
		).RecordNotFound()

		if !notFound {
			db.AddError(fmt.Errorf("Name is already present"))
		}
	}
}
<|endoftext|>


<commit_before>package models

import (
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"fmt"
)

var db *sql.DB
var err error

type Identity interface {
	GetID() int
	GetName() string
}

type User struct {
	ID       int    `form:"id" json:"id"`
	Name     string `form:"name" json:"name"`
	Email    string `form:"email" json:"email" binding:"required"`
	Password string `form:"password" json:"password" binding:"required"`
	Token    string `form:"token" json:"token"`
}

func (u User) GetID() int {
	return u.ID
}

func (u User) GetName() string {
	return u.Name
}

func GetToken(UserEmail string) {
	stmt, _ := db.Prepare("INSERT `users` SET email=?,pasword=?,token=?,name=?")
	res, _ := stmt.Exec("test@domail.com", "Swqa123123123", "sa6d7587d6df7gnh5f2jm5fjm", "Andrew")
	id, _ := res.LastInsertId()

	fmt.Println(id)
	fmt.Println(UserEmail)

	//db.QueryRow("SELECT `id`, `email`, `password`, `token`, `name` FROM users WHERE email = $1", UserEmail)

	//user := new(User)
	//result := row.Scan(&user.ID, &user.Email, &user.Password, &user.Token, &user.Name)
	//
	//fmt.Println(result)
}
<commit_msg>Update user.go<commit_after>package models

import (
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"fmt"
)

var db *sql.DB
var err error

type Identity interface {
	GetID() int
	GetName() string
}

type User struct {
	ID       int    `form:"id" json:"id"`
	Name     string `form:"name" json:"name"`
	Email    string `form:"email" json:"email" binding:"required"`
	Password string `form:"password" json:"password" binding:"required"`
	Token    string `form:"token" json:"token"`
}

func (u User) GetID() int {
	return u.ID
}

func (u User) GetName() string {
	return u.Name
}

func GetToken(email string) {
	var user User

	row := db.QueryRow("SELECT `id`, `email`, `password`, `token`, `name` FROM `users` WHERE `id` = $1", email)
	row.Scan(&user.ID, &user.Name, &user.Email, &user.Password, &user.Token)

	return user
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/astaxie/beego/httplib"
	"github.com/miaolz123/conver"
	"github.com/miaolz123/stockdb/stockdb"
)

func main() {
	records := [][6]float64{}
	req := httplib.Get("https://www.okcoin.cn/api/v1/kline.do?symbol=btc_cny&type=1min&size=300")
	if err := req.ToJSON(&records); err != nil {
		fmt.Println(err)
	} else {
		cli := stockdb.New("http://localhost:8765", "username:password")
		opt := stockdb.Option{
			Period: stockdb.Minute,
		}
		for _, record := range records {
			resp := cli.PutOHLC(stockdb.OHLC{
				Time:   conver.Int64Must(record[0]) / 1000,
				Open:   record[1],
				High:   record[2],
				Low:    record[3],
				Close:  record[4],
				Volume: record[5],
			}, opt)
			if !resp.Success {
				fmt.Println(resp.Message)
			}
		}
	}
}
<commit_msg>update golang example<commit_after>package main

import (
	"log"
	"time"

	"github.com/astaxie/beego/httplib"
	"github.com/miaolz123/conver"
	"github.com/miaolz123/stockdb/stockdb"
)

const (
	uri    = "http://localhost:8765"
	auth   = "username:password"
	market = "okcoin_cn"
	symbol = "BTC_CNY"
	period = "1min"
)

func main() {
	periods := map[string]int64{
		"1min": 60,
		"3min": 180,
		"5min": 300,
	}
	if periods[period] == 0 {
		log.Fatalln("period error")
	}
	opt := stockdb.Option{
		Market: market,
		Symbol: symbol,
		Period: periods[period],
	}
	for {
		fetch(opt)
		time.Sleep(200 * time.Duration(opt.Period) * time.Second)
	}
}

func fetch(opt stockdb.Option) {
	records := [][6]float64{}
	req := httplib.Get("https://www.okcoin.cn/api/v1/kline.do?symbol=btc_cny&type=" + period + "&size=1000")
	if err := req.ToJSON(&records); err != nil {
		log.Println("parse json error: ", err)
	} else {
		ohlcs := []stockdb.OHLC{}
		for _, record := range records {
			ohlcs = append(ohlcs, stockdb.OHLC{
				Time:   conver.Int64Must(record[0]) / 1000,
				Open:   record[1],
				High:   record[2],
				Low:    record[3],
				Close:  record[4],
				Volume: record[5],
			})
		}
		if len(ohlcs) > 0 {
			cli := stockdb.New(uri, auth)
			if resp := cli.PutOHLCs(ohlcs, opt); !resp.Success {
				log.Println("PutOHLCs error: ", resp.Message)
			} else {
				log.Println("PutOHLCs successfully")
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
)

type Foo int

func (f Foo) String() string {
	return "foo"
}

func main() {
	var foo Foo = 1000
	fmt.Printf("%d\n", foo)
	fmt.Println(foo)
}
<commit_msg>update fmt interface example.<commit_after>package main

import (
	"fmt"
)

type IPV4 []byte

// Stringer is implemented by any value that has a String method,
// which defines the ``native'' format for that value.
// The String method is used to print values passed as an operand
// to any format that accepts a string or to an unformatted printer
// such as Print.
func (s IPV4) String() string {
	return fmt.Sprintf("%v.%v.%v.%v", s[0], s[1], s[2], s[3])
}

// GoString method, which defines the Go syntax for that value.
// The GoString method is used to print values passed as an operand
// to a %#v format.
func (s IPV4) GoString() string {
	return fmt.Sprintf("%v.%v.%v.%v", s[0], s[1], s[2], s[3])
}

func main() {
	ipv4 := map[string]IPV4{
		"localhost": {127, 0, 0, 1},
		"Google":    {8, 8, 8, 8},
	}

	for i, v := range ipv4 {
		fmt.Printf("name: %s, ip: %v\n", i, v)
		fmt.Printf("debug: %#v\n", v)
	}
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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
//
// 	https://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 safehttp

import (
	"errors"
	"net/http"
	"net/textproto"
)

var disallowedHeaders = map[string]bool{"Set-Cookie": true}

const (
	disallowedErrorMessage = "disallowed header"
	immutableErrorMessage  = "immutable header"
)

// Header represents the key-value pairs in an HTTP header.
// The keys will be in canonical form, as returned by
// textproto.CanonicalMIMEHeaderKey.
type Header struct {
	wrapped   http.Header
	immutable map[string]bool
}

func newHeader(h http.Header) Header {
	return Header{wrapped: h, immutable: map[string]bool{}}
}

// MarkImmutable marks the header with the given name as immutable.
// This header is now read-only. The name is first canonicalized
// using textproto.CanonicalMIMEHeaderKey.
func (h Header) MarkImmutable(name string) {
	name = textproto.CanonicalMIMEHeaderKey(name)
	h.immutable[name] = true
}

// Set sets the header with the given name to the given value.
// The name is first canonicalized using textproto.CanonicalMIMEHeaderKey.
// If this headers is not immutable, this function removes all other
// values currently associated with this header before setting the new
// value. Returns an error when applied on immutable headers.
func (h Header) Set(name, value string) error {
	name = textproto.CanonicalMIMEHeaderKey(name)
	if disallowedHeaders[name] {
		return errors.New(disallowedErrorMessage)
	}
	if h.immutable[name] {
		return errors.New(immutableErrorMessage)
	}
	h.wrapped.Set(name, value)
	return nil
}

// Add adds a new header with the given name and the given value to
// the collection of headers. The name is first canonicalized using
// textproto.CanonicalMIMEHeaderKey. Returns an error when applied
// on immutable headers.
func (h Header) Add(name, value string) error {
	name = textproto.CanonicalMIMEHeaderKey(name)
	if disallowedHeaders[name] {
		return errors.New(disallowedErrorMessage)
	}
	if h.immutable[name] {
		return errors.New(immutableErrorMessage)
	}
	h.wrapped.Add(name, value)
	return nil
}

// Del deletes all headers with the given name. The name is first
// canonicalized using textproto.CanonicalMIMEHeaderKey. Returns an
// error when applied on immutable headers.
func (h Header) Del(name string) error {
	name = textproto.CanonicalMIMEHeaderKey(name)
	if disallowedHeaders[name] {
		return errors.New(disallowedErrorMessage)
	}
	if h.immutable[name] {
		return errors.New(immutableErrorMessage)
	}
	h.wrapped.Del(name)
	return nil
}

// Get returns the value of the first header with the given name.
// The name is first canonicalized using textproto.CanonicalMIMEHeaderKey.
// If no header exists with the given name then "" is returned.
func (h Header) Get(name string) string {
	return h.wrapped.Get(name)
}

// Values returns all the values of all the headers with the given name.
// The name is first canonicalized using textproto.CanonicalMIMEHeaderKey.
// If no header exists with the name `name` then nil is returned.
func (h Header) Values(name string) []string {
	return h.wrapped.Values(name)
}

// SetCookie adds the cookie provided as a Set-Cookie header in the header
// collection.
// TODO: Replace http.Cookie with safehttp.Cookie.
func (h Header) SetCookie(cookie *http.Cookie) {
	if v := cookie.String(); v != "" {
		h.wrapped.Add("Set-Cookie", v)
	}
}

// TODO: Add Write, WriteSubset and Clone when needed.
<commit_msg>Clarified comment<commit_after>// Copyright 2020 Google LLC
//
// 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
//
// 	https://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 safehttp

import (
	"errors"
	"net/http"
	"net/textproto"
)

var disallowedHeaders = map[string]bool{"Set-Cookie": true}

const (
	disallowedErrorMessage = "disallowed header"
	immutableErrorMessage  = "immutable header"
)

// Header represents the key-value pairs in an HTTP header.
// The keys will be in canonical form, as returned by
// textproto.CanonicalMIMEHeaderKey.
type Header struct {
	wrapped   http.Header
	immutable map[string]bool
}

func newHeader(h http.Header) Header {
	return Header{wrapped: h, immutable: map[string]bool{}}
}

// MarkImmutable marks the header with the given name as immutable.
// This header is now read-only. The name is first canonicalized
// using textproto.CanonicalMIMEHeaderKey.
func (h Header) MarkImmutable(name string) {
	name = textproto.CanonicalMIMEHeaderKey(name)
	h.immutable[name] = true
}

// Set sets the header with the given name to the given value.
// The name is first canonicalized using textproto.CanonicalMIMEHeaderKey.
// If this headers is not immutable, this function removes all other
// values currently associated with this header before setting the new
// value. Returns an error when applied on immutable headers.
func (h Header) Set(name, value string) error {
	name = textproto.CanonicalMIMEHeaderKey(name)
	if disallowedHeaders[name] {
		return errors.New(disallowedErrorMessage)
	}
	if h.immutable[name] {
		return errors.New(immutableErrorMessage)
	}
	h.wrapped.Set(name, value)
	return nil
}

// Add adds a new header with the given name and the given value to
// the collection of headers. The name is first canonicalized using
// textproto.CanonicalMIMEHeaderKey. Returns an error when applied
// on immutable headers.
func (h Header) Add(name, value string) error {
	name = textproto.CanonicalMIMEHeaderKey(name)
	if disallowedHeaders[name] {
		return errors.New(disallowedErrorMessage)
	}
	if h.immutable[name] {
		return errors.New(immutableErrorMessage)
	}
	h.wrapped.Add(name, value)
	return nil
}

// Del deletes all headers with the given name. The name is first
// canonicalized using textproto.CanonicalMIMEHeaderKey. Returns an
// error when applied on immutable headers.
func (h Header) Del(name string) error {
	name = textproto.CanonicalMIMEHeaderKey(name)
	if disallowedHeaders[name] {
		return errors.New(disallowedErrorMessage)
	}
	if h.immutable[name] {
		return errors.New(immutableErrorMessage)
	}
	h.wrapped.Del(name)
	return nil
}

// Get returns the value of the first header with the given name.
// The name is first canonicalized using textproto.CanonicalMIMEHeaderKey.
// If no header exists with the given name then "" is returned.
func (h Header) Get(name string) string {
	return h.wrapped.Get(name)
}

// Values returns all the values of all the headers with the given name.
// The name is first canonicalized using textproto.CanonicalMIMEHeaderKey.
// If no header exists with the name `name` then nil is returned.
func (h Header) Values(name string) []string {
	return h.wrapped.Values(name)
}

// SetCookie adds the cookie provided as a Set-Cookie header in the header
// collection. If the cookie is nil or cookie.Name is invalid, an empty
// string is returned.
// TODO: Replace http.Cookie with safehttp.Cookie.
func (h Header) SetCookie(cookie *http.Cookie) {
	if v := cookie.String(); v != "" {
		h.wrapped.Add("Set-Cookie", v)
	}
}

// TODO: Add Write, WriteSubset and Clone when needed.
<|endoftext|>