<commit_before>/*
 * Copyright (c) 2011 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package fft

import (
	"math"
)

func Fft(x []float64) []complex128 {
	lx := len(x)

	// expand a length of a power of 2
	if lx & (lx - 1) != 0 { // not a power of 2
		nl := int(math.Pow(2, math.Ceil(math.Log2(float64(lx)))))
		nx := make([]float64, nl)
		copy(nx, x)
		for i := 0; i < nl - lx; i++ {
			nx[i + lx] = 0
		}
		x = nx[:]
		lx = nl
	}

	lx_2 := lx / 2

	r := make([]complex128, lx) // result
	t := make([]complex128, lx) // temp
	w := make([]complex128, lx_2)
	w[0] = complex(1, 0)

	// split into event and odd parts
	for n := 0; n < lx_2; n++ {
		r[n] = complex(x[n * 2], 0)
		r[n + lx_2] = complex(x[n * 2 + 1], 0)
	}

	for i := 0; i < int(math.Log2(float64(lx))); i++ {
		stage := 1 << uint(i + 1)

		// 2-point transforms
		if i == 0 {
			for n := 0; n < lx_2; n++ {
				t[n * 2] = r[n * 2] + r[n * 2 + 1]
				t[n * 2 + 1] = r[n * 2] - r[n * 2 + 1]
			}
		// >2-point transforms
		} else {
			blocks := lx / stage
			s_2 := stage / 2

			for j := 1; j < s_2; j++ {
				if j * 4 == stage {
					w[j] = complex(0, -1)
				} else {
					sin, cos := math.Sincos(-2 * math.Pi / float64(stage) * float64(j))
					w[j] = complex(cos, sin)
				}
			}

			for n := 0; n < blocks; n++ {
				nb := n * stage
				for j := 0; j < s_2; j++ {
					w_n := r[j + nb + s_2] * w[j]
					t[j + nb      ] = r[j + nb] + w_n
					t[j + nb + s_2] = r[j + nb] - w_n
				}
			}
		}

		copy(r, t)
	}

	return r
}
<commit_msg>Fix typo<commit_after>/*
 * Copyright (c) 2011 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package fft

import (
	"math"
)

func Fft(x []float64) []complex128 {
	lx := len(x)

	// expand a length of a power of 2
	if lx & (lx - 1) != 0 { // not a power of 2
		nl := int(math.Pow(2, math.Ceil(math.Log2(float64(lx)))))
		nx := make([]float64, nl)
		copy(nx, x)
		for i := 0; i < nl - lx; i++ {
			nx[i + lx] = 0
		}
		x = nx[:]
		lx = nl
	}

	lx_2 := lx / 2

	r := make([]complex128, lx) // result
	t := make([]complex128, lx) // temp
	w := make([]complex128, lx_2)
	w[0] = complex(1, 0)

	// split into even and odd parts
	for n := 0; n < lx_2; n++ {
		r[n] = complex(x[n * 2], 0)
		r[n + lx_2] = complex(x[n * 2 + 1], 0)
	}

	for i := 0; i < int(math.Log2(float64(lx))); i++ {
		stage := 1 << uint(i + 1)

		// 2-point transforms
		if i == 0 {
			for n := 0; n < lx_2; n++ {
				t[n * 2] = r[n * 2] + r[n * 2 + 1]
				t[n * 2 + 1] = r[n * 2] - r[n * 2 + 1]
			}
		// >2-point transforms
		} else {
			blocks := lx / stage
			s_2 := stage / 2

			for j := 1; j < s_2; j++ {
				if j * 4 == stage {
					w[j] = complex(0, -1)
				} else {
					sin, cos := math.Sincos(-2 * math.Pi / float64(stage) * float64(j))
					w[j] = complex(cos, sin)
				}
			}

			for n := 0; n < blocks; n++ {
				nb := n * stage
				for j := 0; j < s_2; j++ {
					w_n := r[j + nb + s_2] * w[j]
					t[j + nb      ] = r[j + nb] + w_n
					t[j + nb + s_2] = r[j + nb] - w_n
				}
			}
		}

		copy(r, t)
	}

	return r
}
<|endoftext|>


<commit_before>// Copyright 2016 Tim Heckman. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

// Package fsm is a simple finite state machine in Go. This state machine is
// safe for concurrent use, so multiple goroutines can work with the machine
// safely.
package fsm

import (
	"fmt"
	"sync"
)

// Version is the semantic version (SemVer) string.
const Version = "0.0.2"

// State is the machine state. It's really just a string.
type State string

// TransitionRuleSet is a set of allowed transitions. This uses map of struct{}
// to implement a set.
type TransitionRuleSet map[State]struct{}

// Copy copies the TransitionRuleSet in to a different TransitionRuleSet.
func (trs TransitionRuleSet) Copy() TransitionRuleSet {
	srt := make(TransitionRuleSet)

	for rule, value := range trs {
		srt[rule] = value
	}

	return srt
}

// CallbackHandler is an interface type defining the interface for receiving callbacks.
type CallbackHandler interface {
	StateTransitionCallback(State) error
}

// Machine is the state machine.
type Machine struct {
	state State
	mu    sync.RWMutex

	transitions map[State]TransitionRuleSet
	rules       map[State]map[State]State

	callback     CallbackHandler
	syncCallback bool
}

// CurrentState returns the machine's current state. If the State returned is
// "", then the machine has not been given an initial state.
func (m *Machine) CurrentState() State {
	m.mu.RLock()
	defer m.mu.RUnlock()

	return m.state
}

// StateTransitionRules returns the allowed states for
func (m *Machine) StateTransitionRules(state State) (TransitionRuleSet, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	if m.transitions == nil {
		return nil, newErrorStruct("the machine has not been fully initialized", ErrorMachineNotInitialized)
	}

	// ensure the state has been registered
	if _, ok := m.transitions[state]; !ok {
		return nil, newErrorStruct(fmt.Sprintf("state %s has not been registered", state), ErrorStateUndefined)
	}

	return m.transitions[state].Copy(), nil
}

// AddStateTransitionRules is a function for adding valid state transitions to the machine.
// This allows you to define which states any given state can be transitioned to.
func (m *Machine) AddStateTransitionRules(sourceState State, destinationStates ...State) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	// if the transitions map is nil, we need to allocate it
	if m.transitions == nil {
		m.transitions = make(map[State]TransitionRuleSet)
	}

	// if the map for the source state does not exist, allocate it
	if m.transitions[sourceState] == nil {
		m.transitions[sourceState] = make(TransitionRuleSet)
	}

	// get a reference to the map we care about
	// avoids doing the map lookup for each iteration
	mp := m.transitions[sourceState]

	for _, dest := range destinationStates {
		mp[dest] = struct{}{}
	}

	return nil
}

// SetStateTransitionCallback for the state transition. This is meant to send
// callbacks back to the consumer for state changes. The callback only sends the
// new state. The synchonous parameter indicates whether the callback is done
// synchronously with the StateTransition() call.
func (m *Machine) SetStateTransitionCallback(callback CallbackHandler, synchronous bool) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	m.callback = callback
	m.syncCallback = synchronous

	return nil
}

// StateTransition triggers a transition to the toState. This function is also
// used to set the initial state of machine.
//
// Before you can transition to any state, even for the initial, you must define
// it with AddStateTransition(). If you are setting the initial state, and that
// state is not define, this will return an ErrInvalidInitialState error.
//
// When transitioning from a state, this function will return an error either
// if the state transition is not allowed, or if the destination state has
// not been defined. In both cases, it's seen as a non-permitted state transition.
func (m *Machine) StateTransition(toState State) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	// if this is nil we cannot assume any state
	if m.transitions == nil {
		return newErrorStruct("the machine has no states added", ErrorMachineNotInitialized)
	}

	// if the state is nothing, this is probably the initial state
	if m.state == "" {
		// if the state is not defined, it's invalid
		if _, ok := m.transitions[toState]; !ok {
			return newErrorStruct("the initial state has not been defined within the machine", ErrorStateUndefined)
		}

		// set the state
		m.state = toState
		return nil
	}

	// if we are not permitted to transition to this state...
	if _, ok := m.transitions[m.state][toState]; !ok {
		return newErrorStruct(fmt.Sprintf("transition from state %s to %s is not permitted", m.state, toState), ErrorTransitionNotPermitted)
	}

	// if the destination state was not defined...
	if _, ok := m.transitions[toState]; !ok {
		return newErrorStruct(fmt.Sprintf("state %s has not been registered", toState), ErrorStateUndefined)
	}

	m.state = toState

	if m.callback != nil {
		if m.syncCallback {
			// do not return the error
			// this may be reconsidered
			m.callback.StateTransitionCallback(toState)
		} else {
			// spin off the callback
			go func() { m.callback.StateTransitionCallback(toState) }()
		}
	}

	return nil
}
<commit_msg>remove unused rules field<commit_after>// Copyright 2016 Tim Heckman. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

// Package fsm is a simple finite state machine in Go. This state machine is
// safe for concurrent use, so multiple goroutines can work with the machine
// safely.
package fsm

import (
	"fmt"
	"sync"
)

// Version is the semantic version (SemVer) string.
const Version = "0.0.2"

// State is the machine state. It's really just a string.
type State string

// TransitionRuleSet is a set of allowed transitions. This uses map of struct{}
// to implement a set.
type TransitionRuleSet map[State]struct{}

// Copy copies the TransitionRuleSet in to a different TransitionRuleSet.
func (trs TransitionRuleSet) Copy() TransitionRuleSet {
	srt := make(TransitionRuleSet)

	for rule, value := range trs {
		srt[rule] = value
	}

	return srt
}

// CallbackHandler is an interface type defining the interface for receiving callbacks.
type CallbackHandler interface {
	StateTransitionCallback(State) error
}

// Machine is the state machine.
type Machine struct {
	state State
	mu    sync.RWMutex

	transitions map[State]TransitionRuleSet

	callback     CallbackHandler
	syncCallback bool
}

// CurrentState returns the machine's current state. If the State returned is
// "", then the machine has not been given an initial state.
func (m *Machine) CurrentState() State {
	m.mu.RLock()
	defer m.mu.RUnlock()

	return m.state
}

// StateTransitionRules returns the allowed states for
func (m *Machine) StateTransitionRules(state State) (TransitionRuleSet, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	if m.transitions == nil {
		return nil, newErrorStruct("the machine has not been fully initialized", ErrorMachineNotInitialized)
	}

	// ensure the state has been registered
	if _, ok := m.transitions[state]; !ok {
		return nil, newErrorStruct(fmt.Sprintf("state %s has not been registered", state), ErrorStateUndefined)
	}

	return m.transitions[state].Copy(), nil
}

// AddStateTransitionRules is a function for adding valid state transitions to the machine.
// This allows you to define which states any given state can be transitioned to.
func (m *Machine) AddStateTransitionRules(sourceState State, destinationStates ...State) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	// if the transitions map is nil, we need to allocate it
	if m.transitions == nil {
		m.transitions = make(map[State]TransitionRuleSet)
	}

	// if the map for the source state does not exist, allocate it
	if m.transitions[sourceState] == nil {
		m.transitions[sourceState] = make(TransitionRuleSet)
	}

	// get a reference to the map we care about
	// avoids doing the map lookup for each iteration
	mp := m.transitions[sourceState]

	for _, dest := range destinationStates {
		mp[dest] = struct{}{}
	}

	return nil
}

// SetStateTransitionCallback for the state transition. This is meant to send
// callbacks back to the consumer for state changes. The callback only sends the
// new state. The synchonous parameter indicates whether the callback is done
// synchronously with the StateTransition() call.
func (m *Machine) SetStateTransitionCallback(callback CallbackHandler, synchronous bool) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	m.callback = callback
	m.syncCallback = synchronous

	return nil
}

// StateTransition triggers a transition to the toState. This function is also
// used to set the initial state of machine.
//
// Before you can transition to any state, even for the initial, you must define
// it with AddStateTransition(). If you are setting the initial state, and that
// state is not define, this will return an ErrInvalidInitialState error.
//
// When transitioning from a state, this function will return an error either
// if the state transition is not allowed, or if the destination state has
// not been defined. In both cases, it's seen as a non-permitted state transition.
func (m *Machine) StateTransition(toState State) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	// if this is nil we cannot assume any state
	if m.transitions == nil {
		return newErrorStruct("the machine has no states added", ErrorMachineNotInitialized)
	}

	// if the state is nothing, this is probably the initial state
	if m.state == "" {
		// if the state is not defined, it's invalid
		if _, ok := m.transitions[toState]; !ok {
			return newErrorStruct("the initial state has not been defined within the machine", ErrorStateUndefined)
		}

		// set the state
		m.state = toState
		return nil
	}

	// if we are not permitted to transition to this state...
	if _, ok := m.transitions[m.state][toState]; !ok {
		return newErrorStruct(fmt.Sprintf("transition from state %s to %s is not permitted", m.state, toState), ErrorTransitionNotPermitted)
	}

	// if the destination state was not defined...
	if _, ok := m.transitions[toState]; !ok {
		return newErrorStruct(fmt.Sprintf("state %s has not been registered", toState), ErrorStateUndefined)
	}

	m.state = toState

	if m.callback != nil {
		if m.syncCallback {
			// do not return the error
			// this may be reconsidered
			m.callback.StateTransitionCallback(toState)
		} else {
			// spin off the callback
			go func() { m.callback.StateTransitionCallback(toState) }()
		}
	}

	return nil
}
<|endoftext|>


<commit_before>// Package fwk provides a set of tools to process High Energy Physics events data.
// fwk is a components-based framework, a-la Gaudi, with builtin support for concurrency.
//
// A fwk application consists of a set of components (fwk.Task) which are:
//  - (optionally) configured
//  - started
//  - given the chance to process each event
//  - stopped
//
// Helper components (fwk.Svc) can provide additional features (such as a
// whiteboard/event-store service, a data-flow service, ...) but do not
// typically take (directly) part of the event processing.
//
// Typically, users will implement fwk.Tasks, ie:
//
//   type MyTask struct {
//     fwk.TaskBase
//   }
//
//   // Configure is called once, after having read the properties
//   // from the data-cards.
//   func (tsk *MyTask) Configure(ctx fwk.Context) error { return nil }
//
//   // StartTask is called once (sequentially), just before
//   // the main event-loop processing.
//   func (tsk *MyTask) StartTask(ctx fwk.Context) error { return nil }
//
//   // Process is called for each event, (quite) possibly concurrently.
//   func (tsk *MyTask) Process(ctx fwk.Context)   error { return nil }
//
//   // StopTask is called once (sequentially), just after the
//   // main event-loop processing finished.
//   func (tsk *MyTask) StopTask(ctx fwk.Context)  error { return nil }
//
// A fwk application processes data concurrently, at 2 different levels:
//  - event-level concurrency: multiple events are processed concurrently
//    at any given time, during the event loop;
//  - task-level concurrency: during the event loop, multiple tasks are
//    executing concurrently.
//
// To ensure the proper self-consistency of the global processed event,
// components need to express their data dependencies (input(s)) as well
// as the data they produce (output(s)) for downstream components.
// This is achieved by the concept of a fwk.Port.
// A fwk.Port consists of a pair { Name string; Type reflect.Type }
// where 'Name' is the unique location in the event-store,
// and 'Type' the expected 'go' type of the data at that event-store location.
//
// fwk.Ports can be either INPUT ports or OUTPUT ports.
// Components declare INPUT ports and OUTPUT ports during the 'Configure' stage
// of a fwk application, like so:
//
//  t := reflect.TypeOf([]Electron{})
//  err = component.DeclInPort("Electrons", t)
//  err = component.DeclOutPort("ReScaledElectrons", t)
//
// Then, during the event processing, one gets and puts data from/to the store
// like so:
//
//   func (tsk *MyTask) Process(ctx fwk.Context) error {
//      var err error
//
//      // retrieve the store associated with this event / region-of-interest
//      store := ctx.Store()
//
//      v, err := store.Get("Electrons")
//      if err != nil {
//         return err
//      }
//      eles := v.([]Electron) // type-cast to the correct (underlying) type
//
//      // create output collection
//      out := make([]Electron, 0, len(eles))
//
//      // make sure the collection be put in the store
//      defer func() {
//         err = store.Put("ReScaledElectrons", out)
//      }()
//
//      // ... do some massaging with 'eles' and 'out'
//
//      return err
//   }
package fwk
<commit_msg>doc: wording<commit_after>// Package fwk provides a set of tools to process High Energy Physics events data.
// fwk is a components-based framework, a-la Gaudi, with builtin support for concurrency.
//
// A fwk application consists of a set of components (fwk.Task) which are:
//  - (optionally) configured
//  - started
//  - given the chance to process each event
//  - stopped
//
// Helper components (fwk.Svc) can provide additional features (such as a
// whiteboard/event-store service, a data-flow service, ...) but do not
// typically take (directly) part of the event processing.
//
// Typically, users will implement fwk.Tasks, ie:
//
//   type MyTask struct {
//     fwk.TaskBase
//   }
//
//   // Configure is called once, after having read the properties
//   // from the data-cards.
//   func (tsk *MyTask) Configure(ctx fwk.Context) error { return nil }
//
//   // StartTask is called once (sequentially), just before
//   // the main event-loop processing.
//   func (tsk *MyTask) StartTask(ctx fwk.Context) error { return nil }
//
//   // Process is called for each event, (quite) possibly concurrently.
//   func (tsk *MyTask) Process(ctx fwk.Context)   error { return nil }
//
//   // StopTask is called once (sequentially), just after the
//   // main event-loop processing finished.
//   func (tsk *MyTask) StopTask(ctx fwk.Context)  error { return nil }
//
// A fwk application processes data and leverages concurrency at
// two different levels:
//  - event-level concurrency: multiple events are processed concurrently
//    at any given time, during the event loop;
//  - task-level concurrency: during the event loop, multiple tasks are
//    executing concurrently.
//
// To ensure the proper self-consistency of the global processed event,
// components need to express their data dependencies (input(s)) as well
// as the data they produce (output(s)) for downstream components.
// This is achieved by the concept of a fwk.Port.
// A fwk.Port consists of a pair { Name string; Type reflect.Type }
// where 'Name' is the unique location in the event-store,
// and 'Type' the expected 'go' type of the data at that event-store location.
//
// fwk.Ports can be either INPUT ports or OUTPUT ports.
// Components declare INPUT ports and OUTPUT ports during the 'Configure' stage
// of a fwk application, like so:
//
//  t := reflect.TypeOf([]Electron{})
//  err = component.DeclInPort("Electrons", t)
//  err = component.DeclOutPort("ReScaledElectrons", t)
//
// Then, during the event processing, one gets and puts data from/to the store
// like so:
//
//   func (tsk *MyTask) Process(ctx fwk.Context) error {
//      var err error
//
//      // retrieve the store associated with this event / region-of-interest
//      store := ctx.Store()
//
//      v, err := store.Get("Electrons")
//      if err != nil {
//         return err
//      }
//      eles := v.([]Electron) // type-cast to the correct (underlying) type
//
//      // create output collection
//      out := make([]Electron, 0, len(eles))
//
//      // make sure the collection be put in the store
//      defer func() {
//         err = store.Put("ReScaledElectrons", out)
//      }()
//
//      // ... do some massaging with 'eles' and 'out'
//
//      return err
//   }
package fwk
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
)

type mpath string
type vdir string

var mpathre = regexp.MustCompile(`^\.(.*)$`)
var vdirre = regexp.MustCompile(`^[a-f0-9]{64}$`)

func newmpath(mp string) mpath {
	res := mpathre.FindAllStringSubmatch(mp, -1)
	mres := mpath("")
	if res != nil && len(res) == 1 && len(res[0]) == 2 {
		mres = mpath(res[0][1])
	}
	return mres
}

func newvdir(vd string) vdir {
	res := vdirre.FindString(vd)
	vres := vdir("")
	if res != "" && res == vd {
		vres = vdir(vd)
	}
	return vres
}

type marker struct {
	path mpath
	dir  vdir
}

var markers = []*marker{}

type volume struct {
	dir  vdir
	mark *marker
}

var volumes = []*volume{}

func (v *volume) String() string {
	return "vol '" + string(v.dir) + "'"
}

type container struct {
	name    string
	id      string
	stopped bool
	volumes []*volume
}

func (c *container) trunc() string {
	if len(c.id) > 0 {
		return c.id[:7]
	}
	return ""
}

func (c *container) String() string {
	return "cnt '" + c.name + "' (" + c.trunc() + ")" + fmt.Sprintf("[%v] - %d vol", c.stopped, len(c.volumes))
}

var containers = []*container{}

func mustcmd(acmd string) string {
	out, err := cmd(acmd)
	if err != nil {
		log.Fatal(fmt.Sprintf("out='%s', err='%s'", out, err))
	}
	return string(out)
}

func cmd(cmd string) (string, error) {
	fmt.Println(cmd)
	out, err := exec.Command("sh", "-c", cmd).Output()
	return strings.TrimSpace(string(out)), err
}

func readVolumes() {
	out := mustcmd("sudo ls -a1F /mnt/sda1/var/lib/docker/vfs/dir")
	vollines := strings.Split(out, "\n")
	// fmt.Println(vollines)
	for _, volline := range vollines {
		dir := volline
		if dir == "./" || dir == "../" {
			continue
		}
		if strings.HasSuffix(dir, "@") {
			dir = dir[:len(dir)-1]
			fdir := fmt.Sprintf("/mnt/sda1/var/lib/docker/vfs/dir/%s", dir)
			mp := newmpath(dir)
			if mp == "" {
				fmt.Printf("Invalid marker detected: '%s'\n", dir)
				mustcmd("sudo rm " + fdir)
			} else {
				dirlink, err := cmd("sudo readlink " + fdir)
				fmt.Printf("---\ndir: '%s'\ndlk: '%s'\nerr='%v'\n", dir, dirlink, err)
				if err != nil {
					fmt.Printf("Invalid marker (no readlink) detected: '%s'\n", dir)
					mustcmd("sudo rm " + fdir)
				} else {
					_, err := cmd("sudo ls /mnt/sda1/var/lib/docker/vfs/dir/" + dirlink)
					if err != nil {
						fmt.Printf("Invalid marker (readlink no ls) detected: '%s'\n", dir)
						mustcmd("sudo rm " + fdir)
					} else {
						vd := newvdir(dirlink)
						if vd == "" {
							fmt.Printf("Invalid marker (readlink no vdir) detected: '%s'\n", dir)
							mustcmd("sudo rm " + fdir)
						} else {
							markers = append(markers, &marker{mp, vd})
						}
					}
				}
			}
		} else if strings.HasSuffix(dir, "/") {

			dir = dir[:len(dir)-1]
			fdir := fmt.Sprintf("/mnt/sda1/var/lib/docker/vfs/dir/%s", dir)
			vd := newvdir(dir)
			if vd == "" {
				fmt.Printf("Invalid volume folder detected: '%s'\n", dir)
				mustcmd("sudo rm " + fdir)
			} else {
				volumes = append(volumes, &volume{vd, nil})
			}
		} else {
			fdir := fmt.Sprintf("/mnt/sda1/var/lib/docker/vfs/dir/%s", dir)
			fmt.Printf("Invalid file detected: '%s'\n", dir)
			mustcmd("sudo rm " + fdir)
		}
	}
	fmt.Printf("volumes: %v\nmarkers: %v\n", volumes, markers)
}

func readContainer() {

	out := mustcmd("docker ps -aq --no-trunc")
	contlines := strings.Split(out, "\n")
	// fmt.Println(contlines)
	for _, contline := range contlines {
		id := contline
		res := mustcmd("docker inspect -f '{{ .Name }},{{ range $key, $value := .Volumes }}{{ $key }},{{ $value }}##~#{{ end }}' " + id)
		// fmt.Println("res1: '" + res + "'")
		name := res[1:strings.Index(res, ",")]
		cont := &container{name: name, id: id}
		res = res[strings.Index(res, ",")+1:]
		// fmt.Println("res2: '" + res + "'")
		vols := strings.Split(res, "##~#")
		// fmt.Println(vols)
		for _, vol := range vols {
			elts := strings.Split(vol, ",")
			if len(elts) == 2 {
				// fmt.Printf("elts: '%v'\n", elts)
				vfs := elts[1]
				if strings.Contains(vfs, "/var/lib/docker/vfs/dir/") {
					vd := newvdir(filepath.Base(vfs))
					if vd == "" {
						fmt.Printf("Invalid volume folder detected: '%s'\n", vfs)
						break
					}
					var newvol *volume
					for _, volume := range volumes {
						if string(volume.dir) == string(vd) {
							newvol = volume
							break
						}
					}
					if newvol == nil {
						newvol = &volume{dir: vd}
					}
					cont.volumes = append(cont.volumes, newvol)
				}
			}
		}
		containers = append(containers, cont)
	}
	fmt.Printf("containers: %v\n", containers)
}

func (v *volume) accept(m *marker) bool {
	// TODO
	return false
}

func checkContainers() {
	for _, container := range containers {
		for _, volume := range container.volumes {
			if volume.mark == nil {
				for _, mark := range markers {
					if volume.accept(mark) {
						fmt.Printf("Set mark '%s' to volume '%v' of container '%v'\n", mark, volume, container)
						volume.mark = mark
						// TODO check if ln is needed
					}
				}
			}
			if volume.mark == nil {
				// TODO check if vfs folder exist.
				// If it does, make the marker
			}
		}
	}
}

func (c *container) accept(v *volume) bool {
	// TODO
	return false
}

func checkVolumes() {
	for _, volume := range volumes {
		orphan := true
		for _, container := range containers {
			if container.accept(volume) {
				orphan = false
				break
			}
		}
		if orphan {
			fmt.Printf("Orphan detected, volume '%v'\n", volume)
			// TODO rm if necessary or at least mv _xxx
		}
	}
}

// docker run --rm -i -t -v `pwd`:`pwd` -w `pwd` --entrypoint="/bin/bash" go -c 'go build gcl.go'
func main() {
	readVolumes()
	readContainer()
	checkContainers()
	checkVolumes()
	os.Exit(0)
}
<commit_msg>gcl.go: mpath is composed of container name + path<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
)

type mpath struct {
	name string
	path string
}
type vdir string

var mpathre = regexp.MustCompile(`^\.(.*)###(.*)$`)
var vdirre = regexp.MustCompile(`^[a-f0-9]{64}$`)

func newmpath(mp string) *mpath {
	res := mpathre.FindAllStringSubmatch(mp, -1)
	var mres *mpath
	if res != nil && len(res) == 1 && len(res[0]) == 3 {
		name := res[0][1]
		path := res[0][2]
		path = strings.Replace(path, ",#,", "/", -1)
		mres = &mpath{name, path}
	}
	return mres
}

func newvdir(vd string) vdir {
	res := vdirre.FindString(vd)
	vres := vdir("")
	if res != "" && res == vd {
		vres = vdir(vd)
	}
	return vres
}

type marker struct {
	mp  *mpath
	dir vdir
}

var markers = []*marker{}

type volume struct {
	dir  vdir
	mark *marker
}

var volumes = []*volume{}

func (v *volume) String() string {
	return "vol '" + string(v.dir) + "'"
}

type container struct {
	name    string
	id      string
	stopped bool
	volumes []*volume
}

func (c *container) trunc() string {
	if len(c.id) > 0 {
		return c.id[:7]
	}
	return ""
}

func (c *container) String() string {
	return "cnt '" + c.name + "' (" + c.trunc() + ")" + fmt.Sprintf("[%v] - %d vol", c.stopped, len(c.volumes))
}

var containers = []*container{}

func mustcmd(acmd string) string {
	out, err := cmd(acmd)
	if err != nil {
		log.Fatal(fmt.Sprintf("out='%s', err='%s'", out, err))
	}
	return string(out)
}

func cmd(cmd string) (string, error) {
	fmt.Println(cmd)
	out, err := exec.Command("sh", "-c", cmd).Output()
	return strings.TrimSpace(string(out)), err
}

func readVolumes() {
	out := mustcmd("sudo ls -a1F /mnt/sda1/var/lib/docker/vfs/dir")
	vollines := strings.Split(out, "\n")
	// fmt.Println(vollines)
	for _, volline := range vollines {
		dir := volline
		if dir == "./" || dir == "../" {
			continue
		}
		if strings.HasSuffix(dir, "@") {
			dir = dir[:len(dir)-1]
			fdir := fmt.Sprintf("/mnt/sda1/var/lib/docker/vfs/dir/%s", dir)
			mp := newmpath(dir)
			if mp == nil {
				fmt.Printf("Invalid marker detected: '%s'\n", dir)
				mustcmd("sudo rm " + fdir)
			} else {
				dirlink, err := cmd("sudo readlink " + fdir)
				fmt.Printf("---\ndir: '%s'\ndlk: '%s'\nerr='%v'\n", dir, dirlink, err)
				if err != nil {
					fmt.Printf("Invalid marker (no readlink) detected: '%s'\n", dir)
					mustcmd("sudo rm " + fdir)
				} else {
					_, err := cmd("sudo ls /mnt/sda1/var/lib/docker/vfs/dir/" + dirlink)
					if err != nil {
						fmt.Printf("Invalid marker (readlink no ls) detected: '%s'\n", dir)
						mustcmd("sudo rm " + fdir)
					} else {
						vd := newvdir(dirlink)
						if vd == "" {
							fmt.Printf("Invalid marker (readlink no vdir) detected: '%s'\n", dir)
							mustcmd("sudo rm " + fdir)
						} else {
							markers = append(markers, &marker{mp, vd})
						}
					}
				}
			}
		} else if strings.HasSuffix(dir, "/") {

			dir = dir[:len(dir)-1]
			fdir := fmt.Sprintf("/mnt/sda1/var/lib/docker/vfs/dir/%s", dir)
			vd := newvdir(dir)
			if vd == "" {
				fmt.Printf("Invalid volume folder detected: '%s'\n", dir)
				mustcmd("sudo rm " + fdir)
			} else {
				volumes = append(volumes, &volume{vd, nil})
			}
		} else {
			fdir := fmt.Sprintf("/mnt/sda1/var/lib/docker/vfs/dir/%s", dir)
			fmt.Printf("Invalid file detected: '%s'\n", dir)
			mustcmd("sudo rm " + fdir)
		}
	}
	fmt.Printf("volumes: %v\nmarkers: %v\n", volumes, markers)
}

func readContainer() {

	out := mustcmd("docker ps -aq --no-trunc")
	contlines := strings.Split(out, "\n")
	// fmt.Println(contlines)
	for _, contline := range contlines {
		id := contline
		res := mustcmd("docker inspect -f '{{ .Name }},{{ range $key, $value := .Volumes }}{{ $key }},{{ $value }}##~#{{ end }}' " + id)
		// fmt.Println("res1: '" + res + "'")
		name := res[1:strings.Index(res, ",")]
		cont := &container{name: name, id: id}
		res = res[strings.Index(res, ",")+1:]
		// fmt.Println("res2: '" + res + "'")
		vols := strings.Split(res, "##~#")
		// fmt.Println(vols)
		for _, vol := range vols {
			elts := strings.Split(vol, ",")
			if len(elts) == 2 {
				// fmt.Printf("elts: '%v'\n", elts)
				vfs := elts[1]
				if strings.Contains(vfs, "/var/lib/docker/vfs/dir/") {
					vd := newvdir(filepath.Base(vfs))
					if vd == "" {
						fmt.Printf("Invalid volume folder detected: '%s'\n", vfs)
						break
					}
					var newvol *volume
					for _, volume := range volumes {
						if string(volume.dir) == string(vd) {
							newvol = volume
							break
						}
					}
					if newvol == nil {
						newvol = &volume{dir: vd}
					}
					cont.volumes = append(cont.volumes, newvol)
				}
			}
		}
		containers = append(containers, cont)
	}
	fmt.Printf("containers: %v\n", containers)
}

func (v *volume) accept(m *marker) bool {
	// TODO
	return false
}

func checkContainers() {
	for _, container := range containers {
		for _, volume := range container.volumes {
			if volume.mark == nil {
				for _, mark := range markers {
					if volume.accept(mark) {
						fmt.Printf("Set mark '%s' to volume '%v' of container '%v'\n", mark, volume, container)
						volume.mark = mark
						// TODO check if ln is needed
					}
				}
			}
			if volume.mark == nil {
				// TODO check if vfs folder exist.
				// If it does, make the marker
			}
		}
	}
}

func (c *container) accept(v *volume) bool {
	// TODO
	return false
}

func checkVolumes() {
	for _, volume := range volumes {
		orphan := true
		for _, container := range containers {
			if container.accept(volume) {
				orphan = false
				break
			}
		}
		if orphan {
			fmt.Printf("Orphan detected, volume '%v'\n", volume)
			// TODO rm if necessary or at least mv _xxx
		}
	}
}

// docker run --rm -i -t -v `pwd`:`pwd` -w `pwd` --entrypoint="/bin/bash" go -c 'go build gcl.go'
func main() {
	readVolumes()
	readContainer()
	checkContainers()
	checkVolumes()
	os.Exit(0)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/micromdm/dep"
)

func getResource(args []string) error {
	if len(args) < 1 {
		return errors.New("get requires at least one resource name")
	}

	var run func([]string) error
	switch strings.ToLower(args[0]) {
	case "dep":
		run = getDep
	default:
		usage()
		os.Exit(1)
	}

	if err := run(args[1:]); err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}

	return nil
}

func getDep(args []string) error {
	if len(args) < 1 {
		return errors.New("get dep requires at least one resource name")
	}
	sm := &config{}
	sm.setupBolt()
	client, err := sm.depClient()
	if err != nil {
		return err
	}
	var run func(dep.Client, []string) error
	switch strings.ToLower(args[0]) {
	case "account-info":
		acc, err := client.Account()
		if err != nil {
			return err
		}
		enc := json.NewEncoder(os.Stdout)
		enc.SetIndent("", "  ")
		err = enc.Encode(acc)
		return err
	case "device":
		run = getDepDevice
	case "profile":
		run = getDepProfile
	case "profile-template":
		run = getDepProfileTpl
	default:
		usage()
		os.Exit(1)
	}

	if err := run(client, args[1:]); err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}
	return nil
}

func getDepProfile(client dep.Client, args []string) error {
	flagset := flag.NewFlagSet("profile", flag.ExitOnError)
	var (
		flUUID = flagset.String("uuid", "", "profile uuid")
	)
	if err := flagset.Parse(args); err != nil {
		return err
	}

	profile, err := client.FetchProfile(*flUUID)
	if err != nil {
		return err
	}
	enc := json.NewEncoder(os.Stdout)
	enc.SetIndent("", "  ")
	err = enc.Encode(profile)
	return err
}

func getDepDevice(client dep.Client, args []string) error {
	flagset := flag.NewFlagSet("device", flag.ExitOnError)
	var (
		flSerial = flagset.String("serial", "", "device serial number")
	)
	if err := flagset.Parse(args); err != nil {
		return err
	}

	resp, err := client.DeviceDetails([]string{*flSerial})
	if err != nil {
		return err
	}
	if dev, ok := resp.Devices[*flSerial]; ok && dev.SerialNumber != "" {
		enc := json.NewEncoder(os.Stdout)
		enc.SetIndent("", "  ")
		err = enc.Encode(dev)
		return err
	} else {
		return errors.New("no device information")
	}
	return nil
}

func getDepProfileTpl(client dep.Client, args []string) error {
	/* omitempty flags on the Profile struct are preventing the (Apple-
	   defined) false defaults from showing up in the example.

	p := dep.Profile{
		ProfileName:           "(Required) Human readable name",
		URL:                   "https://mymdm.example.org",
		AllowPairing:          true,
		IsSupervised:          false,
		IsMultiUser:           false,
		IsMandatory:           false,
		AwaitDeviceConfigured: false,
		IsMDMRemovable:        true,
		SupportPhoneNumber:    "(Optional) +1 408 555 1010",
		SupportEmailAddress:   "(Optional) support@example.com",
		OrgMagic:              "(Optional)",
		AnchorCerts:           []string{},
		SupervisingHostCerts:  []string{},
		SkipSetupItems:        []string{},
		Department:            "(Optional) support@example.com",
		Devices:               []string{},
	}
	enc := json.NewEncoder(os.Stdout)
	enc.SetIndent("", "  ")
	err := enc.Encode(&p)
	*/

	resp := `{
  "profile_name": "(Required) Human readable name",
  "url": "https://mymdm.example.org",
  "allow_pairing": true,
  "is_supervised": false,
  "is_multi_user": false,
  "is_mandatory": false,
  "await_device_configured": false,
  "is_mdm_removable": true,
  "support_phone_number": "(Optional) +1 408 555 1010",
  "support_email_address": "(Optional) support@example.com",
  "org_magic": "(Optional)",
  "anchor_certs": [],
  "supervising_host_certs": [],
  "skip_setup_items": [],
  "deparment": "(Optional) support@example.com",
  "devices": []
}`
	fmt.Println(resp)
	return nil
}
<commit_msg>More appropos message<commit_after>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/micromdm/dep"
)

func getResource(args []string) error {
	if len(args) < 1 {
		return errors.New("get requires at least one resource name")
	}

	var run func([]string) error
	switch strings.ToLower(args[0]) {
	case "dep":
		run = getDep
	default:
		return errors.New("invalid dep resource name")
	}

	if err := run(args[1:]); err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}

	return nil
}

func getDep(args []string) error {
	if len(args) < 1 {
		return errors.New("get dep requires at least one resource name")
	}
	sm := &config{}
	sm.setupBolt()
	client, err := sm.depClient()
	if err != nil {
		return err
	}
	var run func(dep.Client, []string) error
	switch strings.ToLower(args[0]) {
	case "account-info":
		acc, err := client.Account()
		if err != nil {
			return err
		}
		enc := json.NewEncoder(os.Stdout)
		enc.SetIndent("", "  ")
		err = enc.Encode(acc)
		return err
	case "device":
		run = getDepDevice
	case "profile":
		run = getDepProfile
	case "profile-template":
		run = getDepProfileTpl
	default:
		usage()
		os.Exit(1)
	}

	if err := run(client, args[1:]); err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}
	return nil
}

func getDepProfile(client dep.Client, args []string) error {
	flagset := flag.NewFlagSet("profile", flag.ExitOnError)
	var (
		flUUID = flagset.String("uuid", "", "profile uuid")
	)
	if err := flagset.Parse(args); err != nil {
		return err
	}

	profile, err := client.FetchProfile(*flUUID)
	if err != nil {
		return err
	}
	enc := json.NewEncoder(os.Stdout)
	enc.SetIndent("", "  ")
	err = enc.Encode(profile)
	return err
}

func getDepDevice(client dep.Client, args []string) error {
	flagset := flag.NewFlagSet("device", flag.ExitOnError)
	var (
		flSerial = flagset.String("serial", "", "device serial number")
	)
	if err := flagset.Parse(args); err != nil {
		return err
	}

	resp, err := client.DeviceDetails([]string{*flSerial})
	if err != nil {
		return err
	}
	if dev, ok := resp.Devices[*flSerial]; ok && dev.SerialNumber != "" {
		enc := json.NewEncoder(os.Stdout)
		enc.SetIndent("", "  ")
		err = enc.Encode(dev)
		return err
	} else {
		return errors.New("no device information")
	}
	return nil
}

func getDepProfileTpl(client dep.Client, args []string) error {
	/* omitempty flags on the Profile struct are preventing the (Apple-
	   defined) false defaults from showing up in the example.

	p := dep.Profile{
		ProfileName:           "(Required) Human readable name",
		URL:                   "https://mymdm.example.org",
		AllowPairing:          true,
		IsSupervised:          false,
		IsMultiUser:           false,
		IsMandatory:           false,
		AwaitDeviceConfigured: false,
		IsMDMRemovable:        true,
		SupportPhoneNumber:    "(Optional) +1 408 555 1010",
		SupportEmailAddress:   "(Optional) support@example.com",
		OrgMagic:              "(Optional)",
		AnchorCerts:           []string{},
		SupervisingHostCerts:  []string{},
		SkipSetupItems:        []string{},
		Department:            "(Optional) support@example.com",
		Devices:               []string{},
	}
	enc := json.NewEncoder(os.Stdout)
	enc.SetIndent("", "  ")
	err := enc.Encode(&p)
	*/

	resp := `{
  "profile_name": "(Required) Human readable name",
  "url": "https://mymdm.example.org",
  "allow_pairing": true,
  "is_supervised": false,
  "is_multi_user": false,
  "is_mandatory": false,
  "await_device_configured": false,
  "is_mdm_removable": true,
  "support_phone_number": "(Optional) +1 408 555 1010",
  "support_email_address": "(Optional) support@example.com",
  "org_magic": "(Optional)",
  "anchor_certs": [],
  "supervising_host_certs": [],
  "skip_setup_items": [],
  "deparment": "(Optional) support@example.com",
  "devices": []
}`
	fmt.Println(resp)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"strings"

	"github.com/hawx/ggg/repos"
	"github.com/hawx/ggg/web/assets"
	"github.com/hawx/ggg/web/filters"
	"github.com/hawx/ggg/web/handlers"

	"github.com/hawx/mux"
	"github.com/hawx/persona"
	"github.com/hawx/serve"
	"github.com/stvp/go-toml-config"

	"flag"
	"log"

	"github.com/hawx/route"
)

var (
	settingsPath = flag.String("settings", "./settings.toml", "Path to 'settings.toml'")
	port         = flag.String("port", "8080", "Port to run on")
	socket       = flag.String("socket", "", "")

	cookieSecret = config.String("secret", "change-me")
	title        = config.String("title", "ggg")
	gitDir       = config.String("gitDir", "./ggg-data/repos")
	dbPath       = config.String("dbPath", "./ggg-data/db")
	user         = config.String("user", "someone@example.com")
	url          = config.String("url", "http://localhost:8080")
)

func main() {
	flag.Parse()

	if err := config.Parse(*settingsPath); err != nil {
		log.Fatal("toml: ", err)
	}

	db := repos.Open(*dbPath, *gitDir)
	defer db.Close()

	store := persona.NewStore(*cookieSecret)
	persona := persona.New(store, *url, []string{*user})

	dashRouter := route.New()
	dashRouter.Handle("/-/create", persona.Protect(handlers.Create(db)))
	dashRouter.Handle("/-/sign-in", mux.Method{"POST": persona.SignIn})
	dashRouter.Handle("/-/sign-out", mux.Method{"GET": persona.SignOut})

	assetRouter := route.New()
	assetRouter.Handle("/assets/styles.css", mux.Method{"GET": assets.Styles})
	assetRouter.Handle("/assets/core.js", mux.Method{"GET": assets.Core})

	var (
		repo = handlers.Repo(db, *url, persona.Protect)
		list = handlers.List(db, *title, *url)
		edit = persona.Protect(handlers.Edit(db))
		dele = persona.Protect(handlers.Delete(db))
	)

	route.Handle("/", mux.Method{"GET": persona.Switch(list.All, list.Public)})
	route.Handle("/:name", repo.Html)
	route.HandleFunc("/:name/*path", func(w http.ResponseWriter, r *http.Request) {
		vars := route.Vars(r)
		name := vars["name"]
		path := vars["path"]

		if strings.HasSuffix(name, ".git") {
			repo.Git.ServeHTTP(w, r)
			return
		}

		handler, ok := map[string]http.Handler{
			"edit":   edit,
			"delete": dele,
		}[path[1:]]

		if ok {
			handler.ServeHTTP(w, r)
			return
		}

		handler, ok = map[string]http.Handler{
			"-":      dashRouter,
			"assets": assetRouter,
		}[name]

		if ok {
			handler.ServeHTTP(w, r)
			return
		}

		http.NotFound(w, r)
	})

	serve.Serve(*port, *socket, filters.Log(route.Default))
}
<commit_msg>Use new route package<commit_after>package main

import (
	"flag"
	"log"
	"net/http"
	"strings"

	"github.com/hawx/ggg/repos"
	"github.com/hawx/ggg/web/assets"
	"github.com/hawx/ggg/web/filters"
	"github.com/hawx/ggg/web/handlers"
	"github.com/hawx/mux"
	"github.com/hawx/persona"
	"github.com/hawx/route"
	"github.com/hawx/serve"
	"github.com/stvp/go-toml-config"
)

var (
	settingsPath = flag.String("settings", "./settings.toml", "Path to 'settings.toml'")
	port         = flag.String("port", "8080", "Port to run on")
	socket       = flag.String("socket", "", "")

	cookieSecret = config.String("secret", "change-me")
	title        = config.String("title", "ggg")
	gitDir       = config.String("gitDir", "./ggg-data/repos")
	dbPath       = config.String("dbPath", "./ggg-data/db")
	user         = config.String("user", "someone@example.com")
	url          = config.String("url", "http://localhost:8080")
)

func main() {
	flag.Parse()

	if err := config.Parse(*settingsPath); err != nil {
		log.Fatal("toml: ", err)
	}

	db := repos.Open(*dbPath, *gitDir)
	defer db.Close()

	store := persona.NewStore(*cookieSecret)
	persona := persona.New(store, *url, []string{*user})

	list := handlers.List(db, *title, *url)
	repo := handlers.Repo(db, *url, persona.Protect)

	route.Handle("/", mux.Method{"GET": persona.Switch(list.All, list.Public)})

	route.HandleFunc("/:name/*path", func(w http.ResponseWriter, r *http.Request) {
		vars := route.Vars(r)

		if strings.HasSuffix(vars["name"], ".git") {
			repo.Git.ServeHTTP(w, r)
			return
		}

		repo.Html.ServeHTTP(w, r)
	})
	route.Handle("/:name/edit", persona.Protect(handlers.Edit(db)))
	route.Handle("/:name/delete", persona.Protect(handlers.Delete(db)))

	route.Handle("/-/create", persona.Protect(handlers.Create(db)))
	route.Handle("/-/sign-in", mux.Method{"POST": persona.SignIn})
	route.Handle("/-/sign-out", mux.Method{"GET": persona.SignOut})

	route.Handle("/assets/styles.css", mux.Method{"GET": assets.Styles})
	route.Handle("/assets/core.js", mux.Method{"GET": assets.Core})

	serve.Serve(*port, *socket, filters.Log(route.Default))
}
<|endoftext|>


<commit_before>package main

import (
	"net/url"
	"os"
	"strings"

	"github.com/libgit2/git2go"
)

// the git segment provides useful information about a git repository such as the domain of the "origin" remote (with an icon), the current branch, and whether the HEAD is dirty
func gitSegment(segment *segment) {
	dir, err := os.Getwd()
	check(err)
	repo, err := git.OpenRepositoryExtended(dir, 0, "/")
	if err != nil {
		return
	}
	defer repo.Free()

	var domain string
	remote, err := repo.Remotes.Lookup("origin")
	if err == nil {
		uri, err := url.Parse(remote.Url())
		check(err)
		domain = uri.Hostname()
		remote.Free()
	}

	var stashes int
	repo.Stashes.Foreach(func(int, string, *git.Oid) error {
		stashes++
		return nil
	})

	var ahead, behind int
	var branch string
	head, err := repo.Head()
	if err == nil {
		check(err)
		upstream, err := head.Branch().Upstream()
		if err == nil {
			ahead, behind, err = repo.AheadBehind(head.Branch().Reference.Target(), upstream.Target())
			check(err)
		}

		branch, err = head.Branch().Name()
		if err != nil {
			// head is detached
			branch = head.Branch().Target().String()[:7]
		}
		head.Free()
	}

	var dirty, modified, staged bool
	status, err := repo.StatusList(&git.StatusOptions{
		Flags: git.StatusOptIncludeUntracked,
	})
	check(err)
	count, err := status.EntryCount()
	check(err)
	if count != 0 {
		dirty = true
	}
	for i := 0; i < count; i++ {
		entry, err := status.ByIndex(i)
		check(err)
		if entry.Status&git.StatusWtNew != 0 || entry.Status&git.StatusWtModified != 0 || entry.Status&git.StatusWtDeleted != 0 || entry.Status&git.StatusWtTypeChange != 0 || entry.Status&git.StatusWtRenamed != 0 {
			modified = true
		}
		if entry.Status&git.StatusIndexNew != 0 || entry.Status&git.StatusIndexModified != 0 || entry.Status&git.StatusIndexDeleted != 0 || entry.Status&git.StatusIndexRenamed != 0 || entry.Status&git.StatusIndexTypeChange != 0 {
			staged = true
		}
	}
	status.Free()

	var segments []string
	switch domain {
	case "github.com":
		segments = append(segments, iconGithub)
	case "gitlab.com":
		segments = append(segments, iconGitlab)
	case "bitbucket.org":
		segments = append(segments, iconBitbucket)
	default:
		segments = append(segments, iconGit)
	}
	if stashes != 0 || ahead != 0 || behind != 0 {
		segments = append(segments, strings.Repeat(iconStash, stashes)+strings.Repeat(iconAhead, ahead)+strings.Repeat(iconBehind, behind))
	}
	if branch != "" {
		segments = append(segments, branch)
	}
	if dirty {
		segment.background = "yellow"

		var icons string
		if modified {
			icons += iconCircle
		}
		if staged {
			icons += iconPlus
		}
		if icons != "" {
			segments = append(segments, icons)
		}
	}
	segment.visible = true
	segment.value = strings.Join(segments, " ")
}
<commit_msg>removed unnecessary Reference reference<commit_after>package main

import (
	"net/url"
	"os"
	"strings"

	"github.com/libgit2/git2go"
)

// the git segment provides useful information about a git repository such as the domain of the "origin" remote (with an icon), the current branch, and whether the HEAD is dirty
func gitSegment(segment *segment) {
	dir, err := os.Getwd()
	check(err)
	repo, err := git.OpenRepositoryExtended(dir, 0, "/")
	if err != nil {
		return
	}
	defer repo.Free()

	var domain string
	remote, err := repo.Remotes.Lookup("origin")
	if err == nil {
		uri, err := url.Parse(remote.Url())
		check(err)
		domain = uri.Hostname()
		remote.Free()
	}

	var stashes int
	repo.Stashes.Foreach(func(int, string, *git.Oid) error {
		stashes++
		return nil
	})

	var ahead, behind int
	var branch string
	head, err := repo.Head()
	if err == nil {
		check(err)
		upstream, err := head.Branch().Upstream()
		if err == nil {
			ahead, behind, err = repo.AheadBehind(head.Branch().Target(), upstream.Target())
			check(err)
		}

		branch, err = head.Branch().Name()
		if err != nil {
			// head is detached
			branch = head.Branch().Target().String()[:7]
		}
		head.Free()
	}

	var dirty, modified, staged bool
	status, err := repo.StatusList(&git.StatusOptions{
		Flags: git.StatusOptIncludeUntracked,
	})
	check(err)
	count, err := status.EntryCount()
	check(err)
	if count != 0 {
		dirty = true
	}
	for i := 0; i < count; i++ {
		entry, err := status.ByIndex(i)
		check(err)
		if entry.Status&git.StatusWtNew != 0 || entry.Status&git.StatusWtModified != 0 || entry.Status&git.StatusWtDeleted != 0 || entry.Status&git.StatusWtTypeChange != 0 || entry.Status&git.StatusWtRenamed != 0 {
			modified = true
		}
		if entry.Status&git.StatusIndexNew != 0 || entry.Status&git.StatusIndexModified != 0 || entry.Status&git.StatusIndexDeleted != 0 || entry.Status&git.StatusIndexRenamed != 0 || entry.Status&git.StatusIndexTypeChange != 0 {
			staged = true
		}
	}
	status.Free()

	var segments []string
	switch domain {
	case "github.com":
		segments = append(segments, iconGithub)
	case "gitlab.com":
		segments = append(segments, iconGitlab)
	case "bitbucket.org":
		segments = append(segments, iconBitbucket)
	default:
		segments = append(segments, iconGit)
	}
	if stashes != 0 || ahead != 0 || behind != 0 {
		segments = append(segments, strings.Repeat(iconStash, stashes)+strings.Repeat(iconAhead, ahead)+strings.Repeat(iconBehind, behind))
	}
	if branch != "" {
		segments = append(segments, branch)
	}
	if dirty {
		segment.background = "yellow"

		var icons string
		if modified {
			icons += iconCircle
		}
		if staged {
			icons += iconPlus
		}
		if icons != "" {
			segments = append(segments, icons)
		}
	}
	segment.visible = true
	segment.value = strings.Join(segments, " ")
}
<|endoftext|>


<commit_before>package main

import (
  "./app/."
  "flag"
  "log"
)

func main() {
  //Get some Command line options
  config_file := flag.String("c", "./lib/config.gcfg", "location of config file")
  flag.Parse()

  //setup the config file
  cfg, err := app.Getconfig(config_file)
  if err != nil {
    log.Fatal(err)
  }

  list := app.InitMember(cfg)

  app.InitWebserver(list, cfg)
}
<commit_msg>switching to idiomatic import of the app package<commit_after>package main

import (
	"flag"
	"github.com/Tapjoy/riakQueue/app"
	"log"
)

func main() {
	//Get some Command line options
	config_file := flag.String("c", "./lib/config.gcfg", "location of config file")
	flag.Parse()

	//setup the config file
	cfg, err := app.Getconfig(config_file)
	if err != nil {
		log.Fatal(err)
	}

	list := app.InitMember(cfg)

	app.InitWebserver(list, cfg)
}
<|endoftext|>


<commit_before>// Implementing Conway's Game Of Life
// ----------------------------------
//
// Using a map for storing the current state of the world.
//
// We are printing the successive populations in a format that can be fed
// to gnuplot and creating in this way an animated view of the population.
//
// This is just an exercise for using maps in go! Do not take this
// too serious...
//
// To see the simulation in gnuplot, call the program like this:
// ./gol.exe | gnuplot --persist

package main

import (
	"github.com/spf13/cobra"
	"fmt"
	"strings"
	"strconv"
	"os"
)

// We are storing the cells (alive or dead) in a map. The keys are the Cartesian
// coordinates of the cells and the values are the properties of the cells,
// namely their state and number of alive neighbours.

// A cell has its state, and its number of life neighbours
type Cell struct {
	alive bool
	n int
}

// The coordinates are plain 2-d cartesian coordinates
type Coord struct {
	x int
	y int
}

// The world is a map of Coord and Cell
type World map[Coord]Cell

// Inflate inflates the world with dead cells surrounding
// the live cells
func (world World) Inflate() World {
	var newWorld World
	newWorld = make(World)

	for coord, cell := range world {
		newWorld[coord] = cell
		for i := -1; i < 2; i++ {
			for j := -1; j < 2; j++ {
				c := Coord{coord.x + i, coord.y + j}
				if _, found := newWorld[c]; !found {
					newWorld[c] = Cell{false, 0}
				}
			}
		}
	}

	return newWorld
}

// Deflate deflates the world: only the live cells remain
func (world World) Deflate() World {
	var newWorld World
	newWorld = make(World)

	for coord, cell := range world {
		if cell.alive {
			newWorld[coord] = cell
		}
	}

	return newWorld
}

// Tick computes the next generation of live cells in the world
func (world World) Tick() World {
	// count live neighbours for each cell
	for coord, cell := range world {
		n := 0
		for i := -1; i < 2; i++ {
			for j := -1; j < 2; j++ {
				c := Coord{coord.x + i, coord.y + j}
				if (i != 0 || j != 0) && world[c].alive {
					n = n+1
				}
			}
		}
		world[coord] = Cell{cell.alive, n}
	}

	var newWorld World
	newWorld = make(World)

	// apply the rules of the game to each cell
	for coord, cell := range world {
		if cell.alive {
			if 1 < cell.n && cell.n < 4 {
				newWorld[coord] = Cell{true, 0}
			}
		} else {
			if cell.n == 3 {
				newWorld[coord] = Cell{true, 0}
			}
		}
	}

	return newWorld
}

// gnuplotHeader prints the header for gnuplot
func gnuplotHeader(d int) {
	fmt.Printf("unset key; set xrange[-%[1]d:%[1]d]\n", d/2)
	fmt.Printf("set yrange[-%[1]d:%[1]d]\n", d/2)
	fmt.Println("set style line 1 lc rgb '#0060ad' pt 7")
}

// gnuplotWorld prints the coordinates of the cells in the world
func gnuplotWorld(world World) {
	fmt.Println("plot '-' with points ls 1")

	for coord := range world {
		fmt.Printf("%d, %d\n", coord.x, coord.y)
	}

	fmt.Println("e")
}

func main() {
	ticks := 10  // how many ticks the game is running
	pattern := "1,0;0,1;1,1;1,2;2,2"  // initial pattern of life cells
	d := 100 // width and height of gnuplot window: -d/2 <= x <= d/2 and -d/2 <= y <= d/2

	// Cobra configuration
	var rootCmd = &cobra.Command{
		Use: "gol",
		Short: "Run Conway's Game of Life",
		Long: `The Game of Life, also known simply as Life, is a
cellular automaton devised by the British mathematician John Horton Conway in
1970.

The "game" is a zero-player game, meaning that its evolution is determined by
its initial state, requiring no further input. One interacts with the Game of
Life by creating an initial configuration and observing how it evolves or, for
advanced players, by creating patterns with particular properties.`,
		Run: func(cmd *cobra.Command, args []string) {
			gol(d, pattern, ticks)
		},
	}

	rootCmd.Flags().IntVarP(&ticks, "ticks", "t", 10, "ticks to run the game")
	rootCmd.Flags().StringVarP(&pattern, "pattern", "p", "1,0;0,1;1,1;1,2;2,2", "initial pattern of live cells")
	rootCmd.Flags().IntVarP(&d, "dimension", "d", 50, "width and height of gnuplot window")

	rootCmd.Execute()
}

func gol(d int, pattern string, ticks int) {
	// The world
	var world World
	world = make(World)

	/*
	// Define a starting world: the r-Pentomino
	world[Coord{1, 0}] = Cell{true, 0}
	world[Coord{0, 1}] = Cell{true, 0}
	world[Coord{1, 1}] = Cell{true, 0}
	world[Coord{1, 2}] = Cell{true, 0}
	world[Coord{2, 2}] = Cell{true, 0}
	 */

	// The starting configuratio in the string cells
	coordinates := strings.Split(pattern, ";")

	for _, xy := range coordinates {
		c := strings.Split(xy, ",")
		if len(c) < 2 {
			fmt.Println("pattern error:", pattern, ":", xy)
			os.Exit(1)
		}
		x, err := strconv.Atoi(c[0])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		y, err := strconv.Atoi(c[1])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		world[Coord{x, y}] = Cell{true, 0}
	}

	gnuplotHeader(d)

	gnuplotWorld(world)

	for i := 0; i < ticks; i++ {
		world = world.Inflate().Tick().Deflate()
		gnuplotWorld(world)
	}
}
<commit_msg>Added measuring elapsed time.<commit_after>// Implementing Conway's Game Of Life
// ----------------------------------
//
// Using a map for storing the current state of the world.
//
// We are printing the successive populations in a format that can be fed
// to gnuplot and creating in this way an animated view of the population.
//
// This is just an exercise for using maps in go! Do not take this
// too serious...
//
// To see the simulation in gnuplot, call the program like this:
// ./gol.exe | gnuplot --persist

package main

import (
	"github.com/spf13/cobra"
	"fmt"
	"strings"
	"strconv"
	"os"
	"time"
)

// We are storing the cells (alive or dead) in a map. The keys are the Cartesian
// coordinates of the cells and the values are the properties of the cells,
// namely their state and number of alive neighbours.

// A cell has its state, and its number of life neighbours
type Cell struct {
	alive bool
	n int
}

// The coordinates are plain 2-d cartesian coordinates
type Coord struct {
	x int
	y int
}

// The world is a map of Coord and Cell
type World map[Coord]Cell

// Inflate inflates the world with dead cells surrounding
// the live cells
func (world World) Inflate() World {
	var newWorld World
	newWorld = make(World)

	for coord, cell := range world {
		newWorld[coord] = cell
		for i := -1; i < 2; i++ {
			for j := -1; j < 2; j++ {
				c := Coord{coord.x + i, coord.y + j}
				if _, found := newWorld[c]; !found {
					newWorld[c] = Cell{false, 0}
				}
			}
		}
	}

	return newWorld
}

// Deflate deflates the world: only the live cells remain
func (world World) Deflate() World {
	var newWorld World
	newWorld = make(World)

	for coord, cell := range world {
		if cell.alive {
			newWorld[coord] = cell
		}
	}

	return newWorld
}

// Tick computes the next generation of live cells in the world
func (world World) Tick() World {
	// count live neighbours for each cell
	for coord, cell := range world {
		n := 0
		for i := -1; i < 2; i++ {
			for j := -1; j < 2; j++ {
				c := Coord{coord.x + i, coord.y + j}
				if (i != 0 || j != 0) && world[c].alive {
					n = n+1
				}
			}
		}
		world[coord] = Cell{cell.alive, n}
	}

	var newWorld World
	newWorld = make(World)

	// apply the rules of the game to each cell
	for coord, cell := range world {
		if cell.alive {
			if 1 < cell.n && cell.n < 4 {
				newWorld[coord] = Cell{true, 0}
			}
		} else {
			if cell.n == 3 {
				newWorld[coord] = Cell{true, 0}
			}
		}
	}

	return newWorld
}

// gnuplotHeader prints the header for gnuplot
func gnuplotHeader(d int) {
	fmt.Printf("unset key; set xrange[-%[1]d:%[1]d]\n", d/2)
	fmt.Printf("set yrange[-%[1]d:%[1]d]\n", d/2)
	fmt.Println("set style line 1 lc rgb '#0060ad' pt 7")
}

// gnuplotWorld prints the coordinates of the cells in the world
func gnuplotWorld(world World) {
	fmt.Println("plot '-' with points ls 1")

	for coord := range world {
		fmt.Printf("%d, %d\n", coord.x, coord.y)
	}

	fmt.Println("e")
}

func main() {
	ticks := 10  // how many ticks the game is running
	pattern := "1,0;0,1;1,1;1,2;2,2"  // initial pattern of life cells
	d := 100 // width and height of gnuplot window: -d/2 <= x <= d/2 and -d/2 <= y <= d/2

	// Cobra configuration
	var rootCmd = &cobra.Command{
		Use: "gol",
		Short: "Run Conway's Game of Life",
		Long: `The Game of Life, also known simply as Life, is a
cellular automaton devised by the British mathematician John Horton Conway in
1970.

The "game" is a zero-player game, meaning that its evolution is determined by
its initial state, requiring no further input. One interacts with the Game of
Life by creating an initial configuration and observing how it evolves or, for
advanced players, by creating patterns with particular properties.`,
		Run: func(cmd *cobra.Command, args []string) {
			gol(d, pattern, ticks)
		},
	}

	rootCmd.Flags().IntVarP(&ticks, "ticks", "t", 10, "ticks to run the game")
	rootCmd.Flags().StringVarP(&pattern, "pattern", "p", "1,0;0,1;1,1;1,2;2,2", "initial pattern of live cells")
	rootCmd.Flags().IntVarP(&d, "dimension", "d", 50, "width and height of gnuplot window")

	rootCmd.Execute()
}

func gol(d int, pattern string, ticks int) {
	start := time.Now()

	// The world
	var world World
	world = make(World)

	/*
	// Define a starting world: the r-Pentomino
	world[Coord{1, 0}] = Cell{true, 0}
	world[Coord{0, 1}] = Cell{true, 0}
	world[Coord{1, 1}] = Cell{true, 0}
	world[Coord{1, 2}] = Cell{true, 0}
	world[Coord{2, 2}] = Cell{true, 0}
	 */

	// The starting configuratio in the string cells
	coordinates := strings.Split(pattern, ";")

	for _, xy := range coordinates {
		c := strings.Split(xy, ",")
		if len(c) < 2 {
			fmt.Println("pattern error:", pattern, ":", xy)
			os.Exit(1)
		}
		x, err := strconv.Atoi(c[0])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		y, err := strconv.Atoi(c[1])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		world[Coord{x, y}] = Cell{true, 0}
	}

	gnuplotHeader(d)

	gnuplotWorld(world)

	for i := 0; i < ticks; i++ {
		world = world.Inflate().Tick().Deflate()
		gnuplotWorld(world)
	}

	elapsed := time.Since(start)
	fmt.Printf("Elapsed: %s", elapsed)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/gorilla/context"
	"github.com/gorilla/sessions"
	"github.com/maiah/han.go/lib"
	"html/template"
	"log"
	"net/http"
)

var (
	store = sessions.NewCookieStore([]byte("smallelephantandbigfly"))
)

func main() {
	// Setup route handlers
	http.HandleFunc("/", index)
	http.HandleFunc("/login", login)
	http.HandleFunc("/logout", logout)
	http.HandleFunc("/home", home)
	http.HandleFunc("/settings", settings)

	// Start the server
	log.Println("Listening on port 5000")
	log.Fatal(http.ListenAndServe(":5000",
		context.ClearHandler(http.DefaultServeMux)))
}

// Route Handlers

func index(w http.ResponseWriter, r *http.Request) {
	path := r.URL.Path

	if len(path) >= 7 {
		path = r.URL.Path[0:7]
	}

	if path == "/public" {
		public(w, r) // invoke static file handler
	} else {
		fmt.Fprintf(w, "welcome my han.go")
	}
}

// Custom static file handling

func public(w http.ResponseWriter, r *http.Request) {
	file := r.URL.Path[1:]
	http.ServeFile(w, r, file)
}

type page struct {
	Message string
}

func login(w http.ResponseWriter, r *http.Request) {
	if lib.IsAuthorized(store, r) {
		http.Redirect(w, r, "/home", http.StatusFound)

	} else {
		loginPage := "pages/login.html"

		if r.Method == "GET" {
			t, _ := template.ParseFiles(loginPage)
			t.Execute(w, nil)

		} else if r.Method == "POST" {
			if lib.IsAuthenticated(store, w, r) {
				http.Redirect(w, r, "/home", http.StatusFound)

			} else {
				t, err := template.ParseFiles(loginPage)

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

				if t.Execute(w,
					&page{Message: "Invalid username/password"}) != nil {
					log.Fatal(err)
				}
			}
		}
	}
}

func logout(w http.ResponseWriter, r *http.Request) {
	session, _ := store.Get(r, "user-session")
	session.Options = &sessions.Options{MaxAge: -1}
	session.Values = nil
	session.Save(r, w)

	http.Redirect(w, r, "/login", http.StatusFound)
}

func home(w http.ResponseWriter, r *http.Request) {
	if lib.IsAuthorized(store, r) {
		homePage := "pages/home.html"
		t, err := template.ParseFiles(homePage)
		if err != nil {
			log.Fatal(err)
		}

		session, _ := store.Get(r, "user-session")

		t.Execute(w, &page{Message: session.Values["username"].(string)})

	} else {
		http.Redirect(w, r, "/login", http.StatusFound)
	}
}

func settings(w http.ResponseWriter, r *http.Request) {
	if lib.IsAuthorized(store, r, "ADMIN") {
		file := "pages/settings.html"
		http.ServeFile(w, r, file)

	} else {
		http.Redirect(w, r, "/login", http.StatusFound)
	}
}
<commit_msg>Used copy struct<commit_after>package main

import (
	"fmt"
	"github.com/gorilla/context"
	"github.com/gorilla/sessions"
	"github.com/maiah/han.go/lib"
	"html/template"
	"log"
	"net/http"
)

var (
	store = sessions.NewCookieStore([]byte("smallelephantandbigfly"))
)

func main() {
	// Setup route handlers
	http.HandleFunc("/", index)
	http.HandleFunc("/login", login)
	http.HandleFunc("/logout", logout)
	http.HandleFunc("/home", home)
	http.HandleFunc("/settings", settings)

	// Start the server
	log.Println("Listening on port 5000")
	log.Fatal(http.ListenAndServe(":5000",
		context.ClearHandler(http.DefaultServeMux)))
}

// Route Handlers

func index(w http.ResponseWriter, r *http.Request) {
	path := r.URL.Path

	if len(path) >= 7 {
		path = r.URL.Path[0:7]
	}

	if path == "/public" {
		public(w, r) // invoke static file handler
	} else {
		fmt.Fprintf(w, "welcome my han.go")
	}
}

// Custom static file handling

func public(w http.ResponseWriter, r *http.Request) {
	file := r.URL.Path[1:]
	http.ServeFile(w, r, file)
}

type page struct {
	Message string
}

func login(w http.ResponseWriter, r *http.Request) {
	if lib.IsAuthorized(store, r) {
		http.Redirect(w, r, "/home", http.StatusFound)

	} else {
		loginPage := "pages/login.html"

		if r.Method == "GET" {
			t, _ := template.ParseFiles(loginPage)
			t.Execute(w, nil)

		} else if r.Method == "POST" {
			if lib.IsAuthenticated(store, w, r) {
				http.Redirect(w, r, "/home", http.StatusFound)

			} else {
				t, err := template.ParseFiles(loginPage)

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

				if t.Execute(w,
					page{Message: "Invalid username/password"}) != nil {
					log.Fatal(err)
				}
			}
		}
	}
}

func logout(w http.ResponseWriter, r *http.Request) {
	session, _ := store.Get(r, "user-session")
	session.Options = &sessions.Options{MaxAge: -1}
	session.Values = nil
	session.Save(r, w)

	http.Redirect(w, r, "/login", http.StatusFound)
}

func home(w http.ResponseWriter, r *http.Request) {
	if lib.IsAuthorized(store, r) {
		homePage := "pages/home.html"
		t, err := template.ParseFiles(homePage)
		if err != nil {
			log.Fatal(err)
		}

		session, _ := store.Get(r, "user-session")

		t.Execute(w, page{Message: session.Values["username"].(string)})

	} else {
		http.Redirect(w, r, "/login", http.StatusFound)
	}
}

func settings(w http.ResponseWriter, r *http.Request) {
	if lib.IsAuthorized(store, r, "ADMIN") {
		file := "pages/settings.html"
		http.ServeFile(w, r, file)

	} else {
		http.Redirect(w, r, "/login", http.StatusFound)
	}
}
<|endoftext|>


<commit_before>/**
 * hub, core of chat application
 */

package tok

import (
	"expvar"
	"log"
)

var (
	expOnline = expvar.NewInt("tokOnline")
	expUp     = expvar.NewInt("tokUp")
	expDown   = expvar.NewInt("tokDown")
	expEnq    = expvar.NewInt("tokEnq")
	expDeq    = expvar.NewInt("tokDeq")
)

type frame struct {
	uid  int
	data []byte
}

type Hub struct {
	sso          bool
	actor        Actor
	q            Queue
	cons         map[int][]*connection //connection list
	chUp         chan *frame
	chDown       chan *frame //for online user
	chDown2      chan *frame //for all user
	chConState   chan *conState
	chReadSignal chan int
}

func (p *Hub) run() {
	for {
		select {
		case state := <-p.chConState:
			//			log.Printf("connection state change: %v, %v \n", state.online, &state.con)

			if state.online {
				p.online(state.con)
				expOnline.Add(1)
			} else {
				p.offline(state.con)
				expOnline.Add(-1)
			}
		case f := <-p.chUp:
			//			log.Println("up data")
			expUp.Add(1)
			go p.up(f)
		case f := <-p.chDown:
			expDown.Add(1)
			p.down(f)
		case f := <-p.chDown2:
			if len(p.cons[f.uid]) > 0 {
				expDown.Add(1)
				p.down(f)
			} else {
				expEnq.Add(1)
				go p.cache(f)
			}
		case uid := <-p.chReadSignal:
			//only pop msg for online user
			if len(p.cons[uid]) > 0 {
				go p.popMsg(uid)
			}
		}
	}
}

func (p *Hub) up(f *frame) {
	targets, b, err := p.actor.OnReceive(f.uid, f.data)
	if err != nil {
		log.Println("reply err", err)
		return
	}
	for _, uid := range targets {
		p.Send(uid, b, true)
	}
}

func (p *Hub) popMsg(uid int) {
	for {
		b, err := p.q.Deq(uid)
		if err != nil {
			log.Println("deq error", err)
			return
		}
		if b == nil {
			//no more data in queue
			return
		}
		expDeq.Add(1)
		p.chDown <- &frame{uid: uid, data: b}
	}
}

func (p *Hub) Send(to int, b []byte, cacheIfOffline bool) {
	f := &frame{uid: to, data: b}
	if cacheIfOffline {
		p.chDown2 <- f
	} else {
		p.chDown <- f
	}
}

func (p *Hub) cache(f *frame) {
	if err := p.q.Enq(f.uid, f.data); err != nil {
		log.Println("send binary to q err ", err)
	}
}

func (p *Hub) down(f *frame) {
	for _, con := range p.cons[f.uid] {
		con.ch <- f.data
	}
}

func (p *Hub) offline(conn *connection) {
	l := p.cons[conn.uid]
	rest := connExclude(l, conn)

	//this connection has gotten offline, ignore
	if len(l) == len(rest) {
		return
	}

	if len(rest) == 0 {
		delete(p.cons, conn.uid)
	} else {
		p.cons[conn.uid] = rest
	}

	conn.close()
}

func (p *Hub) online(conn *connection) {
	l := p.cons[conn.uid]
	if l == nil {
		l = []*connection{conn}
	} else {
		if p.sso {
			for _, old := range l {
				log.Printf("kick %v\n", old)
				//notify before close connection
				old.ch <- p.actor.Bye("sso")
				old.close()
			}
			l = []*connection{conn}
		} else {
			exists := false
			for _, c := range l {
				if c == conn {
					log.Println("warning, repeat online: ", c)
					exists = true
					break
				}
			}
			if !exists {
				l = append(l, conn)
			}
		}
	}
	p.cons[conn.uid] = l
	p.startRead(conn.uid)
}

func (p *Hub) startRead(uid int) {
	p.chReadSignal <- uid
}

func connExclude(l []*connection, ex *connection) []*connection {
	rest := make([]*connection, 0, len(l))
	for _, c := range l {
		if c != ex {
			rest = append(rest, c)
		}
	}
	return rest
}
<commit_msg>refactor<commit_after>/**
 * hub, core of chat application
 */

package tok

import (
	"expvar"
	"log"
)

var (
	expOnline = expvar.NewInt("tokOnline")
	expUp     = expvar.NewInt("tokUp")
	expDown   = expvar.NewInt("tokDown")
	expEnq    = expvar.NewInt("tokEnq")
	expDeq    = expvar.NewInt("tokDeq")
)

type frame struct {
	uid  int
	data []byte
}

type Hub struct {
	sso          bool
	actor        Actor
	q            Queue
	cons         map[int][]*connection //connection list
	chUp         chan *frame
	chDown       chan *frame //for online user
	chDown2      chan *frame //for all user
	chConState   chan *conState
	chReadSignal chan int
}

func (p *Hub) run() {
	for {
		select {
		case state := <-p.chConState:
			//			log.Printf("connection state change: %v, %v \n", state.online, &state.con)

			if state.online {
				p.online(state.con)
			} else {
				p.offline(state.con)
			}
			expOnline.Set(int64(len(p.cons)))
		case f := <-p.chUp:
			//			log.Println("up data")
			expUp.Add(1)
			go p.up(f)
		case f := <-p.chDown:
			expDown.Add(1)
			p.down(f)
		case f := <-p.chDown2:
			if len(p.cons[f.uid]) > 0 {
				expDown.Add(1)
				p.down(f)
			} else {
				expEnq.Add(1)
				go p.cache(f)
			}
		case uid := <-p.chReadSignal:
			//only pop msg for online user
			if len(p.cons[uid]) > 0 {
				go p.popMsg(uid)
			}
		}
	}
}

func (p *Hub) up(f *frame) {
	targets, b, err := p.actor.OnReceive(f.uid, f.data)
	if err != nil {
		log.Println("reply err", err)
		return
	}
	for _, uid := range targets {
		p.Send(uid, b, true)
	}
}

func (p *Hub) popMsg(uid int) {
	for {
		b, err := p.q.Deq(uid)
		if err != nil {
			log.Println("deq error", err)
			return
		}
		if b == nil {
			//no more data in queue
			return
		}
		expDeq.Add(1)
		p.chDown <- &frame{uid: uid, data: b}
	}
}

func (p *Hub) Send(to int, b []byte, cacheIfOffline bool) {
	f := &frame{uid: to, data: b}
	if cacheIfOffline {
		p.chDown2 <- f
	} else {
		p.chDown <- f
	}
}

func (p *Hub) cache(f *frame) {
	if err := p.q.Enq(f.uid, f.data); err != nil {
		log.Println("send binary to q err ", err)
	}
}

func (p *Hub) down(f *frame) {
	for _, con := range p.cons[f.uid] {
		con.ch <- f.data
	}
}

func (p *Hub) offline(conn *connection) {
	l := p.cons[conn.uid]
	rest := connExclude(l, conn)

	//this connection has gotten offline, ignore
	if len(l) == len(rest) {
		return
	}

	if len(rest) == 0 {
		delete(p.cons, conn.uid)
	} else {
		p.cons[conn.uid] = rest
	}

	conn.close()
}

func (p *Hub) online(conn *connection) {
	l := p.cons[conn.uid]
	if l == nil {
		l = []*connection{conn}
	} else {
		if p.sso {
			for _, old := range l {
				log.Printf("kick %v\n", old)
				//notify before close connection
				old.ch <- p.actor.Bye("sso")
				old.close()
			}
			l = []*connection{conn}
		} else {
			exists := false
			for _, c := range l {
				if c == conn {
					log.Println("warning, repeat online: ", c)
					exists = true
					break
				}
			}
			if !exists {
				l = append(l, conn)
			}
		}
	}
	p.cons[conn.uid] = l
	p.startRead(conn.uid)
}

func (p *Hub) startRead(uid int) {
	p.chReadSignal <- uid
}

func connExclude(l []*connection, ex *connection) []*connection {
	rest := make([]*connection, 0, len(l))
	for _, c := range l {
		if c != ex {
			rest = append(rest, c)
		}
	}
	return rest
}
<|endoftext|>


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

package main

import "fmt"

func main() {
    fmt.Printf("IBM header.\n")
}
<commit_msg>Delete ibm.go<commit_after><|endoftext|>


<commit_before>package ice

import "net"

func HostInterfaces() (ips []string) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return ips
	}

	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			continue // loopback interface
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return ips
		}
		for _, addr := range addrs {
			var ip net.IP
			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}
			if ip == nil || ip.IsLoopback() {
				continue
			}
			ip = ip.To4()
			if ip == nil {
				continue // not an ipv4 address
			}
			ips = append(ips, ip.String())
		}
	}
	return ips
}
<commit_msg>Fix all golint errors<commit_after>package ice

import "net"

// HostInterfaces generates a slice of all the IPs associated with interfaces
func HostInterfaces() (ips []string) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return ips
	}

	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			continue // loopback interface
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return ips
		}
		for _, addr := range addrs {
			var ip net.IP
			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}
			if ip == nil || ip.IsLoopback() {
				continue
			}
			ip = ip.To4()
			if ip == nil {
				continue // not an ipv4 address
			}
			ips = append(ips, ip.String())
		}
	}
	return ips
}
<|endoftext|>


<commit_before>// dulbecco is a IRC bot.
//
// Plugin support through external commands (bash, python, ...).
//
//   most of the code was copied from:
//   - https://github.com/fluffle/goirc
//   - https://github.com/thoj/go-ircevent
package dulbecco

import (
	"bufio"
	"crypto/tls"
	"log"
	"net"
	"strings"
	"sync"
	"time"
)

// A connection to the IRC server, also the main data structure of the IRC bot.
type Connection struct {
	// server address+port: "irc.example.com:6667"
	address string

	username, realname, nickname, password string
	altnicknames                           []string
	channels                               []string

	// ping frequency
	pingFreq time.Duration

	// enable anti-flood protection
	floodProtection bool
	// anti-flood internal counters
	badness         time.Duration
	lastSent        time.Time

	// IO
	sock      net.Conn
	io        *bufio.ReadWriter
	out       chan string
	connected bool

	// lock shutdown calls
	mutex sync.Mutex

	// SSL
	useTLS    bool
	sslConfig *tls.Config

	// Control channels
	cWrite chan bool
	cEvent chan bool
	cPing  chan bool
	CQuit  chan bool

	// callbacks
	events map[string]map[string]func(*Message)
}

func NewConnection(srvConfig *ServerType, genConfig *ConfigurationType, quit chan bool) *Connection {
	// get configuration values from the server config object, falling back
	// to the global config.
	var nickname, username, realname string
	var altnicknames []string

	if nickname = srvConfig.Nickname; len(nickname) == 0 {
		nickname = genConfig.Nickname
	}
	if username = srvConfig.Username; len(username) == 0 {
		username = genConfig.Username
	}
	if realname = srvConfig.Realname; len(realname) == 0 {
		realname = genConfig.Realname
	}

	if len(srvConfig.Altnicknames) > 0 {
		altnicknames = append(altnicknames, srvConfig.Altnicknames...)
	} else {
		altnicknames = append(altnicknames, genConfig.Altnicknames...)
	}

	conn := &Connection{
		address:         srvConfig.Address,
		password:        srvConfig.Password,
		useTLS:          srvConfig.Ssl,
		sslConfig:       nil,
		pingFreq:        3 * time.Minute,
		username:        username,
		realname:        realname,
		nickname:        nickname,
		altnicknames:    altnicknames,
		channels:        srvConfig.Channels,
		out:             make(chan string, 32),
		cWrite:          make(chan bool),
		cPing:           make(chan bool),
		floodProtection: true,
		badness:         0,
		lastSent:        time.Now(),
		CQuit:           quit,
	}

	// setup internal callbacks
	conn.SetupCallbacks()
	conn.SetupPlugins(genConfig.Plugins)

	return conn
}

// Connect to the server, launch all internal goroutines.
func (c *Connection) Connect() error {
	if c.useTLS {
		if s, err := tls.Dial("tcp", c.address, c.sslConfig); err == nil {
			c.sock = s
		} else {
			return err
		}
	} else {
		if s, err := net.Dial("tcp", c.address); err == nil {
			c.sock = s
		} else {
			return err
		}
	}

	log.Println("Connected to:", c.address)
	c.connected = true

	c.io = bufio.NewReadWriter(
		bufio.NewReader(c.sock),
		bufio.NewWriter(c.sock))

	go c.writeLoop()
	go c.readLoop()
	go c.pingLoop()

	c.RunCallbacks(&Message{Cmd: "INIT"})

	return nil
}

func (c *Connection) writeLoop() {
	for {
		select {
		case line := <-c.out:
			c.write(line)
		case <-c.cWrite:
			return
		}
	}
}

func (c *Connection) readLoop() {
	for {
		line, err := c.io.ReadString('\n')
		if err != nil {
			log.Println("read failed:", err)
			go c.shutdown()
			return
		}

		line = strings.TrimRight(line, "\r\n")
		// log.Println("READ: ", line)

		if message := parseMessage(line); message != nil {
			log.Println("message =", message.Dump())
			c.RunCallbacks(message)
		} else {
			log.Println("parsing failed for line:", line)
		}
	}
}

func (c *Connection) pingLoop() {
	tick := time.NewTicker(c.pingFreq)

	for {
		select {
		case <-tick.C:
			c.ServerPing()
		case <-c.cPing:
			tick.Stop()
			return
		}
	}
}

func (c *Connection) write(line string) {
	if !c.floodProtection {
		if t := c.rateLimit(len(line)); t != 0 {
			log.Println("anti-flood: sleeping for %.2f seconds", t.Seconds())
			<-time.After(t)
		}
	}

	if _, err := c.io.WriteString(line); err != nil {
		log.Println("write failed: ", err)
		go c.shutdown()
		return
	}

	if err := c.io.Flush(); err != nil {
		log.Println("flush failed: ", err)
		go c.shutdown()
		return
	}

	// log.Println("wrote line: ", line)
}

func (c *Connection) rateLimit(chars int) time.Duration {
	lineTime := 2*time.Second + time.Duration(chars)*time.Second/120
	elapsed := time.Now().Sub(c.lastSent)
	if c.badness += lineTime - elapsed; c.badness < 0 {
		c.badness = 0
	}
	c.lastSent = time.Now()

	if c.badness > 10*time.Second {
		return lineTime
	}

	return 0
}

func (c *Connection) shutdown() {
	c.mutex.Lock()
	log.Println("enter shutdown()")

	if c.connected {
		log.Println("shutting down connection")

		c.connected = false
		c.sock.Close()
		c.cWrite <- true
		c.cPing <- true

		c.io = nil
		c.sock = nil

		c.RunCallbacks(&Message{Cmd: "DISCONNECT"})
		c.CQuit <- true
		log.Println("end of shutdown")
	}
	c.mutex.Unlock()
	log.Println("exit shutdown()")
}
<commit_msg>exit from the write loop on the first network error<commit_after>// dulbecco is a IRC bot.
//
// Plugin support through external commands (bash, python, ...).
//
//   most of the code was copied from:
//   - https://github.com/fluffle/goirc
//   - https://github.com/thoj/go-ircevent
package dulbecco

import (
	"bufio"
	"crypto/tls"
	"log"
	"net"
	"strings"
	"sync"
	"time"
)

// A connection to the IRC server, also the main data structure of the IRC bot.
type Connection struct {
	// server address+port: "irc.example.com:6667"
	address string

	username, realname, nickname, password string
	altnicknames                           []string
	channels                               []string

	// ping frequency
	pingFreq time.Duration

	// enable anti-flood protection
	floodProtection bool
	// anti-flood internal counters
	badness         time.Duration
	lastSent        time.Time

	// IO
	sock      net.Conn
	io        *bufio.ReadWriter
	out       chan string
	connected bool

	// lock shutdown calls
	mutex sync.Mutex

	// SSL
	useTLS    bool
	sslConfig *tls.Config

	// Control channels
	cWrite chan bool
	cEvent chan bool
	cPing  chan bool
	CQuit  chan bool

	// callbacks
	events map[string]map[string]func(*Message)
}

func NewConnection(srvConfig *ServerType, genConfig *ConfigurationType, quit chan bool) *Connection {
	// get configuration values from the server config object, falling back
	// to the global config.
	var nickname, username, realname string
	var altnicknames []string

	if nickname = srvConfig.Nickname; len(nickname) == 0 {
		nickname = genConfig.Nickname
	}
	if username = srvConfig.Username; len(username) == 0 {
		username = genConfig.Username
	}
	if realname = srvConfig.Realname; len(realname) == 0 {
		realname = genConfig.Realname
	}

	if len(srvConfig.Altnicknames) > 0 {
		altnicknames = append(altnicknames, srvConfig.Altnicknames...)
	} else {
		altnicknames = append(altnicknames, genConfig.Altnicknames...)
	}

	conn := &Connection{
		address:         srvConfig.Address,
		password:        srvConfig.Password,
		useTLS:          srvConfig.Ssl,
		sslConfig:       nil,
		pingFreq:        3 * time.Minute,
		username:        username,
		realname:        realname,
		nickname:        nickname,
		altnicknames:    altnicknames,
		channels:        srvConfig.Channels,
		out:             make(chan string, 32),
		cWrite:          make(chan bool),
		cPing:           make(chan bool),
		floodProtection: true,
		badness:         0,
		lastSent:        time.Now(),
		CQuit:           quit,
	}

	// setup internal callbacks
	conn.SetupCallbacks()
	conn.SetupPlugins(genConfig.Plugins)

	return conn
}

// Connect to the server, launch all internal goroutines.
func (c *Connection) Connect() error {
	if c.useTLS {
		if s, err := tls.Dial("tcp", c.address, c.sslConfig); err == nil {
			c.sock = s
		} else {
			return err
		}
	} else {
		if s, err := net.Dial("tcp", c.address); err == nil {
			c.sock = s
		} else {
			return err
		}
	}

	log.Println("Connected to:", c.address)
	c.connected = true

	c.io = bufio.NewReadWriter(
		bufio.NewReader(c.sock),
		bufio.NewWriter(c.sock))

	go c.writeLoop()
	go c.readLoop()
	go c.pingLoop()

	c.RunCallbacks(&Message{Cmd: "INIT"})

	return nil
}

func (c *Connection) writeLoop() {
	for {
		select {
		case line := <-c.out:
			err := c.write(line)
			if err != nil {
				log.Println("ERROR writing:", err)
				go c.shutdown()
				return
			}
		case <-c.cWrite:
			return
		}
	}
}

func (c *Connection) readLoop() {
	for {
		line, err := c.io.ReadString('\n')
		if err != nil {
			log.Println("read failed:", err)
			go c.shutdown()
			return
		}

		line = strings.TrimRight(line, "\r\n")
		// log.Println("READ: ", line)

		if message := parseMessage(line); message != nil {
			log.Println("message =", message.Dump())
			c.RunCallbacks(message)
		} else {
			log.Println("parsing failed for line:", line)
		}
	}
}

func (c *Connection) pingLoop() {
	tick := time.NewTicker(c.pingFreq)

	for {
		select {
		case <-tick.C:
			c.ServerPing()
		case <-c.cPing:
			tick.Stop()
			return
		}
	}
}

func (c *Connection) write(line string) error {
	if !c.floodProtection {
		if t := c.rateLimit(len(line)); t != 0 {
			log.Println("anti-flood: sleeping for %.2f seconds", t.Seconds())
			<-time.After(t)
		}
	}

	if _, err := c.io.WriteString(line); err != nil {
		return err
	}

	if err := c.io.Flush(); err != nil {
		return err
	}
	return nil
}

func (c *Connection) rateLimit(chars int) time.Duration {
	lineTime := 2*time.Second + time.Duration(chars)*time.Second/120
	elapsed := time.Now().Sub(c.lastSent)
	if c.badness += lineTime - elapsed; c.badness < 0 {
		c.badness = 0
	}
	c.lastSent = time.Now()

	if c.badness > 10*time.Second {
		return lineTime
	}

	return 0
}

func (c *Connection) shutdown() {
	c.mutex.Lock()
	log.Println("enter shutdown()")

	if c.connected {
		log.Println("shutting down connection")

		c.connected = false
		c.sock.Close()
		c.cWrite <- true
		c.cPing <- true

		c.io = nil
		c.sock = nil

		c.RunCallbacks(&Message{Cmd: "DISCONNECT"})
		c.CQuit <- true
		log.Println("end of shutdown")
	}
	c.mutex.Unlock()
	log.Println("exit shutdown()")
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package fdroidcl

import (
	"archive/zip"
	"errors"
	"io"
	"regexp"
)

const indexPath = "index-v1.json"

var (
	sigRegex = regexp.MustCompile(`^META-INF/.*\.(DSA|EC|RSA)$`)

	ErrNoIndex     = errors.New("no json index found inside jar")
	ErrNoSigs      = errors.New("no jar signatures found")
	ErrTooManySigs = errors.New("multiple jar signatures found")
)

func verifySignature(pubkey []byte, sig io.Reader) error {
	// TODO: Implement
	return nil
}

func LoadIndexJar(r io.ReaderAt, size int64, pubkey []byte) (*Index, error) {
	reader, err := zip.NewReader(r, size)
	if err != nil {
		return nil, err
	}
	var index, sig io.ReadCloser
	for _, f := range reader.File {
		if f.Name == indexPath {
			index, err = f.Open()
			if err != nil {
				return nil, err
			}
		} else if sigRegex.MatchString(f.Name) {
			if sig != nil {
				return nil, ErrTooManySigs
			}
			sig, err = f.Open()
			if err != nil {
				return nil, err
			}
		}
	}
	if index == nil {
		return nil, ErrNoIndex
	}
	defer index.Close()
	if sig == nil {
		return nil, ErrNoSigs
	}
	defer sig.Close()
	if err := verifySignature(pubkey, sig); err != nil {
		return nil, err
	}
	return LoadIndexJSON(index)
}
<commit_msg>remove jar signature verification skeleton code<commit_after>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package fdroidcl

import (
	"archive/zip"
	"errors"
	"io"
)

const indexPath = "index-v1.json"

var ErrNoIndex = errors.New("no json index found inside jar")

func LoadIndexJar(r io.ReaderAt, size int64, pubkey []byte) (*Index, error) {
	reader, err := zip.NewReader(r, size)
	if err != nil {
		return nil, err
	}
	var index io.ReadCloser
	for _, f := range reader.File {
		if f.Name == indexPath {
			index, err = f.Open()
			if err != nil {
				return nil, err
			}
			break
		}
	}
	if index == nil {
		return nil, ErrNoIndex
	}
	defer index.Close()
	return LoadIndexJSON(index)
}
<|endoftext|>