thinking in geek tagline’s are so web2.0

YouTrack vi keyboard navigation (j/k and h/l)

Youtrack is an awesome bug tracker. One of it’s best features is that it can be (almost) entirely keyboard driven.

Unfortunately – Jetbrains in their wisdom did not adopt god’s designated keys for moving up and down lists j/k – instead opting to use the cursor keys – forcing users to move their hands from the home row. This has been requested and turned down by the team in JT-565 and JT-5687.

I’m a long standing user of Gmail which uses j/k for moving up and down the list of messages – and it’s difficult to have to go back to moving my hands around. After a couple of days – I decided that a greasemonkey script was called for.

No warranty is implied or given – but this works for me (at least a little bit): youtrackvi.user.js

You’ll need to update the @match with your local youtrack url.


Localizing asp.net applications

I’ve recently had to localize a large software as a service application to support multiple european languages. Overall this was pretty straight forward – because I found a couple of really useful tools.

Resex – This is a resource file editor. It lets you edit a set of resource files side by side – which is very helpful when your trying to figure out what’s been translated and whats still to got. This is especally important when your doing the first translation pass through you app pulling literal strings out of code.

Resource Refactoring Tool – a super easy to use Visual Studio addin which adds a Refactor to Resource refactoring to the ide. It doesn’t currently support any Web project types – but it was still really useful for class library projects.

I was out of time to add Web project support to the Resource Refactoring Tool – so I ended up writing a VS macro to help with the localization of .aspx pages. This was pretty specific to my environment – but it worked well enough.


git svn on windows speedup now in git “next” branch”

Update: This page incorrectly stated that this patch was included in git 1.7.0.1. It’s not! It’s in the git repository’s “next” branch – which will eventually become the git 1.7.2 series. I’ll update again when this is released.

The lovely people on the git mailing list have accepted my patch to include this speedup in the main git distribution. (It’s in git’s “next” branch and will probably be released as 1.7.2 so it’s not yet included in the latest msysgit release).

It lives here.

It didn’t take long to figure out how to package it up using git format-patch once I read SubmittingPatches.txt.

The whole thing was much less scary than I imagined. Thanks to Johannes Schindelin (of msysgit) for nursing me through the process as a complete newb!

This was my first contribution to an OSS project using git (ironically – the project itself was git) – and I’m _amazed_ how much smoother the process was than using SVN/patch files.

I’m now more optimistic that Castle Project’s move to git hub will bring some big benefits.


Speeding up git svn on Windows (win32)

Update: This fix is now included in git releases 1.7.0.1 and greater – for more info – click here.

Update 2: This page incorrectly stated that this patch was included in git 1.7.0.1. It’s not! It’s in the git repository’s “next” branch – which will eventually become the git 1.7.2 series. I’ll update again when this is released.

Some people have noticed that using git svn (in my case msysgit) on Windows VM’s1 can be incredibly slow. I’m one of those people.

Running a no-op rebase (i.e. there are no changes @ the svn end) looks like this.2

$ time perl git svn rebase
Current branch master is up to date.

real 2m56.750s
user 0m3.129s
sys 2m39.232s

Nearly 3 minutes to verify that my local git svn branch is up to date!

I used to (_many_ years ago) – do quite a bit of perl for for sysadmin stuff. I’ve already paid for those sins but this was slow enough that I wanted to see what was causing the problems.

Running perl -d:DProf and collecting a basic trace gave me some interesting info.3 SVN::Base::import (essentially a constructor) was importing all the svn dll entry points (using DynaLoader) every time git svn started up – which was extremely slow in my environment.

On a hunch4 I moved the code which was require’ing SVN::Base::import to run lazily (rather than at git-svn startup).

$ time perl /libexec/git-core/git-svn rebase
Current branch master is up to date.

real 0m33.407s
user 0m1.409s
sys 0m23.054s

6 times faster!

“git svn dcommit” sped up even more. Previously:

$ time perl /libexec/git-core/git-svn.orig dcommit -n
Committing to svn://XXXXX/trunk ...
diff-tree befd87ba1b65fa7d86779c3058faf1f4886d7020~1 befd87ba1b65fa7d86779c3058faf1f4886d7020

real 3m7.046s
user 0m3.190s
sys 2m53.897s

Afterwards:

$ time perl /libexec/git-core/git-svn dcommit -n
Committing to svn://XXXXX/trunk ...
diff-tree befd87ba1b65fa7d86779c3058faf1f4886d7020~1 befd87ba1b65fa7d86779c3058faf1f4886d7020

real 0m10.312s
user 0m1.109s
sys 0m4.632s

19 times faster!

For me – this was enough for now. I’d spent more time on the issue than I had – and git svn operations were now fast enough to not totally break my workflow.

I’ve uploaded the patch here: git-svn.patch

YMMV/No warranty expressed or implied/IANAL etc. If it breaks your repo/application/life – don’t come crying to me.

Thanks to Nic Wise for testing this for me and validating my timing data etc.

  1. VMWare Fusion WinXP vm under OSX 10.5. This is probably important as people not using git svn on a VM don’t seem to sufffer such huge perf problems. []
  2. [1] My svn server is 350ms away – Auckland<->London and on a VPN – I’m using the SVN protocol to access it – SVN seems fastest of the SVN protocols. []
  3. Total Elapsed Time = 140.4030 Seconds
    User+System Time = 3.919008 Seconds
    Exclusive Times
    %Time ExclSec CumulS #Calls sec/call Csec/c Name
    77.7 3.046 3.046 12 0.2538 0.2538 DynaLoader::dl_load_file
    9.16 0.359 0.359 1 0.3590 0.3590 main::read_repo_config
    6.38 0.250 0.250 18 0.0139 0.0139 Git::_command_common_pipe
    1.22 0.048 3.063 40 0.0012 0.0766 SVN::Base::import
    1.20 0.047 0.156 22 0.0021 0.0071 main::BEGIN
    0.41 0.016 0.016 4 0.0040 0.0040 Exporter::as_heavy
    0.41 0.016 0.032 7 0.0023 0.0046 IO::File::BEGIN
    0.41 0.016 0.016 11 0.0015 0.0015 Git::SVN::BEGIN
    0.41 0.016 0.016 7 0.0023 0.0023 Git::SVN::rev_map_max_norebuild
    0.41 0.016 0.016 7 0.0023 0.0023 SVN::Git::Fetcher::BEGIN
    0.38 0.015 0.015 1 0.0150 0.0150 warnings::BEGIN
    0.38 0.015 0.015 7 0.0021 0.0021 Git::BEGIN
    0.38 0.015 0.015 13 0.0012 0.0011 Error::subs::try
    0.00 0.000 0.000 1 0.0000 0.0000 XSLoader::bootstrap_inherit
    0.00 0.000 0.000 1 0.0000 0.0000 Exporter::Heavy::heavy_export_tags

    []
  4. git-svn shell’s out to itself a bunch so it seemed an obvious first step. []

ASP.NET == Usability disaster?

[This has been in the queue for a long time - over 12 months - codebetter just tipped me over the edge!]

Peter Van Dijck asks:

I’ve only worked twice with companies using .NET for web interfaces, and in both cases the UI was a disaster and the usability problems guaranteed lots of consulting hours.. Why is that? Or was that a fluke? (2 cases is hardly proof of anything) I know it’s possible to make usable and elegant web UI with any technology, but does .NET somehow encourage bad UI?

This is a great question and in my opinion – the answer is yes. (Assuming that Peter really means WebForms.)  spike pit of death

This is demonstrated in so many small ways by framework defaults which are totally brain dead (__doPostBack anyone?). Rather than lead dev’s into the pit of success – the framework leads devs to the spiky elephant trap of death. 

 
What’s that – an example? How about the <customErrors> defaults. When an error occurs during processing an ASP.NET request – the default behavior of a new web.config is to redirect the user to another URL. This is what a new web.config looks like in VS2k5. 

        <customErrors mode=”RemoteOnly” defaultRedirect=”GenericErrorPage.htm”>

            <error statusCode=”403″ redirect=”NoAccess.htm” />

            <error statusCode=”404″ redirect=”FileNotFound.htm” />

        </customErrors>

This is really brain dead behavior! Let’s count the ways: 
1. There’s no way to change the HTTP status code from a html page. (E.g. – should be 404, 500 etc). This is just flat out bad – status codes are important for lots of reasons.
2. The effing URL will change. This makes it difficult to correct typing errors or retry a request in case of a server error (500). 
3. Those files don’t even exist! You can get a 404 when the real error is a 500 because the file that your getting redirected to don’t effing exist! 
This just happened to me – I was just wondering if there is a port of the monorail SmartGridComponent to ASP.NET MVC. I do a Google search and get a likely looking result for Billy McCafferty’s blog. I click on the link and I get the following page: 
Oops something went wrong!
Either the site is offline or an unhandled error occurred. We apologize and have logged the error. Please try your request again or if you know who your site administrator is let them know too.

 

The URL in the browsers address bar is: 

http://devlicio.us/error.htm?aspxerrorpath=/themes/blogs/default/post.aspx

HOW the F$%K do I try my request again?
If I’ve opened this result in a new tab (which is my habbit) I’m screwed! There is no back button, refresh (F5 or whatever) just reloads the error page and will never show me the correct page.
If I just clicked the link – the back button takes me back to my google search where I can click on the link again – refresh is still borked. 

Another example? Linkbutton? Anyone who’s tried to open a link in a new tab/window and got a blank window with a URL like: javascript:__doPostBack(‘ctl00$Masthead1$LocaleManagement$ctl00$ctl05′,”) – knows the pain I’m talking about. 

Go on – right now – go try and open a MSDN library page in different language in a new tab. (It’s the little menu up the top right where it says (e.g.): United States – English). 

In my apps – I fix this by disabling customErrors and writing new error handling code which both maintains the url and returns the correct HTTP statuses – but this is code which I should not have to write. This is code which all web servers/apps need to implement correctly – it should be automatic. We shouldn’t have to write custom code to get a HTTP/404 returned when an app encounters a missing file!


A week on mars.

[Warning - digression ahead]

Over the last two weeks I’ve been trying to buy some speakers for (2 channel) music listening.  I’ve listened to a lot of speakers: 

I’ve finally chosen some Jamo c803′s.

The best floorstanding speaker I listened to was the Krix Phoenix – it was also the cheapest (and locally made). 

The best bookshelf was maybe V3M or the XQ20 or the Focus 140′s. They weren’t enough better to justify more than 2x the price though and since I didn’t listen to them in the same session or location – it’s possible they weren’t even better. 

Anyway – it’s been interesting. It turns out that the HiFi/AV/Audiophile world is another planet. A planet where:

Best of all – many of these “subjectivists” claim that double blind testing interferes with the results. 

Which is to say that after this – arguments about ORM’s seem welcome.


The worlds atwitter…

..and so am I.

Somehow – twitter has clicked for me. It could be related to checking out clients and liking Twitterrific enough to keep it running. 

It’s fair to say that twitter itself it pretty unreliable – but it doesn’t seem to matter too much. I’m living proof – somewhat available is good enough for some apps. 


SVN 1.5

Well – (finally) Subversion 1.5 is out! 

For the first time svn has built in support for repeated merges without spurious conflicts or manually managing the list of previously merged revisions.

This is _fantastic_ news. The basis of the merge tracking feature in 1.5 was svnmerge.py which means that many svn users will already have a reasonable idea how it works. (List of merged revisions are stored in svn properties on a branch). 

I’ve been watching the development of svn 1.5 for the last 18 months (give or take) crying everyday that I have to manually manage merging work as I oggle the feature list. 

TortoiseSVN has a significantly enhanced release as well. I’m particularly excited about this because it supports caching the change log which will make a huge difference for me given that my svn server it 2 continents and 300ms away.

It also looks like there may be some progress on cleaning up the working copy implementation.1. Which would involve fixing the whole every folder with .svn folders problem (a la git or svk). 

  1. http://subversion.tigris.org/roadmap.html []

The only way is up

From an altnet list discussion about Team Build (part of TFS):  

On Thu, Jun 12, 2008 at 7:35 PM, David Kean wrote:  

Team Build is more than just MSBuild, it includes build management (retention, CI, drop management, etc). The next version will be even more powerful and based on Windows Workflow.  

 

On Fri, Jun 13, 2008 at 2:43 AM, Ayende Rahien wrote: 

And here I thought that the only way to go was up. 

 

Pure gold. 


Crappystrano

Note: After I started this series Jeremy Miller has posted a very relevant article about source code hygiene issues.

(This is the third part in a series – you should probably read part one and two first.)

Today I’ll present a sanitised copy of my deployment script. I’ve based the design of deploy.cmd on Capistrano1 . The script is nicknamed “Crappystrano”. Here’s the output (pretty htmlized source is here):

>deploy.cmd

Crappystrano – the shit script which (sort of) deploys stuff

deploy.cmd staging|live [branchpath]

Here’s breakdown of the steps2 – skipping some error checking3. :

  1. Do we have the required dependencies4 on the path? If we don’t copy them to the path if they’re just 1 exe – otherwise exit with an error.
  2. Check the command line parameters. We must have the environment we’re releasing to? Are we releasing from the trunk or from a SVN branch?
  3. Construct a release time stamp. This is YYYYMMDDHHMMSSMS.
  4. Perform a “svn export” from the trunk/branch to %tmp%\staging|live%timestamp%. [E]
  5. Use msbuild to build the solution. [E]
  6. Rearrange the folder structure so we only get the artefacts we need in the release package.
  7. Zip up the release package using the environment name + time stamp.
  8. move the release package back to the root directory of the project and delete the export from %tmp%.
  9. Make a SVN tag (svn copy trunk/branch /tags/environment-timestamp).

I’ve uploaded a zip file with the script and folder structure + a little readme. This is not the best way of doing things – it’s just a very lightweight way. Comments, questions, feedback etc… are gratefully received.

  1. http://www.capify.org/ – I know some people are going to say – just use Capistrano. There are two reasons for me not to: 1. I’m the only person in my team familiar with Ruby. 2. Even if you argue that they don’t need to understand ruby to run a cap deployment recipe – they still have to have it installed. It’s just yet another dependency which I’m not willing to take currently. []
  2. This is all simplified as the actual script supports a SaaS product which has multiple instances – one per client []
  3. noted with [E] []
  4. gnu zip.exe, svn []

← Before