Class: Autorespawn::ProgramID
- Inherits:
-
Object
- Object
- Autorespawn::ProgramID
- Defined in:
- lib/autorespawn/program_id.rb
Overview
Management of the ID of a complete Ruby program
It basically stores information about all the files that form this program.
Defined Under Namespace
Classes: FileInfo
Instance Attribute Summary collapse
-
#files ⇒ Hash<Pathname,FileInfo>
readonly
Information about the files that form this program.
Class Method Summary collapse
-
.for_self ⇒ Object
Compute ID information abou thte current Ruby process.
Instance Method Summary collapse
-
#changed? ⇒ Boolean
Whether the state on disk is different than the state stored in self.
-
#clear ⇒ Object
Remove all tracked files.
-
#compute_binary_file_id(file) ⇒ Object
private
Compute the content ID of a binary file.
-
#compute_file_id(file) ⇒ String
Compute a SHA1 that is representative of the file’s contents.
-
#compute_text_file_id(file) ⇒ Object
private
Compute the content ID of a text (code) file.
-
#each_tracked_file {|path| ... } ⇒ Object
Enumerate the path of all the files that are being tracked.
-
#empty? ⇒ Boolean
Whether this program ID tracks some files.
-
#file_info(path, search_path = ruby_load_path) ⇒ FileInfo
Resolve file information about a single file.
-
#id ⇒ Object
Returns a string that can ID this program.
- #include?(path, search_path = ruby_load_path) ⇒ Boolean
-
#initialize ⇒ ProgramID
constructor
A new instance of ProgramID.
- #initialize_copy(old) ⇒ Object
-
#merge!(id) ⇒ Object
Merge the information contained in another ProgramID object into self.
-
#refresh ⇒ Object
Update the information about all the files registered on this object.
-
#register_file(file, search_path = ruby_load_path) ⇒ Boolean
Registers file information for one file.
-
#register_files(files, search_path = ruby_load_path, ignore_not_found: true) ⇒ Boolean
Register a set of files.
-
#register_loaded_features ⇒ void
Registers the file information for all loaded features.
-
#resolve_file_list(files, search_path = ruby_load_path, ignore_not_found: true) ⇒ Object
Resolve a file list into absolute paths.
-
#resolve_file_path(path, search_path = Array.new) ⇒ void
private
Given a path that may be relative, computes the full path to the corresponding file.
-
#ruby_load_path ⇒ Object
The ruby load path.
-
#slice(files, search_path = ruby_load_path, ignore_not_found: true) ⇒ Object
Removes any file in self that is not in the given file list and returns the result.
Constructor Details
#initialize ⇒ ProgramID
Returns a new instance of ProgramID.
18 19 20 |
# File 'lib/autorespawn/program_id.rb', line 18 def initialize @files = Hash.new end |
Instance Attribute Details
#files ⇒ Hash<Pathname,FileInfo> (readonly)
Information about the files that form this program
16 17 18 |
# File 'lib/autorespawn/program_id.rb', line 16 def files @files end |
Class Method Details
Instance Method Details
#changed? ⇒ Boolean
Whether the state on disk is different than the state stored in self
146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/autorespawn/program_id.rb', line 146 def changed? files.each_value do |info| return true if !info.path.exist? stat = info.path.stat if stat.mtime != info.mtime || stat.size != info.size new_id = compute_file_id(info.path) return new_id != info.id end end false end |
#clear ⇒ Object
Remove all tracked files
50 51 52 |
# File 'lib/autorespawn/program_id.rb', line 50 def clear files.clear end |
#compute_binary_file_id(file) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Compute the content ID of a binary file
227 228 229 |
# File 'lib/autorespawn/program_id.rb', line 227 def compute_binary_file_id(file) Digest::SHA1.hexdigest(file.read(enc: 'BINARY')) end |
#compute_file_id(file) ⇒ String
Compute a SHA1 that is representative of the file’s contents
It does some whitespace cleanup, but is not meant to be super-robust to changes that are irrelevant to the end program
238 239 240 241 242 243 244 |
# File 'lib/autorespawn/program_id.rb', line 238 def compute_file_id(file) if file.extname == ".rb" compute_text_file_id(file) else compute_binary_file_id(file) end end |
#compute_text_file_id(file) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Compute the content ID of a text (code) file
212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/autorespawn/program_id.rb', line 212 def compute_text_file_id(file) sanitized = file.readlines.map do |line| # Remove unnecessary spaces line = line.strip line = line.gsub(/\s\s+/, ' ') if !line.empty? line end end.compact Digest::SHA1.hexdigest(sanitized.join("\n")) end |
#each_tracked_file {|path| ... } ⇒ Object
Enumerate the path of all the files that are being tracked
131 132 133 |
# File 'lib/autorespawn/program_id.rb', line 131 def each_tracked_file(&block) files.keys.each(&block) end |
#empty? ⇒ Boolean
Whether this program ID tracks some files
45 46 47 |
# File 'lib/autorespawn/program_id.rb', line 45 def empty? files.empty? end |
#file_info(path, search_path = ruby_load_path) ⇒ FileInfo
Resolve file information about a single file
202 203 204 205 206 207 |
# File 'lib/autorespawn/program_id.rb', line 202 def file_info(path, search_path = ruby_load_path) resolved = resolve_file_path(path, search_path) stat = resolved.stat id = compute_file_id(resolved) return FileInfo.new(path, resolved, stat.mtime, stat.size, id) end |
#id ⇒ Object
Returns a string that can ID this program
136 137 138 139 140 141 142 143 |
# File 'lib/autorespawn/program_id.rb', line 136 def id return @id if @id complete_id = files.keys.sort.map do |p| files[p].id end.join("") @id = Digest::SHA1.hexdigest(complete_id) end |
#include?(path, search_path = ruby_load_path) ⇒ Boolean
158 159 160 |
# File 'lib/autorespawn/program_id.rb', line 158 def include?(path, search_path = ruby_load_path) files.has_key?(resolve_file_path(path, search_path)) end |
#initialize_copy(old) ⇒ Object
22 23 24 25 |
# File 'lib/autorespawn/program_id.rb', line 22 def initialize_copy(old) super @files = @files.dup end |
#merge!(id) ⇒ Object
Merge the information contained in another ProgramID object into self
31 32 33 34 35 |
# File 'lib/autorespawn/program_id.rb', line 31 def merge!(id) @files.merge!(id.files) @id = nil self end |
#refresh ⇒ Object
Update the information about all the files registered on this object
116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/autorespawn/program_id.rb', line 116 def refresh updated = Hash.new files.each_key do |path| next if !path.exist? info = file_info(path) updated[info.path] = info end @files = updated @id = nil updated end |
#register_file(file, search_path = ruby_load_path) ⇒ Boolean
Registers file information for one file
104 105 106 107 108 109 110 111 112 113 |
# File 'lib/autorespawn/program_id.rb', line 104 def register_file(file, search_path = ruby_load_path) info = file_info(file, search_path) modified = (files[info.path] != info) files[info.path] = info if modified @id = nil info.path end end |
#register_files(files, search_path = ruby_load_path, ignore_not_found: true) ⇒ Boolean
Register a set of files
81 82 83 84 85 86 87 |
# File 'lib/autorespawn/program_id.rb', line 81 def register_files(files, search_path = ruby_load_path, ignore_not_found: true) modified = Array.new files = resolve_file_list(files, search_path, ignore_not_found: ignore_not_found) files.find_all do |path| register_file(path, search_path) end end |
#register_loaded_features ⇒ void
This method returns an undefined value.
Registers the file information for all loaded features
57 58 59 60 61 62 |
# File 'lib/autorespawn/program_id.rb', line 57 def register_loaded_features loaded_features = $LOADED_FEATURES.map do |file| Pathname.new(file) end register_files(loaded_features) end |
#resolve_file_list(files, search_path = ruby_load_path, ignore_not_found: true) ⇒ Object
Resolve a file list into absolute paths
65 66 67 68 69 70 71 72 |
# File 'lib/autorespawn/program_id.rb', line 65 def resolve_file_list(files, search_path = ruby_load_path, ignore_not_found: true) files.map do |path| begin resolve_file_path(path, search_path) rescue FileNotFound raise if !ignore_not_found end end.compact end |
#resolve_file_path(path, search_path = Array.new) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Given a path that may be relative, computes the full path to the corresponding file
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/autorespawn/program_id.rb', line 173 def resolve_file_path(path, search_path = Array.new) if !path.absolute? search_path.each do |search_p| full = search_p + path if full.exist? return full end end raise FileNotFound.new(path, search_path), "cannot find #{path} in #{search_path.join(", ")}" elsif !path.exist? raise FileNotFound.new(path, []), "#{path} does not exist" else return path end end |
#ruby_load_path ⇒ Object
The ruby load path
192 193 194 |
# File 'lib/autorespawn/program_id.rb', line 192 def ruby_load_path $LOAD_PATH.map { |p| Pathname.new(p) } end |
#slice(files, search_path = ruby_load_path, ignore_not_found: true) ⇒ Object
Removes any file in self that is not in the given file list and returns the result
91 92 93 94 95 96 97 |
# File 'lib/autorespawn/program_id.rb', line 91 def slice(files, search_path = ruby_load_path, ignore_not_found: true) result = dup files = resolve_file_list(files, search_path, ignore_not_found: ignore_not_found). to_set result.files.delete_if { |k, _| !files.include?(k) } result end |