squared 0.6.3 → 0.6.4

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.
@@ -330,7 +330,8 @@ module Squared
330
330
  end
331
331
  end
332
332
  when 'outdated'
333
- format_desc action, flag, 'eager?,user?,s/elect'
333
+ format_desc(action, flag, "eager?,no-deps?,#{shortname('h', 'i', 's', 'd')}",
334
+ before: ('user?' unless venv))
334
335
  task flag do |_, args|
335
336
  outdated flag, args.to_a
336
337
  end
@@ -406,21 +407,34 @@ module Squared
406
407
 
407
408
  def outdated(flag = nil, opts = [], sync: invoked_sync?('outdated', flag))
408
409
  cmd = pip_session 'list --outdated'
409
- cmd << '--not-required' unless flag || option('not-required', equals: '0')
410
+ cmd << if flag
411
+ se = has_value!(opts, 's', 'select')
412
+ ia = has_value!(opts, 'i', 'interactive') && !se
413
+ hide = has_value! opts, 'h', 'hide'
414
+ dryrun = has_value! opts, 'd', 'dry-run'
415
+ if !sync || stdin?
416
+ se = false
417
+ ia = false
418
+ elsif se || ia
419
+ items = []
420
+ end
421
+ '--not-required' if opts.include?('no-deps')
422
+ else
423
+ '--not-required' unless option('not-required', equals: '0')
424
+ end
410
425
  cmd << '--local' if option('l', 'local')
411
426
  append_global
427
+ dryrun ||= dryrun?
412
428
  cmd = session_done cmd
413
429
  log.info cmd
414
430
  on :first, :outdated
415
431
  banner = format_banner cmd
416
- items = if sync
417
- print_item banner
418
- [] if flag && has_value?(opts, 's', 'select') && !stdin?
419
- end
432
+ print_item banner if sync
420
433
  pwd_set(from: :outdated) do
421
434
  tc = theme[:current]
422
435
  start = 0
423
436
  found = 0
437
+ col = 0
424
438
  major = []
425
439
  minor = []
426
440
  patch = []
@@ -431,53 +445,58 @@ module Squared
431
445
  else
432
446
  IO.popen(runenv || {}, cmd)
433
447
  end.each do |line|
448
+ line.chomp!
434
449
  next if line.match?(/^[ -]+$/)
435
450
 
436
451
  if start > 0
452
+ n = line.size
437
453
  unless stdin?
438
454
  cur, lat = line.scan(SEM_VER)
439
455
  next unless cur && lat
440
456
 
441
- latest = lat.join
442
- current = cur.join
457
+ name = line.split(' ', 2).first
458
+ c = cur.join
459
+ l = lat.join
443
460
  semver cur
444
461
  semver lat
445
- name = line.split(' ', 2).first
446
- type = if semmajor?(cur, lat)
447
- major << name
448
- 2
449
- elsif cur[2] == lat[2]
450
- patch << name
451
- 0
452
- else
453
- minor << name
454
- 1
455
- end
456
- if type == 0
462
+ case (type = semtype(cur, lat))
463
+ when 1
464
+ major << name
465
+ when 2
466
+ minor << name
467
+ else
468
+ patch << name
469
+ end
470
+ next if hide && ((flag == :patch && type < 3) || (flag == :minor && type < 2))
471
+
472
+ if type == 3
457
473
  styles = color(:yellow)
458
474
  else
459
475
  styles = color(:green)
460
- sub_style!(line, if type == 2
476
+ sub_style!(line, if type == 1
461
477
  styles += [:bold]
462
478
  theme[:major]
463
479
  else
464
480
  theme[:active]
465
481
  end, pat: /^(\S+)(.+)$/)
466
482
  end
467
- sub_style!(line, **opt_style(tc, /^(.+)(#{Regexp.escape(current)})(.+)$/, 2)) if tc
468
- sub_style!(line, **opt_style(styles, /^(.+)(#{Regexp.escape(latest)})(.+)$/, 2))
483
+ sub_style!(line, **opt_style(tc, /^(.+)(#{Regexp.escape(c)})(.+)$/, 2)) if tc
484
+ sub_style!(line, **opt_style(styles, /^(.+)(#{Regexp.escape(l)})(.+)$/, 2))
469
485
  found += 1
470
486
  end
471
- if items
472
- items << [line, name]
473
- else
474
- out.call("#{start.to_s.rjust(2)}. #{line}")
475
- end
487
+ s = '%2d. %s' % [start, line]
476
488
  start += 1
489
+ if ia
490
+ next unless confirm_semver(s.ljust(col + line.size - n), type)
491
+ elsif !se
492
+ out.call(s)
493
+ end
494
+ items&.push([line, name])
477
495
  elsif line.start_with?('Package')
478
496
  unless stdin?
497
+ col = line.size + 5
479
498
  sub = [opt_style(theme[:header], /^(.*)(?<!\dm)(Package|Latest)(.+)$/, 2)] * 2
480
- out.call(print_footer(" # #{line.chomp}", reverse: true, sub: sub))
499
+ out.call(print_footer(" # #{line}", reverse: true, sub: sub))
481
500
  end
482
501
  start += 1
483
502
  end
@@ -487,9 +506,11 @@ module Squared
487
506
  puts buffer
488
507
  end
489
508
  if found > 0
490
- if items
509
+ if se
491
510
  choice('Select a package', items.map(&:first),
492
511
  multiple: true, force: false, index: true, border: true).map! { |n| items[n.pred].last }
512
+ elsif ia
513
+ items.map(&:last)
493
514
  else
494
515
  case flag
495
516
  when :major
@@ -501,11 +522,19 @@ module Squared
501
522
  end
502
523
  end.tap do |packages|
503
524
  unless packages.empty?
504
- install(:upgrade, opts.grep(/^(?:eager|user)$/), packages: packages, banner: false)
525
+ base = %w[eager no-deps]
526
+ base << 'user' unless venv
527
+ opts = (base & opts).map! { |val| val == 'eager' ? "upgrade-strategy=#{val}" : val }
528
+ if dryrun
529
+ opts.map! { |val| fill_option(val) }
530
+ print_run pip_output('install --upgrade', *opts, *packages.quote!), false
531
+ else
532
+ install(:upgrade, opts, packages: packages, banner: false)
533
+ end
505
534
  end
506
535
  print_status(major.size, minor.size, patch.size, from: :outdated)
507
536
  end
508
- elsif start == 0
537
+ elsif start == 0 || hide
509
538
  puts 'No updates were found'
510
539
  end
511
540
  end
@@ -730,7 +759,7 @@ module Squared
730
759
  end
731
760
 
732
761
  def outdated?
733
- dependtype > 0
762
+ dependtype > 0 && !task_pass?('outdated')
734
763
  end
735
764
 
736
765
  private
@@ -739,6 +768,10 @@ module Squared
739
768
  session('pip', *cmd, *preopts, path: venv.nil?)
740
769
  end
741
770
 
771
+ def pip_output(*cmd)
772
+ session_output('pip', *cmd, *preopts, path: venv.nil?)
773
+ end
774
+
742
775
  def python_session(*cmd, opts: nil)
743
776
  return session('python', *preopts(quiet: false), *cmd, path: venv.nil?) unless opts
744
777
 
@@ -769,11 +802,11 @@ module Squared
769
802
 
770
803
  def append_pip(flag, opts, target: @session, from: nil)
771
804
  list = OPT_PIP.fetch(from, []) + OPT_PIP[:common]
772
- if pip_install?(flag)
805
+ if pip_install?(flag) || from == :install
773
806
  list.concat(OPT_PIP[:install_a])
774
807
  list.concat(OPT_PIP[:install_b]) unless flag == :index
775
808
  case flag
776
- when :install
809
+ when :install, :editable, :upgrade
777
810
  list.concat(OPT_PIP[:install_c] + OPT_PIP[:debug])
778
811
  when :lock, :wheel
779
812
  list.concat(OPT_PIP[:install_c])
@@ -785,7 +818,7 @@ module Squared
785
818
  op = OptionPartition.new(opts, list, target, project: self, single: singleopt)
786
819
  append_global(target: target)
787
820
  case flag
788
- when :install, :lock, :wheel
821
+ when :install, :lock, :wheel, :editable, :upgrade
789
822
  edit = nil
790
823
  op.each do |opt|
791
824
  if opt =~ op.values
@@ -994,10 +1027,10 @@ module Squared
994
1027
  def venv_init
995
1028
  return if !venv || (venvbin.directory? && !venvbin.empty?)
996
1029
 
997
- puts log_message(Logger::INFO, venv, subject: 'venv', hint: 'init')
1030
+ puts log_message(venv, subject: 'venv', hint: 'init')
998
1031
  opts = @venvopts&.map { |val| OptionPartition.strip(val) }&.flatten
999
1032
  venv_create(venv, opts || ["prompt=#{name}", 'upgrade-deps'], env: false, banner: false)
1000
- puts log_message(Logger::INFO, venv, subject: 'venv', hint: 'created')
1033
+ puts log_message(venv, subject: 'venv', hint: 'created')
1001
1034
  end
1002
1035
 
1003
1036
  def venv_create(dir, opts = [], env: nil, banner: true)
@@ -157,7 +157,7 @@ module Squared
157
157
  end
158
158
 
159
159
  subtasks({
160
- 'outdated' => %i[patch minor major].freeze,
160
+ 'outdated' => %i[major minor patch].freeze,
161
161
  'ruby' => %i[file script version].freeze,
162
162
  'gem' => %i[install uninstall outdated update pristine build push exec command].freeze,
163
163
  'bundle' => %i[install update cache exec config reinstall command].freeze,
@@ -334,14 +334,14 @@ module Squared
334
334
  flags.each do |flag|
335
335
  case action
336
336
  when 'outdated'
337
- format_desc action, flag, 's/elect?,u/pdate?,opts*'
337
+ format_desc action, flag, "#{shortname('i', 's', 'u', 'd')},opts*"
338
338
  task flag do |_, args|
339
- __send__ action, flag, args.to_a
339
+ outdated flag, args.to_a
340
340
  end
341
341
  when 'gem'
342
342
  case flag
343
343
  when :outdated
344
- format_desc action, flag, 'semver?=major|minor|patch,i/nteractive?,s/elect?,u/pdate?,opts*'
344
+ format_desc action, flag, "semver?=major|minor|patch,#{shortname('i', 's', 'u', 'd')},opts*"
345
345
  task flag, [:semver] do |_, args|
346
346
  opts = case (semver = args.semver)
347
347
  when 'major', 'minor', 'patch'
@@ -354,13 +354,14 @@ module Squared
354
354
  semver: semver,
355
355
  update: has_value!(opts, 'u', 'update'),
356
356
  interactive: has_value!(opts, 'i', 'interactive'),
357
- select: has_value!(opts, 's', 'select')
357
+ select: has_value!(opts, 's', 'select'),
358
+ dryrun: has_value!(opts, 'd', 'dry-run')
358
359
  })
359
360
  end
360
361
  when :build, :push, :exec, :update
361
362
  format_desc(action, flag, 'opts*', after: case flag
362
363
  when :exec then 'command,args*'
363
- when :push then 'file?|:'
364
+ when :push then 'file/:'
364
365
  when :update then 'name*'
365
366
  end)
366
367
  task flag do |_, args|
@@ -517,34 +518,44 @@ module Squared
517
518
  def outdated(flag = nil, opts = [], sync: invoked_sync?('outdated', flag))
518
519
  cmd = bundle_output 'outdated'
519
520
  if flag
520
- se = has_value!(opts, 's', 'select') && !stdin?
521
+ se = has_value!(opts, 's', 'select')
522
+ ia = has_value!(opts, 'i', 'interactive') && !se
521
523
  up = has_value!(opts, 'u', 'update')
522
- cmd << "--#{flag}"
523
- OptionPartition.new(opts, bundleopts(:outdated), cmd, project: self)
524
+ dryrun = has_value!(opts, 'd', 'dry-run')
525
+ if !sync || stdin?
526
+ se = false
527
+ ia = false
528
+ elsif se || ia || up
529
+ items = []
530
+ end
531
+ OptionPartition.new(opts, bundleopts(:outdated), cmd << "--#{flag}", project: self)
524
532
  .clear
525
533
  end
534
+ dryrun ||= dryrun?(prefix: 'bundle')
526
535
  log.info cmd.to_s
527
536
  on :first, :outdated
528
537
  banner = format_banner cmd.to_s
529
- items = if sync
530
- print_item banner
531
- [] if flag && (se || up)
532
- end
538
+ print_item banner if sync
533
539
  pwd_set(from: :outdated) do
534
540
  tc = theme[:current]
535
541
  start = 0
536
542
  found = 0
537
543
  major = 0
544
+ col = 0
538
545
  buffer = []
539
546
  out = ->(val) { sync ? puts(val) : buffer << val }
540
547
  IO.popen(cmd.temp('--no-color')).each do |line|
548
+ line.chomp!
541
549
  if start > 0
550
+ n = line.size
542
551
  unless stdin?
552
+ line = line[0...col] if col > 0
543
553
  data = line.scan(SEM_VER)
544
554
  next unless (cur = data.shift) && (lat = data.shift)
545
555
 
546
556
  semver cur
547
557
  semver lat
558
+ type = semtype cur, lat
548
559
  c = cur.join
549
560
  l = lat.join
550
561
  styles = []
@@ -552,9 +563,9 @@ module Squared
552
563
  styles = %i[green bold]
553
564
  major += 1
554
565
  end
555
- mi = -> { styles[0] = cur[2] == lat[2] ? :yellow : :green }
566
+ mi = -> { styles[0] = type == 2 ? :yellow : :green }
556
567
  if data.empty?
557
- semmajor?(cur, lat) ? ma.call : mi.call
568
+ type == 1 ? ma.call : mi.call
558
569
  else
559
570
  data.each do |val|
560
571
  break unless line =~ /(>=?|=|~>|!=|<=?) (#{Regexp.escape(val.join)})/
@@ -562,10 +573,10 @@ module Squared
562
573
  v = semver(val).join
563
574
  case $1
564
575
  when '>', '>='
565
- semmajor?(cur, lat) ? ma.call : mi.call
576
+ type == 1 ? ma.call : mi.call
566
577
  when '<', '<='
567
578
  if c <= v
568
- if semmajor?(cur, lat)
579
+ if type == 1
569
580
  ma.call
570
581
  else
571
582
  styles[0] = :yellow
@@ -597,17 +608,28 @@ module Squared
597
608
  when :yellow
598
609
  found += 1
599
610
  end
600
- l = Regexp.escape(l)
601
611
  sub_style!(line, **opt_style(tc, /^(.+)(#{Regexp.escape(c)})(.+)$/, 2)) if tc
602
- sub_style!(line, **opt_style(colormap(styles), /^((?:\S+\s+){2})(#{l})(.*)$/, 2))
612
+ sub_style!(line, **opt_style(colormap(styles), /^((?:\S+\s+){2})(#{Regexp.escape(l)})(.*)$/, 2))
613
+ end
614
+ end
615
+ s = '%2d. %s' % [start, line]
616
+ if ia
617
+ unless confirm_semver(s.ljust(col + 4 + line.size - n), type)
618
+ start += 1
619
+ next
603
620
  end
621
+ elsif !se
622
+ out.call(s)
604
623
  end
605
624
  items&.push([line, name])
606
- out.call('%2d. %s' % [start, line]) unless se
607
625
  elsif line.start_with?('Gem')
608
626
  unless stdin?
627
+ if ia
628
+ line.sub!(/\sGroups$/, '')
629
+ col = line.size
630
+ end
609
631
  sub = [opt_style(theme[:header], /^(.+)(?<!\dm)(Gem|Latest)(.+)$/, 2)] * 2
610
- out.call(print_footer(" # #{line.chomp}", reverse: true, sub: sub))
632
+ out.call(print_footer(" # #{line}", reverse: true, sub: sub))
611
633
  end
612
634
  else
613
635
  next
@@ -619,26 +641,30 @@ module Squared
619
641
  puts buffer
620
642
  end
621
643
  if found > 0
622
- if items
644
+ unless Array(items).empty?
623
645
  gems = if se
624
646
  choice('Select a package', items.map(&:first),
625
647
  multiple: true, force: false, index: true, border: true).map! { |n| items[n.pred].last }
626
648
  else
627
649
  items.map(&:last)
628
650
  end
629
- bundle(:update, *gems, opts: [flag.to_s])
651
+ if dryrun
652
+ print_run bundle_output("update --#{flag}", *gems.quote!), false
653
+ else
654
+ bundle(:update, *gems, opts: [flag.to_s])
655
+ end
630
656
  end
631
657
  begin
632
- if major == 0 && dependfile.read =~ /\b(?:source\s+(["'])((?~\1))\1|remote:\s+(\S+))/
633
- status = ($2 || $3).chomp('/')
634
- right = true
635
- end
658
+ status = if gems
659
+ "#{gems.size} packages were updated"
660
+ elsif dependfile.read =~ /\b(?:source\s+(["'])((?~\1))\1|remote:\s+(\S+))/
661
+ right = true
662
+ ($2 || $3).chomp('/')
663
+ end
636
664
  rescue StandardError => e
637
665
  log.debug e
638
- ensure
639
- status ||= (items ? 'Updates were made' : 'Updates are available')
640
666
  end
641
- puts print_footer(empty_status(status, 'major', major, always: !right), right: right)
667
+ puts print_footer(status || 'Updates are available', right: right)
642
668
  elsif start == 0 && banner
643
669
  puts 'No updates were found'
644
670
  end
@@ -832,11 +858,7 @@ module Squared
832
858
  if line =~ /^(\S+) \((\S+) < ([^)]+)\)$/
833
859
  cur = semscan $2
834
860
  lat = semscan $3
835
- rows << [$~.to_a.drop(1), if semmajor?(cur, lat)
836
- 1
837
- else
838
- cur[2] == lat[2] ? 3 : 2
839
- end]
861
+ rows << [$~.to_a.drop(1), semtype(cur, lat)]
840
862
  else
841
863
  out.call(line)
842
864
  end
@@ -847,7 +869,6 @@ module Squared
847
869
  e = 0
848
870
  f = 0
849
871
  j = 0
850
- col4 = 0
851
872
  queue = nil
852
873
  rows.each do |row|
853
874
  a, b, c = row.first
@@ -859,10 +880,10 @@ module Squared
859
880
  next if i == 0 && stdin?
860
881
 
861
882
  a, b, c = row.first
883
+ type = row.last
862
884
  if i == 0
863
885
  line = '%-*s %-*s %*s %*s' % [pad, ' #', d, a, e, b, f, c]
864
- col4 = line.size
865
- s = ARG[:BORDER][1] * col4
886
+ s = ARG[:BORDER][1] * line.size
866
887
  queue = if stdin?
867
888
  [line, s]
868
889
  else
@@ -876,7 +897,7 @@ module Squared
876
897
  pat = [/^([^.]+\.)([^.]+\..+)$/, /^([^.]+\.[^.]+\.)(.+)$/]
877
898
  pre = b.start_with?('0.')
878
899
  latest = [theme[:latest]]
879
- case row.last
900
+ case type
880
901
  when 1
881
902
  case semver
882
903
  when 'major'
@@ -926,13 +947,18 @@ module Squared
926
947
  out.call(queue)
927
948
  queue = nil
928
949
  end
929
- s = '%s %s %s' % [g, b, h]
930
- if items
931
- items << [s, a]
932
- else
933
- out.call('%*s %s' % [pad, "#{j}.", s])
950
+ s = ('%s %s %s' % [g, b, h]).yield_self do |val|
951
+ items&.push([val, a])
952
+ '%*s %s' % [pad, "#{j}.", val]
953
+ end
954
+ if ia
955
+ unless confirm_semver(s, type)
956
+ update.delete(a)
957
+ next
958
+ end
959
+ elsif !items
960
+ out.call(s)
934
961
  end
935
- update.delete(a) if ia && !confirm_outdated(a, c, row.last, col4: col4, timeout: 0)
936
962
  end
937
963
  end
938
964
  end
@@ -948,7 +974,7 @@ module Squared
948
974
  update = choice('Select a package', items.map(&:first),
949
975
  multiple: true, force: false, index: true, border: true).map! { |n| items[n.pred].last }
950
976
  end
951
- if update && !update.empty?
977
+ unless Array(update).empty?
952
978
  cmd = gem_output 'update -f'
953
979
  option('document', prefix: 'gem', ignore: false) do |val|
954
980
  cmd << case val
@@ -966,8 +992,12 @@ module Squared
966
992
  '--user-install'
967
993
  end
968
994
  end
969
- cmd.merge(update)
970
- run(cmd, sync: sync, banner: false, from: :'gem:update')
995
+ cmd.merge(update.quote!)
996
+ if filter[:dryrun]
997
+ print_run cmd, false
998
+ else
999
+ run(cmd, sync: sync, banner: false, from: :'gem:update')
1000
+ end
971
1001
  end
972
1002
  print_status(*major, from: :outdated)
973
1003
  end
@@ -1381,7 +1411,7 @@ module Squared
1381
1411
  end
1382
1412
 
1383
1413
  def outdated?
1384
- dependtype > 0
1414
+ dependtype > 0 && !task_pass?('outdated')
1385
1415
  end
1386
1416
 
1387
1417
  private
@@ -49,7 +49,7 @@ module Squared
49
49
  end
50
50
 
51
51
  def compact
52
- to_ary.map!(&:to_s).reject(&:empty?)
52
+ dump to_ary
53
53
  end
54
54
 
55
55
  def last(val, pat)
@@ -79,7 +79,7 @@ module Squared
79
79
  end
80
80
  ret[items.last] = val
81
81
  end
82
- ret.concat(extras.map(&:to_s).reject(&:empty?)) unless extras.empty?
82
+ ret.concat(dump(extras)) unless extras.empty?
83
83
  return ret unless block_given?
84
84
 
85
85
  ret.reject(&blk)
@@ -116,12 +116,12 @@ module Squared
116
116
  self
117
117
  elsif (n = enum.find_index { |val| extras?(val) })
118
118
  data = enum.to_a
119
- @extras = if n == 0
120
- data
121
- else
122
- super(data[0...n])
123
- data[n..-1]
124
- end
119
+ extras.concat(if n == 0
120
+ data
121
+ else
122
+ super(data[0...n])
123
+ data[n..-1]
124
+ end)
125
125
  self
126
126
  else
127
127
  super
@@ -164,6 +164,10 @@ module Squared
164
164
 
165
165
  private
166
166
 
167
+ def dump(enum)
168
+ enum.map(&:to_s).reject(&:empty?)
169
+ end
170
+
167
171
  def extras?(obj)
168
172
  obj == @partition || (include?(obj) && (!@uniq.match?(s = obj.to_s) || multiple.include?(s)))
169
173
  end
@@ -550,7 +550,7 @@ module Squared
550
550
  if path
551
551
  found.each { |val| add_path(val) }
552
552
  else
553
- found.map! { |val| shell_quote(val) } if quote
553
+ found.quote! if quote
554
554
  merge found
555
555
  end
556
556
  end
@@ -3,9 +3,12 @@
3
3
  module Squared
4
4
  module Workspace
5
5
  module Repo
6
+ REPO_URL = 'https://storage.googleapis.com/git-repo-downloads/repo'
7
+ private_constant :REPO_URL
8
+
6
9
  attr_reader :manifest_url, :manifest
7
10
 
8
- def repo(url, manifest = 'latest', run: nil, script: nil, args: nil, dev: nil, prod: nil,
11
+ def repo(url, manifest = 'latest', install: nil, run: nil, script: nil, args: nil, dev: nil, prod: nil,
9
12
  ref: @ref, group: @group)
10
13
  @home = if (val = env('REPO_HOME'))
11
14
  path = Pathname.new(val)
@@ -101,6 +104,7 @@ module Squared
101
104
  data[:prod] = prod
102
105
  script_set(data, group: group, ref: ref)
103
106
  end
107
+ @repo_bin = install.is_a?(String) ? @root + install : @root if install
104
108
  self
105
109
  end
106
110
 
@@ -154,7 +158,7 @@ module Squared
154
158
  desc.call("init[manifest?=#{target},groups?,{0}]", target)
155
159
  task 'init' do |_, args|
156
160
  args = args.to_a
157
- u = env('REPO_URL') || manifest_url
161
+ u = env('REPO_GIT') || manifest_url
158
162
  m = args.first && !opts.include?(args.first) ? args.shift : target
159
163
  g = (args.shift if args.first && !opts.include?(args.first))
160
164
  g = case (val = env('REPO_GROUPS'))
@@ -247,12 +251,26 @@ module Squared
247
251
  end
248
252
 
249
253
  def repo_run(cmd, exception: false)
250
- puts log_message(Logger::INFO, cmd, subject: main, hint: root) if verbose
254
+ puts log_message(cmd, subject: main, hint: root) if verbose
251
255
  Common::System.shell(cmd, chdir: root, exception: exception)
252
256
  end
253
257
 
254
258
  def repo_bin
255
- Common::Shell.shell_bin('repo')
259
+ return Common::Shell.shell_bin('repo') unless @repo_bin
260
+
261
+ @repo_bin.join('repo').tap do |bin|
262
+ next if bin.file?
263
+
264
+ require 'open-uri'
265
+ puts log_message('Installing repo...', subject: main, hint: @repo_bin) if verbose
266
+ URI.open(REPO_URL) do |url|
267
+ @repo_bin.mkpath
268
+ File.open(bin, 'wb') do |f|
269
+ f.write(url.read)
270
+ f.chmod(0o755)
271
+ end
272
+ end
273
+ end
256
274
  end
257
275
 
258
276
  def repo_opts(*args)
@@ -262,7 +280,7 @@ module Squared
262
280
  end
263
281
 
264
282
  def repo?
265
- return false unless manifest_url
283
+ return false unless manifest_url && !windows?
266
284
 
267
285
  repo_install? || @repo_override == true
268
286
  end