Skip to content

Commit 8e5b696

Browse files
committed
Use libgit2 to filter working directory changes
For each changed path, discover the repository for that path and compare it to the repository that is open. If they don't match, it's a submodule or another repo within the top-level one. Either way, changes to that module shouldn't be committed to our repo (not that I offer any guarantee that GitX would do the expected commit correctly anyway…) This fixes brotherbard#1 - although I'm yet to test the performance on a big repo with many files/submodules.
1 parent bf0813e commit 8e5b696

File tree

1 file changed

+33
-7
lines changed

1 file changed

+33
-7
lines changed

PBGitRepositoryWatcher.m

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#import "PBGitDefaults.h"
1212
#import "PBGitRepositoryWatcherEventPath.h"
1313

14+
#import <ObjectiveGit/ObjectiveGit.h>
15+
1416
NSString *PBGitRepositoryEventNotification = @"PBGitRepositoryModifiedNotification";
1517
NSString *kPBGitRepositoryEventTypeUserInfoKey = @"kPBGitRepositoryEventTypeUserInfoKey";
1618
NSString *kPBGitRepositoryEventPathsUserInfoKey = @"kPBGitRepositoryEventPathsUserInfoKey";
@@ -110,10 +112,22 @@ - (BOOL) _gitDirectoryChanged {
110112

111113
- (void) _handleEventCallback:(NSArray *)eventPaths {
112114
PBGitRepositoryWatcherEventType event = 0x0;
113-
115+
114116
if ([self _indexChanged])
115117
event |= PBGitRepositoryWatcherEventTypeIndex;
116118

119+
NSString* ourRepo_ns = repository.fileURL.path;
120+
// libgit2 API results for directories end with a '/'
121+
if (![ourRepo_ns hasSuffix:@"/"])
122+
ourRepo_ns = [NSString stringWithFormat:@"%@/", ourRepo_ns];
123+
124+
const char* ourRepoPath = [ourRepo_ns UTF8String];
125+
126+
// We only use the event path buffer for testing equality to our own repo
127+
// so it's okay to consider failure due to buffer size as inequality.
128+
const int eventPathRepoBufferSize = strlen(ourRepoPath) + 2;
129+
char *eventPathRepoBuffer = malloc(eventPathRepoBufferSize);
130+
117131
NSMutableArray *paths = [NSMutableArray array];
118132

119133
for (PBGitRepositoryWatcherEventPath *eventPath in eventPaths) {
@@ -142,12 +156,22 @@ - (void) _handleEventCallback:(NSArray *)eventPaths {
142156

143157
// subdirs of working dir
144158
else {
145-
// Try to get the git status of the changed path using libgit2
146-
if (![eventPath.path hasSuffix:@"/.git/"])
147-
{
148-
event |= PBGitRepositoryWatcherEventTypeWorkingDirectory;
149-
[paths addObject:eventPath.path];
150-
}
159+
// check that the repo for the changed path is ours, otherwise
160+
// it's most likely a submodule, or a nested clone. Either way,
161+
// we shouldn't be committing to it ourselves.
162+
163+
164+
int discoverStatus = git_repository_discover(eventPathRepoBuffer, eventPathRepoBufferSize,
165+
[eventPath.path UTF8String],
166+
1 /* cross filesystem boundaries, if necessary*/,
167+
ourRepoPath);
168+
if (GIT_SUCCESS == discoverStatus &&
169+
strcmp(ourRepoPath, eventPathRepoBuffer) == 0)
170+
{
171+
event |= PBGitRepositoryWatcherEventTypeWorkingDirectory;
172+
[paths addObject:eventPath.path];
173+
}
174+
// }
151175
}
152176
}
153177

@@ -160,6 +184,8 @@ - (void) _handleEventCallback:(NSArray *)eventPaths {
160184

161185
[[NSNotificationCenter defaultCenter] postNotificationName:PBGitRepositoryEventNotification object:repository userInfo:eventInfo];
162186
}
187+
188+
free(eventPathRepoBuffer);
163189
}
164190

165191
- (void) start {

0 commit comments

Comments
 (0)