summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2016-10-25 14:46:06 (GMT)
committerEdwin Mons <edwin.mons@isode.com>2016-11-14 10:41:17 (GMT)
commit6a033c0efade676403c372f8afecf95b5f9afc79 (patch)
tree14a7044b74c45838c4c4acf28c2625e8e4f57749 /BuildTools
parent97c87cf3e9b5e150152898e7907577c3ca3fdd86 (diff)
downloadswift-6a033c0efade676403c372f8afecf95b5f9afc79.zip
swift-6a033c0efade676403c372f8afecf95b5f9afc79.tar.bz2
Add script generating Sparkle appcast feeds
This Python script parses the folder structure of Swift downloads locally and generates three appcast feeds to use for Sparkle updater. The three appcast feeds are written to the downloads folder supplied to the script. Test-Information: Ran script with Python 2.7.12 and manually checked the output. Change-Id: Ie1e71eecad4f65e48694b805878765806a3465ae
Diffstat (limited to 'BuildTools')
-rwxr-xr-xBuildTools/GenerateAppCastFeeds.py128
1 files changed, 128 insertions, 0 deletions
diff --git a/BuildTools/GenerateAppCastFeeds.py b/BuildTools/GenerateAppCastFeeds.py
new file mode 100755
index 0000000..fe39e3c
--- /dev/null
+++ b/BuildTools/GenerateAppCastFeeds.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python2
+
+# This script generates three app cast feeds for macOS Sparkle updates from Swift releases in the download folder on the Swift website.
+
+from xml.etree import ElementTree as ET
+import argparse
+import datetime
+import email.utils as eut
+import fnmatch
+import jinja2
+import os.path
+import re
+import time
+import urllib2
+import urlparse
+
+class Release:
+ def __init__(self, version, absoluteURL, sizeInBytes, date):
+ self.version = version
+ self.shortVersion = version.split('-', 1)[1]
+ self.url = absoluteURL
+ self.sizeInBytes = sizeInBytes
+ self.date = date
+ dateTumple = date.timetuple()
+ dateTimestamp = time.mktime(dateTumple)
+ self.dateString = eut.formatdate(dateTimestamp)
+
+ def __str__(self):
+ return "Release(%s, %s, %s, %s)" % (self.version, self.url, self.sizeInBytes, self.date)
+
+ def __repr__(self):
+ return "Release(%s, %s, %s, %s)" % (self.version, self.url, self.sizeInBytes, self.date)
+
+def getReleaseFromAbsoluteFilePath(absolutePath, downloadsFolder, downloadsURL):
+ version = os.path.splitext(absolutePath.split('/')[-1])[0]
+ sizeInBytes = os.path.getsize(absolutePath)
+ date = datetime.datetime.fromtimestamp(os.path.getmtime(absolutePath))
+ absoluteURL = urlparse.urljoin(downloadsURL, os.path.relpath(absolutePath, downloadsFolder))
+ return Release(version, absoluteURL, sizeInBytes, date)
+
+def getReleaseFromReleaseFolder(releaseFolder, downloadsFolder, downloadsURL, extension):
+ release = None
+ regex = re.compile(fnmatch.translate(extension))
+
+ files = [f for f in os.listdir(releaseFolder) if os.path.isfile(os.path.join(releaseFolder, f))]
+ for file in files:
+ fileFullPath = os.path.join(releaseFolder, file)
+ if regex.match(fileFullPath):
+ release = getReleaseFromAbsoluteFilePath(fileFullPath, downloadsFolder, downloadsURL)
+ return release
+
+def getReleaseFilesInDownloadsFolder(downloadsFolder, downloadsURL, extension):
+ releasesFolder = os.path.join(downloadsFolder, "releases")
+ releases = []
+
+ dirs = [d for d in os.listdir(releasesFolder) if os.path.isdir(os.path.join(releasesFolder, d))]
+ for d in dirs:
+ release = getReleaseFromReleaseFolder(os.path.join(releasesFolder, d), downloadsFolder, downloadsURL, extension)
+ if release:
+ releases.append(release)
+
+ return releases
+
+def writeAppcastFile(filename, title, description, regexPattern, appcastURL, releases):
+ template = jinja2.Template('''<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
+ <channel>
+ <title>{{ title }}</title>
+ <link>{{ appcast_url }}</link>
+ <description>{{ description }}</description>
+ <language>en</language>
+ {% for item in releases %}<item>
+ <title>Swift version {{ item.version }}</title>
+ <pubDate>{{ item.dateString }}</pubDate>
+ <enclosure url="{{ item.url }}"
+ sparkle:version="{{ item.version }}"
+ sparkle:shortVersionString="{{ item.shortVersion }}"
+ length="{{ item.sizeInBytes }}"
+ type="application/octet-stream" />
+ </item>
+ {% endfor %}</channel>
+</rss>''')
+
+ matchingReleases = [i for i in releases if re.match(regexPattern, i.version)]
+ matchingReleases = matchingReleases[:2] # only include the first two matches in the appcast
+
+ appcastContent = template.render(title=title, appcast_url=appcastURL, description=description, releases=matchingReleases)
+
+ contentParsesOK = False
+ try:
+ x = ET.fromstring(appcastContent)
+ contentParsesOK = True
+ except :
+ contentParsesOK = False
+
+ if contentParsesOK:
+ with open(filename, 'w') as file:
+ file.write(appcastContent)
+ else:
+ print("Failed to generate valid appcast feed %s." % filename)
+
+parser = argparse.ArgumentParser(description='Generate stable/testing/development appcast feeds for Sparkle updater.')
+parser.add_argument('downloadsFolder', type=str, help="e.g. /Users/foo/website/downloads/")
+parser.add_argument('downloadsURL', type=str, help="e.g. https://swift.im/downloads/")
+
+args = parser.parse_args()
+
+releases = getReleaseFilesInDownloadsFolder(args.downloadsFolder, args.downloadsURL, "*.dmg")
+
+releases.sort(key=lambda release: release.date, reverse=True)
+
+writeAppcastFile(filename=os.path.join(args.downloadsFolder, "swift-stable-appcast-mac.xml"),
+ title="Swift Stable Releases",
+ description="",
+ regexPattern="^Swift\-\d+(\.\d+)?(\.\d+)?$",
+ appcastURL=urlparse.urljoin(args.downloadsURL, "swift-stable-appcast-mac.xml"),
+ releases=releases)
+writeAppcastFile(filename=os.path.join(args.downloadsFolder, "swift-testing-appcast-mac.xml"),
+ title="Swift Testing Releases",
+ description="",
+ regexPattern="^Swift\-\d+(\.\d+)?(\.\d+)?(beta\d+)?(rc\d+)?$",
+ appcastURL=urlparse.urljoin(args.downloadsURL, "swift-testing-appcast-mac.xml"),
+ releases=releases)
+writeAppcastFile(filename=os.path.join(args.downloadsFolder, "swift-development-appcast-mac.xml"),
+ title="Swift Development Releases",
+ description="",
+ regexPattern="^Swift\-\d+(\.\d+)?(\.\d+)?(alpha)?(beta\d+)?(rc\d+)?(-dev\d+)?$",
+ appcastURL=urlparse.urljoin(args.downloadsURL, "swift-development-appcast-mac.xml"),
+ releases=releases)