This uses the same mechanisms as git to determine whether a file is binary: By simply searching the first 8000 bytes for a 0-byte. This gets rid of the call to "file" and is a much cleaner and shorter implementation.
Signed-off-by: Johannes Gilger <[email protected]> --- Hi folks, I had that on my TODO and it turns out that git uses a dead-simple (yet seemingly very effective) mechanisms to determine binary-files (see commit message). I thought about using memchr like git does, but then again were coding Objective-C and I don't think using the rangeOfString method here creates too much overhead. If you're wondering why the check for binaryAttributes and for binaryHeader isn't done in the same line: Searching the header (which means invoking "git show" on a possbily large file) is the last resort, and is only done if the other ifs didn't yield anything (like binary attributes or "file too big"). With this patch "git show" is only invoked once (max) per time you select the file. This one is up for discussion, since it can be performance-critical. Greetings, Jojo PBGitTree.m | 23 ++++++++--------------- 1 files changed, 8 insertions(+), 15 deletions(-) diff --git a/PBGitTree.m b/PBGitTree.m index 21c91f8..c8003d1 100644 --- a/PBGitTree.m +++ b/PBGitTree.m @@ -63,18 +63,12 @@ - (BOOL) isLocallyCached return NO; } -- (BOOL)hasBinaryHeader:(NSString *)fileHeader +- (BOOL)hasBinaryHeader:(NSString*)contents { - if (!fileHeader) + if(!contents) return NO; - NSString *filetype = [PBEasyPipe outputForCommand:@"/usr/bin/file" - withArgs:[NSArray arrayWithObjects:@"-b", @"-N", @"-", nil] - inDir:[repository workingDirectory] - inputString:fileHeader - retValue:nil]; - - return [filetype rangeOfString:@"text"].location == NSNotFound; + return [contents rangeOfString:@"\0" options:0 range:NSMakeRange(0, ([contents length] >= 8000) ? 7999 : [contents length])].location != NSNotFound; } - (BOOL)hasBinaryAttributes @@ -143,14 +137,13 @@ - (NSString *)textContents if ([self hasBinaryAttributes]) return [NSString stringWithFormat:@"%@ appears to be a binary file of %d bytes", [self fullPath], [self fileSize]]; - long long fileSize = [self fileSize]; - if (fileSize > 52428800) // ~50MB - return [NSString stringWithFormat:@"%@ is too big to be displayed (%d bytes)", [self fullPath], fileSize]; + if ([self fileSize] > 52428800) // ~50MB + return [NSString stringWithFormat:@"%@ is too big to be displayed (%d bytes)", [self fullPath], [self fileSize]]; - NSString *contents = [self contents]; + NSString* contents = [self contents]; - if ([self hasBinaryHeader:([contents length] >= 100) ? [contents substringToIndex:99] : contents]) - return [NSString stringWithFormat:@"%@ appears to be a binary file of %d bytes", [self fullPath], fileSize]; + if ([self hasBinaryHeader:contents]) + return [NSString stringWithFormat:@"%@ appears to be a binary file of %d bytes", [self fullPath], [self fileSize]]; return contents; } -- 1.6.4.2.236.gf324c
