Skip to content

Commit ede8892

Browse files
committed
PBGitRepository: Abstract revision walking to new class PBGitRevList
The revision walking code made the PBGitRepository unclean. Especially if we want to keep multiple PBGitRepository objects around (e.g. persistent data store), it needs to be more simple. This neatly extracts the revision walking code from the repository code.
1 parent 447a8dc commit ede8892

File tree

7 files changed

+1097
-1055
lines changed

7 files changed

+1097
-1055
lines changed

English.lproj/MainMenu.xib

+964-964
Large diffs are not rendered by default.

GitX.xcodeproj/project.pbxproj

+6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
F5945E170E02B0C200706420 /* PBGitRepository.m in Sources */ = {isa = PBXBuildFile; fileRef = F5945E160E02B0C200706420 /* PBGitRepository.m */; };
3232
F5B721C40E05CF7E00AF29DC /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = F5B721C20E05CF7E00AF29DC /* MainMenu.xib */; };
3333
F5DFFA6C0E075D8800617813 /* PBEasyFS.m in Sources */ = {isa = PBXBuildFile; fileRef = F5DFFA6B0E075D8800617813 /* PBEasyFS.m */; };
34+
F5FF4E180E0829C20006317A /* PBGitRevList.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FF4E170E0829C20006317A /* PBGitRevList.m */; };
3435
/* End PBXBuildFile section */
3536

3637
/* Begin PBXFileReference section */
@@ -76,6 +77,8 @@
7677
F5B721C30E05CF7E00AF29DC /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = "<group>"; };
7778
F5DFFA6A0E075D8800617813 /* PBEasyFS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBEasyFS.h; sourceTree = "<group>"; };
7879
F5DFFA6B0E075D8800617813 /* PBEasyFS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBEasyFS.m; sourceTree = "<group>"; };
80+
F5FF4E160E0829C20006317A /* PBGitRevList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitRevList.h; sourceTree = "<group>"; };
81+
F5FF4E170E0829C20006317A /* PBGitRevList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitRevList.m; sourceTree = "<group>"; };
7982
/* End PBXFileReference section */
8083

8184
/* Begin PBXFrameworksBuildPhase section */
@@ -188,6 +191,8 @@
188191
F56524EF0E02D45200F03B52 /* PBGitCommit.m */,
189192
F56174550E058893001DCD79 /* PBGitTree.h */,
190193
F56174560E058893001DCD79 /* PBGitTree.m */,
194+
F5FF4E160E0829C20006317A /* PBGitRevList.h */,
195+
F5FF4E170E0829C20006317A /* PBGitRevList.m */,
191196
);
192197
name = Git;
193198
sourceTree = "<group>";
@@ -311,6 +316,7 @@
311316
F513085B0E0740F2000C8BCD /* PBQLOutlineView.m in Sources */,
312317
F5DFFA6C0E075D8800617813 /* PBEasyFS.m in Sources */,
313318
F50FE0E30E07BE9600854FCD /* PBGitRevisionCell.m in Sources */,
319+
F5FF4E180E0829C20006317A /* PBGitRevList.m in Sources */,
314320
);
315321
runOnlyForDeploymentPostprocessing = 0;
316322
};

PBGitRepository.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
//
88

99
#import <Cocoa/Cocoa.h>
10+
#import "PBGitRevList.h"
1011

1112
@interface PBGitRepository : NSObject {
1213
NSString* path;
13-
NSArray* commits;
14+
PBGitRevList* revisionList;
1415
}
1516

1617
+ (void) setGitPath;
@@ -24,6 +25,6 @@
2425
- (void) addCommit: (id)obj;
2526

2627
@property (copy) NSString* path;
27-
@property (retain) NSArray* commits;
28+
@property (readonly) PBGitRevList* revisionList;
2829

2930
@end

PBGitRepository.m

+21-88
Original file line numberDiff line numberDiff line change
@@ -14,38 +14,12 @@
1414

1515
@implementation PBGitRepository
1616

17-
@synthesize path, commits;
18-
static NSString* gitPath = @"/usr/bin/env";
17+
@synthesize path;
18+
static NSString* gitPath;
1919

20-
+ (PBGitRepository*) repositoryWithPath:(NSString*) path
21-
{
22-
[self setGitPath];
23-
PBGitRepository* repo = [[PBGitRepository alloc] initWithPath: path];
24-
return repo;
25-
}
26-
27-
- (PBGitRepository*) initWithPath: (NSString*) p
28-
{
29-
if ([p hasSuffix:@".git"])
30-
self.path = p;
31-
else {
32-
NSString* newPath = [PBEasyPipe outputForCommand:gitPath withArgs:[NSArray arrayWithObjects:@"rev-parse", @"--git-dir", nil] inDir:p];
33-
if ([newPath isEqualToString:@".git"])
34-
self.path = [p stringByAppendingPathComponent:@".git"];
35-
else
36-
self.path = newPath;
37-
}
38-
39-
NSLog(@"Git path is: %@", self.path);
40-
41-
NSThread * commitThread = [[NSThread alloc] initWithTarget: self selector: @selector(initializeCommits) object:nil];
42-
[commitThread start];
43-
return self;
44-
}
45-
46-
47-
+ (void) setGitPath
20+
+ (void) initialize
4821
{
22+
// Try to find the path of the Git binary
4923
char* path = getenv("GIT_PATH");
5024
if (path != nil) {
5125
gitPath = [NSString stringWithCString:path];
@@ -54,79 +28,38 @@ + (void) setGitPath
5428

5529
// No explicit path. Try it with "which"
5630
gitPath = [PBEasyPipe outputForCommand:@"/usr/bin/which" withArgs:[NSArray arrayWithObject:@"git"]];
57-
31+
5832
if (gitPath.length == 0) {
5933
NSLog(@"Git path not found. Defaulting to /opt/pieter/bin/git");
6034
gitPath = @"/opt/pieter/bin/git";
6135
}
6236
}
6337

64-
- (void) addCommit: (id) obj
38+
+ (PBGitRepository*) repositoryWithPath:(NSString*) path
6539
{
66-
self.commits = [self.commits arrayByAddingObject:obj];
67-
}
6840

69-
- (void) setCommits:(NSArray*) obj
70-
{
71-
commits = obj;
41+
PBGitRepository* repo = [[PBGitRepository alloc] initWithPath: path];
42+
return repo;
7243
}
7344

74-
- (void) initializeCommits
45+
- (PBGitRepository*) initWithPath: (NSString*) p
7546
{
76-
77-
NSMutableArray * newArray = [NSMutableArray array];
78-
NSDate* start = [NSDate date];
79-
NSFileHandle* handle = [self handleForCommand:@"log --pretty=format:%H\01%an\01%s\01%P\01%at HEAD"];
80-
81-
int fd = [handle fileDescriptor];
82-
FILE* f = fdopen(fd, "r");
83-
int BUFFERSIZE = 2048;
84-
char buffer[BUFFERSIZE];
85-
buffer[BUFFERSIZE - 2] = 0;
86-
87-
char* l;
88-
int num = 0;
89-
NSMutableString* currentLine = [NSMutableString string];
90-
while (l = fgets(buffer, BUFFERSIZE, f)) {
91-
NSString *s = [NSString stringWithCString:(const char *)l encoding:NSUTF8StringEncoding];
92-
if ([s length] == 0)
93-
s = [NSString stringWithCString:(const char *)l encoding:NSASCIIStringEncoding];
94-
[currentLine appendString: s];
95-
96-
// If buffer is full, we go for another round
97-
if (buffer[BUFFERSIZE - 2] != 0) {
98-
//NSLog(@"Line too long!");
99-
buffer[BUFFERSIZE - 2] = 0;
100-
continue;
101-
}
102-
103-
// If we are here, we currentLine is a full line.
104-
NSArray* components = [currentLine componentsSeparatedByString:@"\01"];
105-
if ([components count] < 5) {
106-
NSLog(@"Can't split string: %@", currentLine);
107-
continue;
108-
}
109-
PBGitCommit* newCommit = [[PBGitCommit alloc] initWithRepository: self andSha: [components objectAtIndex:0]];
110-
NSArray* parents = [[components objectAtIndex:3] componentsSeparatedByString:@" "];
111-
newCommit.parents = parents;
112-
newCommit.subject = [components objectAtIndex:2];
113-
newCommit.author = [components objectAtIndex:1];
114-
newCommit.date = [NSDate dateWithTimeIntervalSince1970:[[components objectAtIndex:3] intValue]];
115-
116-
[newArray addObject: newCommit];
117-
num++;
118-
if (num % 10000 == 0)
119-
[self performSelectorOnMainThread:@selector(setCommits:) withObject:newArray waitUntilDone:NO];
120-
currentLine = [NSMutableString string];
47+
if ([p hasSuffix:@".git"])
48+
self.path = p;
49+
else {
50+
NSString* newPath = [PBEasyPipe outputForCommand:gitPath withArgs:[NSArray arrayWithObjects:@"rev-parse", @"--git-dir", nil] inDir:p];
51+
if ([newPath isEqualToString:@".git"])
52+
self.path = [p stringByAppendingPathComponent:@".git"];
53+
else
54+
self.path = newPath;
12155
}
12256

123-
[self performSelectorOnMainThread:@selector(setCommits:) withObject:newArray waitUntilDone:YES];
124-
NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:start];
125-
NSLog(@"Loaded %i commits in %f seconds", num, duration);
126-
127-
[NSThread exit];
57+
NSLog(@"Git path is: %@", self.path);
58+
revisionList = [[PBGitRevList alloc] initWithRepository:self andRevListParameters:[NSArray array]];
59+
return self;
12860
}
12961

62+
13063
- (NSFileHandle*) handleForArguments:(NSArray *)args
13164
{
13265
NSString* gitDirArg = [@"--git-dir=" stringByAppendingString:path];

PBGitRevList.h

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// PBGitRevList.h
3+
// GitX
4+
//
5+
// Created by Pieter de Bie on 17-06-08.
6+
// Copyright 2008 __MyCompanyName__. All rights reserved.
7+
//
8+
9+
#import <Cocoa/Cocoa.h>
10+
11+
12+
@interface PBGitRevList : NSObject {
13+
NSArray* commits;
14+
NSArray* parameters;
15+
id repository;
16+
}
17+
18+
- initWithRepository:(id)repo andRevListParameters:(NSArray*) params;
19+
20+
@property(retain) NSArray* commits;
21+
@end

PBGitRevList.m

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//
2+
// PBGitRevList.m
3+
// GitX
4+
//
5+
// Created by Pieter de Bie on 17-06-08.
6+
// Copyright 2008 __MyCompanyName__. All rights reserved.
7+
//
8+
9+
#import "PBGitRevList.h"
10+
#import "PBGitRepository.h"
11+
#import "PBGitCommit.h"
12+
13+
@implementation PBGitRevList
14+
15+
@synthesize commits;
16+
- initWithRepository: (id) repo andRevListParameters: (NSArray*) params
17+
{
18+
parameters = params;
19+
repository = repo;
20+
NSThread * commitThread = [[NSThread alloc] initWithTarget: self selector: @selector(walkRevisionList) object:nil];
21+
[commitThread start];
22+
return self;
23+
}
24+
25+
- (void) walkRevisionList
26+
{
27+
28+
NSMutableArray * newArray = [NSMutableArray array];
29+
NSDate* start = [NSDate date];
30+
NSFileHandle* handle = [repository handleForCommand:@"log --pretty=format:%H\01%an\01%s\01%P\01%at HEAD"];
31+
32+
int fd = [handle fileDescriptor];
33+
FILE* f = fdopen(fd, "r");
34+
int BUFFERSIZE = 2048;
35+
char buffer[BUFFERSIZE];
36+
buffer[BUFFERSIZE - 2] = 0;
37+
38+
char* l;
39+
int num = 0;
40+
NSMutableString* currentLine = [NSMutableString string];
41+
while (l = fgets(buffer, BUFFERSIZE, f)) {
42+
NSString *s = [NSString stringWithCString:(const char *)l encoding:NSUTF8StringEncoding];
43+
if ([s length] == 0)
44+
s = [NSString stringWithCString:(const char *)l encoding:NSASCIIStringEncoding];
45+
[currentLine appendString: s];
46+
47+
// If buffer is full, we go for another round
48+
if (buffer[BUFFERSIZE - 2] != 0) {
49+
//NSLog(@"Line too long!");
50+
buffer[BUFFERSIZE - 2] = 0;
51+
continue;
52+
}
53+
54+
// If we are here, we currentLine is a full line.
55+
NSArray* components = [currentLine componentsSeparatedByString:@"\01"];
56+
if ([components count] < 5) {
57+
NSLog(@"Can't split string: %@", currentLine);
58+
continue;
59+
}
60+
PBGitCommit* newCommit = [[PBGitCommit alloc] initWithRepository: repository andSha: [components objectAtIndex:0]];
61+
NSArray* parents = [[components objectAtIndex:3] componentsSeparatedByString:@" "];
62+
newCommit.parents = parents;
63+
newCommit.subject = [components objectAtIndex:2];
64+
newCommit.author = [components objectAtIndex:1];
65+
newCommit.date = [NSDate dateWithTimeIntervalSince1970:[[components objectAtIndex:3] intValue]];
66+
67+
[newArray addObject: newCommit];
68+
num++;
69+
if (num % 10000 == 0)
70+
[self performSelectorOnMainThread:@selector(setCommits:) withObject:newArray waitUntilDone:NO];
71+
currentLine = [NSMutableString string];
72+
}
73+
74+
[self performSelectorOnMainThread:@selector(setCommits:) withObject:newArray waitUntilDone:YES];
75+
NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:start];
76+
NSLog(@"Loaded %i commits in %f seconds", num, duration);
77+
78+
[NSThread exit];
79+
}
80+
81+
@end

PBWebGitController.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ - (void) log: (NSString*) logMessage
6565
- (void) selectCommit: (NSString*) sha
6666
{
6767
NSPredicate* selection = [NSPredicate predicateWithFormat:@"sha == %@", sha];
68-
NSArray* selectedCommits = [controller.repository.commits filteredArrayUsingPredicate:selection];
68+
NSArray* selectedCommits = [controller.repository.revisionList.commits filteredArrayUsingPredicate:selection];
6969
// TODO: reimplement this. How can we set the new commit? Our detailscontroller is read-only
7070
}
7171

0 commit comments

Comments
 (0)