Class: Siding::LoadManifest
- Inherits:
-
Object
- Object
- Siding::LoadManifest
- Defined in:
- lib/siding/load_manifest.rb
Defined Under Namespace
Modules: EnvProbe, LoadProbe Classes: DirectoryEntry, EnvEntry, FileEntry
Constant Summary collapse
- RELOADABLE =
:reloadable- REBOOT =
:reboot- EXCLUDED_SUBDIRECTORIES =
%w[tmp log storage node_modules .git vendor/bundle].freeze
- INITIALIZER_DIRECTORY =
File.join("config", "initializers")
Instance Attribute Summary collapse
-
#app_root ⇒ Object
readonly
Returns the value of attribute app_root.
-
#bundle_files ⇒ Object
readonly
Returns the value of attribute bundle_files.
-
#bundle_path ⇒ Object
readonly
Returns the value of attribute bundle_path.
-
#bundle_token ⇒ Object
readonly
Returns the value of attribute bundle_token.
-
#captured_at ⇒ Object
readonly
Returns the value of attribute captured_at.
-
#directory_entries ⇒ Object
readonly
Returns the value of attribute directory_entries.
-
#env_entries ⇒ Object
readonly
Returns the value of attribute env_entries.
-
#file_entries ⇒ Object
readonly
Returns the value of attribute file_entries.
Class Method Summary collapse
- .around_boot(app_root:) ⇒ Object
- .build(app_root:, loaded:, env_reads: {}) ⇒ Object
- .child_names(path, recursive:) ⇒ Object
- .digest_env_value(value) ⇒ Object
- .entry_digest_for(path, recursive:) ⇒ Object
- .label_for(bundle_token:, files:, directories:, envs:) ⇒ Object
- .stamp_for(path) ⇒ Object
- .token_for(paths) ⇒ Object
Instance Method Summary collapse
-
#initialize(app_root:, loaded:, env_reads: {}) ⇒ LoadManifest
constructor
A new instance of LoadManifest.
- #revision_label ⇒ Object
- #to_s ⇒ Object
Constructor Details
#initialize(app_root:, loaded:, env_reads: {}) ⇒ LoadManifest
Returns a new instance of LoadManifest.
87 88 89 90 91 92 93 94 95 96 |
# File 'lib/siding/load_manifest.rb', line 87 def initialize(app_root:, loaded:, env_reads: {}) @app_root = realpath(app_root) @captured_at = Time.now @bundle_path = discover_bundle_path @bundle_files = discover_bundle_files @bundle_token = self.class.token_for(@bundle_files) @file_entries = capture_file_entries(loaded) @directory_entries = capture_directory_entries @env_entries = capture_env_entries(env_reads) end |
Instance Attribute Details
#app_root ⇒ Object (readonly)
Returns the value of attribute app_root.
21 22 23 |
# File 'lib/siding/load_manifest.rb', line 21 def app_root @app_root end |
#bundle_files ⇒ Object (readonly)
Returns the value of attribute bundle_files.
21 22 23 |
# File 'lib/siding/load_manifest.rb', line 21 def bundle_files @bundle_files end |
#bundle_path ⇒ Object (readonly)
Returns the value of attribute bundle_path.
21 22 23 |
# File 'lib/siding/load_manifest.rb', line 21 def bundle_path @bundle_path end |
#bundle_token ⇒ Object (readonly)
Returns the value of attribute bundle_token.
21 22 23 |
# File 'lib/siding/load_manifest.rb', line 21 def bundle_token @bundle_token end |
#captured_at ⇒ Object (readonly)
Returns the value of attribute captured_at.
21 22 23 |
# File 'lib/siding/load_manifest.rb', line 21 def captured_at @captured_at end |
#directory_entries ⇒ Object (readonly)
Returns the value of attribute directory_entries.
21 22 23 |
# File 'lib/siding/load_manifest.rb', line 21 def directory_entries @directory_entries end |
#env_entries ⇒ Object (readonly)
Returns the value of attribute env_entries.
21 22 23 |
# File 'lib/siding/load_manifest.rb', line 21 def env_entries @env_entries end |
#file_entries ⇒ Object (readonly)
Returns the value of attribute file_entries.
21 22 23 |
# File 'lib/siding/load_manifest.rb', line 21 def file_entries @file_entries end |
Class Method Details
.around_boot(app_root:) ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/siding/load_manifest.rb', line 24 def around_boot(app_root:) env = EnvProbe.start loads = LoadProbe.start before = $LOADED_FEATURES.dup yield build(app_root:, loaded: ($LOADED_FEATURES - before) + loads.finish, env_reads: env.finish) ensure env&.stop loads&.stop end |
.build(app_root:, loaded:, env_reads: {}) ⇒ Object
36 37 38 |
# File 'lib/siding/load_manifest.rb', line 36 def build(app_root:, loaded:, env_reads: {}) new(app_root:, loaded:, env_reads:) end |
.child_names(path, recursive:) ⇒ Object
65 66 67 68 69 |
# File 'lib/siding/load_manifest.rb', line 65 def child_names(path, recursive:) recursive ? Dir.glob("**/*", base: path).sort : Dir.children(path).sort rescue SystemCallError nil end |
.digest_env_value(value) ⇒ Object
71 72 73 |
# File 'lib/siding/load_manifest.rb', line 71 def digest_env_value(value) Digest::SHA256.hexdigest(value.nil? ? "0" : "1\0#{value}") end |
.entry_digest_for(path, recursive:) ⇒ Object
58 59 60 61 62 63 |
# File 'lib/siding/load_manifest.rb', line 58 def entry_digest_for(path, recursive:) names = child_names(path, recursive: recursive) return "missing" if names.nil? Digest::SHA256.hexdigest(names.sort.join("\n")) end |
.label_for(bundle_token:, files:, directories:, envs:) ⇒ Object
40 41 42 43 44 45 46 47 |
# File 'lib/siding/load_manifest.rb', line 40 def label_for(bundle_token:, files:, directories:, envs:) digest = Digest::SHA256.new digest << "bundle\0#{bundle_token}\n" files.each { |path, stamp| digest << "file\0#{path}\0#{stamp}\n" } directories.each { |path, entry_digest| digest << "dir\0#{path}\0#{entry_digest}\n" } envs.each { |key, value| digest << "env\0#{key}\0#{value.nil? ? "\1" : value}\n" } digest.hexdigest[0, 12] end |
.stamp_for(path) ⇒ Object
49 50 51 52 53 54 55 56 |
# File 'lib/siding/load_manifest.rb', line 49 def stamp_for(path) stat = File.stat(path) "#{stat.size}:#{format('%.6f', stat.mtime.to_f)}" rescue SystemCallError # A loaded file that no longer exists is a change like any other, and one that must not be # mistaken for "unchanged" by a comparison against nil on both sides. "missing" end |
.token_for(paths) ⇒ Object
75 76 77 78 79 80 81 82 83 84 |
# File 'lib/siding/load_manifest.rb', line 75 def token_for(paths) digest = Digest::SHA256.new paths.each do |path| digest << path << "\0" digest << (File.file?(path) ? File.read(path) : "") end digest.hexdigest[0, 16] rescue SystemCallError nil end |
Instance Method Details
#revision_label ⇒ Object
98 99 100 101 102 103 104 105 |
# File 'lib/siding/load_manifest.rb', line 98 def revision_label @revision_label ||= self.class.label_for( bundle_token: bundle_token, files: file_entries.map { |entry| [entry.path, "#{entry.size}:#{format('%.6f', entry.mtime)}"] }, directories: directory_entries.map { |entry| [entry.path, entry.entry_digest] }, envs: env_entries.map { |entry| [entry.key, entry.value_digest] } ) end |
#to_s ⇒ Object
107 108 |
# File 'lib/siding/load_manifest.rb', line 107 def to_s = "#{file_entries.size} files, #{directory_entries.size} directories, " \ "#{env_entries.size} environment variables" |