HiveBrain v1.2.0
Get Started
← Back to all entries
patternshellMinor

Simple import system for a large shell program

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
simplesystemprogramshelllargeforimport

Problem

I am writing a large shell program comprised of several source files. I was looking for a basic import system that accomplishes three goals.

  • Avoid sourcing entire files for access to just a few functions



  • Prevent files from being sourced multiple times.



  • Imported functions must be executed in the context of their script so that


internal dependancies do not have to be imported individually.

Please see the comments on the last function called import for the usage.

Any feedback on whether or not this is a relatively efficient implementation would be appreciated.

core.sh:

```
#!/bin/sh

# Core utilities
# Author: arctelix

# Make sure repo and library are available
if ! [ "$IMPORT_DIR" ]; then
read -p "Enter directory to import from: " IMPORT_DIR &2
fi
}

# a print function that does not interfere with function output
print () {
printf "%b%b%b\n" $debug_text "$1" $rc 1>&2
}

# Test for the existence of a command
cmd_exists() {
if ! [ "$1" ];then return 1;fi
command -v $1 >/dev/null 2>&1
}

# Test if script contains function
script_func_exists() {
script_exists "$1"
$1 command -v $2 >/dev/null 2>&1
}

# Test if script exists
script_exists() {
if [ -f "$1" ]; then
chmod u+x "$1"
cmd_exists "$1"
return $?
fi
return 1
}

# Creates a local function to call an external script's functions without
# polluting the local scope with all of the external function names.
# Also allows for sourcing external scripts without redundancy.

# external script (only script name available locally):
# import platforms
# PLATFORM="$(platforms get_platform)"

# external script function (only imported function name available locally):
# import platforms get_platform
# PLATFORM="$(get_platform)"

# source external script (makes all functions available locally):
# import source platforms
# PLATFORM="$(get_platform)"

import () {

usage="import [source] []"
usage_full="
source Source entire file
file File to impor

Solution

I don't have enough reputation to comment, but I am rather intrigued by your script, because I also enjoy writing large programs in the shell, and recently have been trying write modular shell scripts. Perhaps the reason nobody has tried to answer your question is because the script is rather intimidating and somewhat confusing.

At the risk of appearing ignorant, I will attempt to offer my insight from the outside perspective of someone that is trying to figure out how to use your script. I think your script suffers from a lack of ...

  • User friendliness -



It's not clear to me how exactly this script is supposed to be used. For instance, when I run it with no arguments, instead of getting a usage message, I get this error:

ghost@devbox:~/source:$ bash core.sh
bash core.sh
core.sh: 9: core.sh: dotsys: not found


Inspecting the code, I see that if the variable "$DOTSYS_REPOSITORY" is not set, than the next action taken is to export it. But since I don't have a program named dotsys that names an argument named "repository" in my $PATH, I end up with a cryptic error message. So, that makes me wonder, is this script also supposed to be sourced itself, from another script?

Funny side note: I created testit.sh, which sourced core.sh, exported "$DOTSYS_REPOSITORY", created the lib directory, placed your example scripts in the proper places, and tried running it with bash core.sh main.sh set_name. Something went wrong, and bash got stuck in a loop, forking itself faster than I could kill the process, until my system crashed due to RAM exhaustion. I'm not sure why that happened.

The reason I mention that is that I think your script could benefit from better documentation and error handling. Admittedly, I am not sure if I am running the script correctly, or whether some of these functions are supposed to run recursively, or what. However, conventional wisdom says...

  • Avoid using variable names that are also programs/shell builtins -



I also don't understand why you use function and variable names that are also common program names, like
import, or script`.

ghost@devbox:~/source/lib:$  which import script
/usr/bin/import
/usr/bin/script


Because those programs exist on my system, it's possible that the shell could become confused. But I am also confused... Perhaps you could more thoroughly explain the context of how this script is supposed to be used?

Code Snippets

ghost@devbox:~/source:$ bash core.sh
bash core.sh
core.sh: 9: core.sh: dotsys: not found
ghost@devbox:~/source/lib:$  which import script
/usr/bin/import
/usr/bin/script

Context

StackExchange Code Review Q#133143, answer score: 3

Revisions (0)

No revisions yet.