git-process 0.9.5 → 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- git-process (0.9.5)
4
+ git-process (0.9.6)
5
5
  highline (~> 1.6.12)
6
6
  json (~> 1.7.3)
7
7
  launchy (~> 2.1.0)
data/README.md CHANGED
@@ -1,29 +1,25 @@
1
1
  [![Build Status](https://secure.travis-ci.org/jdigger/git-process.png)](http://travis-ci.org/jdigger/git-process)
2
2
 
3
- # Purpose and Motivation #
3
+ # Purpose #
4
+
5
+ This provides an easy way to work with a sane git workflow process that encourages using highly-focussed branches to encourage collaboration, enable fearless changes, and improve team communication.
6
+
7
+ See the F.A.Q. for a much more complete explanation for the thoughts and assumptions that motivates this project.
4
8
 
5
- This provides an easy way to work with a sane git workflow process.
6
- Short-lived feature branches can work quite well, but the formal git-flow process can be rather heavy in cost.
7
9
 
8
10
  # Installation #
9
11
 
10
12
  $ sudo gem install git-process
11
13
 
12
- ## Configurables ##
13
- See notes for more details
14
-
15
- * OAuth2 Token
16
- * The name of the integration branch (defaults to `origin/master`, but can be set to `develop` or other)
17
14
 
18
- ---
19
15
  # Overview #
20
16
 
21
17
  ## Anticipated Use Cases ##
22
18
 
23
- 1. User Creates new local branch
24
- 1. User pushes local branch to remote (as feature branch) by rebasing integration branch, then pushing branch to remote
25
- 1. User closes local branch by rebasing integration branch first, then pushing local to integration
26
- 1. User initiates GitHub "pull request"
19
+ 1. User creates new local branch for focussed work.
20
+ 1. User pushes local branch to remote (as feature branch) by merging/rebasing with the integration branch, then pushing to the branch to remote.
21
+ 1. User closes local branch by rebasing integration branch first, then pushing local to integration.
22
+ 1. User initiates GitHub "pull request" to ease collaboration.
27
23
 
28
24
  ## Command List ##
29
25
 
@@ -34,6 +30,7 @@ See notes for more details
34
30
 
35
31
  **All commands are well documented within themselves: Use the "-h" switch to see the full documentation.** (e.g., "`git sync -h`")
36
32
 
33
+
37
34
  # Workflow #
38
35
 
39
36
  _The following assumes that the integration branch is "origin/master"._
@@ -53,6 +50,17 @@ _The following assumes that the integration branch is "origin/master"._
53
50
  5. If you still need to make changes, do so and use "`git sync`" to keep your branch on the
54
51
  server for that feature updated with your work until all issues have been resolved.
55
52
 
53
+ ```
54
+ $ git new-fb my-feature # 1
55
+ # do work # 2
56
+ $ git commit # 3
57
+ $ git sync # 4
58
+ # repeat #2-#4 as necessary # 5
59
+ $ git pull-request # 6
60
+ # repeat #2-#4 as necessary # 7
61
+ $ git to-master # 8
62
+ ```
63
+
56
64
  ## Working Alone or When Pairing ##
57
65
 
58
66
  1. When starting work on a new feature, use "`git new-fb feature-name`".
@@ -64,31 +72,34 @@ _The following assumes that the integration branch is "origin/master"._
64
72
  3. When you are ready to merge your work into the mainline, "`git to-master`".
65
73
  * This will merge and push your changes into "`origin/master`"
66
74
 
75
+ ```
76
+ $ git new-fb my-feature # 1
77
+ # do work # 2
78
+ $ git commit # 3
79
+ $ git sync # 4
80
+ # repeat #2-#4 as necessary # 5
81
+ $ git to-master # 6
82
+ ```
83
+
84
+
85
+ # Assumptions #
86
+
87
+ * You should **_never_** do any work directly on "`master`" (or whatever you define the mainline branch as): everything is done on a feature branch. This is a much safer and more flexible practice than doing everything on the same branch, but may seem odd to people used to old VCSs. In addition to being a much better way of working in general (see the F.A.Q. for more information), it is also a requirement to take advantage of Pull Request functionality.
88
+ * When working on a branch, you should be integrating with "`master`" as often as possible.
89
+ * "`git sync`" makes it extremely easy for you to get any changes that are made in "`master`" into your branch so you can react to it immediately. "`git to-master`" then makes it easy to cleanly integrate the changes you have made, along with encouraging code-review/sign-off, and doing various house-keeping duties.
90
+ * The process that you use should be essentially the same, regardless of whether you are working alone, or on a large distributed team.
91
+ * The exception here is "`git pull-request`" since you do not use pull requests when working solo or when pair-programming.
67
92
 
68
93
  # Notes #
69
94
 
70
- * It's assumed that you **_never_** do any work directly on "`master`": everything is done on a
71
- feature branch. This is a much safer and more flexible practice, but may seem odd to
72
- people used to old VCSs. In addition to being a much better way of working in general,
73
- it is also a requirement to take advantage of Pull Request functionality.
74
- * After publishing changes to the main integration branch (i.e., "`git to-master`") the
75
- old feature branch is removed as part of cleanup. Git is then "parked" on a "`_parking_`"
76
- branch until a new feature branch is created. Work is not expected to be done on this
77
- branch, but any that is done is brought over to a newly created feature branch (i.e.,
78
- "`git new-fb`").
79
- * If there is a problem (such as a merge conflict), this will try to resolve such errors
80
- for you as much as it can do safely. When it can't do so in an automated way, it will try
81
- to tell you the process for doing so manually.
82
- * The first time you use a GitHub feature (e.g., "`git pull-request`"), this will ask for your
83
- username and password. It does not store them, but instead uses them to get an OAuth2 token,
84
- which is stored in "`git config gitProcess.github.authToken`".
85
- * If you want to use a different integration branch other than "`master`", set the
86
- "`gitProcess.integrationBranch`" configuration value. (e.g.,
87
- "`git config gitProcess.integrationBranch my-integ-branch`")
95
+ * After publishing changes to the main integration branch (i.e., "`git to-master`") the old feature branch is removed as part of cleanup. Git is then "parked" on a "`_parking_`" branch until a new feature branch is created. Work is not expected to be done on this branch, but any that is done is brought over to a newly created feature branch (i.e., "`git new-fb`").
96
+ * If there is a problem (such as a merge conflict), this will try to resolve such errors for you as much as it can do safely. When it can't do so in an automated way, it will try to tell you the process for doing so manually.
97
+ * The first time you use a GitHub feature (e.g., "`git pull-request`"), this will ask for your username and password. It does not store them, but instead uses them to get an OAuth2 token, which is stored in "`git config gitProcess.github.authToken`".
98
+ * If you want to use a different integration branch other than "`master`", set the "`gitProcess.integrationBranch`" configuration value. (e.g., "`git config gitProcess.integrationBranch my-integ-branch`")
88
99
  * This tries to respond "intelligently" to the use of 'rerere'.
89
100
 
90
101
 
91
- # FAQ #
102
+ # F.A.Q. #
92
103
 
93
104
  ## Q: How is this different from git-flow or GitHub flow? ##
94
105
 
@@ -101,7 +112,7 @@ _The following assumes that the integration branch is "origin/master"._
101
112
 
102
113
  Branches are extremely powerful tools that allow for clean organization/modularization of development.
103
114
 
104
- * Branches make it easy to sandbox changes while they are in a state of flux, while at the same time be very fearless about making potentially breaking changes.
115
+ * Branches make it easy to sandbox changes while they are in a state of flux, while at the same time allowing you to be very fearless about making potentially breaking changes.
105
116
  * For example, I commit "green to green": Doing [TDD](http://en.wikipedia.org/wiki/Test-driven_development), I commit every time I have a newly passing test case. So, assuming I'm in a regular development flow, I'm committing my changes every five minutes. Tiny commits, but lots of them. What that means is that if I make a "less than wise choice" at some point, it's trivial to rewind to before I'd made the mistake, potentially keep the throw-away code in another branch while I do my cleanup, and generally use the full power of a revision control system to make my life safer and easier. The branch(es) are pretty chaotic, but that's not a problem because before integrating with the mainline, I take a moment to cleanup: Squash related commits together, write clearer commit messages (since now I know what "the answer" is), and generally move from my drafts to a more finished result. (See below on objections related to "lying with rebase.") That may just be me, though, because I'm very paranoid when it comes to computers. I tend to automatically hit Cmd/Ctl-S every time I type a period when I'm writing, or when I close a block when I'm programming. I have a minimum of three copies/backups around the world of all my important documents. And I "`git sync`" frequently to make sure my machine isn't the only place where all my hard work is being stored. Have I mentioned I don't trust computers?
106
117
 
107
118
  * Branches allow for focused collaboration. Because a branch is about exactly one thing, it means that a team can collaborate around a feature/bug (especially when used in conjunction with a "pull request"), and keep such changes sandboxed until such time that they are ready to bring a larger audience into the mix.
@@ -114,7 +125,7 @@ Making it "easier to do things right than wrong" (i.e., using branches and keepi
114
125
 
115
126
  ## Q: Why so much emphasis on rebasing? Isn't rebasing a dangerous lie? ##
116
127
 
117
- Like any powerful tool, "`git rebase`" is "dangerous" if used incorrectly, just like "`rm -rf`". You simply need to know when and how to use it safely. And in the world of version control systems, "rebasing" is easily one of the most _**useful**_ tools to come around since the "`commit`" command.
128
+ Like any powerful tool, "`git rebase`" is "dangerous" if used incorrectly, just like "`rm`"/"`del`". You simply need to know when and how to use it safely. And in the world of version control systems, "rebasing" is easily one of the most _**useful**_ tools to come around since the "`commit`" command.
118
129
 
119
130
  [A famous article](http://paul.stadig.name/2010/12/thou-shalt-not-lie-git-rebase-ammend.html) that people have been parroting in various forms for a while makes the case that rebasing (and its various forms, such as squashing, amending commits, etc.) is a "lie." As with so many things, context is everything.
120
131
 
@@ -124,8 +135,14 @@ Rebasing "your" code is an extremely useful way of communicating clearly. In the
124
135
 
125
136
  If you have ever seen an "active" project that uses a process like "git-flow" that encourages a lot of branching and merging, you've seen how hard it can be to follow a particular line of development. Branch lines are flying around everywhere, and half the commits are pretty much pure noise. (e.g., "Merge branch 'develop' of ... into develop".) It's also hard to follow the order in which commits actually impacted the mainline. In many ways, in practice merges turn into "a truth effectively being a lie (because it's buried in the noise)" versus rebases that are "a lie (changed from it's 'original' form) to tell an effective truth (clean and very clear about its impact)."
126
137
 
127
- I am trying to promote clear communication about current reality over micro-management over no-longer-relevant history. Thus the judicious use of rebase.
138
+ This project is trying to promote clear communication about reality as it applies to the code, over micro-management over no-longer-relevant history. Thus rational for the judicious use of rebase.
139
+
128
140
 
141
+ ## Configurables ##
142
+ See notes for more details
143
+
144
+ * GitHub authentication token
145
+ * The name of the integration branch (defaults to `origin/master`, but can be set to `develop` or other)
129
146
 
130
147
  # Contributing #
131
148
 
data/bin/git-sync CHANGED
@@ -1,8 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ # require "rubygems"
4
+ # require "bundler/setup"
5
+ # $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '../lib')
6
+
3
7
  require 'git-process/git_process_options'
4
8
  require 'git-process/sync'
5
9
 
10
+
6
11
  class SyncOptions
7
12
  include GitProc::GitProcessOptions
8
13
 
@@ -0,0 +1,106 @@
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.require 'shellwords'
12
+
13
+ require 'git-process/git_lib'
14
+ require 'highline/import'
15
+
16
+
17
+ module GitProc
18
+
19
+ #
20
+ # Provides support for prompting the user when the dir/index is dirty.
21
+ #
22
+ # = Assumes =
23
+ # log_level
24
+ # workdir
25
+ #
26
+ module ChangeFileHelper
27
+ include GitLib
28
+
29
+
30
+ def offer_to_help_uncommitted_changes
31
+ stat = status
32
+
33
+ if stat.unmerged.empty?
34
+ handle_unknown_files(stat)
35
+ handle_changed_files(status) # refresh status in case it changed earlier
36
+ else
37
+ logger.info { "Can not offer to auto-add unmerged files: #{stat.unmerged.inspect}" }
38
+ raise UncommittedChangesError.new
39
+ end
40
+ end
41
+
42
+
43
+ def handle_unknown_files(stat)
44
+ if not stat.unknown.empty?
45
+ resp = ask_how_to_handle_unknown_files(stat)
46
+ if resp == :add
47
+ add(stat.unknown)
48
+ end
49
+ end
50
+ end
51
+
52
+
53
+ def handle_changed_files(stat)
54
+ if not stat.modified.empty? or not stat.added.empty? or not stat.deleted.empty?
55
+ resp = ask_how_to_handle_changed_files(stat)
56
+ if resp == :commit
57
+ add((stat.added + stat.modified - stat.deleted).sort.uniq)
58
+ remove(stat.deleted)
59
+ commit(nil)
60
+ else
61
+ stash_save
62
+ @stash_pushed = true
63
+ end
64
+ end
65
+ end
66
+
67
+
68
+ def ask_how_to_handle_unknown_files(stat)
69
+ show_changes(:unknown, stat)
70
+ resp = ask("Would you like to (a)dd them or (i)gnore them? ") do |q|
71
+ q.responses[:not_valid] = "Please respond with either (a)dd or (i)gnore. (Ctl-C to abort.) "
72
+ q.case = :down
73
+ q.validate = /a|i/i
74
+ end
75
+
76
+ resp == 'a' ? :add : :ignore
77
+ end
78
+
79
+
80
+ def show_changes(type, stat)
81
+ files = stat.send(type)
82
+
83
+ if type != :deleted
84
+ files -= stat.deleted
85
+ end
86
+
87
+ if not files.empty?
88
+ say("You have <%= color('#{type}', [:underline]) %> files:\n <%= color('#{files.join("\n ")}', [:bold]) %>")
89
+ end
90
+ end
91
+
92
+
93
+ def ask_how_to_handle_changed_files(stat)
94
+ [:added, :modified, :deleted].each { |t| show_changes(t, stat) }
95
+ resp = ask("Would you like to (c)ommit them or (s)tash them? ") do |q|
96
+ q.responses[:not_valid] = "Please respond with either (c)ommit or (s)tash. (Ctl-C to abort.) "
97
+ q.case = :down
98
+ q.validate = /c|s/i
99
+ end
100
+
101
+ resp == 'c' ? :commit : :stash
102
+ end
103
+
104
+ end
105
+
106
+ end
@@ -70,7 +70,7 @@ module GitProc
70
70
  end
71
71
 
72
72
 
73
- def delete(force = false)
73
+ def delete!(force = false)
74
74
  if local?
75
75
  @lib.branch(@name, :force => force, :delete => true)
76
76
  else
@@ -61,7 +61,7 @@ module GitProc
61
61
  def [](branch_name)
62
62
  branch_name = current.name if branch_name == 'HEAD'
63
63
  br = @items.find {|b| b.name == branch_name}
64
- if br.nil? and branch_name !~ /origin\//
64
+ if br.nil? and branch_name !~ /origin\// and branch_name != '_parking_'
65
65
  @lib.logger.warn {"Could not find '#{branch_name}' in #{@items.map{|i|i.name}.join(',')}"}
66
66
  end
67
67
  br
@@ -28,9 +28,16 @@ class String
28
28
  end
29
29
 
30
30
 
31
+ class NilClass
32
+ def to_boolean
33
+ false
34
+ end
35
+ end
36
+
37
+
31
38
  module GitProc
32
39
 
33
- class GitExecuteError < StandardError
40
+ class GitExecuteError < GitProcessError
34
41
  end
35
42
 
36
43
 
@@ -44,7 +51,7 @@ module GitProc
44
51
  module GitLib
45
52
 
46
53
  def logger
47
- unless @logger
54
+ if @logger.nil?
48
55
  @logger = Logger.new(STDOUT)
49
56
  @logger.level = log_level || Logger::WARN
50
57
  @logger.datetime_format = "%Y-%m-%d %H:%M:%S"
@@ -77,26 +84,31 @@ module GitProc
77
84
 
78
85
 
79
86
  def add(file)
87
+ logger.info { "Adding #{[*file].join(', ')}" }
80
88
  command(:add, ['--', file])
81
89
  end
82
90
 
83
91
 
84
- def commit(msg)
85
- command(:commit, ['-m', msg])
92
+ def commit(msg = nil)
93
+ logger.info "Committing changes"
94
+ command(:commit, msg.nil? ? nil : ['-m', msg])
86
95
  end
87
96
 
88
97
 
89
98
  def rebase(base)
99
+ logger.info { "Rebasing #{branches.current.name} against #{base}" }
90
100
  command('rebase', base)
91
101
  end
92
102
 
93
103
 
94
104
  def merge(base)
105
+ logger.info { "Merging #{branches.current.name} with #{base}" }
95
106
  command(:merge, [base])
96
107
  end
97
108
 
98
109
 
99
110
  def fetch(name = remote_name)
111
+ logger.info "Fetching the latest changes from the server"
100
112
  command(:fetch, ['-p', name])
101
113
  end
102
114
 
@@ -211,6 +223,21 @@ module GitProc
211
223
  end
212
224
 
213
225
 
226
+ def stash_save
227
+ command(:stash, ['save'])
228
+ end
229
+
230
+
231
+ def stash_pop
232
+ command(:stash, ['pop'])
233
+ end
234
+
235
+
236
+ def show(refspec)
237
+ command(:show, refspec)
238
+ end
239
+
240
+
214
241
  def checkout(branch_name, opts = {}, &block)
215
242
  args = []
216
243
  args << '--no-track' if opts[:no_track]
@@ -237,10 +264,10 @@ module GitProc
237
264
  end
238
265
 
239
266
 
240
- def remove(file, opts = {})
267
+ def remove(files, opts = {})
241
268
  args = []
242
269
  args << '-f' if opts[:force]
243
- args << file
270
+ args << [*files]
244
271
  command(:rm, args)
245
272
  end
246
273
 
@@ -250,6 +277,9 @@ module GitProc
250
277
  end
251
278
 
252
279
 
280
+ private :config_hash
281
+
282
+
253
283
  def config(key = nil, value = nil, global = false)
254
284
  if key and value
255
285
  args = global ? ['--global'] : []
@@ -13,6 +13,7 @@
13
13
  require 'git-process/git_lib'
14
14
  require 'git-process/git_rebase_error'
15
15
  require 'git-process/git_merge_error'
16
+ require 'highline/import'
16
17
 
17
18
 
18
19
  module GitProc
@@ -23,25 +24,20 @@ module GitProc
23
24
  def initialize(dir, opts = {})
24
25
  @log_level = Process.log_level(opts)
25
26
 
26
- if dir
27
- @workdir = find_workdir(dir)
28
- if @workdir.nil?
29
- @workdir = dir
30
- logger.info { "Initializing new repository at #{workdir}" }
31
- command(:init)
32
- else
33
- logger.debug { "Opening existing repository at #{workdir}" }
34
- end
35
- end
27
+ set_workdir(dir)
36
28
  end
37
29
 
38
30
 
39
31
  def run
40
32
  begin
33
+ verify_preconditions
34
+
41
35
  runner
42
36
  rescue GitProc::GitProcessError => exp
43
37
  puts exp.message
44
38
  exit(-1)
39
+ ensure
40
+ cleanup
45
41
  end
46
42
  end
47
43
 
@@ -51,6 +47,22 @@ module GitProc
51
47
  end
52
48
 
53
49
 
50
+ def set_workdir(dir)
51
+ if !dir.nil?
52
+ @workdir = find_workdir(dir)
53
+ if @workdir.nil?
54
+ @workdir = dir
55
+ logger.info { "Initializing new repository at #{workdir}" }
56
+ command(:init)
57
+ else
58
+ logger.debug { "Opening existing repository at #{workdir}" }
59
+ end
60
+ else
61
+ logger.debug "Process dir is nil"
62
+ end
63
+ end
64
+
65
+
54
66
  def workdir
55
67
  @workdir
56
68
  end
@@ -76,8 +88,39 @@ module GitProc
76
88
  end
77
89
 
78
90
 
91
+ def verify_preconditions
92
+ if should_remove_master
93
+ if ask_about_removing_master
94
+ branches[master_branch].delete!
95
+ end
96
+ end
97
+ end
98
+
99
+
100
+ def cleanup
101
+ # extension point
102
+ end
103
+
104
+
105
+ def should_remove_master
106
+ my_branches = branches()
107
+ has_a_remote? and
108
+ my_branches.include?(master_branch) and
109
+ my_branches.current.name != master_branch and
110
+ !keep_local_integration_branch? and
111
+ my_branches[integration_branch].contains_all_of(master_branch)
112
+ end
113
+
114
+
115
+ def keep_local_integration_branch?
116
+ keep_local_integration_branch_config_value.to_boolean
117
+ end
118
+
119
+
79
120
  def Process.log_level(opts)
80
- if opts[:quiet]
121
+ if opts[:log_level]
122
+ opts[:log_level]
123
+ elsif opts[:quiet]
81
124
  Logger::ERROR
82
125
  elsif opts[:verbose]
83
126
  Logger::DEBUG
@@ -96,6 +139,28 @@ module GitProc
96
139
  private
97
140
 
98
141
 
142
+ def keep_local_integration_branch_config_value
143
+ config('gitProcess.keepLocalIntegrationBranch')
144
+ end
145
+
146
+
147
+ def ask_about_removing_master
148
+ resp = ask("You should remove your obsolete <%= color('local', [:bold]) %> branch, '#{master_branch}'. Should I remove it for you? (Yn) ") do |q|
149
+ q.responses[:not_valid] = 'Please respond with either (y)es or (n)o. Defaults to (y)es.'
150
+ q.case = :down
151
+ q.default = 'Y'
152
+ q.validate = /y|n/i
153
+ end
154
+
155
+ if resp == 'n'
156
+ say("(You can turn off this message using \"git config gitProcess.keepLocalIntegrationBranch true\").")
157
+ false
158
+ else
159
+ true
160
+ end
161
+ end
162
+
163
+
99
164
  def find_workdir(dir)
100
165
  if dir == File::SEPARATOR
101
166
  nil
@@ -41,26 +41,41 @@ module GitProc
41
41
  stat = s[0..1]
42
42
  file = s[3..-1]
43
43
  #puts "stat #{stat} - #{file}"
44
+ f = unquote(file)
44
45
  case stat
45
46
  when 'U ', ' U'
46
- unmerged << file
47
+ unmerged << f
47
48
  when 'UU'
48
- unmerged << file
49
- modified << file
50
- when 'M ', ' M'
51
- modified << file
49
+ unmerged << f
50
+ modified << f
51
+ when 'M ', ' M', 'MM'
52
+ modified << f
53
+ when 'MD'
54
+ modified << f
55
+ deleted << f
52
56
  when 'D ', ' D'
53
- deleted << file
57
+ deleted << f
54
58
  when 'DU', 'UD'
55
- deleted << file
56
- unmerged << file
59
+ deleted << f
60
+ unmerged << f
57
61
  when 'A ', ' A'
58
- added << file
62
+ added << f
63
+ when 'AD'
64
+ added << f
65
+ deleted << f
59
66
  when 'AA'
60
- added << file
61
- unmerged << file
67
+ added << f
68
+ unmerged << f
62
69
  when '??'
63
- unknown << file
70
+ unknown << f
71
+ when 'R '
72
+ old_file, new_file = file.split(' -> ')
73
+ deleted << unquote(old_file)
74
+ added << unquote(new_file)
75
+ when 'C '
76
+ old_file, new_file = file.split(' -> ')
77
+ added << unquote(old_file)
78
+ added << unquote(new_file)
64
79
  else
65
80
  raise "Do not know what to do with status #{stat} - #{file}"
66
81
  end
@@ -74,6 +89,11 @@ module GitProc
74
89
  end
75
90
 
76
91
 
92
+ def unquote(file)
93
+ file.match(/^"?(.*?)"?$/)[1]
94
+ end
95
+
96
+
77
97
  # @return [Boolean] are there any changes in the index or working directory?
78
98
  def clean?
79
99
  @unmerged.empty? and @modified.empty? and @deleted.empty? and @added.empty? and @unknown.empty?
@@ -28,7 +28,7 @@ module GitProc
28
28
 
29
29
  if on_parking
30
30
  new_branch = checkout(@branch_name, :new_branch => '_parking_')
31
- mybranches.parking.delete
31
+ mybranches.parking.delete!
32
32
  new_branch
33
33
  else
34
34
  checkout(@branch_name, :new_branch => integration_branch)
@@ -14,6 +14,7 @@ require 'git-process/git_process'
14
14
  require 'git-process/git_rebase_error'
15
15
  require 'git-process/git_process_error'
16
16
  require 'git-process/parked_changes_error'
17
+ require 'git-process/uncommitted_changes_error'
17
18
  require 'git-process/github_pull_request'
18
19
 
19
20
 
@@ -21,18 +22,23 @@ module GitProc
21
22
 
22
23
  class RebaseToMaster < Process
23
24
 
24
- def runner
25
+ def verify_preconditions
26
+ super
27
+
25
28
  raise UncommittedChangesError.new unless status.clean?
26
29
  raise ParkedChangesError.new(self) if is_parked?
30
+ end
27
31
 
32
+
33
+ def runner
28
34
  if has_a_remote?
29
35
  fetch(server_name)
30
- proc_rebase(remote_master_branch)
36
+ proc_rebase(integration_branch)
31
37
  push(server_name, branches.current, master_branch)
32
38
  close_pull_request
33
39
  remove_feature_branch
34
40
  else
35
- proc_rebase(master_branch)
41
+ proc_rebase(integration_branch)
36
42
  end
37
43
  end
38
44
 
@@ -42,6 +48,7 @@ module GitProc
42
48
 
43
49
  remote_master = mybranches[remote_master_branch]
44
50
  current_branch = mybranches.current
51
+ logger.debug { "Removing feature branch (#{current_branch})" }
45
52
 
46
53
  unless remote_master.contains_all_of(current_branch.name)
47
54
  raise GitProcessError.new("Branch '#{current_branch.name}' has not been merged into '#{remote_master_branch}'")
@@ -56,12 +63,12 @@ module GitProc
56
63
 
57
64
  logger.warn {bad_parking_branch_msg}
58
65
  else
59
- parking_branch.delete
66
+ parking_branch.delete!
60
67
  end
61
68
  end
62
69
  remote_master.checkout_to_new('_parking_', :no_track => true)
63
70
 
64
- current_branch.delete(true)
71
+ current_branch.delete!(true)
65
72
  if mybranches["#{server_name}/#{current_branch.name}"]
66
73
  push(server_name, nil, nil, :delete => current_branch.name)
67
74
  end