git-process 1.0.11 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/CHANGELOG.md +37 -9
  2. data/Gemfile +2 -2
  3. data/Gemfile.lock +17 -17
  4. data/README.md +14 -7
  5. data/bin/git-new-fb +10 -2
  6. data/bin/git-pull-request +30 -6
  7. data/bin/git-sync +5 -2
  8. data/bin/git-to-master +62 -11
  9. data/git-process.gemspec +15 -15
  10. data/lib/git-process/abstract_error_builder.rb +0 -3
  11. data/lib/git-process/changed_file_helper.rb +30 -24
  12. data/lib/git-process/git_abstract_merge_error_builder.rb +31 -11
  13. data/lib/git-process/git_branch.rb +5 -0
  14. data/lib/git-process/git_config.rb +153 -0
  15. data/lib/git-process/git_lib.rb +212 -164
  16. data/lib/git-process/git_logger.rb +84 -0
  17. data/lib/git-process/git_merge_error.rb +3 -14
  18. data/lib/git-process/git_process.rb +44 -73
  19. data/lib/git-process/git_process_options.rb +6 -6
  20. data/lib/git-process/git_rebase_error.rb +4 -13
  21. data/lib/git-process/git_remote.rb +254 -0
  22. data/lib/git-process/github_configuration.rb +298 -0
  23. data/lib/git-process/github_pull_request.rb +65 -27
  24. data/lib/git-process/new_fb.rb +14 -4
  25. data/lib/git-process/parked_changes_error.rb +1 -1
  26. data/lib/git-process/pull_request.rb +100 -13
  27. data/lib/git-process/pull_request_error.rb +25 -0
  28. data/lib/git-process/rebase_to_master.rb +47 -27
  29. data/lib/git-process/sync.rb +48 -33
  30. data/lib/git-process/uncommitted_changes_error.rb +1 -1
  31. data/lib/git-process/version.rb +2 -2
  32. data/spec/GitRepoHelper.rb +48 -25
  33. data/spec/changed_file_helper_spec.rb +39 -58
  34. data/spec/git_abstract_merge_error_builder_spec.rb +42 -33
  35. data/spec/git_branch_spec.rb +30 -30
  36. data/spec/git_config_spec.rb +45 -0
  37. data/spec/git_lib_spec.rb +103 -122
  38. data/spec/git_logger_spec.rb +66 -0
  39. data/spec/git_process_spec.rb +81 -81
  40. data/spec/git_remote_spec.rb +188 -0
  41. data/spec/git_status_spec.rb +36 -36
  42. data/spec/github_configuration_spec.rb +152 -0
  43. data/spec/github_pull_request_spec.rb +39 -35
  44. data/spec/github_test_helper.rb +49 -0
  45. data/spec/new_fb_spec.rb +65 -24
  46. data/spec/pull_request_helper.rb +94 -0
  47. data/spec/pull_request_spec.rb +128 -0
  48. data/spec/rebase_to_master_spec.rb +241 -145
  49. data/spec/spec_helper.rb +20 -0
  50. data/spec/sync_spec.rb +115 -109
  51. metadata +34 -20
  52. data/lib/git-process/github_client.rb +0 -83
  53. data/lib/git-process/github_service.rb +0 -174
  54. data/spec/github_service_spec.rb +0 -211
@@ -14,9 +14,6 @@ require 'shellwords'
14
14
 
15
15
  module GitProc
16
16
 
17
- #
18
- # Assumes that there are two attributes defined: error_message, lib
19
- #
20
17
  module AbstractErrorBuilder
21
18
 
22
19
  def commands
@@ -19,32 +19,34 @@ module GitProc
19
19
  #
20
20
  # Provides support for prompting the user when the dir/index is dirty.
21
21
  #
22
- # = Assumes =
23
- # log_level
24
- # workdir
25
- #
26
- module ChangeFileHelper
27
- include GitLib
22
+ #noinspection RubyControlFlowConversionInspection,RubyClassMethodNamingConvention,RubyInstanceMethodNamingConvention
23
+ class ChangeFileHelper
24
+
25
+ # @param [GitLib] gitlib
26
+ def initialize(gitlib)
27
+ @gitlib = gitlib
28
+ end
28
29
 
29
30
 
30
31
  def offer_to_help_uncommitted_changes
31
- stat = status
32
+ stat = gitlib.status
32
33
 
33
34
  if stat.unmerged.empty?
34
35
  handle_unknown_files(stat)
35
- handle_changed_files(status) # refresh status in case it changed earlier
36
+ handle_changed_files(gitlib.status) # refresh status in case it changed earlier
36
37
  else
37
- logger.info { "Can not offer to auto-add unmerged files: #{stat.unmerged.inspect}" }
38
+ gitlib.logger.info { "Can not offer to auto-add unmerged files: #{stat.unmerged.inspect}" }
38
39
  raise UncommittedChangesError.new
39
40
  end
40
41
  end
41
42
 
42
43
 
44
+ #noinspection RubyControlFlowConversionInspection
43
45
  def handle_unknown_files(stat)
44
46
  if not stat.unknown.empty?
45
- resp = ask_how_to_handle_unknown_files(stat)
47
+ resp = ChangeFileHelper.ask_how_to_handle_unknown_files(stat)
46
48
  if resp == :add
47
- add(stat.unknown)
49
+ gitlib.add(stat.unknown)
48
50
  end
49
51
  end
50
52
  end
@@ -52,26 +54,25 @@ module GitProc
52
54
 
53
55
  def handle_changed_files(stat)
54
56
  if not stat.modified.empty? or not stat.added.empty? or not stat.deleted.empty?
55
- resp = ask_how_to_handle_changed_files(stat)
57
+ resp = ChangeFileHelper.ask_how_to_handle_changed_files(stat)
56
58
  if resp == :commit
57
59
  changed_files = (stat.added + stat.modified - stat.deleted).sort.uniq
58
60
 
59
- add(changed_files) unless changed_files.empty?
60
- remove(stat.deleted) unless stat.deleted.empty?
61
+ gitlib.add(changed_files) unless changed_files.empty?
62
+ gitlib.remove(stat.deleted) unless stat.deleted.empty?
61
63
 
62
- commit(nil)
64
+ gitlib.commit(nil)
63
65
  else
64
- stash_save
65
- @stash_pushed = true
66
+ gitlib.stash_save
66
67
  end
67
68
  end
68
69
  end
69
70
 
70
71
 
71
- def ask_how_to_handle_unknown_files(stat)
72
+ def self.ask_how_to_handle_unknown_files(stat)
72
73
  show_changes(:unknown, stat)
73
- resp = ask("Would you like to (a)dd them or (i)gnore them? ") do |q|
74
- q.responses[:not_valid] = "Please respond with either (a)dd or (i)gnore. (Ctl-C to abort.) "
74
+ resp = ask('Would you like to (a)dd them or (i)gnore them? ') do |q|
75
+ q.responses[:not_valid] = 'Please respond with either (a)dd or (i)gnore. (Ctl-C to abort.) '
75
76
  q.case = :down
76
77
  q.validate = /a|i/i
77
78
  end
@@ -80,7 +81,7 @@ module GitProc
80
81
  end
81
82
 
82
83
 
83
- def show_changes(type, stat)
84
+ def self.show_changes(type, stat)
84
85
  files = stat.send(type)
85
86
 
86
87
  if type != :deleted
@@ -93,10 +94,10 @@ module GitProc
93
94
  end
94
95
 
95
96
 
96
- def ask_how_to_handle_changed_files(stat)
97
+ def self.ask_how_to_handle_changed_files(stat)
97
98
  [:added, :modified, :deleted].each { |t| show_changes(t, stat) }
98
- resp = ask("Would you like to (c)ommit them or (s)tash them? ") do |q|
99
- q.responses[:not_valid] = "Please respond with either (c)ommit or (s)tash. (Ctl-C to abort.) "
99
+ resp = ask('Would you like to (c)ommit them or (s)tash them? ') do |q|
100
+ q.responses[:not_valid] = 'Please respond with either (c)ommit or (s)tash. (Ctl-C to abort.) '
100
101
  q.case = :down
101
102
  q.validate = /c|s/i
102
103
  end
@@ -104,6 +105,11 @@ module GitProc
104
105
  resp == 'c' ? :commit : :stash
105
106
  end
106
107
 
108
+
109
+ def gitlib
110
+ @gitlib
111
+ end
112
+
107
113
  end
108
114
 
109
115
  end
@@ -15,12 +15,19 @@ require 'shellwords'
15
15
 
16
16
  module GitProc
17
17
 
18
- #
19
- # Assumes that there are three attributes defined: error_message, lib, continue_command
20
- #
21
- module AbstractMergeErrorBuilder
18
+ #noinspection RubyTooManyInstanceVariablesInspection
19
+ class AbstractMergeErrorBuilder
22
20
  include GitProc::AbstractErrorBuilder
23
21
 
22
+ attr_reader :gitlib, :error_message, :continue_command
23
+
24
+
25
+ def initialize(gitlib, error_message, continue_command)
26
+ @gitlib = gitlib
27
+ @error_message = error_message
28
+ @continue_command = continue_command
29
+ end
30
+
24
31
 
25
32
  def resolved_files
26
33
  @resolved_files ||= find_resolved_files
@@ -53,7 +60,7 @@ module GitProc
53
60
  end
54
61
  end
55
62
 
56
- unless lib.rerere_enabled?
63
+ unless config.rerere_enabled?
57
64
  msg << "\n\nConsider turning on 'rerere'.\nSee http://git-scm.com/2010/03/08/rerere.html for more information."
58
65
  end
59
66
 
@@ -70,13 +77,13 @@ module GitProc
70
77
  def build_commands
71
78
  commands = []
72
79
 
73
- commands << 'git config --global rerere.enabled true' unless lib.rerere_enabled?
80
+ commands << 'git config --global rerere.enabled true' unless config.rerere_enabled?
74
81
 
75
82
  resolved_files.each do |file|
76
83
  commands << "# Verify that 'rerere' did the right thing for '#{file}'."
77
84
  end
78
85
 
79
- unless resolved_files.empty? or lib.rerere_autoupdate?
86
+ unless resolved_files.empty? or config.rerere_autoupdate?
80
87
  escaped_files = shell_escaped_files(resolved_files)
81
88
  commands << "git add #{escaped_files}"
82
89
  end
@@ -103,22 +110,35 @@ module GitProc
103
110
 
104
111
 
105
112
  def unmerged
106
- @unmerged ||= lib.status.unmerged
113
+ @unmerged ||= status.unmerged
107
114
  end
108
115
 
109
116
 
110
117
  def added
111
- @added ||= lib.status.added
118
+ @added ||= status.added
112
119
  end
113
120
 
114
121
 
115
122
  def deleted
116
- @deleted ||= lib.status.deleted
123
+ @deleted ||= status.deleted
117
124
  end
118
125
 
119
126
 
120
127
  def modified
121
- @modified ||= lib.status.modified
128
+ @modified ||= status.modified
129
+ end
130
+
131
+
132
+ private
133
+
134
+
135
+ def config
136
+ gitlib.config
137
+ end
138
+
139
+
140
+ def status
141
+ @status ||= gitlib.status
122
142
  end
123
143
 
124
144
  end
@@ -86,6 +86,11 @@ module GitProc
86
86
  end
87
87
 
88
88
 
89
+ def upstream(upstream_name)
90
+ @lib.branch(@name, :upstream => upstream_name)
91
+ end
92
+
93
+
89
94
  def contains_all_of(branch_name)
90
95
  @lib.rev_list(@name, branch_name, :oneline => true, :num_revs => 1) == ''
91
96
  end
@@ -0,0 +1,153 @@
1
+ # Licensed under the Apache License, Version 2.0 (the "License");
2
+ # you may not use this file except in compliance with the License.
3
+ # You may obtain a copy of the License at
4
+ #
5
+ # http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # Unless required by applicable law or agreed to in writing, software
8
+ # distributed under the License is distributed on an "AS IS" BASIS,
9
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the License for the specific language governing permissions and
11
+ # limitations under the License.
12
+
13
+ require 'git-process/git_logger'
14
+ require 'git-process/git_branch'
15
+ require 'git-process/git_branches'
16
+ require 'git-process/git_status'
17
+ require 'git-process/git_process_error'
18
+
19
+
20
+ class String
21
+
22
+ def to_boolean
23
+ return false if self == false || self.nil? || self =~ (/(false|f|no|n|0)$/i)
24
+ return true if self == true || self =~ (/(true|t|yes|y|1)$/i)
25
+ raise ArgumentError.new("invalid value for Boolean: \"#{self}\"")
26
+ end
27
+
28
+ end
29
+
30
+
31
+ class NilClass
32
+ def to_boolean
33
+ false
34
+ end
35
+ end
36
+
37
+
38
+ module GitProc
39
+
40
+ #
41
+ # Provides Git configuration
42
+ #
43
+ class GitConfig
44
+
45
+ def initialize(lib)
46
+ @lib = lib
47
+ end
48
+
49
+
50
+ def [](key)
51
+ value = config_hash[key]
52
+ unless value
53
+ value = @lib.command(:config, ['--get', key])
54
+ value = nil if value.empty?
55
+ config_hash[key] = value unless config_hash.empty?
56
+ end
57
+ value
58
+ end
59
+
60
+
61
+ def []=(key, value)
62
+ @lib.command(:config, [key, value])
63
+ config_hash[key] = value unless config_hash.empty?
64
+ value
65
+ end
66
+
67
+
68
+ def set_global(key, value)
69
+ @lib.command(:config, ['--global', key, value])
70
+ config_hash[key] = value unless config_hash.empty?
71
+ value
72
+ end
73
+
74
+
75
+ def gitlib
76
+ @lib
77
+ end
78
+
79
+
80
+ def logger
81
+ gitlib.logger
82
+ end
83
+
84
+
85
+ def master_branch
86
+ @master_branch ||= self['gitProcess.integrationBranch'] || 'master'
87
+ end
88
+
89
+
90
+ def remote_master_branch
91
+ remote.master_branch_name
92
+ end
93
+
94
+
95
+ def integration_branch
96
+ remote.exists? ? remote_master_branch : self.master_branch
97
+ end
98
+
99
+
100
+ def rerere_enabled?
101
+ re = self['rerere.enabled']
102
+ re && re.to_boolean
103
+ end
104
+
105
+
106
+ def rerere_enabled(re, global = true)
107
+ if global
108
+ set_global('rerere.enabled', re)
109
+ else
110
+ self['rerere.enabled'] = re
111
+ end
112
+ end
113
+
114
+
115
+ def rerere_enabled=(re)
116
+ rerere_enabled(re, false)
117
+ end
118
+
119
+
120
+ def rerere_autoupdate?
121
+ re = self['rerere.autoupdate']
122
+ re && re.to_boolean
123
+ end
124
+
125
+
126
+ def rerere_autoupdate(re, global = true)
127
+ if global
128
+ set_global('rerere.autoupdate', re)
129
+ else
130
+ self['rerere.autoupdate'] = re
131
+ end
132
+ end
133
+
134
+
135
+ def rerere_autoupdate=(re)
136
+ rerere_autoupdate(re, false)
137
+ end
138
+
139
+
140
+ private
141
+
142
+ def remote
143
+ gitlib.remote
144
+ end
145
+
146
+
147
+ def config_hash
148
+ @config_hash ||= {}
149
+ end
150
+
151
+ end
152
+
153
+ end
@@ -13,28 +13,11 @@
13
13
  require 'logger'
14
14
  require 'git-process/git_branch'
15
15
  require 'git-process/git_branches'
16
+ require 'git-process/git_remote'
16
17
  require 'git-process/git_status'
17
18
  require 'git-process/git_process_error'
18
19
 
19
20
 
20
- class String
21
-
22
- def to_boolean
23
- return false if self == false || self.nil? || self =~ (/(false|f|no|n|0)$/i)
24
- return true if self == true || self =~ (/(true|t|yes|y|1)$/i)
25
- raise ArgumentError.new("invalid value for Boolean: \"#{self}\"")
26
- end
27
-
28
- end
29
-
30
-
31
- class NilClass
32
- def to_boolean
33
- false
34
- end
35
- end
36
-
37
-
38
21
  module GitProc
39
22
 
40
23
  class GitExecuteError < GitProcessError
@@ -44,41 +27,95 @@ module GitProc
44
27
  #
45
28
  # Provides Git commands
46
29
  #
47
- # = Assumes =
48
- # log_level
49
- # workdir
50
- #
51
- module GitLib
30
+ #noinspection RubyTooManyMethodsInspection
31
+ class GitLib
32
+
33
+ # @param [Dir] dir
34
+ def initialize(dir, opts)
35
+ self.log_level = GitLib.log_level(opts)
36
+ self.workdir = dir
37
+ end
38
+
52
39
 
53
40
  def logger
54
41
  if @logger.nil?
55
- @logger = Logger.new(STDOUT)
56
- @logger.level = log_level || Logger::WARN
57
- @logger.datetime_format = "%Y-%m-%d %H:%M:%S"
58
- @logger.formatter = proc do |_, _, _, msg|
59
- "#{msg}\n"
60
- end
42
+ @logger = GitLogger.new(log_level)
61
43
  end
62
44
  @logger
63
45
  end
64
46
 
65
47
 
66
- def server_name
67
- @server_name ||= remote_name
48
+ def self.log_level(opts)
49
+ if opts[:log_level]
50
+ opts[:log_level]
51
+ elsif opts[:quiet]
52
+ Logger::ERROR
53
+ elsif opts[:verbose]
54
+ Logger::DEBUG
55
+ else
56
+ Logger::INFO
57
+ end
58
+ end
59
+
60
+
61
+ def log_level
62
+ @log_level || Logger::WARN
63
+ end
64
+
65
+
66
+ def log_level=(lvl)
67
+ @log_level = lvl
68
+ end
69
+
70
+
71
+ def workdir
72
+ @workdir
73
+ end
74
+
75
+
76
+ def workdir=(dir)
77
+ workdir = GitLib.find_workdir(dir)
78
+ if workdir.nil?
79
+ @workdir = dir
80
+ logger.info { "Initializing new repository at #{dir}" }
81
+ command(:init)
82
+ else
83
+ @workdir = workdir
84
+ logger.debug { "Opening existing repository at #{dir}" }
85
+ end
86
+ end
87
+
88
+
89
+ def self.find_workdir(dir)
90
+ if dir == File::SEPARATOR
91
+ nil
92
+ elsif File.directory?(File.join(dir, '.git'))
93
+ dir
94
+ else
95
+ find_workdir(File.expand_path("#{dir}#{File::SEPARATOR}.."))
96
+ end
97
+ end
98
+
99
+
100
+ def config
101
+ if @config.nil?
102
+ @config = GitConfig.new(self)
103
+ end
104
+ @config
68
105
  end
69
106
 
70
107
 
71
- def master_branch
72
- @master_branch ||= config('gitProcess.integrationBranch') || 'master'
108
+ def remote
109
+ if @remote.nil?
110
+ @remote = GitProc::GitRemote.new(config)
111
+ end
112
+ @remote
73
113
  end
74
114
 
75
115
 
76
116
  # @return [Boolean] does this have a remote defined?
77
117
  def has_a_remote?
78
- if @has_remote == nil
79
- @has_remote = (command(:remote) != '')
80
- end
81
- @has_remote
118
+ remote.exists?
82
119
  end
83
120
 
84
121
 
@@ -89,7 +126,7 @@ module GitProc
89
126
 
90
127
 
91
128
  def commit(msg = nil)
92
- logger.info "Committing changes"
129
+ logger.info 'Committing changes'
93
130
  command(:commit, msg.nil? ? nil : ['-m', msg])
94
131
  end
95
132
 
@@ -113,9 +150,60 @@ module GitProc
113
150
  end
114
151
 
115
152
 
116
- def fetch(name = remote_name)
117
- logger.info "Fetching the latest changes from the server"
118
- command(:fetch, ['-p', name])
153
+ def fetch(name = remote.name)
154
+ logger.info 'Fetching the latest changes from the server'
155
+ output = self.command(:fetch, ['-p', name])
156
+
157
+ log_fetch_changes(fetch_changes(output))
158
+
159
+ output
160
+ end
161
+
162
+
163
+ # @param [Hash] changes a hash of the changes that were made
164
+ #
165
+ # @return [void]
166
+ def log_fetch_changes(changes)
167
+ changes.each do |key, v|
168
+ unless v.empty?
169
+ logger.info { " #{key.to_s.sub(/_/, ' ')}: #{v.join(', ')}" }
170
+ end
171
+ end
172
+ end
173
+
174
+
175
+ # @return [Hash]
176
+ def fetch_changes(output)
177
+ changed = output.split("\n")
178
+
179
+ changes = {:new_branch => [], :new_tag => [], :force_updated => [], :deleted => [], :updated => []}
180
+
181
+ line = changed.shift
182
+
183
+ until line.nil? do
184
+ case line
185
+ when /^\s\s\s/
186
+ m = /^\s\s\s(\S+)\s+(\S+)\s/.match(line)
187
+ changes[:updated] << "#{m[2]} (#{m[1]})"
188
+ when /^\s\*\s\[new branch\]/
189
+ m = /^\s\*\s\[new branch\]\s+(\S+)\s/.match(line)
190
+ changes[:new_branch] << m[1]
191
+ when /^\s\*\s\[new tag\]/
192
+ m = /^\s\*\s\[new tag\]\s+(\S+)\s/.match(line)
193
+ changes[:new_tag] << m[1]
194
+ when /^\sx\s/
195
+ m = /^\sx\s\[deleted\]\s+\(none\)\s+->\s+[^\/]+\/(\S+)/.match(line)
196
+ changes[:deleted] << m[1]
197
+ when /^\s\+\s/
198
+ m = /^\s\+\s(\S+)\s+(\S+)\s/.match(line)
199
+ changes[:force_updated] << "#{m[2]} (#{m[1]})"
200
+ else
201
+ # ignore the line
202
+ end
203
+ line = changed.shift
204
+ end
205
+
206
+ changes
119
207
  end
120
208
 
121
209
 
@@ -134,38 +222,27 @@ module GitProc
134
222
  # @option opts [Boolean] :all list all branches, local and remote
135
223
  # @option opts [Boolean] :no_color force not using any ANSI color codes
136
224
  # @option opts [String] :rename the new name for the branch
225
+ # @option opts [String] :upstream the new branch to track
137
226
  # @option opts [String] :base_branch the branch to base the new branch off of;
138
227
  # defaults to 'master'
139
228
  #
140
229
  # @return [String] the output of running the git command
141
230
  def branch(branch_name, opts = {})
142
- args = []
143
231
  if opts[:delete]
144
- logger.info { "Deleting local branch '#{branch_name}'." } unless branch_name == '_parking_'
145
-
146
- args << (opts[:force] ? '-D' : '-d')
147
- args << branch_name
232
+ delete_branch(branch_name, opts[:force])
148
233
  elsif opts[:rename]
149
- logger.info { "Renaming branch '#{branch_name}' to '#{opts[:rename]}'." }
150
-
151
- args << '-m' << branch_name << opts[:rename]
234
+ rename_branch(branch_name, opts[:rename])
235
+ elsif opts[:upstream]
236
+ set_upstream_branch(branch_name, opts[:upstream])
152
237
  elsif branch_name
153
238
  if opts[:force]
154
- raise ArgumentError.new("Need :base_branch when using :force for a branch.") unless opts[:base_branch]
155
- logger.info { "Changing branch '#{branch_name}' to point to '#{opts[:base_branch]}'." }
156
-
157
- args << '-f' << branch_name << opts[:base_branch]
239
+ change_branch(branch_name, opts[:base_branch])
158
240
  else
159
- logger.info { "Creating new branch '#{branch_name}' based on '#{opts[:base_branch]}'." }
160
-
161
- args << branch_name
162
- args << (opts[:base_branch] ? opts[:base_branch] : 'master')
241
+ create_branch(branch_name, opts[:base_branch])
163
242
  end
164
243
  else
165
- args << '-a' if opts[:all]
166
- args << '--no-color' if opts[:no_color]
244
+ list_branches(opts[:all], opts[:no_color])
167
245
  end
168
- command(:branch, args)
169
246
  end
170
247
 
171
248
 
@@ -195,10 +272,10 @@ module GitProc
195
272
  elsif !(opts[:delete].is_a? TrueClass)
196
273
  rb = opts[:delete]
197
274
  else
198
- raise ArgumentError.new("Need a branch name to delete.")
275
+ raise ArgumentError.new('Need a branch name to delete.')
199
276
  end
200
277
 
201
- int_branch = master_branch
278
+ int_branch = config.master_branch
202
279
  if rb == int_branch
203
280
  raise GitProc::GitProcessError.new("Can not delete the integration branch '#{int_branch}'")
204
281
  end
@@ -278,69 +355,6 @@ module GitProc
278
355
  end
279
356
 
280
357
 
281
- def config_hash
282
- @config_hash ||= {}
283
- end
284
-
285
-
286
- private :config_hash
287
-
288
-
289
- def config(key = nil, value = nil, global = false)
290
- if key and value
291
- args = global ? %w(--global) : []
292
- args << key << value
293
- command(:config, args)
294
- config_hash[key] = value unless config_hash.empty?
295
- value
296
- elsif key
297
- value = config_hash[key]
298
- unless value
299
- value = command(:config, ['--get', key])
300
- value = nil if value.empty?
301
- config_hash[key] = value unless config_hash.empty?
302
- end
303
- value
304
- else
305
- if config_hash.empty?
306
- str = command(:config, '--list')
307
- lines = str.split("\n")
308
- lines.each do |line|
309
- (key, *values) = line.split('=')
310
- config_hash[key] = values.join('=')
311
- end
312
- end
313
- config_hash
314
- end
315
- end
316
-
317
-
318
- def repo_name
319
- unless @repo_name
320
- origin_url = config("remote.#{remote_name}.url")
321
- raise GitProc::Process::GitProcessError.new("There is no #{remote_name} url set up.") if origin_url.empty?
322
- @repo_name = origin_url.sub(/^.*:(.*?)(.git)?$/, '\1')
323
- end
324
- @repo_name
325
- end
326
-
327
-
328
- def remote_name
329
- unless @remote_name
330
- @remote_name = config('gitProcess.remoteName')
331
- if @remote_name.nil? or @remote_name.empty?
332
- remote_str = command(:remote)
333
- unless remote_str == nil or remote_str.empty?
334
- @remote_name = remote_str.split(/\n/)[0]
335
- raise "!@remote_name.is_a? String" unless @remote_name.is_a? String
336
- end
337
- end
338
- logger.debug { "Using remote name of '#@remote_name'" }
339
- end
340
- @remote_name
341
- end
342
-
343
-
344
358
  #
345
359
  # Returns the status of the git repository.
346
360
  #
@@ -367,28 +381,6 @@ module GitProc
367
381
  end
368
382
 
369
383
 
370
- def rerere_enabled?
371
- re = config('rerere.enabled')
372
- re && re.to_boolean
373
- end
374
-
375
-
376
- def rerere_enabled(re, global = true)
377
- config('rerere.enabled', re, global)
378
- end
379
-
380
-
381
- def rerere_autoupdate?
382
- re = config('rerere.autoupdate')
383
- re && re.to_boolean
384
- end
385
-
386
-
387
- def rerere_autoupdate(re, global = true)
388
- config('rerere.autoupdate', re, global)
389
- end
390
-
391
-
392
384
  def rev_list(start_revision, end_revision, opts ={})
393
385
  args = []
394
386
  args << "-#{opts[:num_revs]}" if opts[:num_revs]
@@ -406,40 +398,52 @@ module GitProc
406
398
  alias sha rev_parse
407
399
 
408
400
 
409
- def add_remote(remote_name, url)
410
- command(:remote, ['add', remote_name, url])
401
+ # @return [String]
402
+ def command(cmd, opts = [], chdir = true, redirect = '', &block)
403
+ ENV['GIT_INDEX_FILE'] = File.join(workdir, '.git', 'index')
404
+ ENV['GIT_DIR'] = File.join(workdir, '.git')
405
+ ENV['GIT_WORK_TREE'] = workdir
406
+ path = workdir
407
+
408
+ git_cmd = create_git_command(cmd, opts, redirect)
409
+
410
+ out = command_git_cmd(path, git_cmd, chdir, block)
411
+
412
+ if logger
413
+ logger.debug(git_cmd)
414
+ logger.debug(out)
415
+ end
416
+
417
+ handle_exitstatus($?, git_cmd, out)
411
418
  end
412
419
 
413
420
 
414
421
  private
415
422
 
416
423
 
417
- def command(cmd, opts = [], chdir = true, redirect = '', &block)
418
- ENV['GIT_DIR'] = File.join(workdir, '.git')
419
- ENV['GIT_INDEX_FILE'] = File.join(workdir, '.git', 'index')
420
- ENV['GIT_WORK_TREE'] = workdir
421
- path = workdir
422
-
424
+ def create_git_command(cmd, opts, redirect)
423
425
  opts = [opts].flatten.map { |s| escape(s) }.join(' ')
424
- git_cmd = "git #{cmd} #{opts} #{redirect} 2>&1"
426
+ "git #{cmd} #{opts} #{redirect} 2>&1"
427
+ end
425
428
 
429
+
430
+ def command_git_cmd(path, git_cmd, chdir, block)
426
431
  out = nil
427
432
  if chdir and (Dir.getwd != path)
428
433
  Dir.chdir(path) { out = run_command(git_cmd, &block) }
429
434
  else
430
435
  out = run_command(git_cmd, &block)
431
436
  end
437
+ out
438
+ end
432
439
 
433
- if logger
434
- logger.debug(git_cmd)
435
- logger.debug(out)
436
- end
437
440
 
438
- if $?.exitstatus > 0
439
- if $?.exitstatus == 1 && out == ''
440
- return ''
441
+ # @return [String]
442
+ def handle_exitstatus(proc_status, git_cmd, out)
443
+ if proc_status.exitstatus > 0
444
+ unless proc_status.exitstatus == 1 && out == ''
445
+ raise GitProc::GitExecuteError.new(git_cmd + ':' + out.to_s)
441
446
  end
442
- raise GitProc::GitExecuteError.new(git_cmd + ':' + out.to_s)
443
447
  end
444
448
  out
445
449
  end
@@ -459,6 +463,50 @@ module GitProc
459
463
  %Q{"#{escaped}"}
460
464
  end
461
465
 
466
+
467
+ def change_branch(branch_name, base_branch)
468
+ raise ArgumentError.new('Need :base_branch when using :force for a branch.') unless base_branch
469
+ logger.info { "Changing branch '#{branch_name}' to point to '#{base_branch}'." }
470
+
471
+ command(:branch, ['-f', branch_name, base_branch])
472
+ end
473
+
474
+
475
+ def create_branch(branch_name, base_branch)
476
+ logger.info { "Creating new branch '#{branch_name}' based on '#{base_branch}'." }
477
+
478
+ command(:branch, [branch_name, (base_branch || 'master')])
479
+ end
480
+
481
+
482
+ def list_branches(all_branches, no_color)
483
+ args = []
484
+ args << '-a' if all_branches
485
+ args << '--no-color' if no_color
486
+ command(:branch, args)
487
+ end
488
+
489
+
490
+ def delete_branch(branch_name, force)
491
+ logger.info { "Deleting local branch '#{branch_name}'." } unless branch_name == '_parking_'
492
+
493
+ command(:branch, [force ? '-D' : '-d', branch_name])
494
+ end
495
+
496
+
497
+ def rename_branch(branch_name, new_name)
498
+ logger.info { "Renaming branch '#{branch_name}' to '#{new_name}'." }
499
+
500
+ command(:branch, ['-m', branch_name, new_name])
501
+ end
502
+
503
+
504
+ def set_upstream_branch(branch_name, upstream)
505
+ logger.info { "Setting upstream/tracking for branch '#{branch_name}' to '#{upstream}'." }
506
+
507
+ command(:branch, ['--set-upstream-to', upstream, branch_name])
508
+ end
509
+
462
510
  end
463
511
 
464
512
  end