Skip to content

Commit 3f7a79c

Browse files
committed
New History view
Less javascript
1 parent 6959a15 commit 3f7a79c

File tree

8 files changed

+339
-391
lines changed

8 files changed

+339
-391
lines changed

GLFileView.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
- (void)didLoad;
3030
- (NSString *)parseBlame:(NSString *)txt;
3131
+ (NSString *)parseHTML:(NSString *)txt;
32-
+ (NSString *) parseDiff:(NSString *)txt;
32+
+ (NSString *)parseDiff:(NSString *)txt;
33+
+ (NSString *)parseDiffTree:(NSString *)txt;
3334
+(BOOL)isStartDiff:(NSString *)line;
3435
+(BOOL)isStartBlock:(NSString *)line;
3536

GLFileView.m

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,31 @@ + (NSString *) parseHTML:(NSString *)txt
223223
return txt;
224224
}
225225

226-
+ (NSString *) parseDiff:(NSString *)txt
226+
+ (NSString *)parseDiffTree:(NSString *)txt
227+
{
228+
NSArray *lines = [txt componentsSeparatedByString:@"\n"];
229+
NSMutableString *res=[NSMutableString string];
230+
[res appendString:@"<ul>"];
231+
int i;
232+
for (i=1; i<[lines count]; i++) {
233+
NSString *line=[lines objectAtIndex:i];
234+
NSArray *fields=[line componentsSeparatedByString:@" "];
235+
NSArray *fileStatus=[[fields objectAtIndex:4] componentsSeparatedByString:@"\t"];
236+
NSString *status=[[fileStatus objectAtIndex:0] substringToIndex:1]; // ignore the score
237+
NSString *file=[fileStatus objectAtIndex:1];
238+
NSString *txt=file;
239+
NSString *fileName=file;
240+
if([status isEqualToString:@"C"] || [status isEqualToString:@"R"]){
241+
txt=[NSString stringWithFormat:@"%@ -&gt; %@",file,[fileStatus objectAtIndex:2]];
242+
fileName=[fileStatus objectAtIndex:2];
243+
}
244+
[res appendString:[NSString stringWithFormat:@"<li><a class='%@' href='#%@' representedFile='%@'>%@</a></li>",status,file,fileName,txt]];
245+
}
246+
[res appendString:@"</ul>"];
247+
return res;
248+
}
249+
250+
+ (NSString *)parseDiff:(NSString *)txt
227251
{
228252
txt=[self parseHTML:txt];
229253

@@ -250,11 +274,15 @@ + (NSString *) parseDiff:(NSString *)txt
250274
NSArray *pos_l=[[pos objectAtIndex:0] componentsSeparatedByString:@","];
251275
NSArray *pos_r=[[pos objectAtIndex:1] componentsSeparatedByString:@","];
252276

253-
l_line=l_int=abs([[pos_l objectAtIndex:0]integerValue]);
254-
l_end=l_line+[[pos_l objectAtIndex:1]integerValue];
277+
l_end=l_line=l_int=abs([[pos_l objectAtIndex:0]integerValue]);
278+
if ([pos_l count]>1) {
279+
l_end=l_line+[[pos_l objectAtIndex:1]integerValue];
280+
}
255281

256-
r_line=r_int=[[pos_r objectAtIndex:0]integerValue];
257-
r_end=r_line+[[pos_r objectAtIndex:1]integerValue];
282+
r_end=r_line=r_int=[[pos_r objectAtIndex:0]integerValue];
283+
if ([pos_r count]>1) {
284+
r_end=r_line+[[pos_r objectAtIndex:1]integerValue];
285+
}
258286

259287
[res appendString:[NSString stringWithFormat:@"<tr class='header'><td colspan='3'>%@</td></tr>",line]];
260288
inBlock=TRUE;
@@ -274,7 +302,8 @@ + (NSString *) parseDiff:(NSString *)txt
274302
if(inDiff)
275303
[res appendString:@"</tbody></table>"];
276304
inDiff=TRUE;
277-
[res appendString:@"<table class='diff'><thead><tr><td colspan='3'>"];
305+
NSString *fileName=[self getFileName:line];
306+
[res appendString:[NSString stringWithFormat:@"<table id='%@' class='diff'><thead><tr><td colspan='3'>",fileName]];
278307
[res appendString:[NSString stringWithFormat:@"<p>%@</p>",line]];
279308
}else if(inDiff){
280309
[res appendString:[NSString stringWithFormat:@"<p>%@</p>",line]];
@@ -285,14 +314,20 @@ + (NSString *) parseDiff:(NSString *)txt
285314
return res;
286315
}
287316

317+
+(NSString *)getFileName:(NSString *)line{
318+
NSRange b = [line rangeOfString:@"b/"];
319+
NSString *file=[line substringFromIndex:b.location+2];
320+
return file;
321+
}
322+
288323
+(BOOL)isStartDiff:(NSString *)line
289324
{
290325
return (([line length]>10) && [[line substringToIndex:10] isEqualToString:@"diff --git"]);
291326
}
292327

293328
+(BOOL)isStartBlock:(NSString *)line
294329
{
295-
return (([line length]>2) && [[line substringToIndex:2] isEqualToString:@"@@"]);
330+
return (([line length]>3) && [[line substringToIndex:3] isEqualToString:@"@@ "]);
296331
}
297332

298333
- (NSString *) parseBlame:(NSString *)txt

PBWebController.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,6 @@
2626

2727
- (WebScriptObject *) script;
2828
- (void) closeView;
29+
- (BOOL) isFeatureEnabled:(NSString *)feature;
30+
2931
@end

PBWebHistoryController.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
@class PBGitSHA;
1818

19-
2019
@interface PBWebHistoryController : PBWebController {
2120
IBOutlet PBGitHistoryController* historyController;
2221
IBOutlet id<PBRefContextDelegate> contextMenuDelegate;
@@ -27,6 +26,8 @@
2726

2827
- (void) changeContentTo: (PBGitCommit *) content;
2928
- (void) sendKey: (NSString*) key;
29+
- (NSString *)parseHeader:(NSString *)txt withRefs:(NSString *)badges;
30+
- (NSString *) someMethodThatReturnsSomeHashForSomeString:(NSString*)concat;
3031

3132
@property (readonly) NSString* diff;
3233
@end

PBWebHistoryController.m

Lines changed: 123 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#import "PBWebHistoryController.h"
1010
#import "PBGitDefaults.h"
1111
#import "PBGitSHA.h"
12+
#import "GLFileView.h"
13+
#import <CommonCrypto/CommonDigest.h>
1214

1315
@implementation PBWebHistoryController
1416

@@ -26,7 +28,7 @@ - (void)closeView
2628
{
2729
[[self script] setValue:nil forKey:@"commit"];
2830
[historyController removeObserver:self forKeyPath:@"webCommit"];
29-
31+
3032
[super closeView];
3133
}
3234

@@ -48,31 +50,17 @@ - (void) changeContentTo: (PBGitCommit *) content
4850
{
4951
if (content == nil || !finishedLoading)
5052
return;
51-
52-
// The sha is the same, but refs may have changed.. reload it lazy
53-
if ([currentSha isEqual:[content sha]])
54-
{
55-
[[self script] callWebScriptMethod:@"reload" withArguments: nil];
56-
return;
57-
}
58-
59-
NSArray *arguments = [NSArray arrayWithObjects:content, [[[historyController repository] headRef] simpleRef], nil];
60-
id scriptResult = [[self script] callWebScriptMethod:@"loadCommit" withArguments: arguments];
61-
if (!scriptResult) {
62-
// the web view is not really ready for scripting???
63-
[self performSelector:_cmd withObject:content afterDelay:0.05];
64-
return;
65-
}
53+
6654
currentSha = [content sha];
67-
55+
6856
// Now we load the extended details. We used to do this in a separate thread,
6957
// but this caused some funny behaviour because NSTask's and NSThread's don't really
7058
// like each other. Instead, just do it async.
71-
72-
NSMutableArray *taskArguments = [NSMutableArray arrayWithObjects:@"show", @"--pretty=raw", @"-M", @"--no-color", [currentSha string], nil];
59+
60+
NSMutableArray *taskArguments = [NSMutableArray arrayWithObjects:@"show", @"--summary", @"--pretty=raw", [currentSha string], nil];
7361
if (![PBGitDefaults showWhitespaceDifferences])
7462
[taskArguments insertObject:@"-w" atIndex:1];
75-
63+
7664
NSFileHandle *handle = [repository handleForArguments:taskArguments];
7765
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
7866
// Remove notification, in case we have another one running
@@ -84,25 +72,122 @@ - (void) changeContentTo: (PBGitCommit *) content
8472
- (void)commitDetailsLoaded:(NSNotification *)notification
8573
{
8674
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSFileHandleReadToEndOfFileCompletionNotification object:nil];
87-
75+
8876
NSData *data = [[notification userInfo] valueForKey:NSFileHandleNotificationDataItem];
8977
if (!data)
9078
return;
91-
79+
9280
NSString *details = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
9381
if (!details)
9482
details = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
95-
83+
9684
if (!details)
9785
return;
86+
87+
88+
NSMutableString *refs=[NSMutableString string];
89+
NSArray *refsA=[historyController.webCommit refs];
90+
NSString *currentRef=[[[historyController repository] headRef] simpleRef];
91+
NSString *style=@"";
92+
int r=0;
93+
for(r=0;r<[refsA count];r++){
94+
PBGitRef *ref=[refsA objectAtIndex:r];
95+
if([currentRef isEqualToString:[ref ref]]){
96+
style=[NSString stringWithFormat:@"currentBranch refs %@",[ref type]];
97+
}else{
98+
style=[NSString stringWithFormat:@"refs %@",[ref type]];
99+
}
100+
[refs appendString:[NSString stringWithFormat:@"<span class='%@'>%@</span>",style,[ref shortName]]];
101+
}
102+
103+
// Header
104+
NSString *header=[self parseHeader:details withRefs:refs];
105+
106+
// File list
107+
NSString *dt=[repository outputInWorkdirForArguments:[NSArray arrayWithObjects:@"diff-tree", @"-r", @"-C90%", @"-M90%", [currentSha string], nil]];
108+
NSString *fileList=[GLFileView parseDiffTree:dt];
109+
110+
// Diffs list
111+
NSString *d=[repository outputInWorkdirForArguments:[NSArray arrayWithObjects:@"diff-tree", @"--cc", @"-C90%", @"-M90%", [currentSha string], nil]];
112+
NSString *diffs=[GLFileView parseDiff:d];
113+
114+
NSString *html=[NSString stringWithFormat:@"%@%@%@",header,fileList,diffs];
115+
116+
[[view windowScriptObject] callWebScriptMethod:@"showDiff" withArguments:[NSArray arrayWithObject:html]];
117+
118+
#if 1
119+
NSString *dom=[[[[view mainFrame] DOMDocument] documentElement] outerHTML];
120+
NSString *tmpFile=@"~/tmp/test2.html";
121+
[dom writeToFile:[tmpFile stringByExpandingTildeInPath] atomically:true encoding:NSUTF8StringEncoding error:nil];
122+
#endif
123+
}
124+
125+
- (NSString *)parseHeader:(NSString *)txt withRefs:(NSString *)badges
126+
{
127+
NSArray *lines = [txt componentsSeparatedByString:@"\n"];
128+
NSString *line;
129+
NSString *last_mail=@"";
130+
NSMutableString *auths=[NSMutableString string];
131+
NSMutableString *refs=[NSMutableString string];
132+
NSMutableString *subject=[NSMutableString string];
133+
BOOL subj=FALSE;
134+
135+
int i;
136+
for (i=0; i<[lines count]; i++) {
137+
line=[lines objectAtIndex:i];
138+
if([line length]==0){
139+
if(!subj){
140+
subj=TRUE;
141+
}else{
142+
i=[lines count];
143+
}
144+
}else{
145+
if (subj) {
146+
[subject appendString:[NSString stringWithFormat:@"%@<br/>",[line stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]]];
147+
}else{
148+
NSArray *comps=[line componentsSeparatedByString:@" "];
149+
if([comps count]==2){
150+
[refs appendString:[NSString stringWithFormat:@"<tr><td>%@</td><td><a href='' onclick='selectCommit(this.innerHTML); return false;'>%@</a></td></tr>",[comps objectAtIndex:0],[comps objectAtIndex:1]]];
151+
}else if([comps count]>2){
152+
NSRange r_email_i = [line rangeOfString:@"<"];
153+
NSRange r_email_e = [line rangeOfString:@">"];
154+
NSRange r_name_i = [line rangeOfString:@" "];
155+
156+
NSString *rol=[line substringToIndex:r_name_i.location];
157+
NSString *name=[line substringWithRange:NSMakeRange(r_name_i.location,(r_email_i.location-r_name_i.location))];
158+
NSString *email=[line substringWithRange:NSMakeRange(r_email_i.location+1,((r_email_e.location-1)-r_email_i.location))];
159+
NSString *time=[line substringFromIndex:r_email_e.location+2];
160+
161+
if(![email isEqualToString:last_mail]){
162+
[auths appendString:[NSString stringWithFormat:@"<div class='user %@ clearfix'>",rol]];
163+
if([self isFeatureEnabled:@"gravatar"]){
164+
NSString *hash=[self someMethodThatReturnsSomeHashForSomeString:email];
165+
[auths appendString:[NSString stringWithFormat:@"<img class='avatar' src='http://www.gravatar.com/avatar/%@?d=wavatar&s=30'/>",hash]];
166+
}
167+
[auths appendString:[NSString stringWithFormat:@"<p class='name'>%@ <span class='rol'>(%@)</span></p>",name,rol]];
168+
[auths appendString:[NSString stringWithFormat:@"<p class='time'>%@</p></div>",time]];
169+
}
170+
last_mail=email;
171+
}
172+
}
173+
}
174+
}
175+
176+
return [NSString stringWithFormat:@"<div id='header' class='clearfix'><table class='references'>%@</table><p class='subject'>%@</p>%@<div id='badges'>%@</div></div>",refs,subject,auths,badges];
177+
}
98178

99-
NSRange range = [details rangeOfString:@"diff --git"];
100-
NSString *commitDetails=[details substringToIndex:range.location];
101-
NSString *diffs=[details substringFromIndex:range.location];
102-
NSString *pd=[GLFileView parseDiff:diffs];
179+
- (NSString *) someMethodThatReturnsSomeHashForSomeString:(NSString*)concat {
180+
const char *concat_str = [concat UTF8String];
181+
unsigned char result[CC_MD5_DIGEST_LENGTH];
182+
CC_MD5(concat_str, strlen(concat_str), result);
183+
184+
NSMutableString *hash = [NSMutableString string];
185+
186+
int i;
187+
for (i = 0; i < 16; i++)
188+
[hash appendFormat:@"%02x", result[i]];
103189

104-
[[view windowScriptObject] callWebScriptMethod:@"loadCommitDetails" withArguments:[NSArray arrayWithObject:commitDetails]];
105-
[[view windowScriptObject] callWebScriptMethod:@"newStyle" withArguments:[NSArray arrayWithObject:pd]];
190+
return hash;
106191
}
107192

108193
- (void)selectCommit:(NSString *)sha
@@ -126,10 +211,10 @@ - (void) copySource
126211

127212
- (NSArray *) webView:(WebView *)sender
128213
contextMenuItemsForElement:(NSDictionary *)element
129-
defaultMenuItems:(NSArray *)defaultMenuItems
214+
defaultMenuItems:(NSArray *)defaultMenuItems
130215
{
131216
DOMNode *node = [element valueForKey:@"WebElementDOMNode"];
132-
217+
133218
while (node) {
134219
// Every ref has a class name of 'refs' and some other class. We check on that to see if we pressed on a ref.
135220
if ([[node className] hasPrefix:@"refs "]) {
@@ -144,27 +229,27 @@ - (NSArray *) webView:(WebView *)sender
144229
}
145230
if ([node hasAttributes] && [[node attributes] getNamedItem:@"representedFile"])
146231
return [historyController menuItemsForPaths:[NSArray arrayWithObject:[[[node attributes] getNamedItem:@"representedFile"] value]]];
147-
else if ([[node class] isEqual:[DOMHTMLImageElement class]]) {
148-
// Copy Image is the only menu item that makes sense here since we don't need
232+
else if ([[node class] isEqual:[DOMHTMLImageElement class]]) {
233+
// Copy Image is the only menu item that makes sense here since we don't need
149234
// to download the image or open it in a new window (besides with the
150235
// current implementation these two entries can crash GitX anyway)
151236
for (NSMenuItem *item in defaultMenuItems)
152237
if ([item tag] == WebMenuItemTagCopyImageToClipboard)
153238
return [NSArray arrayWithObject:item];
154239
return nil;
155-
}
156-
240+
}
241+
157242
node = [node parentNode];
158243
}
159-
244+
160245
return defaultMenuItems;
161246
}
162247

163248

164249
// Open external links in the default browser
165250
- (void)webView:(WebView *)sender decidePolicyForNewWindowAction:(NSDictionary *)actionInformation
166-
request:(NSURLRequest *)request
167-
newFrameName:(NSString *)frameName
251+
request:(NSURLRequest *)request
252+
newFrameName:(NSString *)frameName
168253
decisionListener:(id < WebPolicyDecisionListener >)listener
169254
{
170255
[[NSWorkspace sharedWorkspace] openURL:[request URL]];

0 commit comments

Comments
 (0)