Re: [PATCH v2 5/8] builtins/source: parse the -i option
Date:Sat, 18 May 2024 23:00:41 + From:Matheus Afonso Martins Moreira Message-ID: | If you resolve the path, you're just reinventing the source builtin. Nonsense, the real work of the source ('.' really) utility is to read the file, parse it, and execute it. None of the proposed solutions here do that. What file names work for this purpose is an irrelevant consideration. | It also depends on source actually accepting the absolute path | which renders it incompatible with restricted shells. That's the only point here that has any merit. And a better solution to that would be to remove that restriction, which has no purpose that I can imagine. The commands run by the source builtin would be restricted, and whatever they are, could simply be typed as input to the same effect, so stopping a rbash user from accessing stuff in some common (full path named) file seems pointless to me. Just remove that restriction and this point goes away, and there's no reason left to modify bash in one particular way (rather than some other way that someone else would prefer). [Aside: the restriction on rbash using "exec" to replace the shell makes no sense either - obviously whatever is exec'd would need to be a command the user could run without exec, and assuming that condition is maintained, then a user can just do "cmd" and stay in that until they're done, which is effectively identical to "exec cmd" except the former keeps the rbash process hanging around for no useful purpose. I also find it hard to believe that anyone can usefully use any shell which doesn't allow stdout to be redirected - what files can be used, that can be restricted, but simply banning redirection? Weird. Then again, my general opinion of restricted shells is that they were a joke when first invented (long long ago when lots of users shared a computer, which is a very rare setup these days) and while the joke has become stale, that's still what they are.] | I don't really understand why there seems to be so much | opposition to this. It is extra stuff that once added needs to be maintained forever. Unless it proves useful, and unable to be done some other way, adding it is typically the wrong thing to do. | So why add the source builtin to begin with? That one is simple ... when it ('.' in sh, "source" in csh) was added there were no functions, while read & eval might have been enough for simple one line scripts, they wouldn't work for more complex ones, to invent your own '.' command that way you'd need to do it in a moderately complex function, which didn't exist at the time. And like anything else, once added, it is there forever. | > if I needed something like that, I could write my own, similar ones. | And you would run into the limitations described above. I wouldn't, as I don't care about restricted shells (never have, not even when I was running a system used by many hundreds of (*evil*) students).And that's the only real restriction, which should be removed anyway. I agree that modifying PATH isn't a great solution - though for any use I'd have of '.' that wouldn't bother me either (both because I've never used a '.' command that actually searches PATH, and because I don't put anything which would require a PATH search in files I use via '.' - such scripts are simply run as scripts. '.' is used when the current shell environment needs to be modified, so is useful for defining functions, and assigning values to variables (and perhaps the odd option setting) - almost never anything more than that (at least for me - so I wouldn't run into the limitations described.) kre
Re: [PATCH v2 5/8] builtins/source: parse the -i option
> distros, sysadmins, and users can already break your scripts > in plenty of ways -- changing existing shell variables, setting > shopts your scripts don't account for, etc. Existing footguns doesn't justify addition of new ones. We have the ability to prevent a lot of breakage here. Shouldn't we take that opportunity? > By this logic, ALL future shell variables ought to be gated similarly. Maybe. I haven't really thought that far but it would probably be a good thing. > it seems a bit heavy-handed Why? Most if not all of the other builtins have options. > Note that "source -i" precludes a sort of mirror situation. > Someone who sourced scripts via PATH but wanted to > switch to BASH_SOURCE_PATH would not be able to > simply move the relevant directories from one variable > to the other but would have to modify all sourcing scripts > -- including third-party ones -- to use "source -i". Yes, that's intentional. This ensures that users who wrote code expecting PATH semantics actually get those semantics. Then the new variable can be set in the environment without impacting those users and their scripts. > If they declined to do this, then they'd have to keep using > PATH for at least some scripts, possibly indefinitely. Those should continue to work without any changes. They should even be compatible with each other: there should be no problems with sourcing -i a script which then sources another script normally or uses one of the module management solutions. -- Matheus
Re: [PATCH v2 5/8] builtins/source: parse the -i option
> The issue is that what you want, and what I want, > and what konsolebox wants (and everyone else) > are all slighty different. The option solution which I proposed is not really in opposition to anything that anyone else wants. It will not break anything, it supports the same inputs and use cases as before, including the absolute path case you cited. On the other hand, the variable solution which everyone else seems to favor _does_ get in the way of what I want to do. > And as konsolebox's functions show, all this can be implemented, > reasonably easily, outside of the bash source code No. By discussing this I ended up discovering additional reasons why it should actually be in bash as a builtin feature. Pure bash solutions have two choices and both of them break stuff. Either they clobber PATH, or they resolve the file's path on their own and pass an absolute path to the source builtin. If you clobber PATH, sourced scripts can't easily find commands anymore. That completely changes the way that scripts work and therefore the way they must be written. If you resolve the path, you're just reinventing the source builtin. It also depends on source actually accepting the absolute path which renders it incompatible with restricted shells. The option solution completely avoids all that. It leaves PATH alone, and as a builtin it can integrate with restricted shells. I even made BASH_SOURCE_PATH be read only in that context, just like PATH. And it accomplishes all that in a compatible way that's fully opt in, anyone who does not want it can simply not use it. Existing code is not impacted because existing code simply does not pass -i as an option to the source builtin. I don't really understand why there seems to be so much opposition to this. Ability to do something in pure bash is not an argument against this feature, especially since it overcomes limitations present in the pure bash solutions. Those are _real_ limitations, not some "personal hangups" as others called it. The pure bash solutions simply _cannot_ both of these things, they must sacrifice one of them. Even if that wasn't the case, it wouldn't be an argument. By this logic, the source builtin itself should not have been added either. I mean it's just read and eval, and bash has both of those primitives built into it already. There's a comment which even explains source in these terms: it reads in the file into a string and just evaluates it. So why add the source builtin to begin with? > if I needed something like that, I could write my own, similar ones. And you would run into the limitations described above. > I think all this just shows that there's no real need to add any > code to bash at all for this I don't know about "need" but there are certainly advantages. > use full path names instead Incompatible with restricted shells. -- Matheus
Re: [PATCH v2 5/8] builtins/source: parse the -i option
On Sat, May 18, 2024, at 11:17 AM, Phi Debian wrote: > I am xing fingers the consensus, if any of theses takes off, > is to have [...] protection against alias source='source -i' This seems out of scope, regardless of what happens with "-i". > I really depend on actual 'source' behavior, and can't update my packages > (distributed since long). I don't plan to use BASH_SOURCE_PATH, so if one, > distro, sysadmin, and ultimatly the user fiddle with BASH_SOURCE_PATH in > the ENV (*rc files), changing the good'ol 'source' behavior, it would be a > serious regression to me. A reasonable concern, but distros, sysadmins, and users can already break your scripts in plenty of ways -- changing existing shell variables, setting shopts your scripts don't account for, etc. > So to me BASH_SOURCE_PATH enablement must be guarded by a never used yet > option to 'source or dot' (here -i apparently) and an enforcement that no > alias source='source -i' could ever be possible. By this logic, ALL future shell variables ought to be gated similarly. No doubt some would embrace this, but it seems a bit heavy-handed. > All this is because one writing a 'main' script (#!/bin/bash), sourcing a > package of mine through my package management system, expecting the current > source behavior, and later add the loading of a 'libraries' from a friend > (terminal color jazz) that in turn start to mess around with alias > source='source -i' and BASH_SOURCE_PATH cold start to break my way of > finding my packages. There's only so much you or bash itself can do to prevent users from breaking their own setups. Note that "source -i" precludes a sort of mirror situation. Someone who sourced scripts via PATH but wanted to switch to BASH_SOURCE_PATH would not be able to simply move the relevant directories from one variable to the other but would have to modify all sourcing scripts -- including third-party ones -- to use "source -i". If they declined to do this, then they'd have to keep using PATH for at least some scripts, possibly indefinitely. -- vq
Re: [PATCH v2 5/8] builtins/source: parse the -i option
Date:Sat, 18 May 2024 08:39:57 -0300 From:Matheus Afonso Martins Moreira Message-ID: | As the user, it should be my prerogative to set the | variable on my environment and/or rc so that I can | organize my sourceable scripts however I want Of course. The issue is that what you want, and what I want, and what konsolebox wants (and everyone else) are all slighty different. And as konsolebox's functions show, all this can be implemented, reasonably easily, outside of the bash source code, in code that implements whatever you want. Those functions aren't what I'd want (for several reasons, not least because they are very bash dependent) but if I needed something like that, I could write my own, similar ones. I think all this just shows that there's no real need to add any code to bash at all for this, it is OK as it is now (and everyone should just continue ignoring the PATH search when using '.' (or "source") and use full path names instead - whether generated by a function, or an install script, or simply written that way). If Chet wants to alter the way this works in bash, he can do it however seems best to him for what the majority of users are likely to prefer, or just whatever it is he prefers - I am fairly sure it wouldn't break the simple ". /path/to/file" usage, which is all we really need to work to be able to do anything we personally like. kre
count in vi mode alters prompt
Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: darwin23.2.0 Compiler: /usr/bin/clang Compilation CFLAGS: -pipe -Os -DSSH_SOURCE_BASHRC -isysroot/Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk -arch x86_64 uname output: Darwin Mohameds-MBP 23.4.0 Darwin Kernel Version 23.4.0: Fri Mar 15 00:11:05 PDT 2024; root:xnu-10063.101.17~1/RELEASE_X86_64 x86_64 Machine Type: x86_64-apple-darwin23.2.0 Bash Version: 5.2 Patch Level: 26 Release Status: release Description: When using vi mode in bash, whenever a count is used before a command, bash replaces the prompt with (arg: n) where n is the count entered. This causes the entire line to shift, which is particularly jarring if a long prompt is used, as is common. It should instead silently accept the count as it does any other input in command mode. Repeat-By: 1. set -o vi 2. edit a line and use a count before a command
Re: [PATCH v2 5/8] builtins/source: parse the -i option
On Sat, May 18, 2024, at 11:41 AM, Matheus Afonso Martins Moreira wrote: >> I am xing fingers the consensus, if any of theses takes off, >> is to have the -i implemented (not omitted) > > Me too. Do you know anyone else who could be impacted? > Consensus might move in that direction if more voices make > themselves heard on this list. Consensus does not depend on how many people openly agree with you, except insofar as additional discussion sways those who disagree. -- vq
Re: [PATCH v2 5/8] builtins/source: parse the -i option
> I am xing fingers the consensus, if any of theses takes off, > is to have the -i implemented (not omitted) Me too. Do you know anyone else who could be impacted? Consensus might move in that direction if more voices make themselves heard on this list. > if one, distro, sysadmin, and ultimatly the user > fiddle with BASH_SOURCE_PATH in the ENV (*rc files), > changing the good'ol 'source' behavior, > it would be a serious regression to me. That's exactly what I mean. > So to me BASH_SOURCE_PATH enablement must be guarded by a never used yet > option to 'source or dot' (here -i apparently) Agree. I initially chose -l which stands for library but that terminology proved problematic. So I chose -i which stands for isolated, the option "isolates" source to only the directories defined in the new variable. Maybe there's a better word/character. Naming things is hard. > and an enforcement that no alias > source='source -i' could ever be possible. I don't really have any objections to that but I'd say there are probably too many ways for people to get around such a filter. It would probably be ineffective. -- Matheus
Re: [PATCH v2 5/8] builtins/source: parse the -i option
On Sat, May 18, 2024 at 3:23 PM Matheus Afonso Martins Moreira < math...@matheusmoreira.com> wrote: > > > That would cause shell scripts to see it and exhibit a change in > behavior. > > Only if the -i option is not implemented. > If it is, there will be zero change in behavior > whether BASH_SOURCE_PATH is set or not. > Only if the script explicitly passes -i to source > will the behavior change. > I am xing fingers the consensus, if any of theses takes off, is to have the -i implemented (not omitted) along with a protection against alias source='source -i' I really depend on actual 'source' behavior, and can't update my packages (distributed since long). I don't plan to use BASH_SOURCE_PATH, so if one, distro, sysadmin, and ultimatly the user fiddle with BASH_SOURCE_PATH in the ENV (*rc files), changing the good'ol 'source' behavior, it would be a serious regression to me. So to me BASH_SOURCE_PATH enablement must be guarded by a never used yet option to 'source or dot' (here -i apparently) and an enforcement that no alias source='source -i' could ever be possible. All this is because one writing a 'main' script (#!/bin/bash), sourcing a package of mine through my package management system, expecting the current source behavior, and later add the loading of a 'libraries' from a friend (terminal color jazz) that in turn start to mess around with alias source='source -i' and BASH_SOURCE_PATH cold start to break my way of finding my packages. An alternative to this would be BASH_SOURCE_PATH="" don't do nothing with 'source', and allow the 'libraries' designer to do typeset -r BASH_SOURCE_PATH="" in the early step of the main script, so nobody will ever be able to do anything clever with BASH_SOURCE_PATH, or could add import from incompatible packages system. But even this idea is a pb to me because it would require a change an my side that is not really doable. Well in short don't break the old source semantic.
Re: [PATCH v2 5/8] builtins/source: parse the -i option
> You've made contradictory statements here. I don't see how. > First you said you wanted to put it into your *environment*. Yes. > That would cause shell scripts to see it and exhibit a change in behavior. Only if the -i option is not implemented. If it is, there will be zero change in behavior whether BASH_SOURCE_PATH is set or not. Only if the script explicitly passes -i to source will the behavior change. > Next you said you would like to set it in your .bashrc file. > That's totally different. How is it different? If I export a variable in .bashrc, and bash reads and evaluates that file at startup, then that variable gets exported to the shell and all processes spawned by it. > Setting it in .bashrc *without* putting it into the > environment (no export) is "safe". It will only affect > your interactive shell, and not any scripts that you run. I know. I'm just saying it doesn't have to be that way. I'm saying that in addition to it being safe if unset or unexported, it could _also_ be made safe if exported. The -i option provides that safety by requiring that source code be changed in order to enable it. Existing code will never be impacted by the feature whether the variable is set or not, simply because they do not pass -i to the source builtin. -- Matheus
Re: [PATCH v2 5/8] builtins/source: parse the -i option
On Sat, May 18, 2024 at 08:39:57AM -0300, Matheus Afonso Martins Moreira wrote: > > Setting the variable at all is opting in to new behavior, and you do > > that at your own risk, after reading the documentation and deciding > > that this is what you want. > > As the user, it should be my prerogative to set the > variable on my environment and/or rc so that I can > organize my sourceable scripts however I want and > have the scripts which enabled the isolated sourcing > just work no matter where I chose to install them. > > As the user, I should be able to run shell scripts > regardless of whether they support this or not. > I should be to set this variable on my .bashrc > and enjoy the nice infrastructure it provides > without worrying about whether or not > some script takes it into account. You've made contradictory statements here. First you said you wanted to put it into your *environment*. That would cause shell scripts to see it and exhibit a change in behavior. Next you said you would like to set it in your .bashrc file. That's totally different. Setting it in .bashrc *without* putting it into the environment (no export) is "safe". It will only affect your interactive shell, and not any scripts that you run.
Re: [PATCH v2 5/8] builtins/source: parse the -i option
> Setting the variable at all is opting in to new behavior, and you do > that at your own risk, after reading the documentation and deciding > that this is what you want. As the user, it should be my prerogative to set the variable on my environment and/or rc so that I can organize my sourceable scripts however I want and have the scripts which enabled the isolated sourcing just work no matter where I chose to install them. As the user, I should be able to run shell scripts regardless of whether they support this or not. I should be to set this variable on my .bashrc and enjoy the nice infrastructure it provides without worrying about whether or not some script takes it into account. I shouldn't be forced to choose between legacy shell scripts which don't support this and new shell scripts which do. There's no technical reason why I shouldn't be able to run both in the same bash, or even have one type of script source the other. Environment variables are recursively passed down the process tree. If you choose the variable approach, my choice to "opt in" will get applied recursively as well. I'll be making that choice for every script that I run and every script sourced by those scripts. That's actually a breaking change that fails to be compatible. All that could be achieved without incompatibility by simply adding the -i option to source. Then my choice remains mine alone when I pass -i to source while interacting with bash via the terminal. Then the script writer's choice becomes theirs alone when they write their scripts. It becomes a local choice, not a recursive and inheritable one. The recursive and inheritable nature of environment variables are useful for programs _after_ they have chosen to use them. If the presence of the variable becomes a choice unto itself, that choice will end up being inadvertently forced on others. > I do not foresee people setting BASH_SOURCE_PATH > in their basic interactive shell environments and login > sessions. That should definitely be foreseen because that's _exactly_ what I plan to do if this feature gets merged. I will set it on my .bashrc just like this: export BASH_SOURCE_PATH="${HOME}"/.local/share/bash/source Then I will commit that to my dotfiles repository. > Why would they do that? > What purpose would it serve? I will set the variable in order to create a fixed location for loading libraries. Then I will break up my growing collection of shell scripts into reusable functions, put them into separate files and then put those files in the BASH_SOURCE_PATH. Then I can easily source those libraries of functions from my bash programs. The purpose is to be able to more easily write more complex bash scripts. This will allow me to write scripts by following a process like: source -i terminal source -i options # use option parsing functions to get inputs # compute some useful output # color output with terminal functions > But you wouldn't want it to be set in your other windows. I absolutely want it set on every bash process, including interactive ones. I always want the ability to source the nice functions that I put effort into writing and debugging and organizing. I will even add shorthand aliases for them so that they will be easy to type on the terminal. > What I'm imagining here is that the variable will be used almost exclusively by scripts, to set the location of their resource files, which they source. I have nothing against that use case but that's not at all what I'm imagining. For me this is very much a feature for the _users_ to help them manage their shell script collections. It should be in no way exclusive to the scripts. > They're not useful outside of the script which sources them > so only that script needs to set BASH_SOURCE_PATH False. The variable will be extremely and directly useful to me as a bash user. That's why I proposed and implemented it. I didn't even intend for the scripts to override it. The whole idea is scripts would give source some symbol that represents what they need and source would take care of loading it so that the functions are available. They need not care where or even what the scripts are, they can just say: source -i my-functions And it gets done. I have no objections to scripts overriding it at all. However I don't think that's an argument against users being able to control their environment just like they have control over PATH. -- Matheus
Re: proposed BASH_SOURCE_PATH
On Sat, May 18, 2024 at 9:18 AM Martin D Kealey wrote: > On Thu, 16 May 2024 at 22:50, konsolebox wrote: >> >> On Thu, May 16, 2024 at 4:59 PM Martin D Kealey >> wrote: >> > As I understood your counter-proposal, it would result in this: >> > * ./a and ./b/c/d would be treated as relative to $PWD >> >> Not to $PWD but the calling script's directory. source as it is now >> already refers to $PWD. `source -i` will refer to the calling >> script's directory instead. > > > Ok, that seems more reasonable, and seemingly parallels the supposed (*) > special-case behaviour of './' elsewhere. > >> > * a and b/c/d (any paths not starting with '/' or './') would remain as I >> > specified, and be treated as relative to $(dirname $(realpath $0)) >> >> Only if BASH_SOURCE_PATH is empty will $0 be used as reference because >> it becomes the default as you have suggested. But if it isn't, the >> paths specified in BASH_SOURCE_PATH will be used instead. > > > Strongly agreed; I over-simplified my description. > >> `cmd` searches for the binary in PATH, `./cmd` doesn't. >> `source script` searches for the script in PATH. `source ./script` doesn't. > > > Yes I get that, but that's because ./script is a particular case of > subdir/script, and in POSIX subdir/script isn't searched for. (Supposedly > that behaviour is different when not in POSIX mode, but I couldn't confirm > that experimentally.) > >> Why would you decide to change `source -i ./script` to also search for >> the script in BASH_SOURCE_PATH just because a bunch of newbies might >> misinterpret it? > > > To be clear, I was suggesting that "modulegroup/module.bash" should search > BASH_SOURCE_PATH; my fairly weak objection was to treating "./module.bash" > differently based on its textual form, but it's not the hill I want to die > on. If there's precedent elsewhere then I withdraw that objection. > > I wonder whether 'source -i' should ignore POSIX mode and behave as if it's > always "on"? > >> Even without considering source and "cmd"'s current behavior, it >> doesn't make sense to add an additional option just to make the shell >> know that you're referring to an explicit path relative to the current >> directory (or script) or not. > > > Put that way, it does sound a bit odd. > >> Also just to make sure things are clear. I'm referring to "$0" here >> as the main script's path and not the calling script's path. >> BASH_SOURCE_PATH can be allowed to have a default value but it doesn't >> make sense if that "default value" changes meaning depending on the >> location of the script running. BASH_SOURCE_PATH's values are >> supposed to always refer to the same paths regardless if the values >> are relative or not otherwise that would be a broken behavior. >> Relative paths in BASH_SOURCE_PATHS if they become allowed should use >> the main script's directory as reference as well. > > > Hmm, I can see cases for both relative to $0 and relative to whichever file > contains the "source" command. > Is there a consensus on this? I don't know. I didn't get a direct reply on this besides yours yet and I haven't thoroughly read the other thread. I just think it's the most sensible way to do it if ever default values and relative paths in BASH_SOURCE_PATH become supported. I also now think it's better to not support them at all since the main script itself is not a reliable reference. Relying on PWD makes it worse as well. Scripts less likely changing directories while calling `source -i` is not a valid reason to use it. `source -i` has to work consistently through and through in all cases. Please make sure you reply to bug-bash as well and not just to me. -- konsolebox
Re: source -i prototype implementation and other features
I also uploaded a copy of the script and the patch to gist: https://gist.github.com/konsolebox/a908cf13e511abdf05daec89a9cbdd8d -- konsolebox
source -i prototype implementation and other features
This is what I think an acceptable implementation of `source -i` should look like: #!/bin/bash if [[ BASH_VERSINFO -ge 5 && ${SOURCE_EXTENSIONS_LOADED-} != true ]]; then function source._die { printf '%s\n' "$1" >&2 exit "${2-1}" } function source._get_calling_script_dir { [[ ${BASH_SOURCE[3]+.} ]] || source._die "Calling script's location unknown." [[ ${BASH_SOURCE[3]} == /* ]] || source._die "Calling script's path not absolute." _calling_script_dir=${BASH_SOURCE[2]%/*} _calling_script_dir=${_calling_script_dir:-/} } function source._a { local paths realpath p _calling_script_dir=() IFS=: read -r paths <<< "$1" for p in "${paths[@]}"; do [[ $p ]] || continue if [[ $p != /* ]]; then [[ ${_calling_script_dir+.} ]] || source._get_calling_script_dir p=${_calling_script_dir}/$p fi realpath=$(realpath -Pm -- "$p") || source._die "Failed to get realpath of '$p'." BASH_SOURCE_PATH+=${BASH_SOURCE_PATH:+:}${realpath} done } function source._I { declare -gA BASH_SOURCE_INCLUDED local filename=$2 realpath shift 2 realpath=$(realpath -Pe -- "${filename}") || \ source._die "Failed to get realpath of '${filename}'." if [[ -z ${BASH_SOURCE_INCLUDED[${realpath}]+.} ]]; then BASH_SOURCE_INCLUDED[${realpath}]=. command source -- "${realpath}" "$@" fi } function source._i { local callback=$1 filename=$2 main_script_dir=() p _calling_script_dir=() shift 2 if [[ ${filename} == @(/*|./*|../*) ]]; then if [[ $1 != /* ]]; then [[ ${_calling_script_dir+.} ]] || source._get_calling_script_dir filename=${_calling_script_dir}/${filename} fi [[ -e ${filename} ]] || source._die "File doesn't exist: ${filename}" "${callback}" -- "${filename}" "$@" else IFS=: read -r paths <<< "${BASH_SOURCE_PATH}" [[ ${#paths[@]} -gt 0 ]] || paths=(.) for p in "${paths[@]}"; do [[ $p ]] || continue if [[ $p != /* ]]; then if [[ -z ${main_script_dir+.} ]]; then [[ ${#BASH_SOURCE[@]} -gt 2 ]] || source._die "Main script's location unknown." [[ ${BASH_SOURCE[-1]} == /* ]] || source._die "Main script's path isn't absolute." main_script_dir=${BASH_SOURCE[-1]%/*} main_script_dir=${main_script_dir:-/} fi p=${main_script_dir}/$p fi if [[ -e ${p}/${filename} ]]; then "${callback}" -- "${p}/${filename}" "$@" return fi done source._die "File not found in BASH_SOURCE_PATH: ${filename}" fi } function source { local mode= while [[ $# -gt 0 ]]; do case $1 in -[aA]) [[ ${2+.} ]] || source._die "No argument specified to $1." [[ $1 == -A ]] && BASH_SOURCE_PATH= source._a "$2" shift ;; -[iI]) mode=${1#-} ;; --) shift break ;; -?*) source._die "Invalid option: $1" ;; *) break ;; esac shift done [[ ${1+.} ]] || source._die "Filename argument required" [[ $1 ]] || source._die "Invalid empty filename" if [[ ${mode} == i ]]; then source._i source "$@" elif [[ ${mode} == I ]]; then source._i source._I "$@" else command source -- "$@" fi } SOURCE_EXTENSIONS_LOADED=true fi The other features like `source -I`, `source -a` and `source -A` are optional. `source -I` is the same as `source -i` but it only allows a file to be source'd if it hasn't been included using `source -I` yet. `source -a` adds paths to BASH_SOURCE_PATH in their realpath format using the calling script as reference. `source -A` works the same as `source -a` except it overrides the values in BASH_SOURCE_PATH. Details on how `source -i` works are the following: - Paths beginning with /, ./, or ../ aren't searched in BASH_SOURCE_PATH. - Paths beginning with ./ or ../ use the calling script's directory as reference. - Paths not beginning with /, ./, or ../ are searched in BASH_SOURCE_PATH. - If BASH_SOURCE_PATH is unset, '.' is used as a default value. - If a path in BASH_SOURCE_PATH points to a relative location, it uses the directory of the main script as reference. The main script is basically