squared 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +68 -1
- data/README.md +3 -0
- data/README.ruby.md +120 -40
- data/lib/squared/app.rb +0 -2
- data/lib/squared/common/base.rb +20 -14
- data/lib/squared/common/class.rb +18 -1
- data/lib/squared/common/format.rb +9 -9
- data/lib/squared/common/shell.rb +17 -8
- data/lib/squared/common/system.rb +56 -20
- data/lib/squared/common/utils.rb +5 -5
- data/lib/squared/config.rb +130 -82
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +168 -51
- data/lib/squared/workspace/project/base.rb +341 -130
- data/lib/squared/workspace/project/git.rb +705 -270
- data/lib/squared/workspace/project/node.rb +174 -100
- data/lib/squared/workspace/project/python.rb +176 -61
- data/lib/squared/workspace/project/ruby.rb +337 -171
- data/lib/squared/workspace/repo.rb +35 -46
- data/lib/squared/workspace/series.rb +16 -14
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 447c24bc317440fcf3f5b8e8c8f542f5e8f7641e3b548c5ee0204ba948460881
|
4
|
+
data.tar.gz: 1f048b1de055cd375e9e50f18361ef61a26c87602bb56a5f40245951faf05358
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf73faecb83832adfa1cbb21212939a93cc2fa133c4a13d24f008eb432cbc663a198294a944b35449921902fa3045cfa581839e52bea6723703c95772e537e05
|
7
|
+
data.tar.gz: a9db1c7dfd58750be1285fb1c2b39f9c087a3488560c6c2d35eb77939f69753127b2d97121450c5409f8b0c7b7fd821cd722291d57cabc0c5a7930f50ae338fb
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,71 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [0.2.0] - 2025-01-07
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Event system when executing a base or extension command.
|
8
|
+
- Git extension module with clone command was created.
|
9
|
+
- Missing workspace projects can create generation tasks.
|
10
|
+
- Node copies over symlinks when global store is detected.
|
11
|
+
- Git command rebase was implemented.
|
12
|
+
- Ruby command copy uses resolve_feature_path for autodetect.
|
13
|
+
- Task descriptions can be transformed using Regexp.
|
14
|
+
- Python command outdated is SemVer stylized.
|
15
|
+
- Config viewer can pre-parse and autoload file types.
|
16
|
+
- Projects can use dependency injection to create tasks.
|
17
|
+
- Config viewer can load multiple files of the same type.
|
18
|
+
- Unused Project class sub-tasks can be excluded.
|
19
|
+
- Project method property version was created.
|
20
|
+
- Git pull and fetch action remote can include refspec.
|
21
|
+
- Project dependency graph displays version when printed.
|
22
|
+
- Git command diff actions between and contain were implemented.
|
23
|
+
- Event system was appled to all git commands.
|
24
|
+
- Python command depend with Distutils was implemented.
|
25
|
+
- Full executable path to programs can be defined in Common.
|
26
|
+
- Banners can be hidden by group or reference.
|
27
|
+
- Git command reset action patch was implemented.
|
28
|
+
- Git command branch was implemented.
|
29
|
+
- Project build graph can be created using group or reference.
|
30
|
+
- Git command restore action source was implemented.
|
31
|
+
- Gem install and update non-deprecated options are fully complete.
|
32
|
+
- Pip install options are fully complete.
|
33
|
+
- Node command bump action version was implemented.
|
34
|
+
- Node command add was implemented.
|
35
|
+
- Python command install can use single character options.
|
36
|
+
- Gem install and pristine options are fully complete.
|
37
|
+
- Gem command outdated was implemented.
|
38
|
+
- Git command checkout action track was implemented.
|
39
|
+
- Theme style current used with outdated was created.
|
40
|
+
|
41
|
+
### Changed
|
42
|
+
|
43
|
+
- Task description uses a separate Application method.
|
44
|
+
- Project populate method base commands can be removed.
|
45
|
+
- Git pull and fetch options were revised.
|
46
|
+
- Git show actions were reduced to format and oneline.
|
47
|
+
- Common module System copy methods were renamed.
|
48
|
+
- Unused task arguments as placeholders were removed.
|
49
|
+
- Top-level namespaces are not used for standard gems.
|
50
|
+
- Task descriptions use a wrapper when calling Rake method.
|
51
|
+
- Git pull and fetch actions were reduced to origin and remote.
|
52
|
+
- Series class uses delegation for Application instance methods.
|
53
|
+
- Global constant alias to module Common was removed.
|
54
|
+
- Config viewer delegates task attributes to Project workspace.
|
55
|
+
- Global git commands pull-s and rebase-s were renamed using +s.
|
56
|
+
- Ruby command gem using pristine was implemented.
|
57
|
+
- Git class methods were given same name as command name.
|
58
|
+
- Abbreviated command options are no longer supported.
|
59
|
+
- Git commit hash uses string interpolation format.
|
60
|
+
- Git options ending with "!" use conventional "no-" prefix.
|
61
|
+
- Git pull and reset commands were reduced.
|
62
|
+
|
63
|
+
### Fixed
|
64
|
+
|
65
|
+
- Workspace did not locate root folder when main was named.
|
66
|
+
- Node tasks without any action are not displayed.
|
67
|
+
- Git fetch commands that do not apply to pull are rejected.
|
68
|
+
|
3
69
|
## [0.1.3] - 2024-01-02
|
4
70
|
|
5
71
|
### Fixed
|
@@ -29,7 +95,7 @@
|
|
29
95
|
- Workspace did not check base project for Windows filename.
|
30
96
|
- Regexp for SemVer did not recognize package names.
|
31
97
|
|
32
|
-
## [0.1.1] -
|
98
|
+
## [0.1.1] - 2025-12-14
|
33
99
|
|
34
100
|
### Added
|
35
101
|
|
@@ -79,6 +145,7 @@
|
|
79
145
|
|
80
146
|
- Changelog was created.
|
81
147
|
|
148
|
+
[0.2.0]: https://github.com/anpham6/squared/releases/tag/v0.2.0-ruby
|
82
149
|
[0.1.3]: https://github.com/anpham6/squared/releases/tag/v0.1.3-ruby
|
83
150
|
[0.1.2]: https://github.com/anpham6/squared/releases/tag/v0.1.2-ruby
|
84
151
|
[0.1.1]: https://github.com/anpham6/squared/releases/tag/v0.1.1-ruby
|
data/README.md
CHANGED
data/README.ruby.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# squared 0.
|
1
|
+
# squared 0.2
|
2
2
|
|
3
3
|
* [source](https://github.com/anpham6/squared)
|
4
4
|
* [manifest](https://github.com/anpham6/squared-repo)
|
@@ -6,9 +6,12 @@
|
|
6
6
|
|
7
7
|
## Version Compatibility
|
8
8
|
|
9
|
-
| Date
|
10
|
-
|
|
11
|
-
| 12-07
|
9
|
+
| Date | squared | Min | Max |
|
10
|
+
| :--------: | ------: | -----: | -----: |
|
11
|
+
| 2024-12-07 | 0.1.0 | 2.4.0 | 3.3.6 |
|
12
|
+
| 2025-01-07 | 0.2.0 | 2.4.0 | 3.4.0 |
|
13
|
+
|
14
|
+
The range chart indicates the latest Ruby tested against at the time of release.
|
12
15
|
|
13
16
|
## Installation
|
14
17
|
|
@@ -77,7 +80,7 @@ Workspace::Application
|
|
77
80
|
"CFLAGS" => "-fPIC -O1"
|
78
81
|
})
|
79
82
|
.add("optparse", doc: "rake rdoc", group: "default") # Uses bundler/gem_tasks (without C extensions)
|
80
|
-
.add("logger", copy: { from: "lib", glob: "**/*.rb", into: "~/.rvm/gems/ruby-3.
|
83
|
+
.add("logger", copy: { from: "lib", glob: "**/*.rb", into: "~/.rvm/gems/ruby-3.4.0/gems/logger-1.6.1" }, clean: ["tmp/"]) # autodetect: true
|
81
84
|
.add("e-mc", "emc", copy: { from: "publish", scope: "@e-mc", also: [:pir, "squared-express/"] }, ref: :node) # Node
|
82
85
|
.add("pi-r", "pir", copy: { from: "publish", scope: "@pi-r" }, clean: ["publish/**/*.js", "tmp/"]) # Trailing slash required for directories
|
83
86
|
.add("squared", script: ["build:stage1", "build:stage2"], group: "app") do # Copy target (main)
|
@@ -89,8 +92,8 @@ Workspace::Application
|
|
89
92
|
# OR
|
90
93
|
add(["publish/sqd-cli", "publish/sqd-serve", "publish/sqd-admin"], true, exclude: [:base]) # rake squared:sqd-serve:build
|
91
94
|
end
|
92
|
-
.add("squared/sqd", exclude: [:
|
93
|
-
variable_set :script, "build:sqd"
|
95
|
+
.add("squared/sqd", exclude: :git, pass: [:node, 'checkout', 'bump']) do # Skip initialize(:node) + squared:checkout:* + squared:bump:*
|
96
|
+
variable_set :script, "build:sqd" # Override detection
|
94
97
|
variable_set :depend, false
|
95
98
|
variable_set :clean, ["build/sqd/"]
|
96
99
|
end
|
@@ -112,26 +115,71 @@ Workspace::Application
|
|
112
115
|
# chrome = /workspaces/chrome-docs
|
113
116
|
|
114
117
|
Workspace::Application
|
115
|
-
.new(ENV["SQUARED_HOME"], prefix: "rb", common: false)
|
118
|
+
.new(ENV["SQUARED_HOME"], prefix: "rb", common: false) # Local styles
|
116
119
|
.group("ruby", "default", run: "rake build", copy: "rake install", clean: "rake clean", ref: :ruby, override: {
|
117
120
|
pathname: {
|
118
|
-
run: "rake compile"
|
121
|
+
run: "rake compile" # rake rb:pathname:build
|
119
122
|
}
|
120
123
|
})
|
121
|
-
.with(:python) do
|
122
|
-
banner([:name, ": ", :version], "path")
|
123
|
-
doc("make html")
|
124
|
-
run(false)
|
125
|
-
exclude(%i[base git])
|
126
|
-
add("android-docs", "android")
|
127
|
-
add("chrome-docs", "chrome")
|
128
|
-
end
|
124
|
+
.with(:python) do # ref=Symbol | group=String
|
125
|
+
banner([:name, ": ", :version], "path") # chrome-docs: 0.1.0 | /workspaces/chrome-docs
|
126
|
+
doc("make html") # rake rb:doc:python
|
127
|
+
run(false) # rake rb:build:python (disabled)
|
128
|
+
exclude(%i[base git]) # Project::Git.ref (superclass)
|
129
|
+
add("android-docs", "android") # rake rb:android:doc
|
130
|
+
add("chrome-docs", "chrome") # rake rb:chrome:doc
|
131
|
+
end
|
129
132
|
.style("inline", "bold")
|
130
133
|
.build
|
131
134
|
```
|
132
135
|
|
133
136
|
**NOTE**: The use of "**ref**" (class name) is only necessary when initializing an empty directory (e.g. *rake repo:init*).
|
134
137
|
|
138
|
+
### Clone
|
139
|
+
|
140
|
+
The task is only active when the project directory is empty or does not exist.
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
Workspace::Application
|
144
|
+
.new(main: "squared")
|
145
|
+
.git(
|
146
|
+
"emc": "https://github.com/anpham6/e-mc", # rake emc:clone
|
147
|
+
"pir": { # rake pir:clone
|
148
|
+
uri: "https://github.com/anpham6/pi-r", #
|
149
|
+
options: { #
|
150
|
+
"origin": "github", # --origin='github'
|
151
|
+
"recurse-submodules": false, # --no-recurse-submodules
|
152
|
+
"shallow-exclude": ["v0.0.1", "v0.0.2"] # --shallow-exclude='v0.0.1' --shallow-exclude='v0.0.2'
|
153
|
+
}
|
154
|
+
}
|
155
|
+
)
|
156
|
+
.git("squared", "/path/to/squared", options: { local: true }) # Relative paths resolve from workspace root
|
157
|
+
.git(
|
158
|
+
{
|
159
|
+
emc: { uri: "e-mc", options: { "depth": 2 } }, # https://github.com/anpham6/e-mc
|
160
|
+
pir: "pi-r" # Maps task alias to repository folder
|
161
|
+
},
|
162
|
+
base: "https://github.com/anpham6", # Required
|
163
|
+
repo: ["squared", "android-docs", "chrome-docs"], # https://github.com/anpham6/squared
|
164
|
+
options: { # Only "repo"
|
165
|
+
"depth": 1,
|
166
|
+
"quiet": true
|
167
|
+
}
|
168
|
+
)
|
169
|
+
.with(:node) do # rake clone:node
|
170
|
+
add("e-mc", "emc") # https://github.com/anpham6/e-mc
|
171
|
+
add("pi-r", "pir") # https://github.com/anpham6/pi-r
|
172
|
+
add("squared") # https://github.com/anpham6/squared
|
173
|
+
end
|
174
|
+
.with(:python) do # rake clone:python
|
175
|
+
add("android-docs")
|
176
|
+
add("chrome-docs")
|
177
|
+
end
|
178
|
+
.git("https://github.com/anpham6") # Uses already defined root projects
|
179
|
+
.git("https://github.com/anpham6", ["emc", "pir"]) # Targets any defined project
|
180
|
+
.build(parallel: ["clone"]) # rake clone + rake clone:sync
|
181
|
+
```
|
182
|
+
|
135
183
|
### Graph
|
136
184
|
|
137
185
|
```ruby
|
@@ -143,17 +191,30 @@ Workspace::Application
|
|
143
191
|
add("chrome-docs", "chrome", graph: "android")
|
144
192
|
end
|
145
193
|
.with(:node) do
|
146
|
-
graph(["build", "copy"]
|
147
|
-
|
148
|
-
|
194
|
+
graph(["build", "copy"], on: { # Overrides "git"
|
195
|
+
first: proc { puts "1" },
|
196
|
+
last: proc { puts "2" }
|
197
|
+
})
|
198
|
+
add("e-mc", "emc") do
|
199
|
+
first("build", "emc:clean", "emc:depend") # rake emc:clean; rake emc:depend; rake emc:build; puts "123";
|
200
|
+
last("build", out: "123") { |out: nil| puts out } #
|
201
|
+
error("build") { |err: nil| log.debug err } #
|
202
|
+
end
|
203
|
+
add("pi-r", "pir", graph: "emc", first: {
|
204
|
+
build: proc { puts self.name } # puts "pir"
|
205
|
+
})
|
149
206
|
add("squared-express", "express", graph: "pir")
|
150
|
-
add("squared", graph: ["chrome", "express"])
|
207
|
+
add("squared", graph: ["chrome", "express"]) do
|
208
|
+
first("git:ls-files") { puts path }
|
209
|
+
last("git:ls-files") { puts workspace.root }
|
210
|
+
end
|
151
211
|
end
|
152
212
|
.with(:ruby) do
|
153
213
|
add("pathname")
|
154
214
|
add("fileutils", graph: "pathname")
|
155
215
|
add("optparse")
|
156
216
|
add("rake", graph: ["fileutils", "optparse"])
|
217
|
+
banner(command: false) # Always hide banner
|
157
218
|
end
|
158
219
|
.build
|
159
220
|
```
|
@@ -188,27 +249,30 @@ Workspace::Series.rename("depend", "install")
|
|
188
249
|
## Usage
|
189
250
|
|
190
251
|
```sh
|
191
|
-
rake -T
|
192
|
-
rake
|
252
|
+
rake -T # List tasks
|
253
|
+
rake # rake status (usually "build")
|
193
254
|
|
194
255
|
# GIT_OPTIONS=rebase
|
195
|
-
rake pull
|
196
|
-
rake pull:ruby
|
197
|
-
rake pull:default
|
198
|
-
rake pull:app
|
199
|
-
rake pull:node
|
200
|
-
|
201
|
-
rake build
|
202
|
-
rake doc
|
203
|
-
rake depend
|
204
|
-
|
205
|
-
rake build:ruby
|
206
|
-
|
207
|
-
rake clean
|
208
|
-
rake clean:ruby
|
209
|
-
rake clean:default
|
210
|
-
rake clean:app
|
211
|
-
rake clean:node
|
256
|
+
rake pull # All except "default" + "app"
|
257
|
+
rake pull:ruby # pathname + optparse + logger
|
258
|
+
rake pull:default # pathname + optparse
|
259
|
+
rake pull:app # squared
|
260
|
+
rake pull:node # emc + pir + squared
|
261
|
+
|
262
|
+
rake build # All except "android"
|
263
|
+
rake doc # optparse + android
|
264
|
+
rake depend # All except "default"
|
265
|
+
|
266
|
+
rake build:ruby # rake compile + rake install + rake install
|
267
|
+
|
268
|
+
rake clean # All except "default" + "app"
|
269
|
+
rake clean:ruby # rake clean + rake clean + ["tmp/"]
|
270
|
+
rake clean:default # rake clean + rake clean + skip
|
271
|
+
rake clean:app # none + skip + ["build/"]
|
272
|
+
rake clean:node # none + ["publish/**/*.js", "tmp/"] + ["build/"]
|
273
|
+
|
274
|
+
rake squared:run[#] # List scripts (node)
|
275
|
+
rake squared:rake[#] # List tasks (ruby)
|
212
276
|
```
|
213
277
|
|
214
278
|
```sh
|
@@ -242,6 +306,7 @@ Non-task:
|
|
242
306
|
* header
|
243
307
|
* active
|
244
308
|
* inline
|
309
|
+
* current
|
245
310
|
* major
|
246
311
|
* red
|
247
312
|
* yellow
|
@@ -249,6 +314,21 @@ Non-task:
|
|
249
314
|
|
250
315
|
## Environment
|
251
316
|
|
317
|
+
### Path
|
318
|
+
|
319
|
+
All project executable programs can have their binary path set to a non-global alias.
|
320
|
+
|
321
|
+
```ruby
|
322
|
+
Common::PATH.merge!({
|
323
|
+
GIT: '/usr/bin/git',
|
324
|
+
GEM: '~/.rvm/rubies/ruby-3.4.0/bin/gem',
|
325
|
+
BUNDLE: '~/.rvm/gems/ruby-3.4.0/bin/bundle',
|
326
|
+
RAKE: '~/.rvm/gems/ruby-3.4.0/bin/rake',
|
327
|
+
NPM: '/opt/node/v22.0.0/bin/npm',
|
328
|
+
PYTHON: "#{ENV['PYTHONPATH']}/bin/python"
|
329
|
+
})
|
330
|
+
```
|
331
|
+
|
252
332
|
### Build
|
253
333
|
|
254
334
|
```ruby
|
data/lib/squared/app.rb
CHANGED
data/lib/squared/common/base.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
module Squared
|
4
4
|
module Common
|
5
|
+
PATH = {}
|
5
6
|
ARG = {
|
6
7
|
PIPE: 1,
|
7
8
|
OUT: nil,
|
@@ -11,6 +12,7 @@ module Squared
|
|
11
12
|
BANNER: true,
|
12
13
|
SPACE: ' => ',
|
13
14
|
GRAPH: ['│', '─', '├', '└', '┬'],
|
15
|
+
VIEW: 'view',
|
14
16
|
COLOR: ENV.fetch('NO_COLOR', '').empty?
|
15
17
|
}
|
16
18
|
VAR = {
|
@@ -35,29 +37,31 @@ module Squared
|
|
35
37
|
},
|
36
38
|
theme: {
|
37
39
|
workspace: {
|
38
|
-
header:
|
39
|
-
active:
|
40
|
-
inline:
|
41
|
-
|
40
|
+
header: [:bold],
|
41
|
+
active: [:bold],
|
42
|
+
inline: [:bold],
|
43
|
+
current: nil,
|
44
|
+
major: [:bold]
|
42
45
|
},
|
43
46
|
project: {},
|
44
47
|
viewer: {
|
45
|
-
banner:
|
46
|
-
|
47
|
-
|
48
|
-
|
48
|
+
banner: [:bold],
|
49
|
+
border: [:blue],
|
50
|
+
key: nil,
|
51
|
+
value: [:green],
|
52
|
+
string: [:yellow],
|
49
53
|
hash: %i[green black!],
|
50
54
|
array: %i[blue black!],
|
51
|
-
number:
|
55
|
+
number: [:magenta],
|
52
56
|
undefined: %i[red italic]
|
53
57
|
},
|
54
58
|
logger: {
|
55
|
-
unknown:
|
59
|
+
unknown: [:cyan],
|
56
60
|
fatal: %i[white bold red!],
|
57
61
|
error: %i[red bold],
|
58
62
|
warn: %i[yellow bold],
|
59
|
-
info:
|
60
|
-
debug:
|
63
|
+
info: [:blue],
|
64
|
+
debug: [:green]
|
61
65
|
}
|
62
66
|
}
|
63
67
|
}.compare_by_identity
|
@@ -76,6 +80,7 @@ module Squared
|
|
76
80
|
end
|
77
81
|
|
78
82
|
def __freeze__
|
83
|
+
PATH.freeze
|
79
84
|
ARG.freeze
|
80
85
|
VAR.each_value(&:freeze)
|
81
86
|
VAR[:theme].each_value(&:freeze)
|
@@ -84,7 +89,7 @@ module Squared
|
|
84
89
|
|
85
90
|
module_function
|
86
91
|
|
87
|
-
def as_a(obj, meth = nil, flat: nil, compact: false)
|
92
|
+
def as_a(obj, meth = nil, flat: nil, compact: false, &blk)
|
88
93
|
return [] if obj.nil?
|
89
94
|
|
90
95
|
unless obj.is_a?(::Array)
|
@@ -96,7 +101,8 @@ module Squared
|
|
96
101
|
end
|
97
102
|
obj = obj.flatten(flat.is_a?(::Numeric) ? flat : nil) if flat
|
98
103
|
obj = obj.compact if compact
|
99
|
-
|
104
|
+
obj = obj.map(&meth) if meth
|
105
|
+
block_given? ? obj.select(&blk) : obj
|
100
106
|
end
|
101
107
|
end
|
102
108
|
end
|
data/lib/squared/common/class.rb
CHANGED
@@ -34,11 +34,28 @@ module Squared
|
|
34
34
|
super.match(/[^:]+\z/)[0]
|
35
35
|
end
|
36
36
|
|
37
|
+
attr_reader :delim
|
38
|
+
|
37
39
|
def initialize(data = [], delim: ' ')
|
38
40
|
super(data.compact)
|
39
41
|
@delim = delim
|
40
42
|
end
|
41
43
|
|
44
|
+
def pass(&blk)
|
45
|
+
ret = to_a.map!(&:to_s).reject(&:empty?)
|
46
|
+
block_given? ? ret.reject(&blk) : ret
|
47
|
+
end
|
48
|
+
|
49
|
+
def temp(*args, &blk)
|
50
|
+
args.compact!
|
51
|
+
ret = pass(&blk)
|
52
|
+
unless args.empty?
|
53
|
+
ret += args
|
54
|
+
ret = Set.new(ret).to_a
|
55
|
+
end
|
56
|
+
ret.join(@delim)
|
57
|
+
end
|
58
|
+
|
42
59
|
def done
|
43
60
|
ret = to_s
|
44
61
|
clear
|
@@ -46,7 +63,7 @@ module Squared
|
|
46
63
|
end
|
47
64
|
|
48
65
|
def to_s
|
49
|
-
|
66
|
+
pass.join(@delim)
|
50
67
|
end
|
51
68
|
end
|
52
69
|
end
|
@@ -138,15 +138,15 @@ module Squared
|
|
138
138
|
def log_sym(level)
|
139
139
|
if level.is_a?(::Numeric)
|
140
140
|
case level
|
141
|
-
when
|
141
|
+
when Logger::DEBUG
|
142
142
|
:debug
|
143
|
-
when
|
143
|
+
when Logger::INFO
|
144
144
|
:info
|
145
|
-
when
|
145
|
+
when Logger::WARN
|
146
146
|
:warn
|
147
|
-
when
|
147
|
+
when Logger::ERROR
|
148
148
|
:error
|
149
|
-
when
|
149
|
+
when Logger::FATAL
|
150
150
|
:fatal
|
151
151
|
else
|
152
152
|
:unknown
|
@@ -185,10 +185,10 @@ module Squared
|
|
185
185
|
end
|
186
186
|
|
187
187
|
def puts_oe(*args, pipe: 1)
|
188
|
-
if pipe.is_a?(
|
188
|
+
if pipe.is_a?(Pathname)
|
189
189
|
begin
|
190
|
-
|
191
|
-
br =
|
190
|
+
File.open(pipe, 'a') do |f|
|
191
|
+
br = File::SEPARATOR == '\\' ? "\r\n" : "\n"
|
192
192
|
args.flatten.each { |val| f.write("#{strip_style(val.chomp)}#{br}") }
|
193
193
|
end
|
194
194
|
return
|
@@ -279,7 +279,7 @@ module Squared
|
|
279
279
|
end
|
280
280
|
|
281
281
|
def raise_error(*args, hint: nil, kind: ArgumentError)
|
282
|
-
raise kind, message(*args, hint: hint, empty: true)
|
282
|
+
raise kind, message(*args, hint: hint, empty: true), caller_locations(1)
|
283
283
|
end
|
284
284
|
end
|
285
285
|
end
|
data/lib/squared/common/shell.rb
CHANGED
@@ -27,7 +27,7 @@ module Squared
|
|
27
27
|
|
28
28
|
def shell_quote(val, force: true)
|
29
29
|
val = val.to_s
|
30
|
-
return val if (!force && !val.include?(' ')) || val
|
30
|
+
return val if (!force && !val.include?(' ')) || val.match?(/(?:^|\S=|[^=]\s+)(["']).+\1\z/m)
|
31
31
|
|
32
32
|
Rake::Win32.windows? ? "\"#{double_quote(val)}\"" : "'#{single_quote(val)}'"
|
33
33
|
end
|
@@ -40,13 +40,14 @@ module Squared
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def shell_option(flag, val = nil, quote: false, escape: true)
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
43
|
+
a, b = flag.size == 1 ? ['-', ' '] : ['--', '=']
|
44
|
+
"#{a}#{flag}#{if val
|
45
|
+
"#{b}#{if escape
|
46
|
+
shell_escape(val, quote: quote)
|
47
|
+
else
|
48
|
+
quote ? shell_quote(val) : val
|
49
|
+
end}"
|
50
|
+
end}"
|
50
51
|
end
|
51
52
|
|
52
53
|
def fill_option(val)
|
@@ -55,6 +56,14 @@ module Squared
|
|
55
56
|
shell_escape(val.start_with?('-') ? val : "--#{val}")
|
56
57
|
end
|
57
58
|
|
59
|
+
def quote_option(flag, val)
|
60
|
+
shell_option(flag, val, escape: false, quote: true)
|
61
|
+
end
|
62
|
+
|
63
|
+
def basic_option(flag, val)
|
64
|
+
shell_option(flag, val, escape: false)
|
65
|
+
end
|
66
|
+
|
58
67
|
def single_quote(val)
|
59
68
|
val.gsub("'", "'\\\\''")
|
60
69
|
end
|
@@ -20,44 +20,80 @@ module Squared
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
src =
|
25
|
-
dest =
|
23
|
+
def copy_dir(src, dest, glob = ['**/*'], create: false, link: nil, force: false, pass: nil, verbose: true)
|
24
|
+
src = Pathname.new(src)
|
25
|
+
dest = Pathname.new(dest)
|
26
26
|
raise "#{dest} (not found)" if !create && !dest.parent.exist?
|
27
27
|
|
28
|
-
subdir =
|
29
|
-
files = 0
|
28
|
+
subdir = {}
|
30
29
|
dest.mkpath if create
|
31
30
|
if pass
|
32
31
|
exclude = []
|
33
|
-
|
32
|
+
pass = [pass] unless pass.is_a?(::Array)
|
33
|
+
pass.each { |val| exclude += Dir.glob(src.join(val)) }
|
34
34
|
end
|
35
35
|
(glob.is_a?(::Array) ? glob : [glob]).each do |val|
|
36
|
-
|
37
|
-
next if exclude&.include?(path) || (path =
|
36
|
+
Dir.glob(src.join(val)) do |path|
|
37
|
+
next if exclude&.include?(path) || (path = Pathname.new(path)).directory?
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
dir = dest.join(path.relative_path_from(src)).dirname
|
40
|
+
if (data = subdir[dir.to_s])
|
41
|
+
data << path
|
42
|
+
else
|
42
43
|
dir.mkpath
|
43
|
-
subdir
|
44
|
+
subdir[dir.to_s] = [path]
|
44
45
|
end
|
45
|
-
copy_f path, target
|
46
|
-
files += 1
|
47
46
|
end
|
48
47
|
end
|
49
|
-
|
48
|
+
count = 0
|
49
|
+
soft = 0
|
50
|
+
subdir.each do |dir, files|
|
51
|
+
if link
|
52
|
+
items = files.dup
|
53
|
+
files.clear
|
54
|
+
items.each do |file|
|
55
|
+
if file.exist?
|
56
|
+
if file.symlink?
|
57
|
+
next unless force
|
58
|
+
else
|
59
|
+
files << file
|
60
|
+
next
|
61
|
+
end
|
62
|
+
end
|
63
|
+
if link == 'hard'
|
64
|
+
FileUtils.ln(file, dir, force: force, verbose: false)
|
65
|
+
else
|
66
|
+
FileUtils.ln_s(file, dir, force: force, verbose: false)
|
67
|
+
end
|
68
|
+
soft += 1
|
69
|
+
end
|
70
|
+
end
|
71
|
+
next if files.empty?
|
72
|
+
|
73
|
+
out = FileUtils.cp(files, dir, verbose: false)
|
74
|
+
count += out.size
|
75
|
+
end
|
76
|
+
puts [dest.realpath, subdir.size, soft > 0 ? "#{count}+#{soft}" : count].join(' => ') if verbose
|
50
77
|
end
|
51
78
|
|
52
|
-
def
|
53
|
-
unless
|
54
|
-
if (path =
|
55
|
-
src =
|
79
|
+
def copy_guard(src, dest, link: nil, force: false, verbose: true)
|
80
|
+
unless force
|
81
|
+
if (path = Pathname.new(dest)).directory?
|
82
|
+
src = [src] unless src.is_a?(::Array)
|
83
|
+
src = src.reject { |val| path.join(File.basename(val)).exist? }
|
84
|
+
return if src.empty?
|
56
85
|
elsif path.exist?
|
57
86
|
return
|
58
87
|
end
|
59
88
|
end
|
60
|
-
|
89
|
+
case link
|
90
|
+
when 'hard', 1
|
91
|
+
FileUtils.ln(src, dest, force: force, verbose: verbose)
|
92
|
+
when true, 'soft', 0
|
93
|
+
FileUtils.ln_s(src, dest, force: force, verbose: verbose)
|
94
|
+
else
|
95
|
+
FileUtils.cp(src, dest, verbose: verbose)
|
96
|
+
end
|
61
97
|
end
|
62
98
|
end
|
63
99
|
end
|