mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 18:24:30 -04:00
Implement #1830 (Add Exherbo to http://calibre.kovidgoyal.net/download_linux (Get Calibre / Linux))
This commit is contained in:
parent
e7cc8d990d
commit
08615ee359
@ -1,26 +1,7 @@
|
|||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
import re
|
|
||||||
from pkg_resources import resource_filename
|
|
||||||
|
|
||||||
from trac.core import Component, implements
|
|
||||||
from trac.web.chrome import INavigationContributor, ITemplateProvider, add_stylesheet
|
|
||||||
from trac.web.main import IRequestHandler
|
|
||||||
from trac.util import Markup
|
|
||||||
|
|
||||||
|
|
||||||
__appname__ = 'calibre'
|
__appname__ = 'calibre'
|
||||||
DOWNLOAD_DIR = '/var/www/calibre.kovidgoyal.net/htdocs/downloads'
|
import re
|
||||||
MOBILEREAD = 'https://dev.mobileread.com/dist/kovid/calibre/'
|
|
||||||
|
|
||||||
class OS(dict):
|
|
||||||
"""Dictionary with a default value for unknown keys."""
|
|
||||||
def __init__(self, dict):
|
|
||||||
self.update(dict)
|
|
||||||
if not dict.has_key('img'):
|
|
||||||
self['img'] = self['name']
|
|
||||||
|
|
||||||
class Distribution(object):
|
|
||||||
|
|
||||||
DEPENDENCIES = [
|
DEPENDENCIES = [
|
||||||
#(Generic, version, gentoo, ubuntu, fedora)
|
#(Generic, version, gentoo, ubuntu, fedora)
|
||||||
@ -30,7 +11,7 @@ class Distribution(object):
|
|||||||
('libusb', '0.1.12', None, None, None),
|
('libusb', '0.1.12', None, None, None),
|
||||||
('Qt', '4.4.0', 'qt', 'libqt4-core libqt4-gui', 'qt4'),
|
('Qt', '4.4.0', 'qt', 'libqt4-core libqt4-gui', 'qt4'),
|
||||||
('PyQt', '4.4.2', 'PyQt4', 'python-qt4', 'PyQt4'),
|
('PyQt', '4.4.2', 'PyQt4', 'python-qt4', 'PyQt4'),
|
||||||
('mechanize for python', '0.1.11', 'dev-python/mechanize', 'python-mechanize', 'python-mechanize'),
|
('python-mechanize', '0.1.11', 'dev-python/mechanize', 'python-mechanize', 'python-mechanize'),
|
||||||
('ImageMagick', '6.3.5', 'imagemagick', 'imagemagick', 'ImageMagick'),
|
('ImageMagick', '6.3.5', 'imagemagick', 'imagemagick', 'ImageMagick'),
|
||||||
('xdg-utils', '1.0.2', 'xdg-utils', 'xdg-utils', 'xdg-utils'),
|
('xdg-utils', '1.0.2', 'xdg-utils', 'xdg-utils', 'xdg-utils'),
|
||||||
('dbus-python', '0.82.2', 'dbus-python', 'python-dbus', 'dbus-python'),
|
('dbus-python', '0.82.2', 'dbus-python', 'python-dbus', 'dbus-python'),
|
||||||
@ -40,51 +21,59 @@ class Distribution(object):
|
|||||||
('help2man', '1.36.4', 'help2man', 'help2man', 'help2man'),
|
('help2man', '1.36.4', 'help2man', 'help2man', 'help2man'),
|
||||||
]
|
]
|
||||||
|
|
||||||
DISTRO_MAP = {'gentoo':2, 'ubuntu':3, 'fedora':4, 'debian':3}
|
|
||||||
|
|
||||||
INSTALLERS = ('emerge -avn', 'apt-get install', 'yum install')
|
class CoolDistro:
|
||||||
AS_ROOT = (True, False, True)
|
|
||||||
|
|
||||||
TITLEMAP = {'gentoo':'Gentoo', 'ubuntu':'Ubuntu Intrepid Ibex',
|
def __init__(self, name, title, prefix=''):
|
||||||
'fedora':'Fedora 10', 'debian':'Debian sid', 'generic': 'Install from source'}
|
self.title = title
|
||||||
|
url = prefix + '/chrome/dl/images/%s_logo.png'
|
||||||
|
self.img = url%name
|
||||||
|
|
||||||
MANUAL_MAP = {
|
def get_linux_data(version='1.0.0'):
|
||||||
'fedora' : '''<li>You have to upgrade Qt to at least 4.4.0 and PyQt to at least 4.4.2</li>''',
|
data = {'version':version, 'app':__appname__}
|
||||||
}
|
data['title'] = 'Download calibre for linux'
|
||||||
|
data['supported'] = []
|
||||||
|
for name, title in [
|
||||||
|
('ubuntu', 'Ubuntu Jaunty Jackalope'),
|
||||||
|
('debian', 'Debian Sid'),
|
||||||
|
('exherbo', 'Exherbo'),
|
||||||
|
]:
|
||||||
|
data['supported'].append(CoolDistro(name, title,
|
||||||
|
prefix='http://calibre.kovidgoyal.net'))
|
||||||
|
data['dependencies'] = DEPENDENCIES
|
||||||
|
return data
|
||||||
|
|
||||||
def __init__(self, os):
|
if __name__ == '__main__':
|
||||||
self.os = os
|
import os
|
||||||
self.img = os
|
from calibre.utils.genshi.template import MarkupTemplate
|
||||||
self.title = self.TITLEMAP[os]
|
import cherrypy
|
||||||
self.app = __appname__
|
class Test:
|
||||||
self.is_generic = os == 'generic'
|
def index(self):
|
||||||
offset = 0
|
raw = open(os.path.dirname(os.path.abspath(__file__))+'/templates/download.html').read()
|
||||||
if not self.is_generic:
|
return MarkupTemplate(raw).generate(**get_linux_data()).render('xhtml')
|
||||||
index = self.DISTRO_MAP[self.os]
|
index.exposed = True
|
||||||
if os == 'debian':
|
t = Test()
|
||||||
self.as_root = True
|
t.index()
|
||||||
else: self.as_root = self.AS_ROOT[index-2]
|
cherrypy.quickstart(t)
|
||||||
prefix = ''
|
|
||||||
if not self.as_root: prefix = 'sudo '
|
|
||||||
cmd = prefix + self.INSTALLERS[index-2]
|
|
||||||
pre = ' \\\n '.ljust(len(cmd)+4)
|
|
||||||
for dep in self.DEPENDENCIES:
|
|
||||||
if len(cmd) > 70+offset:
|
|
||||||
offset += 70
|
|
||||||
cmd += pre
|
|
||||||
cmd += ' '
|
|
||||||
if dep[index]: cmd += dep[index]
|
|
||||||
self.command = cmd.strip()
|
|
||||||
easy_install = 'easy_install'
|
|
||||||
if os == 'debian':
|
|
||||||
easy_install = 'easy_install-2.5'
|
|
||||||
self.command += '\n'+prefix+easy_install+' -U calibre \n'+prefix+'calibre_postinstall'
|
|
||||||
try:
|
|
||||||
self.manual = Markup(self.MANUAL_MAP[os])
|
|
||||||
except KeyError:
|
|
||||||
self.manual = None
|
|
||||||
else:
|
else:
|
||||||
self.img = 'linux'
|
from pkg_resources import resource_filename
|
||||||
|
|
||||||
|
from trac.core import Component, implements
|
||||||
|
from trac.web.chrome import INavigationContributor, ITemplateProvider, add_stylesheet
|
||||||
|
from trac.web.main import IRequestHandler
|
||||||
|
from trac.util import Markup
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DOWNLOAD_DIR = '/var/www/calibre.kovidgoyal.net/htdocs/downloads'
|
||||||
|
MOBILEREAD = 'https://dev.mobileread.com/dist/kovid/calibre/'
|
||||||
|
|
||||||
|
class OS(dict):
|
||||||
|
"""Dictionary with a default value for unknown keys."""
|
||||||
|
def __init__(self, dict):
|
||||||
|
self.update(dict)
|
||||||
|
if not dict.has_key('img'):
|
||||||
|
self['img'] = self['name']
|
||||||
|
|
||||||
|
|
||||||
class Download(Component):
|
class Download(Component):
|
||||||
@ -130,12 +119,6 @@ class Download(Component):
|
|||||||
else:
|
else:
|
||||||
return self.linux_distro(req, os)
|
return self.linux_distro(req, os)
|
||||||
|
|
||||||
def linux_distro(self, req, os):
|
|
||||||
version = self.version_from_filename()
|
|
||||||
distro = Distribution(os)
|
|
||||||
data = dict(distro=distro,title=distro.title, version=version)
|
|
||||||
return 'distro.html', data, None
|
|
||||||
|
|
||||||
def top_level(self, req):
|
def top_level(self, req):
|
||||||
operating_systems = [
|
operating_systems = [
|
||||||
OS({'name' : 'windows', 'title' : 'Windows'}),
|
OS({'name' : 'windows', 'title' : 'Windows'}),
|
||||||
@ -212,16 +195,7 @@ select Install.</li>
|
|||||||
return 'binary.html', data, None
|
return 'binary.html', data, None
|
||||||
|
|
||||||
def linux(self, req):
|
def linux(self, req):
|
||||||
operating_systems = [
|
data = get_linux_data(version=self.version_from_filename())
|
||||||
OS({'name' : 'binary', 'title': 'Binary Installer'}),
|
|
||||||
OS({'name' : 'gentoo', 'title': 'Gentoo'}),
|
|
||||||
OS({'name' : 'ubuntu', 'title': 'Ubuntu'}),
|
|
||||||
OS({'name' : 'fedora', 'title': 'Fedora'}),
|
|
||||||
OS({'name' : 'debian', 'title': 'Debian'}),
|
|
||||||
OS({'name' : 'generic','title': 'Install from source', 'img':'linux'}),
|
|
||||||
]
|
|
||||||
data = dict(title='Choose linux distribution', width=100,
|
|
||||||
operating_systems=operating_systems, font_size='x-large', top_level=False)
|
|
||||||
return 'download.html', data, None
|
return 'download.html', data, None
|
||||||
|
|
||||||
|
|
||||||
@ -417,3 +391,4 @@ def main():
|
|||||||
subprocess.call(pi, shell=True)
|
subprocess.call(pi, shell=True)
|
||||||
return 0
|
return 0
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
@ -6,36 +6,142 @@
|
|||||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||||
<xi:include href="layout.html" />
|
<xi:include href="layout.html" />
|
||||||
<head>
|
<head>
|
||||||
<title>$title</title>
|
<title>${title}</title>
|
||||||
|
<style type="text/css">
|
||||||
|
.distro_type {
|
||||||
|
font-family: monospace;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: larger;
|
||||||
|
text-align: center;
|
||||||
|
border-bottom: solid 1pt black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
margin-left:2em;
|
||||||
|
border-left: solid 1pt black;
|
||||||
|
}
|
||||||
|
|
||||||
|
table#info {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-width: 1pt;
|
||||||
|
border-style: solid;
|
||||||
|
table-layout: fixed;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
table#dependencies {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-width: 0pt;
|
||||||
|
font-family:monospace;
|
||||||
|
}
|
||||||
|
.tdata {vertical-align: top;}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="ctxtnav" class="nav"></div>
|
<div id="ctxtnav" class="nav"></div>
|
||||||
<p py:if="not top_level">If you have a 64bit computer, or an outdated operating system, the distribution
|
|
||||||
specific installation may not work for you. In that case, first try the binary installer.
|
|
||||||
If that also does not work, your only recourse is to try to install from source. In order
|
|
||||||
to do that you will have to install all the dependencies as well as the -dev package of PyQt4.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div id="content" class="download">
|
<div id="content" class="download">
|
||||||
<h1>$title</h1>
|
<h1>${title}</h1>
|
||||||
<center>
|
<p>
|
||||||
<table cellspacing="40px">
|
The latest release of ${app} is ${version}. See the
|
||||||
<tr>
|
<a href="/wiki/Changelog">Changelog</a> for a list of new features.
|
||||||
<td style="text-align:center; font-size: ${font_size}" py:for="os in operating_systems">
|
</p>
|
||||||
<a href="download_${os['name']}" style="text-decoration:none; border:0;">
|
<p>
|
||||||
<img width="${width}" height="${width+20}" src="${href.chrome('/dl/images/%s_logo.png'%(os['img'],))}" />
|
${app} is available in the software repositories of the following
|
||||||
</a>
|
linux distributions:
|
||||||
<a href="download_${os['name']}" style="text-decoration:none; border:0">
|
<table id="info">
|
||||||
<br />
|
<col width="150" /><col width="*" />
|
||||||
${os['title']}
|
<tr class="distro_type">
|
||||||
</a>
|
<td class="left">Supported distributions</td>
|
||||||
|
<td class="right">Unsupported distributions</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="tdata">
|
||||||
|
<td class="left" style="overflow-y:scroll">
|
||||||
|
<div py:for="distro in supported"
|
||||||
|
style="text-align:center;margin-top:2ex;">
|
||||||
|
<div>
|
||||||
|
<img width="64px" height="64px"
|
||||||
|
src="${distro.img}" alt="${distro.title}" />
|
||||||
|
</div>
|
||||||
|
${distro.title}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="right">
|
||||||
|
<div style="margin-left:2em">
|
||||||
|
<h3>Binary install</h3>
|
||||||
|
<p>
|
||||||
|
${app} has a binary installer that has been
|
||||||
|
tested on a number of distributions on both
|
||||||
|
32-bit and 64-bit x86 machines. To install,
|
||||||
|
copy paste the following command into a terminal
|
||||||
|
and press Enter:
|
||||||
|
</p>
|
||||||
|
<pre class="wiki">
|
||||||
|
sudo python -c "import urllib2; exec urllib2.urlopen('http://calibre.kovidgoyal.net/download_linux_binary_installer').read(); main()"
|
||||||
|
</pre>
|
||||||
|
<h4>Note</h4>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
When running the command line utilities,
|
||||||
|
they will segfault after completion. This can
|
||||||
|
be ignored.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
You must have help2man and xdg-utils installed
|
||||||
|
on your system before running the installer.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3>Source install</h3>
|
||||||
|
<p>
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
Make sure your system has python ≥ ${dependencies[0][1]}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Install the various dependencies listed below
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Run the following commands in a terminal:
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<pre class="wiki">
|
||||||
|
wget -O- http://calibre.kovidgoyal.net/downloads/${app}-${version}.tar.gz | tar xvz
|
||||||
|
cd calibre*
|
||||||
|
python setup.py build && sudo python setup.py install
|
||||||
|
</pre>
|
||||||
|
Note that if your distribution does not have a
|
||||||
|
correctly compiled libunrar.so, ${app} will not
|
||||||
|
support rar files.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<br />
|
</p>
|
||||||
|
<p>
|
||||||
|
While you wait for the download to complete, please consider
|
||||||
|
donating to support the development of ${app}.
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
|
||||||
|
<input type="hidden" name="cmd" value="_s-xclick" />
|
||||||
|
<input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!" />
|
||||||
|
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1" />
|
||||||
|
<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----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-----END PKCS7-----" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
<h3>Dependencies</h3>
|
||||||
|
${app} has the following dependencies (the listed version is the minimum version)
|
||||||
|
<br/><br/>
|
||||||
|
<table id="dependencies">
|
||||||
|
<tr>
|
||||||
|
<th style="margin-right:2em">Package</th><th>Version</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
</center>
|
<tr class="dependency" py:for="dep in dependencies">
|
||||||
|
<td style="margin-right:2em">${dep[0]}</td><td>${dep[1]}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -58,7 +58,7 @@ class Checker(object):
|
|||||||
"specific sections. You must explicitly pass "
|
"specific sections. You must explicitly pass "
|
||||||
"application config via "
|
"application config via "
|
||||||
"cherrypy.tree.mount(..., config=app_config)")
|
"cherrypy.tree.mount(..., config=app_config)")
|
||||||
warnings.warn(msg)
|
warnings.warn(msg[:5])
|
||||||
return
|
return
|
||||||
|
|
||||||
def check_static_paths(self):
|
def check_static_paths(self):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user