Class: Copse::Worktree
- Inherits:
-
Object
- Object
- Copse::Worktree
- Defined in:
- lib/copse/worktree.rb
Overview
Answers "what am I called, and what port do I get" by shelling out to git.
Holds no state and touches no files. Nothing here needs git to succeed -- git only answers the naming question more precisely. A plain directory, or a machine with no git at all, degrades to the directory name.
Constant Summary collapse
- LABEL_LIMIT =
63
Instance Attribute Summary collapse
-
#root ⇒ Object
readonly
Returns the value of attribute root.
Class Method Summary collapse
-
.slug(value) ⇒ Object
Reduces an arbitrary string to a single valid DNS label.
Instance Method Summary collapse
- #branch ⇒ Object
- #companion_port ⇒ Object
-
#database_suffix ⇒ Object
What a linked worktree's development database name is suffixed with, or nil in a main worktree -- which keeps the app's plain database.
-
#host ⇒ Object
<project>.localhostfor a main worktree,<branch>.<project>.localhostfor a linked one. -
#initialize(root = Dir.pwd) ⇒ Worktree
constructor
A new instance of Worktree.
- #linked? ⇒ Boolean
- #port ⇒ Object
-
#project ⇒ Object
The project name: the main worktree's directory name, even when called from a linked worktree.
-
#slug ⇒ Object
nil for a main worktree; the branch name (or this directory's name on a detached HEAD) for a linked one.
- #url ⇒ Object
Constructor Details
Instance Attribute Details
#root ⇒ Object (readonly)
Returns the value of attribute root.
14 15 16 |
# File 'lib/copse/worktree.rb', line 14 def root @root end |
Class Method Details
.slug(value) ⇒ Object
Reduces an arbitrary string to a single valid DNS label.
A whitelist, not a substitution list. Git accepts branch names containing
;, $(, &&, quotes, and more, and the slug flows into COPSE_HOST,
COPSE_URL, every child process's environment, and a generated Procfile that
a shell will execute -- so anything outside [a-z0-9-] is replaced rather
than passed through. Branch names also arrive from collaborators via
git fetch; they are not necessarily the developer's own input.
Returns nil when nothing survives, so callers can fall back.
88 89 90 91 92 |
# File 'lib/copse/worktree.rb', line 88 def self.slug(value) collapsed = value.to_s.downcase.gsub(/[^a-z0-9]+/, "-") trimmed = collapsed[0, LABEL_LIMIT].to_s.gsub(/\A-+|-+\z/, "") trimmed.empty? ? nil : trimmed end |
Instance Method Details
#branch ⇒ Object
70 71 72 73 74 75 76 |
# File 'lib/copse/worktree.rb', line 70 def branch return @branch if defined?(@branch) name = git("rev-parse", "--abbrev-ref", "HEAD") # "HEAD" means detached; there is no branch to name the worktree after. @branch = (name == "HEAD" ? nil : name) end |
#companion_port ⇒ Object
30 31 32 |
# File 'lib/copse/worktree.rb', line 30 def companion_port @companion_port ||= Copse.companion_port_for(host) end |
#database_suffix ⇒ Object
What a linked worktree's development database name is suffixed with, or nil in a main worktree -- which keeps the app's plain database.
The same slug the hostname uses, with - swapped for _: a hyphen is
legal in a database name but has to be quoted on every psql and mysql
command line, and _ is what Rails' own <app>_development already uses.
44 45 46 |
# File 'lib/copse/worktree.rb', line 44 def database_suffix slug&.tr("-", "_") end |
#host ⇒ Object
<project>.localhost for a main worktree, <branch>.<project>.localhost
for a linked one.
22 23 24 |
# File 'lib/copse/worktree.rb', line 22 def host @host ||= [slug, project, "localhost"].compact.join(".") end |
#linked? ⇒ Boolean
64 65 66 67 68 |
# File 'lib/copse/worktree.rb', line 64 def linked? return @linked if defined?(@linked) @linked = !main_root.nil? && !toplevel.nil? && main_root != toplevel end |
#port ⇒ Object
26 27 28 |
# File 'lib/copse/worktree.rb', line 26 def port @port ||= Copse.port_for(host) end |
#project ⇒ Object
The project name: the main worktree's directory name, even when called from a linked worktree.
50 51 52 |
# File 'lib/copse/worktree.rb', line 50 def project @project ||= self.class.slug(File.basename(main_root)) || "app" end |
#slug ⇒ Object
nil for a main worktree; the branch name (or this directory's name on a detached HEAD) for a linked one.
56 57 58 59 60 61 62 |
# File 'lib/copse/worktree.rb', line 56 def slug return @slug if defined?(@slug) @slug = if linked? self.class.slug(branch) || self.class.slug(File.basename(toplevel)) end end |
#url ⇒ Object
34 35 36 |
# File 'lib/copse/worktree.rb', line 34 def url "http://#{host}:#{port}" end |