squared 0.0.5 → 0.0.6

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.
@@ -0,0 +1,201 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Squared
4
+ module Workspace
5
+ module Repo
6
+ include Common
7
+ include Format
8
+ include System
9
+ include Task
10
+
11
+ attr_accessor :warning
12
+
13
+ def repo(url, manifest = 'latest', run: nil, dev: nil, prod: nil)
14
+ @home = if (val = env('REPO_HOME'))
15
+ home = Pathname.new(val)
16
+ if @main == home.basename.to_s
17
+ @root = home.parent
18
+ if home.exist?
19
+ @root = nil unless home.directory?
20
+ elsif !@root.exist?
21
+ @root.mkpath
22
+ elsif !install?
23
+ @root = nil unless confirm_install
24
+ end
25
+ end
26
+ raise_error('REPO_HOME', val, hint: 'invalid') unless @root
27
+
28
+ home.realdirpath
29
+ elsif (val = env('REPO_ROOT'))
30
+ @root = Pathname.new(val).realdirpath
31
+ if !@root.exist?
32
+ @root.mkpath
33
+ elsif !install?
34
+ raise_error('REPO_ROOT', val, hint: 'exist') unless confirm_install
35
+ end
36
+ @root.join(@main).realdirpath
37
+ else
38
+ install?(pwd = Pathname.pwd) ? pwd.join(@main) : pwd
39
+ end
40
+ @root = @home.parent
41
+ @manifest_url = url
42
+ @manifest = manifest
43
+ if repo?
44
+ @script[:build] = case (val = env('REPO_BUILD'))
45
+ when 'verbose'
46
+ @verbose = true
47
+ "#{run}:verbose" if run
48
+ when 'silent'
49
+ @verbose = false
50
+ @warning = false
51
+ run
52
+ else
53
+ val || run
54
+ end
55
+ @script[:dev] = bool_match(env('REPO_DEV'), dev)
56
+ @script[:prod] = bool_match(env('REPO_PROD'), prod)
57
+ @warning = case env('REPO_WARN')
58
+ when '0'
59
+ false
60
+ when '1'
61
+ true
62
+ else
63
+ !empty?(@root)
64
+ end
65
+ @extensions << :__repo__
66
+ else
67
+ @script[:build] = run
68
+ @script[:dev] = dev
69
+ @script[:prod] = prod
70
+ end
71
+ self
72
+ end
73
+
74
+ protected
75
+
76
+ def repo?
77
+ !@manifest_url.nil? && (install? || !!@override)
78
+ end
79
+
80
+ def empty?(dir)
81
+ dir.empty? || (dir.children.size == 1 && dir.join(dir.children.first).to_s == __FILE__)
82
+ end
83
+
84
+ private
85
+
86
+ def __repo__(**kwargs)
87
+ kwargs.delete(:parallel) if env('REPO_SYNC', ignore: '0')
88
+
89
+ branch = env('REPO_MANIFEST') || read_manifest
90
+ target = branch || @manifest
91
+ stage = nil
92
+ failfast = true
93
+ cmd = []
94
+ newline = ARGV.index { |val| val.start_with?('repo:') }.to_i > 0
95
+ parse_opts = lambda do |args|
96
+ collect_args(args, :opts).each do |val|
97
+ case val
98
+ when 'no-fail'
99
+ failfast = false
100
+ when 'force'
101
+ cmd << '--force-checkout'
102
+ when 'rebase'
103
+ cmd << '--rebase'
104
+ when 'detach'
105
+ cmd << '--detach'
106
+ when 'gc'
107
+ cmd << '--auto-gc'
108
+ when 'no-update'
109
+ cmd << '--no-manifest-update'
110
+ end
111
+ end
112
+ end
113
+ status = lambda do |val, alt = nil|
114
+ ver = branch || alt
115
+ ver ? message('repo', val.sub('{0}', 'opts*=force,rebase,detach,gc,no-update,no-fail'), ver) : 'inactive'
116
+ end
117
+
118
+ namespace 'repo' do |repo|
119
+ desc status.('all[{0}]')
120
+ task 'all', [:opts] do |_, args|
121
+ parse_opts.(args)
122
+ stage ||= 'all'
123
+ repo['sync'].invoke
124
+ @project.select do |_, proj|
125
+ if proj.enabled?
126
+ proj.depend
127
+ proj.build?
128
+ end
129
+ end
130
+ .each_value { |proj| proj.has?(:dev) ? proj.refresh : proj.build }
131
+ end
132
+
133
+ desc status.("init[manifest?=#{target},{0}]", target)
134
+ task 'init', [:manifest, :opts] do |_, args|
135
+ parse_opts.(args)
136
+ stage = 'init'
137
+ puts if newline
138
+ system("repo init -u #{@manifest_url} -m #{args.manifest || target}.xml", chdir: root)
139
+ repo['all'].invoke
140
+ end
141
+
142
+ desc status.('sync[{0}]')
143
+ task 'sync', [:opts] do |_, args|
144
+ raise_error('repo is not initialized', 'rake repo:init', kind: LoadError) unless branch || stage == 'init'
145
+
146
+ parse_opts.(args)
147
+ cmd << "-j#{ENV.fetch('REPO_JOBS', ::Rake::CpuCounter.count)}"
148
+ cmd << '--fail-fast' if failfast
149
+ puts if newline && stage != 'init'
150
+ begin
151
+ shell("repo sync #{cmd.join(' ')}", chdir: root, exception: failfast)
152
+ rescue StandardError => e
153
+ emphasize(e, title: "rake stash repo:#{stage || 'sync'}")
154
+ raise
155
+ end
156
+ end
157
+ end
158
+ end
159
+
160
+ def read_manifest
161
+ require 'rexml/document'
162
+ return unless (file = root_path('.repo/manifest.xml')).exist?
163
+
164
+ doc = REXML::Document.new(file.read)
165
+ doc.elements['manifest/include'].attributes['name']&.sub('.xml', '')
166
+ end
167
+
168
+ def confirm_install
169
+ return false unless @root.directory?
170
+
171
+ @override = confirm(
172
+ "#{log_title(:warn)} \"#{sub_style(@root, :bold)}\" is not empty. Continue with installation? [y/N] ",
173
+ default: 'N',
174
+ timeout: env('REPO_TIMEOUT', ignore: '0', default: 15)
175
+ )
176
+ end
177
+
178
+ def bool_match(val, pat)
179
+ case val
180
+ when nil, ''
181
+ pat
182
+ when '0'
183
+ false
184
+ when '1'
185
+ true
186
+ else
187
+ Regexp.new(val)
188
+ end
189
+ end
190
+
191
+ def install?(dir = @root)
192
+ return true if empty?(dir) || dir.join('.repo').directory?
193
+ return false unless dir == root && env('REPO_HOME').nil? && !env('REPO_ROOT').nil?
194
+
195
+ root.children.none? { |path| path.directory? && path.basename.to_s[0] != '.' && path.to_s != home.to_s }
196
+ end
197
+ end
198
+
199
+ Application.include Repo
200
+ end
201
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ module Squared
6
+ module Workspace
7
+ class Series
8
+ include ::Rake::DSL
9
+ extend Forwardable
10
+
11
+ attr_reader :workspace, :sync, :multiple, :parallel
12
+
13
+ def_delegators :@data, :[], :each, :each_key, :keys, :fetch, :to_a, :to_s, :inspect, :merge!, :key?, :has_key?
14
+
15
+ def initialize(tasks, workspace, keys: Workspace::Application::WORKSPACE_KEYS)
16
+ if tasks.is_a?(Array)
17
+ @data = {}
18
+ tasks.each { |key| __set__ key }
19
+ else
20
+ @data = tasks.dup
21
+ end
22
+ @workspace = workspace
23
+ @keys = keys
24
+ @sync = []
25
+ @multiple = []
26
+ @parallel = []
27
+ @session = {
28
+ group: {},
29
+ parent: {},
30
+ id: []
31
+ }
32
+ end
33
+
34
+ def __set__(key)
35
+ self[key.to_sym] ||= []
36
+ end
37
+
38
+ def populate(proj)
39
+ return unless @session
40
+
41
+ group, parent, id = @session.values
42
+ each do |key, items|
43
+ target = "#{proj.name}:#{key}"
44
+ if @keys.include?(key)
45
+ next unless proj.has?(key) || (target = workspace.task_base?(key, target))
46
+ else
47
+ next unless workspace.task_include?(proj, key)
48
+ end
49
+ if (g = proj.group)
50
+ id << g
51
+ (group[:"#{key}:#{g}"] ||= []).push(target)
52
+ else
53
+ items << target
54
+ end
55
+ next unless (b = find_base(proj)) && (name = b.to_sym.to_s) != g
56
+
57
+ id << name
58
+ (parent[:"#{key}:#{name}"] ||= []).push(target)
59
+ end
60
+ end
61
+
62
+ def method_missing(key, *)
63
+ self[key]
64
+ end
65
+
66
+ def finalize!(thread = [])
67
+ thread.map!(&:to_s)
68
+ group, parent, id = @session.values
69
+ merge!(parent) if id.uniq.size > 1
70
+ merge!(group)
71
+ each do |key, items|
72
+ next if items.empty?
73
+
74
+ key = key.to_s
75
+ if items.size > 1
76
+ multiple << key
77
+ if thread.include?(key) || (key.include?(':') && thread.include?(key.split(':').first.to_sym))
78
+ desc "#{key} (thread)"
79
+ multitask key => items
80
+ parallel << key
81
+
82
+ desc "#{key} (sync)"
83
+ task "#{key}:sync": items
84
+ sync << "#{key}:sync"
85
+ multiple << "#{key}:sync"
86
+ next
87
+ end
88
+ end
89
+
90
+ desc key
91
+ task key => items
92
+ end
93
+ @session = nil
94
+ end
95
+
96
+ def has?(key)
97
+ !key.nil? && key?(key = key.to_sym) && !self[key].empty?
98
+ end
99
+
100
+ def multiple?(val = nil)
101
+ already_invoked?(multiple, val)
102
+ end
103
+
104
+ def sync?(val = nil)
105
+ already_invoked?(sync, val)
106
+ end
107
+
108
+ def parallel?(val = nil)
109
+ already_invoked?(parallel, val)
110
+ end
111
+
112
+ def respond_to_missing?(key, *)
113
+ key?(key)
114
+ end
115
+
116
+ private
117
+
118
+ def already_invoked?(list, val)
119
+ return list.include?(val) && invoked?(val) if val
120
+
121
+ ::Rake::Task.tasks.any? { |item| item.already_invoked && list.include?(item.name) }
122
+ end
123
+ end
124
+ end
125
+ end
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'common'
4
+
3
5
  module Squared
4
- module Repo
6
+ module Workspace
5
7
  class << self
6
8
  def resolve(*args)
7
9
  ret = args.map do |id|
@@ -35,5 +37,6 @@ module Squared
35
37
  end
36
38
  end
37
39
 
38
- require_relative 'repo/workspace'
39
- require_relative 'repo/project'
40
+ require_relative 'workspace/application'
41
+ require_relative 'workspace/series'
42
+ require_relative 'workspace/project'
data/lib/squared.rb CHANGED
@@ -1,13 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'squared/version'
4
- require_relative 'squared/common'
5
- require_relative 'squared/repo'
6
- require_relative 'squared/config'
4
+ require_relative 'squared/workspace'
7
5
 
8
- Repo::Workspace.implement(
9
- Repo::Project::Git,
10
- Repo::Project::Node,
11
- Repo::Project::Python,
12
- Repo::Project::Ruby
6
+ Workspace = Squared::Workspace
7
+ Project = Squared::Workspace::Project
8
+
9
+ Workspace::Application.implement(
10
+ Project::Git,
11
+ Project::Node,
12
+ Project::Python,
13
+ Project::Ruby
13
14
  )
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squared
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-03 00:00:00.000000000 Z
11
+ date: 2024-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -50,21 +50,24 @@ files:
50
50
  - README.ruby.md
51
51
  - lib/squared.rb
52
52
  - lib/squared/common.rb
53
+ - lib/squared/common/base.rb
53
54
  - lib/squared/common/class.rb
54
55
  - lib/squared/common/format.rb
55
56
  - lib/squared/common/shell.rb
56
57
  - lib/squared/common/system.rb
57
58
  - lib/squared/common/task.rb
58
59
  - lib/squared/config.rb
59
- - lib/squared/repo.rb
60
- - lib/squared/repo/project.rb
61
- - lib/squared/repo/project/base.rb
62
- - lib/squared/repo/project/git.rb
63
- - lib/squared/repo/project/node.rb
64
- - lib/squared/repo/project/python.rb
65
- - lib/squared/repo/project/ruby.rb
66
- - lib/squared/repo/workspace.rb
67
60
  - lib/squared/version.rb
61
+ - lib/squared/workspace.rb
62
+ - lib/squared/workspace/application.rb
63
+ - lib/squared/workspace/project.rb
64
+ - lib/squared/workspace/project/base.rb
65
+ - lib/squared/workspace/project/git.rb
66
+ - lib/squared/workspace/project/node.rb
67
+ - lib/squared/workspace/project/python.rb
68
+ - lib/squared/workspace/project/ruby.rb
69
+ - lib/squared/workspace/repo.rb
70
+ - lib/squared/workspace/series.rb
68
71
  - squared.gemspec
69
72
  homepage: https://github.com/anpham6/squared
70
73
  licenses: