From 5aa94a79891c7b457459b45ec9ce344046cf5b8f Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Thu, 19 Dec 2013 11:22:08 -0800 Subject: [PATCH] Adding basic CLI infrastructure --- .gitignore | 1 + command/version.go | 38 ++++++++++++++++++++++++ command/version_test.go | 10 +++++++ commands.go | 44 ++++++++++++++++++++++++++++ main.go | 43 +++++++++++++++++++++++++++ main_test.go | 1 + scripts/build.sh | 34 +++++++++++++++++++++ scripts/dist.sh | 65 +++++++++++++++++++++++++++++++++++++++++ version.go | 12 ++++++++ 9 files changed, 248 insertions(+) create mode 100644 command/version.go create mode 100644 command/version_test.go create mode 100644 commands.go create mode 100644 main.go create mode 100644 main_test.go create mode 100755 scripts/build.sh create mode 100755 scripts/dist.sh create mode 100644 version.go diff --git a/.gitignore b/.gitignore index 836562412..aee2b6dd9 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ _testmain.go *.exe *.test +bin/ diff --git a/command/version.go b/command/version.go new file mode 100644 index 000000000..9124f23a9 --- /dev/null +++ b/command/version.go @@ -0,0 +1,38 @@ +package command + +import ( + "bytes" + "fmt" + "github.com/mitchellh/cli" +) + +// VersionCommand is a Command implementation prints the version. +type VersionCommand struct { + Revision string + Version string + VersionPrerelease string + Ui cli.Ui +} + +func (c *VersionCommand) Help() string { + return "" +} + +func (c *VersionCommand) Run(_ []string) int { + var versionString bytes.Buffer + fmt.Fprintf(&versionString, "Consul v%s", c.Version) + if c.VersionPrerelease != "" { + fmt.Fprintf(&versionString, ".%s", c.VersionPrerelease) + + if c.Revision != "" { + fmt.Fprintf(&versionString, " (%s)", c.Revision) + } + } + + c.Ui.Output(versionString.String()) + return 0 +} + +func (c *VersionCommand) Synopsis() string { + return "Prints the Consul version" +} diff --git a/command/version_test.go b/command/version_test.go new file mode 100644 index 000000000..da7aa8608 --- /dev/null +++ b/command/version_test.go @@ -0,0 +1,10 @@ +package command + +import ( + "github.com/mitchellh/cli" + "testing" +) + +func TestVersionCommand_implements(t *testing.T) { + var _ cli.Command = &VersionCommand{} +} diff --git a/commands.go b/commands.go new file mode 100644 index 000000000..9a86283a5 --- /dev/null +++ b/commands.go @@ -0,0 +1,44 @@ +package main + +import ( + "github.com/hashicorp/consul/command" + "github.com/mitchellh/cli" + "os" + "os/signal" +) + +// Commands is the mapping of all the available Serf commands. +var Commands map[string]cli.CommandFactory + +func init() { + ui := &cli.BasicUi{Writer: os.Stdout} + + Commands = map[string]cli.CommandFactory{ + "version": func() (cli.Command, error) { + return &command.VersionCommand{ + Revision: GitCommit, + Version: Version, + VersionPrerelease: VersionPrerelease, + Ui: ui, + }, nil + }, + } +} + +// makeShutdownCh returns a channel that can be used for shutdown +// notifications for commands. This channel will send a message for every +// interrupt received. +func makeShutdownCh() <-chan struct{} { + resultCh := make(chan struct{}) + + signalCh := make(chan os.Signal, 4) + signal.Notify(signalCh, os.Interrupt) + go func() { + for { + <-signalCh + resultCh <- struct{}{} + } + }() + + return resultCh +} diff --git a/main.go b/main.go new file mode 100644 index 000000000..1fda84e6a --- /dev/null +++ b/main.go @@ -0,0 +1,43 @@ +package main + +import ( + "fmt" + "github.com/mitchellh/cli" + "io/ioutil" + "log" + "os" +) + +func main() { + os.Exit(realMain()) +} + +func realMain() int { + log.SetOutput(ioutil.Discard) + + // Get the command line args. We shortcut "--version" and "-v" to + // just show the version. + args := os.Args[1:] + for _, arg := range args { + if arg == "-v" || arg == "--version" { + newArgs := make([]string, len(args)+1) + newArgs[0] = "version" + copy(newArgs[1:], args) + args = newArgs + break + } + } + + cli := &cli.CLI{ + Args: args, + Commands: Commands, + } + + exitCode, err := cli.Run() + if err != nil { + fmt.Fprintf(os.Stderr, "Error executing CLI: %s\n", err.Error()) + return 1 + } + + return exitCode +} diff --git a/main_test.go b/main_test.go new file mode 100644 index 000000000..06ab7d0f9 --- /dev/null +++ b/main_test.go @@ -0,0 +1 @@ +package main diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 000000000..205877720 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# +# This script builds the application from source. +set -e + +# Get the parent directory of where this script is. +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done +DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )" + +# Change into that directory +cd $DIR + +# Get the git commit +GIT_COMMIT=$(git rev-parse HEAD) +GIT_DIRTY=$(test -n "`git status --porcelain`" && echo "+CHANGES" || true) + +# If we're building on Windows, specify an extension +EXTENSION="" +if [ "$(go env GOOS)" = "windows" ]; then + EXTENSION=".exe" +fi + +# Install dependencies +echo "--> Installing dependencies to speed up builds..." +go get ./... + +# Build! +echo "--> Building..." +go build \ + -ldflags "-X main.GitCommit ${GIT_COMMIT}${GIT_DIRTY}" \ + -v \ + -o bin/consul${EXTENSION} +cp bin/consul${EXTENSION} $GOPATH/bin diff --git a/scripts/dist.sh b/scripts/dist.sh new file mode 100755 index 000000000..88959a7b3 --- /dev/null +++ b/scripts/dist.sh @@ -0,0 +1,65 @@ +#!/bin/bash +set -e + +# Get the parent directory of where this script is. +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done +DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )" + +# Change into that dir because we expect that +cd $DIR + +# Determine the version that we're building based on the contents +# of packer/version.go. +VERSION=$(grep "const Version " version.go | sed -E 's/.*"(.+)"$/\1/') +VERSIONDIR="${VERSION}" +PREVERSION=$(grep "const VersionPrerelease " version.go | sed -E 's/.*"(.*)"$/\1/') +if [ ! -z $PREVERSION ]; then + PREVERSION="${PREVERSION}.$(date -u +%s)" + VERSIONDIR="${VERSIONDIR}-${PREVERSION}" +fi + +echo "Version: ${VERSION} ${PREVERSION}" + +# Determine the arch/os combos we're building for +XC_ARCH=${XC_ARCH:-"386 amd64 arm"} +XC_OS=${XC_OS:-linux darwin windows freebsd openbsd} + +echo "Arch: ${XC_ARCH}" +echo "OS: ${XC_OS}" + +# Make sure that if we're killed, we kill all our subprocseses +trap "kill 0" SIGINT SIGTERM EXIT + +# This function builds whatever directory we're in... +goxc \ + -arch="$XC_ARCH" \ + -os="$XC_OS" \ + -d="${DIR}/pkg" \ + -pv="${VERSION}" \ + -pr="${PREVERSION}" \ + $XC_OPTS \ + go-install \ + xc + +# Zip all the packages +mkdir -p ./pkg/${VERSIONDIR}/dist +for PLATFORM in $(find ./pkg/${VERSIONDIR} -mindepth 1 -maxdepth 1 -type d); do + PLATFORM_NAME=$(basename ${PLATFORM}) + ARCHIVE_NAME="${VERSIONDIR}_${PLATFORM_NAME}" + + if [ $PLATFORM_NAME = "dist" ]; then + continue + fi + + pushd ${PLATFORM} + zip ${DIR}/pkg/${VERSIONDIR}/dist/${ARCHIVE_NAME}.zip ./* + popd +done + +# Make the checksums +pushd ./pkg/${VERSIONDIR}/dist +shasum -a256 * > ./${VERSIONDIR}_SHA256SUMS +popd + +exit 0 diff --git a/version.go b/version.go new file mode 100644 index 000000000..b0a906a05 --- /dev/null +++ b/version.go @@ -0,0 +1,12 @@ +package main + +// The git commit that was compiled. This will be filled in by the compiler. +var GitCommit string + +// The main version number that is being run at the moment. +const Version = "0.1.0" + +// A pre-release marker for the version. If this is "" (empty string) +// then it means that it is a final release. Otherwise, this is a pre-release +// such as "dev" (in development), "beta", "rc1", etc. +const VersionPrerelease = "dev"