Class: Gemvault::GhostSpecification

Inherits:
Object
  • Object
show all
Defined in:
lib/gemvault/ghost_specification.rb

Overview

A gem installation record -- specifications/.gemspec -- whose gems/ directory is gone: the wreckage of an interrupted uninstall or a hand-cleaned gem home.

RubyGems still lists such a gem as installed, and Bundler's Gemfile-driven plugin installer trusts that record: it materializes the plugin against the ambient gem roots, reinstalls the missing gem into the plugin root, but then validates plugins.rb against the ghost's dead directory instead of the copy it just extracted. Every bundle install after that dies with MalformattedPlugin (plugins.rb was not found in the plugin.) -- issue #23. Removing the ghost record lets the next install see the machine as it really is.

Detection never evaluates the record. The gem directory's name is the record's file name minus .gemspec by RubyGems' own install convention, so a missing payload is recognized from the filesystem alone -- which lets a truncated or unreadable record, wreckage in its own right, be swept rather than silently skipped. Scoping to the asked gem reads the record's "# stub:" header when it is readable and falls back to the filename when it is not.

Deliberately out of scope: a gem directory that exists but has lost part of its payload. Telling that wreck apart from a healthy install would mean trusting the record's file list, and a false positive here deletes a working installation's record.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file) ⇒ GhostSpecification

Returns a new instance of GhostSpecification.



76
77
78
# File 'lib/gemvault/ghost_specification.rb', line 76

def initialize(file)
  @file = file
end

Instance Attribute Details

#fileObject (readonly)

Returns the value of attribute file.



74
75
76
# File 'lib/gemvault/ghost_specification.rb', line 74

def file
  @file
end

Class Method Details

.of(name, roots: Gem.path) ⇒ Object

All ghost specifications of name across roots (gem homes as listed on Gem.path, the same view Bundler's plugin installer resolves against).



33
34
35
# File 'lib/gemvault/ghost_specification.rb', line 33

def self.of(name, roots: Gem.path)
  roots.flat_map { |root| in_root(Pathname(root), name) }
end

Instance Method Details

#deleteObject



83
84
85
# File 'lib/gemvault/ghost_specification.rb', line 83

def delete
  File.delete(file)
end

#to_sObject



81
# File 'lib/gemvault/ghost_specification.rb', line 81

def to_s = file.to_s