ghedsh 1.1.40 → 2.3.8

Sign up to get free protection for your applications and to get access to all the features.
data/lib/commands.rb ADDED
@@ -0,0 +1,465 @@
1
+ require 'version'
2
+ require 'common'
3
+ require 'ostruct'
4
+ require 'fileutils'
5
+
6
+ # Class that registers commands into has COMMANDS located in common.rb
7
+ # The interface access that hash to look up for the command. If command is defined,
8
+ # and the class that points @deep has the method defined, the interface calls it with
9
+ # parameters provided.
10
+ #
11
+ # If a command should be available in different contexts, each class (e.g User or Organization)
12
+ # must implement that command (and perform acrions related to that context)
13
+ class Commands
14
+ attr_reader :enviroment
15
+
16
+ # when Commands class is instantiated, all methods are added to COMMANDS hash with a name (string)
17
+ # that identify each one and the caller method within Commands class.
18
+ def initialize
19
+ @context_stack = []
20
+ add_command('clear', method(:clear))
21
+ # add_command('help', method(:help))
22
+ add_command('exit', method(:exit))
23
+ add_command('version', method(:show_version))
24
+ add_command('new_issue', method(:new_issue))
25
+ add_command('issues', method(:display_issues))
26
+ add_command('repos', method(:display_repos))
27
+ add_command('new_repo', method(:new_repo))
28
+ add_command('rm_repo', method(:rm_repo))
29
+ add_command('new_team', method(:new_team))
30
+ add_command('set_private', method(:set_private))
31
+ add_command('set_public', method(:set_public))
32
+ add_command('files', method(:show_files))
33
+ add_command('rm_team', method(:rm_team))
34
+ add_command('clone', method(:clone_repo))
35
+ add_command('rm_cloned', method(:delete_cloned_repos))
36
+ add_command('commits', method(:display_commits))
37
+ add_command('orgs', method(:display_orgs))
38
+ add_command('new_eval', method(:new_eval))
39
+ add_command('foreach', method(:foreach_eval))
40
+ add_command('foreach_try', method(:foreach_try))
41
+ add_command('invite_member', method(:invite_member))
42
+ add_command('remove_member', method(:remove_member))
43
+ add_command('invite_member_from_file', method(:invite_member_from_file))
44
+ add_command('invite_outside_collaborators', method(:invite_outside_collaborators))
45
+ add_command('people', method(:display_people))
46
+ add_command('teams', method(:display_teams))
47
+ add_command('orgsn', method(:orgsn))
48
+ add_command('cd', method(:change_context))
49
+ add_command('open', method(:open))
50
+ add_command('bash', method(:bash))
51
+ end
52
+
53
+ # Fills COMMANDS hash with available commands.
54
+ #
55
+ # @param [String] command_name string that identifies a command, when user types it, command
56
+ # executes depending on context.
57
+ # @param [Method] command method inside Class Commands that triggers the action depending on where
58
+ # is pointing @deep
59
+ def add_command(command_name, command)
60
+ COMMANDS[command_name] = command
61
+ end
62
+
63
+ # Gets enviroment from class ShellContext. Includes all GitHub authenticated user configuration,
64
+ # ghedsh configuration etc.
65
+ # Also it stores the default enviroment to avoid context_stack underflow.
66
+ #
67
+ # @param [ShellContext] console_enviroment object containing running enviroment.
68
+ def load_enviroment(console_enviroment)
69
+ @enviroment = console_enviroment
70
+ @default_enviroment = OpenStruct.new
71
+ default_config = {
72
+ 'User' => @enviroment.client.login.to_s,
73
+ 'user_url' => @enviroment.client.web_endpoint.to_s << @enviroment.client.login.to_s,
74
+ 'Org' => nil,
75
+ 'org_url' => nil,
76
+ 'Repo' => nil,
77
+ 'repo_url' => nil,
78
+ 'Team' => nil,
79
+ 'team_url' => nil,
80
+ 'TeamID' => nil,
81
+ 'Assig' => nil
82
+ }
83
+ @default_enviroment.config = default_config
84
+ @default_enviroment.deep = User
85
+ @context_stack.push(@default_enviroment)
86
+ end
87
+
88
+ # Display organization depending on context. If method is not defined in current deep, information
89
+ # is provided.
90
+ #
91
+ # @param [Array<String>] params user provided parameters, like Regexp to show matching organizations
92
+ def display_orgs(params)
93
+ if @enviroment.deep.method_defined? :show_organizations
94
+ @enviroment.deep.new.show_organizations(@enviroment.client, params)
95
+ else
96
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
97
+ end
98
+ puts
99
+ end
100
+
101
+ # Creates a 'super repo' containing subrepos of assignments
102
+ #
103
+ # @param [Array<String>] params first provide name of eval repository and a Regexp to match
104
+ # repos to add them as submodules
105
+ def new_eval(params)
106
+ if @enviroment.deep.method_defined? :new_eval
107
+ @enviroment.deep.new.new_eval(@enviroment.client, @enviroment.config, params)
108
+ else
109
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
110
+ end
111
+ puts
112
+ end
113
+
114
+ # Run a bash command over each submodule inside a evaluation repo
115
+ # Requirements: Current working directory must be the evaluation repo containing all submodules
116
+ #
117
+ # @param [Array<String>] params command to run over each submodule
118
+ def foreach_eval(params)
119
+ if @enviroment.deep.method_defined? :foreach_eval
120
+ @enviroment.deep.new.foreach_eval(@enviroment.client, @enviroment.config, params)
121
+ else
122
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
123
+ end
124
+ puts
125
+ end
126
+
127
+ def foreach_try(params)
128
+ if @enviroment.deep.method_defined? :foreach_try
129
+ @enviroment.deep.new.foreach_try(@enviroment.client, @enviroment.config, params)
130
+ else
131
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
132
+ end
133
+ puts
134
+ end
135
+
136
+ # Display files from current repo.
137
+ #
138
+ # @param [Array<String>] params user provided parameters, like path within a repository
139
+ def show_files(params)
140
+ if @enviroment.deep.method_defined? :show_files
141
+ @enviroment.deep.new.show_files(@enviroment.client, @enviroment.config, params)
142
+ else
143
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
144
+ end
145
+ puts
146
+ end
147
+
148
+ # Invite member to organization
149
+ # @param [Array<String>] params user provided parameters, like members to be added
150
+ def invite_member(params)
151
+ if @enviroment.deep.method_defined? :add_members
152
+ @enviroment.deep.new.add_members(@enviroment.client, @enviroment.config, params)
153
+ else
154
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
155
+ end
156
+ puts
157
+ end
158
+
159
+ # Invite members from JSON files. file_templates directory has template with file structure for this command.
160
+ # @param [Array<String>] params path to JSON file containing members
161
+ def invite_member_from_file(params)
162
+ if @enviroment.deep.method_defined? :add_members_from_file
163
+ @enviroment.deep.new.add_members_from_file(@enviroment.client, @enviroment.config, params[0])
164
+ else
165
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
166
+ end
167
+ puts
168
+ end
169
+
170
+ # Remove member from oranization.
171
+ # @param [Array<String>] params path to JSON file containing members to be removed or Regexp to match members
172
+ # to be removed. file_templates contains a template for this command.
173
+ def remove_member(params)
174
+ if @enviroment.deep.method_defined? :delete_member
175
+ @enviroment.deep.new.delete_member(@enviroment.client, @enviroment.config, params[0])
176
+ else
177
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
178
+ end
179
+ puts
180
+ end
181
+
182
+ # Invite outside collaborators of an organization to be members of that organization.
183
+ # @param [Array<String>] params path to file or Regexp to match outside collaborators to be invited.
184
+ # file_templates contains a JSON template for this command.
185
+ def invite_outside_collaborators(params)
186
+ if @enviroment.deep.method_defined? :invite_all_outside_collaborators
187
+ @enviroment.deep.new.invite_all_outside_collaborators(@enviroment.client, @enviroment.config, params[0])
188
+ else
189
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
190
+ end
191
+ puts
192
+ end
193
+
194
+ # Exit Github Education Shell CLI saving configuration. When user runs the CLI again, configuration
195
+ # and context are restored from last session. However, previous contexts are not restored, only last one.
196
+ def exit(_params)
197
+ @enviroment.sysbh.save_memory(@enviroment.config_path, @enviroment.config)
198
+ @enviroment.sysbh.save_cache(@enviroment.config_path, @enviroment.config)
199
+ @enviroment.sysbh.remove_temp("#{ENV['HOME']}/.ghedsh/temp")
200
+
201
+ 0
202
+ end
203
+
204
+ # Runs a bash command.
205
+ # @param [Array<String>] params bash command to perform
206
+ def bash(params)
207
+ bash_command = params.join(' ')
208
+ system(bash_command)
209
+ puts
210
+ end
211
+
212
+ # Open info depending on context. Within organization will open GitHub organization profile, member profile, etc.
213
+ def open(params)
214
+ if @enviroment.deep.method_defined? :open_info
215
+ @enviroment.deep.new.open_info(@enviroment.config, params[0], @enviroment.client)
216
+ else
217
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
218
+ end
219
+ end
220
+
221
+ # Create new repository with the provided name. Two modes are available: fast and custom. Fast mode creates a public repo.
222
+ # Custom mode allows to set several details, like privacy, description, .gitignore template, etc.
223
+ #
224
+ # @param [Array<String>] params repository name
225
+ def new_repo(params)
226
+ if @enviroment.deep.method_defined? :create_repo
227
+ begin
228
+ repo_name = params[0]
229
+ options = repo_creation_guide
230
+ if options == 'Default'
231
+ @enviroment.deep.new.create_repo(@enviroment, repo_name, options = {})
232
+ else
233
+ @enviroment.deep.new.create_repo(@enviroment, repo_name, options)
234
+ end
235
+ rescue StandardError => exception
236
+ puts Rainbow(exception.message.to_s).color('#cc0000')
237
+ end
238
+ else
239
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
240
+ end
241
+ puts
242
+ end
243
+
244
+ # Remove repository
245
+ #
246
+ # @param [Array<String>] params repository name to be deleted
247
+ def rm_repo(params)
248
+ if @enviroment.deep.method_defined? :remove_repo
249
+ @enviroment.deep.new.remove_repo(@enviroment, params[0])
250
+ else
251
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
252
+ end
253
+ puts
254
+ end
255
+
256
+ # Change repository to private.
257
+ #
258
+ # @param [Array<String>] params Regexp to match repositories and edit its privacy
259
+ def set_private(params)
260
+ if @enviroment.deep.method_defined? :change_to_private_repo
261
+ @enviroment.deep.new.change_to_private_repo(@enviroment.client, @enviroment.config, params[0])
262
+ else
263
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
264
+ end
265
+ puts
266
+ end
267
+
268
+ # Change repository to public
269
+ #
270
+ # @param [Array<String>] params Regexp to match repositories and edit its privacy
271
+ def set_public(params)
272
+ if @enviroment.deep.method_defined? :change_to_public_repo
273
+ @enviroment.deep.new.change_to_public_repo(@enviroment.client, @enviroment.config, params[0])
274
+ else
275
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
276
+ end
277
+ puts
278
+ end
279
+
280
+ # Clone repository
281
+ #
282
+ # @param [Array<String>] params Regexp to match repositories to be cloned or individual repository to be cloned.
283
+ # Second parameter is custom path to find cloned repositories. If not provided CWD is the path.
284
+ def clone_repo(params)
285
+ if @enviroment.deep.method_defined? :clone_repository
286
+ @enviroment.deep.new.clone_repository(@enviroment, params[0], params[1])
287
+ else
288
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
289
+ end
290
+ end
291
+
292
+ # Delete cloned repository
293
+ def delete_cloned_repos(_params)
294
+ ####### FileUtils.remove_entry_secure("", force = true)
295
+ puts Rainbow("Cloned content deleted.\n").color('#00529B')
296
+ end
297
+
298
+ # Display commits
299
+ #
300
+ # @param [Array<String>] params repository name and baranch. If user is already inside a repository, a branch
301
+ # can be specified, if not 'master' is default branch.
302
+ def display_commits(params)
303
+ if @enviroment.deep.method_defined? :show_commits
304
+ @enviroment.deep.new.show_commits(@enviroment, params)
305
+ else
306
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
307
+ end
308
+ puts
309
+ end
310
+
311
+ # Display a table with GitHub IDs and membership type within an prganization
312
+ #
313
+ # @param [Array<String>] params Regexp to show matching people, if empty, shows all people.
314
+ def display_people(params)
315
+ if @enviroment.deep.method_defined? :show_people
316
+ @enviroment.deep.new.show_people(@enviroment.client, @enviroment.config, params[0])
317
+ else
318
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
319
+ end
320
+ puts
321
+ end
322
+
323
+ # Show teams within an organization
324
+ #
325
+ # @param [Array<String>] params Regexp to show matching teams
326
+ def display_teams(params)
327
+ if @enviroment.deep.method_defined? :show_teams
328
+ @enviroment.deep.new.show_teams(@enviroment.client, @enviroment.config, params[0])
329
+ else
330
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
331
+ end
332
+ puts
333
+ end
334
+
335
+ # Create teams from file or by name
336
+ #
337
+ # @param [Array<String>] params path to JSON template or team name to be created
338
+ def new_team(params)
339
+ if @enviroment.deep.method_defined? :create_team
340
+ @enviroment.deep.new.create_team(@enviroment.client, @enviroment.config, params[0])
341
+ else
342
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
343
+ end
344
+ puts
345
+ end
346
+
347
+ # Remove team
348
+ def rm_team(_params)
349
+ if @enviroment.deep.method_defined? :remove_team
350
+ @enviroment.deep.new.remove_team(@enviroment.config)
351
+ else
352
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
353
+ end
354
+ puts
355
+ end
356
+
357
+ # Open repository issue creation form URL
358
+ def new_issue(_params)
359
+ if @enviroment.deep.method_defined? :create_issue
360
+ @enviroment.deep.new.create_issue(@enviroment.config)
361
+ else
362
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
363
+ end
364
+ end
365
+
366
+ # Open browser with active issues URL
367
+ def display_issues(_params)
368
+ if @enviroment.deep.method_defined? :show_issues
369
+ @enviroment.deep.new.show_issues(@enviroment.config)
370
+ else
371
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
372
+ end
373
+ end
374
+
375
+ # Display respositories
376
+ #
377
+ # @param [Array<String>] param Regexp to show matchin repository names. If not provided, show all
378
+ def display_repos(params)
379
+ if @enviroment.deep.method_defined? :show_repos
380
+ @enviroment.deep.new.show_repos(@enviroment.client, @enviroment.config, params[0])
381
+ else
382
+ puts Rainbow("Command not available in context \"#{@enviroment.deep.name}\"").color(WARNING_CODE)
383
+ end
384
+ puts
385
+ end
386
+
387
+ # Show ghedsh current version
388
+ def show_version(_params)
389
+ puts "GitHub Education Shell v#{Ghedsh::VERSION}"
390
+ end
391
+
392
+ # Clear screen
393
+ def clear(_params)
394
+ system('clear')
395
+ end
396
+
397
+ def orgsn(params)
398
+ # params[0].prepend("/")
399
+ # file_path = "#{Dir.home}#{params[0]}"
400
+ # p file_path[0]
401
+ # p file_path = file_path.delete('"')
402
+ # puts File.file?(file_path) ? true : false
403
+ end
404
+
405
+ # Change CLI context and move between repositories, organization, teams
406
+ # Contexts are stored in a stack
407
+ # @param [Array<String>] params cd operation
408
+ # @example change to organization
409
+ # User > cd org /regexp/
410
+ # @example change to repository
411
+ # User > Org > cd repo /regexp/ or String
412
+ def change_context(params)
413
+ if params.empty?
414
+ @enviroment.config['Org'] = nil
415
+ @enviroment.config['Repo'] = nil
416
+ @enviroment.config['Team'] = nil
417
+ @enviroment.config['TeamID'] = nil
418
+ @enviroment.config['Assig'] = nil
419
+
420
+ @context_stack.clear
421
+ @context_stack.push(@default_enviroment)
422
+
423
+ @enviroment.deep = User
424
+ elsif params[0] == '..'
425
+ if @context_stack.size > 1
426
+ @context_stack.pop
427
+ stack_pointer = @context_stack.last
428
+
429
+ @enviroment.config = stack_pointer.config
430
+ @enviroment.deep = stack_pointer.deep
431
+ else
432
+ @enviroment.config = @default_enviroment.config
433
+ @enviroment.deep = @default_enviroment.deep
434
+ end
435
+ else
436
+ begin
437
+ name = params[1]
438
+ name = name.gsub(/\A("|')|("|')\Z/, '')
439
+ name.insert(0, '\'')
440
+ name.insert(-1, '\'')
441
+ action = @enviroment.deep.new.build_cd_syntax(params[0], name)
442
+ env = OpenStruct.new
443
+ env.config = Marshal.load(Marshal.dump(@enviroment.config))
444
+ env.deep = @enviroment.deep
445
+ client = @enviroment.client
446
+ changed_enviroment = eval(action)
447
+ unless changed_enviroment.nil?
448
+ current_enviroment = OpenStruct.new
449
+ current_enviroment.config = changed_enviroment.config
450
+ current_enviroment.deep = changed_enviroment.deep
451
+ @context_stack.push(current_enviroment)
452
+ @enviroment.config = changed_enviroment.config
453
+ @enviroment.deep = changed_enviroment.deep
454
+ end
455
+ rescue SyntaxError => err
456
+ puts Rainbow('Syntax Error typing the command. Tip: cd <type> <Regexp|String>').color('#cc0000')
457
+ puts Rainbow('Regexp options for Ruby: /i, /m, /x, /o').color('#cc0000')
458
+ puts
459
+ rescue StandardError => exception
460
+ puts Rainbow('Error while running cd command. Usage: cd <type> <Regexp|String>').color('#D8000C')
461
+ end
462
+ end
463
+ end
464
+ end
465
+
data/lib/common.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'actions/system'
2
+ require 'actions/orgs'
3
+ require 'actions/teams'
4
+ require 'actions/user'
5
+
6
+ #color codes
7
+ ERROR_CODE = '#cc0000'
8
+ WARNING_CODE = '#9f6000'
9
+ INFO_CODE = '#00529B'
10
+ SUCCESS_CODE = '#4f8a10'
11
+
12
+ COMMANDS = {}
13
+ User
14
+ Organization
15
+ Team
data/lib/context.rb ADDED
@@ -0,0 +1,42 @@
1
+ require 'common'
2
+ require 'version'
3
+ require 'commands'
4
+
5
+ class ShellContext
6
+ attr_accessor :deep
7
+ attr_accessor :config
8
+ attr_accessor :client
9
+ attr_accessor :sysbh
10
+ attr_accessor :commands
11
+ attr_accessor :config_path
12
+
13
+ def initialize(user, config_path, argv_token)
14
+ @commands = {}
15
+ @config_path = config_path
16
+ @sysbh = Sys.new
17
+ @sysbh.write_initial_memory
18
+
19
+ if !user.nil?
20
+ @config = @sysbh.load_config_user(config_path, user)
21
+ @client = @sysbh.client
22
+ @deep = User
23
+ else
24
+ @config = @sysbh.load_config(config_path, argv_token) # retorna la configuracion ya guardada anteriormente
25
+ @client = @sysbh.client
26
+ @deep = @sysbh.return_deep(config_path)
27
+ end
28
+ @sysbh.load_memory(config_path, @config)
29
+ unless @client.nil?
30
+ @sysbh.add_history_str(2, Organization.new.read_orgs(@client))
31
+ end
32
+
33
+ # let commands class access context variables
34
+ share_context = Commands.new
35
+ share_context.load_enviroment(self)
36
+ @commands = COMMANDS
37
+ end
38
+
39
+ def prompt
40
+ @deep.shell_prompt(@config)
41
+ end
42
+ end
data/lib/helpers.rb ADDED
@@ -0,0 +1,147 @@
1
+ require 'tty-prompt'
2
+ require 'tty-spinner'
3
+ require 'rainbow'
4
+ require 'fileutils'
5
+ require 'rbconfig'
6
+ require 'terminal-table'
7
+
8
+ # colors:
9
+ # error: .color('#cc0000')
10
+ # command not found: .yellow
11
+ # warning: .color('#9f6000')
12
+ # info: .color(#00529B)
13
+ # success: .color(79, 138, 16)
14
+
15
+ def custom_spinner(message)
16
+ TTY::Spinner.new(Rainbow(message.to_s).color(79, 138, 16), format: :bouncing_ball)
17
+ end
18
+
19
+ def build_item_table(item, pattern)
20
+ matches = 0
21
+ rows = []
22
+ item.each do |i, v|
23
+ if pattern.match(i)
24
+ rows << [i, v]
25
+ matches += 1
26
+ end
27
+ end
28
+ table = Terminal::Table.new headings: ['Github ID', 'Role'], rows: rows
29
+ puts table
30
+ matches
31
+ end
32
+
33
+ def show_matching_items(item, pattern)
34
+ occurrences = 0
35
+ item.each do |i|
36
+ if pattern.match(i)
37
+ puts i
38
+ occurrences += 1
39
+ end
40
+ end
41
+ occurrences
42
+ end
43
+
44
+ def build_regexp_from_string(string)
45
+ str = eval(string) # string.gsub(/\//, '')
46
+ Regexp.new(str)
47
+ rescue SyntaxError => e
48
+ puts Rainbow('Error building Regexp, check syntax.').color('#cc0000')
49
+ puts
50
+ end
51
+
52
+ def is_file?(path)
53
+ path = path.delete('"')
54
+ File.file?("#{Dir.home}#{path}") ? true : false
55
+ end
56
+
57
+ def repo_creation_guide
58
+ puts Rainbow("Select 'Default' to create a quick public repo.").color('#f18973')
59
+ puts Rainbow("Select 'Custom' for private/public repo whith specific options.").color('#f18973')
60
+ puts Rainbow('To skip any option just hit Enter (Default options).').color('#f18973')
61
+ puts
62
+ choices = %w[Default Custom]
63
+ prompt = TTY::Prompt.new
64
+ answer = prompt.select('Select configuration', choices)
65
+ if answer == 'Default'
66
+ return answer
67
+ else
68
+ puts Rainbow('Answer questions with yes/true or no/false').color('#f18973')
69
+ custom_options = prompt.collect do
70
+ key(:private).ask('Private repo? (Default: false) [yes/true, no/false]', convert: :bool)
71
+ key(:description).ask('Write description of the repo')
72
+ key(:has_issues).ask('Has issues? (Default:true) [yes/true, no/false]', convert: :bool)
73
+ key(:has_wiki).ask('Has wiki? (Default: true) [yes/true, no/false]', convert: :bool)
74
+ key(:auto_init).ask('Create an initial commit with empty README? (Default: false) (if you want .gitignore template must be yes/true)',
75
+ convert: :bool)
76
+ key(:gitignore_template).ask('Desired language or platform for .gitignore template')
77
+ end
78
+ return custom_options = custom_options.compact
79
+ end
80
+ end
81
+
82
+ def select_member(config, pattern, client)
83
+ members = []
84
+ members_url = {}
85
+ client.organization_members(config['Org'].to_s).each do |member|
86
+ if pattern.match(member[:login].to_s)
87
+ members << member[:login]
88
+ members_url[member[:login]] = member[:html_url]
89
+ end
90
+ end
91
+ if members.empty?
92
+ puts Rainbow("No member matched with #{pattern.source} inside organization #{config['Org']}").color('#9f6000')
93
+ puts
94
+ else
95
+ prompt = TTY::Prompt.new
96
+ answer = prompt.select('Select desired organization member', members)
97
+ end
98
+ members_url[answer]
99
+ end
100
+
101
+ def perform_git_clone(repos_to_clone, custom_path)
102
+ begin
103
+ dir_path = if custom_path.nil?
104
+ Dir.pwd.to_s
105
+ else
106
+ "#{Dir.home}#{custom_path}"
107
+ end
108
+ FileUtils.mkdir_p(dir_path)
109
+ rescue StandardError => exception
110
+ puts Rainbow(exception.message.to_s).color('#cc0000')
111
+ end
112
+ repos_to_clone.each do |repos|
113
+ FileUtils.cd(dir_path) do
114
+ if !Dir.exist?("#{dir_path}/#{repos[:name]}") || Dir.empty?("#{dir_path}/#{repos[:name]}")
115
+ system("git clone --recurse-submodules --progress #{repos[:ssh_url]}")
116
+ puts
117
+ else
118
+ FileUtils.cd("#{dir_path}/#{repos[:name]}") do
119
+ puts repos[:name]
120
+ system('git pull --all --recurse-submodules')
121
+ puts
122
+ end
123
+ end
124
+ end
125
+ end
126
+ rescue StandardError => exception
127
+ puts Rainbow(exception.message.to_s).color('#cc0000')
128
+ puts
129
+ end
130
+
131
+ def split_members(members_list)
132
+ members = []
133
+ members_list.each do |i|
134
+ string = i.split(/[,(\s)?]/)
135
+ members.push(string)
136
+ end
137
+ members = members.flatten
138
+ end
139
+
140
+ def open_url(url)
141
+ os = RbConfig::CONFIG['host_os']
142
+ if os.downcase.include?('linux')
143
+ system("xdg-open #{url}")
144
+ elsif os.downcase.include?('darwin')
145
+ system("open #{url}")
146
+ end
147
+ end