I've made progress on freeing two packages from their dependency on BottomFeeder - PatchFileDelivery and SyndicationHandling. The former is a simple toolset for setting up HTTP based updates to an application. To use it, you have to set up an XML based config file on a server, and have HTTP access to that file. Setting up the file works like this:
defs := OrderedCollection new.
list := #('ParcelFileName/pcl').
names := #('My Application Parcel').
descripts := #('Description of this component').
sizes := list collect: [:each | each asFilename fileSize].
allows := #(true).
list do: [:each | | version nm timestamp properties index |
properties := [CodeReader new readInfoFromFileNamed: each]
on: OsError, CodeReader fileFormatSignal
do: [:ex | ex return: Dictionary new].
version := properties at: #version.
nm := properties at: #parcel.
timestamp := properties at: #timestamp.
index := list indexOf: each.
comp := ComponentDefinition
parcelFilename: (each asFilename tail asString)
descriptiveName: (names at: index).
comp description: (descripts at: index).
comp fileSize: (sizes at: index).
comp allowDynamicLoad: (allows at: index).
defs add: comp].
That sets up a simple configuration file. You place that in an accessible location (along with the parcel, obviously), and you're ready to go. On the client end, you need to have the UpgradeManager class check for updates. You do that with the #grabRemoteUpgradeDefinitions message. That looks like this:
"try to connect to remote server and get the available updates"
| url defs |
url := self settings upgradeURL last = $/
ifTrue: [self settings upgradeURL, self settings upgradeFilename]
ifFalse: [self settings upgradeURL, '/', self settings upgradeFilename].
defs := (XMLConfigFile loadFromURL: url).
(defs isNil or: [defs isEmpty])
ifTrue: [self patches: #()]
ifFalse: [| tmps |
tmps := defs first.
tmps do: [:each |
each oldVersion: each getCurrentlyLoadedVersion].
self patches: (tmps select: [:each | each couldReplaceLoadedComponent])]
That uses the XMLConfigFile class (in a separate package) to load the update definitions. Those are then checked agains what's actually loaded, and we come up with a list of potential updates. In Bf, that's presented to the user - you could automate it from there. In the UpgradeManager, there's an #upgrade: and #upgradeAll API for doing that.
The other package, Syndication-Handling, is not as cleanly separated yet. There are a few ugly #isDefined checks, but it does load and work independently of Bf. Once you load it, you can see how it works by doing this:
doc := Constructor
cls := Constructor determineClassToHandle: doc content.
target := cls objectForData.
feed := cls
processDocument: doc content
You'll get back this if you inspect to feed object:
That code should work against any version of RSS or Atom out there, and should give you back a FeedList (a collection of feeds) if you hand it OPML or OCS.