@@ -3,20 +3,23 @@ const assert = std.debug.assert;
3
3
const testing = std .testing ;
4
4
5
5
/// Creates tar Writer which will write tar content to the `underlying_writer`.
6
- /// All paths will be prefixed with `perfix` if it is not empty string.
7
- pub fn writer (underlying_writer : anytype , prefix : []const u8 ) ! Writer (@TypeOf (underlying_writer )) {
8
- return Writer (@TypeOf (underlying_writer )).init (
9
- underlying_writer ,
10
- prefix ,
11
- );
6
+ /// Use setRoot to nest all following entries under single root. If file don't
7
+ /// fit into posix header (name+prefix: 100+155 bytes) gnu extented header will
8
+ /// be used for long names. Options enables setting file premission mode and
9
+ /// mtime. Default is to use current time for mtime and
10
+ /// `default_mode`.file/dir/sym_link for mode.
11
+ pub fn writer (underlying_writer : anytype ) Writer (@TypeOf (underlying_writer )) {
12
+ return .{ .underlying_writer = underlying_writer };
12
13
}
13
14
14
15
pub fn Writer (comptime WriterType : type ) type {
15
16
return struct {
16
17
const block_size = @sizeOf (Header );
17
18
const zero : [@sizeOf (Header )]u8 = .{0 } ** @sizeOf (Header );
18
19
pub const Options = struct {
20
+ /// File system permission mode.
19
21
mode : u32 = 0 ,
22
+ /// File system modification time.
20
23
mtime : u64 = 0 ,
21
24
};
22
25
const Self = @This ();
@@ -27,21 +30,16 @@ pub fn Writer(comptime WriterType: type) type {
27
30
block_buffer : [block_size ]u8 = undefined ,
28
31
mtime_now : u64 = 0 ,
29
32
30
- /// Tar will be written to the `underlying_writer`. All paths will be
31
- /// prefixed with `perfix` if it is not empty string.
32
- pub fn init (underlying_writer : WriterType , prefix : []const u8 ) ! Self {
33
- var self = Self {
34
- .underlying_writer = underlying_writer ,
35
- };
36
- if (prefix .len > 0 ) {
37
- try self .addDir (prefix , .{});
38
- self .prefix = prefix ;
33
+ /// Sets prefix for all other add* method paths.
34
+ pub fn setRoot (self : * Self , root : []const u8 ) ! void {
35
+ if (root .len > 0 ) {
36
+ try self .addDir (root , .{});
39
37
}
40
- return self ;
38
+ self . prefix = root ;
41
39
}
42
40
43
41
/// Writes directory. If options are omitted `default_mode.dir` is used
44
- /// for mode and current time for mtime.
42
+ /// for mode and current time for ` mtime` .
45
43
pub fn addDir (self : * Self , sub_path : []const u8 , opt : Options ) ! void {
46
44
var header = Header .init (.directory );
47
45
try self .setPath (& header , sub_path );
@@ -86,7 +84,7 @@ pub fn Writer(comptime WriterType: type) type {
86
84
}
87
85
88
86
/// Writes symlink. If options are omitted `default_mode.sym_link` is
89
- /// used for mode and current time for mtime.
87
+ /// used for mode and current time for ` mtime` .
90
88
pub fn addLink (self : * Self , sub_path : []const u8 , link_name : []const u8 , opt : Options ) ! void {
91
89
var header = Header .init (.symbolic_link );
92
90
try self .setPath (& header , sub_path );
@@ -99,8 +97,8 @@ pub fn Writer(comptime WriterType: type) type {
99
97
try header .write (self .underlying_writer );
100
98
}
101
99
102
- /// Writes fs.Dir.WalkerEntry. Uses mtime from file system entry and
103
- /// defaults from `default_mode` for mode.
100
+ /// Writes fs.Dir.WalkerEntry. Uses ` mtime` from file system entry and
101
+ /// default from `default_mode` for entry mode.
104
102
pub fn addEntry (self : * Self , entry : std.fs.Dir.Walker.WalkerEntry ) ! void {
105
103
const stat = try entry .dir .statFile (entry .basename );
106
104
const mtime : u64 = @intCast (@divFloor (stat .mtime , std .time .ns_per_s ));
@@ -140,6 +138,7 @@ pub fn Writer(comptime WriterType: type) type {
140
138
};
141
139
}
142
140
141
+ /// Writes gnu extended header: gnu_long_name or gnu_long_link.
143
142
fn writeExtendedHeader (self : * Self , typeflag : Header.FileType , buffers : []const []const u8 ) ! void {
144
143
var len : usize = 0 ;
145
144
for (buffers ) | buf |
@@ -413,11 +412,12 @@ test "write files" {
413
412
414
413
// with root
415
414
{
416
- const prefix = "root" ;
415
+ const root = "root" ;
417
416
418
417
var output = std .ArrayList (u8 ).init (testing .allocator );
419
418
defer output .deinit ();
420
- var wrt = try writer (output .writer (), prefix );
419
+ var wrt = writer (output .writer ());
420
+ try wrt .setRoot (root );
421
421
for (files ) | file | {
422
422
var content = std .io .fixedBufferStream (file .content );
423
423
try wrt .addFile (file .path , file .content .len , content .reader (), .{});
@@ -432,17 +432,17 @@ test "write files" {
432
432
// first entry is directory with prefix
433
433
{
434
434
const actual = (try iter .next ()).? ;
435
- try testing .expectEqualStrings (prefix , actual .name );
435
+ try testing .expectEqualStrings (root , actual .name );
436
436
try testing .expectEqual (std .tar .FileKind .directory , actual .kind );
437
437
}
438
438
439
439
var i : usize = 0 ;
440
440
while (try iter .next ()) | actual | {
441
441
defer i += 1 ;
442
442
const expected = files [i ];
443
- try testing .expectEqualStrings (prefix , actual .name [0.. prefix .len ]);
444
- try testing .expectEqual ('/' , actual .name [prefix .len .. ][0 ]);
445
- try testing .expectEqualStrings (expected .path , actual .name [prefix .len + 1 .. ]);
443
+ try testing .expectEqualStrings (root , actual .name [0.. root .len ]);
444
+ try testing .expectEqual ('/' , actual .name [root .len .. ][0 ]);
445
+ try testing .expectEqualStrings (expected .path , actual .name [root .len + 1 .. ]);
446
446
447
447
var content = std .ArrayList (u8 ).init (testing .allocator );
448
448
defer content .deinit ();
@@ -454,7 +454,7 @@ test "write files" {
454
454
{
455
455
var output = std .ArrayList (u8 ).init (testing .allocator );
456
456
defer output .deinit ();
457
- var wrt = try writer (output .writer (), "" );
457
+ var wrt = writer (output .writer ());
458
458
for (files ) | file | {
459
459
var content = std .io .fixedBufferStream (file .content );
460
460
try wrt .addFile (file .path , file .content .len , content .reader (), .{});
@@ -592,7 +592,8 @@ test "sourcesTar" {
592
592
{
593
593
var out_file = try out_dir .createFile ("sources_new.tar" , .{});
594
594
defer out_file .close ();
595
- var w = try writer (out_file .writer (), "std" );
595
+ var w = writer (out_file .writer ());
596
+ try w .setRoot ("std" );
596
597
597
598
var std_dir = try lib_dir .openDir ("std" , .{ .iterate = true });
598
599
defer std_dir .close ();
0 commit comments