grim/convey

Bump the version for release
v0.14.0-alpha3
2018-02-20, Gary Kramlich
166a6d1979fa
Bump the version for release
// Convey
// Copyright 2016-2018 Gary Kramlich <grim@reaperworld.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Package command provides utilities for running external commands.
package command
import (
"math"
"sync"
)
const (
minAlloc = 10
)
// Generator represents a command generator.
type Generator struct {
args []string
next int
lock sync.Mutex
}
// NewGenerator creates a new generator initialized with the gives arguments.
func NewGenerator(args ...string) *Generator {
g := &Generator{
args: make([]string, minAlloc),
next: 0,
}
g.Appendv(args)
return g
}
// resize will resize the slice to the required size or minimum allocation
// which ever is larger.
func (g *Generator) resize(reqSize int) {
if g.next >= len(g.args) {
newSize := len(g.args)
if reqSize > minAlloc {
newSize += reqSize
} else {
newSize += minAlloc
}
newArgs := make([]string, newSize)
copy(newArgs, g.args)
g.args = newArgs
}
}
// Append appends the given arguments to the end of the arguments.
func (g *Generator) Append(args ...string) {
g.Appendv(args)
}
// Appendv appends the give string slice to the command
func (g *Generator) Appendv(args []string) {
g.lock.Lock()
defer g.lock.Unlock()
if len(args) <= 0 {
return
}
for _, item := range args {
g.resize(1)
g.args[g.next] = item
g.next++
}
}
// Prepend prepends the given arguments to the beginning of the arguments.
func (g *Generator) Prepend(args ...string) {
g.Prependv(args)
}
// Prependv prepends the given string slice to the command.
func (g *Generator) Prependv(args []string) {
g.lock.Lock()
defer g.lock.Unlock()
if len(args) <= 0 {
return
}
// allocate a new slice that's the size of the
newSize := int(math.Max(float64(len(args)), float64(minAlloc))) + len(g.args)
newArgs := make([]string, newSize)
// set our current index to 0
idx := 0
// add the prepended items
for ; idx < len(args); idx++ {
newArgs[idx] = args[idx]
}
// add the original items
offset := len(args)
for ; idx < g.next+offset; idx++ {
newArgs[idx] = g.args[idx-offset]
}
// now assign newArgs
g.args = newArgs
g.next += len(args)
}
// Command returns the currently built command.
func (g *Generator) Command() []string {
g.lock.Lock()
defer g.lock.Unlock()
ret := make([]string, g.next)
for i := 0; i < g.next; i++ {
ret[i] = g.args[i]
}
return ret
}