Skip to content

Commit 54f907e

Browse files
committed
Load commit summaries asynchronously again
1 parent 7af30a7 commit 54f907e

File tree

1 file changed

+72
-18
lines changed

1 file changed

+72
-18
lines changed

Classes/Controllers/PBWebHistoryController.m

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
#import <ObjectiveGit/GTConfiguration.h>
1212
#import "PBGitRef.h"
1313
#import "PBGitRevSpecifier.h"
14+
#import <stdatomic.h>
15+
16+
@interface PBWebHistoryController ()
17+
@property (nonatomic) atomic_ulong commitSummaryGeneration;
18+
@end
1419

1520
@implementation PBWebHistoryController
1621

@@ -83,6 +88,8 @@ - (void) changeContentToMultipleSelectionMessage {
8388
}
8489
}
8590

91+
static NSDictionary *loadCommitSummary(GTRepository *repo, GTCommit *commit, BOOL (^isCanceled)());
92+
8693
- (void) changeContentToCommit:(PBGitCommit *)commit
8794
{
8895
// The sha is the same, but refs may have changed. reload it lazy
@@ -101,29 +108,76 @@ - (void) changeContentToCommit:(PBGitCommit *)commit
101108
}
102109
currentOID = commit.OID;
103110

111+
unsigned long gen = atomic_fetch_add(&_commitSummaryGeneration, 1) + 1;
112+
113+
// Open a new repo instance for the background queue
114+
NSError *err = nil;
115+
GTRepository *repo =
116+
[GTRepository repositoryWithURL:[repository gtRepo].gitDirectoryURL error:&err];
117+
if (!repo) {
118+
NSLog(@"Failed to open repository: %@", err);
119+
return;
120+
}
121+
GTCommit *queueCommit = [repo lookUpObjectByOID:commit.OID error:&err];
122+
if (!queueCommit) {
123+
NSLog(@"Failed to find commit: %@", err);
124+
return;
125+
}
126+
127+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
128+
NSDictionary *summary = loadCommitSummary(repo, queueCommit, ^BOOL {
129+
return gen != atomic_load(&_commitSummaryGeneration);
130+
});
131+
if (!summary) return;
132+
NSError *err = nil;
133+
NSString *summaryJSON =
134+
[[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:summary
135+
options:0
136+
error:&err]
137+
encoding:NSUTF8StringEncoding];
138+
if (!summaryJSON) {
139+
NSLog(@"Commit summary JSON error: %@", err);
140+
return;
141+
}
142+
dispatch_async(dispatch_get_main_queue(), ^{
143+
[self commitSummaryLoaded:summaryJSON forOID:commit.OID];
144+
});
145+
});
146+
}
147+
148+
static NSDictionary *loadCommitSummary(GTRepository *repo, GTCommit *commit, BOOL (^isCanceled)()) {
149+
if (isCanceled()) return nil;
104150
GTDiffFindOptionsFlags flags = GTDiffFindOptionsFlagsFindRenames;
105151
if (![PBGitDefaults showWhitespaceDifferences]) {
106152
flags |= GTDiffFindOptionsFlagsIgnoreWhitespace;
107153
}
108154
NSError *err = nil;
109-
GTDiff *d = // TODO async?
110-
[GTDiff diffOldTree:commit.gtCommit.parents.firstObject.tree
111-
withNewTree:commit.gtCommit.tree
112-
inRepository:[repository gtRepo]
113-
options:@{
114-
GTDiffFindOptionsFlagsKey : @(flags)
115-
}
116-
error:&err];
155+
GTDiff *d = [GTDiff diffOldTree:commit.parents.firstObject.tree
156+
withNewTree:commit.tree
157+
inRepository:repo
158+
options:@{
159+
GTDiffFindOptionsFlagsKey : @(flags)
160+
}
161+
error:&err];
117162
if (!d) {
118163
NSLog(@"Commit summary diff error: %@", err);
119-
return;
164+
return nil;
120165
}
166+
if (isCanceled()) return nil;
121167
NSMutableArray *fileDeltas = [NSMutableArray array];
122168
[d enumerateDeltasUsingBlock:^(GTDiffDelta *_Nonnull delta, BOOL *_Nonnull stop) {
169+
if (isCanceled()) {
170+
*stop = YES;
171+
return;
172+
}
123173
NSUInteger numLinesAdded = 0;
124174
NSUInteger numLinesRemoved = 0;
125175
NSError *err = nil;
126176
GTDiffPatch *patch = [delta generatePatch:&err];
177+
if (isCanceled()) {
178+
*stop = YES;
179+
return;
180+
}
127181
if (patch) {
128182
numLinesAdded = patch.addedLinesCount;
129183
numLinesRemoved = patch.deletedLinesCount;
@@ -141,20 +195,20 @@ - (void) changeContentToCommit:(PBGitCommit *)commit
141195
[NSNumber numberWithBool:(delta.flags & GTDiffFileFlagBinary) != 0],
142196
}];
143197
}];
144-
NSDictionary *summaryDict = @{
198+
if (isCanceled()) return nil;
199+
return @{
145200
@"filesInfo" : fileDeltas,
146201
};
147-
NSString *summary =
148-
[[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:summaryDict
149-
options:0
150-
error:&err]
151-
encoding:NSUTF8StringEncoding];
152-
if (!summary) {
153-
NSLog(@"Commit summary JSON error: %@", err);
202+
}
203+
204+
- (void)commitSummaryLoaded:(NSString *)summaryJSON forOID:(GTOID *)summaryOID
205+
{
206+
if (![currentOID isEqual:summaryOID]) {
207+
// a different summary finished loading late
154208
return;
155209
}
156210

157-
[self.view.windowScriptObject callWebScriptMethod:@"loadCommitSummary" withArguments:@[summary]];
211+
[self.view.windowScriptObject callWebScriptMethod:@"loadCommitSummary" withArguments:@[summaryJSON]];
158212

159213
// Now load the full diff
160214
NSMutableArray *taskArguments = [NSMutableArray arrayWithObjects:@"show", @"--pretty=raw", @"-M", @"--no-color", currentOID.SHA, nil];

0 commit comments

Comments
 (0)