Skip to content

Commit 85f2c72

Browse files
committed
Merge branch 'pu/pb/fix_refresh'
* pu/pb/fix_refresh: Rename 'CachedChanges" to "StagedChanges" for greater consistency PBChangedFile: remove shouldBeDeleted boolean GitCommitController: Also use dictionary lookup for untracked files CommitController: Use a dictionary lookup when refreshing index GitCommitController: clean up index functions
2 parents 1c80701 + 0d8ba8c commit 85f2c72

File tree

4 files changed

+97
-80
lines changed

4 files changed

+97
-80
lines changed

PBChangedFile.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ typedef enum {
1717

1818
@interface PBChangedFile : NSObject {
1919
NSString *path;
20-
BOOL hasCachedChanges;
20+
BOOL hasStagedChanges;
2121
BOOL hasUnstagedChanges;
22-
BOOL shouldBeDeleted;
2322

2423
// Index and HEAD stuff, to be used to revert changes
2524
NSString *commitBlobSHA;
@@ -31,7 +30,7 @@ typedef enum {
3130

3231
@property (copy) NSString *path, *commitBlobSHA, *commitBlobMode;
3332
@property (assign) PBChangedFileStatus status;
34-
@property (assign) BOOL hasCachedChanges, hasUnstagedChanges, shouldBeDeleted;
33+
@property (assign) BOOL hasStagedChanges, hasUnstagedChanges;
3534

3635
- (NSImage *)icon;
3736
- (NSString *)indexInfo;

PBChangedFile.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
@implementation PBChangedFile
1313

14-
@synthesize path, status, hasCachedChanges, hasUnstagedChanges, commitBlobSHA, commitBlobMode, shouldBeDeleted;
14+
@synthesize path, status, hasStagedChanges, hasUnstagedChanges, commitBlobSHA, commitBlobMode;
1515

1616
- (id) initWithPath:(NSString *)p
1717
{

PBGitCommitController.m

Lines changed: 92 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@
1111
#import "PBChangedFile.h"
1212
#import "PBWebChangesController.h"
1313

14+
15+
@interface PBGitCommitController (PrivateMethods)
16+
- (NSArray *) linesFromNotification:(NSNotification *)notification;
17+
- (void) doneProcessingIndex;
18+
- (NSMutableDictionary *)dictionaryForLines:(NSArray *)lines;
19+
- (void) addFilesFromDictionary:(NSMutableDictionary *)dictionary staged:(BOOL)staged tracked:(BOOL)tracked;
20+
@end
21+
1422
@implementation PBGitCommitController
1523

1624
@synthesize files, status, busy, amend;
@@ -24,7 +32,7 @@ - (void)awakeFromNib
2432
[commitMessageView setTypingAttributes:[NSDictionary dictionaryWithObject:[NSFont fontWithName:@"Monaco" size:12.0] forKey:NSFontAttributeName]];
2533

2634
[unstagedFilesController setFilterPredicate:[NSPredicate predicateWithFormat:@"hasUnstagedChanges == 1"]];
27-
[cachedFilesController setFilterPredicate:[NSPredicate predicateWithFormat:@"hasCachedChanges == 1"]];
35+
[cachedFilesController setFilterPredicate:[NSPredicate predicateWithFormat:@"hasStagedChanges == 1"]];
2836

2937
[unstagedFilesController setSortDescriptors:[NSArray arrayWithObjects:
3038
[[NSSortDescriptor alloc] initWithKey:@"status" ascending:false],
@@ -91,24 +99,22 @@ - (NSString *) parentTree
9199

92100
- (void) refresh:(id) sender
93101
{
94-
for (PBChangedFile *file in files)
95-
file.shouldBeDeleted = YES;
102+
if (![repository workingDirectory])
103+
return;
96104

97105
self.status = @"Refreshing index…";
98-
if (![repository workingDirectory]) {
99-
//if ([[repository outputForCommand:@"rev-parse --is-inside-work-tree"] isEqualToString:@"false"]) {
100-
return;
101-
}
102106

103-
self.busy++;
107+
// If self.busy reaches 0, all tasks have finished
108+
self.busy = 0;
104109

110+
// Refresh the index, necessary for the next methods (that's why it's blocking)
111+
// FIXME: Make this non-blocking. This call can be expensive in large repositories
105112
[repository outputInWorkdirForArguments:[NSArray arrayWithObjects:@"update-index", @"-q", @"--unmerged", @"--ignore-missing", @"--refresh", nil]];
106-
self.busy--;
107113

108114
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
109115
[nc removeObserver:self];
110116

111-
// Other files
117+
// Other files (not tracked, not ignored)
112118
NSArray *arguments = [NSArray arrayWithObjects:@"ls-files", @"--others", @"--exclude-standard", @"-z", nil];
113119
NSFileHandle *handle = [repository handleInWorkDirForArguments:arguments];
114120
[nc addObserver:self selector:@selector(readOtherFiles:) name:NSFileHandleReadToEndOfFileCompletionNotification object:handle];
@@ -121,7 +127,7 @@ - (void) refresh:(id) sender
121127
self.busy++;
122128
[handle readToEndOfFileInBackgroundAndNotify];
123129

124-
// Cached files
130+
// Staged files
125131
handle = [repository handleInWorkDirForArguments:[NSArray arrayWithObjects:@"diff-index", @"--cached", @"-z", [self parentTree], nil]];
126132
[nc addObserver:self selector:@selector(readCachedFiles:) name:NSFileHandleReadToEndOfFileCompletionNotification object:handle];
127133
self.busy++;
@@ -133,15 +139,19 @@ - (void) updateView
133139
[self refresh:nil];
134140
}
135141

142+
// This method is called for each of the three processes from above.
143+
// If all three are finished (self.busy == 0), then we can delete
144+
// all files previously marked as deletable
136145
- (void) doneProcessingIndex
137146
{
138147
[self willChangeValueForKey:@"files"];
139148
if (!--self.busy) {
140149
self.status = @"Ready";
141-
NSArray *filesToBeDeleted = [files filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"shouldBeDeleted == 1"]];
142-
for (PBChangedFile *file in filesToBeDeleted) {
150+
for (PBChangedFile *file in files) {
151+
if (!file.hasStagedChanges && !file.hasUnstagedChanges) {
143152
NSLog(@"Deleting file: %@", [file path]);
144153
[files removeObject:file];
154+
}
145155
}
146156
}
147157
[self didChangeValueForKey:@"files"];
@@ -151,105 +161,109 @@ - (void) readOtherFiles:(NSNotification *)notification;
151161
{
152162
[unstagedFilesController setAutomaticallyRearrangesObjects:NO];
153163
NSArray *lines = [self linesFromNotification:notification];
154-
for (NSString *line in lines) {
155-
if ([line length] == 0)
164+
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:[lines count]];
165+
// We fake this files status as good as possible.
166+
NSArray *fileStatus = [NSArray arrayWithObjects:@":000000", @"100644", @"0000000000000000000000000000000000000000", @"0000000000000000000000000000000000000000", @"A", nil];
167+
for (NSString *path in lines) {
168+
if ([path length] == 0)
156169
continue;
157-
158-
BOOL added = NO;
159-
// Check if file is already in our index
160-
for (PBChangedFile *file in files) {
161-
if ([[file path] isEqualToString:line]) {
162-
file.shouldBeDeleted = NO;
163-
added = YES;
164-
file.status = NEW;
165-
file.hasCachedChanges = NO;
166-
file.hasUnstagedChanges = YES;
167-
break;
168-
}
169-
}
170-
171-
if (added)
172-
continue;
173-
174-
// File does not exist yet, so add it
175-
PBChangedFile *file =[[PBChangedFile alloc] initWithPath:line];
176-
file.status = NEW;
177-
file.hasCachedChanges = NO;
178-
file.hasUnstagedChanges = YES;
179-
[files addObject: file];
170+
[dictionary setObject:fileStatus forKey:path];
180171
}
181-
[unstagedFilesController setAutomaticallyRearrangesObjects:YES];
182-
[unstagedFilesController rearrangeObjects];
172+
[self addFilesFromDictionary:dictionary staged:NO tracked:NO];
183173
[self doneProcessingIndex];
184174
}
185175

186-
- (void) addFilesFromLines:(NSArray *)lines cached:(BOOL) cached
176+
- (NSMutableDictionary *)dictionaryForLines:(NSArray *)lines
187177
{
178+
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:[lines count]/2];
179+
180+
// Fill the dictionary with the new information
188181
NSArray *fileStatus;
189-
int even = 0;
182+
BOOL even = FALSE;
190183
for (NSString *line in lines) {
191184
if (!even) {
192-
even = 1;
185+
even = TRUE;
193186
fileStatus = [line componentsSeparatedByString:@" "];
194187
continue;
195188
}
196-
even = 0;
197189

198-
NSString *mode = [[fileStatus objectAtIndex:0] substringFromIndex:1];
199-
NSString *sha = [fileStatus objectAtIndex:2];
190+
even = FALSE;
191+
[dictionary setObject:fileStatus forKey:line];
192+
}
193+
return dictionary;
194+
}
200195

201-
BOOL isNew = YES;
202-
// If the file is already added, we shouldn't add it again
203-
// but rather update it to incorporate our changes
204-
for (PBChangedFile *file in files) {
205-
if ([file.path isEqualToString:line]) {
206-
if (cached && file.hasCachedChanges) { // if we're listing cached files
207-
file.shouldBeDeleted = NO; // and the matching file in files had cached changes
208-
file.commitBlobSHA = sha; // we don't delete it
196+
- (void) addFilesFromDictionary:(NSMutableDictionary *)dictionary staged:(BOOL)staged tracked:(BOOL)tracked
197+
{
198+
// Iterate over all existing files
199+
for (PBChangedFile *file in files) {
200+
NSArray *fileStatus = [dictionary objectForKey:file.path];
201+
// Object found, this is still a cached / uncached thing
202+
if (fileStatus) {
203+
if (tracked) {
204+
NSString *mode = [[fileStatus objectAtIndex:0] substringFromIndex:1];
205+
NSString *sha = [fileStatus objectAtIndex:2];
206+
207+
if (staged) {
208+
file.hasStagedChanges = YES;
209+
file.commitBlobSHA = sha;
209210
file.commitBlobMode = mode;
210-
isNew = NO;
211-
break;
212-
} else if ((!cached) && file.hasUnstagedChanges) { // if we're listing unstaged files and the
213-
file.shouldBeDeleted = NO; // matching file in files had unstaged changes
214-
isNew = NO; // we don't delete it
215-
break;
216-
}
211+
} else
212+
file.hasUnstagedChanges = YES;
213+
} else {
214+
// Untracked file, set status to NEW, only unstaged changes
215+
file.hasStagedChanges = NO;
216+
file.hasUnstagedChanges = YES;
217+
file.status = NEW;
217218
}
219+
[dictionary removeObjectForKey:file.path];
220+
} else { // Object not found, let's remove it from the changes
221+
if (staged)
222+
file.hasStagedChanges = NO;
223+
else if (tracked && file.status != NEW) // Only remove it if it's not an untracked file. We handle that with the other thing
224+
file.hasUnstagedChanges = NO;
225+
else if (!tracked && file.status == NEW)
226+
file.hasUnstagedChanges = NO;
218227
}
228+
}
219229

220-
if (!isNew)
221-
continue;
230+
// Do new files
231+
for (NSString *path in [dictionary allKeys]) {
232+
NSArray *fileStatus = [dictionary objectForKey:path];
222233

223-
PBChangedFile *file = [[PBChangedFile alloc] initWithPath:line];
234+
PBChangedFile *file = [[PBChangedFile alloc] initWithPath:path];
224235
if ([[fileStatus objectAtIndex:4] isEqualToString:@"D"])
225236
file.status = DELETED;
226237
else if([[fileStatus objectAtIndex:0] isEqualToString:@":000000"])
227238
file.status = NEW;
228239
else
229240
file.status = MODIFIED;
230241

231-
file.commitBlobSHA = sha;
232-
file.commitBlobMode = mode;
242+
if (staged) {
243+
file.commitBlobSHA = [[fileStatus objectAtIndex:0] substringFromIndex:1];
244+
file.commitBlobMode = [fileStatus objectAtIndex:2];
245+
}
233246

234-
file.hasCachedChanges = cached;
235-
file.hasUnstagedChanges = !cached;
247+
file.hasStagedChanges = staged;
248+
file.hasUnstagedChanges = !staged;
236249

237250
[files addObject: file];
238251
}
239-
240252
}
241253

242254
- (void) readUnstagedFiles:(NSNotification *)notification
243255
{
244256
NSArray *lines = [self linesFromNotification:notification];
245-
[self addFilesFromLines:lines cached:NO];
257+
NSMutableDictionary *dic = [self dictionaryForLines:lines];
258+
[self addFilesFromDictionary:dic staged:NO tracked:YES];
246259
[self doneProcessingIndex];
247260
}
248261

249262
- (void) readCachedFiles:(NSNotification *)notification
250263
{
251264
NSArray *lines = [self linesFromNotification:notification];
252-
[self addFilesFromLines:lines cached:YES];
265+
NSMutableDictionary *dic = [self dictionaryForLines:lines];
266+
[self addFilesFromDictionary:dic staged:YES tracked:YES];
253267
[self doneProcessingIndex];
254268
}
255269

@@ -356,12 +370,16 @@ - (void) stageHunk:(NSString *)hunk reverse:(BOOL)reverse
356370
if (reverse)
357371
[array addObject:@"--reverse"];
358372

359-
int ret;
373+
int ret = 1;
360374
NSString *error = [repository outputForArguments:array
361375
inputString:hunk
362-
retValue: &ret];
376+
retValue:&ret];
377+
378+
// FIXME: show this error, rather than just logging it
363379
if (ret)
364380
NSLog(@"Error: %@", error);
365-
[self refresh:self]; // TODO: We should do this smarter by checking if the file diff is empty, which is faster.
381+
382+
// TODO: We should do this smarter by checking if the file diff is empty, which is faster.
383+
[self refresh:self];
366384
}
367385
@end

PBGitIndexController.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ - (void) stageFiles:(NSArray *)files
5858
for (PBChangedFile *file in files)
5959
{
6060
file.hasUnstagedChanges = NO;
61-
file.hasCachedChanges = YES;
61+
file.hasStagedChanges = YES;
6262
}
6363
[self resumeTrackingIndex];
6464
}
@@ -85,7 +85,7 @@ - (void) unstageFiles:(NSArray *)files
8585
for (PBChangedFile *file in files)
8686
{
8787
file.hasUnstagedChanges = YES;
88-
file.hasCachedChanges = NO;
88+
file.hasStagedChanges = NO;
8989
}
9090
[self resumeTrackingIndex];
9191
}

0 commit comments

Comments
 (0)