diff --git a/setup/installer/__init__.py b/setup/installer/__init__.py index 4ebfb35cc7..edd5150606 100644 --- a/setup/installer/__init__.py +++ b/setup/installer/__init__.py @@ -1,9 +1,8 @@ #!/usr/bin/env python2 # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai -from __future__ import (unicode_literals, division, absolute_import, - print_function) +from __future__ import (unicode_literals, division, absolute_import, print_function) -__license__ = 'GPL v3' +__license__ = 'GPL v3' __copyright__ = '2009, Kovid Goyal ' __docformat__ = 'restructuredtext en' @@ -15,27 +14,34 @@ from setup.build_environment import BUILD_HOST, PROJECT BASE_RSYNC = ['rsync', '-av', '--delete', '--force'] EXCLUDES = [] for x in [ - '/src/calibre/plugins', '/manual', '/translations', '/build', '/dist', '/imgsrc', '/format_docs', '/.build-cache', - '.bzr', '.git', '.build', '.svn', '*.pyc', '*.pyo', '*.swp', '*.swo', '*.pyj-cached']: + '/src/calibre/plugins', '/manual', '/translations', '/build', '/dist', '/imgsrc', + '/format_docs', '/.build-cache', '.bzr', '.git', '.build', '.svn', '*.pyc', + '*.pyo', '*.swp', '*.swo', '*.pyj-cached' +]: EXCLUDES.extend(['--exclude', ('/calibre' + x) if x.startswith('/') else x]) -SAFE_EXCLUDES = ['"%s"'%x if '*' in x else x for x in EXCLUDES] +SAFE_EXCLUDES = ['"%s"' % x if '*' in x else x for x in EXCLUDES] + def get_rsync_pw(): - return open('/home/kovid/work/env/private/buildbot').read().decode('utf-8').partition( - ':')[-1].strip() + return open(os.environ['PENV'] + '/buildbot' + ).read().decode('utf-8').partition(':')[-1].strip() + def is_vm_running(name): qname = '"%s"' % name try: - lines = subprocess.check_output('VBoxManage list runningvms'.split()).decode('utf-8').splitlines() + lines = subprocess.check_output('VBoxManage list runningvms'.split() + ).decode('utf-8').splitlines() except Exception: time.sleep(1) - lines = subprocess.check_output('VBoxManage list runningvms'.split()).decode('utf-8').splitlines() + lines = subprocess.check_output('VBoxManage list runningvms'.split() + ).decode('utf-8').splitlines() for line in lines: if line.startswith(qname): return True return False + def is_host_reachable(name, timeout=1): try: socket.create_connection((name, 22), timeout).close() @@ -43,12 +49,15 @@ def is_host_reachable(name, timeout=1): except: return False + class Rsync(Command): description = 'Sync source tree from development machine' - SYNC_CMD = ' '.join(BASE_RSYNC+SAFE_EXCLUDES+ - ['rsync://buildbot@{host}/work/{project}', '..']) + SYNC_CMD = ' '.join( + BASE_RSYNC + SAFE_EXCLUDES + + ['rsync://buildbot@{host}/work/{project}', '..'] + ) def run(self, opts): cmd = self.SYNC_CMD.format(host=BUILD_HOST, project=PROJECT) @@ -57,6 +66,7 @@ class Rsync(Command): self.info(cmd) subprocess.check_call(cmd, shell=True, env=env) + def push(host, vmname, available): if vmname is None: hostname = host.partition(':')[0].partition('@')[-1] @@ -66,9 +76,10 @@ def push(host, vmname, available): if ok: available[vmname or host] = True rcmd = BASE_RSYNC + EXCLUDES + ['.', host] - print ('\n\nPushing to:', vmname or host, '\n') + print('\n\nPushing to:', vmname or host, '\n') subprocess.check_call(rcmd, stdout=open(os.devnull, 'wb')) + class Push(Command): description = 'Push code to another host' @@ -77,21 +88,24 @@ class Push(Command): from threading import Thread threads, available = {}, {} for host, vmname in { - r'Owner@winxp:/cygdrive/c/Documents\ and\ Settings/Owner/calibre':'winxp', - 'kovid@ox:calibre':None, - r'kovid@win7:/cygdrive/c/Users/kovid/calibre':'Windows 7', - 'kovid@win7-x64:calibre':'win7-x64', - 'kovid@tiny:calibre':None, - 'kovid@getafix:calibre-src':None, - }.iteritems(): - threads[vmname or host] = thread = Thread(target=push, args=(host, vmname, available)) - thread.start() + r'Owner@winxp:/cygdrive/c/Documents\ and\ Settings/Owner/calibre': + 'winxp', + 'kovid@ox:calibre': None, + r'kovid@win7:/cygdrive/c/Users/kovid/calibre': 'Windows 7', + 'kovid@win7-x64:calibre': 'win7-x64', + 'kovid@tiny:calibre': None, + 'kovid@getafix:calibre-src': None, + }.iteritems(): + threads[vmname or host] = thread = Thread( + target=push, args=(host, vmname, available) + ) + thread.start() while threads: for name, thread in tuple(threads.iteritems()): thread.join(0.01) if not thread.is_alive(): if available.get(name, False): - print ('\n\n', name, 'done') + print('\n\n', name, 'done') threads.pop(name) @@ -105,22 +119,36 @@ class VMInstaller(Command): IS_64_BIT = False BUILD_PREFIX = ['#!/bin/sh', 'export CALIBRE_BUILDBOT=1'] - BUILD_RSYNC = ['mkdir -p ~/build/{project}', r'cd ~/build/{project}', Rsync.SYNC_CMD] - BUILD_CLEAN = ['rm -rf dist/* build/* src/calibre/plugins/*'] - BUILD_BUILD = ['python setup.py build',] + BUILD_RSYNC = [ + 'mkdir -p ~/build/{project}', r'cd ~/build/{project}', Rsync.SYNC_CMD + ] + BUILD_CLEAN = ['rm -rf dist/* build/* src/calibre/plugins/*'] + BUILD_BUILD = [ + 'python setup.py build', + ] FORCE_SHUTDOWN = 0 # number of seconds to wait before doing a forced power off (0 means disabled) def add_options(self, parser): if not parser.has_option('--dont-shutdown'): - parser.add_option('-s', '--dont-shutdown', default=False, - action='store_true', help='Dont shutdown the VM after building') + parser.add_option( + '-s', + '--dont-shutdown', + default=False, + action='store_true', + help='Dont shutdown the VM after building' + ) if not parser.has_option('--dont-strip'): - parser.add_option('-x', '--dont-strip', default=False, - action='store_true', help='Dont strip the generated binaries') + parser.add_option( + '-x', + '--dont-strip', + default=False, + action='store_true', + help='Dont strip the generated binaries' + ) def get_build_script(self): - rs = ['export RSYNC_PASSWORD=%s'%get_rsync_pw()] - ans = '\n'.join(self.BUILD_PREFIX + rs)+'\n\n' + rs = ['export RSYNC_PASSWORD=%s' % get_rsync_pw()] + ans = '\n'.join(self.BUILD_PREFIX + rs) + '\n\n' ans += ' && \\\n'.join(self.BUILD_RSYNC) + ' && \\\n' ans += ' && \\\n'.join(self.BUILD_CLEAN) + ' && \\\n' ans += ' && \\\n'.join(self.BUILD_BUILD) + ' && \\\n' @@ -131,7 +159,9 @@ class VMInstaller(Command): def run_vm(self): if is_vm_running(self.VM_NAME): return True - self.__p = subprocess.Popen(("VBoxManage startvm %s --type gui" % self.VM_NAME).split()) + self.__p = subprocess.Popen( + ("VBoxManage startvm %s --type gui" % self.VM_NAME).split() + ) return False def start_vm(self, sleep=75): @@ -139,20 +169,23 @@ class VMInstaller(Command): already_running = self.run_vm() if not already_running: time.sleep(2) - print ('Waiting for SSH server to start') + print('Waiting for SSH server to start') while not is_host_reachable(ssh_host, timeout=1): time.sleep(0.1) def run_vm_builder(self): ssh_host = self.VM_NAME build_script = self.get_build_script() - build_script = build_script.encode('utf-8') if isinstance(build_script, unicode) else build_script - print ('Running VM builder') + build_script = build_script.encode('utf-8') if isinstance( + build_script, unicode + ) else build_script + print('Running VM builder') p = subprocess.Popen(['ssh', ssh_host, 'bash -s'], stdin=subprocess.PIPE) p.stdin.write(build_script), p.stdin.flush(), p.stdin.close() # Save the build script on the build machine for convenient manual # invocation, if needed - p2 = subprocess.Popen(['ssh', ssh_host, 'cat > build-calibre'], stdin=subprocess.PIPE) + p2 = subprocess.Popen(['ssh', ssh_host, 'cat > build-calibre'], + stdin=subprocess.PIPE) p2.stdin.write(build_script), p2.stdin.flush(), p2.stdin.close() p2.wait() rc = p.wait() @@ -172,27 +205,29 @@ class VMInstaller(Command): startup_time = time.time() - start_time start_time = time.time() self.run_vm_builder() - print ('Startup completed in %d seconds' % round(startup_time)) + print('Startup completed in %d seconds' % round(startup_time)) secs = time.time() - start_time - print ('Build completed in %d minutes %d seconds' % (secs // 60, secs % 60)) + print('Build completed in %d minutes %d seconds' % (secs // 60, secs % 60)) if not opts.dont_shutdown: - print ('Shutting down', self.VM_NAME) - subprocess.call(['ssh', self.VM_NAME]+self.SHUTDOWN_CMD) + print('Shutting down', self.VM_NAME) + subprocess.call(['ssh', self.VM_NAME] + self.SHUTDOWN_CMD) if self.FORCE_SHUTDOWN: while is_host_reachable(self.VM_NAME): time.sleep(0.1) # wait for SSH server to shutdown time.sleep(self.FORCE_SHUTDOWN) - subprocess.check_call(('VBoxManage controlvm %s poweroff' % self.VM_NAME).split()) + subprocess.check_call( + ('VBoxManage controlvm %s poweroff' % self.VM_NAME).split() + ) def download_installer(self): installer = self.installer() - subprocess.check_call(['scp', - self.VM_NAME+':build/calibre/'+installer, 'dist']) + subprocess.check_call([ + 'scp', self.VM_NAME + ':build/calibre/' + installer, 'dist' + ]) if not os.path.exists(installer): - raise SystemExit('Failed to download installer: '+installer) + raise SystemExit('Failed to download installer: ' + installer) def clean(self): installer = self.installer() if os.path.exists(installer): os.remove(installer) - diff --git a/setup/upload.py b/setup/upload.py index c2f6221016..99094f4e79 100644 --- a/setup/upload.py +++ b/setup/upload.py @@ -1,7 +1,7 @@ #!/usr/bin/env python2 # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai -__license__ = 'GPL v3' +__license__ = 'GPL v3' __copyright__ = '2009, Kovid Goyal ' __docformat__ = 'restructuredtext en' @@ -18,20 +18,24 @@ from setup import Command, __version__, installer_name, __appname__ DOWNLOADS = '/srv/main/downloads' HTML2LRF = "calibre/ebooks/lrf/html/demo" -TXT2LRF = "src/calibre/ebooks/lrf/txt/demo" +TXT2LRF = "src/calibre/ebooks/lrf/txt/demo" STAGING_HOST = 'download.calibre-ebook.com' STAGING_USER = 'root' STAGING_DIR = '/root/staging' + def installers(include_source=True): installers = list(map(installer_name, ('dmg', 'msi', 'txz'))) installers.append(installer_name('txz', is64bit=True)) installers.append(installer_name('msi', is64bit=True)) if include_source: - installers.insert(0, 'dist/%s-%s.tar.xz'%(__appname__, __version__)) - installers.append('dist/%s-portable-installer-%s.exe'%(__appname__, __version__)) + installers.insert(0, 'dist/%s-%s.tar.xz' % (__appname__, __version__)) + installers.append( + 'dist/%s-portable-installer-%s.exe' % (__appname__, __version__) + ) return installers + def installer_description(fname): if fname.endswith('.tar.xz'): return 'Source code' @@ -39,13 +43,14 @@ def installer_description(fname): bits = '32' if 'i686' in fname else '64' return bits + 'bit Linux binary' if fname.endswith('.msi'): - return 'Windows %sinstaller'%('64bit ' if '64bit' in fname else '') + return 'Windows %sinstaller' % ('64bit ' if '64bit' in fname else '') if fname.endswith('.dmg'): return 'OS X dmg' if fname.endswith('.exe'): return 'Calibre Portable' return 'Unknown file' + def upload_signatures(): tdir = mkdtemp() scp = ['scp'] @@ -53,22 +58,28 @@ def upload_signatures(): for installer in installers(): if not os.path.exists(installer): continue - sig = os.path.join(tdir, os.path.basename(installer+'.sig')) + sig = os.path.join(tdir, os.path.basename(installer + '.sig')) scp.append(sig) - check_call([os.path.expanduser('~/work/env/private/gpg-as-kovid'), '--output', sig, '--detach-sig', installer]) + check_call([ + os.environ['PENV'] + '/gpg-as-kovid', '--output', sig, + '--detach-sig', installer + ]) with open(installer, 'rb') as f: raw = f.read() fingerprint = hashlib.sha512(raw).hexdigest() - sha512 = os.path.join(tdir, os.path.basename(installer+'.sha512')) + sha512 = os.path.join(tdir, os.path.basename(installer + '.sha512')) with open(sha512, 'wb') as f: f.write(fingerprint) scp.append(sha512) for srv in 'code main'.split(): check_call(scp + ['{0}:/srv/{0}/signatures/'.format(srv)]) - check_call(['ssh', srv, 'chown', '-R', 'http:http', '/srv/%s/signatures' % srv]) + check_call( + ['ssh', srv, 'chown', '-R', 'http:http', '/srv/%s/signatures' % srv] + ) finally: shutil.rmtree(tdir) + class ReUpload(Command): # {{{ description = 'Re-upload any installers present in dist/' @@ -79,51 +90,69 @@ class ReUpload(Command): # {{{ opts.replace = True exists = {x for x in installers() if os.path.exists(x)} if not exists: - print ('There appear to be no installers!') + print('There appear to be no installers!') raise SystemExit(1) def run(self, opts): for x in installers(): if os.path.exists(x): os.remove(x) + + # }}} + # Data {{{ def get_github_data(): - with open(os.path.expanduser('~/work/env/private/github'), 'rb') as f: + with open(os.environ['PENV'] + '/github', 'rb') as f: un, pw = f.read().strip().split(':') - return { - 'username':un, 'password':pw - } + return {'username': un, 'password': pw} + def get_sourceforge_data(): - return {'username':'kovidgoyal', 'project':'calibre'} + return {'username': 'kovidgoyal', 'project': 'calibre'} + def get_fosshub_data(): - with open(os.path.expanduser('~/work/env/private/fosshub'), 'rb') as f: + with open(os.environ['PENV'] + '/fosshub', 'rb') as f: return f.read().decode('utf-8') + def send_data(loc): - subprocess.check_call(['rsync', '--inplace', '--delete', '-r', '-z', '-h', '--progress', '-e', 'ssh -x', - loc+'/', '%s@%s:%s'%(STAGING_USER, STAGING_HOST, STAGING_DIR)]) + subprocess.check_call([ + 'rsync', '--inplace', '--delete', '-r', '-z', '-h', '--progress', '-e', + 'ssh -x', loc + '/', '%s@%s:%s' % (STAGING_USER, STAGING_HOST, STAGING_DIR) + ]) + def gh_cmdline(ver, data): - return [__appname__, ver, 'fmap', 'github', __appname__, data['username'], data['password']] + return [ + __appname__, ver, 'fmap', 'github', __appname__, data['username'], + data['password'] + ] + def sf_cmdline(ver, sdata): - return [__appname__, ver, 'fmap', 'sourceforge', sdata['project'], - sdata['username']] + return [ + __appname__, ver, 'fmap', 'sourceforge', sdata['project'], sdata['username'] + ] + def calibre_cmdline(ver): return [__appname__, ver, 'fmap', 'calibre'] + def run_remote_upload(args): print 'Running remotely:', ' '.join(args) - subprocess.check_call(['ssh', '-x', '%s@%s'%(STAGING_USER, STAGING_HOST), - 'cd', STAGING_DIR, '&&', 'python2', 'hosting.py']+args) + subprocess.check_call([ + 'ssh', '-x', '%s@%s' % (STAGING_USER, STAGING_HOST), 'cd', STAGING_DIR, '&&', + 'python2', 'hosting.py' + ] + args) + # }}} + def upload_to_fosshub(): # fosshub has no API to do partial uploads, so we always upload all files. print('Sending upload request to fosshub...') @@ -131,34 +160,60 @@ def upload_to_fosshub(): entries = [] for fname in files: desc = installer_description(fname) - url = 'https://download.calibre-ebook.com/%s/%s' % (__version__, os.path.basename(fname)) + url = 'https://download.calibre-ebook.com/%s/%s' % ( + __version__, os.path.basename(fname) + ) entries.append({ - 'url':url, + 'url': url, 'type': desc, 'version': __version__, }) - jq = {'software': 'Calibre', 'apiKey':get_fosshub_data(), 'upload':entries, 'delete':[{'type':'*', 'version':'*', 'name':'*'}]} + jq = { + 'software': 'Calibre', + 'apiKey': get_fosshub_data(), + 'upload': entries, + 'delete': [{ + 'type': '*', + 'version': '*', + 'name': '*' + }] + } # print(json.dumps(jq, indent=2)) - rq = urllib2.urlopen('https://www.fosshub.com/JSTools/uploadJson', urllib.urlencode({'content':json.dumps(jq)})) + rq = urllib2.urlopen( + 'https://www.fosshub.com/JSTools/uploadJson', + urllib.urlencode({ + 'content': json.dumps(jq) + }) + ) resp = rq.read() if rq.getcode() != httplib.OK: - raise SystemExit('Failed to upload to fosshub, with HTTP error code: %d and response: %s' % (rq.getcode(), resp)) + raise SystemExit( + 'Failed to upload to fosshub, with HTTP error code: %d and response: %s' + % (rq.getcode(), resp) + ) class UploadInstallers(Command): # {{{ def add_options(self, parser): - parser.add_option('--replace', default=False, action='store_true', help='Replace existing installers') + parser.add_option( + '--replace', + default=False, + action='store_true', + help='Replace existing installers' + ) def run(self, opts): # return upload_to_fosshub() all_possible = set(installers()) available = set(glob.glob('dist/*')) - files = {x:installer_description(x) for x in - all_possible.intersection(available)} + files = { + x: installer_description(x) + for x in all_possible.intersection(available) + } for x in files: - os.chmod(x, stat.S_IRUSR|stat.S_IWUSR|stat.S_IRGRP|stat.S_IROTH) - sizes = {os.path.basename(x):os.path.getsize(x) for x in files} + os.chmod(x, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH) + sizes = {os.path.basename(x): os.path.getsize(x) for x in files} self.record_sizes(sizes) tdir = mkdtemp() backup = os.path.join('/mnt/external/calibre/%s' % __version__) @@ -177,25 +232,31 @@ class UploadInstallers(Command): # {{{ shutil.rmtree(tdir, ignore_errors=True) def record_sizes(self, sizes): - print ('\nRecording dist sizes') - args = ['%s:%s:%s' % (__version__, fname, size) for fname, size in sizes.iteritems()] + print('\nRecording dist sizes') + args = [ + '%s:%s:%s' % (__version__, fname, size) + for fname, size in sizes.iteritems() + ] check_call(['ssh', 'code', '/usr/local/bin/dist_sizes'] + args) def upload_to_staging(self, tdir, backup, files): - os.mkdir(tdir+'/dist') - hosting = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'hosting.py') + os.mkdir(tdir + '/dist') + hosting = os.path.join( + os.path.dirname(os.path.abspath(__file__)), 'hosting.py' + ) shutil.copyfile(hosting, os.path.join(tdir, 'hosting.py')) for f in files: - for x in (tdir+'/dist', backup): + for x in (tdir + '/dist', backup): dest = os.path.join(x, os.path.basename(f)) shutil.copy2(f, x) - os.chmod(dest, stat.S_IREAD|stat.S_IWRITE|stat.S_IRGRP|stat.S_IROTH) + os.chmod( + dest, stat.S_IREAD | stat.S_IWRITE | stat.S_IRGRP | stat.S_IROTH + ) with open(os.path.join(tdir, 'fmap'), 'wb') as fo: for f, desc in files.iteritems(): - fo.write('%s: %s\n'%(f, desc)) + fo.write('%s: %s\n' % (f, desc)) while True: try: @@ -221,8 +282,10 @@ class UploadInstallers(Command): # {{{ def upload_to_calibre(self): run_remote_upload(calibre_cmdline(__version__)) + # }}} + class UploadUserManual(Command): # {{{ description = 'Build and upload the User Manual' sub_commands = ['manual'] @@ -230,8 +293,10 @@ class UploadUserManual(Command): # {{{ def build_plugin_example(self, path): from calibre import CurrentDir with NamedTemporaryFile(suffix='.zip') as f: - os.fchmod(f.fileno(), - stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH|stat.S_IWRITE) + os.fchmod( + f.fileno(), stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | + stat.S_IWRITE + ) with CurrentDir(path): with ZipFile(f, 'w') as zf: for x in os.listdir('.'): @@ -242,8 +307,8 @@ class UploadUserManual(Command): # {{{ for y in os.listdir(x): zf.write(os.path.join(x, y)) bname = self.b(path) + '_plugin.zip' - dest = '%s/%s'%(DOWNLOADS, bname) - subprocess.check_call(['scp', f.name, 'main:'+dest]) + dest = '%s/%s' % (DOWNLOADS, bname) + subprocess.check_call(['scp', f.name, 'main:' + dest]) def run(self, opts): path = self.j(self.SRC, '..', 'manual', 'plugin_examples') @@ -251,30 +316,45 @@ class UploadUserManual(Command): # {{{ self.build_plugin_example(x) srcdir = self.j(gettempdir(), 'user-manual-build', 'en', 'html') + '/' - check_call(' '.join(['rsync', '-zrl', '--info=progress2', srcdir, 'main:/srv/manual/']), shell=True) + check_call( + ' '.join( + ['rsync', '-zrl', '--info=progress2', srcdir, 'main:/srv/manual/'] + ), + shell=True + ) check_call('ssh main chown -R http:http /srv/manual'.split()) + + # }}} + class UploadDemo(Command): # {{{ description = 'Rebuild and upload various demos' def run(self, opts): check_call( - '''ebook-convert %s/demo.html /tmp/html2lrf.lrf ''' - '''--title='Demonstration of html2lrf' --authors='Kovid Goyal' ''' - '''--header ''' - '''--serif-family "/usr/share/fonts/corefonts, Times New Roman" ''' - '''--mono-family "/usr/share/fonts/corefonts, Andale Mono" ''' - ''''''%self.j(self.SRC, HTML2LRF), shell=True) + '''ebook-convert %s/demo.html /tmp/html2lrf.lrf ''' + '''--title='Demonstration of html2lrf' --authors='Kovid Goyal' ''' + '''--header ''' + '''--serif-family "/usr/share/fonts/corefonts, Times New Roman" ''' + '''--mono-family "/usr/share/fonts/corefonts, Andale Mono" ''' + '''''' % self.j(self.SRC, HTML2LRF), + shell=True + ) lrf = self.j(self.SRC, 'calibre', 'ebooks', 'lrf', 'html', 'demo') check_call( - 'cd %s && zip -j /tmp/html-demo.zip * /tmp/html2lrf.lrf' % lrf, shell=True) + 'cd %s && zip -j /tmp/html-demo.zip * /tmp/html2lrf.lrf' % lrf, + shell=True + ) + + check_call('scp /tmp/html-demo.zip main:%s/' % (DOWNLOADS, ), shell=True) + - check_call('scp /tmp/html-demo.zip main:%s/'%(DOWNLOADS,), shell=True) # }}} + class UploadToServer(Command): # {{{ description = 'Upload miscellaneous data to calibre server' @@ -283,32 +363,45 @@ class UploadToServer(Command): # {{{ src_file = glob.glob('dist/calibre-*.tar.xz')[0] upload_signatures() check_call(['git', 'push']) - check_call(['/home/kovid/work/env/private/gpg-as-kovid', '--armor', '--yes', '--detach-sign', src_file]) + check_call([ + os['PENV'] + '/gpg-as-kovid', '--armor', '--yes', + '--detach-sign', src_file + ]) check_call(['scp', src_file + '.asc', 'code:/srv/code/signatures/']) check_call('ssh code /usr/local/bin/update-calibre-code.py'.split()) - check_call(('ssh code /apps/update-calibre-version.py ' + __version__).split()) + check_call( + ('ssh code /apps/update-calibre-version.py ' + __version__).split() + ) check_call(( - 'ssh main /usr/local/bin/update-calibre-version.py %s && /usr/local/bin/update-calibre-code.py && /apps/static/generate.py' % __version__ + 'ssh main /usr/local/bin/update-calibre-version.py %s && /usr/local/bin/update-calibre-code.py && /apps/static/generate.py' + % __version__ ).split()) + + # }}} # Testing {{{ + def write_files(fmap): for f in fmap: with open(f, 'wb') as f: f.write(os.urandom(100)) - f.write(b'a'*1000000) + f.write(b'a' * 1000000) with open('fmap', 'wb') as fo: for f, desc in fmap.iteritems(): - fo.write('%s: %s\n'%(f, desc)) + fo.write('%s: %s\n' % (f, desc)) + def setup_installers(): ver = '0.0.1' - files = {x.replace(__version__, ver):installer_description(x) for x in installers()} + files = { + x.replace(__version__, ver): installer_description(x) + for x in installers() + } tdir = mkdtemp() os.chdir(tdir) return tdir, files, ver -# }}} +# }}}