gli 2.21.1 → 2.21.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/CONTRIBUTING.md +63 -21
- data/Dockerfile.dx +28 -0
- data/README.rdoc +6 -2
- data/Rakefile +6 -0
- data/bin/ci +12 -24
- data/bin/setup +8 -2
- data/dx/build +60 -0
- data/dx/docker-compose.env +5 -0
- data/dx/dx.sh.lib +24 -0
- data/dx/exec +59 -0
- data/dx/prune +19 -0
- data/dx/setupkit.sh.lib +144 -0
- data/dx/show-help-in-app-container-then-wait.sh +38 -0
- data/dx/start +30 -0
- data/dx/stop +23 -0
- data/gli.gemspec +10 -1
- data/lib/gli/commands/scaffold.rb +1 -1
- data/lib/gli/gli_option_parser.rb +4 -3
- data/lib/gli/version.rb +1 -1
- data/test/integration/gli_cli_test.rb +1 -1
- data/test/integration/gli_powered_app_test.rb +1 -1
- data/test/integration/scaffold_test.rb +1 -1
- data/test/unit/command_finder_test.rb +1 -1
- data/test/unit/command_test.rb +1 -1
- data/test/unit/compound_command_test.rb +1 -1
- data/test/unit/doc_test.rb +1 -1
- data/test/unit/flag_test.rb +1 -1
- data/test/unit/gli_test.rb +40 -1
- data/test/unit/help_test.rb +1 -1
- data/test/unit/options_test.rb +1 -1
- data/test/unit/subcommand_parsing_test.rb +1 -1
- data/test/unit/subcommands_test.rb +1 -1
- data/test/unit/switch_test.rb +1 -1
- data/test/unit/terminal_test.rb +1 -1
- data/test/unit/verbatim_wrapper_test.rb +1 -1
- metadata +27 -13
- data/.circleci/config.yml +0 -30
- data/.tool-versions +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4090c5ae7772cf0833abb4eda596a2eb558577de6493a1389e90e68327f41093
|
4
|
+
data.tar.gz: 8f18bf74f7ac11bf544ac28be9c326355199a138364b7189a10537c7eb2903f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '02638fe45837c6e17d83d8e1afaf3a90e94da181419b1dfc6f53db9487a90566ff281a2e9adc4155bd4baa379f5f43f379a716e788330e12f828ad2d9a233f99'
|
7
|
+
data.tar.gz: fbd6c9281eaf31a203cf5f6331ce21f4241eeb6b7e8cfafc5c3c4d63e81455a60246d76aa411ec4c3ffee3137c48921c569b819f6e0b7cc0e95225c5cdf18a1f
|
data/.gitignore
CHANGED
data/CONTRIBUTING.md
CHANGED
@@ -1,21 +1,63 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
1
|
+
# Contributing/Developing
|
2
|
+
|
3
|
+
## Types of Contributions
|
4
|
+
|
5
|
+
GLI is relatively stable. As such:
|
6
|
+
|
7
|
+
* No major new features should be added
|
8
|
+
* No refactorings or "modernization" is desired
|
9
|
+
* No runtime dependencies should be added.
|
10
|
+
|
11
|
+
If you really want to make a change like this, open an issue first to discuss.
|
12
|
+
|
13
|
+
That said, I welcome:
|
14
|
+
|
15
|
+
* Bugfixes
|
16
|
+
* Doc changes
|
17
|
+
* Minor improvements
|
18
|
+
|
19
|
+
I am responsive on issues, so reach out there if you have a question.
|
20
|
+
|
21
|
+
## How to Do Development
|
22
|
+
|
23
|
+
GLI us using a Docker-based development system to ensure consistency. To use it, you will need to have Docker installed, as well
|
24
|
+
as Bash. This should all work under Windows Subsystem for Linux.
|
25
|
+
|
26
|
+
### Setting Up
|
27
|
+
|
28
|
+
1. Install Docker
|
29
|
+
2. `dx/build`
|
30
|
+
|
31
|
+
This will use `Dockerfile.dx` to create one Docker image for each supported Ruby version (see `dx/docker-compose.env`'s `RUBY_VERSIONS` variable for the current list). This will also generate `docker-compose.dx.yml` which will run all versions of Ruby for GLI at the same time.
|
32
|
+
3. `dx/start`
|
33
|
+
|
34
|
+
This will start Docker using `docker-compose.dx.yml`, which will run containers for all the images generated by `dx/build`
|
35
|
+
|
36
|
+
4. From here, you can run commands inside the running containers, or you can run `bash` inside a container to effectively "log
|
37
|
+
in" and run commands.
|
38
|
+
|
39
|
+
### Doing Development
|
40
|
+
|
41
|
+
Once you are set up, you should run `dx/exec bash`. This will log you into the container running the oldest supported version of
|
42
|
+
Ruby. This is the version where you should do your basic work. This container has access to the source code you cloned from
|
43
|
+
GitHub.
|
44
|
+
|
45
|
+
1. `on-your-computer> dx/exec bash`
|
46
|
+
2. `inside-docker-container> bin/setup # installs all gems`
|
47
|
+
3. `inside-docker-container> bin/rake # runs all tests`
|
48
|
+
|
49
|
+
Once you have stuff working, run tests on the other versions. Since the container you were working in was operating on your
|
50
|
+
checked-out files, the other containers will have access as well.
|
51
|
+
|
52
|
+
1. `on-your-computer> dx/exec -v 3.3 bash # connects to the conatiner where Ruby 3.3 is installed`
|
53
|
+
2. `inside-docker-container> bin/setup # installs all gems`
|
54
|
+
3. `inside-docker-container> bin/rake # runs all tests`
|
55
|
+
|
56
|
+
You can also try using `bin/ci` on your computer (not inside a Docker container), which will run tests across the entire build
|
57
|
+
matrix.
|
58
|
+
|
59
|
+
#### If You Want To Use Your Local Computer
|
60
|
+
|
61
|
+
In theory, GLI can be worked on using RVM, RBEnv, asdf, or whatever other way you want to manage Ruby. You can create a
|
62
|
+
`.ruby-version` or `.tool-versions`. These are ignored so you can keep them on your machine. I don't support this setup, so if
|
63
|
+
something is wrong, I probably can't help. This is why I have it set up with Docker.
|
data/Dockerfile.dx
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
ARG RUBY_VERSION
|
2
|
+
FROM ruby:${RUBY_VERSION}
|
3
|
+
|
4
|
+
ENV DEBIAN_FRONTEND noninteractive
|
5
|
+
RUN apt-get -y update
|
6
|
+
|
7
|
+
|
8
|
+
# dx.snippet.start=templates/snippets/bundler/latest__bundler.dockerfile-snippet
|
9
|
+
# Based on documentation at https://guides.rubygems.org/command-reference/#gem-update
|
10
|
+
# based on the vendor's documentation
|
11
|
+
RUN echo "gem: --no-document" >> ~/.gemrc && \
|
12
|
+
gem update --system && \
|
13
|
+
gem install bundler
|
14
|
+
|
15
|
+
# dx.snippet.end=templates/snippets/bundler/latest__bundler.dockerfile-snippet
|
16
|
+
|
17
|
+
|
18
|
+
# dx.snippet.start=templates/snippets/vim/bullseye_vim.dockerfile-snippet
|
19
|
+
# Based on documentation at https://packages.debian.org/search?keywords=vim
|
20
|
+
# based on the vendor's documentation
|
21
|
+
ENV EDITOR=vim
|
22
|
+
RUN apt-get install -y vim && \
|
23
|
+
echo "set -o vi" >> /root/.bashrc
|
24
|
+
# dx.snippet.end=templates/snippets/vim/bullseye_vim.dockerfile-snippet
|
25
|
+
|
26
|
+
# This entrypoint produces a nice help message and waits around for you to do
|
27
|
+
# something with the container.
|
28
|
+
COPY dx/show-help-in-app-container-then-wait.sh /root
|
data/README.rdoc
CHANGED
@@ -92,9 +92,9 @@ Get a more detailed walkthrough on the {main site}[http://davetron5000.github.io
|
|
92
92
|
|
93
93
|
== Supported Platforms
|
94
94
|
|
95
|
-
See
|
95
|
+
See `dx/docker-compose.env` and the variable `RUBY_VERSIONS` for the versions that are supported. This should generally track with the supported version of Ruby from Ruby's maintainers.
|
96
96
|
|
97
|
-
GLI should work on
|
97
|
+
That said, GLI should generally work on other Rubies as it doesn't have any runtime dependencies and there are no plans to use more modern features of Ruby in the codebase.
|
98
98
|
|
99
99
|
== Documentation
|
100
100
|
|
@@ -102,6 +102,10 @@ Extensive documentation is {available at the wiki}[https://github.com/davetron50
|
|
102
102
|
|
103
103
|
API Documentation is available {here}[http://davetron5000.github.io/gli/rdoc/index.html]. Recommend starting with GLI::DSL or GLI::App.
|
104
104
|
|
105
|
+
== Developing
|
106
|
+
|
107
|
+
See `CONTRIBUTING.md`
|
108
|
+
|
105
109
|
== Credits
|
106
110
|
|
107
111
|
Author:: Dave Copeland (mailto:davetron5000 at g mail dot com)
|
data/Rakefile
CHANGED
@@ -80,6 +80,9 @@ Rake::TestTask.new("test:unit") do |t|
|
|
80
80
|
ENV["RUBYOPT"].split(/\s/).each do |opt|
|
81
81
|
t.ruby_opts << opt
|
82
82
|
end
|
83
|
+
if t.ruby_opts.none? { |x| x =~ /^\-W/ }
|
84
|
+
t.ruby_opts << "-W0"
|
85
|
+
end
|
83
86
|
t.test_files = FileList["test/unit/**/*_test.rb"]
|
84
87
|
end
|
85
88
|
|
@@ -89,6 +92,9 @@ Rake::TestTask.new("test:integration") do |t|
|
|
89
92
|
ENV["RUBYOPT"].split(/\s/).each do |opt|
|
90
93
|
t.ruby_opts << opt
|
91
94
|
end
|
95
|
+
if t.ruby_opts.none? { |x| x =~ /^\-W/ }
|
96
|
+
t.ruby_opts << "-W0"
|
97
|
+
end
|
92
98
|
explicitly_named_files = ARGV[1..-1]
|
93
99
|
if Array(explicitly_named_files).size == 0
|
94
100
|
t.test_files = FileList["test/integration/**/*_test.rb"]
|
data/bin/ci
CHANGED
@@ -1,29 +1,17 @@
|
|
1
1
|
#!/bin/bash
|
2
2
|
|
3
3
|
set -e
|
4
|
-
if [ -z $1 ]; then
|
5
|
-
echo "[bin/ci] Running with default warnings"
|
6
|
-
export RUBYOPT=
|
7
|
-
else
|
8
|
-
if [ $1 == 'warnings' ]; then
|
9
|
-
echo "[bin/ci] Running with all warnings on"
|
10
|
-
export RUBYOPT=-w
|
11
|
-
else
|
12
|
-
if [ $1 == 'none' ]; then
|
13
|
-
echo "[bin/ci] Running with all warnings off"
|
14
|
-
export RUBYOPT='-W0'
|
15
|
-
else
|
16
|
-
echo "[bin/ci] '$1' is not a supported option"
|
17
|
-
echo "[bin/ci] usage: $0 # run with default warnings"
|
18
|
-
echo "[bin/ci] usage: $0 warnings # run with all warnings"
|
19
|
-
echo "[bin/ci] usage: $0 none # run with warnings disabled"
|
20
|
-
exit 1
|
21
|
-
fi
|
22
|
-
fi
|
23
|
-
fi
|
24
4
|
|
25
|
-
|
26
|
-
|
5
|
+
SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd )
|
6
|
+
DX_DIR="${SCRIPT_DIR}/../dx"
|
7
|
+
|
8
|
+
. "${DX_DIR}/docker-compose.env"
|
9
|
+
. "${DX_DIR}/setupkit.sh.lib"
|
10
|
+
|
11
|
+
for ruby_version in ${RUBY_VERSIONS[@]}; do
|
12
|
+
log "Setting up for Ruby version '${ruby_version}'"
|
13
|
+
dx/exec -v ${ruby_version} bin/setup
|
14
|
+
log "Running tests for Ruby version '${ruby_version}'"
|
15
|
+
dx/exec -v ${ruby_version} bin/rake
|
16
|
+
done
|
27
17
|
|
28
|
-
echo "[bin/ci] Running integration tests"
|
29
|
-
bin/rake test:integration
|
data/bin/setup
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
#!/bin/bash
|
2
2
|
|
3
3
|
set -e
|
4
|
-
|
5
|
-
|
4
|
+
if [ Gemfile.lock -ot gli.gemspec ] ; then
|
5
|
+
echo "[ bin/setup ] gli.gemspec has been modified - deleting Gemfile.lock"
|
6
|
+
rm Gemfile.lock
|
7
|
+
bundle install
|
8
|
+
else
|
9
|
+
echo "[ bin/setup ] checking bundle and updating as necessary"
|
10
|
+
bundle check || bundle install
|
11
|
+
fi
|
data/dx/build
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd )
|
6
|
+
|
7
|
+
. "${SCRIPT_DIR}/dx.sh.lib"
|
8
|
+
|
9
|
+
require_command "docker"
|
10
|
+
load_docker_compose_env
|
11
|
+
|
12
|
+
usage_on_help "Builds the Docker image based on the Dockerfile" "" "build.pre" "build.post" "${@}"
|
13
|
+
|
14
|
+
for ruby_version in ${RUBY_VERSIONS[@]}; do
|
15
|
+
dockerfile="Dockerfile.dx"
|
16
|
+
docker_image_name="${IMAGE}:ruby-${ruby_version}"
|
17
|
+
|
18
|
+
log "Building for Ruby '${ruby_version}' using Docker image name '${docker_image_name}'"
|
19
|
+
|
20
|
+
exec_hook_if_exists "build.pre" "${dockerfile}" "${docker_image_name}"
|
21
|
+
|
22
|
+
docker build \
|
23
|
+
--file "${dockerfile}" \
|
24
|
+
--build-arg="RUBY_VERSION=${ruby_version}" \
|
25
|
+
--tag "${docker_image_name}" \
|
26
|
+
./
|
27
|
+
|
28
|
+
exec_hook_if_exists "build.post" "${dockerfile}" "${docker_image_name}"
|
29
|
+
log "🌈" "Your Docker image has been built tagged '${docker_image_name}'"
|
30
|
+
done
|
31
|
+
|
32
|
+
log "✅" "All images built"
|
33
|
+
|
34
|
+
log "✨" "Creating docker-compose.dx.yml"
|
35
|
+
compose_file="docker-compose.dx.yml"
|
36
|
+
log "🗑️" "Deleting previous ${compose_file}"
|
37
|
+
|
38
|
+
rm -f "${compose_file}"
|
39
|
+
echo "# THIS IS GENERATED - DO NOT EDIT" > "${compose_file}"
|
40
|
+
echo "" >> "${compose_file}"
|
41
|
+
echo "services:" >> "${compose_file}"
|
42
|
+
|
43
|
+
for ruby_version in ${RUBY_VERSIONS[@]}; do
|
44
|
+
log "Generating stanza for version '${ruby_version}'"
|
45
|
+
docker_image_name="${IMAGE}:ruby-${ruby_version}"
|
46
|
+
echo " gli-${ruby_version}:" >> "${compose_file}"
|
47
|
+
echo " image: ${docker_image_name}" >> "${compose_file}"
|
48
|
+
echo " init: true" >> "${compose_file}"
|
49
|
+
echo " volumes:" >> "${compose_file}"
|
50
|
+
echo " - type: bind" >> "${compose_file}"
|
51
|
+
echo " source: \"./\"" >> "${compose_file}"
|
52
|
+
echo " target: \"/root/work\"" >> "${compose_file}"
|
53
|
+
echo " consistency: \"consistent\"" >> "${compose_file}"
|
54
|
+
echo " entrypoint: /root/show-help-in-app-container-then-wait.sh" >> "${compose_file}"
|
55
|
+
echo " working_dir: /root/work" >> "${compose_file}"
|
56
|
+
done
|
57
|
+
log "🎼" "${compose_file} is now created"
|
58
|
+
log "🔄" "You can run dx/start to start it up, though you may need to stop it first with Ctrl-C"
|
59
|
+
|
60
|
+
# vim: ft=bash
|
data/dx/dx.sh.lib
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# shellcheck shell=bash
|
2
|
+
|
3
|
+
. "${SCRIPT_DIR}/setupkit.sh.lib"
|
4
|
+
|
5
|
+
require_command "realpath"
|
6
|
+
require_command "cat"
|
7
|
+
|
8
|
+
ENV_FILE=$(realpath "${SCRIPT_DIR}")/docker-compose.env
|
9
|
+
|
10
|
+
load_docker_compose_env() {
|
11
|
+
. "${ENV_FILE}"
|
12
|
+
}
|
13
|
+
|
14
|
+
exec_hook_if_exists() {
|
15
|
+
script_name=$1
|
16
|
+
shift
|
17
|
+
if [ -x "${SCRIPT_DIR}"/"${script_name}" ]; then
|
18
|
+
log "🪝" "${script_name} exists - executing"
|
19
|
+
"${SCRIPT_DIR}"/"${script_name}" "${@}"
|
20
|
+
else
|
21
|
+
debug "${script_name} does not exist"
|
22
|
+
fi
|
23
|
+
}
|
24
|
+
# vim: ft=bash
|
data/dx/exec
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd )
|
6
|
+
|
7
|
+
. "${SCRIPT_DIR}/dx.sh.lib"
|
8
|
+
|
9
|
+
require_command "docker"
|
10
|
+
load_docker_compose_env
|
11
|
+
|
12
|
+
usage_description="Execute a command inside the app's container."
|
13
|
+
usage_args="[-s service] [-v ruby_version] command"
|
14
|
+
usage_pre="exec.pre"
|
15
|
+
usage_on_help "${usage_description}" "${usage_args}" "${usage_pre}" "" "${@}"
|
16
|
+
|
17
|
+
LATEST_RUBY=${RUBY_VERSIONS[0]}
|
18
|
+
DEFAULT_SERVICE=gli-${LATEST_RUBY}
|
19
|
+
SERVICE="${SERVICE_NAME:-${DEFAULT_SERVICE}}"
|
20
|
+
while getopts "v:s:" opt "${@}"; do
|
21
|
+
case ${opt} in
|
22
|
+
v )
|
23
|
+
SERVICE="gli-${OPTARG}"
|
24
|
+
;;
|
25
|
+
s )
|
26
|
+
SERVICE="${OPTARG}"
|
27
|
+
;;
|
28
|
+
\? )
|
29
|
+
log "🛑" "Unknown option: ${opt}"
|
30
|
+
usage "${description}" "${usage_args}" "${usage_pre}"
|
31
|
+
;;
|
32
|
+
: )
|
33
|
+
log "🛑" "Invalid option: ${opt} requires an argument"
|
34
|
+
usage "${description}" "${usage_args}" "${usage_pre}"
|
35
|
+
;;
|
36
|
+
esac
|
37
|
+
done
|
38
|
+
shift $((OPTIND -1))
|
39
|
+
|
40
|
+
if [ $# -eq 0 ]; then
|
41
|
+
log "🛑" "You must provide a command e.g. bash or ls -l"
|
42
|
+
usage "${description}" "${usage_args}" "${usage_pre}"
|
43
|
+
fi
|
44
|
+
|
45
|
+
|
46
|
+
exec_hook_if_exists "exec.pre"
|
47
|
+
|
48
|
+
log "🚂" "Running '${*}' inside container with service name '${SERVICE}'"
|
49
|
+
|
50
|
+
docker \
|
51
|
+
compose \
|
52
|
+
--file docker-compose.dx.yaml \
|
53
|
+
--project-name "${PROJECT_NAME}" \
|
54
|
+
--env-file "${ENV_FILE}" \
|
55
|
+
exec \
|
56
|
+
"${SERVICE}" \
|
57
|
+
"${@}"
|
58
|
+
|
59
|
+
# vim: ft=bash
|
data/dx/prune
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd )
|
6
|
+
|
7
|
+
. "${SCRIPT_DIR}/dx.sh.lib"
|
8
|
+
require_command "docker"
|
9
|
+
load_docker_compose_env
|
10
|
+
|
11
|
+
usage_on_help "Prune containers for this repo" "" "" "" "${@}"
|
12
|
+
|
13
|
+
for container_id in $(docker container ls -a -f "name=^${PROJECT_NAME}-.*-1$" --format="{{.ID}}"); do
|
14
|
+
log "🗑" "Removing container with id '${container_id}'"
|
15
|
+
docker container rm "${container_id}"
|
16
|
+
done
|
17
|
+
echo "🧼" "Containers removed"
|
18
|
+
|
19
|
+
# vim: ft=bash
|
data/dx/setupkit.sh.lib
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
# shellcheck shell=bash
|
2
|
+
|
3
|
+
fatal() {
|
4
|
+
remainder=${*:2}
|
5
|
+
if [ -z "$remainder" ]; then
|
6
|
+
log "🛑" "${@}"
|
7
|
+
else
|
8
|
+
log "${@}"
|
9
|
+
fi
|
10
|
+
exit 1
|
11
|
+
}
|
12
|
+
|
13
|
+
log() {
|
14
|
+
emoji=$1
|
15
|
+
remainder=${*:2}
|
16
|
+
if [ -z "${NO_EMOJI}" ]; then
|
17
|
+
echo "[ ${0} ] ${*}"
|
18
|
+
else
|
19
|
+
# if remainder is empty that means no emoji was passed
|
20
|
+
if [ -z "$remainder" ]; then
|
21
|
+
echo "[ ${0} ] ${*}"
|
22
|
+
else # emoji was passed, but we ignore it
|
23
|
+
echo "[ ${0} ] ${remainder}"
|
24
|
+
fi
|
25
|
+
fi
|
26
|
+
}
|
27
|
+
|
28
|
+
debug() {
|
29
|
+
message=$1
|
30
|
+
if [ -z "${DOCKBOX_DEBUG}" ]; then
|
31
|
+
return
|
32
|
+
fi
|
33
|
+
log "🐛" "${message}"
|
34
|
+
}
|
35
|
+
|
36
|
+
usage() {
|
37
|
+
description=$1
|
38
|
+
arg_names=$2
|
39
|
+
pre_hook=$3
|
40
|
+
post_hook=$4
|
41
|
+
echo "usage: ${0} [-h] ${arg_names}"
|
42
|
+
if [ -n "${description}" ]; then
|
43
|
+
echo
|
44
|
+
echo "DESCRIPTION"
|
45
|
+
echo " ${description}"
|
46
|
+
fi
|
47
|
+
if [ -n "${pre_hook}" ] || [ -n "${post_hook}" ]; then
|
48
|
+
echo
|
49
|
+
echo "HOOKS"
|
50
|
+
if [ -n "${pre_hook}" ]; then
|
51
|
+
echo " ${pre_hook} - if present, called before the main action"
|
52
|
+
fi
|
53
|
+
if [ -n "${post_hook}" ]; then
|
54
|
+
echo " ${post_hook} - if present, called after the main action"
|
55
|
+
fi
|
56
|
+
fi
|
57
|
+
exit 0
|
58
|
+
}
|
59
|
+
|
60
|
+
usage_on_help() {
|
61
|
+
description=$1
|
62
|
+
arg_names=$2
|
63
|
+
pre_hook=$3
|
64
|
+
post_hook=$4
|
65
|
+
# These are the args passed to the invocation so this
|
66
|
+
# function can determine if the user requested help
|
67
|
+
cli_args=( "${@:5}" )
|
68
|
+
|
69
|
+
for arg in "${cli_args[@]}"; do
|
70
|
+
if [ "${arg}" = "-h" ] || [ "${arg}" = "--help" ]; then
|
71
|
+
usage "${description}" "${arg_names}" "${pre_hook}" "${post_hook}"
|
72
|
+
fi
|
73
|
+
done
|
74
|
+
}
|
75
|
+
|
76
|
+
# Read user input into the variable 'INPUT'
|
77
|
+
#
|
78
|
+
# Args:
|
79
|
+
#
|
80
|
+
# [1] - an emoji to use for messages
|
81
|
+
# [2] - the message explaining what input is being requested
|
82
|
+
# [3] - a default value to use if no value is provided
|
83
|
+
#
|
84
|
+
# Respects NO_EMOJI when outputing messages to the user
|
85
|
+
user_input() {
|
86
|
+
emoji=$1
|
87
|
+
message=$2
|
88
|
+
default=$3
|
89
|
+
prompt=$4
|
90
|
+
|
91
|
+
if [ -z "$message" ]; then
|
92
|
+
echo "user_input requires a message"
|
93
|
+
exit 1
|
94
|
+
fi
|
95
|
+
|
96
|
+
INPUT=
|
97
|
+
|
98
|
+
if [ -z "${prompt}" ]; then
|
99
|
+
prompt=$(log "${emoji}" "Value: ")
|
100
|
+
if [ -n "${default}" ]; then
|
101
|
+
prompt=$(log "${emoji}" "Value (or hit return to use '${default}'): ")
|
102
|
+
fi
|
103
|
+
fi
|
104
|
+
|
105
|
+
while [ -z "${INPUT}" ]; do
|
106
|
+
|
107
|
+
log "$emoji" "$message"
|
108
|
+
read -r -p "${prompt}" INPUT
|
109
|
+
if [ -z "$INPUT" ]; then
|
110
|
+
INPUT=$default
|
111
|
+
fi
|
112
|
+
if [ -z "$INPUT" ]; then
|
113
|
+
log "😶", "You must provide a value"
|
114
|
+
fi
|
115
|
+
done
|
116
|
+
}
|
117
|
+
|
118
|
+
user_confirm() {
|
119
|
+
user_input "$1" "$2" "$3" "y/n> "
|
120
|
+
}
|
121
|
+
|
122
|
+
require_not_exist() {
|
123
|
+
file=$1
|
124
|
+
message=$2
|
125
|
+
if [ -e "${file}" ]; then
|
126
|
+
fatal "$message"
|
127
|
+
fi
|
128
|
+
}
|
129
|
+
require_exist() {
|
130
|
+
file=$1
|
131
|
+
message=$2
|
132
|
+
if [ ! -e "${file}" ]; then
|
133
|
+
fatal "$message"
|
134
|
+
fi
|
135
|
+
}
|
136
|
+
|
137
|
+
require_command() {
|
138
|
+
command_name=$1
|
139
|
+
if ! command -v "${command_name}" >/dev/null 2>&1; then
|
140
|
+
fatal "Command '${command_name}' not found - it is required for this script to run"
|
141
|
+
fi
|
142
|
+
}
|
143
|
+
|
144
|
+
# vim: ft=bash
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
# Ideally, the message below is shown after everything starts up. We can't
|
6
|
+
# achieve this using healtchecks because the interval for a healtcheck is
|
7
|
+
# also an initial delay, and we don't really want to do healthchecks on
|
8
|
+
# our DB or Redis every 2 seconds. So, we sleep just a bit to let
|
9
|
+
# the other containers start up and vomit out their output first.
|
10
|
+
sleep 2
|
11
|
+
# Output some helpful messaging when invoking `dx/start` (which itself is
|
12
|
+
# a convenience script for `docker compose up`.
|
13
|
+
#
|
14
|
+
# Adding this to work around the mild inconvenience of the `app` container's
|
15
|
+
# entrypoint generating no output.
|
16
|
+
#
|
17
|
+
cat <<-'PROMPT'
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
🎉 Dev Environment Initialized! 🎉
|
22
|
+
|
23
|
+
ℹ️ To use this environment, open a new terminal and run
|
24
|
+
|
25
|
+
dx/exec bash
|
26
|
+
|
27
|
+
🕹 Use `ctrl-c` to exit.
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
PROMPT
|
32
|
+
|
33
|
+
# Using `sleep infinity` instead of `tail -f /dev/null`. This may be a
|
34
|
+
# performance improvement based on the conversation on a semi-related
|
35
|
+
# StackOverflow page.
|
36
|
+
#
|
37
|
+
# @see https://stackoverflow.com/a/41655546
|
38
|
+
sleep infinity
|
data/dx/start
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd )
|
6
|
+
|
7
|
+
. "${SCRIPT_DIR}/dx.sh.lib"
|
8
|
+
require_command "docker"
|
9
|
+
load_docker_compose_env
|
10
|
+
|
11
|
+
usage_on_help "Starts all services, including a container in which to run your app" "" "" "" "${@}"
|
12
|
+
|
13
|
+
log "🚀" "Starting docker-compose.dx.yml"
|
14
|
+
|
15
|
+
BUILD=--build
|
16
|
+
if [ "${1}" == "--no-build" ]; then
|
17
|
+
BUILD=
|
18
|
+
fi
|
19
|
+
|
20
|
+
docker \
|
21
|
+
compose \
|
22
|
+
--file docker-compose.dx.yml \
|
23
|
+
--project-name "${PROJECT_NAME}" \
|
24
|
+
--env-file "${ENV_FILE}" \
|
25
|
+
up \
|
26
|
+
"${BUILD}" \
|
27
|
+
--timestamps \
|
28
|
+
--force-recreate
|
29
|
+
|
30
|
+
# vim: ft=bash
|
data/dx/stop
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd )
|
6
|
+
|
7
|
+
. "${SCRIPT_DIR}/dx.sh.lib"
|
8
|
+
require_command "docker"
|
9
|
+
load_docker_compose_env
|
10
|
+
|
11
|
+
usage_on_help "Stops all services, the container in which to run your app and removes any volumes" "" "" "" "${@}"
|
12
|
+
|
13
|
+
log "🚀" "Stopping docker-compose.dx.yml"
|
14
|
+
|
15
|
+
docker \
|
16
|
+
compose \
|
17
|
+
--file docker-compose.dx.yml \
|
18
|
+
--project-name "${PROJECT_NAME}" \
|
19
|
+
--env-file "${ENV_FILE}" \
|
20
|
+
down \
|
21
|
+
--volumes
|
22
|
+
|
23
|
+
# vim: ft=bash
|
data/gli.gemspec
CHANGED
@@ -12,6 +12,15 @@ spec = Gem::Specification.new do |s|
|
|
12
12
|
s.summary = "Build command-suite CLI apps that are awesome."
|
13
13
|
s.description = "Build command-suite CLI apps that are awesome. Bootstrap your app, add commands, options and documentation while maintaining a well-tested idiomatic command-line app"
|
14
14
|
|
15
|
+
s.metadata = {
|
16
|
+
'bug_tracker_uri' => 'https://github.com/davetron5000/gli/issues',
|
17
|
+
'changelog_uri' => 'https://github.com/davetron5000/gli/releases',
|
18
|
+
'documentation_uri' => 'https://davetron5000.github.io/gli/rdoc/index.html',
|
19
|
+
'homepage_uri' => 'https://davetron5000.github.com/gli/',
|
20
|
+
'source_code_uri' => 'https://github.com/davetron5000/gli/',
|
21
|
+
'wiki_url' => 'https://github.com/davetron5000/gli/wiki',
|
22
|
+
}
|
23
|
+
|
15
24
|
s.files = `git ls-files`.split("\n")
|
16
25
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
26
|
s.require_paths = ["lib"]
|
@@ -26,5 +35,5 @@ spec = Gem::Specification.new do |s|
|
|
26
35
|
s.add_development_dependency("rdoc")
|
27
36
|
s.add_development_dependency("rainbow", "~> 1.1", "~> 1.1.1")
|
28
37
|
s.add_development_dependency("sdoc")
|
29
|
-
s.add_development_dependency("minitest")
|
38
|
+
s.add_development_dependency("minitest", "~> 5")
|
30
39
|
end
|
@@ -109,9 +109,10 @@ module GLI
|
|
109
109
|
def verify_required_options!(flags, command, options)
|
110
110
|
missing_required_options = flags.values.
|
111
111
|
select(&:required?).
|
112
|
-
|
113
|
-
options[option.name]
|
114
|
-
|
112
|
+
select { |option|
|
113
|
+
options[option.name] == nil ||
|
114
|
+
( options[option.name].kind_of?(Array) && options[option.name].empty? )
|
115
|
+
}
|
115
116
|
unless missing_required_options.empty?
|
116
117
|
missing_required_options.sort!
|
117
118
|
raise MissingRequiredArgumentsException.new(missing_required_options.map { |option|
|
data/lib/gli/version.rb
CHANGED
data/test/unit/command_test.rb
CHANGED
data/test/unit/doc_test.rb
CHANGED
data/test/unit/flag_test.rb
CHANGED
data/test/unit/gli_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require_relative "test_helper"
|
2
2
|
require_relative "support/fake_std_out"
|
3
3
|
|
4
|
-
class GLITest <
|
4
|
+
class GLITest < Minitest::Test
|
5
5
|
include TestHelper
|
6
6
|
|
7
7
|
def setup
|
@@ -81,6 +81,25 @@ class GLITest < MiniTest::Test
|
|
81
81
|
|
82
82
|
end
|
83
83
|
|
84
|
+
def test_command_options_accepting_multiple_values_can_be_required
|
85
|
+
@app.reset
|
86
|
+
@called = false
|
87
|
+
@app.command :foo do |c|
|
88
|
+
c.flag :flag, :required => true, :multiple => true
|
89
|
+
c.action do |global, options, arguments|
|
90
|
+
@called = true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
assert_equal 64, @app.run(['foo']), "Expected exit status to be 64"
|
94
|
+
assert @fake_stderr.contained?(/flag is required/), @fake_stderr.strings.inspect
|
95
|
+
assert @fake_stderr.contained?(/flag is required/), @fake_stderr.strings.inspect
|
96
|
+
assert !@called
|
97
|
+
|
98
|
+
assert_equal 0, @app.run(['foo','--flag=bar']), "Expected exit status to be 0 #{@fake_stderr.strings.join(',')}"
|
99
|
+
assert @called
|
100
|
+
|
101
|
+
end
|
102
|
+
|
84
103
|
def test_global_options_can_be_required
|
85
104
|
@app.reset
|
86
105
|
@called = false
|
@@ -102,6 +121,25 @@ class GLITest < MiniTest::Test
|
|
102
121
|
|
103
122
|
end
|
104
123
|
|
124
|
+
def test_global_options_accepting_multiple_can_be_required
|
125
|
+
@app.reset
|
126
|
+
@called = false
|
127
|
+
@app.flag :flag, :required => true, :multiple => true
|
128
|
+
@app.command :foo do |c|
|
129
|
+
c.action do |global, options, arguments|
|
130
|
+
@called = true
|
131
|
+
end
|
132
|
+
end
|
133
|
+
assert_equal 64, @app.run(['foo']), "Expected exit status to be 64"
|
134
|
+
assert @fake_stderr.contained?(/flag is required/), @fake_stderr.strings.inspect
|
135
|
+
assert @fake_stderr.contained?(/flag is required/), @fake_stderr.strings.inspect
|
136
|
+
assert !@called
|
137
|
+
|
138
|
+
assert_equal 0, @app.run(['--flag=bar','foo']), "Expected exit status to be 0 #{@fake_stderr.strings.join(',')}"
|
139
|
+
assert @called
|
140
|
+
|
141
|
+
end
|
142
|
+
|
105
143
|
def test_global_required_options_are_ignored_on_help
|
106
144
|
@app.reset
|
107
145
|
@called = false
|
@@ -161,6 +199,7 @@ class GLITest < MiniTest::Test
|
|
161
199
|
raise failure if !failure.nil?
|
162
200
|
end
|
163
201
|
|
202
|
+
|
164
203
|
def test_command_line_overrides_config
|
165
204
|
failure = nil
|
166
205
|
@app.reset
|
data/test/unit/help_test.rb
CHANGED
data/test/unit/options_test.rb
CHANGED
data/test/unit/switch_test.rb
CHANGED
data/test/unit/terminal_test.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.21.
|
4
|
+
version: 2.21.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Copeland
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-07-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -76,16 +76,16 @@ dependencies:
|
|
76
76
|
name: minitest
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
78
78
|
requirements:
|
79
|
-
- - "
|
79
|
+
- - "~>"
|
80
80
|
- !ruby/object:Gem::Version
|
81
|
-
version: '
|
81
|
+
version: '5'
|
82
82
|
type: :development
|
83
83
|
prerelease: false
|
84
84
|
version_requirements: !ruby/object:Gem::Requirement
|
85
85
|
requirements:
|
86
|
-
- - "
|
86
|
+
- - "~>"
|
87
87
|
- !ruby/object:Gem::Version
|
88
|
-
version: '
|
88
|
+
version: '5'
|
89
89
|
description: Build command-suite CLI apps that are awesome. Bootstrap your app, add
|
90
90
|
commands, options and documentation while maintaining a well-tested idiomatic command-line
|
91
91
|
app
|
@@ -97,10 +97,9 @@ extra_rdoc_files:
|
|
97
97
|
- README.rdoc
|
98
98
|
- gli.rdoc
|
99
99
|
files:
|
100
|
-
- ".circleci/config.yml"
|
101
100
|
- ".gitignore"
|
102
|
-
- ".tool-versions"
|
103
101
|
- CONTRIBUTING.md
|
102
|
+
- Dockerfile.dx
|
104
103
|
- Gemfile
|
105
104
|
- LICENSE.txt
|
106
105
|
- README.rdoc
|
@@ -109,6 +108,15 @@ files:
|
|
109
108
|
- bin/gli
|
110
109
|
- bin/rake
|
111
110
|
- bin/setup
|
111
|
+
- dx/build
|
112
|
+
- dx/docker-compose.env
|
113
|
+
- dx/dx.sh.lib
|
114
|
+
- dx/exec
|
115
|
+
- dx/prune
|
116
|
+
- dx/setupkit.sh.lib
|
117
|
+
- dx/show-help-in-app-container-then-wait.sh
|
118
|
+
- dx/start
|
119
|
+
- dx/stop
|
112
120
|
- exe/gli
|
113
121
|
- gli.cheat
|
114
122
|
- gli.gemspec
|
@@ -204,8 +212,14 @@ files:
|
|
204
212
|
homepage: http://davetron5000.github.io/gli
|
205
213
|
licenses:
|
206
214
|
- Apache-2.0
|
207
|
-
metadata:
|
208
|
-
|
215
|
+
metadata:
|
216
|
+
bug_tracker_uri: https://github.com/davetron5000/gli/issues
|
217
|
+
changelog_uri: https://github.com/davetron5000/gli/releases
|
218
|
+
documentation_uri: https://davetron5000.github.io/gli/rdoc/index.html
|
219
|
+
homepage_uri: https://davetron5000.github.com/gli/
|
220
|
+
source_code_uri: https://github.com/davetron5000/gli/
|
221
|
+
wiki_url: https://github.com/davetron5000/gli/wiki
|
222
|
+
post_install_message:
|
209
223
|
rdoc_options:
|
210
224
|
- "--title"
|
211
225
|
- Git Like Interface
|
@@ -224,8 +238,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
224
238
|
- !ruby/object:Gem::Version
|
225
239
|
version: '0'
|
226
240
|
requirements: []
|
227
|
-
rubygems_version: 3.
|
228
|
-
signing_key:
|
241
|
+
rubygems_version: 3.5.15
|
242
|
+
signing_key:
|
229
243
|
specification_version: 4
|
230
244
|
summary: Build command-suite CLI apps that are awesome.
|
231
245
|
test_files: []
|
data/.circleci/config.yml
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
version: 2.1
|
2
|
-
orbs:
|
3
|
-
# See https://circleci.com/developer/orbs/orb/circleci/ruby
|
4
|
-
ruby: circleci/ruby@2.0.1
|
5
|
-
jobs: # keyword
|
6
|
-
test: # my name for the job
|
7
|
-
parameters: # keyword
|
8
|
-
ruby-version: # my parameter name
|
9
|
-
type: string # type is a keyword
|
10
|
-
docker: # keyword
|
11
|
-
- image: cimg/base:stable
|
12
|
-
steps: # keyword
|
13
|
-
- checkout # magic name
|
14
|
-
- ruby/install: # ruby/ is from the orb name, install is a command in that orb
|
15
|
-
version: << parameters.ruby-version >> # magic nonsense for param subst (version param to the command)
|
16
|
-
- run:
|
17
|
-
command: "bin/setup"
|
18
|
-
- run:
|
19
|
-
command: "bin/ci none"
|
20
|
-
workflows: # keyword
|
21
|
-
all-rubies: # my name for the workflow
|
22
|
-
jobs: # keyword
|
23
|
-
- test: # my name for the job
|
24
|
-
matrix: # keyword
|
25
|
-
parameters: # keyword
|
26
|
-
# All rubies being maintained per this page:
|
27
|
-
# https://www.ruby-lang.org/en/downloads/branches/
|
28
|
-
# These also need to have complete version numbers
|
29
|
-
# or rvm won't install
|
30
|
-
ruby-version: [ "3.0.4", "3.1.3", "3.2.2" ]
|
data/.tool-versions
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
ruby 2.7.1
|