/* Copyright (C) 2002-2003, Jeffrey D. Argast. The authors make NO WARRANTY or representation, either express or implied, with respect to this software, its quality, accuracy, merchantability, or fitness for a particular purpose. This software is provided "AS IS", and you, its user, assume the entire risk as to its quality and accuracy. Permission is hereby granted to use, copy, modify, and distribute this software or portions thereof for any purpose, without fee, subject to these conditions: (1) If any part of the source code is distributed, then this statement must be included, with this copyright and no-warranty notice unaltered. (2) Permission for use of this software is granted only if the user accepts full responsibility for any undesirable consequences; the authors accept NO LIABILITY for damages of any kind. */ #import "PerforceFile.h" #import "IconController.h" #import "IconDefs.h" #import "PerforceAction.h" #import "PerforceActionSync.h" #import "PerforceActionFstat.h" #import "PerforceActionFilelog.h" #import "PerforceActionEdit.h" #import "PerforceActionRevert.h" #import "PerforceActionDelete.h" #import "PerforceActionPrint.h" #import "PerforceActionDiff.h" #import "AppUtils.h" #import "AppDefaults.h" #import "MessageDefs.h" #import "RevisionsController.h" enum { kIsHeadRevision = 0, kIsOldRevision = 1, kIsMissingRevision = 2 }; static NSString* kDepotFileTag = @"depotFile"; static NSString* kClientFileTag = @"clientFile"; static NSString* kHeadActionTag = @"headAction"; static NSString* kHeadTypeTag = @"headType"; static NSString* kHeadRevTag = @"headRev"; static NSString* kHeadChangeTag = @"headChange"; static NSString* kHaveRevTag = @"haveRev"; static NSString* kActionTag = @"action"; static NSString* kChangeTag = @"change"; static NSString* kUnresolvedTag = @"unresolved"; static NSString* kOtherOpenTag = @"otherOpen"; static NSString* kOtherLockTag = @"otherLock"; static NSString* kOurLockTag = @"ourLock"; //static NSString* kOtherActionTag = @"otherAction"; static NSString* kDeleteStatus_Have = @"<-deleted->"; static NSString* kDeleteStatus_Old = @"<-head rev deleted->"; @implementation PerforceFile - (id) initWithDict: (NSDictionary*) fileDictionary otherOpen: (NSArray*) otherOpenArray otherAction: (NSArray*) otherActionArray { BOOL otherEdit = NO; BOOL otherDelete = NO; NSMutableString* displayString = nil; int revType = 0; NSString* valueString = nil; self = [super init]; /////////////////////////////// valueString = [fileDictionary objectForKey:kDepotFileTag]; if ( valueString ) { fDepotPath = [valueString retain]; } else { fDepotPath = [[NSString alloc] initWithString:@""]; } fFileName = ExtractLastPathComponent (fDepotPath); [fFileName retain]; /////////////////////////////// valueString = [fileDictionary objectForKey:kClientFileTag]; if ( valueString ) { fClientPath = [valueString retain]; } else { fClientPath = [[NSString alloc] initWithString:@""]; } /////////////////////////////// valueString = [fileDictionary objectForKey:kHeadActionTag]; if ( valueString ) { fHeadAction = [valueString retain]; } else { fHeadAction = [[NSString alloc] initWithString:@""]; } /////////////////////////////// valueString = [fileDictionary objectForKey:kHeadTypeTag]; if ( valueString ) { fHeadType = [valueString retain]; } else { fHeadType = [[NSString alloc] initWithString:@""]; } /////////////////////////////// valueString = [fileDictionary objectForKey:kHeadRevTag]; if ( valueString ) { fHeadRev = [valueString retain]; } else { fHeadRev = [[NSString alloc] initWithString:@""]; } /////////////////////////////// valueString = [fileDictionary objectForKey:kHeadChangeTag]; if ( valueString ) { fHeadChange = [valueString retain]; } else { fHeadChange = [[NSString alloc] initWithString:@""]; } /////////////////////////////// valueString = [fileDictionary objectForKey:kHaveRevTag]; if ( valueString ) { fHaveRev = [valueString retain]; } else { fHaveRev = [[NSString alloc] initWithString:@"0"]; // NOTE: the zero instead of empty string } /////////////////////////////// valueString = [fileDictionary objectForKey:kActionTag]; if ( valueString ) { fAction = [valueString retain]; } else { fAction = [[NSString alloc] initWithString:@""]; } /////////////////////////////// valueString = [fileDictionary objectForKey:kChangeTag]; if ( valueString ) { fChange = [valueString retain]; } else { fChange = [[NSString alloc] initWithString:@""]; } /////////////////////////////// valueString = [fileDictionary objectForKey:kUnresolvedTag]; if ( valueString ) { fUnresolved = [valueString retain]; } else { fUnresolved = [[NSString alloc] initWithString:@""]; } /////////////////////////////// valueString = [fileDictionary objectForKey:kOtherOpenTag]; if ( valueString ) { fOtherOpen = [valueString retain]; } else { fOtherOpen = [[NSString alloc] initWithString:@""]; } /////////////////////////////// valueString = [fileDictionary objectForKey:kOtherLockTag]; if ( valueString ) { fOtherLock = [valueString retain]; } else { fOtherLock = [[NSString alloc] initWithString:@""]; } /////////////////////////////// valueString = [fileDictionary objectForKey:kOurLockTag]; if ( valueString ) { fOurLock = [valueString retain]; } else { fOurLock = [[NSString alloc] initWithString:@""]; } fOtherUsers = [otherOpenArray retain]; fOtherActions = [otherActionArray retain]; // Is this file equal to head, out of date, or not on clients machine? if ( [fHaveRev isEqualToString:fHeadRev] ) { revType = kIsHeadRevision; } else if ( [fHaveRev isEqualToString:@"0"] ) { revType = kIsMissingRevision; } else { revType = kIsOldRevision; } // Build the display string displayString = [[NSMutableString alloc] initWithString:fFileName]; [displayString appendString:@" #"]; [displayString appendString:fHaveRev]; [displayString appendString:@"/"]; [displayString appendString:fHeadRev]; [displayString appendString:@" <"]; [displayString appendString:fHeadType]; [displayString appendString:@"> "]; if ( [fHeadAction isEqualToString:@"delete"] ) { if ( revType == kIsOldRevision ) { [displayString appendString:kDeleteStatus_Old]; } else { [displayString appendString:kDeleteStatus_Have]; } } // force into an NSString so that later when we return it // it is faster (assuming Cocoa implemented NSString copy // as a simple retain) fDisplayString = [[NSString alloc] initWithCString:[displayString cString]]; if ( fOtherActions ) { int numActions = [fOtherActions count]; int n; for ( n = 0; (n < numActions) && !(otherEdit && otherDelete); n++ ) { NSString* otherAction = [fOtherActions objectAtIndex:n]; if ( !otherEdit && [otherAction isEqualTo:@"edit"] ) { otherEdit = YES; } if ( !otherDelete && [otherAction isEqualTo:@"delete"] ) { otherDelete = YES; } } } int iconID = 0; // Figure out icon id if ( revType == kIsHeadRevision ) { if ( [fAction isEqualTo:@"edit"] ) { if ( otherDelete ) { iconID = kHaveFileOurLockOtherDeleteIcon; } else if ( otherEdit ) { iconID = kHaveFileBothLockIcon; } else { iconID = kHaveFileOurLockIcon; } } else if ( [fAction isEqualTo:@"delete"] ) { if ( otherDelete ) { iconID = kHaveFileBothDeleteIcon; } else if ( otherEdit ) { iconID = kHaveFileOurDeleteOtherLockIcon; } else { iconID = kHaveFileDeleteIcon; } } else { if ( otherDelete ) { iconID = kHaveFileOtherDeleteIcon; } else if ( otherEdit ) { iconID = kHaveFileOtherLockIcon; } else { iconID = kHaveFileIcon; } } } else if ( revType == kIsOldRevision ) { if ( [fAction isEqualTo:@"edit"] ) { if ( otherDelete ) { iconID = kOldFileOurLockOtherDeleteIcon; } else if ( otherEdit ) { iconID = kOldFileBothLockIcon; } else { iconID = kOldFileOurLockIcon; } } else if ( [fAction isEqualTo:@"delete"] ) { if ( otherDelete ) { iconID = kOldFileBothDeleteIcon; } else if ( otherEdit ) { iconID = kOldFileOurDeleteOtherLockIcon; } else { iconID = kOldFileDeleteIcon; } } else { if ( otherDelete ) { iconID = kOldFileOtherDeleteIcon; } else if ( otherEdit ) { iconID = kOldFileOtherLockIcon; } else { iconID = kOldFileIcon; } } } else { if ( otherDelete ) { iconID = kMissingFileOtherDeleteIcon; } else if ( otherEdit ) { iconID = kMissingFileOtherLockIcon; } else { iconID = kMissingFileIcon; } } IconController* iconController = [IconController defaultIconController]; fIcon = [[iconController getIcon:iconID] retain]; return self; } - (void) copyFrom: (PerforceFile*) fromFile { [self releaseData]; fFileName = [fromFile->fFileName retain]; fDepotPath = [fromFile->fDepotPath retain]; fClientPath = [fromFile->fClientPath retain]; fHeadAction = [fromFile->fHeadAction retain]; fHeadType = [fromFile->fHeadType retain]; fHeadRev = [fromFile->fHeadRev retain]; fHeadChange = [fromFile->fHeadChange retain]; fHaveRev = [fromFile->fHaveRev retain]; fAction = [fromFile->fAction retain]; fChange = [fromFile->fChange retain]; fUnresolved = [fromFile->fUnresolved retain]; fOtherOpen = [fromFile->fOtherOpen retain]; fOtherLock = [fromFile->fOtherLock retain]; fOurLock = [fromFile->fOurLock retain]; fOtherUsers = [fromFile->fOtherUsers retain]; fOtherActions = [fromFile->fOtherActions retain]; fDisplayString = [fromFile->fDisplayString retain]; fIcon = [fromFile->fIcon retain]; } - (void) releaseData { [fFileName release]; [fDepotPath release]; [fClientPath release]; [fHeadAction release]; [fHeadType release]; [fHeadRev release]; [fHeadChange release]; [fHaveRev release]; [fAction release]; [fChange release]; [fUnresolved release]; [fOtherOpen release]; [fOtherUsers release]; [fOtherActions release]; [fOtherLock release]; [fOurLock release]; [fDisplayString release]; [fIcon release]; } - (void) dealloc { [self releaseData]; [super dealloc]; } - (int) getNumberOfChildren { return 0; } - (BOOL) hasChildren { return NO; } - (id) getChildAtIndex: (int) index { return nil; } - (id) getCellText { return fDisplayString; } - (id) getCellImage { return fIcon; } // // Perforce Protocol // // // data // // // Enablement // - (BOOL) canSyncToHead { if ( [fHaveRev isEqualTo:fHeadRev] ) { return NO; } if ( [fHeadAction isEqualTo:@"delete"] && [fHaveRev isEqualTo:@"0"] ) { return NO; } return YES; } - (BOOL) canSyncToNone { if ( ![fAction isEqualTo:@""] ) { return NO; } if ( [fHaveRev isEqualTo:@"0"] ) { return NO; } return YES; } - (BOOL) canEdit { if ( ![fAction isEqualTo:@""] ) { return NO; } if ( [fHaveRev isEqualTo:@"0"] ) { return NO; } return YES; } - (BOOL) canDelete { if ( ![fAction isEqualTo:@""] ) { return NO; } if ( [fHaveRev isEqualTo:@"0"] ) { return NO; } return YES; } - (BOOL) canRevert { if ( ![fAction isEqualTo:@""] ) { return YES; } return NO; } - (BOOL) canDiff { if ( [fAction isEqualTo:@"edit"] ) { return YES; } return NO; } - (BOOL) canGetRevisions { return YES; } - (BOOL) canViewInEditor { if ( [fHaveRev isEqualTo:@"0"] && [fHeadAction isEqualTo:@"delete"] ) { return NO; } return YES; } // // Actions // - (void) resultFromPerforceFstat: (PerforceActionFstat*) action { if ( [action wasSuccess] ) { [self copyFrom:[[action getFiles] objectAtIndex:0]]; SendNotificationWithObject (kDepotControllerChildChanged, self); } } - (void) resultFromActionDoFstat: (id) nothing { [PerforceActionFstat defaultRunFor:self selector:@selector(resultFromPerforceFstat:) withPath:fDepotPath includeDeletes:YES]; } - (void) resultFromPerforceFilelog: (PerforceActionFilelog*) action { if ( [action wasSuccess] ) { [RevisionsController showWithRevisions:[action getRevisions]]; } } - (void) showRevisionHistory { [PerforceActionFilelog defaultRunFor:self selector:@selector(resultFromPerforceFilelog:) withPath:fDepotPath]; } - (void) resultFromActionDoDiff: (NSString*) outputPath { DiffFiles (fClientPath, outputPath); } - (void) diff { [PerforceActionDiff depotPath:fDepotPath]; } - (void) viewFromTempFile { NSString* fileName = GetTempFileName (fFileName, fHeadRev); [PerforceActionPrint defaultRunFor:self selector:@selector(viewAfterPrint:) withPath:fDepotPath outputPath:fileName]; } - (void) viewInEditor { if ( [fHaveRev isEqualTo:@"0"] ) { [self viewFromTempFile]; } else { ViewFileInEditor (fClientPath); } } - (NSString*) getPasteboardData { return fDepotPath; } - (void) viewAfterPrint:(PerforceActionPrint*) action { if ( [action wasSuccess] ) { ViewFileInEditor ([action getOutputPath]); } } - (void) pathChanged:(NSString*)depotPath theFile:(PerforceFile**)theFile { if ( [depotPath isEqualToString:fDepotPath] ) { *theFile = self; } } - (NSString*) getDepotPath { return fDepotPath; } - (NSString*) getPerforceActionPath { return fDepotPath; } @end