/*
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 "PerforceOutputParsers.h"
#import "AppUtils.h"
#import "PerforceDepot.h"
#import "PerforceDirectory.h"
#import "PerforceFile.h"
#import "PerforceFileRevision.h"
#import "PerforceChangeFile.h"
#import "PerforceChangeList.h"
#import "PerforceSubmittedChange.h"
#import "PerforceBranch.h"
#import "PerforceJob.h"
#import "PerforceLabel.h"
#import "PerforceClient.h"
#import "PerforceUser.h"
#import <Foundation/Foundation.h>
#include <string>
BOOL ScanJustPastChar (char** inCurPos, char* endPos, char scanChar);
static NSString* kEndOfLineToken = @"\n";
@implementation PerforceOutputParsers
+ (NSArray*) parseFilelogOutput:(NSString*)dataString
{
NSMutableArray* revisionArray = [[[NSMutableArray alloc] init] autorelease];
NSScanner* dataScanner = [NSScanner scannerWithString:dataString];
NSString* resultString = nil;
NSString* fileName = nil;
while ( [dataScanner scanUpToString:kEndOfLineToken intoString:&resultString] == YES )
{
const char* data = [resultString cString];
if ( *data != '.' )
{
[fileName release];
fileName = [resultString retain];
}
else
{
std::string fileRev, fileChangelist, fileDate, fileUser, fileAction, fileDescription;
const char* indata = data + 4; // skip the ...
// skip branch history info
if ( *indata == '#' )
{
indata++; // skip #
// fileRev
while ( *indata != ' ' )
{
fileRev += *indata;
indata++;
}
// skip space
indata++;
//skip the word change
while ( *indata++ != ' ' );
// changelist
while ( *indata != ' ' )
{
fileChangelist += *indata;
indata++;
}
// skip space
indata++;
// action
while ( *indata != ' ' )
{
fileAction += *indata;
indata++;
}
// skip space
indata++;
//skip the word on
while ( *indata++ != ' ' );
// date
while ( *indata != ' ' )
{
fileDate += *indata;
indata++;
}
// skip space
indata++;
//skip the word by
while ( *indata++ != ' ' );
// user
while ( *indata != ' ' )
{
fileUser += *indata;
indata++;
}
// skip space
indata++;
//skip the file type
while ( *indata++ != ' ' );
// skip the '
indata++;
// desc
while ( *indata != '\'' )
{
fileDescription += *indata;
indata++;
}
[revisionArray addObject:[[[PerforceFileRevision alloc] initWithRevision:fileRev.c_str()
withFileName:[fileName cString]
withChangeList:fileChangelist.c_str()
withDate:fileDate.c_str()
withUser:fileUser.c_str()
withAction:fileAction.c_str()
withDescription:fileDescription.c_str()]
autorelease]];
}
}
}
[fileName release];
return revisionArray;
}
+ (NSArray*) parseOpenedOutput:(NSString*)dataString clientOnly:(BOOL)isClientOnly
{
NSMutableArray* changesFileArray = [[[NSMutableArray alloc] init] autorelease];
NSScanner* dataScanner = [NSScanner scannerWithString:dataString];
NSString* resultString = nil;
NSString* userAtClient = GetUserAtClientString();
while ( [dataScanner scanUpToString:kEndOfLineToken intoString:&resultString] == YES )
{
char* data = (char*)[resultString cString];
NSString* fileName;
NSString* changeType;
NSString* changeName;
NSString* fileType;
NSString* userInfo = nil;
int revision;
char* startPos = data;
char* curPos = data;
char* endPos = data + [resultString length];
// go until we get to a # sign
if ( !ScanJustPastChar (&curPos, endPos, '#') )
continue;
// get the fileName
fileName = [NSString stringWithCString:startPos length:(curPos - startPos - 1)];
// go past the '#'
startPos = curPos;
// now go until we get to a space
if ( !ScanJustPastChar (&curPos, endPos, ' ') )
continue;
// get the revision number
revision = [[NSString stringWithCString:startPos length:(curPos - startPos - 1)] intValue];
// skip the '- '
curPos++;
curPos++;
startPos = curPos;
// go until we get to a space
if ( !ScanJustPastChar (&curPos, endPos, ' ') )
continue;
// the change type is next
changeType = [NSString stringWithCString:startPos length:(curPos - startPos - 1)];
startPos = curPos;
// go until we get to a space
if ( !ScanJustPastChar (&curPos, endPos, ' ') )
continue;
// The last word scanned is either change or default
if ( *startPos == 'c' )
{
startPos = curPos;
// go until we get to a space
while ( *curPos++ != ' ' );
// Get the change number
changeName = [NSString stringWithCString:startPos length:(curPos - startPos - 1)];
}
else
{
// The change name should be default in this case
changeName = [NSString stringWithCString:startPos length:(curPos - startPos - 1)];
}
// go until we get to a (
if ( !ScanJustPastChar (&curPos, endPos, '(') )
continue;
startPos = curPos;
// go until we get to a )
if ( !ScanJustPastChar (&curPos, endPos, ')') )
continue;
// get the fileType
fileType = [NSString stringWithCString:startPos length:(curPos - startPos - 1)];
// When this is called without the -a option, the user name is left off
if ( !isClientOnly )
{
// is there user info?
if ( (*curPos != '\n') && (*curPos != 0) )
{
// skip the ' by '
curPos += 4;
startPos = curPos;
// go until we get to the end
while ( (*curPos != '\n') && (*curPos != 0) )
{
curPos++;
}
// get the fileType
userInfo = [NSString stringWithCString:startPos length:(curPos - startPos)];
}
}
else
{
userInfo = userAtClient;
}
[changesFileArray addObject:[[[PerforceChangeFile alloc]
initWithName:fileName
withRevision:revision
withFileType:fileType
withChangeName:changeName
withChangeType:changeType
withUserInfo:userInfo
isClient:(userInfo ? [userAtClient isEqualTo:userInfo] : YES)] autorelease]];
}
if ( [changesFileArray count] > 0 )
{
// Sort the changeFileArray by change name
[changesFileArray sortUsingSelector:@selector(compare:)];
}
return changesFileArray;
}
//
//
//
+ (NSArray*) parseChangesPendingOutput:(NSString*)dataString
{
NSMutableArray* changesArray = [[[NSMutableArray alloc] init] autorelease];
NSScanner* dataScanner = [NSScanner scannerWithString:dataString];
NSString* resultString = nil;
NSString* userAtClient = GetUserAtClientString();
while ( [dataScanner scanUpToString:kEndOfLineToken intoString:&resultString] == YES )
{
char* data = (char*)[resultString cString];
NSString* changeNumber;
NSString* userInfo;
NSString* changeDesc;
char* startPos = data;
char* curPos = data;
char* endPos = data + [resultString length];
// now go until we get to a space, skipping 'Change '
if ( !ScanJustPastChar (&curPos, endPos, ' ') )
continue;
startPos = curPos;
// now go until we get to a space
if ( !ScanJustPastChar (&curPos, endPos, ' ') )
continue;
// get the change number
changeNumber = [NSString stringWithCString:startPos length:(curPos - startPos - 1)];
// skip 'on '
curPos += 3;
startPos = curPos;
// go until we get to a space
if ( !ScanJustPastChar (&curPos, endPos, ' ') )
continue;
// skip 'by '
curPos += 3;
startPos = curPos;
// go until we get to a space
if ( !ScanJustPastChar (&curPos, endPos, ' ') )
continue;
// the user info is next
userInfo = [NSString stringWithCString:startPos length:(curPos - startPos - 1)];
// go until we get to a '
if ( !ScanJustPastChar (&curPos, endPos, '\'') )
continue;
startPos = curPos;
// go until we get to a '
if ( !ScanJustPastChar (&curPos, endPos, '\'') )
continue;
// get the change desc
changeDesc = [NSString stringWithCString:startPos length:(curPos - startPos - 1)];
[changesArray addObject:[[[PerforceChangeList alloc]
initWithNumber:changeNumber
withUserInfo:userInfo
withChangeDesc:changeDesc
isClient:[userAtClient isEqualTo:userInfo]] autorelease]];
}
if ( [changesArray count] > 0 )
{
// Sort the changeFileArray by change name
[changesArray sortUsingSelector:@selector(compare:)];
}
return changesArray;
}
BOOL ScanJustPastChar (char** inCurPos, char* endPos, char scanChar)
{
char* curPos = *inCurPos;
if ( curPos >= endPos )
return NO;
// go until we get to a space
while ( (*curPos != scanChar) && (curPos < endPos) )
{
curPos++;
}
curPos++;
// continue if we are at end of line
if ( curPos > endPos )
return NO;
*inCurPos = curPos;
return YES;
}
@end
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #6 | 4208 | Jeff Argast |
Added command line parsing and changed the sorting of user information in the pending changes view |
||
| #5 | 3941 | Jeff Argast | Simplified fstat, branches, and job parsing. | ||
| #4 | 3936 | Jeff Argast |
Integrated changes from Paul Ferguson's branch Fixed parse error in PerforceUser |
||
| #3 | 3196 | Jeff Argast |
Submitted Paul's changes to fix a hanging bug when a client root has a non-ASCII character. His changes also clean up the parsing of clients tremendously. |
||
| #2 | 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. |
||
| #1 | 2732 | Jeff Argast | Initial submission of P4Cocoa |