-
Notifications
You must be signed in to change notification settings - Fork 603
/
PBGitRevList.m
117 lines (95 loc) · 3.69 KB
/
PBGitRevList.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//
// PBGitRevList.m
// GitX
//
// Created by Pieter de Bie on 17-06-08.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import "PBGitRevList.h"
#import "PBGitRepository.h"
#import "PBGitCommit.h"
#import "PBGitGrapher.h"
@implementation PBGitRevList
@synthesize commits, grapher;
- initWithRepository: (id) repo andRevListParameters: (NSArray*) params
{
parameters = params;
repository = repo;
[self readCommits];
[repository addObserver:self forKeyPath:@"currentBranch" options:0 context:nil];
return self;
}
- (void) readCommits
{
// We use refparse to get the commit sha that we will parse. That way,
// we can check if the current branch is the same as the previous one
// and in that case we don't have to reload the revision list.
// If no branch was selected, use the current HEAD
NSString* newRef = [repository currentBranch];
if (!newRef || [newRef isEqualToString:@""])
newRef = @"HEAD";
newRef = [repository parseReference:newRef];
if ([newRef isEqualToString:currentRef])
return;
currentRef = newRef;
NSThread * commitThread = [[NSThread alloc] initWithTarget: self selector: @selector(walkRevisionList) object:nil];
[commitThread start];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context
{
if (object == repository)
[self readCommits];
}
- (void) walkRevisionList
{
NSMutableArray * newArray = [NSMutableArray array];
NSDate* start = [NSDate date];
NSFileHandle* handle = [repository handleForArguments:[NSArray arrayWithObjects:@"log", @"--topo-order", @"--pretty=format:%H\01%an\01%s\01%P\01%at", currentRef, nil]];
int fd = [handle fileDescriptor];
FILE* f = fdopen(fd, "r");
int BUFFERSIZE = 2048;
char buffer[BUFFERSIZE];
buffer[BUFFERSIZE - 2] = 0;
char* l;
int num = 0;
NSMutableString* currentLine = [NSMutableString string];
while (l = fgets(buffer, BUFFERSIZE, f)) {
NSString *s = [NSString stringWithCString:(const char *)l encoding:NSUTF8StringEncoding];
if ([s length] == 0)
s = [NSString stringWithCString:(const char *)l encoding:NSASCIIStringEncoding];
[currentLine appendString: s];
// If buffer is full, we go for another round
if (buffer[BUFFERSIZE - 2] != 0) {
//NSLog(@"Line too long!");
buffer[BUFFERSIZE - 2] = 0;
continue;
}
// If we are here, we currentLine is a full line.
NSArray* components = [currentLine componentsSeparatedByString:@"\01"];
if ([components count] < 5) {
NSLog(@"Can't split string: %@", currentLine);
continue;
}
PBGitCommit* newCommit = [[PBGitCommit alloc] initWithRepository: repository andSha: [components objectAtIndex:0]];
NSArray* parents = [[components objectAtIndex:3] componentsSeparatedByString:@" "];
newCommit.parents = parents;
newCommit.subject = [components objectAtIndex:2];
newCommit.author = [components objectAtIndex:1];
newCommit.date = [NSDate dateWithTimeIntervalSince1970:[[components objectAtIndex:4] intValue]];
[newArray addObject: newCommit];
num++;
if (num % 10000 == 0)
[self performSelectorOnMainThread:@selector(setCommits:) withObject:newArray waitUntilDone:NO];
currentLine = [NSMutableString string];
}
[self performSelectorOnMainThread:@selector(setCommits:) withObject:newArray waitUntilDone:YES];
PBGitGrapher* g = [[PBGitGrapher alloc] initWithRepository: repository];
[g parseCommits: self.commits];
[self performSelectorOnMainThread:@selector(setGrapher:) withObject:g waitUntilDone:YES];
[self performSelectorOnMainThread:@selector(setCommits:) withObject:newArray waitUntilDone:YES];
NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:start];
NSLog(@"Loaded %i commits in %f seconds", num, duration);
[NSThread exit];
}
@end