Merging with gsoc09-gui branch so that this is not outdated.

git-svn-id: https://svn.macports.org/repository/macports/contrib/MacPorts_Framework@65491 d073be05-634f-4543-b044-5fe20cf6d1d6
This commit is contained in:
Juan Germán Castañeda Echevarría
2010-03-26 19:46:35 +00:00
23 changed files with 1578 additions and 345 deletions
@@ -47,6 +47,7 @@
// Define BAS_PRIVATE so that we pick up our private definitions from
// "BetterAuthorizationSampleLib.h".
#define BAS_PRIVATE 1
#include "BetterAuthorizationSampleLib.h"
@@ -77,7 +78,7 @@
enum {
kIdleTimeoutInSeconds = 120, // if we get no requests in 2 minutes, we quit
kWatchdogTimeoutInSeconds = 65 // any given request must be completely in 65 seconds
kWatchdogTimeoutInSeconds = 500000 // any given request must be completed in ~5 days (is this ok?)
};
// IMPORTANT:
@@ -93,12 +94,12 @@ enum {
// 2. Because it's less than 4 GB, this limit ensures that the dictionary size
// can be sent as an architecture-neutral uint32_t.
#define kBASMaxNumberOfKBytes (1024 * 1024)
#define kBASMaxNumberOfKBytes (1024 * 1024)
// A hard-wired file system path for the UNIX domain socket; %s is the placeholder
// for the bundle ID (in file system representation).
#define kBASSocketPathFormat "/var/run/%s.socket"
#define kBASSocketPathFormat "/var/run/%s.socket"
// The key used to get our describe our socket in the launchd property list file.
@@ -117,9 +118,9 @@ extern int BASOSStatusToErrno(OSStatus errNum)
retval = ident; \
break
switch (errNum) {
case noErr:
retval = 0;
break;
case noErr:
retval = 0;
break;
case kENORSRCErr:
retval = ESRCH; // no ENORSRC on Mac OS X, so use ESRCH
break;
@@ -128,9 +129,9 @@ extern int BASOSStatusToErrno(OSStatus errNum)
break;
CASE(EDEADLK);
CASE(EAGAIN);
case kEOPNOTSUPPErr:
retval = ENOTSUP;
break;
case kEOPNOTSUPPErr:
retval = ENOTSUP;
break;
CASE(EPROTO);
CASE(ETIME);
CASE(ENOSR);
@@ -145,12 +146,12 @@ extern int BASOSStatusToErrno(OSStatus errNum)
CASE(ENOMSG);
default:
if ( (errNum <= kEPERMErr) && (errNum >= kENOMSGErr) ) {
retval = (-3200 - errNum) + 1; // OT based error
retval = (-3200 - errNum) + 1; // OT based error
} else if ( (errNum >= errSecErrnoBase) && (errNum <= (errSecErrnoBase + ELAST)) ) {
retval = (int) errNum - errSecErrnoBase; // POSIX based error
retval = (int) errNum - errSecErrnoBase; // POSIX based error
} else {
retval = (int) errNum; // just return the value unmodified
}
retval = (int) errNum; // just return the value unmodified
}
}
#undef CASE
return retval;
@@ -1920,39 +1921,45 @@ static const char * kPlistTemplate =
// We install the job disabled, then enable it as the last step.
" <key>Disabled</key>\n"
" <true/>\n"
" <key>Disabled</key>\n"
" <true/>\n"
// Use the bundle identifier as the job label.
" <key>Label</key>\n"
" <string>%s</string>\n"
" <key>Label</key>\n"
" <string>%s</string>\n"
// Use launch on demaind.
" <key>OnDemand</key>\n"
" <true/>\n"
" <key>OnDemand</key>\n"
" <true/>\n"
// We don't want our helper tool to be respawned every 10 seconds
// after a faliure ... hopefully this won't ALSO prevent us from
// rerunning the helper tool without rebooting the machine
// " <key>LaunchOnlyOnce</key>\n"
// " <true/>\n"
// We don't want our helper tool to be respawned every 10 seconds
// after a faliure ... hopefully this won't ALSO prevent us from
// rerunning the helper tool without rebooting the machine
" <key>LaunchOnlyOnce</key>\n"
" <true/>\n"
// There are no program arguments, other that the path to the helper tool itself.
// There are no program arguments, other that the path to the helper tool itself
// but we must force it to run using the i386 binary if the Framework is
// being used as a i386 binary.
//
// IMPORTANT
// kBASToolPathFormat embeds a %s
" <key>ProgramArguments</key>\n"
" <array>\n"
" <string>" kBASToolPathFormat "</string>\n"
" </array>\n"
" <key>ProgramArguments</key>\n"
" <array>\n"
#ifdef __i386__
" <string>/usr/bin/arch</string>\n"
" <string>-i386</string>\n"
#endif
" <string>" kBASToolPathFormat "</string>\n"
" </array>\n"
// The tool is required to check in with launchd.
" <key>ServiceIPC</key>\n"
" <true/>\n"
" <key>ServiceIPC</key>\n"
" <true/>\n"
// This specifies the UNIX domain socket used to launch the tool, including
// the permissions on the socket (438 is 0666).
@@ -1960,20 +1967,20 @@ static const char * kPlistTemplate =
// IMPORTANT
// kBASSocketPathFormat embeds a %s
" <key>Sockets</key>\n"
" <dict>\n"
" <key>" kLaunchDSocketDictKey "</key>\n"
" <dict>\n"
" <key>SockFamily</key>\n"
" <string>Unix</string>\n"
" <key>SockPathMode</key>\n"
" <integer>438</integer>\n"
" <key>SockPathName</key>\n"
" <string>" kBASSocketPathFormat "</string>\n"
" <key>SockType</key>\n"
" <string>Stream</string>\n"
" </dict>\n"
" </dict>\n"
" <key>Sockets</key>\n"
" <dict>\n"
" <key>" kLaunchDSocketDictKey "</key>\n"
" <dict>\n"
" <key>SockFamily</key>\n"
" <string>Unix</string>\n"
" <key>SockPathMode</key>\n"
" <integer>438</integer>\n"
" <key>SockPathName</key>\n"
" <string>" kBASSocketPathFormat "</string>\n"
" <key>SockType</key>\n"
" <string>Stream</string>\n"
" </dict>\n"
" </dict>\n"
"</dict>\n"
"</plist>\n"
;
@@ -2460,3 +2467,23 @@ extern OSStatus BASFixFailure(
return retval;
}
extern void BASTerminateCommand (
AuthorizationRef auth,
const char * bundleID,
const char * installToolPath
)
// Terminate the HelperTool.
{
// Pre-conditions
assert(auth != NULL);
assert(bundleID != NULL);
assert(installToolPath != NULL);
// Run the install tool as root using AuthorizationExecuteWithPrivileges.
RunInstallToolAsRoot(auth, installToolPath, kBASInstallToolTerminateCommand, bundleID, NULL);
return;
}
@@ -738,6 +738,12 @@ extern void BASCloseDescriptorArray(
CFArrayRef descArray
);
extern void BASTerminateCommand(
AuthorizationRef auth,
const char * bundleID,
const char * installToolPath
);
/////////////////////////////////////////////////////////////////
#pragma mark ***** Utility Routines
@@ -763,6 +769,7 @@ extern void BASCloseDescriptorArray(
#define kBASInstallToolInstallCommand "install"
#define kBASInstallToolEnableCommand "enable"
#define kBASInstallToolTerminateCommand "terminate"
// Magic values used to bracket the process ID returned by the install tool.
@@ -395,6 +395,24 @@ static int EnableCommand(
return err;
}
static int TerminateCommand(
const char *bundleID
)
// Utility function to call through to RunLaunchCtl in order to terminate a job
// given by the path contructed from the (const char *) bundleID.
{
int err;
char plistPath[PATH_MAX];
// Pre-condition.
assert(bundleID != NULL);
(void) snprintf(plistPath, sizeof(plistPath), kBASPlistPathFormat, bundleID);
err = RunLaunchCtl(false, "unload", plistPath);
return err;
}
int main(int argc, char **argv)
{
int err;
@@ -453,10 +471,17 @@ int main(int argc, char **argv)
fprintf(stderr, "usage4\n");
err = EINVAL;
}
} else {
fprintf(stderr, "usage2\n");
err = EINVAL;
}
} else if (strcmp(argv[1], kBASInstallToolTerminateCommand) == 0) {
if (argc == 3) {
err = TerminateCommand(argv[2]);
} else {
fprintf(stderr, "usage4\n");
err = EINVAL;
}
} else {
fprintf(stderr, "usage2\n");
err = EINVAL;
}
}
// Write "oK" to stdout and quit. The presence of the "oK" on the last
+8 -1
View File
@@ -19,8 +19,15 @@
<key>CFBundleSignature</key>
<string>Randall Wood</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<string>1.1</string>
<key>NSPrincipalClass</key>
<string></string>
<key>LSMinimumSystemVersionByArchitecture</key>
<dict>
<key>i386</key>
<string>10.4.0</string>
<key>x86_64</key>
<string>10.6.0</string>
</dict>
</dict>
</plist>
+6 -7
View File
@@ -53,7 +53,6 @@
#include <signal.h>
//According to the docs all I need is
//the file descriptor that MPNotifications
//obtained when creating the server socket
@@ -822,12 +821,6 @@ int SimpleLog_Command
/////////////////////////////////////////////////////////////////
#pragma mark ***** Tool Infrastructure
/*
IMPORTANT
---------
This array must be exactly parallel to the kMPHelperCommandSet array
in "MPHelperCommon.c".
*/
static OSStatus DoEvaluateTclString
(
@@ -984,6 +977,12 @@ static OSStatus DoEvaluateTclString
}
/*
IMPORTANT
---------
This array must be exactly parallel to the kMPHelperCommandSet array
in "MPHelperCommon.c".
*/
static const BASCommandProc kMPHelperCommandProcs[] = {
DoEvaluateTclString,
NULL
+11 -4
View File
@@ -52,7 +52,6 @@
#define MPPackage @"macports"
#define MPPackageVersion @"1.0"
#define MP_DEFAULT_PKG_PATH @"/Library/Tcl"
#define TCL_RETURN_CODE @"return code"
#define TCL_RETURN_STRING @"return string"
#define MPFrameworkErrorDomain @"MacPortsFrameworkErrorDomain"
@@ -85,9 +84,6 @@
#define MPTRACE @"ports_trace"
/*!
@class MPInterpreter
@abstract Tcl interpreter object
@@ -104,9 +100,19 @@
}
+(NSString*) PKGPath;
+(void) setPKGPath:(NSString*)newPath;
+(void) terminateMPHelperTool;
+(NSTask*) task;
//Internal methods
-(BOOL) setOptionsForNewTclPort:(NSArray *)options;
-(BOOL) resetTclInterpreterWithPath:(NSString *)path;
/*!
@brief Return singleton shared MPInterpreter instance
*/
@@ -198,5 +204,6 @@
- (void)setAuthorizationRef:(AuthorizationRef)authRef;
- (BOOL)checkIfAuthorized;
-(NSString *)evaluateStringWithMPHelperTool:(NSString *)statement error:(NSError **)mportError;
-(NSString *)evaluateStringWithMPPortProcess:(NSString *)statement error:(NSError **)mportError;
@end
+124 -69
View File
@@ -34,18 +34,19 @@
*/
#import "MPInterpreter.h"
#import "MPMacPorts.h"
#include "BetterAuthorizationSampleLib.h"
#include "MPHelperCommon.h"
#include "MPHelperNotificationsProtocol.h"
static AuthorizationRef internalMacPortsAuthRef;
static NSString* PKGPath = @"/Library/Tcl";
static NSTask* aTask;
#pragma mark -
@implementation MPInterpreter
#pragma mark Notifications Code
#pragma mark Notifications Code
int Notifications_Send(int objc, Tcl_Obj *CONST objv[], int global, Tcl_Interp *interpreter) {
NSString *name;
NSMutableString *msg;
@@ -164,6 +165,20 @@ int Notifications_Command(ClientData clientData, Tcl_Interp *interpreter, int ob
//tool
static NSString * tclInterpreterPkgPath = nil;
+(NSString*) PKGPath {
return PKGPath;
}
+(void) setPKGPath:(NSString*)newPath {
if([PKGPath isNotEqualTo:newPath]) {
[PKGPath release];
PKGPath = [newPath copy];
//I should check if interp is nil. *not needed now
MPInterpreter *interp = (MPInterpreter*) [[[NSThread currentThread] threadDictionary] objectForKey:@"sharedMPInterpreter"];
[interp resetTclInterpreterWithPath:PKGPath];
}
}
#pragma mark -
#pragma mark Internal Methods
//Internal method for initializing actual C Tcl interpreter
@@ -184,7 +199,7 @@ static NSString * tclInterpreterPkgPath = nil;
}
if (path == nil)
path = MP_DEFAULT_PKG_PATH;
path = PKGPath;
NSString * mport_fastload = [[@"source [file join \"" stringByAppendingString:path]
@@ -247,7 +262,7 @@ static NSString * tclInterpreterPkgPath = nil;
Tcl_DeleteInterp(_interpreter);
if (tclInterpreterPkgPath == nil)
result = [self initTclInterpreter:&_interpreter withPath:MP_DEFAULT_PKG_PATH];
result = [self initTclInterpreter:&_interpreter withPath:PKGPath];
else
result = [self initTclInterpreter:&_interpreter withPath:tclInterpreterPkgPath];
@@ -259,9 +274,13 @@ static NSString * tclInterpreterPkgPath = nil;
return (result && tempResult) ;
}
-(BOOL) resetTclInterpreterWithPath:(NSString*) path {
Tcl_DeleteInterp(_interpreter);
return [self initTclInterpreter:&_interpreter withPath:PKGPath];
}
- (id) initWithPkgPath:(NSString *)path portOptions:(NSArray *)options {
if (self = [super init]) {
[self initTclInterpreter:&_interpreter withPath:path];
//set port options maybe I should do this elsewhere?
@@ -284,26 +303,23 @@ static NSString * tclInterpreterPkgPath = nil;
#pragma mark API methods
- (id) init {
return [self initWithPkgPath:MP_DEFAULT_PKG_PATH portOptions:nil];
return [self initWithPkgPath:PKGPath portOptions:nil];
}
+ (MPInterpreter*)sharedInterpreterWithPkgPath:(NSString *)path {
@synchronized(self) {
if ([[[NSThread currentThread] threadDictionary] objectForKey:@"sharedMPInterpreter"] == nil) {
[[self alloc] initWithPkgPath:path portOptions:nil]; // assignment not done here
}
}
return [[[NSThread currentThread] threadDictionary] objectForKey:@"sharedMPInterpreter"];
return [self sharedInterpreterWithPkgPath:path portOptions:nil];
}
+ (MPInterpreter*)sharedInterpreter{
return [self sharedInterpreterWithPkgPath:MP_DEFAULT_PKG_PATH];
return [self sharedInterpreterWithPkgPath:PKGPath];
}
+ (MPInterpreter*)sharedInterpreterWithPkgPath:(NSString *)path portOptions:(NSArray *)options {
@synchronized(self) {
if ([PKGPath isNotEqualTo:path]) {
[self setPKGPath:path];
}
if ([[[NSThread currentThread] threadDictionary] objectForKey:@"sharedMPInterpreter"] == nil) {
[[self alloc] initWithPkgPath:path portOptions:options]; // assignment not done here
}
@@ -438,30 +454,24 @@ static NSString * tclInterpreterPkgPath = nil;
}
- (NSString *)evaluateStringWithPossiblePrivileges:(NSString *)statement error:(NSError **)mportError {
//N.B. I am going to insist that funciton users not pass in nil for the
//mportError parameter
NSString * firstResult;
NSString * secondResult;
NSString * result;
*mportError = nil;
firstResult = [self evaluateStringAsString:statement error:mportError];
//Because of string results of methods like mportsync (which returns the empty string)
//the only way to truly check for an error is to check the mportError parameter.
//If it is nil then there was no error, if not we re-evaluate with privileges using
//the helper tool
if ( *mportError != nil) {
*mportError = nil;
secondResult = [self evaluateStringWithMPHelperTool:statement error:mportError];
return secondResult;
}
return firstResult;
[[MPNotifications sharedListener]
sendIPCNotification:@"MPInfoNotification_&MP&_stdout_&MP&_None_&MP&_Starting up"];
// Is this the best way to know if the running user can use macports without privileges?
if ([[NSFileManager defaultManager] isWritableFileAtPath:PKGPath]) {
result = [self evaluateStringWithMPPortProcess:statement error:mportError];
} else {
result = [self evaluateStringWithMPHelperTool:statement error:mportError];
}
[[MPNotifications sharedListener]
sendIPCNotification:@"MPInfoNotification_&MP&_stdout_&MP&_None_&MP&_Shutting down"];
return result;
}
//NOTE: We expect the Framework client to initialize the AuthorizationRef
@@ -583,38 +593,10 @@ static NSString * tclInterpreterPkgPath = nil;
//Making the following assumption in error handling. If we return
//a noErr then response dictionary cannot be nil since everything went ok.
//Hence I'm only checking for errors WITHIN the following blocks ...
if (err == noErr) {
err = BASExecuteRequestInHelperTool(internalMacPortsAuthRef,
kMPHelperCommandSet,
(CFStringRef) bundleID,
(CFDictionaryRef) request,
&response);
if (err == noErr){// retrieve result here if available
if( response != NULL)
result = (NSString *) (CFStringRef) CFDictionaryGetValue(response, CFSTR(kTclStringEvaluationResult));
}
else { //If we executed unsuccessfully
if (mportError != NULL) {
NSError * undError = [[[NSError alloc] initWithDomain:NSOSStatusErrorDomain
code:err
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
NSLocalizedString(@"Check error code for OSStatus returned",@""),
NSLocalizedDescriptionKey,
nil]] autorelease];
*mportError = [[[NSError alloc] initWithDomain:MPFrameworkErrorDomain
code:MPHELPINSTFAILED
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
NSLocalizedString(@"Unable to execute MPHelperTool successfuly", @""),
NSLocalizedDescriptionKey,
undError, NSUnderlyingErrorKey,
NSLocalizedString(@"BASExecuteRequestInHelperTool execution failed", @""),
NSLocalizedFailureReasonErrorKey,
nil]] autorelease];
}
}
}
else {//This means FixFaliure failed ... Report that in returned error
//
// NOTE: We don't automatically retry as the user wants to have a consistent cancel
// action (i.e. terminate the process when he wants to)
if (err != noErr) {//This means FixFaliure failed ... Report that in returned error
if (mportError != NULL) {
//I'm not sure of exactly how to report this error ...
//Do we need some error codes for our domain? I'll define one
@@ -643,6 +625,79 @@ static NSString * tclInterpreterPkgPath = nil;
return result;
}
- (NSString *) evaluateStringWithMPPortProcess:(NSString *) statement error:(NSError **)mportError {
aTask = [[NSTask alloc] init];
NSMutableArray *args = [NSMutableArray array];
/* set arguments */
[args addObject:PKGPath];
[aTask setCurrentDirectoryPath:[[NSBundle bundleForClass:[self class]] resourcePath]];
[aTask setLaunchPath:[[NSBundle bundleForClass:[self class]] pathForResource:@"MPPortProcess" ofType:@""]];
[aTask setArguments:args];
[aTask launch];
NSConnection *notificationsConnection = [NSConnection defaultConnection];
// Vending MPNotifications sharedListener
[notificationsConnection setRootObject:[MPNotifications sharedListener]];
// Register the named connection
if ( [notificationsConnection registerName:@"MPNotifications"] ) {
NSLog( @"Successfully registered connection with port %@",
[[notificationsConnection receivePort] description] );
} else {
NSLog( @"Name used by %@",
[[[NSPortNameServer systemDefaultPortNameServer] portForName:@"MPNotifications"] description] );
}
id theProxy;
do {
theProxy = [NSConnection
rootProxyForConnectionWithRegisteredName:@"MPPortProcess"
host:nil];
}
while (theProxy == nil);
[theProxy evaluateString:statement];
[aTask waitUntilExit];
int status = [aTask terminationStatus];
if (status != TCL_OK) {
NSLog(@"Task failed. Code: %i", status);
}
[[notificationsConnection receivePort] invalidate];
return nil;
}
+ (NSTask*) task {
return aTask;
}
+ (void) terminateMPHelperTool {
NSString * bundleID;
//In order to make the framework work normally by default ... we do a bare initialization
//of internalMacPortsAuthRef if the delegate hasn't iniitialzed it already
if (internalMacPortsAuthRef == NULL) {
OSStatus res = AuthorizationCreate (NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &internalMacPortsAuthRef);
assert(res == noErr);
}
NSBundle * mpBundle = [NSBundle bundleForClass:[self class]];
NSString * installToolPath = [mpBundle pathForResource:@"MPHelperInstallTool" ofType:nil];
bundleID = [mpBundle bundleIdentifier];
BASSetDefaultRules(internalMacPortsAuthRef,
kMPHelperCommandSet,
(CFStringRef) bundleID,
NULL);
BASTerminateCommand(internalMacPortsAuthRef,
[bundleID UTF8String],
[installToolPath UTF8String]);
return;
}
#pragma mark -
#pragma mark Authorization Code
+5 -4
View File
@@ -76,15 +76,15 @@
}
+ (NSString*) PKGPath;
+ (void) setPKGPath:(NSString*)newPath;
/*!
@brief Returns an MPMacPorts object that represents the MacPorts system on user's machine.
*/
+ (MPMacPorts *)sharedInstance;
+ (MPMacPorts *)sharedInstanceWithPortOptions:(NSArray *)options;
//Names of messages below are subject to change
+ (MPMacPorts *)sharedInstanceWithPkgPath:(NSString *)path;
+ (MPMacPorts *)sharedInstanceWithPkgPath:(NSString *)path portOptions:(NSArray *)options;
- (id) initWithPkgPath:(NSString *)path portOptions:(NSArray *)options;
- (BOOL) setPortOptions:(NSArray *)options;
@@ -221,6 +221,7 @@
*/
-(BOOL) authorizationMode;
- (void) cancelCurrentCommand;
//Notifications stuff for private use and testing purposes
-(void)registerForLocalNotifications;
+29 -16
View File
@@ -39,12 +39,10 @@
@implementation MPMacPorts
- (id) init {
return [self initWithPkgPath:MP_DEFAULT_PKG_PATH portOptions:nil];
return [self initWithPkgPath:[MPInterpreter PKGPath] portOptions:nil];
}
- (id) initWithPkgPath:(NSString *)path portOptions:(NSArray *)options {
if (self = [super init]) {
interpreter = [MPInterpreter sharedInterpreterWithPkgPath:path portOptions:nil];
@@ -53,16 +51,40 @@
return self;
}
+ (MPMacPorts *)sharedInstance {
return [self sharedInstanceWithPkgPath:MP_DEFAULT_PKG_PATH];
+(NSString*) PKGPath {
return [MPInterpreter PKGPath];
}
+ (MPMacPorts *)sharedInstanceWithPortOptions:(NSArray *)options {
return [self sharedInstanceWithPkgPath:MP_DEFAULT_PKG_PATH portOptions:options];
+(void) setPKGPath:(NSString*)newPath {
[MPInterpreter setPKGPath:newPath];
}
- (void) cancelCurrentCommand {
if ([[NSFileManager defaultManager] isWritableFileAtPath:[MPInterpreter PKGPath]]) {
NSLog(@"Terminating MPPortProcess");
NSTask *task = [MPInterpreter task];
if(task != nil && [task isRunning]) {
[task terminate];
}
} else {
NSLog(@"Terminating MPHelperTool");
[MPInterpreter terminateMPHelperTool];
}
}
+ (MPMacPorts *)sharedInstance {
return [self sharedInstanceWithPkgPath:[MPInterpreter PKGPath] portOptions:nil];
}
+ (MPMacPorts *)sharedInstanceWithPkgPath:(NSString *)path portOptions:(NSArray *)options {
@synchronized(self) {
if ([path isEqual:nil]) {
path = [MPInterpreter PKGPath];
}
if ([[MPInterpreter PKGPath] isNotEqualTo:path]) {
[self setPKGPath:path];
}
if ([[[NSThread currentThread] threadDictionary] objectForKey:@"sharedMPMacPorts"] == nil) {
[[self alloc] initWithPkgPath:path portOptions:options ]; // assignment not done here
}
@@ -70,15 +92,6 @@
return [[[NSThread currentThread] threadDictionary] objectForKey:@"sharedMPMacPorts"];
}
+ (MPMacPorts *)sharedInstanceWithPkgPath:(NSString *)path {
@synchronized(self) {
if ([[[NSThread currentThread] threadDictionary] objectForKey:@"sharedMPMacPorts"] == nil) {
[[self alloc] initWithPkgPath:path portOptions:nil ]; // assignment not done here
}
}
return [[[NSThread currentThread] threadDictionary] objectForKey:@"sharedMPMacPorts"];
}
- (BOOL) setPortOptions:(NSArray *)options {
return [interpreter setOptionsForNewTclPort:options];
}
+8 -1
View File
@@ -65,7 +65,7 @@
//Ask Randall about what exactly port tree path is
-(void) testPathToPortIndex {
NSURL *pindex = [testPort pathToPortIndex:@"file:///Users/Armahg/macportsbuild/build1/"];
NSURL *pindex = [testPort pathToPortIndex:@"file:///Users/juanger/local/macportsbuild/branch-unprivileged/"];
STAssertNotNil(pindex, @"URL for port index should not be nil");
}
@@ -74,7 +74,14 @@
STAssertNotNil(searchResults, @"This dictionary should have at least %d key value pairs", [searchResults count]);
}
-(void) testPKGPathChange {
NSString *newPkgPath = @"/Users/juanger/local/macportsbuild/branch-unprivileged/Library/Tcl";
STAssertEqualObjects([MPInterpreter PKGPath], @"/Library/Tcl", @"Initialy, the PKGPath should be /Library/Tcl");
[MPMacPorts sharedInstanceWithPkgPath:newPkgPath portOptions:nil];
STAssertEqualObjects([MPInterpreter PKGPath], newPkgPath, @"The global PKGPath should change as needed");
}
/*-(void) testSync {
NSError * syncError = nil;
[testPort sync:&syncError];
+9 -1
View File
@@ -140,6 +140,13 @@
*/
- (void)deactivateWithVersion:(NSString *)version error:(NSError**)mpError;
/*!
@brief Upgrades an outdated MPPort.
@discussion Only installed and active ports
should be upgraded
*/
- (void)upgradeWithError:(NSError**)mpError;
/*!
@brief Executes the specified target for this MPPort
@@ -290,4 +297,5 @@
- (void)execPortProc:(NSString *)procedure withOptions:(NSArray *)options version:(NSString *)version error:(NSError **)execError;
//Even more generic method to execute a Tcl command with any given number of args
- (void)execPortProc:(NSString *)procedure withParams:(NSArray *)params error:(NSError **)execError;
@end
@end
+47 -21
View File
@@ -98,6 +98,10 @@
[self setObject:[self objectForKey:@"categories"] forKey:@"categoriesAsString"];
[self setObject:[interpreter arrayFromTclListAsString:[self objectForKey:@"categories"]] forKey:@"categories"];
}
if ([self objectForKey:@"variants"] != nil) {
[self setObject:[self objectForKey:@"variants"] forKey:@"variantsAsString"];
[self setObject:[interpreter arrayFromTclListAsString:[self objectForKey:@"variants"]] forKey:@"variants"];
}
if ([self objectForKey:@"depends_build"] != nil) {
[self setObject:[self objectForKey:@"depends_build"] forKey:@"depends_buildAsString"];
[self setObject:[interpreter arrayFromTclListAsString:[self objectForKey:@"depends_build"]] forKey:@"depends_build"];
@@ -115,8 +119,8 @@
}
@try {
if ([[self valueForKey:@"long_description"] characterAtIndex:0] == '{') {
[self setValue:[self valueForKey:@"description"] forKey:@"long_description"];
if ([[self valueForKey:@"description"] characterAtIndex:0] == '{') {
[self setValue:[self valueForKey:@"description"] forKey:@"description"];
}
}
@catch (NSException *e) {
@@ -124,7 +128,22 @@
NSLocalizedStringWithDefaultValue(@"setPortWithTclListAsStringDescreiptionError",
@"Localizable",
[NSBundle mainBundle],
@"Port has an invalid desciption or long_description key.",
@"Port has an invalid desciption key.",
@"Error statement for exception raised when testing description.")]
forKey:@"description"];
}
@try {
if ([[self valueForKey:@"long_description"] characterAtIndex:0] == '{') {
[self setValue:[self valueForKey:@"long_description"] forKey:@"long_description"];
}
}
@catch (NSException *e) {
[self setValue:[NSString stringWithFormat:
NSLocalizedStringWithDefaultValue(@"setPortWithTclListAsStringDescreiptionError",
@"Localizable",
[NSBundle mainBundle],
@"Port has an invalid long_description key.",
@"Error statement for exception raised when testing long_description.")]
forKey:@"long_description"];
}
@@ -211,7 +230,13 @@
procedure, [self name], v, opts]
error:execError];
}
// I must get the new state of the port from the registry
// instead of just [self setState:MPPortStateLearnState];
//NSArray *receipts = [[[MPRegistry sharedRegistry] installed:[self name]] objectForKey:[self name]];
//[self setStateFromReceipts:receipts];
[self removeObjectForKey:@"receipts"];
[self setState:MPPortStateLearnState];
[[MPNotifications sharedListener] setPerformingTclCommand:@""];
[self sendGlobalExecNotification:procedure withStatus:@"Finished"];
}
@@ -241,23 +266,14 @@
//NSString * tclCmd = [@"YES_" stringByAppendingString:target];
[[MPNotifications sharedListener] setPerformingTclCommand:target];
if ([parentMacPortsInstance authorizationMode]) {
[interpreter evaluateStringWithMPHelperTool:
[NSString stringWithFormat:
@"set portHandle [mportopen %@ %@ %@]; mportexec $portHandle %@; mportclose $portHandle",
[self valueForKey:@"porturl"], opts, vrnts, target]
error:execError];
}
else {
[interpreter evaluateStringWithPossiblePrivileges:
[NSString stringWithFormat:
@"set portHandle [mportopen %@ %@ %@]; mportexec $portHandle %@; mportclose $portHandle",
[self valueForKey:@"porturl"], opts, vrnts, target]
error:execError];
}
[interpreter evaluateStringWithPossiblePrivileges:
[NSString stringWithFormat:
@"set portHandle [mportopen %@ %@ %@]; mportexec $portHandle %@; mportclose $portHandle",
[self valueForKey:@"porturl"], opts, vrnts, target]
error:execError];
[self setState:MPPortStateLearnState];
[[MPNotifications sharedListener] setPerformingTclCommand:@""];
[self sendGlobalExecNotification:target withStatus:@"Finished"];
@@ -331,6 +347,10 @@
}
}
- (void)upgradeWithError:(NSError **)mError {
[self execPortProc:@"mportupgrade" withOptions:nil version:@"" error:mError];
}
-(void)configureWithOptions:(NSArray *)options variants:(NSArray *)variants error:(NSError **)mError {
[self exec:@"configure" withOptions:options variants:variants error:mError];
}
@@ -383,6 +403,7 @@
[self exec:@"srpm" withOptions:options variants:variants error:mError];
}
# pragma mark -
@@ -390,7 +411,12 @@
- (id)objectForKey:(id)aKey {
if ([aKey isEqualToString:@"receipts"] && ![super objectForKey:aKey]) {
[self setObject:[[[MPRegistry sharedRegistry] installed:[self objectForKey:@"name"]] objectForKey:[self objectForKey:@"name"]]forKey:aKey];
NSArray *receipts = [[[MPRegistry sharedRegistry] installed:[self objectForKey:@"name"]] objectForKey:[self objectForKey:@"name"]];
if (receipts == nil) {
return nil;
} else {
[self setObject:receipts forKey:aKey];
}
}
return [super objectForKey:aKey];
}
@@ -436,7 +462,7 @@
}
- (void)setStateFromReceipts:(NSArray *)receipts {
[self setObject:receipts forKey:@"receipts"];
[self setObject:receipts forKey:@"receipts"];
[self setState:MPPortStateLearnState];
}
+11 -6
View File
@@ -18,9 +18,11 @@
-(BOOL) installUninstallManipulation:(NSString *)portName {
BOOL ret = NO;
MPMacPorts * port = [MPMacPorts sharedInstanceWithPkgPath:@"/Users/juanger/Projects/gsoc09-gui/MPGUI/build/Debug-InstallMacPorts/macports-1.8/Library/Tcl"
portOptions:nil];
NSLog(@"PkgPath1: %@", [MPInterpreter PKGPath]);
MPRegistry * registry = [MPRegistry sharedRegistry];
MPMacPorts * port = [MPMacPorts sharedInstance];
NSLog(@"PkgPath2: %@", [MPInterpreter PKGPath]);
// Check if portName is installed
unsigned int installed = [[registry installed:portName] count];
@@ -41,7 +43,7 @@
//I guess we should just return here
return ret;
}
NSLog(@"Uninstallation Successful.");
//Uninstallation was successful ... now check registry to make sure its gone
installed = [[registry installed:portName] count];
if (installed > 0) { //Uh oh ... is this suppose to happen?
@@ -67,9 +69,11 @@
//I guess we should just return here
return ret;
}
NSLog(@"Installation successful");
//Installation was successful ... now check registry to make sure its gone
installed = [[registry installed:portName] count];
NSLog(@"%@", [registry installed]);
if (installed == 0) { //Uh oh ... is this suppose to happen?
NSLog(@"%@ is not installed after successful install operation ... double check this from commandline", portName);
//for now return
@@ -119,15 +123,16 @@
// NSLog(@"\n\n Installation successful \n\n");
//
//
// }
// }
//
// //Double check somehow
// MPRegistry * registry = [MPRegistry sharedRegistry];
// NSLog(@"\n\n Result from registry is %@ \n\n", [registry installed:[keyArray objectAtIndex:0]]);
PortManipulator * pm = [[PortManipulator alloc] init];
STAssertTrue([pm installUninstallManipulation:@"pngcrush"] , @"This test should always return true on success");
[pm release];
}
@end
+19
View File
@@ -0,0 +1,19 @@
//
// MPPortProcess.h
// MacPorts.Framework
//
// Created by Juan Germán Castañeda Echevarría on 7/9/09.
// Copyright 2009 UNAM. All rights reserved.
//
#include <tcl.h>
@interface MPPortProcess : NSObject {
Tcl_Interp *interpreter;
NSString *PKGPath;
}
- (oneway void)evaluateString:(bycopy id)statement;
@end
+104
View File
@@ -0,0 +1,104 @@
//
// MPPortProcess.m
// MacPorts.Framework
//
// Created by Juan Germán Castañeda Echevarría on 7/9/09.
// Copyright 2009 UNAM. All rights reserved.
//
#import "MPPortProcess.h"
#import "SimpleLog.h"
@interface MPPortProcess (PrivateMethods)
- (void)initializeInterpreter;
@end
@implementation MPPortProcess
- (id)initWithPKGPath:(NSString*)pkgPath {
PKGPath = pkgPath;
[self initializeInterpreter];
return self;
}
- (oneway void)evaluateString:(bycopy id)statement {
// TODO Handle the posible errors and notifications
int retCode = Tcl_Eval(interpreter, [statement UTF8String]);
if (retCode != TCL_OK) {
Tcl_Obj * interpObj = Tcl_GetObjResult(interpreter);
int length, errCode;
NSString * errString = [NSString stringWithUTF8String:Tcl_GetStringFromObj(interpObj, &length)];
errCode = Tcl_GetErrno();
NSLog(@"- %@ - %i", errString, errCode);
exit(errCode);
}
exit(retCode);
}
#pragma mark Private Methods
- (void)initializeInterpreter {
// Create interpreter
interpreter = Tcl_CreateInterp();
if(interpreter == NULL) {
NSLog(@"Error in Tcl_CreateInterp, aborting.");
}
// Initialize interpreter
if(Tcl_Init(interpreter) == TCL_ERROR) {
NSLog(@"Error in Tcl_Init: %s", Tcl_GetStringResult(interpreter));
Tcl_DeleteInterp(interpreter);
}
// Load macports_fastload.tcl from PKGPath/macports1.0
NSString * mport_fastload = [[@"source [file join \"" stringByAppendingString:PKGPath]
stringByAppendingString:@"\" macports1.0 macports_fastload.tcl]"];
if(Tcl_Eval(interpreter, [mport_fastload UTF8String]) == TCL_ERROR) {
NSLog(@"Error in Tcl_EvalFile macports_fastload.tcl: %s", Tcl_GetStringResult(interpreter));
Tcl_DeleteInterp(interpreter);
}
// Load notifications methods
Tcl_CreateObjCommand(interpreter, "simplelog", SimpleLog_Command, NULL, NULL);
if (Tcl_PkgProvide(interpreter, "simplelog", "1.0") != TCL_OK) {
NSLog(@"Error in Tcl_PkgProvide: %s", Tcl_GetStringResult(interpreter));
}
// Load portProcessInit.tcl
NSString *portProcessInitPath = @"portProcessInit.tcl";
if( Tcl_EvalFile(interpreter, [portProcessInitPath UTF8String]) == TCL_ERROR) {
NSLog(@"Error in Tcl_EvalFile portProcessInit.tcl: %s", Tcl_GetStringResult(interpreter));
Tcl_DeleteInterp(interpreter);
}
}
@end
int main(int argc, char const * argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSConnection *portProcessConnection;
portProcessConnection = [NSConnection defaultConnection];
NSString *PKGPath = [[NSString alloc] initWithCString:argv[1] encoding:NSUTF8StringEncoding];
// NSString *portProcessInitPath = [[NSString alloc] initWithCString:argv[2] encoding:NSUTF8StringEncoding];
MPPortProcess *portProcess = [[MPPortProcess alloc] initWithPKGPath:PKGPath];
// Vending portProcess
[portProcessConnection setRootObject:portProcess];
// Register the named connection
if ( [portProcessConnection registerName:@"MPPortProcess"] ) {
NSLog( @"Successfully registered connection with port %@",
[[portProcessConnection receivePort] description] );
} else {
NSLog( @"Name used by %@",
[[[NSPortNameServer systemDefaultPortNameServer] portForName:@"MPPortProcess"] description] );
}
// Wait for any message
[[NSRunLoop currentRunLoop] run];
[pool release];
return 0;
}
+1 -1
View File
@@ -60,7 +60,7 @@
- (NSDictionary *)installed;
/*
@brief Calls [self installed:name version:@""]
@brief Calls [self installed:name withVersion:@""]
@param name Text to match the port name
*/
- (NSDictionary *)installed:(NSString *)name;
File diff suppressed because it is too large Load Diff
+12
View File
@@ -0,0 +1,12 @@
/*
* SimpleLog.h
* MacPorts.Framework
*
* Created by Juan Germán Castañeda Echevarría on 7/21/09.
* Copyright 2009 UNAM. All rights reserved.
*
*/
#include <tcl.h>
int SimpleLog_Command(ClientData clientData, Tcl_Interp *interpreter, int objc, Tcl_Obj *CONST objv[]);
+76
View File
@@ -0,0 +1,76 @@
/*
* SimpleLog.m
* MacPorts.Framework
*
* Created by Juan Germán Castañeda Echevarría on 7/21/09.
* Copyright 2009 UNAM. All rights reserved.
*
*/
#include "SimpleLog.h"
#define MPSEPARATOR @"_&MP&_"
int SimpleLog_Command(ClientData clientData, Tcl_Interp *interpreter, int objc, Tcl_Obj *CONST objv[]) {
int tclResult = TCL_ERROR;
NSMutableString * data;
++objv, --objc;
if (objc) {
int tclCount;
const char **tclElements;
tclResult = Tcl_SplitList(interpreter, Tcl_GetString(*objv), &tclCount, &tclElements);
if (tclResult == TCL_OK) {
if (tclCount > 0) {
NSLog([NSString stringWithUTF8String:tclElements[0]]);
data = [NSMutableString stringWithUTF8String:tclElements[0]];
[data appendString:MPSEPARATOR];
if(tclCount > 1 && tclElements[1]) {
NSLog([NSString stringWithUTF8String:tclElements[1]]);
[data appendString:[NSString stringWithUTF8String:tclElements[1]]];
[data appendString:MPSEPARATOR];
}
else {
[data appendString:@"None"];
[data appendString:MPSEPARATOR];
}
if(tclCount > 2 && tclElements[2]) {
NSLog([NSString stringWithUTF8String:tclElements[2]]);
[data appendString:[NSString stringWithUTF8String:tclElements[2]]];
[data appendString:MPSEPARATOR];
}
else {
[data appendString:@"None"];
[data appendString:MPSEPARATOR];
}
}
else {
data = [NSMutableString stringWithFormat:@"None%@None%@None%@", MPSEPARATOR, MPSEPARATOR, MPSEPARATOR ];
}
}
}
//Now get the actual message
++objv; --objc;
if (objc) {
[data appendString:[NSString stringWithUTF8String:Tcl_GetString(*objv)]];
}
else {
[data appendString:@"None"];
}
id theProxy = [NSConnection
rootProxyForConnectionWithRegisteredName:@"MPNotifications"
host:nil];
[theProxy sendIPCNotification:data];
NSLog(@"-----%@", data);
return tclResult;
}
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.yourcompany.${PRODUCT_NAME:identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
</dict>
</plist>

Some files were not shown because too many files have changed in this diff Show More