A few months back I got annoyed at having to maintain some documentation both in README files and on-wiki. I figured I’d be a lot nicer if I could just embed those README files in the wiki and have their contents rendered. I therefore created the GitWeb MediaWiki extension, that would get the contents of files in a git repo via the WMF GitWeb interface.
This worked nicely until recently the WMF decided to use GitBlit (which appears to be less fail then GitWeb) without continuing their GitWeb support. This meant that all the wiki pages that where embedding content pulled from it suddenly broke. After kgh, the SMW wiki overlord, pointed this out to me, I was lazy and preoccupied with other things, so did not do anything on this for a month or so.
I’m currently on a week long holiday in Belgium and yesterday (Friday) evening was hanging out at the local hackerspace 0×20 (whitespace). I figured I really ought to fix the file content embedding issue and thought this would be a quick bit of hacking to make the old GitWeb extension work with GitBlit that would take roughly an hour.
It occurred to me that the new code could also fetch the file contents from GitHub, and that this have some advantages. For one it provides increased stability. Clearly the WMF does not care about the stability of the paths provided by their git browser, so a future upgrade of GitBlit or switch to yet another tool might result in re-occurrence of the problem. Something similar happening for GitHub seems much less likely. Another point for GitHub is that more people use it, thus increasing the number of people this tool is useful for.
I started work on this new GitHub extension by copying the GitWeb files and replacing GitWeb by GitHub. Inevitably I ended up wanting to do something more exciting then that. And lucky me, I saw some room for design improvements to the code.
The technical part
Though it certainly is not the most elegant code ever, the old Gitweb extension certainly wins the “not a lot of code there” badge. Do admire the 30ish lines of code that make up the meat of the extension. Not very testable, flexible, extensible or reusable. Though a perfectly valid approach for such a small task. Nevertheless, boring!
The steps I took in refactoring this code to the current state where roughly as follows. Some of my thoughts along the way are between these things: “”.
- Move code from anonymous function to a new GitHubParserHook class.
- “Bah, this caching logic does not belong here”. Injected a Cache implementing object in the constructor.
- Created Cache interface.
- Created MediaWikiCache implementation that is an adapter around MediaWiki’s BagOStuff.
- “Actually, this file fetching logic is also its own responsibility”. Also inject a FileFetcher via the constructor.
- Created Filefetcher interface.
- “This parser hook class should not know about use of caching at all”. Dropped Cache parameter from the constructor.
- Created CachingFileFetcher which takes a FileFetcher and a Cache in its constructor.
- “Having a simple in memory cache as well would be nice. And being able to combine this with a more complex cache such as the MediaWikiCache in a smart way would be awesome. Actually, I ran into this before, and will so again. Better do something neat and reusable in its own component”.
- Created SimpleCache repo and move Cache interface and MediaWikiCache implementation there.
- Created SimpleInMemoryCache and CombinatoryCache implementations.
After that I still needed to to a bunch of work on the setup code, putting in place composer.json and README files, etc. That is not as interesting though, so skipped here.
So now I ended up with this new GitHub extension and a small reusable SimpleCache library. Both are at version 0.1, are available on GitHub, have their PHPUnit tests run on TravisCI and are on Packagist, so can be installed via Composer.
Though I do not anticipate poking at the GitHub extension much in the future (if at all), the SimpleCache library seems to have good potential for reuse in other projects I’m working on. It’s thus quite possible I’ll be adding in more things there. And of course, you are welcome to do so as well.