fgi 1.0.2 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2c10109eb480ab557f79d477ff770b7b4113d079
4
- data.tar.gz: a718badc264ab8b9483e11ec76082db9a04aac99
3
+ metadata.gz: 01ff812f6d7df394c97c84fe04677f1421726d96
4
+ data.tar.gz: d8888bd13fd3f3b38ad99d3dc4ca659d438def4d
5
5
  SHA512:
6
- metadata.gz: 7eab634762636cc11025a56296c9b20e3e8d767935c245db69acefc7313b8ed02646d1660737343d50bc71d75ac128d2cb775127777c6166745281ba78633a44
7
- data.tar.gz: ce9f2d259e89d34e3ee9fb822d0b0dfa6516f71cf91b74d3a5f51dbffed28aea0ddf7077125d4cf567f789506586a3a390365b01992fe6ff14f77489b85cd12e
6
+ metadata.gz: a2a5e66b748bf7f182b2b0c4757e575bcad60f8a04016bbb9d91634e228415831a4bf3e5d40d0fa7982b98172c3210a01c1058e558277c7c83559dd4ac6898a3
7
+ data.tar.gz: 5a7965629498624bfd1f66a50708c9e9fc1da3ec35319e205baad5f2e976694989fafd01cbaef1ac7c1919494d53a4ca6443ab45314fe2f6cb519c51ad7231b3
data/bin/fgi CHANGED
@@ -17,20 +17,32 @@ options_parser = OptionParser.new do |fgi|
17
17
  fgi.separator ' config : run the FGI configurator.'
18
18
  fgi.separator ' token [TOKEN] : define the new user token.'
19
19
  fgi.separator ' new [ISSUE_NAME] : create the issue with the given name.'
20
+ fgi.separator ' fix : fix the current issue.'
20
21
  fgi.separator ' ... more comming soon ...'
21
22
  fgi.separator ''
22
23
  fgi.separator 'Options'
23
24
 
25
+ fgi.on('-h', '--help', 'Display the FGI manual')
26
+
27
+ fgi.on('-v', '--version', 'Display the FGI version') do
28
+ puts "FGI #{Fgi::VERSION}"
29
+ exit!
30
+ end
31
+
24
32
  fgi.on('-e', '--estimate [ESTIMATION]', 'How many time do you think you will spend on this issue ? (example: 1d13h37m05s)') do |estimate|
25
33
  options[:estimate] = estimate
26
34
  end
27
35
 
28
- fgi.on('-l', '--later', 'Tell FGI that you anly want to create an issue but not to create and switch branch.') do
36
+ fgi.on('-l', '--later', 'Tell FGI that you only want to create an issue but not to create and switch branch.') do
29
37
  options[:later] = true
30
38
  end
31
39
 
32
- fgi.on('-h', '--help', 'Display the FGI manual') do
33
- puts options_parser
40
+ fgi.on('-p', '--prefix [PREFIX]', 'Tell FGI that you want to add a prefix to the branch name.') do |prefix|
41
+ options[:prefix] = prefix
42
+ end
43
+
44
+ fgi.on('-m', '--fix-message [MESSAGE]', %q(Add a custom message with the basic 'Fix #ID')) do |message|
45
+ options[:fix_message] = message
34
46
  end
35
47
  end
36
48
  options_parser.parse!
@@ -50,15 +62,17 @@ when 'config'
50
62
  Fgi::Configuration.new_config
51
63
  when 'new'
52
64
  Fgi.configured?
53
- if argv[1].start_with?('-')
65
+ if !argv[1].nil? && argv[1].start_with?('-')
54
66
  puts %q(You can't begin your issue's title with '-')
55
67
  exit!
56
68
  end
57
69
  title = get_full_issue_title(argv)
58
- Fgi::GitService.create_issue(title: title, options: options)
70
+ Fgi::GitService.new_issue(title: title, options: options)
59
71
  when 'token'
60
72
  Fgi.configured?
61
73
  Fgi::Tokens.add_token(argv[1])
74
+ when 'fix'
75
+ Fgi::GitService.fix_issue(options)
62
76
  else
63
77
  puts options_parser
64
78
  end
data/lib/fgi.rb CHANGED
@@ -6,6 +6,7 @@ module Fgi
6
6
  require 'json'
7
7
  require 'yaml'
8
8
  require 'uri'
9
+ require 'cgi'
9
10
 
10
11
  require_relative 'fgi/git_services/gitlab'
11
12
  require_relative 'fgi/http_requests'
@@ -13,19 +14,28 @@ module Fgi
13
14
  require_relative 'fgi/configuration'
14
15
  require_relative 'fgi/git_service'
15
16
 
16
- # Define const variables if fgi config files exists
17
+ VERSION = '1.1.1'.freeze
18
+
19
+ # Add FGI user's current issues to the gitignore
20
+ if `cat .gitignore | grep '.current_issues.fgi.yml'`.empty?
21
+ File.open('.gitignore', 'a') { |f| f.write("\n.current_issues.fgi.yml\n") }
22
+ end
23
+
24
+ ISSUES = YAML.load_file('.current_issues.fgi.yml') if File.exist?('.current_issues.fgi.yml')
25
+ # Define const variables if fgi config files exists
17
26
  # otherwise ask for configuration
18
- if File.exists?('.config.fgi.yml')
27
+ if File.exist?('.config.fgi.yml')
19
28
  CONFIG = YAML.load_file('.config.fgi.yml')
20
29
  git_service = CONFIG[:git_service_class].new
21
- if File.exists?("#{Dir.home}/.tokens.fgi.yml")
22
- TOKEN = YAML.load_file("#{Dir.home}/.tokens.fgi.yml")[git_service.to_sym]
30
+ if File.exist?("#{Dir.home}/.tokens.fgi.yml")
31
+ TOKEN = YAML.load_file("#{Dir.home}/.tokens.fgi.yml")[git_service.to_sym][CONFIG[:url]]
23
32
  end
24
33
  end
25
34
 
26
35
  def self.configured?
27
- return if File.exists?('.config.fgi.yml')
36
+ return if File.exist?('.config.fgi.yml')
28
37
  puts "\nThere is no FGI configuration file on this project. Please run 'fgi config'.\n\n"
29
38
  exit!
30
39
  end
40
+
31
41
  end
@@ -2,6 +2,7 @@
2
2
  module Fgi
3
3
  class Configuration
4
4
  class << self
5
+
5
6
  include HttpRequests
6
7
 
7
8
  # Launch the process to create the fresh project fgi config file
@@ -21,7 +22,6 @@ module Fgi
21
22
  # INITIALIZERS #
22
23
  # -------------------------- #
23
24
 
24
-
25
25
  # The hash that will contain the project's fgi configuration to save as yml
26
26
  # It will contain :
27
27
  # :url
@@ -38,18 +38,17 @@ module Fgi
38
38
  # TODO - HARD REFECTO NEEDED HERE...
39
39
  git_service = config[:git_service_class].new(config: config)
40
40
  config[:git_service] = git_service.to_sym
41
- user_token = save_user_token(git_service)
41
+ user_token = save_user_token(config: config, git_service: git_service)
42
42
  project_name_and_id = define_project_name_and_id(git_service, user_token)
43
43
  config = config.merge(project_name_and_id)
44
44
  git_service = config[:git_service_class].new(config: config)
45
45
  config[:default_branch] = define_default_branch(git_service, user_token)
46
46
 
47
-
48
47
  # -------------------------- #
49
48
  # CREATORS #
50
49
  # -------------------------- #
51
50
 
52
- Fgi::Tokens.create_user_tokens_file(config[:git_service], user_token)
51
+ Fgi::Tokens.create_user_tokens_file(config: config, git_service: git_service, token: user_token)
53
52
  create_fgi_config_file(config)
54
53
  end
55
54
 
@@ -57,21 +56,19 @@ module Fgi
57
56
 
58
57
  # Check if we are in a git repository. Exit FGI if not.
59
58
  def git_directory?
60
- unless Dir.exists?('.git')
61
- puts 'You are not in a git project repository.'
62
- exit!
63
- end
59
+ return if Dir.exist?('.git')
60
+ puts 'You are not in a git project repository.'
61
+ exit!
64
62
  end
65
63
 
66
64
  # Check if FGI has already been configured. Exit FGI if not.
67
65
  def already_configured?
68
- if File.exists?('.config.fgi.yml')
69
- puts 'There is already a FGI config on this project.'
70
- exit!
71
- end
66
+ return unless File.exist?('.config.fgi.yml')
67
+ puts 'There is already a FGI config on this project.'
68
+ exit!
72
69
  end
73
70
 
74
- # Ask the user to shoose the project's Git service
71
+ # Ask the user to shoose the project's Git service
75
72
  # @return [Class] the project's Git service class
76
73
  def define_git_service
77
74
  puts "\nPlease insert the number of the used Git service :"
@@ -81,9 +78,9 @@ module Fgi
81
78
  git_services = Fgi::GitService.services
82
79
  # Display theses services to let the user choose the project's one
83
80
  git_services.each_with_index do |service, index|
84
- puts "#{index+1} : #{service.capitalize}"
81
+ puts "#{index + 1} : #{service.capitalize}"
85
82
  end
86
- puts "... More soon ..."
83
+ puts '... More soon ...'
87
84
 
88
85
  begin
89
86
  input = STDIN.gets.chomp
@@ -91,15 +88,15 @@ module Fgi
91
88
  # Convert the string input to an integer
92
89
  input = input.to_i
93
90
  # If the input isn't out of range...
94
- if (1..git_services.count).include?(input)
91
+ if (1..git_services.count).cover?(input)
95
92
  # Set a variable with the Git service name for displays
96
- @git_service = git_services[input-1].capitalize
93
+ @git_service = git_services[input - 1].capitalize
97
94
  Fgi::GitServices.const_get(@git_service)
98
95
  else
99
96
  puts "\nSorry, the option is out of range. Try again :"
100
97
  define_git_service
101
98
  end
102
- rescue Interrupt => int
99
+ rescue Interrupt
103
100
  exit!
104
101
  end
105
102
  end
@@ -116,18 +113,18 @@ module Fgi
116
113
  exit! if input == 'quit'
117
114
  # force scheme if not specified
118
115
  # TODO - Find a way to clear this... Find the correct scheme.
119
- input = if input.start_with?('gitlab.com')
120
- "https://#{input}"
121
- elsif !input.start_with?('http://', 'https://')
122
- "http://#{input}"
123
- end
116
+ if input.start_with?('gitlab.com')
117
+ input = "https://#{input}"
118
+ elsif !input.start_with?('http://', 'https://')
119
+ input = "http://#{input}"
120
+ end
124
121
  # Call the entered url to know if it exist or not.
125
122
  # If not, would raise an exception
126
123
  get(url: input)
127
124
  input
128
- rescue Interrupt => int
125
+ rescue Interrupt
129
126
  exit!
130
- rescue Exception => e
127
+ rescue Exception
131
128
  puts "\nOops, seems to be a bad url. Try again or quit (quit)"
132
129
  save_git_url
133
130
  end
@@ -136,10 +133,9 @@ module Fgi
136
133
  # Ask for the user for his Git service token
137
134
  # @param git_service [Class] the current project's git service class
138
135
  # @return [String] the user Git service token
139
- def save_user_token(git_service)
140
- token = Fgi::Tokens.get_token(git_service)
136
+ def save_user_token(config:, git_service:)
137
+ token = Fgi::Tokens.get_token(config: config, git_service: git_service)
141
138
  return token unless token.nil?
142
- save_user_token(git_service)
143
139
  end
144
140
 
145
141
  # Ask the user to search for the project and to select the correct one.
@@ -161,7 +157,7 @@ module Fgi
161
157
  if response[:status] == '200' && !response[:body].empty?
162
158
  puts "\nFound #{response[:body].count} match(es):"
163
159
  response[:body].each_with_index do |project, index|
164
- puts "#{index+1} - #{project['name_with_namespace']}"
160
+ puts "#{index + 1} - #{project['name_with_namespace']}"
165
161
  end
166
162
 
167
163
  puts "\nPlease insert the number of the current project :"
@@ -174,10 +170,10 @@ module Fgi
174
170
 
175
171
  else
176
172
  puts "\nOops, we couldn't find a project called #{input}. Try again or quit (quit) :"
177
- puts '-------------------------------------------------------------------'+('-'*input.length) # Don't be upset, i'm a perfectionist <3
173
+ puts '-------------------------------------------------------------------' + ('-' * input.length) # Don't be upset, i'm a perfectionist <3
178
174
  define_project_name_and_id(git_service, user_token)
179
175
  end
180
- rescue Interrupt => int
176
+ rescue Interrupt
181
177
  exit!
182
178
  end
183
179
  end
@@ -186,23 +182,21 @@ module Fgi
186
182
  puts "\nPlease define the default project branch :"
187
183
  puts '------------------------------------------'
188
184
 
189
- url = "#{git_service.routes[:branches]}"
185
+ url = git_service.routes[:branches]
190
186
  response = get(url: url, headers: { git_service.token_header => user_token })
187
+ return unless response[:status] == '200' && !response[:body].empty?
191
188
 
192
- if response[:status] == '200' && !response[:body].empty?
193
- begin
194
- response[:body].each_with_index do |branch, index|
195
- puts "#{index+1} - #{branch['name']}"
196
- end
197
-
198
- puts "\nPlease insert the number of the default project branch :"
199
- puts '--------------------------------------------------------'
200
- input = validate_choice(response[:body])
201
- response[:body][input - 1]['name']
202
-
203
- rescue Interrupt => int
204
- exit!
189
+ begin
190
+ response[:body].each_with_index do |branch, index|
191
+ puts "#{index + 1} - #{branch['name']}"
205
192
  end
193
+
194
+ puts "\nPlease insert the number of the default project branch :"
195
+ puts '--------------------------------------------------------'
196
+ input = validate_choice(response[:body])
197
+ response[:body][input - 1]['name']
198
+ rescue Interrupt
199
+ exit!
206
200
  end
207
201
  end
208
202
 
@@ -210,7 +204,7 @@ module Fgi
210
204
  input = STDIN.gets.chomp
211
205
  exit! if input == 'quit'
212
206
  input = input.to_i
213
- if (1..response_body.count).include?(input)
207
+ if (1..response_body.count).cover?(input)
214
208
  input
215
209
  else
216
210
  puts "\nSorry, the option is out of range. Try again :"
@@ -2,120 +2,227 @@
2
2
  module Fgi
3
3
  class GitService
4
4
  class << self
5
+
5
6
  include HttpRequests
6
7
 
8
+ # @return [Array<String>] an array containing all the git services available.
7
9
  def services
8
10
  services = []
9
11
  Dir.entries("#{File.dirname(__FILE__)}/git_services").each do |service|
10
- services << service.gsub(/.rb/, '').to_sym unless %w(. ..).include?(service)
12
+ services << service.gsub(/.rb/, '').to_sym unless %w[. ..].include?(service)
11
13
  end
12
14
  services
13
15
  end
14
16
 
15
- def create_issue(title: title, options: {})
17
+ # All the process initiated by the issue creation
18
+ # => Create issue
19
+ # => Create a new branch from the default one
20
+ # => Set the issue estimation time
21
+ # @param title [String] the issue title
22
+ # @param options [Hash] the options given by the user in the command line
23
+ def new_issue(title:, options: {})
16
24
  git_service = CONFIG[:git_service_class].new
17
25
  title = get_issue_title if title.nil?
18
- description = get_issue_description
19
-
20
- headers = { git_service.token_header => TOKEN, 'Content-Type' => 'application/json' }
21
- url_with_querystring = "#{git_service.routes[:issues]}?title=#{URI.encode(title)}&description=#{URI.encode(description)}"
22
-
23
- response = post(url: url_with_querystring, headers: headers)
24
- response_body = JSON.parse(response[:body])
25
-
26
- post_issue_display(response_body)
26
+ response = create_issue(title: title, git_service: git_service)
27
27
 
28
28
  if CONFIG[:default_branch].nil?
29
29
  puts "\n/!\\ FGI IS NOT UP-TO-DATE /!\\"
30
30
  puts 'We are not able to create and switch you to the new branch.'
31
31
  puts 'Delete .config.fgi.yml and reconfigure fgi by running `fgi config`'
32
- else
33
- create_new_branch(title) unless response_body['iid'].nil? || options[:later]
32
+ elsif !response['iid'].nil?
33
+ branch_name = snakify(title)
34
+ branch_name = "#{options[:prefix]}/#{branch_name}" unless options[:prefix].nil?
35
+ save_issue(branch: branch_name, id: response['iid'], title: response['title'].tr("'", ' '))
36
+ create_branch(branch_name) unless options[:later]
37
+ set_issue_estimation(
38
+ issue_id: response['iid'],
39
+ estimation: options[:estimate],
40
+ git_service: git_service
41
+ )
34
42
  end
43
+ end
35
44
 
36
- unless options[:estimate].nil?
37
- # Since GitLab version isn't up to date, we should be able to add estimations in issues comments (/estimate)
38
- url_with_querystring = "#{git_service.routes[:issues]}/#{response_body['iid']}/time_estimate?duration=#{options[:estimate]}"
39
- response = post(url: url_with_querystring, headers: headers)
40
- # GitLab sucks sometimes... This API is an example
41
- begin
42
- response_body = JSON.parse(response[:body])
43
- rescue Exception => e
44
- response_body = response[:body]
45
+ # All the process initiated by the issue fix
46
+ # => Commiting with a 'Fix #<id>' message
47
+ # => Pushing the current branch to the remote repo
48
+ # => Return to the default project branch
49
+ # @param options [Hash] the options given by the user in the command line
50
+ def fix_issue(options)
51
+ current_branch = `git branch | grep '*'`.gsub('* ', '').chomp
52
+ if ISSUES[current_branch].nil?
53
+ puts "We could not find any issues to fix on your current branch (#{current_branch})."
54
+ exit!
55
+ end
56
+ git_remote = ask_for_remote
57
+ `git add .`
58
+ puts "Are you sure to want to close the issue #{ISSUES[current_branch][:title]} ?"
59
+ begin
60
+ input = STDIN.gets.chomp
61
+ if %w[y yes].include?(input)
62
+ commit_message = "Fix ##{ISSUES[current_branch][:id]}"
63
+ commit_message += " - #{options[:fix_message]}" unless options[:fix_message].nil?
64
+ `git commit -a --allow-empty -m '#{commit_message}'`
65
+ `git push #{git_remote} HEAD`
66
+ `git checkout #{CONFIG[:default_branch]}` # Be sure to be on the default branch.
67
+ remove_issue(current_branch)
68
+ puts "Congrat's ! You're now back to work on the default branch (#{CONFIG[:default_branch]})"
45
69
  end
46
-
47
- post_estimation_display(response_body, options[:estimate])
70
+ rescue Interrupt
71
+ puts %q"Why did you killed me ? :'("
72
+ exit!
48
73
  end
49
74
  end
50
75
 
51
- def create_new_branch(issue_title)
52
- branch_name = snakecase(issue_title)
53
- unless %x(git status -s).empty?
54
- begin
55
- puts "\nThere are unsaved changes on your current branch."
56
- puts "Do you want to see them ? (y/n)"
57
- puts '-------------------------------'
58
- input = STDIN.gets.chomp
59
- system('git diff') if %w[y yes].include?(input)
60
-
61
- puts "\nDo you want to COMMIT theses changes ? (y/n)"
62
- puts '--------------------------------------------'
63
- input = STDIN.gets.chomp
64
- if %w[y yes].include?(input)
65
- commit_changes
66
- else
67
- stash_changes
68
- end
69
-
70
- rescue Interrupt => int
71
- puts %q"Why did you killed me ? :'("
72
- exit!
76
+ private
77
+
78
+ def ask_for_remote
79
+ remotes = `git remote`.split("\n")
80
+ return remotes.first if remotes.count == 1
81
+
82
+ puts "\nHere are your remotes :"
83
+ remotes.each_with_index do |remote, index|
84
+ puts "#{index + 1} - #{remote}"
85
+ end
86
+
87
+ begin
88
+ puts "\nPlease insert the number of the remote to use :"
89
+ puts '-----------------------------------------------'
90
+ input = STDIN.gets.chomp
91
+ exit! if input == 'quit'
92
+ input = input.to_i
93
+ if (1..remotes.count).cover?(input)
94
+ remotes[input-1]
95
+ else
96
+ puts "\nSorry, the option is out of range. Try again :"
97
+ ask_for_remote
73
98
  end
99
+ rescue Interrupt
100
+ puts %q"Why did you killed me ? :'("
101
+ exit!
74
102
  end
75
- %x(git checkout #{CONFIG[:default_branch]}) # Be sure to be on the default branch.
76
- from = %x(git branch | grep '*').gsub('* ', '').chomp
77
- %x(git pull origin HEAD) # Be sure to get the remote changes locally.
78
- %x(git checkout -b #{branch_name}) # Create the new branch.
79
- to = %x(git branch | grep '*').gsub('* ', '').chomp
80
- puts "\nYou are now working on branch #{to} created from #{from} !"
81
103
  end
82
104
 
83
- private
105
+ # Save the current user's FGI created issue in the gitignored file 'current_issue.fgi.yml'
106
+ # @param id [Integer] the current issue id
107
+ # @param title [String] the current issue name
108
+ def save_issue(branch:, id:, title:)
109
+ if File.exist?('.current_issues.fgi.yml')
110
+ issues = YAML.load_file('.current_issues.fgi.yml')
111
+ issues[branch] = { id: id, title: title }
112
+ else
113
+ issues = {
114
+ branch => {
115
+ id: id,
116
+ title: title
117
+ }
118
+ }
119
+ end
120
+ # Shouldn't we define some access restrictions on this file ?
121
+ File.open('.current_issues.fgi.yml', 'w') { |f| f.write(issues.to_yaml) }
122
+ end
123
+
124
+ def remove_issue(branch)
125
+ issues = YAML.load_file('.current_issues.fgi.yml')
126
+ issues.delete(branch) unless ISSUES[branch].nil?
127
+ File.open('.current_issues.fgi.yml', 'w') { |f| f.write(issues.to_yaml) }
128
+ end
129
+
130
+ # TODO, Make sure it works for all git services
131
+ # The method to set the estimation time to resolve the issue
132
+ # @param issue_id [Integer] the issue id to set its estimation time
133
+ # @param estimation [String] the estimation time given by the user
134
+ # @param git_service [Class] the git service class to use for this project
135
+ def set_issue_estimation(issue_id:, estimation:, git_service:)
136
+ return if estimation.nil?
137
+ # Since GitLab version isn't up to date, we should be able
138
+ # to add estimations in issues comments (/estimate)
139
+ url_with_querystring = "#{git_service.routes[:issues]}/#{issue_id}/time_estimate?duration=#{estimation}"
140
+ response = post(url: url_with_querystring, headers: headers)
141
+ # GitLab sucks sometimes... This API is an example
142
+ begin
143
+ response_body = JSON.parse(response[:body])
144
+ rescue Exception
145
+ response_body = response[:body]
146
+ end
147
+ post_estimation_display(response_body['human_time_estimate'], estimation)
148
+ end
149
+
150
+ # TODO, Make sure it works for all git services
151
+ # The method used to create issues
152
+ # @param title [String] the issue title
153
+ # @param git_service [Class] the git service class to use for this project
154
+ # @return [Boolean] true if the issue has been created, false otherwise
155
+ def create_issue(title:, git_service:)
156
+ description = get_issue_description
157
+
158
+ headers = { git_service.token_header => TOKEN, 'Content-Type' => 'application/json' }
159
+ url_with_querystring = "#{git_service.routes[:issues]}?title=#{CGI.escape(title)}&description=#{CGI.escape(description)}"
160
+
161
+ response = post(url: url_with_querystring, headers: headers)
162
+ response_body = JSON.parse(response[:body])
163
+
164
+ post_issue_display(response_body['iid'])
165
+ response_body
166
+ end
84
167
 
168
+ # The method used to create branches
169
+ # @param name [String] the branch name
170
+ def create_branch(name)
171
+ check_status
172
+ git_remote = ask_for_remote
173
+ `git checkout #{CONFIG[:default_branch]}` # Be sure to be on the default branch.
174
+ from = `git branch | grep '*'`.gsub('* ', '').chomp
175
+ `git pull #{git_remote} HEAD` # Be sure to get the remote changes locally.
176
+ `git checkout -b #{name}` # Create the new branch.
177
+ to = `git branch | grep '*'`.gsub('* ', '').chomp
178
+ puts "\nYou are now working on branch #{to} created from #{from} !"
179
+ end
180
+
181
+ # The method used to get the issue description
182
+ # @return [String] the issue description
85
183
  def get_issue_description
86
184
  puts "\nWrite your issue description right bellow (save and quit with CTRL+D) :"
87
185
  puts "-----------------------------------------------------------------------\n\n"
88
186
  begin
89
187
  STDIN.read
90
- rescue Interrupt => int
188
+ rescue Interrupt
91
189
  puts %q"Why did you killed me ? :'("
92
190
  exit!
93
191
  end
94
192
  end
95
193
 
194
+ # The method used to get the issue title if not given the first time
195
+ # @return [String] the issue title
96
196
  def get_issue_title
97
- puts "\nWhat if your issue title :"
197
+ puts "\nWhat is your issue title :"
98
198
  puts "--------------------------\n\n"
99
199
  begin
100
200
  STDIN.gets.chomp
101
- rescue Interrupt => int
201
+ rescue Interrupt
102
202
  puts %q"Why did you killed me ? :'("
103
203
  exit!
104
204
  end
105
205
  end
106
206
 
107
- def post_issue_display(response)
108
- unless response['iid'].nil?
207
+ # The display method to let the user know
208
+ # if the issue has correctly been created
209
+ # @param issue_id [Integer] the id of the created issue
210
+ def post_issue_display(issue_id)
211
+ if !issue_id.nil?
109
212
  puts 'Your issue has been successfully created.'
110
213
  puts 'To view it, please follow the link bellow :'
111
- puts "\n#{CONFIG[:url]}/#{CONFIG[:project_slug]}/issues/#{response['iid']}"
214
+ puts "\n#{CONFIG[:url]}/#{CONFIG[:project_slug]}/issues/#{issue_id}"
112
215
  else
113
216
  puts %q(Your issue couldn't be created. Check your FGI configuration.)
114
217
  end
115
218
  end
116
219
 
117
- def post_estimation_display(response, estimation)
118
- if response['human_time_estimate'].nil?
220
+ # The display method to let the user know if the
221
+ # estimation time has correctly been set on the issue
222
+ # @param response_estimation [String] the estimation time response from the git service
223
+ # @param estimation [String] the estimation time given by the user
224
+ def post_estimation_display(response_estimation, estimation)
225
+ if response_estimation.nil?
119
226
  puts "\nWe weren't able to save your estimation."
120
227
  puts "You'll have to do it manually on #{CONFIG[:git_service].capitalize}."
121
228
  else
@@ -123,28 +230,59 @@ module Fgi
123
230
  end
124
231
  end
125
232
 
233
+ # The method used to commit the user's local changes
126
234
  def commit_changes
127
235
  puts 'Enter your commit message :'
128
236
  commit_message = STDIN.gets.chomp
129
- %x(git add .)
130
- %x(git commit -am '#{commit_message}')
237
+ `git add .`
238
+ `git commit -am '#{commit_message}'`
131
239
  puts 'Your changes have been commited !'
132
240
  end
133
241
 
242
+ # The method used to stash the user's local changes
134
243
  def stash_changes
135
- %x(git add .)
136
- %x(git stash)
244
+ `git add .`
245
+ `git stash`
137
246
  puts "\nYour changes have been stashed."
138
- puts "We will let you manually `git stash pop` to get your work back if needed.\n"
247
+ puts "We will let you manually git stash pop to get your work back if needed.\n"
248
+ end
249
+
250
+ # The method used to check if there are local changes and to
251
+ # ask the user if he want to commit or stash theses changes
252
+ def check_status
253
+ return if `git status -s`.empty?
254
+ begin
255
+ puts "\nThere are unsaved changes on your current branch."
256
+ puts 'Do you want to see them ? (y/n)'
257
+ puts '-------------------------------'
258
+ input = STDIN.gets.chomp
259
+ system('git diff') if %w[y yes].include?(input)
260
+
261
+ puts "\nDo you want to COMMIT theses changes ? (y/n)"
262
+ puts '--------------------------------------------'
263
+ input = STDIN.gets.chomp
264
+ if %w[y yes].include?(input)
265
+ commit_changes
266
+ else
267
+ stash_changes
268
+ end
269
+ rescue Interrupt
270
+ puts %q"Why did you killed me ? :'("
271
+ exit!
272
+ end
139
273
  end
140
274
 
141
- def snakecase(string)
142
- string.gsub(/::/, '/').
143
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
144
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
145
- tr('-', '_').
146
- tr(' ', '_').
147
- downcase
275
+ # The method used to snakify strings
276
+ # @param string [String] the string to snakify
277
+ # @return [String] the snakified string
278
+ def snakify(string)
279
+ string.gsub(/::/, '/')
280
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
281
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
282
+ .tr('-', '_')
283
+ .tr(' ', '_')
284
+ .tr("'", '_')
285
+ .downcase
148
286
  end
149
287
 
150
288
  end
@@ -3,27 +3,18 @@ module Fgi
3
3
  module GitServices
4
4
  class Gitlab
5
5
 
6
+ attr_reader :version, :token_header, :routes
7
+
6
8
  def initialize(config: CONFIG)
7
- @version = 'v4'
9
+ @version = 'v4'
10
+ @main_url = "#{config[:url]}/api/#{@version}"
8
11
  @token_header = 'PRIVATE-TOKEN'
9
12
  @routes = {
10
- projects: "#{config[:url]}/api/#{@version}/projects",
11
- search_projects: "#{config[:url]}/api/#{@version}/projects?search=",
12
- issues: "#{config[:url]}/api/#{@version}/projects/#{config[:project_id]}/issues",
13
- branches: "#{config[:url]}/api/#{@version}/projects/#{config[:project_id]}/repository/branches"
14
- }
15
- end
16
-
17
- def version
18
- @version
19
- end
20
-
21
- def token_header
22
- @token_header
23
- end
24
-
25
- def routes
26
- @routes
13
+ projects: "#{@main_url}/projects",
14
+ search_projects: "#{@main_url}/projects?search=",
15
+ issues: "#{@main_url}/projects/#{config[:project_id]}/issues",
16
+ branches: "#{@main_url}/projects/#{config[:project_id]}/repository/branches"
17
+ }
27
18
  end
28
19
 
29
20
  def to_sym
@@ -2,55 +2,56 @@
2
2
  module Fgi
3
3
  module HttpRequests
4
4
 
5
- # Generic method to GET requests
6
- # @param url [String] the given Git service API url for GET request
7
- # @param headers [Hash] the headers to set for the request
8
- # @return [String] the received response from the Git service API
9
- def get(url:, headers: nil)
10
- http_request(verb: :get, url: url, headers: headers)
5
+ # Generic method to GET requests
6
+ # @param url [String] the given Git service API url for GET request
7
+ # @param headers [Hash] the headers to set for the request
8
+ # @return [String] the received response from the Git service API
9
+ def get(url:, headers: nil)
10
+ http_request(verb: :get, url: url, headers: headers)
11
+ end
12
+
13
+ # Generic method to POST requests
14
+ # @param url [String] the given Git service API url for POST request
15
+ # @param headers [Hash] the headers to set for the request
16
+ # @param body [Hash] the body to set for the request
17
+ # @return [String] the received response from the Git service API
18
+ def post(url:, headers: nil, body: nil)
19
+ http_request(verb: :post, url: url, headers: headers, body: body)
20
+ end
21
+
22
+ private
23
+
24
+ # Generic method for HTTP requests
25
+ # @param url [String] the given Git service API url for a HTTP request
26
+ # @param headers [Hash] the headers to set for the request
27
+ # @param body [Hash] the body to set for the request
28
+ # @return [String] the received response from the Git service API
29
+ def http_request(verb:, url:, headers: nil, body: nil)
30
+ is_https = url.start_with?('https')
31
+ uri = URI.parse(url)
32
+
33
+ req = case verb
34
+ when :get
35
+ Net::HTTP::Get.new(url)
36
+ when :post
37
+ Net::HTTP::Post.new(url)
38
+ end
39
+
40
+ # Set headers if given
41
+ headers.each { |k, v| req[k] = v } unless headers.nil?
42
+ # Set body if given
43
+ req.body = body.to_json unless body.nil?
44
+
45
+ res = Net::HTTP.start(uri.host, uri.port, use_ssl: is_https) do |http|
46
+ http.request(req)
11
47
  end
12
48
 
13
- # Generic method to POST requests
14
- # @param url [String] the given Git service API url for POST request
15
- # @param headers [Hash] the headers to set for the request
16
- # @param body [Hash] the body to set for the request
17
- # @return [String] the received response from the Git service API
18
- def post(url:, headers: nil, body: nil)
19
- http_request(verb: :post, url: url, headers: headers)
20
- end
21
-
22
- private
23
-
24
- # Generic method for HTTP requests
25
- # @param url [String] the given Git service API url for a HTTP request
26
- # @param headers [Hash] the headers to set for the request
27
- # @param body [Hash] the body to set for the request
28
- # @return [String] the received response from the Git service API
29
- def http_request(verb:, url:, headers: nil, body: nil)
30
- is_https = url.start_with?('https')
31
- uri = URI.parse(url)
32
- req = case verb
33
- when :get
34
- Net::HTTP::Get.new(url)
35
- when :post
36
- Net::HTTP::Post.new(url)
37
- end
38
-
39
- # Set headers if given
40
- headers.each { |k, v| req[k] = v } unless headers.nil?
41
- # Set body if given
42
- req.body = body.to_json unless body.nil?
43
-
44
- res = Net::HTTP.start(uri.host, uri.port, use_ssl: is_https) do |http|
45
- http.request(req)
46
- end
47
-
48
- if res.code == '200'
49
- { status: '200', body: JSON.parse(res.body) }
50
- else
51
- { status: res.code, body: res.body }
52
- end
49
+ if res.code == '200'
50
+ { status: '200', body: JSON.parse(res.body) }
51
+ else
52
+ { status: res.code, body: res.body }
53
53
  end
54
+ end
54
55
 
55
56
  end
56
57
  end
data/lib/fgi/tokens.rb CHANGED
@@ -2,16 +2,21 @@
2
2
  module Fgi
3
3
  class Tokens
4
4
  class << self
5
+
5
6
  include HttpRequests
6
7
 
7
8
  # @param git_service_name [String] the git service to associate a token to
8
9
  # @param token [String] the token to associate to the git service
9
- def create_user_tokens_file(git_service, token)
10
- if File.exists?("#{Dir.home}/.tokens.fgi.yml")
10
+ def create_user_tokens_file(config:, git_service:, token:)
11
+ if File.exist?("#{Dir.home}/.tokens.fgi.yml")
11
12
  tokens = YAML.load_file("#{Dir.home}/.tokens.fgi.yml")
12
- tokens[git_service] = token
13
+ tokens[git_service.to_sym] = { config[:url] => token }
13
14
  else
14
- tokens = { git_service => token }
15
+ tokens = {
16
+ git_service => {
17
+ config[:url] => token
18
+ }
19
+ }
15
20
  end
16
21
  # Shouldn't we define some access restrictions on this file ?
17
22
  File.open("#{Dir.home}/.tokens.fgi.yml", 'w') { |f| f.write(tokens.to_yaml) }
@@ -34,12 +39,12 @@ module Fgi
34
39
  # @param git_service [Class] the current project's git service class
35
40
  # @return [String] the current token associated to the project's git service
36
41
  # @return [NilClass] if there is no token associated to the project's git service
37
- def get_token(git_service)
38
- if File.exists?("#{Dir.home}/.tokens.fgi.yml")
42
+ def get_token(config:, git_service:)
43
+ if File.exist?("#{Dir.home}/.tokens.fgi.yml")
39
44
  tokens = YAML.load_file("#{Dir.home}/.tokens.fgi.yml")
40
- tokens[git_service.to_sym]
45
+ tokens[git_service.to_sym][config[:url]]
41
46
  else
42
- puts "\nPlease enter your #{git_service.to_s} token :"
47
+ puts "\nPlease enter your #{git_service} token :"
43
48
  puts '(use `fgi --help` to check how to get your token)'
44
49
  puts '-------------------------------------------------'
45
50
  begin
@@ -47,7 +52,7 @@ module Fgi
47
52
  exit! if token == 'quit'
48
53
  return token if token_valid?(git_service, token)
49
54
  nil
50
- rescue Interrupt => int
55
+ rescue Interrupt
51
56
  exit!
52
57
  end
53
58
  end
@@ -57,7 +62,10 @@ module Fgi
57
62
  # @param token [String] the token to check the validity
58
63
  # @return [Boolean] true if the token is valid, false otherwise
59
64
  def token_valid?(git_service, token)
60
- response = get(url: git_service.routes[:projects], headers: { git_service.token_header => token })
65
+ response = get(
66
+ url: git_service.routes[:projects],
67
+ headers: { git_service.token_header => token }
68
+ )
61
69
  response[:status] == '200'
62
70
  end
63
71
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fgi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julien Philibin
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-09-14 00:00:00.000000000 Z
12
+ date: 2017-10-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler