mini_tarball 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 186593f6df9a85bfd1247d7ac48d2e2516d21d3dc7cd92e97774667ecc0768be
4
- data.tar.gz: 7b4c0465dddd0c67822fca7f7d44c5e134dea5dae4e839f307975d42aacf5728
3
+ metadata.gz: bb6115ef818ae567ea4efad8646977a26cbb62f5164e656bd8d403dd1775ff38
4
+ data.tar.gz: 5364a6eece1aa623c4bb900eaf50de383017dcd4b9285f5f7b3b52423638d9b2
5
5
  SHA512:
6
- metadata.gz: 76239123207c12d071fa25ac28a7ee9e1d1796e3a68f15a5d124eeaf695590900130dff61cfe3e8af8c92f6b48ffa41e9be6e311ab0e93c42da5b0fb7efa1da8
7
- data.tar.gz: e8bfcc562c8569b8f9168757406dfe162f31417a5bf7fb3b658b99a76de6896fa9b8dd3b5d73f8e1c33b434499dadc332a9c5dd6659185359a0d278d41b872c5
6
+ metadata.gz: d8978adda8f400f47d37d037fc439d6d803538910aaa97a78cee3ec111b34616c0b3acd298a6a5b406a02a8e0d698e25743a5a4ff32a2e1b827835892621d186
7
+ data.tar.gz: 543abee46d1e1bd3df2abdd0b0164f2e72363d65ec63a7ac8c120302c94a0fc247315fcb7c4541774ab08ef00178e4de1df355cb2699e0056f0d984e53f532bc
@@ -11,7 +11,7 @@ module MiniTarball
11
11
  # rubocop:disable Layout/HashAlignment
12
12
  FIELDS = {
13
13
  name: { length: 100, type: :chars },
14
- mode: { length: 8, type: :number },
14
+ mode: { length: 8, type: :mode },
15
15
  uid: { length: 8, type: :number },
16
16
  gid: { length: 8, type: :number },
17
17
  size: { length: 12, type: :number },
@@ -4,6 +4,8 @@ module MiniTarball
4
4
  ValueTooLargeError = Class.new(StandardError)
5
5
 
6
6
  class HeaderFormatter
7
+ PERMISSION_BITMASK = 0007777
8
+
7
9
  # @param value [Integer]
8
10
  # @param length [Integer]
9
11
  def self.format_number(value, length)
@@ -38,5 +40,12 @@ module MiniTarball
38
40
 
39
41
  encoded.pack("C#{length}")
40
42
  end
43
+
44
+ # Removes file type bitfields and returns file permissions as formatted number
45
+ # @param value [Integer]
46
+ # @param length [Integer]
47
+ def self.format_permissions(value, length)
48
+ format_number(value & PERMISSION_BITMASK, length)
49
+ end
41
50
  end
42
51
  end
@@ -22,6 +22,8 @@ module MiniTarball
22
22
  case field[:type]
23
23
  when :number
24
24
  values_by_field[name] = HeaderFormatter.format_number(value, field[:length])
25
+ when :mode
26
+ values_by_field[name] = HeaderFormatter.format_permissions(value, field[:length])
25
27
  when :checksum
26
28
  values_by_field[name] = " " * field[:length]
27
29
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MiniTarball
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'etc'
4
+
3
5
  module MiniTarball
4
6
  class Writer
5
7
  END_OF_TAR_BLOCK_SIZE = 1024
@@ -27,7 +29,7 @@ module MiniTarball
27
29
  end
28
30
 
29
31
  def initialize(io)
30
- check_io!(io)
32
+ ensure_valid_io!(io)
31
33
 
32
34
  @io = io
33
35
  @write_only_io = WriteOnlyStream.new(@io)
@@ -35,8 +37,30 @@ module MiniTarball
35
37
  @closed = false
36
38
  end
37
39
 
38
- def add_file(name:, mode: 0644, uname: "nobody", gname: "nogroup", uid: nil, gid: nil, mtime: nil)
39
- check_closed!
40
+ def add_file(name:, source_file_path:, mode: nil, uname: nil, gname: nil, uid: nil, gid: nil, mtime: nil)
41
+ ensure_not_closed!
42
+
43
+ file = File.open(source_file_path, "rb")
44
+ stat = File.stat(source_file_path)
45
+
46
+ @header_writer.write(Header.new(
47
+ name: name,
48
+ size: stat.size,
49
+ mode: mode || stat.mode,
50
+ uid: uid || stat.uid,
51
+ gid: gid || stat.gid,
52
+ uname: uname || Etc.getpwuid(stat.uid).name,
53
+ gname: gname || Etc.getgrgid(stat.gid).name,
54
+ mtime: mtime || stat.mtime
55
+ ))
56
+
57
+ IO.copy_stream(file, @write_only_io)
58
+ write_padding
59
+ nil
60
+ end
61
+
62
+ def add_file_from_stream(name:, mode: 0644, uname: "nobody", gname: "nogroup", uid: nil, gid: nil, mtime: nil)
63
+ ensure_not_closed!
40
64
 
41
65
  header_start_position = @io.pos
42
66
  @header_writer.write(Header.new(name: name))
@@ -59,6 +83,7 @@ module MiniTarball
59
83
  ))
60
84
 
61
85
  @io.seek(0, IO::SEEK_END)
86
+ nil
62
87
  end
63
88
 
64
89
  def closed?
@@ -66,7 +91,7 @@ module MiniTarball
66
91
  end
67
92
 
68
93
  def close
69
- check_closed!
94
+ ensure_not_closed!
70
95
 
71
96
  @io.write("\0" * END_OF_TAR_BLOCK_SIZE)
72
97
  @io.close
@@ -75,15 +100,12 @@ module MiniTarball
75
100
 
76
101
  private
77
102
 
78
- def check_io!(io)
103
+ def ensure_valid_io!(io)
79
104
  raise "No IO object given" unless io.respond_to?(:pos) &&
80
- io.respond_to?(:seek) && io.respond_to?(:write) && io.respond_to?(:close)
81
-
82
- io.seek(0, IO::SEEK_END)
83
- raise "Stream must be empty" unless io.pos == 0
105
+ io.respond_to?(:write) && io.respond_to?(:close)
84
106
  end
85
107
 
86
- def check_closed!
108
+ def ensure_not_closed!
87
109
  raise IOError.new("#{self.class} is closed") if closed?
88
110
  end
89
111
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mini_tarball
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Discourse
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-22 00:00:00.000000000 Z
11
+ date: 2021-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -129,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
129
  - !ruby/object:Gem::Version
130
130
  version: '0'
131
131
  requirements: []
132
- rubygems_version: 3.0.3
132
+ rubygems_version: 3.1.4
133
133
  signing_key:
134
134
  specification_version: 4
135
135
  summary: A minimal implementation of the GNU Tar format.