Programming in C#, Java, and god knows what not

Mercurial on FreeNAS

Illustration

In search for smallest possible Mercurial installation I remembered my old friend FreeNAS. This is small NAS server (at least in 0.7 version) based on FreeBSD 7.3. System requirements are low: 256 MB of RAM and 512 MB system disk is all that is needed. And, of course, you need to have full installation of FreeNAS. Embedded will not suffice.

I will not explain how to setup FreeNAS here since it works out of box with pure defaults. Only thing to configure is where you want your data to be and this should be easy enough to do by yourself (hint: check “Disks” menu). My final goal is to have equivalent for Mercurial under Ubuntu.

First step is to install needed packets. This can be done from web interface (System->Packages) and following packets are needed (given in order of installation):

Now we need to copy some basic files: [bash highlight=“1,2”] $ cp /usr/local/share/doc/mercurial/www/hgweb.cgi /mnt/data/hg/hgweb.cgi $ cp /var/etc/lighttpd.conf /var/etc/lighttpd2.conf [/bash]

We also need a new config file that should be situated at “/mnt/data/hg/hgweb.config” and it should have following lines:

[collections]
/mnt/data/hg/ = /mnt/data/hg/

[web]
baseurl=/hg/
allow_push=*
push_ssl=false

We need to edit “/mnt/data/hg/hgweb.cgi” in order to fix config parameter. Just change example config line with:

config = "/mnt/data/hgweb.config"

At the BOTTOM of existing “/var/etc/lighttpd2.conf” (notice that we created this file via cp few steps ago) we need to add:

server.modules += ( "mod_rewrite" )
url.rewrite-once = (
    "^/hg([/?].*)?$" => "/hgweb.cgi/$1"
)
$HTTP["url"] =~ "^/hgweb.cgi([/?].*)?$" {
    server.document-root = "/mnt/data/hg/"
    cgi.assign = ( ".cgi" => "/usr/local/bin/python" )
}
$HTTP["querystring"] =~ "cmd=unbundle" {
    auth.require = (
        "" => (
            "method"  => "basic",
            "realm"   => "Mercurial",
            "require" => "valid-user"
        )
    )
    auth.backend = "htpasswd"
    auth.backend.htpasswd.userfile = "/mnt/data/hg/.htpasswd"
}

This config will ensure that everybody can pull repositories while only users in .htpasswd file can push. If you want authorization for pull also, just delete two highlighted files. Notice that users are defined in .htpasswd file that needs to be created with htpasswd command-line tool. Since that tool is not available in FreeNAS easiest way to get user lines is to use online tool.

In order to test how everything works, just go to shell and restart lighttpd with new config:

kill -9 `ps auxw | grep lighttpd | grep -v grep | awk '{print $2}'`
/usr/local/sbin/lighttpd -f /var/etc/lighttpd2.conf start

If everything goes fine, you should be able to access repositories at “http://192.168.1.250/hg/” (or whatever you machine ip/host name is).

As last step we need to add those two commands above (kill and lighttpd) to System->Advanced->Command scripts. Both lines get into their own PostInit command. This ensures that, after every reboot, we start lighttpd with our “enhanced” config file.

P.S. Do not even try to edit “/var/etc/lighttpd.conf”. It gets overwritten after every restart.

P.P.S. This post is just about enabling Mercurial under FreeNAS and because of this it is simplified. It is mere starting point. For further reading check official Publishing Repositories with hgwebdir.cgi guide and my guide on setting-up Mercurial under Ubuntu.

Getting String Value for All Object's Properties

In last post I wen’t through task of restoring properties from their textual representation. But how did we end up with text?

It is as simple as loop through all public properties and then using TypeConverter in order to properly convert a value to it’s string representation. Do notice that ConvertToInvariantString is preferred over ConvertToString in order for code to properly work on non-USA Windows.

public static IDictionary<string, string> GetPairs(object objectInstance) {
    var result = new Dictionary<string, string>();
    foreach (var propertyInfo in objectInstance.GetType().GetProperties()) {  //loops through all public properties
        var propertyConverter = TypeDescriptor.GetConverter(propertyInfo.PropertyType);  //gets converter for property
        var stringValue = propertyConverter.ConvertToInvariantString(propertyInfo.GetValue(objectInstance, null));  //converts value to string
        result.Add(propertyInfo.Name, stringValue);
    }
    return result;
}

P.S. Saving key/value pairs to file is not shown here… guess how it is done… :)

Setting a Value From String

It all started with list of key value pairs from file. Each key was some property on object that needed to be set and value was obviously value for that property. Since there was no type information in file, I had to use reflection in order to set value. And then problem hit me. Reflection would not sort out my problem with converting string value to proper type.

To solve it, I just loop through all key/value pairs and find property with that name in my object’s instance. Once property is found, I get a magic thing called TypeConverter. TypeConverter enables conversion from string to proper type that can be used in standard reflection SetValue call. And thus problem is solved. Code follows:

foreach (var item in pairs) {                                                                         //go through all key/value pairs
    var propertyInfo = instance.GetType().GetProperty(item.Key);                                      //find property with same name
    Trace.Assert(propertyInfo != null);                                                               //we must have this property
    var propertyConverter = TypeDescriptor.GetConverter(propertyInfo.PropertyType);                   //lets find proper converter.
    Trace.Assert(propertyConverter != null);                                                          //we must have converter
    propertyInfo.SetValue(instance, propertyConverter.ConvertFromInvariantString(item.Value), null);  //set value
}

Microsoft’s All In One Code Framework

Browsing through one Belgian guy’s blog I found news about Microsoft’s All In One Code Framework.

In short, it is a site where you should be able to find best practice code samples. You can even make a request for some sample that you need. Of course, not all requests will be granted but interesting and much sought code should appear there eventually.

Of course, anybody can upload their code sample for any request and thus take some load off poor Microsoft guy who got writing samples as a task. :)

It is interesting idea, but let’s wait whether usefulness/noise will be better than rest of Internet.

Directory.Move Is Case Insensitive

In order to rename file one would use code that looks something like this:

File.Move("file1.txt", "file2.txt");
File.Move("file.txt", "FILE.txt");

Both lines work without any issue, just as you would expect it.

What happens when we do rename with directories (aka folders):

Directory.Move("dir1", "dir2");
Directory.Move("dir", "DIR");

First line works but second one raises IOException (Source and destination path must be different). For some reason Directory.Move does case insensitive checks. For this to work we need slightly different code:

Directory.Move("dir", "DIR.somereallyunexpectedtext");
Directory.Move("DIR.somereallyunexpectedtext", "DIR");

This code first renames directory to temporary name and then renames it to desired one. Tricky code not shown here is exception handling. Either Directory.Move can fail and thus we would need code like this:

Directory.Move("dir", "DIR.somereallyunexpectedtext");
try {
    Directory.Move("DIR.somereallyunexpectedtext", "DIR");
} catch (IOException) {
    Directory.Move("DIR.somereallyunexpectedtext", "dir");
} catch (UnauthorizedAccessException) {
    Directory.Move("DIR.somereallyunexpectedtext", "dir");
}

For any failure cause we need to do rollback (renaming it back to original name from intermediate one). And worst thing is that, if second rename fails, there is probably no chance in rollback working anyhow. Most common solution? Just forget about handling exceptions and rollback between those two renames. Probability is on your side that, if first operation passes, other will pass too.

Canceling Dialog

As I made review of one application I got reminded of one common error. Theory of cancel button is easy enough. It is enough to set button’s DialogResult to Cancel and form’s CancelButton property to that button and form will close automatically. However, what to do if we need to cancel some background operation?

More than once I saw cancel code inside of cancel button’s Click event. This is WRONG. If you are wondering why, just take a look at your application state when somebody decides to close dialog via small red button in upper right corner instead of pressing cancel button. All that carefully crafted cancel code never gets chance to execute.

Solution is trivial. All your code should go inside of either FormClosing or FormClosed event. These events get triggered whatever way you do form cancelling:

    private void Form_FormClosed(object sender, FormClosedEventArgs e) {
        if (backgroundWorker.IsBusy) { backgroundWorker.CancelAsync(); } //just an example of cancellation code
    }

Cancel button should NEVER have any code in it.

P.S. Whether to use FormClosing or FormClosed is mostly matter of philosophical discussion that I intend to leave for other post.

Select or Focus, Which One to Use?

Quite a few Windows Forms controls have both Focus() and Select() methods available. This presents unique challenge - which method to use?

While they both offer same result (ok, almost same) there is subtle difference. Focus is intended only for control authoring, e.g. when you have some composite UserControl. For all other scenarios, Select should be used. Probably nothing bad will happen (or maybe some kittens will die) if you use Focus on controls that behave. However, small differences might force you to use Select on some other controls and that leads to code with uses Focus half of time and Select another half. Kinda hard to read.

It might improve actual readability if Select is used all the time.

Nullable Fields in Database

Duty of every decent Data Access Layer is to convert data types that we have in database to data types of our favorite programming language (C# in this case). And this is easy in case of “normal” data types. Great example here is humble integer. Database and C# have 1 to 1 mapping here. It is as easy as “var x = (int)dr["field"];”.

However, database can have one more trick up it’s sleeve. Every data type can be “nullable”. That is, it can be integer but it can also have special state which signifies lack of data. C# also has same possibility with his nullable types. Intuitive code “var x = (int?)dr["field"];” will not work properly.

While we can make wrapper function for any nullable data type that we need, there is simpler way. All that we need is:

private static Nullable<T> ToNullable<T>(object value) where T : struct {
    if (value == null) { return null; }
    if (System.Convert.IsDBNull(value)) { return null; }
    return (T)value;
}

Now conversion can proceed with “var x = ToNullable(dr["field"]);”. That doesn’t look that ugly, does it?

Detection of Executing Program in Inno Setup

Illustration

When upgrading your application it is very good practice to let your setup program know whether your application is running. This way setup will tell you to close your application instead of requiring Windows restart.

Solution comes in form of Mutex synchronization primitive. Application will create it and hold it until it is closed. If setup notices that application already has mutex under control, it will “complain” to user. It is then user’s task to close application. It is not as comfortable as closing application automatically but it does the job.

Since we need a global mutex for this purpose, we should not use something that could get used in other application for other purpose. To me best format of name is MyCompany_MyApplication. It is highly improbable that anybody else would use it. If you want to be (almost) sure getting random string is also a possibility.

For this to work we need to tell InnoSetup which mutex we plan on holding:

[Setup]
...
AppMutex=Global\MyCompany_MyApplication
...

In application we need to use same Mutex name:

namespace MyNamespace {
    internal static class App {
        private static readonly Mutex SetupMutex = new Mutex(false, @"Global\MyCompany_MyApplication");

        [STAThread]
        internal static void Main() {
            //do some great stuff.

            Application.Run(new MainForm());

            SetupMutex.Close(); //notice that it HAS to be after Application.Run
        }
}

P.S. Why do we MUST put SetupMutex.Close() after Application.Run() is exercise left to user. I will just note that it has something to do with garbage collection.

P.P.S. While this was written with InnoSetup in mind it is also applicable to virtually all setup systems out there.