TweetFollow Us on Twitter

September 95 - MPW Tips and Tricks: Customizing Source Control With SourceServer

MPW Tips and Tricks: Customizing Source Control With SourceServer

Tim Maroney

When two engineers on a team edit the same source file at the same time, the resulting chaos can be terrible to behold. Source control was invented to mitigate the problem. Most Macintosh programmers are familiar with the MPW Shell's Check In and Check Out dialogs, and with its Projector commands. The next frontier of custom source control involves SourceServer, a nearly faceless application that implements most of the Projector commands. MPW scripts are easy to write, but they're no match for the power, speed, and friendliness of compiled software. SourceServer exports Projector commands as Apple events, allowing source control from compiled software without launching the MPW Shell in all its pomp and splendor.

Popular third-party development environments often send Apple events to SourceServer for integrated source control. You can also use SourceServer to customize Projector beyond what you might have thought possible. For instance, you can drag source control, kicking and screaming, into the modern world of user experience with drop-on applications. In this column, I'll show you how to check a file in or out with a simple drag and drop, and how to use SourceServer for other things as well. The sample code is provided on this issue's CD; SourceServer is distributed, with documentation, on the MPW Pro and E.T.O. CDs (available from Apple Developer Catalog) and with third-party development systems.

APPLE EVENTS FOR SOURCESERVER

Apple events have many faces, but they're primarily a way of communicating between different applications.

Each Apple event encapsulates a message as a command with any number of input parameters; the receiver of the message may return any number of result parameters to the sender. The most basic unit of data is the Apple event descriptor, which consists of a type code and a data handle. Apple events are built out of descriptors and are themselves special kinds of complex descriptors.

    For an excellent introduction to Apple events, see "Scripting the Finder From Your Application" by Greg Anderson in develop Issue 20.*

SourceServer's commands are represented as descriptor lists. Its Apple events are exact duplicates of the MPW Shell's Projector commands, but to avoid the overhead of a full command parser, both the command name and each argument are descriptors in the descriptor list. This saves you the trouble of putting quotes and escapes into arguments that might contain spaces or other special characters. The downside is that you have to expand arguments yourself: you can't pass in MPW wildcard characters, backquoted commands for expansion, or other special constructs.

Creating descriptor lists may sound harder than writing MPW scripts, but that's only because it is. I've provided some utility routines to ease the way, though. Listing 1 shows the utilities and illustrates how to make a command to check out a file for modification. As illustrated in the CheckOut routine in this listing, you call the CreateCommand routine first and then use the AddXArg routines to add arguments.

Listing 1. Creating SourceServer commands

OSErr CreateCommand(AEDesc *command, CString commandText)
// Begin a new SourceServer command; name of command is in
// commandText.
{
   OSErr err = AECreateList(NULL, 0, false, command);
   if (err != noErr) return err;
   err = AddCStringArg(command, commandText);
   if (err != noErr) (void) AEDisposeDesc(command);
   return err;
}

OSErr AddCommentArg(AEDesc *command, StringPtr comment)
/* Add a "-cs comment" argument to a SourceServer command. */
{
   OSErr err;
   if (comment[0] == 0) return noErr;
   err = AddCStringArg(command, "-cs");
   if (err != noErr) return err;
   err = AddPStringArg(command, comment);
   return err;
}

/* Other SourceServer argument utilities */
OSErr AddDirArg(AEDesc *command, short vRefNum, long folderID);
OSErr AddProjectArg(AEDesc *command, StringPtr projectName);
OSErr AddUserArg(AEDesc *command, StringPtr userName);
OSErr AddFullNameArg(AEDesc *command, FSSpec *file);
OSErr AddPStringArg(AEDesc *command, StringPtr string);
OSErr AddCStringArg(AEDesc *command, CString string);

OSErr CheckOut(FSSpec *file, StringPtr userName,
               StringPtr projectName, StringPtr comment)
/* Create a "Check Out Modifiable" command for SourceServer: */
/* CheckOut -m -cs <comment> -d <dir> -project < */
/*           project> -u <user> <file> */
{
   OSErr             err;
   AEDesc          command;
   CStringHandle    output = NULL, diagnostic = NULL;

   err = CreateCommand(&command, "CheckOut");
   if (err != noErr) return err;
   err = AddCStringArg(&command, "-m");
   if (err == noErr) err = AddCommentArg(&command, comment);
   if (err == noErr)
     err = AddDirArg(&command, file->vRefNum, file->parID);
   if (err == noErr) err = AddProjectArg(&command, projectName);
   if (err == noErr) err = AddUserArg(&command, userName);
   if (err == noErr) err = AddPStringArg(&command, file->name);
   if (err == noErr)
     err = SourceServerCommand(&command, &output, &diagnostic);
   (void) AEDisposeDesc(&command);
   /* Display output or diagnostic text as desired. */
   if (output != NULL) DisposeHandle((Handle) output);
   if (diagnostic != NULL) DisposeHandle((Handle) diagnostic);
   return err;
}

Some of the utilities take Pascal strings, while others take C strings, which could well be considered bad programming practice. I chose this dubious method not because I'm on drugs, but because Pascal strings and C strings are used in different ways. SourceServer's text descriptors are C strings; when passed to these utilities as string constants, they shouldn't be converted from Pascal format in place, since some compilers put constants in read-only areas. If you're internationally savvy, you may have another objection: string constants themselves are bad practice. However, for better or worse, MPW scripts and tools are not internationalized. Just like aliens in Star Trek, all MPW programmers are assumed to speak English.

While on the subject of programming practice, I must gently reprimand SourceServer for its approach to Apple events, in which script commands are simulated through a single 'cmnd' event. SourceServer's idiosyncratic convention dates from the earliest days of Apple events, and modern guidelines discourage this type of design. An application implementing its own Apple events should designate a different command code for each operation, treating arguments as keyword parameters.

Listing 2 shows how to send an Apple event to SourceServer. It's first necessary to find and perhaps launch the SourceServer application. The snippet called SignatureToApp (by Jens Alfke) on this issue's CD accomplishes this with a single function call. Simply pass in the creator code of SourceServer, which is 'MPSP'.

Listing 2. Sending commands to SourceServer

OSErr SourceServerCommand(AEDesc *command, CStringHandle *output,
                          CStringHandle *diagnostic)
{
   AppleEvent            aeEvent;
   AERecord              aeReply;
   AEDesc                sourceServerAddress, paramDesc;
   ProcessSerialNumber   sourceServerProcess;
   /* SignatureToApp requires this due to a minor bug */
   FSSpec                appSpec;
   long                  theLong, theSize;
   DescType              theType;
   OSErr                 err;

   *output = *diagnostic = NULL;   /* default replies */
   
   /* Find the SourceServer process and make a descriptor for its */
   /* process ID. */
   err = SignatureToApp('MPSP', NULL, &sourceServerProcess,
                         &appSpec, NULL, Sig2App_LaunchApplication,
                         launchContinue + launchDontSwitch);
   if (err != noErr) return err;
   err = AECreateDesc(typeProcessSerialNumber,
                      (Ptr) &sourceServerProcess,
                     sizeof(ProcessSerialNumber),
                     &sourceServerAddress);
   if (err != noErr) return err;

   /* Create and send the SourceServer Apple event. */
   err = AECreateAppleEvent('MPSP', 'cmnd', &sourceServerAddress,
                           kAutoGenerateReturnID, kAnyTransactionID,
                           &aeEvent);
   /* done with the address descriptor */
   (void) AEDisposeDesc(&sourceServerAddress);
   if (err != noErr) return err;
   /* add the command */
   err = AEPutParamDesc(&aeEvent, keyDirectObject, command);
   if (err != noErr) { (void) AEDisposeDesc(&aeEvent); return err; }
   err = AESend(&aeEvent, &aeReply,
                kAEWaitReply + kAENeverInteract, kAENormalPriority,
                kNoTimeOut, NULL, NULL);
   (void) AEDisposeDesc(&aeEvent);   /* done with the Apple event */
   if (err != noErr) return err;

   /* Check for an error return in the keyErrorNumber parameter. */
   err = AEGetParamPtr(&aeReply, keyErrorNumber, typeInteger,
                      &theType, &theLong, sizeof(long),
                      &theSize);
   if (err == noErr && (err = theLong) == noErr) {
      /* Get the standard output from the keyDirectObject parameter. */
      err = AEGetParamDesc(&aeReply, keyDirectObject, typeChar,
                           &paramDesc);
      if (err == noErr)
          *output = (CStringHandle) paramDesc.dataHandle;
      /* Get the diagnostic output from the 'diag' parameter. */
      err = AEGetParamDesc (&aeReply, 'diag', typeChar,
          &paramDesc);
      if (err == noErr)
          *diagnostic = (CStringHandle) paramDesc.dataHandle;
      /* Get the MPW status from the 'stat' parameter -- it */
      /* becomes our error return. */
      err = AEGetParamPtr(&aeReply, 'stat', typeInteger,
                         &theType, &theLong,
                         sizeof(long), &theSize);
      if (err == noErr) err = theLong;
   }

   /* done with the reply descriptor */
   (void) AEDisposeDesc(&aeReply);
   return err;
}

The event must be created before it can be sent. For SourceServer, there's a single parameter, named keyDirectObject, which is the descriptor list containing the command. After sending the event, you must extract the results. The results of an Apple event are returned as keyword parameters in a reply descriptor. First there's the standard keyErrorNumber parameter, which returns an error code if delivery failed. SourceServer returns three other parameters: The 'stat' parameter contains a second error code; if it's nonzero, SourceServer tried to execute the command and failed. When there's an error, there will be diagnostic output in the 'diag' parameter, a handle containing text from the MPW diagnostic (error) channel. Finally, there's standard output -- a handle specified by keyDirectObject -- which contains explanatory text.

PROJECTDRAG -- DRAG AND DROP SOURCE CONTROL

The Macintosh has always had a drag and drop user experience, but the true power and generality of dragging has been widely recognized only recently. The drag paradigm can even be used for source control. To turn Projector into a drag-savvy system, I've written a set of utilities called ProjectDrag (source code and documentation are provided on this issue's CD). You simply drag and drop icons onto the following miniapplications that make up ProjectDrag, and the corresponding function is performed:
  • Check In and Check Out, for checking files in and out

  • ModifyReadOnly, for editing a file without checking it out

  • Update, for bringing a file or folder up to date, as well as canceling checkouts and modify-read-only changes

  • ProjectDrag Setup, for configuring the system
These utilities are based on a drop-on application framework called DropShell (written by Leonard Rosenthol and Stephan Somogyi), also on the CD. When a file is dropped onto an application, the application receives an Open Documents ('odoc') event. DropShell takes care of the rigmarole of receiving this and other required Apple events. The ProjectDrag miniapplications pull the file specifications out of 'odoc' events and create SourceServer commands that operate on the files and folders that were dropped on their icons.
    DropShell is also available on the Internet at ftp://ftp.hawaii.edu/pub/mac/info-mac/Development/src/ and at other Info-Mac mirror sites.*
Some setup is required. ProjectDrag needs to know the locations of Projector databases. It maps between project names and Projector database files by keeping aliases to database folders in its Preferences folder. To start using a project, simply drag its ProjectorDB file or the enclosing folder onto ProjectDrag Setup. Projector also needs to know your user name, and your initials or a nickname are used in change comments at the start of files. These are stored in a text file in the Preferences folder. ProjectDrag asks you for this information if it can't find it, or you can launch ProjectDrag Setup and give the Set User Name command.

ProjectDrag is scriptable, unlike SourceServer and the MPW Shell. The miniapplications have an Apple event terminology resource ('aete') to advertise their events to scripting systems. This allows you to add source control commands to any application that lets you add AppleScript scripts to its menus.

ProjectDrag is able to run remotely over a network. This circumvents a limitation of SourceServer, which can only be driven locally. ProjectDrag can receive remote Apple events and then drive a copy of SourceServer that's local to it. Among other uses, this could support an accelerator for Apple Remote Access. Checking a file in or out over ARA takes a few minutes, which is fine, especially for those who find tedium particularly enjoyable. Copying files is faster. With local AppleScript front ends for remote ProjectDrag miniapplications, you could copy files to and from a remote "shadow folder" and initiate SourceServer commands at the remote location, where they would execute over a fast network such as Ethernet.

I like to think that I can solve user interface problems in my sleep. When I was writing ProjectDrag, I had a dream of a better user experience. Instead of miniapplications, ProjectDrag would be a magical system extension that would put a single small icon at some convenient place on the screen. When you dragged a file onto this icon, it would pop open into a temporary window and show you icons for the various options. Dreams are great for creativity, but it's easier to weigh alternatives when you're awake. After I woke up, I realized that miniapplications will be able to do the same thing.

Here's how: In Copland, the next generation of the Mac OS, the Finder will spring-load folders so that they open automatically when you drag onto them. It will also let you stash commonly used folders at the bottom of the screen, where they appear as short title bars. Drag the ProjectDrag folder to the bottom of the screen and you're set! Since the Finder will be providing my dream interface, there's no point in a lot of trap patching and extensibility infrastructure to accomplish the same thing.

Copland will bring another user experience benefit to ProjectDrag: it's planned that document windows will have a draggable file icon in their title bar, so you'll be able to use ProjectDrag on an open document by dragging the icon from its window.

YOU TAKE IT FROM HERE

You can create programs that use SourceServer for many other tasks. On cross-platform projects, Projector is sometimes used to control both platforms' source folders. This can lead to baroque and error-prone processes. With SourceServer, you can create front ends that do the right thing. They could copy to remote folders over a network, or lock read-only files since the other platform doesn't see Projector's 'ckid' resources.

Quality is an interesting area for source control applications. A quality tool could query Projector databases for the frequency and scope of changes at various stages of the project, correlating them with bug tracking to develop project metrics. Along similar lines, a tool could measure the change rate of various files to assist in what the quality gods refer to as root-cause analysis.

SourceServer is much more than a way for development systems to provide integrated source control. It's great for structuring your internal development process as well!

TIM MARONEY wrote TOPS Terminal and BackDrop, and has been a major contributor to TOPS for Macintosh, FaxPro, and Cachet. He has also contributed to Fiery, the Disney Screen Saver, Ofoto, Colortron, and the Usenet Mac Programmer's Guide. Tim learned computer networking while working on the Andrew and MacIP projects at Carnegie Mellon and studied compiler design in graduate school at Chapel Hill. He has written for all three major operating systems and a few minor ones. On the Macintosh, Tim's code has included applications, INITs, control panels, HyperCard stacks, XCMDs, shared libraries, trap patches, plug-ins, scripts, and things more difficult to characterize. Tim is currently doing contract work at Apple, and is available for parties and special events at a nominal cost.*

Thanks to Greg Anderson, Arno Gourdol, and B. Winston Hendrickson for reviewing this column.*

Special thanks to Jens Alfke, Jon Pugh, Leonard Rosenthol, and Stephan Somogyi.*

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Parallels Desktop 12.0.0 - Run Windows a...
Parallels allows you to run Windows and Mac applications side by side. Choose your view to make Windows invisible while still using its applications, or keep the familiar Windows background and... Read more
Firefox 48.0.2 - Fast, safe Web browser.
Firefox offers a fast, safe Web browsing experience. Browse quickly, securely, and effortlessly. With its industry-leading features, Firefox is the choice of Web development professionals and casual... Read more
Apple iOS 9.3.5 - The latest version of...
iOS is the world’s most advanced mobile operating system, and it’s the foundation of iPhone, iPad, and iPod touch. It comes with a collection of apps and features that let you do the everyday things... Read more
Spotify 1.0.36.124. - Stream music, crea...
Spotify is a streaming music service that gives you on-demand access to millions of songs. Whether you like driving rock, silky R&B, or grandiose classical music, Spotify's massive catalogue puts... Read more
Apple iOS 9.3.5 - The latest version of...
iOS is the world’s most advanced mobile operating system, and it’s the foundation of iPhone, iPad, and iPod touch. It comes with a collection of apps and features that let you do the everyday things... Read more
Parallels Desktop 12.0.0 - Run Windows a...
Parallels allows you to run Windows and Mac applications side by side. Choose your view to make Windows invisible while still using its applications, or keep the familiar Windows background and... Read more
Spotify 1.0.36.124. - Stream music, crea...
Spotify is a streaming music service that gives you on-demand access to millions of songs. Whether you like driving rock, silky R&B, or grandiose classical music, Spotify's massive catalogue puts... Read more
Firefox 48.0.2 - Fast, safe Web browser.
Firefox offers a fast, safe Web browsing experience. Browse quickly, securely, and effortlessly. With its industry-leading features, Firefox is the choice of Web development professionals and casual... Read more
BBEdit 11.6.1 - Powerful text and HTML e...
BBEdit is the leading professional HTML and text editor for the Mac. Specifically crafted in response to the needs of Web authors and software developers, this award-winning product provides a... Read more
OmniGraffle Pro 6.6.1 - Create diagrams,...
OmniGraffle Pro helps you draw beautiful diagrams, family trees, flow charts, org charts, layouts, and (mathematically speaking) any other directed or non-directed graphs. We've had people use... Read more

Cartoon Network Superstar Soccer: Goal!!...
Cartoon Network Superstar Soccer: Goal!!! – Multiplayer Sports Game Starring Your Favorite Characters 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Become a soccer superstar with your... | Read more »
NFL Huddle: What's new in Topps NFL...
Can you smell that? It's the scent of pigskin in the air, which either means that cliches be damned, pigs are flying in your neck of the woods, or the new NFL season is right around the corner. [Read more] | Read more »
FarmVille: Tropic Escape tips, tricks, a...
Maybe farming is passé in mobile games now. Ah, but farming -- and doing a lot of a other things too -- in an island paradise might be a little different. At least you can work on your tan and sip some pina coladas while tending to your crops. [... | Read more »
Become the King of Avalon in FunPlus’ la...
King Arthur is dead. Considering the legend dates back to the 5th century, it would be surprising if he wasn’t. But in the context of real-time MMO game King of Avalon: Dragon Warfare, Arthur’s death plunges the kingdom into chaos. Evil sorceress... | Read more »
Nightgate (Games)
Nightgate 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: *** Launch Sale: 25% OFF for a limited time! *** In the year 2398, after a great war, a network of intelligent computers known as... | Read more »
3 best fantasy football apps to get you...
Last season didn't go the way you wanted it to in fantasy football. You were super happy following your drafts or auctions, convinced you had outsmarted everyone. You were all set to hustle on the waiver wire, work out some sweet trades, and make... | Read more »
Pokemon GO update: Take me to your leade...
The Team Leaders in Pokemon GO have had it pretty easy up until now. They show up when players reach level 5, make their cases for joining their respective teams, and that's pretty much it. Light work, as Floyd Mayweather might say. [Read more] | Read more »
Ruismaker FM (Music)
Ruismaker FM 1.0 Device: iOS Universal Category: Music Price: $4.99, Version: 1.0 (iTunes) Description: Following up on the success of Ruismaker, here's her crazy twin-sister, designed for people who want to design their own... | Read more »
Space Marshals 2 (Games)
Space Marshals 2 1.0.15 Device: iOS iPhone Category: Games Price: $5.99, Version: 1.0.15 (iTunes) Description: The sci-fi wild west adventure in outer space continues with Space Marshals 2. This tactical top-down shooter puts you in... | Read more »
Dungeon Warfare (Games)
Dungeon Warfare 1.0 Device: iOS Universal Category: Games Price: $3.99, Version: 1.0 (iTunes) Description: Dungeon Warfare is a challenging tower defense game where you become a dungeon lord to defend your dungeon against greedy... | Read more »

Price Scanner via MacPrices.net

BookBook Releases SurfacePad, BookBook &...
BookBook has released three new covers just for iPad Pro: SurfacePad, BookBook and BookBook Rutledge Edition. BookBook for iPad Pro is a gorgeous leather case reminiscent of a vintage sketchbook.... Read more
Clean Text 1.0 for iOS Reduces Text Cleanup a...
Apimac today announced availability of Clean Text for iOS, a tool for webmasters, graphic designers, developers and magazine editors to reduce text cleanup and editing time, and also for any iPhone... Read more
27-inch iMacs on sale for up to $220 off MSRP
B&H Photo has 27″ Apple iMacs on sale for up to $200 off MSRP including free shipping plus NY sales tax only: - 27″ 3.3GHz iMac 5K: $2099 $200 off MSRP - 27″ 3.2GHz/1TB Fusion iMac 5K: $1899 $100... Read more
Apple refurbished 13-inch MacBook Airs availa...
Apple has Certified Refurbished 2016 and 2015 13″ MacBook Airs now available starting at $849. An Apple one-year warranty is included with each MacBook, and shipping is free: - 2016 13″ 1.6GHz/8GB/... Read more
Apple refurbished iPad mini 2s available for...
Apple is offering Certified Refurbished iPad mini 2s for up to $80 off the cost of new minis. An Apple one-year warranty is included with each model, and shipping is free: - 16GB iPad mini 2 WiFi: $... Read more
Save up to $600 with Apple refurbished Mac Pr...
Apple has Certified Refurbished Mac Pros available for up to $600 off the cost of new models. An Apple one-year warranty is included with each Mac Pro, and shipping is free. The following... Read more
Mac Pros on sale for $200 off MSRP
B&H Photo has Mac Pros on sale for $200 off MSRP. Shipping is free, and B&H charges sales tax in NY only: - 3.7GHz 4-core Mac Pro: $2799, $200 off MSRP - 3.5GHz 6-core Mac Pro: $3799, $200... Read more
Will We See A 10.5″ iPad Pro in 2017? – The ‘...
A MacRumors report, cites a research note from KGI Securities analyst Ming-Chi Kuo, saying a new size iPad model is in the works. According to the highly respected Cho, who has a strong track record... Read more
IOGEAR USB-C Docking Station Transforms Lapto...
IOGEAR has announced the launch of its innovative USB-C Docking Station with Power Delivery which turns USB-C enabled laptops into desktop workstations. The new IOGEAR USB-C Docking Station features... Read more
12-inch Retina MacBooks on sale for up to $10...
Amazon has 2016 12″ Apple Retina MacBooks on sale for $100 off MSRP. Shipping is free: - 12″ 1.1GHz Space Gray Retina MacBook: $1199 $100 off MSRP - 12″ 1.1GHz Silver Retina MacBook: $1224.99 $75 off... Read more

Jobs Board

*Apple* Engineer - Softthink Solutions, Inc....
Job Description:- Proven experience in administering IOS and OSX Apple devices in enterprises - Experience in administering Apple devices in Windows environments Read more
*Apple* Professional Learning Specialist - A...
# Apple Professional Learning Specialist Job Number: 51234243 Portland, Maine, Maine, United States Posted: Aug. 18, 2016 Weekly Hours: 40.00 **Job Summary** The Read more
*Apple* Mobile Master - Best Buy (United Sta...
What does a Best Buy Apple Mobile Master do? At Best Buy, our mission is to leverage the unique talents and passions of our employees to inspire, delight, and enrich Read more
*Apple* Retail - Multiple Positions Akron, O...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Simply Mac *Apple* Specialist- Repair Techn...
…The Technician is a master at working with our customers to diagnose and repair Apple devices in a manner that exceeds the expectations set forth by Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.