Call super's implementation of textDidChange: in AICompletingTextField
[adiumx.git] / Utilities / AppcastReplaceItem.py
blobd21cdd46682a3907a2a047cae8502feb5c1ea623
1 #!/usr/bin/env python
3 """
4 Usage: AppcastReplaceItem path-to-appcast version-to-replace version-to-replace-with path-to-dmg
6 Example: AppcastReplaceItem appcast-release.xml 1.1.4 1.2 Release/build/Adium_1.2.dmg
7 """
9 # Configurable variables.
10 app_name = 'Adium'
11 changelog_fmt = 'http://www.adiumx.com/changelogs/%(version)s.html'
12 enclosure_fmt = ' <enclosure sparkle:md5Sum="%(md5)s" sparkle:version="%(version)s" url="%(url)s" length="%(file_size)s" type="application/octet-stream"/>\n'
13 # End of configurable variables.
15 import xml.etree.cElementTree as ElementTree
16 import sys
17 import os
18 import time
19 import subprocess
20 from stat import *
22 args = dict(zip(('appcast_path', 'old_version', 'version', 'dmg_pathname'), sys.argv[1:]))
23 try:
24 appcast_path = args['appcast_path']
25 old_version = args['old_version']
26 version = args['version']
27 dmg_pathname = args['dmg_pathname']
28 except KeyError:
29 print >>sys.stderr, __doc__
30 else:
31 args['app_name'] = app_name
33 # Get the length and modification time of the dmg file.
34 sb = os.stat(dmg_pathname)
35 file_size = args['file_size'] = sb[ST_SIZE]
36 dmg_mod_time = time.localtime(sb[ST_MTIME])
38 # Suffix for the day of the month.
39 th = ['st', 'nd', 'rd'] + ['th'] * (31 - 3)
41 # GMT offset in hours.
42 gmt_offset = '%+i' % (-int(time.timezone / 3600),)
44 # Format, which we must fill in with the above items first.
45 time_fmt = '%A, %B %dth, %Y %H:%M:%S GMT+0'.replace('th', th[dmg_mod_time.tm_mday]).replace('+0', gmt_offset)
46 dmg_mod_date = args['dmg_mod_date'] = time.strftime(time_fmt, dmg_mod_time)
48 openssl_md5 = subprocess.Popen(['openssl', 'md5', dmg_pathname], stdout=subprocess.PIPE)
49 # Skip the prefix
50 openssl_md5.stdout.read(len('MD5(') + len(dmg_pathname) + len(')= '))
51 md5 = args['md5'] = openssl_md5.stdout.read().strip()
52 exit_status = openssl_md5.wait()
53 if exit_status != 0: sys.exit('openssl md5 exited with status ' + str(exit_status))
54 # An MD5 hash is 16 bytes, which is 32 digits hexadecimal.
55 assert len(md5) == 32, 'MD5 sum is %u bytes' % (len(md5),)
57 dmg_filename = os.path.split(dmg_pathname)[1]
58 url = args['url'] = 'http://adiumx.cachefly.net/' + dmg_filename
60 # Because XML parsing with the standard library is a PITA, we're going to do it the hackish way.
61 xmlfile = file(appcast_path)
62 lines = []
63 is_in_item = False
64 is_correct_item = False
65 found_correct_item = False
66 for line in xmlfile:
67 if not is_in_item:
68 if '<item>' in line:
69 is_in_item = True
70 else:
71 if '</item>' in line:
72 is_in_item = False
73 is_correct_item = False
74 elif '<title>' in line:
75 if '>%(app_name)s %(old_version)s<' % args in line:
76 line = line.replace(old_version, version)
77 is_correct_item = found_correct_item = True
78 elif is_correct_item:
79 if'<pubDate>' in line:
80 line = ' <pubDate>%(dmg_mod_date)s</pubDate>\n' % args
81 elif '<sparkle:releaseNotesLink>' in line:
82 line = ' <sparkle:releaseNotesLink>%s</sparkle:releaseNotesLink>\n' % (changelog_fmt % args,)
83 elif '<enclosure' in line:
84 line = enclosure_fmt % args
85 lines.append(line)
87 if not found_correct_item:
88 sys.exit('No item found for version %(old_version)s' % args)
90 xmlfile = file(appcast_path, 'w')
91 xmlfile.writelines(lines)