PerforceFile.m #3

  • //
  • guest/
  • jeff_argast/
  • P4Cocoa/
  • source/
  • Perforce/
  • PerforceFile.m
  • View
  • Commits
  • Open Download .zip Download (16 KB)
/*

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) syncToHead
{
//	[PerforceActionSync defaultRunFor:self selector:@selector(resultFromActionDoFstat:) withPath:fDepotPath];	
}

- (void) syncToNone
{
 /*
    NSMutableString* filePath = [[[NSMutableString alloc] initWithString:fDepotPath] autorelease];
    
    [filePath appendString:@"#none"];

	[PerforceActionSync defaultRunFor:self selector:@selector(resultFromActionDoFstat:) withPath:filePath];	
*/
}

- (void) syncTo: (NSString*) target
{	
/*
    NSMutableString* filePath = [[[NSMutableString alloc] initWithString:fDepotPath] autorelease];
    
    [filePath appendString:target];

	[PerforceActionSync defaultRunFor:self selector:@selector(resultFromActionDoFstat:) withPath:filePath];	
*/
}

- (void) resultFromPerforceFilelog: (PerforceActionFilelog*) action
{
	if ( [action wasSuccess] )
	{
		[RevisionsController showWithRevisions:[action getRevisions]];
	}
}

- (void) showRevisionHistory
{
	[PerforceActionFilelog defaultRunFor:self selector:@selector(resultFromPerforceFilelog:) withPath:fDepotPath];	
}

- (void) edit
{
//	[PerforceActionEdit defaultRunFor:self selector:@selector(resultFromActionDoFstat:) withPath:fDepotPath];	
}

- (void) delete
{
//	[PerforceActionDelete defaultRunFor:self selector:@selector(resultFromActionDoFstat:) withPath:fDepotPath];	
}

- (void) revert
{
//	[PerforceActionRevert defaultRevertPaths:[NSArray arrayWithObject: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) fileChanged:(NSString*)depotPath
{
	if ( [depotPath isEqualToString:fDepotPath] )
	{
		[PerforceActionFstat defaultRunFor:self 
							 selector:@selector(resultFromPerforceFstat:) withPath:fDepotPath includeDeletes:YES];
	}
}

- (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

# Change User Description Committed
#9 4277 Jeff Argast Fixed two bugs and updated version to 0.23
#8 4225 Jeff Argast Added resolve support, reveal in finder, drag and drop edit,
show local files, and showing added files.
#7 3980 Jeff Argast Added distributed protocol
#6 3941 Jeff Argast Simplified fstat, branches, and job parsing.
#5 3134 Jeff Argast Added copy/paste support in the depot view
Added expand path to depot view
Added bookmarks
#4 3113 Jeff Argast Reduced the times the depot view completely collapses.
Now it won't collapse on refresh views or submit, but
still collapses when the defaults change.
#3 3111 Jeff Argast Made multiple selection smarter by operating on the entire selection as an atomic
operation with the server. Also partially fixed the read only window to not wrap
at the window boundary.  I did the same for the editable window, but now the problem
appears to be that p4 change -o is breaking its output at some character location
before the string gets into the editor (at least I think that is the problem).
#2 2741 Jeff Argast Fixed viewing files that are not in client
#1 2732 Jeff Argast Initial submission of P4Cocoa