<commit_before>/*
Copyright (c) 2015-2016 VMware, Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package object

import (
	"fmt"
	"io"
	"math/rand"
	"path"
	"strings"

	"net/http"
	"net/url"

	"github.com/vmware/govmomi/property"
	"github.com/vmware/govmomi/session"
	"github.com/vmware/govmomi/vim25"
	"github.com/vmware/govmomi/vim25/mo"
	"github.com/vmware/govmomi/vim25/soap"
	"github.com/vmware/govmomi/vim25/types"
	"golang.org/x/net/context"
)

// DatastoreNoSuchDirectoryError is returned when a directory could not be found.
type DatastoreNoSuchDirectoryError struct {
	verb    string
	subject string
}

func (e DatastoreNoSuchDirectoryError) Error() string {
	return fmt.Sprintf("cannot %s '%s': No such directory", e.verb, e.subject)
}

// DatastoreNoSuchFileError is returned when a file could not be found.
type DatastoreNoSuchFileError struct {
	verb    string
	subject string
}

func (e DatastoreNoSuchFileError) Error() string {
	return fmt.Sprintf("cannot %s '%s': No such file", e.verb, e.subject)
}

type Datastore struct {
	Common
}

func NewDatastore(c *vim25.Client, ref types.ManagedObjectReference) *Datastore {
	return &Datastore{
		Common: NewCommon(c, ref),
	}
}

func (d Datastore) Path(path string) string {
	name := d.Name()
	if name == "" {
		panic("expected non-empty name")
	}

	return fmt.Sprintf("[%s] %s", name, path)
}

// URL for datastore access over HTTP
func (d Datastore) URL(ctx context.Context, dc *Datacenter, path string) (*url.URL, error) {
	var mdc mo.Datacenter
	if err := dc.Properties(ctx, dc.Reference(), []string{"name"}, &mdc); err != nil {
		return nil, err
	}

	var mds mo.Datastore
	if err := d.Properties(ctx, d.Reference(), []string{"name"}, &mds); err != nil {
		return nil, err
	}

	u := d.c.URL()

	return &url.URL{
		Scheme: u.Scheme,
		Host:   u.Host,
		Path:   fmt.Sprintf("/folder/%s", path),
		RawQuery: url.Values{
			"dcPath": []string{mdc.Name},
			"dsName": []string{mds.Name},
		}.Encode(),
	}, nil
}

func (d Datastore) Browser(ctx context.Context) (*HostDatastoreBrowser, error) {
	var do mo.Datastore

	err := d.Properties(ctx, d.Reference(), []string{"browser"}, &do)
	if err != nil {
		return nil, err
	}

	return NewHostDatastoreBrowser(d.c, do.Browser), nil
}

// ServiceTicket obtains a ticket via AcquireGenericServiceTicket and returns it an http.Cookie with the url.URL
// that can be used along with the ticket cookie to access the given path.
func (d Datastore) ServiceTicket(ctx context.Context, path string, method string) (*url.URL, *http.Cookie, error) {
	// We are uploading to an ESX host
	u := &url.URL{
		Scheme: d.c.URL().Scheme,
		Host:   d.c.URL().Host,
		Path:   fmt.Sprintf("/folder/%s", path),
		RawQuery: url.Values{
			"dsName": []string{d.Name()},
		}.Encode(),
	}

	// If connected to VC, the ticket request must be for an ESX host.
	if d.c.IsVC() {
		hosts, err := d.AttachedHosts(ctx)
		if err != nil {
			return nil, nil, err
		}

		if len(hosts) == 0 {
			return nil, nil, fmt.Errorf("no hosts attached to datastore %#v", d.Reference())
		}

		// Pick a random attached host
		host := hosts[rand.Intn(len(hosts))]
		name, err := host.ObjectName(ctx)
		if err != nil {
			return nil, nil, err
		}
		u.Host = name
	}

	spec := types.SessionManagerHttpServiceRequestSpec{
		Url: u.String(),
		// See SessionManagerHttpServiceRequestSpecMethod enum
		Method: fmt.Sprintf("http%s%s", method[0:1], strings.ToLower(method[1:])),
	}

	sm := session.NewManager(d.Client())

	ticket, err := sm.AcquireGenericServiceTicket(ctx, &spec)
	if err != nil {
		return nil, nil, err
	}

	cookie := &http.Cookie{
		Name:  "vmware_cgi_ticket",
		Value: ticket.Id,
	}

	return u, cookie, nil
}

func (d Datastore) uploadTicket(ctx context.Context, path string, param *soap.Upload) (*url.URL, *soap.Upload, error) {
	p := soap.DefaultUpload
	if param != nil {
		p = *param // copy
	}

	u, ticket, err := d.ServiceTicket(ctx, path, p.Method)
	if err != nil {
		return nil, nil, err
	}

	p.Ticket = ticket

	return u, &p, nil
}

func (d Datastore) downloadTicket(ctx context.Context, path string, param *soap.Download) (*url.URL, *soap.Download, error) {
	p := soap.DefaultDownload
	if param != nil {
		p = *param // copy
	}

	u, ticket, err := d.ServiceTicket(ctx, path, p.Method)
	if err != nil {
		return nil, nil, err
	}

	p.Ticket = ticket

	return u, &p, nil
}

// Upload via soap.Upload with an http service ticket
func (d Datastore) Upload(ctx context.Context, f io.Reader, path string, param *soap.Upload) error {
	u, p, err := d.uploadTicket(ctx, path, param)
	if err != nil {
		return err
	}
	return d.Client().Upload(f, u, p)
}

// UploadFile via soap.Upload with an http service ticket
func (d Datastore) UploadFile(ctx context.Context, file string, path string, param *soap.Upload) error {
	u, p, err := d.uploadTicket(ctx, path, param)
	if err != nil {
		return err
	}
	return d.Client().UploadFile(file, u, p)
}

// Download via soap.Download with an http service ticket
func (d Datastore) Download(ctx context.Context, path string, param *soap.Download) (io.ReadCloser, int64, error) {
	u, p, err := d.downloadTicket(ctx, path, param)
	if err != nil {
		return nil, 0, err
	}
	return d.Client().Download(u, p)
}

// DownloadFile via soap.Download with an http service ticket
func (d Datastore) DownloadFile(ctx context.Context, path string, file string, param *soap.Download) error {
	u, p, err := d.downloadTicket(ctx, path, param)
	if err != nil {
		return err
	}
	return d.Client().DownloadFile(file, u, p)
}

// AttachedHosts returns hosts that have this Datastore attached, accessible and writable.
func (d Datastore) AttachedHosts(ctx context.Context) ([]*HostSystem, error) {
	var ds mo.Datastore
	var hosts []*HostSystem

	pc := property.DefaultCollector(d.Client())
	err := pc.RetrieveOne(ctx, d.Reference(), []string{"host"}, &ds)
	if err != nil {
		return nil, err
	}

	mounts := make(map[types.ManagedObjectReference]types.DatastoreHostMount)
	var refs []types.ManagedObjectReference
	for _, host := range ds.Host {
		refs = append(refs, host.Key)
		mounts[host.Key] = host
	}

	var hs []mo.HostSystem
	err = pc.Retrieve(ctx, refs, []string{"runtime.connectionState", "runtime.powerState"}, &hs)
	if err != nil {
		return nil, err
	}

	for _, host := range hs {
		if host.Runtime.ConnectionState == types.HostSystemConnectionStateConnected &&
			host.Runtime.PowerState == types.HostSystemPowerStatePoweredOn {

			mount := mounts[host.Reference()]
			info := mount.MountInfo

			if *info.Mounted && *info.Accessible && info.AccessMode == string(types.HostMountModeReadWrite) {
				hosts = append(hosts, NewHostSystem(d.Client(), mount.Key))
			}
		}
	}

	return hosts, nil
}

// AttachedHosts returns hosts that have this Datastore attached, accessible and writable and are members of the given cluster.
func (d Datastore) AttachedClusterHosts(ctx context.Context, cluster *ComputeResource) ([]*HostSystem, error) {
	var hosts []*HostSystem

	clusterHosts, err := cluster.Hosts(ctx)
	if err != nil {
		return nil, err
	}

	attachedHosts, err := d.AttachedHosts(ctx)
	if err != nil {
		return nil, err
	}

	refs := make(map[types.ManagedObjectReference]bool)
	for _, host := range attachedHosts {
		refs[host.Reference()] = true
	}

	for _, host := range clusterHosts {
		if refs[host.Reference()] {
			hosts = append(hosts, host)
		}
	}

	return hosts, nil
}

func (d Datastore) Stat(ctx context.Context, file string) (types.BaseFileInfo, error) {
	b, err := d.Browser(ctx)
	if err != nil {
		return nil, err
	}

	spec := types.HostDatastoreBrowserSearchSpec{
		Details: &types.FileQueryFlags{
			FileType:     true,
			FileSize:     true,
			Modification: true,
			FileOwner:    types.NewBool(true),
		},
		MatchPattern: []string{path.Base(file)},
	}

	dsPath := d.Path(path.Dir(file))
	task, err := b.SearchDatastore(context.TODO(), dsPath, &spec)
	if err != nil {
		return nil, err
	}

	info, err := task.WaitForResult(context.TODO(), nil)
	if err != nil {
		if info == nil || info.Error != nil {
			_, ok := info.Error.Fault.(*types.FileNotFound)
			if ok {
				// FileNotFound means the base path doesn't exist.
				return nil, DatastoreNoSuchDirectoryError{"stat", dsPath}
			}
		}

		return nil, err
	}

	res := info.Result.(types.HostDatastoreBrowserSearchResults)
	if len(res.File) == 0 {
		// File doesn't exist
		return nil, DatastoreNoSuchFileError{"stat", d.Path(file)}
	}

	return res.File[0], nil

}

// Type returns the type of file system volume.
func (d Datastore) Type(ctx context.Context) (types.HostFileSystemVolumeFileSystemType, error) {
	var mds mo.Datastore

	if err := d.Properties(ctx, d.Reference(), []string{"summary.type"}, &mds); err != nil {
		return types.HostFileSystemVolumeFileSystemType(""), err
	}
	return types.HostFileSystemVolumeFileSystemType(mds.Summary.Type), nil
}
<commit_msg>Use ticket HostName for Datastore http access<commit_after>/*
Copyright (c) 2015-2016 VMware, Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package object

import (
	"fmt"
	"io"
	"math/rand"
	"path"
	"strings"

	"net/http"
	"net/url"

	"github.com/vmware/govmomi/property"
	"github.com/vmware/govmomi/session"
	"github.com/vmware/govmomi/vim25"
	"github.com/vmware/govmomi/vim25/mo"
	"github.com/vmware/govmomi/vim25/soap"
	"github.com/vmware/govmomi/vim25/types"
	"golang.org/x/net/context"
)

// DatastoreNoSuchDirectoryError is returned when a directory could not be found.
type DatastoreNoSuchDirectoryError struct {
	verb    string
	subject string
}

func (e DatastoreNoSuchDirectoryError) Error() string {
	return fmt.Sprintf("cannot %s '%s': No such directory", e.verb, e.subject)
}

// DatastoreNoSuchFileError is returned when a file could not be found.
type DatastoreNoSuchFileError struct {
	verb    string
	subject string
}

func (e DatastoreNoSuchFileError) Error() string {
	return fmt.Sprintf("cannot %s '%s': No such file", e.verb, e.subject)
}

type Datastore struct {
	Common
}

func NewDatastore(c *vim25.Client, ref types.ManagedObjectReference) *Datastore {
	return &Datastore{
		Common: NewCommon(c, ref),
	}
}

func (d Datastore) Path(path string) string {
	name := d.Name()
	if name == "" {
		panic("expected non-empty name")
	}

	return fmt.Sprintf("[%s] %s", name, path)
}

// URL for datastore access over HTTP
func (d Datastore) URL(ctx context.Context, dc *Datacenter, path string) (*url.URL, error) {
	var mdc mo.Datacenter
	if err := dc.Properties(ctx, dc.Reference(), []string{"name"}, &mdc); err != nil {
		return nil, err
	}

	var mds mo.Datastore
	if err := d.Properties(ctx, d.Reference(), []string{"name"}, &mds); err != nil {
		return nil, err
	}

	u := d.c.URL()

	return &url.URL{
		Scheme: u.Scheme,
		Host:   u.Host,
		Path:   fmt.Sprintf("/folder/%s", path),
		RawQuery: url.Values{
			"dcPath": []string{mdc.Name},
			"dsName": []string{mds.Name},
		}.Encode(),
	}, nil
}

func (d Datastore) Browser(ctx context.Context) (*HostDatastoreBrowser, error) {
	var do mo.Datastore

	err := d.Properties(ctx, d.Reference(), []string{"browser"}, &do)
	if err != nil {
		return nil, err
	}

	return NewHostDatastoreBrowser(d.c, do.Browser), nil
}

// ServiceTicket obtains a ticket via AcquireGenericServiceTicket and returns it an http.Cookie with the url.URL
// that can be used along with the ticket cookie to access the given path.
func (d Datastore) ServiceTicket(ctx context.Context, path string, method string) (*url.URL, *http.Cookie, error) {
	// We are uploading to an ESX host
	u := &url.URL{
		Scheme: d.c.URL().Scheme,
		Host:   d.c.URL().Host,
		Path:   fmt.Sprintf("/folder/%s", path),
		RawQuery: url.Values{
			"dsName": []string{d.Name()},
		}.Encode(),
	}

	// If connected to VC, the ticket request must be for an ESX host.
	if d.c.IsVC() {
		hosts, err := d.AttachedHosts(ctx)
		if err != nil {
			return nil, nil, err
		}

		if len(hosts) == 0 {
			return nil, nil, fmt.Errorf("no hosts attached to datastore %#v", d.Reference())
		}

		// Pick a random attached host
		host := hosts[rand.Intn(len(hosts))]
		name, err := host.ObjectName(ctx)
		if err != nil {
			return nil, nil, err
		}
		u.Host = name
	}

	spec := types.SessionManagerHttpServiceRequestSpec{
		Url: u.String(),
		// See SessionManagerHttpServiceRequestSpecMethod enum
		Method: fmt.Sprintf("http%s%s", method[0:1], strings.ToLower(method[1:])),
	}

	sm := session.NewManager(d.Client())

	ticket, err := sm.AcquireGenericServiceTicket(ctx, &spec)
	if err != nil {
		return nil, nil, err
	}

	cookie := &http.Cookie{
		Name:  "vmware_cgi_ticket",
		Value: ticket.Id,
	}

	if d.c.IsVC() && ticket.HostName != "" {
		u.Host = ticket.HostName
	}

	return u, cookie, nil
}

func (d Datastore) uploadTicket(ctx context.Context, path string, param *soap.Upload) (*url.URL, *soap.Upload, error) {
	p := soap.DefaultUpload
	if param != nil {
		p = *param // copy
	}

	u, ticket, err := d.ServiceTicket(ctx, path, p.Method)
	if err != nil {
		return nil, nil, err
	}

	p.Ticket = ticket

	return u, &p, nil
}

func (d Datastore) downloadTicket(ctx context.Context, path string, param *soap.Download) (*url.URL, *soap.Download, error) {
	p := soap.DefaultDownload
	if param != nil {
		p = *param // copy
	}

	u, ticket, err := d.ServiceTicket(ctx, path, p.Method)
	if err != nil {
		return nil, nil, err
	}

	p.Ticket = ticket

	return u, &p, nil
}

// Upload via soap.Upload with an http service ticket
func (d Datastore) Upload(ctx context.Context, f io.Reader, path string, param *soap.Upload) error {
	u, p, err := d.uploadTicket(ctx, path, param)
	if err != nil {
		return err
	}
	return d.Client().Upload(f, u, p)
}

// UploadFile via soap.Upload with an http service ticket
func (d Datastore) UploadFile(ctx context.Context, file string, path string, param *soap.Upload) error {
	u, p, err := d.uploadTicket(ctx, path, param)
	if err != nil {
		return err
	}
	return d.Client().UploadFile(file, u, p)
}

// Download via soap.Download with an http service ticket
func (d Datastore) Download(ctx context.Context, path string, param *soap.Download) (io.ReadCloser, int64, error) {
	u, p, err := d.downloadTicket(ctx, path, param)
	if err != nil {
		return nil, 0, err
	}
	return d.Client().Download(u, p)
}

// DownloadFile via soap.Download with an http service ticket
func (d Datastore) DownloadFile(ctx context.Context, path string, file string, param *soap.Download) error {
	u, p, err := d.downloadTicket(ctx, path, param)
	if err != nil {
		return err
	}
	return d.Client().DownloadFile(file, u, p)
}

// AttachedHosts returns hosts that have this Datastore attached, accessible and writable.
func (d Datastore) AttachedHosts(ctx context.Context) ([]*HostSystem, error) {
	var ds mo.Datastore
	var hosts []*HostSystem

	pc := property.DefaultCollector(d.Client())
	err := pc.RetrieveOne(ctx, d.Reference(), []string{"host"}, &ds)
	if err != nil {
		return nil, err
	}

	mounts := make(map[types.ManagedObjectReference]types.DatastoreHostMount)
	var refs []types.ManagedObjectReference
	for _, host := range ds.Host {
		refs = append(refs, host.Key)
		mounts[host.Key] = host
	}

	var hs []mo.HostSystem
	err = pc.Retrieve(ctx, refs, []string{"runtime.connectionState", "runtime.powerState"}, &hs)
	if err != nil {
		return nil, err
	}

	for _, host := range hs {
		if host.Runtime.ConnectionState == types.HostSystemConnectionStateConnected &&
			host.Runtime.PowerState == types.HostSystemPowerStatePoweredOn {

			mount := mounts[host.Reference()]
			info := mount.MountInfo

			if *info.Mounted && *info.Accessible && info.AccessMode == string(types.HostMountModeReadWrite) {
				hosts = append(hosts, NewHostSystem(d.Client(), mount.Key))
			}
		}
	}

	return hosts, nil
}

// AttachedHosts returns hosts that have this Datastore attached, accessible and writable and are members of the given cluster.
func (d Datastore) AttachedClusterHosts(ctx context.Context, cluster *ComputeResource) ([]*HostSystem, error) {
	var hosts []*HostSystem

	clusterHosts, err := cluster.Hosts(ctx)
	if err != nil {
		return nil, err
	}

	attachedHosts, err := d.AttachedHosts(ctx)
	if err != nil {
		return nil, err
	}

	refs := make(map[types.ManagedObjectReference]bool)
	for _, host := range attachedHosts {
		refs[host.Reference()] = true
	}

	for _, host := range clusterHosts {
		if refs[host.Reference()] {
			hosts = append(hosts, host)
		}
	}

	return hosts, nil
}

func (d Datastore) Stat(ctx context.Context, file string) (types.BaseFileInfo, error) {
	b, err := d.Browser(ctx)
	if err != nil {
		return nil, err
	}

	spec := types.HostDatastoreBrowserSearchSpec{
		Details: &types.FileQueryFlags{
			FileType:     true,
			FileSize:     true,
			Modification: true,
			FileOwner:    types.NewBool(true),
		},
		MatchPattern: []string{path.Base(file)},
	}

	dsPath := d.Path(path.Dir(file))
	task, err := b.SearchDatastore(context.TODO(), dsPath, &spec)
	if err != nil {
		return nil, err
	}

	info, err := task.WaitForResult(context.TODO(), nil)
	if err != nil {
		if info == nil || info.Error != nil {
			_, ok := info.Error.Fault.(*types.FileNotFound)
			if ok {
				// FileNotFound means the base path doesn't exist.
				return nil, DatastoreNoSuchDirectoryError{"stat", dsPath}
			}
		}

		return nil, err
	}

	res := info.Result.(types.HostDatastoreBrowserSearchResults)
	if len(res.File) == 0 {
		// File doesn't exist
		return nil, DatastoreNoSuchFileError{"stat", d.Path(file)}
	}

	return res.File[0], nil

}

// Type returns the type of file system volume.
func (d Datastore) Type(ctx context.Context) (types.HostFileSystemVolumeFileSystemType, error) {
	var mds mo.Datastore

	if err := d.Properties(ctx, d.Reference(), []string{"summary.type"}, &mds); err != nil {
		return types.HostFileSystemVolumeFileSystemType(""), err
	}
	return types.HostFileSystemVolumeFileSystemType(mds.Summary.Type), nil
}
<|endoftext|>


<commit_before>package xstrings

import (
	"github.com/wallclockbuilder/testify/assert"
	"testing"
)

func TestDowncase(t *testing.T) {
	assert := assert.New(t)
	assert.Equal("hello", Downcase("hEllO"))
}
<commit_msg>Add example to Downcase<commit_after>package xstrings

import (
	"fmt"
	"github.com/wallclockbuilder/testify/assert"
	"testing"
)

func ExampleDowncase() {
	fmt.Println(Downcase("hEllO"))
	// Output: hello
}

func TestDowncase(t *testing.T) {
	assert := assert.New(t)
	assert.Equal("hello", Downcase("hEllO"))
}
<|endoftext|>


<commit_before>package segment_count

import (
	"fmt"
	"log"
	"math"
	"time"

	"github.com/huichen/sego"
)

var (
	dataobj   data
	segmenter sego.Segmenter
)

func Exec(srcDB string, srcTable string, srcField string, distTable string) error {
	tStart := time.Now()
	dataobj.srcDB = srcDB
	dataobj.SrcTable = srcTable
	dataobj.SrcField = srcField
	dataobj.DistTable = distTable

	if err := dataobj.init(); err != nil {
		return err
	}
	defer dataobj.db.Close()

	// 载入词典
	segmenter.LoadDictionary(DICT_FILE)

	count, err := dataobj.count()
	if err != nil {
		return err
	}
	fmt.Println("total count: ", count)

	num := int(math.Ceil(float64(count) / float64(GROUP_COUNT)))

	for i := 0; i < num; i++ {
		log.Println("worker :", (i + 1), " / ", num)
		offset := i * GROUP_COUNT
		worker(offset, GROUP_COUNT)
	}

	tEnd := time.Now()
	duration := tEnd.Sub(tStart)
	fmt.Println("Used time:", duration)

	return nil
}

func worker(offset int, limit int) error {
	titleArray, err := dataobj.read(offset, limit)
	if err != nil {
		return err
	}

	var wordSlice []string

	for _, title := range titleArray {
		text := []byte(title)
		segments := segmenter.Segment(text)
		segmentArray := sego.SegmentsToSlice(segments, false)
		for _, segment := range segmentArray {
			wordSlice = append(wordSlice, segment)
		}
	}
	if err := dataobj.write(wordSlice); err != nil {
		return err
	}
	return nil
}
<commit_msg>add percent view<commit_after>package segment_count

import (
	"log"
	"math"
	"time"

	"github.com/huichen/sego"
)

var (
	dataobj   data
	segmenter sego.Segmenter
)

func Exec(srcDB string, srcTable string, srcField string, distTable string) error {
	tStart := time.Now()
	dataobj.srcDB = srcDB
	dataobj.SrcTable = srcTable
	dataobj.SrcField = srcField
	dataobj.DistTable = distTable

	if err := dataobj.init(); err != nil {
		return err
	}
	defer dataobj.db.Close()

	// 载入词典
	segmenter.LoadDictionary(DICT_FILE)

	count, err := dataobj.count()
	if err != nil {
		return err
	}
	log.Println("Total count: ", count)

	num := int(math.Ceil(float64(count) / float64(GROUP_COUNT)))

	for i := 0; i < num; i++ {
		log.Printf("worker : %d/%d -- percent : %.2f%%", (i + 1), num, float64(i+1)/float64(num)*100)
		offset := i * GROUP_COUNT
		worker(offset, GROUP_COUNT)
	}

	tEnd := time.Now()
	duration := tEnd.Sub(tStart)
	log.Println("Used time:", duration)

	return nil
}

func worker(offset int, limit int) error {
	titleArray, err := dataobj.read(offset, limit)
	if err != nil {
		return err
	}

	var wordSlice []string

	for _, title := range titleArray {
		text := []byte(title)
		segments := segmenter.Segment(text)
		segmentArray := sego.SegmentsToSlice(segments, false)
		for _, segment := range segmentArray {
			wordSlice = append(wordSlice, segment)
		}
	}
	if err := dataobj.write(wordSlice); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func main() {
	input, err := os.Open(os.Args[1])
	if err != nil {
		fmt.Fprintln(os.Stderr, "opening file:", err)
		os.Exit(1)
	}
	scanner := bufio.NewScanner(input)

	fuel := 0
	for scanner.Scan() {
		module, err := strconv.Atoi(scanner.Text())
		if err != nil {
			fmt.Fprintln(os.Stderr, "converting to int:", err)
			os.Exit(1)
		}

		fuel += module/3 - 2
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading input:", err)
		os.Exit(1)
	}

	fmt.Println(fuel)
}
<commit_msg>Add convenience functions<commit_after>package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func main() {
	scanner, err := getInputScanner()
	if err != nil {
		die("getting scanner", err)
	}

	fuel := 0
	for scanner.Scan() {
		module, err := strconv.Atoi(scanner.Text())
		if err != nil {
			die("converting to int", err)
		}

		fuel += module/3 - 2
	}
	if err := scanner.Err(); err != nil {
		die("reading input", err)
	}

	fmt.Println(fuel)
}

func getInputScanner() (*bufio.Scanner, error) {
	if len(os.Args) == 1 {
		os.Args = append(os.Args, "input")
	}
	input, err := os.Open(os.Args[1])
	if err != nil {
		return nil, err
	}

	return bufio.NewScanner(input), nil
}

func die(msg string, err error) {
	fmt.Fprintf(os.Stderr, "%s: %v", msg, err)
	os.Exit(1)
}
<|endoftext|>


<commit_before><commit_msg>Minor import fix<commit_after><|endoftext|>


<commit_before><commit_msg>Fix race condition in TestHTMLNoRace<commit_after><|endoftext|>


<commit_before><commit_msg>wire in the add service method<commit_after><|endoftext|>


<commit_before><commit_msg>rpcc: Cleanup sync store when Stream closes<commit_after><|endoftext|>


<commit_before>/**
 * @file main.go
 * @author Mikhail Klementyev jollheef<AT>riseup.net
 * @license GNU AGPLv3
 * @date December, 2015
 * @brief contest checking system CLI
 *
 * Entry point for contest checking system CLI
 */

package main

import (
	"database/sql"
	"encoding/xml"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"sort"

	"github.com/jollheef/henhouse/config"
	"github.com/jollheef/henhouse/db"
	"github.com/olekukonko/tablewriter"
	kingpin "gopkg.in/alecthomas/kingpin.v2"
)

var (
	configPath = kingpin.Flag("config", "Path to configuration file.").String()

	// Task
	task = kingpin.Command("task", "Work with tasks.")

	taskList        = task.Command("list", "List tasks.")
	taskListWOFlags = taskList.Flag("without-flags", "Do not include flags in output.").Bool()

	taskAdd    = task.Command("add", "Add task.")
	taskAddXML = taskAdd.Arg("xml", "Path to xml.").Required().String()

	taskUpdate    = task.Command("update", "Update task.")
	taskUpdateID  = taskUpdate.Arg("id", "ID of task.").Required().Int()
	taskUpdateXML = taskUpdate.Arg("xml", "Path to xml.").Required().String()

	taskOpen   = task.Command("open", "Open task.")
	taskOpenID = taskOpen.Arg("id", "ID of task").Required().Int()

	taskClose   = task.Command("close", "Close task.")
	taskCloseID = taskClose.Arg("id", "ID of task").Required().Int()

	taskDump   = task.Command("dump", "Dump task to xml.")
	taskDumpID = taskDump.Arg("id", "ID of task").Required().Int()

	// Category
	category = kingpin.Command("category", "Work with categories.")

	categoryList = category.Command("list", "List categories.")

	categoryAdd  = category.Command("add", "Add category.")
	categoryName = categoryAdd.Arg("name", "Name.").Required().String()

	// Team
	team = kingpin.Command("team", "Work with teams.")

	teamList   = team.Command("list", "List teams.")
	teamInfo   = team.Command("info", "Information about team.")
	teamInfoID = teamInfo.Arg("id", "ID of task").Required().Int()
)

var (
	// CommitID fill in ./build.sh
	CommitID string
	// BuildDate fill in ./build.sh
	BuildDate string
	// BuildTime fill in ./build.sh
	BuildTime string
)

func getCategoryByID(categoryID int, categories []db.Category) string {
	for _, cat := range categories {
		if cat.ID == categoryID {
			return cat.Name
		}
	}
	return "Unknown"
}

func getCategoryByName(name string, categories []db.Category) (id int, err error) {
	for _, cat := range categories {
		if cat.Name == name {
			return cat.ID, nil
		}
	}

	return 0, errors.New("Category " + name + " not found")
}

type byID []db.Task

func (t byID) Len() int           { return len(t) }
func (t byID) Swap(i, j int)      { t[i], t[j] = t[j], t[i] }
func (t byID) Less(i, j int) bool { return t[i].ID < t[j].ID }

func parseTask(path string, categories []db.Category) (t db.Task, err error) {

	content, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}

	task, err := config.ParseXMLTask(content)
	if err != nil {
		return
	}

	t.Name = task.Name
	t.Desc = task.Description
	t.NameEn = task.NameEn
	t.DescEn = task.DescriptionEn
	t.CategoryID, err = getCategoryByName(task.Category, categories)
	if err != nil {
		log.Println("Cant find category")
		return
	}

	t.Level = task.Level
	t.Flag = task.Flag
	t.Price = 500         // TODO support non-shared task
	t.Shared = true       // TODO support non-shared task
	t.MaxSharePrice = 500 // TODO support value from xml
	t.MinSharePrice = 100 // TODO support value from xml
	t.Opened = false      // by default task is closed
	t.Author = task.Author
	t.Tags = task.Tags
	t.ForceClosed = task.ForceClosed

	return
}

var cfgFiles = []string{"/etc/henhouse/cli.toml", "/etc/henhouse.toml",
	"cli.toml", "henhouse.toml"}

func taskUpdateCmd(database *sql.DB, categories []db.Category) (err error) {
	task, err := db.GetTask(database, *taskUpdateID)
	if err != nil {
		return
	}

	id := task.ID

	task, err = parseTask(*taskUpdateXML, categories)
	if err != nil {
		return
	}

	task.ID = id

	err = db.UpdateTask(database, &task)
	if err != nil {
		return
	}

	return
}

func taskAddCmd(database *sql.DB, categories []db.Category) (err error) {
	t, err := parseTask(*taskAddXML, categories)
	if err != nil {
		return
	}

	err = db.AddTask(database, &t)
	if err != nil {
		return
	}

	return
}

func taskListCmd(database *sql.DB, categories []db.Category) (err error) {
	tasks, err := db.GetTasks(database)
	if err != nil {
		return
	}

	sort.Sort(byID(tasks))

	table := tablewriter.NewWriter(os.Stdout)
	var header []string
	if *taskListWOFlags {
		header = []string{"ID", "Name", "Category", "Opened", "Solved by"}
	} else {
		header = []string{"ID", "Name", "Category", "Flag", "Opened", "Solved by"}
	}
	table.SetHeader(header)

	for _, task := range tasks {
		var solvedBy int
		solvedBy, err = db.GetSolvedCount(database, task.ID)
		if err != nil {
			return
		}

		var row []string

		row = append(row, fmt.Sprintf("%d", task.ID))
		row = append(row, task.Name)
		row = append(row, getCategoryByID(task.CategoryID, categories))
		if !*taskListWOFlags {
			row = append(row, task.Flag)
		}
		row = append(row, fmt.Sprintf("%v", task.Opened))
		row = append(row, fmt.Sprintf("%d", solvedBy))

		table.Append(row)
	}

	table.Render()

	return
}

func taskDumpCmd(database *sql.DB, categories []db.Category) (err error) {
	task, err := db.GetTask(database, *taskDumpID)
	if err != nil {
		return
	}

	xmlTask := config.Task{
		Name:          task.Name,
		NameEn:        task.NameEn,
		Description:   task.Desc,
		DescriptionEn: task.DescEn,
		Category:      getCategoryByID(task.CategoryID, categories),
		Level:         task.Level,
		Flag:          task.Flag,
		Author:        task.Author,
		ForceClosed:   task.ForceClosed,
		Tags:          task.Tags,
	}

	output, err := xml.MarshalIndent(xmlTask, "", "	")
	if err != nil {
		return

	}

	fmt.Fprintln(os.Stdout, string(output))

	return
}

func categoryListCmd(database *sql.DB) (err error) {
	categories, err := db.GetCategories(database)
	if err != nil {
		return
	}

	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"ID", "Name"})

	for _, cat := range categories {
		row := []string{fmt.Sprintf("%d", cat.ID), cat.Name}
		table.Append(row)
	}

	table.Render()

	return
}

type byScore [][]string

func (t byScore) Len() int      { return len(t) }
func (t byScore) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
func (t byScore) Less(i, j int) bool {
	var in, jn int
	fmt.Sscanf(t[i][3], "%d", &in)
	fmt.Sscanf(t[j][3], "%d", &jn)
	return in > jn
}

func teamListCmd(database *sql.DB) (err error) {
	teams, err := db.GetTeams(database)
	if err != nil {
		return
	}

	flags, err := db.GetFlags(database)
	if err != nil {
		return
	}

	tasks, err := db.GetTasks(database)
	if err != nil {
		return
	}

	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"ID", "Name", "Score", "Solved"})

	rows := [][]string{}

	for _, t := range teams {
		row := []string{fmt.Sprintf("%d", t.ID), t.Name}

		var score db.Score
		score, err = db.GetLastScore(database, t.ID)
		if err != nil {
			return
		}
		row = append(row, fmt.Sprintf("%d", score.Score))

		solvedCount := 0
		for _, f := range flags {
			if f.TeamID == t.ID {
				solvedCount += 1
			}
		}

		row = append(row, fmt.Sprintf("%d/%d", solvedCount, len(tasks)))

		rows = append(rows, row)
	}

	sort.Sort(byScore(rows))

	for _, row := range rows {
		table.Append(row)
	}

	table.Render()

	return
}

func teamInfoCmd(database *sql.DB) (err error) {
	teams, err := db.GetTeams(database)
	if err != nil {
		return
	}

	flags, err := db.GetFlags(database)
	if err != nil {
		return
	}

	tasks, err := db.GetTasks(database)
	if err != nil {
		return
	}

	for _, t := range teams {
		if t.ID == *teamInfoID {
			fmt.Println("ID:", t.ID)
			fmt.Println("Name:", t.Name)
			fmt.Println("Email:", t.Email)
			fmt.Println("Description:", t.Desc)
			fmt.Println("Token:", t.Token)
			fmt.Println("Test:", t.Test)
			fmt.Print("Solved: ")
			solvedCount := 0
			for _, f := range flags {
				if f.TeamID == t.ID {
					var task db.Task
					task, err = db.GetTask(database, f.TaskID)
					if err != nil {
						return
					}
					solvedCount += 1
					fmt.Printf("%s (%d), ", task.Name, task.ID)
				}
			}
			fmt.Println()
			fmt.Printf("Solved: %d/%d\n", solvedCount, len(tasks))
		}
	}

	return
}

func runCommandLine(database *sql.DB, categories []db.Category) (err error) {
	switch kingpin.Parse() {
	case "task add":
		err = taskAddCmd(database, categories)
	case "task update":
		err = taskUpdateCmd(database, categories)
	case "task list":
		err = taskListCmd(database, categories)
	case "task open":
		err = db.SetOpened(database, *taskOpenID, true)
	case "task close":
		err = db.SetOpened(database, *taskCloseID, false)
	case "task dump":
		err = taskDumpCmd(database, categories)
	case "category add":
		err = db.AddCategory(database, &db.Category{Name: *categoryName})
	case "category list":
		err = categoryListCmd(database)
	case "team list":
		err = teamListCmd(database)
	case "team info":
		err = teamInfoCmd(database)
	}

	return
}

func main() {

	if len(CommitID) > 7 {
		CommitID = CommitID[:7] // abbreviated commit hash
	}

	kingpin.Version(BuildDate + " " + CommitID +
		" (Mikhail Klementyev <jollheef@riseup.net>)")

	kingpin.Parse()

	var cfgPath string

	if *configPath != "" {
		cfgPath = *configPath
	} else {

		for _, cfgFile := range cfgFiles {
			_, err := os.Stat(cfgFile)
			if err == nil {
				cfgPath = cfgFile
				break
			}
		}
	}

	if cfgPath == "" {
		log.Fatalln("Config not found")
	}

	cfg, err := config.ReadConfig(cfgPath)
	if err != nil {
		log.Fatalln("Cannot open config:", err)
	}

	database, err := db.OpenDatabase(cfg.Database.Connection)
	if err != nil {
		log.Fatalln("Error:", err)
	}

	defer database.Close()

	database.SetMaxOpenConns(cfg.Database.MaxConnections)

	categories, err := db.GetCategories(database)
	if err != nil {
		log.Fatalln("Error:", err)
	}

	err = runCommandLine(database, categories)
	if err != nil {
		log.Fatalln("Error:", err)
	}
}
<commit_msg>Do not stop without score<commit_after>/**
 * @file main.go
 * @author Mikhail Klementyev jollheef<AT>riseup.net
 * @license GNU AGPLv3
 * @date December, 2015
 * @brief contest checking system CLI
 *
 * Entry point for contest checking system CLI
 */

package main

import (
	"database/sql"
	"encoding/xml"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"sort"

	"github.com/jollheef/henhouse/config"
	"github.com/jollheef/henhouse/db"
	"github.com/olekukonko/tablewriter"
	kingpin "gopkg.in/alecthomas/kingpin.v2"
)

var (
	configPath = kingpin.Flag("config", "Path to configuration file.").String()

	// Task
	task = kingpin.Command("task", "Work with tasks.")

	taskList        = task.Command("list", "List tasks.")
	taskListWOFlags = taskList.Flag("without-flags", "Do not include flags in output.").Bool()

	taskAdd    = task.Command("add", "Add task.")
	taskAddXML = taskAdd.Arg("xml", "Path to xml.").Required().String()

	taskUpdate    = task.Command("update", "Update task.")
	taskUpdateID  = taskUpdate.Arg("id", "ID of task.").Required().Int()
	taskUpdateXML = taskUpdate.Arg("xml", "Path to xml.").Required().String()

	taskOpen   = task.Command("open", "Open task.")
	taskOpenID = taskOpen.Arg("id", "ID of task").Required().Int()

	taskClose   = task.Command("close", "Close task.")
	taskCloseID = taskClose.Arg("id", "ID of task").Required().Int()

	taskDump   = task.Command("dump", "Dump task to xml.")
	taskDumpID = taskDump.Arg("id", "ID of task").Required().Int()

	// Category
	category = kingpin.Command("category", "Work with categories.")

	categoryList = category.Command("list", "List categories.")

	categoryAdd  = category.Command("add", "Add category.")
	categoryName = categoryAdd.Arg("name", "Name.").Required().String()

	// Team
	team = kingpin.Command("team", "Work with teams.")

	teamList   = team.Command("list", "List teams.")
	teamInfo   = team.Command("info", "Information about team.")
	teamInfoID = teamInfo.Arg("id", "ID of task").Required().Int()
)

var (
	// CommitID fill in ./build.sh
	CommitID string
	// BuildDate fill in ./build.sh
	BuildDate string
	// BuildTime fill in ./build.sh
	BuildTime string
)

func getCategoryByID(categoryID int, categories []db.Category) string {
	for _, cat := range categories {
		if cat.ID == categoryID {
			return cat.Name
		}
	}
	return "Unknown"
}

func getCategoryByName(name string, categories []db.Category) (id int, err error) {
	for _, cat := range categories {
		if cat.Name == name {
			return cat.ID, nil
		}
	}

	return 0, errors.New("Category " + name + " not found")
}

type byID []db.Task

func (t byID) Len() int           { return len(t) }
func (t byID) Swap(i, j int)      { t[i], t[j] = t[j], t[i] }
func (t byID) Less(i, j int) bool { return t[i].ID < t[j].ID }

func parseTask(path string, categories []db.Category) (t db.Task, err error) {

	content, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}

	task, err := config.ParseXMLTask(content)
	if err != nil {
		return
	}

	t.Name = task.Name
	t.Desc = task.Description
	t.NameEn = task.NameEn
	t.DescEn = task.DescriptionEn
	t.CategoryID, err = getCategoryByName(task.Category, categories)
	if err != nil {
		log.Println("Cant find category")
		return
	}

	t.Level = task.Level
	t.Flag = task.Flag
	t.Price = 500         // TODO support non-shared task
	t.Shared = true       // TODO support non-shared task
	t.MaxSharePrice = 500 // TODO support value from xml
	t.MinSharePrice = 100 // TODO support value from xml
	t.Opened = false      // by default task is closed
	t.Author = task.Author
	t.Tags = task.Tags
	t.ForceClosed = task.ForceClosed

	return
}

var cfgFiles = []string{"/etc/henhouse/cli.toml", "/etc/henhouse.toml",
	"cli.toml", "henhouse.toml"}

func taskUpdateCmd(database *sql.DB, categories []db.Category) (err error) {
	task, err := db.GetTask(database, *taskUpdateID)
	if err != nil {
		return
	}

	id := task.ID

	task, err = parseTask(*taskUpdateXML, categories)
	if err != nil {
		return
	}

	task.ID = id

	err = db.UpdateTask(database, &task)
	if err != nil {
		return
	}

	return
}

func taskAddCmd(database *sql.DB, categories []db.Category) (err error) {
	t, err := parseTask(*taskAddXML, categories)
	if err != nil {
		return
	}

	err = db.AddTask(database, &t)
	if err != nil {
		return
	}

	return
}

func taskListCmd(database *sql.DB, categories []db.Category) (err error) {
	tasks, err := db.GetTasks(database)
	if err != nil {
		return
	}

	sort.Sort(byID(tasks))

	table := tablewriter.NewWriter(os.Stdout)
	var header []string
	if *taskListWOFlags {
		header = []string{"ID", "Name", "Category", "Opened", "Solved by"}
	} else {
		header = []string{"ID", "Name", "Category", "Flag", "Opened", "Solved by"}
	}
	table.SetHeader(header)

	for _, task := range tasks {
		var solvedBy int
		solvedBy, err = db.GetSolvedCount(database, task.ID)
		if err != nil {
			return
		}

		var row []string

		row = append(row, fmt.Sprintf("%d", task.ID))
		row = append(row, task.Name)
		row = append(row, getCategoryByID(task.CategoryID, categories))
		if !*taskListWOFlags {
			row = append(row, task.Flag)
		}
		row = append(row, fmt.Sprintf("%v", task.Opened))
		row = append(row, fmt.Sprintf("%d", solvedBy))

		table.Append(row)
	}

	table.Render()

	return
}

func taskDumpCmd(database *sql.DB, categories []db.Category) (err error) {
	task, err := db.GetTask(database, *taskDumpID)
	if err != nil {
		return
	}

	xmlTask := config.Task{
		Name:          task.Name,
		NameEn:        task.NameEn,
		Description:   task.Desc,
		DescriptionEn: task.DescEn,
		Category:      getCategoryByID(task.CategoryID, categories),
		Level:         task.Level,
		Flag:          task.Flag,
		Author:        task.Author,
		ForceClosed:   task.ForceClosed,
		Tags:          task.Tags,
	}

	output, err := xml.MarshalIndent(xmlTask, "", "	")
	if err != nil {
		return

	}

	fmt.Fprintln(os.Stdout, string(output))

	return
}

func categoryListCmd(database *sql.DB) (err error) {
	categories, err := db.GetCategories(database)
	if err != nil {
		return
	}

	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"ID", "Name"})

	for _, cat := range categories {
		row := []string{fmt.Sprintf("%d", cat.ID), cat.Name}
		table.Append(row)
	}

	table.Render()

	return
}

type byScore [][]string

func (t byScore) Len() int      { return len(t) }
func (t byScore) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
func (t byScore) Less(i, j int) bool {
	var in, jn int
	fmt.Sscanf(t[i][3], "%d", &in)
	fmt.Sscanf(t[j][3], "%d", &jn)
	return in > jn
}

func teamListCmd(database *sql.DB) (err error) {
	teams, err := db.GetTeams(database)
	if err != nil {
		return
	}

	flags, err := db.GetFlags(database)
	if err != nil {
		return
	}

	tasks, err := db.GetTasks(database)
	if err != nil {
		return
	}

	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"ID", "Name", "Score", "Solved"})

	rows := [][]string{}

	for _, t := range teams {
		row := []string{fmt.Sprintf("%d", t.ID), t.Name}

		var score db.Score
		score, err = db.GetLastScore(database, t.ID)
		if err != nil {
			continue
		}
		row = append(row, fmt.Sprintf("%d", score.Score))

		solvedCount := 0
		for _, f := range flags {
			if f.TeamID == t.ID {
				solvedCount += 1
			}
		}

		row = append(row, fmt.Sprintf("%d/%d", solvedCount, len(tasks)))

		rows = append(rows, row)
	}

	sort.Sort(byScore(rows))

	for _, row := range rows {
		table.Append(row)
	}

	table.Render()

	return
}

func teamInfoCmd(database *sql.DB) (err error) {
	teams, err := db.GetTeams(database)
	if err != nil {
		return
	}

	flags, err := db.GetFlags(database)
	if err != nil {
		return
	}

	tasks, err := db.GetTasks(database)
	if err != nil {
		return
	}

	for _, t := range teams {
		if t.ID == *teamInfoID {
			fmt.Println("ID:", t.ID)
			fmt.Println("Name:", t.Name)
			fmt.Println("Email:", t.Email)
			fmt.Println("Description:", t.Desc)
			fmt.Println("Token:", t.Token)
			fmt.Println("Test:", t.Test)
			fmt.Print("Solved: ")
			solvedCount := 0
			for _, f := range flags {
				if f.TeamID == t.ID {
					var task db.Task
					task, err = db.GetTask(database, f.TaskID)
					if err != nil {
						return
					}
					solvedCount += 1
					fmt.Printf("%s (%d), ", task.Name, task.ID)
				}
			}
			fmt.Println()
			fmt.Printf("Solved: %d/%d\n", solvedCount, len(tasks))
		}
	}

	return
}

func runCommandLine(database *sql.DB, categories []db.Category) (err error) {
	switch kingpin.Parse() {
	case "task add":
		err = taskAddCmd(database, categories)
	case "task update":
		err = taskUpdateCmd(database, categories)
	case "task list":
		err = taskListCmd(database, categories)
	case "task open":
		err = db.SetOpened(database, *taskOpenID, true)
	case "task close":
		err = db.SetOpened(database, *taskCloseID, false)
	case "task dump":
		err = taskDumpCmd(database, categories)
	case "category add":
		err = db.AddCategory(database, &db.Category{Name: *categoryName})
	case "category list":
		err = categoryListCmd(database)
	case "team list":
		err = teamListCmd(database)
	case "team info":
		err = teamInfoCmd(database)
	}

	return
}

func main() {

	if len(CommitID) > 7 {
		CommitID = CommitID[:7] // abbreviated commit hash
	}

	kingpin.Version(BuildDate + " " + CommitID +
		" (Mikhail Klementyev <jollheef@riseup.net>)")

	kingpin.Parse()

	var cfgPath string

	if *configPath != "" {
		cfgPath = *configPath
	} else {

		for _, cfgFile := range cfgFiles {
			_, err := os.Stat(cfgFile)
			if err == nil {
				cfgPath = cfgFile
				break
			}
		}
	}

	if cfgPath == "" {
		log.Fatalln("Config not found")
	}

	cfg, err := config.ReadConfig(cfgPath)
	if err != nil {
		log.Fatalln("Cannot open config:", err)
	}

	database, err := db.OpenDatabase(cfg.Database.Connection)
	if err != nil {
		log.Fatalln("Error:", err)
	}

	defer database.Close()

	database.SetMaxOpenConns(cfg.Database.MaxConnections)

	categories, err := db.GetCategories(database)
	if err != nil {
		log.Fatalln("Error:", err)
	}

	err = runCommandLine(database, categories)
	if err != nil {
		log.Fatalln("Error:", err)
	}
}
<|endoftext|>


<commit_before>package components

type Sensor struct {
	Id                    int64  //sensor.id
	IoType                int64  //NotNeeded
	IoAddress             int    //NotNeeded
	NumberOfValues        int    //lenght of bytes that belong to this sensor (between 1 and 8)
	LenghtOfValues        int    //number of values that belong to this sensor (1,2,4 or 8)
	HeaderOrder           int    //index in which the messages are send that belong to this sensor
	Description           string //NotNeeded - user input
	Conversion_expression string //math expression that transforms the message
	DataType              int    // or int or string, or anything that shows what type of data this sensor is returning
}

func NewHeaderSensor(
	id int64,
	number_of_values,
	lenght_of_values,
	header_order,
	data_type int,
	conversion_expression string) Sensor {
	//return sensor(id:id, IoType:io_type)
	return Sensor{id, 0, 0, number_of_values, lenght_of_values, header_order, "", conversion_expression, data_type}
}

func NewSensor(
	id,
	ioType int64,
	ioAddress,
	number_of_values,
	lenght_of_values,
	header_order,
	data_type int,
	description,
	conversion_expression string) Sensor {
	//return sensor(id:id, IoType:io_type)
	return Sensor{id, ioType, ioAddress, number_of_values, lenght_of_values, header_order, description, conversion_expression, data_type}
}
<commit_msg>Added minimalistic documentation<commit_after>package components

type Sensor struct {
	Id                    int64  //sensor.id
	IoType                int64  //NotNeeded
	IoAddress             int    //NotNeeded
	NumberOfValues        int    //lenght of bytes that belong to this sensor (between 1 and 8)
	LenghtOfValues        int    //number of values that belong to this sensor (1,2,4 or 8)
	HeaderOrder           int    //index in which the messages are send that belong to this sensor
	Description           string //NotNeeded - user input
	Conversion_expression string //math expression that transforms the message
	DataType              int    // or int or string, or anything that shows what type of data this sensor is returning
}

// Headersensor will return a sensor object with default values for fields that are not needed durring proccesing
func NewHeaderSensor(
	id int64,
	number_of_values,
	lenght_of_values,
	header_order,
	data_type int,
	conversion_expression string) Sensor {
	//return sensor(id:id, IoType:io_type)
	return Sensor{id, 0, 0, number_of_values, lenght_of_values, header_order, "", conversion_expression, data_type}
}

//Default constructor
func NewSensor(
	id,
	ioType int64,
	ioAddress,
	number_of_values,
	lenght_of_values,
	header_order,
	data_type int,
	description,
	conversion_expression string) Sensor {
	return Sensor{id, ioType, ioAddress, number_of_values, lenght_of_values, header_order, description, conversion_expression, data_type}
}
<|endoftext|>


<commit_before>package discordgo

import (
	"encoding/json"
)

// This file contains all the possible structs that can be
// handled by AddHandler/EventHandler.
// DO NOT ADD ANYTHING BUT EVENT HANDLER STRUCTS TO THIS FILE.
//go:generate go run tools/cmd/eventhandlers/main.go

// Connect is the data for a Connect event.
// This is a sythetic event and is not dispatched by Discord.
type Connect struct{}

// Disconnect is the data for a Disconnect event.
// This is a sythetic event and is not dispatched by Discord.
type Disconnect struct{}

// RateLimit is the data for a RateLimit event.
// This is a sythetic event and is not dispatched by Discord.
type RateLimit struct {
	*TooManyRequests
	URL string
}

// Event provides a basic initial struct for all websocket events.
type Event struct {
	Operation int             `json:"op"`
	Sequence  int64           `json:"s"`
	Type      string          `json:"t"`
	RawData   json.RawMessage `json:"d"`
	// Struct contains one of the other types in this file.
	Struct interface{} `json:"-"`
}

// A Ready stores all data for the websocket READY event.
type Ready struct {
	Version         int          `json:"v"`
	SessionID       string       `json:"session_id"`
	User            *User        `json:"user"`
	ReadState       []*ReadState `json:"read_state"`
	PrivateChannels []*Channel   `json:"private_channels"`
	Guilds          []*Guild     `json:"guilds"`

	// Undocumented fields
	Settings          *Settings            `json:"user_settings"`
	UserGuildSettings []*UserGuildSettings `json:"user_guild_settings"`
	Relationships     []*Relationship      `json:"relationships"`
	Presences         []*Presence          `json:"presences"`
	Notes             map[string]string    `json:"notes"`
}

// ChannelCreate is the data for a ChannelCreate event.
type ChannelCreate struct {
	*Channel
}

// ChannelUpdate is the data for a ChannelUpdate event.
type ChannelUpdate struct {
	*Channel
}

// ChannelDelete is the data for a ChannelDelete event.
type ChannelDelete struct {
	*Channel
}

// ChannelPinsUpdate stores data for a ChannelPinsUpdate event.
type ChannelPinsUpdate struct {
	LastPinTimestamp string `json:"last_pin_timestamp"`
	ChannelID        string `json:"channel_id"`
	GuildID          string `json:"guild_id,omitempty"`
}

// GuildCreate is the data for a GuildCreate event.
type GuildCreate struct {
	*Guild
}

// GuildUpdate is the data for a GuildUpdate event.
type GuildUpdate struct {
	*Guild
}

// GuildDelete is the data for a GuildDelete event.
type GuildDelete struct {
	*Guild
}

// GuildBanAdd is the data for a GuildBanAdd event.
type GuildBanAdd struct {
	User    *User  `json:"user"`
	GuildID string `json:"guild_id"`
}

// GuildBanRemove is the data for a GuildBanRemove event.
type GuildBanRemove struct {
	User    *User  `json:"user"`
	GuildID string `json:"guild_id"`
}

// GuildMemberAdd is the data for a GuildMemberAdd event.
type GuildMemberAdd struct {
	*Member
}

// GuildMemberUpdate is the data for a GuildMemberUpdate event.
type GuildMemberUpdate struct {
	*Member
}

// GuildMemberRemove is the data for a GuildMemberRemove event.
type GuildMemberRemove struct {
	*Member
}

// GuildRoleCreate is the data for a GuildRoleCreate event.
type GuildRoleCreate struct {
	*GuildRole
}

// GuildRoleUpdate is the data for a GuildRoleUpdate event.
type GuildRoleUpdate struct {
	*GuildRole
}

// A GuildRoleDelete is the data for a GuildRoleDelete event.
type GuildRoleDelete struct {
	RoleID  string `json:"role_id"`
	GuildID string `json:"guild_id"`
}

// A GuildEmojisUpdate is the data for a guild emoji update event.
type GuildEmojisUpdate struct {
	GuildID string   `json:"guild_id"`
	Emojis  []*Emoji `json:"emojis"`
}

// A GuildMembersChunk is the data for a GuildMembersChunk event.
type GuildMembersChunk struct {
	GuildID string    `json:"guild_id"`
	Members []*Member `json:"members"`
}

// GuildIntegrationsUpdate is the data for a GuildIntegrationsUpdate event.
type GuildIntegrationsUpdate struct {
	GuildID string `json:"guild_id"`
}

// MessageAck is the data for a MessageAck event.
type MessageAck struct {
	MessageID string `json:"message_id"`
	ChannelID string `json:"channel_id"`
}

// MessageCreate is the data for a MessageCreate event.
type MessageCreate struct {
	*Message
}

// MessageUpdate is the data for a MessageUpdate event.
type MessageUpdate struct {
	*Message
}

// MessageDelete is the data for a MessageDelete event.
type MessageDelete struct {
	*Message
}

// MessageReactionAdd is the data for a MessageReactionAdd event.
type MessageReactionAdd struct {
	*MessageReaction
}

// MessageReactionRemove is the data for a MessageReactionRemove event.
type MessageReactionRemove struct {
	*MessageReaction
}

// MessageReactionRemoveAll is the data for a MessageReactionRemoveAll event.
type MessageReactionRemoveAll struct {
	*MessageReaction
}

// PresencesReplace is the data for a PresencesReplace event.
type PresencesReplace []*Presence

// PresenceUpdate is the data for a PresenceUpdate event.
type PresenceUpdate struct {
	Presence
	GuildID string   `json:"guild_id"`
	Roles   []string `json:"roles"`
}

// Resumed is the data for a Resumed event.
type Resumed struct {
	Trace []string `json:"_trace"`
}

// RelationshipAdd is the data for a RelationshipAdd event.
type RelationshipAdd struct {
	*Relationship
}

// RelationshipRemove is the data for a RelationshipRemove event.
type RelationshipRemove struct {
	*Relationship
}

// TypingStart is the data for a TypingStart event.
type TypingStart struct {
	UserID    string `json:"user_id"`
	ChannelID string `json:"channel_id"`
	GuildID   string `json:"guild_id,omitempty"`
	Timestamp int    `json:"timestamp"`
}

// UserUpdate is the data for a UserUpdate event.
type UserUpdate struct {
	*User
}

// UserSettingsUpdate is the data for a UserSettingsUpdate event.
type UserSettingsUpdate map[string]interface{}

// UserGuildSettingsUpdate is the data for a UserGuildSettingsUpdate event.
type UserGuildSettingsUpdate struct {
	*UserGuildSettings
}

// UserNoteUpdate is the data for a UserNoteUpdate event.
type UserNoteUpdate struct {
	ID   string `json:"id"`
	Note string `json:"note"`
}

// VoiceServerUpdate is the data for a VoiceServerUpdate event.
type VoiceServerUpdate struct {
	Token    string `json:"token"`
	GuildID  string `json:"guild_id"`
	Endpoint string `json:"endpoint"`
}

// VoiceStateUpdate is the data for a VoiceStateUpdate event.
type VoiceStateUpdate struct {
	*VoiceState
}

// MessageDeleteBulk is the data for a MessageDeleteBulk event
type MessageDeleteBulk struct {
	Messages  []string `json:"ids"`
	ChannelID string   `json:"channel_id"`
	GuildID   string   `json:"guild_id"`
}

// WebhooksUpdate is the data for a WebhooksUpdate event
type WebhooksUpdate struct {
	GuildID   string `json:"guild_id"`
	ChannelID string `json:"channel_id"`
}
<commit_msg>Fix spelling of `synthetic` (#613)<commit_after>package discordgo

import (
	"encoding/json"
)

// This file contains all the possible structs that can be
// handled by AddHandler/EventHandler.
// DO NOT ADD ANYTHING BUT EVENT HANDLER STRUCTS TO THIS FILE.
//go:generate go run tools/cmd/eventhandlers/main.go

// Connect is the data for a Connect event.
// This is a synthetic event and is not dispatched by Discord.
type Connect struct{}

// Disconnect is the data for a Disconnect event.
// This is a synthetic event and is not dispatched by Discord.
type Disconnect struct{}

// RateLimit is the data for a RateLimit event.
// This is a synthetic event and is not dispatched by Discord.
type RateLimit struct {
	*TooManyRequests
	URL string
}

// Event provides a basic initial struct for all websocket events.
type Event struct {
	Operation int             `json:"op"`
	Sequence  int64           `json:"s"`
	Type      string          `json:"t"`
	RawData   json.RawMessage `json:"d"`
	// Struct contains one of the other types in this file.
	Struct interface{} `json:"-"`
}

// A Ready stores all data for the websocket READY event.
type Ready struct {
	Version         int          `json:"v"`
	SessionID       string       `json:"session_id"`
	User            *User        `json:"user"`
	ReadState       []*ReadState `json:"read_state"`
	PrivateChannels []*Channel   `json:"private_channels"`
	Guilds          []*Guild     `json:"guilds"`

	// Undocumented fields
	Settings          *Settings            `json:"user_settings"`
	UserGuildSettings []*UserGuildSettings `json:"user_guild_settings"`
	Relationships     []*Relationship      `json:"relationships"`
	Presences         []*Presence          `json:"presences"`
	Notes             map[string]string    `json:"notes"`
}

// ChannelCreate is the data for a ChannelCreate event.
type ChannelCreate struct {
	*Channel
}

// ChannelUpdate is the data for a ChannelUpdate event.
type ChannelUpdate struct {
	*Channel
}

// ChannelDelete is the data for a ChannelDelete event.
type ChannelDelete struct {
	*Channel
}

// ChannelPinsUpdate stores data for a ChannelPinsUpdate event.
type ChannelPinsUpdate struct {
	LastPinTimestamp string `json:"last_pin_timestamp"`
	ChannelID        string `json:"channel_id"`
	GuildID          string `json:"guild_id,omitempty"`
}

// GuildCreate is the data for a GuildCreate event.
type GuildCreate struct {
	*Guild
}

// GuildUpdate is the data for a GuildUpdate event.
type GuildUpdate struct {
	*Guild
}

// GuildDelete is the data for a GuildDelete event.
type GuildDelete struct {
	*Guild
}

// GuildBanAdd is the data for a GuildBanAdd event.
type GuildBanAdd struct {
	User    *User  `json:"user"`
	GuildID string `json:"guild_id"`
}

// GuildBanRemove is the data for a GuildBanRemove event.
type GuildBanRemove struct {
	User    *User  `json:"user"`
	GuildID string `json:"guild_id"`
}

// GuildMemberAdd is the data for a GuildMemberAdd event.
type GuildMemberAdd struct {
	*Member
}

// GuildMemberUpdate is the data for a GuildMemberUpdate event.
type GuildMemberUpdate struct {
	*Member
}

// GuildMemberRemove is the data for a GuildMemberRemove event.
type GuildMemberRemove struct {
	*Member
}

// GuildRoleCreate is the data for a GuildRoleCreate event.
type GuildRoleCreate struct {
	*GuildRole
}

// GuildRoleUpdate is the data for a GuildRoleUpdate event.
type GuildRoleUpdate struct {
	*GuildRole
}

// A GuildRoleDelete is the data for a GuildRoleDelete event.
type GuildRoleDelete struct {
	RoleID  string `json:"role_id"`
	GuildID string `json:"guild_id"`
}

// A GuildEmojisUpdate is the data for a guild emoji update event.
type GuildEmojisUpdate struct {
	GuildID string   `json:"guild_id"`
	Emojis  []*Emoji `json:"emojis"`
}

// A GuildMembersChunk is the data for a GuildMembersChunk event.
type GuildMembersChunk struct {
	GuildID string    `json:"guild_id"`
	Members []*Member `json:"members"`
}

// GuildIntegrationsUpdate is the data for a GuildIntegrationsUpdate event.
type GuildIntegrationsUpdate struct {
	GuildID string `json:"guild_id"`
}

// MessageAck is the data for a MessageAck event.
type MessageAck struct {
	MessageID string `json:"message_id"`
	ChannelID string `json:"channel_id"`
}

// MessageCreate is the data for a MessageCreate event.
type MessageCreate struct {
	*Message
}

// MessageUpdate is the data for a MessageUpdate event.
type MessageUpdate struct {
	*Message
}

// MessageDelete is the data for a MessageDelete event.
type MessageDelete struct {
	*Message
}

// MessageReactionAdd is the data for a MessageReactionAdd event.
type MessageReactionAdd struct {
	*MessageReaction
}

// MessageReactionRemove is the data for a MessageReactionRemove event.
type MessageReactionRemove struct {
	*MessageReaction
}

// MessageReactionRemoveAll is the data for a MessageReactionRemoveAll event.
type MessageReactionRemoveAll struct {
	*MessageReaction
}

// PresencesReplace is the data for a PresencesReplace event.
type PresencesReplace []*Presence

// PresenceUpdate is the data for a PresenceUpdate event.
type PresenceUpdate struct {
	Presence
	GuildID string   `json:"guild_id"`
	Roles   []string `json:"roles"`
}

// Resumed is the data for a Resumed event.
type Resumed struct {
	Trace []string `json:"_trace"`
}

// RelationshipAdd is the data for a RelationshipAdd event.
type RelationshipAdd struct {
	*Relationship
}

// RelationshipRemove is the data for a RelationshipRemove event.
type RelationshipRemove struct {
	*Relationship
}

// TypingStart is the data for a TypingStart event.
type TypingStart struct {
	UserID    string `json:"user_id"`
	ChannelID string `json:"channel_id"`
	GuildID   string `json:"guild_id,omitempty"`
	Timestamp int    `json:"timestamp"`
}

// UserUpdate is the data for a UserUpdate event.
type UserUpdate struct {
	*User
}

// UserSettingsUpdate is the data for a UserSettingsUpdate event.
type UserSettingsUpdate map[string]interface{}

// UserGuildSettingsUpdate is the data for a UserGuildSettingsUpdate event.
type UserGuildSettingsUpdate struct {
	*UserGuildSettings
}

// UserNoteUpdate is the data for a UserNoteUpdate event.
type UserNoteUpdate struct {
	ID   string `json:"id"`
	Note string `json:"note"`
}

// VoiceServerUpdate is the data for a VoiceServerUpdate event.
type VoiceServerUpdate struct {
	Token    string `json:"token"`
	GuildID  string `json:"guild_id"`
	Endpoint string `json:"endpoint"`
}

// VoiceStateUpdate is the data for a VoiceStateUpdate event.
type VoiceStateUpdate struct {
	*VoiceState
}

// MessageDeleteBulk is the data for a MessageDeleteBulk event
type MessageDeleteBulk struct {
	Messages  []string `json:"ids"`
	ChannelID string   `json:"channel_id"`
	GuildID   string   `json:"guild_id"`
}

// WebhooksUpdate is the data for a WebhooksUpdate event
type WebhooksUpdate struct {
	GuildID   string `json:"guild_id"`
	ChannelID string `json:"channel_id"`
}
<|endoftext|>


<commit_before>package dom

import (
	"time"

	"github.com/gopherjs/gopherjs/js"
)

func WrapEvent(o js.Object) Event {
	return wrapEvent(o)
}

func wrapEvent(o js.Object) Event {
	if o.IsNull() || o.IsUndefined() {
		return nil
	}
	ev := &BasicEvent{o}
	c := o.Get("constructor")
	switch c {
	case js.Global.Get("AnimationEvent"):
		return &AnimationEvent{ev}
	case js.Global.Get("AudioProcessingEvent"):
		return &AudioProcessingEvent{ev}
	case js.Global.Get("BeforeInputEvent"):
		return &BeforeInputEvent{ev}
	case js.Global.Get("BeforeUnloadEvent"):
		return &BeforeUnloadEvent{ev}
	case js.Global.Get("BlobEvent"):
		return &BlobEvent{ev}
	case js.Global.Get("ClipboardEvent"):
		return &ClipboardEvent{ev}
	case js.Global.Get("CloseEvent"):
		return &CloseEvent{BasicEvent: ev}
	case js.Global.Get("CompositionEvent"):
		return &CompositionEvent{ev}
	case js.Global.Get("CSSFontFaceLoadEvent"):
		return &CSSFontFaceLoadEvent{ev}
	case js.Global.Get("CustomEvent"):
		return &CustomEvent{ev}
	case js.Global.Get("DeviceLightEvent"):
		return &DeviceLightEvent{ev}
	case js.Global.Get("DeviceMotionEvent"):
		return &DeviceMotionEvent{ev}
	case js.Global.Get("DeviceOrientationEvent"):
		return &DeviceOrientationEvent{ev}
	case js.Global.Get("DeviceProximityEvent"):
		return &DeviceProximityEvent{ev}
	case js.Global.Get("DOMTransactionEvent"):
		return &DOMTransactionEvent{ev}
	case js.Global.Get("DragEvent"):
		return &DragEvent{ev}
	case js.Global.Get("EditingBeforeInputEvent"):
		return &EditingBeforeInputEvent{ev}
	case js.Global.Get("ErrorEvent"):
		return &ErrorEvent{ev}
	case js.Global.Get("FocusEvent"):
		return &FocusEvent{ev}
	case js.Global.Get("GamepadEvent"):
		return &GamepadEvent{ev}
	case js.Global.Get("HashChangeEvent"):
		return &HashChangeEvent{ev}
	case js.Global.Get("IDBVersionChangeEvent"):
		return &IDBVersionChangeEvent{ev}
	case js.Global.Get("KeyboardEvent"):
		return &KeyboardEvent{BasicEvent: ev}
	case js.Global.Get("MediaStreamEvent"):
		return &MediaStreamEvent{ev}
	case js.Global.Get("MessageEvent"):
		return &MessageEvent{ev}
	case js.Global.Get("MouseEvent"):
		return &MouseEvent{UIEvent: &UIEvent{ev}}
	case js.Global.Get("MutationEvent"):
		return &MutationEvent{ev}
	case js.Global.Get("OfflineAudioCompletionEvent"):
		return &OfflineAudioCompletionEvent{ev}
	case js.Global.Get("PageTransitionEvent"):
		return &PageTransitionEvent{ev}
	case js.Global.Get("PointerEvent"):
		return &PointerEvent{ev}
	case js.Global.Get("PopStateEvent"):
		return &PopStateEvent{ev}
	case js.Global.Get("ProgressEvent"):
		return &ProgressEvent{ev}
	case js.Global.Get("RelatedEvent"):
		return &RelatedEvent{ev}
	case js.Global.Get("RTCPeerConnectionIceEvent"):
		return &RTCPeerConnectionIceEvent{ev}
	case js.Global.Get("SensorEvent"):
		return &SensorEvent{ev}
	case js.Global.Get("StorageEvent"):
		return &StorageEvent{ev}
	case js.Global.Get("SVGEvent"):
		return &SVGEvent{ev}
	case js.Global.Get("SVGZoomEvent"):
		return &SVGZoomEvent{ev}
	case js.Global.Get("TimeEvent"):
		return &TimeEvent{ev}
	case js.Global.Get("TouchEvent"):
		return &TouchEvent{ev}
	case js.Global.Get("TrackEvent"):
		return &TrackEvent{ev}
	case js.Global.Get("TransitionEvent"):
		return &TransitionEvent{ev}
	case js.Global.Get("UIEvent"):
		return &UIEvent{ev}
	case js.Global.Get("UserProximityEvent"):
		return &UserProximityEvent{ev}
	case js.Global.Get("WheelEvent"):
		return &WheelEvent{BasicEvent: ev}
	default:
		return ev
	}
}

const (
	EvPhaseNone      = 0
	EvPhaseCapturing = 1
	EvPhaseAtTarget  = 2
	EvPhaseBubbling  = 3
)

type Event interface {
	Bubbles() bool
	Cancelable() bool
	CurrentTarget() Element
	DefaultPrevented() bool
	EventPhase() int
	Target() Element
	Timestamp() time.Time
	Type() string
	PreventDefault()
	StopImmediatePropagation()
	StopPropagation()
}

// Type BasicEvent implements the Event interface and is embedded by
// concrete event types.
type BasicEvent struct{ js.Object }

func (ev *BasicEvent) Bubbles() bool {
	return ev.Get("bubbles").Bool()
}

func (ev *BasicEvent) Cancelable() bool {
	return ev.Get("cancelable").Bool()
}

func (ev *BasicEvent) CurrentTarget() Element {
	return wrapElement(ev.Get("currentTarget"))
}

func (ev *BasicEvent) DefaultPrevented() bool {
	return ev.Get("defaultPrevented").Bool()
}

func (ev *BasicEvent) EventPhase() int {
	return ev.Get("eventPhase").Int()
}

func (ev *BasicEvent) Target() Element {
	return wrapElement(ev.Get("target"))
}

func (ev *BasicEvent) Timestamp() time.Time {
	ms := ev.Get("timeStamp").Int()
	s := ms / 1000
	ns := (ms % 1000 * 1e6)
	return time.Unix(int64(s), int64(ns))
}

func (ev *BasicEvent) Type() string {
	return ev.Get("type").Str()
}

func (ev *BasicEvent) PreventDefault() {
	ev.Call("preventDefault")
}

func (ev *BasicEvent) StopImmediatePropagation() {
	ev.Call("stopImmediatePropagation")
}

func (ev *BasicEvent) StopPropagation() {
	ev.Call("stopPropagation")
}

type AnimationEvent struct{ *BasicEvent }
type AudioProcessingEvent struct{ *BasicEvent }
type BeforeInputEvent struct{ *BasicEvent }
type BeforeUnloadEvent struct{ *BasicEvent }
type BlobEvent struct{ *BasicEvent }
type ClipboardEvent struct{ *BasicEvent }

type CloseEvent struct {
	*BasicEvent
	Code     int    `js:"code"`
	Reason   string `js:"reason"`
	WasClean bool   `js:"wasClean"`
}

type CompositionEvent struct{ *BasicEvent }
type CSSFontFaceLoadEvent struct{ *BasicEvent }
type CustomEvent struct{ *BasicEvent }
type DeviceLightEvent struct{ *BasicEvent }
type DeviceMotionEvent struct{ *BasicEvent }
type DeviceOrientationEvent struct{ *BasicEvent }
type DeviceProximityEvent struct{ *BasicEvent }
type DOMTransactionEvent struct{ *BasicEvent }
type DragEvent struct{ *BasicEvent }
type EditingBeforeInputEvent struct{ *BasicEvent }
type ErrorEvent struct{ *BasicEvent }
type FocusEvent struct{ *BasicEvent }
type GamepadEvent struct{ *BasicEvent }
type HashChangeEvent struct{ *BasicEvent }
type IDBVersionChangeEvent struct{ *BasicEvent }

const (
	KeyLocationStandard = 0
	KeyLocationLeft     = 1
	KeyLocationRight    = 2
	KeyLocationNumpad   = 3
)

type KeyboardEvent struct {
	*BasicEvent
	AltKey   bool   `js:"altKey"`
	CharCode int    `js:"charCode"`
	CtrlKey  bool   `js:"ctrlKey"`
	Key      string `js:"key"`
	Locale   string `js:"locale"`
	Location int    `js:"location"`
	MetaKey  bool   `js:"metaKey"`
	Repeat   bool   `js:"repeat"`
	ShiftKey bool   `js:"shiftKey"`
}

func (ev *KeyboardEvent) ModifierState(mod string) bool {
	return ev.Call("getModifierState", mod).Bool()
}

type MediaStreamEvent struct{ *BasicEvent }
type MessageEvent struct{ *BasicEvent }

type MouseEvent struct {
	*UIEvent
	AltKey    bool `js:"altKey"`
	Button    int  `js:"button"`
	ClientX   int  `js:"clientX"`
	ClientY   int  `js:"clientY"`
	CtrlKey   bool `js:"ctrlKey"`
	MetaKey   bool `js:"metaKey"`
	MovementX int  `js:"movementX"`
	MovementY int  `js:"movementY"`
	ScreenX   int  `js:"screenX"`
	ScreenY   int  `js:"screenY"`
	ShiftKey  bool `js:"shiftKey"`
}

func (ev *MouseEvent) RelatedTarget() Element {
	return wrapElement(ev.Get("target"))
}

func (ev *MouseEvent) ModifierState(mod string) bool {
	return ev.Call("getModifierState", mod).Bool()
}

type MutationEvent struct{ *BasicEvent }
type OfflineAudioCompletionEvent struct{ *BasicEvent }
type PageTransitionEvent struct{ *BasicEvent }
type PointerEvent struct{ *BasicEvent }
type PopStateEvent struct{ *BasicEvent }
type ProgressEvent struct{ *BasicEvent }
type RelatedEvent struct{ *BasicEvent }
type RTCPeerConnectionIceEvent struct{ *BasicEvent }
type SensorEvent struct{ *BasicEvent }
type StorageEvent struct{ *BasicEvent }
type SVGEvent struct{ *BasicEvent }
type SVGZoomEvent struct{ *BasicEvent }
type TimeEvent struct{ *BasicEvent }
type TouchEvent struct{ *BasicEvent }
type TrackEvent struct{ *BasicEvent }
type TransitionEvent struct{ *BasicEvent }
type UIEvent struct{ *BasicEvent }
type UserProximityEvent struct{ *BasicEvent }

const (
	DeltaPixel = 0
	DeltaLine  = 1
	DeltaPage  = 2
)

type WheelEvent struct {
	*BasicEvent
	DeltaX    float64 `js:"deltaX"`
	DeltaY    float64 `js:"deltaY"`
	DeltaZ    float64 `js:"deltaZ"`
	DeltaMode int     `js:"deltaMode"`
}

type EventTarget interface {
	// AddEventListener adds a new event listener and returns the
	// wrapper function it generated. If using RemoveEventListener,
	// that wrapper has to be used.
	AddEventListener(typ string, useCapture bool, listener func(Event)) func(js.Object)
	RemoveEventListener(typ string, useCapture bool, listener func(js.Object))
	// DispatchEvent() // TODO
}
<commit_msg>add Data attribute to MessageEvent<commit_after>package dom

import (
	"time"

	"github.com/gopherjs/gopherjs/js"
)

func WrapEvent(o js.Object) Event {
	return wrapEvent(o)
}

func wrapEvent(o js.Object) Event {
	if o.IsNull() || o.IsUndefined() {
		return nil
	}
	ev := &BasicEvent{o}
	c := o.Get("constructor")
	switch c {
	case js.Global.Get("AnimationEvent"):
		return &AnimationEvent{ev}
	case js.Global.Get("AudioProcessingEvent"):
		return &AudioProcessingEvent{ev}
	case js.Global.Get("BeforeInputEvent"):
		return &BeforeInputEvent{ev}
	case js.Global.Get("BeforeUnloadEvent"):
		return &BeforeUnloadEvent{ev}
	case js.Global.Get("BlobEvent"):
		return &BlobEvent{ev}
	case js.Global.Get("ClipboardEvent"):
		return &ClipboardEvent{ev}
	case js.Global.Get("CloseEvent"):
		return &CloseEvent{BasicEvent: ev}
	case js.Global.Get("CompositionEvent"):
		return &CompositionEvent{ev}
	case js.Global.Get("CSSFontFaceLoadEvent"):
		return &CSSFontFaceLoadEvent{ev}
	case js.Global.Get("CustomEvent"):
		return &CustomEvent{ev}
	case js.Global.Get("DeviceLightEvent"):
		return &DeviceLightEvent{ev}
	case js.Global.Get("DeviceMotionEvent"):
		return &DeviceMotionEvent{ev}
	case js.Global.Get("DeviceOrientationEvent"):
		return &DeviceOrientationEvent{ev}
	case js.Global.Get("DeviceProximityEvent"):
		return &DeviceProximityEvent{ev}
	case js.Global.Get("DOMTransactionEvent"):
		return &DOMTransactionEvent{ev}
	case js.Global.Get("DragEvent"):
		return &DragEvent{ev}
	case js.Global.Get("EditingBeforeInputEvent"):
		return &EditingBeforeInputEvent{ev}
	case js.Global.Get("ErrorEvent"):
		return &ErrorEvent{ev}
	case js.Global.Get("FocusEvent"):
		return &FocusEvent{ev}
	case js.Global.Get("GamepadEvent"):
		return &GamepadEvent{ev}
	case js.Global.Get("HashChangeEvent"):
		return &HashChangeEvent{ev}
	case js.Global.Get("IDBVersionChangeEvent"):
		return &IDBVersionChangeEvent{ev}
	case js.Global.Get("KeyboardEvent"):
		return &KeyboardEvent{BasicEvent: ev}
	case js.Global.Get("MediaStreamEvent"):
		return &MediaStreamEvent{ev}
	case js.Global.Get("MessageEvent"):
		return &MessageEvent{BasicEvent: ev}
	case js.Global.Get("MouseEvent"):
		return &MouseEvent{UIEvent: &UIEvent{ev}}
	case js.Global.Get("MutationEvent"):
		return &MutationEvent{ev}
	case js.Global.Get("OfflineAudioCompletionEvent"):
		return &OfflineAudioCompletionEvent{ev}
	case js.Global.Get("PageTransitionEvent"):
		return &PageTransitionEvent{ev}
	case js.Global.Get("PointerEvent"):
		return &PointerEvent{ev}
	case js.Global.Get("PopStateEvent"):
		return &PopStateEvent{ev}
	case js.Global.Get("ProgressEvent"):
		return &ProgressEvent{ev}
	case js.Global.Get("RelatedEvent"):
		return &RelatedEvent{ev}
	case js.Global.Get("RTCPeerConnectionIceEvent"):
		return &RTCPeerConnectionIceEvent{ev}
	case js.Global.Get("SensorEvent"):
		return &SensorEvent{ev}
	case js.Global.Get("StorageEvent"):
		return &StorageEvent{ev}
	case js.Global.Get("SVGEvent"):
		return &SVGEvent{ev}
	case js.Global.Get("SVGZoomEvent"):
		return &SVGZoomEvent{ev}
	case js.Global.Get("TimeEvent"):
		return &TimeEvent{ev}
	case js.Global.Get("TouchEvent"):
		return &TouchEvent{ev}
	case js.Global.Get("TrackEvent"):
		return &TrackEvent{ev}
	case js.Global.Get("TransitionEvent"):
		return &TransitionEvent{ev}
	case js.Global.Get("UIEvent"):
		return &UIEvent{ev}
	case js.Global.Get("UserProximityEvent"):
		return &UserProximityEvent{ev}
	case js.Global.Get("WheelEvent"):
		return &WheelEvent{BasicEvent: ev}
	default:
		return ev
	}
}

const (
	EvPhaseNone      = 0
	EvPhaseCapturing = 1
	EvPhaseAtTarget  = 2
	EvPhaseBubbling  = 3
)

type Event interface {
	Bubbles() bool
	Cancelable() bool
	CurrentTarget() Element
	DefaultPrevented() bool
	EventPhase() int
	Target() Element
	Timestamp() time.Time
	Type() string
	PreventDefault()
	StopImmediatePropagation()
	StopPropagation()
}

// Type BasicEvent implements the Event interface and is embedded by
// concrete event types.
type BasicEvent struct{ js.Object }

func (ev *BasicEvent) Bubbles() bool {
	return ev.Get("bubbles").Bool()
}

func (ev *BasicEvent) Cancelable() bool {
	return ev.Get("cancelable").Bool()
}

func (ev *BasicEvent) CurrentTarget() Element {
	return wrapElement(ev.Get("currentTarget"))
}

func (ev *BasicEvent) DefaultPrevented() bool {
	return ev.Get("defaultPrevented").Bool()
}

func (ev *BasicEvent) EventPhase() int {
	return ev.Get("eventPhase").Int()
}

func (ev *BasicEvent) Target() Element {
	return wrapElement(ev.Get("target"))
}

func (ev *BasicEvent) Timestamp() time.Time {
	ms := ev.Get("timeStamp").Int()
	s := ms / 1000
	ns := (ms % 1000 * 1e6)
	return time.Unix(int64(s), int64(ns))
}

func (ev *BasicEvent) Type() string {
	return ev.Get("type").Str()
}

func (ev *BasicEvent) PreventDefault() {
	ev.Call("preventDefault")
}

func (ev *BasicEvent) StopImmediatePropagation() {
	ev.Call("stopImmediatePropagation")
}

func (ev *BasicEvent) StopPropagation() {
	ev.Call("stopPropagation")
}

type AnimationEvent struct{ *BasicEvent }
type AudioProcessingEvent struct{ *BasicEvent }
type BeforeInputEvent struct{ *BasicEvent }
type BeforeUnloadEvent struct{ *BasicEvent }
type BlobEvent struct{ *BasicEvent }
type ClipboardEvent struct{ *BasicEvent }

type CloseEvent struct {
	*BasicEvent
	Code     int    `js:"code"`
	Reason   string `js:"reason"`
	WasClean bool   `js:"wasClean"`
}

type CompositionEvent struct{ *BasicEvent }
type CSSFontFaceLoadEvent struct{ *BasicEvent }
type CustomEvent struct{ *BasicEvent }
type DeviceLightEvent struct{ *BasicEvent }
type DeviceMotionEvent struct{ *BasicEvent }
type DeviceOrientationEvent struct{ *BasicEvent }
type DeviceProximityEvent struct{ *BasicEvent }
type DOMTransactionEvent struct{ *BasicEvent }
type DragEvent struct{ *BasicEvent }
type EditingBeforeInputEvent struct{ *BasicEvent }
type ErrorEvent struct{ *BasicEvent }
type FocusEvent struct{ *BasicEvent }
type GamepadEvent struct{ *BasicEvent }
type HashChangeEvent struct{ *BasicEvent }
type IDBVersionChangeEvent struct{ *BasicEvent }

const (
	KeyLocationStandard = 0
	KeyLocationLeft     = 1
	KeyLocationRight    = 2
	KeyLocationNumpad   = 3
)

type KeyboardEvent struct {
	*BasicEvent
	AltKey   bool   `js:"altKey"`
	CharCode int    `js:"charCode"`
	CtrlKey  bool   `js:"ctrlKey"`
	Key      string `js:"key"`
	Locale   string `js:"locale"`
	Location int    `js:"location"`
	MetaKey  bool   `js:"metaKey"`
	Repeat   bool   `js:"repeat"`
	ShiftKey bool   `js:"shiftKey"`
}

func (ev *KeyboardEvent) ModifierState(mod string) bool {
	return ev.Call("getModifierState", mod).Bool()
}

type MediaStreamEvent struct{ *BasicEvent }

type MessageEvent struct {
	*BasicEvent
	Data js.Object `js:"data"`
}

type MouseEvent struct {
	*UIEvent
	AltKey    bool `js:"altKey"`
	Button    int  `js:"button"`
	ClientX   int  `js:"clientX"`
	ClientY   int  `js:"clientY"`
	CtrlKey   bool `js:"ctrlKey"`
	MetaKey   bool `js:"metaKey"`
	MovementX int  `js:"movementX"`
	MovementY int  `js:"movementY"`
	ScreenX   int  `js:"screenX"`
	ScreenY   int  `js:"screenY"`
	ShiftKey  bool `js:"shiftKey"`
}

func (ev *MouseEvent) RelatedTarget() Element {
	return wrapElement(ev.Get("target"))
}

func (ev *MouseEvent) ModifierState(mod string) bool {
	return ev.Call("getModifierState", mod).Bool()
}

type MutationEvent struct{ *BasicEvent }
type OfflineAudioCompletionEvent struct{ *BasicEvent }
type PageTransitionEvent struct{ *BasicEvent }
type PointerEvent struct{ *BasicEvent }
type PopStateEvent struct{ *BasicEvent }
type ProgressEvent struct{ *BasicEvent }
type RelatedEvent struct{ *BasicEvent }
type RTCPeerConnectionIceEvent struct{ *BasicEvent }
type SensorEvent struct{ *BasicEvent }
type StorageEvent struct{ *BasicEvent }
type SVGEvent struct{ *BasicEvent }
type SVGZoomEvent struct{ *BasicEvent }
type TimeEvent struct{ *BasicEvent }
type TouchEvent struct{ *BasicEvent }
type TrackEvent struct{ *BasicEvent }
type TransitionEvent struct{ *BasicEvent }
type UIEvent struct{ *BasicEvent }
type UserProximityEvent struct{ *BasicEvent }

const (
	DeltaPixel = 0
	DeltaLine  = 1
	DeltaPage  = 2
)

type WheelEvent struct {
	*BasicEvent
	DeltaX    float64 `js:"deltaX"`
	DeltaY    float64 `js:"deltaY"`
	DeltaZ    float64 `js:"deltaZ"`
	DeltaMode int     `js:"deltaMode"`
}

type EventTarget interface {
	// AddEventListener adds a new event listener and returns the
	// wrapper function it generated. If using RemoveEventListener,
	// that wrapper has to be used.
	AddEventListener(typ string, useCapture bool, listener func(Event)) func(js.Object)
	RemoveEventListener(typ string, useCapture bool, listener func(js.Object))
	// DispatchEvent() // TODO
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Xuyuan Pang
 * Author: Xuyuan Pang
 *
 * 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 hodor

import (
	"log"
	"net/http"
	"time"
)

// Filter interface
type Filter interface {
	Do(http.Handler) http.Handler
}

// FilterFunc type
type FilterFunc func(next http.Handler) http.Handler

// Do calls FilterFunc
func (f FilterFunc) Do(next http.Handler) http.Handler {
	return f(next)
}

var emptyFilter FilterFunc = func(next http.Handler) http.Handler {
	return next
}

// MergeFilters merges multi fileers into a single one.
func MergeFilters(filters ...Filter) Filter {
	return FilterFunc(
		func(next http.Handler) http.Handler {
			for i := len(filters) - 1; i >= 0; i-- {
				next = filters[i].Do(next)
			}
			return next
		})
}

// LogFilter new filter
func LogFilter(l *log.Logger) FilterFunc {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(
			func(w http.ResponseWriter, r *http.Request) {
				start := time.Now()
				l.Printf("%s %s", r.Method, r.RemoteAddr)
				next.ServeHTTP(w, r)
				status := w.(ResponseWriter).Status()
				l.Printf("%d %s %s", status, http.StatusText(status), time.Since(start))
			})
	}
}
<commit_msg>Added RecoveryFilter<commit_after>/*
 * Copyright 2016 Xuyuan Pang
 * Author: Xuyuan Pang
 *
 * 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 hodor

import (
	"net/http"
	"runtime"
	"time"
)

// Filter interface
type Filter interface {
	Do(http.Handler) http.Handler
}

// FilterFunc type
type FilterFunc func(next http.Handler) http.Handler

// Do calls FilterFunc
func (f FilterFunc) Do(next http.Handler) http.Handler {
	return f(next)
}

var emptyFilter FilterFunc = func(next http.Handler) http.Handler {
	return next
}

// MergeFilters merges multi fileers into a single one.
func MergeFilters(filters ...Filter) Filter {
	return FilterFunc(
		func(next http.Handler) http.Handler {
			for i := len(filters) - 1; i >= 0; i-- {
				next = filters[i].Do(next)
			}
			return next
		})
}

// Logger interface
type Logger interface {
	Printf(string, ...interface{})
}

// LogFilter new filter
func LogFilter(l Logger) FilterFunc {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(
			func(w http.ResponseWriter, r *http.Request) {
				start := time.Now()
				l.Printf("%s %s", r.Method, r.RemoteAddr)
				next.ServeHTTP(w, r)
				status := w.(ResponseWriter).Status()
				l.Printf("%d %s %s", status, http.StatusText(status), time.Since(start))
			})
	}
}

func RecoveryFilter(l Logger) FilterFunc {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(
			func(w http.ResponseWriter, r *http.Request) {
				defer func() {
					if err := recover(); err != nil {
						trace := make([]byte, 1<<16)
						n := runtime.Stack(trace, true)
						stack := trace[:n]
						l.Printf("PANIC: %v\n%s", err, stack)
						http.Error(w, http.StatusText(http.StatusInternalServerError),
							http.StatusInternalServerError)
					}
				}()
				next.ServeHTTP(w, r)
			})
	}
}
<|endoftext|>


<commit_before>package main

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

	"github.com/codegangsta/cli"
	"github.com/docker/docker/daemon/graphdriver"
	"github.com/docker/docker/graph"
	"github.com/docker/docker/image"
)

func listLayer(img *image.Image, tags *map[string][]string) {
	fmt.Printf("%s", img.ID[:12])
	if tags != nil {
		if taglist, ok := (*tags)[img.ID]; ok {
			for i, tag := range taglist {
				if i > 0 {
					fmt.Printf(",")
				} else {
					fmt.Printf("\t")
				}
				fmt.Printf("%s", tag)
			}
		}
	}
	fmt.Printf("\n")
}

func initDriver(c *cli.Context) graphdriver.Driver {
	graphdriver.DefaultDriver = c.GlobalString("driver")
	if graphdriver.DefaultDriver == "" {
		fmt.Printf("No graphdriver specified.\n")
		os.Exit(1)
	}
	homedir := filepath.Join(c.GlobalString("home"))
	drv, err := graphdriver.New(homedir, c.GlobalStringSlice("storage-opt"))
	if err != nil {
		fmt.Printf("Failed to instantiate graphdriver: %s\n", err)
		os.Exit(1)
	}
	if c.GlobalBool("debug") {
		fmt.Printf("[DEBUG] Using driver %s.\n[DEBUG] %g\n[DEBUG] Home directory: %s\n", drv.String(), drv.Status(), homedir)
	}
	return drv
}

func initGraph(c *cli.Context) (*graph.Graph, graphdriver.Driver) {
	drv := initDriver(c)
	homedir := filepath.Join(c.GlobalString("home"), "graph")
	g, err := graph.NewGraph(homedir, drv)
	if err != nil {
		fmt.Printf("Failed to instantiate graph: %s\n", err)
		os.Exit(1)
	}
	return g, drv
}

func initTagStore(c *cli.Context) (*graph.TagStore, *graph.Graph, graphdriver.Driver) {
	g, d := initGraph(c)
	tsfile := filepath.Join(c.GlobalString("home"), "repositories-"+c.GlobalString("driver"))
	config := graph.TagStoreConfig{
		Graph: g,
	}
	t, err := graph.NewTagStore(tsfile, &config)
	if err != nil {
		fmt.Printf("Failed to instantiate tag store: %s\n", err)
		os.Exit(1)
	}
	return t, g, d
}

var commands []cli.Command

func main() {
	graphc := cli.NewApp()
	graphc.Name = "graphc"
	graphc.Usage = "manage graphc storage"
	graphc.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "home",
			Value:  "/var/lib/docker/",
			Usage:  "home directory for graphdriver storage operations",
			EnvVar: "GRAPHDRIVER_HOME",
		},
		cli.StringFlag{
			Name:   "driver, s",
			Value:  "",
			Usage:  "storage driver to use",
			EnvVar: "GRAPHDRIVER_BACKEND",
		},
		cli.StringSliceFlag{
			Name:   "storage-opt",
			Value:  &cli.StringSlice{},
			Usage:  "set storage driver options",
			EnvVar: "GRAPHDRIVER_OPTIONS",
		},
		cli.StringFlag{
			Name:  "context, c",
			Value: "",
			Usage: "optional mountlabel (SELinux context)",
		},
		cli.BoolFlag{
			Name:  "debug, D",
			Usage: "print debugging information",
		},
	}
	graphc.EnableBashCompletion = true
	graphc.Commands = commands

	graphc.Run(os.Args)

	os.Exit(0)
}
<commit_msg>Debug log the number of images<commit_after>package main

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

	"github.com/codegangsta/cli"
	"github.com/docker/docker/daemon/graphdriver"
	"github.com/docker/docker/graph"
	"github.com/docker/docker/image"
)

func listLayer(img *image.Image, tags *map[string][]string) {
	fmt.Printf("%s", img.ID[:12])
	if tags != nil {
		if taglist, ok := (*tags)[img.ID]; ok {
			for i, tag := range taglist {
				if i > 0 {
					fmt.Printf(",")
				} else {
					fmt.Printf("\t")
				}
				fmt.Printf("%s", tag)
			}
		}
	}
	fmt.Printf("\n")
}

func initDriver(c *cli.Context) graphdriver.Driver {
	graphdriver.DefaultDriver = c.GlobalString("driver")
	if graphdriver.DefaultDriver == "" {
		fmt.Printf("No graphdriver specified.\n")
		os.Exit(1)
	}
	homedir := filepath.Join(c.GlobalString("home"))
	drv, err := graphdriver.New(homedir, c.GlobalStringSlice("storage-opt"))
	if err != nil {
		fmt.Printf("Failed to instantiate graphdriver: %s\n", err)
		os.Exit(1)
	}
	if c.GlobalBool("debug") {
		fmt.Printf("[DEBUG] Using driver %s.\n[DEBUG] %g\n[DEBUG] Home directory: %s\n", drv.String(), drv.Status(), homedir)
	}
	return drv
}

func initGraph(c *cli.Context) (*graph.Graph, graphdriver.Driver) {
	drv := initDriver(c)
	homedir := filepath.Join(c.GlobalString("home"), "graph")
	g, err := graph.NewGraph(homedir, drv)
	if err != nil {
		fmt.Printf("Failed to instantiate graph: %s\n", err)
		os.Exit(1)
	}
	if c.GlobalBool("debug") {
		fmt.Printf("[DEBUG] %d images.\n", len(g.Map()))
	}
	return g, drv
}

func initTagStore(c *cli.Context) (*graph.TagStore, *graph.Graph, graphdriver.Driver) {
	g, d := initGraph(c)
	tsfile := filepath.Join(c.GlobalString("home"), "repositories-"+c.GlobalString("driver"))
	config := graph.TagStoreConfig{
		Graph: g,
	}
	t, err := graph.NewTagStore(tsfile, &config)
	if err != nil {
		fmt.Printf("Failed to instantiate tag store: %s\n", err)
		os.Exit(1)
	}
	return t, g, d
}

var commands []cli.Command

func main() {
	graphc := cli.NewApp()
	graphc.Name = "graphc"
	graphc.Usage = "manage graphc storage"
	graphc.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "home",
			Value:  "/var/lib/docker/",
			Usage:  "home directory for graphdriver storage operations",
			EnvVar: "GRAPHDRIVER_HOME",
		},
		cli.StringFlag{
			Name:   "driver, s",
			Value:  "",
			Usage:  "storage driver to use",
			EnvVar: "GRAPHDRIVER_BACKEND",
		},
		cli.StringSliceFlag{
			Name:   "storage-opt",
			Value:  &cli.StringSlice{},
			Usage:  "set storage driver options",
			EnvVar: "GRAPHDRIVER_OPTIONS",
		},
		cli.StringFlag{
			Name:  "context, c",
			Value: "",
			Usage: "optional mountlabel (SELinux context)",
		},
		cli.BoolFlag{
			Name:  "debug, D",
			Usage: "print debugging information",
		},
	}
	graphc.EnableBashCompletion = true
	graphc.Commands = commands

	graphc.Run(os.Args)

	os.Exit(0)
}
<|endoftext|>