- Optimize startup path #494
  - Cuts fisher-related startup time to roughly 25ms
  - Reduce legacy fish support (~~>=2.0~~ >=2.1)
- Read fishfile from `$fisher_path` instead of `$fish_config` #480, #479
- Don't add invalid packages to fishfile / validate fishfile #478 #484 #492
- Rewrite tar expansion logic / don't use `--strip-components` #489 #496
  - Better OpenBSD support
  - Better msys2 on Windows 10 support
- Create symbolic links of original files when adding local packages #502
This commit is contained in:
Jorge Bucaran 2019-01-01 02:49:03 +09:00
parent d65b86487b
commit 39e9f3f340
No known key found for this signature in database
GPG key ID: E54BA3C0E646DB30
2 changed files with 244 additions and 207 deletions

View file

@ -81,31 +81,35 @@ You can use Fisher to add, update, and remove packages interactively, taking adv
### Adding packages ### Adding packages
Install packages using the `add` command followed by the path to the repository on GitHub. Add packages using the `add` command followed by the path to the repository on GitHub.
``` ```
fisher add jethrokuan/z rafaelrinaldi/pure fisher add jethrokuan/z rafaelrinaldi/pure
``` ```
A username or organization name is required. To install a package from anywhere else, use the address of the server and the path to the repository. HTTPS is always assumed so you don't need to specify the protocol. To add a package from anywhere other than GitHub, use the address of the server and the path to the repository. HTTPS is always assumed so you don't need to specify the protocol.
``` ```
fisher add gitlab.com/jorgebucaran/mermaid fisher add gitlab.com/jorgebucaran/mermaid
``` ```
To install a package from a tag, branch or a [commit-ish](https://git-scm.com/docs/gitglossary#gitglossary-aiddefcommit-ishacommit-ishalsocommittish), specify the reference following an `@` symbol after the package name. If none is given, we'll use the latest code. To add a specific version of a package use an `@` symbol after the package name followed by the tag, branch or [commit-ish](https://git-scm.com/docs/gitglossary#gitglossary-aiddefcommit-ishacommit-ishalsocommittish) you want. Only one package version can be installed at any given time.
``` ```
fisher add edc/bass@20f73ef jethrokuan/z@pre27 fisher add edc/bass@20f73ef jethrokuan/z@pre27
``` ```
You can also install packages from a local directory. Local packages are managed through [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link) so that they can be developed and used at the same time. To add a package from a private repository set the `fisher_user_api_token` variable to your username followed by a colon and your authorization token or password.
``` ```fish
fisher add ~/path/to/myfish/pkg set -g fisher_user_api_token jorgebucaran:ce04da9bd93ddb5e729cfff4a58c226322c8d142
``` ```
You can only install one package version at a time. If two packages depend on a different version of the same package, the first one that gets installed will take precedence over the other. You can also add packages from a local directory. Local packages will be copied as [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link) so changes in the original files will be reflected in future shell sessions without the need to run `fisher` again.
```
fisher add ~/path/to/local/pkg
```
### Listing packages ### Listing packages
@ -162,7 +166,7 @@ fisher version
Whenever you add or remove a package from the command line we'll write to a text file in `~/.config/fish/fishfile`. This is your fishfile. It lists every package that is currently installed on your system. You should add this file to your dotfiles or version control if you want to reproduce your configuration on a different system. Whenever you add or remove a package from the command line we'll write to a text file in `~/.config/fish/fishfile`. This is your fishfile. It lists every package that is currently installed on your system. You should add this file to your dotfiles or version control if you want to reproduce your configuration on a different system.
You can edit this file to add or remove packages and then run `fisher` to commit your changes. Only the packages listed in this file will be installed after `fisher` returns. If a package is already installed, it will be updated. Empty lines and anything after a `#` symbol will be ignored. You can edit this file to add or remove packages and run `fisher` to commit your changes. Only the packages listed in this file will be installed after `fisher` returns. If a package is already installed, it will be updated. Everything after a `#` symbol (comments) will be ignored.
```fish ```fish
vi ~/.config/fish/fishfile vi ~/.config/fish/fishfile
@ -271,7 +275,7 @@ bind \cg "vi ~/.config/fish/fishfile"
set -l name (basename (status -f) .fish){_uninstall} set -l name (basename (status -f) .fish){_uninstall}
function $name --on-event $name function $name --event $name
bind -e \cg bind -e \cg
end end
``` ```

View file

@ -1,4 +1,4 @@
set -g fisher_version 3.1.1 set -g fisher_version 3.2.0
function fisher -a cmd -d "fish package manager" function fisher -a cmd -d "fish package manager"
set -q XDG_CACHE_HOME; or set XDG_CACHE_HOME ~/.cache set -q XDG_CACHE_HOME; or set XDG_CACHE_HOME ~/.cache
@ -10,29 +10,31 @@ function fisher -a cmd -d "fish package manager"
set -q fisher_path; or set -g fisher_path $fish_config set -q fisher_path; or set -g fisher_path $fish_config
for dir in {$fish_config,$fisher_path}/{functions,completions,conf.d} $fisher_cache for path in {$fish_config,$fisher_path}/{functions,completions,conf.d} $fisher_cache
if test ! -e $dir if test ! -d $path
command mkdir -p $dir command mkdir -p $path
end end
end end
if test ! -e "$fisher_path/completions/fisher.fish" if test ! -e $fisher_path/completions/fisher.fish
echo "fisher self-complete" > $fisher_path/completions/fisher.fish echo "fisher self-complete" >$fisher_path/completions/fisher.fish
_fisher_self_complete _fisher_self_complete
end end
if test ! -e "$fisher_path/conf.d/fisher.fish" if test -e $fisher_path/conf.d/fisher.fish
switch "$version" switch "$version"
case 2\* \*-\* case \*-\*
echo "fisher copy-user-key-bindings" > $fisher_path/conf.d/fisher.fish command rm -f $fisher_path/conf.d/fisher.fish
end case 2\*
else
switch "$version"
case 2\* \*-\*
case \* case \*
command rm -f $fisher_path/conf.d/fisher.fish command rm -f $fisher_path/conf.d/fisher.fish
end end
else
switch "$version"
case \*-\*
case 2\*
echo "fisher copy-user-key-bindings" >$fisher_path/conf.d/fisher.fish
end
end end
switch "$cmd" switch "$cmd"
@ -41,28 +43,33 @@ function fisher -a cmd -d "fish package manager"
case copy-user-key-bindings case copy-user-key-bindings
_fisher_copy_user_key_bindings _fisher_copy_user_key_bindings
case ls case ls
_fisher_ls | command sed "s|$HOME|~|" _fisher_ls | _fisher_fmt
case self-update
_fisher_self_update (status -f)
case self-uninstall
_fisher_self_uninstall
case -v {,--}version case -v {,--}version
_fisher_version (status -f) _fisher_version (status -f)
case -h {,--}help case -h {,--}help
_fisher_help _fisher_help
case self-update case ""
_fisher_self_update (status -f); or return _fisher_commit -- $argv
_fisher_self_complete case add rm
case self-uninstall if not isatty
_fisher_self_uninstall while read -l arg
case add rm "" set argv $argv $arg
if test ! -z "$argv"
if not isatty
while read -l i
set argv $argv $i
end
end end
end end
_fisher_commit $argv; or return
_fisher_self_complete if test (count $argv) = 1
echo "invalid number of arguments" >&2
_fisher_help >&2
return 1
end
_fisher_commit $argv
case \* case \*
echo "error: unknown flag or command \"$cmd\"" >&2 echo "unknown flag or command \"$cmd\"" >&2
_fisher_help >&2 _fisher_help >&2
return 1 return 1
end end
@ -70,13 +77,13 @@ end
function _fisher_self_complete function _fisher_self_complete
complete -c fisher --erase complete -c fisher --erase
complete -xc fisher -n __fish_use_subcommand -a version -d "Show version"
complete -xc fisher -n __fish_use_subcommand -a help -d "Show help"
complete -xc fisher -n __fish_use_subcommand -a self-update -d "Update fisher"
complete -xc fisher -n __fish_use_subcommand -a ls -d "List installed packages"
complete -xc fisher -n __fish_use_subcommand -a rm -d "Remove packages"
complete -xc fisher -n __fish_use_subcommand -a add -d "Add packages" complete -xc fisher -n __fish_use_subcommand -a add -d "Add packages"
for pkg in (_fisher_ls) complete -xc fisher -n __fish_use_subcommand -a rm -d "Remove packages"
complete -xc fisher -n __fish_use_subcommand -a ls -d "List added packages"
complete -xc fisher -n __fish_use_subcommand -a help -d "Show usage help"
complete -xc fisher -n __fish_use_subcommand -a version -d "$fisher_version"
complete -xc fisher -n __fish_use_subcommand -a self-update -d "Update to the latest version"
for pkg in (_fisher_ls | _fisher_fmt)
complete -xc fisher -n "__fish_seen_subcommand_from rm" -a $pkg complete -xc fisher -n "__fish_seen_subcommand_from rm" -a $pkg
end end
end end
@ -98,8 +105,8 @@ end
function _fisher_ls function _fisher_ls
set -l pkgs $fisher_config/*/*/* set -l pkgs $fisher_config/*/*/*
for pkg in $pkgs for pkg in $pkgs
command readlink $pkg; and continue; or echo $pkg command readlink $pkg; or echo $pkg
end | command sed "s|$fisher_config/*||;s|github\.com/||" end
end end
function _fisher_version -a file function _fisher_version -a file
@ -107,35 +114,33 @@ function _fisher_version -a file
end end
function _fisher_help function _fisher_help
echo "usage: " echo "usage:"
echo " fisher add <PACKAGES> add packages" echo " fisher add <PACKAGES> Add packages"
echo " fisher rm <PACKAGES> remove packages" echo " fisher rm <PACKAGES> Remove packages"
echo " fisher update installed packages" echo " fisher Update all packages"
echo " fisher ls show installed packages" echo " fisher ls List added packages"
echo " fisher help show this help" echo " fisher help Show this help"
echo " fisher version show version" echo " fisher version Show the current version"
echo " fisher self-update update fisher" echo " fisher self-update Update to the latest version"
echo " fisher self-uninstall uninstall fisher" echo " fisher self-uninstall Uninstall from your system"
echo echo
echo "examples:" echo "examples:"
echo " fisher add jethrokuan/z rafaelrinaldi/pure" echo " fisher add jethrokuan/z rafaelrinaldi/pure"
echo " fisher add gitlab.com/owner/foobar@v2" echo " fisher add gitlab.com/foo/bar@v2"
echo " fisher add ~/path/to/myfish/pkg" echo " fisher add ~/path/to/local/pkg"
echo " fisher rm rafaelrinaldi/pure" echo " fisher rm rafaelrinaldi/pure"
echo " fisher ls | fisher rm"
echo " fisher add < bundle" echo " fisher add < bundle"
end end
function _fisher_self_update -a file function _fisher_self_update -a file
set -l url "https://raw.githubusercontent.com/jorgebucaran/fisher/master/fisher.fish" set -l url "https://raw.githubusercontent.com/jorgebucaran/fisher/master/fisher.fish"
echo "fetching $url" >&2 echo "fetching $url" >&2
command curl -s "$url?nocache" >$file.
command curl -s "$url?nocache" >$file@ set -l next_version (command awk 'NR == 1 { print $4 }' < $file.)
set -l next_version (awk 'NR == 1 { print $4; exit }' < $file@)
switch "$next_version" switch "$next_version"
case "" $fisher_version case "" $fisher_version
command rm -f $file@ command rm -f $file.
if test -z "$next_version" if test -z "$next_version"
echo "cannot update fisher -- are you offline?" >&2 echo "cannot update fisher -- are you offline?" >&2
return 1 return 1
@ -143,17 +148,21 @@ function _fisher_self_update -a file
echo "fisher is already up-to-date" >&2 echo "fisher is already up-to-date" >&2
case \* case \*
echo "linking $file" | command sed "s|$HOME|~|" >&2 echo "linking $file" | command sed "s|$HOME|~|" >&2
command mv -f $file@ $file command mv -f $file. $file
source $file source $file
echo "updated fisher to $fisher_version -- hooray!" >&2 echo "updated to $fisher_version -- hooray!" >&2
_fisher_self_complete
end end
end end
function _fisher_self_uninstall function _fisher_self_uninstall
set -l current_pkgs $fisher_config/*/*/* for pkg in (_fisher_ls)
for path in $fisher_cache (_fisher_pkg_remove_all $current_pkgs) $fisher_config $fisher_path/{functions,completions,conf.d}/fisher.fish $fisher_path/fishfile _fisher_rm $pkg
echo "removing $path" end
command rm -rf $path 2>/dev/null
for file in $fisher_cache $fisher_config $fisher_path/{functions,completions,conf.d}/fisher.fish $fisher_path/fishfile
echo "removing $file"
command rm -Rf $file 2>/dev/null
end | command sed "s|$HOME|~|" >&2 end | command sed "s|$HOME|~|" >&2
set -e fisher_cache set -e fisher_cache
@ -167,69 +176,150 @@ function _fisher_self_uninstall
echo "done -- see you again!" >&2 echo "done -- see you again!" >&2
end end
function _fisher_commit function _fisher_commit -a cmd
set -e argv[1]
set -l elapsed (_fisher_now) set -l elapsed (_fisher_now)
set -l current_pkgs $fisher_config/*/*/*
set -l removed_pkgs (_fisher_pkg_remove_all $current_pkgs)
command rm -rf $fisher_config
command mkdir -p $fisher_config
set -l fishfile $fisher_path/fishfile set -l fishfile $fisher_path/fishfile
if test ! -e "$fishfile" if test ! -e "$fishfile"
command touch $fishfile command touch $fishfile
echo "created empty fishfile in $fishfile" | command sed "s|$HOME|~|" >&2 echo "created new fishfile in $fishfile" | command sed "s|$HOME|~|" >&2
end end
printf "%s\n" (_fisher_fishfile_format (echo -s $argv\;) < $fishfile) > $fishfile
set -l expected_pkgs (_fisher_fishfile_read < $fishfile) set -l rm_pkgs (_fisher_ls | _fisher_fmt)
set -l added_pkgs (_fisher_pkg_fetch_all $expected_pkgs) for pkg in (_fisher_ls)
set -l updated_pkgs ( _fisher_rm $pkg
for pkg in $removed_pkgs end
set pkg (echo $pkg | command sed "s|$fisher_config/*||") command rm -Rf $fisher_config
if contains -- $pkg $added_pkgs command mkdir -p $fisher_config
echo $pkg
end
end)
if test -z "$added_pkgs$updated_pkgs$removed_pkgs$expected_pkgs" set -l next_pkgs (_fisher_fmt < $fishfile | _fisher_read $cmd (printf "%s\n" $argv | _fisher_fmt))
set -l new_pkgs (_fisher_fetch $next_pkgs)
set -l old_pkgs
for pkg in $rm_pkgs
if contains -- $pkg $new_pkgs
set old_pkgs $old_pkgs $pkg
end
end
if test -z "$new_pkgs$old_pkgs$rm_pkgs$next_pkgs"
echo "nothing to commit -- try adding some packages" >&2 echo "nothing to commit -- try adding some packages" >&2
return 1 return 1
end end
_fisher_status (count $added_pkgs) (count $updated_pkgs) (count $removed_pkgs) (_fisher_now $elapsed) >&2 set -l actual_pkgs
end if test "$cmd" = "rm"
set actual_pkgs $next_pkgs
function _fisher_pkg_remove_all else
for pkg in $argv for pkg in $next_pkgs
echo $pkg if contains -- (echo $pkg | command sed "s|@.*||") $new_pkgs
_fisher_pkg_uninstall $pkg set actual_pkgs $actual_pkgs $pkg
end
end
end end
_fisher_fmt <$fishfile | _fisher_write $cmd $actual_pkgs >$fishfile.
command mv -f $fishfile. $fishfile
_fisher_self_complete
command awk -v N=(count $new_pkgs) -v O=(count $old_pkgs) -v R=(count $rm_pkgs) -v E=(_fisher_now $elapsed) '
BEGIN {
if (N = N - O) res = msg(res, "added", N)
if (O) res = msg(res, "updated", O)
if (R = R - O) res = msg(res, "removed", R)
printf((res ? res : "done") " in %.2fs\n", E / 1000)
}
function msg(res, str, n) {
return (res ? res ", " : "") str " " n " package" (n > 1 ? "s" : "")
}
' >&2
end end
function _fisher_pkg_fetch_all function _fisher_fmt
command sed "s|^[ \t]*||;s|^$fisher_config/||;s|^$HOME|~|;s|^\.\/|$PWD/|;s|^github\.com/||;s|^https*://||;s|/*\$||"
end
function _fisher_read -a cmd
set -e argv[1]
command awk -v FS=\# -v CMD="$cmd" -v ARGS="$argv" '
BEGIN {
split(ARGS, args, " ")
for (i in args) {
if (!((k = getkey(args[i])) in pkgs)) {
pkgs[k] = args[i]
if (CMD == "add") out[n++] = args[i]
}
}
}
!/^#/ && NF {
if (!file[k = getkey($1)]++ && !(k in pkgs)) out[n++] = $1
}
END {
for (i = 0; i < n; i++) print out[i]
if (CMD == "rm") {
for (pkg in pkgs) {
if (!(pkg in file)) {
print "cannot remove \"" pkg "\" -- package not found" > "/dev/stderr"
}
}
}
}
function getkey(s) {
return (split(s, a, /@+|:/) > 2) ? a[2]"/"a[1]"/"a[3] : a[1]
}
'
end
function _fisher_write -a cmd
set -e argv[1]
command awk -v CMD="$cmd" -v ARGS="$argv" '
BEGIN {
split(ARGS, args, " ")
for (i in args) pkgs[getkey(args[i])] = args[i]
}
{
if (/^#/ || !NF) print $0
else {
k = getkey($0)
if (out = pkgs[k] != 0 ? pkgs[k] : CMD != "rm" ? $0 : "") print out
pkgs[k] = 0
}
}
END {
for (k in pkgs) if (pkgs[k]) print pkgs[k]
}
function getkey(s) {
return (split(s, a, /@+|:/) > 2) ? a[2]"/"a[1]"/"a[3] : a[1]
}
'
end
function _fisher_fetch
set -l pkg_jobs set -l pkg_jobs
set -l next_pkgs
set -l local_pkgs set -l local_pkgs
set -l actual_pkgs set -l actual_pkgs
set -l expected_pkgs set -q fisher_user_api_token; and set -l user_info -u $fisher_user_api_token
for id in $argv for i in $argv
switch $id switch $i
case \~\* /\* case \~\* /\*
set -l path (echo "$id" | command sed "s|~|$HOME|") set -l path (echo "$i" | command sed "s|~|$HOME|")
if test -e "$path" if test -e "$path"
set local_pkgs $local_pkgs $path set local_pkgs $local_pkgs $path
else else
echo "cannot install \"$id\" -- is this a valid file?" >&2 echo "cannot add \"$i\" -- is this a valid file?" >&2
end end
continue continue
end end
command awk -v ID=$id -v FS=/ 'BEGIN { command awk -v NAME=$i -v FS=/ 'BEGIN {
if (split(ID, tmp, /@+|:/) > 2) { if (split(NAME, tmp, /@+|:/) > 2) {
if (tmp[4]) sub("@"tmp[4], "", ID) if (tmp[4]) sub("@"tmp[4], "", NAME)
print ID "\t" tmp[2]"/"tmp[1]"/"tmp[3] "\t" (tmp[4] ? tmp[4] : "master") print NAME "\t" tmp[2]"/"tmp[1]"/"tmp[3] "\t" (tmp[4] ? tmp[4] : "master")
} else { } else {
pkg = split(ID, _, "/") <= 2 ? "github.com/"tmp[1] : tmp[1] pkg = split(NAME, _, "/") <= 2 ? "github.com/"tmp[1] : tmp[1]
tag = tmp[2] ? tmp[2] : "master" tag = tmp[2] ? tmp[2] : "master"
print (\ print (\
pkg ~ /^github/ ? "https://codeload."pkg"/tar.gz/"tag : \ pkg ~ /^github/ ? "https://codeload."pkg"/tar.gz/"tag : \
@ -237,74 +327,74 @@ function _fisher_pkg_fetch_all
pkg ~ /^bitbucket/ ? "https://"pkg"/get/"tag".tar.gz" : pkg \ pkg ~ /^bitbucket/ ? "https://"pkg"/get/"tag".tar.gz" : pkg \
) "\t" pkg ) "\t" pkg
} }
}' | read -l url pkg tag }' | read -l url pkg branch
if test ! -d "$fisher_config/$pkg" if test ! -d "$fisher_config/$pkg"
fish -c " fish -c "
echo fetching $url >&2 echo fetching $url >&2
command mkdir -p \"$fisher_config/$pkg\" command mkdir -p {$fisher_config,$fisher_cache}/$pkg
if test ! -z \"$tag\" if test ! -z \"$branch\"
command git clone $url \"$fisher_config/$pkg\" --branch $tag --depth 1 2>/dev/null command git clone $url $fisher_config/$pkg --branch $branch --depth 1 2>/dev/null
or echo cannot clone \"$url\" -- is this a valid url\? >&2 or echo cannot clone \"$url\" -- is this a valid url\? >&2
else if command curl -Ss $url 2>&1 | command tar -xzf- -C \"$fisher_config/$pkg\" --strip-components=1 2>/dev/null else if command curl $user_info -Ss $url 2>&1 | command tar -xzf- -C $fisher_config/$pkg 2>/dev/null
command mkdir -p \"$fisher_cache/$pkg\" command rm -Rf $fisher_cache/$pkg
command cp -Rf \"$fisher_config/$pkg\" \"$fisher_cache/$pkg/..\" command mv -f $fisher_config/$pkg/* $fisher_cache/$pkg
command rm -Rf $fisher_config/$pkg
command cp -Rf {$fisher_cache,$fisher_config}/$pkg
else if test -d \"$fisher_cache/$pkg\" else if test -d \"$fisher_cache/$pkg\"
echo cannot connect to server -- searching in \"$fisher_cache/$pkg\" | command sed 's|$HOME|~|' >&2 echo cannot connect to server -- searching in \"$fisher_cache/$pkg\" | command sed 's|$HOME|~|' >&2
command cp -Rf \"$fisher_cache/$pkg\" \"$fisher_config/$pkg/..\" command cp -Rf $fisher_cache/$pkg $fisher_config/$pkg/..
else else
command rm -rf \"$fisher_config/$pkg\" command rm -Rf $fisher_config/$pkg
echo cannot install \"$pkg\" -- is this a valid package\? >&2 echo cannot add \"$pkg\" -- is this a valid package\? >&2
end end
" >/dev/null & " >/dev/null &
set pkg_jobs $pkg_jobs (_fisher_jobs --last) set pkg_jobs $pkg_jobs (_fisher_jobs --last)
set expected_pkgs $expected_pkgs "$pkg" set next_pkgs $next_pkgs "$fisher_config/$pkg"
end end
end end
if test ! -z "$pkg_jobs" if test ! -z "$pkg_jobs"
_fisher_wait $pkg_jobs _fisher_wait $pkg_jobs
for pkg in $expected_pkgs for pkg in $next_pkgs
if test -d "$fisher_config/$pkg" if test -d "$pkg"
set actual_pkgs $actual_pkgs $pkg set actual_pkgs $actual_pkgs $pkg
_fisher_pkg_install $fisher_config/$pkg _fisher_add $pkg
end end
end end
end end
for pkg in $local_pkgs set -l local_path $fisher_config/local/$USER
set -l path local/$USER for src in $local_pkgs
set -l name (command basename $pkg) command mkdir -p $local_path
command mkdir -p $fisher_config/$path command ln -sf $src $local_path/(command basename $src)
command ln -sf $pkg $fisher_config/$path set actual_pkgs $actual_pkgs $src
set actual_pkgs $actual_pkgs $path/$name _fisher_add $src --link
_fisher_pkg_install $fisher_config/$path/$name
end end
if test ! -z "$actual_pkgs" if test ! -z "$actual_pkgs"
_fisher_pkg_fetch_all (_fisher_pkg_get_deps $actual_pkgs | command sort --unique) _fisher_fetch (_fisher_deps $actual_pkgs | command awk '!seen[$0]++')
printf "%s\n" $actual_pkgs printf "%s\n" $actual_pkgs | _fisher_fmt
end end
end end
function _fisher_pkg_get_deps function _fisher_deps
for pkg in $argv for pkg in $argv
set -l path $fisher_config/$pkg if test ! -d "$pkg"
if test ! -d "$path"
echo $pkg echo $pkg
else if test -s "$path/fishfile" else if test -s "$pkg/fishfile"
_fisher_pkg_get_deps (_fisher_fishfile_format < $path/fishfile | _fisher_fishfile_read) _fisher_deps (_fisher_fmt < $pkg/fishfile | _fisher_read)
end end
end end
end end
function _fisher_pkg_install -a pkg function _fisher_add -a pkg opts
set -l name (command basename $pkg) set -l name (command basename $pkg)
set -l files $pkg/{functions,completions,conf.d}/**.* $pkg/*.fish set -l files $pkg/{functions,completions,conf.d}/**.* $pkg/*.fish
for source in $files for src in $files
set -l target (command basename $source) set -l target (command basename $src)
switch $source switch $src
case $pkg/conf.d\* case $pkg/conf.d\*
set target $fisher_path/conf.d/$target set target $fisher_path/conf.d/$target
case $pkg/completions\* case $pkg/completions\*
@ -320,7 +410,11 @@ function _fisher_pkg_install -a pkg
end end
end end
echo "linking $target" | command sed "s|$HOME|~|" >&2 echo "linking $target" | command sed "s|$HOME|~|" >&2
command cp -f $source $target if test -z "$opts"
command cp -f $src $target
else
command ln -sf $src $target
end
switch $target switch $target
case \*.fish case \*.fish
source $target >/dev/null 2>/dev/null source $target >/dev/null 2>/dev/null
@ -328,13 +422,13 @@ function _fisher_pkg_install -a pkg
end end
end end
function _fisher_pkg_uninstall -a pkg function _fisher_rm -a pkg
set -l name (command basename $pkg) set -l name (command basename $pkg)
set -l files $pkg/{conf.d,completions,functions}/**.* $pkg/*.fish set -l files $pkg/{conf.d,completions,functions}/**.* $pkg/*.fish
for source in $files for src in $files
set -l target (command basename $source) set -l target (command basename $src)
set -l filename (command basename $target .fish) set -l filename (command basename $target .fish)
switch $source switch $src
case $pkg/conf.d\* case $pkg/conf.d\*
test "$filename.fish" = "$target"; and emit "$filename"_uninstall test "$filename.fish" = "$target"; and emit "$filename"_uninstall
set target conf.d/$target set target conf.d/$target
@ -345,7 +439,7 @@ function _fisher_pkg_uninstall -a pkg
test "$filename.fish" = "$target"; and functions -e $filename test "$filename.fish" = "$target"; and functions -e $filename
switch $target switch $target
case uninstall.fish case uninstall.fish
source $source source $src
continue continue
case init.fish key_bindings.fish case init.fish key_bindings.fish
set target conf.d/$name\_$target set target conf.d/$name\_$target
@ -360,75 +454,14 @@ function _fisher_pkg_uninstall -a pkg
end end
end end
function _fisher_fishfile_read
command awk -v FS=\# '!/^#/ && NF { print $1 }'
end
function _fisher_fishfile_format -a pkgs
command awk -v PWD=$PWD -v HOME=$HOME -v PKGS="$pkgs" '
BEGIN {
pkg_count = split(PKGS, pkgs, ";") - 1
cmd = pkgs[1]
for (i = 2; i <= pkg_count; i++) {
pkg_ids[i - 1] = get_pkg_id( pkgs[i] = normalize(pkgs[i]) )
}
} {
if (NF) {
$0 = normalize($0)
newln = newln > 0 ? "" : newln
if (/^#/) print newln$0
else if (!seen_pkgs[(pkg_id = get_pkg_id($0))]++) {
for (i = 1; i < pkg_count; i++) {
if (pkg_ids[i] == pkg_id) {
if (cmd == "rm") next
$0 = pkgs[i + 1]
break
}
}
print newln$0
}
newln = NF
} else if (newln) newln = "\n"(newln > 0 ? "" : newln)
}
END {
if (cmd == "rm" || pkg_count <= 1) exit
for (i = 2; i <= pkg_count; i++) {
if (!seen_pkgs[pkg_ids[i - 1]]) print pkgs[i]
}
}
function normalize(s) {
gsub(/^[ \t]*(https?:\/\/)?(.*github\.com\/)?|[\/ \t]*$/, "", s)
sub(/^\.\//, PWD"/", s)
sub(HOME, "~", s)
return s
}
function get_pkg_id(s) {
return (split(s, tmp, /@+|:/) > 2) ? tmp[2]"/"tmp[1]"/"tmp[3] : tmp[1]
}
'
end
function _fisher_status -a added updated removed elapsed
command awk -v ADDED=$added -v UPDATED=$updated -v REMOVED=$removed -v ELAPSED=$elapsed '
BEGIN {
if (ADDED = ADDED - UPDATED) res = msg(res, "added", ADDED)
if (UPDATED) res = msg(res, "updated", UPDATED)
if (REMOVED = REMOVED - UPDATED) res = msg(res, "removed", REMOVED)
printf((res ? res : "done") " in %.2fs\n", ELAPSED / 1000)
}
function msg(res, str, n) {
return (res ? res ", " : "") str " " n " package" (n > 1 ? "s" : "")
}
'
end
function _fisher_jobs function _fisher_jobs
jobs $argv | command awk '/[0-9]+\t/ { print $1 }' builtin jobs $argv | command awk '/[0-9]+\t/ { print $1 }'
end end
function _fisher_wait function _fisher_wait
while for job in $argv while for job in $argv
contains -- $job (_fisher_jobs); and break contains -- $job (_fisher_jobs)
and break
end end
end end
end end