fundle icon indicating copy to clipboard operation
fundle copied to clipboard

Global installation

Open BarbzYHOOL opened this issue 7 years ago • 7 comments

I think when we install fundle in /etc/fish, the plugins should also be in a global directory so all users use the same plugins instead of installing each plugin for each user (which wastes time and disk)

BarbzYHOOL avatar Jan 13 '19 15:01 BarbzYHOOL

One way I got this to work is place fundle.fish under /root/.config/fish/functions:

for i in functions completions
	command sudo wget https://raw.githubusercontent.com/danhper/fundle/master/$i/fundle.fish -O /root/.config/fish/$i/fundle.fish
	command sudo chmod o+x /root/.config/fish/$i/fundle.fish
end

... in /root/.config/fish/config.fish (or a file it references), set up the plugins and ln the loaded files to /etc/fish:

builtin source /root/.config/fish/functions/fundle.fish
fundle plugin 'one-line/per-plugin'
fundle init
if test ! -d /root/.config/fish/fundle
	fundle install
	for i in (fundle list | command grep -v https://github.com)
		for f in functions completions
			builtin test -d /root/.config/fish/fundle/$i/$f;
				and command chmod a+x /root/.config/fish/fundle/$i/$f/*;
				and command ln -v /root/.config/fish/fundle/$i/$f/* /etc/fish/$f/
		end
	end
end

Then just make sure root is the only one who updates fundle:

function __update_fundle
	command sudo --user=root fish -c "builtin source /root/.config/fish/functions/fundle.fish; fundle self-update; and fundle clean; and fundle update"
end

It's definitely not ideal, but it works.

hunter-richardson avatar Feb 13 '19 22:02 hunter-richardson

yeah, with symlink there is always a solution xD but it's damn dirty

thank you for idea, for now I just install it on every user (hopefully in my final setup I'll have only 2 users lol)

BarbzYHOOL avatar Feb 14 '19 16:02 BarbzYHOOL

@danhper

BarbzYHOOL avatar Oct 18 '22 22:10 BarbzYHOOL

Hey, I agree this would be nicer indeed! Would you have time to send a PR for this please?

danhper avatar Oct 26 '22 11:10 danhper

I don't know how to code this, I know a bit of fish scripting but what would be a good way to do all of this? at least if there was a plan to follow, me or someone could attempt to follow it

BarbzYHOOL avatar Oct 26 '22 16:10 BarbzYHOOL

Okay, let's place functions/fundle.fish under /root/.config/fish/functions, and optionally sym-link it to /etc/fish/functions to allow non-sudoer plugin installation:

for i in functions completions
	command sudo mkdir -pv /etc/fish/$i /root/.config/$i
		and command sudo wget --show-progress -v https;//raw.githubusercontent.com/danhper/fundle/master/$i/fundle.fish -O /root/.config/fish/$i/
		and command sudo ln -v /root/.config/fish/$i/fundle.fish /etc/fish/$i/ # allows non-sudoer plugin installation
		and command chmod -c a+rx /root/.config/$i/fundle.fish # allows non-sudoer plugin installation
end

Configure /root/.config/fish/config.fish for fundle, if necessary:

builtin source /root/.config/fish/functions/fundle.fish

Write the following functions to functions/fundle.fish:

function __fundle_validate_sudo -d "test whether the user is a sudoer"
	command sudo -v
	builtin set -l temp $status
	builtin printf 'You are %sa sudoer!' (builtin test $temp -eq 0
											or builtin printf 'not ')
	builtin return $temp
end

functions __fundle_is_global -d "test whether fundle is installed globally or locally"
	builtin string match -qr (builtin printf '^/home/%s' (command whoami)) (builtin status fish-path)
		and builtin printf 'You should have installed fundle globally!\nSee https://github.com/danhper/fundle#global-installation'
		and builtin return 1
	builtin return 0
end

functions __fundle_list_plugins -d "list installed plugins under given directory" -a dir
	builtin test -n "$dir" -a -d $dir -a -r $dir
		and command find $dir -type d -mindepth 2 -maxdepth 2 2>/dev/null | command string replace $dir ''
end

function __fundle_local_plugins -d "list locally installed plugins"
	__fundle_list_plugins __fundle_plugins_dir
end

function __fundle_global_plugins -d "list globally installed plugins"
	__fundle_list_plugins /etc/fish/fundle
end

function __fundle_plugins -d "list all available plugins"
	begin; __fundle_global_plugins; and __fundle_local_plugins; end | command sort -dfu
end

function __fundle_global_plugin -d "install global plugin to fundle"
	__fundle_is_global
		or builtin return $status
	__fundle_validate_sudo
		or builtin return $status
	builtin set -l name (command awk -F '[[:blank:]@]+' '{print $1}' "$argv")
	command sudo --user=root fish -c "fundle plugin $argv; and fundle init; and fundle install; and command chmod -cR a+rx /root/.config/fish"
		and for f in (command find -L /root/.config/fish/fundle/$name -type f -name '*.fish')
				builtin set -l dir (builtin string replace /root/.config /etc (command dirname $f))
					and command mkdir -pv $dir
					and command sudo ln -v $f $dir
			end
end

function __fundle_update_global -d "update global plugins" -a name
	__fundle_is_global
		or builtin return $status
	__fundle_validate_sudo
		or builtin return $status
	builtin test -n "$name"
		and command sudo --user=root fish -c "fundle update $name"
		or command sudo --user=root fish -c "fundle update"
end

The following cases under the switch in the fundle function itself:

		case "global-plugin"
			__fundle_global_plugin $sub_args
		case "global-update"
			__fundle_update_global $sub_args

And the following lines to completions/fundle.fish:

builtin complete -f -c fundle -n '__fish_prog_needs_command' -a global-plugin -d "add a global plugin"
builtin complete -f -c fundle -n '__fish_prog_needs_command' -a global-update -d "update existing global plugin"
builtin complete -f -c fundle -n '__fish_prog_using_command global-plugin' -l url -d "set the plugin URL"
builtin complete -f -c fundle -n '__fish_prog_using_command global-plugin' -l path -d "set the plugin load path"

Now prevent the local installation of plugins already installed globally:

functions __fundle_plugin -d "add plugin to fundle" -a name
	...
		if not contains $name (__fundle_plugins)
			...
		end
end

Then configure the global /etc/fish/config.fish to search for sym-links, depth-last (this might break for paths containing whitespace):

for f in (command find /etc/fish -type l -name '*.fish' -printf '%d %p\n' | command sort | command cut -d' ' -f2-)
	builtin source (command readlink -f "$f")
end

Now (unless I missed something) a sudoer may choose to install/update plugins for all users, and to allow non-sudoers to install any other plugin.

NOTE: Due to complexity of the __fundle_global_plugin function (which is due to the sym-linking), there's no need to run fundle init or after fundle global-plugin <plugin-identifier>. They simply need to source /etc/fish/config.fish to load freshly-installed global plugins.

hunter-richardson avatar Oct 26 '22 22:10 hunter-richardson

Why not make a PR if you have sorted it out Hunter?

BarbzYHOOL avatar Oct 27 '22 21:10 BarbzYHOOL