mini_tarball 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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.