mirror of https://github.com/kdabir/has.git
Freshen Makefile and update README.md (#31)
Details: * Freshen Makefile and update README.md - [x] Add `sudo` to revelvant commands - [x] Use named languages (bash) in fenced codeblocks - [x] Use `console` in fenced codeblocks for command output - [x] Use `install` with permission mode The permissions on `has` were 777 from `git clone`. - [x] Add option to use $PREFIX What if I don't want to install to /usr/local/bin? `make PREFIX=$HOME/.local install` now works. - [x] Add `update` target for `git pull` - [x] Include .PHONY targets * Freshen Makefile and update README.md - [x] Add `sudo` to revelvant commands - [x] Use named languages (bash) in fenced codeblocks - [x] Use `console` in fenced codeblocks for command output - [x] Use `install` with permissions set The permissions on `has` were 777 from `git clone`. - [x] Add option to use $PREFIX What if I don't want to install to /usr/local/bin? `make PREFIX=$HOME/.local install` now works. - [x] Add `update` target for `git pull` - [x] Include .PHONY targets - [x] Add tests for Makefile changes - [x] Uses `bats` variables for directories - ✓ make install creates a valid installation - ✓ ..even if has is missing from directory - ✓ make update runs git pull * Update .hastest.bats temp remove "git pull" check. * Update travis to use bats-core 1.10 Do not be concerned about dirty working tree when running make update. * Change version output to non-blinking. * Update travis to use bats-core 1.10 Do not be concerned about dirty working tree when running make update. * Working makefile * Use `[[` and `@` for the $lines match. * `make install` MacOS friendly again
This commit is contained in:
parent
3b26771c8a
commit
36e11e238f
|
@ -1,19 +1,64 @@
|
||||||
#!/usr/bin/env bats
|
#!/usr/bin/env bats
|
||||||
|
|
||||||
|
INSTALL_DIR=
|
||||||
|
BATS_TMPDIR=${BATS_TMPDIR:-/tmp}
|
||||||
|
|
||||||
## We need to create a new directory to that .hasrc file in the root does not get read by the `has` instance under test
|
## We need to create a new directory so that .hasrc file in the root does not get read by the `has` instance under test
|
||||||
setup() {
|
setup() {
|
||||||
mkdir -p ./tmp-for-test
|
export BATS_TEST_TMPDIR="$BATS_TMPDIR/tmp-for-test"
|
||||||
cp -f has ./tmp-for-test/
|
mkdir -p "$BATS_TEST_TMPDIR"
|
||||||
cd tmp-for-test
|
cp -f has "$BATS_TEST_TMPDIR"
|
||||||
|
cd "$BATS_TEST_TMPDIR"
|
||||||
}
|
}
|
||||||
|
|
||||||
teardown() {
|
teardown() {
|
||||||
cd ..
|
if [[ -n "$BATS_TEST_TMPDIR" ]]; then
|
||||||
rm -rf ./tmp-for-test
|
rm -rf "$BATS_TEST_TMPDIR"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "make install creates a valid installation" {
|
||||||
|
INSTALL_DIR="${BATS_TEST_TMPDIR}/.local"
|
||||||
|
cd "${BATS_TEST_DIRNAME}"
|
||||||
|
run make PREFIX="${INSTALL_DIR}" install
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[ -x "${INSTALL_DIR}/bin/has" ]
|
||||||
|
|
||||||
|
# has reads .hasrc from $PWD, so change anywhere else.
|
||||||
|
cd "${INSTALL_DIR}"
|
||||||
|
run "${INSTALL_DIR}/bin/has"
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[ "${lines[0]%% *}" == 'has' ]
|
||||||
|
[ "${lines[1]%% *}" == 'USAGE:' ]
|
||||||
|
rm -rf ${INSTALL_DIR}
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "..even if has is missing from directory" {
|
||||||
|
INSTALL_DIR="${BATS_TEST_TMPDIR}/system_local"
|
||||||
|
cd "${BATS_TEST_DIRNAME}"
|
||||||
|
mv has has-been
|
||||||
|
run make PREFIX="${INSTALL_DIR}" install
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[ -x "${INSTALL_DIR}/bin/has" ]
|
||||||
|
cd "${BATS_TEST_DIRNAME}"
|
||||||
|
mv has-been has
|
||||||
|
rm -rf ${INSTALL_DIR}
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "make update runs git fetch" {
|
||||||
|
cd "${BATS_TEST_DIRNAME}"
|
||||||
|
run make update
|
||||||
|
[[ "$status" -eq 0 ]]
|
||||||
|
[[ "${lines[@]}" =~ "git fetch --verbose" ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "has prints help" {
|
||||||
|
run bash has
|
||||||
|
|
||||||
|
[[ "$(echo "${output}" | grep "has")" ]]
|
||||||
|
[[ "$(echo "${output}" | grep "USAGE:")" ]]
|
||||||
|
[[ "$(echo "${output}" | grep "EXAMPLE:")" ]]
|
||||||
|
}
|
||||||
@test "works with single command check" {
|
@test "works with single command check" {
|
||||||
run bash has git
|
run bash has git
|
||||||
|
|
||||||
|
@ -73,12 +118,3 @@ teardown() {
|
||||||
[[ "$(echo "${output}" | grep "✔" | grep "git")" ]]
|
[[ "$(echo "${output}" | grep "✔" | grep "git")" ]]
|
||||||
[[ "$(echo "${output}" | grep "✔" | grep "bc")" ]]
|
[[ "$(echo "${output}" | grep "✔" | grep "bc")" ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "has prints help" {
|
|
||||||
|
|
||||||
run bash has
|
|
||||||
|
|
||||||
[[ "$(echo "${output}" | grep "has")" ]]
|
|
||||||
[[ "$(echo "${output}" | grep "USAGE:")" ]]
|
|
||||||
[[ "$(echo "${output}" | grep "EXAMPLE:")" ]]
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
language: bash
|
language: bash
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- sudo add-apt-repository ppa:duggan/bats --yes
|
- git clone https://github.com/bats-core/bats-core.git /tmp/bats-core
|
||||||
- sudo apt-get update -qq
|
- mkdir -p /tmp/local
|
||||||
- sudo apt-get install -qq bats
|
- bash /tmp/bats-core/install.sh /tmp/local
|
||||||
|
- export PATH=$PATH:/tmp/local/bin
|
||||||
install:
|
install:
|
||||||
- sudo apt-get install -qq bc
|
- sudo apt-get install -qq bc
|
||||||
script:
|
script:
|
||||||
|
|
40
Makefile
40
Makefile
|
@ -1,8 +1,38 @@
|
||||||
test:
|
# Makefile for has
|
||||||
|
# https://github.com/kdabir/has
|
||||||
|
|
||||||
|
# PREFIX is an environment variable.
|
||||||
|
# Use default value if not set.
|
||||||
|
ifeq ($(PREFIX),)
|
||||||
|
PREFIX := /usr/local
|
||||||
|
endif
|
||||||
|
|
||||||
|
test : has
|
||||||
bats .hastest.bats
|
bats .hastest.bats
|
||||||
|
|
||||||
install:
|
has :
|
||||||
cp has /usr/local/bin/has
|
# ensure 'has' in repo
|
||||||
|
git checkout --force -- has
|
||||||
|
|
||||||
|
install : has
|
||||||
|
# install 'has' in specified directory
|
||||||
|
chmod 755 has && \
|
||||||
|
mkdir --verbose --parents $(DESTDIR)$(PREFIX)/bin && \
|
||||||
|
cp --verbose --update has $(DESTDIR)$(PREFIX)/bin/has
|
||||||
|
|
||||||
|
# update: has
|
||||||
|
update : update-fetch has
|
||||||
|
|
||||||
|
update-fetch : update-force
|
||||||
|
# update repo from upstream
|
||||||
|
git fetch --verbose --force
|
||||||
|
|
||||||
|
update-force :
|
||||||
|
# remove local repo 'has' to force update
|
||||||
|
rm --force has
|
||||||
|
|
||||||
|
uninstall :
|
||||||
|
rm --force /usr/local/bin/has
|
||||||
|
|
||||||
|
.PHONY: test install uninstall update
|
||||||
|
|
||||||
uninstall:
|
|
||||||
rm -f /usr/local/bin/has
|
|
||||||
|
|
136
README.md
136
README.md
|
@ -1,93 +1,115 @@
|
||||||
# has
|
# has
|
||||||
|
|
||||||
`has` checks presence of various command line tools on the PATH and reports their installed version.
|
`has` checks presence of various command line tools on the PATH and reports their installed version.
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/kdabir/has.svg?branch=master)](https://travis-ci.org/kdabir/has)
|
[![Build Status](https://travis-ci.org/kdabir/has.svg?branch=master)](https://travis-ci.org/kdabir/has)
|
||||||
[![Open Source Helpers](https://www.codetriage.com/kdabir/has/badges/users.svg)](https://www.codetriage.com/kdabir/has)
|
[![Open Source Helpers](https://www.codetriage.com/kdabir/has/badges/users.svg)](https://www.codetriage.com/kdabir/has)
|
||||||
|
|
||||||
|
|
||||||
[![demo](demo.svg)](demo.svg)
|
[![demo](demo.svg)](demo.svg)
|
||||||
|
|
||||||
|
|
||||||
## How ?
|
## How ?
|
||||||
|
|
||||||
[Install](#installing) the `has` script. There is no dependency apart from `bash` itself
|
[Install](#installing) the `has` script. There is no dependency apart from `bash` itself.
|
||||||
|
|
||||||
$ has node npm java git gradle
|
```console
|
||||||
✔ node 8.2.1
|
$ has node npm java git gradle
|
||||||
✔ npm 5.3.0
|
✔ node 8.2.1
|
||||||
✔ java 1.8.0
|
✔ npm 5.3.0
|
||||||
✔ git 2.14.1
|
✔ java 1.8.0
|
||||||
✔ gradle 4.0.1
|
✔ git 2.14.1
|
||||||
|
✔ gradle 4.0.1
|
||||||
|
```
|
||||||
|
|
||||||
If everything is good `has` exits with status code `0`. The status code
|
If everything is good `has` exits with status code `0`. The status code reflects number of commands **not found** on your path.
|
||||||
reflects number of commands **not found** on your path.
|
|
||||||
|
|
||||||
$ has node go javac
|
```console
|
||||||
✔ node 8.2.1
|
$ has node go javac
|
||||||
✔ go 1.8.3
|
✔ node 8.2.1
|
||||||
✘ javac
|
✔ go 1.8.3
|
||||||
|
✘ javac
|
||||||
|
```
|
||||||
|
|
||||||
And echo the status:
|
And echo the status:
|
||||||
|
|
||||||
$ echo $?
|
```console
|
||||||
1
|
$ echo $?
|
||||||
|
1
|
||||||
|
```
|
||||||
|
|
||||||
## Installing
|
## Installing
|
||||||
|
|
||||||
`has` is a single bash script that does it all. Just [download](https://raw.githubusercontent.com/kdabir/has/master/has) the script and make it available on your `$PATH`. However, to make it even simpler, just follow *one* of these methods.
|
`has` is a single bash script that does it all. Just [download](https://raw.githubusercontent.com/kdabir/has/master/has) the script and make it available on your `$PATH`. However, to make it even simpler, just follow *one* of these methods.
|
||||||
|
|
||||||
|
|
||||||
### Cloning the Repo
|
### Cloning the Repo
|
||||||
|
|
||||||
Just execute the following command in terminal, it clones has repo and install it in your path
|
Just execute the following command in a terminal: it clones `has` repo and installs it into your path.
|
||||||
|
|
||||||
git clone https://github.com/kdabir/has.git && cd has && make install
|
```bash
|
||||||
|
git clone https://github.com/kdabir/has.git && cd has && sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
To update just do a `git pull` and `make install`.
|
For a non-root installation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/kdabir/has.git
|
||||||
|
cd has
|
||||||
|
make PREFIX=$HOME/.local install
|
||||||
|
```
|
||||||
|
|
||||||
|
To update just do a `git fetch` or `make update` followed by the appropriate `make install` command.
|
||||||
|
|
||||||
### Downloading to a file
|
### Downloading to a file
|
||||||
|
|
||||||
curl -sL https://git.io/_has > /usr/local/bin/has
|
```bash
|
||||||
|
curl -sL https://git.io/_has > /usr/local/bin/has
|
||||||
|
```
|
||||||
|
|
||||||
This command is safe to be called multiple times as well. (to update `has`)
|
```bash
|
||||||
|
curl -sL https://git.io/_has | sudo tee /usr/local/bin/has >/dev/null
|
||||||
|
```
|
||||||
|
|
||||||
### Running directly off the internet
|
These commands are safe to be called multiple times as well (to update `has`)
|
||||||
|
|
||||||
If you are lazy, you can run `has` directly off the internet as well:
|
### Running directly off the Internet
|
||||||
|
|
||||||
curl -sL https://git.io/_has | bash -s git node npm
|
If you are lazy, you can run `has` directly off the Internet as well:
|
||||||
✔ git 2.14.1
|
|
||||||
✔ node 8.2.1
|
|
||||||
✔ npm 5.3.0
|
|
||||||
|
|
||||||
|
```console
|
||||||
|
curl -sL https://git.io/_has | bash -s git node npm
|
||||||
|
✔ git 2.17.1
|
||||||
|
✔ node 11.11.0
|
||||||
|
✔ npm 6.7.0
|
||||||
|
```
|
||||||
|
|
||||||
**ProTip**: if that's too much of typing every time, setup an alias in your `.bashrc`/`.zshrc` file:
|
**ProTip**: if that's too much typing every time, setup an alias in your `.bashrc`/`.zshrc` file:
|
||||||
|
|
||||||
alias has="curl -sL https://git.io/_has | bash -s"
|
```.bashrc
|
||||||
|
alias has="curl -sL https://git.io/_has | bash -s"
|
||||||
|
```
|
||||||
|
|
||||||
And use it
|
And use it
|
||||||
|
|
||||||
$ has git
|
```console
|
||||||
✔ git 2.14.1
|
$ has git
|
||||||
|
✔ git 2.17.1
|
||||||
|
$ type has
|
||||||
|
has is aliased to `curl -sL https://git.io/_has | bash -s'
|
||||||
|
```
|
||||||
|
|
||||||
## Command not understood by has?
|
## Command not understood by has?
|
||||||
|
|
||||||
Let's say `$ has foobar` returns `foobar not understood`, because `has` may not have whitelisted `foobar`.
|
Let's say `$ has foobar` returns `foobar not understood`, because `has` may not have whitelisted `foobar`.
|
||||||
|
|
||||||
In such cases, pass `HAS_ALLOW_UNSAFE=y has foobar`. This is should still check for existance of `foobar` and tries to detect version as well.
|
In such cases, pass `HAS_ALLOW_UNSAFE=y has foobar`. This should still check for existance of `foobar` and tries to detect version as well.
|
||||||
|
|
||||||
|
|
||||||
## The `.hasrc` file
|
## The `.hasrc` file
|
||||||
|
|
||||||
`has` looks for `.hasrc` file in the directory from where `has` command is issued. This file can contain commands that `has`
|
`has` looks for `.hasrc` file in the directory from where `has` command is issued. This file can contain commands that `has`
|
||||||
will check for. List one command per line. Lines starting with `#` are treated as comments.
|
will check for. List one command per line. Lines starting with `#` are treated as comments.
|
||||||
|
|
||||||
|
|
||||||
Following is example of `.hasrc` file:
|
Following is example of `.hasrc` file:
|
||||||
|
|
||||||
```
|
```hs
|
||||||
# tools
|
# tools
|
||||||
git
|
git
|
||||||
curl
|
curl
|
||||||
|
@ -95,22 +117,22 @@ curl
|
||||||
# interpreters
|
# interpreters
|
||||||
ruby
|
ruby
|
||||||
node
|
node
|
||||||
```
|
|
||||||
|
|
||||||
When `has` is run in dir containing this file, it produces:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
When `has` is run in directory containing this file, it produces:
|
||||||
|
|
||||||
|
```console
|
||||||
$ has
|
$ has
|
||||||
✔ git 2.19.1
|
✔ git 2.19.1
|
||||||
✔ curl 7.54.0
|
✔ curl 7.54.0
|
||||||
✔ ruby 2.3.1
|
✔ ruby 2.3.1
|
||||||
✔ node 10.7.0
|
✔ node 10.7.0
|
||||||
```
|
```
|
||||||
|
|
||||||
Also, CLI arguments passed to `has` are additive to `.hasrc` file. For example, in the same dir, if the following command is fired,
|
Also, CLI arguments passed to `has` are additive to `.hasrc` file. For example, in the same dir, if the following command is fired,
|
||||||
`has` checks for both commands passed from cli args and provided in `.hasrc` file.
|
`has` checks for both commands passed from cli args and provided in `.hasrc` file.
|
||||||
|
|
||||||
```
|
```bash
|
||||||
$ has java
|
$ has java
|
||||||
✔ java 11.0.1
|
✔ java 11.0.1
|
||||||
✔ git 2.19.1
|
✔ git 2.19.1
|
||||||
|
@ -119,31 +141,27 @@ $ has java
|
||||||
✔ node 10.7.0
|
✔ node 10.7.0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
**Pro Tip**: commit `.hasrc` file in root of your project. This can work as a quick check for confirming presence all command
|
**Pro Tip**: commit `.hasrc` file in root of your project. This can work as a quick check for confirming presence all command
|
||||||
line tools required to build and run your project.
|
line tools required to build and run your project.
|
||||||
|
|
||||||
On machines that don't even have `has` installed, your project's `.hasrc` is honored by this command:
|
On machines that don't even have `has` installed, your project's `.hasrc` is honored by this command:
|
||||||
|
|
||||||
`curl -sL https://git.io/_has | bash -s`
|
`curl -sL https://git.io/_has | bash -s`
|
||||||
|
|
||||||
> take a look at [.hasrc](https://github.com/kdabir/has/blob/master/.hasrc) file of this repo
|
|
||||||
|
|
||||||
|
> take a look at [.hasrc](https://github.com/kdabir/has/blob/master/.hasrc) file for this repo.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
1. Star the repo, tweet about it, spread the word
|
||||||
1. Star the repo, tweet about it, spread the word
|
|
||||||
2. Update the documentation (i.e. the README file)
|
2. Update the documentation (i.e. the README file)
|
||||||
3. Adding support for more commands
|
3. Adding support for more commands
|
||||||
4. Adding more features to `has`
|
4. Adding more features to `has`
|
||||||
|
|
||||||
|
|
||||||
## Adding Features
|
## Adding Features
|
||||||
|
|
||||||
If you are contributing a feature, please ensure to check current tests. Add test cases for your feature. Tests are
|
If you are contributing a feature, please ensure to check current tests. Add test cases for your feature. Tests are
|
||||||
executed using the excellent [bats](https://github.com/bats-core/bats-core) testing framework. Add tests and run `make test`
|
executed using the excellent [bats](https://github.com/bats-core/bats-core) testing framework. Add tests and run `make test`
|
||||||
|
|
||||||
Raise the PR and make sure the tests pass on [Travis-CI](https://travis-ci.org/kdabir/has).
|
|
||||||
|
|
||||||
#### ♥
|
Raise the PR and **make sure the tests pass** on [Travis-CI](https://travis-ci.org/kdabir/has).
|
||||||
|
|
||||||
|
### ♥
|
||||||
|
|
3
has
3
has
|
@ -19,7 +19,6 @@ REGEX_SIMPLE_VERSION="([[:digit:]]+\.?){2,3}"
|
||||||
## RC file can contain commands to be tested
|
## RC file can contain commands to be tested
|
||||||
RC_FILE=".hasrc"
|
RC_FILE=".hasrc"
|
||||||
|
|
||||||
|
|
||||||
# try to extract version by executing $1 with $2 arg
|
# try to extract version by executing $1 with $2 arg
|
||||||
__dynamic_detect(){
|
__dynamic_detect(){
|
||||||
cmd=$1
|
cmd=$1
|
||||||
|
@ -77,7 +76,7 @@ __detect(){
|
||||||
vim|emacs|nano|subl) __dynamic_detect--version ${command} ;;
|
vim|emacs|nano|subl) __dynamic_detect--version ${command} ;;
|
||||||
bats|tree|ack|autojump) __dynamic_detect--version ${command} ;;
|
bats|tree|ack|autojump) __dynamic_detect--version ${command} ;;
|
||||||
jq|ag|brew) __dynamic_detect--version ${command} ;;
|
jq|ag|brew) __dynamic_detect--version ${command} ;;
|
||||||
|
|
||||||
R) __dynamic_detect--version ${command} ;;
|
R) __dynamic_detect--version ${command} ;;
|
||||||
node|npm|yarn) __dynamic_detect--version ${command} ;;
|
node|npm|yarn) __dynamic_detect--version ${command} ;;
|
||||||
grunt|brunch) __dynamic_detect--version ${command} ;;
|
grunt|brunch) __dynamic_detect--version ${command} ;;
|
||||||
|
|
Loading…
Reference in New Issue