PBGitTree: Don't try to print binary-file contents

This patch prevents the plaintext display of files with binary content
in tree-view by connecting the content to the textContents attribute.

PBGitTree is extended with the method textContents, which returns the
textual representation of a PBGitTree-object. The methods first checks
the output of "git check-attr binary <file>" to see if the user
set/unset the binary attribute manually. Then it checks for common
binary file-extensions. If this method can't determine whether the file
is binary, the file-content is loaded and Unix "file" is run on the
first 100 bytes of the file to make a decision.

It also adds the -[PBGitTree fileSize] method to check the size
of the file before actually loading its contents.

Signed-off-by: Johannes Gilger <heipei@hackvalue.de>
Edited-by: Pieter de Bie <pdebie@ai.rug.nl>
This commit is contained in:
Johannes Gilger
2009-08-28 18:05:29 +02:00
committed by Pieter de Bie
parent 8750060621
commit 8243cf58b3
3 changed files with 124 additions and 45 deletions
+37 -32
View File
@@ -43,6 +43,7 @@
<string>path</string>
<string>contents</string>
<string>selectedTab</string>
<string>textContents</string>
</object>
<string key="NSObjectClassName">PBGitTree</string>
<object class="_NSManagedProxy" key="_NSManagedProxy"/>
@@ -2047,35 +2048,6 @@
</object>
<int key="connectionID">264</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: selection.contents</string>
<reference key="source" ref="75600241"/>
<reference key="destination" ref="69733037"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="75600241"/>
<reference key="NSDestination" ref="69733037"/>
<string key="NSLabel">value: selection.contents</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">selection.contents</string>
<object class="NSDictionary" key="NSOptions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMutableArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>NSAllowsEditingMultipleValuesSelection</string>
<string>NSConditionallySetsEditable</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<integer value="0" id="8"/>
<reference ref="8"/>
</object>
</object>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">266</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">branchPopUp</string>
@@ -2146,6 +2118,35 @@
</object>
<int key="connectionID">290</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: selection.textContents</string>
<reference key="source" ref="75600241"/>
<reference key="destination" ref="69733037"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="75600241"/>
<reference key="NSDestination" ref="69733037"/>
<string key="NSLabel">value: selection.textContents</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">selection.textContents</string>
<object class="NSDictionary" key="NSOptions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMutableArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>NSAllowsEditingMultipleValuesSelection</string>
<string>NSConditionallySetsEditable</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<boolean value="NO" id="6"/>
<reference ref="6"/>
</object>
</object>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">291</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
@@ -2858,6 +2859,8 @@
<string>273.IBPluginDependency</string>
<string>28.IBPluginDependency</string>
<string>28.IBShouldRemoveOnLegacySave</string>
<string>287.IBPluginDependency</string>
<string>288.IBPluginDependency</string>
<string>29.IBPluginDependency</string>
<string>29.IBShouldRemoveOnLegacySave</string>
<string>3.IBPluginDependency</string>
@@ -2950,7 +2953,7 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{504, 612}, {346, 102}}</string>
<string>{{504, 612}, {346, 102}}</string>
<reference ref="8"/>
<integer value="0" id="8"/>
<boolean value="YES" id="5"/>
<reference ref="5"/>
<string>{1000, 102}</string>
@@ -2990,6 +2993,8 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
@@ -3021,7 +3026,7 @@
</object>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{59, 67}, {852, 432}}</string>
<string>{{321, 67}, {852, 432}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -3056,7 +3061,7 @@
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">290</int>
<int key="maxID">291</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+4 -1
View File
@@ -10,13 +10,15 @@
#import "PBGitRepository.h"
@interface PBGitTree : NSObject {
long long _fileSize;
NSString* sha;
NSString* path;
PBGitRepository* repository;
__weak PBGitTree* parent;
NSArray* children;
BOOL leaf;
NSString* localFileName;
NSDate* localMtime;
}
@@ -26,6 +28,7 @@
- (void) saveToFolder: (NSString *) directory;
- (NSString*) tmpFileNameForContents;
- (long long)fileSize;
@property(copy) NSString* sha;
@property(copy) NSString* path;
+83 -12
View File
@@ -63,25 +63,96 @@
return NO;
}
- (BOOL)hasBinaryHeader:(NSString *)fileHeader
{
if (!fileHeader)
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;
}
- (BOOL)hasBinaryAttributes
{
// First ask git check-attr if the file has a binary attribute custom set
NSFileHandle *handle = [repository handleInWorkDirForArguments:[NSArray arrayWithObjects:@"check-attr", @"binary", [self fullPath], nil]];
NSData *data = [handle readDataToEndOfFile];
NSString *string = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
if (!string)
return NO;
string = [string stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
if ([string hasSuffix:@"binary: set"])
return YES;
if ([string hasSuffix:@"binary: unset"])
return NO;
// Binary state unknown, do a check on common filename-extensions
for (NSString *extension in [NSArray arrayWithObjects:@".pdf", @".jpg", @".jpeg", @".png", @".bmp", @".gif", @".o", nil]) {
if ([[self fullPath] hasSuffix:extension])
return YES;
}
return NO;
}
- (NSString*) contents
{
if (!leaf)
return [NSString stringWithFormat:@"This is a tree with path %@", [self fullPath]];
NSData* data = nil;
if ([self isLocallyCached])
data = [NSData dataWithContentsOfFile: localFileName];
else {
NSFileHandle* handle = [repository handleForArguments:[NSArray arrayWithObjects:@"show", [self refSpec], nil]];
data = [handle readDataToEndOfFile];
if ([self isLocallyCached]) {
NSData *data = [NSData dataWithContentsOfFile:localFileName];
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if (!string)
string = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
return string;
}
NSString* string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if (!string) {
string = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
}
return string;
return [repository outputForArguments:[NSArray arrayWithObjects:@"show", [self refSpec], nil]];
}
- (long long)fileSize
{
if (_fileSize)
return _fileSize;
NSFileHandle *handle = [repository handleForArguments:[NSArray arrayWithObjects:@"cat-file", @"-s", [self refSpec], nil]];
NSString *sizeString = [[NSString alloc] initWithData:[handle readDataToEndOfFile] encoding:NSISOLatin1StringEncoding];
if (!sizeString)
_fileSize = -1;
else
_fileSize = [sizeString longLongValue];
return _fileSize;
}
- (NSString *)textContents
{
if (!leaf)
return [NSString stringWithFormat:@"This is a tree with path %@", [self fullPath]];
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];
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];
return contents;
}
- (void) saveToFolder: (NSString *) dir