Skip to content

Commit abe6a54

Browse files
authored
Merge pull request #155 from mbland/template
Add go-template for bootstrapping ./go scripts
2 parents 5dd8651 + 1f23ffb commit abe6a54

File tree

3 files changed

+170
-11
lines changed

3 files changed

+170
-11
lines changed

README.md

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,29 @@ If you do not see this, follow the instructions in the [Installing
206206
Bash](#installing-bash) section later in this document.
207207

208208
__Note: While Bash is required to run this framework, your individual command
209-
scripts can be in any other interpreted language.__
209+
scripts can be in any other interpreted language installed on the host system.__
210210

211211
### How to use this framework
212212

213213
First you'll need a copy of this framework available in your project sources.
214-
Archives are available at:
214+
The most expedient way to bootstrap your program is to use the [`go-template`
215+
file](https://github.com/mbland/go-script-bash/blob/master/go-template) as a
216+
starting point (replacing `curl` with `wget`, `fetch`, or whichever tool you
217+
prefer):
218+
219+
```bash
220+
$ curl https://raw.githubusercontent.com/mbland/go-script-bash/master/go-template >./go
221+
$ chmod ugo+rx ./go
222+
```
223+
224+
You may rename this file whatever you wish (i.e. it doesn't have to be named
225+
`./go`), update its documentation and variables to fit your project, and check
226+
it into your project repository. See the `go-template` comments for details.
227+
228+
If you'd prefer to download a copy of the framework and check it into your
229+
sources, versioned archives are available from the [go-script-bash Releases
230+
page](https://github.com/mbland/go-script-bash/releases). The archives for the
231+
current release are:
215232

216233
- https://github.com/mbland/go-script-bash/archive/v1.3.0.tar.gz
217234
- https://github.com/mbland/go-script-bash/archive/v1.3.0.zip
@@ -228,21 +245,24 @@ $ git submodule update --init
228245
where `<target-dir>` is any point inside your project directory structure that
229246
you prefer.
230247

231-
Then create a bash script in the root directory of your project to act as the
232-
main `./go` script. This script need not be named `go`, but it must contain the
233-
following as the first and last executable lines, respectively:
248+
If you're not using `go-template`, create a bash script in the root directory of
249+
your project to act as the main `./go` script. This script need not be named
250+
`go`, but it must contain the following lines, with `@go "$@"` as the last line
251+
of the script:
234252

235253
```bash
236254
. "${0%/*}/go-core.bash" "scripts"
237255
@go "$@"
238256
```
239257

240258
where:
241-
- `"${0%/*}"` produces the path to the project's root directory
242-
- `go-core.bash` is the path to the file of the same name imported from this
243-
repository
259+
- `${0%/*}` produces the path to the project's root directory based on the path
260+
to the `./go` script
261+
- `${0%/*}/go-core.bash` produces the path to the framework's `go-core.bash`
262+
file within your project's copy of the framework (adjusted to reflect where
263+
your copy of `go-script-bash` actually resides)
244264
- `scripts` is the path to the directory holding your project's command scripts
245-
relative to the project root
265+
relative to the project root (it can be any name you like)
246266

247267
#### Directory structure
248268

@@ -489,8 +509,8 @@ need the following utilities installed:
489509
- `tput` (ncurses) on Linux, OS X, UNIX
490510
- `mode.com` should be present on Windows
491511

492-
To use the `get` builtin, the `curl`, `wget`, and `git` programs must be
493-
installed on your system.
512+
To use the `get file` builtin, either `curl`, `wget`, or `fetch` must be
513+
installed on your system. `get git-repo` requires `git`, naturally.
494514

495515
### Open Source License
496516

go-template

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#! /usr/bin/env bash
2+
#
3+
# Template for a Bash program based on the go-script-bash framework
4+
#
5+
# You should replace this comment with your own program's high-level
6+
# description. You may remove any other comments from this template as well.
7+
#
8+
# This template automatically checks for the presence of the go-script-bash
9+
# sources and makes a shallow clone of the the go-script-bash repository if
10+
# necessary before dispatching commands. (If you prefer, you can change the
11+
# logic to create a regular clone instead.) This allows users to set up the
12+
# framework without taking any extra steps when running the command for the
13+
# first time, without the need to commit the framework to your repository.
14+
#
15+
# Alternatively, you can make the `GO_SCRIPT_BASH_REPO_URL` a Git submodule of
16+
# your project or check in a versioned copy of the sources. See the "How to use
17+
# this framework" section of `README.md` for details.
18+
#
19+
# Make sure the `_GO_STANDALONE`, `SCRIPTS_DIR`, and `GO_SCRIPT_BASH_VERSION`
20+
# variables within this script are configured as necessary for your program.
21+
# You can also add any other initialization or configuration logic between:
22+
#
23+
# . "$_GO_SCRIPT_BASH_CORE" "${SCRIPTS_DIR##*/}"`
24+
# `@go "$@"`
25+
26+
# Set `_GO_STANDALONE='true'` if your program isn't a project-specific script.
27+
readonly _GO_STANDALONE=
28+
29+
# Set SCRIPTS_DIR to the path where your command scripts reside.
30+
#
31+
# For `_GO_STANDALONE` programs and plugins containing command scripts, you may
32+
# wish to set SCRIPTS_DIR to end with `bin` and have a separate `./go` script to
33+
# manage project tasks that finds its command scripts in `scripts`.
34+
readonly SCRIPTS_DIR="${0%/*}/scripts"
35+
36+
# Set this to the `GO_SCRIPT_BASH_REPO_URL` tag or branch you wish to use.
37+
readonly GO_SCRIPT_BASH_VERSION='v1.3.0'
38+
39+
readonly GO_SCRIPT_BASH_CORE="$SCRIPTS_DIR/go-script-bash/go-core.bash"
40+
readonly GO_SCRIPT_BASH_REPO_URL='https://github.com/mbland/go-script-bash.git'
41+
42+
if [[ ! -e "$GO_SCRIPT_BASH_CORE" ]]; then
43+
printf "Cloning framework from '%s'...\n" "$GO_SCRIPT_BASH_REPO_URL"
44+
if ! git clone --depth 1 -c advice.detachedHead=false \
45+
-b "$GO_SCRIPT_BASH_VERSION" "$GO_SCRIPT_BASH_REPO_URL" \
46+
"${GO_SCRIPT_BASH_CORE%/*}"; then
47+
printf "Failed to clone '%s'; aborting.\n" "$GO_SCRIPT_BASH_REPO_URL" >&2
48+
exit 1
49+
fi
50+
printf "Clone of '%s' successful.\n\n" "$GO_SCRIPT_BASH_REPO_URL"
51+
fi
52+
53+
. "$GO_SCRIPT_BASH_CORE" "${SCRIPTS_DIR##*/}"
54+
# Add any other configuration or initialization steps here.
55+
@go "$@"

tests/template.bats

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#! /usr/bin/env bats
2+
3+
load environment
4+
5+
# By default, the test will try to clone its own repo to avoid flakiness due to
6+
# an external dependency. However, doing so causes a failure on Travis, since it
7+
# uses shallow clones to produce test runs, resulting in the error:
8+
#
9+
# fatal: attempt to fetch/clone from a shallow repository
10+
#
11+
# However, since Travis already depends on having a good connection to GitHub,
12+
# we'll use the real URL. Alternatively, `git` could be stubbed out via
13+
# `stub_program_in_path` from `_GO_CORE_DIR/lib/bats/helpers`, but the potential
14+
# for neither flakiness nor complexity seems that great, and this approach
15+
# provides extra confidence that the mechanism works as advertised.
16+
#
17+
# A developer can also run the test locally against the real URL by setting
18+
# `TEST_USE_REAL_URL` on the command line. The value of `GO_CORE_URL` is
19+
# subsequently displayed in the name of the test case to validate which repo is
20+
# being used during the test run.
21+
TEST_USE_REAL_URL="${TEST_USE_REAL_URL:-$TRAVIS}"
22+
GO_CORE_URL="${TEST_USE_REAL_URL:+$_GO_CORE_URL}"
23+
GO_CORE_URL="${GO_CORE_URL:-$_GO_CORE_DIR}"
24+
25+
setup() {
26+
test_filter
27+
mkdir "$TEST_GO_ROOTDIR"
28+
29+
if [[ -e "$GO_CORE_URL/.git/shallow" ]]; then
30+
skip "Can't clone shallow repositories"
31+
fi
32+
}
33+
34+
teardown() {
35+
@go.remove_test_go_rootdir
36+
}
37+
38+
create_template_script() {
39+
local repo_url="$1"
40+
local version="$2"
41+
local template="$(< "$_GO_CORE_DIR/go-template")"
42+
local replacement
43+
44+
if [[ "$template" =~ GO_SCRIPT_BASH_REPO_URL=[^$'\n']+ ]]; then
45+
replacement="GO_SCRIPT_BASH_REPO_URL='$repo_url'"
46+
template="${template/${BASH_REMATCH[0]}/$replacement}"
47+
fi
48+
if [[ "$template" =~ GO_SCRIPT_BASH_VERSION=[^$'\n']+ ]]; then
49+
replacement="GO_SCRIPT_BASH_VERSION='$version'"
50+
template="${template/${BASH_REMATCH[0]}/$replacement}"
51+
fi
52+
printf '%s\n' "$template" > "$TEST_GO_ROOTDIR/go-template"
53+
chmod 700 "$TEST_GO_ROOTDIR/go-template"
54+
}
55+
56+
@test "$SUITE: clone the go-script-bash repository from $GO_CORE_URL" {
57+
create_template_script "$GO_CORE_URL" "$_GO_CORE_VERSION"
58+
run "$TEST_GO_ROOTDIR/go-template"
59+
60+
# Without a command argument, the script will print the top-level help and
61+
# return an error, but the core repo should exist as expected.
62+
assert_failure
63+
assert_output_matches "Cloning framework from '$GO_CORE_URL'\.\.\."
64+
65+
# Use `.*/scripts/go-script-bash` to account for the fact that `git clone` on
66+
# MSYS2 will output `C:/Users/<user>/AppData/Local/Temp/` in place of `/tmp`.
67+
assert_output_matches "Cloning into '.*/scripts/go-script-bash'\.\.\."
68+
assert_output_matches "Clone of '$GO_CORE_URL' successful\."$'\n\n'
69+
assert_output_matches "Usage: $TEST_GO_ROOTDIR/go-template <command>"
70+
[[ -f "$TEST_GO_ROOTDIR/scripts/go-script-bash/go-core.bash" ]]
71+
72+
cd "$TEST_GO_ROOTDIR/scripts/go-script-bash"
73+
run git log --oneline -n 1
74+
assert_success
75+
assert_output_matches "go-script-bash $_GO_CORE_VERSION"
76+
}
77+
78+
@test "$SUITE: fail to clone a nonexistent repo" {
79+
create_template_script 'bogus-repo-that-does-not-exist'
80+
run "$TEST_GO_ROOTDIR/go-template"
81+
assert_failure "Cloning framework from 'bogus-repo-that-does-not-exist'..." \
82+
"fatal: repository 'bogus-repo-that-does-not-exist' does not exist" \
83+
"Failed to clone 'bogus-repo-that-does-not-exist'; aborting."
84+
}

0 commit comments

Comments
 (0)