1
#import <Foundation/Foundation.h>
4
#import "NSString+Custom.h"
5
#import "Preferences.h"
6
#import "NSArray+Custom.h"
8
@interface TarArchive (PrivateAPI)
9
- (NSData *)dataByRunningTar;
10
- (FileInfo *)fileInfoFromLine:(NSString *)line;
13
@implementation TarArchive : Archive
16
* register our supported file extensions with superclass.
20
[self registerFileExtension:@"tar" forArchiveClass:self];
21
[self registerFileExtension:@"gz" forArchiveClass:self];
22
[self registerFileExtension:@"tgz" forArchiveClass:self];
23
[self registerFileExtension:@"bz2" forArchiveClass:self];
26
+ (NSString *)unarchiveExecutable
28
return [Preferences tarExecutable];
32
* Tar files inherently have the full path info and can't be uncompressed flat.
34
+ (BOOL)canExtractWithoutFullPath;
39
+ (NSString *)archiveType
44
//------------------------------------------------------------------------------
45
// expanding the archive
46
//------------------------------------------------------------------------------
47
- (int)expandFiles:(NSArray *)files withPathInfo:(BOOL)usePathInfo toPath:(NSString *)path
50
NSString *compressionArg;
53
compressionArg = [Preferences compressionArgumentForFile:[self path]];
54
NSParameterAssert(compressionArg != nil);
56
args = [NSMutableArray array];
57
[args addObject:@"-x"];
59
[args addObject:compressionArg];
61
[args addObject:@"-C"];
62
[args addObject:path];
64
[args addObject:@"-f"];
65
[args addObject:[self path]];
69
NSEnumerator *cursor = [files objectEnumerator];
70
while ((fileInfo = [cursor nextObject]) != nil)
72
[args addObject:[fileInfo fullPath]];
76
return [self runUnarchiverWithArguments:args];
79
- (NSArray *)listContents
83
NSMutableArray *results = [NSMutableArray array];
84
NSData *data = [self dataByRunningTar];
85
NSString *string = [[[NSString alloc] initWithData:data
86
encoding:NSASCIIStringEncoding] autorelease];
87
NSArray *lines = [string componentsSeparatedByString:@"\n"];
89
NSEnumerator *cursor = [lines objectEnumerator];
90
while ((line = [cursor nextObject]) != nil)
94
// BSD tar seems to add linefeed at the end of the line. strip that
95
if ([line hasSuffix:@"\r"])
97
line = [line substringToIndex:[line length] - 1];
100
// we skip empty lines and plain directory entries
101
if (([line length] == 0) || [line hasSuffix:@"/"])
106
info = [self fileInfoFromLine:line];
107
[results addObject:info];
112
//------------------------------------------------------------------------------
114
//------------------------------------------------------------------------------
115
+ (void)createArchive:(NSString *)archivePath withFiles:(NSArray *)filenames
117
NSEnumerator *filenameCursor;
120
NSMutableArray *arguments;
122
// make sure archivePath has the correct suffix
123
if ([archivePath hasSuffix:@".tar.gz"] == NO)
125
archivePath = [archivePath stringByAppendingString:@".tar.gz"];
128
// build arguments for commandline: tar -czf filename <list of files>
129
arguments = [NSMutableArray array];
130
[arguments addObject:@"-czf"];
131
[arguments addObject:archivePath];
133
// filenames contains absolute paths, convert them to relative paths. This works
134
// because you can select only files/directories below a current directory in
135
// GWorkspace so all the files *have* to have a common filesystem root.
136
filenameCursor = [filenames objectEnumerator];
137
while ((filename = [filenameCursor nextObject]) != nil)
139
[arguments addObject:[filename lastPathComponent]];
142
// change into this directory when running the task
143
workdir = [[filenames objectAtIndex:0] stringByDeletingLastPathComponent];
145
// create the archive. In the case of TarArchive the unarchiver can also create
147
[self runUnarchiverWithArguments:arguments inDirectory:workdir];
150
//------------------------------------------------------------------------------
152
//------------------------------------------------------------------------------
153
- (NSData *)dataByRunningTar
155
NSString *compressionArg;
156
NSMutableArray *arguments;
158
compressionArg = [Preferences compressionArgumentForFile:[self path]];
159
NSParameterAssert(compressionArg != nil);
161
arguments = [NSMutableArray arrayWithObject:@"-tv"];
162
if ([compressionArg isEqual:@""] == NO)
164
[arguments addObject:compressionArg];
166
[arguments addObject:@"-f"];
167
[arguments addObject:[self path]];
169
return [self dataByRunningUnachiverWithArguments:arguments];
172
- (FileInfo *)fileInfoFromLine:(NSString *)line
174
int index, length = -1;
175
NSString *path = nil;
176
NSString *dateString = nil;
177
NSString *time = nil;
178
NSCalendarDate *calendarDate = nil;
180
NSArray *components = [line componentsSeparatedByString:@" "];
181
components = [components arrayByRemovingEmptyStrings];
183
if ([Preferences isBsdTar])
185
NSArray *dateComponents;
188
length = [[components objectAtIndex:2] intValue];
190
dateComponents = [components subarrayWithRange:NSMakeRange(3, 4)];
191
dateString = [dateComponents componentsJoinedByString:@" "];
192
calendarDate = [NSCalendarDate dateWithString:dateString
193
calendarFormat:@"%b %d %H:%M %Y"];
200
length = [[components objectAtIndex:2] intValue];
202
date = [components objectAtIndex:3];
203
time = [components objectAtIndex:4];
204
dateString = [NSString stringWithFormat:@"%@ %@", date, time];
205
calendarDate = [NSCalendarDate dateWithString:date
206
calendarFormat:@"%Y-%m-%d %H:%M:%S"];
209
// The path is everything afer the date string. Since it can contain blanks,
210
// do *not* just grab any objects from components array
211
index = [line rangeOfString:dateString].location;
212
index += [dateString length];
213
path = [[line substringFromIndex:index] stringByRemovingWhitespaceFromBeginning];
215
return [FileInfo newWithPath:path date:calendarDate
216
size:[NSNumber numberWithInt:length]];