Software/Device Development and Design

The Perfect Browser is Easy! Yet It Still Doesn't Exist...

All I want is a modern Firefox with a FF2+Winestripe[1] UI. You know: Modern efficiency, reliability and standards-compliance, but with a classic UI. A UI that doesn't even try to ape the idiotic look and feel of the world's ugliest web browser: Chrome.

Is that really so hard to ask for?

Apparently so. It would seem that if I want an efficient, reliable, "modern-standards" browser, I'm required to take it with the god-awful ideas that are "modern browser UI design".

Fuck that shit.

But let me be clear: I really don't mind if you like those "modern" browser UIs. That's fine, whatever floats your boat. What the hell do I care? Nothing.

Interestingly though, I've noticed that people do seem to care very much what browser I use. I bet that means I'm special and adored by everyone. Hmm, or maybe it's because unlike those people, I've chosen the wrong browser: Firefox 2.

Yup, and I'm a web developer, too. A web developer with an "ancient" browser.

I don't give a rat's ass what browser you use. It's none of my business. But judging from my past experiences on message boards, chances are your nuts are chafing right now over the knowledge that I use Firefox 2, the "wrong" browser.

That's good. Let those balls chafe for a moment...But consider this proposal before you reach for that "Bitch that someone on the Internet made the wrong choice" button (aka "Submit comment"):

I'd love to just jump into the code myself and put a proper UI back in. And it's fully been my intent to do so. But my plate, honestly, is overflowing. I just haven't had the time and I won't for the foreseeable future. There are, however, people who are already neck-deep in web browser source code. People who may even be paid to do so. People who work at Mozilla, for example.

So, since my choice of browser is so offensively wrong, how about enticing me to join your collective by tossing in a "Non-trendy UI" option? Hell, even call it "Old Fart UI", as long as it's there: No toolbar minimalism, no unified forward/back dropdown, no "smart" this or "smart" that, no AwfulBar look or feel, no non-native window skinning (or misuse of buttons as tabs *couch*Opera*cough*)...And most of all, NO asinine "What the hell is wrong with you dumb trolls who refuse to love our obviously and objectively superior new UI?" bullshit.

Modern technology, classic UI.

That's all I ask. That's not such a terrible request, is it?

If you're wonderful enough to do that for me, I'll happily jump on board your modernism train. Heck, once there, I'll even apply some salve (figuratively, of course - don't get too excited!). Sounds like a great deal to me, for both sides.

But wait, there's more!

I'm not gonna shut the others out from this deal-of-a-lifetime: Mozilla may have a leg up, but I'm game for some ship-jumping with anyone who can close the gap. Simply keep in mind that I'll hold onto FF2 well into the 2060's before I give up the following plugins:

Those are absolute minimum. I won't even consider your browser without those. Also mandatory is a complete lack of stealth/piggyback/background software (ex: I'll never install Chrome as long as SRWare Iron exists). Extra brownie points if I don't have to give up these:

So how 'bout it? Fair enough? Excellent!

[1] Winestripe: A FF1.x theme for FF2 that makes FF2 look non-ugly. Doesn't work on FF3 and up. I'm talking the real one here. The newer remakes just don't fit the bill: There's too many changes in FF3+ they still fail to revert.

Read more


The Better "SVN -> Git" Guide

Converting a Subversion repository to Git can be a pain since there's no simple tool that automates the whole process. Worse, most guides and scripts out there completely ignore a couple basic differences between SVN and Git:

  • Unlike Git, SVN supports empty directories. Consequently, many SVN projects rely on these. These need to be preserved with placeholder directories.
  • SVN repos don't usually get cloned, so they're more likely to contain large binary files. For example, I used to be in the habit of keeping my precompiled binaries in the repository in addition to the source code. Since Git repos are always cloned, it's good to prune out such files when converting.

I've recently gone through the pains of converting a few of my SVN projects to Git. So here are my notes on how to do it (just as much for my own reference as for anyone else).

One important note that Windows users (like me) aren't going to like to hear: Since Git is heavily Linux-oriented and all the needed scripts are Linux shell scripts...you'll have to do this on a Linux system (The "Git Bash" that comes with Git on Windows might be sufficient, but I haven't tried). If you don't have a Linux machine, and Git Bash gives you problems, I recommend installing Linux into a VM using Sun'sOracle's free VirtualBox.

Also, you will need at least Git v1.7.7 (and also git-svn). Anything older than v1.7.7 lacks the --preserve-empty-dirs switch we'll be using. You can check your version of Git with:

$git --version

If you need to upgrade it, and you're on a system that uses apt-get, remember: With apt-get, you upgrade a program with the install command, not the upgrade command. Ie:

$sudo apt-get install git git-svn

1. Copy SVN Repo to Local System

We'll be creating a lot of files and directories, so we should work in a clean directory:

$mkdir my-proj-convert-vcs $cd my-proj-convert-vcs

The SVN repository needs to be copied to your local system if it isn't already there. If your only way of accessing the repo is through SVN itself, you can do it like this:

$svnadmin create my-local-svn-repo $cd my-local-svn-repo $echo '#!/bin/sh' > hooks/pre-revprop-change $chmod +x hooks/pre-revprop-change $svnsync init file:///`pwd` https://url_to_svn_repo $svnsync sync file:///`pwd` $cd ..

That synsync sync... command may take awhile as it downloads each revision in order.

2. Prune the Repo

If you don't have any big binary files (or anything else) that you want pruned out of the repo, you can skip this step.

First, dump the SVN repo:

$svnadmin dump my-local-svn-repo > my-local-svn-repo.dump

Subversion has an official svndumpfilter tool for removing content from a dumped repo, but it's known to be crap. It didn't even work at all for me. Instead, you should use the vastly superior svndumpsanitizer.

Download, extract and compile svndumpsanitizer:

$wget http://miria.linuxmaniac.net/svndumpsanitizer/svndumpsanitizer-0.8.4.tar.bz2 $tar xvjf svndumpsanitizer-0.8.4.tar.bz2 $gcc svndumpsanitizer-0.8.4/svndumpsanitizer.c -o svndumpsanitizer

Now, create a little script to run svndumpsanitizer. Depending if you're on a KDE-based, GNOME-based system or text-based system:

$kate prune-repo.sh & or $gedit prune-repo.sh & or $pico prune-repo.sh

Enter something like this (note that svndumpsanitizer doesn't support wildcards):

#!/bin/sh ./svndumpsanitizer --infile my-local-svn-repo.dump --outfile my-pruned-svn-repo.dump \ --exclude trunk/bin/myApp1 \ --exclude trunk/bin/myApp1.exe \ --exclude trunk/bin/myApp2 \ --exclude trunk/bin/myApp2.exe \ --exclude branches/fooBranch/myApp1 \ --exclude branches/fooBranch/myApp1.exe \ --exclude branches/fooBranch/myApp2 \ --exclude branches/fooBranch/myApp2.exe

Save that, and then back at the command prompt, run it:

$chmod +x prune-repo.sh $./prune-repo.sh

Double-check that it actually pruned the files by comparing the file sizes and making sure the pruned version is indeed smaller:

$ls -l

Now, we create our newly-pruned SVN repo:

$svnadmin create my-pruned-svn-repo $svnadmin load --ignore-uuid my-pruned-svn-repo < my-pruned-svn-repo.dump

That last command may take awhile. It creates a new SVN repository one commit at a time.

3. Convert the Authors

Make an empty checkout of any of your project's SVN repos. The original SVN repo works just as well as any:

$svn co --depth empty https://url_to_svn_repo my-working-copy

Create this file and name it svn-authors.sh :

#!/usr/bin/env bash svn log -q | \ awk -F '|' \ '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | \ sort -u

Make it executable, and run it on your checked out working copy:

$chmod +x svn-authors.sh $cd my-working-copy $../svn-authors.sh > ../my-repo-authors.txt $cd ..

The file my-repo-authors.txt now contains a list of all the authors who have committed to the repo. It looks like this:

User1 = User1 User2 = User2 User3 = User3

Edit that file, changing the right-side to the user's name/email for Git. Don't change the left the left-hand side - those are the SVN user names.

4. Fix git-svn

This part is a bit of an annoyance. From v1.7.7 onward, Git has a --preserve-empty-dirs. Problem is, the damn thing's broken. If you try to use it as-is, the whole operation will likely just fail partway through. It has to be fixed.

First, find your git-svn file:

$find / 2> /dev/null | grep git-svn

For me, it was at /usr/libexec/git-core/git-svn. Open it in your favorite editor:

$sudo [your favorite editor] /path/to/git-svn

Now, in this git-svn file, search for die "Failed to strip path. It should be somewhere near line 4583. Change the die to print and save. Your git-svn is now fixed.

5. Convert to Git

As you may have already guessed, we're going to use git-svn. For very large repos (ex: ten or so thousand commits, hundreds of branches/tags, and thousands of files) git-svn has been known to take forever and then crap out. Allegedly, such repos can be converted quickly with svn-fe and git-fast-import, but good luck actually figuring out how to do it without screwing up your branches, tags, and empty dirs. Personally, I just gave up. This git-svn method may not be suitable for such huge repos, but at least it's actually feasible for mere mortals.

The exact flags to use depend on the structure of your SVN repo. If your repo uses the standard SVN trunk/branches/tags layout, then the proper command is:

$git svn clone file://`pwd`/my-pruned-svn-repo --preserve-empty-dirs \ --placeholder-filename=.stupidgit --authors-file=my-repo-authors.txt \ --stdlayout my-temp-git-repo

The traditional name for the empty-directory-preserving placeholder file is .gitignore (and that's the default), but I think .stupidgit is much more appropriate (and satisfying).

Note that the above command is equivalent to:

$git svn clone file://`pwd`/my-pruned-svn-repo --preserve-empty-dirs \ --placeholder-filename=.stupidgit --authors-file=my-repo-authors.txt \ --trunk=trunk --branches=branches --tags=tags \ my-temp-git-repo

So if your SVN repo uses a non-standard layout for trunk/branches/tags, you handle it like this:

$git svn clone file://`pwd`/my-pruned-svn-repo --preserve-empty-dirs \ --placeholder-filename=.stupidgit --authors-file=my-repo-authors.txt \ --trunk=whatever/trunk/path --branches=whatever/branches/path \ --tags=whatever/tags/path my-temp-git-repo

Even though we now have a Git repo, we're still not done yet.

6. Clean Up the Mess Git Left Behind

First, we'll convert the ignore list, since Git didn't bother to do that automatically:

$cd my-temp-git-repo $git svn show-ignore > .gitignore $git add .gitignore $git commit -m 'Convert svn:ignore properties to .gitignore.'

Even though Git was able to insert dummy files to preserve your empty directories, it was still too dumb to know when to actually get rid of them. So now you likely have a bunch of useless old directories that had already been deleted in SVN which Git wasn't intelligent enough to mimic the removal of. These directories are being held in existence by the .stupidgit placeholder files. You may also have unneeded .stupidgit files in directories that already have other files. So while some of your .stupidgit files are holding legitimate empty directories in existence, we need to remove the rest of them from version control. For each of these useless .stupidgit files, run:

$git rm path/to/useless/placeholder/.stupidgit

Once you've gotten them all (but none of the ones you legitimately want to keep!), commit the changes:

$git commit -m 'Remove superfluous .stupidgit files.'

Now we'll create a new bare Git repository (ie, a repository without a working copy):

$cd .. $git init --bare my-bare-git-repo.git $cd my-bare-git-repo .git $git symbolic-ref HEAD refs/heads/trunk $cd ../my-temp-git-repo $git remote add bare ../my-bare-git-repo.git $git config remote.bare.push 'refs/remotes/*:refs/heads/*' $git push bare $cd ../my-bare-git-repo $git branch -m trunk master $cd ..

At this point, you can delete the temporary Git repo if you want:

$rm my-temp-git-repo -rf

Create a script to convert the tags from Git branches into actual Git tags:

$[your favorite editor] clean-tags.sh

Enter the following:

#!/bin/sh git for-each-ref --format='%(refname)' refs/heads/tags | cut -d / -f 4 | while read ref do git tag "$ref" "refs/heads/tags/$ref"; git branch -D "tags/$ref"; done

Save, then exit back to the command line and run it on the bare Git repo:

$chmod +x clean-tags.sh $cd my-bare-git-repo $../clean-tags.sh

Finally, you're done! You can copy your my-bare-git-repo.git to whatever computer you want, clone from it, push it to BitBucket, etc.

References:

Read more


A Professional Coder With A Dynamic Language...

...is like a professional racer with automatic transmission.

Read more


Stupid Git

Jesus christ, I just want to shoot Git in the face.

I wish Git had a face so I could shoot it in the face.

I wouldn't even be trying to use the stupid thing if TortoiseGit wasn't so damn much better than TortoiseHg.

Of course, with Hg I'd be having all that fun dealing with Python's separate incompatible runtimes bullshit.

Ggrrrraaaaaaaa!!

Read more


Doesn't Anyone Understand Proper Usability Design?

A new Linux user (Debian-based. Umm...the OS, not the user) learns how to install software:

$apt-get install [list of package names] Barf, GTFO. Are you root? $sudo make me a sandwich make: *** No rule to make target `me'. Stop. $sudo apt-get install [list of package names]

Great!

Then eventually they need to upgrade something:

"Obviously I'm not trying to install it, it's already installed! I just want it updated. Hmm, but how do I do that?"

$apt-get --help ... install - Install new packages (pkg is libc6 not libc6.deb) ...

"Hm, ok, yes, once again, it's obviously not install, because I'm not trying to 'Install new packages'. Just update exiting ones. Let's look at the other options..."

update...

"Bam! That must be it!"

(Don't anyone try to tell me you've never been impulsive like this. It doesn't matter how much of an expert you are: You've done it, and you know it.)

$sudo apt-get update foosoft E: The update command takes no arguments

"WTF? Hmm, well I guess I didn't actually bother to read it..."

update - Retrieve new lists of packages

"Oh! Ok, of course that didn't work. Silly me! So then what do I want...?"

upgrade - Perform an upgrade

"The upgrade command upgrades? No crap! (Must have been a job for Captain Obvious and his trusty sidekick, Shit Sherlock.) Well, obviously I want to upgrade the package that I'm trying to upgrade, so it's pretty damn obvious which command to use:"

$sudo apt-get upgrade foosoft ...bunch of upgrading...

"Hmm, it looks like it's upgrading the dependencies, too. Neat! Some of them seem odd, but they must be indirect dependencies. Ah, it's done!"

$foosoft FooSoft v2.8

"Yay! The new version!"

Those of you truly familiar with apt-get already know where this is going...

Months later...(actually around two years in my case...yes, I'll admit this all actually happened to me...)

"I need to upgrade something again:"

$sudo apt-get update^H^H^H^H

"...Crap, that's right, it's the other one:"

$sudo apt-get upgrade barzoom ...whiiirrrrr... done $barzoom Barz Oom v1.0 (Ha ha! You thought it was "Bar Zoom"!)

"WTF! That's the version I already had!"

$sudo apt-get upgrade barzoom Fuck you, I did my job already.

"Grrr!!!"

Do you know what's happening?

The apt-get upgrade doesn't upgrade specific packages. In fact, it doesn't even take any package names as parameters at all, but you wouldn't know that from either the help page or from apt-get's actual response to your command. What apt-get upgrade does do is upgrade all the packages on your system that can be upgraded without new packages being installed. (Apparently, apt-get dist-upgrade does the same, but allows new packages to be installed.)

So normally, it all seems to work fine because the package you request (*ahem*, that is, the package you thought you requested) is one of the packages on your system and apt-get upgrade simply tries to upgrade all of them. But then, when a new version of your program comes out that has a new dependency you don't already have, apt-get upgrade skips your package.

So what are you supposed to do?

Even though apt-get's help page never bothers to mention it, you're actually supposed to use the install command to upgrade any specific programs that are already installed. Yup, that's right. Exactly the command that "obviously" couldn't have been the right one.

Here's what should have happened:

"I want to upgrade foosoft. Hmm, but how do I do that?"

$apt-get --help ... update... ...

"Bam! That must be it!"

$sudo apt-get update foosoft Error: The update command retrieves a list of new packages. It takes no arguments.

"Oh, I see. That was the wrong one. What else is there?"

upgrade...

"The upgrade command upgrades? No shit, Sherlock! Clearly this must be it:"

$sudo apt-get upgrade foosoft Error: The upgrade command takes no arguments because it upgrades all packages (without installing new ones). To upgrade specific packages, use the 'install' command.

"Whaa...? Lemme look at that help page again..."

upgrade - Upgrades all possible packages (without installing new ones) install [package list] - Install or upgrade specific packages

"Ahh, alright. I get it now."

$sudo apt-get install foobar ...whiiirrrrr... done $foosoft FooSoft v2.8

"Yay! The new version!"

Months later...

"I need to upgrade Barz Oom:"

$sudo apt-get update^H^H^H^H

"...Crap, wait, that's just the list of packages."

$sudo apt-get upgrade barzoom Error: The upgrade command takes no arguments because...

(Smacks forehead) "Of course! I knew that! What the hell is wrong with me today?"

$sudo apt-get install barzoom ...whiiirrrrr... done $barzoom Barz Oom v1.0 (Ha ha! You thought it was "Bar Zoom"!)

"Awesome!"

$thank you You're most very welcome, of course!

Remember: When you write software, make sure to think through its interactions through the eyes of a new user.

As a side note, I'm curious: Are there any people out there who primarily use Linux (an apt-get based distro) that didn't already know this about apt-get? If you did know, how did you find out? Did you always know? Drop a note in the comments section!

Read more


If Git cares about speed so much...

...then why is GitHub so goddamn slow? Even compared to BitBucket it's a dog.

LaunchPad is wonderfully zippy, much more than any of the others. It's unfortunate that LaunchPad's interface is so messy.

Read more