Skip to content

Commit ddca079

Browse files
committed
Linux binary build: Create an uninstall script named calibre-uninstall
Fixes #1283154 [linux uninstaller (/usr/bin/calibre-uninstall)](https://bugs.launchpad.net/calibre/+bug/1283154)
1 parent 64cb14a commit ddca079

File tree

2 files changed

+106
-73
lines changed

2 files changed

+106
-73
lines changed

resources/calibre-mimetypes.xml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
3+
<mime-type type="application/x-sony-bbeb">
4+
<comment>SONY E-book compiled format</comment>
5+
<glob pattern="*.lrf"/>
6+
</mime-type>
7+
<mime-type type="application/epub+zip">
8+
<comment>EPUB ebook format</comment>
9+
<glob pattern="*.epub"/>
10+
</mime-type>
11+
<mime-type type="text/lrs">
12+
<comment>SONY E-book source format</comment>
13+
<glob pattern="*.lrs"/>
14+
</mime-type>
15+
<mime-type type="application/x-mobipocket-ebook">
16+
<comment>Amazon Mobipocket e-book format</comment>
17+
<sub-class-of type="application/x-palm-database"/>
18+
<glob pattern="*.azw"/>
19+
</mime-type>
20+
<mime-type type="application/x-topaz-ebook">
21+
<comment>Amazon Topaz ebook format</comment>
22+
<glob pattern="*.tpz"/>
23+
<glob pattern="*.azw1"/>
24+
</mime-type>
25+
<mime-type type="application/x-kindle-application">
26+
<comment>Amazon Kindle Application (Kindlet)</comment>
27+
<sub-class-of type="application/x-java-archive"/>
28+
<glob pattern="*.azw2"/>
29+
</mime-type>
30+
<mime-type type="application/x-mobipocket-subscription">
31+
<comment>Amazon Mobipocket ebook newspaper format</comment>
32+
<sub-class-of type="application/x-mobipocket-ebook"/>
33+
<!-- Technically, this depends on the cdeType (NWPR or MAGZ), but since EXTH headers have a variable length, it's tricky to probe via magic... -->
34+
<alias type="application/x-mobipocket-subscription-magazine"/>
35+
<glob pattern="*.pobi"/>
36+
</mime-type>
37+
<mime-type type="application/x-mobi8-ebook">
38+
<comment>Amazon KF8 ebook format</comment>
39+
<sub-class-of type="application/x-palm-database"/>
40+
<glob pattern="*.azw3"/>
41+
</mime-type>
42+
</mime-info>

src/calibre/linux.py

Lines changed: 64 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -84,42 +84,76 @@ def __exit__(self, *args):
8484
# Uninstall script {{{
8585
UNINSTALL = '''\
8686
#!{python}
87+
from __future__ import print_function, unicode_literals
8788
euid = {euid}
8889
8990
import os, subprocess, shutil
9091
91-
if os.geteuid() != euid:
92-
print 'WARNING: uninstaller must be run as', euid, 'to remove all files'
92+
try:
93+
raw_input
94+
except NameError:
95+
raw_input = input
9396
94-
for x in {manifest!r}:
95-
if not os.path.exists(x): continue
96-
print 'Removing', x
97+
if os.geteuid() != euid:
98+
print ('The installer was last run as user id:', euid, 'To remove all files you must run the uninstaller as the same user')
99+
if raw_input('Proceed anyway? [y/n]:').lower() != 'y':
100+
raise SystemExit(1)
101+
102+
frozen_path = {frozen_path!r}
103+
if not frozen_path or not os.path.exists(os.path.join(frozen_path, 'resources', 'calibre-mimetypes.xml')):
104+
frozen_path = None
105+
106+
for x in tuple({manifest!r}) + tuple({appdata_resources!r}) + (os.path.abspath(__file__), __file__, frozen_path):
107+
if not x or not os.path.exists(x):
108+
continue
109+
print ('Removing', x)
97110
try:
98111
if os.path.isdir(x):
99112
shutil.rmtree(x)
100113
else:
101114
os.unlink(x)
102115
except Exception as e:
103-
print 'Failed to delete', x
104-
print '\t', e
116+
print ('Failed to delete', x)
117+
print ('\t', e)
105118
106119
icr = {icon_resources!r}
107-
for context, name, size in icr:
120+
mimetype_icons = []
121+
122+
def remove_icon(context, name, size, update=False):
108123
cmd = ['xdg-icon-resource', 'uninstall', '--context', context, '--size', size, name]
109-
if (context, name) != icr[-1]:
124+
if not update:
110125
cmd.insert(2, '--noupdate')
126+
print ('Removing icon:', name, 'from context:', context, 'at size:', size)
111127
ret = subprocess.call(cmd)
112128
if ret != 0:
113-
print 'WARNING: Failed to remove icon', name
129+
print ('WARNING: Failed to remove icon', name)
130+
131+
for i, (context, name, size) in enumerate(icr):
132+
if context == 'mimetypes':
133+
mimetype_icons.append((name, size))
134+
continue
135+
remove_icon(context, name, size, update=i == len(icr) - 1)
114136
115137
mr = {menu_resources!r}
116138
for f in mr:
117139
cmd = ['xdg-desktop-menu', 'uninstall', f]
140+
print ('Removing desktop file:', f)
118141
ret = subprocess.call(cmd)
119142
if ret != 0:
120-
print 'WARNING: Failed to remove menu item', f
143+
print ('WARNING: Failed to remove menu item', f)
121144
122-
os.remove(os.path.abspath(__file__))
145+
for f in {mime_resources!r}:
146+
cmd = ['xdg-mime', 'uninstall', f]
147+
print ('Removing mime resource:', os.path.basename(f))
148+
ret = subprocess.call(cmd)
149+
if ret != 0:
150+
print ('WARNING: Failed to remove mime resource', f)
151+
152+
print ()
153+
154+
if mimetype_icons and raw_input('Remove the ebook format icons? [y/n]:').lower() in ['', 'y']:
155+
for i, (name, size) in enumerate(mimetype_icons):
156+
remove_icon('mimetypes', name, size, update=i == len(mimetype_icons) - 1)
123157
'''
124158

125159
# }}}
@@ -447,6 +481,7 @@ def __init__(self, opts, info=prints, warn=None, manifest=None):
447481
self.icon_resources = []
448482
self.menu_resources = []
449483
self.mime_resources = []
484+
self.appdata_resources = []
450485
if islinux or isbsd:
451486
self.setup_completion()
452487
if islinux or isbsd:
@@ -472,9 +507,12 @@ def __init__(self, opts, info=prints, warn=None, manifest=None):
472507

473508
def create_uninstaller(self):
474509
dest = os.path.join(self.opts.staging_bindir, 'calibre-uninstall')
475-
raw = UNINSTALL.format(python=os.path.abspath(sys.executable), euid=os.geteuid(),
476-
manifest=self.manifest, icon_resources=self.icon_resources,
477-
menu_resources=self.menu_resources)
510+
self.info('Creating un-installer:', dest)
511+
raw = UNINSTALL.format(
512+
python='/usr/bin/python', euid=os.geteuid(),
513+
manifest=self.manifest, icon_resources=self.icon_resources,
514+
mime_resources=self.mime_resources, menu_resources=self.menu_resources,
515+
appdata_resources=self.appdata_resources, frozen_path=getattr(sys, 'frozen_path', None))
478516
try:
479517
with open(dest, 'wb') as f:
480518
f.write(raw)
@@ -677,13 +715,13 @@ def setup_desktop_integration(self): # {{{
677715
self.icon_resources.append(('mimetypes', 'application-x-mobi8-ebook', '128'))
678716
render_img('lt.png', 'calibre-gui.png', width=256, height=256)
679717
cc('xdg-icon-resource install --noupdate --size 256 calibre-gui.png calibre-gui', shell=True)
680-
self.icon_resources.append(('apps', 'calibre-gui', '128'))
681-
render_img('viewer.png', 'calibre-viewer.png')
682-
cc('xdg-icon-resource install --size 128 calibre-viewer.png calibre-viewer', shell=True)
683-
self.icon_resources.append(('apps', 'calibre-viewer', '128'))
684-
render_img('tweak.png', 'calibre-ebook-edit.png')
685-
cc('xdg-icon-resource install --size 128 calibre-ebook-edit.png calibre-ebook-edit', shell=True)
686-
self.icon_resources.append(('apps', 'calibre-ebook-edit', '128'))
718+
self.icon_resources.append(('apps', 'calibre-gui', '256'))
719+
render_img('viewer.png', 'calibre-viewer.png', width=256, height=256)
720+
cc('xdg-icon-resource install --size 256 calibre-viewer.png calibre-viewer', shell=True)
721+
self.icon_resources.append(('apps', 'calibre-viewer', '256'))
722+
render_img('tweak.png', 'calibre-ebook-edit.png', width=256, height=256)
723+
cc('xdg-icon-resource install --size 256 calibre-ebook-edit.png calibre-ebook-edit', shell=True)
724+
self.icon_resources.append(('apps', 'calibre-ebook-edit', '256'))
687725

688726
mimetypes = set([])
689727
for x in all_input_formats():
@@ -731,13 +769,11 @@ def write_mimetypes(f):
731769
self.menu_resources.append(x)
732770
ak = x.partition('.')[0]
733771
if ak in APPDATA and os.access(appdata, os.W_OK):
734-
write_appdata(ak, APPDATA[ak], appdata, translators)
772+
self.appdata_resources.append(write_appdata(ak, APPDATA[ak], appdata, translators))
735773
cc(['xdg-desktop-menu', 'forceupdate'])
736-
f = open('calibre-mimetypes.xml', 'wb')
737-
f.write(MIME)
738-
f.close()
739-
self.mime_resources.append('calibre-mimetypes.xml')
740-
cc('xdg-mime install ./calibre-mimetypes.xml', shell=True)
774+
MIME = P('calibre-mimetypes.xml')
775+
self.mime_resources.append(MIME)
776+
cc(['xdg-mime', 'install', MIME])
741777
except Exception:
742778
if self.opts.fatal_errors:
743779
raise
@@ -972,51 +1008,6 @@ def write_appdata(key, entry, base, translators):
9721008
return fpath
9731009

9741010

975-
MIME = '''\
976-
<?xml version="1.0"?>
977-
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
978-
<mime-type type="application/x-sony-bbeb">
979-
<comment>SONY E-book compiled format</comment>
980-
<glob pattern="*.lrf"/>
981-
</mime-type>
982-
<mime-type type="application/epub+zip">
983-
<comment>EPUB ebook format</comment>
984-
<glob pattern="*.epub"/>
985-
</mime-type>
986-
<mime-type type="text/lrs">
987-
<comment>SONY E-book source format</comment>
988-
<glob pattern="*.lrs"/>
989-
</mime-type>
990-
<mime-type type="application/x-mobipocket-ebook">
991-
<comment>Amazon Mobipocket e-book format</comment>
992-
<sub-class-of type="application/x-palm-database"/>
993-
<glob pattern="*.azw"/>
994-
</mime-type>
995-
<mime-type type="application/x-topaz-ebook">
996-
<comment>Amazon Topaz ebook format</comment>
997-
<glob pattern="*.tpz"/>
998-
<glob pattern="*.azw1"/>
999-
</mime-type>
1000-
<mime-type type="application/x-kindle-application">
1001-
<comment>Amazon Kindle Application (Kindlet)</comment>
1002-
<sub-class-of type="application/x-java-archive"/>
1003-
<glob pattern="*.azw2"/>
1004-
</mime-type>
1005-
<mime-type type="application/x-mobipocket-subscription">
1006-
<comment>Amazon Mobipocket ebook newspaper format</comment>
1007-
<sub-class-of type="application/x-mobipocket-ebook"/>
1008-
<!-- Technically, this depends on the cdeType (NWPR or MAGZ), but since EXTH headers have a variable length, it's tricky to probe via magic... -->
1009-
<alias type="application/x-mobipocket-subscription-magazine"/>
1010-
<glob pattern="*.pobi"/>
1011-
</mime-type>
1012-
<mime-type type="application/x-mobi8-ebook">
1013-
<comment>Amazon KF8 ebook format</comment>
1014-
<sub-class-of type="application/x-palm-database"/>
1015-
<glob pattern="*.azw3"/>
1016-
</mime-type>
1017-
</mime-info>
1018-
'''
1019-
10201011
def render_img(image, dest, width=128, height=128):
10211012
from PyQt4.Qt import QImage, Qt
10221013
img = QImage(I(image)).scaled(width, height, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)

0 commit comments

Comments
 (0)