<commit_before>// Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package webp

/*
#cgo CFLAGS: -I./libwebp/include  -I./libwebp/src -DWEBP_EXPERIMENTAL_FEATURES

#include "webp.h"
*/
import "C"
import (
	"errors"
	"unsafe"
)

func webpGetInfo(data []byte) (width, height int, has_alpha bool, err error) {
	if len(data) == 0 {
		err = errors.New("webpGetInfo: bad arguments")
		return
	}
	var c_width, c_height, c_has_alpha C.int
	rv := C.webpGetInfo(
		(*C.uint8_t)(unsafe.Pointer(&data[0])), C.size_t(len(data)),
		&c_width, &c_height, &c_has_alpha,
	)
	if rv == 0 {
		err = errors.New("webpGetInfo: failed")
		return
	}
	width, height = int(c_width), int(c_height)
	has_alpha = (c_has_alpha != 0)
	return
}

func webpDecodeGray(data []byte) (pix []byte, width, height int, err error) {
	if len(data) == 0 {
		err = errors.New("webpDecodeGray: bad arguments")
		return
	}
	var c_width, c_height C.int
	d := C.webpDecodeGray(
		(*C.uint8_t)(unsafe.Pointer(&data[0])), C.size_t(len(data)),
		&c_width, &c_height,
	)
	if d == nil {
		err = errors.New("webpDecodeGray: failed")
		return
	}
	width, height = int(c_width), int(c_height)
	pix = make([]byte, width*height*1)
	copy(pix, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(pix):len(pix)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpDecodeRGB(data []byte) (pix []byte, width, height int, err error) {
	if len(data) == 0 {
		err = errors.New("webpDecodeRGB: bad arguments")
		return
	}
	var c_width, c_height C.int
	d := C.webpDecodeRGB(
		(*C.uint8_t)(unsafe.Pointer(&data[0])), C.size_t(len(data)),
		&c_width, &c_height,
	)
	if d == nil {
		err = errors.New("webpDecodeRGB: failed")
		return
	}
	width, height = int(c_width), int(c_height)
	pix = make([]byte, width*height*3)
	copy(pix, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(pix):len(pix)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpDecodeRGBA(data []byte) (pix []byte, width, height int, err error) {
	if len(data) == 0 {
		err = errors.New("webpDecodeRGBA: bad arguments")
		return
	}
	var c_width, c_height C.int
	d := C.webpDecodeRGBA(
		(*C.uint8_t)(unsafe.Pointer(&data[0])), C.size_t(len(data)),
		&c_width, &c_height,
	)
	if d == nil {
		err = errors.New("webpDecodeRGBA: failed")
		return
	}
	width, height = int(c_width), int(c_height)
	pix = make([]byte, width*height*4)
	copy(pix, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(pix):len(pix)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpEncodeGray(
	pix []byte, width, height, stride int,
	quality_factor float32,
) (output []byte, err error) {
	if len(pix) == 0 || width <= 0 || height <= 0 || stride <= 0 || quality_factor < 0.0 {
		err = errors.New("webpEncodeGray: bad arguments")
		return
	}
	if stride < width*1 && len(pix) < height*stride {
		err = errors.New("webpEncodeGray: bad arguments")
		return
	}
	var d *C.uint8_t
	d_size := C.webpEncodeGray(
		(*C.uint8_t)(unsafe.Pointer(&pix[0])), C.int(width), C.int(height),
		C.int(stride), C.float(quality_factor),
		&d,
	)
	if d_size == 0 {
		err = errors.New("webpEncodeGray: failed")
		return
	}
	output = make([]byte, int(d_size))
	copy(output, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(output):len(output)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpEncodeRGB(
	pix []byte, width, height, stride int,
	quality_factor float32,
) (output []byte, err error) {
	if len(pix) == 0 || width <= 0 || height <= 0 || stride <= 0 || quality_factor < 0.0 {
		err = errors.New("webpEncodeRGB: bad arguments")
		return
	}
	if stride < width*3 && len(pix) < height*stride {
		err = errors.New("webpEncodeRGB: bad arguments")
		return
	}
	var d *C.uint8_t
	d_size := C.webpEncodeRGB(
		(*C.uint8_t)(unsafe.Pointer(&pix[0])), C.int(width), C.int(height),
		C.int(stride), C.float(quality_factor),
		&d,
	)
	if d_size == 0 {
		err = errors.New("webpEncodeRGB: failed")
		return
	}
	output = make([]byte, int(d_size))
	copy(output, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(output):len(output)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpEncodeRGBA(
	pix []byte, width, height, stride int,
	quality_factor float32,
) (output []byte, err error) {
	if len(pix) == 0 || width <= 0 || height <= 0 || stride <= 0 || quality_factor < 0.0 {
		err = errors.New("webpEncodeRGBA: bad arguments")
		return
	}
	if stride < width*4 && len(pix) < height*stride {
		err = errors.New("webpEncodeRGBA: bad arguments")
		return
	}
	var d *C.uint8_t
	d_size := C.webpEncodeRGBA(
		(*C.uint8_t)(unsafe.Pointer(&pix[0])), C.int(width), C.int(height),
		C.int(stride), C.float(quality_factor),
		&d,
	)
	if d_size == 0 {
		err = errors.New("webpEncodeRGBA: failed")
		return
	}
	output = make([]byte, int(d_size))
	copy(output, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(output):len(output)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpEncodeLosslessGray(
	pix []byte, width, height, stride int,
) (output []byte, err error) {
	if len(pix) == 0 || width <= 0 || height <= 0 || stride <= 0 {
		err = errors.New("webpEncodeLosslessGray: bad arguments")
		return
	}
	if stride < width*1 && len(pix) < height*stride {
		err = errors.New("webpEncodeLosslessGray: bad arguments")
		return
	}
	var d *C.uint8_t
	d_size := C.webpEncodeLosslessGray(
		(*C.uint8_t)(unsafe.Pointer(&pix[0])), C.int(width), C.int(height),
		C.int(stride),
		&d,
	)
	if d_size == 0 {
		err = errors.New("webpEncodeLosslessGray: failed")
		return
	}
	output = make([]byte, int(d_size))
	copy(output, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(output):len(output)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpEncodeLosslessRGB(
	pix []byte, width, height, stride int,
) (output []byte, err error) {
	if len(pix) == 0 || width <= 0 || height <= 0 || stride <= 0 {
		err = errors.New("webpEncodeLosslessRGB: bad arguments")
		return
	}
	if stride < width*3 && len(pix) < height*stride {
		err = errors.New("webpEncodeLosslessRGB: bad arguments")
		return
	}
	var d *C.uint8_t
	d_size := C.webpEncodeLosslessRGB(
		(*C.uint8_t)(unsafe.Pointer(&pix[0])), C.int(width), C.int(height),
		C.int(stride),
		&d,
	)
	if d_size == 0 {
		err = errors.New("webpEncodeLosslessRGB: failed")
		return
	}
	output = make([]byte, int(d_size))
	copy(output, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(output):len(output)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpEncodeLosslessRGBA(
	pix []byte, width, height, stride int,
) (output []byte, err error) {
	if len(pix) == 0 || width <= 0 || height <= 0 || stride <= 0 {
		err = errors.New("webpEncodeLosslessRGBA: bad arguments")
		return
	}
	if stride < width*4 && len(pix) < height*stride {
		err = errors.New("webpEncodeLosslessRGBA: bad arguments")
		return
	}
	var d *C.uint8_t
	d_size := C.webpEncodeLosslessRGBA(
		(*C.uint8_t)(unsafe.Pointer(&pix[0])), C.int(width), C.int(height),
		C.int(stride),
		&d,
	)
	if d_size == 0 {
		err = errors.New("webpEncodeLosslessRGBA: failed")
		return
	}
	output = make([]byte, int(d_size))
	copy(output, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(output):len(output)])
	C.webpFree(unsafe.Pointer(d))
	return
}
<commit_msg>BUG: Build error, the reason is the math lib missing on linux.<commit_after>// Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package webp

/*
#cgo CFLAGS: -I./libwebp/include  -I./libwebp/src -DWEBP_EXPERIMENTAL_FEATURES
#cgo !windows LDFLAGS: -lm

#include "webp.h"
*/
import "C"
import (
	"errors"
	"unsafe"
)

func webpGetInfo(data []byte) (width, height int, has_alpha bool, err error) {
	if len(data) == 0 {
		err = errors.New("webpGetInfo: bad arguments")
		return
	}
	var c_width, c_height, c_has_alpha C.int
	rv := C.webpGetInfo(
		(*C.uint8_t)(unsafe.Pointer(&data[0])), C.size_t(len(data)),
		&c_width, &c_height, &c_has_alpha,
	)
	if rv == 0 {
		err = errors.New("webpGetInfo: failed")
		return
	}
	width, height = int(c_width), int(c_height)
	has_alpha = (c_has_alpha != 0)
	return
}

func webpDecodeGray(data []byte) (pix []byte, width, height int, err error) {
	if len(data) == 0 {
		err = errors.New("webpDecodeGray: bad arguments")
		return
	}
	var c_width, c_height C.int
	d := C.webpDecodeGray(
		(*C.uint8_t)(unsafe.Pointer(&data[0])), C.size_t(len(data)),
		&c_width, &c_height,
	)
	if d == nil {
		err = errors.New("webpDecodeGray: failed")
		return
	}
	width, height = int(c_width), int(c_height)
	pix = make([]byte, width*height*1)
	copy(pix, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(pix):len(pix)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpDecodeRGB(data []byte) (pix []byte, width, height int, err error) {
	if len(data) == 0 {
		err = errors.New("webpDecodeRGB: bad arguments")
		return
	}
	var c_width, c_height C.int
	d := C.webpDecodeRGB(
		(*C.uint8_t)(unsafe.Pointer(&data[0])), C.size_t(len(data)),
		&c_width, &c_height,
	)
	if d == nil {
		err = errors.New("webpDecodeRGB: failed")
		return
	}
	width, height = int(c_width), int(c_height)
	pix = make([]byte, width*height*3)
	copy(pix, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(pix):len(pix)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpDecodeRGBA(data []byte) (pix []byte, width, height int, err error) {
	if len(data) == 0 {
		err = errors.New("webpDecodeRGBA: bad arguments")
		return
	}
	var c_width, c_height C.int
	d := C.webpDecodeRGBA(
		(*C.uint8_t)(unsafe.Pointer(&data[0])), C.size_t(len(data)),
		&c_width, &c_height,
	)
	if d == nil {
		err = errors.New("webpDecodeRGBA: failed")
		return
	}
	width, height = int(c_width), int(c_height)
	pix = make([]byte, width*height*4)
	copy(pix, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(pix):len(pix)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpEncodeGray(
	pix []byte, width, height, stride int,
	quality_factor float32,
) (output []byte, err error) {
	if len(pix) == 0 || width <= 0 || height <= 0 || stride <= 0 || quality_factor < 0.0 {
		err = errors.New("webpEncodeGray: bad arguments")
		return
	}
	if stride < width*1 && len(pix) < height*stride {
		err = errors.New("webpEncodeGray: bad arguments")
		return
	}
	var d *C.uint8_t
	d_size := C.webpEncodeGray(
		(*C.uint8_t)(unsafe.Pointer(&pix[0])), C.int(width), C.int(height),
		C.int(stride), C.float(quality_factor),
		&d,
	)
	if d_size == 0 {
		err = errors.New("webpEncodeGray: failed")
		return
	}
	output = make([]byte, int(d_size))
	copy(output, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(output):len(output)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpEncodeRGB(
	pix []byte, width, height, stride int,
	quality_factor float32,
) (output []byte, err error) {
	if len(pix) == 0 || width <= 0 || height <= 0 || stride <= 0 || quality_factor < 0.0 {
		err = errors.New("webpEncodeRGB: bad arguments")
		return
	}
	if stride < width*3 && len(pix) < height*stride {
		err = errors.New("webpEncodeRGB: bad arguments")
		return
	}
	var d *C.uint8_t
	d_size := C.webpEncodeRGB(
		(*C.uint8_t)(unsafe.Pointer(&pix[0])), C.int(width), C.int(height),
		C.int(stride), C.float(quality_factor),
		&d,
	)
	if d_size == 0 {
		err = errors.New("webpEncodeRGB: failed")
		return
	}
	output = make([]byte, int(d_size))
	copy(output, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(output):len(output)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpEncodeRGBA(
	pix []byte, width, height, stride int,
	quality_factor float32,
) (output []byte, err error) {
	if len(pix) == 0 || width <= 0 || height <= 0 || stride <= 0 || quality_factor < 0.0 {
		err = errors.New("webpEncodeRGBA: bad arguments")
		return
	}
	if stride < width*4 && len(pix) < height*stride {
		err = errors.New("webpEncodeRGBA: bad arguments")
		return
	}
	var d *C.uint8_t
	d_size := C.webpEncodeRGBA(
		(*C.uint8_t)(unsafe.Pointer(&pix[0])), C.int(width), C.int(height),
		C.int(stride), C.float(quality_factor),
		&d,
	)
	if d_size == 0 {
		err = errors.New("webpEncodeRGBA: failed")
		return
	}
	output = make([]byte, int(d_size))
	copy(output, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(output):len(output)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpEncodeLosslessGray(
	pix []byte, width, height, stride int,
) (output []byte, err error) {
	if len(pix) == 0 || width <= 0 || height <= 0 || stride <= 0 {
		err = errors.New("webpEncodeLosslessGray: bad arguments")
		return
	}
	if stride < width*1 && len(pix) < height*stride {
		err = errors.New("webpEncodeLosslessGray: bad arguments")
		return
	}
	var d *C.uint8_t
	d_size := C.webpEncodeLosslessGray(
		(*C.uint8_t)(unsafe.Pointer(&pix[0])), C.int(width), C.int(height),
		C.int(stride),
		&d,
	)
	if d_size == 0 {
		err = errors.New("webpEncodeLosslessGray: failed")
		return
	}
	output = make([]byte, int(d_size))
	copy(output, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(output):len(output)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpEncodeLosslessRGB(
	pix []byte, width, height, stride int,
) (output []byte, err error) {
	if len(pix) == 0 || width <= 0 || height <= 0 || stride <= 0 {
		err = errors.New("webpEncodeLosslessRGB: bad arguments")
		return
	}
	if stride < width*3 && len(pix) < height*stride {
		err = errors.New("webpEncodeLosslessRGB: bad arguments")
		return
	}
	var d *C.uint8_t
	d_size := C.webpEncodeLosslessRGB(
		(*C.uint8_t)(unsafe.Pointer(&pix[0])), C.int(width), C.int(height),
		C.int(stride),
		&d,
	)
	if d_size == 0 {
		err = errors.New("webpEncodeLosslessRGB: failed")
		return
	}
	output = make([]byte, int(d_size))
	copy(output, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(output):len(output)])
	C.webpFree(unsafe.Pointer(d))
	return
}

func webpEncodeLosslessRGBA(
	pix []byte, width, height, stride int,
) (output []byte, err error) {
	if len(pix) == 0 || width <= 0 || height <= 0 || stride <= 0 {
		err = errors.New("webpEncodeLosslessRGBA: bad arguments")
		return
	}
	if stride < width*4 && len(pix) < height*stride {
		err = errors.New("webpEncodeLosslessRGBA: bad arguments")
		return
	}
	var d *C.uint8_t
	d_size := C.webpEncodeLosslessRGBA(
		(*C.uint8_t)(unsafe.Pointer(&pix[0])), C.int(width), C.int(height),
		C.int(stride),
		&d,
	)
	if d_size == 0 {
		err = errors.New("webpEncodeLosslessRGBA: failed")
		return
	}
	output = make([]byte, int(d_size))
	copy(output, ((*[1 << 30]byte)(unsafe.Pointer(d)))[0:len(output):len(output)])
	C.webpFree(unsafe.Pointer(d))
	return
}
<|endoftext|>


<commit_before>package libvirt

import (
	"fmt"
	"io"
	"log"
	"strconv"
	"strings"
	"time"

	libvirt "github.com/digitalocean/go-libvirt"
)

func newCopier(virConn *libvirt.Libvirt, volume *libvirt.StorageVol, size uint64) func(src io.Reader) error {
	copier := func(src io.Reader) error {
		// FIXME - validate behaviour
		// https://github.com/digitalocean/go-libvirt/pull/63/files#

		r, w := io.Pipe()
		defer func() {
			cerr := w.Close()
			if cerr != nil {
				log.Printf("Error while closing IO stream %s", cerr)
			}
		}()

		if err := virConn.StorageVolUpload(*volume, r, 0, size, 0); err != nil {
			return fmt.Errorf("Error while uploading volume %s", err)
		}

		bytesCopied, err := io.Copy(w, src)
		cerr := w.Close()

		// if we get unexpected EOF this mean that connection was closed suddently from server side
		// the problem is not on the plugin but on server hosting currupted images
		if err == io.ErrUnexpectedEOF {
			return fmt.Errorf("Error: transfer was unexpectedly closed from the server while downloading. Please try again later or check the server hosting sources")
		}
		if err != nil {
			return fmt.Errorf("Error while copying source to volume %s", err)
		}
		if cerr != nil {
			return fmt.Errorf("Error while closing IO stream %s", cerr)
		}

		log.Printf("%d bytes uploaded\n", bytesCopied)
		if uint64(bytesCopied) != size {
			return fmt.Errorf("Error during volume Upload. BytesCopied: %d != %d volume.size", bytesCopied, size)
		}

		return nil
	}
	return copier
}

func timeFromEpoch(str string) time.Time {
	var s, ns int

	ts := strings.Split(str, ".")
	if len(ts) == 2 {
		ns, _ = strconv.Atoi(ts[1])
	}
	s, _ = strconv.Atoi(ts[0])

	return time.Unix(int64(s), int64(ns))
}
<commit_msg>port - pipe in goroutine so can close - TBC pipe required<commit_after>package libvirt

import (
	"fmt"
	"io"
	"log"
	"strconv"
	"strings"
	"time"

	libvirt "github.com/digitalocean/go-libvirt"
)

func newCopier(virConn *libvirt.Libvirt, volume *libvirt.StorageVol, size uint64) func(src io.Reader) error {
	copier := func(src io.Reader) error {
		r, w := io.Pipe()
		defer w.Close()

		go func() error {
			bytesCopied, err := io.Copy(w, src)

			// if we get unexpected EOF this mean that connection was closed suddently from server side
			// the problem is not on the plugin but on server hosting currupted images
			if err == io.ErrUnexpectedEOF {
				return fmt.Errorf("Error: transfer was unexpectedly closed from the server while downloading. Please try again later or check the server hosting sources")
			}
			if err != nil {
				return fmt.Errorf("Error while copying source to volume %s", err)
			}

			log.Printf("%d bytes uploaded\n", bytesCopied)
			if uint64(bytesCopied) != size {
				return fmt.Errorf("Error during volume Upload. BytesCopied: %d != %d volume.size", bytesCopied, size)
			}

			return w.Close()

		}()

		/*
			* FIXME: use alternate simpler implementation without pipe?
				if err := virConn.StorageVolUpload(*volume, src, 0, size, 0); err != nil {
					return fmt.Errorf("Error while uploading volume %s", err)
				}
		*/

		if err := virConn.StorageVolUpload(*volume, r, 0, size, 0); err != nil {
			return fmt.Errorf("Error while uploading volume %s", err)
		}

		return nil
	}
	return copier
}

func timeFromEpoch(str string) time.Time {
	var s, ns int

	ts := strings.Split(str, ".")
	if len(ts) == 2 {
		ns, _ = strconv.Atoi(ts[1])
	}
	s, _ = strconv.Atoi(ts[0])

	return time.Unix(int64(s), int64(ns))
}
<|endoftext|>


<commit_before>package trello

import (
	"encoding/json"
	"net/url"
	"time"
)

const cardurl = "cards"

type Card struct {
	//	Badges
	//	CheckItemStates
	Closed           bool
	DateLastActivity *time.Time
	Desc             string
	//	DescData
	Due *time.Time
	Id  string
	//	IdAttachmentCover
	IdBoard string
	//	IdChecklists
	IdList         string
	IdMembers      []string
	IdMembersVoted []string
	IdShort        float64
	//	Labels                []string
	ManualCoverAttachment bool
	Name                  string
	Pos                   float64
	ShortLink             string
	ShortUrl              string
	Subscribed            bool
	Url                   string
	c                     *Client `json"-"`
}

// Card retrieves a trello card by ID
func (c *Client) Card(id string) (*Card, error) {
	b, err := c.Request("GET", cardurl+"/"+id, nil, nil)

	if err != nil {
		return nil, err
	}

	card := Card{
		c: c,
	}

	err = json.Unmarshal(b, &card)
	if err != nil {
		return nil, err
	}

	return &card, nil
}

func (c *Card) AddComment(comment string) error {
	extra := url.Values{"text": {comment}}
	_, err := c.c.Request("POST", cardurl+"/"+c.Id+"/actions/comments", nil, extra)
	if err != nil {
		return err
	}
	return nil
}

// AddChecklist created a new checklist on the card.
func (c *Card) AddChecklist(name string) (*Checklist, error) {
	qp := url.Values{"name":{name}}
	b, err := c.c.Request("POST", cardurl+"/"+c.Id+"/checklists", nil, qp)
	if err != nil {
		return nil, err
	}

	var cl *Checklist
	err = json.Unmarshal(b, &cl)
	return cl, err
}

// Checklists retrieves all checklists from a trello card
func (c *Card) Checklists() ([]*Checklist, error) {
	b, err := c.c.Request("GET", cardurl+"/"+c.Id+"/checklists", nil, nil)
	if err != nil {
		return nil, err
	}

	var checklists []*Checklist

	err = json.Unmarshal(b, &checklists)
	if err != nil {
		return nil, err
	}

	for _, checklist := range checklists {
		checklist.c = c.c
		for _, ci := range checklist.CheckItems {
			ci.c = c.c
		}
	}

	return checklists, nil
}

// Actions retrieves a list of all actions (e.g. events, activity)
// performed on a card
func (c *Card) Actions() ([]*Action, error) {
	b, err := c.c.Request("GET", cardurl+"/"+c.Id+"/actions", nil, nil)
	if err != nil {
		return nil, err
	}

	var act []*Action

	err = json.Unmarshal(b, &act)

	if err != nil {
		return nil, err
	}

	for _, a := range act {
		a.c = c.c
	}

	return act, nil
}
<commit_msg>correct struct tag to ignore Client<commit_after>package trello

import (
	"encoding/json"
	"net/url"
	"time"
)

const cardurl = "cards"

type Card struct {
	//	Badges
	//	CheckItemStates
	Closed           bool
	DateLastActivity *time.Time
	Desc             string
	//	DescData
	Due *time.Time
	Id  string
	//	IdAttachmentCover
	IdBoard string
	//	IdChecklists
	IdList         string
	IdMembers      []string
	IdMembersVoted []string
	IdShort        float64
	//	Labels                []string
	ManualCoverAttachment bool
	Name                  string
	Pos                   float64
	ShortLink             string
	ShortUrl              string
	Subscribed            bool
	Url                   string
	c                     *Client `json:"-"`
}

// Card retrieves a trello card by ID
func (c *Client) Card(id string) (*Card, error) {
	b, err := c.Request("GET", cardurl+"/"+id, nil, nil)

	if err != nil {
		return nil, err
	}

	card := Card{
		c: c,
	}

	err = json.Unmarshal(b, &card)
	if err != nil {
		return nil, err
	}

	return &card, nil
}

func (c *Card) AddComment(comment string) error {
	extra := url.Values{"text": {comment}}
	_, err := c.c.Request("POST", cardurl+"/"+c.Id+"/actions/comments", nil, extra)
	if err != nil {
		return err
	}
	return nil
}

// AddChecklist created a new checklist on the card.
func (c *Card) AddChecklist(name string) (*Checklist, error) {
	qp := url.Values{"name":{name}}
	b, err := c.c.Request("POST", cardurl+"/"+c.Id+"/checklists", nil, qp)
	if err != nil {
		return nil, err
	}

	var cl *Checklist
	err = json.Unmarshal(b, &cl)
	return cl, err
}

// Checklists retrieves all checklists from a trello card
func (c *Card) Checklists() ([]*Checklist, error) {
	b, err := c.c.Request("GET", cardurl+"/"+c.Id+"/checklists", nil, nil)
	if err != nil {
		return nil, err
	}

	var checklists []*Checklist

	err = json.Unmarshal(b, &checklists)
	if err != nil {
		return nil, err
	}

	for _, checklist := range checklists {
		checklist.c = c.c
		for _, ci := range checklist.CheckItems {
			ci.c = c.c
		}
	}

	return checklists, nil
}

// Actions retrieves a list of all actions (e.g. events, activity)
// performed on a card
func (c *Card) Actions() ([]*Action, error) {
	b, err := c.c.Request("GET", cardurl+"/"+c.Id+"/actions", nil, nil)
	if err != nil {
		return nil, err
	}

	var act []*Action

	err = json.Unmarshal(b, &act)

	if err != nil {
		return nil, err
	}

	for _, a := range act {
		a.c = c.c
	}

	return act, nil
}
<|endoftext|>


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

import (
	"context"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"strconv"
	"strings"

	"kythe.io/kythe/go/platform/vfs"
	"kythe.io/kythe/go/services/xrefs"
	"kythe.io/kythe/go/util/kytheuri"
	"kythe.io/kythe/go/util/schema/facts"

	cpb "kythe.io/kythe/proto/common_proto"
	xpb "kythe.io/kythe/proto/xref_proto"
)

var (
	// DefaultFileCorpus is the --corpus flag used by source/decor/diagnostics
	// commands to construct a file ticket from a raw file path.
	DefaultFileCorpus string

	// DefaultFileRoot is the --root flag used by source/decor/diagnostics commands
	// to construct a file ticket from a raw file path.
	DefaultFileRoot string

	// DefaultFilePathPrefix is the --path_prefix flag used by
	// source/decor/diagnostics commands to construct a file ticket from a raw file
	// path.
	DefaultFilePathPrefix string
)

// baseDecorCommand is a shared base for the source/decor/diagnostics commands
type baseDecorCommand struct {
	decorSpan                string
	corpus, root, pathPrefix string
}

func (c *baseDecorCommand) SetFlags(flag *flag.FlagSet) {
	flag.StringVar(&c.decorSpan, "span", "",
		`Limit results to this span (e.g. "10-30", "b1462-b1847", "3:5-3:10")
      Formats:
        b\d+-b\d+             -- Byte-offsets
        \d+(:\d+)?-\d+(:\d+)? -- Line offsets with optional column offsets`)
	flag.StringVar(&c.corpus, "corpus", DefaultFileCorpus, "File corpus to use if given a raw path")
	flag.StringVar(&c.root, "root", DefaultFileRoot, "File root to use if given a raw path")
	flag.StringVar(&c.pathPrefix, "path_prefix", DefaultFilePathPrefix, "File path prefix to use if given a raw path (this is prepended directly to the raw path without any joining slashes)")
}

func (c baseDecorCommand) fileTicketArg(flag *flag.FlagSet) (string, error) {
	if flag.NArg() < 0 {
		return "", errors.New("no file given")
	}
	file := flag.Arg(0)
	if strings.HasPrefix(file, kytheuri.Scheme) {
		return file, nil
	}
	return (&kytheuri.URI{
		Corpus: c.corpus,
		Root:   c.root,
		Path:   c.pathPrefix + file,
	}).String(), nil
}

func (c baseDecorCommand) baseRequest(flag *flag.FlagSet) (*xpb.DecorationsRequest, error) {
	ticket, err := c.fileTicketArg(flag)
	if err != nil {
		return nil, err
	}
	req := &xpb.DecorationsRequest{
		Location: &xpb.Location{Ticket: ticket},
	}
	span, err := c.spanArg()
	if err != nil {
		return nil, err
	} else if span != nil {
		req.Location.Kind = xpb.Location_SPAN
		req.Location.Span = span
	}
	return req, nil
}

func (c baseDecorCommand) spanArg() (*cpb.Span, error) {
	if c.decorSpan == "" {
		return nil, nil
	}
	span, err := parseSpan(c.decorSpan)
	if err != nil {
		return nil, fmt.Errorf("invalid --span %q: %v", c.decorSpan, err)
	}
	return span, nil
}

type decorCommand struct {
	baseDecorCommand
	targetDefs       bool
	dirtyFile        string
	refFormat        string
	extendsOverrides bool
}

func (decorCommand) Name() string     { return "decor" }
func (decorCommand) Synopsis() string { return "list a file's decorations" }
func (decorCommand) Usage() string    { return "" }
func (c *decorCommand) SetFlags(flag *flag.FlagSet) {
	c.baseDecorCommand.SetFlags(flag)
	// TODO(schroederc): add option to look for dirty files based on file-ticket path and a directory root
	flag.StringVar(&c.dirtyFile, "dirty", "", "Send the given file as the dirty buffer for patching references")
	flag.StringVar(&c.refFormat, "format", "@edgeKind@\t@^line@:@^col@-@$line@:@$col@\t@targetKind@\t@target@",
		`Format for each decoration result.
      Format Markers:
        @target@     -- ticket of referenced target node
        @targetDef@  -- ticket of referenced target's definition
        @edgeKind@   -- edge kind from anchor node to its referenced target
        @targetKind@ -- node kind and subkind of referenced target
        @nodeKind@   -- node kind of referenced target
        @subkind@    -- subkind of referenced target
        @^offset@    -- anchor source's starting byte-offset
        @^line@      -- anchor source's starting line
        @^col@       -- anchor source's starting column offset
        @$offset@    -- anchor source's ending byte-offset
        @$line@      -- anchor source's ending line
        @$col@       -- anchor source's ending column offset`)
	flag.BoolVar(&c.targetDefs, "target_definitions", false, "Whether to request definitions (@targetDef@ format marker) for each reference's target")
	flag.BoolVar(&c.extendsOverrides, "extends_overrides", false, "Whether to request extends/overrides information")
}
func (c decorCommand) Run(ctx context.Context, flag *flag.FlagSet, api API) error {
	req, err := c.baseRequest(flag)
	if err != nil {
		return err
	}
	req.References = true
	req.TargetDefinitions = c.targetDefs
	req.ExtendsOverrides = c.extendsOverrides
	req.Filter = []string{
		facts.NodeKind,
		facts.Subkind,
	}
	if c.dirtyFile != "" {
		f, err := vfs.Open(ctx, c.dirtyFile)
		if err != nil {
			return fmt.Errorf("error opening dirty buffer file at %q: %v", c.dirtyFile, err)
		}
		buf, err := ioutil.ReadAll(f)
		if err != nil {
			f.Close()
			return fmt.Errorf("error reading dirty buffer file: %v", err)
		} else if err := f.Close(); err != nil {
			return fmt.Errorf("error closing dirty buffer file: %v", err)
		}
		req.DirtyBuffer = buf
	}

	LogRequest(req)
	reply, err := api.XRefService.Decorations(ctx, req)
	if err != nil {
		return err
	}

	return c.displayDecorations(reply)
}

func (c decorCommand) displayDecorations(decor *xpb.DecorationsReply) error {
	if DisplayJSON {
		return PrintJSONMessage(decor)
	}

	nodes := xrefs.NodesMap(decor.Nodes)

	for _, ref := range decor.Reference {
		nodeKind := factValue(nodes, ref.TargetTicket, facts.NodeKind, "UNKNOWN")
		subkind := factValue(nodes, ref.TargetTicket, facts.Subkind, "")

		tgtKind := nodeKind
		if subkind != "" {
			tgtKind += "/" + subkind
		}

		var targetDef string
		if ref.TargetDefinition != "" {
			targetDef = ref.TargetDefinition
			// TODO(schroederc): fields from decor.DefinitionLocations
			// TODO(zarko): fields from decor.ExtendsOverrides
		}

		r := strings.NewReplacer(
			"@target@", ref.TargetTicket,
			"@edgeKind@", ref.Kind,
			"@targetKind@", tgtKind,
			"@nodeKind@", nodeKind,
			"@subkind@", subkind,
			"@^offset@", itoa(ref.Span.Start.ByteOffset),
			"@^line@", itoa(ref.Span.Start.LineNumber),
			"@^col@", itoa(ref.Span.Start.ColumnOffset),
			"@$offset@", itoa(ref.Span.End.ByteOffset),
			"@$line@", itoa(ref.Span.End.LineNumber),
			"@$col@", itoa(ref.Span.End.ColumnOffset),
			"@targetDef@", targetDef,
		)
		if _, err := r.WriteString(out, c.refFormat+"\n"); err != nil {
			return err
		}
	}

	return nil
}

func itoa(n int32) string { return strconv.Itoa(int(n)) }

func factValue(m map[string]map[string][]byte, ticket, factName, def string) string {
	if n, ok := m[ticket]; ok {
		if val, ok := n[factName]; ok {
			return string(val)
		}
	}
	return def
}
<commit_msg>kythe tool: by default, print --target_definitions if requested<commit_after>/*
 * Copyright 2017 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 cli

import (
	"context"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"strconv"
	"strings"

	"kythe.io/kythe/go/platform/vfs"
	"kythe.io/kythe/go/services/xrefs"
	"kythe.io/kythe/go/util/kytheuri"
	"kythe.io/kythe/go/util/schema/facts"

	cpb "kythe.io/kythe/proto/common_proto"
	xpb "kythe.io/kythe/proto/xref_proto"
)

var (
	// DefaultFileCorpus is the --corpus flag used by source/decor/diagnostics
	// commands to construct a file ticket from a raw file path.
	DefaultFileCorpus string

	// DefaultFileRoot is the --root flag used by source/decor/diagnostics commands
	// to construct a file ticket from a raw file path.
	DefaultFileRoot string

	// DefaultFilePathPrefix is the --path_prefix flag used by
	// source/decor/diagnostics commands to construct a file ticket from a raw file
	// path.
	DefaultFilePathPrefix string
)

// baseDecorCommand is a shared base for the source/decor/diagnostics commands
type baseDecorCommand struct {
	decorSpan                string
	corpus, root, pathPrefix string
}

func (c *baseDecorCommand) SetFlags(flag *flag.FlagSet) {
	flag.StringVar(&c.decorSpan, "span", "",
		`Limit results to this span (e.g. "10-30", "b1462-b1847", "3:5-3:10")
      Formats:
        b\d+-b\d+             -- Byte-offsets
        \d+(:\d+)?-\d+(:\d+)? -- Line offsets with optional column offsets`)
	flag.StringVar(&c.corpus, "corpus", DefaultFileCorpus, "File corpus to use if given a raw path")
	flag.StringVar(&c.root, "root", DefaultFileRoot, "File root to use if given a raw path")
	flag.StringVar(&c.pathPrefix, "path_prefix", DefaultFilePathPrefix, "File path prefix to use if given a raw path (this is prepended directly to the raw path without any joining slashes)")
}

func (c baseDecorCommand) fileTicketArg(flag *flag.FlagSet) (string, error) {
	if flag.NArg() < 0 {
		return "", errors.New("no file given")
	}
	file := flag.Arg(0)
	if strings.HasPrefix(file, kytheuri.Scheme) {
		return file, nil
	}
	return (&kytheuri.URI{
		Corpus: c.corpus,
		Root:   c.root,
		Path:   c.pathPrefix + file,
	}).String(), nil
}

func (c baseDecorCommand) baseRequest(flag *flag.FlagSet) (*xpb.DecorationsRequest, error) {
	ticket, err := c.fileTicketArg(flag)
	if err != nil {
		return nil, err
	}
	req := &xpb.DecorationsRequest{
		Location: &xpb.Location{Ticket: ticket},
	}
	span, err := c.spanArg()
	if err != nil {
		return nil, err
	} else if span != nil {
		req.Location.Kind = xpb.Location_SPAN
		req.Location.Span = span
	}
	return req, nil
}

func (c baseDecorCommand) spanArg() (*cpb.Span, error) {
	if c.decorSpan == "" {
		return nil, nil
	}
	span, err := parseSpan(c.decorSpan)
	if err != nil {
		return nil, fmt.Errorf("invalid --span %q: %v", c.decorSpan, err)
	}
	return span, nil
}

type decorCommand struct {
	baseDecorCommand
	targetDefs       bool
	dirtyFile        string
	refFormat        string
	extendsOverrides bool
}

func (decorCommand) Name() string     { return "decor" }
func (decorCommand) Synopsis() string { return "list a file's decorations" }
func (decorCommand) Usage() string    { return "" }
func (c *decorCommand) SetFlags(flag *flag.FlagSet) {
	c.baseDecorCommand.SetFlags(flag)
	// TODO(schroederc): add option to look for dirty files based on file-ticket path and a directory root
	flag.StringVar(&c.dirtyFile, "dirty", "", "Send the given file as the dirty buffer for patching references")
	flag.StringVar(&c.refFormat, "format", "@edgeKind@\t@^line@:@^col@-@$line@:@$col@\t@targetKind@\t@target@\t@targetDef@",
		`Format for each decoration result.
      Format Markers:
        @target@     -- ticket of referenced target node
        @targetDef@  -- ticket of referenced target's definition
        @edgeKind@   -- edge kind from anchor node to its referenced target
        @targetKind@ -- node kind and subkind of referenced target
        @nodeKind@   -- node kind of referenced target
        @subkind@    -- subkind of referenced target
        @^offset@    -- anchor source's starting byte-offset
        @^line@      -- anchor source's starting line
        @^col@       -- anchor source's starting column offset
        @$offset@    -- anchor source's ending byte-offset
        @$line@      -- anchor source's ending line
        @$col@       -- anchor source's ending column offset`)
	flag.BoolVar(&c.targetDefs, "target_definitions", false, "Whether to request definitions (@targetDef@ format marker) for each reference's target")
	flag.BoolVar(&c.extendsOverrides, "extends_overrides", false, "Whether to request extends/overrides information")
}
func (c decorCommand) Run(ctx context.Context, flag *flag.FlagSet, api API) error {
	req, err := c.baseRequest(flag)
	if err != nil {
		return err
	}
	req.References = true
	req.TargetDefinitions = c.targetDefs
	req.ExtendsOverrides = c.extendsOverrides
	req.Filter = []string{
		facts.NodeKind,
		facts.Subkind,
	}
	if c.dirtyFile != "" {
		f, err := vfs.Open(ctx, c.dirtyFile)
		if err != nil {
			return fmt.Errorf("error opening dirty buffer file at %q: %v", c.dirtyFile, err)
		}
		buf, err := ioutil.ReadAll(f)
		if err != nil {
			f.Close()
			return fmt.Errorf("error reading dirty buffer file: %v", err)
		} else if err := f.Close(); err != nil {
			return fmt.Errorf("error closing dirty buffer file: %v", err)
		}
		req.DirtyBuffer = buf
	}

	LogRequest(req)
	reply, err := api.XRefService.Decorations(ctx, req)
	if err != nil {
		return err
	}

	return c.displayDecorations(reply)
}

func (c decorCommand) displayDecorations(decor *xpb.DecorationsReply) error {
	if DisplayJSON {
		return PrintJSONMessage(decor)
	}

	nodes := xrefs.NodesMap(decor.Nodes)

	for _, ref := range decor.Reference {
		nodeKind := factValue(nodes, ref.TargetTicket, facts.NodeKind, "UNKNOWN")
		subkind := factValue(nodes, ref.TargetTicket, facts.Subkind, "")

		tgtKind := nodeKind
		if subkind != "" {
			tgtKind += "/" + subkind
		}

		var targetDef string
		if ref.TargetDefinition != "" {
			targetDef = ref.TargetDefinition
			// TODO(schroederc): fields from decor.DefinitionLocations
			// TODO(zarko): fields from decor.ExtendsOverrides
		}

		r := strings.NewReplacer(
			"@target@", ref.TargetTicket,
			"@edgeKind@", ref.Kind,
			"@targetKind@", tgtKind,
			"@nodeKind@", nodeKind,
			"@subkind@", subkind,
			"@^offset@", itoa(ref.Span.Start.ByteOffset),
			"@^line@", itoa(ref.Span.Start.LineNumber),
			"@^col@", itoa(ref.Span.Start.ColumnOffset),
			"@$offset@", itoa(ref.Span.End.ByteOffset),
			"@$line@", itoa(ref.Span.End.LineNumber),
			"@$col@", itoa(ref.Span.End.ColumnOffset),
			"@targetDef@", targetDef,
		)
		if _, err := r.WriteString(out, c.refFormat+"\n"); err != nil {
			return err
		}
	}

	return nil
}

func itoa(n int32) string { return strconv.Itoa(int(n)) }

func factValue(m map[string]map[string][]byte, ticket, factName, def string) string {
	if n, ok := m[ticket]; ok {
		if val, ok := n[factName]; ok {
			return string(val)
		}
	}
	return def
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"os"
	"strings"
	"time"
)

const (
	DEFAULT_SYNC_DIR = "/loftus"
	SYNC_IDLE_SECS   = 5

	CMD_ALERT = "loftus_alert"
	CMD_INFO  = "loftus_info"

	SUGGEST_CMD_ALERT = "#!/bin/bash\nzenity --warning --title=loftus --text=\"$1\""
	SUGGEST_CMD_INFO  = "#!/bin/bash\nnotify-send loftus \"$1\""
)

type Storage interface {

	// Perform all possible sanity checks, returning a user-helpful error
	Check() error

	// Can we contact remote storage server (i.e. git remote)
	IsOnline() bool

	// Update storage from remote storage server
	Pull() error

	// Add all files to the storage
	AddAll() error

	// Commit files to storage
	Commit(string) error

	// Send files to remote storage server
	Push() error
}

type Config struct {
	isServer   bool
	isCheck    bool
	serverAddr string
	syncDir    string
}

type Client struct {
	backend  Storage
	watch    chan Event
	external External
	incoming chan string
	isOnline bool
}

func main() {

	config := confFromFlags()

	if config.isServer {
		log.Println("Server mode")
		startServer(config)
	} else {
		log.Println("Client mode")
		startClient(config)
	}
}

// Parse commands line flags in to a configuration object
func confFromFlags() *Config {

	defaultSync := os.Getenv("HOME") + DEFAULT_SYNC_DIR
	var syncDir = flag.String(
		"dir",
		defaultSync,
		"Synchronise this directory. Must already be a git repo with a remote (i.e. 'git pull' works)")

	var isServer = flag.Bool("server", false, "Be the server")
	var serverAddr = flag.String(
		"address",
		"",
		"address:port where server is listening. e.g. an.example.com:8007")

	flag.Parse()

	return &Config{
		isServer:   *isServer,
		serverAddr: *serverAddr,
		syncDir:    *syncDir}
}

// Watch directories, called sync methods on syncer, etc
func startClient(config *Config) {

	syncDir := config.syncDir
	syncDir = strings.TrimRight(syncDir, "/")
	log.Println("Synchronising:", syncDir)

	external := &RealExternal{}
	backend := NewGitBackend(config, external)

	CheckEverything(external, syncDir, backend, config)

	log.Println("Watching", syncDir, "and all sub-directories")
	watchChannel, err := Watch(syncDir)
	if err != nil {
		log.Fatal(err)
	}

	incomingChannel := make(chan string)

	client := Client{
		backend:  backend,
		watch:    watchChannel,
		external: external,
		incoming: incomingChannel,
		isOnline: true,
	}

	go udpListen(incomingChannel)
	go tcpListen(config.serverAddr, incomingChannel)
	client.run()
}

// Main loop
func (self *Client) run() {

	// Always start with a sync to bring us up to date
	err := self.Sync("Startup sync")
	if err != nil {
		self.warn(err.Error())
	}

	events := make([]Event, 0, 1)

	for {
		select {

		case event := <-self.watch:
			events = append(events, event)

		case <-self.incoming:
			log.Println("Remote update notification")
			self.Sync("Incoming")

		case <-time.After(SYNC_IDLE_SECS * time.Second):
			if len(events) != 0 {
				self.Sync(commitMsg(events))
				events = make([]Event, 0, 1)
			}
		}
	}

}

// Format the underlying events into a nice commit message
func commitMsg(events []Event) string {

	var msg string
	var msgs, arr []string
	byType := make(map[string] []string)

	// Group by event type
	for _, event := range events {
		arr = byType[event.Event]
		if arr == nil {
			arr = make([]string, 0)
		}

		arr = append(arr, event.Filename)
		byType[event.Event] = arr
	}

	for evType, evFilenames := range byType {
		msg = evType + ": " + strings.Join(evFilenames, ", ")
		msgs = append(msgs, msg)
	}

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

// Run: git pull; git add --all ; git commit --all; git push
func (self *Client) Sync(commitMsg string) error {

	log.Println("* Sync start")

	var err error

	isOnline := self.backend.IsOnline()
	if isOnline != self.isOnline {

		self.isOnline = isOnline

		if isOnline {
			log.Println("Back online")
			self.info("Back online")
		} else {
			log.Println("Working offline")
			self.info("Could not connect to remote git repo. Working offline.")
		}
	}

	if self.isOnline {
		// Pull first to ensure a fast-forward when we push
		err = self.backend.Pull()
		if err != nil {
			log.Println("Returning error from Pull")
			return err
		}
	}

	err = self.backend.AddAll()
	if err != nil {
		return err
	}

	self.backend.Commit(commitMsg)
	if err != nil {
		return err
	}

	if self.isOnline { //&& self.isBehindRemote() {
		err = self.backend.Push()
		if err != nil {
			return err
		}
		self.broadcast()
	}

	log.Println("* Sync end")
	return nil
}

// Tell other loftus instances to update themselves, because something changed.
func (self *Client) broadcast() {
	msg := "Updated\n"
	if remoteConn != nil { // remoteConn is global in comms.go
		tcpSend(remoteConn, msg)
	}
	udpSend(msg)
}

// Utility function to warn user about something - for example a git error
func (self *Client) warn(msg string) {
	self.external.Exec("", CMD_ALERT, msg)
}

// Utility function to inform user about something - for example file changes
func (self *Client) info(msg string) {
	self.external.Exec("", CMD_INFO, msg)
}
<commit_msg>Don't broadcast when we Sync because of receiving a broadcast - otherwise loop-de-loop.<commit_after>package main

import (
	"flag"
	"log"
	"os"
	"strings"
	"time"
)

const (
	DEFAULT_SYNC_DIR = "/loftus"
	SYNC_IDLE_SECS   = 5

	CMD_ALERT = "loftus_alert"
	CMD_INFO  = "loftus_info"

	SUGGEST_CMD_ALERT = "#!/bin/bash\nzenity --warning --title=loftus --text=\"$1\""
	SUGGEST_CMD_INFO  = "#!/bin/bash\nnotify-send loftus \"$1\""
)

type Storage interface {

	// Perform all possible sanity checks, returning a user-helpful error
	Check() error

	// Can we contact remote storage server (i.e. git remote)
	IsOnline() bool

	// Update storage from remote storage server
	Pull() error

	// Add all files to the storage
	AddAll() error

	// Commit files to storage
	Commit(string) error

	// Send files to remote storage server
	Push() error
}

type Config struct {
	isServer   bool
	isCheck    bool
	serverAddr string
	syncDir    string
}

type Client struct {
	backend  Storage
	watch    chan Event
	external External
	incoming chan string
	isOnline bool
}

func main() {

	config := confFromFlags()

	if config.isServer {
		log.Println("Server mode")
		startServer(config)
	} else {
		log.Println("Client mode")
		startClient(config)
	}
}

// Parse commands line flags in to a configuration object
func confFromFlags() *Config {

	defaultSync := os.Getenv("HOME") + DEFAULT_SYNC_DIR
	var syncDir = flag.String(
		"dir",
		defaultSync,
		"Synchronise this directory. Must already be a git repo with a remote (i.e. 'git pull' works)")

	var isServer = flag.Bool("server", false, "Be the server")
	var serverAddr = flag.String(
		"address",
		"",
		"address:port where server is listening. e.g. an.example.com:8007")

	flag.Parse()

	return &Config{
		isServer:   *isServer,
		serverAddr: *serverAddr,
		syncDir:    *syncDir}
}

// Watch directories, called sync methods on syncer, etc
func startClient(config *Config) {

	syncDir := config.syncDir
	syncDir = strings.TrimRight(syncDir, "/")
	log.Println("Synchronising:", syncDir)

	external := &RealExternal{}
	backend := NewGitBackend(config, external)

	CheckEverything(external, syncDir, backend, config)

	log.Println("Watching", syncDir, "and all sub-directories")
	watchChannel, err := Watch(syncDir)
	if err != nil {
		log.Fatal(err)
	}

	incomingChannel := make(chan string)

	client := Client{
		backend:  backend,
		watch:    watchChannel,
		external: external,
		incoming: incomingChannel,
		isOnline: true,
	}

	go udpListen(incomingChannel)
	go tcpListen(config.serverAddr, incomingChannel)
	client.run()
}

// Main loop
func (self *Client) run() {

	// Always start with a sync to bring us up to date
	err := self.Sync("Startup sync")
	if err != nil {
		self.warn(err.Error())
	}

	events := make([]Event, 0, 1)

	for {
		select {

		case event := <-self.watch:
			events = append(events, event)

		case <-self.incoming:
			log.Println("Remote update notification")
			self.Sync("Incoming")

		case <-time.After(SYNC_IDLE_SECS * time.Second):

			if len(events) != 0 {

				self.Sync(commitMsg(events))
				if self.isOnline {
					self.broadcast()
				}

				events = make([]Event, 0, 1)
			}
		}
	}

}

// Format the underlying events into a nice commit message
func commitMsg(events []Event) string {

	var msg string
	var msgs, arr []string
	byType := make(map[string][]string)

	// Group by event type
	for _, event := range events {
		arr = byType[event.Event]
		if arr == nil {
			arr = make([]string, 0)
		}

		arr = append(arr, event.Filename)
		byType[event.Event] = arr
	}

	for evType, evFilenames := range byType {
		msg = evType + ": " + strings.Join(evFilenames, ", ")
		msgs = append(msgs, msg)
	}

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

// Run: git pull; git add --all ; git commit --all; git push
func (self *Client) Sync(commitMsg string) error {

	log.Println("* Sync start")

	var err error

	isOnline := self.backend.IsOnline()
	if isOnline != self.isOnline {

		self.isOnline = isOnline

		if isOnline {
			log.Println("Back online")
			self.info("Back online")
		} else {
			log.Println("Working offline")
			self.info("Could not connect to remote git repo. Working offline.")
		}
	}

	if self.isOnline {
		// Pull first to ensure a fast-forward when we push
		err = self.backend.Pull()
		if err != nil {
			log.Println("Returning error from Pull")
			return err
		}
	}

	err = self.backend.AddAll()
	if err != nil {
		return err
	}

	self.backend.Commit(commitMsg)
	if err != nil {
		return err
	}

	if self.isOnline { //&& self.isBehindRemote() {
		err = self.backend.Push()
		if err != nil {
			return err
		}
	}

	log.Println("* Sync end")
	return nil
}

// Tell other loftus instances to update themselves, because something changed.
func (self *Client) broadcast() {
	msg := "Updated\n"
	if remoteConn != nil { // remoteConn is global in comms.go
		tcpSend(remoteConn, msg)
	}
	udpSend(msg)
}

// Utility function to warn user about something - for example a git error
func (self *Client) warn(msg string) {
	self.external.Exec("", CMD_ALERT, msg)
}

// Utility function to inform user about something - for example file changes
func (self *Client) info(msg string) {
	self.external.Exec("", CMD_INFO, msg)
}
<|endoftext|>


<commit_before>package main

import (
	"log"

	"github.com/hailocab/gocassa"
)

var keySpace gocassa.KeySpace

var plantMap map[string]gocassa.MapTable

func Initialize() {
	log.Println("Initializing GoCassa")

	var err error
	keySpace, err = gocassa.ConnectToKeySpace("test", []string{"127.0.0.1"}, "", "")
	if err != nil {
		panic(err)
	}
	plantMap = map[string]gocassa.MapTable{}
}

func WriteToCassandra(plantId string, pheremone Pheremone) {
	log.Println("Writing pheremone: ", pheremone)
	log.Println("With plantId: ", plantId)
	plant := plantMap[plantId]
	if plant == nil {
		plant = keySpace.MapTable(plantId, "Ant", Pheremone{})
		log.Print("creating table : ", plantId)
		err := plant.Create()
		if err != nil {
			log.Println("Error:", err)
			return
		} else {
			plantMap[plantId] = plant
		}
	}
	err := plant.Set(pheremone).Run()
	if err != nil {
		panic(err)
	}

	//	result := Pheremone{}
	//	if err := salesTable.Read("abcdefg", &result).Run(); err != nil {
	//		panic(err)
	//	}
	//	fmt.Println(result)
}
<commit_msg>changing name of cassandra instance to api.skydome.io<commit_after>package main

import (
	"log"

	"github.com/hailocab/gocassa"
)

var keySpace gocassa.KeySpace

var plantMap map[string]gocassa.MapTable

func Initialize() {
	log.Println("Initializing GoCassa")

	var err error
	keySpace, err = gocassa.ConnectToKeySpace("test", []string{"api.skydome.io"}, "", "")
	if err != nil {
		panic(err)
	}
	plantMap = map[string]gocassa.MapTable{}
}

func WriteToCassandra(plantId string, pheremone Pheremone) {
	log.Println("Writing pheremone: ", pheremone)
	log.Println("With plantId: ", plantId)
	plant := plantMap[plantId]
	if plant == nil {
		plant = keySpace.MapTable(plantId, "Ant", Pheremone{})
		log.Print("creating table : ", plantId)
		err := plant.Create()
		if err != nil {
			log.Println("Error:", err)
			return
		} else {
			plantMap[plantId] = plant
		}
	}
	err := plant.Set(pheremone).Run()
	if err != nil {
		panic(err)
	}

	//	result := Pheremone{}
	//	if err := salesTable.Read("abcdefg", &result).Run(); err != nil {
	//		panic(err)
	//	}
	//	fmt.Println(result)
}
<|endoftext|>


<commit_before>package main

import "github.com/codegangsta/martini"

func main() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "<title>martini</title>
Hello world!
"
  })
  m.Run()
}
<commit_msg>Adding ID for Dalekjs.<commit_after>package main

import "github.com/codegangsta/martini"

func main() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "<title>martini</title>
Hello world!
"
  })
  m.Run()
}
<|endoftext|>


<commit_before>package leetcode

import "testing"

func Test_StringIterator(t *testing.T) {
	it := Constructor("L1e2t1C1o1d1e1")
	for it.HasNext() {
		t.Log(string(it.Next()))
	}

	iterator := Constructor("L1e2")
	if next := iterator.Next(); next != 'L' {
		t.Fatal(string(next))
	}

	if HasNext := iterator.HasNext(); HasNext != true {
		t.Fatal("HasNext error.")
	}

	iterator.Next()
	iterator.Next()
	if HasNext := iterator.HasNext(); HasNext != false {
		t.Fatal(HasNext)
	}
	if next := iterator.Next(); next != ' ' {
		t.Fatal("isempty must return a white space.")
	}
}
<commit_msg>// noused test code<commit_after>package leetcode

import "testing"

func Test_StringIterator(t *testing.T) {
	/*
		it := Constructor("L1e2t1C1o1d1e1")
		for it.HasNext() {
			t.Log(string(it.Next()))
		}
	*/

	iterator := Constructor("L1e2")
	if next := iterator.Next(); next != 'L' {
		t.Fatal(string(next))
	}

	if HasNext := iterator.HasNext(); HasNext != true {
		t.Fatal("HasNext error.")
	}

	iterator.Next()
	iterator.Next()
	if HasNext := iterator.HasNext(); HasNext != false {
		t.Fatal(HasNext)
	}
	if next := iterator.Next(); next != ' ' {
		t.Fatal("isempty must return a white space.")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"io"
	"os"
	"strings"
	"testing"
)

// commandOutput returns stdout for a deisctl command line as a string.
func commandOutput(args []string) (output string) {
	old := os.Stdout
	r, w, _ := os.Pipe()
	os.Stdout = w

	Command(args)

	outC := make(chan string)
	go func() {
		var buf bytes.Buffer
		io.Copy(&buf, r)
		outC <- buf.String()
	}()

	w.Close()
	os.Stdout = old
	output = <-outC
	return
}

// TestHelp tests that deisctl is flexible when being asked to print built-in help.
func TestHelp(t *testing.T) {
	allArgs := [][]string{{"-h"}, {"--help"}, {"help"}}
	out := ""
	for _, args := range allArgs {
		out = commandOutput(args)
		if !strings.Contains(out, "Usage: deisctl [options] <command> [<args>...]") ||
			!strings.Contains(out, "Commands, use \"deisctl help <command>\" to learn more") {
			t.Error(out)
		}
	}
}

// TestUsage ensures that deisctl prints a short usage string when no arguments were provided.
func TestUsage(t *testing.T) {
	out := commandOutput(nil)
	if out != "Usage: deisctl [options] <command> [<args>...]\n" {
		t.Error(out)
	}
}

// TestVersion verifies that "deisctl --version" prints the current version string.
func TestVersion(t *testing.T) {
	args := []string{"--version"}
	out := commandOutput(args)
	if !strings.HasPrefix(out, Version) {
		t.Error(out)
	}
}
<commit_msg>fix(deisctl): unit test should also use main version package<commit_after>package main

import (
	"bytes"
	"io"
	"os"
	"strings"
	"testing"

	"github.com/deis/deis/version"
)

// commandOutput returns stdout for a deisctl command line as a string.
func commandOutput(args []string) (output string) {
	old := os.Stdout
	r, w, _ := os.Pipe()
	os.Stdout = w

	Command(args)

	outC := make(chan string)
	go func() {
		var buf bytes.Buffer
		io.Copy(&buf, r)
		outC <- buf.String()
	}()

	w.Close()
	os.Stdout = old
	output = <-outC
	return
}

// TestHelp tests that deisctl is flexible when being asked to print built-in help.
func TestHelp(t *testing.T) {
	allArgs := [][]string{{"-h"}, {"--help"}, {"help"}}
	out := ""
	for _, args := range allArgs {
		out = commandOutput(args)
		if !strings.Contains(out, "Usage: deisctl [options] <command> [<args>...]") ||
			!strings.Contains(out, "Commands, use \"deisctl help <command>\" to learn more") {
			t.Error(out)
		}
	}
}

// TestUsage ensures that deisctl prints a short usage string when no arguments were provided.
func TestUsage(t *testing.T) {
	out := commandOutput(nil)
	if out != "Usage: deisctl [options] <command> [<args>...]\n" {
		t.Error(out)
	}
}

// TestVersion verifies that "deisctl --version" prints the current version string.
func TestVersion(t *testing.T) {
	args := []string{"--version"}
	out := commandOutput(args)
	if !strings.HasPrefix(out, version.Version) {
		t.Error(out)
	}
}
<|endoftext|>


<commit_before><commit_msg>use the new type switch multicase to clean up a little.<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2013 The AUTHORS
//
// Use of this source code is governed by The MIT License
// that can be found in the LICENSE file.

package main

import (
	// Stdlib
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"strings"
	"text/template"

	// Others
	"github.com/dmotylev/nutrition"
	"github.com/tchap/gocli"
)

// Subcommand initialisation and registration.
func init() {
	ieExt := &gocli.Command{
		UsageLine: `
  ie_ext SUBCMD`,
		Short: "IE extensions manipulation",
	}

	genBhoversionRc := &gocli.Command{
		UsageLine: `
  gen_bhoversion_rc [-manifest MANIFEST_FILE] [FILE]`,
		Short: "generate bhoversion.rc",
		Long: `
  gen_brhoversion_rc generates bhoversion.rc in the current working directory
  unless FILE is specified. It can optionally read a Chrome extension
  manifest.json to get the extension version.

  This subcommand uses environmental variables to fill the bhoversion.rc template.
  The required environmental variables are:
    BHRC_COMPANYNAME
    BHRC_FILEDESCRIPTION
    BHRC_VERSION - must be a.b.c.d, $BUILD_NUMBER is used for $d if present;
                   does not have to be set if manifest is being used
    BHRC_LEGALCOPYRIGHT
    BHRC_PRODUCTNAME
		`,
		Action: runGenBhoversionRc,
	}
	genBhoversionRc.Flags.StringVar(&manifestJson, "manifest", manifestJson,
		"read version from manifest.json")
	ieExt.MustRegisterSubcommand(genBhoversionRc)

	getApp().MustRegisterSubcommand(ieExt)
}

var manifestJson string

// Subcommand handler.
func runGenBhoversionRc(cmd *gocli.Command, args []string) {
	if len(args) > 1 {
		cmd.Usage()
		os.Exit(2)
	}

	var filename string
	if len(args) == 1 {
		filename = args[0]
	} else {
		filename = "bhoversion.rc"
	}

	var version string
	if manifestJson != "" {
		var manifest struct {
			Version string
		}

		content, err := ioutil.ReadFile(manifestJson)
		if err != nil {
			log.Fatalf("Error: %v\n", err)
		}

		if err := json.Unmarshal(content, &manifest); err != nil {
			log.Fatalf("Error: %v\n", err)
		}

		version = manifest.Version
	}

	var ctx struct {
		CompanyName     string
		FileDescription string
		Version         string
		VersionCommas   string
		LegalCopyright  string
		ProductName     string
	}

	if err := nutrition.Env("BHRC_").Feed(&ctx); err != nil {
		log.Fatalf("Error: %v\n", err)
	}

	if version != "" {
		ctx.Version = version
	}

	switch {
	case ctx.CompanyName == "":
		log.Fatalln("Error: BHRC_COMPANYNAME not set")
	case ctx.FileDescription == "":
		log.Fatalln("Error: BHRC_FILEDESCRIPTION not set")
	case ctx.Version == "":
		log.Fatalln("Error: BHRC_VERSION not set")
	case ctx.LegalCopyright == "":
		log.Fatalln("Error: BHRC_LEGALCOPYRIGHT not set")
	case ctx.ProductName == "":
		log.Fatalln("Error: BHRC_PRODUCTNAME not set")
	}

	buildNum := os.Getenv("BUILD_NUMBER")
	if buildNum == "" {
		buildNum = "0"
	}
	ctx.Version = fmt.Sprintf("%v.%v", ctx.Version, buildNum)

	matched, err := regexp.Match("[0-9]+([.][0-9]){3}", []byte(ctx.Version))
	if err != nil {
		panic(err)
	}
	if !matched {
		log.Fatalf("Error: invalid version string")
	}

	ctx.VersionCommas = strings.Replace(ctx.Version, ".", ",", -1)

	t := template.Must(template.New("bhoversion.rc").Parse(bhoversionRcTemplate))

	file, err := os.OpenFile(filename, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatalf("Error: %v\n", err)
	}

	if err := t.Execute(file, ctx); err != nil {
		file.Close()
		log.Fatalf("Error: %v\n", err)
	}

	if err := file.Close(); err != nil {
		log.Fatalf("Error: %v\n", err)
	}
}

const bhoversionRcTemplate = `
1 VERSIONINFO
FILEVERSION {{.VersionCommas}}
PRODUCTVERSION {{.VersionCommas}}
FILEOS 0x4
FILETYPE 0x2
{
BLOCK "StringFileInfo"
{
        BLOCK "040904b0"
        {
                VALUE "CompanyName", "{{.CompanyName}}"
                VALUE "FileDescription", "{{.FileDescription}}"
                VALUE "FileVersion", "{{.Version}}"
                VALUE "InternalName", "ancho.dll"
                VALUE "LegalCopyright", "{{.LegalCopyright}}"
                VALUE "OriginalFilename", "ancho.dll"
                VALUE "ProductName", "{{.ProductName}}"
                VALUE "ProductVersion", "{{.Version}}"
        }
}

BLOCK "VarFileInfo"
{
        VALUE "Translation", 0x0409 0x04E4
}
}
`
<commit_msg>bugfix: gen_bhoversion_rc template<commit_after>// Copyright (c) 2013 The AUTHORS
//
// Use of this source code is governed by The MIT License
// that can be found in the LICENSE file.

package main

import (
	// Stdlib
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"strings"
	"text/template"

	// Others
	"github.com/dmotylev/nutrition"
	"github.com/tchap/gocli"
)

// Subcommand initialisation and registration.
func init() {
	ieExt := &gocli.Command{
		UsageLine: `
  ie_ext SUBCMD`,
		Short: "IE extensions manipulation",
	}

	genBhoversionRc := &gocli.Command{
		UsageLine: `
  gen_bhoversion_rc [-manifest MANIFEST_FILE] [FILE]`,
		Short: "generate bhoversion.rc",
		Long: `
  gen_brhoversion_rc generates bhoversion.rc in the current working directory
  unless FILE is specified. It can optionally read a Chrome extension
  manifest.json to get the extension version.

  This subcommand uses environmental variables to fill the bhoversion.rc template.
  The required environmental variables are:
    BHRC_COMPANYNAME
    BHRC_FILEDESCRIPTION
    BHRC_VERSION - must be a.b.c.d, $BUILD_NUMBER is used for $d if present;
                   does not have to be set if manifest is being used
    BHRC_LEGALCOPYRIGHT
    BHRC_PRODUCTNAME
		`,
		Action: runGenBhoversionRc,
	}
	genBhoversionRc.Flags.StringVar(&manifestJson, "manifest", manifestJson,
		"read version from manifest.json")
	ieExt.MustRegisterSubcommand(genBhoversionRc)

	getApp().MustRegisterSubcommand(ieExt)
}

var manifestJson string

// Subcommand handler.
func runGenBhoversionRc(cmd *gocli.Command, args []string) {
	if len(args) > 1 {
		cmd.Usage()
		os.Exit(2)
	}

	var filename string
	if len(args) == 1 {
		filename = args[0]
	} else {
		filename = "bhoversion.rc"
	}

	var version string
	if manifestJson != "" {
		var manifest struct {
			Version string
		}

		content, err := ioutil.ReadFile(manifestJson)
		if err != nil {
			log.Fatalf("Error: %v\n", err)
		}

		if err := json.Unmarshal(content, &manifest); err != nil {
			log.Fatalf("Error: %v\n", err)
		}

		version = manifest.Version
	}

	var ctx struct {
		CompanyName     string
		FileDescription string
		Version         string
		VersionCommas   string
		LegalCopyright  string
		ProductName     string
	}

	if err := nutrition.Env("BHRC_").Feed(&ctx); err != nil {
		log.Fatalf("Error: %v\n", err)
	}

	if version != "" {
		ctx.Version = version
	}

	switch {
	case ctx.CompanyName == "":
		log.Fatalln("Error: BHRC_COMPANYNAME not set")
	case ctx.FileDescription == "":
		log.Fatalln("Error: BHRC_FILEDESCRIPTION not set")
	case ctx.Version == "":
		log.Fatalln("Error: BHRC_VERSION not set")
	case ctx.LegalCopyright == "":
		log.Fatalln("Error: BHRC_LEGALCOPYRIGHT not set")
	case ctx.ProductName == "":
		log.Fatalln("Error: BHRC_PRODUCTNAME not set")
	}

	buildNum := os.Getenv("BUILD_NUMBER")
	if buildNum == "" {
		buildNum = "0"
	}
	ctx.Version = fmt.Sprintf("%v.%v", ctx.Version, buildNum)

	matched, err := regexp.Match("[0-9]+([.][0-9]){3}", []byte(ctx.Version))
	if err != nil {
		panic(err)
	}
	if !matched {
		log.Fatalf("Error: invalid version string")
	}

	ctx.VersionCommas = strings.Replace(ctx.Version, ".", ",", -1)

	t := template.Must(template.New("bhoversion.rc").Parse(bhoversionRcTemplate))

	file, err := os.OpenFile(filename, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatalf("Error: %v\n", err)
	}

	if err := t.Execute(file, ctx); err != nil {
		file.Close()
		log.Fatalf("Error: %v\n", err)
	}

	if err := file.Close(); err != nil {
		log.Fatalf("Error: %v\n", err)
	}
}

const bhoversionRcTemplate = `
1 VERSIONINFO
FILEVERSION {{.VersionCommas}}
PRODUCTVERSION {{.VersionCommas}}
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904e4"
        BEGIN
            VALUE "CompanyName", "{{.CompanyName}}"
            VALUE "FileDescription", "{{.FileDescription}}"
            VALUE "FileVersion", "{{.Version}}"
            VALUE "InternalName", "ancho.dll"
            VALUE "LegalCopyright", "{{.LegalCopyright}}"
            VALUE "OriginalFilename", "ancho.dll"
            VALUE "ProductName", "{{.ProductName}}"
            VALUE "ProductVersion", "{{.Version}}"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1252
    END
END
`

/*
const bhoversionRcTemplate = `
1 VERSIONINFO
FILEVERSION {{.VersionCommas}}
PRODUCTVERSION {{.VersionCommas}}
FILEOS 0x4
FILETYPE 0x2
{
BLOCK "StringFileInfo"
{
        BLOCK "040904b0"
        {
                VALUE "CompanyName", "{{.CompanyName}}"
                VALUE "FileDescription", "{{.FileDescription}}"
                VALUE "FileVersion", "{{.Version}}"
                VALUE "InternalName", "ancho.dll"
                VALUE "LegalCopyright", "{{.LegalCopyright}}"
                VALUE "OriginalFilename", "ancho.dll"
                VALUE "ProductName", "{{.ProductName}}"
                VALUE "ProductVersion", "{{.Version}}"
        }
}

BLOCK "VarFileInfo"
{
        VALUE "Translation", 0x0409 0x04E4
}
}
`
*/
<|endoftext|>


<commit_before>package goose

import (
	"github.com/PuerkitoBio/goquery"
	"regexp"
	"strconv"
	"strings"
)

type candidate struct {
	url     string
	surface int
	score   int
}

var largebig = regexp.MustCompile("(large|big)")

var rules = map[*regexp.Regexp]int{
	regexp.MustCompile("(large|big)"):          1,
	regexp.MustCompile("upload"):               1,
	regexp.MustCompile("media"):                1,
	regexp.MustCompile("gravatar.com"):         -1,
	regexp.MustCompile("feeds.feedburner.com"): -1,
	regexp.MustCompile("(?i)icon"):             -1,
	regexp.MustCompile("(?i)logo"):             -1,
	regexp.MustCompile("(?i)spinner"):          -1,
	regexp.MustCompile("(?i)loading"):          -1,
	regexp.MustCompile("(?i)ads"):              -1,
	regexp.MustCompile("badge"):                -1,
	regexp.MustCompile("1x1"):                  -1,
	regexp.MustCompile("pixel"):                -1,
	regexp.MustCompile("thumbnail[s]*"):        -1,
	regexp.MustCompile(".html|.gif|.ico|button|twitter.jpg|facebook.jpg|ap_buy_photo|digg.jpg|digg.png|delicious.png|facebook.png|reddit.jpg|doubleclick|diggthis|diggThis|adserver|/ads/|ec.atdmt.com|mediaplex.com|adsatt|view.atdmt"): -1,
}

func score(tag *goquery.Selection) int {
	src, _ := tag.Attr("src")
	if src == "" {
		src, _ = tag.Attr("data-src")
	}
	if src == "" {
		src, _ = tag.Attr("data-lazy-src")
	}
	if src == "" {
		return -1
	}
	tagScore := 0
	for rule, score := range rules {
		if rule.MatchString(src) {
			tagScore += score
		}
	}

	alt, exists := tag.Attr("alt")
	if exists {
		if strings.Contains(alt, "thumbnail") {
			tagScore--
		}
	}
	return tagScore
}

func WebPageResolver(article *Article) string {
	doc := article.Doc
	imgs := doc.Find("img")
	topImage := ""
	candidates := make([]candidate, 0)
	significantSurface := 320 * 200
	significantSurfaceCount := 0
	src := ""
	imgs.Each(func(i int, tag *goquery.Selection) {
		surface := 0
		src, _ = tag.Attr("src")
		if src == "" {
			src, _ = tag.Attr("data-src")
		}
		if src == "" {
			src, _ = tag.Attr("data-lazy-src")
		}
		if src == "" {
			return
		}

		width, _ := tag.Attr("width")
		height, _ := tag.Attr("height")
		if width != "" {
			w, _ := strconv.Atoi(width)
			if height != "" {
				h, _ := strconv.Atoi(height)
				surface = w * h
			} else {
				surface = w
			}
		} else {
			if height != "" {
				surface, _ = strconv.Atoi(height)
			} else {
				surface = 0
			}
		}

		if surface > significantSurface {
			significantSurfaceCount++
		}

		tagscore := score(tag)
		if tagscore >= 0 {
			c := candidate{
				url:     src,
				surface: surface,
				score:   score(tag),
			}
			candidates = append(candidates, c)
		}
	})

	if len(candidates) == 0 {
		return ""
	}

	if significantSurfaceCount > 0 {
		bestCandidate := findBestCandidateFromSurface(candidates)
		topImage = bestCandidate.url
	} else {
		bestCandidate := findBestCandidateFromScore(candidates)
		topImage = bestCandidate.url
	}

	if topImage != "" && !strings.HasPrefix(topImage, "http") {
		topImage = "http://" + topImage
	}

	return topImage
}

func findBestCandidateFromSurface(candidates []candidate) candidate {
	max := 0
	var bestCandidate candidate
	for _, candidate := range candidates {
		surface := candidate.surface
		if surface >= max {
			max = surface
			bestCandidate = candidate
		}
	}

	return bestCandidate
}

func findBestCandidateFromScore(candidates []candidate) candidate {
	max := 0
	var bestCandidate candidate
	for _, candidate := range candidates {
		score := candidate.score
		if score >= max {
			max = score
			bestCandidate = candidate
		}
	}

	return bestCandidate
}

type ogTag struct {
	tpe       string
	attribute string
	name      string
	value     string
}

var ogTags = [4]ogTag{
	ogTag{
		tpe:       "facebook",
		attribute: "property",
		name:      "og:image",
		value:     "content",
	},
	ogTag{
		tpe:       "facebook",
		attribute: "rel",
		name:      "image_src",
		value:     "href",
	},
	ogTag{
		tpe:       "twitter",
		attribute: "name",
		name:      "twitter:image",
		value:     "value",
	},
	ogTag{
		tpe:       "twitter",
		attribute: "name",
		name:      "twitter:image",
		value:     "content",
	},
}

type ogImage struct {
	url   string
	tpe   string
	score int
}

func OpenGraphResolver(article *Article) string {
	doc := article.Doc
	meta := doc.Find("meta")
	links := doc.Find("link")
	topImage := ""
	meta = meta.Union(links)
	ogImages := make([]ogImage, 0)
	meta.Each(func(i int, tag *goquery.Selection) {
		for _, ogTag := range ogTags {
			attr, exist := tag.Attr(ogTag.attribute)
			value, vexist := tag.Attr(ogTag.value)
			if exist && attr == ogTag.name && vexist {
				ogImage := ogImage{
					url:   value,
					tpe:   ogTag.tpe,
					score: 0,
				}

				ogImages = append(ogImages, ogImage)
			}
		}
	})

	if len(ogImages) == 1 {
		topImage = ogImages[0].url
	} else {
		for _, ogImage := range ogImages {
			if largebig.MatchString(ogImage.url) {
				ogImage.score++
			}
			if ogImage.tpe == "twitter" {
				ogImage.score++
			}
		}
		topImage = findBestImageFromScore(ogImages).url
	}

	if topImage != "" && !strings.HasPrefix(topImage, "http") {
		topImage = "http://" + topImage
	}

	return topImage
}

func findBestImageFromScore(ogImages []ogImage) ogImage {
	max := 0
	var bestOGImage ogImage
	for _, ogImage := range ogImages {
		score := ogImage.score
		//println("OG", ogImage.url, score)
		if score >= max {
			max = score
			bestOGImage = ogImage
		}
	}

	return bestOGImage
}
<commit_msg>fix absolute image URL<commit_after>package goose

import (
	"github.com/PuerkitoBio/goquery"
	"regexp"
	"strconv"
	"strings"
	"net/url"
)

type candidate struct {
	url     string
	surface int
	score   int
}

var largebig = regexp.MustCompile("(large|big)")

var rules = map[*regexp.Regexp]int{
	regexp.MustCompile("(large|big)"):          1,
	regexp.MustCompile("upload"):               1,
	regexp.MustCompile("media"):                1,
	regexp.MustCompile("gravatar.com"):         -1,
	regexp.MustCompile("feeds.feedburner.com"): -1,
	regexp.MustCompile("(?i)icon"):             -1,
	regexp.MustCompile("(?i)logo"):             -1,
	regexp.MustCompile("(?i)spinner"):          -1,
	regexp.MustCompile("(?i)loading"):          -1,
	regexp.MustCompile("(?i)ads"):              -1,
	regexp.MustCompile("badge"):                -1,
	regexp.MustCompile("1x1"):                  -1,
	regexp.MustCompile("pixel"):                -1,
	regexp.MustCompile("thumbnail[s]*"):        -1,
	regexp.MustCompile(".html|.gif|.ico|button|twitter.jpg|facebook.jpg|ap_buy_photo|digg.jpg|digg.png|delicious.png|facebook.png|reddit.jpg|doubleclick|diggthis|diggThis|adserver|/ads/|ec.atdmt.com|mediaplex.com|adsatt|view.atdmt"): -1,
}

func score(tag *goquery.Selection) int {
	src, _ := tag.Attr("src")
	if src == "" {
		src, _ = tag.Attr("data-src")
	}
	if src == "" {
		src, _ = tag.Attr("data-lazy-src")
	}
	if src == "" {
		return -1
	}
	tagScore := 0
	for rule, score := range rules {
		if rule.MatchString(src) {
			tagScore += score
		}
	}

	alt, exists := tag.Attr("alt")
	if exists {
		if strings.Contains(alt, "thumbnail") {
			tagScore--
		}
	}
	return tagScore
}

func WebPageResolver(article *Article) string {
	doc := article.Doc
	imgs := doc.Find("img")
	topImage := ""
	candidates := make([]candidate, 0)
	significantSurface := 320 * 200
	significantSurfaceCount := 0
	src := ""
	imgs.Each(func(i int, tag *goquery.Selection) {
		surface := 0
		src, _ = tag.Attr("src")
		if src == "" {
			src, _ = tag.Attr("data-src")
		}
		if src == "" {
			src, _ = tag.Attr("data-lazy-src")
		}
		if src == "" {
			return
		}

		width, _ := tag.Attr("width")
		height, _ := tag.Attr("height")
		if width != "" {
			w, _ := strconv.Atoi(width)
			if height != "" {
				h, _ := strconv.Atoi(height)
				surface = w * h
			} else {
				surface = w
			}
		} else {
			if height != "" {
				surface, _ = strconv.Atoi(height)
			} else {
				surface = 0
			}
		}

		if surface > significantSurface {
			significantSurfaceCount++
		}

		tagscore := score(tag)
		if tagscore >= 0 {
			c := candidate{
				url:     src,
				surface: surface,
				score:   score(tag),
			}
			candidates = append(candidates, c)
		}
	})

	if len(candidates) == 0 {
		return ""
	}

	if significantSurfaceCount > 0 {
		bestCandidate := findBestCandidateFromSurface(candidates)
		topImage = bestCandidate.url
	} else {
		bestCandidate := findBestCandidateFromScore(candidates)
		topImage = bestCandidate.url
	}

	if topImage != "" && !strings.HasPrefix(topImage, "http") {
		a, err := url.Parse(topImage)
		if err != nil {
			return topImage
		}
		if a.Scheme == ""{
			a.Scheme = "http"
		}
		if a.Host == ""{
			a.Host = article.Domain
		}
		topImage = a.String()
	}

	return topImage
}

func findBestCandidateFromSurface(candidates []candidate) candidate {
	max := 0
	var bestCandidate candidate
	for _, candidate := range candidates {
		surface := candidate.surface
		if surface >= max {
			max = surface
			bestCandidate = candidate
		}
	}

	return bestCandidate
}

func findBestCandidateFromScore(candidates []candidate) candidate {
	max := 0
	var bestCandidate candidate
	for _, candidate := range candidates {
		score := candidate.score
		if score >= max {
			max = score
			bestCandidate = candidate
		}
	}

	return bestCandidate
}

type ogTag struct {
	tpe       string
	attribute string
	name      string
	value     string
}

var ogTags = [4]ogTag{
	ogTag{
		tpe:       "facebook",
		attribute: "property",
		name:      "og:image",
		value:     "content",
	},
	ogTag{
		tpe:       "facebook",
		attribute: "rel",
		name:      "image_src",
		value:     "href",
	},
	ogTag{
		tpe:       "twitter",
		attribute: "name",
		name:      "twitter:image",
		value:     "value",
	},
	ogTag{
		tpe:       "twitter",
		attribute: "name",
		name:      "twitter:image",
		value:     "content",
	},
}

type ogImage struct {
	url   string
	tpe   string
	score int
}

func OpenGraphResolver(article *Article) string {
	doc := article.Doc
	meta := doc.Find("meta")
	links := doc.Find("link")
	topImage := ""
	meta = meta.Union(links)
	ogImages := make([]ogImage, 0)
	meta.Each(func(i int, tag *goquery.Selection) {
		for _, ogTag := range ogTags {
			attr, exist := tag.Attr(ogTag.attribute)
			value, vexist := tag.Attr(ogTag.value)
			if exist && attr == ogTag.name && vexist {
				ogImage := ogImage{
					url:   value,
					tpe:   ogTag.tpe,
					score: 0,
				}

				ogImages = append(ogImages, ogImage)
			}
		}
	})

	if len(ogImages) == 1 {
		topImage = ogImages[0].url
	} else {
		for _, ogImage := range ogImages {
			if largebig.MatchString(ogImage.url) {
				ogImage.score++
			}
			if ogImage.tpe == "twitter" {
				ogImage.score++
			}
		}
		topImage = findBestImageFromScore(ogImages).url
	}

	if topImage != "" && !strings.HasPrefix(topImage, "http") {
		topImage = "http://" + topImage
	}

	return topImage
}

func findBestImageFromScore(ogImages []ogImage) ogImage {
	max := 0
	var bestOGImage ogImage
	for _, ogImage := range ogImages {
		score := ogImage.score
		//println("OG", ogImage.url, score)
		if score >= max {
			max = score
			bestOGImage = ogImage
		}
	}

	return bestOGImage
}
<|endoftext|>


<commit_before>// +build windows

package disk

import (
	"bytes"
	"fmt"
	"syscall"
	"time"
	"unsafe"

	common "github.com/shirou/gopsutil/common"
)

var (
	procGetDiskFreeSpaceExW     = common.Modkernel32.NewProc("GetDiskFreeSpaceExW")
	procGetLogicalDriveStringsW = common.Modkernel32.NewProc("GetLogicalDriveStringsW")
	procGetDriveType            = common.Modkernel32.NewProc("GetDriveTypeW")
	provGetVolumeInformation    = common.Modkernel32.NewProc("GetVolumeInformationW")
)

var (
	FileFileCompression = int64(16)     // 0x00000010
	FileReadOnlyVolume  = int64(524288) // 0x00080000
)

const WaitMSec = 500

func DiskUsage(path string) (DiskUsageStat, error) {
	ret := DiskUsageStat{}

	ret.Path = path
	lpFreeBytesAvailable := int64(0)
	lpTotalNumberOfBytes := int64(0)
	lpTotalNumberOfFreeBytes := int64(0)
	diskret, _, err := procGetDiskFreeSpaceExW.Call(
		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
		uintptr(unsafe.Pointer(&lpFreeBytesAvailable)),
		uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)),
		uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes)))
	if diskret == 0 {
		return ret, err
	}
	ret.Total = uint64(lpTotalNumberOfBytes)
	//	ret.Free = uint64(lpFreeBytesAvailable) // python psutil does not use this
	ret.Free = uint64(lpTotalNumberOfFreeBytes)
	ret.Used = ret.Total - ret.Free
	ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0

	//TODO: implement inodes stat
	ret.InodesTotal = 0
	ret.InodesUsed = 0
	ret.InodesFree = 0
	ret.InodesUsedPercent = 0.0
	return ret, nil
}

func DiskPartitions(all bool) ([]DiskPartitionStat, error) {
	var ret []DiskPartitionStat
	lpBuffer := make([]byte, 254)
	diskret, _, err := procGetLogicalDriveStringsW.Call(
		uintptr(len(lpBuffer)),
		uintptr(unsafe.Pointer(&lpBuffer[0])))
	if diskret == 0 {
		return ret, err
	}
	for _, v := range lpBuffer {
		if v >= 65 && v <= 90 {
			path := string(v) + ":"
			if path == "A:" || path == "B:" { // skip floppy drives
				continue
			}
			typepath, _ := syscall.UTF16PtrFromString(path)
			typeret, _, _ := procGetDriveType.Call(uintptr(unsafe.Pointer(typepath)))
			if typeret == 0 {
				return ret, syscall.GetLastError()
			}
			// 2: DRIVE_REMOVABLE 3: DRIVE_FIXED 5: DRIVE_CDROM

			if typeret == 2 || typeret == 3 || typeret == 5 {
				lpVolumeNameBuffer := make([]byte, 256)
				lpVolumeSerialNumber := int64(0)
				lpMaximumComponentLength := int64(0)
				lpFileSystemFlags := int64(0)
				lpFileSystemNameBuffer := make([]byte, 256)
				volpath, _ := syscall.UTF16PtrFromString(string(v) + ":/")
				driveret, _, err := provGetVolumeInformation.Call(
					uintptr(unsafe.Pointer(volpath)),
					uintptr(unsafe.Pointer(&lpVolumeNameBuffer[0])),
					uintptr(len(lpVolumeNameBuffer)),
					uintptr(unsafe.Pointer(&lpVolumeSerialNumber)),
					uintptr(unsafe.Pointer(&lpMaximumComponentLength)),
					uintptr(unsafe.Pointer(&lpFileSystemFlags)),
					uintptr(unsafe.Pointer(&lpFileSystemNameBuffer[0])),
					uintptr(len(lpFileSystemNameBuffer)))
				if driveret == 0 {
					return ret, err
				}
				opts := "rw"
				if lpFileSystemFlags&FileReadOnlyVolume != 0 {
					opts = "ro"
				}
				if lpFileSystemFlags&FileFileCompression != 0 {
					opts += ".compress"
				}

				d := DiskPartitionStat{
					Mountpoint: path,
					Device:     path,
					Fstype:     string(bytes.Replace(lpFileSystemNameBuffer, []byte("\x00"), []byte(""), -1)),
					Opts:       opts,
				}
				ret = append(ret, d)
			}
		}
	}
	return ret, nil
}

func DiskIOCounters() (map[string]DiskIOCountersStat, error) {
	ret := make(map[string]DiskIOCountersStat, 0)
	query, err := common.CreateQuery()
	if err != nil {
		return ret, err
	}

	drivebuf := make([]byte, 256)
	r, _, err := procGetLogicalDriveStringsW.Call(
		uintptr(len(drivebuf)),
		uintptr(unsafe.Pointer(&drivebuf[0])))

	if r == 0 {
		return ret, err
	}

	drivemap := make(map[string][]*common.CounterInfo, 0)
	for _, v := range drivebuf {
		if v >= 65 && v <= 90 {
			drive := string(v)
			r, _, err = procGetDriveType.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(drive + `:\`))))
			if r != common.DRIVE_FIXED {
				continue
			}
			drivemap[drive] = make([]*common.CounterInfo, 0, 2)
			var counter *common.CounterInfo

			counter, err = common.CreateCounter(query,
				"read",
				fmt.Sprintf(`\PhysicalDisk(0 %s:)\Disk Reads/sec`, drive))
			if err != nil {
				return nil, err
			}
			drivemap[drive] = append(drivemap[drive], counter)
			counter, err = common.CreateCounter(query,
				"write",
				fmt.Sprintf(`\PhysicalDisk(0 %s:)\Disk Writes/sec`, drive))
			if err != nil {
				return nil, err
			}
			drivemap[drive] = append(drivemap[drive], counter)
		}
	}
	r, _, err = common.PdhCollectQueryData.Call(uintptr(query))
	if r != 0 && err != nil {
		return nil, err
	}
	time.Sleep(time.Duration(WaitMSec) * time.Millisecond)
	r, _, err = common.PdhCollectQueryData.Call(uintptr(query))
	if r != 0 && err != nil {
		return nil, err
	}

	for drive, counters := range drivemap {
		stat := DiskIOCountersStat{}
		for _, v := range counters {
			var fmtValue common.PDH_FMT_COUNTERVALUE_LARGE
			r, _, err := common.PdhGetFormattedCounterValue.Call(uintptr(v.Counter), common.PDH_FMT_LARGE, uintptr(0), uintptr(unsafe.Pointer(&fmtValue)))
			if r != 0 && r != common.PDH_INVALID_DATA {
				return nil, err
			}

			switch v.PostName {
			case "read":
				stat.ReadCount = uint64(fmtValue.LargeValue)
			case "write":
				stat.WriteCount = uint64(fmtValue.LargeValue)
			default:
				return ret, fmt.Errorf("unknown postname: %s", v.PostName)
			}
			stat.Name = drive
		}
		ret[drive] = stat
	}

	return ret, nil
}
<commit_msg>Fix disk usage stats for windows<commit_after>// +build windows

package disk

import (
	"bytes"
	"fmt"
	"syscall"
	"time"
	"unsafe"

	common "github.com/shirou/gopsutil/common"
)

var (
	procGetDiskFreeSpaceExW     = common.Modkernel32.NewProc("GetDiskFreeSpaceExW")
	procGetLogicalDriveStringsW = common.Modkernel32.NewProc("GetLogicalDriveStringsW")
	procGetDriveType            = common.Modkernel32.NewProc("GetDriveTypeW")
	provGetVolumeInformation    = common.Modkernel32.NewProc("GetVolumeInformationW")
)

var (
	FileFileCompression = int64(16)     // 0x00000010
	FileReadOnlyVolume  = int64(524288) // 0x00080000
)

const WaitMSec = 500

func DiskUsage(path string) (*DiskUsageStat, error) {
	ret := DiskUsageStat{}

	lpFreeBytesAvailable := int64(0)
	lpTotalNumberOfBytes := int64(0)
	lpTotalNumberOfFreeBytes := int64(0)
	diskret, _, err := procGetDiskFreeSpaceExW.Call(
		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
		uintptr(unsafe.Pointer(&lpFreeBytesAvailable)),
		uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)),
		uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes)))
	if diskret == 0 {
		return nil, err
	}
	ret := &DiskUsageStat{
		Path:  path,
		Total: uint64(lpTotalNumberOfBytes),
		Free:  uint64(lpTotalNumberOfFreeBytes),
		// Used: uint64(lpTotalNumberOfBytes) - uint64(lpTotalNumberOfFreeBytes)
		// UsedPercent: (float64(lpTotalNumberOfBytes) - float64(lpTotalNumberOfFreeBytes)) / float64(lpTotalNumberOfBytes) * 100
		// InodesTotal: 0,
		// InodesFree: 0,
		// InodesUsed: 0,
		// InodesUsedPercent: 0,
	}
	return ret, nil
}

func DiskPartitions(all bool) ([]DiskPartitionStat, error) {
	var ret []DiskPartitionStat
	lpBuffer := make([]byte, 254)
	diskret, _, err := procGetLogicalDriveStringsW.Call(
		uintptr(len(lpBuffer)),
		uintptr(unsafe.Pointer(&lpBuffer[0])))
	if diskret == 0 {
		return ret, err
	}
	for _, v := range lpBuffer {
		if v >= 65 && v <= 90 {
			path := string(v) + ":"
			if path == "A:" || path == "B:" { // skip floppy drives
				continue
			}
			typepath, _ := syscall.UTF16PtrFromString(path)
			typeret, _, _ := procGetDriveType.Call(uintptr(unsafe.Pointer(typepath)))
			if typeret == 0 {
				return ret, syscall.GetLastError()
			}
			// 2: DRIVE_REMOVABLE 3: DRIVE_FIXED 5: DRIVE_CDROM

			if typeret == 2 || typeret == 3 || typeret == 5 {
				lpVolumeNameBuffer := make([]byte, 256)
				lpVolumeSerialNumber := int64(0)
				lpMaximumComponentLength := int64(0)
				lpFileSystemFlags := int64(0)
				lpFileSystemNameBuffer := make([]byte, 256)
				volpath, _ := syscall.UTF16PtrFromString(string(v) + ":/")
				driveret, _, err := provGetVolumeInformation.Call(
					uintptr(unsafe.Pointer(volpath)),
					uintptr(unsafe.Pointer(&lpVolumeNameBuffer[0])),
					uintptr(len(lpVolumeNameBuffer)),
					uintptr(unsafe.Pointer(&lpVolumeSerialNumber)),
					uintptr(unsafe.Pointer(&lpMaximumComponentLength)),
					uintptr(unsafe.Pointer(&lpFileSystemFlags)),
					uintptr(unsafe.Pointer(&lpFileSystemNameBuffer[0])),
					uintptr(len(lpFileSystemNameBuffer)))
				if driveret == 0 {
					return ret, err
				}
				opts := "rw"
				if lpFileSystemFlags&FileReadOnlyVolume != 0 {
					opts = "ro"
				}
				if lpFileSystemFlags&FileFileCompression != 0 {
					opts += ".compress"
				}

				d := DiskPartitionStat{
					Mountpoint: path,
					Device:     path,
					Fstype:     string(bytes.Replace(lpFileSystemNameBuffer, []byte("\x00"), []byte(""), -1)),
					Opts:       opts,
				}
				ret = append(ret, d)
			}
		}
	}
	return ret, nil
}

func DiskIOCounters() (map[string]DiskIOCountersStat, error) {
	ret := make(map[string]DiskIOCountersStat, 0)
	query, err := common.CreateQuery()
	if err != nil {
		return ret, err
	}

	drivebuf := make([]byte, 256)
	r, _, err := procGetLogicalDriveStringsW.Call(
		uintptr(len(drivebuf)),
		uintptr(unsafe.Pointer(&drivebuf[0])))

	if r == 0 {
		return ret, err
	}

	drivemap := make(map[string][]*common.CounterInfo, 0)
	for _, v := range drivebuf {
		if v >= 65 && v <= 90 {
			drive := string(v)
			r, _, err = procGetDriveType.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(drive + `:\`))))
			if r != common.DRIVE_FIXED {
				continue
			}
			drivemap[drive] = make([]*common.CounterInfo, 0, 2)
			var counter *common.CounterInfo

			counter, err = common.CreateCounter(query,
				"read",
				fmt.Sprintf(`\PhysicalDisk(0 %s:)\Disk Reads/sec`, drive))
			if err != nil {
				return nil, err
			}
			drivemap[drive] = append(drivemap[drive], counter)
			counter, err = common.CreateCounter(query,
				"write",
				fmt.Sprintf(`\PhysicalDisk(0 %s:)\Disk Writes/sec`, drive))
			if err != nil {
				return nil, err
			}
			drivemap[drive] = append(drivemap[drive], counter)
		}
	}
	r, _, err = common.PdhCollectQueryData.Call(uintptr(query))
	if r != 0 && err != nil {
		return nil, err
	}
	time.Sleep(time.Duration(WaitMSec) * time.Millisecond)
	r, _, err = common.PdhCollectQueryData.Call(uintptr(query))
	if r != 0 && err != nil {
		return nil, err
	}

	for drive, counters := range drivemap {
		stat := DiskIOCountersStat{}
		for _, v := range counters {
			var fmtValue common.PDH_FMT_COUNTERVALUE_LARGE
			r, _, err := common.PdhGetFormattedCounterValue.Call(uintptr(v.Counter), common.PDH_FMT_LARGE, uintptr(0), uintptr(unsafe.Pointer(&fmtValue)))
			if r != 0 && r != common.PDH_INVALID_DATA {
				return nil, err
			}

			switch v.PostName {
			case "read":
				stat.ReadCount = uint64(fmtValue.LargeValue)
			case "write":
				stat.WriteCount = uint64(fmtValue.LargeValue)
			default:
				return ret, fmt.Errorf("unknown postname: %s", v.PostName)
			}
			stat.Name = drive
		}
		ret[drive] = stat
	}

	return ret, nil
}
<|endoftext|>


<commit_before><commit_msg>removing unused code<commit_after><|endoftext|>