cinnabar 0.0.1 → 0.0.2
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 +4 -4
- data/docs/ChangeLog.md +5 -0
- data/docs/Readme.md +8 -4
- data/lib/cinnabar/00_pre.rb +2 -3
- data/lib/cinnabar/path.rb +253 -0
- data/lib/cinnabar/version.rb +1 -1
- data/lib/cinnabar.rb +1 -0
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0d07b1f0ca422a414fa67b7017920940bd12eadfe4f2d104de088e6ce67c9def
|
|
4
|
+
data.tar.gz: a2065bf84722d56727ce1d12602ef3d498d0026ba420f3e213ce5b9d24fdd558
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ca95b7d444e89dd2c169d16b1255779c482dd4ed36bda09f7050a2d6c99f1049e27e52c660b4a2c35f0045b0c668a2954f7b982006257f3f74dcdb0a71a9d03c
|
|
7
|
+
data.tar.gz: 7da5135f3602cf662ea4bbc53e86cada66dc5d5601223600beaf53ac56d05262d7bb518a18cbfa2c22fc9128184032882c885e2906c438c3a7c7a00de8c3a69f
|
data/docs/ChangeLog.md
ADDED
data/docs/Readme.md
CHANGED
|
@@ -40,7 +40,7 @@ env:
|
|
|
40
40
|
RUBYOPT: "--disable=gems"
|
|
41
41
|
default_ci_shell: ruby cinnabar/ci.rb {0}
|
|
42
42
|
# optional values: debug, info, warn, error, fatal, unknown
|
|
43
|
-
RUBY_LOG:
|
|
43
|
+
RUBY_LOG: debug
|
|
44
44
|
|
|
45
45
|
jobs:
|
|
46
46
|
build:
|
|
@@ -56,7 +56,7 @@ jobs:
|
|
|
56
56
|
with:
|
|
57
57
|
repository: 2moe/cinnabar
|
|
58
58
|
path: cinnabar
|
|
59
|
-
ref: v0.0.
|
|
59
|
+
ref: v0.0.2
|
|
60
60
|
|
|
61
61
|
- name: (example) run cargo command
|
|
62
62
|
run: |
|
|
@@ -85,7 +85,7 @@ jobs:
|
|
|
85
85
|
stdout.to_i == 5 #=> true
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
#### `.async_run`
|
|
88
|
+
#### `.async_run` + log
|
|
89
89
|
|
|
90
90
|
```ruby,yaml
|
|
91
91
|
- run: |
|
|
@@ -98,6 +98,10 @@ jobs:
|
|
|
98
98
|
} .to_argv
|
|
99
99
|
.async_run
|
|
100
100
|
|
|
101
|
+
# log_dbg, log_info, log_warn, log_err, log_fatal, log_unk
|
|
102
|
+
"You can now do other things without waiting for
|
|
103
|
+
the process to complete.".log_dbg
|
|
104
|
+
|
|
101
105
|
stdout, status = task.wait_with_output
|
|
102
106
|
stdout.log_info
|
|
103
107
|
raise "wasi" unless status.success?
|
|
@@ -117,7 +121,7 @@ jobs:
|
|
|
117
121
|
# opts = { stdin_data:, stdin_binmode: false }
|
|
118
122
|
opts = { stdin_data: }
|
|
119
123
|
|
|
120
|
-
accel = %w[kvm hvf
|
|
124
|
+
accel = %w[kvm hvf whpx].join ':'
|
|
121
125
|
task = {
|
|
122
126
|
'qemu-system-x86_64': (),
|
|
123
127
|
machine: "accel=#{accel}",
|
data/lib/cinnabar/00_pre.rb
CHANGED
|
@@ -7,9 +7,8 @@
|
|
|
7
7
|
# @see https://github.com/2moe/cinnabar
|
|
8
8
|
module Cinnabar; end
|
|
9
9
|
|
|
10
|
+
require 'pathname'
|
|
11
|
+
|
|
10
12
|
# To ensure compatibility with "--disable=gems" (allowing users to pre-require),
|
|
11
13
|
# add conditional checks before requiring these libraries.
|
|
12
14
|
require 'sinlog' unless defined? Sinlog::VERSION
|
|
13
|
-
# require 'argvise' unless defined? Argvise::VERSION
|
|
14
|
-
|
|
15
|
-
require 'pathname'
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# NOTE: This file can be run independently;
|
|
4
|
+
# Although **00_pre.rb** has already imported the relevant libraries, they still need to be imported here.
|
|
5
|
+
require 'pathname'
|
|
6
|
+
|
|
7
|
+
module Cinnabar
|
|
8
|
+
# Build a Proc that converts a directory-like value into a {Kernel.Pathname}.
|
|
9
|
+
#
|
|
10
|
+
# This is handy when you want to pass a converter into higher-order APIs
|
|
11
|
+
# (e.g., map/filter pipelines).
|
|
12
|
+
#
|
|
13
|
+
# @param dir [String, #to_s] a directory path (or any object convertible to String)
|
|
14
|
+
# @return [Proc] a lambda that maps `dir` to `Pathname(dir)`
|
|
15
|
+
#
|
|
16
|
+
# @example Convert a list of directories to Pathname objects
|
|
17
|
+
#
|
|
18
|
+
# conv = Cinnabar.to_path_proc
|
|
19
|
+
# %w[/tmp /var].map(&conv)
|
|
20
|
+
# #=> [#<Pathname:/tmp>, #<Pathname:/var>]
|
|
21
|
+
def self.to_path_proc = ->(dir) { Pathname(dir) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Adds `String#to_path` as a convenience helper to convert strings into {Kernel.Pathname}.
|
|
25
|
+
#
|
|
26
|
+
# This module supports two integration styles:
|
|
27
|
+
#
|
|
28
|
+
# - {Cinnabar::StrToPath::Mixin}: globally extends {String} (monkey patch).
|
|
29
|
+
# - {Cinnabar::StrToPath::Refin}: lexically-scoped extension via refinements.
|
|
30
|
+
#
|
|
31
|
+
# @note This feature relies on Ruby's {Pathname} class.
|
|
32
|
+
# Make sure `require "pathname"` is loaded before calling `to_path`.
|
|
33
|
+
module Cinnabar::StrToPath
|
|
34
|
+
# Implementation of the `#to_path` method intended to be mixed into {String}.
|
|
35
|
+
module Ext
|
|
36
|
+
# Convert the receiver (a String) into a {Pathname}.
|
|
37
|
+
#
|
|
38
|
+
# @return [Pathname] `Pathname(self)`
|
|
39
|
+
#
|
|
40
|
+
# @example
|
|
41
|
+
#
|
|
42
|
+
# "lib".to_path
|
|
43
|
+
# #=> #<Pathname:lib>
|
|
44
|
+
def to_path = ::Kernel.Pathname(self)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# This is a "mixin switch": `include Cinnabar::StrToPath::Mixin` will modify
|
|
48
|
+
# {::String} for the entire process (i.e., a monkey patch).
|
|
49
|
+
#
|
|
50
|
+
# @note Side effect: this will affect *all* strings in the process, including
|
|
51
|
+
# third-party code. If you want scoped behavior, prefer {Refin}.
|
|
52
|
+
#
|
|
53
|
+
# @example
|
|
54
|
+
#
|
|
55
|
+
# include Cinnabar::StrToPath::Mixin
|
|
56
|
+
#
|
|
57
|
+
# __dir__.to_path
|
|
58
|
+
# # Same as `Pathname(__dir__)`
|
|
59
|
+
module Mixin
|
|
60
|
+
# Hook invoked when this module is included.
|
|
61
|
+
#
|
|
62
|
+
# @param _host [Module] the including host (unused)
|
|
63
|
+
# @return [void]
|
|
64
|
+
def self.included(_host) = ::String.include Ext
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Adds `String#to_path` via Ruby refinements (lexically scoped).
|
|
68
|
+
#
|
|
69
|
+
# This avoids global monkey patches. The method is only visible within scopes
|
|
70
|
+
# where `using Cinnabar::StrToPath::Refin` is active.
|
|
71
|
+
#
|
|
72
|
+
# @example
|
|
73
|
+
#
|
|
74
|
+
# using Cinnabar::StrToPath::Refin
|
|
75
|
+
#
|
|
76
|
+
# __dir__.to_path
|
|
77
|
+
# # Same as `Pathname(__dir__)`
|
|
78
|
+
module Refin
|
|
79
|
+
# Refinement for {String} to import {Ext#to_path}.
|
|
80
|
+
refine ::String do
|
|
81
|
+
import_methods Ext
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
module Cinnabar::Path
|
|
87
|
+
module_function
|
|
88
|
+
|
|
89
|
+
# Appends a directory to Ruby's load path (`$LOAD_PATH` / `$:`)
|
|
90
|
+
# if it is not already included.
|
|
91
|
+
#
|
|
92
|
+
# @param dir [String] directory path to add into `$LOAD_PATH`
|
|
93
|
+
# @return [void]
|
|
94
|
+
# @example
|
|
95
|
+
#
|
|
96
|
+
# Cinnabar::Path.append_load_path '/opt/ruby/4.0.0/lib/ruby/4.0.0'
|
|
97
|
+
def append_load_path(dir)
|
|
98
|
+
# $: is an alias of $LOAD_PATH
|
|
99
|
+
$: << dir unless $:.include?(dir)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Finds the gem's "lib directory" (via `gem which -V`) and append it to $LOAD_PATH.
|
|
103
|
+
#
|
|
104
|
+
# This method maintains a small cache file to avoid running `gem which` repeatedly.
|
|
105
|
+
# Cache format (per line):
|
|
106
|
+
# <gem_name><two spaces><lib_dir>
|
|
107
|
+
#
|
|
108
|
+
# If the gem cannot be located, it will try to install it and retry up to `max_retries`.
|
|
109
|
+
#
|
|
110
|
+
# @param gem_name [String, Symbol] gem name to locate (default: 'logger')
|
|
111
|
+
# @param cache_file [String] cache file path (default: 'tmp/load_path.txt')
|
|
112
|
+
# @param max_retries [Integer] maximum retries for gem install + re-check (default: 2)
|
|
113
|
+
# @return [void]
|
|
114
|
+
def find_and_append_load_path(gem_name = 'logger', cache_file: 'tmp/load_path.txt', max_retries: 2)
|
|
115
|
+
pkg = gem_name.to_s
|
|
116
|
+
cache_data = decode_cache_file(cache_file)
|
|
117
|
+
|
|
118
|
+
# If cached, append immediately and return.
|
|
119
|
+
case val = cache_data&.[](pkg)
|
|
120
|
+
when nil then ()
|
|
121
|
+
else return append_load_path(val)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Locate the gem's lib directory, installing the gem if necessary.
|
|
125
|
+
lib_dir = gem_dir_with_retry(pkg, max_retries)
|
|
126
|
+
|
|
127
|
+
# Update cache and write it back to disk.
|
|
128
|
+
cache_data[pkg] = lib_dir
|
|
129
|
+
encoded = encode_cache_hash(cache_data)
|
|
130
|
+
|
|
131
|
+
# Ensure parent directory exists, then write the cache file.
|
|
132
|
+
Kernel.Pathname(cache_file)
|
|
133
|
+
.tap { _1.dirname.mkpath }
|
|
134
|
+
.write(encoded)
|
|
135
|
+
|
|
136
|
+
# Finally, append the located directory to $LOAD_PATH.
|
|
137
|
+
append_load_path(lib_dir)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Decodes cache file into a Hash.
|
|
141
|
+
#
|
|
142
|
+
# It ignores:
|
|
143
|
+
#
|
|
144
|
+
# - leading spaces (lstrip)
|
|
145
|
+
# - empty lines
|
|
146
|
+
# - comment lines that start with '#'
|
|
147
|
+
#
|
|
148
|
+
# Each line is split by "two spaces" into:
|
|
149
|
+
# `key value`
|
|
150
|
+
#
|
|
151
|
+
# @param file [String] cache file path
|
|
152
|
+
# @return [Hash{String => String}] mapping from gem name to lib dir
|
|
153
|
+
def decode_cache_file(file)
|
|
154
|
+
# If cache file does not exist, treat as empty cache.
|
|
155
|
+
return {} unless File.exist?(file)
|
|
156
|
+
|
|
157
|
+
File.foreach(file)
|
|
158
|
+
.lazy
|
|
159
|
+
.map(&:lstrip) # allow indentation; normalize leading spaces
|
|
160
|
+
.map(&:chomp) # remove trailing newline
|
|
161
|
+
.reject(&:empty?) # drop blank lines
|
|
162
|
+
.reject { _1.start_with? '#' } # drop comments
|
|
163
|
+
.map { |line| line.split(' ', 2) } # split into [key, value] by two spaces
|
|
164
|
+
.to_h
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Encodes a Hash into the cache file format.
|
|
168
|
+
#
|
|
169
|
+
# @param data [Hash] mapping from gem name to lib dir
|
|
170
|
+
# @return [String] encoded cache content
|
|
171
|
+
# @raise [ArgumentError] if `data` is not a Hash
|
|
172
|
+
#
|
|
173
|
+
# @example
|
|
174
|
+
#
|
|
175
|
+
# CiPath = Cinnabar::Path
|
|
176
|
+
#
|
|
177
|
+
# gem_home = "#{Dir.home}/.local/share/gem"
|
|
178
|
+
# data = {
|
|
179
|
+
# "logger" => "#{gem_home}/gems/logger-1.7.0/lib",
|
|
180
|
+
# "irb" => "#{gem_home}/gems/irb-1.16.0/lib",
|
|
181
|
+
# "reline" => "#{gem_home}/gems/reline-0.6.3/lib",
|
|
182
|
+
# }
|
|
183
|
+
# str = CiPath.encode_cache_hash(data)
|
|
184
|
+
def encode_cache_hash(data)
|
|
185
|
+
Kernel.raise ArgumentError, 'data must be a hash' unless data.is_a? ::Hash
|
|
186
|
+
|
|
187
|
+
# Use "two spaces" as a stable delimiter (same as decode).
|
|
188
|
+
data.map { |k, v| "#{k} #{v}" }.join("\n")
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Resolves gem's lib directory by invoking:
|
|
192
|
+
# `gem which -V <pkg>`
|
|
193
|
+
#
|
|
194
|
+
# `gem which -V` prints the resolved file path; we strip it and take its dirname.
|
|
195
|
+
#
|
|
196
|
+
# @param pkg [String] gem name
|
|
197
|
+
# @return [String] directory containing the resolved file
|
|
198
|
+
# @raise [RuntimeError] if gem which returns empty
|
|
199
|
+
#
|
|
200
|
+
# @note Please do not use `Gem::Specification` in this method,
|
|
201
|
+
# as this function and the script must remain compatible with `--disable=gems`.
|
|
202
|
+
def gem_dir(pkg)
|
|
203
|
+
path = IO.popen(%w[gem which -V] << pkg.to_s, &:read).to_s.strip
|
|
204
|
+
Kernel.raise "gem which returned empty for #{pkg}" if path.empty?
|
|
205
|
+
|
|
206
|
+
File.dirname(path)
|
|
207
|
+
end
|
|
208
|
+
private_class_method :gem_dir
|
|
209
|
+
|
|
210
|
+
# Locates the lib directory for the given gem_name; if it fails, retries by installing the gem.
|
|
211
|
+
#
|
|
212
|
+
# Behavior:
|
|
213
|
+
#
|
|
214
|
+
# - If `gem_dir` raises, print a warning and run `gem install <pkg>`.
|
|
215
|
+
# - Retry up to `max_retries`.
|
|
216
|
+
#
|
|
217
|
+
# @param gem_name [String, Symbol] gem name
|
|
218
|
+
# @param max_retries [Integer] max retry count (default: 2)
|
|
219
|
+
# @return [String] resolved lib directory
|
|
220
|
+
# @raise [RuntimeError] when install fails or retries exceed max
|
|
221
|
+
#
|
|
222
|
+
#
|
|
223
|
+
# @example
|
|
224
|
+
#
|
|
225
|
+
# CiPath = Cinnabar::Path
|
|
226
|
+
#
|
|
227
|
+
# dir_str = CiPath.gem_dir_with_retry("logger")
|
|
228
|
+
def gem_dir_with_retry(gem_name, max_retries = 2)
|
|
229
|
+
pkg = gem_name.to_s
|
|
230
|
+
attempts = 0
|
|
231
|
+
|
|
232
|
+
begin
|
|
233
|
+
logger_dir = gem_dir(pkg)
|
|
234
|
+
rescue StandardError => e
|
|
235
|
+
# Inform user about the failure and the planned automatic install attempt.
|
|
236
|
+
#
|
|
237
|
+
# Do not use `Sinlog.warn` or any "advanced" logger here!
|
|
238
|
+
# As this function is intended for lower-level APIs.
|
|
239
|
+
Kernel.warn "[WARN] #{e}; Try installing #{pkg}"
|
|
240
|
+
|
|
241
|
+
# Attempt to install; raise if installation fails.
|
|
242
|
+
Kernel.system "gem install #{pkg}" or Kernel.raise 'Failed to install'
|
|
243
|
+
|
|
244
|
+
attempts += 1
|
|
245
|
+
Kernel.raise 'Already retried 3 times' if attempts > max_retries
|
|
246
|
+
|
|
247
|
+
retry
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
logger_dir
|
|
251
|
+
end
|
|
252
|
+
# private_class_method :gem_dir_with_retry
|
|
253
|
+
end
|
data/lib/cinnabar/version.rb
CHANGED
data/lib/cinnabar.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cinnabar
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- 2moe
|
|
@@ -31,12 +31,14 @@ files:
|
|
|
31
31
|
- ".rubocop.yml"
|
|
32
32
|
- ".yardopts"
|
|
33
33
|
- License
|
|
34
|
+
- docs/ChangeLog.md
|
|
34
35
|
- docs/Readme-zh.md
|
|
35
36
|
- docs/Readme.md
|
|
36
37
|
- lib/cinnabar.rb
|
|
37
38
|
- lib/cinnabar/00_pre.rb
|
|
38
39
|
- lib/cinnabar/cmd_runner.rb
|
|
39
40
|
- lib/cinnabar/net.rb
|
|
41
|
+
- lib/cinnabar/path.rb
|
|
40
42
|
- lib/cinnabar/pipe.rb
|
|
41
43
|
- lib/cinnabar/version.rb
|
|
42
44
|
homepage: https://github.com/2moe/cinnabar
|
|
@@ -44,6 +46,7 @@ licenses:
|
|
|
44
46
|
- Apache-2.0
|
|
45
47
|
metadata:
|
|
46
48
|
homepage_uri: https://github.com/2moe/cinnabar
|
|
49
|
+
documentation_uri: https://2moe.github.io/cinnabar
|
|
47
50
|
rdoc_options: []
|
|
48
51
|
require_paths:
|
|
49
52
|
- lib
|
|
@@ -58,7 +61,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
58
61
|
- !ruby/object:Gem::Version
|
|
59
62
|
version: '0'
|
|
60
63
|
requirements: []
|
|
61
|
-
rubygems_version:
|
|
64
|
+
rubygems_version: 4.0.3
|
|
62
65
|
specification_version: 4
|
|
63
66
|
summary: CI Utils
|
|
64
67
|
test_files: []
|