Top Tags

Apple Water

Recently, an “Apple Water” parody made the rounds on social media; it’s a mockup of a fictional Apple product.  Go have a look at it; even if you’ve seen it already, I encourage you to pull it up and have it on-screen as you read this post.

Now, as you read this post, you see me as being a killjoy, but I’m going to spend a minute taking issue with this parody.

Apple would never treat their logo as a color-changing factotum — heck, they stripped the colors from the original logo and pulled it from the ⌘ key years ago.

They certainly wouldn’t mimic the ugly “grip” profile of today’s water bottles. If anything, Apple has a history of erring on the side of form over function (for example, see the hockey-puck mouse, the scratch-happy nano 1G, and the uncomfortable grips on the Mac Pro).

They wouldn’t use inflated language like “ingestion vessel” and “waterfication.” There’s plenty about Apple deserving of parody, but one thing they do right is communicating the benefits of their products in plain English.

And there’s no way Apple would have a cap design that leaves the ring behind when twisted off — if they can make high-end music players, phones, tablets, and computers with no removable battery and almost no visible seams or screws, it’s inconceivable that they would settle on a water bottle design that includes a vestigial piece of plastic that remains ringed around the body of the product for the lifetime of its use.

Parody consists of imitation and ridicule. I’m afraid this mockup only succeeds at the latter.

Neil Young Is A Customer

Neil Young made a lot of news last week with his remarks about digital audio and the need to make music available in higher resolution audio formats.  But it was his remarks about the much-maligned record labels that surprised me:

Mr. Young moved from his pitch for high-quality audio to his defense of both record companies and piracy.

“What I like about record companies is that they nurture an artist,” he said.

A few days later, we have a post from Seth Godin, Who is your customer?, that points out that his perspective should not come as a surprise:

Columbia Records has no idea who buys their music and never has. On the other hand, they understand that their customer is the musician, and they have an entire department devoted to keeping that ‘customer’ happy.

The next time you’re surprised at the level of service that you receive from a company, or if you find that your viewpoint on a company doesn’t agree with someone like Mr. Young, ask yourself, are you actually the company’s customer?  Or perhaps you’re actually the product being sold?

Getting the SQL Server Version from a .bak File

I was working on deployment instructions for a client today, and I wanted to include directions on how to back up the SQL Server database for the product being deployed. There was only one problem: the product supports several versions of SQL Server, and I didn’t know which version they were using.

However, I did have a database backup (i.e., a .bak file) that they had provided to us for testing. Could I somehow inspect that .bak and determine what SQL Server version that they’re running? It turns out that the answer is yes. From an MSDN Forums thread :

RESTORE HEADERONLY
FROM DISK = N'd:\testdb.bak'
WITH NOUNLOAD;

I’m happy to report that this works like a charm. Simply substitute the path for your .bak file, run the query in SQL Server Management Studio, look at the values of the SoftwareVersionMajor, SoftwareVersionMinor, and SoftwareVersionBuild, and compare them to Microsoft’s information on how to identify the version of SQL Server that you have.

Removing Large Files from TFS

I recently worked with a client to automate a process that rebuilds several databases based on licensed data that is delivered to them via FTP on a weekly basis. At the end of this process, a backup of the newly built database is checked into version control as a means of backup, history, and deployment (i.e., conveniently making the database available to other developers and additional build automation).

They use Team Foundation Server (TFS) for version control. We grew concerned that these checkins, along with a number of others, would bloat the overall size of the version control database over time, especially since TFS stores full copies of every revision of very large files. I found a post by Eugene Zakhareyev that described how to identify large files, but I still wanted a good strategy for cleaning them up.

TFS provides a destroy command that can be used to permanently remove some or all revisions of a file from version control. But obviously, we didn’t want to destroy these files entirely; just older revisions. I decided to automate this process. I put together a Perl script which will enumerate all the files found under a specified folder in version control, identify those that are larger than a user-configurable threshold, and provide tf.exe commands to destroy older revisions of those files. The user can specify a maximum number of revisions to keep as well as a minimum timespan of history to keep; if the two are in conflict, the timespan specified overrides.

Some readers may be asking why I used Perl for this. As I saw it, there were three basic approaches: querying TFS’ version control database directly, writing an application with the version control API, or scripting tf.exe. Working directly against the database is bad because it isn’t documented, and the risk of shooting myself in the foot appeared high. Writing a compiled program for this task felt heavyweight, but in hindsight it probably would have been simpler.

The resulting script is available on GitHub. It has been tested against multiple TFS 2008 version control databases, with Strawberry Perl. Looking back, I discovered several non-related but interesting things:

  • Perl feels much more mature than when I last used it five or six years ago. I had to pull in a number of modules to complete this script. All were available as part of the Strawberry Perl distribution — I didn’t have to go out to CPAN for anything, and they all worked exactly as documented on CPAN.
  • At first, I was shocked at the poor performance of the script due to the many invocations of tf.exe . After searching a bit, I discovered that tf.exe has an “@ mode” or “console mode” that you can use to run many version control commands with a single invocation of tf.exe. This appears undocumented; I only found a single mention of it within an MSDN forums thread. After the fact, I discovered that tf.exe also supports response files, and I expect they would have worked equally well.
  • One complication I encountered involved dates: tf history‘s console output prints dates according to Windows’ regional settings, which can obviously vary from one system to the next. To address this, I pull the Windows date format from the Registry and then do a little munging of that string so that I can parse it using the Time::Piece module. This worked quite nicely and could prove useful for scripting other command line utilities.

If you have been looking for a way to clean large files from your TFS database and have stumbled upon this post, I encourage you to give the script a try. It’s safe to run — it emits the tf destroy commands you’ll want to run, but leaves it to you to actually perform them.