util

package
v0.0.0-...-48fa796 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 10, 2021 License: GPL-3.0 Imports: 16 Imported by: 0

Documentation

Overview

Package util contains a collection of miscellaneous utility functions.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Basename

func Basename(p string) string

Basename is the base of a path string.

func Bool

func Bool(x interface{}) bool

Bool returns the interface value if it is a bool, and otherwise it panics.

func BoolMapTrue

func BoolMapTrue(l []bool) bool

BoolMapTrue returns true if everyone in the list is true.

func BoolMapValues

func BoolMapValues(m map[string]bool) []bool

BoolMapValues returns the sorted list of bool values in a map with string values.

func CloseAfter

func CloseAfter(ctx context.Context, d time.Duration) <-chan struct{}

CloseAfter takes a duration, similarly to `time.After`, and returns a channel that closes when either the context is done, or the duration expires.

func Code

func Code(code string) string

Code takes a code block as a backtick enclosed `heredoc` and removes any common indentation from each line. This helps inline code as strings to be formatted nicely without unnecessary indentation. It also drops the very first line of code if it has zero length.

func ContextWithCloser

func ContextWithCloser(ctx context.Context, ch <-chan struct{}) (context.Context, context.CancelFunc)

ContextWithCloser wraps a context and returns a new one exactly like the other context.With* functions, except that it takes a channel as an alternate cancel signal. TODO: switch to interface{} instead of <-chan struct to allow any chan type.

func CopyDiskContentsToFs

func CopyDiskContentsToFs(dstFs afero.Fs, src, dst string, force bool) error

CopyDiskContentsToFs performs exactly as CopyFs, except that the src fs is our local disk os fs, and we don't keep the source dir name, we only copy the contents.

func CopyDiskToFs

func CopyDiskToFs(dstFs afero.Fs, src, dst string, force bool) error

CopyDiskToFs performs exactly as CopyFs, except that the src fs is our local disk os fs.

func CopyDiskToFsAll

func CopyDiskToFsAll(dstFs afero.Fs, src, dst string, force, all bool) error

CopyDiskToFsAll performs exactly as CopyDiskToFs, except that it allows you to specify the `all` argument which switches CopyFs to using MkdirAll instead of the regular Mkdir. TODO: This works around weird copying issues. POSIX is hard.

func CopyFs

func CopyFs(srcFs, dstFs afero.Fs, src, dst string, force bool, all bool) error

CopyFs copies a dir from the srcFs to a dir on the dstFs. It expects that the dst will be either empty, or that the force flag will be set to true. If the dst has a different set of contents in the same location, the behaviour is currently undefined. TODO: this should be made more rsync like and robust!

func CopyFsContents

func CopyFsContents(srcFs afero.Fs, dstFs afero.Fs, src string, dst string, force bool) error

CopyFsContents copies a dir from the srcFs to a dir on the dstFs. It expects that the dst will be either empty, or that the force flag will be set to true. If the dst has a different set of contents in the same location, the behaviour is currently undefined. Notably, this does not copy the src dir itself, and only includes the contents. This is similar to `rsync dir/` vs. `rsync dir`. This function does the former, where as CopyFs does the latter. TODO: this should be made more rsync like and robust!

func CopyFsContentsToDisk

func CopyFsContentsToDisk(srcFs afero.Fs, src, dst string, force bool) error

CopyFsContentsToDisk performs exactly as CopyFs, except that the dst fs is our local disk os fs, and we don't keep the source dir name, we only copy the contents.

func CopyFsToDisk

func CopyFsToDisk(srcFs afero.Fs, src, dst string, force bool) error

CopyFsToDisk performs exactly as CopyFs, except that the dst fs is our local disk os fs.

func CtxWithWg

func CtxWithWg(ctx context.Context, wg *sync.WaitGroup) context.Context

CtxWithWg takes a context and a wait group, and returns a new context that is embedded with the wait group. You must use WgFromCtx to extract it.

func DirParents

func DirParents(p string) []string

DirParents returns a list of the parent directories in a given path. If you pass it an empty string, or a single slash, then you will get an empty list. If you pass it a malformed path, then you might get unexpected results.

func DirifyFileList

func DirifyFileList(fileList []string, removeDirs bool) []string

DirifyFileList adds trailing slashes to any likely dirs in a package manager fileList if removeDirs is true, otherwise, don't keep the dirs in our output.

func Dirname

func Dirname(p string) string

Dirname is similar to the GNU dirname command.

func ExpandHome

func ExpandHome(p string) (string, error)

ExpandHome does an expansion of ~/ or ~james/ into user's home dir value.

func FirstToUpper

func FirstToUpper(str string) string

FirstToUpper returns the string with the first character capitalized.

func FlattenListWithSplit

func FlattenListWithSplit(input []string, split []string) []string

FlattenListWithSplit flattens a list of input by splitting each element by any and all of the strings listed in the split array

func FsTree

func FsTree(fs afero.Fs, name string) (string, error)

FsTree returns a string representation of the file system tree similar to the well-known `tree` command.

func HasPathPrefix

func HasPathPrefix(p, prefix string) bool

HasPathPrefix tells us if a path string contain the given path prefix in it.

func MissingMkdirs

func MissingMkdirs(input []string) ([]string, error)

MissingMkdirs takes a list of paths, and returns a list of any missing paths that would be needed to avoid having to `mkdir -p` to prevent missing parent directory errors from happening. This adds paths all the way up to the root, but without including it, because it's implied. TODO: do we want to include the root? TODO: this could probably be implemented in a more efficient way...

func NumToAlpha

func NumToAlpha(idx int) string

NumToAlpha returns a lower case string of letters representing a number. If you specify 0, you'll get `a`, 25 gives you `z`, and 26 gives you `aa` and so on...

func PathPrefixDelta

func PathPrefixDelta(p, prefix string) int

PathPrefixDelta returns the delta of the path prefix, which tells you how many path tokens different the prefix is.

func PathSplit

func PathSplit(p string) []string

PathSplit splits a path into an array of tokens excluding any trailing empty tokens.

func PathSplitFullReversed

func PathSplitFullReversed(p string) []string

PathSplitFullReversed returns the full list of "dependency" paths for a given path in reverse order.

func PriorityStrSliceSort

func PriorityStrSliceSort(input []string, fn func(string) bool) []string

PriorityStrSliceSort filters any elements matching fn to the end of the list. You can reverse the match result with a not to filter to the front instead! A copy of the list is returned, the original is not modified.

func Rebase

func Rebase(path, base, root string) (string, error)

Rebase takes an absolute base path (directory prefix) and removes it from an absolute path and then returns that path with a new root as an absolute path if root is an absolute dir, and as a relative path if root is a relative dir. Eg: Rebase("/usr/bin/foo", "/usr/", "/usr/local/") -> "/usr/local/bin/foo" Eg: Rebase("/var/lib/dir/file.conf", "/var/lib/", "") -> "dir/file.conf"

func RemoveBasePath

func RemoveBasePath(path, base string) (string, error)

RemoveBasePath removes an absolute base path (directory prefix) from an absolute path that is any file or directory. Eg: RemoveBasePath("/usr/bin/foo", "/usr/") -> "bin/foo" Eg: RemoveBasePath("/usr/bin/project/", "/usr/") -> "bin/project/".

func RemoveCommonFilePrefixes

func RemoveCommonFilePrefixes(paths []string) []string

RemoveCommonFilePrefixes removes redundant file path prefixes that are under the tree of other files.

func RemovePathPrefix

func RemovePathPrefix(s string) (string, error)

RemovePathPrefix takes an absolute path and removes the first chunk. It returns the remainder as an absolute path. This function is a bit of a hack, and could probably be re-written to support any kind of path, and return a relative path.

func RemovePathSuffix

func RemovePathSuffix(s string) (string, error)

RemovePathSuffix takes an absolute path and removes the last chunk. It returns the remainder as an absolute path. This function is a bit of a hack, and could probably be re-written to support any kind of path, and return a relative path.

func ReverseStringList

func ReverseStringList(in []string) []string

ReverseStringList reverses a list of strings.

func SessionBusPrivateUsable

func SessionBusPrivateUsable() (conn *dbus.Conn, err error)

SessionBusPrivateUsable makes using the private bus usable. TODO: should be upstream: https://github.com/godbus/dbus/issues/15

func SortMapStringValuesByUInt64Keys

func SortMapStringValuesByUInt64Keys(m map[uint64]string) []string

SortMapStringValuesByUInt64Keys builds a list of strings, sorted by the corresponding key that is associated with that value. TODO: add some tests

func SortedStrSliceCompare

func SortedStrSliceCompare(a, b []string) error

SortedStrSliceCompare takes two lists of strings and returns whether or not they are equivalent. It will return nil if both sets contain the same elements, regardless of order, and an error if they do not.

func StrFilterElementsInList

func StrFilterElementsInList(filter []string, list []string) []string

StrFilterElementsInList removes any of the elements in filter, if they exist in the list.

func StrInList

func StrInList(needle string, haystack []string) bool

StrInList returns true if a string exists inside a list, otherwise false.

func StrInPathPrefixList

func StrInPathPrefixList(needle string, haystack []string) bool

StrInPathPrefixList returns true if the needle is a PathPrefix in the haystack.

func StrListIntersection

func StrListIntersection(list1 []string, list2 []string) []string

StrListIntersection removes any of the elements in filter, if they don't exist in the list. This is an in order intersection of two lists.

func StrMapKeys

func StrMapKeys(m map[string]string) []string

StrMapKeys return the sorted list of string keys in a map with string keys. NOTE: i thought it would be nice for this to use: map[string]interface{} but it turns out that's not allowed. I know we don't have generics, but come on!

func StrMapKeysUint64

func StrMapKeysUint64(m map[string]uint64) []string

StrMapKeysUint64 return the sorted list of string keys in a map with string keys but uint64 values.

func StrMapValues

func StrMapValues(m map[string]string) []string

StrMapValues returns the sorted list of string values in a map with string values.

func StrMapValuesUint64

func StrMapValuesUint64(m map[uint64]string) []string

StrMapValuesUint64 return the sorted list of string values in a map with string values.

func StrRemoveDuplicatesInList

func StrRemoveDuplicatesInList(list []string) []string

StrRemoveDuplicatesInList removes any duplicate values in the list. This implementation is possibly sub-optimal (O(n^2)?) but preserves ordering.

func SystemBusPrivateUsable

func SystemBusPrivateUsable() (conn *dbus.Conn, err error)

SystemBusPrivateUsable makes using the private bus usable. TODO: should be upstream: https://github.com/godbus/dbus/issues/15

func TestDir

func TestDir(suffix string) (string, error)

TestDir gets the absolute path to the test directory if it exists. If the dir does not exist, then this will error, but the path will still be returned. This is a utility function that is used in some tests.

func TestDirFull

func TestDirFull() (string, error)

TestDirFull gets the full absolute path to a unique test directory if it exists. If the dir does not exist, then this will error, but the path will still be returned. This is a utility function that is used in some tests.

func TimeAfterOrBlock

func TimeAfterOrBlock(t int) <-chan time.Time

TimeAfterOrBlock is aspecial version of time.After that blocks when given a negative integer. When used in a case statement, the timer restarts on each select call to it.

func TimeAfterOrBlockCtx

func TimeAfterOrBlockCtx(ctx context.Context, t int) <-chan struct{}

TimeAfterOrBlockCtx returns a channel that closes after a timeout. If you use a negative timeout, it will block forever. It can also unblock using context. Make sure to cancel the context when you're done, or you'll leak a goroutine.

func Uint

func Uint(x interface{}) uint

Uint returns the interface value if it is a uint, and otherwise it panics.

func Uint64KeyFromStrInMap

func Uint64KeyFromStrInMap(needle string, haystack map[uint64]string) (uint64, bool)

Uint64KeyFromStrInMap returns true if needle is found in haystack of keys that have uint64 type.

func WgFromCtx

func WgFromCtx(ctx context.Context) *sync.WaitGroup

WgFromCtx takes a context and returns the stored wait group. You must use CtxWithWg to store it.

Types

type EasyAck

type EasyAck struct {
	// contains filtered or unexported fields
}

EasyAck is a wrapper to build ack functionality into a simple interface.

func NewEasyAck

func NewEasyAck() *EasyAck

NewEasyAck builds the object. This must be called before use.

func (*EasyAck) Ack

func (obj *EasyAck) Ack()

Ack sends the acknowledgment message. This can only be called once.

func (*EasyAck) Wait

func (obj *EasyAck) Wait() <-chan struct{}

Wait returns a channel that you can wait on for the ack message.

type EasyAckOnce

type EasyAckOnce struct {
	// contains filtered or unexported fields
}

EasyAckOnce is a wrapper to build ack functionality into a simple interface. It is safe because the Ack function can be called multiple times safely.

func NewEasyAckOnce

func NewEasyAckOnce() *EasyAckOnce

NewEasyAckOnce builds the object. This must be called before use.

func (*EasyAckOnce) Ack

func (obj *EasyAckOnce) Ack()

Ack sends the acknowledgment message. This can be called as many times as you like. Only the first Ack is meaningful. Subsequent Ack's are redundant. It is thread-safe.

func (*EasyAckOnce) Wait

func (obj *EasyAckOnce) Wait() <-chan struct{}

Wait returns a channel that you can wait on for the ack message. The return channel closes on the first Ack it receives. Subsequent Ack's have no effect.

type EasyExit

type EasyExit struct {
	// contains filtered or unexported fields
}

EasyExit is a struct that helps you build a close switch and signal which can be called multiple times safely, and used as a signal many times in parallel. It can also provide a context, if you prefer to use that as a signal instead.

func NewEasyExit

func NewEasyExit() *EasyExit

NewEasyExit builds an easy exit struct.

func (*EasyExit) Context

func (obj *EasyExit) Context() context.Context

Context returns a context that is canceled when the Done signal is triggered. This can be used in addition to or instead of the Signal method.

func (*EasyExit) Done

func (obj *EasyExit) Done(err error)

Done triggers the exit signal. It associates an error condition with it too. This is thread-safe.

func (*EasyExit) Error

func (obj *EasyExit) Error() error

Error returns the error condition associated with the Done signal. It blocks until Done is called at least once. It then returns any of the errors or nil. It is only guaranteed to at least return the error from the first Done error.

func (*EasyExit) Signal

func (obj *EasyExit) Signal() <-chan struct{}

Signal returns the channel that we watch for the exit signal on. It will close to signal us when triggered by Exit().

type EasyOnce

type EasyOnce struct {
	Func func()
	// contains filtered or unexported fields
}

EasyOnce is a wrapper for the sync.Once functionality which lets you define and register the associated `run once` function at declaration time. It may be copied at any time.

func (*EasyOnce) Done

func (obj *EasyOnce) Done()

Done runs the function which was defined in `Func` a maximum of once. Please note that this is not currently thread-safe. Wrap calls to this with a mutex.

type Fs

type Fs struct {
	*afero.Afero
}

Fs is a simple wrapper to a file system to be used for standalone deploys. This is basically a pass-through so that we fulfill the same interface that the deploy mechanism uses. To use this, wrap it with the implied field name, which will prevent `go vet` warnings, eg: `fs := &util.Fs{Afero: afs}`. NOTE: This struct is here, since I don't know where else to put it for now.

func (*Fs) URI

func (obj *Fs) URI() string

URI returns the unique URI of this filesystem. It returns the root path.

type PathSlice

type PathSlice []string

PathSlice is a type used to implement sort.Interface on a slice of strings, where each string is a path. This allows you to call sort.Sort() on a list of paths, after casting the []string{} to this type. Paths will be sorted by depth in alphabetical order.

func (PathSlice) Len

func (obj PathSlice) Len() int

Len returns the length of obj. It is required to satisfy sort.Interface.

func (PathSlice) Less

func (obj PathSlice) Less(i, j int) bool

Less returns whether obj[i] is less than obj[j]. It performs the logic required to satisfy sort.Interface.

func (PathSlice) Sort

func (obj PathSlice) Sort()

Sort is a convenience method.

func (PathSlice) Swap

func (obj PathSlice) Swap(i, j int)

Swap swaps obj[i] and obj[j]. it is required to satisfy sort.Interface.

type SubscribedSignal

type SubscribedSignal struct {
	// contains filtered or unexported fields
}

SubscribedSignal represents a synchronized read signal. It doesn't need to be instantiated before it can be used. It must not be copied after first use. It is equivalent to receiving a multicast signal from a closing channel, except that it must be acknowledged by every reader of the signal, and once this is done, it is reset and can be re-used. Readers must obtain a handle to the signal with the Subscribe method, and the signal is sent out with the Done method.

Example
fmt.Println("hello")

x := &SubscribedSignal{}
wg := &sync.WaitGroup{}
ready := &sync.WaitGroup{}

// unit1
wg.Add(1)
ready.Add(1)
go func() {
	defer wg.Done()
	ch, ack := x.Subscribe()
	ready.Done()
	select {
	case <-ch:
		fmt.Println("got signal")
	}
	time.Sleep(1 * time.Second) // wait a bit for fun
	fmt.Println("(1) sending ack...")
	ack() // must call ack
	fmt.Println("done sending ack")
}()

// unit2
wg.Add(1)
ready.Add(1)
go func() {
	defer wg.Done()
	ch, ack := x.Subscribe()
	ready.Done()
	select {
	case <-ch:
		fmt.Println("got signal")
	}
	time.Sleep(2 * time.Second) // wait a bit for fun
	fmt.Println("(2) sending ack...")
	ack() // must call ack
	fmt.Println("done sending ack")
}()

// unit3
wg.Add(1)
ready.Add(1)
go func() {
	defer wg.Done()
	ch, ack := x.Subscribe()
	ready.Done()
	select {
	case <-ch:
		fmt.Println("got signal")
	}
	time.Sleep(3 * time.Second) // wait a bit for fun
	fmt.Println("(3) sending ack...")
	ack() // must call ack
	fmt.Println("done sending ack")
}()

ready.Wait() // wait for all subscribes
fmt.Println("sending signal...")
x.Send()                    // trigger!
time.Sleep(1 * time.Second) // wait a bit so the next print doesn't race
fmt.Println("done sending signal")

wg.Wait() // wait for everyone to exit
fmt.Println("exiting...")
Output:

hello
sending signal...
got signal
got signal
got signal
(1) sending ack...
(2) sending ack...
(3) sending ack...
done sending ack
done sending ack
done sending ack
done sending signal
exiting...

func (*SubscribedSignal) Send

func (obj *SubscribedSignal) Send()

Send is called if you want to multicast the signal to all subscribed parties. It will require all parties to acknowledge the receipt of the signal before it will unblock. Just before returning, it will reset the signal so that it can be called a subsequent time. This is thread safe and can be called multiple times in parallel because this call is protected by a mutex. The mutex also prevents simultaneous calls with the Subscribe method.

func (*SubscribedSignal) Subscribe

func (obj *SubscribedSignal) Subscribe() (<-chan struct{}, func())

Subscribe is used by any reader of the signal. Once this function returns, it means that you're now ready to watch the signal. The signal can be watched as is done normally with any other ready channel. Once you have received the signal or when you are no longer interested in the signal you *must* call the cancel/ack function which is returned by this function on subscribe. If you do not, you will block the Send portion of this subscribed signal indefinitely. This is thread safe and can be called multiple times in parallel because this call is protected by a mutex. The mutex also prevents simultaneous calls with the Send method. the returned cancel/ack method must return before it's safe to call this method a subsequent time for a new signal. One important note: there is a possible race that *you* can cause if you race this Subscribe call, with the Send call. Make sure you run Subscribe and it returns *before* you run Send if you want to be sure to receive the next signal. This should be common sense but it is mentioned here to be helpful. They are protected by a lock, so they can't both run simultaneously.

type UInt64Slice

type UInt64Slice []uint64

UInt64Slice attaches the methods of sort.Interface to []uint64, sorting in increasing order.

func (UInt64Slice) Len

func (obj UInt64Slice) Len() int

Len returns the length of the slice of uint64's.

func (UInt64Slice) Less

func (obj UInt64Slice) Less(i, j int) bool

Less returns the smaller element in the sort order.

func (UInt64Slice) Sort

func (obj UInt64Slice) Sort()

Sort is a convenience method.

func (UInt64Slice) Swap

func (obj UInt64Slice) Swap(i, j int)

Swap swaps two elements in the slice.

Directories

Path Synopsis
Package errwrap contains some error helpers.
Package errwrap contains some error helpers.
Package semaphore contains an implementation of a counting semaphore.
Package semaphore contains an implementation of a counting semaphore.
Package socketset is in API for creating a select style netlink socket to receive events from the kernel.
Package socketset is in API for creating a select style netlink socket to receive events from the kernel.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL