Class: Autorespawn::ProgramID

Inherits:
Object
  • Object
show all
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

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeProgramID

Returns a new instance of ProgramID.



17
18
19
# File 'lib/autorespawn/program_id.rb', line 17

def initialize
    @files = Hash.new
end

Instance Attribute Details

#filesHash<Pathname,FileInfo> (readonly)

Information about the files that form this program

Returns:



15
16
17
# File 'lib/autorespawn/program_id.rb', line 15

def files
  @files
end

Class Method Details

.for_selfObject

Compute ID information abou thte current Ruby process



37
38
39
40
41
# File 'lib/autorespawn/program_id.rb', line 37

def self.for_self
    id = ProgramID.new
    id.register_loaded_features
    id
end

Instance Method Details

#changed?Boolean

Whether the state on disk is different than the state stored in self

Returns:

  • (Boolean)


162
163
164
165
166
167
168
# File 'lib/autorespawn/program_id.rb', line 162

def changed?
    files.each_value.any? do |info|
        return true if !info.path.exist?
        stat = info.path.stat
        stat.mtime != info.mtime || stat.size != info.size
    end
end

#clearObject

Remove all tracked files



49
50
51
# File 'lib/autorespawn/program_id.rb', line 49

def clear
    files.clear
end

#each_tracked_file(with_status: false) {|path| ... } ⇒ Object

Enumerate the path of all the files that are being tracked

Yield Parameters:

  • path (Pathname)


140
141
142
143
144
145
146
147
148
149
# File 'lib/autorespawn/program_id.rb', line 140

def each_tracked_file(with_status: false, &block)
    if with_status
        return enum_for(__method__, with_status: true) if !block_given?
        files.each do |path, info|
            yield(path, info.mtime, info.size)
        end
    else
        files.keys.each(&block)
    end
end

#empty?Boolean

Whether this program ID tracks some files

Returns:

  • (Boolean)


44
45
46
# File 'lib/autorespawn/program_id.rb', line 44

def empty?
    files.empty?
end

#file_info(path) ⇒ FileInfo

Resolve file information about a single file

Parameters:

  • path (Pathname)

    abolute path to the file

Returns:



212
213
214
215
# File 'lib/autorespawn/program_id.rb', line 212

def file_info(path)
    stat = path.stat
    return FileInfo.new(path, stat.mtime, stat.size)
end

#idObject

Returns a string that can ID this program



152
153
154
155
156
157
158
159
# File 'lib/autorespawn/program_id.rb', line 152

def id
    return @id if @id

    complete_id = files.keys.sort.map do |p|
        "#{p}#{files[p].mtime}#{files[p].size}"
    end.join("")
    @id = Digest::SHA1.hexdigest(complete_id)
end

#include?(path, search_path = ruby_load_path) ⇒ Boolean

Returns:

  • (Boolean)


170
171
172
# File 'lib/autorespawn/program_id.rb', line 170

def include?(path, search_path = ruby_load_path)
    files.has_key?(resolve_file_path(path, search_path))
end

#initialize_copy(old) ⇒ Object



21
22
23
24
# File 'lib/autorespawn/program_id.rb', line 21

def initialize_copy(old)
    super
    @files = @files.dup
end

#merge!(id) ⇒ Object

Merge the information contained in another ProgramID object into self

Parameters:

  • id (ProgramID)

    the object whose information we should merge

Returns:

  • self



30
31
32
33
34
# File 'lib/autorespawn/program_id.rb', line 30

def merge!(id)
    @files.merge!(id.files)
    @id = nil
    self
end

#refreshObject

Update the information about all the files registered on this object



125
126
127
128
129
130
131
132
133
134
135
# File 'lib/autorespawn/program_id.rb', line 125

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) ⇒ Boolean

Registers file information for one file

Parameters:

  • file (Pathname)

    the path to the file

Returns:

  • (Boolean)

    whether the registration modified the program ID’s state



113
114
115
116
117
118
119
120
121
122
# File 'lib/autorespawn/program_id.rb', line 113

def register_file(file)
    info = file_info(file)
    modified = (files[info.path] != info)
    files[info.path] = info

    if modified
        @id = nil 
        info.path
    end
end

#register_files(files, ignore_not_found: true) ⇒ Boolean

Register a set of files

Parameters:

  • files (Array<String>)

    the list of files

  • search_path (Array<String>)

    the path to resolve relative paths

  • ignore_not_found (Boolean) (defaults to: true)

    whether files that cannot be resolved are ignored or cause a FileNotFound exception

Returns:

  • (Boolean)

    whether the program ID has been modified



80
81
82
83
84
85
86
87
88
89
# File 'lib/autorespawn/program_id.rb', line 80

def register_files(files, ignore_not_found: true)
    files.find_all do |path|
        if path.exist?
            register_file(path)
        elsif ignore_not_found
            false
        else raise FileNotFound, "#{path} cannot be found"
        end
    end
end

#register_loaded_featuresvoid

This method returns an undefined value.

Registers the file information for all loaded features



56
57
58
59
60
61
# File 'lib/autorespawn/program_id.rb', line 56

def register_loaded_features
    loaded_features = $LOADED_FEATURES.map do |file|
        Pathname.new(file)
    end
    register_files(resolve_file_list(loaded_features))
end

#resolve_file_list(files, search_path = ruby_load_path, ignore_not_found: true) ⇒ Object

Resolve a file list into absolute paths



64
65
66
67
68
69
70
71
# File 'lib/autorespawn/program_id.rb', line 64

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

Parameters:

  • path (Pathname)

    the file path

  • search_path (Array<Pathname>) (defaults to: Array.new)

    the search path to use to resolve relative paths

Raises:

  • FileNotFound when a relative path cannot be resolved into a global one



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/autorespawn/program_id.rb', line 185

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_pathObject

The ruby load path

Parameters:

  • (Array<Pathname>)


204
205
206
# File 'lib/autorespawn/program_id.rb', line 204

def ruby_load_path
    @ruby_load_path ||= $LOAD_PATH.map { |p| Pathname.new(p) }
end

#slice(files, ignore_not_found: true) ⇒ Object

Removes any file in self that is not in the given file list and returns the result



93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/autorespawn/program_id.rb', line 93

def slice(files, ignore_not_found: true)
    result = dup
    result.files.delete_if do |k, _|
        if !files.include?(k)
            true
        elsif !k.exist?
            if !ignore_not_found
                raise FileNotFound, "#{k} does not exist"
            end
            true
        end
    end
    result
end