Add support for shar and unshar.

This commit is contained in:
Bastian Kleineidam 2012-05-25 22:07:22 +02:00
parent 59a6975345
commit 14cfeb9607
9 changed files with 221 additions and 7 deletions

View File

@ -1,11 +1,12 @@
0.17 "" (released xx.xx.2012)
* Added support for Monkey's Audio Compressor handling APE (.ape) files.
* Added support for shorten handling SHN (.shn) files.
* Added support for flac handling FLAC (.flac) files.
* Added support for Monkey's Audio Compressor handling APE (.ape) archives.
* Added support for shorten handling SHN (.shn) archives.
* Added support for flac handling FLAC (.flac) archives.
* Added support for the BSD cpio and tar programs.
* Added support for lhasa handling LZH (.lzh, .lha) files.
* Added support for lcap handling CAB (.cab) files.
* Added support for lhasa handling LZH (.lzh, .lha) archives.
* Added support for lcap handling CAB (.cab) archives.
* Added support for shar handling SHAR (.shar) shell archives.
* Generate standalone Windows .exe and Linux .rpm installer.
* Initialize the internal MIME database correct on all platforms.
* Improved option compatibility for the ar, cpio and tar programs.

View File

@ -24,7 +24,7 @@ ArchiveCommands = ('list', 'extract', 'test', 'create')
# Supported archive formats
ArchiveFormats = ('7z', 'ace', 'alzip', 'ape', 'ar', 'arc', 'arj', 'bzip2',
'cab', 'compress', 'cpio', 'deb', 'dms', 'flac', 'gzip', 'lrzip', 'lzh',
'lzip', 'lzma', 'lzop', 'rar', 'rpm', 'rzip', 'shn', 'tar', 'xz',
'lzip', 'lzma', 'lzop', 'rar', 'rpm', 'rzip', 'shar', 'shn', 'tar', 'xz',
'zip', 'zoo')
# Supported compressions (used with tar for example)
@ -64,6 +64,7 @@ ArchiveMimetypes = {
'application/x-rzip': 'rzip',
'application/x-zoo': 'zoo',
'application/x-dms': 'dms',
'application/x-shar': 'shar',
'audio/x-ape': 'ape',
'audio/x-shn': 'shn',
'audio/flac': 'flac',
@ -127,7 +128,7 @@ ArchivePrograms = {
'create': ('zip',),
},
'gzip': {
None: ('pigz', 'gzip', '7z', '7za'),
None: ('7z', '7za', 'pigz', 'gzip'),
'extract': ('py_gzip',),
'create': ('py_gzip',),
},
@ -198,6 +199,10 @@ ArchivePrograms = {
'list': ('py_echo',),
'create': ('rzip',),
},
'shar': {
'create': ('shar',),
'extract': ('unshar',),
},
'shn': {
'extract': ('shorten',),
'list': ('py_echo',),

26
patoolib/programs/shar.py Normal file
View File

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2012 Bastian Kleineidam
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Archive commands for the shar program."""
from patoolib import util
def create_shar (archive, compression, cmd, *args, **kwargs):
"""Create a SHAR archive."""
cmdlist = [util.shell_quote(cmd)]
if not kwargs['verbose']:
cmdlist.append('-q')
cmdlist.extend([util.shell_quote(x) for x in args])
cmdlist.extend(['>', util.shell_quote(archive)])
return (cmdlist, {'shell': True})

View File

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2012 Bastian Kleineidam
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Archive commands for the unshar program."""
import os
def extract_shar (archive, compression, cmd, **kwargs):
"""Extract a SHAR archive."""
cmdlist = [cmd, os.path.abspath(archive)]
return (cmdlist, {'cwd': kwargs['outdir']})

View File

@ -64,6 +64,7 @@ def add_mimedb_data(mimedb):
add_mimetype(mimedb, 'application/x-zoo', '.zoo')
add_mimetype(mimedb, 'application/x-dms', '.dms')
add_mimetype(mimedb, 'application/x-zip-compressed', '.crx')
add_mimetype(mimedb, 'application/x-shar', '.shar')
add_mimetype(mimedb, 'audio/x-ape', '.ape')
add_mimetype(mimedb, 'audio/x-shn', '.shn')
add_mimetype(mimedb, 'audio/flac', '.flac')

View File

@ -175,6 +175,8 @@ class ArchiveTest (unittest.TestCase):
command = 'list'
elif self.program == 'lcab':
program = 'cabextract'
elif self.program == 'shar':
return
patoolib._handle_archive(archive, command, program=program)
def check_created_archive_with_diff(self, archive, srcfile):
@ -191,6 +193,8 @@ class ArchiveTest (unittest.TestCase):
program = 'unzip'
elif self.program == 'lcab':
program = 'cabextract'
elif self.program == 'shar':
program = 'unshar'
tmpdir = patoolib.util.tmpdir(dir=basedir)
try:
olddir = os.getcwd()

144
tests/data/t.shar Normal file
View File

@ -0,0 +1,144 @@
#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.11).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `#!/bin/sh' line above, then type `sh FILE'.
#
lock_dir=_sh09682
#
# Existing files will *not* be overwritten, unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 2 -rw-r--r-- t.txt
#
MD5SUM=${MD5SUM-md5sum}
f=`${MD5SUM} --version | egrep '^md5sum .*(core|text)utils'`
test -n "${f}" && md5check=true || md5check=false
${md5check} || \
echo 'Note: not verifying md5sums. Consider installing GNU coreutils.'
if test "X$1" = "X-c"
then keep_file=''
else keep_file=true
fi
echo=echo
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=
locale_dir=
set_echo=false
for dir in $PATH
do
if test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
case `$dir/gettext --version 2>&1 | sed 1q` in
*GNU*) gettext_dir=$dir
set_echo=true
break ;;
esac
fi
done
if ${set_echo}
then
set_echo=false
for dir in $PATH
do
if test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
set_echo=true
break
fi
done
if ${set_echo}
then
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
fi
IFS="$save_IFS"
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null
then if (echo -n test; echo 1,2,3) | grep n >/dev/null
then shar_n= shar_c='
'
else shar_n=-n shar_c= ; fi
else shar_n= shar_c='\c' ; fi
f=shar-touch.$$
st1=200112312359.59
st2=123123592001.59
st2tr=123123592001.5 # old SysV 14-char limit
st3=1231235901
if touch -am -t ${st1} ${f} >/dev/null 2>&1 && \
test ! -f ${st1} && test -f ${f}; then
shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
elif touch -am ${st2} ${f} >/dev/null 2>&1 && \
test ! -f ${st2} && test ! -f ${st2tr} && test -f ${f}; then
shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
elif touch -am ${st3} ${f} >/dev/null 2>&1 && \
test ! -f ${st3} && test -f ${f}; then
shar_touch='touch -am $3$4$5$6$2 "$8"'
else
shar_touch=:
echo
${echo} 'WARNING: not restoring timestamps. Consider getting and
installing GNU `touch'\'', distributed in GNU coreutils...'
echo
fi
rm -f ${st1} ${st2} ${st2tr} ${st3} ${f}
#
if test ! -d ${lock_dir} ; then :
else ${echo} "lock directory ${lock_dir} exists"
exit 1
fi
if mkdir ${lock_dir}
then ${echo} "x - created lock directory ${lock_dir}."
else ${echo} "x - failed to create lock directory ${lock_dir}."
exit 1
fi
# ============= t.txt ==============
if test -n "${keep_file}" && test -f 't.txt'
then
${echo} "x - SKIPPING t.txt (file already exists)"
else
${echo} "x - extracting t.txt (binary)"
sed 's/^X//' << 'SHAR_EOF' | uudecode &&
begin 600 t.txt
"-#)B
`
end
SHAR_EOF
(set 20 12 05 25 20 11 37 't.txt'
eval "${shar_touch}") && \
chmod 0644 't.txt'
if test $? -ne 0
then ${echo} "restore of t.txt failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 't.txt': 'MD5 check failed'
) << \SHAR_EOF
a1d0c6e83f027327d8461063f4ac58a6 t.txt
SHAR_EOF
else
test `LC_ALL=C wc -c < 't.txt'` -ne 2 && \
${echo} "restoration warning: size of 't.txt' is not 2"
fi
fi
if rm -fr ${lock_dir}
then ${echo} "x - removed lock directory ${lock_dir}."
else ${echo} "x - failed to remove lock directory ${lock_dir}."
exit 1
fi
exit 0

View File

@ -514,3 +514,13 @@ class TestArchives (ArchiveTest):
self.archive_extract('t.flac', check=None)
self.archive_test('t.flac')
self.archive_create('t.flac', srcfile="t.wav")
@needs_program('shar')
def test_shar (self):
self.program = 'shar'
self.archive_create('t.shar', singlefile=True)
@needs_program('unshar')
def test_unshar (self):
self.program = 'unshar'
self.archive_extract('t.shar', check=None)

View File

@ -190,6 +190,7 @@ class TestMime (unittest.TestCase):
self.mime_test_mimedb("t.rz", "application/x-rzip", None)
self.mime_test_mimedb("t.zoo", "application/x-zoo", None)
self.mime_test_mimedb("t.dms", "application/x-dms", None)
self.mime_test_mimedb("t.shar", "application/x-shar", None)
self.mime_test_mimedb("t.ape", "audio/x-ape", None)
self.mime_test_mimedb("t.shn", "audio/x-shn", None)
self.mime_test_mimedb("t.flac", "audio/flac", None)