This page will be used to keep track of progress made on the MacPorts.Framework GSoC project. It can be viewed as a blog of sorts.

Week 1

  • I spent most of this week with family so didn't get to do too much. Most of my time was spent on reading the current Framework code.
  • I made sure that commit access was working ok. There were a few initial problems with that.
  • I managed to get the current MP.Framework to compile on my mac.
  • There were some problems getting the current OCUnit tests for MPInterpreter to compile. My mentor suspects that it has something to do with the "thread protection" code that is part of the method being tested. We'll be looking more into figuring that out but won't spend too much time on it. Ping me for more details.

Weeks 2 & 3

These past two weeks were spent:

  • Writing a MacPortsFrameworkTester GUI because I hadn't figured out how to get Unit tests working yet and wanted to start some preliminary testing.
  • After some help from Chris Hanson (Hanson's Unit Testing Posts) and a lot of fuddling, I finally got the Unit tests to work. There were two main issues as far as I could tell:
    1. Setting correct "Compliling Sources" for the Test Bundle: This I think only needs to include the *test.h and *test.m classes i.e. the classes that contain the unit tests. Since we already had a dependency on MacPorts.Framework set in the Test Bundle, we didn't need to include any of its source files in the compile stages for the Test bundle. Doing this led to some really weird behavior. For example, in MPInterpreter.m, asking for the bundle of the class returned the Test bundle instead of the MacPorts.Framework so we couldn't find any resource files etc.
    2. The Bundle Loader settings had been set to $(BUILT_PRODUCTS_DIR)/MacPorts.framework/MacPorts. Changing this setting to blank for all configurations for the Test bundle finally fixed the rest of the problems.
  • I was also at WWDC from June 9 - June 13 and got to have lunch with drernie, wms and some other Apple Engineers, was lots of fun.
  • I am currently working on writing more Tests and merging the current code from my mentor on notifications into my branch. Speaking of notifications, we are currently facing a design issue which I will document below as best as I possibly can, the reason being that we are looking for feedback.

Notifications in MacPorts.Framework
The framework is suppose to be able to notify the system of port activities that it performs. Depending on the print options set by a user (debug, info) etc. various port messages are sent to STDOUT during the execution of a port command. Our current solution to for Notifications involves listening for these messages and posting global/local NSNotifications as they arrive. (See notifications.m in gsoc08-framework/ for some preliminary code by rhwood for this).

Is there a better way to go about doing this? If at all possible, we would like to not have to change code in the current macports1.0/ or ports/ folders. You can ping me on irc (Armahg) or email armahg@… with suggestions or more questions on the "problem".

Weeks 4 & 5

I have completed documenting (with some gaps and holes) all of the Foundation Framework's classes. Of course that will undergo a couple of revisions.

I also, completed bare, smoke Unit Tests for the MPMacPorts and all of those run successfully. I will be unit testing more thoroughly later. For the most part, the current tests check that return values are not null, as opposed to checking for correctness which I think they should do.

We currently have a way to implement NSNotifications from within the TCL API. This is thanks to sample code from Growl and help from my mentor. More on that later this week. Hopefully with enough refinement, it should be an acceptable solution to the Notfications issue.

I am currently using a build of MacPorts from the source code in trunk. This was my first time doing this. I have been able to get the Framework running and passing tests on this new build (which includes a patch to allow for the Notifications sending). Whilst installing MacPorts from source, I ran into a problem with Pextlib 1.0 not being found. A little Googling showed me that this problem has occured before for some other users. If you try to install MacPorts from a trunk source build and have that problem, symlink tclsh in /usr/bin/ to tclsh8.4.7, it would have previously been pointing to tclsh8.4. That cleared up the problem for me.

Weeks 6 & 7

So things took a somewhat different (and I think positive) turn these past two weeks. I added some more routines for port activation, deactivation and uninstallation to MPMacPorts class.

In addition Randall suggested the following method to be used for evaluating strings as tcl commands instead of the original NSArray parsing we were doing. This meant that code that originally looked like:

-(NSURL *)pathToPortIndex:(NSString *)source {
   return [NSURL fileURLWithPath:
                 [interpreter evaluateArrayAsString:
                            [NSArray arrayWithObjects:
			       @"return [macports::getindex",

now looked like:

-(NSURL *)pathToPortIndex:(NSString *)source {
  return [NSURL fileURLWithPath:
	   [interpreter evaluateStringAsString:
	[NSString stringWithFormat:@"return [macports::getindex %@ ]", source]]];

This definitely made for much more cleaner code. In fact it led to my writing a generic function for evaluating a given Tcl command with an array of arguments. Each element in this array can be either an NSString or NSArray for flexilbility. Also, there's no limit to the size of the argument array. The method looks like:

- (void)execPortProc:(NSString *)procedure withParams:(NSArray *)params {
	//params can contain either NSStrings or NSArrays
	NSString * sparams = @" ";
	NSEnumerator * penums = [params objectEnumerator];
	MPInterpreter *interpreter = [MPInterpreter sharedInterpreter];
	id elem;
	while (elem = [penums nextObject]) {
		if ([elem isMemberOfClass:[NSString class]]) {
			sparams = [sparams stringByAppendingString:elem];
			sparams = [sparams stringByAppendingString:@" "];
		else if ([elem isKindOfClass:[NSArray class]]) {
			//Maybe I should be more careful in the above if statement and
			//explicitly check for the classes i'm interested in?
			sparams = [sparams stringByAppendingString:[elem componentsJoinedByString:@" "]];
			sparams = [sparams stringByAppendingString:@" "];
	[interpreter evaluateStringAsString:
	 [NSString stringWithFormat:@"[%@ %@]" , procedure, sparams]];

thanks Randall.

Second thing worth mentioning I think I have found a solution to Notifications in the framework. I won't give too many details but basically it involves having a "bridge" singleton instance class between the Tcl API and Framework. When a ui_$priority procedure is calls, it in turn calls a notifications procedure which calls a method (and this can be any method) of the "bridge" class. This method can be a notification, message to a Framework class, delegate triggering method ... the important thing is the Framework is notified of the change without having to do a system-wide broadcast (e.g. NSDistributedNotification center notification). More details after this has been refined. The current code for it has been checked into svn.

Finally, I'll be releasing a MidTerm Evaluation version of the Framework today. IT HAS NOT BEEN TESTED. The main purpose is for feedback on the current functionality as is being advertised by the Docmentation. The main things it is currently lacking are incorporation of Authorization, finished Notifications and thorough Testing. Any and all feedback is welcome. The .dmg and .zip files can be downloaded from svn by doing

svn co for the dmg

svn co for the .zip file

and svn co for the whole folder

Weeks 8 & 9

I scrapped my initial solutions to the Notifications issue and just embedded all the code for the Tcl notifications command within MPInterpreter.m. I also added an MPNotifications class whose main function is to let Framework users block and unblock sending of various notifications. It seems like too much flexibility on first thought: A framework user can turn on e.g. Debug notifications, then choose to register for them or turn them off. Why didn't I just let users choose to register and then send all notifications? I didn't want the Framework to become sluggish because of NSNotification "flooding".

I was almost done with most of the Framework's functionality when I ran into a small problem: Authorization. Technically, the approach we are using is to use NSError handling to report errors to Framework users, they can then proceed from there by taking an appropriate action based on the error reported. I decided to try this out by putting myself in the shoes of a Framework User (with the Framework Tester GUI App.). What I found out was that, for processes that required running as root, we couldn't do things the way Apple recommends. This is because we haven't really factored out root operations into some binary executable within the Framework.

I was a bit panicky at first but then I realized, we could just have an executable that called the very same method that we were calling before (with the right arguments of course). So right now here is our basic policy for Authorization. We have our own internal auth ref which we preauthorize. We have clients implement a delegate method with which they can override our internal auth ref with their own. When it comes to time to call the root process, we check for authorization with whichver auth ref we happen to have. If we gain permission we go ahead with the process, else we report the error back to the client. I think thats a sane solution (and it was all Randall's idea :P).

Ok .. its off to coding now then ...

Back to Armahg's main GSoC page

Last modified 8 years ago Last modified on Sep 11, 2012, 6:02:29 PM