run

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 10, 2022 License: Apache-2.0 Imports: 10 Imported by: 20

README

🏃‍♂️ run

A new way to execute commands in Go

Example usage

package main

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

  "github.com/sourcegraph/run"
)

func main() {
  ctx := context.Background()

  // Easily stream all output back to standard out
  err := run.Cmd(ctx, "echo", "hello world").Run().Stream(os.Stdout)
  if err != nil {
    log.Fatal(err.Error())
  }

  // Or collect filter and modify standard out, then collect string lines from it
  lines, err := run.Cmd(ctx, "ls").Run().
    Filter(func(s []byte) ([]byte, bool) {
      if !bytes.HasSuffix(s, []byte(".go")) {
        return nil, true
      }
      return bytes.TrimSuffix(s, []byte(".go")), false
    }).
    Lines()
  if err != nil {
    log.Fatal(err.Error())
  }
  for i, l := range lines {
    fmt.Printf("line %d: %q\n", i, l)
  }

  // Errors include standard error by default, so we can just stream stdout.
  err = run.Cmd(ctx, "ls", "foobar").Run().StdOut().Stream(os.Stdout)
  if err != nil {
    println(err.Error()) // exit status 1: ls: foobar: No such file or directory
  }

  // Generate data from a file, replacing tabs with spaces for Markdown purposes
  var exampleData bytes.Buffer
  exampleData.Write([]byte(exampleStart + "\n\n```go\n"))
  if err = run.Cmd(ctx, "cat", "cmd/example/main.go").Run().
    Filter(func(line []byte) ([]byte, bool) {
      return bytes.ReplaceAll(line, []byte("\t"), []byte("  ")), false
    }).
    Stream(&exampleData); err != nil {
    log.Fatal(err)
  }
  exampleData.Write([]byte("```\n\n" + exampleEnd))

  // Render new README file
  var readmeData bytes.Buffer
  if err = run.Cmd(ctx, "cat", "README.md").Run().Stream(&readmeData); err != nil {
    log.Fatal(err)
  }
  replaced := exampleBlockRegexp.ReplaceAll(readmeData.Bytes(), exampleData.Bytes())

  // Pipe data to command
  err = run.Cmd(ctx, "cp /dev/stdin README.md").Input(bytes.NewReader(replaced)).Run().Wait()
  if err != nil {
    log.Fatal(err)
  }
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Command

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

Command builds a command for execution. Functions modify the underlying command.

func Cmd

func Cmd(ctx context.Context, parts ...string) *Command

Cmd joins all the parts and builds a command from it.

func (*Command) Dir

func (c *Command) Dir(dir string) *Command

Dir sets the directory this command should be executed in.

func (*Command) Env

func (c *Command) Env(env map[string]string) *Command

Env adds the given environment variables to the command.

func (*Command) Environ

func (c *Command) Environ(environ []string) *Command

InheritEnv adds the given strings representing the environment (key=value) to the command, for example os.Environ().

func (*Command) Input

func (c *Command) Input(input io.Reader) *Command

Input pipes the given io.Reader to the command.

func (*Command) Run

func (c *Command) Run() Output

Run starts command execution and returns Output, which defaults to combined output.

type LineFilter

type LineFilter func(line []byte) (newLine []byte, skip bool)

LineFilter allows modifications of individual lines from Output.

An explicit "skip" return parameter is required because many bytes library functions return nil to denote empty lines, which should be preserved: https://github.com/golang/go/issues/46415

type Output

type Output interface {
	// StdOut configures this Output to only provide StdErr. By default, Output works with
	// combined output.
	StdOut() Output
	// StdErr configures this Output to only provide StdErr. By default, Output works with
	// combined output.
	StdErr() Output
	// Filter adds a filter to this Output. It is only applied at aggregation time using
	// e.g. Stream, Lines, and so on.
	Filter(filter LineFilter) Output

	// Stream writes filtered output from the command to the destination writer until
	// command completion.
	Stream(dst io.Writer) error
	// StreamLines writes filtered output from the command and sends it line by line to the
	// destination callback until command completion.
	StreamLines(dst func(line []byte)) error
	// Lines waits for command completion and aggregates filtered output from the command.
	Lines() ([]string, error)
	// Wait waits for command completion and returns.
	Wait() error

	// Reader is implemented so that Output can be provided directly to another Command
	// using Input().
	io.Reader
}

Output configures output and aggregation from a command.

It is behind an interface to more easily enable mock outputs and build different types of outputs, such as multi-outputs and error-only outputs, without complicating the core commandOutput implementation.

Directories

Path Synopsis
cmd
example command
pipeexample command
pollexample command

Jump to

Keyboard shortcuts

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