Giter Club home page Giter Club logo

has's Introduction

has

has checks presence of various command line tools on the PATH and reports their installed version.

Build Status Open Source Helpers

demo

Quick Start 🚴

Just install the has script, (there is no dependency apart from bash itself). From the command line, pass the list of commands you want to check as arguments to has, for example:

$ has node npm java git gradle
✔ node 8.2.1
✔ npm 5.3.0
✔ java 1.8.0
✔ git 2.14.1
✔ gradle 4.0.1

If everything is good has exits with status code 0. The exit status code reflects number of commands not found on your path.

$ has node go javac
✔ node 8.2.1
✔ go 1.8.3
✘ javac

And echo the status:

$ echo $?
1

Use has in scripts

has can be used in shell scripts to check presence of tool in very readable way

if has node
    then echo you have what it takes 🎉
fi

Pro Tip: the has in above command can be replaced with the entire curl command for to ensure portability of script → if curl -sL https://git.io/_has | bash -s node then ...

Installing 🚀

has is a single bash script that does it all. You can download the script and make it available on your $PATH. However, to make it even simpler, just follow one of these methods.

Homebrew (MacOS) 🍺

Just run the following:

brew install kdabir/tap/has

Cloning the Repo

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 && sudo make install

For a non-root installation:

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

curl -sL https://git.io/_has > /usr/local/bin/has
curl -sL https://git.io/_has | sudo tee /usr/local/bin/has >/dev/null

These commands are safe to be called multiple times as well (to update has)

asdf users

asdf plugin add has https://github.com/sylvainmetayer/asdf-has
asdf install has 1.4.0

Running directly off the Internet

If you are lazy, you can run has directly off the Internet as well:

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 typing every time, setup an alias in your .bashrc/.zshrc file:

alias has="curl -sL https://git.io/_has | bash -s"

And use it

$ 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?

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 should still check for existence of foobar and tries to detect version as well.

the value must exactly be y for it to work.

The .hasrc file

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.

Following is example of .hasrc file:

# tools
git
curl

# interpreters
ruby
node

When has is run in directory containing this file, it produces:

$ has
✔ git 2.19.1
✔ curl 7.54.0
✔ ruby 2.3.1
✔ 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, has checks for both commands passed from cli args and provided in .hasrc file.

$ has java
✔ java 11.0.1
✔ git 2.19.1
✔ curl 7.54.0
✔ ruby 2.3.1
✔ 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 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:

curl -sL https://git.io/_has | bash -s

take a look at .hasrc file for this repo.

Contributing

  1. Star the repo, tweet about it, spread the word
  2. Update the documentation (i.e. the README file)
  3. Adding support for more commands
  4. Adding more features to has

Adding more tools

The current list of supported packages can be viewed with bash tests/packages_all.sh

If the command you wish to include supports any of -v, --version, -version, version, -V then you can find corresponding function which can be called to check presence and extract version. However, for many tools version extraction may not work and you will need to add custom parsing of command's output. The has script is commented to guide developers about what needs to be done to add more tools.

/tests/test_all_packages.bats will test every package has supports. This includes newly added commands so please add new packages to

  • alpine.Dockerfile and ubuntu.Dockerfile to install the tool OR
  • packages_alpine_skip.txt and packages_ubuntu_skip.txt to exclude the package from the tests

Adding Features

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 testing framework. Add tests and run make test

Raise the PR and make sure the tests pass on GitHub Actions.

has's People

Contributors

abhishekamralkar avatar agarrharr avatar arkoprabho avatar ashishmohite avatar cclauss avatar codetriage-readme-bot avatar dexterous avatar fairclothjm avatar freed-wu avatar iamtalas avatar johan-ejstrud avatar kdabir avatar layik avatar mak9su4roi avatar peterdavehello avatar ptt-homme avatar reyemxela avatar sdolenc avatar sneedcat avatar someth2say avatar sylvainmetayer avatar thornycrackers avatar vimist avatar virgilwashere avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

has's Issues

add GnuPG/gpg

Question

  • gpg* command map to gnupg
    • gpg
    • gpg2
    • gpgconf
    • gpg-agent

``console`
$ gpg --version
gpg (GnuPG) 2.2.4

improve documentation and add code comments

Let alone new contributors, even for myself when looking at the project after an year or so, it is very difficult to understand what the specific section of the script does.

  • Create a CONTRIBUTING.md
  • annotate tricky sections of code with comments
  • Create simple how to's, eg:
    • how to add a new tool,
    • how to update tests

Exit code can overflow, falsely indicating success

has $(for i in {1..256}; do echo go; done)
echo $?

This will appear to indicate success regardless of whether the system has go or not, because the real exit code of 256 is truncated (only the least significant eight bits are used).

More recipes, please!

Awesome tool! I once wrote a similar tool, for quickly gathering disparate and differently syntaxed program information, specs:

https://github.com/mcandre/specs

Feel free to steal more commands for gathering versions into has, I'd love to see has be able to handle Web browser versions, OS versions, and more!

Eliminate the need to build binaries

Coupled with a single top level dq executable, this should allow us to just drop/checkout the code into $HOME/bin or add it to PATH and have access to all the dq niceness.

implement timeout

no idea how yet, but sbt gets stuck sometimes (may be it was trying to download the internet).

support quiet mode

support -q of something similar to disable output for command line. This can be useful in scripts using has only for the exit status code.

`has` can't identity `nvim` (Neovim)

Running has over the Internet i.e with a curl command like the following:

curl -sL https://git.io/_has | bash -s nvim

... throws the following error:

✗ nvim not understood

I would like to make it clear, nvim is a valid command I invoke Neovim with & running nvim --version returns the following output:

NVIM v0.6.1
Build type: Release
LuaJIT 2.1.0-beta3
Compiled by linuxbrew@a1e553b903c7

Features: +acl +iconv +tui
See ":help feature-compile"

   system vimrc file: "$VIM/sysinit.vim"
  fall-back for $VIM: "
/home/linuxbrew/.linuxbrew/Cellar/neovim/0.6.1/share/nvim"

Run :checkhealth for more info

So, how do I check if Neovim has been installed or not with has?

Add more tools

This is an umbrella issue to support more tools from various languages ecosystems like python, clojure, scala, php and others.

Following commands need to be supported. More can be added/suggested:

  • clojure, lein
  • scala, sbt
  • php
  • python ecosystem

Fix the CI

Some test are always failing, need to look into it and fix them

image
  • fix shell check
  • fix test_all (ubuntu/alpine)

[feature] Add shell completions

Just change Makefile to install /usr/share/zsh/site-functions/_has:

#compdef has

_arguments -s -S \
  -q'[Silent mode]' \
  {-h,--help}'[Display this help text and quit]' \
  {-V,--version}'[Show version number and quit]' \
  '*: :{_command_names -e}'
❯ has -<TAB>
external command
option
-h          Display this help text and quit
--help      Display this help text and quit
-q          Silent mode
--version   Show version number and quit
-V          Show version number and quit
❯ has -q <TAB>
external command
7za                                 A file archiver with highest compression ratio
7z                                  A file archiver with highest compression ratio
7zr                                 A file archiver with highest compression ratio
a2ping                              convert between PS, EPS and PDF and other page description formats
a52dec                              decode ATSC A/52 audio streams
...

TIA.

Should detect nvm for node

The script doesn't detect the presence of the node version manager script which can be used to handle having multiple node version installed. When no version is selected by default the node command is not available but that shouldn't lower the dev quotient

( you probably want to detect rvm too :D )

SIGPIPE

While implementing some new tools (php5 on alpine in this case), I have found that SIGPIPE (exit code 141) is being returned. The version is correctly captured, it's just that the head command truncates the output.

bash-4.3# bash -x ./has php5
# Removed some output here for brevity
+ __dynamic_detect php5 --version
+ cmd=php5
+ params=--version
++ eval php5 --version '2>&1'
++ +++ egrep php5 -o --version'([[:digit:]]+\.?){2,3}'

++ head -1
+ version=5.6.31
+ status=141
+ '[' 141 -eq -1 ']'
+ '[' 141 -eq 127 ']'
+ '[' 141 -eq 0 ']'
+ echo ✔ php5
✔ php5
+ OK=1
+ exit 0

I think we should output the version and treat 141 as a success. I'll put a pull request in to implement this.

add OpenSSH and OpenSSL

config

  • ssh command map to openssh

Question

  • OpenSSL regex to include date string ??

``console`
$ ssh -V
OpenSSH_7.6p1 Ubuntu-4ubuntu0.3, OpenSSL 1.0.2n 7 Dec 2017
$ openssl version
OpenSSL 1.1.1b 26 Feb 2019

Hide versions info

Since this is achievable by following command, I don't really see the need to incorporate a flag in has to hide versions. let's keep has as cli-flags-free as possible.

$ has java node | cut -d' ' -f1,2
✔ java
✔ node

inception: "has not understood" and "✔ has 22"

It feels like has should handle itself, eh ;)

$ has has
✘ has not understood

And even it was hard coded to do so, it parses its own version incorrectly:

$ HAS_ALLOW_UNSAFE=y has has
✔ has 22

This is using:

$ has
has v1.1.0
USAGE:    has <command-names>..
EXAMPLE:  has git curl node

First time here. Thanks for an interesting tool. In the best of the best world, all software tools should have versions and there should be a standard way of querying it.

Ability to test version output in isolation

If we change the current regex, we are not sure if existing commands' version can still be extracted. we can't run all commands in CI because they might not be present on CI servers in the first place.

To solve this, the code needs to be organized such that the version extraction is decoupled from the command execution part.

  1. Execute the command and capture the output (both out & err), and exit status
  2. Compare the exit status against valid status (mostly 0 but can be different for some commands)
  3. Pass the output for some default version extraction strategies, or custom ones if command needs one
  4. These strategies must be functions that can be unit tested in bats file against actual output of commands.

test container location

Thank you for merging #43 which gets us closer to testing every package has supports. I'll aim to submit pull requests that get us even closer to 100% in the future.

The Github Actions tests are currently using containers built from my fork of has, but it would be better if we built the containers using this official fork https://github.com/kdabir/has . That way future changes to the official dockerfiles would update the containers we use for testing.

If that sounds okay to you then could you please

  1. Sign in to https://hub.docker.com/ to create a new testing-has repository
  2. Build the four dockerfiles using settings similar to these
    image
  3. Then (after successful builds) updating Github Actions to use the official images instead of the "sdolenc" ones
    container: sdolenc/testing-has:${{ matrix.container }}
    and
    container: sdolenc/testing-has:${{ matrix.container }}

If it helps: I've added you as a collaborator for my repository on https://hub.docker.com

[feature] add support for detecting the stdout

❯ has python > a.txt && cat -A a.txt
^[[1m^[[32mM-bM-^\M-^S^[[m^O python ^[[1m^[[33m3.9.6^[[m^O$

why not let has detect stdout? if the output is a stdout, let has output with color, if the output is a file, let has output without color.
A simple solution is

# stdout is /dev/fd/1
[ -t 1 ] && color=1 || color=0

Moreover, like a option named --color={always, auto, never}, default is auto will be better. many program like fd, rg, exa use --color to control if the program output with color.

thanks.

Support rc file

Projects can check-in their dependencies in .hasrc or Hasfile. Users can keep a.hasrc in their home directory. Has should check current dir for this file or home dir.

Commands passed from CLI should be additive to the ones in this files.

Add command options for help and version.

Add -h and -V options

Basic getopts version:

  #-----------------------------------------------------------------------
  #  Handle command line arguments
  #-----------------------------------------------------------------------
  while getopts ":hV" opt
  do
    # shellcheck disable=SC2214
    case "${opt}" in

      h|help      ) _usage;    exit 0 ;;
      V|version   ) _version;  exit 0 ;;

      \?  ) printf '\nInvalid option: %s\n\n' "${OPTARG}"
            _usage;    exit 2 ;;

    esac    # --- end of case ---
  done
  shift $(( OPTIND-1 ))

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.