Monday, July 29, 2013

Sidestepping Windows NTFS Path Length Limitations

I was trying to compare a set of tests in Quality Center (QC) against some test scripts I had on a network drive. I decided to dump the QC tests to folders, so I can use "Beyond Compare" to make the comparison.

Problem:

The problem I hit however, was the path length limitation of NTFS. It seems that although NTFS allows quite long path names (around 32767 character) the dos path can't be more than 259 (or something like that). 

Lots of the tests, and most of the folders, in our test tree have long names, meaning we were easily hitting this limit. 

Solution:

Remembering that NTFS allows symbolic links (through the "mklink" command) I decided to:
  • For each folder in QC
    • Create a folder C:\Dump\[QC folder id]
    • Create a symlink in it's parent folder (C:\Dump\[QC parent folder id]\[full name of the folder]) to the C:\Dump\[QC folder id]
  • Dump the tests in the C:\Dump\[QC folder id] folders, naming the files to match the test names. 
This gave me a tree of symlink folders I could navigate that matched the QC folders exactly. Beyond Compare 3.2+ has an option to follow symlinks, which makes this all useful.

Gotchas:

My export script is written in Ruby. I hit a problem trying to execute `mklink /D #{from} #{to}` directly from Ruby. In the end I made a simple bat file:

mklink /d %1 %2

which I called from ruby

puts `link.bat "#{from}" "#{to}"`

See the source at https://gist.github.com/NigelThorne/6102634


Thursday, April 18, 2013

Please define "background" for me...

Getting a HTTP 501 When Starting a Project in Stash


I just started using "Stash" at work. I started a project and tried to push my existing git code into their repo.


c:\LeicaAutomation>git push origin master
Username for 'http://xxx:7990': nwt
Password for 'http://nwt@xxx:7990':
Counting objects: 2010, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (882/882), done.
error: RPC failed; result=22, HTTP code = 501
fWatal: The remote end hung up unexpectedly
Writing objects: 100% (2010/2010), 448.82 MiB | 86.20 MiB/s, done.
Total 2010 (delta 1441), reused 1442 (delta 1059)
fatal: The remote end hung up unexpectedly
Everything up-to-date

c:\LeicaAutomation>git config http.proxy ""

c:\LeicaAutomation>git push origin master
Username for 'http://xxx:7990': nwt
Password for 'http://nwt@xxx:7990':
Counting objects: 2010, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (882/882), done.
Writing objects: 100% (2010/2010), 448.80 MiB | 16.37 MiB/s, done.
Total 2010 (delta 1442), reused 1441 (delta 1059)
To http://xxx:7990/scm/AUTO/leicatestframework.git
 * [new branch]      master -> master

c:\LeicaAutomation>
Removing my proxy settings fixed it. Hope this helps.

Friday, July 22, 2011

Heroku, Node.js, CoffeeScript, Redis, Express...

I read http://blog.xebia.com/2011/06/getting-started-with-node-js-npm-coffeescript-express-jade-and-redis/ and loved it!

My first thought was "Heroku support all these technologies right? Let's get it running on there!" --- and it worked!

To get this working on Heroku I needed to include some ideas from here to get Redis working.

The end result is here, and the source is on Github.

If I get enough comments I'll write a step by step how-to, but basically ...
* Download my code.
* Use the ruby heroku gem to create a heroku app and turn on redis
* Use git to deploy..

That's all you need.

Update: Sorry the app is down at the moment. It has been ages since I last looked at it, and Heroku have upgraded the instances since then.

Thursday, December 30, 2010

When thinking Design, think Jobs vs. Skills

I've been trying to get people to see that code should be built as layers of building blocks for some time. It's only just occurred to me how to explain another dimension of design that I see lacking most of the time in code I have to deal with.

It's what people refer to when they talk about building your language towards you domain. The idea is that you should be able to clearly concisely describe your problem domain in your language. If you can't they you end up with domain objects getting their hands dirty with implementation details.. like "how lists work in this language" or "managing back references" etc...

Here's my thought... Your building blocks should be separable into Skills and Jobs. Jobs are specific roles played by objects in your code. Skills are transferable, then include the details of how you manage to achieve things. You could reuse the skills in many different jobs.

When your domain objects are not <5 methods each with <5 lines... then see what skills your object has and factor them out.

Sometimes this will be extension methods on basic types (or lists, arrays, etc.), other times it's make a specific collection type that doesn't reference your domain, but identifies the relationship items of the collection have.

Does this make sense?
Do I need an example?
Is this just obvious?

Ok... needs an example.


I found this code on github... it's part of the Player class for a Battleships game.
   public void TakeTurnAutomated(Player otherPlayer)
        {
            bool takenShot = false;
            while (!takenShot)
            {
                int row = rnd.Next(GRID_SIZE);
                int col = rnd.Next(GRID_SIZE);

                if (EnemyGrid[row][col].Type == SquareType.Unknown)
                {
                    Fire(row, col, otherPlayer);
                    takenShot = true;
                }
            }
        }
The point I was trying to make is .. the intent of this code is to fire on the first random location that is 'unknown'... so it should say that. One way would be something like this...
public void TakeTurnAutomated(Player otherPlayer)
        {   
   Fire(RandomLocations.First(IsUnknown), otherPlayer);
        }
Or this...
public void TakeTurnAutomated(Player otherPlayer)
        {
   Fire(RandomUnknownLocation, otherPlayer);
        }

private Location RandomUnknownLocation
{ 
  get{
    return EnemyGrid.UnknownLocations.SelectOneAtRandom();
  }
}

Here.. SelectOneAtRandom becomes an extension method to IEnumerable. We don't care how it selects one at random.. as long as it doesn't take too long about it. Picking an item at random is a Skill we have... we use it in the Job of selecting a random unknown location. Any clearer?

GitHub Projects