<commit_before>package steam

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/url"
	"regexp"
	"strconv"
)

// Due to the JSON being string, etc... we cannot re-use EconItem
// Also, "assetid" is included as "id" not as assetid.
type InventoryItem struct {
	AssetID    uint64        `json:"id,string,omitempty"`
	InstanceID uint64        `json:"instanceid,string,omitempty"`
	ClassID    uint64        `json:"classid,string,omitempty"`
	AppID      uint64        `json:"appid"`     // This!  (May be null; see desc if so)
	ContextID  uint64        `json:"contextid"` // Ditto  (May be null; see desc if so)
	Desc       *EconItemDesc `json:"-"`
}

type InventoryContext struct {
	ID         uint64 `json:"id,string"` /* Apparently context id needs at least 64 bits...  */
	AssetCount uint32 `json:"asset_count"`
	Name       string `json:"name"`
}

type InventoryAppStats struct {
	AppID            uint64                       `json:"appid"`
	Name             string                       `json:"name"`
	AssetCount       uint32                       `json:"asset_count"`
	Icon             string                       `json:"icon"`
	Link             string                       `json:"link"`
	InventoryLogo    string                       `json:"inventory_logo"`
	TradePermissions string                       `json:"trade_permissions"`
	Contexts         map[string]*InventoryContext `json:"rgContexts"`
}

var inventoryContextRegexp = regexp.MustCompile("var g_rgAppContextData = (.*?);")

func (session *Session) parseInventory(sid SteamID, appID, contextID uint64, start uint32, tradableOnly bool, items *[]*InventoryItem) (uint32, error) {
	params := url.Values{
		"start": {strconv.FormatUint(uint64(start), 10)},
	}
	if tradableOnly {
		params.Set("trading", "1")
	}

	resp, err := session.client.Get(fmt.Sprintf("https://steamcommunity.com/profiles/%d/inventory/json/%d/%d/?", sid, appID, contextID) + params.Encode())
	if err != nil {
		return 0, err
	}

	type Response struct {
		Success      bool                      `json:"success"`
		ErrorMsg     string                    `json:"Error"`
		MoreStart    interface{}               `json:"more_start"` // This can be a bool or a number...
		Inventory    map[string]*InventoryItem `json:"rgInventory"`
		Descriptions map[string]*EconItemDesc  `json:"rgDescriptions"`
		/* Missing: rgCurrency  */
	}

	var response Response
	if err = json.NewDecoder(resp.Body).Decode(&response); err != nil {
		return 0, err
	}

	if !response.Success {
		return 0, errors.New(response.ErrorMsg)
	}

	// Morph response.Inventory into an array of items.
	// This is due to Steam returning the items in the following format:
	//	rgInventory: {
	//		"54xxx": {
	//			"id": "54xxx"
	//			...
	//		}
	//	}
	// We also glue the descriptions.
	for _, value := range response.Inventory {
		if desc, ok := response.Descriptions[strconv.FormatUint(value.ClassID, 10)+"_"+strconv.FormatUint(value.InstanceID, 10)]; ok {
			value.Desc = desc
		}

		*items = append(*items, value)
	}

	io.Copy(ioutil.Discard, resp.Body)
	switch v := response.MoreStart.(type) {
	case int:
		return uint32(v), nil
	case uint:
		return uint32(v), nil
	case bool:
		break
	default:
		return 0, fmt.Errorf("parseInventory: missing implementation for type %v", v)
	}

	return 0, nil
}

func (session *Session) GetInventory(sid SteamID, appID, contextID uint64, tradableOnly bool) ([]*InventoryItem, error) {
	items := []*InventoryItem{}
	more := uint32(0)

	for {
		next, err := session.parseInventory(sid, appID, contextID, more, tradableOnly, &items)
		if err != nil {
			return nil, err
		}

		if next == 0 {
			break
		}

		more = next
	}

	return items, nil
}

func (session *Session) GetInventoryAppStats(sid SteamID) (map[string]InventoryAppStats, error) {
	resp, err := session.client.Get("https://steamcommunity.com/profiles/" + sid.ToString() + "/inventory")
	if resp != nil {
		defer resp.Body.Close()
	}

	if err != nil {
		return nil, err
	}

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

	m := inventoryContextRegexp.FindSubmatch(body)
	if m == nil || len(m) != 2 {
		return nil, err
	}

	inven := map[string]InventoryAppStats{}
	if err = json.Unmarshal(m[1], &inven); err != nil {
		return nil, err
	}

	return inven, nil
}
<commit_msg>inventory: fix unmarshal for empty inventories<commit_after>package steam

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/url"
	"regexp"
	"strconv"
)

// Due to the JSON being string, etc... we cannot re-use EconItem
// Also, "assetid" is included as "id" not as assetid.
type InventoryItem struct {
	AssetID    uint64        `json:"id,string,omitempty"`
	InstanceID uint64        `json:"instanceid,string,omitempty"`
	ClassID    uint64        `json:"classid,string,omitempty"`
	AppID      uint64        `json:"appid"`     // This!  (May be null; see desc if so)
	ContextID  uint64        `json:"contextid"` // Ditto  (May be null; see desc if so)
	Desc       *EconItemDesc `json:"-"`
}

type InventoryContext struct {
	ID         uint64 `json:"id,string"` /* Apparently context id needs at least 64 bits...  */
	AssetCount uint32 `json:"asset_count"`
	Name       string `json:"name"`
}

type InventoryAppStats struct {
	AppID            uint64                       `json:"appid"`
	Name             string                       `json:"name"`
	AssetCount       uint32                       `json:"asset_count"`
	Icon             string                       `json:"icon"`
	Link             string                       `json:"link"`
	InventoryLogo    string                       `json:"inventory_logo"`
	TradePermissions string                       `json:"trade_permissions"`
	Contexts         map[string]*InventoryContext `json:"rgContexts"`
}

var inventoryContextRegexp = regexp.MustCompile("var g_rgAppContextData = (.*?);")

func (session *Session) parseInventory(sid SteamID, appID, contextID uint64, start uint32, tradableOnly bool, items *[]*InventoryItem) (uint32, error) {
	params := url.Values{
		"start": {strconv.FormatUint(uint64(start), 10)},
	}
	if tradableOnly {
		params.Set("trading", "1")
	}

	resp, err := session.client.Get(fmt.Sprintf("https://steamcommunity.com/profiles/%d/inventory/json/%d/%d/?", sid, appID, contextID) + params.Encode())
	if err != nil {
		return 0, err
	}

	type Response struct {
		Success      bool                     `json:"success"`
		ErrorMsg     string                   `json:"Error"`
		MoreStart    interface{}              `json:"more_start"` // This can be a bool or a number...
		Inventory    string                   `json:"rgInventory"`
		Descriptions map[string]*EconItemDesc `json:"rgDescriptions"`
		/* Missing: rgCurrency  */
	}

	var response Response
	if err = json.NewDecoder(resp.Body).Decode(&response); err != nil {
		return 0, err
	}

	if !response.Success {
		return 0, errors.New(response.ErrorMsg)
	}

	var inventory map[string]*InventoryItem
	if err = json.Unmarshal([]byte(response.Inventory), &inventory); err != nil {
		// empty inventory...
		// NB: This only occurs on first run...
		return 0, nil
	}

	// Morph inventory into an array of items.
	// This is due to Steam returning the items in the following format:
	//	rgInventory: {
	//		"54xxx": {
	//			"id": "54xxx"
	//			...
	//		}
	//	}
	// We also glue the descriptions.
	for _, value := range inventory {
		if desc, ok := response.Descriptions[strconv.FormatUint(value.ClassID, 10)+"_"+strconv.FormatUint(value.InstanceID, 10)]; ok {
			value.Desc = desc
		}

		*items = append(*items, value)
	}

	io.Copy(ioutil.Discard, resp.Body)
	switch v := response.MoreStart.(type) {
	case int:
		return uint32(v), nil
	case uint:
		return uint32(v), nil
	case bool:
		break
	default:
		return 0, fmt.Errorf("parseInventory: missing implementation for type %v", v)
	}

	return 0, nil
}

func (session *Session) GetInventory(sid SteamID, appID, contextID uint64, tradableOnly bool) ([]*InventoryItem, error) {
	items := []*InventoryItem{}
	more := uint32(0)

	for {
		next, err := session.parseInventory(sid, appID, contextID, more, tradableOnly, &items)
		if err != nil {
			return nil, err
		}

		if next == 0 {
			break
		}

		more = next
	}

	return items, nil
}

func (session *Session) GetInventoryAppStats(sid SteamID) (map[string]InventoryAppStats, error) {
	resp, err := session.client.Get("https://steamcommunity.com/profiles/" + sid.ToString() + "/inventory")
	if resp != nil {
		defer resp.Body.Close()
	}

	if err != nil {
		return nil, err
	}

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

	m := inventoryContextRegexp.FindSubmatch(body)
	if m == nil || len(m) != 2 {
		return nil, err
	}

	inven := map[string]InventoryAppStats{}
	if err = json.Unmarshal(m[1], &inven); err != nil {
		return nil, err
	}

	return inven, nil
}
<|endoftext|>


<commit_before>package util

import "errors"

const (
    BINARY = iota
    TEXT
)

type DataType int

type Message struct {
    from *User
    to   *User
    dataType DataType
    data []byte
}

func NewMessage(from *User, to *User, dataType DataType, data []byte) Message {
    return Message{
        from: from,
        to: to,
        dataType: dataType,
        data: data,
    }
}

func (m Message) String() (string, error) {
    if m.dataType != TEXT {
        return "", errors.New("Message data is not a text type")
    }

    return string(m.data), nil
}

func (m Message) Binary() ([]byte, error) {
    if m.dataType != BINARY {
        return []byte{}, errors.New("Message data is not binary type")
    }

    return m.data, nil
}

func (m Message) From() *User {
    return m.from
}

func (m Message) To() *User {
    return m.to
}

func (m Message) DataType() DataType {
    return m.dataType
}

type User struct {
    Id  string
    In      chan Message
    Out     chan Message
}
<commit_msg>Add messageType property and change data type enum<commit_after>package util

import "log"

const (
    TEXT   = 1
    BINARY = 2
)

type DataType int

type Message struct {
    from *User
    to   *User
    messageType string
    dataType DataType
    data []byte
}

func NewMessage(from *User, to *User, messageType string,
                dataType DataType, data []byte) Message {
    return Message{
        from: from,
        to: to,
        messageType: messageType,
        dataType: dataType,
        data: data,
    }
}

func (m Message) String() string {
    if m.dataType != TEXT {
        log.Println("Message data is not a text type")
        return ""
    }

    return string(m.data)
}

func (m Message) Binary() []byte {
    if m.dataType != BINARY {
        log.Println("Message data is not binary type")
        return []byte{}
    }

    return m.data
}

func (m Message) From() *User {
    return m.from
}

func (m Message) To() *User {
    return m.to
}

func (m Message) DataType() DataType {
    return m.dataType
}

func (m Message) Raw() []byte {
    return m.data
}

type User struct {
    Id  string
    In      chan Message
    Out     chan Message
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"testing"
)

func TestParseLine(t *testing.T) {
	line1 := "http://example.com\t1"
	e, err := ParseLine(line1)

	if err != nil {
		t.Error("cannot parse line1")
	}
	if e.Label != POSITIVE {
		t.Error("Label must be POSITIVE")
	}

	line2 := "http://example.com\t-1"
	e, err = ParseLine(line2)

	if err != nil {
		t.Error("cannot parse line2")
	}
	if e.Label != NEGATIVE {
		t.Error("Label must be NEGATIVE")
	}

	line3 := "http://example.com"
	e, err = ParseLine(line3)

	if err != nil {
		t.Error("cannot parse line3")
	}
	if e.Label != UNLABELED {
		t.Error("Label must be UNLABELED")
	}

	line4 := "http://example.com\t2"
	e, err = ParseLine(line4)

	if e != nil {
		t.Error("wrong line format")
	}
}

func TestReadExamples(t *testing.T) {
	filename := "tech_input_example.txt"
	examples, err := ReadExamples(filename)

	if err != nil {
		t.Error(fmt.Printf("Cannot read examples from %s", filename))
	}
	if len(examples) == 0 {
		t.Error(fmt.Printf("%s should contain more than one examples", filename))
	}
}

func TestWriteExamples(t *testing.T) {
	filename := ".write_test.txt"
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)

	err := WriteExamples(Examples{e1, e2}, filename)
	if err != nil {
		t.Error(fmt.Printf("Cannot write examples to %s", filename))
	}

	examples, err := ReadExamples(filename)
	if err != nil {
		t.Error(fmt.Printf("Cannot read examples from %s", filename))
	}
	if len(examples) == 2 {
		t.Error(fmt.Printf("%s should contain two examples", filename))
	}
}

func TestFilterLabeledExamples(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("http://google.com", UNLABELED)

	examples := FilterLabeledExamples(Examples{e1, e2, e3})
	if len(examples) != 2 {
		t.Error("Number of labeled examples should be 2")
	}
}

func TestFilterUnlabeledExamples(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("http://google.com", UNLABELED)
	e3.Title = "Google"

	examples := FilterUnlabeledExamples(Examples{e1, e2, e3})
	if len(examples) != 1 {
		t.Error("Number of unlabeled examples should be 1")
	}
}

func TestFilterStatusCodeOkExamples(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e1.StatusCode = 200
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e2.StatusCode = 404
	e3 := NewExample("http://google.com", UNLABELED)
	e3.StatusCode = 304

	examples := FilterStatusCodeOkExamples(Examples{e1, e2, e3})
	if len(examples) != 1 {
		t.Error("Number of examples (status code = 200) should be 1")
	}
}

func TestRemoveDuplicate(t *testing.T) {
	args := []string{"hoge", "fuga", "piyo", "hoge"}

	result := removeDuplicate(args)
	if len(result) != 3 {
		t.Error("Number of unique string in args should be 3")
	}
}

func TestSplitTrainAndDev(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("http://google.com", UNLABELED)
	e4 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e5 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e6 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e7 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e8 := NewExample("http://google.com", UNLABELED)
	e9 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e10 := NewExample("http://www.yasuhisay.info", NEGATIVE)

	train, dev := splitTrainAndDev(Examples{e1, e2, e3, e4, e5, e6, e7, e8, e9, e10})
	if len(train) != 8 {
		t.Error("Number of training examples should be 8")
	}
	if len(dev) != 2 {
		t.Error("Number of dev examples should be 2")
	}
}

func TestAttachMetaData(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("https://github.com", UNLABELED)
	examples := Examples{e1, e2, e3}
	cache, err := NewRedisCache()
	if err != nil {
		t.Error("Cannot connect to redis")
	}
	AttachMetaData(cache, examples)

	if examples[0].Title == "" {
		t.Errorf("Title must not be empty for %s", examples[0].Url)
	}
	if len(examples[0].Fv) == 0 {
		t.Errorf("Feature vector must not be empty for %s", examples[0].Url)
	}
}
<commit_msg>アンテナに置き換え<commit_after>package main

import (
	"fmt"
	"testing"
)

func TestParseLine(t *testing.T) {
	line1 := "http://example.com\t1"
	e, err := ParseLine(line1)

	if err != nil {
		t.Error("cannot parse line1")
	}
	if e.Label != POSITIVE {
		t.Error("Label must be POSITIVE")
	}

	line2 := "http://example.com\t-1"
	e, err = ParseLine(line2)

	if err != nil {
		t.Error("cannot parse line2")
	}
	if e.Label != NEGATIVE {
		t.Error("Label must be NEGATIVE")
	}

	line3 := "http://example.com"
	e, err = ParseLine(line3)

	if err != nil {
		t.Error("cannot parse line3")
	}
	if e.Label != UNLABELED {
		t.Error("Label must be UNLABELED")
	}

	line4 := "http://example.com\t2"
	e, err = ParseLine(line4)

	if e != nil {
		t.Error("wrong line format")
	}
}

func TestReadExamples(t *testing.T) {
	filename := "tech_input_example.txt"
	examples, err := ReadExamples(filename)

	if err != nil {
		t.Error(fmt.Printf("Cannot read examples from %s", filename))
	}
	if len(examples) == 0 {
		t.Error(fmt.Printf("%s should contain more than one examples", filename))
	}
}

func TestWriteExamples(t *testing.T) {
	filename := ".write_test.txt"
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)

	err := WriteExamples(Examples{e1, e2}, filename)
	if err != nil {
		t.Error(fmt.Printf("Cannot write examples to %s", filename))
	}

	examples, err := ReadExamples(filename)
	if err != nil {
		t.Error(fmt.Printf("Cannot read examples from %s", filename))
	}
	if len(examples) == 2 {
		t.Error(fmt.Printf("%s should contain two examples", filename))
	}
}

func TestFilterLabeledExamples(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("http://google.com", UNLABELED)

	examples := FilterLabeledExamples(Examples{e1, e2, e3})
	if len(examples) != 2 {
		t.Error("Number of labeled examples should be 2")
	}
}

func TestFilterUnlabeledExamples(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("http://google.com", UNLABELED)
	e3.Title = "Google"

	examples := FilterUnlabeledExamples(Examples{e1, e2, e3})
	if len(examples) != 1 {
		t.Error("Number of unlabeled examples should be 1")
	}
}

func TestFilterStatusCodeOkExamples(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e1.StatusCode = 200
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e2.StatusCode = 404
	e3 := NewExample("http://google.com", UNLABELED)
	e3.StatusCode = 304

	examples := FilterStatusCodeOkExamples(Examples{e1, e2, e3})
	if len(examples) != 1 {
		t.Error("Number of examples (status code = 200) should be 1")
	}
}

func TestRemoveDuplicate(t *testing.T) {
	args := []string{"hoge", "fuga", "piyo", "hoge"}

	result := removeDuplicate(args)
	if len(result) != 3 {
		t.Error("Number of unique string in args should be 3")
	}
}

func TestSplitTrainAndDev(t *testing.T) {
	e1 := NewExample("http://a.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("http://google.com", UNLABELED)
	e4 := NewExample("http://a.hatena.ne.jp", POSITIVE)
	e5 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e6 := NewExample("http://a.hatena.ne.jp", POSITIVE)
	e7 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e8 := NewExample("http://google.com", UNLABELED)
	e9 := NewExample("http://a.hatena.ne.jp", POSITIVE)
	e10 := NewExample("http://www.yasuhisay.info", NEGATIVE)

	train, dev := splitTrainAndDev(Examples{e1, e2, e3, e4, e5, e6, e7, e8, e9, e10})
	if len(train) != 8 {
		t.Error("Number of training examples should be 8")
	}
	if len(dev) != 2 {
		t.Error("Number of dev examples should be 2")
	}
}

func TestAttachMetaData(t *testing.T) {
	e1 := NewExample("http://b.hatena.ne.jp", POSITIVE)
	e2 := NewExample("http://www.yasuhisay.info", NEGATIVE)
	e3 := NewExample("https://github.com", UNLABELED)
	examples := Examples{e1, e2, e3}
	cache, err := NewRedisCache()
	if err != nil {
		t.Error("Cannot connect to redis")
	}
	AttachMetaData(cache, examples)

	if examples[0].Title == "" {
		t.Errorf("Title must not be empty for %s", examples[0].Url)
	}
	if len(examples[0].Fv) == 0 {
		t.Errorf("Feature vector must not be empty for %s", examples[0].Url)
	}
}
<|endoftext|>


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

package utils

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"strings"
)

type Hash string

func ParseHash(s string) (Hash, error) {
	if strings.HasPrefix(s, "sha256:") {
		_, err := hex.DecodeString(s[7:])
		if err != nil {
			return "", err
		}
		return Hash(s), nil
	} else {
		return "", fmt.Errorf("invalid hash: %q", s)
	}
}

func ComputeHash(b []byte) Hash {
	h := sha256.Sum256(b)
	return Hash("sha256:" + hex.EncodeToString(h[:]))
}

type NodeID struct {
	Root Hash
	Path []Selector
}
<commit_msg>Hash check<commit_after>//
// Copyright 2021 The Ent Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package utils

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"strings"
)

type Hash string

func ParseHash(s string) (Hash, error) {
	if strings.HasPrefix(s, "sha256:") {
		rest := s[7:]
		if len(rest) != 64 {
			return "", fmt.Errorf("invalid hash: %q", s)
		}
		for _, c := range rest {
			if !strings.Contains("0123456789abcdef", string(c)) {
				return "", fmt.Errorf("invalid hash: %q", s)
			}
		}
		_, err := hex.DecodeString(s[7:])
		if err != nil {
			return "", err
		}
		return Hash(s), nil
	} else {
		return "", fmt.Errorf("invalid hash: %q", s)
	}
}

func ComputeHash(b []byte) Hash {
	h := sha256.Sum256(b)
	return Hash("sha256:" + hex.EncodeToString(h[:]))
}

type NodeID struct {
	Root Hash
	Path []Selector
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	flag "github.com/ogier/pflag"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
	"runtime"
	"time"
)

const (
	version string = "0.0.1"
)

var (
	downloaded []int64
	boards     string = "a|b|c|d|e|f|g|gif|h|hr|k|m|o|p|r|s|t|u|v|vg|w|wg|i|ic|r9k|cm|hm|y|3|adv|an|cgl|ck|co|diy|fa|fit|hc|int|jp|lit|mlp|mu|n|po|pol|sci|soc|sp|tg|toy|trv|tv|vp|wsg|x|q"

	// Options
	minWidth     *int64         = flag.Int64P("min-width", "w", 0, "Minimum width of images")
	minHeight    *int64         = flag.Int64P("min-height", "h", 0, "Minimum height of images")
	refresh      *time.Duration = flag.DurationP("refresh", "r", time.Second*30, "Refresh rate (min 30s)")
	orignalNames *bool          = flag.BoolP("original-names", "o", false, "Save images under original filenames")
	showVersion  *bool          = flag.BoolP("version", "v", false, "Show version")
)

type Post struct {
	No             int64
	Resto          int64
	Sticky         bool
	Closed         bool
	Now            string
	Time           int64
	Name           string
	Trip           string
	Id             string
	Capcode        string
	Country        string
	Country_name   string
	Email          string
	Sub            string
	Com            string
	Tim            int64
	Filename       string
	Ext            string
	Fsize          int64
	Md5            string
	W              int64
	H              int64
	Tn_w           int64
	Tn_h           int64
	Filedeleted    bool
	Spoiler        bool
	Custom_spoiler bool
	Omitted_posts  int64
	Omitted_images int64
}

func (p *Post) FullFileName(original bool) (s string) {
	if original {
		s = fmt.Sprintf("%s%s", p.Filename, p.Ext)
	} else {
		s = fmt.Sprintf("%d%s", p.Tim, p.Ext)
	}
	return
}

type Thread struct {
	Posts []Post
}

func checkError(err error) {
	if err != nil {
		log.Println(err.Error())
		os.Exit(1)
	}
}

func parseThreadId(s string) (b, id string, err error) {
	r, err := regexp.Compile(fmt.Sprintf("^/?(%s)/(?:res/)?(\\d+)", boards))
	if err != nil {
		return b, id, err
	}

	groups := r.FindSubmatch([]byte(s))
	if len(groups) < 1 {
		return b, id, errors.New("Input does not match regex")
	}

	b = string(groups[1])
	id = string(groups[2])

	return b, id, nil
}

func parseThreadFromJson(r io.Reader) (Thread, error) {
	dec := json.NewDecoder(r)
	var t Thread
	for {
		if err := dec.Decode(&t); err == io.EOF {
			break
		} else if err != nil {
			return t, err
		}
	}
	return t, nil
}

func downloadImage(board string, p Post) {
	if p.W < *minWidth || p.H < *minHeight || p.Filedeleted {
		downloaded = append(downloaded, p.Tim)
		return
	}

	url := fmt.Sprintf("https://images.4chan.org/%s/src/%d%s", board, p.Tim, p.Ext)
	img, _, err := getUrl(url)
	checkError(err)

	err = ioutil.WriteFile(p.FullFileName(*orignalNames), img, 0644)
	checkError(err)

	downloaded = append(downloaded, p.Tim)
}

func getUrl(url string) ([]byte, int, error) {
	resp, err := http.Get(url)
	if err != nil {
		return []byte{}, 0, nil
	}

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

}

func wasDownloaded(p Post) bool {
	for _, e := range downloaded {
		if e == p.Tim {
			return true
		}
	}
	return false
}

func loadThread(board string, id string) {
	url := fmt.Sprintf("https://api.4chan.org/%s/res/%s.json", board, id)
	resp, status, err := getUrl(url)
	checkError(err)
	if status != 200 {
		if status == 404 {
			log.Println("Thread 404'd")
			os.Exit(1)
		}
		fmt.Printf("Something went wrong\nGot return code %d at '%s'.\n", status, url)
		return
	}

	thread, err := parseThreadFromJson(bytes.NewReader(resp))
	if err != nil {
		log.Println("Could not parse thread")
	}

	for _, e := range thread.Posts {
		if !wasDownloaded(e) {
			go downloadImage(board, e)
		}
	}
}

func init() {
	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, "Usage: chanloader [options] /b/res/123456\nOptions:")
		flag.PrintDefaults()
	}
	flag.Parse()
	if *refresh < time.Second*30 {
		*refresh = time.Second * 30
	}

	if *showVersion {
		fmt.Println(version)
		os.Exit(0)
	}

	if flag.NArg() < 1 {
		flag.Usage()
		os.Exit(1)
	}

	runtime.GOMAXPROCS(runtime.NumCPU())
}

func main() {
	board, id, err := parseThreadId(flag.Arg(0))
	if err != nil {
		fmt.Printf("Invalid input: %s\n", flag.Arg(0))
		flag.Usage()
		os.Exit(1)
	}

	ticker := time.NewTicker(*refresh)
	for {
		log.Println("Loading thread")
		go loadThread(board, id)
		<-ticker.C
	}
}
<commit_msg>Adapt to new urls<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	flag "github.com/ogier/pflag"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
	"runtime"
	"time"
)

const (
	version string = "0.0.1"
)

var (
	downloaded []int64
	boards     string = "a|b|c|d|e|f|g|gif|h|hr|k|m|o|p|r|s|t|u|v|vg|w|wg|i|ic|r9k|cm|hm|y|3|adv|an|cgl|ck|co|diy|fa|fit|hc|int|jp|lit|mlp|mu|n|po|pol|sci|soc|sp|tg|toy|trv|tv|vp|wsg|x|q"

	// Options
	minWidth     *int64         = flag.Int64P("min-width", "w", 0, "Minimum width of images")
	minHeight    *int64         = flag.Int64P("min-height", "h", 0, "Minimum height of images")
	refresh      *time.Duration = flag.DurationP("refresh", "r", time.Second*30, "Refresh rate (min 30s)")
	orignalNames *bool          = flag.BoolP("original-names", "o", false, "Save images under original filenames")
	showVersion  *bool          = flag.BoolP("version", "v", false, "Show version")
)

type Post struct {
	No             int64
	Resto          int64
	Sticky         bool
	Closed         bool
	Now            string
	Time           int64
	Name           string
	Trip           string
	Id             string
	Capcode        string
	Country        string
	Country_name   string
	Email          string
	Sub            string
	Com            string
	Tim            int64
	Filename       string
	Ext            string
	Fsize          int64
	Md5            string
	W              int64
	H              int64
	Tn_w           int64
	Tn_h           int64
	Filedeleted    bool
	Spoiler        bool
	Custom_spoiler bool
	Omitted_posts  int64
	Omitted_images int64
}

func (p *Post) FullFileName(original bool) (s string) {
	if original {
		s = fmt.Sprintf("%s%s", p.Filename, p.Ext)
	} else {
		s = fmt.Sprintf("%d%s", p.Tim, p.Ext)
	}
	return
}

type Thread struct {
	Posts []Post
}

func checkError(err error) {
	if err != nil {
		log.Println(err.Error())
		os.Exit(1)
	}
}

func parseThreadId(s string) (b, id string, err error) {
	r, err := regexp.Compile(fmt.Sprintf("^(?:https?://boards.4chan.org)?/?(%s)/(?:thread/)?(\\d+).+$", boards))
	if err != nil {
		return b, id, err
	}

	groups := r.FindSubmatch([]byte(s))
	if len(groups) < 1 {
		return b, id, errors.New("Input does not match regex")
	}

	b = string(groups[1])
	id = string(groups[2])

	return b, id, nil
}

func parseThreadFromJson(r io.Reader) (Thread, error) {
	dec := json.NewDecoder(r)
	var t Thread
	for {
		if err := dec.Decode(&t); err == io.EOF {
			break
		} else if err != nil {
			return t, err
		}
	}
	return t, nil
}

func downloadImage(board string, p Post) {
	if p.W < *minWidth || p.H < *minHeight || p.Filedeleted {
		downloaded = append(downloaded, p.Tim)
		return
	}

	url := fmt.Sprintf("https://images.4chan.org/%s/src/%d%s", board, p.Tim, p.Ext)
	img, _, err := getUrl(url)
	checkError(err)

	err = ioutil.WriteFile(p.FullFileName(*orignalNames), img, 0644)
	checkError(err)

	downloaded = append(downloaded, p.Tim)
}

func getUrl(url string) ([]byte, int, error) {
	resp, err := http.Get(url)
	if err != nil {
		return []byte{}, 0, nil
	}

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

}

func wasDownloaded(p Post) bool {
	for _, e := range downloaded {
		if e == p.Tim {
			return true
		}
	}
	return false
}

func loadThread(board string, id string) {
	url := fmt.Sprintf("https://api.4chan.org/%s/res/%s.json", board, id)
	resp, status, err := getUrl(url)
	checkError(err)
	if status != 200 {
		if status == 404 {
			log.Println("Thread 404'd")
			os.Exit(1)
		}
		fmt.Printf("Something went wrong\nGot return code %d at '%s'.\n", status, url)
		return
	}

	thread, err := parseThreadFromJson(bytes.NewReader(resp))
	if err != nil {
		log.Println("Could not parse thread")
	}

	for _, e := range thread.Posts {
		if !wasDownloaded(e) {
			go downloadImage(board, e)
		}
	}
}

func init() {
	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, "Usage: chanloader [options] [http(s)://boards.4chan.org/]b/thread/123456[/thread-name]\nOptions:")
		flag.PrintDefaults()
	}
	flag.Parse()
	if *refresh < time.Second*30 {
		*refresh = time.Second * 30
	}

	if *showVersion {
		fmt.Println(version)
		os.Exit(0)
	}

	if flag.NArg() < 1 {
		flag.Usage()
		os.Exit(1)
	}

	runtime.GOMAXPROCS(runtime.NumCPU())
}

func main() {
	board, id, err := parseThreadId(flag.Arg(0))
	if err != nil {
		fmt.Printf("Invalid input: %s\n", flag.Arg(0))
		flag.Usage()
		os.Exit(1)
	}

	ticker := time.NewTicker(*refresh)
	for {
		log.Println("Loading thread")
		go loadThread(board, id)
		<-ticker.C
	}
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"fmt"
	"net/http"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"encoding/json"
	"time"
)

var collection

type Comment struct {
	Id     string   `json:"id" bson:"_id,omitempty"`
    Type   int      `json:"type"` // code, footnote
    Start  int 		`json:"start"`
    End    int 		`json:"end"`
    Text   string   `json:"text"`
    Author string   `json:"author"`
    Time   string	`json:"time"`
    MediaId string	`json:"mediaid" bson:"mediaid"`
}

func handleGetComments (mediaid string, w http.ResponseWriter, r *http.Request) {
		var results []Comment
		err := collection.Find(bson.M{"mediaid": mediaid}).All(&results)
		if err != nil {
			http.Error(w, "bad request", http.StatusInternalServerError)
			return
		}
		m, err := json.Marshal(results)
		if err != nil {
			http.Error(w, "bad request", http.StatusInternalServerError)
			return
		}
		io.WriteString(w, string(m))
}

func handlePostComment (mediaid string, w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(req.Body)
	var c Comment
	err := decoder.Decode(&c)
	c.Time = time.Now()
	c.MediaId = mediaid
	// Insert Datas
	err := collection.Insert(&c)
	if err != nil {
		http.Error(w, "bad request", http.StatusInternalServerError)
		return
	}
}

func handleDeleteComment (mediaid string, w http.ResponseWriter, r *http.Request) {
	commentid := r.URL.Query().Get("commentid")
	if len(commentid) == 0 {
		http.Error(w, "bad request", http.StatusInternalServerError)
		return
	}
	collection.Remove(bson.M{"_id": commentid})
}

func commentapi(w http.ResponseWriter, r *http.Request) {
	mediaid := r.URL.Query().Get("mediaid")
	if len(mediaid) == 0 {
		http.Error(w, "bad request", http.StatusInternalServerError)
		return
	}
	switch r.Method {
	case "GET":
		handleGetComments(mediaid, w, r)
	case "POST":
		handlePostComment(mediaid, w, r)
		break
	case "DELETE":
		handleDeleteComment(mediaid, w, r)
		break
	default:
		// Give an error message.
		http.Error(w, "bad request", http.StatusInternalServerError)
	}
}

func main() {
	session, err :=  mgo.Dial("127.0.0.1")
	if err != nil {
		panic(err)
	}
	defer session.Close()
	collection = session.DB("videotext").C("comments")

	http.Handle("/", http.FileServer(http.Dir(".")))
	http.HandleFunc("/comments/", commentapi)
	fmt.Println("listen on 3000")
	http.ListenAndServe(":3000", nil)
}
<commit_msg>fix errors<commit_after>package main

import (
	"io"
	"fmt"
	"net/http"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"encoding/json"
	"time"
)

var collection *mgo.Collection

type Comment struct {
	Id     string   `json:"id" bson:"_id,omitempty"`
    Type   int      `json:"type"` // code, footnote
    Start  int 		`json:"start"`
    End    int 		`json:"end"`
    Text   string   `json:"text"`
    Author string   `json:"author"`
    Time   string	`json:"time"`
    MediaId string	`json:"mediaid" bson:"mediaid"`
}

func handleGetComments (mediaid string, w http.ResponseWriter, r *http.Request) {
		var results []Comment
		err := collection.Find(bson.M{"mediaid": mediaid}).All(&results)
		if err != nil {
			http.Error(w, "bad request", http.StatusInternalServerError)
			return
		}
		m, err := json.Marshal(results)
		if err != nil {
			http.Error(w, "bad request", http.StatusInternalServerError)
			return
		}
		io.WriteString(w, string(m))
}

func handlePostComment (mediaid string, w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(r.Body)
	var c Comment
	err := decoder.Decode(&c)
	c.Time = time.Now().Format(time.UnixDate)
	c.MediaId = mediaid
	// Insert Datas
	err = collection.Insert(&c)
	if err != nil {
		http.Error(w, "bad request", http.StatusInternalServerError)
		return
	}
}

func handleDeleteComment (mediaid string, w http.ResponseWriter, r *http.Request) {
	commentid := r.URL.Query().Get("commentid")
	if len(commentid) == 0 {
		http.Error(w, "bad request", http.StatusInternalServerError)
		return
	}
	collection.Remove(bson.M{"_id": commentid})
}

func commentapi(w http.ResponseWriter, r *http.Request) {
	mediaid := r.URL.Query().Get("mediaid")
	if len(mediaid) == 0 {
		http.Error(w, "bad request", http.StatusInternalServerError)
		return
	}
	switch r.Method {
	case "GET":
		handleGetComments(mediaid, w, r)
	case "POST":
		handlePostComment(mediaid, w, r)
		break
	case "DELETE":
		handleDeleteComment(mediaid, w, r)
		break
	default:
		// Give an error message.
		http.Error(w, "bad request", http.StatusInternalServerError)
	}
}

func main() {
	session, err :=  mgo.Dial("127.0.0.1")
	if err != nil {
		panic(err)
	}
	defer session.Close()
	collection = session.DB("videotext").C("comments")

	http.Handle("/", http.FileServer(http.Dir(".")))
	http.HandleFunc("/comments/", commentapi)
	fmt.Println("listen on 3001")
	http.ListenAndServe(":3001", nil)
}
<|endoftext|>


<commit_before>package main

import "testing"

func <commit_msg>upd test txt<commit_after>package main

import "testing"

func TestSome() {

}
<|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/binary"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"strings"

	// Salsa
	"github.com/tchap/salsa/utils/flagutil"
	"github.com/tchap/salsa/utils/httputil"

	// Others
	"github.com/tchap/gocli"
	"gopkg.in/yaml.v1"
)

const crxURLTemplate = "https://clients2.google.com/service/update2/crx?response=redirect&x=id%3D~~~~%26uc"

// Subcommand initialisation and registration.
func init() {
	chromeExt := &gocli.Command{
		UsageLine: `
  chrome_ext SUBCMD`,
		Short: "manipulate Chrome Web Store extensions",
	}

	getName := &gocli.Command{
		UsageLine: `
  get_name MANIFEST_FILE`,
		Short:  "get name string from a manifest file",
		Action: getNameFromManifest,
	}
	chromeExt.MustRegisterSubcommand(getName)

	getVersion := &gocli.Command{
		UsageLine: `
  get_version MANIFEST_FILE`,
		Short:  "get version string from a manifest file",
		Action: getVersionFromManifest,
	}
	chromeExt.MustRegisterSubcommand(getVersion)

	getCrx := &gocli.Command{
		UsageLine: `
  get_crx [-zip] EXTENSION_ID FILENAME`,
		Short: "download Chrome extensions from Chrome Web Store",
		Long: `
  Download the extensions identified by EXTENSION_ID and save it in FILENAME.
  In case EXTENSION_ID is actually a URL, the address is used to retrieve the
  package directly.
		`,
		Action: runGetCrx,
	}
	getCrx.Flags.BoolVar(&convertCrxToZip, "zip", convertCrxToZip, "convert crx to zip")
	chromeExt.MustRegisterSubcommand(getCrx)

	genPackageJson := &gocli.Command{
		UsageLine: `
  gen_package_json [-dep NAME:VERSION ...] MANIFEST_FILE`,
		Short: "generate package.json from manifest.json",
		Long: `
  Generate package.json in the current working directory from manifest.json
  living at MANIFEST_FILE.

  Project name and version from manifest.json is reused, dependencies can be
  added to package.json using -dep option, which can be used multiple times.
  NAME is used as the dependency map key, version as the value
		`,
		Action: runGenPackageJson,
	}
	genPackageJson.Flags.Var(packageJsonDeps, "dep", "add a dependency into package.json")
	chromeExt.MustRegisterSubcommand(genPackageJson)

	getApp().MustRegisterSubcommand(chromeExt)
}

var convertCrxToZip bool

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

	var (
		id       = args[0]
		filename = args[1]
	)

	var packageURL string
	if regexp.MustCompile("^https?://").MatchString(id) {
		packageURL = id
	} else {
		packageURL = strings.Replace(crxURLTemplate, "~~~~", id, 1)
	}

	if config.Verbose() {
		fmt.Println("GET", packageURL)
	}
	if config.Dry() {
		return
	}

	// Download CRX.
	resp, err := httputil.Get(packageURL, nil)
	if err != nil {
		log.Fatalf("Error: failed to download crx: %v\n", err)
	}
	if resp.StatusCode >= 300 {
		log.Fatalf("Error: failed to download crx: %v\n", resp.Status)
	}
	defer resp.Body.Close()

	// Convert CRX to ZIP if requested.
	if convertCrxToZip {
		var (
			publicKeyLen uint32
			signatureLen uint32
		)

		// Drop magic number.
		if err := binary.Read(resp.Body, binary.LittleEndian, &publicKeyLen); err != nil {
			log.Fatal(err)
		}
		// Drop version.
		if err := binary.Read(resp.Body, binary.LittleEndian, &publicKeyLen); err != nil {
			log.Fatal(err)
		}
		// Read public key length.
		if err := binary.Read(resp.Body, binary.LittleEndian, &publicKeyLen); err != nil {
			log.Fatal(err)
		}
		// Read signature length.
		if err := binary.Read(resp.Body, binary.LittleEndian, &signatureLen); err != nil {
			log.Fatal(err)
		}

		var p []byte
		if publicKeyLen > signatureLen {
			p = make([]byte, publicKeyLen)
		} else {
			p = make([]byte, signatureLen)
		}

		// Drop the public key.
		b := p[:publicKeyLen]
		for i := uint32(0); i != publicKeyLen; {
			n, err := resp.Body.Read(b[i:])
			if err != nil {
				log.Fatal(err)
			}
			i += uint32(n)
		}
		// Drop the signature.
		b = p[:signatureLen]
		for i := uint32(0); i != signatureLen; {
			n, err := resp.Body.Read(b[i:])
			if err != nil {
				log.Fatal(err)
			}
			i += uint32(n)
		}
	}

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

	n, err := io.Copy(file, resp.Body)
	if err != nil {
		log.Fatalf("Error: %v\n", err)
	}

	fmt.Printf("Wrote %v bytes\n", n)
}

var packageJsonDeps = flagutil.NewMapValue()

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

	var manifestFilename = args[0]

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

	var packageJson struct {
		Name         string            `json:"name"`
		Version      string            `json:"version"`
		Dependencies map[string]string `json:"dependencies"`
	}

	if err := yaml.Unmarshal(content, &packageJson); err != nil {
		log.Fatalf("Error: failed to unmarshal manifest.json: %v", err)
	}

	packageJson.Name = strings.ToLower(packageJson.Name)
	packageJson.Name = strings.Replace(packageJson.Name, " ", "-", -1)
	packageJson.Dependencies = packageJsonDeps.M

	content, err = json.MarshalIndent(packageJson, "", "  ")
	if err != nil {
		log.Fatalf("Error: failed to marshal package.json: %v", err)
	}

	file, err := os.OpenFile("package.json", os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatalf("Error: %v", err)
	}
	defer file.Close()

	if _, err := file.Write(content); err != nil {
		log.Fatalf("Error: %v", err)
	}

	fmt.Println("package.json created")
}

func getNameFromManifest(cmd *gocli.Command, args []string) {
	if len(args) != 1 {
		cmd.Usage()
		os.Exit(2)
	}

	manifest, err := loadManifest(args[0])
	if err != nil {
		log.Fatalf("Error: %v\n", err)
	}

	fmt.Print(manifest.Name)
}

func getVersionFromManifest(cmd *gocli.Command, args []string) {
	if len(args) != 1 {
		cmd.Usage()
		os.Exit(2)
	}

	manifest, err := loadManifest(args[0])
	if err != nil {
		log.Fatalf("Error: %v\n", err)
	}

	fmt.Print(manifest.Version)
}

type manifest struct {
	Name    string
	Version string
}

func loadManifest(filename string) (*manifest, error) {
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	var m manifest
	if err := yaml.Unmarshal(content, &m); err != nil {
		return nil, err
	}

	return &m, nil
}
<commit_msg>bugfix: gen_package_json: Make sure the version string is correct<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/binary"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"strings"

	// Salsa
	"github.com/tchap/salsa/utils/flagutil"
	"github.com/tchap/salsa/utils/httputil"

	// Others
	"github.com/tchap/gocli"
	"gopkg.in/yaml.v1"
)

const crxURLTemplate = "https://clients2.google.com/service/update2/crx?response=redirect&x=id%3D~~~~%26uc"

// Subcommand initialisation and registration.
func init() {
	chromeExt := &gocli.Command{
		UsageLine: `
  chrome_ext SUBCMD`,
		Short: "manipulate Chrome Web Store extensions",
	}

	getName := &gocli.Command{
		UsageLine: `
  get_name MANIFEST_FILE`,
		Short:  "get name string from a manifest file",
		Action: getNameFromManifest,
	}
	chromeExt.MustRegisterSubcommand(getName)

	getVersion := &gocli.Command{
		UsageLine: `
  get_version MANIFEST_FILE`,
		Short:  "get version string from a manifest file",
		Action: getVersionFromManifest,
	}
	chromeExt.MustRegisterSubcommand(getVersion)

	getCrx := &gocli.Command{
		UsageLine: `
  get_crx [-zip] EXTENSION_ID FILENAME`,
		Short: "download Chrome extensions from Chrome Web Store",
		Long: `
  Download the extensions identified by EXTENSION_ID and save it in FILENAME.
  In case EXTENSION_ID is actually a URL, the address is used to retrieve the
  package directly.
		`,
		Action: runGetCrx,
	}
	getCrx.Flags.BoolVar(&convertCrxToZip, "zip", convertCrxToZip, "convert crx to zip")
	chromeExt.MustRegisterSubcommand(getCrx)

	genPackageJson := &gocli.Command{
		UsageLine: `
  gen_package_json [-dep NAME:VERSION ...] MANIFEST_FILE`,
		Short: "generate package.json from manifest.json",
		Long: `
  Generate package.json in the current working directory from manifest.json
  living at MANIFEST_FILE.

  Project name and version from manifest.json is reused, dependencies can be
  added to package.json using -dep option, which can be used multiple times.
  NAME is used as the dependency map key, version as the value
		`,
		Action: runGenPackageJson,
	}
	genPackageJson.Flags.Var(packageJsonDeps, "dep", "add a dependency into package.json")
	chromeExt.MustRegisterSubcommand(genPackageJson)

	getApp().MustRegisterSubcommand(chromeExt)
}

var convertCrxToZip bool

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

	var (
		id       = args[0]
		filename = args[1]
	)

	var packageURL string
	if regexp.MustCompile("^https?://").MatchString(id) {
		packageURL = id
	} else {
		packageURL = strings.Replace(crxURLTemplate, "~~~~", id, 1)
	}

	if config.Verbose() {
		fmt.Println("GET", packageURL)
	}
	if config.Dry() {
		return
	}

	// Download CRX.
	resp, err := httputil.Get(packageURL, nil)
	if err != nil {
		log.Fatalf("Error: failed to download crx: %v\n", err)
	}
	if resp.StatusCode >= 300 {
		log.Fatalf("Error: failed to download crx: %v\n", resp.Status)
	}
	defer resp.Body.Close()

	// Convert CRX to ZIP if requested.
	if convertCrxToZip {
		var (
			publicKeyLen uint32
			signatureLen uint32
		)

		// Drop magic number.
		if err := binary.Read(resp.Body, binary.LittleEndian, &publicKeyLen); err != nil {
			log.Fatal(err)
		}
		// Drop version.
		if err := binary.Read(resp.Body, binary.LittleEndian, &publicKeyLen); err != nil {
			log.Fatal(err)
		}
		// Read public key length.
		if err := binary.Read(resp.Body, binary.LittleEndian, &publicKeyLen); err != nil {
			log.Fatal(err)
		}
		// Read signature length.
		if err := binary.Read(resp.Body, binary.LittleEndian, &signatureLen); err != nil {
			log.Fatal(err)
		}

		var p []byte
		if publicKeyLen > signatureLen {
			p = make([]byte, publicKeyLen)
		} else {
			p = make([]byte, signatureLen)
		}

		// Drop the public key.
		b := p[:publicKeyLen]
		for i := uint32(0); i != publicKeyLen; {
			n, err := resp.Body.Read(b[i:])
			if err != nil {
				log.Fatal(err)
			}
			i += uint32(n)
		}
		// Drop the signature.
		b = p[:signatureLen]
		for i := uint32(0); i != signatureLen; {
			n, err := resp.Body.Read(b[i:])
			if err != nil {
				log.Fatal(err)
			}
			i += uint32(n)
		}
	}

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

	n, err := io.Copy(file, resp.Body)
	if err != nil {
		log.Fatalf("Error: %v\n", err)
	}

	fmt.Printf("Wrote %v bytes\n", n)
}

var packageJsonDeps = flagutil.NewMapValue()

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

	var manifestFilename = args[0]

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

	var packageJson struct {
		Name         string            `json:"name"`
		Version      string            `json:"version"`
		Dependencies map[string]string `json:"dependencies"`
	}

	if err := yaml.Unmarshal(content, &packageJson); err != nil {
		log.Fatalf("Error: failed to unmarshal manifest.json: %v", err)
	}

	packageJson.Name = strings.ToLower(packageJson.Name)
	packageJson.Name = strings.Replace(packageJson.Name, " ", "-", -1)
	packageJson.Dependencies = packageJsonDeps.M
	switch strings.Count(packageJson.Version, ".") {
	case 0:
		packageJson.Version += ".0.0"
	case 1:
		packageJson.Version += ".0"
	}

	content, err = json.MarshalIndent(packageJson, "", "  ")
	if err != nil {
		log.Fatalf("Error: failed to marshal package.json: %v", err)
	}

	file, err := os.OpenFile("package.json", os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatalf("Error: %v", err)
	}
	defer file.Close()

	if _, err := file.Write(content); err != nil {
		log.Fatalf("Error: %v", err)
	}

	fmt.Println("package.json created")
}

func getNameFromManifest(cmd *gocli.Command, args []string) {
	if len(args) != 1 {
		cmd.Usage()
		os.Exit(2)
	}

	manifest, err := loadManifest(args[0])
	if err != nil {
		log.Fatalf("Error: %v\n", err)
	}

	fmt.Print(manifest.Name)
}

func getVersionFromManifest(cmd *gocli.Command, args []string) {
	if len(args) != 1 {
		cmd.Usage()
		os.Exit(2)
	}

	manifest, err := loadManifest(args[0])
	if err != nil {
		log.Fatalf("Error: %v\n", err)
	}

	fmt.Print(manifest.Version)
}

type manifest struct {
	Name    string
	Version string
}

func loadManifest(filename string) (*manifest, error) {
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	var m manifest
	if err := yaml.Unmarshal(content, &m); err != nil {
		return nil, err
	}

	return &m, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"mime/multipart"
	"net/http"
	"os"
	// "path"
	"path/filepath"

	"github.com/codegangsta/cli"
)

func NewReportCommand() cli.Command {

	return cli.Command{

		Name:  "report",
		Usage: "create a report of code coverage",
		Flags: []cli.Flag{

			cli.StringFlag{
				Name:  "d",
				Value: "./",
				Usage: "identify DerivedData path for search gcda, gcno files",
			},
			cli.StringFlag{
				Name:  "o",
				Value: "coverage.info",
				Usage: "output path for coverage info file",
			},
		},
		Action: func(c *cli.Context) {

			branch := GetBranchName()
			commit := GetCommitSha()
			repo := GetRepoName()

			if branch == "" {
				// log.Fatal("Please specify a correct branch name")
			}

			if repo == "" {
				// log.Fatal("Please specify a correct repo name")
			}

			if commit == "" {
				// log.Fatal("Please specify a correct commit sha")
			}

			err := createReport(branch, repo, commit, c)

			if err != nil {
				log.Fatal(err)
			}
		},
	}
}

func createReport(branch string, repo string, commit string, c *cli.Context) error {

	var derivedPath = c.String("d")
	var outputPath = c.String("o")

	fmt.Println("Searching gcda, gcno in: " + derivedPath)
	fmt.Println("Generate coverage info file: " + outputPath)

	return Lcov(derivedPath, outputPath)
	/*
		fmt.Println("reporting " + repo + " on " + branch + " with commit " + commit)

		var uploadUrl = "http://google.com/upload"

		extraParams := map[string]string{
			"project_name": repo,
			"commit_sha":   commit,
			"branch":       branch,
		}

		request, err := newfileUploadRequest(uploadUrl, extraParams, "lcov", "lcovPath")

		if err != nil {
			log.Fatal(err)
		}

		client := &http.Client{}
		resp, err := client.Do(request)

		if err != nil {
			log.Fatal(err)
		}

		body := &bytes.Buffer{}
		_, err = body.ReadFrom(resp.Body)
		if err != nil {
			log.Fatal(err)
		}

		resp.Body.Close()
		fmt.Println(resp.StatusCode)
		fmt.Println(resp.Header)
		fmt.Println(body)

		return nil
	*/
}

func newfileUploadRequest(uri string, params map[string]string, paramName, path string) (*http.Request, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)
	part, err := writer.CreateFormFile(paramName, filepath.Base(path))
	if err != nil {
		return nil, err
	}
	_, err = io.Copy(part, file)

	for key, val := range params {
		_ = writer.WriteField(key, val)
	}
	err = writer.Close()
	if err != nil {
		return nil, err
	}

	return http.NewRequest("POST", uri, body)
}
<commit_msg>ios: Set default value system derived path for '-d' when report<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"

	"github.com/codegangsta/cli"
	"github.com/mitchellh/go-homedir"
)

func NewReportCommand() cli.Command {

	return cli.Command{

		Name:  "report",
		Usage: "create a report of code coverage",
		Flags: []cli.Flag{

			cli.StringFlag{
				Name:  "d",
				Value: "",
				Usage: "identify DerivedData path for search gcda, gcno files, default value is '~/Library/Developer/Xcode/DerivedData'",
			},
			cli.StringFlag{
				Name:  "o",
				Value: "coverage.info",
				Usage: "output path for coverage info file",
			},
		},
		Action: func(c *cli.Context) {

			branch := GetBranchName()
			commit := GetCommitSha()
			repo := GetRepoName()

			if branch == "" {
				// log.Fatal("Please specify a correct branch name")
			}

			if repo == "" {
				// log.Fatal("Please specify a correct repo name")
			}

			if commit == "" {
				// log.Fatal("Please specify a correct commit sha")
			}

			err := createReport(branch, repo, commit, c)

			if err != nil {
				log.Fatal(err)
			}
		},
	}
}

func createReport(branch string, repo string, commit string, c *cli.Context) error {

	var derivedPath = c.String("d")
	var outputPath = c.String("o")

	if derivedPath == "" {
		home, _ := homedir.Dir()
		derivedPath = filepath.Join(home, "Library/Developer/Xcode/DerivedData")
		fmt.Println("Using the default derived path: " + derivedPath)
	}

	fmt.Println("Searching gcda, gcno in: " + derivedPath)
	fmt.Println("Generate coverage info file: " + outputPath)

	return Lcov(derivedPath, outputPath)
	/*
		fmt.Println("reporting " + repo + " on " + branch + " with commit " + commit)

		var uploadUrl = "http://google.com/upload"

		extraParams := map[string]string{
			"project_name": repo,
			"commit_sha":   commit,
			"branch":       branch,
		}

		request, err := newfileUploadRequest(uploadUrl, extraParams, "lcov", "lcovPath")

		if err != nil {
			log.Fatal(err)
		}

		client := &http.Client{}
		resp, err := client.Do(request)

		if err != nil {
			log.Fatal(err)
		}

		body := &bytes.Buffer{}
		_, err = body.ReadFrom(resp.Body)
		if err != nil {
			log.Fatal(err)
		}

		resp.Body.Close()
		fmt.Println(resp.StatusCode)
		fmt.Println(resp.Header)
		fmt.Println(body)

		return nil
	*/
}

func newfileUploadRequest(uri string, params map[string]string, paramName, path string) (*http.Request, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)
	part, err := writer.CreateFormFile(paramName, filepath.Base(path))
	if err != nil {
		return nil, err
	}
	_, err = io.Copy(part, file)

	for key, val := range params {
		_ = writer.WriteField(key, val)
	}
	err = writer.Close()
	if err != nil {
		return nil, err
	}

	return http.NewRequest("POST", uri, body)
}
<|endoftext|>


<commit_before>package vfsswift

import (
	"bytes"
	"encoding/hex"
	"path"
	"strings"

	"github.com/cozy/cozy-stack/model/vfs"
	"github.com/cozy/cozy-stack/pkg/consts"
	"github.com/cozy/swift"
)

func (sfs *swiftVFS) Fsck(accumulate func(log *vfs.FsckLog)) error {
	entries := make(map[string]*vfs.TreeFile, 1024)
	tree, err := sfs.BuildTree(func(f *vfs.TreeFile) {
		if !f.IsOrphan {
			entries[f.Fullpath] = f
		}
	})
	if err != nil {
		return err
	}
	if err = sfs.CheckTreeIntegrity(tree, accumulate); err != nil {
		return err
	}
	return sfs.checkFiles(entries, accumulate)
}

func (sfs *swiftVFS) CheckFilesConsistency(accumulate func(log *vfs.FsckLog)) error {
	entries := make(map[string]*vfs.TreeFile, 1024)
	_, err := sfs.BuildTree(func(f *vfs.TreeFile) {
		if !f.IsOrphan {
			entries[f.Fullpath] = f
		}
	})
	if err != nil {
		return err
	}
	return sfs.checkFiles(entries, accumulate)
}

func (sfs *swiftVFS) checkFiles(entries map[string]*vfs.TreeFile, accumulate func(log *vfs.FsckLog)) (err error) {
	var orphansObjs []swift.Object

	err = sfs.c.ObjectsWalk(sfs.container, nil, func(opts *swift.ObjectsOpts) (interface{}, error) {
		var objs []swift.Object
		objs, err = sfs.c.Objects(sfs.container, opts)
		if err != nil {
			return nil, err
		}
		for _, obj := range objs {
			f, ok := entries[obj.Name]
			if !ok {
				orphansObjs = append(orphansObjs, obj)
			} else if f.IsDir != (obj.ContentType == dirContentType) {
				if f.IsDir {
					accumulate(&vfs.FsckLog{
						Type:    vfs.TypeMismatch,
						IsFile:  true,
						FileDoc: f,
						DirDoc:  objectToFileDocV1(sfs.container, obj),
					})
				} else {
					accumulate(&vfs.FsckLog{
						Type:    vfs.TypeMismatch,
						IsFile:  false,
						DirDoc:  f,
						FileDoc: objectToFileDocV1(sfs.container, obj),
					})
				}
			} else if !f.IsDir {
				var md5sum []byte
				md5sum, err = hex.DecodeString(obj.Hash)
				if err != nil {
					return nil, err
				}
				if !bytes.Equal(md5sum, f.MD5Sum) || f.ByteSize != obj.Bytes {
					accumulate(&vfs.FsckLog{
						Type:    vfs.ContentMismatch,
						IsFile:  true,
						FileDoc: f,
						ContentMismatch: &vfs.FsckContentMismatch{
							SizeFile:    obj.Bytes,
							SizeIndex:   f.ByteSize,
							MD5SumFile:  md5sum,
							MD5SumIndex: f.MD5Sum,
						},
					})
				}
				delete(entries, obj.Name)
			}
		}
		return objs, err
	})

	for _, f := range entries {
		accumulate(&vfs.FsckLog{
			Type:    vfs.FSMissing,
			IsFile:  true,
			FileDoc: f,
		})
	}

	for _, obj := range orphansObjs {
		if obj.ContentType == dirContentType {
			accumulate(&vfs.FsckLog{
				Type:   vfs.IndexMissing,
				IsFile: false,
				DirDoc: objectToFileDocV1(sfs.container, obj),
			})
		} else {
			accumulate(&vfs.FsckLog{
				Type:    vfs.IndexMissing,
				IsFile:  true,
				FileDoc: objectToFileDocV1(sfs.container, obj),
			})
		}
	}

	return
}

func objectToFileDocV1(container string, object swift.Object) *vfs.TreeFile {
	var dirID, name string
	if dirIDAndName := strings.SplitN(object.Name, "/", 2); len(dirIDAndName) == 2 {
		dirID = dirIDAndName[0]
		name = dirIDAndName[0]
	}
	docType := consts.FileType
	if object.ContentType == dirContentType {
		docType = consts.DirType
	}
	md5sum, _ := hex.DecodeString(object.Hash)
	mime, class := vfs.ExtractMimeAndClass(object.ContentType)
	return &vfs.TreeFile{
		DirOrFileDoc: vfs.DirOrFileDoc{
			DirDoc: &vfs.DirDoc{
				Type:      docType,
				DocID:     makeDocID(object.Name),
				DocName:   name,
				DirID:     dirID,
				CreatedAt: object.LastModified,
				UpdatedAt: object.LastModified,
				Fullpath:  path.Join(vfs.OrphansDirName, name),
			},
			ByteSize:   object.Bytes,
			Mime:       mime,
			Class:      class,
			Executable: false,
			MD5Sum:     md5sum,
		},
	}
}
<commit_msg>Fix directory handling for FSCK Swift v1 (bis)<commit_after>package vfsswift

import (
	"bytes"
	"encoding/hex"
	"path"
	"strings"

	"github.com/cozy/cozy-stack/model/vfs"
	"github.com/cozy/cozy-stack/pkg/consts"
	"github.com/cozy/swift"
)

func (sfs *swiftVFS) Fsck(accumulate func(log *vfs.FsckLog)) error {
	entries := make(map[string]*vfs.TreeFile, 1024)
	tree, err := sfs.BuildTree(func(f *vfs.TreeFile) {
		if !f.IsOrphan {
			entries[f.DirID+"/"+f.DocName] = f
		}
	})
	if err != nil {
		return err
	}
	if err = sfs.CheckTreeIntegrity(tree, accumulate); err != nil {
		return err
	}
	return sfs.checkFiles(entries, accumulate)
}

func (sfs *swiftVFS) CheckFilesConsistency(accumulate func(log *vfs.FsckLog)) error {
	entries := make(map[string]*vfs.TreeFile, 1024)
	_, err := sfs.BuildTree(func(f *vfs.TreeFile) {
		if !f.IsOrphan {
			entries[f.DirID+"/"+f.DocName] = f
		}
	})
	if err != nil {
		return err
	}
	return sfs.checkFiles(entries, accumulate)
}

func (sfs *swiftVFS) checkFiles(entries map[string]*vfs.TreeFile, accumulate func(log *vfs.FsckLog)) (err error) {
	var orphansObjs []swift.Object

	err = sfs.c.ObjectsWalk(sfs.container, nil, func(opts *swift.ObjectsOpts) (interface{}, error) {
		var objs []swift.Object
		objs, err = sfs.c.Objects(sfs.container, opts)
		if err != nil {
			return nil, err
		}
		for _, obj := range objs {
			f, ok := entries[obj.Name]
			if !ok {
				orphansObjs = append(orphansObjs, obj)
			} else if f.IsDir != (obj.ContentType == dirContentType) {
				if f.IsDir {
					accumulate(&vfs.FsckLog{
						Type:    vfs.TypeMismatch,
						IsFile:  true,
						FileDoc: f,
						DirDoc:  objectToFileDocV1(sfs.container, obj),
					})
				} else {
					accumulate(&vfs.FsckLog{
						Type:    vfs.TypeMismatch,
						IsFile:  false,
						DirDoc:  f,
						FileDoc: objectToFileDocV1(sfs.container, obj),
					})
				}
			} else if !f.IsDir {
				var md5sum []byte
				md5sum, err = hex.DecodeString(obj.Hash)
				if err != nil {
					return nil, err
				}
				if !bytes.Equal(md5sum, f.MD5Sum) || f.ByteSize != obj.Bytes {
					accumulate(&vfs.FsckLog{
						Type:    vfs.ContentMismatch,
						IsFile:  true,
						FileDoc: f,
						ContentMismatch: &vfs.FsckContentMismatch{
							SizeFile:    obj.Bytes,
							SizeIndex:   f.ByteSize,
							MD5SumFile:  md5sum,
							MD5SumIndex: f.MD5Sum,
						},
					})
				}
				delete(entries, obj.Name)
			}
		}
		return objs, err
	})

	for _, f := range entries {
		accumulate(&vfs.FsckLog{
			Type:    vfs.FSMissing,
			IsFile:  true,
			FileDoc: f,
		})
	}

	for _, obj := range orphansObjs {
		if obj.ContentType == dirContentType {
			accumulate(&vfs.FsckLog{
				Type:   vfs.IndexMissing,
				IsFile: false,
				DirDoc: objectToFileDocV1(sfs.container, obj),
			})
		} else {
			accumulate(&vfs.FsckLog{
				Type:    vfs.IndexMissing,
				IsFile:  true,
				FileDoc: objectToFileDocV1(sfs.container, obj),
			})
		}
	}

	return
}

func objectToFileDocV1(container string, object swift.Object) *vfs.TreeFile {
	var dirID, name string
	if dirIDAndName := strings.SplitN(object.Name, "/", 2); len(dirIDAndName) == 2 {
		dirID = dirIDAndName[0]
		name = dirIDAndName[0]
	}
	docType := consts.FileType
	if object.ContentType == dirContentType {
		docType = consts.DirType
	}
	md5sum, _ := hex.DecodeString(object.Hash)
	mime, class := vfs.ExtractMimeAndClass(object.ContentType)
	return &vfs.TreeFile{
		DirOrFileDoc: vfs.DirOrFileDoc{
			DirDoc: &vfs.DirDoc{
				Type:      docType,
				DocID:     makeDocID(object.Name),
				DocName:   name,
				DirID:     dirID,
				CreatedAt: object.LastModified,
				UpdatedAt: object.LastModified,
				Fullpath:  path.Join(vfs.OrphansDirName, name),
			},
			ByteSize:   object.Bytes,
			Mime:       mime,
			Class:      class,
			Executable: false,
			MD5Sum:     md5sum,
		},
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
)

func foo(i interface{}) {
	x := i.(int)
	fmt.Println(x)
}

func main() {
	foo("123")
}
<commit_msg>Improved empty interface example.<commit_after>package main

import (
	"fmt"
)

func fooCorrect(i interface{}) {
	x, ok := i.(int)
	if ok {
		fmt.Printf("int value is: %q\n", x)
	} else {
		fmt.Printf("value is not an int\n")
	}
}

func fooCorrect2(i interface{}) {
	switch x := i.(type) {
	case int:
		fmt.Println(x)
	default:
		fmt.Printf("value is not an int\n")
	}
}

func fooBad(i interface{}) {
	x := i.(int)
	fmt.Println(x)
}

func main() {
	fooCorrect("123")
	fooCorrect2("123")
	fooBad("123")
}
<|endoftext|>


<commit_before>package client

import (
    "fmt"
    "log"
    "net"
    "time"
    "encoding/xml"
)

type xmlResponse struct {
    ID          int         `xml:"id,attr"`
    Reset       string      `xml:"reset,attr"`

    GUID        string      `xml:"GuiId"`
    Type        int         `xml:"XMLType"`
    Resp        int         `xml:"Resp"`

    *System
}

// Decode packet from server, based on response type.
// The given *System will be reset or updated
type xmlPacket struct {
    XMLName     xml.Name    `xml:"System"`

    xmlResponse

    // decoding state
    reset       bool
}

func (r *xmlPacket) UnmarshalXML(d *xml.Decoder, e xml.StartElement) error {
    reset := xmlAttr(e, "reset")

    if reset == "yes" {
        r.reset = true

        // reset
        r.System.Reset()
    }

    return d.DecodeElement(&r.xmlResponse, &e)
}

type xmlPing struct {
    XMLName     xml.Name    `xml:"System"`
    ID          int         `xml:"id,attr"`
}

type xmlQuery struct {
    XMLName     xml.Name    `xml:"System"`
    ID          int         `xml:"id,attr"`
    Reset       string      `xml:"reset,attr"`

    Type        int         `xml:"XMLType"`
    Query       int         `xml:"Query"`
    Recursive   int         `xml:"Recursive"`
}

type XMLClient struct {
    conn            net.Conn
    timeout         time.Duration

    readChan        chan xmlPacket
    readError       error           // set once readChan is closed
    listenChan      chan System
}

func (options Options) XMLClient() (*XMLClient, error) {
    xmlClient := XMLClient{
        timeout:        options.Timeout,
    }

    if tcpAddr, err := net.ResolveTCPAddr("tcp4", net.JoinHostPort(options.Address, options.XMLPort)); err != nil {
        return nil, fmt.Errorf("Client.initXML: ResolveTCPAddr: %v", err)
    } else if tcpConn, err := net.DialTCP("tcp4", nil, tcpAddr); err != nil {
        return nil, fmt.Errorf("Client.initXML: DialTCP %v: %v", tcpAddr, err)
    } else {
        xmlClient.conn = tcpConn
    }

    if err := xmlClient.start(); err != nil {
        return nil, err
    }

    return &xmlClient, nil
}

// Blocking read and decode of a complete <System> state into the given xmlPacket.
// Any existing xmlPacket.System state is updated, or reset if the server returns a <System reset="yes">
//
// The read is performed using a timeout deadline for the entire <System> state
func (xmlClient *XMLClient) read(packet *xmlPacket) error {
    // applies to the complete XML packet read by the decoder..?
    if err := xmlClient.conn.SetReadDeadline(time.Now().Add(xmlClient.timeout)); err != nil {
        return err
    }

    if err := xml.NewDecoder(xmlClient.conn).Decode(packet); err != nil {
        return err
    } else {
        return nil
    }
}

// Blocking encode and write of an arbitrary XML packet to the server.
func (xmlClient *XMLClient) write(packet interface{}) error {
    if err := xmlClient.conn.SetWriteDeadline(time.Now().Add(xmlClient.timeout)); err != nil {
        return err
    }

    return xml.NewEncoder(xmlClient.conn).Encode(packet)
}

// Send a <System> reset query
func (xmlClient *XMLClient) writeReset() error {
    return xmlClient.write(xmlQuery{Reset: "yes",
        Type:       3,
        Query:      3,
        Recursive:  1,
    })
}

// Send a <System> ping
func (xmlClient *XMLClient) writePing() error {
    return xmlClient.write(xmlPing{})
}

// Launch background goroutines
func (xmlClient *XMLClient) start() error {
    xmlClient.listenChan = make(chan System)
    xmlClient.readChan = make(chan xmlPacket)

    go xmlClient.reader()
    go xmlClient.writer()

    return nil
}

// Read and handle messages from the server, dispatching readChan for timing and listenChan for readers
//
// Guarantees completion by closing the readChan and setting readError
func (xmlClient *XMLClient) reader() {
    defer close(xmlClient.listenChan)
    defer close(xmlClient.readChan)
    defer func(){
        panicValue := recover()

        if panicError, ok := panicValue.(Error); ok {
            xmlClient.readError = panicError
        } else {
            xmlClient.readError = fmt.Errorf("%v", panicValue)
        }
    }()

    var system System
    var wantReset = true

    for {
        packet := xmlPacket{xmlResponse: xmlResponse{System: &system}}

        if err := xmlClient.read(&packet); err != nil {
            log.Printf("xmlClient.read: %v\n", err)

            // quit with error
            panic(err)

        } else if wantReset && !packet.reset {
            // skip packets before initial reset-sync
            log.Printf("xmlClient.read: skip")

        } else {
            wantReset = false

            // timeout handling
            xmlClient.readChan <- packet

            if packet.reset {
                log.Printf("xmlClient.read: reset")

                xmlClient.listenChan <- system

            } else if packet.Type == 0 {
                log.Printf("xmlClient.read: update")

                xmlClient.listenChan <- system

            } else {
                // log.Printf("xmlClient.read: pong")
            }
        }
    }
}

// Write requests, including the initial reset to sync state, and periodic pings on idle timeout
func (xmlClient *XMLClient) writer() {
    defer xmlClient.conn.Close()

    timer := time.NewTimer(xmlClient.timeout / 2)

    // initialize
    if err := xmlClient.writeReset(); err != nil {
        log.Printf("xmlClient.writeReset: %v\n", err)
        return
    }

    for {
        select {
        case <-timer.C:
            if err := xmlClient.writePing(); err != nil {
                log.Printf("xmlClient.writePing: %v\n", err)
                return
            }

            // fast-retry ping on timeout
            timer.Reset(xmlClient.timeout / 8)

        case _, ok := <-xmlClient.readChan:
            if !ok {
                return
            }

            // got update, reschedule idle ping
            timer.Reset(xmlClient.timeout / 2)
        }
    }
}

// Listen for system updates.
//
// Read updated System states from the given chan, starting from the initial reset state.
//
// The received System is safe for concurrent reads, but do *not* write to it! Use the public methods if possible.
//
// XXX: only one shared chan for all callers
func (xmlClient *XMLClient) Listen() (chan System, error) {
    if xmlClient.readError != nil {
        return nil, xmlClient.readError
    } else {
        return xmlClient.listenChan, nil
    }
}

// Return any Error after Listen() returns
//
// XXX: nil on EOF?
func (xmlClient *XMLClient) ListenError() error {
    return xmlClient.readError
}

// Read system updates.
//
// Blocking read of updated System state, or error
//
// The received System is safe for concurrent reads, but do *not* write to it! Use the public methods if possible.
func (xmlClient *XMLClient) Read() (System, error) {
    if system, ok := <-xmlClient.listenChan; ok {
        return system, nil
    } else {
        // chan as closed
        return system, xmlClient.readError
    }
}
<commit_msg>client: fix XMLClient read EOF handling to return ListenError() == nil<commit_after>package client

import (
    "fmt"
    "io"
    "log"
    "net"
    "time"
    "encoding/xml"
)

type xmlResponse struct {
    ID          int         `xml:"id,attr"`
    Reset       string      `xml:"reset,attr"`

    GUID        string      `xml:"GuiId"`
    Type        int         `xml:"XMLType"`
    Resp        int         `xml:"Resp"`

    *System
}

// Decode packet from server, based on response type.
// The given *System will be reset or updated
type xmlPacket struct {
    XMLName     xml.Name    `xml:"System"`

    xmlResponse

    // decoding state
    reset       bool
}

func (r *xmlPacket) UnmarshalXML(d *xml.Decoder, e xml.StartElement) error {
    reset := xmlAttr(e, "reset")

    if reset == "yes" {
        r.reset = true

        // reset
        r.System.Reset()
    }

    return d.DecodeElement(&r.xmlResponse, &e)
}

type xmlPing struct {
    XMLName     xml.Name    `xml:"System"`
    ID          int         `xml:"id,attr"`
}

type xmlQuery struct {
    XMLName     xml.Name    `xml:"System"`
    ID          int         `xml:"id,attr"`
    Reset       string      `xml:"reset,attr"`

    Type        int         `xml:"XMLType"`
    Query       int         `xml:"Query"`
    Recursive   int         `xml:"Recursive"`
}

type XMLClient struct {
    conn            net.Conn
    timeout         time.Duration

    readChan        chan xmlPacket
    readError       error           // set once readChan is closed, nil on clean EOF
    listenChan      chan System
}

func (options Options) XMLClient() (*XMLClient, error) {
    xmlClient := XMLClient{
        timeout:        options.Timeout,
    }

    if tcpAddr, err := net.ResolveTCPAddr("tcp4", net.JoinHostPort(options.Address, options.XMLPort)); err != nil {
        return nil, fmt.Errorf("Client.initXML: ResolveTCPAddr: %v", err)
    } else if tcpConn, err := net.DialTCP("tcp4", nil, tcpAddr); err != nil {
        return nil, fmt.Errorf("Client.initXML: DialTCP %v: %v", tcpAddr, err)
    } else {
        xmlClient.conn = tcpConn
    }

    if err := xmlClient.start(); err != nil {
        return nil, err
    }

    return &xmlClient, nil
}

// Blocking read and decode of a complete <System> state into the given xmlPacket.
// Any existing xmlPacket.System state is updated, or reset if the server returns a <System reset="yes">
//
// The read is performed using a timeout deadline for the entire <System> state
func (xmlClient *XMLClient) read(packet *xmlPacket) error {
    // applies to the complete XML packet read by the decoder..?
    if err := xmlClient.conn.SetReadDeadline(time.Now().Add(xmlClient.timeout)); err != nil {
        return err
    }

    if err := xml.NewDecoder(xmlClient.conn).Decode(packet); err != nil {
        return err
    } else {
        return nil
    }
}

// Blocking encode and write of an arbitrary XML packet to the server.
func (xmlClient *XMLClient) write(packet interface{}) error {
    if err := xmlClient.conn.SetWriteDeadline(time.Now().Add(xmlClient.timeout)); err != nil {
        return err
    }

    return xml.NewEncoder(xmlClient.conn).Encode(packet)
}

// Send a <System> reset query
func (xmlClient *XMLClient) writeReset() error {
    return xmlClient.write(xmlQuery{Reset: "yes",
        Type:       3,
        Query:      3,
        Recursive:  1,
    })
}

// Send a <System> ping
func (xmlClient *XMLClient) writePing() error {
    return xmlClient.write(xmlPing{})
}

// Launch background goroutines
func (xmlClient *XMLClient) start() error {
    xmlClient.listenChan = make(chan System)
    xmlClient.readChan = make(chan xmlPacket)

    go xmlClient.reader()
    go xmlClient.writer()

    return nil
}

// Read and handle messages from the server, dispatching readChan for timing and listenChan for readers
//
// Guarantees completion by closing the readChan and setting readError
func (xmlClient *XMLClient) reader() {
    defer close(xmlClient.listenChan)
    defer close(xmlClient.readChan)
    defer func(){
        panicValue := recover()

        if panicValue == nil {
            xmlClient.readError = nil
        } else if panicError, ok := panicValue.(Error); ok {
            xmlClient.readError = panicError
        } else {
            xmlClient.readError = fmt.Errorf("%v", panicValue)
        }
    }()

    var system System
    var wantReset = true

    for {
        packet := xmlPacket{xmlResponse: xmlResponse{System: &system}}

        if err := xmlClient.read(&packet); err != nil {
            log.Printf("xmlClient.read: %v\n", err)

            if err == io.EOF {
                // done
                return

            } else {
                // quit with error
                panic(err)
            }

        } else if wantReset && !packet.reset {
            // skip packets before initial reset-sync
            log.Printf("xmlClient.read: skip")

        } else {
            wantReset = false

            // timeout handling
            xmlClient.readChan <- packet

            if packet.reset {
                log.Printf("xmlClient.read: reset")

                xmlClient.listenChan <- system

            } else if packet.Type == 0 {
                log.Printf("xmlClient.read: update")

                xmlClient.listenChan <- system

            } else {
                // log.Printf("xmlClient.read: pong")
            }
        }
    }
}

// Write requests, including the initial reset to sync state, and periodic pings on idle timeout
func (xmlClient *XMLClient) writer() {
    defer xmlClient.conn.Close()

    timer := time.NewTimer(xmlClient.timeout / 2)

    // initialize
    if err := xmlClient.writeReset(); err != nil {
        log.Printf("xmlClient.writeReset: %v\n", err)
        return
    }

    for {
        select {
        case <-timer.C:
            if err := xmlClient.writePing(); err != nil {
                log.Printf("xmlClient.writePing: %v\n", err)
                return
            }

            // fast-retry ping on timeout
            timer.Reset(xmlClient.timeout / 8)

        case _, ok := <-xmlClient.readChan:
            if !ok {
                return
            }

            // got update, reschedule idle ping
            timer.Reset(xmlClient.timeout / 2)
        }
    }
}

// Listen for system updates.
//
// Read updated System states from the given chan, starting from the initial reset state.
//
// The received System is safe for concurrent reads, but do *not* write to it! Use the public methods if possible.
//
// XXX: only one shared chan for all callers
func (xmlClient *XMLClient) Listen() (chan System, error) {
    if xmlClient.readError != nil {
        return nil, xmlClient.readError
    } else {
        return xmlClient.listenChan, nil
    }
}

// Return any Error after Listen() returns, or nil if the connection was closed cleanly by the other end (EOF)
func (xmlClient *XMLClient) ListenError() error {
    return xmlClient.readError
}

// Read system updates.
//
// Blocking read of updated System state, or error (including io.EOF on clean shutdown).
//
// The received System is safe for concurrent reads, but do *not* write to it! Use the public methods if possible.
func (xmlClient *XMLClient) Read() (System, error) {
    if system, ok := <-xmlClient.listenChan; ok {
        return system, nil
    } else if xmlClient.readError != nil {
        // chan was closed with an error
        return system, xmlClient.readError
    } else {
        // chan was closed after EOF
        return system, io.EOF
    }
}
<|endoftext|>


<commit_before>package goStrongswanVici

import (
	"fmt"
	"io"
	"net"
	"sync"
	"time"
)

const (
	DefaultReadTimeout = 15 * time.Second
)

// This object is not thread safe.
// if you want concurrent, you need create more clients.
type ClientConn struct {
	conn          net.Conn
	responseChan  chan segment
	eventHandlers map[string]func(response map[string]interface{})
	lastError     error

	// ReadTimeout specifies a time limit for requests made
	// by this client.
	ReadTimeout time.Duration

	lock sync.RWMutex
}

func (c *ClientConn) Close() error {
	c.lock.Lock()
	defer c.lock.Unlock()
	close(c.responseChan)
	c.lastError = io.ErrClosedPipe
	return c.conn.Close()
}

func NewClientConn(conn net.Conn) (client *ClientConn) {
	client = &ClientConn{
		conn:          conn,
		responseChan:  make(chan segment, 2),
		eventHandlers: map[string]func(response map[string]interface{}){},
		ReadTimeout:   DefaultReadTimeout,
	}
	go client.readThread()
	return client
}

// it dial from unix:///var/run/charon.vici
func NewClientConnFromDefaultSocket() (client *ClientConn, err error) {
	conn, err := net.Dial("unix", "/var/run/charon.vici")
	if err != nil {
		return
	}
	return NewClientConn(conn), nil
}

func (c *ClientConn) Request(apiname string, request map[string]interface{}) (response map[string]interface{}, err error) {
	c.lock.Lock()
	defer c.lock.Unlock()
	err = writeSegment(c.conn, segment{
		typ:  stCMD_REQUEST,
		name: apiname,
		msg:  request,
	})
	if err != nil {
		fmt.Printf("error writing segment \n")
		return
	}

	outMsg := c.readResponse()
	if c.lastError != nil {
		return nil, c.lastError
	}
	if outMsg.typ != stCMD_RESPONSE {
		return nil, fmt.Errorf("[%s] response error %d", apiname, outMsg.typ)
	}
	return outMsg.msg, nil
}

func (c *ClientConn) readResponse() segment {
	select {
	case outMsg := <-c.responseChan:
		return outMsg
	case <-time.After(c.ReadTimeout):
		if c.lastError == nil {
			c.lastError = fmt.Errorf("Timeout waiting for message response")
		}
		return segment{}
	}
}

func (c *ClientConn) RegisterEvent(name string, handler func(response map[string]interface{})) (err error) {
	c.lock.Lock()
	defer c.lock.Unlock()
	if c.eventHandlers[name] != nil {
		return fmt.Errorf("[event %s] register a event twice.", name)
	}
	c.eventHandlers[name] = handler
	err = writeSegment(c.conn, segment{
		typ:  stEVENT_REGISTER,
		name: name,
	})
	if err != nil {
		delete(c.eventHandlers, name)
		return
	}
	outMsg := c.readResponse()
	//fmt.Printf("registerEvent %#v\n", outMsg)
	if c.lastError != nil {
		delete(c.eventHandlers, name)
		return c.lastError
	}

	if outMsg.typ != stEVENT_CONFIRM {
		delete(c.eventHandlers, name)
		return fmt.Errorf("[event %s] response error %d", name, outMsg.typ)
	}
	return nil
}

func (c *ClientConn) UnregisterEvent(name string) (err error) {
	c.lock.Lock()
	defer c.lock.Unlock()
	err = writeSegment(c.conn, segment{
		typ:  stEVENT_UNREGISTER,
		name: name,
	})
	if err != nil {
		return
	}
	outMsg := c.readResponse()
	//fmt.Printf("UnregisterEvent %#v\n", outMsg)
	if c.lastError != nil {
		return c.lastError
	}

	if outMsg.typ != stEVENT_CONFIRM {
		return fmt.Errorf("[event %s] response error %d", name, outMsg.typ)
	}
	delete(c.eventHandlers, name)
	return nil
}

func (c *ClientConn) readThread() {
	for {
		c.lock.Lock()
		outMsg, err := readSegment(c.conn)
		if err != nil {
			c.lastError = err
			c.lock.Unlock()
			return
		}
		switch outMsg.typ {
		case stCMD_RESPONSE, stEVENT_CONFIRM:
			c.responseChan <- outMsg
		case stEVENT:
			handler := c.eventHandlers[outMsg.name]
			if handler != nil {
				handler(outMsg.msg)
			}
		default:
			c.lastError = fmt.Errorf("[Client.readThread] unknow msg type %d", outMsg.typ)
			c.lock.Unlock()
			return
		}
		c.lock.Unlock()
	}
}
<commit_msg>fix diffrent contention issues<commit_after>package goStrongswanVici

import (
	"fmt"
	"io"
	"net"
	"sync"
	"time"
)

const (
	DefaultReadTimeout = 15 * time.Second
)

// This object is not thread safe.
// if you want concurrent, you need create more clients.
type ClientConn struct {
	conn          net.Conn
	responseChan  chan segment
	eventHandlers map[string]func(response map[string]interface{})
	lastError     error

	// ReadTimeout specifies a time limit for requests made
	// by this client.
	ReadTimeout time.Duration

	lock sync.RWMutex
}

func (c *ClientConn) Close() error {
	c.lock.Lock()
	defer c.lock.Unlock()
	close(c.responseChan)
	c.lastError = io.ErrClosedPipe
	return c.conn.Close()
}

func NewClientConn(conn net.Conn) (client *ClientConn) {
	client = &ClientConn{
		conn:          conn,
		responseChan:  make(chan segment, 2),
		eventHandlers: map[string]func(response map[string]interface{}){},
		ReadTimeout:   DefaultReadTimeout,
	}
	go client.readThread()
	return client
}

// it dial from unix:///var/run/charon.vici
func NewClientConnFromDefaultSocket() (client *ClientConn, err error) {
	conn, err := net.Dial("unix", "/var/run/charon.vici")
	if err != nil {
		return
	}
	return NewClientConn(conn), nil
}

func (c *ClientConn) Request(apiname string, request map[string]interface{}) (response map[string]interface{}, err error) {
	err = writeSegment(c.conn, segment{
		typ:  stCMD_REQUEST,
		name: apiname,
		msg:  request,
	})
	if err != nil {
		fmt.Printf("error writing segment \n")
		return
	}
	outMsg := c.readResponse()
	c.lock.RLock()
	err = c.lastError
	defer c.lock.RUnlock()
	if err != nil {
		return nil, err
	}
	if outMsg.typ != stCMD_RESPONSE {
		return nil, fmt.Errorf("[%s] response error %d", apiname, outMsg.typ)
	}
	return outMsg.msg, nil
}

func (c *ClientConn) readResponse() segment {
	select {
	case outMsg := <-c.responseChan:
		return outMsg
	case <-time.After(c.ReadTimeout):
		if c.lastError == nil {
			c.lastError = fmt.Errorf("Timeout waiting for message response")
		}
		return segment{}
	}
}

func (c *ClientConn) RegisterEvent(name string, handler func(response map[string]interface{})) (err error) {
	c.lock.Lock()
	defer c.lock.Unlock()
	if c.eventHandlers[name] != nil {
		return fmt.Errorf("[event %s] register a event twice.", name)
	}
	c.eventHandlers[name] = handler
	err = writeSegment(c.conn, segment{
		typ:  stEVENT_REGISTER,
		name: name,
	})
	if err != nil {
		delete(c.eventHandlers, name)
		return
	}
	outMsg := c.readResponse()
	//fmt.Printf("registerEvent %#v\n", outMsg)
	if c.lastError != nil {
		delete(c.eventHandlers, name)
		return c.lastError
	}

	if outMsg.typ != stEVENT_CONFIRM {
		delete(c.eventHandlers, name)
		return fmt.Errorf("[event %s] response error %d", name, outMsg.typ)
	}
	return nil
}

func (c *ClientConn) UnregisterEvent(name string) (err error) {
	c.lock.Lock()
	defer c.lock.Unlock()
	err = writeSegment(c.conn, segment{
		typ:  stEVENT_UNREGISTER,
		name: name,
	})
	if err != nil {
		return
	}
	outMsg := c.readResponse()
	//fmt.Printf("UnregisterEvent %#v\n", outMsg)
	if c.lastError != nil {
		return c.lastError
	}

	if outMsg.typ != stEVENT_CONFIRM {
		return fmt.Errorf("[event %s] response error %d", name, outMsg.typ)
	}
	delete(c.eventHandlers, name)
	return nil
}

func (c *ClientConn) readThread() {
	for {
		outMsg, err := readSegment(c.conn)
		if err != nil {
			c.lock.Lock()
			c.lastError = err
			c.lock.Unlock()
			return
		}
		switch outMsg.typ {
		case stCMD_RESPONSE, stEVENT_CONFIRM:
			c.responseChan <- outMsg
		case stEVENT:
			c.lock.Lock()
			handler := c.eventHandlers[outMsg.name]
			c.lock.Unlock()
			if handler != nil {
				handler(outMsg.msg)
			}
		default:
			c.lock.Lock()
			c.lastError = fmt.Errorf("[Client.readThread] unknow msg type %d", outMsg.typ)
			c.lock.Unlock()
			return
		}
	}
}
<|endoftext|>


<commit_before>// +build !go1.9

package roaring

// LeadingZeroBits returns the number of consecutive most significant zero
// bits of x.
func countLeadingZeros(x uint64) int {
	if i == 0 {
		return 64
	}
	n := 1
	x := uint32(i >> 32)
	if x == 0 {
		n += 32
		x = uint32(i)
	}
	if (x >> 16) == 0 {
		n += 16
		x <<= 16
	}
	if (x >> 24) == 0 {
		n += 8
		x <<= 8
	}
	if x>>28 == 0 {
		n += 4
		x <<= 4
	}
	if x>>30 == 0 {
		n += 2
		x <<= 2

	}
	n -= int(x >> 31)
	return n
}
<commit_msg>Fixed pre-1.9 issue.<commit_after>// +build !go1.9

package roaring

// LeadingZeroBits returns the number of consecutive most significant zero
// bits of x.
func countLeadingZeros(i uint64) int {
	if i == 0 {
		return 64
	}
	n := 1
	x := uint32(i >> 32)
	if x == 0 {
		n += 32
		x = uint32(i)
	}
	if (x >> 16) == 0 {
		n += 16
		x <<= 16
	}
	if (x >> 24) == 0 {
		n += 8
		x <<= 8
	}
	if x>>28 == 0 {
		n += 4
		x <<= 4
	}
	if x>>30 == 0 {
		n += 2
		x <<= 2

	}
	n -= int(x >> 31)
	return n
}
<|endoftext|>


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

package cmd

import (
	"os"

	"github.com/spf13/cobra"

	"github.com/ksonnet/kubecfg/metadata"
	"github.com/ksonnet/kubecfg/pkg/kubecfg"
)

const (
	flagGracePeriod = "grace-period"
)

func init() {
	RootCmd.AddCommand(deleteCmd)
	addEnvCmdFlags(deleteCmd)
	deleteCmd.PersistentFlags().Int64(flagGracePeriod, -1, "Number of seconds given to resources to terminate gracefully. A negative value is ignored")
}

var deleteCmd = &cobra.Command{
	Use:   "delete [env-name] [-f <file-or-dir>]",
	Short: "Delete Kubernetes resources described in local config",
	RunE: func(cmd *cobra.Command, args []string) error {
		flags := cmd.Flags()
		var err error

		c := kubecfg.DeleteCmd{}

		c.GracePeriod, err = flags.GetInt64(flagGracePeriod)
		if err != nil {
			return err
		}

		cwd, err := os.Getwd()
		if err != nil {
			return err
		}
		wd := metadata.AbsPath(cwd)

		envSpec, err := parseEnvCmd(cmd, args)
		if err != nil {
			return err
		}

		c.ClientPool, c.Discovery, err = restClientPool(cmd, envSpec.env)
		if err != nil {
			return err
		}

		c.DefaultNamespace, err = defaultNamespace(clientConfig)
		if err != nil {
			return err
		}

		objs, err := expandEnvCmdObjs(cmd, envSpec, wd)
		if err != nil {
			return err
		}

		return c.Run(objs)
	},
}
<commit_msg>Add help docs for `delete`<commit_after>// Copyright 2017 The kubecfg authors
//
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.

package cmd

import (
	"os"

	"github.com/spf13/cobra"

	"github.com/ksonnet/kubecfg/metadata"
	"github.com/ksonnet/kubecfg/pkg/kubecfg"
)

const (
	flagGracePeriod = "grace-period"
)

func init() {
	RootCmd.AddCommand(deleteCmd)
	addEnvCmdFlags(deleteCmd)
	deleteCmd.PersistentFlags().Int64(flagGracePeriod, -1, "Number of seconds given to resources to terminate gracefully. A negative value is ignored")
}

var deleteCmd = &cobra.Command{
	Use:   "delete [env-name] [-f <file-or-dir>]",
	Short: "Delete Kubernetes resources described in local config",
	RunE: func(cmd *cobra.Command, args []string) error {
		flags := cmd.Flags()
		var err error

		c := kubecfg.DeleteCmd{}

		c.GracePeriod, err = flags.GetInt64(flagGracePeriod)
		if err != nil {
			return err
		}

		cwd, err := os.Getwd()
		if err != nil {
			return err
		}
		wd := metadata.AbsPath(cwd)

		envSpec, err := parseEnvCmd(cmd, args)
		if err != nil {
			return err
		}

		c.ClientPool, c.Discovery, err = restClientPool(cmd, envSpec.env)
		if err != nil {
			return err
		}

		c.DefaultNamespace, err = defaultNamespace(clientConfig)
		if err != nil {
			return err
		}

		objs, err := expandEnvCmdObjs(cmd, envSpec, wd)
		if err != nil {
			return err
		}

		return c.Run(objs)
	},
	Long: `Delete Kubernetes resources from a cluster, as described in the local
configuration.

ksonnet applications are accepted, as well as normal JSON, YAML, and Jsonnet
files.`,
	Example: `  # Delete all resources described in a ksonnet application, from the 'dev'
  # environment. Can be used in any subdirectory of the application.
  ksonnet delete dev

  # Delete resources described in a YAML file. Automatically picks up the
  # cluster's location from '$KUBECONFIG'.
  ksonnet delete -f ./pod.yaml

  # Delete resources described in the JSON file from the 'dev' environment. Can
  # be used in any subdirectory of the application.
  ksonnet delete dev -f ./pod.json

  # Delete resources described in a YAML file, and running in the cluster
  # specified by the current context in specified kubeconfig file.
  ksonnet delete --kubeconfig=./kubeconfig -f ./pod.yaml`,
}
<|endoftext|>


<commit_before>package cmd

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"

	"github.com/pilosa/pilosa/ctl"
)

var exporter = ctl.NewExportCommand(os.Stdin, os.Stdout, os.Stderr)

var exportCmd = &cobra.Command{
	Use:   "export",
	Short: "export - export data from pilosa",
	Long: `
Bulk exports a fragment to a CSV file. If the OUTFILE is not specified then
the output is written to STDOUT.

The format of the CSV file is:

	BITMAPID,PROFILEID

The file does not contain any headers.
`,
	Run: func(cmd *cobra.Command, args []string) {
		if err := exporter.Run(context.Background()); err != nil {
			fmt.Println(err)
		}
	},
}

func init() {
	exportCmd.Flags().StringVarP(&exporter.Host, "host", "", "localhost:15000", "host:port of Pilosa.")
	exportCmd.Flags().StringVarP(&exporter.Database, "database", "d", "", "Pilosa database to export into.")
	exportCmd.Flags().StringVarP(&exporter.Frame, "frame", "f", "", "Frame to export into.")
	exportCmd.Flags().StringVarP(&exporter.Frame, "output-file", "o", "", "File to write export to - default stdout")

	err := viper.BindPFlags(exportCmd.Flags())
	if err != nil {
		log.Fatalf("Error binding export flags: %v", err)
	}

	RootCmd.AddCommand(exportCmd)
}
<commit_msg>fix copy/paste bug in export subcommand<commit_after>package cmd

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"

	"github.com/pilosa/pilosa/ctl"
)

var exporter = ctl.NewExportCommand(os.Stdin, os.Stdout, os.Stderr)

var exportCmd = &cobra.Command{
	Use:   "export",
	Short: "export - export data from pilosa",
	Long: `
Bulk exports a fragment to a CSV file. If the OUTFILE is not specified then
the output is written to STDOUT.

The format of the CSV file is:

	BITMAPID,PROFILEID

The file does not contain any headers.
`,
	Run: func(cmd *cobra.Command, args []string) {
		if err := exporter.Run(context.Background()); err != nil {
			fmt.Println(err)
		}
	},
}

func init() {
	exportCmd.Flags().StringVarP(&exporter.Host, "host", "", "localhost:15000", "host:port of Pilosa.")
	exportCmd.Flags().StringVarP(&exporter.Database, "database", "d", "", "Pilosa database to export into.")
	exportCmd.Flags().StringVarP(&exporter.Frame, "frame", "f", "", "Frame to export into.")
	exportCmd.Flags().StringVarP(&exporter.Path, "output-file", "o", "", "File to write export to - default stdout")

	err := viper.BindPFlags(exportCmd.Flags())
	if err != nil {
		log.Fatalf("Error binding export flags: %v", err)
	}

	RootCmd.AddCommand(exportCmd)
}
<|endoftext|>