For a brief period of time, when coming across a package or tool that I wanted to make a note of, I added it to this blog in the form of a link post. I’ve recently started using Pinboard for this purpose, meaning that there’s no longer a need to keep adding them here. Besides, I’ve found that their presence was cluttering up the index page a bit, not to mention the RSS feed.
So I plan to stop publishing links to packages and tools here unless I have something to say about them. The existing link posts have been deleted, and the links themselves have been moved to Pinboard. Some of them I’ve kept in the Bookmarks section, but they may not be safe even here. I’m intending to have Pinboard act as the source of truth for this sort of stuff going forward, so there may not be a need for a dedicated section for them on this blog at all.
I’ll probably keep adding link posts to articles though. At least there’s a post on the other end that may be worth reading.
P.S. I kept forgetting the name of the Pinboard service before I actually signed up to it. I think this happened at least three times in the last few weeks. I probably should have added a link to it when I came across it the first time.
19 April 2021
Jumping to the Root of a Git Repo
Sometimes, when you’re browsing your social feeds, you come across a tool or technique for doing something that you think is good to know, but you have no immediate use for it. Then a couple of hours later, while working on something else, you find yourself needing that exact bit of information.
This occurred to me this morning. While getting coffee, I saw someone post a tweet documenting a way to get to the root directory of a Git repo. Could be useful, I thought. Then, while writing a script to prep a Pull Request, I found myself needing to do exactly this.
Here is the command to jump to the root of a Git repo:
$ cd $(git rev-parse --show-toplevel)
Truly a Serendipitous Event.
13 April 2021
Showing A File At A Specific Git Revision
Here is a technique for showing the version of a file at a specific Git revision. It’s not a novel technique — there’s naturally a Stack Overflow answer for explaining this process — but I constantly forgetting how to do this and end up having to search for it. So I’m including it here just so I know where to go when I need to look this up again.
To display the contents of a file at a given revision, run the following command:
$ git show <revision>:<filename>
For example, to view the version of “README.md” on the
$ git show dev:README.md
There is an alternative form of this command that will show the changes applied to that file as part of the commit:
$ git show <revision> -- <filename>
This can be used alongside the log command to work out what happened to a file that was deleted.
First, view the history of the file. You are interested in the ID before the commit that deleted the file: attempting to run
git show using the deletion commit ID it will result in nothing being shown.
$ git log -- file/that/was/deleted
Author: The Deleter <email@example.com>
Deleted this file. Ha ha ha!
Author: File Changer <firstname.lastname@example.org>
Added a new file at file/that/was/deleted
git show to view the version before it was deleted:
9 April 2021
$ git show beforeCommit:file/that/was/deleted
On Google and Winer’s Rule One
Here’s another blog post about Google, because, why not?
It all started when I read a post from Dave Winer, in which he talks about a principal of software evolution that he applies to his work. Simply calls Rule 1, it dictates that the environment between successive versions of a software platform cannot change such that they will break any existing apps built atop it.
Rule 1 was not a joke, it was dead serious. I was sick of programmers who choose to break users and developers. I had worked with a deprecator, for years, and learned the hard way that a development process that permitted user breakage was not much of a process. Eventually the users will go somewhere where they aren’t always having to start over because a programmer changed their mind about how something should work. Sometimes breakage happens, all rules have exceptions, but you have to work really hard to avoid those situations, and usually there’s a way to do it.
This post really resonated with me. It actually reminded me of another blog post by Steve Yegge on Google GCP and their love of deprecating things. I have little experience with GCP myself, but given how they go about consumer product development, I can certainly believe this.
I know building new stuff is a lot more fun than maintaining stuff. Take it from me, a person who has list of completely unfinished, unreleased, and unmaintained personal projects a mile long. But this trigger happy approach to deprecating things is not good. Developers get value out of a platform if they are able to build and operate something on it with less effort than they would have if they didn’t use it at all. That is why they spend money on it.
If the platform vendor keeps moving the goal posts like this, meaning more effort is required just to keep their software running, then I personally don’t see the value in continued use the platform. Why would you? You’ve got plenty of work already on your plate evolving your service without having to be on the deprecation treadmill.
Google really needs to improve here if they ever want to be taken seriously as a cloud platform vendor.
31 March 2021
Up there with naming, caching, concurrency, and off by one errors, I think versioning and dependency management are two aspects of software development that is difficult.
Picking version numbers; ensuring that versions are correct; ensuring that artefacts are in sync across everyone in the team; designing a branching structure that is flexible enough to produce releases quickly, while sane enough to know which branch has what, and where new work should come from.
Coming from a place that offloaded a lot of this to build servers to one in which this is done manually is a bit of a shock to the system. It’s an excellent reminder on how much work and coordination it takes to get all of this correct.
29 March 2021
I’ve started working on a small Go tool to quickly add bookmarks to this site from the command line. This Blot.im site uses Git as the sync engine, so in order to publish the updates, the tool will need to add the changed files to Git, commit the changes, and push them to Blot.im. It does this by “shelling out” to the Git command line using the exec package.
For some reason, whenever the tool tries to run
git add with the updated files, the error code that is returned is 128. Since the error code is not zero, the tool interprets this as an error and terminates the program. As far as I can tell, the files are being added to the repository without any issues. When I run the command from the terminal, it seems to work correctly, and the returning error code is zero. I do know some shells actually add something to the error code when they succeed properly, which may explain this odd behaviour.
Interestingly, this doesn’t happen with the other tool that I’ve written to quickly write and publish posts for this site. This one shells out to Git in the same way, and I have had zero trouble with it doing so. The only reason for this discrepancy that I can think of is that this other tool is written in Swift, and there might be some difference in how Core Foundation interprets error codes.
I guess further investigation is warranted.
26 March 2021
Google Still Don’t Understand Services
It’s been a little while since I’ve though of Steve Yeggie’s platform rant on the the state of Google’s services. But spending a few hours exploring the capabilities of Google Sites, that classic blog-post has been front of mind once again.
Google Sites allows you to build and publish web-sites using a WYSIWYG designer, similar to Microsoft Front-page (anyone remember that?). These can be viewable by anyone on the public web, but when created within a Google Workplace, they could also be restricted to those that are within the workspace they are created in. This makes it a suitable choice for publishing internal sites that live within an organisation, which is what I want to use it for.
The current version of Google Sites is actually a redesign of an older version of Sites that has been around since 2008. This new version has a few niceties over the “classic” version — which is still around — like a nicer designer and better looking templates.
What it doesn’t have is an API.
Without giving too much away, I was hoping to dynamically modify the contents of the site without building something as involved like a web-app. A simple bot, or something glued together with Google App Script, would be perfect. This is possible to do with classic Google sites, but this functionality has not been ported to the redesigned version. This new version has been around since 2016, and yet the only way that the contents of the site can be changed is through the WYSIWYG editor.
If I really wanted to make the content dynamic, I’d either have to use the classic version — which is probably no longer maintain, and could be shutdown whenever Google feels like it — or take up the work to build a completely bespoke web-app.
This is a shame. It’s clear that in this instance Google has not only failed to internalise the message of Yeggie’s rant, they have actually gone backwards. It might be that they are OK with this: after all, Sites is a consumer offering and may not be targeted to those with needs that demand this feature. But this line of thinking does a disservice to their offerings. It limits what is possible with these services, and reduced the number of paths available to those that want to do just that bit more.
22 March 2021
It looks like Intel has released a series of ads that have a go at Apple’s M1 chips. From Ars Technica:
Chipmaker Intel has produced a series of ads mocking Apple’s M1 Macs, and it brought on actor Justin Long—famous for his role in Apple’s 2000s “I’m a Mac” ads opposite comedian John Hodgman—to satirize Apple’s own ad campaign.
It’s noteworthy that Intel has released ads that reference Apple’s “I’m a Mac” campaign. This is the second throwback to this campaign that I can recall: the first were a series of ads from Microsoft released shortly after
Windows 8 Windows Vista. It shows how good that particular ad campaign was.
It’s also noteworthy, after watching half of one of the ads (sorry, I couldn’t really watch the whole thing), that the comparison between the two machine don’t relate to chip performance. Attributes like the number of monitors that can be driven are fair game, although remember these are still early days for the M1 chip. But the lack of gaming on MacOS, and touchscreens Macs? I don’t see how that relates to chip performance.
This whole thing smells of desperation on Intel’s part. I think what we’re witnessing here is a classic case of disruption of Intel’s PC chip incumbency, and instead of doing what’s necessary to pivot and compete with Apple head on — something that may require dramatic changes to how the company operates — Intel is going for quick wins to reach the mind of buyers. I’m not sure it will be enough to save it, though.
18 March 2021
Web Platform Wish List: Single Tab Pages
I wonder if there should be a web-standard of some form to indicate that certain pages should not be open in more than one tab. This would be particularly useful for certain web-apps that are large enough, or complex enough, that it’s better to avoid having multiple copies of them opened at the same time.
Here’s how I’d see this working:
- Open a web page at a specific URL in the browser.
- The server returns the page content with either a specific header, or a meta-tag of some sort, indicating that there should only be one tab of this specific page opened at any one time.
- While that tab is opened, clicking a link to that URL from another page will bring you to that tab that was already opened. This will also work for links that are found outside the browser, like in emails or a chat.
A classic use case for this would be something like Google Calendar. I have Google Calendar opened in a browser tab, but I get meeting invites sent to me in another app. Clicking the invite link will bring up Google Calendar in a brand new tab, instead of simply highlighting the proposed meeting slot in tab that I already have opened.
The usual practice around miss-use can be applied here, like only applying to TLD+1 or the domains of the actual page that is requesting this feature. This should also be something that the user can override: there should be nothing stopping the user from disabling this feature or explicitly creating a new tab and copying and pasting the URL in order to open the new the page in a new tab.
This is probably something that will only be useful in a limited number of circumstances. Web-pages with content, like news and blogs, will be better of not using this feature.
Anyway, one more idea for the already huge web platform 🙂.
17 March 2021
Something that would be nice to see in GitHub and Bitbucket is the ability to prevent merging of a pull request if a comment containing a particular regular expression is found in the diff. For example, if I were to add a comment that begins with
TEMP in the code, and submit that code as a pull request, I would be unable to merge that pull request until that comment is removed.
This would be useful for protecting accidental merges of temporary changes. Usually I make a note of such changes when I’m working on the code, and I may forget about them when it comes time to merging the pull request.
An example of such a change that I make often is temporary release versions of libraries. I may have made a change to a library that’s sitting in another pull request. Until that pull request has been merged, I cannot make a release version of that library, but I can make a temporary release so that a dependant change I’m working on can be built. That temporary release is listed as a dependency, but I don’t want to merge the pull request until the change to the library has been merged and a proper release has been made.
Surrounding the temporary release version with comments that begin with
11 March 2021
TEMP make that clear the reviewers, but preventing the pull request from being merged until I change the version and remove the comments would be a nice safety feature.
“Buffalo New” and Missing Templates
I was working on a Buffalo app over the weekend, and I made a mistake which manifested in an interesting way. The Buffalo framework is a lot like Ruby on Rails: it’s a rapid development tool for web applications backed by a database, but it uses Go instead of Ruby. A lot of this development speed comes from using generators, of which Buffalo has two different types: one for creating new applications, which is executed when running
buffalo new, and one for adding stuff to an existing application, which is executed when running
buffalo generate <thing>. The trouble is I can never quite remember which one is which.
I wanted to create a new resource, which is effectively a new model to store in the database along with some screens to modify it. However, I accidentally ran
buffalo new resource, instead of
buffalo generate resource. I saw that Buffalo was starting to generate a new project, completely within my existing project. I quickly pressed Ctrl+C, hoping to stop it before it began destroying work. Once it stopped, I took a brief look to see if any files were changed or removed. There was a new “resource” directory, but thinking that this was where working files went, I didn’t think much of it. Thinking that I caught it in time, I continue working on the project.
Then I started seeing weird things happen, like Buffalo being unable to find JS or CSS files, or being unable to find templates to generate HTML pages. This only happened intermittently: after a few restarts, the application started working again. I knew that it somehow related to the mistake I made, but going through my Git history, I didn’t see any files deleted or modified, so I was unsure as to what the problem actually was.
I finished the feature I was working on, and deployed it to my server. It started up properly and I did some quick testing before finding a few things I wanted to fix. I made the fix and deployed it again. I tried to go to the home screen, and I saw a system error. I tried again: system error. From the logs I looked like the same problem I saw in development: missing JS, CSS and template files. I started doing the things I did in development, like restarting or redeploying the app. I even started doing things like upgrading the version of libraries. No good. I was constantly seeing system error.
This morning, I decided to take a good look through the Git commits to see what actually changed. It was only then that I realised that new “resource” directory was not part of the original app, but was instead a completely new Buffalo app, complete with templates, JS and CSS files. It turns out that running
buffalo new didn’t modify any of my existing files, but it did go through with creating a brand new app.
I’ve removed the “resource” directory completely and redeployed the app. The system errors disappeared and I saw the app run again.
So if there is anyone else using Buffalo that is experiencing intermittent issues with the app being unable to find JS, CSS or templates, check to see if you’ve accidentally run
10 March 2021
buffalo new instead of
On Go Libraries Authors Coding to Interfaces
One convention of the Java programming world that I really like is the encouragement of writing code to interfaces instead of concrete types. When deciding on a type for a new variable or field, you’re advised against choosing concrete types like
HashMap, unless you have a specific need for them. Instead, you’re encouraged to use interface types, like
Map, so if it’s necessary to change the specific implementation, you can do so without changing the type of that field or variable. This is especially useful when dealing with libraries, where you may not have full control over the source code.
It would be nice if this convention showed up a bit more often in Go, particularly in libraries. There have been two instances in the last week when I wished the developer of a third-party library used an interface instead of a concrete type. My needs deviated a bit from the concrete type they were using, and if the library author used an interface instead, I could have coded up a type that wrapped the concrete type with some custom logic that satisfied my use case.
Instead, I either need to look for another library, or consider submitting a pull request which changes that concrete type to an interface.
9 March 2021