11module 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
40152end
0 commit comments