Module: Railbow::Status::Ghosts
- Defined in:
- lib/railbow/status/ghosts.rb
Overview
Recovery of "NO FILE" migrations through the optional mighost gem: rows applied to the database whose migration file is no longer on disk.
Defined Under Namespace
Classes: Row
Constant Summary collapse
- GHOST_FG =
matches Table::Renderer::GHOST_FG, the row it sits in
"\e[38;5;217m"- MUTED =
"\e[38;5;245m"- BRANCH =
"\e[38;5;222m"
Class Method Summary collapse
- .api_superseded_by(version) ⇒ Object
- .available? ⇒ Boolean
-
.display_name(ghost) ⇒ Object
The name a ghost row displays, derived from its recovered filename.
-
.from_live_recovery(version, with_content) ⇒ Object
Detect reads stored snapshots only.
- .from_orphan(orphan, version, with_content) ⇒ Object
- .load(versions, with_content: false) ⇒ Object
- .read_attr(obj, name) ⇒ Object
- .snapshot_content(version) ⇒ Object
-
.tag(ghost) ⇒ Object
One tag slot per ghost row; the most informative wins.
Class Method Details
.api_superseded_by(version) ⇒ Object
109 110 111 112 113 114 115 |
# File 'lib/railbow/status/ghosts.rb', line 109 def api_superseded_by(version) return nil unless Mighost::API.respond_to?(:superseded_by) Mighost::API.superseded_by(version) rescue nil end |
.available? ⇒ Boolean
33 34 35 |
# File 'lib/railbow/status/ghosts.rb', line 33 def available? defined?(Mighost::API) && Mighost.enabled? end |
.display_name(ghost) ⇒ Object
The name a ghost row displays, derived from its recovered filename.
135 136 137 138 139 140 141 |
# File 'lib/railbow/status/ghosts.rb', line 135 def display_name(ghost) ghost.filename .sub(/\A\d+_/, "") # strip version prefix .sub(/\.rb\z/, "") # strip extension .tr("_", " ") .gsub(/\b\w/, &:upcase) # titleize end |
.from_live_recovery(version, with_content) ⇒ Object
Detect reads stored snapshots only. A version it lists without a filename has no snapshot yet, so fall back to live git/worktree recovery - that keeps fresh clones working with zero setup.
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/railbow/status/ghosts.rb', line 79 def from_live_recovery(version, with_content) snapshot = begin Mighost::API.find_or_recover_snapshot(version) rescue nil end return nil unless snapshot&.filename && !snapshot.filename.empty? Row.new( filename: snapshot.filename, branch_name: snapshot.branch_name, source: read_attr(snapshot, :source), superseded_by: api_superseded_by(version), deleted_in_sha: read_attr(snapshot, :deleted_in_sha), author_name: read_attr(snapshot, :author_name), author_email: read_attr(snapshot, :author_email), content: with_content ? snapshot.content : nil ) end |
.from_orphan(orphan, version, with_content) ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/railbow/status/ghosts.rb', line 63 def from_orphan(orphan, version, with_content) Row.new( filename: orphan.filename, branch_name: orphan.branch_name, source: read_attr(orphan, :source), superseded_by: read_attr(orphan, :superseded_by), deleted_in_sha: read_attr(orphan, :deleted_in_sha), author_name: read_attr(orphan, :author_name), author_email: read_attr(orphan, :author_email), content: with_content ? snapshot_content(version) : nil ) end |
.load(versions, with_content: false) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/railbow/status/ghosts.rb', line 37 def load(versions, with_content: false) # Detect once: OrphanedMigration carries the classification (supersession, # deletion commit) that a bare snapshot does not, and already honors # dismissals and hide_superseded. orphans = begin Mighost::API.orphaned_migrations.to_h { |o| [o.version.to_s, o] } rescue return {} end rows = {} versions.each do |v| # Absent from detect = deliberately suppressed (dismissed, or superseded # with hide_superseded on) - render as plain NO FILE, do not re-recover. next unless (orphan = orphans[v]) row = if orphan.filename && !orphan.filename.empty? from_orphan(orphan, v, with_content) else from_live_recovery(v, with_content) end rows[v] = row if row end rows end |
.read_attr(obj, name) ⇒ Object
99 100 101 |
# File 'lib/railbow/status/ghosts.rb', line 99 def read_attr(obj, name) obj.respond_to?(name) ? obj.public_send(name) : nil end |
.snapshot_content(version) ⇒ Object
103 104 105 106 107 |
# File 'lib/railbow/status/ghosts.rb', line 103 def snapshot_content(version) Mighost::API.find_snapshot(version)&.content rescue nil end |
.tag(ghost) ⇒ Object
One tag slot per ghost row; the most informative wins. Each ends in the ghost foreground rather than a reset, so the rest of the row keeps its ghost styling.
120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/railbow/status/ghosts.rb', line 120 def tag(ghost) if ghost.superseded_by "#{MUTED}≡ #{ghost.superseded_by}#{GHOST_FG}" elsif ghost.branch_name if ghost.source == "worktree" "#{BRANCH}⌥ₜ#{ghost.branch_name}#{GHOST_FG}" else "#{BRANCH}⌥ #{ghost.branch_name}#{GHOST_FG}" end elsif ghost.deleted_in_sha "#{MUTED}✂ deleted in:#{ghost.deleted_in_sha[0, 8]}#{GHOST_FG}" end end |