From: Ian Kelling Date: Fri, 17 Jun 2016 08:13:24 +0000 (-0700) Subject: several bug fixes, simplify to just one script file X-Git-Url: https://iankelling.org/git/?p=lnf;a=commitdiff_plain;h=e51702380450ee0b4719a17744208975730ddff7 several bug fixes, simplify to just one script file --- diff --git a/README b/README index b3829e2..4c5077f 100644 --- a/README +++ b/README @@ -1,12 +1,8 @@ -The main documentation is availiable via --help and near the top of any bash -script files which sit next to this file. +The main documentation is availiable via --help and near the top of the bash +script file which sit next to this file. -Files ending in -function are for sourcing then calling as a function. Files -without -function are exactly the same except they are for calling as a script. +The script file can be stripped of the last line and used as a function +instead of a script. -Patches, bugs, and any feedback is very welcome via gitorious or email to +Patches, bugs, and any feedback is very welcome via email to Ian Kelling . - -This program is also part of a collection of programs, -https://gitorious.org/bash-programs-by-ian, which are unrelated except -having the same author and being being bash programs. diff --git a/lnf b/lnf index c907b62..b4701df 100755 --- a/lnf +++ b/lnf @@ -9,7 +9,8 @@ Usage: lnf TARGET (2nd form) lnf TARGET... DIRECTORY (3rd form) -Remove existing file in the using trash-put or rm -rf if it is not available. +Remove existing file in the using trash-put or rm -rf if it is not available, +or trash-put fails due to a cross-filesystem link. Create directory if needed. Slightly more restrictive arguments than ln. In the 1st form, create a link to TARGET with the name LINK_NAME. In the 2nd @@ -36,32 +37,32 @@ links to each TARGET in DIRECTORY." shopt -s extglob - local remove x - if type -P trash-put >/dev/null; then - remove=trash-put - else - remove="rm -rf" - fi + local x ret prefix dir to_remove + to_remove=() if [[ $nodir ]]; then - if [[ -e "$2" || -L "$2" ]]; then - $remove "$2" - elif ! mkdir -p "$(dirname "$2")"; then - echo "lnf error: failed to make directory $(dirname "$2")" - return 1 + dir="$(dirname "$2")" + if [[ -e $2 || -L $2 ]]; then + to_remove+=("$2") + elif [[ ! -d $dir ]]; then + if [[ -e $dir || -L $dir ]]; then + to_remove+=("$dir") + fi + if ! mkdir -p "$(dirname "$2")"; then + echo "lnf error: failed to make directory $(dirname "$2")" + return 1 + fi fi elif (( $# >= 2 )); then if [[ -d ${!#} ]]; then - local oldcwd=$PWD - cd "${!#}" # last arg + prefix="${!#}/" # last arg for x in "${@:1:$(( $# - 1 ))}"; do # all but last arg - # remove any trailing slashes, uses extglob + # Remove 1 or more trailing slashes, using. x="${x%%+(/)}" - # remove any leading directory components - x="${x##*/}" - [[ -e "$x" || -L "$x" ]] && $remove "$x" + # remove any leading directory components, add prefix + x="$prefix/${x##*/}" + [[ -e "$x" || -L "$x" ]] && to_remove+=("$x") done - cd "$oldcwd" else if ! mkdir -p "${!#}"; then echo "lnf error: failed to make directory ${!#}" @@ -69,7 +70,26 @@ links to each TARGET in DIRECTORY." fi fi elif [[ $# -eq 1 ]]; then - [[ -e "${1##*/}" || -L "${1##*/}" ]] && $remove "${1##*/}" + [[ -e "${1##*/}" || -L "${1##*/}" ]] && to_remove+=("${1##*/}") + fi + if (( ${#to_remove[@]} >= 1 )); then + if type -P trash-put >/dev/null; then + trash-put -- "${to_remove[@]}" || ret=$? + # trash-put will fail to trash a link that goes across filesystems (72), + # and for empty files (74) + # so revert to rm -rf in that case + if [[ $ret == 72 ]]; then + echo "$0: using rm -rf to overcome cross filesystem trash-put limitation" + rm -rf -- "${to_remove[@]}" + elif [[ $ret == 74 ]]; then + echo "$0: using rm -rf to overcome empty file/dir trash-put limitation" + rm -rf -- "${to_remove[@]}" + elif [[ $ret && $ret != 0 ]]; then + return $x + fi + else + rm -rf -- "${to_remove[@]}" + fi fi $reset_extglob && shopt -u extglob diff --git a/lnf-function b/lnf-function deleted file mode 100644 index 0d43112..0000000 --- a/lnf-function +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/bash -# Copyright (C) 2014 Ian Kelling -# This program is under GPL v. 3 or later, see - -lnf() { - local help="lnf - Create symlinks conveniently and forcefully. -Usage: - lnf -T TARGET LINK_NAME (1st form) - lnf TARGET (2nd form) - lnf TARGET... DIRECTORY (3rd form) - -Remove existing file in the using trash-put or rm -rf if it is not available. -Create directory if needed. Slightly more restrictive arguments than ln. - -In the 1st form, create a link to TARGET with the name LINK_NAME. In the 2nd -form, create a link to TARGET in the current directory. In the 3rd form, create -links to each TARGET in DIRECTORY." - - if [[ $1 == --help || $# -eq 0 ]]; then - echo "$help" - return 0 - fi - - local nodir - if [[ $1 == -T ]]; then - nodir=-T - shift - if (( $# != 2 )); then - echo "lnf error: expected 2 arguments with -T flag. Got $#" - return 1 - fi - fi - - local reset_extglob=false - ! shopt extglob >/dev/null && reset_extglob=true - shopt -s extglob - - - local remove x - if type -P trash-put >/dev/null; then - remove=trash-put - else - remove="rm -rf" - fi - - if [[ $nodir ]]; then - if [[ -e "$2" || -L "$2" ]]; then - $remove "$2" - elif ! mkdir -p "$(dirname "$2")"; then - echo "lnf error: failed to make directory $(dirname "$2")" - return 1 - fi - elif (( $# >= 2 )); then - if [[ -d ${!#} ]]; then - local oldcwd=$PWD - cd "${!#}" # last arg - for x in "${@:1:$(( $# - 1 ))}"; do # all but last arg - # remove any trailing slashes, uses extglob - x="${x%%+(/)}" - # remove any leading directory components - x="${x##*/}" - [[ -e "$x" || -L "$x" ]] && $remove "$x" - done - cd "$oldcwd" - else - if ! mkdir -p "${!#}"; then - echo "lnf error: failed to make directory ${!#}" - return 1 - fi - fi - elif [[ $# -eq 1 ]]; then - [[ -e "${1##*/}" || -L "${1##*/}" ]] && $remove "${1##*/}" - fi - - $reset_extglob && shopt -u extglob - ln -s $nodir -- "$@" -} diff --git a/test/test b/test/test index d3a5eac..692938a 100755 --- a/test/test +++ b/test/test @@ -61,7 +61,8 @@ docases() { done } -source ${0%/*}/../lnf-function +PATH="$(readlink -f ${0%/*}/..):$PATH" + # might want to undo this if things go wrong # set -x @@ -69,12 +70,13 @@ source ${0%/*}/../lnf-function set -E; trap 'echo "${BASH_COMMAND:+BASH_COMMAND=\"$BASH_COMMAND\" } ${FUNCNAME:+FUNCNAME=\"$FUNCNAME\" }${LINENO:+LINENO=\"$LINENO\" }\$?=$?"' ERR -cd $(mktemp -d) +tempdir=$(mktemp -d) +cd $tempdir docases # test again, using rm -rf in place of trash-put. -# assumes that rm is in /bin and trash-put is in /usr/bin -PATH="${PATH//:\/usr\/bin}" -PATH="${PATH//\/usr\/bin:}" +trash-put() { rm -rf -- "$@"; } +export -f trash-put docases +rm -rf $tempdir echo tests concluded