Giter VIP home page Giter VIP logo

bashew's Introduction

bashew's People

Contributors

atistler avatar cinemapub avatar drmikecrowe avatar jetm avatar pforret avatar tangoman75 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

bashew's Issues

Proof of concept | Request for comments

Hi Peter !

Your project is pretty cool !

Thank you for the inspiration, I didn't know about shellcheck or bashunit so the last few weeks I rewrited most of my scripts. It feels great to have them compliant with latest standards and I learned a lot.

I intended to use bashew it in my symfony projects but I realised I needed a way to have several actions in the same script.

I needed a versatile script to install, deploy, run tests, lint code, and run commands. Also I need them to work seemlessly in production, in the development environment, on bare metal, inside containers or in the ci pipeline...

Also I wanted to reduce complexity to the maximum.

I gave it a lot of thought, and I eventually ended up with this proof of concept

I would love to hear your thoughts about it, maybe you would like to use this idea in the next version of bashew.

Str:lower and others don't work out of the box on MacOS

Describe the bug

Some of the Str functions don't work out of the box on MacOS, because of the older bash version that is installed by default.
The bash substitutions used only work from bash 4 and up.

To Reproduce

  1. Clone bashew on a mac
  2. Create a script with bashew
  3. Attempt to run the command with an action (like env or check)4.

Output:

./bin/script: line 284: ${input,,}: bad substitution

Expected behavior

The command should just run

Desktop (please complete the following information):

  • OS: MacOS 12.5.1
  • bash version: 3.2
  • Script version: 1.18.3
  • copy/paste output of script.sh -v
# 🌼 Script path: ./bin/script
# 🌼 Linked path: ./bin/script
# 🌼 In folder  : /Users/[redacted]/Code/[redacted]/bin
# 🌼 Shell type : bash - version 3.2.57(1)-release
# 🌼 System OS  : macOS (Darwin) 12.5.1 on arm64
# 🌼 Package mgt: brew install
# 🌼 Version  : 0.0.1
# 🌼 Created  : 2022-09-01
# 🌼 Modified : Sep  1 23:35:53 2022
# 🌼 Lines    : 1027 lines / md5: 5f99194d
# 🌼 User     : [redacted]
# 🌼 git remote : [email protected]:[redacted]
# 🌼 git folder : /Users/[redacted]/Code/[redacted]
# 🌱 Read  dotenv: [./.env]
# 🧽 Clean dotenv: [./.env.__.sh]
./.env.__.sh: line 39: YGcLOX15/Tu5Rrf7vcbZwnxvJPZLh8uvVUrQwg5sbG0bIoNtJDyEWVM=: No such file or directory
# 🌱 flag: verbose=1
# 🌱 Expect : 1 choice(s): action
β›” script: need the choice(s) [action]
./bin/crdbrd: line 361: temp_files[@]: unbound variable
β›” script: ERROR 1 after 0 seconds
> last command : 'Script:exit'
${error_prefix} from line 1020 :   Option:parse "$@"       # overwrite with specified options if any
./bin/script: line 361: temp_files[@]: unbound variable

Additional context

Note that the issue mentioned in #14 is present here as well

Suggestions

  • Make sure that a minimal version of bash is present, if that is what is being relied on.
  • Really solely on awk for the Str methods (or only in the context of bash < 4)
  • Document the required bash version

Do not call `check_last_version` if no `.git` directory found

Describe the bug
When running a script in a non-git folder, you see:

fatal: not a git repository (or any parent up to mount point /)
Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).

To Reproduce
Steps to reproduce the behavior:

  1. Run bashew script in your root folder
  2. Execute the new script with -h

Expected behavior
No git error should occur

Desktop (please complete the following information):

  • Shell type : bash - version 5.0.17(1)-release
  • OS Version : Distributor ID: Ubuntu (Linux) Release: 20.10 on x86_64
  • Program: bashew 1.15.0
  • Updated: 2021-02-28 05:39

bashew cannot handle path to script

Sorry Peter, another one :)

 $  bashew -v script 
# πŸ“œ Script path: /home/mcrowe/.basher/cellar/bin/bashew - folder /home/mcrowe/.basher/cellar/bin 
# πŸ”— Linked to: /home/mcrowe/.basher/cellar/packages/pforret/bashew/bashew - folder /home/mcrowe/.basher/cellar/packages/pforret/bashew 
# πŸ”— Linked to: /home/mcrowe/.basher/cellar/packages/pforret/bashew/bashew.sh - folder /home/mcrowe/.basher/cellar/packages/pforret/bashew 
# Executing : [/home/mcrowe/.basher/cellar/packages/pforret/bashew/bashew.sh] 
# In folder : [/home/mcrowe/.basher/cellar/packages/pforret/bashew] 
# Detected shell: bash - version 5.0.17(1)-release 
# System    : Distributor ID:   Ubuntu (Linux) Release: 20.10 on x86_64 
# Installer : apt install 
# Expect : 1 single parameter(s): action 
# Found  : action=script 
# No multi param to process 
# all parameters have been processed 
# Cleanup: [.tmp] - delete files older than 1 day(s) 
# Tmpfile: .tmp/2020-12-29.qo0ejz 
# Cleanup: [log] - delete files older than 7 day(s) 
# Logfile: log/bashew.2020-12-29.log 
# Program: bashew 1.10.2 
# Updated: 2020-12-28 07:59 
# Run as : mcrowe@mcrowe-Inspiron-7537 
# Running: on Linux (#33-Ubuntu SMP Mon Nov 23 18:44:54 UTC 2020) 
# Verify : git tput uname  
# Using [scotia_screws.sh] as name 
…  1. first we need the information of the author
Author full name         (Mike Crowe): 
Author email             ([email protected]): 
Author (github) username (.): drmikecrowe
…  2. now we need the path and name of this new script/repo
Script name (./scotia_screws.sh): /home/mcrowe/bin/media
…  3. give some description of what the script should do
Script description (This is my script media): Start/Stop media processes
…  Creating script /home/mcrowe/bin/media ...
sed: -e expression #1, char 29: unknown option to `s'
/home/mcrowe/bin/media
# bashew finished after 43 seconds 

For reference:

 $  sed --version --help
sed (GNU sed) 4.7

 $  sed --help
Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]...

  -n, --quiet, --silent
                 suppress automatic printing of pattern space
      --debug
                 annotate program execution
  -e script, --expression=script
                 add the script to the commands to be executed
  -f script-file, --file=script-file
                 add the contents of script-file to the commands to be executed
  --follow-symlinks
                 follow symlinks when processing in place
  -i[SUFFIX], --in-place[=SUFFIX]
                 edit files in place (makes backup if SUFFIX supplied)
  -l N, --line-length=N
                 specify the desired line-wrap length for the `l' command
  --posix
                 disable all GNU extensions.
  -E, -r, --regexp-extended
                 use extended regular expressions in the script
                 (for portability use POSIX -E).
  -s, --separate
                 consider files as separate rather than as a single,
                 continuous long stream.
      --sandbox
                 operate in sandbox mode (disable e/r/w commands).
  -u, --unbuffered
                 load minimal amounts of data from the input files and flush
                 the output buffers more often
  -z, --null-data
                 separate lines by NUL characters
      --help     display this help and exit
      --version  output version information and exit

If no -e, --expression, -f, or --file option is given, then the first
non-option argument is taken as the sed script to interpret.  All
remaining arguments are names of input files; if no input files are
specified, then the standard input is read.

GNU sed home page: <https://www.gnu.org/software/sed/>.
General help using GNU software: <https://www.gnu.org/gethelp/>.
E-mail bug reports to: <[email protected]>.

Self update

An option [script] update that would update to latest GitHub version (git pull)

Also maybe an indication of whether this is necessary in [script] -h

Basher can do this too, but would be nice to have this always.

unbound variable

[ 17:06:05 ] jurikor@linvirt0:~/src/github/bashew$ ./bashew.sh script
⏳  1. first we need the information of the author
Author full name         (Yury Korneev) >
Author email             ([email protected]) >
Author (github) username (pforret) >
⏳  2. now we need the path and name of this new script/repo
Script name (./driblet_several.sh) >
⏳  3. give some description of what the script should do
Script description (This is my script driblet_several) >
⏳  Creating script ./driblet_several.sh ...
./driblet_several.sh
[ 17:06:20 ] jurikor@linvirt0:~/src/github/bashew$ ./driblet_several.sh -v
./driblet_several.sh: line 199: txtInfo: unbound variable
./driblet_several.sh: line 1: script_install_path: unbound variable
./driblet_several.sh: line 204: txtError: unbound variable

temporary solution: in function IO:initialize()
move line
IO:debug "script $script_basename started at $script_started_at"
to the end of the function, because ${txtInfo} is still undefined

feature request: optional list options

Hi @pforret,
bashew is a really great template and it saves me a lot of time!

I was wondering if you could add support for optional list options.
As an example I can present the -f option of the docker-compose CLI command.
It is optional but you can pass it multiple times to source different docker-compose-files:

docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...] 
docker-compose up # works!
docker-compose -f docker-compose.yml -f docker-compose.admin.yml up # works too!

I can achieve something similar using bashew when I pass the options as a single string:

bashew-compose -f "docker-compose.yml docker-compose.admin.yml" up

However, doing it this way I lose the benefit of filename completion by my shell.

Do you think this would be a useful feature?
Is there an easy way to add this to bashew?

Handle git >= v2.35.2 with wrapper function after CVE-2022-24765

Describe the bug
When the generated script is run with sudo, git complains about an unsafe repository.

To Reproduce
Steps to reproduce the behavior:

  1. Call generated script with parameters sudo <script> -v -h
  2. Wait for <1 seconds
  3. See error:
fatal: unsafe repository ('<repository folder>' is owned by someone else)
To add an exception for this directory, call:

git config --global --add safe.directory <repository folder>

Expected behavior
Run git as user without error.

Screenshots
/

Desktop (please complete the following information):

  • OS: Ubuntu 20.04
  • bash version 5.0.17
  • Script version: bashew 1.18.6
  • copy/paste output of script.sh -v: not needed, see solution below

Additional context
Add any other context about the problem here.

Possible solution: wrap git

function Tool:git_safe() {
  # handle running git v2.35.2 with "run_as_root=1" after CVE-2022-24765
  # but without "git config --global --add safe.directory ..."
  # https://github.blog/2022-04-12-git-security-vulnerability-announced/
  IO:debug "Tool:git_safe() called"
  if [[ $run_as_root == 1 ]] ; then
    IO:debug " -> run_as_root=1: sudo -u $SUDO_USER -- git $*"
    sudo -u "$SUDO_USER" -- git "$@"
  elif [[ $run_as_root == -1 ]] ; then
    IO:debug " -> run_as_root=-1: git $*"
    git "$@"
  else
    if [[ "$(whoami)" == "root" ]] ; then
      IO:debug " -> run_as_root=0: sudo -u $SUDO_USER -- git $*"
      sudo -u "$SUDO_USER" -- git "$@"
    else
      IO:debug " -> run_as_root=0: git $*"
      git "$@"
    fi
  fi
}

Then replace git calls in all functions with Tool:git_safe.

Add `bashew diag` to print details for bug report

Is your feature request related to a problem? Please describe.
bashew -v -h prints an interesting header. If you tweaked it a bit, it could print what you want for bug reports

Describe the solution you'd like
No preference, offering as suggestion for your consideration

automatic bash_completion script generation

It would be better if we have bash_completion generation based on the inputs and parameters for the script.

action and options will be autocomplete if we have bash_completion feature.

BUG: Installation from basher cannot find installation directory

Error:

 $  bashew.sh script 
…  1. first we need the information of the author
Author full name         (mcrowe): Mike Crowe
Author email             (mcrowe@mcrowe-Inspiron-7537): 
Author (github) username (mcrowe): drmikecrowe
…  2. now we need the path and name of this new script/repo
Script name (./brando_decided.sh): test.sh
…  3. give some description of what the script should do
Script description (This is my script test): 
…  Creating script test.sh ...
/home/mcrowe/.basher/cellar/bin/bashew.sh: line 85: /home/mcrowe/.basher/cellar/bin/template/normal.sh: No such file or directory
test.sh

[Question] Why have you prefixed the name of some functions ?

Hello,
I have a foolish question.. :)
Why some functions are prefixed (with IO: or Str:, ..) ?
Can you share your experience for this feature ?

For example if we want to print to output with print(), some users (not fluent in bash :)) can think : "I want to print a string for the output console so I will make Str:print() on my code". But the correct syntax is IO:print() ?
The prefix can sometimes be confusing.

Thanks for your feedback !
Maxime

.env issue

.env issue

Hello again! :-)

Faced with the following problem:

prepare

create empty script

./bashew -f -n sample.sh script

add params

option|a|var_a|option sample|def_a
list|b|var_b|list sample

modify "env" action

Script:check
echo "# var_a is: ${var_a:-}"
echo "# var_b length is:" "${#var_b[@]}"
for item in "${var_b[@]}"; do
  echo "# var_b[i] is: ${item}"
done
;;

sample 1

$ ./sample.sh -a 'aaa$bbb' env >.env
$ cat ./.env
## boolean flags:
force=0
help=0
quiet=0
verbose=0
 
## option defaults:
log_dir=/home/jurikor/log/sample
tmp_dir=/tmp/sample
var_a=aaa$bbb
 
## list options:
var_b=()
 
 
## required commands:
# apt install awk
# var_a is: aaa$bbb
# var_b length is: 0
$ ./sample.sh check
force="0"
help="0"
quiet="0"
verbose="0"
log_dir="/home/jurikor/log/sample"
tmp_dir="/tmp/sample"
var_a="aaa$bbb"
var_b="()"
/home/jurikor/src/github/bashew/.env.__.sh: line 7: bbb: unbound variable
β›” sample.sh: ERROR 1 after 1 seconds 
> last command : 'source "$clean_file"' 
${error_prefix} from line 1 : #!/usr/bin/env bash

sample 2

$ ./sample.sh -b 'aaa' -b 'bbb' -b 'ccc' env>.env
$ cat ./.env
## boolean flags:
force=0
help=0
quiet=0
verbose=0
 
## option defaults:
log_dir=/home/jurikor/log/sample
tmp_dir=/tmp/sample
var_a=def_a
 
## list options:
var_b=(aaa bbb ccc)
 
 
## required commands:
# apt install awk
# var_a is: def_a
# var_b length is: 3
# var_b[i] is: aaa
# var_b[i] is: bbb
# var_b[i] is: ccc
$ ./sample.sh check
force="0"
help="0"
quiet="0"
verbose="0"
log_dir="/home/jurikor/log/sample"
tmp_dir="/tmp/sample"
var_a="def_a"
var_b="(aaa bbb ccc)"
## boolean flags:
force=0  help=0  quiet=0  verbose=0   
## option defaults:
log_dir=/home/jurikor/log/sample  tmp_dir=/tmp/sample  var_a=def_a   
## list options:
var_b=((aaa bbb ccc))   
## choice:
action="check"   
 
## required commands:
# apt install awk
# var_a is: def_a
# var_b length is: 1
# var_b[i] is: (aaa bbb ccc)

sample 3

./sample.sh -b 'aaa' -b 'bbb "ccc" ddd' env >.env
$ cat ./.env
## boolean flags:
force=0
help=0
quiet=0
verbose=0
 
## option defaults:
log_dir=/home/jurikor/log/sample
tmp_dir=/tmp/sample
var_a=def_a
 
## list options:
var_b=(aaa bbb "ccc" ddd)
 
 
## required commands:
# apt install awk
# var_a is: def_a
# var_b length is: 2
# var_b[i] is: aaa
# var_b[i] is: bbb "ccc" ddd
$ ./sample.sh check
force="0"
help="0"
quiet="0"
verbose="0"
log_dir="/home/jurikor/log/sample"
tmp_dir="/tmp/sample"
var_a="def_a"
var_b="(aaa bbb "ccc" ddd)"
## boolean flags:
force=0  help=0  quiet=0  verbose=0   
## option defaults:
log_dir=/home/jurikor/log/sample  tmp_dir=/tmp/sample  var_a=def_a   
## list options:
var_b=((aaa bbb ccc ddd))   
## choice:
action="check"   
 
## required commands:
# apt install awk
# var_a is: def_a
# var_b length is: 1
# var_b[i] is: (aaa bbb ccc ddd)

and so on...

my workaround

diff --git a/sample.sh b/sample.sh
index 81a8145..5f2a492 100755
--- a/sample.sh
+++ b/sample.sh
@@ -52,6 +52,8 @@ flag|f|force|do not ask for confirmation (always yes)
 option|l|log_dir|folder for log files |$HOME/log/$script_prefix
 option|t|tmp_dir|folder for temp files|/tmp/$script_prefix
 choice|1|action|action to perform|action1,action2,check,env,update
+option|a|var_a|option sample|def_a
+list|b|var_b|list sample
 #param|?|input|input file/text
 " -v -e '^#' -e '^\s*$'
 }
@@ -85,6 +87,12 @@ function Script:main() {
       #TIP: use Β«$script_prefix envΒ» to generate an example .env file
       #TIP:> $script_prefix env > .env
       Script:check
+      echo "#####"
+      echo "# var_a is: ${var_a:-}"
+      echo "# var_b length is:" "${#var_b[@]}"
+      for item in "${var_b[@]}"; do
+        echo "# var_b[i] is: ${item}"
+      done
       ;;
 
     update)
@@ -499,9 +507,9 @@ Script:check() {
     Option:filter flag |
       while read -r name; do
         if ((piped)); then
-          eval "echo \"$name=\$${name:-}\""
+          declare -p "$name"
         else
-          eval "echo -n \"$name=\$${name:-}  \""
+          declare -p "$name"
         fi
       done
     IO:print " "
@@ -512,9 +520,9 @@ Script:check() {
     Option:filter option |
       while read -r name; do
         if ((piped)); then
-          eval "echo \"$name=\$${name:-}\""
+          declare -p "$name"
         else
-          eval "echo -n \"$name=\$${name:-}  \""
+          declare -p "$name"
         fi
       done
     IO:print " "
@@ -525,9 +533,9 @@ Script:check() {
     Option:filter list |
       while read -r name; do
         if ((piped)); then
-          eval "echo \"$name=(\${${name}[@]})\""
+          declare -p "$name"
         else
-          eval "echo -n \"$name=(\${${name}[@]})  \""
+          declare -p "$name"
         fi
       done
     IO:print " "
@@ -541,7 +549,7 @@ Script:check() {
       Option:filter param |
         while read -r name; do
           # shellcheck disable=SC2015
-          ((piped)) && eval "echo \"$name=\\\"\${$name:-}\\\"\"" || eval "echo -n \"$name=\\\"\${$name:-}\\\"  \""
+          declare -p "$name"
         done
       echo " "
     fi
@@ -556,7 +564,7 @@ Script:check() {
       Option:filter choice |
         while read -r name; do
           # shellcheck disable=SC2015
-          ((piped)) && eval "echo \"$name=\\\"\${$name:-}\\\"\"" || eval "echo -n \"$name=\\\"\${$name:-}\\\"  \""
+          declare -p "$name"
         done
       echo " "
     fi
@@ -1084,7 +1092,30 @@ Script:meta   # find installation folder
 [[ $run_as_root == -1 ]] && [[ $UID -eq 0 ]] && IO:die "user is $USER, CANNOT be root to run [$script_basename]"
 
 Option:initialize # set default values for flags & options
-Os:import_env     # overwrite with .env if any
+# Os:import_env     # overwrite with .env if any
+  if [[ $(pwd) == "$script_install_folder" ]]; then
+    env_files=(
+      "$script_install_folder/.env"
+      "$script_install_folder/.$script_prefix.env"
+      "$script_install_folder/$script_prefix.env"
+    )
+  else
+    env_files=(
+      "$script_install_folder/.env"
+      "$script_install_folder/.$script_prefix.env"
+      "$script_install_folder/$script_prefix.env"
+      "./.env"
+      "./.$script_prefix.env"
+      "./$script_prefix.env"
+    )
+  fi
+
+  for env_file in "${env_files[@]}"; do
+    if [[ -f "$env_file" ]]; then
+      IO:debug "$config_icon Read  dotenv: [$env_file]"
+      source "$env_file"
+    fi
+  done
 
 if [[ $sourced -eq 0 ]]; then
   Option:parse "$@" # overwrite with specified options if any

result

$ ./sample.sh -a '111$qqq' -b 'aaa' -b 'bbb $ccc ddd' env >.env
$ ./sample.sh check
## boolean flags:
declare -- force="0"
declare -- help="0"
declare -- quiet="0"
declare -- verbose="0"
 
## option defaults:
declare -- log_dir="/home/jurikor/log/sample"
declare -- tmp_dir="/tmp/sample"
declare -- var_a="111\$qqq"
 
## list options:
declare -a var_b=([0]="aaa" [1]="bbb \$ccc ddd")
 
## choice:
declare -- action="check"
 
 
## required commands:
# apt install awk
#####
# var_a is: 111$qqq
# var_b length is: 2
# var_b[i] is: aaa
# var_b[i] is: bbb $ccc ddd

[Question] For what purpose in the function "Os:follow_link()" lines:

Hello.
It's just a question

For what purpose in the function "Os:follow_link()" lines:

857  [[ "$file_folder" != /* ]] && link_folder="$(cd -P "$file_folder" &> /dev/null && pwd)"
858  local symlink
859  symlink=$(readlink "$1")
860  link_folder=$(dirname "$symlink")

it looks pointless in the part concerning link_folder

Thanks for your feedback
Yury

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.