Skip to content

Commit 1521b42

Browse files
committed
refactor(commands): implement install wrap around shards
1 parent 14580d0 commit 1521b42

File tree

1 file changed

+117
-5
lines changed

1 file changed

+117
-5
lines changed

src/commands/install.cr

Lines changed: 117 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
module Geode::Commands
22
class Install < Base
3+
private TARGET = {{ flag?(:win32) ? "windows" : "linux" }}
4+
35
def setup : Nil
46
@name = "install"
57
@summary = "installs dependencies from shard.yml"
@@ -8,23 +10,23 @@ module Geode::Commands
810
unless you include the '--production' flag.
911
DESC
1012

11-
add_usage "install [-D|--no-development] [-e|--executable] [--frozen] [--production] [--verbose]"
12-
add_option 'D', "no-development"
13-
add_option 'e', "executable"
13+
add_usage "install [-D|--without-development] [--frozen] [--production] [-S|--skip-postinstall]"
14+
add_option 'D', "without-development"
1415
add_option "frozen"
1516
add_option "production"
17+
add_option 'S', "skip-postinstall"
1618
end
1719

1820
def pre_run(arguments : Cling::Arguments, options : Cling::Options) : Nil
1921
super arguments, options
2022

21-
nodev = options.has? "no-development"
23+
nodev = options.has? "without-development"
2224
frozen = options.has? "frozen"
2325
production = options.has? "production"
2426
return unless (nodev || frozen) && production
2527

2628
flags = [] of String
27-
flags << "no-development" if nodev
29+
flags << "without-development" if nodev
2830
flags << "frozen" if frozen
2931

3032
warn [
@@ -35,6 +37,116 @@ module Geode::Commands
3537
end
3638

3739
def run(arguments : Cling::Arguments, options : Cling::Options) : Nil
40+
unless File.exists? "shard.yml"
41+
error ["A shard.yml file was not found", "Run 'geode init' to initialize one"]
42+
system_exit
43+
end
44+
45+
shards = Process.find_executable "shards"
46+
unless shards
47+
error [
48+
"Could not find the Shards executable",
49+
"(wrapped around for dependency resolution)",
50+
]
51+
system_exit
52+
end
53+
54+
args = %w[install --skip-postinstall]
55+
args << "--frozen" if options.has? "frozen"
56+
args << "--no-color" if options.has? "no-color"
57+
args << "--without-development" if options.has? "without-development"
58+
args << "--production" if options.has? "production"
59+
60+
start = Time.monotonic
61+
deps = [] of String
62+
63+
Process.run(shards, args) do |proc|
64+
while message = proc.output.gets
65+
if message.includes? "Using"
66+
deps << message.split(' ', 3)[1]
67+
end
68+
stdout.puts message
69+
end
70+
stdout.puts
71+
end
72+
73+
if $?.success?
74+
if deps.empty? || options.has? "skip-postinstall"
75+
success "Install completed in #{format_time(Time.monotonic - start)}"
76+
return
77+
end
78+
else
79+
error "Install failed (#{format_time(Time.monotonic - start)})"
80+
system_exit
81+
end
82+
83+
shards = [] of Shard
84+
Dir.each_child("lib") do |child|
85+
next if child.starts_with? '.'
86+
next unless File.exists?(path = Path["lib"] / child / "shard.yml")
87+
88+
shard = Shard.from_yaml File.read path
89+
if shard.scripts.keys.any? &.starts_with? "postinstall"
90+
shards << shard
91+
end
92+
rescue YAML::ParseException
93+
warn "Failed to parse shard.yml contents for '#{child}'"
94+
end
95+
96+
shards.each do |shard|
97+
if shard.scripts.keys.any? &.starts_with? "postinstall@"
98+
if script = shard.scripts["postinstall@#{Geode::HOST_TRIPLE}"]?
99+
run_postinstall shard.name, Geode::HOST_TRIPLE, script
100+
elsif script = shard.scripts["postinstall@#{TARGET}"]?
101+
run_postinstall shard.name, TARGET, script
102+
elsif script = shard.scripts["postinstall"]?
103+
run_postinstall shard.name, nil, script
104+
else
105+
warn "No postinstall script available for this target"
106+
end
107+
else
108+
run_postinstall shard.name, nil, shard.scripts["postinstall"]
109+
end
110+
end
111+
112+
success "Install completed in #{format_time(Time.monotonic - start)}"
113+
end
114+
115+
private def run_postinstall(name : String, target : String?, script : String) : Nil
116+
stdout << "» Running " << name << " postinstall"
117+
if target
118+
stdout << " (" << target << "):\n"
119+
elsif script.lines.size > 1
120+
stdout << ":\n"
121+
else
122+
stdout << ": "
123+
end
124+
stdout << script.colorize.light_gray << "\n\n"
125+
126+
status : Process::Status
127+
taken : String
128+
start = Time.monotonic
129+
130+
{% begin %}
131+
{% if flag?(:win32) %}begin{% end %}
132+
status = Process.run(script, shell: true, chdir: Path["lib"] / name, output: stdout, error: stderr)
133+
taken = format_time(Time.monotonic - start)
134+
{% if flag?(:win32) %}
135+
rescue ex : File::NotFoundError
136+
error [
137+
"Failed to start process for script:",
138+
ex.to_s,
139+
]
140+
return
141+
end
142+
{% end %}
143+
{% end %}
144+
145+
if status.success?
146+
success "Script completed in #{taken}"
147+
else
148+
error "Script '#{name}' failed (#{taken})"
149+
end
38150
end
39151
end
40152
end

0 commit comments

Comments
 (0)