cli-kit 5.3.0 → 5.3.1

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: c406f8c2cf0b1c558c25cd0e6af9e4dd1de520f8a304e8762ee4e2086d72ab15
4
- data.tar.gz: c916e638ee9dafd16b5ad646ba43ed1d226fe386488e1a0072a7b5f9107713f5
3
+ metadata.gz: a71589e7905e5dc0152e3f34baada5c16289f98af365aa7f4f795cc2fee3c3d1
4
+ data.tar.gz: 796526fbab7044920aa42f5d42ca86c6f17a28c9285c344fa210dda10f0e8397
5
5
  SHA512:
6
- metadata.gz: c111015f730162b6ccf7f6f83d45782b27bdc044739cdc100146e08468acc4888ae363a9703f7c044b14e248a291f82d0c8f77cd7986bc2539f52d361b17356f
7
- data.tar.gz: 9f8716992e5a263a8657a2e20035e679eb953cf790727283855804e6d433d5c53b412ec8f34b4fe5b09b6b82a98067ab76b32377c0108203d2c31d6f08143ca8
6
+ metadata.gz: 645d68f82d0147a7176b8a29d5d75f42848456528c06e3db2798823fc9cd732317f3935ddd5d4572e580d13186d6b17267d168f654ef57a19eaec5510074f64d
7
+ data.tar.gz: 5c9250e416b97184027b1742bfb88ee05873baf07d5d8bdfdcb6d5b24102eea0498914ee29ee3056a27dcb557879209c85c36f7c80ea53682b3b580cb887b773
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cli-kit (5.3.0)
4
+ cli-kit (5.3.1)
5
5
  cli-ui (~> 2.4)
6
6
  logger (~> 1.7)
7
7
 
@@ -14,11 +14,9 @@ module CLI
14
14
  # pointing into +/nix/store+).
15
15
  #
16
16
  # Inherits from SystemCallError so existing `rescue SystemCallError`
17
- # handlers around +Config#set+ continue to match. The message contains
18
- # only the keys that actually changed; unchanged keys (which may
19
- # include sensitive values such as API tokens) are intentionally
20
- # excluded so the failure message can never leak secrets through
21
- # stderr or exception reports.
17
+ # handlers around +Config#set+ continue to match. Diagnostics contain
18
+ # only changed section/key names, never their values. Config contents
19
+ # are not retained on the exception, to keep them out of error reports.
22
20
  class ConfigWriteError < SystemCallError
23
21
  class << self
24
22
  # Ruby's +SystemCallError.===+ uses errno-based matching,
@@ -41,10 +39,10 @@ module CLI
41
39
  # checkers and callers see the real signature, and allocate
42
40
  # the instance manually to bypass +SystemCallError+'s
43
41
  # factory behaviour.
44
- #: (String config_path, String old_content, String new_content, SystemCallError cause) -> ConfigWriteError
45
- def new(config_path, old_content, new_content, cause)
42
+ #: (String config_path, Hash[String, Hash[String, String]] old_config, Hash[String, Hash[String, String]] new_config, SystemCallError cause) -> ConfigWriteError
43
+ def new(config_path, old_config, new_config, cause)
46
44
  instance = allocate
47
- instance.__send__(:initialize, config_path, old_content, new_content, cause)
45
+ instance.__send__(:initialize, config_path, old_config, new_config, cause)
48
46
  instance
49
47
  end
50
48
  end
@@ -53,10 +51,7 @@ module CLI
53
51
  attr_reader :config_path
54
52
 
55
53
  #: String
56
- attr_reader :old_content
57
-
58
- #: String
59
- attr_reader :new_content
54
+ attr_reader :diff
60
55
 
61
56
  # rubocop:disable Lint/MissingSuper
62
57
  # +SystemCallError#initialize+ has a factory-style signature that
@@ -65,16 +60,15 @@ module CLI
65
60
  # initialize via Exception so we just get a message-only
66
61
  # exception that +rescue SystemCallError+ still catches via
67
62
  # inheritance. +super+ would not work here.
68
- #: (String config_path, String old_content, String new_content, SystemCallError cause) -> void
69
- def initialize(config_path, old_content, new_content, cause)
63
+ #: (String config_path, Hash[String, Hash[String, String]] old_config, Hash[String, Hash[String, String]] new_config, SystemCallError cause) -> void
64
+ def initialize(config_path, old_config, new_config, cause)
70
65
  @config_path = config_path
71
- @old_content = old_content
72
- @new_content = new_content
66
+ @diff = build_diff(old_config, new_config)
73
67
  @wrapped_errno = cause.errno
74
68
  message = <<~MSG.rstrip
75
69
  Could not write to #{config_path}: #{cause.message}
76
70
 
77
- Attempted changes (unchanged keys omitted):
71
+ Attempted changes (values and unchanged keys omitted):
78
72
  #{diff}
79
73
  MSG
80
74
  Exception.instance_method(:initialize).bind(self).call(message)
@@ -88,19 +82,14 @@ module CLI
88
82
  @wrapped_errno
89
83
  end
90
84
 
91
- # A line-by-line diff of only the sections/keys that changed
92
- # between +old_content+ and +new_content+. Unchanged keys are
93
- # omitted so that sensitive values stored elsewhere in the config
94
- # are never included in the failure message.
95
- #: -> String
96
- def diff
97
- old_ini = CLI::Kit::Ini.new(config: @old_content).tap(&:parse).ini
98
- new_ini = CLI::Kit::Ini.new(config: @new_content).tap(&:parse).ini
85
+ private
99
86
 
87
+ #: (Hash[String, Hash[String, String]] old_config, Hash[String, Hash[String, String]] new_config) -> String
88
+ def build_diff(old_config, new_config)
100
89
  lines = []
101
- (old_ini.keys | new_ini.keys).each do |section|
102
- old_section = old_ini[section] || {}
103
- new_section = new_ini[section] || {}
90
+ (old_config.keys | new_config.keys).each do |section|
91
+ old_section = old_config[section] || {}
92
+ new_section = new_config[section] || {}
104
93
 
105
94
  changes = []
106
95
  (old_section.keys | new_section.keys).each do |key|
@@ -108,8 +97,8 @@ module CLI
108
97
  new_val = new_section[key]
109
98
  next if old_val == new_val
110
99
 
111
- changes << "- #{key} = #{old_val}" if old_val
112
- changes << "+ #{key} = #{new_val}" if new_val
100
+ changes << "- #{key}" if old_val
101
+ changes << "+ #{key}" if new_val
113
102
  end
114
103
  next if changes.empty?
115
104
 
@@ -270,8 +259,8 @@ module CLI
270
259
  # for nix/home-manager configs that live in +/nix/store+. Wrap
271
260
  # it the same way as +EACCES+/+EPERM+ so callers always see
272
261
  # the diff and any +rescue ConfigWriteError+ handler matches.
273
- old_content = read_config_for_diff(config_path)
274
- raise(ConfigWriteError.new(config_path, old_content, new_content, e))
262
+ old_config = read_config_for_diff(config_path)
263
+ raise(ConfigWriteError.new(config_path, old_config, all_configs, e))
275
264
  end
276
265
  end
277
266
 
@@ -285,17 +274,14 @@ module CLI
285
274
  begin
286
275
  tmpfile.write(new_content)
287
276
  tmpfile.close
288
- # Tempfile defaults to 0o600. Match the permissions a plain
289
- # +File.write+ would have produced: preserve the existing
290
- # mode when the config is being updated, and use the
291
- # umask-adjusted default (matching +open(2)+ for new files)
292
- # otherwise. This avoids silently tightening permissions on
293
- # an existing config and avoids creating new configs with
294
- # the more restrictive Tempfile default.
277
+ # Configs may contain credentials. Keep them private to the
278
+ # owner, including when replacing a previously shared file.
279
+ # Preserve stricter owner permissions on existing files and
280
+ # respect the umask when creating new ones.
295
281
  mode = if File.exist?(config_path)
296
- File.stat(config_path).mode
282
+ File.stat(config_path).mode & 0o600
297
283
  else
298
- 0o666 & ~File.umask
284
+ 0o600 & ~File.umask
299
285
  end
300
286
  File.chmod(mode, tmpfile_path)
301
287
  File.rename(tmpfile_path, config_path)
@@ -306,11 +292,11 @@ module CLI
306
292
  end
307
293
  end
308
294
 
309
- #: (String config_path) -> String
295
+ #: (String config_path) -> Hash[String, Hash[String, String]]
310
296
  def read_config_for_diff(config_path)
311
- File.read(config_path)
297
+ CLI::Kit::Ini.new(config: File.read(config_path)).tap(&:parse).ini
312
298
  rescue SystemCallError
313
- ''
299
+ {}
314
300
  end
315
301
 
316
302
  # Resolve +config_path+ through any symlinks so the atomic rename
@@ -17,6 +17,7 @@ class Exception
17
17
  def to_s = raise NotImplementedError, 'abstract method called'
18
18
 
19
19
  # A bug in the tool itself (dev, tec, cli-kit, etc.).
20
+ # @sealed
20
21
  class System < Fault
21
22
  # @override
22
23
  #: -> String
@@ -2,6 +2,6 @@
2
2
 
3
3
  module CLI
4
4
  module Kit
5
- VERSION = '5.3.0'
5
+ VERSION = '5.3.1'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cli-kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.3.0
4
+ version: 5.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Burke Libbey