monofile 0.1.0 → 0.2.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 460899daff3c93d15ae49ed3163f2c56bb7e15e9
4
- data.tar.gz: 7b3e215fe00027e3f4b85e107f30029e048b6e35
3
+ metadata.gz: dc46a512fd3305af7a7d3949bdfe049de0e1e238
4
+ data.tar.gz: f152af472841c5145d37ca45f54504fbb48e6f3a
5
5
  SHA512:
6
- metadata.gz: 6aa5bf5125f770f42d2063d62991779cf7cde8ed06c5752dcd8cd1a3f84556e438b638246884e826951e56219125fafda1e2f00bcb7525fa405f8cc4608996ab
7
- data.tar.gz: 4b1452d92bd1e7104fe8f918596978661bdbf3997ab9121327e7ed4527269bdc1ac04d3db4007408582710fdaf74a50691cebda387c645127ac3d9f5f983321c
6
+ metadata.gz: 83b933f57ceab663f8186d1fd8f99737bebc1f35ecde411b44f4a24d6dc3476b510376d7194f77f68f9d9f5537919e00c7fcf66aedc2a22ce90e37fa75f840ea
7
+ data.tar.gz: 73acb18f7deb86cc6e4669459c4f531b98cdd7c248c12f36c820577550fcc1ba4eeebc65edbac2ba2fb9f0b697fe73f0b028c828c9f0c420d9c225b3be3b27fa
@@ -4,4 +4,9 @@ README.md
4
4
  Rakefile
5
5
  bin/monofile
6
6
  lib/monofile.rb
7
+ lib/monofile/monofile.rb
8
+ lib/monofile/mononame.rb
9
+ lib/monofile/tool.rb
7
10
  lib/monofile/version.rb
11
+ test/helper.rb
12
+ test/test_names.rb
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
- # monofile - read in/ parse mono (source) tree defintions with git (and github) projects, and more
1
+ # monofile - read in / parse monorepo / mono source tree definitions - a list of git (and github) projects, and more
2
2
 
3
- * home :: [github.com/rubycoco/git](https://github.com/rubycoco/git)
4
- * bugs :: [github.com/rubycoco/git/issues](https://github.com/rubycoco/git/issues)
3
+ * home :: [github.com/rubycoco/monos](https://github.com/rubycoco/monos)
4
+ * bugs :: [github.com/rubycoco/monos/issues](https://github.com/rubycoco/monos/issues)
5
5
  * gem :: [rubygems.org/gems/monofile](https://rubygems.org/gems/monofile)
6
6
  * rdoc :: [rubydoc.info/gems/monofile](http://rubydoc.info/gems/monofile)
7
7
 
@@ -9,7 +9,127 @@
9
9
 
10
10
  ## Usage
11
11
 
12
- To be done
12
+
13
+ Use `Monofile.read` to read in / parse monorepo / mono source tree definitions - supporting a ruby or a yaml format.
14
+
15
+
16
+ Example - `Monofile`:
17
+ ``` ruby
18
+ project "@openfootball/england"
19
+ project "@openfootball/world-cup"
20
+ project "@geraldb/austria"
21
+ project "@geraldb/geraldb.github.io"
22
+
23
+ project "geraldb", "catalog"
24
+ project "openfootball", "europe"
25
+ project "openfootball", "south-america"
26
+ ```
27
+
28
+ or
29
+
30
+ Example - `monofile.yml`:
31
+
32
+ ``` yaml
33
+ geraldb:
34
+ - austria
35
+ - catalog
36
+ - geraldb.github.io
37
+
38
+ openfootball:
39
+ - england
40
+ - europe
41
+ - south-america
42
+ - world-cup
43
+ ```
44
+
45
+
46
+ To read use.
47
+
48
+ ``` ruby
49
+ monofile = Monofile.read( "./Monofile" )
50
+ # -or-
51
+ monofile = Monofile.read( "./monofile.yml" )
52
+ pp monofile.to_a
53
+ #=> ["@openfootball/england",
54
+ # "@openfootball/world-cup",
55
+ # "@geraldb/austria",
56
+ # "@geraldb/geraldb.github.io",
57
+ # "@geraldb/catalog",
58
+ # "@openfootball/europe"]
59
+ # "@openfootball/south-america"]
60
+
61
+ pp monofile.to_h
62
+ #=> {"openfootball"=>["england", "world-cup", "europe", "south-america"],
63
+ # "geraldb" =>["austria", "geraldb.github.io", "catalog"]}
64
+
65
+ monofile.each do |proj|
66
+ puts " #{proj}"
67
+ end
68
+ #=> @openfootball/england
69
+ # @openfootball/world-cup
70
+ # @geraldb/austria
71
+ # @geraldb/geraldb.github.io
72
+ # @geraldb/catalog
73
+ # @openfootball/europe
74
+ # @openfootball/south-america
75
+
76
+ monofile.size
77
+ #=> 7
78
+ ```
79
+
80
+ and so on. That's it for now.
81
+
82
+
83
+
84
+ ### Troubleshooting / Debugging
85
+
86
+ Use the `monofile` command line tool to test reading in of
87
+ monorepo / mono source tree definitions.
88
+ Example:
89
+
90
+ ``` shell
91
+ # option 1) try to find default name (e.g. Monofile, Monofile.rb, etc.)
92
+ $ monofile
93
+
94
+ # option 2) pass in monofiles
95
+ $ monofile ./Monofile
96
+ $ monofile ./monfile.yml
97
+ # ...
98
+ ```
99
+
100
+ Printing the normalized / canonical names of the repo sources. Example.
101
+
102
+ ```
103
+ @openfootball/england
104
+ @openfootball/world-cup
105
+ @geraldb/austria
106
+ @geraldb/geraldb.github.io
107
+ @geraldb/catalog
108
+ @openfootball/europe
109
+ @openfootball/south-america
110
+ ```
111
+
112
+
113
+
114
+
115
+ ## Real-World Usage
116
+
117
+ See the [`monos`](https://github.com/rubycoco/monos/tree/master/monos) package that incl. the `mono` (or short `mo`)
118
+ command line tool lets you run
119
+ git commands on multiple repo(sitories) with a single command.
120
+
121
+
122
+ ## Installation
123
+
124
+ Use
125
+
126
+ gem install monofile
127
+
128
+ or add to your Gemfile
129
+
130
+ gem 'monofile'
131
+
132
+
13
133
 
14
134
  ## License
15
135
 
data/Rakefile CHANGED
@@ -6,10 +6,10 @@ Hoe.spec 'monofile' do
6
6
 
7
7
  self.version = Mono::Module::Monofile::VERSION
8
8
 
9
- self.summary = "monofile - read in/ parse mono (source) tree defintions with git (and github) projects, and more"
9
+ self.summary = "monofile - read in / parse monorepo / mono source tree definitions - a list of git (and github) projects, and more"
10
10
  self.description = summary
11
11
 
12
- self.urls = { home: 'https://github.com/rubycoco/git' }
12
+ self.urls = { home: 'https://github.com/rubycoco/monos' }
13
13
 
14
14
  self.author = 'Gerald Bauer'
15
15
  self.email = 'opensport@googlegroups.com'
@@ -13,14 +13,16 @@ require 'net/http'
13
13
  require 'net/https'
14
14
 
15
15
 
16
- require 'optparse'
16
+ require 'optparse' ## used by monofile (built-in test/debug) command line tool
17
17
 
18
18
 
19
19
 
20
20
  #####################
21
21
  # our own code
22
22
  require 'monofile/version' # note: let version always go first
23
-
23
+ require 'monofile/mononame'
24
+ require 'monofile/monofile'
25
+ require 'monofile/tool'
24
26
 
25
27
 
26
28
 
@@ -46,291 +48,17 @@ module Mono
46
48
  ## use expand path to make (assure) absolute path - why? why not?
47
49
  @@root = File.expand_path( path )
48
50
  end
49
-
50
-
51
-
52
- def self.monofile
53
- path = Monofile.find
54
- Monofile.read( path )
55
-
56
- # if path
57
- # GitRepoSet.read( path )
58
- # else
59
- # puts "!! WARN: no mono configuration file found; looking for #{MONOFILES.join(', ')} in (#{Dir.getwd})"
60
- # GitRepoSet.new( {} ) ## return empty set -todo/check: return nil - why? why not?
61
- # end
62
- end
63
51
  end ## module Mono
64
52
 
65
53
 
66
54
 
67
55
 
68
-
69
- class Monofile
70
- ## holds a list of projects
71
-
72
- ## nested class
73
- class Project
74
-
75
- ## use some different names / attributes ??
76
- attr_reader :org, ## todo/check: find a different name (or add alias e.g. login/user/etc.)
77
- :name
78
-
79
- ## todo/fix:
80
- ## - use *args and than split if args==2 or args==1 etc.
81
- def initialize( *args )
82
- if args.size == 2 && args[0].is_a?(String) && args[1].is_a?(String)
83
- ## assume [org, name]
84
- @org = args[0]
85
- @name = args[1]
86
- elsif args.size == 1 && args[0].is_a?( String )
87
- ## todo/fix: use norm_name parser or such!!!!
88
- parts = args[0].split( '/' )
89
- @org = parts[0][1..-1] ## cut-off leading @ (always assume for now!!)
90
- @name = parts[1]
91
- else
92
- raise ArgumentError, "[Monorepo::Project] one or two string args expected; got: #{args.pretty_inspect}"
93
- end
94
- end
95
-
96
- def to_s() "@#{org}/#{name}"; end
97
- def to_path() "#{org}/#{name}"; end
98
-
99
- ## add clone_ssh_url or such too!!!!
100
- end ## (nested) class Project
101
-
102
-
103
-
104
- class Builder ## "clean room" pattern/spell - keep accessible methods to a minimum (by eval in "cleanroom")
105
- def initialize( monofile )
106
- @monofile = monofile
107
- end
108
-
109
- def project( *args )
110
- project = Project.new( *args )
111
- @monofile.projects << project
112
- end
113
- end # (nested) class Builder
114
-
115
-
116
-
117
- RUBY_NAMES = ['monofile',
118
- 'Monofile',
119
- 'monofile.rb',
120
- 'Monofile.rb',
121
- ]
122
-
123
- TXT_NAMES = ['monofile.txt',
124
- 'monotree.txt', ## keep monotree - why? why not?
125
- 'monorepo.txt',
126
- 'repos.txt']
127
-
128
- ## note: yaml always requires an extension
129
- YML_NAMES = ['monofile.yml', 'monofile.yaml',
130
- 'monotree.yml', 'monotree.yaml', ## keep monotree - why? why not?
131
- 'monorepo.yml', 'monorepo.yaml',
132
- 'repos.yml', 'repos.yaml',
133
- ] ## todo/check: add mono.yml too - why? why not?
134
-
135
- NAMES = RUBY_NAMES + TXT_NAMES + YML_NAMES
136
-
137
-
138
- def self.find
139
- RUBY_NAMES.each do |name|
140
- return "./#{name}" if File.exist?( "./#{name}")
141
- end
142
-
143
- TXT_NAMES.each do |name|
144
- return "./#{name}" if File.exist?( "./#{name}")
145
- end
146
-
147
- YML_NAMES.each do |name|
148
- return "./#{name}" if File.exist?( "./#{name}")
149
- end
150
-
151
- nil ## no monofile found; return nil
152
- end
153
-
154
-
155
- def self.read( path )
156
- txt = File.open( path, 'r:utf-8') { |f| f.read }
157
-
158
- ## check for yml or yaml extension;
159
- ## or for txt extension; otherwise assume ruby
160
- extname = File.extname( path ).downcase
161
- if ['.yml', '.yaml'].include?( extname )
162
- hash = YAML.load( txt )
163
- new( hash )
164
- elsif ['.txt'].include?( extname )
165
- new( txt )
166
- else ## assume ruby code (as text in string)
167
- new().load( txt )
168
- end
169
- end
170
-
171
-
172
-
173
- def self.load( code )
174
- monofile = new
175
- monofile.load( code )
176
- monofile
177
- end
178
-
179
- def self.load_file( path ) ## keep (or add load_yaml to or such) - why? why not?
180
- code = File.open( path, 'r:utf-8') { |f| f.read }
181
- load( code )
182
- end
183
-
184
-
185
- ### attr readers
186
- def projects() @projects; end
187
- def size() @projects.size; end
188
-
189
-
190
- def initialize( obj={} ) ## todo/fix: change default to obj=[]
191
- @projects = []
192
-
193
- ## puts "[debug] obj.class=#{obj.class.name}"
194
- add( obj )
195
- end
196
-
197
- def load( code ) ## note: code is text as a string
198
- builder = Builder.new( self )
199
- builder.instance_eval( code )
200
- self ## note: for chaining always return self
201
- end
202
-
203
-
204
- def add( obj )
205
- ## todo/check: check for proc too! and use load( proc/block ) - possible?
206
- if obj.is_a?( String )
207
- puts "sorry add String - to be done!!!"
208
- exit 1
209
- elsif obj.is_a?( Array )
210
- puts "sorry add Array- to be done!!!"
211
- exit 1
212
- elsif obj.is_a?( Hash )
213
- add_hash( obj )
214
- else ## assume text (evaluate/parse)
215
- puts "sorry add Text - to be done!!!"
216
- exit 1
217
- end
218
- self ## note: return self for chaining
219
- end
220
-
221
-
222
- def add_hash( hash )
223
- hash.each do |org_with_counter, names|
224
-
225
- ## remove optional number from key e.g.
226
- ## mrhydescripts (3) => mrhydescripts
227
- ## footballjs (4) => footballjs
228
- ## etc.
229
-
230
- ## todo/check: warn about duplicates or such - why? why not?
231
-
232
- org = org_with_counter.sub( /\([0-9]+\)/, '' ).strip.to_s
233
-
234
- names.each do |name|
235
- @projects << Project.new( org, name )
236
- end
237
- end
238
-
239
- self ## note: return self for chaining
240
- end
241
-
242
-
243
-
244
- def each( &block )
245
- ## puts "[debug] arity: #{block.arity}"
246
-
247
- ## for backwards compatibility support "old" each with/by org & names
248
- ## add deprecated warnings and use to_h or such - why? why not?
249
- if block.arity == 2
250
- puts "!! DEPRECATED - please, use Monofile#to_h or Monofile.each {|proj| ...}"
251
- to_h.each do |org, names|
252
- block.call( org, names )
253
- end
254
- else
255
- ## assume just regular
256
- @projects.each do |project|
257
- block.call( project )
258
- end
259
- end
260
- end # method each
261
-
262
- def each_with_index( &block )
263
- @projects.each_with_index do |project,i|
264
- block.call( project, i )
265
- end
266
- end
267
-
268
-
269
-
270
- ### for backward compat(ibility) add a hash in the form e.g:
271
- ##
272
- ## geraldb:
273
- ## - austria
274
- ## - catalog
275
- ## - geraldb.github.io
276
- ## - logos
277
- ## yorobot:
278
- ## - auto
279
- ## - backup
280
- ## - football.json
281
- ## - logs
282
- ##
283
- def to_h
284
- h = {}
285
- @projects.each do |project|
286
- h[ project.org ] ||= []
287
- h[ project.org ] << project.name
288
- end
289
- h
290
- end
291
-
292
- def to_a
293
- ## todo/check:
294
- ## - sort all entries a-z - why? why not?
295
- ## - always start name with @ marker - why? why not?
296
- @projects.map {|project| project.to_s }
297
- end
298
- end # class Monofile
299
-
300
-
301
-
302
-
303
-
304
- class Monofile
305
- class Tool
306
- def self.main( args=ARGV )
307
-
308
- path = Monofile.find
309
- if path.nil?
310
- puts "!! ERROR: no mono configuration file found; looking for #{Monofile::NAMES.join(', ')} in (#{Dir.getwd})"
311
- exit 1
312
- end
313
-
314
- ## add check for auto-require (e.g. ./config.rb)
315
- config_path = "./config.rb"
316
- if File.exist?( config )
317
- puts "[monofile] auto-require >#{config_path}<..."
318
- require( config_path )
319
- end
320
-
321
- puts "[monofile] reading >#{path}<..."
322
- monofile=Monofile.read( path )
323
- pp monofile
324
-
325
- ## print one project per line
326
- puts "---"
327
- monofile.each do |proj|
328
- puts proj.to_s
329
- end
330
- end
331
- end # (nested) class Tool
332
- end # class Monofile
56
+ ###
57
+ ## add some convenience alias for alternate spelling (CamelCase)
58
+ MonoName = Mononame
59
+ MonoPath = Monopath
60
+ MonoFile = Monofile
333
61
 
334
62
 
335
- Mono::Module::Monofile.banner
63
+ puts Mono::Module::Monofile.banner ## say hello
336
64
 
@@ -0,0 +1,251 @@
1
+
2
+ class Monofile
3
+ ## holds a list of projects
4
+
5
+ ## nested class
6
+ class Project ## todo/fix: change to Monoproject/MonoProject - why? why not?
7
+ def initialize( *args )
8
+ if args.size == 1 && args[0].is_a?( String )
9
+ @name = Mononame.parse( args[0] )
10
+ elsif args.size == 2 && args[0].is_a?(String) && args[1].is_a?(String)
11
+ ## assume [org, name]
12
+ @name = Mononame.new( *args )
13
+ else
14
+ raise ArgumentError, "[MonoProject] one or two string args expected; got: #{args.inspect}"
15
+ end
16
+ end
17
+
18
+ def org() @name.org; end
19
+ def name() @name.name; end
20
+
21
+ def to_path() @name.to_path; end
22
+ def to_s() @name.to_s; end
23
+
24
+ ## add clone_ssh_url or such too!!!!
25
+ end ## (nested) class Project
26
+
27
+
28
+
29
+ class Builder ## "clean room" pattern/spell - keep accessible methods to a minimum (by eval in "cleanroom")
30
+ def initialize( monofile )
31
+ @monofile = monofile
32
+ end
33
+
34
+ def project( *args )
35
+ ## auto-convert symbols to string
36
+ args = args.map do |arg|
37
+ arg.is_a?( Symbol ) ? arg.to_s : arg
38
+ end
39
+
40
+ project = Project.new( *args )
41
+ @monofile.projects << project
42
+ end
43
+
44
+ ###
45
+ ## adding many projects at once (by batch) - keep - why? why not?
46
+ def projects( *args )
47
+ ## note: for now only support (list of) hash
48
+ ## add more later (nested array or text or such) - why? why not?
49
+ args.each do |arg|
50
+ raise ArgumentError, "expected Hash type - got: #{arg.inspect} : #{arg.class.name}" unless arg.is_a?( Hash )
51
+ end
52
+
53
+ ## pp arg
54
+ args.each do |arg|
55
+ arg.each do |org, names|
56
+ names.each do |name|
57
+ ## puts "adding #{org} #{name}"
58
+ project( org, name )
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end # (nested) class Builder
64
+
65
+
66
+
67
+
68
+ RUBY_NAMES = ['monofile',
69
+ 'Monofile',
70
+ 'monofile.rb',
71
+ 'Monofile.rb',
72
+ ]
73
+
74
+ TXT_NAMES = ['monofile.txt',
75
+ 'monotree.txt', ## keep monotree - why? why not?
76
+ 'monorepo.txt',
77
+ 'repos.txt']
78
+
79
+ ## note: yaml always requires an extension
80
+ YML_NAMES = ['monofile.yml', 'monofile.yaml',
81
+ 'monotree.yml', 'monotree.yaml', ## keep monotree - why? why not?
82
+ 'monorepo.yml', 'monorepo.yaml',
83
+ 'repos.yml', 'repos.yaml',
84
+ ] ## todo/check: add mono.yml too - why? why not?
85
+
86
+ NAMES = RUBY_NAMES + TXT_NAMES + YML_NAMES
87
+
88
+
89
+ def self.find
90
+ RUBY_NAMES.each do |name|
91
+ return "./#{name}" if File.exist?( "./#{name}")
92
+ end
93
+
94
+ TXT_NAMES.each do |name|
95
+ return "./#{name}" if File.exist?( "./#{name}")
96
+ end
97
+
98
+ YML_NAMES.each do |name|
99
+ return "./#{name}" if File.exist?( "./#{name}")
100
+ end
101
+
102
+ nil ## no monofile found; return nil
103
+ end
104
+
105
+
106
+ def self.read( path )
107
+ txt = File.open( path, 'r:utf-8') { |f| f.read }
108
+
109
+ ## check for yml or yaml extension;
110
+ ## or for txt extension; otherwise assume ruby
111
+ extname = File.extname( path ).downcase
112
+ if ['.yml', '.yaml'].include?( extname )
113
+ hash = YAML.load( txt )
114
+ new( hash )
115
+ elsif ['.txt'].include?( extname )
116
+ new( txt )
117
+ else ## assume ruby code (as text in string)
118
+ new().load( txt )
119
+ end
120
+ end
121
+
122
+
123
+
124
+ def self.load( code )
125
+ monofile = new
126
+ monofile.load( code )
127
+ monofile
128
+ end
129
+
130
+ def self.load_file( path ) ## keep (or add load_yaml to or such) - why? why not?
131
+ code = File.open( path, 'r:utf-8') { |f| f.read }
132
+ load( code )
133
+ end
134
+
135
+
136
+ ### attr readers
137
+ def projects() @projects; end
138
+ def size() @projects.size; end
139
+
140
+
141
+ def initialize( obj={} ) ## todo/fix: change default to obj=[]
142
+ @projects = []
143
+
144
+ ## puts "[debug] obj.class=#{obj.class.name}"
145
+ add( obj )
146
+ end
147
+
148
+ def load( code ) ## note: code is text as a string
149
+ builder = Builder.new( self )
150
+ builder.instance_eval( code )
151
+ self ## note: for chaining always return self
152
+ end
153
+
154
+
155
+ def add( obj )
156
+ ## todo/check: check for proc too! and use load( proc/block ) - possible?
157
+ if obj.is_a?( String )
158
+ puts "sorry add String - to be done!!!"
159
+ exit 1
160
+ elsif obj.is_a?( Array )
161
+ puts "sorry add Array- to be done!!!"
162
+ exit 1
163
+ elsif obj.is_a?( Hash )
164
+ add_hash( obj )
165
+ else ## assume text (evaluate/parse)
166
+ puts "sorry add Text - to be done!!!"
167
+ exit 1
168
+ end
169
+ self ## note: return self for chaining
170
+ end
171
+
172
+
173
+ def add_hash( hash )
174
+ hash.each do |org_with_counter, names|
175
+
176
+ ## remove optional number from key e.g.
177
+ ## mrhydescripts (3) => mrhydescripts
178
+ ## footballjs (4) => footballjs
179
+ ## etc.
180
+
181
+ ## todo/check: warn about duplicates or such - why? why not?
182
+
183
+ org = org_with_counter.sub( /\([0-9]+\)/, '' ).strip.to_s
184
+
185
+ names.each do |name|
186
+ @projects << Project.new( org, name )
187
+ end
188
+ end
189
+
190
+ self ## note: return self for chaining
191
+ end
192
+
193
+
194
+
195
+ def each( &block )
196
+ ## puts "[debug] arity: #{block.arity}"
197
+
198
+ ## for backwards compatibility support "old" each with/by org & names
199
+ ## add deprecated warnings and use to_h or such - why? why not?
200
+ if block.arity == 2
201
+ puts "!! DEPRECATED - please, use Monofile#to_h or Monofile.each {|proj| ...}"
202
+ to_h.each do |org, names|
203
+ block.call( org, names )
204
+ end
205
+ else
206
+ ## assume just regular
207
+ @projects.each do |project|
208
+ block.call( project )
209
+ end
210
+ end
211
+ end # method each
212
+
213
+ def each_with_index( &block )
214
+ @projects.each_with_index do |project,i|
215
+ block.call( project, i )
216
+ end
217
+ end
218
+
219
+
220
+
221
+ ### for backward compat(ibility) add a hash in the form e.g:
222
+ ##
223
+ ## geraldb:
224
+ ## - austria
225
+ ## - catalog
226
+ ## - geraldb.github.io
227
+ ## openfootball:
228
+ ## - england
229
+ ## - europe
230
+ ## - south-america
231
+ ## - world-cup
232
+ ##
233
+ def to_h
234
+ h = {}
235
+ @projects.each do |project|
236
+ h[ project.org ] ||= []
237
+ h[ project.org ] << project.name
238
+ end
239
+ h
240
+ end
241
+
242
+ def to_a
243
+ ## todo/check:
244
+ ## - sort all entries a-z - why? why not?
245
+ ## - always start name with @ marker - why? why not?
246
+ @projects.map {|project| project.to_s }
247
+ end
248
+ end # class Monofile
249
+
250
+
251
+
@@ -0,0 +1,176 @@
1
+ #####
2
+ # mononame (e.g. @org/hello) machinery
3
+ # turn
4
+ # - @openfootball/england/2020-21
5
+ # - 2020-21@openfootball/england
6
+ # - england/2020-21@openfootball
7
+ # => into
8
+ # - openfootball/england/2020-21
9
+
10
+
11
+
12
+
13
+ module Mono
14
+ ## shared parse/norm helper (for Name/Path)
15
+ ## - find something better - why? why not?
16
+ def self.parse_name( line )
17
+ if line.is_a?( String )
18
+ parts = line.split( '@' )
19
+ raise ArgumentError, "[Mononame] no @ found BUT required in name; got >#{line}<" if parts.size == 1
20
+ raise ArgumentError, "[Mononame] too many @ found (#{parts.size-1}) in name; got >#{line}<" if parts.size > 2
21
+
22
+ ## pass 1) rebuild (normalized) name/path
23
+ name = String.new('')
24
+ name << parts[1] ## add orgs path first - w/o leading @ - gets removed by split :-)
25
+ if parts[0].length > 0 ## has leading repo name (w/ optional path)
26
+ name << '/'
27
+ name << parts[0]
28
+ end
29
+
30
+ ## pass 2) split (normalized) name/path into components (org/name/path)
31
+ parts = name.split( '/' )
32
+
33
+ args = [parts[0], parts[1]]
34
+
35
+ more_parts = parts[2..-1] ## check for any extra (optional) path parts
36
+ args << more_parts.join( '/' ) if more_parts.size > 0
37
+
38
+ args
39
+ else
40
+ raise ArgumentError, "[Mononame] string with @ expected; got: #{line.pretty_inspect} of type #{line.class.name}"
41
+ end
42
+ end
43
+ end # module Mono
44
+
45
+
46
+
47
+ class Mononame
48
+ def self.parse( line )
49
+ values = Mono.parse_name( line )
50
+ raise ArgumentError, "[Mononame] expected two parts (org/name); got #{values.pretty_inspect}" if values.size != 2
51
+ new( *values )
52
+ end
53
+
54
+ def self.real_path( line )
55
+ ## add one-time (quick) usage convenience shortcut
56
+ mononame = parse( line )
57
+ mononame.real_path
58
+ end
59
+
60
+
61
+ ## note: org and name for now required
62
+ ## - make name optional too - why? why not?!!!
63
+ ## use some different names / attributes ??
64
+ attr_reader :org, ## todo/check: find a different name (or add alias e.g. login/user/etc.)
65
+ :name
66
+
67
+ def initialize( org, name )
68
+ if org.is_a?(String) && name.is_a?(String)
69
+ @org = org
70
+ @name = name
71
+ else
72
+ raise ArgumentError, "[Mononame] expected two strings (org, name); got >#{org}< of type #{org.class.name}, >#{name}< of type #{name.class.name}"
73
+ end
74
+ end
75
+
76
+ def to_path() "#{@org}/#{@name}"; end
77
+ def to_s() "@#{to_path}"; end
78
+
79
+ def real_path() "#{Mono.root}/#{to_path}"; end
80
+ end # class Mononame
81
+
82
+
83
+
84
+ ####
85
+ ## todo/check:
86
+ ## use as shared Mono/nomen/resource or such
87
+ # shared base class for Mononame & Monopath - why? why not?
88
+ #
89
+ # Monoloc (for location)
90
+ # Monores (for resource)
91
+ # Mono__ ??
92
+ #
93
+ # name components:
94
+ # - better name for path? - use filepath, relpath, ...
95
+
96
+
97
+
98
+ class Monopath
99
+ def self.parse( line )
100
+ values = Mono.parse_name( line )
101
+ raise ArgumentError, "[Monopath] expected three parts (org/name/path); got #{values.pretty_inspect}" if values.size != 3
102
+ new( *values )
103
+ end
104
+
105
+ def self.real_path( line )
106
+ monopath = parse( line )
107
+ monopath.real_path
108
+ end
109
+
110
+
111
+ ## note: org and name AND path for now required
112
+ ## - make name path optional too - why? why not?!!!
113
+ attr_reader :org, :name, :path
114
+
115
+ def initialize( org, name, path )
116
+ ## support/check for empty path too - why? why not?
117
+
118
+ if org.is_a?(String) && name.is_a?(String) && path.is_a?(String)
119
+ ## assume [org, name, path?]
120
+ ## note: for now assumes proper formatted strings
121
+ ## e.g. no leading @ or combined @hello/text in org
122
+ ## or name or such
123
+ ## - use parse/norm_name here too - why? why not?
124
+ @org = org
125
+ @name = name
126
+ @path = path
127
+ else
128
+ raise ArgumentError, "[Monopath] expected three strings (org, name, path); got >#{org}< of type #{org.class.name}, >#{name}< of type #{name.class.name}, >#{path}< of type #{path.class.name}"
129
+ end
130
+ end
131
+
132
+ def to_path() "#{@org}/#{@name}/#{@path}"; end
133
+ def to_s() "@#{to_path}"; end
134
+
135
+ def real_path() "#{Mono.root}/#{to_path}"; end
136
+
137
+
138
+ ## some File-like convenience helpers
139
+ ## e.g. File.exist? => Monopath.exist?
140
+ ## File.open => Monopath.open( ... ) { block }
141
+ ## etc.
142
+ def self.exist?( line )
143
+ File.exist?( real_path( line ) )
144
+ end
145
+
146
+
147
+ ## path always relative to Mono.root
148
+ ## todo/fix: use File.expand_path( path, Mono.root ) - why? why not?
149
+ ## or always enfore "absolut" path e.g. do NOT allow ../ or ./ or such
150
+ def self.open( line, mode='r:utf-8', &block )
151
+ path = real_path( line )
152
+ ## make sure path exists if we open for writing/appending - why? why not?
153
+ if mode[0] == 'w' || mode[0] == 'a'
154
+ FileUtils.mkdir_p( File.dirname( path ) ) ## make sure path exists
155
+ end
156
+
157
+ File.open( path, mode ) do |file|
158
+ block.call( file )
159
+ end
160
+ end
161
+
162
+ def self.read_utf8( line )
163
+ open( line, 'r:utf-8') { |file| file.read }
164
+ end
165
+ end # class Monopath
166
+ ## note: use Monopath - avoid confusion with Monofile (a special file with a list of mono projects)!!!!
167
+
168
+
169
+
170
+
171
+
172
+ ## todo/check: add a (global) Mono/Mononame converter - why? why not?
173
+ ##
174
+ ## module Kernel
175
+ ## def Mono( *args ) Mononame.parse( *args ); end
176
+ ## end
@@ -0,0 +1,59 @@
1
+ class Monofile
2
+ class Tool
3
+ def self.main( args=ARGV )
4
+
5
+ options = {}
6
+ OptionParser.new do |parser|
7
+ ## note:
8
+ ## you can add many/multiple modules
9
+ ## e.g. -r gitti -r mono etc.
10
+ parser.on( '-r NAME', '--require NAME') do |name|
11
+ options[:requires] ||= []
12
+ options[:requires] << name
13
+ end
14
+ ## todo/fix:
15
+ ## add --verbose
16
+ ## add -d/--debug
17
+ end.parse!( args )
18
+
19
+
20
+ if args.size == 0 ## auto-add default arg (monofile)
21
+ monofile_path = Monofile.find
22
+ if monofile_path.nil?
23
+ puts "!! ERROR: no mono configuration file found; looking for #{Monofile::NAMES.join(', ')} in (#{Dir.getwd})"
24
+ exit 1
25
+ end
26
+ args << monofile_path
27
+ end
28
+
29
+
30
+ ## add check for auto-require (e.g. ./config.rb)
31
+ if options[:requires] ## use custom (auto-)requires
32
+ options[:requires].each do |path|
33
+ puts "[monofile] auto-require >#{path}<..."
34
+ require( path )
35
+ end
36
+ else ## use/try defaults
37
+ config_path = "./config.rb"
38
+ if File.exist?( config_path )
39
+ puts "[monofile] auto-require (default) >#{config_path}<..."
40
+ require( config_path )
41
+ end
42
+ end
43
+
44
+
45
+ args.each do |path|
46
+ puts "[monofile] reading >#{path}<..."
47
+ monofile=Monofile.read( path )
48
+ pp monofile
49
+
50
+ ## print one project per line
51
+ puts "---"
52
+ monofile.each do |proj|
53
+ puts proj.to_s
54
+ end
55
+ end
56
+ end # method self.main
57
+ end # (nested) class Tool
58
+ end # class Monofile
59
+
@@ -4,8 +4,8 @@ module Module
4
4
  module Monofile
5
5
 
6
6
  MAJOR = 0 ## todo: namespace inside version or something - why? why not??
7
- MINOR = 1
8
- PATCH = 0
7
+ MINOR = 2
8
+ PATCH = 3
9
9
  VERSION = [MAJOR,MINOR,PATCH].join('.')
10
10
 
11
11
  def self.version
@@ -0,0 +1,7 @@
1
+ # minitest setup
2
+ require 'minitest/autorun'
3
+
4
+
5
+ ## our own code
6
+ require 'monofile'
7
+
@@ -0,0 +1,97 @@
1
+ ###
2
+ # to run use
3
+ # ruby -I ./lib -I ./test test/test_names.rb
4
+
5
+
6
+ require 'helper'
7
+
8
+
9
+ class TestNames < MiniTest::Test
10
+
11
+ def test_parse
12
+ %w[
13
+ @openfootball/england
14
+ england@openfootball
15
+ ].each do |line|
16
+ mono = Mononame.parse( line )
17
+
18
+ assert_equal '@openfootball/england', mono.to_s
19
+ assert_equal 'openfootball/england', mono.to_path
20
+
21
+ assert_equal 'openfootball', mono.org
22
+ assert_equal 'england', mono.name
23
+ end
24
+
25
+
26
+ %w[
27
+ @openfootball/england/2020-21
28
+ 2020-21@openfootball/england
29
+ england/2020-21@openfootball
30
+ ].each do |line|
31
+ mono = Monopath.parse( line )
32
+
33
+ assert_equal '@openfootball/england/2020-21', mono.to_s
34
+ assert_equal 'openfootball/england/2020-21', mono.to_path
35
+
36
+ assert_equal 'openfootball', mono.org
37
+ assert_equal 'england', mono.name
38
+ assert_equal '2020-21', mono.path
39
+ end
40
+
41
+ %w[
42
+ @openfootball/england/2020-21/premierleague.txt
43
+ 2020-21/premierleague.txt@openfootball/england
44
+ england/2020-21/premierleague.txt@openfootball
45
+ ].each do |line|
46
+ mono = Monopath.parse( line )
47
+
48
+ assert_equal '@openfootball/england/2020-21/premierleague.txt', mono.to_s
49
+ assert_equal 'openfootball/england/2020-21/premierleague.txt', mono.to_path
50
+
51
+ assert_equal 'openfootball', mono.org
52
+ assert_equal 'england', mono.name
53
+ assert_equal '2020-21/premierleague.txt', mono.path
54
+ end
55
+ end # method test_parse
56
+
57
+
58
+
59
+ def test_init
60
+ mono = Mononame.new( 'openfootball','england' )
61
+
62
+ assert_equal '@openfootball/england', mono.to_s
63
+ assert_equal 'openfootball/england', mono.to_path
64
+
65
+ assert_equal 'openfootball', mono.org
66
+ assert_equal 'england', mono.name
67
+
68
+
69
+ mono = Monopath.new( 'openfootball', 'england', '2020-21' )
70
+
71
+ assert_equal '@openfootball/england/2020-21', mono.to_s
72
+ assert_equal 'openfootball/england/2020-21', mono.to_path
73
+
74
+ assert_equal 'openfootball', mono.org
75
+ assert_equal 'england', mono.name
76
+ assert_equal '2020-21', mono.path
77
+
78
+
79
+ ## !!!!todo/check/fix!!!!!:
80
+ ## - support '2020-21', 'premierleague.txt' too (or only) - why? why not?
81
+ ##
82
+ ## todo/check/fix:
83
+ ## find a better name for path/path? component / part - why? why not?
84
+ ## to_path and path/path? to confusing!!!
85
+ mono = Monopath.new( 'openfootball', 'england', '2020-21/premierleague.txt' )
86
+
87
+ assert_equal '@openfootball/england/2020-21/premierleague.txt', mono.to_s
88
+ assert_equal 'openfootball/england/2020-21/premierleague.txt', mono.to_path
89
+
90
+ assert_equal 'openfootball', mono.org
91
+ assert_equal 'england', mono.name
92
+ assert_equal '2020-21/premierleague.txt', mono.path
93
+ end # method test_init
94
+
95
+
96
+
97
+ end # class TestNames
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: monofile
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-29 00:00:00.000000000 Z
11
+ date: 2020-11-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc
@@ -44,8 +44,8 @@ dependencies:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
46
  version: '3.22'
47
- description: monofile - read in/ parse mono (source) tree defintions with git (and
48
- github) projects, and more
47
+ description: monofile - read in / parse monorepo / mono source tree definitions -
48
+ a list of git (and github) projects, and more
49
49
  email: opensport@googlegroups.com
50
50
  executables:
51
51
  - monofile
@@ -61,8 +61,13 @@ files:
61
61
  - Rakefile
62
62
  - bin/monofile
63
63
  - lib/monofile.rb
64
+ - lib/monofile/monofile.rb
65
+ - lib/monofile/mononame.rb
66
+ - lib/monofile/tool.rb
64
67
  - lib/monofile/version.rb
65
- homepage: https://github.com/rubycoco/git
68
+ - test/helper.rb
69
+ - test/test_names.rb
70
+ homepage: https://github.com/rubycoco/monos
66
71
  licenses:
67
72
  - Public Domain
68
73
  metadata: {}
@@ -87,6 +92,6 @@ rubyforge_project:
87
92
  rubygems_version: 2.5.2
88
93
  signing_key:
89
94
  specification_version: 4
90
- summary: monofile - read in/ parse mono (source) tree defintions with git (and github)
91
- projects, and more
95
+ summary: monofile - read in / parse monorepo / mono source tree definitions - a list
96
+ of git (and github) projects, and more
92
97
  test_files: []