Skip to content

Commit 8243cf5

Browse files
heipeipieter
authored andcommitted
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 <[email protected]> Edited-by: Pieter de Bie <[email protected]>
1 parent 8750060 commit 8243cf5

File tree

3 files changed

+124
-45
lines changed

3 files changed

+124
-45
lines changed

PBGitHistoryView.xib

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
<string>path</string>
4444
<string>contents</string>
4545
<string>selectedTab</string>
46+
<string>textContents</string>
4647
</object>
4748
<string key="NSObjectClassName">PBGitTree</string>
4849
<object class="_NSManagedProxy" key="_NSManagedProxy"/>
@@ -2047,35 +2048,6 @@
20472048
</object>
20482049
<int key="connectionID">264</int>
20492050
</object>
2050-
<object class="IBConnectionRecord">
2051-
<object class="IBBindingConnection" key="connection">
2052-
<string key="label">value: selection.contents</string>
2053-
<reference key="source" ref="75600241"/>
2054-
<reference key="destination" ref="69733037"/>
2055-
<object class="NSNibBindingConnector" key="connector">
2056-
<reference key="NSSource" ref="75600241"/>
2057-
<reference key="NSDestination" ref="69733037"/>
2058-
<string key="NSLabel">value: selection.contents</string>
2059-
<string key="NSBinding">value</string>
2060-
<string key="NSKeyPath">selection.contents</string>
2061-
<object class="NSDictionary" key="NSOptions">
2062-
<bool key="EncodedWithXMLCoder">YES</bool>
2063-
<object class="NSMutableArray" key="dict.sortedKeys">
2064-
<bool key="EncodedWithXMLCoder">YES</bool>
2065-
<string>NSAllowsEditingMultipleValuesSelection</string>
2066-
<string>NSConditionallySetsEditable</string>
2067-
</object>
2068-
<object class="NSMutableArray" key="dict.values">
2069-
<bool key="EncodedWithXMLCoder">YES</bool>
2070-
<integer value="0" id="8"/>
2071-
<reference ref="8"/>
2072-
</object>
2073-
</object>
2074-
<int key="NSNibBindingConnectorVersion">2</int>
2075-
</object>
2076-
</object>
2077-
<int key="connectionID">266</int>
2078-
</object>
20792051
<object class="IBConnectionRecord">
20802052
<object class="IBOutletConnection" key="connection">
20812053
<string key="label">branchPopUp</string>
@@ -2146,6 +2118,35 @@
21462118
</object>
21472119
<int key="connectionID">290</int>
21482120
</object>
2121+
<object class="IBConnectionRecord">
2122+
<object class="IBBindingConnection" key="connection">
2123+
<string key="label">value: selection.textContents</string>
2124+
<reference key="source" ref="75600241"/>
2125+
<reference key="destination" ref="69733037"/>
2126+
<object class="NSNibBindingConnector" key="connector">
2127+
<reference key="NSSource" ref="75600241"/>
2128+
<reference key="NSDestination" ref="69733037"/>
2129+
<string key="NSLabel">value: selection.textContents</string>
2130+
<string key="NSBinding">value</string>
2131+
<string key="NSKeyPath">selection.textContents</string>
2132+
<object class="NSDictionary" key="NSOptions">
2133+
<bool key="EncodedWithXMLCoder">YES</bool>
2134+
<object class="NSMutableArray" key="dict.sortedKeys">
2135+
<bool key="EncodedWithXMLCoder">YES</bool>
2136+
<string>NSAllowsEditingMultipleValuesSelection</string>
2137+
<string>NSConditionallySetsEditable</string>
2138+
</object>
2139+
<object class="NSMutableArray" key="dict.values">
2140+
<bool key="EncodedWithXMLCoder">YES</bool>
2141+
<boolean value="NO" id="6"/>
2142+
<reference ref="6"/>
2143+
</object>
2144+
</object>
2145+
<int key="NSNibBindingConnectorVersion">2</int>
2146+
</object>
2147+
</object>
2148+
<int key="connectionID">291</int>
2149+
</object>
21492150
</object>
21502151
<object class="IBMutableOrderedSet" key="objectRecords">
21512152
<object class="NSArray" key="orderedObjects">
@@ -2858,6 +2859,8 @@
28582859
<string>273.IBPluginDependency</string>
28592860
<string>28.IBPluginDependency</string>
28602861
<string>28.IBShouldRemoveOnLegacySave</string>
2862+
<string>287.IBPluginDependency</string>
2863+
<string>288.IBPluginDependency</string>
28612864
<string>29.IBPluginDependency</string>
28622865
<string>29.IBShouldRemoveOnLegacySave</string>
28632866
<string>3.IBPluginDependency</string>
@@ -2950,7 +2953,7 @@
29502953
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
29512954
<string>{{504, 612}, {346, 102}}</string>
29522955
<string>{{504, 612}, {346, 102}}</string>
2953-
<reference ref="8"/>
2956+
<integer value="0" id="8"/>
29542957
<boolean value="YES" id="5"/>
29552958
<reference ref="5"/>
29562959
<string>{1000, 102}</string>
@@ -2990,6 +2993,8 @@
29902993
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
29912994
<reference ref="9"/>
29922995
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
2996+
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
2997+
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
29932998
<reference ref="9"/>
29942999
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
29953000
<reference ref="9"/>
@@ -3021,7 +3026,7 @@
30213026
</object>
30223027
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
30233028
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
3024-
<string>{{59, 67}, {852, 432}}</string>
3029+
<string>{{321, 67}, {852, 432}}</string>
30253030
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
30263031
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
30273032
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -3056,7 +3061,7 @@
30563061
</object>
30573062
</object>
30583063
<nil key="sourceID"/>
3059-
<int key="maxID">290</int>
3064+
<int key="maxID">291</int>
30603065
</object>
30613066
<object class="IBClassDescriber" key="IBDocument.Classes">
30623067
<object class="NSMutableArray" key="referencedPartialClassDescriptions">

PBGitTree.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
1010
#import "PBGitRepository.h"
1111

1212
@interface PBGitTree : NSObject {
13+
long long _fileSize;
14+
1315
NSString* sha;
1416
NSString* path;
1517
PBGitRepository* repository;
1618
__weak PBGitTree* parent;
1719
NSArray* children;
1820
BOOL leaf;
19-
21+
2022
NSString* localFileName;
2123
NSDate* localMtime;
2224
}
@@ -26,6 +28,7 @@
2628
- (void) saveToFolder: (NSString *) directory;
2729

2830
- (NSString*) tmpFileNameForContents;
31+
- (long long)fileSize;
2932

3033
@property(copy) NSString* sha;
3134
@property(copy) NSString* path;

PBGitTree.m

Lines changed: 83 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,25 +63,96 @@ - (BOOL) isLocallyCached
6363
return NO;
6464
}
6565

66+
- (BOOL)hasBinaryHeader:(NSString *)fileHeader
67+
{
68+
if (!fileHeader)
69+
return NO;
70+
71+
NSString *filetype = [PBEasyPipe outputForCommand:@"/usr/bin/file"
72+
withArgs:[NSArray arrayWithObjects:@"-b", @"-N", @"-", nil]
73+
inDir:[repository workingDirectory]
74+
inputString:fileHeader
75+
retValue:nil];
76+
77+
return [filetype rangeOfString:@"text"].location == NSNotFound;
78+
}
79+
80+
- (BOOL)hasBinaryAttributes
81+
{
82+
// First ask git check-attr if the file has a binary attribute custom set
83+
NSFileHandle *handle = [repository handleInWorkDirForArguments:[NSArray arrayWithObjects:@"check-attr", @"binary", [self fullPath], nil]];
84+
NSData *data = [handle readDataToEndOfFile];
85+
NSString *string = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
86+
87+
if (!string)
88+
return NO;
89+
string = [string stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
90+
91+
if ([string hasSuffix:@"binary: set"])
92+
return YES;
93+
94+
if ([string hasSuffix:@"binary: unset"])
95+
return NO;
96+
97+
// Binary state unknown, do a check on common filename-extensions
98+
for (NSString *extension in [NSArray arrayWithObjects:@".pdf", @".jpg", @".jpeg", @".png", @".bmp", @".gif", @".o", nil]) {
99+
if ([[self fullPath] hasSuffix:extension])
100+
return YES;
101+
}
102+
103+
return NO;
104+
}
105+
66106
- (NSString*) contents
67107
{
68108
if (!leaf)
69109
return [NSString stringWithFormat:@"This is a tree with path %@", [self fullPath]];
70110

71-
NSData* data = nil;
72-
73-
if ([self isLocallyCached])
74-
data = [NSData dataWithContentsOfFile: localFileName];
75-
else {
76-
NSFileHandle* handle = [repository handleForArguments:[NSArray arrayWithObjects:@"show", [self refSpec], nil]];
77-
data = [handle readDataToEndOfFile];
111+
if ([self isLocallyCached]) {
112+
NSData *data = [NSData dataWithContentsOfFile:localFileName];
113+
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
114+
if (!string)
115+
string = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
116+
return string;
78117
}
79118

80-
NSString* string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
81-
if (!string) {
82-
string = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
83-
}
84-
return string;
119+
return [repository outputForArguments:[NSArray arrayWithObjects:@"show", [self refSpec], nil]];
120+
}
121+
122+
- (long long)fileSize
123+
{
124+
if (_fileSize)
125+
return _fileSize;
126+
127+
NSFileHandle *handle = [repository handleForArguments:[NSArray arrayWithObjects:@"cat-file", @"-s", [self refSpec], nil]];
128+
NSString *sizeString = [[NSString alloc] initWithData:[handle readDataToEndOfFile] encoding:NSISOLatin1StringEncoding];
129+
130+
if (!sizeString)
131+
_fileSize = -1;
132+
else
133+
_fileSize = [sizeString longLongValue];
134+
135+
return _fileSize;
136+
}
137+
138+
- (NSString *)textContents
139+
{
140+
if (!leaf)
141+
return [NSString stringWithFormat:@"This is a tree with path %@", [self fullPath]];
142+
143+
if ([self hasBinaryAttributes])
144+
return [NSString stringWithFormat:@"%@ appears to be a binary file of %d bytes", [self fullPath], [self fileSize]];
145+
146+
long long fileSize = [self fileSize];
147+
if (fileSize > 52428800) // ~50MB
148+
return [NSString stringWithFormat:@"%@ is too big to be displayed (%d bytes)", [self fullPath], fileSize];
149+
150+
NSString *contents = [self contents];
151+
152+
if ([self hasBinaryHeader:([contents length] >= 100) ? [contents substringToIndex:99] : contents])
153+
return [NSString stringWithFormat:@"%@ appears to be a binary file of %d bytes", [self fullPath], fileSize];
154+
155+
return contents;
85156
}
86157

87158
- (void) saveToFolder: (NSString *) dir

0 commit comments

Comments
 (0)