diff --git a/GLFileView.m b/GLFileView.m index dcedd3a..7fc7fe3 100644 --- a/GLFileView.m +++ b/GLFileView.m @@ -20,6 +20,10 @@ @interface GLFileView () - (void)saveSplitViewPosition; ++ (NSString *)parseDiffBlock:(NSString *)txt; ++ (NSString *)parseDiffHeader:(NSString *)txt; ++ (NSString *)parseDiffChunk:(NSString *)txt; ++ (NSString *)parseBinaryDiff:(NSString *)txt; @end @@ -120,11 +124,12 @@ if(!theError){ NSString *filePath = [file fullPath]; fileTxt=[fileTxt stringByReplacingOccurrencesOfString:@"\t" withString:@"    "]; - fileTxt=[fileTxt stringByReplacingOccurrencesOfString:@"{SHA}" withString:file.sha]; + NSLog(@"file.sha='%@'",file.sha); + fileTxt=[fileTxt stringByReplacingOccurrencesOfString:@"{SHA_PREV}" withString:file.sha]; if(diffType==@"h") { - fileTxt=[fileTxt stringByReplacingOccurrencesOfString:@"{SHA2}" withString:@"HEAD"]; + fileTxt=[fileTxt stringByReplacingOccurrencesOfString:@"{SHA}" withString:@"HEAD"]; }else { - fileTxt=[fileTxt stringByReplacingOccurrencesOfString:@"{SHA2}" withString:@"--"]; + fileTxt=[fileTxt stringByReplacingOccurrencesOfString:@"{SHA}" withString:@"--"]; } [script callWebScriptMethod:@"showFile" withArguments:[NSArray arrayWithObjects:fileTxt, filePath, nil]]; }else{ @@ -287,245 +292,291 @@ + (NSString *)parseDiff:(NSString *)txt { txt=[self parseHTML:txt]; - - NSArray *lines = [txt componentsSeparatedByString:@"\n"]; - NSString *line; + NSMutableString *res=[NSMutableString string]; + NSScanner *scan=[NSScanner scannerWithString:txt]; + NSString *block; - int l_line,l_end; - int r_line,r_end; + [scan scanUpToString:@"diff --git" intoString:NULL]; //move to first diff - int i=0; - do { - line=[lines objectAtIndex:i]; - if([GLFileView isStartDiff:line]){ - NSString *fileName=[self getFileName:line]; - [res appendString:[NSString stringWithFormat:@""]; + while([scan scanString:@"diff --git" intoString:NULL]){ // is a diff start? + [scan scanUpToString:@"diff --git" intoString:&block]; + [res appendString:[GLFileView parseDiffBlock:[NSString stringWithFormat:@"diff --git %@",block]]]; + } + + return res; +} - if (!line) - break; // do nothing, this is probably header-only diff (permissions change, maybe) - - if([self isBinaryFile:line]){ - NSArray *files=[self getFilesNames:line]; - if(![[files objectAtIndex:0] isAbsolutePath]){ - [res appendString:[NSString stringWithFormat:@"",[files objectAtIndex:0]]]; - if([GLFileView isImage:[files objectAtIndex:0]]){ - [res appendString:[NSString stringWithFormat:@"",[files objectAtIndex:0]]]; - } - } - if(![[files objectAtIndex:1] isAbsolutePath]){ - [res appendString:[NSString stringWithFormat:@"",[files objectAtIndex:1]]]; - if([GLFileView isImage:[files objectAtIndex:1]]){ - [res appendString:[NSString stringWithFormat:@"",[files objectAtIndex:1]]]; - } - } - }else{ - do{ - NSString *header=[line substringFromIndex:3]; - NSRange hr = NSMakeRange(0, [header rangeOfString:@" @@"].location); - header=[header substringWithRange:hr]; - - NSArray *pos=[header componentsSeparatedByString:@" "]; - NSArray *pos_l=[[pos objectAtIndex:0] componentsSeparatedByString:@","]; - NSArray *pos_r=[[pos objectAtIndex:1] componentsSeparatedByString:@","]; - - l_end=l_line=abs([[pos_l objectAtIndex:0]integerValue]); - if ([pos_l count]>1) { - l_end=l_line+[[pos_l objectAtIndex:1]integerValue]; - } - - r_end=r_line=[[pos_r objectAtIndex:0]integerValue]; - if ([pos_r count]>1) { - r_end=r_line+[[pos_r objectAtIndex:1]integerValue]; - } - - [res appendString:[NSString stringWithFormat:@"",line]]; - do{ - line=[lines objectAtIndex:++i]; - NSString *s=[line substringToIndex:1]; - if([s isEqualToString:@" "]){ - [res appendString:[NSString stringWithFormat:@"",l_line++,r_line++]]; - }else if([s isEqualToString:@"-"]){ - [res appendString:[NSString stringWithFormat:@"",l_line++]]; - }else if([s isEqualToString:@"+"]){ - [res appendString:[NSString stringWithFormat:@"",r_line++]]; - } - if(![s isEqualToString:@"\\"]){ - [res appendString:[NSString stringWithFormat:@"",[line substringFromIndex:1]]]; - } - }while((l_line
",fileName]]; - do{ - [res appendString:[NSString stringWithFormat:@"

%@

",line]]; - line=nil; - if (i<([lines count]-1)) - line = [lines objectAtIndex:++i]; - }while([GLFileView isDiffHeader:line]); - [res appendString:@"
"]; - if(![self isBinaryFile:line]){ - [res appendString:[NSString stringWithFormat:@"",fileName]]; - } - [res appendString:@"
%@
%@
%@
%d%d
%d
%d%@
"]; - }else { - i++; - } - }while(i<[lines count]); - - return res; ++ (NSString *)parseDiffBlock:(NSString *)txt +{ + NSMutableString *res=[NSMutableString string]; + NSScanner *scan=[NSScanner scannerWithString:txt]; + NSString *block; + + [scan scanUpToString:@"\n@@ " intoString:&block]; + [res appendString:@""]; + [res appendString:[GLFileView parseDiffHeader:block]]; + [res appendString:@""]; + + if([txt rangeOfString:@"Binary files"].location!=NSNotFound){ + [res appendString:[GLFileView parseBinaryDiff:block]]; + } + + while([scan scanString:@"@@ " intoString:NULL]){ + [scan scanUpToString:@"\n@@ " intoString:&block]; + [res appendString:[GLFileView parseDiffChunk:[NSString stringWithFormat:@"@@ %@",block]]]; + } + + [res appendString:@"
"]; + + return res; +} + ++ (NSString *)parseBinaryDiff:(NSString *)txt +{ + NSMutableString *res=[NSMutableString string]; + NSScanner *scan=[NSScanner scannerWithString:txt]; + NSString *block; + + [scan scanUpToString:@"Binary files" intoString:NULL]; + [scan scanUpToString:@"" intoString:&block]; + + NSArray *files=[self getFilesNames:block]; + [res appendString:@""]; + [res appendString:[NSString stringWithFormat:@"%@
",[files objectAtIndex:0]]]; + if(![[files objectAtIndex:0] isAbsolutePath]){ + if([GLFileView isImage:[files objectAtIndex:0]]){ + [res appendString:[NSString stringWithFormat:@"",[files objectAtIndex:0]]]; + } + } + [res appendString:@"=>"]; + [res appendString:[NSString stringWithFormat:@"%@
",[files objectAtIndex:1]]]; + if(![[files objectAtIndex:1] isAbsolutePath]){ + if([GLFileView isImage:[files objectAtIndex:1]]){ + [res appendString:[NSString stringWithFormat:@"",[files objectAtIndex:1]]]; + } + } + [res appendString:@""]; + + return res; +} + ++ (NSString *)parseDiffChunk:(NSString *)txt +{ + NSEnumerator *lines = [[txt componentsSeparatedByString:@"\n"] objectEnumerator]; + NSMutableString *res=[NSMutableString string]; + + NSString *line; + int l_line,l_end; + int r_line,r_end; + + line=[lines nextObject]; + NSLog(@"-=%@=-",line); + NSString *header=[line substringFromIndex:3]; + NSRange hr = NSMakeRange(0, [header rangeOfString:@" @@"].location); + header=[header substringWithRange:hr]; + + NSArray *pos=[header componentsSeparatedByString:@" "]; + NSArray *pos_l=[[pos objectAtIndex:0] componentsSeparatedByString:@","]; + NSArray *pos_r=[[pos objectAtIndex:1] componentsSeparatedByString:@","]; + + l_end=l_line=abs([[pos_l objectAtIndex:0]integerValue]); + if ([pos_l count]>1) { + l_end=l_line+[[pos_l objectAtIndex:1]integerValue]; + } + + r_end=r_line=[[pos_r objectAtIndex:0]integerValue]; + if ([pos_r count]>1) { + r_end=r_line+[[pos_r objectAtIndex:1]integerValue]; + } + + [res appendString:[NSString stringWithFormat:@"%@",line]]; + do{ + line=[lines nextObject]; + NSString *s=[line substringToIndex:1]; + if([s isEqualToString:@" "]){ + [res appendString:[NSString stringWithFormat:@"%d%d",l_line++,r_line++]]; + }else if([s isEqualToString:@"-"]){ + [res appendString:[NSString stringWithFormat:@"%d",l_line++]]; + }else if([s isEqualToString:@"+"]){ + [res appendString:[NSString stringWithFormat:@"%d",r_line++]]; + } + if(![s isEqualToString:@"\\"]){ + [res appendString:[NSString stringWithFormat:@"%@",[line substringFromIndex:1]]]; + } + }while((l_line
",fileName]]; + do{ + [res appendString:[NSString stringWithFormat:@"

%@

",line]]; + }while((line=[lines nextObject])); + [res appendString:@"
"]; + + if([txt rangeOfString:@"Binary files"].location==NSNotFound){ + [res appendString:[NSString stringWithFormat:@"

open in
FileMerge
",fileName]]; + } + + [res appendString:@""]; + + return res; } +(NSString *)getFileName:(NSString *)line { - NSRange b = [line rangeOfString:@"b/"]; - NSString *file=[line substringFromIndex:b.location+2]; - return file; + NSRange b = [line rangeOfString:@"b/"]; + NSString *file=[line substringFromIndex:b.location+2]; + return file; } +(NSArray *)getFilesNames:(NSString *)line { - NSString *a = nil; - NSString *b = nil; - NSScanner *scanner=[NSScanner scannerWithString:line]; - if([scanner scanString:@"Binary files " intoString:NULL]){ - [scanner scanUpToString:@" and" intoString:&a]; - [scanner scanString:@"and" intoString:NULL]; - [scanner scanUpToString:@" differ" intoString:&b]; - } - if (![a isAbsolutePath]) { - a=[a substringFromIndex:2]; - } - if (![b isAbsolutePath]) { - b=[b substringFromIndex:2]; - } - - return [NSArray arrayWithObjects:a,b,nil]; + NSString *a = nil; + NSString *b = nil; + NSScanner *scanner=[NSScanner scannerWithString:line]; + if([scanner scanString:@"Binary files " intoString:NULL]){ + [scanner scanUpToString:@" and" intoString:&a]; + [scanner scanString:@"and" intoString:NULL]; + [scanner scanUpToString:@" differ" intoString:&b]; + } + if (![a isAbsolutePath]) { + a=[a substringFromIndex:2]; + } + if (![b isAbsolutePath]) { + b=[b substringFromIndex:2]; + } + + return [NSArray arrayWithObjects:a,b,nil]; } +(NSString*)mimeTypeForFileName:(NSString*)name { NSString *mimeType = nil; - NSInteger i=[name rangeOfString:@"." options:NSBackwardsSearch].location; - if(i!=NSNotFound){ - NSString *ext=[name substringFromIndex:i+1]; - CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)ext, NULL); - if(UTI){ - CFStringRef registeredType = UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType); - if(registeredType){ - mimeType = NSMakeCollectable(registeredType); - } - CFRelease(UTI); - } - } + NSInteger i=[name rangeOfString:@"." options:NSBackwardsSearch].location; + if(i!=NSNotFound){ + NSString *ext=[name substringFromIndex:i+1]; + CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)ext, NULL); + if(UTI){ + CFStringRef registeredType = UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType); + if(registeredType){ + mimeType = NSMakeCollectable(registeredType); + } + CFRelease(UTI); + } + } return mimeType; } +(BOOL)isDiffHeader:(NSString*)line { - unichar c=[line characterAtIndex:0]; - return (c=='i') || (c=='m') || (c=='n') || (c=='d') || (c=='-') || (c=='+'); + unichar c=[line characterAtIndex:0]; + return (c=='i') || (c=='m') || (c=='n') || (c=='d') || (c=='-') || (c=='+'); } +(BOOL)isImage:(NSString*)file { - NSString *mimeType=[GLFileView mimeTypeForFileName:file]; - return (mimeType!=nil) && ([mimeType rangeOfString:@"image/" options:NSCaseInsensitiveSearch].location!=NSNotFound); + NSString *mimeType=[GLFileView mimeTypeForFileName:file]; + return (mimeType!=nil) && ([mimeType rangeOfString:@"image/" options:NSCaseInsensitiveSearch].location!=NSNotFound); } +(BOOL)isBinaryFile:(NSString *)line { - return (([line length]>12) && [[line substringToIndex:12] isEqualToString:@"Binary files"]); + return (([line length]>12) && [[line substringToIndex:12] isEqualToString:@"Binary files"]); } +(BOOL)isStartDiff:(NSString *)line { - return (([line length]>10) && [[line substringToIndex:10] isEqualToString:@"diff --git"]); + return (([line length]>10) && [[line substringToIndex:10] isEqualToString:@"diff --git"]); } +(BOOL)isStartBlock:(NSString *)line { - return (([line length]>3) && [[line substringToIndex:3] isEqualToString:@"@@ "]); + return (([line length]>3) && [[line substringToIndex:3] isEqualToString:@"@@ "]); } - (NSString *) parseBlame:(NSString *)txt { - txt=[GLFileView parseHTML:txt]; - - NSArray *lines = [txt componentsSeparatedByString:@"\n"]; - NSString *line; - NSMutableDictionary *headers=[NSMutableDictionary dictionary]; - NSMutableString *res=[NSMutableString string]; - - [res appendString:@"\n"]; - int i=0; - while(i<[lines count]){ - line=[lines objectAtIndex:i]; - NSArray *header=[line componentsSeparatedByString:@" "]; - if([header count]==4){ - NSString *commitID = (NSString *)[header objectAtIndex:0]; - int nLines=[(NSString *)[header objectAtIndex:3] intValue]; - [res appendFormat:@"\n",nLines]; - line=[lines objectAtIndex:++i]; - if([[[line componentsSeparatedByString:@" "] objectAtIndex:0] isEqual:@"author"]){ - NSString *author=[line stringByReplacingOccurrencesOfString:@"author" withString:@""]; - NSString *summary=nil; - while(summary==nil){ - line=[lines objectAtIndex:i++]; - if([[[line componentsSeparatedByString:@" "] objectAtIndex:0] isEqual:@"summary"]){ - summary=[line stringByReplacingOccurrencesOfString:@"summary" withString:@""]; - } - } - NSRange trunc_c={0,7}; - NSString *truncate_c=commitID; - if([commitID length]>8){ - truncate_c=[commitID substringWithRange:trunc_c]; - } - NSRange trunc={0,22}; - NSString *truncate_a=author; - if([author length]>22){ - truncate_a=[author substringWithRange:trunc]; - } - NSString *truncate_s=summary; - if([summary length]>30){ - truncate_s=[summary substringWithRange:trunc]; - } - NSString *block=[NSString stringWithFormat:@"\n\n"]; - }else{ - break; - } - [res appendString:@"\n"]; - } - [res appendString:@"

%@ %@

%@

\n",commitID,truncate_c,truncate_a,truncate_s]; - [headers setObject:block forKey:[header objectAtIndex:0]]; - } - [res appendString:[headers objectForKey:[header objectAtIndex:0]]]; - - NSMutableString *code=[NSMutableString string]; - do{ - line=[lines objectAtIndex:i++]; - }while([line characterAtIndex:0]!='\t'); - line=[line substringFromIndex:1]; - [code appendString:line]; - [code appendString:@"\n"]; - - int n; - for(n=1;n%@",[header objectAtIndex:2],code]; - [res appendString:@"
\n"]; - //NSLog(@"%@",res); - - return (NSString *)res; + txt=[GLFileView parseHTML:txt]; + + NSArray *lines = [txt componentsSeparatedByString:@"\n"]; + NSString *line; + NSMutableDictionary *headers=[NSMutableDictionary dictionary]; + NSMutableString *res=[NSMutableString string]; + + [res appendString:@"\n"]; + int i=0; + while(i<[lines count]){ + line=[lines objectAtIndex:i]; + NSArray *header=[line componentsSeparatedByString:@" "]; + if([header count]==4){ + NSString *commitID = (NSString *)[header objectAtIndex:0]; + int nLines=[(NSString *)[header objectAtIndex:3] intValue]; + [res appendFormat:@"\n",nLines]; + line=[lines objectAtIndex:++i]; + if([[[line componentsSeparatedByString:@" "] objectAtIndex:0] isEqual:@"author"]){ + NSString *author=[line stringByReplacingOccurrencesOfString:@"author" withString:@""]; + NSString *summary=nil; + while(summary==nil){ + line=[lines objectAtIndex:i++]; + if([[[line componentsSeparatedByString:@" "] objectAtIndex:0] isEqual:@"summary"]){ + summary=[line stringByReplacingOccurrencesOfString:@"summary" withString:@""]; + } + } + NSRange trunc_c={0,7}; + NSString *truncate_c=commitID; + if([commitID length]>8){ + truncate_c=[commitID substringWithRange:trunc_c]; + } + NSRange trunc={0,22}; + NSString *truncate_a=author; + if([author length]>22){ + truncate_a=[author substringWithRange:trunc]; + } + NSString *truncate_s=summary; + if([summary length]>30){ + truncate_s=[summary substringWithRange:trunc]; + } + NSString *block=[NSString stringWithFormat:@"\n\n"]; + }else{ + break; + } + [res appendString:@"\n"]; + } + [res appendString:@"

%@ %@

%@

\n",commitID,truncate_c,truncate_a,truncate_s]; + [headers setObject:block forKey:[header objectAtIndex:0]]; + } + [res appendString:[headers objectForKey:[header objectAtIndex:0]]]; + + NSMutableString *code=[NSMutableString string]; + do{ + line=[lines objectAtIndex:i++]; + }while([line characterAtIndex:0]!='\t'); + line=[line substringFromIndex:1]; + [code appendString:line]; + [code appendString:@"\n"]; + + int n; + for(n=1;n%@",[header objectAtIndex:2],code]; + [res appendString:@"
\n"]; + //NSLog(@"%@",res); + + return (NSString *)res; } @@ -538,38 +589,38 @@ - (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)dividerIndex { - return kFileListSplitViewLeftMin; + return kFileListSplitViewLeftMin; } - (CGFloat)splitView:(NSSplitView *)splitView constrainMaxCoordinate:(CGFloat)proposedMax ofSubviewAt:(NSInteger)dividerIndex { - return [splitView frame].size.width - [splitView dividerThickness] - kFileListSplitViewRightMin; + return [splitView frame].size.width - [splitView dividerThickness] - kFileListSplitViewRightMin; } // while the user resizes the window keep the left (file list) view constant and just resize the right view // unless the right view gets too small - (void)splitView:(NSSplitView *)splitView resizeSubviewsWithOldSize:(NSSize)oldSize { - NSRect newFrame = [splitView frame]; - - float dividerThickness = [splitView dividerThickness]; - - NSView *leftView = [[splitView subviews] objectAtIndex:0]; - NSRect leftFrame = [leftView frame]; - leftFrame.size.height = newFrame.size.height; - - if ((newFrame.size.width - leftFrame.size.width - dividerThickness) < kFileListSplitViewRightMin) { - leftFrame.size.width = newFrame.size.width - kFileListSplitViewRightMin - dividerThickness; - } - - NSView *rightView = [[splitView subviews] objectAtIndex:1]; - NSRect rightFrame = [rightView frame]; - rightFrame.origin.x = leftFrame.size.width + dividerThickness; - rightFrame.size.width = newFrame.size.width - rightFrame.origin.x; - rightFrame.size.height = newFrame.size.height; - - [leftView setFrame:leftFrame]; - [rightView setFrame:rightFrame]; + NSRect newFrame = [splitView frame]; + + float dividerThickness = [splitView dividerThickness]; + + NSView *leftView = [[splitView subviews] objectAtIndex:0]; + NSRect leftFrame = [leftView frame]; + leftFrame.size.height = newFrame.size.height; + + if ((newFrame.size.width - leftFrame.size.width - dividerThickness) < kFileListSplitViewRightMin) { + leftFrame.size.width = newFrame.size.width - kFileListSplitViewRightMin - dividerThickness; + } + + NSView *rightView = [[splitView subviews] objectAtIndex:1]; + NSRect rightFrame = [rightView frame]; + rightFrame.origin.x = leftFrame.size.width + dividerThickness; + rightFrame.size.width = newFrame.size.width - rightFrame.origin.x; + rightFrame.size.height = newFrame.size.height; + + [leftView setFrame:leftFrame]; + [rightView setFrame:rightFrame]; } // NSSplitView does not save and restore the position of the SplitView correctly so do it manually diff --git a/PBWebHistoryController.m b/PBWebHistoryController.m index 859387e..5c74df5 100644 --- a/PBWebHistoryController.m +++ b/PBWebHistoryController.m @@ -116,8 +116,8 @@ NSString *html=[NSString stringWithFormat:@"%@%@
%@
",header,fileList,diffs]; - html=[html stringByReplacingOccurrencesOfString:@"{SHA}" withString:[NSString stringWithFormat:@"%@^",[currentSha string]]]; - html=[html stringByReplacingOccurrencesOfString:@"{SHA2}" withString:[currentSha string]]; + html=[html stringByReplacingOccurrencesOfString:@"{SHA_PREV}" withString:[NSString stringWithFormat:@"%@^",[currentSha string]]]; + html=[html stringByReplacingOccurrencesOfString:@"{SHA}" withString:[currentSha string]]; [[view windowScriptObject] callWebScriptMethod:@"showCommit" withArguments:[NSArray arrayWithObject:html]]; diff --git a/html/views/diff/diffWindow.css b/html/views/diff/diffWindow.css index b80b988..932dbc1 100644 --- a/html/views/diff/diffWindow.css +++ b/html/views/diff/diffWindow.css @@ -4,6 +4,7 @@ table.diff { width: 100%; border-collapse: collapse; margin-bottom: 10px; + -webkit-box-shadow: 5px 5px 5px #ccc; } table.diff tr td { @@ -71,7 +72,6 @@ table.diff .filemerge { } #diff table.diff { - -webkit-box-shadow: 5px 5px 5px #ccc; width: 98%; margin: auto auto 20px 1%; }