squared 0.0.10 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/README.ruby.md +98 -26
 - data/lib/squared/app.rb +10 -0
 - data/lib/squared/common/base.rb +12 -16
 - data/lib/squared/common/class.rb +26 -1
 - data/lib/squared/common/format.rb +79 -24
 - data/lib/squared/common/prompt.rb +36 -0
 - data/lib/squared/common/shell.rb +4 -3
 - data/lib/squared/common/system.rb +15 -47
 - data/lib/squared/common/utils.rb +51 -16
 - data/lib/squared/common.rb +1 -4
 - data/lib/squared/config.rb +48 -43
 - data/lib/squared/version.rb +1 -1
 - data/lib/squared/workspace/application.rb +245 -125
 - data/lib/squared/workspace/project/base.rb +448 -188
 - data/lib/squared/workspace/project/git.rb +97 -113
 - data/lib/squared/workspace/project/node.rb +217 -109
 - data/lib/squared/workspace/project/python.rb +37 -34
 - data/lib/squared/workspace/project/ruby.rb +137 -100
 - data/lib/squared/workspace/project.rb +0 -3
 - data/lib/squared/workspace/repo.rb +32 -18
 - data/lib/squared/workspace/series.rb +82 -53
 - data/lib/squared/workspace.rb +6 -5
 - data/lib/squared.rb +1 -11
 - metadata +4 -3
 - data/lib/squared/common/task.rb +0 -24
 
| 
         @@ -8,21 +8,22 @@ module Squared 
     | 
|
| 
       8 
8 
     | 
    
         
             
              module Workspace
         
     | 
| 
       9 
9 
     | 
    
         
             
                module Project
         
     | 
| 
       10 
10 
     | 
    
         
             
                  class Base
         
     | 
| 
       11 
     | 
    
         
            -
                    include Common
         
     | 
| 
       12 
     | 
    
         
            -
                    include Format
         
     | 
| 
      
 11 
     | 
    
         
            +
                    include Common::Format
         
     | 
| 
       13 
12 
     | 
    
         
             
                    include System
         
     | 
| 
       14 
13 
     | 
    
         
             
                    include Shell
         
     | 
| 
       15 
     | 
    
         
            -
                    include Task
         
     | 
| 
       16 
14 
     | 
    
         
             
                    include Utils
         
     | 
| 
       17 
15 
     | 
    
         
             
                    include ::Rake::DSL
         
     | 
| 
       18 
16 
     | 
    
         | 
| 
       19 
17 
     | 
    
         
             
                    SEM_VER = /(\d+)(?:(\.)(\d+))?(?:(\.)(\d+)(\S+)?)?/.freeze
         
     | 
| 
       20 
18 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
                    VAR_SET = %i[parent global envname theme run script env depend doc test copy clean].freeze
         
     | 
| 
      
 19 
     | 
    
         
            +
                    VAR_SET = %i[parent global envname dependfile theme run script env depend graph doc test copy clean].freeze
         
     | 
| 
       22 
20 
     | 
    
         
             
                    private_constant :VAR_SET
         
     | 
| 
       23 
21 
     | 
    
         | 
| 
       24 
22 
     | 
    
         
             
                    class << self
         
     | 
| 
       25 
23 
     | 
    
         
             
                      def populate(*); end
         
     | 
| 
      
 24 
     | 
    
         
            +
                      def batchargs(*); end
         
     | 
| 
      
 25 
     | 
    
         
            +
                      def aliasargs(*); end
         
     | 
| 
      
 26 
     | 
    
         
            +
                      def bannerargs(*); end
         
     | 
| 
       26 
27 
     | 
    
         | 
| 
       27 
28 
     | 
    
         
             
                      def tasks
         
     | 
| 
       28 
29 
     | 
    
         
             
                        [].freeze
         
     | 
| 
         @@ -42,32 +43,39 @@ module Squared 
     | 
|
| 
       42 
43 
     | 
    
         
             
                      end
         
     | 
| 
       43 
44 
     | 
    
         | 
| 
       44 
45 
     | 
    
         
             
                      def to_s
         
     | 
| 
       45 
     | 
    
         
            -
                        super. 
     | 
| 
      
 46 
     | 
    
         
            +
                        super.match(/[^:]+$/)[0]
         
     | 
| 
      
 47 
     | 
    
         
            +
                      end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                      def config?(*)
         
     | 
| 
      
 50 
     | 
    
         
            +
                        false
         
     | 
| 
       46 
51 
     | 
    
         
             
                      end
         
     | 
| 
       47 
52 
     | 
    
         
             
                    end
         
     | 
| 
       48 
53 
     | 
    
         | 
| 
      
 54 
     | 
    
         
            +
                    @@tasks = {
         
     | 
| 
      
 55 
     | 
    
         
            +
                      "#{ref}": {
         
     | 
| 
      
 56 
     | 
    
         
            +
                        graph: %i[run print].freeze
         
     | 
| 
      
 57 
     | 
    
         
            +
                      }.freeze
         
     | 
| 
      
 58 
     | 
    
         
            +
                    }
         
     | 
| 
       49 
59 
     | 
    
         
             
                    @@print_order = 0
         
     | 
| 
       50 
     | 
    
         
            -
                    @@tasks = {}
         
     | 
| 
       51 
60 
     | 
    
         | 
| 
       52 
     | 
    
         
            -
                    attr_reader :name, :project, :workspace, : 
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
      
 61 
     | 
    
         
            +
                    attr_reader :name, :project, :workspace, :path, :exception, :pipe, :theme, :group, :parent,
         
     | 
| 
      
 62 
     | 
    
         
            +
                                :dependfile, :verbose
         
     | 
| 
       54 
63 
     | 
    
         | 
| 
       55 
     | 
    
         
            -
                    def initialize( 
     | 
| 
       56 
     | 
    
         
            -
                                    
     | 
| 
       57 
     | 
    
         
            -
                                   common: Common::KEY[:COMMON], pipe: Common::KEY[:PIPE], **kwargs)
         
     | 
| 
       58 
     | 
    
         
            -
                      @name = name.to_s
         
     | 
| 
      
 64 
     | 
    
         
            +
                    def initialize(workspace, path, name, *, group: nil, graph: nil, pass: nil, exclude: nil,
         
     | 
| 
      
 65 
     | 
    
         
            +
                                   common: ARG[:COMMON], **kwargs)
         
     | 
| 
       59 
66 
     | 
    
         
             
                      @path = path
         
     | 
| 
       60 
     | 
    
         
            -
                      @project = @path.basename.to_s
         
     | 
| 
       61 
67 
     | 
    
         
             
                      @workspace = workspace
         
     | 
| 
       62 
     | 
    
         
            -
                      @ 
     | 
| 
      
 68 
     | 
    
         
            +
                      @name = name.to_s.freeze
         
     | 
| 
      
 69 
     | 
    
         
            +
                      @project = @path.basename.to_s.freeze
         
     | 
| 
      
 70 
     | 
    
         
            +
                      @group = group&.to_s.freeze
         
     | 
| 
       63 
71 
     | 
    
         
             
                      @depend = kwargs[:depend]
         
     | 
| 
       64 
72 
     | 
    
         
             
                      @doc = kwargs[:doc]
         
     | 
| 
       65 
73 
     | 
    
         
             
                      @test = kwargs[:test]
         
     | 
| 
       66 
74 
     | 
    
         
             
                      @copy = kwargs[:copy]
         
     | 
| 
       67 
75 
     | 
    
         
             
                      @clean = kwargs[:clean]
         
     | 
| 
       68 
     | 
    
         
            -
                      @exception = workspace.exception
         
     | 
| 
       69 
     | 
    
         
            -
                      @pipe = env_pipe(pipe 
     | 
| 
       70 
     | 
    
         
            -
                      @verbose =  
     | 
| 
      
 76 
     | 
    
         
            +
                      @exception = kwargs.key?(:exception) ? env_bool(kwargs[:exception]) : workspace.exception
         
     | 
| 
      
 77 
     | 
    
         
            +
                      @pipe = kwargs.key?(:pipe) ? env_pipe(kwargs[:pipe]) : workspace.pipe
         
     | 
| 
      
 78 
     | 
    
         
            +
                      @verbose = kwargs.key?(:verbose) ? kwargs[:verbose] : workspace.verbose
         
     | 
| 
       71 
79 
     | 
    
         
             
                      @theme = if !@verbose
         
     | 
| 
       72 
80 
     | 
    
         
             
                                 {}
         
     | 
| 
       73 
81 
     | 
    
         
             
                               elsif common
         
     | 
| 
         @@ -78,12 +86,16 @@ module Squared 
     | 
|
| 
       78 
86 
     | 
    
         
             
                      @output = []
         
     | 
| 
       79 
87 
     | 
    
         
             
                      @ref = []
         
     | 
| 
       80 
88 
     | 
    
         
             
                      @children = []
         
     | 
| 
      
 89 
     | 
    
         
            +
                      @graph = if graph
         
     | 
| 
      
 90 
     | 
    
         
            +
                                 as_a(graph, workspace.prefix ? ->(val) { workspace.task_name(val).to_sym } : :to_sym).freeze
         
     | 
| 
      
 91 
     | 
    
         
            +
                               end
         
     | 
| 
       81 
92 
     | 
    
         
             
                      @pass = (pass ? as_a(pass, :to_sym) : []).freeze
         
     | 
| 
       82 
93 
     | 
    
         
             
                      @exclude = (exclude ? as_a(exclude, :to_sym) : []).freeze
         
     | 
| 
       83 
     | 
    
         
            -
                      @envname = @name.gsub(/[^\w]+/, '_').upcase
         
     | 
| 
       84 
     | 
    
         
            -
                      @desc = @name.split(':').join( 
     | 
| 
      
 94 
     | 
    
         
            +
                      @envname = @name.gsub(/[^\w]+/, '_').upcase.freeze
         
     | 
| 
      
 95 
     | 
    
         
            +
                      @desc = (@name.include?(':') ? @name.split(':').join(ARG[:SPACE]) : @name).freeze
         
     | 
| 
      
 96 
     | 
    
         
            +
                      @parent = nil
         
     | 
| 
       85 
97 
     | 
    
         
             
                      @global = false
         
     | 
| 
       86 
     | 
    
         
            -
                      run_set 
     | 
| 
      
 98 
     | 
    
         
            +
                      run_set(kwargs[:run], kwargs[:env], opts: kwargs.fetch(:opts, true))
         
     | 
| 
       87 
99 
     | 
    
         
             
                      initialize_ref(Base.ref)
         
     | 
| 
       88 
100 
     | 
    
         
             
                    end
         
     | 
| 
       89 
101 
     | 
    
         | 
| 
         @@ -93,7 +105,7 @@ module Squared 
     | 
|
| 
       93 
105 
     | 
    
         | 
| 
       94 
106 
     | 
    
         
             
                    def initialize_build(ref, **kwargs)
         
     | 
| 
       95 
107 
     | 
    
         
             
                      initialize_ref(ref)
         
     | 
| 
       96 
     | 
    
         
            -
                      if (@script = @workspace. 
     | 
| 
      
 108 
     | 
    
         
            +
                      if (@script = @workspace.script_get(group: @group, ref: ref))
         
     | 
| 
       97 
109 
     | 
    
         
             
                        if @script[:log] && !kwargs.key?(:log)
         
     | 
| 
       98 
110 
     | 
    
         
             
                          kwargs[:log] = @script[:log]
         
     | 
| 
       99 
111 
     | 
    
         
             
                          @log = nil
         
     | 
| 
         @@ -107,7 +119,7 @@ module Squared 
     | 
|
| 
       107 
119 
     | 
    
         
             
                      initialize_logger(**kwargs)
         
     | 
| 
       108 
120 
     | 
    
         
             
                      return if @output[0] == false
         
     | 
| 
       109 
121 
     | 
    
         | 
| 
       110 
     | 
    
         
            -
                      data = @workspace. 
     | 
| 
      
 122 
     | 
    
         
            +
                      data = @workspace.script_find(*@ref, @group)
         
     | 
| 
       111 
123 
     | 
    
         
             
                      if @output[0].nil?
         
     | 
| 
       112 
124 
     | 
    
         
             
                        if (scr = data[:script])
         
     | 
| 
       113 
125 
     | 
    
         
             
                          @global = true
         
     | 
| 
         @@ -140,8 +152,8 @@ module Squared 
     | 
|
| 
       140 
152 
     | 
    
         
             
                      return if @log
         
     | 
| 
       141 
153 
     | 
    
         | 
| 
       142 
154 
     | 
    
         
             
                      log = log.is_a?(::Hash) ? log.dup : { file: log }
         
     | 
| 
       143 
     | 
    
         
            -
                       
     | 
| 
       144 
     | 
    
         
            -
                        file = case  
     | 
| 
      
 155 
     | 
    
         
            +
                      unless (file = env('LOG_FILE'))
         
     | 
| 
      
 156 
     | 
    
         
            +
                        file = case env('LOG_AUTO')
         
     | 
| 
       145 
157 
     | 
    
         
             
                               when 'y', 'year'
         
     | 
| 
       146 
158 
     | 
    
         
             
                                 "#{@name}-#{Date.today.year}.log"
         
     | 
| 
       147 
159 
     | 
    
         
             
                               when 'm', 'month'
         
     | 
| 
         @@ -152,7 +164,7 @@ module Squared 
     | 
|
| 
       152 
164 
     | 
    
         
             
                      end
         
     | 
| 
       153 
165 
     | 
    
         
             
                      if file ||= log[:file]
         
     | 
| 
       154 
166 
     | 
    
         
             
                        file = Date.today.strftime(file)
         
     | 
| 
       155 
     | 
    
         
            -
                        file = (dir = env('LOG_DIR')) ?  
     | 
| 
      
 167 
     | 
    
         
            +
                        file = (dir = env('LOG_DIR')) ? @workspace.home.join(dir, file) : @workspace.home.join(file)
         
     | 
| 
       156 
168 
     | 
    
         
             
                        begin
         
     | 
| 
       157 
169 
     | 
    
         
             
                          file = file.realdirpath
         
     | 
| 
       158 
170 
     | 
    
         
             
                        rescue StandardError => e
         
     | 
| 
         @@ -163,7 +175,7 @@ module Squared 
     | 
|
| 
       163 
175 
     | 
    
         
             
                        end
         
     | 
| 
       164 
176 
     | 
    
         
             
                      end
         
     | 
| 
       165 
177 
     | 
    
         
             
                      log[:progname] ||= @name
         
     | 
| 
       166 
     | 
    
         
            -
                      if (val = env('LOG_LEVEL', ignore:  
     | 
| 
      
 178 
     | 
    
         
            +
                      if (val = env('LOG_LEVEL', ignore: false))
         
     | 
| 
       167 
179 
     | 
    
         
             
                        log[:level] = val
         
     | 
| 
       168 
180 
     | 
    
         
             
                      end
         
     | 
| 
       169 
181 
     | 
    
         
             
                      log.delete(:file)
         
     | 
| 
         @@ -171,10 +183,14 @@ module Squared 
     | 
|
| 
       171 
183 
     | 
    
         
             
                    end
         
     | 
| 
       172 
184 
     | 
    
         | 
| 
       173 
185 
     | 
    
         
             
                    def initialize_env(dev: nil, prod: nil, **)
         
     | 
| 
       174 
     | 
    
         
            -
                       
     | 
| 
       175 
     | 
    
         
            -
                      @dev = env_match("#{ 
     | 
| 
       176 
     | 
    
         
            -
                      @prod = env_match("#{ 
     | 
| 
       177 
     | 
    
         
            -
                       
     | 
| 
      
 186 
     | 
    
         
            +
                      pre = "BUILD_#{@envname}"
         
     | 
| 
      
 187 
     | 
    
         
            +
                      @dev = env_match("#{pre}_DEV", dev)
         
     | 
| 
      
 188 
     | 
    
         
            +
                      @prod = env_match("#{pre}_PROD", prod)
         
     | 
| 
      
 189 
     | 
    
         
            +
                      cmd = @output[0]
         
     | 
| 
      
 190 
     | 
    
         
            +
                      unless cmd == false || cmd.is_a?(::Array) || (val = env('BUILD', suffix: 'OPTS')).nil?
         
     | 
| 
      
 191 
     | 
    
         
            +
                        @output[cmd ? 1 : 3] = shell_split(val, join: true)
         
     | 
| 
      
 192 
     | 
    
         
            +
                      end
         
     | 
| 
      
 193 
     | 
    
         
            +
                      unless @output[2] == false || (val = env('BUILD', suffix: 'ENV')).nil?
         
     | 
| 
       178 
194 
     | 
    
         
             
                        begin
         
     | 
| 
       179 
195 
     | 
    
         
             
                          data = JSON.parse(val)
         
     | 
| 
       180 
196 
     | 
    
         
             
                          raise_error('invalid JSON object', val, hint: "#{prefix}_ENV") unless data.is_a?(::Hash)
         
     | 
| 
         @@ -186,10 +202,12 @@ module Squared 
     | 
|
| 
       186 
202 
     | 
    
         
             
                      return unless (val = env('BUILD', strict: true))
         
     | 
| 
       187 
203 
     | 
    
         | 
| 
       188 
204 
     | 
    
         
             
                      @global = false
         
     | 
| 
       189 
     | 
    
         
            -
                      if  
     | 
| 
      
 205 
     | 
    
         
            +
                      if val == '0'
         
     | 
| 
      
 206 
     | 
    
         
            +
                        @output = [false]
         
     | 
| 
      
 207 
     | 
    
         
            +
                      elsif script?
         
     | 
| 
       190 
208 
     | 
    
         
             
                        script_set val
         
     | 
| 
       191 
209 
     | 
    
         
             
                      else
         
     | 
| 
       192 
     | 
    
         
            -
                        run_set 
     | 
| 
      
 210 
     | 
    
         
            +
                        run_set val
         
     | 
| 
       193 
211 
     | 
    
         
             
                      end
         
     | 
| 
       194 
212 
     | 
    
         
             
                    end
         
     | 
| 
       195 
213 
     | 
    
         | 
| 
         @@ -198,36 +216,90 @@ module Squared 
     | 
|
| 
       198 
216 
     | 
    
         
             
                    end
         
     | 
| 
       199 
217 
     | 
    
         | 
| 
       200 
218 
     | 
    
         
             
                    def populate(*)
         
     | 
| 
       201 
     | 
    
         
            -
                      check = lambda do |proj, key|
         
     | 
| 
       202 
     | 
    
         
            -
                        workspace.series.include?(key) ? proj.has?(key, Base.ref) : workspace.task_extend?(proj, key)
         
     | 
| 
       203 
     | 
    
         
            -
                      end
         
     | 
| 
       204 
     | 
    
         
            -
             
     | 
| 
       205 
219 
     | 
    
         
             
                      namespace name do
         
     | 
| 
       206 
220 
     | 
    
         
             
                        workspace.series.each_key do |key|
         
     | 
| 
       207 
     | 
    
         
            -
                          next unless  
     | 
| 
      
 221 
     | 
    
         
            +
                          next unless workspace.task_include?(self, key)
         
     | 
| 
       208 
222 
     | 
    
         | 
| 
       209 
     | 
    
         
            -
                           
     | 
| 
       210 
     | 
    
         
            -
             
     | 
| 
       211 
     | 
    
         
            -
                             
     | 
| 
      
 223 
     | 
    
         
            +
                          s = workspace.series.name_get(key)
         
     | 
| 
      
 224 
     | 
    
         
            +
                          unless workspace.task_defined?(name, s)
         
     | 
| 
      
 225 
     | 
    
         
            +
                            desc message(@desc, s)
         
     | 
| 
      
 226 
     | 
    
         
            +
                            task s do
         
     | 
| 
       212 
227 
     | 
    
         
             
                              __send__(key)
         
     | 
| 
       213 
228 
     | 
    
         
             
                            end
         
     | 
| 
       214 
229 
     | 
    
         
             
                          end
         
     | 
| 
       215 
     | 
    
         
            -
                          next if (items = @children.select { |item|  
     | 
| 
      
 230 
     | 
    
         
            +
                          next if (items = @children.select { |item| workspace.task_include?(item, key) }).empty?
         
     | 
| 
       216 
231 
     | 
    
         | 
| 
       217 
     | 
    
         
            -
                          desc message(@desc,  
     | 
| 
       218 
     | 
    
         
            -
                          task  
     | 
| 
      
 232 
     | 
    
         
            +
                          desc message(@desc, s, 'workspace')
         
     | 
| 
      
 233 
     | 
    
         
            +
                          task task_join(s, 'workspace') => items.map { |item| task_join(item.name, s) }
         
     | 
| 
      
 234 
     | 
    
         
            +
                        end
         
     | 
| 
      
 235 
     | 
    
         
            +
                        next unless ref?(Base.ref)
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
      
 237 
     | 
    
         
            +
                        @@tasks[Base.ref].each do |action, flags|
         
     | 
| 
      
 238 
     | 
    
         
            +
                          namespace action do
         
     | 
| 
      
 239 
     | 
    
         
            +
                            flags.each do |flag|
         
     | 
| 
      
 240 
     | 
    
         
            +
                              case action
         
     | 
| 
      
 241 
     | 
    
         
            +
                              when :graph
         
     | 
| 
      
 242 
     | 
    
         
            +
                                next unless graph?
         
     | 
| 
      
 243 
     | 
    
         
            +
             
     | 
| 
      
 244 
     | 
    
         
            +
                                if flag == :run
         
     | 
| 
      
 245 
     | 
    
         
            +
                                  desc format_desc(action, flag, 'pass*')
         
     | 
| 
      
 246 
     | 
    
         
            +
                                  task flag, [:pass] do |_, args|
         
     | 
| 
      
 247 
     | 
    
         
            +
                                    graph(pass: args.to_a)
         
     | 
| 
      
 248 
     | 
    
         
            +
                                  end
         
     | 
| 
      
 249 
     | 
    
         
            +
                                else
         
     | 
| 
      
 250 
     | 
    
         
            +
                                  desc format_desc(action, flag)
         
     | 
| 
      
 251 
     | 
    
         
            +
                                  task flag do
         
     | 
| 
      
 252 
     | 
    
         
            +
                                    out = graph(out: [])
         
     | 
| 
      
 253 
     | 
    
         
            +
                                    emphasize(out, title: path, right: true, border: borderstyle,
         
     | 
| 
      
 254 
     | 
    
         
            +
                                                   footer: "dependencies: #{out.size - 1}",
         
     | 
| 
      
 255 
     | 
    
         
            +
                                                   sub: [
         
     | 
| 
      
 256 
     | 
    
         
            +
                                                     { pat: /^(#{Regexp.escape(path.to_s)})(.*)$/, styles: theme[:header] },
         
     | 
| 
      
 257 
     | 
    
         
            +
                                                     { pat: /^(#{Regexp.escape(name)})(.*)$/, styles: theme[:active] },
         
     | 
| 
      
 258 
     | 
    
         
            +
                                                     { pat: /^(\s*)([a-z]+: )(\d+)$/, styles: theme[:inline], index: 3 }
         
     | 
| 
      
 259 
     | 
    
         
            +
                                                   ])
         
     | 
| 
      
 260 
     | 
    
         
            +
                                  end
         
     | 
| 
      
 261 
     | 
    
         
            +
                                end
         
     | 
| 
      
 262 
     | 
    
         
            +
                              end
         
     | 
| 
      
 263 
     | 
    
         
            +
                            end
         
     | 
| 
      
 264 
     | 
    
         
            +
                          end
         
     | 
| 
       219 
265 
     | 
    
         
             
                        end
         
     | 
| 
       220 
266 
     | 
    
         
             
                      end
         
     | 
| 
       221 
267 
     | 
    
         
             
                    end
         
     | 
| 
       222 
268 
     | 
    
         | 
| 
       223 
     | 
    
         
            -
                    def  
     | 
| 
       224 
     | 
    
         
            -
                       
     | 
| 
      
 269 
     | 
    
         
            +
                    def with(**kwargs, &blk)
         
     | 
| 
      
 270 
     | 
    
         
            +
                      @withargs = kwargs.empty? ? nil : kwargs
         
     | 
| 
      
 271 
     | 
    
         
            +
                      if block_given?
         
     | 
| 
      
 272 
     | 
    
         
            +
                        instance_eval(&blk)
         
     | 
| 
      
 273 
     | 
    
         
            +
                        @withargs = nil
         
     | 
| 
      
 274 
     | 
    
         
            +
                      end
         
     | 
| 
      
 275 
     | 
    
         
            +
                      self
         
     | 
| 
      
 276 
     | 
    
         
            +
                    end
         
     | 
| 
       225 
277 
     | 
    
         | 
| 
      
 278 
     | 
    
         
            +
                    def add(path, name = nil, **kwargs, &blk)
         
     | 
| 
      
 279 
     | 
    
         
            +
                      if path.is_a?(::String) && (data = %r{^(.+)[\\/]\*+$}.match(path))
         
     | 
| 
      
 280 
     | 
    
         
            +
                        path = basepath(data[1]).children.select(&:directory?)
         
     | 
| 
      
 281 
     | 
    
         
            +
                      end
         
     | 
| 
      
 282 
     | 
    
         
            +
                      if path.is_a?(::Array)
         
     | 
| 
      
 283 
     | 
    
         
            +
                        name = @name if name == true
         
     | 
| 
      
 284 
     | 
    
         
            +
                        path.each { |val| add(val, name && task_join(name, File.basename(val)), **kwargs, &blk) }
         
     | 
| 
      
 285 
     | 
    
         
            +
                        return self
         
     | 
| 
      
 286 
     | 
    
         
            +
                      elsif !projectpath?(path = basepath(path))
         
     | 
| 
      
 287 
     | 
    
         
            +
                        return self
         
     | 
| 
      
 288 
     | 
    
         
            +
                      elsif name.is_a?(::Symbol)
         
     | 
| 
      
 289 
     | 
    
         
            +
                        name = name.to_s
         
     | 
| 
      
 290 
     | 
    
         
            +
                      elsif !name.is_a?(::String)
         
     | 
| 
      
 291 
     | 
    
         
            +
                        name = nil
         
     | 
| 
      
 292 
     | 
    
         
            +
                      end
         
     | 
| 
      
 293 
     | 
    
         
            +
                      if @withargs
         
     | 
| 
      
 294 
     | 
    
         
            +
                        data = @withargs.dup
         
     | 
| 
      
 295 
     | 
    
         
            +
                        data.merge!(kwargs)
         
     | 
| 
      
 296 
     | 
    
         
            +
                        kwargs = data
         
     | 
| 
      
 297 
     | 
    
         
            +
                      end
         
     | 
| 
       226 
298 
     | 
    
         
             
                      kwargs[:group] = group unless kwargs.key?(:group)
         
     | 
| 
       227 
299 
     | 
    
         
             
                      kwargs[:ref] = ref unless kwargs.key?(:ref)
         
     | 
| 
       228 
300 
     | 
    
         
             
                      parent = self
         
     | 
| 
       229 
301 
     | 
    
         
             
                      proj = nil
         
     | 
| 
       230 
     | 
    
         
            -
                      workspace.add(path, name || path.basename 
     | 
| 
      
 302 
     | 
    
         
            +
                      workspace.add(path, name || path.basename, **kwargs) do
         
     | 
| 
       231 
303 
     | 
    
         
             
                        variable_set :parent, parent
         
     | 
| 
       232 
304 
     | 
    
         
             
                        proj = self
         
     | 
| 
       233 
305 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -236,54 +308,49 @@ module Squared 
     | 
|
| 
       236 
308 
     | 
    
         
             
                      self
         
     | 
| 
       237 
309 
     | 
    
         
             
                    end
         
     | 
| 
       238 
310 
     | 
    
         | 
| 
       239 
     | 
    
         
            -
                    def build(*args, sync:  
     | 
| 
      
 311 
     | 
    
         
            +
                    def build(*args, sync: invoked_sync?('build'), **)
         
     | 
| 
       240 
312 
     | 
    
         
             
                      if args.empty?
         
     | 
| 
       241 
     | 
    
         
            -
                        cmd, opts, var = @output
         
     | 
| 
       242 
     | 
    
         
            -
                         
     | 
| 
      
 313 
     | 
    
         
            +
                        cmd, opts, var, flags = @output
         
     | 
| 
      
 314 
     | 
    
         
            +
                        banner = verbose == 1
         
     | 
| 
       243 
315 
     | 
    
         
             
                      else
         
     | 
| 
       244 
316 
     | 
    
         
             
                        cmd = args.shift
         
     | 
| 
       245 
317 
     | 
    
         
             
                        opts = args.map { |val| shell_quote(val, force: false) }.join(' ')
         
     | 
| 
      
 318 
     | 
    
         
            +
                        banner = verbose
         
     | 
| 
       246 
319 
     | 
    
         
             
                      end
         
     | 
| 
       247 
320 
     | 
    
         
             
                      if cmd
         
     | 
| 
       248 
     | 
    
         
            -
                         
     | 
| 
      
 321 
     | 
    
         
            +
                        case opts
         
     | 
| 
      
 322 
     | 
    
         
            +
                        when ::String
         
     | 
| 
       249 
323 
     | 
    
         
             
                          cmd = "#{cmd} #{opts}"
         
     | 
| 
       250 
     | 
    
         
            -
                         
     | 
| 
      
 324 
     | 
    
         
            +
                        when ::Array
         
     | 
| 
       251 
325 
     | 
    
         
             
                          cmd = cmd.join(' && ')
         
     | 
| 
      
 326 
     | 
    
         
            +
                        else
         
     | 
| 
      
 327 
     | 
    
         
            +
                          cmd = [cmd, compose(opts, script: false)].compact.join(' ') unless opts == false || !respond_to?(:compose)
         
     | 
| 
       252 
328 
     | 
    
         
             
                        end
         
     | 
| 
       253 
     | 
    
         
            -
                        banner = verbose != false
         
     | 
| 
       254 
329 
     | 
    
         
             
                      else
         
     | 
| 
       255 
330 
     | 
    
         
             
                        return unless respond_to?(:compose)
         
     | 
| 
       256 
331 
     | 
    
         | 
| 
       257 
     | 
    
         
            -
                        cmd = compose(opts)
         
     | 
| 
       258 
     | 
    
         
            -
                        banner = verbose == 1
         
     | 
| 
      
 332 
     | 
    
         
            +
                        cmd = compose(opts, flags, script: true)
         
     | 
| 
       259 
333 
     | 
    
         
             
                      end
         
     | 
| 
       260 
334 
     | 
    
         
             
                      run(cmd, var, banner: banner, sync: sync)
         
     | 
| 
       261 
335 
     | 
    
         
             
                    end
         
     | 
| 
       262 
336 
     | 
    
         | 
| 
       263 
     | 
    
         
            -
                    def  
     | 
| 
       264 
     | 
    
         
            -
                       
     | 
| 
       265 
     | 
    
         
            -
                      return if run_task "#{name}:copy"
         
     | 
| 
       266 
     | 
    
         
            -
             
     | 
| 
       267 
     | 
    
         
            -
                      copy if copy?
         
     | 
| 
      
 337 
     | 
    
         
            +
                    def depend(*, sync: invoked_sync?('depend'), **)
         
     | 
| 
      
 338 
     | 
    
         
            +
                      run(@depend, sync: sync) if @depend
         
     | 
| 
       268 
339 
     | 
    
         
             
                    end
         
     | 
| 
       269 
340 
     | 
    
         | 
| 
       270 
     | 
    
         
            -
                    def  
     | 
| 
       271 
     | 
    
         
            -
                       
     | 
| 
      
 341 
     | 
    
         
            +
                    def copy(*, sync: invoked_sync?('copy'), **)
         
     | 
| 
      
 342 
     | 
    
         
            +
                      run_s(@copy, sync: sync) if @copy
         
     | 
| 
       272 
343 
     | 
    
         
             
                    end
         
     | 
| 
       273 
344 
     | 
    
         | 
| 
       274 
     | 
    
         
            -
                    def  
     | 
| 
       275 
     | 
    
         
            -
                       
     | 
| 
      
 345 
     | 
    
         
            +
                    def doc(*, sync: invoked_sync?('doc'), **)
         
     | 
| 
      
 346 
     | 
    
         
            +
                      build(@doc, sync: sync) if @doc
         
     | 
| 
       276 
347 
     | 
    
         
             
                    end
         
     | 
| 
       277 
348 
     | 
    
         | 
| 
       278 
     | 
    
         
            -
                    def  
     | 
| 
       279 
     | 
    
         
            -
                      build(@ 
     | 
| 
      
 349 
     | 
    
         
            +
                    def test(*, sync: invoked_sync?('test'), **)
         
     | 
| 
      
 350 
     | 
    
         
            +
                      build(@test, sync: sync) if @test
         
     | 
| 
       280 
351 
     | 
    
         
             
                    end
         
     | 
| 
       281 
352 
     | 
    
         | 
| 
       282 
     | 
    
         
            -
                    def  
     | 
| 
       283 
     | 
    
         
            -
                      build(@test, sync: invoked_sync?('test')) if @test
         
     | 
| 
       284 
     | 
    
         
            -
                    end
         
     | 
| 
       285 
     | 
    
         
            -
             
     | 
| 
       286 
     | 
    
         
            -
                    def clean
         
     | 
| 
      
 353 
     | 
    
         
            +
                    def clean(*)
         
     | 
| 
       287 
354 
     | 
    
         
             
                      case @clean
         
     | 
| 
       288 
355 
     | 
    
         
             
                      when ::String
         
     | 
| 
       289 
356 
     | 
    
         
             
                        run_s(@clean, sync: invoked_sync?('clean'))
         
     | 
| 
         @@ -291,13 +358,13 @@ module Squared 
     | 
|
| 
       291 
358 
     | 
    
         
             
                        as_a(@clean).each do |val|
         
     | 
| 
       292 
359 
     | 
    
         
             
                          if (val = val.to_s) =~ %r{[\\/]$}
         
     | 
| 
       293 
360 
     | 
    
         
             
                            dir = Pathname.new(val)
         
     | 
| 
       294 
     | 
    
         
            -
                            dir =  
     | 
| 
      
 361 
     | 
    
         
            +
                            dir = basepath(dir) unless dir.absolute?
         
     | 
| 
       295 
362 
     | 
    
         
             
                            next unless dir.directory?
         
     | 
| 
       296 
363 
     | 
    
         | 
| 
       297 
364 
     | 
    
         
             
                            log.warn "rm -rf #{dir}"
         
     | 
| 
       298 
365 
     | 
    
         
             
                            dir.rmtree(verbose: true)
         
     | 
| 
       299 
366 
     | 
    
         
             
                          else
         
     | 
| 
       300 
     | 
    
         
            -
                            files = val.include?('*') ? Dir[ 
     | 
| 
      
 367 
     | 
    
         
            +
                            files = val.include?('*') ? Dir[basepath(val)] : [basepath(val)]
         
     | 
| 
       301 
368 
     | 
    
         
             
                            files.each do |file|
         
     | 
| 
       302 
369 
     | 
    
         
             
                              begin
         
     | 
| 
       303 
370 
     | 
    
         
             
                                File.delete(file) if File.file?(file)
         
     | 
| 
         @@ -310,16 +377,29 @@ module Squared 
     | 
|
| 
       310 
377 
     | 
    
         
             
                      end
         
     | 
| 
       311 
378 
     | 
    
         
             
                    end
         
     | 
| 
       312 
379 
     | 
    
         | 
| 
      
 380 
     | 
    
         
            +
                    def graph(*, sync: invoked_sync?('graph'), pass: [], out: nil)
         
     | 
| 
      
 381 
     | 
    
         
            +
                      data = graph_collect(self)
         
     | 
| 
      
 382 
     | 
    
         
            +
                      data[name] << self unless out
         
     | 
| 
      
 383 
     | 
    
         
            +
                      run_graph(data, name, out, sync: sync, pass: pass)
         
     | 
| 
      
 384 
     | 
    
         
            +
                      out
         
     | 
| 
      
 385 
     | 
    
         
            +
                    end
         
     | 
| 
      
 386 
     | 
    
         
            +
             
     | 
| 
       313 
387 
     | 
    
         
             
                    def log
         
     | 
| 
       314 
     | 
    
         
            -
                       
     | 
| 
       315 
     | 
    
         
            -
             
     | 
| 
       316 
     | 
    
         
            -
                       
     | 
| 
       317 
     | 
    
         
            -
                        @log
         
     | 
| 
       318 
     | 
    
         
            -
                      end
         
     | 
| 
      
 388 
     | 
    
         
            +
                      return @log unless @log.is_a?(::Array)
         
     | 
| 
      
 389 
     | 
    
         
            +
             
     | 
| 
      
 390 
     | 
    
         
            +
                      @log = Logger.new(enabled? ? @log[0] : nil, **@log[1])
         
     | 
| 
       319 
391 
     | 
    
         
             
                    end
         
     | 
| 
       320 
392 
     | 
    
         | 
| 
       321 
     | 
    
         
            -
                    def  
     | 
| 
       322 
     | 
    
         
            -
                      path.join(*args)
         
     | 
| 
      
 393 
     | 
    
         
            +
                    def basepath(*args, ascend: nil)
         
     | 
| 
      
 394 
     | 
    
         
            +
                      ret = path.join(*args)
         
     | 
| 
      
 395 
     | 
    
         
            +
                      return ret unless ascend && !ret.exist?
         
     | 
| 
      
 396 
     | 
    
         
            +
             
     | 
| 
      
 397 
     | 
    
         
            +
                      path.parent.ascend.each do |dir|
         
     | 
| 
      
 398 
     | 
    
         
            +
                        target = dir.join(*args)
         
     | 
| 
      
 399 
     | 
    
         
            +
                        return target if target.exist?
         
     | 
| 
      
 400 
     | 
    
         
            +
                        break if (ascend.is_a?(String) && dir.join(ascend).exist?) || workspace.root == dir || parent&.path == dir
         
     | 
| 
      
 401 
     | 
    
         
            +
                      end
         
     | 
| 
      
 402 
     | 
    
         
            +
                      ret
         
     | 
| 
       323 
403 
     | 
    
         
             
                    end
         
     | 
| 
       324 
404 
     | 
    
         | 
| 
       325 
405 
     | 
    
         
             
                    def color(val)
         
     | 
| 
         @@ -328,26 +408,43 @@ module Squared 
     | 
|
| 
       328 
408 
     | 
    
         
             
                    end
         
     | 
| 
       329 
409 
     | 
    
         | 
| 
       330 
410 
     | 
    
         
             
                    def variable_set(key, *val, **kwargs)
         
     | 
| 
       331 
     | 
    
         
            -
                      if  
     | 
| 
      
 411 
     | 
    
         
            +
                      if variables.include?(key)
         
     | 
| 
       332 
412 
     | 
    
         
             
                        case key
         
     | 
| 
       333 
413 
     | 
    
         
             
                        when :run
         
     | 
| 
       334 
     | 
    
         
            -
                          run_set(*val,  
     | 
| 
      
 414 
     | 
    
         
            +
                          run_set(*val, **kwargs)
         
     | 
| 
       335 
415 
     | 
    
         
             
                        when :script
         
     | 
| 
       336 
416 
     | 
    
         
             
                          script_set(*val, **kwargs)
         
     | 
| 
       337 
417 
     | 
    
         
             
                        when :env
         
     | 
| 
       338 
     | 
    
         
            -
                          run_set(output[0], *val,  
     | 
| 
      
 418 
     | 
    
         
            +
                          run_set(output[0], *val, **kwargs)
         
     | 
| 
      
 419 
     | 
    
         
            +
                        when :parent
         
     | 
| 
      
 420 
     | 
    
         
            +
                          @parent = val if (val = val.first).is_a?(Project::Base)
         
     | 
| 
      
 421 
     | 
    
         
            +
                        when :graph
         
     | 
| 
      
 422 
     | 
    
         
            +
                          @graph = case val.first
         
     | 
| 
      
 423 
     | 
    
         
            +
                                   when nil, false
         
     | 
| 
      
 424 
     | 
    
         
            +
                                     nil
         
     | 
| 
      
 425 
     | 
    
         
            +
                                   else
         
     | 
| 
      
 426 
     | 
    
         
            +
                                     val.flatten.map!(&:to_s).freeze
         
     | 
| 
      
 427 
     | 
    
         
            +
                                   end
         
     | 
| 
      
 428 
     | 
    
         
            +
                        when :dependfile
         
     | 
| 
      
 429 
     | 
    
         
            +
                          @dependfile = basepath(*val)
         
     | 
| 
       339 
430 
     | 
    
         
             
                        else
         
     | 
| 
       340 
431 
     | 
    
         
             
                          instance_variable_set :"@#{key}", val.first
         
     | 
| 
       341 
432 
     | 
    
         
             
                        end
         
     | 
| 
       342 
433 
     | 
    
         
             
                      else
         
     | 
| 
       343 
     | 
    
         
            -
                        log.warn "variable_set: @#{key} ( 
     | 
| 
      
 434 
     | 
    
         
            +
                        log.warn "variable_set: @#{key} (private)"
         
     | 
| 
       344 
435 
     | 
    
         
             
                      end
         
     | 
| 
       345 
436 
     | 
    
         
             
                    end
         
     | 
| 
       346 
437 
     | 
    
         | 
| 
       347 
     | 
    
         
            -
                    def  
     | 
| 
       348 
     | 
    
         
            -
                       
     | 
| 
      
 438 
     | 
    
         
            +
                    def allref
         
     | 
| 
      
 439 
     | 
    
         
            +
                      @ref.reverse_each
         
     | 
| 
       349 
440 
     | 
    
         
             
                    end
         
     | 
| 
       350 
441 
     | 
    
         | 
| 
      
 442 
     | 
    
         
            +
                    def dependtype(*)
         
     | 
| 
      
 443 
     | 
    
         
            +
                      @dependindex ? @dependindex.succ : 0
         
     | 
| 
      
 444 
     | 
    
         
            +
                    end
         
     | 
| 
      
 445 
     | 
    
         
            +
             
     | 
| 
      
 446 
     | 
    
         
            +
                    def version(*); end
         
     | 
| 
      
 447 
     | 
    
         
            +
             
     | 
| 
       351 
448 
     | 
    
         
             
                    def inspect
         
     | 
| 
       352 
449 
     | 
    
         
             
                      "#<#{self.class}: #{name} => #{self}>"
         
     | 
| 
       353 
450 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -384,12 +481,16 @@ module Squared 
     | 
|
| 
       384 
481 
     | 
    
         
             
                      @output[0].nil? && !!@output[1] && respond_to?(:compose)
         
     | 
| 
       385 
482 
     | 
    
         
             
                    end
         
     | 
| 
       386 
483 
     | 
    
         | 
| 
       387 
     | 
    
         
            -
                    def  
     | 
| 
       388 
     | 
    
         
            -
                       
     | 
| 
      
 484 
     | 
    
         
            +
                    def depend?
         
     | 
| 
      
 485 
     | 
    
         
            +
                      !!@depend
         
     | 
| 
       389 
486 
     | 
    
         
             
                    end
         
     | 
| 
       390 
487 
     | 
    
         | 
| 
       391 
     | 
    
         
            -
                    def  
     | 
| 
       392 
     | 
    
         
            -
                      @ 
     | 
| 
      
 488 
     | 
    
         
            +
                    def graph?
         
     | 
| 
      
 489 
     | 
    
         
            +
                      @graph.is_a?(::Array) && !@graph.empty?
         
     | 
| 
      
 490 
     | 
    
         
            +
                    end
         
     | 
| 
      
 491 
     | 
    
         
            +
             
     | 
| 
      
 492 
     | 
    
         
            +
                    def copy?
         
     | 
| 
      
 493 
     | 
    
         
            +
                      runnable?(@copy) || workspace.task_defined?(name, 'copy')
         
     | 
| 
       393 
494 
     | 
    
         
             
                    end
         
     | 
| 
       394 
495 
     | 
    
         | 
| 
       395 
496 
     | 
    
         
             
                    def doc?
         
     | 
| 
         @@ -400,12 +501,8 @@ module Squared 
     | 
|
| 
       400 
501 
     | 
    
         
             
                      !!@test
         
     | 
| 
       401 
502 
     | 
    
         
             
                    end
         
     | 
| 
       402 
503 
     | 
    
         | 
| 
       403 
     | 
    
         
            -
                    def copy?
         
     | 
| 
       404 
     | 
    
         
            -
                      runnable?(@copy) || workspace.task_defined?("#{name}:copy")
         
     | 
| 
       405 
     | 
    
         
            -
                    end
         
     | 
| 
       406 
     | 
    
         
            -
             
     | 
| 
       407 
504 
     | 
    
         
             
                    def clean?
         
     | 
| 
       408 
     | 
    
         
            -
                      runnable?(@clean) || workspace.task_defined?( 
     | 
| 
      
 505 
     | 
    
         
            +
                      runnable?(@clean) || workspace.task_defined?(name, 'clean')
         
     | 
| 
       409 
506 
     | 
    
         
             
                    end
         
     | 
| 
       410 
507 
     | 
    
         | 
| 
       411 
508 
     | 
    
         
             
                    def dev?
         
     | 
| 
         @@ -418,18 +515,22 @@ module Squared 
     | 
|
| 
       418 
515 
     | 
    
         | 
| 
       419 
516 
     | 
    
         
             
                    private
         
     | 
| 
       420 
517 
     | 
    
         | 
| 
       421 
     | 
    
         
            -
                    def  
     | 
| 
       422 
     | 
    
         
            -
                       
     | 
| 
       423 
     | 
    
         
            -
             
     | 
| 
       424 
     | 
    
         
            -
             
     | 
| 
       425 
     | 
    
         
            -
             
     | 
| 
       426 
     | 
    
         
            -
                       
     | 
| 
      
 518 
     | 
    
         
            +
                    def variables
         
     | 
| 
      
 519 
     | 
    
         
            +
                      VAR_SET
         
     | 
| 
      
 520 
     | 
    
         
            +
                    end
         
     | 
| 
      
 521 
     | 
    
         
            +
             
     | 
| 
      
 522 
     | 
    
         
            +
                    def puts(*args)
         
     | 
| 
      
 523 
     | 
    
         
            +
                      puts_oe(*args, pipe: pipe)
         
     | 
| 
      
 524 
     | 
    
         
            +
                    end
         
     | 
| 
      
 525 
     | 
    
         
            +
             
     | 
| 
      
 526 
     | 
    
         
            +
                    def run(cmd = @session, var = nil, exception: @exception, sync: true, banner: true, **)
         
     | 
| 
      
 527 
     | 
    
         
            +
                      cmd = session_done(cmd)
         
     | 
| 
       427 
528 
     | 
    
         
             
                      log.info cmd
         
     | 
| 
       428 
529 
     | 
    
         
             
                      begin
         
     | 
| 
       429 
530 
     | 
    
         
             
                        if cmd =~ /^\S+:(\S+:?)+$/ && workspace.task_defined?(cmd)
         
     | 
| 
       430 
531 
     | 
    
         
             
                          print_item if sync
         
     | 
| 
       431 
532 
     | 
    
         
             
                          log.warn "ENV was discarded: #{var}" if var
         
     | 
| 
       432 
     | 
    
         
            -
                           
     | 
| 
      
 533 
     | 
    
         
            +
                          task_invoke(cmd, exception: exception, warning: warning?)
         
     | 
| 
       433 
534 
     | 
    
         
             
                        else
         
     | 
| 
       434 
535 
     | 
    
         
             
                          print_item format_banner(cmd, banner: banner) if sync
         
     | 
| 
       435 
536 
     | 
    
         
             
                          args = var.is_a?(::Hash) ? [var, cmd] : [cmd]
         
     | 
| 
         @@ -441,52 +542,114 @@ module Squared 
     | 
|
| 
       441 
542 
     | 
    
         
             
                      end
         
     | 
| 
       442 
543 
     | 
    
         
             
                    end
         
     | 
| 
       443 
544 
     | 
    
         | 
| 
       444 
     | 
    
         
            -
                    def run_s(cmd, **kwargs)
         
     | 
| 
       445 
     | 
    
         
            -
                       
     | 
| 
      
 545 
     | 
    
         
            +
                    def run_s(*cmd, env: nil, banner: verbose != false, **kwargs)
         
     | 
| 
      
 546 
     | 
    
         
            +
                      cmd.each { |val| run(val, env, banner: banner, **kwargs) }
         
     | 
| 
       446 
547 
     | 
    
         
             
                    end
         
     | 
| 
       447 
548 
     | 
    
         | 
| 
       448 
     | 
    
         
            -
                    def  
     | 
| 
       449 
     | 
    
         
            -
                       
     | 
| 
      
 549 
     | 
    
         
            +
                    def run_graph(data, start, out = nil, sync: true, pass: [], done: [], depth: 0, last: false)
         
     | 
| 
      
 550 
     | 
    
         
            +
                      check = ->(deps) { deps.reject { |val| done.include?(val) } }
         
     | 
| 
      
 551 
     | 
    
         
            +
                      items = check.(data[start])
         
     | 
| 
      
 552 
     | 
    
         
            +
                      if out
         
     | 
| 
      
 553 
     | 
    
         
            +
                        a, b, c, d, e = ARG[:GRAPH]
         
     | 
| 
      
 554 
     | 
    
         
            +
                        out << case depth
         
     | 
| 
      
 555 
     | 
    
         
            +
                               when 0
         
     | 
| 
      
 556 
     | 
    
         
            +
                                 start
         
     | 
| 
      
 557 
     | 
    
         
            +
                               when 1
         
     | 
| 
      
 558 
     | 
    
         
            +
                                 if items.empty?
         
     | 
| 
      
 559 
     | 
    
         
            +
                                   "#{d}#{b * 4} #{start}"
         
     | 
| 
      
 560 
     | 
    
         
            +
                                 else
         
     | 
| 
      
 561 
     | 
    
         
            +
                                   "#{last ? d : c}#{b * 3}#{e} #{start}"
         
     | 
| 
      
 562 
     | 
    
         
            +
                                 end
         
     | 
| 
      
 563 
     | 
    
         
            +
                               else
         
     | 
| 
      
 564 
     | 
    
         
            +
                                 "#{a}#{'   ' * (depth - 1)}#{d}#{b * 2}#{items.empty? ? b : e} #{start}"
         
     | 
| 
      
 565 
     | 
    
         
            +
                               end
         
     | 
| 
      
 566 
     | 
    
         
            +
                      end
         
     | 
| 
      
 567 
     | 
    
         
            +
                      items.each_with_index do |proj, i|
         
     | 
| 
      
 568 
     | 
    
         
            +
                        next if done.include?(proj)
         
     | 
| 
       450 
569 
     | 
    
         | 
| 
       451 
     | 
    
         
            -
             
     | 
| 
       452 
     | 
    
         
            -
             
     | 
| 
       453 
     | 
    
         
            -
             
     | 
| 
      
 570 
     | 
    
         
            +
                        j = out ? i == items.size - 1 || check.(items[i + 1..-1]).empty? : false
         
     | 
| 
      
 571 
     | 
    
         
            +
                        s = proj.name
         
     | 
| 
      
 572 
     | 
    
         
            +
                        unless start == s || (none = check.(data.fetch(s, [])).empty?)
         
     | 
| 
      
 573 
     | 
    
         
            +
                          run_graph(data, s, out, sync: sync, pass: pass, done: done, depth: depth.succ, last: j)
         
     | 
| 
      
 574 
     | 
    
         
            +
                        end
         
     | 
| 
      
 575 
     | 
    
         
            +
                        if !out
         
     | 
| 
      
 576 
     | 
    
         
            +
                          if (script = workspace.script_get(group: proj.group, ref: proj.ref))
         
     | 
| 
      
 577 
     | 
    
         
            +
                            tasks = script[:graph]
         
     | 
| 
      
 578 
     | 
    
         
            +
                          end
         
     | 
| 
      
 579 
     | 
    
         
            +
                          (tasks || (dev? ? %w[build copy] : %w[depend build])).each do |meth|
         
     | 
| 
      
 580 
     | 
    
         
            +
                            next if pass.include?(meth)
         
     | 
| 
       454 
581 
     | 
    
         | 
| 
       455 
     | 
    
         
            -
             
     | 
| 
       456 
     | 
    
         
            -
             
     | 
| 
       457 
     | 
    
         
            -
             
     | 
| 
       458 
     | 
    
         
            -
             
     | 
| 
       459 
     | 
    
         
            -
             
     | 
| 
       460 
     | 
    
         
            -
             
     | 
| 
       461 
     | 
    
         
            -
                         
     | 
| 
      
 582 
     | 
    
         
            +
                            if workspace.task_defined?(cmd = task_join(s, meth))
         
     | 
| 
      
 583 
     | 
    
         
            +
                              run(cmd, sync: false, banner: false)
         
     | 
| 
      
 584 
     | 
    
         
            +
                            elsif proj.has?(meth)
         
     | 
| 
      
 585 
     | 
    
         
            +
                              proj.__send__(meth.to_sym, sync: sync)
         
     | 
| 
      
 586 
     | 
    
         
            +
                            end
         
     | 
| 
      
 587 
     | 
    
         
            +
                          end
         
     | 
| 
      
 588 
     | 
    
         
            +
                        elsif none
         
     | 
| 
      
 589 
     | 
    
         
            +
                          a, b, c, d = ARG[:GRAPH]
         
     | 
| 
      
 590 
     | 
    
         
            +
                          out << if depth == 0
         
     | 
| 
      
 591 
     | 
    
         
            +
                                   "#{i == items.size - 1 ? d : c}#{b * 4} #{s}"
         
     | 
| 
      
 592 
     | 
    
         
            +
                                 else
         
     | 
| 
      
 593 
     | 
    
         
            +
                                   "#{last && depth == 1 ? ' ' : a}#{'   ' * depth}#{j ? d : c}#{b * 3} #{s}"
         
     | 
| 
      
 594 
     | 
    
         
            +
                                 end
         
     | 
| 
      
 595 
     | 
    
         
            +
                        end
         
     | 
| 
      
 596 
     | 
    
         
            +
                        done << proj
         
     | 
| 
       462 
597 
     | 
    
         
             
                      end
         
     | 
| 
       463 
     | 
    
         
            -
             
     | 
| 
       464 
     | 
    
         
            -
             
     | 
| 
      
 598 
     | 
    
         
            +
                    end
         
     | 
| 
      
 599 
     | 
    
         
            +
             
     | 
| 
      
 600 
     | 
    
         
            +
                    def graph_collect(target, data: {})
         
     | 
| 
      
 601 
     | 
    
         
            +
                      deps = []
         
     | 
| 
      
 602 
     | 
    
         
            +
                      target.instance_variable_get(:@graph)&.each do |val|
         
     | 
| 
      
 603 
     | 
    
         
            +
                        next unless (proj = workspace.find(name: val))
         
     | 
| 
       465 
604 
     | 
    
         | 
| 
       466 
     | 
    
         
            -
             
     | 
| 
      
 605 
     | 
    
         
            +
                        deps << proj
         
     | 
| 
      
 606 
     | 
    
         
            +
                        graph_collect(proj, data: data) if proj.graph? && !data.key?(proj.name)
         
     | 
| 
      
 607 
     | 
    
         
            +
                        deps += data.fetch(val, [])
         
     | 
| 
      
 608 
     | 
    
         
            +
                      end
         
     | 
| 
      
 609 
     | 
    
         
            +
                      data[target.name] = deps.uniq.reject { |proj| proj == target }
         
     | 
| 
      
 610 
     | 
    
         
            +
                      data
         
     | 
| 
       467 
611 
     | 
    
         
             
                    end
         
     | 
| 
       468 
612 
     | 
    
         | 
| 
       469 
     | 
    
         
            -
                    def  
     | 
| 
       470 
     | 
    
         
            -
                       
     | 
| 
      
 613 
     | 
    
         
            +
                    def env(key, default = nil, suffix: nil, equals: nil, ignore: nil, strict: false)
         
     | 
| 
      
 614 
     | 
    
         
            +
                      a = "#{key}_#{@envname}"
         
     | 
| 
      
 615 
     | 
    
         
            +
                      ret = if suffix
         
     | 
| 
      
 616 
     | 
    
         
            +
                              ENV.fetch("#{a}_#{suffix}", '')
         
     | 
| 
      
 617 
     | 
    
         
            +
                            else
         
     | 
| 
      
 618 
     | 
    
         
            +
                              ignore = ['0'].freeze if ignore.nil? && !strict
         
     | 
| 
      
 619 
     | 
    
         
            +
                              ENV[a] || (strict ? '' : ENV.fetch(key, ''))
         
     | 
| 
      
 620 
     | 
    
         
            +
                            end
         
     | 
| 
      
 621 
     | 
    
         
            +
                      return ret == equals.to_s unless equals.nil?
         
     | 
| 
      
 622 
     | 
    
         
            +
             
     | 
| 
      
 623 
     | 
    
         
            +
                      ret.empty? || (ignore && as_a(ignore).any? { |val| ret == val.to_s }) ? default : ret
         
     | 
| 
       471 
624 
     | 
    
         
             
                    end
         
     | 
| 
       472 
625 
     | 
    
         | 
| 
       473 
     | 
    
         
            -
                    def session(*cmd, prefix:  
     | 
| 
       474 
     | 
    
         
            -
                      if (val =  
     | 
| 
      
 626 
     | 
    
         
            +
                    def session(*cmd, prefix: cmd.first)
         
     | 
| 
      
 627 
     | 
    
         
            +
                      if (val = env("#{prefix.upcase}_OPTIONS"))
         
     | 
| 
       475 
628 
     | 
    
         
             
                        split_escape(val).each { |opt| cmd << fill_option(opt) }
         
     | 
| 
       476 
629 
     | 
    
         
             
                      end
         
     | 
| 
       477 
630 
     | 
    
         
             
                      @session = JoinSet.new(cmd)
         
     | 
| 
       478 
631 
     | 
    
         
             
                    end
         
     | 
| 
       479 
632 
     | 
    
         | 
| 
       480 
     | 
    
         
            -
                    def  
     | 
| 
       481 
     | 
    
         
            -
                      return cmd unless cmd.respond_to?(:done)
         
     | 
| 
      
 633 
     | 
    
         
            +
                    def session_done(cmd)
         
     | 
| 
      
 634 
     | 
    
         
            +
                      return cmd.to_s unless cmd.respond_to?(:done)
         
     | 
| 
       482 
635 
     | 
    
         | 
| 
       483 
636 
     | 
    
         
             
                      raise_error('no args were added', hint: cmd.first || name) unless cmd.size > 1
         
     | 
| 
       484 
637 
     | 
    
         
             
                      @session = nil if cmd == @session
         
     | 
| 
       485 
638 
     | 
    
         
             
                      cmd.done
         
     | 
| 
       486 
639 
     | 
    
         
             
                    end
         
     | 
| 
       487 
640 
     | 
    
         | 
| 
      
 641 
     | 
    
         
            +
                    def option(*args, prefix: @session&.first, **kwargs)
         
     | 
| 
      
 642 
     | 
    
         
            +
                      if prefix
         
     | 
| 
      
 643 
     | 
    
         
            +
                        args.each do |val|
         
     | 
| 
      
 644 
     | 
    
         
            +
                          ret = env("#{prefix}_#{val.gsub(/\W/, '_')}".upcase, **kwargs)
         
     | 
| 
      
 645 
     | 
    
         
            +
                          return ret if ret
         
     | 
| 
      
 646 
     | 
    
         
            +
                        end
         
     | 
| 
      
 647 
     | 
    
         
            +
                      end
         
     | 
| 
      
 648 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 649 
     | 
    
         
            +
                    end
         
     | 
| 
      
 650 
     | 
    
         
            +
             
     | 
| 
       488 
651 
     | 
    
         
             
                    def print_item(*val)
         
     | 
| 
       489 
     | 
    
         
            -
                      puts  
     | 
| 
      
 652 
     | 
    
         
            +
                      puts if @@print_order > 0 && verbose && !stdin?
         
     | 
| 
       490 
653 
     | 
    
         
             
                      @@print_order += 1
         
     | 
| 
       491 
654 
     | 
    
         
             
                      puts val unless val.empty? || (val.size == 1 && val.first.nil?)
         
     | 
| 
       492 
655 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -497,7 +660,7 @@ module Squared 
     | 
|
| 
       497 
660 
     | 
    
         
             
                        if styles.any? { |s| s.to_s.end_with?('!') }
         
     | 
| 
       498 
661 
     | 
    
         
             
                          pad = 1
         
     | 
| 
       499 
662 
     | 
    
         
             
                        elsif !client && styles.size <= 1
         
     | 
| 
       500 
     | 
    
         
            -
                          styles = [ 
     | 
| 
      
 663 
     | 
    
         
            +
                          styles = %i[bold] + styles
         
     | 
| 
       501 
664 
     | 
    
         
             
                        end
         
     | 
| 
       502 
665 
     | 
    
         
             
                      end
         
     | 
| 
       503 
666 
     | 
    
         
             
                      n = Project.max_width(lines)
         
     | 
| 
         @@ -516,33 +679,37 @@ module Squared 
     | 
|
| 
       516 
679 
     | 
    
         
             
                      out.join("\n")
         
     | 
| 
       517 
680 
     | 
    
         
             
                    end
         
     | 
| 
       518 
681 
     | 
    
         | 
| 
       519 
     | 
    
         
            -
                    def print_footer(*lines, sub: nil,  
     | 
| 
      
 682 
     | 
    
         
            +
                    def print_footer(*lines, sub: nil, reverse: false, right: false, **kwargs)
         
     | 
| 
      
 683 
     | 
    
         
            +
                      border = kwargs.key?(:border) ? kwargs[:border] : borderstyle
         
     | 
| 
       520 
684 
     | 
    
         
             
                      n = Project.max_width(lines)
         
     | 
| 
       521 
685 
     | 
    
         
             
                      sub = as_a(sub)
         
     | 
| 
       522 
686 
     | 
    
         
             
                      lines.map! do |val|
         
     | 
| 
       523 
     | 
    
         
            -
                        s = val.ljust(n)
         
     | 
| 
      
 687 
     | 
    
         
            +
                        s = right ? val.rjust(n) : val.ljust(n)
         
     | 
| 
       524 
688 
     | 
    
         
             
                        sub.each { |h| s = sub_style(s, **h) }
         
     | 
| 
       525 
689 
     | 
    
         
             
                        s
         
     | 
| 
       526 
690 
     | 
    
         
             
                      end
         
     | 
| 
       527 
     | 
    
         
            -
                      ret = [sub_style('-' * n, styles: border), *lines]
         
     | 
| 
      
 691 
     | 
    
         
            +
                      ret = [sub_style('-' * n, styles: border || theme[:border]), *lines]
         
     | 
| 
       528 
692 
     | 
    
         
             
                      ret.reverse! if reverse
         
     | 
| 
       529 
693 
     | 
    
         
             
                      ret.join("\n")
         
     | 
| 
       530 
694 
     | 
    
         
             
                    end
         
     | 
| 
       531 
695 
     | 
    
         | 
| 
       532 
     | 
    
         
            -
                    def format_desc(action, flag, opts = nil, req:  
     | 
| 
      
 696 
     | 
    
         
            +
                    def format_desc(action, flag, opts = nil, req: nil, arg: 'opts*')
         
     | 
| 
       533 
697 
     | 
    
         
             
                      opts = "#{arg}=#{opts.join(',')}" if opts.is_a?(::Array)
         
     | 
| 
       534 
     | 
    
         
            -
                       
     | 
| 
      
 698 
     | 
    
         
            +
                      out = [@desc]
         
     | 
| 
      
 699 
     | 
    
         
            +
                      if flag
         
     | 
| 
      
 700 
     | 
    
         
            +
                        out << action
         
     | 
| 
      
 701 
     | 
    
         
            +
                      else
         
     | 
| 
       535 
702 
     | 
    
         
             
                        flag = action
         
     | 
| 
       536 
     | 
    
         
            -
                        action = ''
         
     | 
| 
       537 
703 
     | 
    
         
             
                      end
         
     | 
| 
       538 
     | 
    
         
            -
                      req  
     | 
| 
       539 
     | 
    
         
            -
                       
     | 
| 
      
 704 
     | 
    
         
            +
                      req &&= opts ? "#{req}," : "[#{req}]"
         
     | 
| 
      
 705 
     | 
    
         
            +
                      out << (opts ? "#{flag}[#{req}#{opts}]" : "#{flag}#{req}")
         
     | 
| 
      
 706 
     | 
    
         
            +
                      message(*out)
         
     | 
| 
       540 
707 
     | 
    
         
             
                    end
         
     | 
| 
       541 
708 
     | 
    
         | 
| 
       542 
     | 
    
         
            -
                    def format_banner(cmd, banner: true 
     | 
| 
       543 
     | 
    
         
            -
                      return unless banner
         
     | 
| 
      
 709 
     | 
    
         
            +
                    def format_banner(cmd, banner: true)
         
     | 
| 
      
 710 
     | 
    
         
            +
                      return unless banner && ARG[:BANNER]
         
     | 
| 
       544 
711 
     | 
    
         | 
| 
       545 
     | 
    
         
            -
                      if (data = workspace. 
     | 
| 
      
 712 
     | 
    
         
            +
                      if (data = workspace.banner_get(*@ref, group: group))
         
     | 
| 
       546 
713 
     | 
    
         
             
                        client = true
         
     | 
| 
       547 
714 
     | 
    
         
             
                      else
         
     | 
| 
       548 
715 
     | 
    
         
             
                        data = { command: true, order: %i[path], styles: theme[:banner], border: theme[:border] }
         
     | 
| 
         @@ -550,13 +717,62 @@ module Squared 
     | 
|
| 
       550 
717 
     | 
    
         
             
                      if verbose
         
     | 
| 
       551 
718 
     | 
    
         
             
                        out = []
         
     | 
| 
       552 
719 
     | 
    
         
             
                        out << cmd.sub(/^\S+/, &:upcase) if data[:command]
         
     | 
| 
       553 
     | 
    
         
            -
                        data[:order].each  
     | 
| 
      
 720 
     | 
    
         
            +
                        data[:order].each do |val|
         
     | 
| 
      
 721 
     | 
    
         
            +
                          if val.is_a?(::Array)
         
     | 
| 
      
 722 
     | 
    
         
            +
                            s = ' '
         
     | 
| 
      
 723 
     | 
    
         
            +
                            found = false
         
     | 
| 
      
 724 
     | 
    
         
            +
                            val = val.map do |meth|
         
     | 
| 
      
 725 
     | 
    
         
            +
                              if meth.is_a?(::String)
         
     | 
| 
      
 726 
     | 
    
         
            +
                                s = ''
         
     | 
| 
      
 727 
     | 
    
         
            +
                                meth
         
     | 
| 
      
 728 
     | 
    
         
            +
                              elsif respond_to?(meth)
         
     | 
| 
      
 729 
     | 
    
         
            +
                                found = true
         
     | 
| 
      
 730 
     | 
    
         
            +
                                __send__(meth)
         
     | 
| 
      
 731 
     | 
    
         
            +
                              end
         
     | 
| 
      
 732 
     | 
    
         
            +
                            end
         
     | 
| 
      
 733 
     | 
    
         
            +
                            val = val.compact.join(s)
         
     | 
| 
      
 734 
     | 
    
         
            +
                            next unless found && !val.empty?
         
     | 
| 
      
 735 
     | 
    
         
            +
                          elsif (val = __send__(val)).nil?
         
     | 
| 
      
 736 
     | 
    
         
            +
                            next
         
     | 
| 
      
 737 
     | 
    
         
            +
                          end
         
     | 
| 
      
 738 
     | 
    
         
            +
                          out << val.to_s
         
     | 
| 
      
 739 
     | 
    
         
            +
                        end
         
     | 
| 
       554 
740 
     | 
    
         
             
                        print_banner(*out, styles: data[:styles], border: data[:border], client: client)
         
     | 
| 
       555 
741 
     | 
    
         
             
                      elsif multiple && workspace.series.multiple?
         
     | 
| 
       556 
742 
     | 
    
         
             
                        "## #{__send__(data[:order].first || :path)} ##"
         
     | 
| 
       557 
743 
     | 
    
         
             
                      end
         
     | 
| 
       558 
744 
     | 
    
         
             
                    end
         
     | 
| 
       559 
745 
     | 
    
         | 
| 
      
 746 
     | 
    
         
            +
                    def format_list(items, cmd, type, grep: [], from: nil, each: nil)
         
     | 
| 
      
 747 
     | 
    
         
            +
                      reg = grep.map { |val| Regexp.new(val) }
         
     | 
| 
      
 748 
     | 
    
         
            +
                      out = []
         
     | 
| 
      
 749 
     | 
    
         
            +
                      if (pad = items.size) > 0
         
     | 
| 
      
 750 
     | 
    
         
            +
                        pad = pad.to_s.size
         
     | 
| 
      
 751 
     | 
    
         
            +
                        items.each_with_index do |val, i|
         
     | 
| 
      
 752 
     | 
    
         
            +
                          next unless reg.empty? || reg.any? { |pat| pat.match?(val[0]) }
         
     | 
| 
      
 753 
     | 
    
         
            +
             
     | 
| 
      
 754 
     | 
    
         
            +
                          out << "#{(i + 1).to_s.rjust(pad)}. #{each ? each.(val) : val[0]}"
         
     | 
| 
      
 755 
     | 
    
         
            +
                        end
         
     | 
| 
      
 756 
     | 
    
         
            +
                      end
         
     | 
| 
      
 757 
     | 
    
         
            +
                      if out.empty?
         
     | 
| 
      
 758 
     | 
    
         
            +
                        out = ["No #{type} were found:", '']
         
     | 
| 
      
 759 
     | 
    
         
            +
                        unless grep.empty?
         
     | 
| 
      
 760 
     | 
    
         
            +
                          i = 0
         
     | 
| 
      
 761 
     | 
    
         
            +
                          out += grep.map { |s| "#{i += 1}. #{s}" }
         
     | 
| 
      
 762 
     | 
    
         
            +
                          out << ''
         
     | 
| 
      
 763 
     | 
    
         
            +
                        end
         
     | 
| 
      
 764 
     | 
    
         
            +
                        if from
         
     | 
| 
      
 765 
     | 
    
         
            +
                          out << from
         
     | 
| 
      
 766 
     | 
    
         
            +
                          pat = /^(#{Regexp.escape(out.last)})(.*)$/
         
     | 
| 
      
 767 
     | 
    
         
            +
                        end
         
     | 
| 
      
 768 
     | 
    
         
            +
                      else
         
     | 
| 
      
 769 
     | 
    
         
            +
                        pat = /^(\s*\d+\.)(.+)$/
         
     | 
| 
      
 770 
     | 
    
         
            +
                      end
         
     | 
| 
      
 771 
     | 
    
         
            +
                      sub = [headerstyle]
         
     | 
| 
      
 772 
     | 
    
         
            +
                      sub << { pat: pat, styles: theme[:active] } if pat
         
     | 
| 
      
 773 
     | 
    
         
            +
                      emphasize(out, title: task_join(name, cmd), border: borderstyle, sub: sub)
         
     | 
| 
      
 774 
     | 
    
         
            +
                    end
         
     | 
| 
      
 775 
     | 
    
         
            +
             
     | 
| 
       560 
776 
     | 
    
         
             
                    def empty_status(msg, title, obj, always: false)
         
     | 
| 
       561 
777 
     | 
    
         
             
                      "#{msg}#{!always && (!obj || obj == 0 || obj.to_s.empty?) ? '' : message(hint: message(title, obj.to_s))}"
         
     | 
| 
       562 
778 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -569,22 +785,22 @@ module Squared 
     | 
|
| 
       569 
785 
     | 
    
         
             
                      opts.each { |val| @session << val }
         
     | 
| 
       570 
786 
     | 
    
         
             
                    end
         
     | 
| 
       571 
787 
     | 
    
         | 
| 
       572 
     | 
    
         
            -
                    def append_nocolor
         
     | 
| 
       573 
     | 
    
         
            -
                      @session <<  
     | 
| 
      
 788 
     | 
    
         
            +
                    def append_nocolor(flag = nil)
         
     | 
| 
      
 789 
     | 
    
         
            +
                      @session << '--no-color' if flag || !ARG[:COLOR] || stdin?
         
     | 
| 
       574 
790 
     | 
    
         
             
                    end
         
     | 
| 
       575 
791 
     | 
    
         | 
| 
       576 
792 
     | 
    
         
             
                    def guard_params(action, flag, args: nil, key: nil, pat: nil)
         
     | 
| 
       577 
793 
     | 
    
         
             
                      if args && key
         
     | 
| 
       578 
     | 
    
         
            -
                         
     | 
| 
      
 794 
     | 
    
         
            +
                        val = args[key]
         
     | 
| 
      
 795 
     | 
    
         
            +
                        return val unless val.nil? || (pat && !val.match?(pat))
         
     | 
| 
       579 
796 
     | 
    
         | 
| 
       580 
797 
     | 
    
         
             
                        @session = nil
         
     | 
| 
       581 
798 
     | 
    
         
             
                        raise_error(action, "#{flag}[#{key}]", hint: val.nil? ? 'missing' : 'invalid')
         
     | 
| 
       582 
     | 
    
         
            -
                      elsif args.is_a?(::Array)
         
     | 
| 
       583 
     | 
    
         
            -
                        return unless args.empty?
         
     | 
| 
       584 
     | 
    
         
            -
             
     | 
| 
      
 799 
     | 
    
         
            +
                      elsif args.is_a?(::Array) && args.empty?
         
     | 
| 
       585 
800 
     | 
    
         
             
                        @session = nil
         
     | 
| 
       586 
     | 
    
         
            -
                        raise_error(action, "#{flag} 
     | 
| 
      
 801 
     | 
    
         
            +
                        raise_error(action, "#{flag}+", hint: 'empty')
         
     | 
| 
       587 
802 
     | 
    
         
             
                      end
         
     | 
| 
      
 803 
     | 
    
         
            +
                      args
         
     | 
| 
       588 
804 
     | 
    
         
             
                    end
         
     | 
| 
       589 
805 
     | 
    
         | 
| 
       590 
806 
     | 
    
         
             
                    def pwd_set(done = nil, &blk)
         
     | 
| 
         @@ -612,39 +828,27 @@ module Squared 
     | 
|
| 
       612 
828 
     | 
    
         
             
                      end
         
     | 
| 
       613 
829 
     | 
    
         
             
                    end
         
     | 
| 
       614 
830 
     | 
    
         | 
| 
       615 
     | 
    
         
            -
                    def  
     | 
| 
       616 
     | 
    
         
            -
                      unless  
     | 
| 
       617 
     | 
    
         
            -
                         
     | 
| 
       618 
     | 
    
         
            -
             
     | 
| 
      
 831 
     | 
    
         
            +
                    def run_set(cmd, val = nil, opts: nil, **)
         
     | 
| 
      
 832 
     | 
    
         
            +
                      unless @output[1] == false && !@output[0].nil?
         
     | 
| 
      
 833 
     | 
    
         
            +
                        if opts == false
         
     | 
| 
      
 834 
     | 
    
         
            +
                          @output[1] = false
         
     | 
| 
      
 835 
     | 
    
         
            +
                        elsif opts && opts != true
         
     | 
| 
      
 836 
     | 
    
         
            +
                          @output[1] = opts
         
     | 
| 
      
 837 
     | 
    
         
            +
                        end
         
     | 
| 
       619 
838 
     | 
    
         
             
                      end
         
     | 
| 
       620 
     | 
    
         
            -
                      unless  
     | 
| 
       621 
     | 
    
         
            -
                        val 
     | 
| 
       622 
     | 
    
         
            -
             
     | 
| 
      
 839 
     | 
    
         
            +
                      unless @output[2] == false
         
     | 
| 
      
 840 
     | 
    
         
            +
                        if val.is_a?(::Hash)
         
     | 
| 
      
 841 
     | 
    
         
            +
                          @output[2] = val
         
     | 
| 
      
 842 
     | 
    
         
            +
                        elsif val == false
         
     | 
| 
      
 843 
     | 
    
         
            +
                          @output[2] = false
         
     | 
| 
      
 844 
     | 
    
         
            +
                        end
         
     | 
| 
       623 
845 
     | 
    
         
             
                      end
         
     | 
| 
       624 
     | 
    
         
            -
                      val
         
     | 
| 
       625 
     | 
    
         
            -
                    end
         
     | 
| 
       626 
     | 
    
         
            -
             
     | 
| 
       627 
     | 
    
         
            -
                    def semmajor(cur, want)
         
     | 
| 
       628 
     | 
    
         
            -
                      (cur[0] == '0' && want[0] == '0' ? cur[2] != want[2] : cur[0] != want[0]) && !want[5]
         
     | 
| 
       629 
     | 
    
         
            -
                    end
         
     | 
| 
       630 
     | 
    
         
            -
             
     | 
| 
       631 
     | 
    
         
            -
                    def scriptargs
         
     | 
| 
       632 
     | 
    
         
            -
                      { target: script? ? @output[1] : @output[0], ref: ref, group: group, global: @global }
         
     | 
| 
       633 
     | 
    
         
            -
                    end
         
     | 
| 
       634 
     | 
    
         
            -
             
     | 
| 
       635 
     | 
    
         
            -
                    def run_set(cmd, val = nil, *, opts: true, **)
         
     | 
| 
       636 
846 
     | 
    
         
             
                      @output[0] = cmd
         
     | 
| 
       637 
     | 
    
         
            -
                      @output[1] = if cmd && opts
         
     | 
| 
       638 
     | 
    
         
            -
                                     env('BUILD', opts.is_a?(::String) ? opts : nil, suffix: 'OPTS')
         
     | 
| 
       639 
     | 
    
         
            -
                                   end
         
     | 
| 
       640 
     | 
    
         
            -
                      if val.is_a?(::Hash)
         
     | 
| 
       641 
     | 
    
         
            -
                        @output[2] = val
         
     | 
| 
       642 
     | 
    
         
            -
                      elsif val == false
         
     | 
| 
       643 
     | 
    
         
            -
                        @output[2] = nil
         
     | 
| 
       644 
     | 
    
         
            -
                      end
         
     | 
| 
       645 
847 
     | 
    
         
             
                    end
         
     | 
| 
       646 
848 
     | 
    
         | 
| 
       647 
     | 
    
         
            -
                    def script_set(cmd,  
     | 
| 
      
 849 
     | 
    
         
            +
                    def script_set(cmd, prod: nil, **)
         
     | 
| 
      
 850 
     | 
    
         
            +
                      return if @output[1] == false && @output[0].nil?
         
     | 
| 
      
 851 
     | 
    
         
            +
             
     | 
| 
       648 
852 
     | 
    
         
             
                      @output[0] = nil
         
     | 
| 
       649 
853 
     | 
    
         
             
                      @output[1] = if @global && cmd.is_a?(::Array)
         
     | 
| 
       650 
854 
     | 
    
         
             
                                     cmd[prod == true ? 1 : 0]
         
     | 
| 
         @@ -653,16 +857,12 @@ module Squared 
     | 
|
| 
       653 
857 
     | 
    
         
             
                                   end
         
     | 
| 
       654 
858 
     | 
    
         
             
                    end
         
     | 
| 
       655 
859 
     | 
    
         | 
| 
       656 
     | 
    
         
            -
                    def  
     | 
| 
       657 
     | 
    
         
            -
                      Pathname.new(val).absolute? ? val.to_s.start_with?(File.join(path, '')) : !val.to_s. 
     | 
| 
      
 860 
     | 
    
         
            +
                    def projectpath?(val)
         
     | 
| 
      
 861 
     | 
    
         
            +
                      Pathname.new(val).absolute? ? val.to_s.start_with?(File.join(path, '')) : !val.to_s.start_with?('..')
         
     | 
| 
       658 
862 
     | 
    
         
             
                    end
         
     | 
| 
       659 
863 
     | 
    
         | 
| 
       660 
     | 
    
         
            -
                    def  
     | 
| 
       661 
     | 
    
         
            -
                       
     | 
| 
       662 
     | 
    
         
            -
                    end
         
     | 
| 
       663 
     | 
    
         
            -
             
     | 
| 
       664 
     | 
    
         
            -
                    def stdin?
         
     | 
| 
       665 
     | 
    
         
            -
                      pipe == 0
         
     | 
| 
      
 864 
     | 
    
         
            +
                    def semmajor?(cur, want)
         
     | 
| 
      
 865 
     | 
    
         
            +
                      (cur[0] == '0' && want[0] == '0' ? cur[2] != want[2] : cur[0] != want[0]) && !want[5]
         
     | 
| 
       666 
866 
     | 
    
         
             
                    end
         
     | 
| 
       667 
867 
     | 
    
         | 
| 
       668 
868 
     | 
    
         
             
                    def runnable?(val)
         
     | 
| 
         @@ -676,23 +876,83 @@ module Squared 
     | 
|
| 
       676 
876 
     | 
    
         
             
                      end
         
     | 
| 
       677 
877 
     | 
    
         
             
                    end
         
     | 
| 
       678 
878 
     | 
    
         | 
| 
       679 
     | 
    
         
            -
                    def from_sync?(val)
         
     | 
| 
       680 
     | 
    
         
            -
                      if  
     | 
| 
       681 
     | 
    
         
            -
                        !workspace.task_defined?( 
     | 
| 
       682 
     | 
    
         
            -
                      elsif workspace.series.sync?( 
     | 
| 
      
 879 
     | 
    
         
            +
                    def from_sync?(*val)
         
     | 
| 
      
 880 
     | 
    
         
            +
                      if task_invoked?(key = task_join(*val))
         
     | 
| 
      
 881 
     | 
    
         
            +
                        !workspace.task_defined?(key, 'sync')
         
     | 
| 
      
 882 
     | 
    
         
            +
                      elsif workspace.series.sync?(task_join(key, 'sync'))
         
     | 
| 
       683 
883 
     | 
    
         
             
                        true
         
     | 
| 
       684 
884 
     | 
    
         
             
                      end
         
     | 
| 
       685 
885 
     | 
    
         
             
                    end
         
     | 
| 
       686 
886 
     | 
    
         | 
| 
       687 
887 
     | 
    
         
             
                    def invoked_sync?(action, val = nil)
         
     | 
| 
       688 
888 
     | 
    
         
             
                      return true if !val.nil? || from_sync?(ac = workspace.task_name(action))
         
     | 
| 
      
 889 
     | 
    
         
            +
                      return val if group && !(val = from_sync?(ac, group)).nil?
         
     | 
| 
      
 890 
     | 
    
         
            +
                      return val if (base = workspace.find_base(self)) && !(val = from_sync?(ac, base.ref)).nil?
         
     | 
| 
       689 
891 
     | 
    
         | 
| 
       690 
     | 
    
         
            -
                       
     | 
| 
       691 
     | 
    
         
            -
             
     | 
| 
      
 892 
     | 
    
         
            +
                      if task_invoked?(task_join(name, ac)) && (!task_invoked?(ac) || !workspace.task_defined?(ac, 'sync'))
         
     | 
| 
      
 893 
     | 
    
         
            +
                        true
         
     | 
| 
      
 894 
     | 
    
         
            +
                      else
         
     | 
| 
      
 895 
     | 
    
         
            +
                        val = workspace.series.name_get(action)
         
     | 
| 
      
 896 
     | 
    
         
            +
                        val == action ? false : invoked_sync?(val)
         
     | 
| 
      
 897 
     | 
    
         
            +
                      end
         
     | 
| 
      
 898 
     | 
    
         
            +
                    end
         
     | 
| 
      
 899 
     | 
    
         
            +
             
     | 
| 
      
 900 
     | 
    
         
            +
                    def stdin?
         
     | 
| 
      
 901 
     | 
    
         
            +
                      pipe == 0
         
     | 
| 
      
 902 
     | 
    
         
            +
                    end
         
     | 
| 
      
 903 
     | 
    
         
            +
             
     | 
| 
      
 904 
     | 
    
         
            +
                    def warning?
         
     | 
| 
      
 905 
     | 
    
         
            +
                      workspace.warning
         
     | 
| 
      
 906 
     | 
    
         
            +
                    end
         
     | 
| 
      
 907 
     | 
    
         
            +
             
     | 
| 
      
 908 
     | 
    
         
            +
                    def projectmap(files, parent: false)
         
     | 
| 
      
 909 
     | 
    
         
            +
                      files = files.select { |val| projectpath?(val) } unless parent
         
     | 
| 
      
 910 
     | 
    
         
            +
                      files.map { |val| val == '.' ? '.' : shell_quote(basepath(val.strip)) }
         
     | 
| 
      
 911 
     | 
    
         
            +
                    end
         
     | 
| 
      
 912 
     | 
    
         
            +
             
     | 
| 
      
 913 
     | 
    
         
            +
                    def semver(val)
         
     | 
| 
      
 914 
     | 
    
         
            +
                      return val if val[3]
         
     | 
| 
      
 915 
     | 
    
         
            +
             
     | 
| 
      
 916 
     | 
    
         
            +
                      val[3] = '.'
         
     | 
| 
      
 917 
     | 
    
         
            +
                      val[4] = '0'
         
     | 
| 
      
 918 
     | 
    
         
            +
                      unless val[1]
         
     | 
| 
      
 919 
     | 
    
         
            +
                        val[1] = '.'
         
     | 
| 
      
 920 
     | 
    
         
            +
                        val[2] = '0'
         
     | 
| 
      
 921 
     | 
    
         
            +
                      end
         
     | 
| 
      
 922 
     | 
    
         
            +
                      val
         
     | 
| 
      
 923 
     | 
    
         
            +
                    end
         
     | 
| 
      
 924 
     | 
    
         
            +
             
     | 
| 
      
 925 
     | 
    
         
            +
                    def semscan(val)
         
     | 
| 
      
 926 
     | 
    
         
            +
                      val.scan(SEM_VER).first
         
     | 
| 
      
 927 
     | 
    
         
            +
                    end
         
     | 
| 
       692 
928 
     | 
    
         | 
| 
       693 
     | 
    
         
            -
             
     | 
| 
      
 929 
     | 
    
         
            +
                    def borderstyle
         
     | 
| 
      
 930 
     | 
    
         
            +
                      if (data = workspace.banner_get(*@ref, group: group))
         
     | 
| 
      
 931 
     | 
    
         
            +
                        data[:border]
         
     | 
| 
      
 932 
     | 
    
         
            +
                      end
         
     | 
| 
      
 933 
     | 
    
         
            +
                    end
         
     | 
| 
      
 934 
     | 
    
         
            +
             
     | 
| 
      
 935 
     | 
    
         
            +
                    def headerstyle
         
     | 
| 
      
 936 
     | 
    
         
            +
                      { pat: /^(\S+)(\s+)$/, styles: theme[:header] }
         
     | 
| 
      
 937 
     | 
    
         
            +
                    end
         
     | 
| 
      
 938 
     | 
    
         
            +
             
     | 
| 
      
 939 
     | 
    
         
            +
                    def scriptargs
         
     | 
| 
      
 940 
     | 
    
         
            +
                      { target: script? ? @output[1] : @output[0], ref: ref, group: group, global: @global }
         
     | 
| 
      
 941 
     | 
    
         
            +
                    end
         
     | 
| 
      
 942 
     | 
    
         
            +
             
     | 
| 
      
 943 
     | 
    
         
            +
                    def indexdata(val)
         
     | 
| 
      
 944 
     | 
    
         
            +
                      if (data = /\A\^(\d+)(:.+)?\z/.match(val))
         
     | 
| 
      
 945 
     | 
    
         
            +
                        [data[1].to_i, data[2] ? data[2][1..-1] : nil]
         
     | 
| 
      
 946 
     | 
    
         
            +
                      end
         
     | 
| 
      
 947 
     | 
    
         
            +
                    end
         
     | 
| 
      
 948 
     | 
    
         
            +
             
     | 
| 
      
 949 
     | 
    
         
            +
                    def indexerror(val, list = nil)
         
     | 
| 
      
 950 
     | 
    
         
            +
                      raise_error("requested index #{val}", hint: list && "of #{list.size}")
         
     | 
| 
       694 
951 
     | 
    
         
             
                    end
         
     | 
| 
       695 
952 
     | 
    
         
             
                  end
         
     | 
| 
      
 953 
     | 
    
         
            +
             
     | 
| 
      
 954 
     | 
    
         
            +
                  Application.impl_project = Base
         
     | 
| 
      
 955 
     | 
    
         
            +
                  Application.attr_banner = Common::SymSet.new(%i[name project path ref group parent])
         
     | 
| 
       696 
956 
     | 
    
         
             
                end
         
     | 
| 
       697 
957 
     | 
    
         
             
              end
         
     | 
| 
       698 
958 
     | 
    
         
             
            end
         
     |