Giter Club home page Giter Club logo

basher's Introduction

basher

A package manager for shell scripts and functions.

Basher allows you to quickly install shell packages directly from github (or other sites). Instead of looking for specific install instructions for each package and messing with your path, basher will create a central location for all packages and manage their binaries for you.

Even though it is called basher, it also works with zsh and fish.

Build Status

Installation

You can install Basher in 1 line. This will install Basher, and add it to your .bashrc/.zshrc file - in a way that can automatically be uninstalled later:

curl -s https://raw.githubusercontent.com/basherpm/basher/master/install.sh | bash

Install on Mac OSX

Basher requires bash >= 4, and the realpath utility from coreutils. On osx you can install both with brew:

$ brew install bash coreutils

Manual method to Install

  1. Checkout basher on ~/.basher

    $ git clone --depth=1 https://github.com/basherpm/basher.git ~/.basher
  2. Initialize basher in your shell initialization

    export PATH="$HOME/.basher/bin:$PATH"
    eval "$(basher init - bash)" # replace `bash` with `zsh` if you use zsh

    Fish: Use the following commands instead:

    if test -d ~/.basher
      set basher ~/.basher/bin
    end
    set -gx PATH $basher $PATH
    status --is-interactive; and . (basher init - fish|psub)

Updating

Go to the directory where you cloned basher and pull the latest changes:

$ cd ~/.basher
$ git pull

Usage

Installing packages from Github

$ basher install sstephenson/bats

This will install bats from https://github.com/sstephenson/bats and add bin/bats to the PATH.

Installing packages from other sites

$ basher install bitbucket.org/user/repo_name

This will install repo_name from https://bitbucket.org/user/repo_name

Using ssh instead of https

If you want to do local development on installed packages and you have ssh access to the site, use --ssh to override the protocol:

$ basher install --ssh juanibiapina/gg

Installing a local package

If you develop a package locally and want to try it through basher, use the link command:

$ basher link directory my_namespace/my_package

The link command will install the dependencies of the local package. You can prevent that with the --no-deps option:

$ basher link --no-deps directory my_namespace/my_package

Sourcing files from a package into current shell

Basher provides an include function that allows sourcing files into the current shell. After installing a package, you can run:

include username/repo lib/file.sh

This will source a file lib/file.sh under the package username/repo.

Command summary

  • basher commands - List commands
  • basher help <command> - Display help for a command
  • basher uninstall <package> - Uninstall a package
  • basher list - List installed packages
  • basher outdated - List packages which are not in the latest version
  • basher upgrade <package> - Upgrade a package to the latest version

Configuration options

To change the behavior of basher, you can set the following variables either globally or before each command:

  • If $XDG_DATA_HOME/basher is a directory, then $BASHER_ROOT will be set to $XDG_DATA_HOME/basher instead of the usual $HOME/.basher. If $XDG_DATA_HOME is not set or is empty, then it defaults to ~/.local/share.
  • BASHER_FULL_CLONE=true - Clones the full repo history instead of only the last commit (useful for package development)
  • BASHER_PREFIX - set the installation and package checkout prefix (default is $BASHER_ROOT/cellar). Setting this to /usr/local, for example, will install binaries to /usr/local/bin, manpages to /usr/local/man, completions to /usr/local/completions, and clone packages to /usr/local/packages. This allows you to manage "global packages", distinct from individual user packages.

Packages

Packages are simply repos (username/repo). You may also specify a site (site/username/repo).

Any files inside a bin directory are added to the path. If there is no bin directory, any executable files in the package root are added to the path.

Any manpages (files ended in \.[0-9]) inside a man directory are added to the manpath.

Optionally, a repo might contain a package.sh file which specifies binaries, dependencies and completions in the following format:

BINS=folder/file1:folder/file2.sh
DEPS=user1/repo1:user2/repo2
BASH_COMPLETIONS=completions/package
ZSH_COMPLETIONS=completions/_package

BINS specified in this fashion have higher precedence then the inference rules above.

Package Directory

A list of working packages can be found on https://www.basher.it/. There you can also find a badge if you want to include it in your readme:

basher install

basher's People

Contributors

beevelop avatar bltavares avatar cornfeedhobo avatar hugot avatar hyperupcall avatar isaacs avatar juanibiapina avatar jvortmann avatar nhomble avatar pawamoy avatar pforret avatar pjeby avatar soraxas avatar tyll avatar weakish avatar welding-torch avatar yarektyshchenko 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

basher's Issues

Test for completions and source them

Many projects that follow the bin/ and lib/ conventions are starting include a completions/ directory. Basher should test for those files and source them.

readlink has no -e option on busybox/alpine, realpath has no options at all

The resolve_link functions do not work on Alpine / Busybox (Alpine uses Busybox), because
Busybox's realpath has no option at all and its readlink just has the following (not -e):

BusyBox v1.28.4 (2018-07-17 15:21:40 UTC) multi-call binary.

Usage: readlink [-fnv] FILE

Display the value of a symlink

	-f	Canonicalize by following all symlinks
	-n	Don't add newline
	-v	Verbose

So I guess we'll have complexify the function a bit. Also I noticed you did not update the resolve_link function in basher, it still uses greadlink.

Here is a first draft:

resolve_link() {
  if type -p realpath >/dev/null; then
    realpath "$1"
  elif type -p readlink >/dev/null; then
    readlink -f "$1"
    # -e is actually not mandatory for our use-case, but -f is, to resolve . and ..
  # else ??
  fi
}

basher run

I have some scripts that depend on basher being initialized, and I would like to run them in non-terminal places like GUI or Conky.

To do that I had written my own wrapper, but I now think it could be included in basher as a run command.

The run command would be written like:

# get basher install dir
basher_path="$(dirname "$(dirname "$(readlink -e "$0")")")"

# set path
export PATH="${basher_path}/bin:${PATH}"

# init basher
eval "$(basher init - bash)"

# execute given command
"$@"

(Note this is written for bash only, I did not consider other shells)

You would typicall call it like

~/.basher/bin/basher run my_script my_args

An example for Conky:

${execpi 5 ~/.basher/bin/basher run my_script my_args}

Add some relevant GitHub topics

Hello! It would be awesome to add some relevant GitHub topics to this repository. Is it possible? ๐Ÿš€

If you need inspiration, I develop similar software, so you can take a look. Or there are others like bpkg, from which you can get inspiration as well. ๐Ÿ˜ƒ

basher link, improve error message on bad format

I am running the basher link <dir> <package> command

I incorrectly defined the package argument since I didn't have the namespace argument. The error message just led me to the default usage function

Usage: basher link [--no-deps] <directory> <package>

Installs a local directory as a basher package

It wasn't until I added my own debug statements to the basher-link file that I figured out with -z check was failing.

I think it would be helpful if the error messages told me which variable is incorrectly empty.

Allow sources other than github

I use bitbucket in addition to github and it would be nice to be able to specify that as a source for a particular dependency in DEPS.

Perhaps an optional prepend of source to the DEP, which defaults to github if not specified, a la "bitbucket/my-user/my-package" or somesuch.

Shifting options from $@

I think the code that checks for --ssh or --no-deps options is wrong.

What I mean is that it works only when the option is the first argument given. If it is second or third, then the wrong argument will be shifted (the first one, not the option).

So instead we should either:

  • just check if the first argument is equal to option we look for (no need for a for loop)
  • allow the option to be placed elsewhere in the command line with something like:
args=()
while [ $# -ne 0 ]; do
  case $1 in
    --option) option=true ;;
    *) args+=("$1") ;;
  esac
  shift
done
set -- "${args[@]}"

check manpages after upgrade

To pull in some new manpages, I had to uninstall and install a basher package. I was expecting basher upgrade <package> to be check for a new man/ dir after upgrade.

More generally, I see in the install script, there is a lot of linkage done after cloning the repository. Assuming the linking is idempotent, should we do this similar linkage at the end of the upgrade step?

"detect shell" test failing on alpine

Issue again, sorry ๐Ÿ˜ !!

There is just a test failing on Alpine/Busybox, the "detect shell" one, because the ps command returns nothing (surely different/missing options as well).

I'm talking about Alpine because the official bash docker images are based on it :O https://github.com/tianon/docker-bash

I can try and fix it if you're okay!

Avoiding the linking of all executables in the root of a repository

I ran basher install tests-always-included/mo and then checked out ~/.basher/cellar/bin/ to see what files were linked. I saw several:

lrwxrwxrwx 1 fidian fidian 72 Sep  1 13:53 diagnostic -> /home/fidian/.basher/cellar/packages/tests-always-included/mo/diagnostic*
lrwxrwxrwx 1 fidian fidian 63 Sep  1 13:53 lasher -> /home/fidian/.basher/cellar/packages/basherpm/lasher/bin/lasher*
lrwxrwxrwx 1 fidian fidian 64 Sep  1 13:53 mo -> /home/fidian/.basher/cellar/packages/tests-always-included/mo/mo*
lrwxrwxrwx 1 fidian fidian 73 Sep  1 13:53 run-spec.js -> /home/fidian/.basher/cellar/packages/tests-always-included/mo/run-spec.js*
lrwxrwxrwx 1 fidian fidian 71 Sep  1 13:53 run-tests -> /home/fidian/.basher/cellar/packages/tests-always-included/mo/run-tests*

There are several executable programs in tests-always-included/mo and I would like only mo to be linked. Would you consider adding something to package.sh that would list the programs that should be linked?

Support arbitrary https or ssh uris

We're using gitlab internally, which a) operates on port 10022 and b) supports nested namespaces. I can imagine a shortcut, so that when somebody types basher install [email protected]:10044/group/subgroup/project basher takes the uri as-is.

Allow ssh protocol

As mentioned on #21 , allow users to specify ssh protocol when installing. This gives you easy push access if you're developing packages.

A possible syntax would be:

$ basher install --protocol=ssh user/repo

or

$ basher install --ssh user/repo

Protocol would default to https. It should also not affect dependencies, which should always be https.

@binaryphile thoughts?

Windows support

After executing this command (using MINGW64 terminal, which comes with git):

export PATH="$HOME/.basher/bin:$PATH"
eval "$(basher init - bash)"

I get this error:

/c/Users/Jerry/.basher/bin/basher: line 1: ../libexec/basher: No such file or directory

Or if I try to use it:

$ basher install jerrygreen/git-pr
/c/Users/Jerry/.basher/bin/basher: line 1: ../libexec/basher: No such file or directory

It would be cool if it worked on Windows too, so my bash commands would be trasportable, whatever system I use.

Request for cooperation: bash-modules

I'm author of bash-modules project: https://github.com/vlisivka/bash-modules . I'm preparing to release version 4.0 of bash-modules.

I want to know, is it possible to install bash-modules, or third-party modules for bash-modules, using basher. What I can do to add support for this to my project.

Also, I hope that someone will review my bash code and provide feeback.

install doesn't work?

Tried installing https://github.com/bashup/gitea-cli, but the only files are in ~/.basher/cellar/bin, not ~/.basher/bin, as described in the basher install files for what to set your path to.

Is it correct to have ~/.basher/cellar/bin in the path variable as well, or should it be linking packages to ~/.basher/bin?

Confused.

Package Manager

Dear Dev,

I recently encountered your project. It says that it's a package Manager for bash, but is it possible to convert this to a regular package management system for Linux, if we want to, for let's say a distro?

Best regards,
RennyDemmy

Upgrading a package does not add/remove links

The upgrade command issues a pull, but before that it should unlink everything, then relink after pulling. Otherwise, new commands, completions and man pages aren't installed, and old ones aren't removed.

link-bins mistakenly finds package itself as bin under certain conditions

...which were too long for the title and are the following:

  • when package was linked with basher link
  • when no BINS are specified in package.sh
  • when no bin directory exists

When all these conditions meet, then basher tries to find all files in the root of the packages that have exec perm and are either a regular file or a symlink. It thus catches the directory name itself, creates a dangling symlink in cellar/bin, and attempt to chmod +x this symlink (and this is were it finally fails).

The culprit:

bins=($(find "$BASHER_PACKAGES_PATH/$package" -maxdepth 1 -perm -u+x -type f -or -type l))

Thankfully, it is easily solved with the -mindepth levels option of find:

Do not apply any tests or actions at levels less than levels (a non-negative integer). -mindepth 1 means process all files except the starting-points.

- bins=($(find "$BASHER_PACKAGES_PATH/$package" -maxdepth 1 -perm -u+x -type f -or -type l))
+ bins=($(find "$BASHER_PACKAGES_PATH/$package" -maxdepth 1 -mindepth 1 -perm -u+x -type f -or -type l))

Thoughts about same namespace but different provider?

What about the following situation?

basher install github.com/namespace/project
basher install gitlab.com/namespace/project

The whole point of using namespace to uniquely identify packages is defeated by the possibility to use different sources (github.com, gitlab.com, bitbucket.com, etc.).

Can something be done regarding this ๐Ÿ˜•?

[feature] dependencies on other programs

Hello! I'm wondering if there's been any thoughts around declaring and verifying shell dependencies during installation.

An example I had today: I did a basher install but then I noticed jq was missing.

Maybe there could be a known file in the basher directory structure such that basher could check against $PATH.

Eventually, we could hook into other managers for complicated installs. Maybe declare other basher dependencies but maybe brew as well?

Call for help, maybe maintainers

I'm not using basher extensively anymore, which means in practice I can't find the energy to improve it and tackle issues.

I'm considering retiring it, or giving it to someone else.

Any thoughts?

Add step for ./configure && make?

Would you be inclined to accept a pr to add libexec/basher-_build that would do ./configure if a configure script is available, and make if a Makefile is present?

It would make a lot of programs installable with basher pretty easily, and could be overridden by something in package.sh if the user wanted to specify a custom build script.

Set BASHER_PACKAGES_PATH with eval $(basher init -)

Hi @juanibiapina ๐Ÿ˜ธ!

Sometimes in my scripts I need to get the path to some file in a basher-installed package.

I myself export the BASHER_PACKAGES_PATH variable, so I can reliably use ${BASHER_PACKAGES_PATH}/namespace/package/file in my own scripts.

But I noticed that eval "$(basher init -)" does not export this variable for users that do not set it themselves. It should not be a problem in most cases, because we still have access to the basher package-path command.

Now I also noticed that using basher package-path impacts performance. Obviously, running all the following machinery

basher
search for command basher, unless already cached
spawn basher process
set many variables, resolving paths, etc
set PATH to add basher's libexec
search for command basher-package-path
exec it
get result

...is much slower that just using the environment variable BASHER_PACKAGES_PATH, especially if the script is called in a loop!

So what I'm requesting here is simply to add this variable in basher-init, for it to be set when eval "$(basher init -)" is ran. This way I can reliably use it in scripts that are destined for others, not just for me.

I couldn't think of any problem that could arise if we indeed set BASHER_PACKAGES_PATH with basher-init, but maybe you can?

If you can, then it's not a problem either because there is still a simple workaround to get the performance of using the environment variable while still falling back to the command if it's not set. Example:

# (I do this in shellm/core package itself, so I know it exists)
if [ -d "${BASHER_PACKAGES_PATH}" ]; then
  PATH="${BASHER_PACKAGES_PATH}/shellm/core/libexec:${PATH}"
else
  PATH="$(basher package-path shellm/core/libexec):${PATH}"
fi

If this request gets implemented, I could simply drop the fallback:

PATH="${BASHER_PACKAGES_PATH}/shellm/core/libexec:${PATH}"

And there would be no performance impact, even for users who do not set BASHER_PACKAGES_PATH variable themselves (and I would not need to tell them to do so to improve performance).

The implementation should hold on two lines:

diff --git a/libexec/basher-init b/libexec/basher-init
index 6cdd4f0..22f57c9 100755
--- a/libexec/basher-init
+++ b/libexec/basher-init
@@ -16,6 +16,7 @@ print_fish_commands() {
   echo "set -gx BASHER_SHELL $shell"
   echo "set -gx BASHER_ROOT $BASHER_ROOT"
   echo "set -gx BASHER_PREFIX $BASHER_PREFIX"
+  echo "set -gx BASHER_PACKAGES_PATH $BASHER_PACKAGES_PATH"
 
   echo 'if not contains $BASHER_ROOT/cellar/bin $PATH'
   echo 'set -gx PATH $BASHER_ROOT/cellar/bin $PATH'
@@ -26,6 +27,7 @@ print_sh_commands(){
   echo "export BASHER_SHELL=$shell"
   echo "export BASHER_ROOT=$BASHER_ROOT"
   echo "export BASHER_PREFIX=$BASHER_PREFIX"
+  echo "export BASHER_PACKAGES_PATH=$BASHER_PACKAGES_PATH"
 
   echo 'export PATH="$BASHER_ROOT/cellar/bin:$PATH"'
 }

Create wrappers instead of symlinks

Many tools expect to be run from a specific location.

I've made PRs to fix this in downstream tools, but I think it's time to consider having basher write wrappers scripts that are little more than

cd $repo_path
exec ./bin/repo_name

This would work around scripts that don't handle linking when sourcing child scripts

Handle more cases for basher link

basher link expects the name of a directory in the current directory, which is very limited. It means I can't run basher link .. I have to go one directory up to use the command, and in some cases it might be possible that I don't even know the directory name. I cannot use an absolute path either (so no basher link $(pwd)).

ln -s "$(pwd)/$directory" "${BASHER_PACKAGES_PATH}/link/$directory"

It would be great if basher could handle these two cases: absolute and relative paths (including use of . and ..). It would need to resolve the given argument to an absolute path, then use it's basename when linking, something like

directory="$(readlink -e "$1")"

ln -s "$directory" "${BASHER_PACKAGES_PATH}/link/$(basename "$directory")"

My use case is CI: I end up with the working directory being the project directory. I would like to be able to run basher link . or basher link $(pwd) before actually running the tests.

basher list doesn't handle deeper directory structures

I've been hosting some scripts in a gitlab organization which doesn't follow the nice username/project structure we have in github. It's more like org/group/function/repo.

When I do basher list, I only get part of the path which means basher upgrade trivially succeeds cause it doesn't find the git project to pull.

My current workaround is to manually pull in the basher cellar.

Looking at the implementation, the assumption looks to be in the package_path loop in basher-list

for package_path in "${BASHER_PACKAGES_PATH}"/*/*
.
.
.

--
@juanibiapina maybe we can come up with a better list of git repos with find?

allow dependency versioning requirements

The DEPS specification allows me to pull particular packages from github. However, I would also like to be able to specify the particular version of the desired package, since master is usually a moving target and can break the contract with my code over time.

The simplest thing would be to specify a tag like "v1.0" which would check out that tag from the repository after it had been cloned.

This would also affect the upgrade command, since this package wouldn't be updated without changing the version specified in DEPS.

I'm not requesting that multiple versions of the dependency be able to coexist under basher, although that would be another nice-to-have (i.e. different feature request). I could definitely see specifying the version number in the repo's path in anticipation of such a feature, however, such as "cellar/packages/my-user/my-package-v0.1".

Feature request: config files

Now that we have BASHER_PREFIX and such, it'd be nice to be able to set it, especially systemwide. Perhaps we could have basher source /etc/basher.conf and ~/.basherrc if they exist, in that order. Then people like me could have a systemwide /etc/basher.conf that said something like:

if test `id -u` == "0"; then
    # customize these to sysadmin taste
    BASHER_PREFIX=/usr/local
    BASHER_PACKAGES_PATH=/usr/local/basher-packages
else
    # also customized to taste; can be overridden by user in ~/.basherrc
    BASHER_PREFIX="$HOME"
    BASHER_PACKAGES_PATH=~/.basher-packages
fi

This would let a globally-installed basher work for both end users and root; sudo basher install would install a package globally, and regular basher install would work locally. This would be a big step towards making basher usable as a system-level packaging tool, rather than just a personal one. (i.e., there's just one global install of basher as a program, even if individual users and the system have their own package directories.)

nest package in subfolder

We would like to keep multiple packages in a single repo (mono-repo). To achieve that we would need basher to be able to install from sub-folders of a repo, rather than assuming the whole repo is a single package.

Example:

basher install --path <path> <user>/<repo>

Error while running tests on OS X

I keep getting these failures during the basher test run on OS X. There isn't a lot of info about what the actual error is, what code is being run, etc.

 โœ“ extracts only usage
 โœ“ multiline usage section
 /var/folders/vv/yvb4m22n5f511tbzjjjwcm240000gn/T/bats.44779.src: line 66: syntax error near unexpected token `>'                                                                                                                    51/119
 โœ“ multiline extended help section

119 tests, 0 failures

make: *** [test] Error 1

Add a LIBS configuration variable

I usually have scripts inside bin/ and libraries inside libs/. It would be nice if Basher also installed the file specified in LIBS inside a lib directory in the cellar.

Non executable packages

How do we package & install non-exectuable shell scripts to be source ed by other scripts?

Dead code from previous basher link command

Here

create_link_package() {
local name="$1"
mkdir -p "${BASHER_PACKAGES_PATH}/link"
mkdir -p "${BASHER_ORIGIN_DIR}/$name"
ln -s "${BASHER_ORIGIN_DIR}/$name" "${BASHER_PACKAGES_PATH}/link/$name"
}

and here

@test "ignores link packages" {
mock_clone
create_package username/outdated
basher-install username/outdated
create_exec username/outdated "second"
create_link_package skip
run basher-outdated
assert_success
assert_output username/outdated
}

Package.yml

Hi. I have a proposal for you. What about package.yml for quick and easy installation of dependencies. Cuz I want a list of dependencies for my project that includes YAML parsing and I don't want to find the dependencies on Google. Can you make it?

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.