JPz'log Coin Coin and Plop da Plop

4Aug/100

Howto: fork a Subversion project with Git

This is a short excerpt on how you can use Git to fork a Subversion project.

I assume that:

  • you want to maintain your own fork of a project, and intend to follow its evolutions
  • you have no commit-access to the upstream Subversion server, or you do not intend to push you changes back.

We will take XStream as a running example.

Import the Subversion project into Git

git svn clone --stdlayout --prefix=svn/ http://svn.codehaus.org/xstream/ xstream-fork

This creates a complete clone of the XStream Subversion repository. Tags and branches will be imported as well (--stdlayout).

Git has local and remote branches. The local ones are those you make modifications too. They generally merge from remote branches, which you can think of as read-only copies of upstream branches.

Git-SVN turns Subversion branches as Git remote branches. The --prefix=svn/ makes it easier to differentiate them from regular Git branches.

What you get

You can check what was imported:

git branch -a
* master
  remotes/svn/pull-parser-merge
  remotes/svn/tags/XSTREAM_0_2
  remotes/svn/tags/XSTREAM_0_3
  remotes/svn/tags/XSTREAM_0_4
  remotes/svn/tags/XSTREAM_0_5
  remotes/svn/tags/XSTREAM_0_6
  remotes/svn/tags/XSTREAM_0_6_RC1
  remotes/svn/tags/XSTREAM_1_0_1
  remotes/svn/tags/XSTREAM_1_0_2
  remotes/svn/tags/XSTREAM_1_0_RC1
  remotes/svn/tags/XSTREAM_1_1
  remotes/svn/tags/XSTREAM_1_1_1
  remotes/svn/tags/XSTREAM_1_1_2
  remotes/svn/tags/XSTREAM_1_1_3
  remotes/svn/tags/XSTREAM_1_2
  remotes/svn/tags/XSTREAM_1_2_1
  remotes/svn/tags/XSTREAM_1_2_2
  remotes/svn/tags/XSTREAM_1_3
  remotes/svn/tags/XSTREAM_1_3_1
  remotes/svn/trunk
  remotes/svn/xmlencoder-spike

By default, your master branch tracks svn/trunk. You can easily make a local branch based on something else, such as the xmlencoder-spike branch:

git checkout -b xmlencoder-spike xmlencoder-spike

Another thing is that tags in Subversion are just folders, so Git-SVN imported them as branches. You may transform those into real Git tags:

git tag -m 'Tag for v0.2' -a v0.2 svn/tags/XSTREAM_0_2

Work!

The best practice in Git is to work with feature branches, so each time you need to work on something, you should really spin a branch!

Choose which local branch to fork, such as:

git checkout -b my-cool-feature master

Make your commits along the way, and when your work is ready to be merged:

git checkout master
git merge my-cool-feature

# Optional, if you don't need the feature branch anynore
git branch -d my-cool-feature

For quick one-offs, you may not need feature branches though.

Synchronize!

To update all Git-SVN remote branches:

git svn fetch

To merge onto local branches that track Git-SVN remote branches:

git svn fetch
git checkout master
git merge svn/trunk
git checkout 3.1
git merge svn/branch-3.1

You may also directly fetch and apply the changes if your branch was created from a Git-SVN branch:

git svn rebase

Make a real Git clone repository available

You can't push Subversion remote branches to another repository, so if you need to make your Git fork public somewhere (such as on GitHub), you will need to:

  • create tags as mentioned above
  • create a local branch for each Subversion branch that you want to republish such as stable branches
  • push those tags and local branches to your public repository.
Share this post:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • Live
  • Netvibes
  • StumbleUpon
  • Technorati
  • FriendFeed
  • Wikio
  • Twitter
  • Identi.ca
  • Reddit
  • RSS
  • Slashdot
29Jul/100

Bring an iPhone 3G back to life from iOS 4

So you've updated your iPhone 3G to iOS 4 and cannot use it anymore due to frequent freezes, seconds-long delays to get taps feedback, and the general sensation that "this is really sluggish!"?

Apple does not provide an official way to downgrade to a previous version of iOS. A real shame as iOS 4 is not usable at all on a 3G while 3.1.3 just worked like a charm.

The solution to downgrade is rather easy though. I won't make this a real tutorial given that there are already lots of them on the Internet, but here is what you have to do.

  1. Grab a 3.1.3 firmware. I recommend looking around on this page.
  2. Grab RecBoot, a utility that puts you in and out of the damn DFU/recovery mode.
  3. Put your iPhone in DFU mode. Opt to restore, but alt+click the button in iTunes instead of just clicking it. Pick the 3.1.3 firmware that you just downloaded.
  4. When the phone reboots you will get an error message. Nevermind, and use RecBoot to get out of the DFU mode.
  5. Enjoy the activation process, and preferably, do start with a fresh setup rather than an old backup.
  6. If you failed during this process then don't blame or sue me. Blame your brain and fingers.

In my case I recovered a fully functional iPhone 3G. I won't upgrade it again to iOS 4 unless Apple makes some serious performance improvements. I honestly think that they made a big big mistake here, making their happy customers angry ones.

Share this post:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • Live
  • Netvibes
  • StumbleUpon
  • Technorati
  • FriendFeed
  • Wikio
  • Twitter
  • Identi.ca
  • Reddit
  • RSS
  • Slashdot
Filed under: English, Geeking No Comments
8Jun/100

nose: testing in Python made easy

I have recently been doing some quick experiments, and chose Python to do that, mostly due to a need for efficient system-level programming APIs. Python just excels at that.

One thing that always annoyed me in Python is the relative poor state of testing frameworks. See, Ruby has RSpec, Groovy/Java have EasyB, Scala has ScalaTest, and much more.

By contrast, Python comes bundled with the unittest module which is basically a straight port of JUnit to Python. This is not the most Python-esque API around, and writing fixture classes can be overkill at times, especially when you are used to the elegance of a BDD testing framework like EasyB. What really surprised me is that there are actually few testing frameworks for Python.

I initially wrote a few tests using unittest, but got quickly bored by the API and the headaches for having the testing code being in another tree of the project, while still being able to import the modules that I wrote.

Fortunately some clever people wrote nose, a testing framework that just works awesomely well. It is actually a tests launcher rather than a testing framework.

It scans the arborescence from where you invoke it, looking for any directory and python file have "test" in its filename. When it encounters such Python file, it will look inside for unittest.UnitTest classes, docstrings,... and any function that also has "test" as part of its name. This gives you a great deal of flexibility, as it will also look for "setup_*" and "teardown_*" functions.

The other selling point in nose is that no matter how deep your test Python scripts / classes are located within your source tree, packages / modules resolution is made from the invocation directory. This means that your main source code folder can have the modules directories as well as a "tests" folder, which is not a Python module, that you can structure cleanly (think separating unit_tests, functionnal_tests, ...) and that will have no issues resolving the modules. Neat.

Finally, nose is flexible through its plugins: you can get HTML output, JUnit-style XML tests reports for continuous integration servers integration, code coverage reports and much more.

If you code in Python, I highly recommend that you give it a try!

Share this post:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • Live
  • Netvibes
  • StumbleUpon
  • Technorati
  • FriendFeed
  • Wikio
  • Twitter
  • Identi.ca
  • Reddit
  • RSS
  • Slashdot
Filed under: Uncategorized No Comments
7Apr/100

Sending an email on iPhone OS

I have been coding on the iPhone OS recently (for a research prototype). The application is basically capturing some data from the GPS and the accelerometers.

The data is stored in a sqlite database that is accessed through Core Data. From time to time, the user can send the data by email. Doing that is extremely easy with the iPhone OS.

I first added a method for creating a CSV representation of the data:

- (NSMutableString*) csvData {
    NSError *error = nil;
	if (![[self fetchedResultsController] performFetch:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
		abort();
	}
 
    NSMutableString* str = [[NSMutableString alloc] initWithString:@"timestamp,altitude,latitude,longitude,xAcceleration,yAcceleration,zAcceleration\n"];
    for (NSManagedObject* entry in self.fetchedResultsController.fetchedObjects) {
        [str appendFormat:@"%@,%@,%@,%@,%@,%@,%@\n",
         [entry valueForKey:@"timestamp"],
         [entry valueForKey:@"altitude"],
         [entry valueForKey:@"latitude"],
         [entry valueForKey:@"longitude"],
         [entry valueForKey:@"xAcceleration"],
         [entry valueForKey:@"yAcceleration"],
         [entry valueForKey:@"zAcceleration"]];
    }
 
    [str autorelease];
    return str;
}

The data is represented as NSMutableString, from which can later extract a NSData representation from. The actual code is just a walk over the data rows that Core Data manages.

The controller method that sends the email is very simple as it uses the ready-to-go MFMailComposeViewController controller.

- (void)sendMail {
    if (! [MFMailComposeViewController canSendMail]) {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Unsupported operation"
                                                            message:@"This device is not configured to send emails." 
                                                           delegate:nil cancelButtonTitle:@"Ok"
                                                  otherButtonTitles:nil];
        [alertView show];
        [alertView release];        
        return;
    }
 
    MFMailComposeViewController* mailController = [[MFMailComposeViewController alloc] init];
    [mailController setSubject:@"Entropia Data"];
    [mailController setMessageBody:@"This data was captured by Entropia.app" isHTML:NO];
    [mailController addAttachmentData:[[self csvData] dataUsingEncoding:NSUTF8StringEncoding]
                             mimeType:@"application/csv"
                             fileName:@"data.csv"];
 
    mailController.mailComposeDelegate = self;
    [self.navigationController presentModalViewController:mailController animated:YES];
}

The mail composition controller gets some pre-defined data: the subject, a message body and a first attachment which is the CSV data we computed earlier.

When the user either taps for sending the email or canceling it, the mail controller delegate is called. It can perform some checks and cleanups to see if the mail was sent or not, but at the very least you must discard the mail controller and release it. Otherwise, your application will stay blocked on that screen!

- (void)mailComposeController:(MFMailComposeViewController *)controller 
          didFinishWithResult:(MFMailComposeResult)result 
                        error:(NSError *)error {    
    [self.navigationController dismissModalViewControllerAnimated:YES];
 
    if (result == MFMailComposeResultFailed) {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[error localizedDescription]
                                                            message:[error localizedFailureReason]
                                                           delegate:nil cancelButtonTitle:@"Ok"
                                                  otherButtonTitles:nil];
        [alertView show];
        [alertView release];
    }
 
    [controller release];
}

As you can see, the iPhone OS provides a very sound and easy framework :-)

Share this post:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • Live
  • Netvibes
  • StumbleUpon
  • Technorati
  • FriendFeed
  • Wikio
  • Twitter
  • Identi.ca
  • Reddit
  • RSS
  • Slashdot

JPz'log is Digg proof thanks to caching by WP Super Cache