Spelunking desktop apps saves time

20th Apr '205 of your Earth minutes

Spelunking desktop apps saves time

A tale of restoring Tower bookmarks

I’m a big fan of Tower, a native Git GUI for Mac and Windows. I was really lucky to be working with Joel Gascoigne on a project while he was building Buffer when he heard about an early release of Tower. He was able to get both of us a copy, and I’ve used it almost every day ever since. That was almost 10 years ago.

When I was just starting with Git, I wasn’t as comfortable on the command line as I am now (note: I’m still not great), so Tower was a life-saver — even in that early release it was hands down the best Git GUI I’d used… and it still is!

I’ve not had many issues with Tower over the years. With a steady release of new versions, many of my feature requests have been ticked off. I probably still don’t even use the full power of Tower every day, but it keeps getting better.

There is one thing that I’ve come across a few times though which would be a very useful feature. On more than a handful of occasions, I could have done with a way to update repository paths. Occasionally I reorganise files and it’s currently not possible in Tower to point a bookmark at a new location. You have to remove it and add it again from its new source. This is a little frustrating on those occasions.

Slightly more frustrating is if you have to do what I did this weekend, which is to move to a new Mac. Imagine my slight horror this morning after booting up my freshly migrated Mac, only to find Tower looking like this:


Every repo is broken :(

After some quick digging, it was clear why: the username folder generated during the migration of my account has a different name to the one on my previous Mac.

This means all of my Tower bookmarks are now broken 😢 I have quite a few, so updating them one-by-one would be a boring and time-consuming task. As there’s no way to re-point individual bookmarks, you can bet there’s no way to re-point a load of them en masse from with the Tower UI.

Maybe I should just shut up, get some coffee and get on with it? Well this was a challenge I didn’t want to back down from because I was confident given 10 minutes I could find a quicker way to do it. And I did! So, in case you find yourself ever needing to automatically update some or all of your Tower bookmarks in one go, here’s how I did it…

0. Quit Tower

Make sure Tower isn’t open for any of this. We’re modifying some things under-the-hood and we wouldn’t want the engine running… things could get corrupted. I certainly don’t want an email from you telling me you started following this process only to lose all of your bookmarks. There may be no way back from that other than to recreate them all by hand.

You have been warned.

But now that’s out of the way…

1. Edit the bookmarks plist

Create a backup copy of and then open the original~/Library/Application Support/com.fournova.Tower3/bookmarks.plist and update any bookmarks with incorrect/broken paths. This should be self-evident, but the path is in a <string> node that appears after a <key>fileURL</key>, one for each bookmark — a find & replace in your favourite text editor should make light work of this.


Here’s what some of my bookmarks.plist looks like in Sublime

2. Update the Tower database

Tower uses a SQLite database to cache a bunch of data about your repos and keep the UI snappy. This stores some path info too, so it needs to be updated.

Firstly make a backup copy of ~/Library/Application Support/com.fournova.Tower3/Tower.sqlite3 in case you royally screw this one up.

Then open the original in a good DBA tool (I really like TablePlus as it has great SQLite support) or use the SQLite CLI.

Find the table called ZGTGITREPOSITORY and run a query to update the relevant parts of the paths for each repo — you’ll need to update values in the following 3 columns: ZFILEURLSTRING, ZGITDIRECTORYURLSTRING, ZWORKINGTREEDIRECTORYURLSTRING.

Here’s my query as a sample:

1UPDATE ZGTGITREPOSITORY
2SET ZFILEURLSTRING = REPLACE(ZFILEURLSTRING, 'simonhamp', 'simon'),
3 ZGITDIRECTORYURLSTRING = REPLACE(ZGITDIRECTORYURLSTRING, 'simonhamp', 'simon'),
4 ZWORKINGTREEDIRECTORYURLSTRING = REPLACE(ZWORKINGTREEDIRECTORYURLSTRING, 'simonhamp', 'simon');

3. Open Tower

Once those changes are all made and saved, you can open Tower and your broken bookmarks should be back to normal.

Lessons

I’ve written this out for a couple of reasons:

  1. I think it may be useful for others.
  2. I think it’s going to be useful to me/my team in the future.
  3. It shows that with a little digging you can find quick ways to solve otherwise time-consuming problems.
  4. Hackable software is great!

If the makers of Tower had opted to use some custom binary format in some spurious database, I would never have been able to fix this myself. As it is, they used an open solution in SQLite, making it easy to find the data that needed changing and also to change it using generally-available tools.

I saved my time by not having to manually update all of my bookmarks, I sped up the resolution of my problem (didn’t have to wait for Tower support) and I saved the Tower team’s time by not hassling them with a request.

I will be raising a feature request from this, but I’m not dependent on that to solve my immediate problem. Also, I highly doubt that any ‘relocate bookmark’ feature would solve this specific case and would likely only have made the problem slightly easier to solve than without it. So it’s still good to occasionally go spelunking into other people’s systems before asking for help.


This story also highlights something that I’ve rarely considered before but am starting to come around to the idea more and more. I love using and building web apps. I still believe the web (platform) to be the future. Indeed, it is very much the present. However, this little crusade has made me consider the beauty of having apps that are installed onto my computer — they can be ‘hacked’ (by me) much more easily.

It’s a major shortcoming of many web apps that don’t give me direct access to my data. In many cases, there is either no API, a very limited API, or a very complex API, with many technical hurdles and/or requiring an increased subscription level.

I believe there is something possible in the middle where a web app that either operates centrally — or better yet, installed locally — can connect to my data stored locally or at least in some online space that I control (e.g. personal cloud such as iCloud or Dropbox).

This is really interesting to me and something I will be thinking more about.

#notadesigner • #sometimesitworks

All content licensed CC BY-SA 4.0  •  Code highlighting by Torchlight