ghedsh 1.1.40 → 2.3.8

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.
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