tools_erc 10.2 KB
Newer Older
1 2
#!/bin/bash
#
3 4
# Copyright (C) 2013-2015, 2017, 2020, 2023  Etersoft
# Copyright (C) 2013-2015, 2017, 2020, 2023  Vitaly Lipatov <lav@etersoft.ru>
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

PROGDIR=$(dirname $0)
[ "$PROGDIR" = "." ] && PROGDIR=$(pwd)

# will replaced to /usr/share/erc during install
SHAREDIR=$(dirname $0)

load_helper()
{
    local CMD="$SHAREDIR/$1"
    [ -r "$CMD" ] || fatal "Have no $CMD helper file"
    . $CMD
}

load_helper erc-sh-functions
load_helper erc-sh-archive

check_tty

# 1.zip tar:  -> 1.tar
build_target_name()
{
	is_target_format $2 && echo $(get_archive_name "$1").${2/:/} && return
	echo "$1"
        return 1
}

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

# TODO: list of $HAVE_7Z supported (see list_formats)

# target file1 [file2...]
create_archive()
{
	local arc="$1"
	shift
	if have_patool ; then
		docmd patool $verbose create "$arc" "$@"
		return
	fi

	# FIXME: get type by ext only
	local type="$(get_archive_type "$arc")"
	case "$type" in
62 63
		tar)
			#docmd $HAVE_7Z a -l $arc "$@"
64
			docmd tar cvf "$arc" "$@"
65
			;;
66
		*)
67
			# TODO: fix symlinks support
68 69
			# https://bugzilla.altlinux.org/49852
			# FIXME: creating .tar.* (.tar.gz) is not supported
70
			docmd $HAVE_7Z a -l "$arc" "$@"
71 72 73 74 75 76 77 78 79 80
			#fatal "Not yet supported creating of $type archives"
			;;
	esac
}

extract_archive()
{
	local arc="$1"
	shift

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
	local type="$(get_archive_type "$arc")"
	[ -n "$type" ] || fatal "Can't recognize type of $arc."

	# TODO: move to patool
	if [ "$type" = "exe" ] ; then
		docmd $HAVE_7Z x "$arc"
		exit
	fi

	if [ "$type" = "AppImage" ] || [ "$type" = "appimage" ] ; then
		docmd chmod u+x "$arc" || fatal "Can't set executable permission"
		docmd "$(realpath $arc)" --appimage-extract
		mv squashfs-root "$(basename "$(basename "$arc" .AppImage)" .appimage)"
		exit
	fi

97 98 99 100 101
	if have_patool ; then
        docmd patool $verbose extract "$arc" "$@"
		return
	fi

102
	arc="$(realpath -s "$arc")"
103 104
	tdir=$(mktemp -d $(pwd)/UXXXXXXXX) && cd "$tdir" || fatal

105
	local TSUBDIR="$(basename "$arc" .$type | sed -e 's|^tar\.||')"
106

107 108
	# TODO: check if there is only one file?
	# use subdir if there is no subdir in archive
109
	case "$type" in
110 111 112 113 114 115 116 117 118 119 120 121 122 123
		tar.gz|tgz)
			is_command gzip || fatal "Could not find gzip package. Please install gzip package and retry."
			extract_command "tar -xhzf" "$arc"
			;;
		tar.xz|txz|tar.lzma)
			is_command xz || fatal "Could not find xz package. Please install xz package and retry."
			extract_command "tar -xhJf" "$arc"
			;;
		tar.zst)
			is_command zstd || fatal "Could not find zstd package. Please install zstd package and retry."
			extract_command "tar -I zstd -xhf" "$arc"
			;;
		tar)
			extract_command "tar -xhf" "$arc"
124
			;;
125
		*)
126
			docmd $HAVE_7Z x -y "$arc" "$@"
127 128 129 130
			#fatal "Not yet supported extracting of $type archives"
			;;
	esac

131 132 133 134 135 136 137 138
	cd - >/dev/null
	# if only one dir in the subdir
	if [ -e "$(echo $tdir/*)" ] ; then
		mv $tdir/* .
		rmdir $tdir
	else
		mv $tdir "$TSUBDIR"
	fi
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
}

list_archive()
{
	local arc="$1"
	shift

	# TODO: move to patool
	if [ "$(get_archive_type "$arc" 2>/dev/null)" = "exe" ] ; then
		docmd $HAVE_7Z l "$arc" || fatal
		return
	fi

	if have_patool ; then
		docmd patool $verbose list "$arc" "$@"
		return
	fi

	local type="$(get_archive_type "$arc")"
	case "$type" in
		*)
160
			docmd $HAVE_7Z l "$arc" "$@"
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
			#fatal "Not yet supported listing of $type archives"
			;;
	esac

}

test_archive()
{
	local arc="$1"
	shift

	# TODO: move to patool
	if [ "$(get_archive_type "$arc" 2>/dev/null)" = "exe" ] ; then
		docmd $HAVE_7Z t "$arc" || fatal
		return
	fi

	if have_patool ; then
		docmd patool $verbose test "$arc" "$@"
		return
	fi

	local type="$(get_archive_type "$arc")"
	case "$type" in
		*)
186
			docmd $HAVE_7Z t "$arc" "$@"
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
			#fatal "Not yet supported test of $type archives"
			;;
	esac

}

repack_archive()
{
	if have_patool ; then
		docmd patool $verbose repack "$1" "$2"
		return
	fi

	# TODO: if both have tar, try unpack | pack

	local ftype="$(get_archive_type "$1")"
	local ttype="$(get_archive_type "$2")"
	case "$ftype-$ttype" in
205
		tar.*-tar|tgz-tar)
206 207 208 209 210 211 212 213 214
			docmd $HAVE_7Z x -so "$1" > "$2"
			;;
		tar-tar.*)
			docmd $HAVE_7Z a -si "$2" < "$1"
			;;
		tar.*-tar.*)
			docmd $HAVE_7Z x -so "$1" | $HAVE_7Z a -si "$2"
			;;
		*)
215
			fatal "Not yet supported repack of $ftype-$ttype archives in 7z mode (try install patool)"
216 217 218 219 220 221
			;;
	esac

}


222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
phelp()
{
	echo "$Descr
$Usage
 Commands:
$(get_help HELPCMD)

 Options:
$(get_help HELPOPT)

 Examples:
    # erc dir - pack dir to dirname.zip
    # erc a archive.zip file(s)... - pack files to archive.zip
    # erc [x] archive.zip - unpack
    # unerc archive.zip - unpack
237 238
    # erc [repack] archive1.zip... archive2.rar $HAVE_7Z: - repack all to $HAVE_7Z
    # erc -f [repack] archive.zip archive.$HAVE_7Z - force repack zip to $HAVE_7Z (override target in anyway)
239 240 241 242 243 244 245
    # erc file/dir zip: - pack file to zip
"
}

print_version()
{
        echo "Etersoft archive manager version @VERSION@"
246
        echo "Copyright (c) Etersoft 2013-2023"
247 248 249 250 251 252 253 254 255 256 257 258 259 260
        echo "This program may be freely redistributed under the terms of the GNU AGPLv3."
}

progname="${0##*/}"

Usage="Usage: $progname [options] [<command>] [params]..."
Descr="erc - universal archive manager"

progname="${0##*/}"


force=
target=
verbose=--verbose
261 262
use_7z=
use_patool=
263

264 265 266 267 268 269 270
if [ -z "$" ] ; then
    echo "Etersoft archive manager version @VERSION@" >&2
    echo "Run $0 --help to get help" >&2
    exit 1
fi

while [ -n "$1" ] ; do
271 272 273 274 275 276 277 278 279 280 281 282 283 284
case "$1" in
    -h|--help|help)       # HELPOPT: this help
        phelp
        exit
        ;;
    -V|--version)         # HELPOPT: print version
        print_version
        exit
        ;;
    -q|--quiet)           # HELPOPT: be silent
        verbose=
        ;;
    -f|--force)           # HELPOPT: override target
        force=-f
285
        ;;
286 287 288 289 290 291
    --use-patool)         # HELPOPT: force use patool as backend
        use_patool=1
        ;;
    --use-7z)             # HELPOPT: force use 7z as backend
        use_7z=1
        ;;
292 293 294 295 296
    -*)
        fatal "Unknown option '$1'"
        ;;
    *)
        break
297 298
        ;;
esac
299 300
shift
done
301

302 303
set_backend

304 305 306 307
cmd="$1"

eval lastarg=\${$#}

308 309 310 311 312 313 314 315 316
# Just printout help if run without args
if [ -z "$cmd" ] ; then
    print_version
    echo
    fatal "Run $ $progname --help for get help"
fi



317 318 319 320 321 322 323 324 325 326 327 328
# if the first arg is some archive, suggest extract
if get_archive_type "$cmd" 2>/dev/null >/dev/null ; then
    if is_target_format $lastarg ; then
        cmd=repack
    else
        cmd=extract
    fi
# erc dir (pack to zip by default)
elif [ -d "$cmd" ] && [ -z "$2" ] ; then
    cmd=pack
    target=$(basename "$1").zip
# erc dir zip:
329
elif test -r "$1" && is_target_format "$2" ; then
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
    cmd=pack
elif [ "$progname" = "unerc" ] ; then
    cmd=extract
else
    shift
fi


# TODO: Если программа-архиватор не установлена, предлагать установку с помощью epm

case $cmd in
    a|-a|create|pack|add)        # HELPCMD: create archive / add file(s) to archive
        # TODO: realize archive addition if already exist (and separate adding?)
        if [ -z "$target" ] && is_target_format $lastarg ; then
            [ $# = 2 ] || fatal "Need two args"
            target="$(build_target_name "$1" "$2")"
346 347
            # clear last arg
            set -- "${@:1:$(($#-1))}"
348
        fi
349 350 351 352
        [ -z "$target" ] && target="$1" && shift

        [ -e "$target" ] && [ -n "$force" ] && docmd rm -f "$target"
        create_archive "$target" "$@"
353 354
        ;;
    e|x|-e|-x|u|-u|extract|unpack)          # HELPCMD: extract files from archive
355
        extract_archive "$@"
356 357 358 359 360 361
        ;;
# TODO: implement deletion
#    d|delete)             # HELPCMD: delete file(s) from archive
#        docmd patool delete "$@"
#        ;;
    l|-l|list)               # HELPCMD: list archive contents
362
        list_archive "$@"
363 364
        ;;
    t|-t|test|check)         # HELPCMD: test for archive integrity
365
        test_archive "$@"
366 367 368 369 370 371 372 373 374
        ;;
    type)                 # HELPCMD: print type of archive
        get_archive_type "$1" || fatal "Can't recognize $1 as archive"
        ;;
    diff)                 # HELPCMD: compare two archive
        # check 2 arg
        docmd patool $verbose diff "$@"
        ;;
    b|-b|bench|benchmark)    # HELPCMD: do CPU benchmark
375 376 377
        #assure_cmd $HAVE_7Z
        # TODO: can be $HAVE_7Za?
        docmd $HAVE_7Z b
378 379 380 381 382 383 384 385 386 387 388
        ;;
    search|grep)               # HELPCMD: search in files from archive
        docmd patool $verbose search "$@"
        ;;
    repack|conv)          # HELPCMD: convert source archive to target
        # TODO: need repack remove source file?
        # TODO: check for 2 arg
        if ! is_target_format $lastarg ; then
            [ $# = 2 ] || fatal "Need two args"
            [ "$(realpath "$1")" = "$(realpath "$2")" ] && warning "Output file is the same as input" && exit
            [ -e "$2" ] && [ -n "$force" ] && docmd rm -f "$2"
389
            repack_archive "$1" "$2"
390 391 392 393 394 395 396 397 398
            exit
        fi

        # add support for target zip:
        for i in "$@" ; do
            [ "$i" = "$lastarg" ] && continue
            target="$(build_target_name "$i" "$lastarg")"
            [ "$(realpath "$1")" = "$(realpath "$target")" ] && warning "Output file is the same as input" && exit
            [ -e "$target" ] && [ -n "$force" ] && docmd rm -f "$target"
399
            repack_archive "$i" "$target" || exit
400 401 402 403 404
        done

        ;;
    formats)              # HELPCMD: lists supported archive formats
        # TODO: print allowed with current programs separately
405
        if [ -n "$verbose" ] && have_patool ; then
406 407 408 409 410 411 412 413 414 415 416 417
            docmd patool formats "$@"
            echo "Also we supports:"
            ( list_subformats ; list_extraformats ) | sed -e "s|^|  |"
        else
            list_formats
        fi
        ;;
    *)
        # TODO: If we have archive in parameter, just unpack it
        fatal "Unknown command $1"
        ;;
esac