Skip to content

Commit 3aa60d3

Browse files
committed
Migrate GTFilter off the deprecated apply callback
1 parent e34b1e0 commit 3aa60d3

1 file changed

Lines changed: 66 additions & 8 deletions

File tree

‎ObjectiveGit/GTFilter.m‎

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
#import "git2/errors.h"
1515
#import "git2/sys/filter.h"
16-
#import "git2/deprecated.h"
1716

1817
NSString * const GTFilterErrorDomain = @"GTFilterErrorDomain";
1918

@@ -57,7 +56,7 @@ - (instancetype)initWithName:(NSString *)name attributes:(NSString *)attributes
5756

5857
_filter.version = GIT_FILTER_VERSION;
5958
_filter.attributes = attributes.UTF8String;
60-
_filter.apply = &GTFilterApply;
59+
_filter.stream = &GTFilterStreamNew;
6160

6261
_name = [name copy];
6362
_applyBlock = [applyBlock copy];
@@ -103,14 +102,73 @@ static int GTFilterCheck(git_filter *filter, void **payload, const git_filter_so
103102
return accept ? 0 : GIT_PASSTHROUGH;
104103
}
105104

106-
static int GTFilterApply(git_filter *filter, void **payload, git_buf *to, const git_buf *from, const git_filter_source *src) {
107-
GTFilter *self = GTFiltersGitFilterToRegisteredFilters[[NSValue valueWithPointer:filter]];
108-
NSData *fromData = [NSData dataWithBytesNoCopy:from->ptr length:from->size freeWhenDone:NO];
105+
// Backing storage for the `git_writestream` handed to libgit2 by
106+
// `GTFilterStreamNew`. `git_writestream` structs are used with C-style
107+
// "inheritance": `parent` must be the first field so a `GTFilterWriteStream *`
108+
// can be reinterpreted as a `git_writestream *`.
109+
//
110+
// The apply block operates on a complete buffer (an `NSData`), not a stream,
111+
// so incoming chunks are accumulated in `bufferRef` and only handed to the
112+
// block once `close` is called (i.e. once all data has been written).
113+
typedef struct {
114+
git_writestream parent;
115+
void *filterRef; // (GTFilter *), retained via CFBridgingRetain
116+
void *sourceRef; // (GTFilterSource *), retained via CFBridgingRetain
117+
void *bufferRef; // (NSMutableData *), retained via CFBridgingRetain
118+
void **payload;
119+
git_writestream *next;
120+
} GTFilterWriteStream;
121+
122+
static int GTFilterStreamWrite(git_writestream *s, const char *buffer, size_t len) {
123+
GTFilterWriteStream *stream = (GTFilterWriteStream *)s;
124+
NSMutableData *data = (__bridge NSMutableData *)stream->bufferRef;
125+
[data appendBytes:buffer length:len];
126+
return 0;
127+
}
128+
129+
static int GTFilterStreamClose(git_writestream *s) {
130+
GTFilterWriteStream *stream = (GTFilterWriteStream *)s;
131+
GTFilter *filter = (__bridge GTFilter *)stream->filterRef;
132+
GTFilterSource *source = (__bridge GTFilterSource *)stream->sourceRef;
133+
NSData *fromData = (__bridge NSData *)stream->bufferRef;
134+
109135
BOOL applied = YES;
110-
NSData *toData = self.applyBlock(payload, fromData, [[GTFilterSource alloc] initWithGitFilterSource:src], &applied);
111-
if (!applied) return GIT_PASSTHROUGH;
136+
NSData *toData = filter.applyBlock(stream->payload, fromData, source, &applied);
137+
NSData *outputData = applied ? toData : fromData;
138+
139+
git_writestream *next = stream->next;
140+
int result = next->write(next, outputData.bytes, outputData.length);
141+
if (result < 0) return result;
142+
143+
return next->close(next);
144+
}
145+
146+
static void GTFilterStreamFree(git_writestream *s) {
147+
GTFilterWriteStream *stream = (GTFilterWriteStream *)s;
148+
CFBridgingRelease(stream->filterRef);
149+
CFBridgingRelease(stream->sourceRef);
150+
CFBridgingRelease(stream->bufferRef);
151+
free(stream);
152+
}
153+
154+
static int GTFilterStreamNew(git_writestream **out, git_filter *filter, void **payload, const git_filter_source *src, git_writestream *next) {
155+
GTFilter *self = GTFiltersGitFilterToRegisteredFilters[[NSValue valueWithPointer:filter]];
156+
GTFilterSource *source = [[GTFilterSource alloc] initWithGitFilterSource:src];
157+
NSCAssert(source != nil, @"Unexpected nil filter source");
158+
159+
GTFilterWriteStream *stream = calloc(1, sizeof(GTFilterWriteStream));
160+
if (stream == NULL) return GIT_ERROR;
161+
162+
stream->parent.write = GTFilterStreamWrite;
163+
stream->parent.close = GTFilterStreamClose;
164+
stream->parent.free = GTFilterStreamFree;
165+
stream->filterRef = (void *)CFBridgingRetain(self);
166+
stream->sourceRef = (void *)CFBridgingRetain(source);
167+
stream->bufferRef = (void *)CFBridgingRetain([NSMutableData data]);
168+
stream->payload = payload;
169+
stream->next = next;
112170

113-
git_buf_set(to, toData.bytes, toData.length);
171+
*out = (git_writestream *)stream;
114172
return 0;
115173
}
116174

0 commit comments

Comments
 (0)