|
1 | 1 | #!/usr/local/bin/ruby
|
2 | 2 | require 'optparse'
|
| 3 | +require 'fileutils' |
3 | 4 |
|
4 | 5 | def getconfig(conf)
|
5 | 6 | output=`git config --get #{conf}`.strip
|
@@ -69,6 +70,14 @@ def run(cmd)
|
69 | 70 | options[:password] = val
|
70 | 71 | end
|
71 | 72 |
|
| 73 | + opts.on("--abort", "Used to abort a lib pull.") do |
| 74 | + options[:abort] = true |
| 75 | + end |
| 76 | + |
| 77 | + opts.on("--continue", "Used to continue after resolving merge conflicts during a lib pull.") do |
| 78 | + options[:continue] = true |
| 79 | + end |
| 80 | + |
72 | 81 | opts.on_tail("-h", "--help", "Show this message.") do
|
73 | 82 | puts opts
|
74 | 83 | exit
|
@@ -102,6 +111,23 @@ def ensure_clean()
|
102 | 111 | abort "Index has modifications. Cannot pull." unless $?.success?
|
103 | 112 | end
|
104 | 113 |
|
| 114 | +def produce_merge_commit(head_rev, fetch_rev, commit_message) |
| 115 | + if !head_rev.empty? && head_rev != fetch_rev then |
| 116 | + headp = "-p #{head_rev}" |
| 117 | + else |
| 118 | + headp = "" |
| 119 | + end |
| 120 | + |
| 121 | + tree = %x(git write-tree).strip |
| 122 | + abort "git write-tree failed" unless $?.success? |
| 123 | + |
| 124 | + commit = %x(git commit-tree #{tree} #{headp} -p #{fetch_rev} -m '#{commit_message}') |
| 125 | + abort "git commit failed" unless $?.success? |
| 126 | + |
| 127 | + %x(git reset #{commit}) |
| 128 | + abort "git reset failed" unless $?.success? |
| 129 | +end |
| 130 | + |
105 | 131 | commands = {
|
106 | 132 |
|
107 | 133 | "split" => lambda do
|
@@ -132,76 +158,85 @@ def ensure_clean()
|
132 | 158 | end,
|
133 | 159 |
|
134 | 160 | "pull" => lambda do
|
135 |
| - ensure_clean() |
| 161 | + git_dir = %x(git rev-parse --git-dir).strip |
| 162 | + lib_pull_file = "#{git_dir}/LIB_PULL" |
136 | 163 |
|
137 |
| - puts "Fetching remote lib..." |
138 |
| - %x(git fetch #{options[:url]} #{options[:refspec]}) |
139 |
| - abort "Could not fetch from repository: #{options[:url]}" unless $?.success? |
| 164 | + if (options[:abort] || options[:continue]) |
| 165 | + abort "Not currently in a lib pull" unless File.exists? lib_pull_file |
| 166 | + head_rev, fetch_rev, libname = File.read(lib_pull_file).split(' ') |
140 | 167 |
|
141 |
| - fetch_rev = %x(git rev-parse --revs-only fetch_head).split(' ')[0].strip |
142 |
| - head_rev = %x(git rev-parse head).strip |
143 |
| - if !head_rev.empty? && head_rev != fetch_rev then |
144 |
| - headp = "-p #{head_rev}" |
| 168 | + if (options[:abort]) |
| 169 | + %x(git reset --hard #{head_rev}) |
| 170 | + elsif (options[:continue]) |
| 171 | + commit_message = "Merged lib \"#{libname}\"" |
| 172 | + end |
145 | 173 | else
|
146 |
| - headp = "" |
147 |
| - end |
| 174 | + ensure_clean() |
| 175 | + libname = options[:libname] |
148 | 176 |
|
149 |
| - if !Dir.exists? options[:prefix] |
150 |
| - puts "Adding lib..." |
| 177 | + puts "Fetching remote lib..." |
| 178 | + %x(git fetch #{options[:url]} #{options[:refspec]}) |
| 179 | + abort "Could not fetch from repository: #{options[:url]}" unless $?.success? |
151 | 180 |
|
152 |
| - %x(git read-tree --prefix="#{options[:prefix]}" fetch_head) |
153 |
| - abort "git read-tree failed" unless $?.success? |
| 181 | + fetch_rev = %x(git rev-parse --revs-only fetch_head).split(' ')[0].strip |
| 182 | + head_rev = %x(git rev-parse head).strip |
| 183 | + File.write(lib_pull_file, "#{head_rev} #{fetch_rev}") |
154 | 184 |
|
155 |
| - %x(git checkout -- "#{options[:prefix]}") |
156 |
| - abort "git checkout tree failed" unless $?.success? |
| 185 | + if !Dir.exists? options[:prefix] |
| 186 | + puts "Adding lib..." |
157 | 187 |
|
158 |
| - commit_message = "Add lib \"#{options[:libname]}\"" |
159 |
| - else |
160 |
| - puts "Rejoining lib..." |
161 |
| - split_sha, success = call "#{gitsubtree} --prefix #{options[:prefix]} --with fetch_head" |
162 |
| - abort "Split failed" unless success |
| 188 | + %x(git read-tree --prefix="#{options[:prefix]}" fetch_head) |
| 189 | + abort "git read-tree failed" unless $?.success? |
163 | 190 |
|
164 |
| - puts "Merging lib..." |
| 191 | + %x(git checkout -- "#{options[:prefix]}") |
| 192 | + abort "git checkout tree failed" unless $?.success? |
165 | 193 |
|
166 |
| - if !%x(git rev-list #{split_sha}..fetch_head).empty? |
167 |
| - %x(git merge -s ours -m 'Rejoin lib "#{options[:libname]}"' #{split_sha}) |
168 |
| - |
169 |
| - commit_message = "Merged lib \"#{options[:libname]}\"" |
170 |
| - output = %x(git merge -Xsubtree=#{options[:prefix]} --message='#{commit_message}' -q --no-commit fetch_head 2>&1) |
171 |
| - abort "Merge failed:\n#{output}" unless $?.success? |
| 194 | + commit_message = "Add lib \"#{libname}\"" |
172 | 195 | else
|
173 |
| - puts "Everything up-to-date" |
| 196 | + puts "Rejoining lib..." |
| 197 | + split_sha, success = call "#{gitsubtree} --prefix #{options[:prefix]} --with fetch_head" |
| 198 | + abort "Split failed" unless success |
| 199 | + |
| 200 | + puts "Merging lib..." |
| 201 | + |
| 202 | + if !%x(git rev-list #{split_sha}..fetch_head).empty? |
| 203 | + %x(git merge -s ours -m 'Rejoin lib "#{options[:libname]}"' #{split_sha}) |
| 204 | + |
| 205 | + commit_message = "Merged lib \"#{libname}\"" |
| 206 | + output = %x(git merge -Xsubtree=#{options[:prefix]} --message='#{commit_message}' -q --no-commit fetch_head 2>&1) |
| 207 | + abort 'Merge failed; Fix conflicts and then issue "git lib pull --continue"' unless $?.success? |
| 208 | + else |
| 209 | + puts "Everything up-to-date" |
| 210 | + end |
174 | 211 | end
|
175 | 212 | end
|
176 | 213 |
|
177 | 214 | if commit_message
|
178 |
| - tree = %x(git write-tree).strip |
179 |
| - abort "git write-tree failed" unless $?.success? |
180 |
| - |
181 |
| - commit = %x(git commit-tree #{tree} #{headp} -p #{fetch_rev} -m '#{commit_message}') |
182 |
| - abort "git commit failed" unless $?.success? |
183 |
| - |
184 |
| - %x(git reset #{commit}) |
| 215 | + produce_merge_commit(head_rev, fetch_rev, commit_message) |
185 | 216 | end
|
| 217 | + |
| 218 | + FileUtils.rm(lib_pull_file) |
186 | 219 | end,
|
187 | 220 | }
|
188 | 221 |
|
189 | 222 |
|
190 | 223 | ########################################
|
191 | 224 | # Main
|
192 | 225 |
|
193 |
| -if ARGV.length != 2 then |
| 226 | +if ARGV.length < 1 then |
194 | 227 | puts option_parser
|
195 | 228 | else
|
196 | 229 | commandname = ARGV[0]
|
197 | 230 | options[:libname] = ARGV[1]
|
198 | 231 |
|
199 |
| - options[:url] = %x(#{githost} url-for #{options[:libname]} #{host_options(options)}).strip |
200 |
| - exit(1) unless $?.success? |
| 232 | + if !(options[:abort] || options[:continue]) |
| 233 | + options[:url] = %x(#{githost} url-for #{options[:libname]} #{host_options(options)}).strip |
| 234 | + exit(1) unless $?.success? |
201 | 235 |
|
202 |
| - if not options[:prefix] then |
203 |
| - reldir = pwd[gitdir.length + 1..-1] || '.' |
204 |
| - options[:prefix] = reldir != '.' && File.join(reldir, options[:libname]) || options[:libname] |
| 236 | + if not options[:prefix] then |
| 237 | + reldir = pwd[gitdir.length + 1..-1] || '.' |
| 238 | + options[:prefix] = reldir != '.' && File.join(reldir, options[:libname]) || options[:libname] |
| 239 | + end |
205 | 240 | end
|
206 | 241 |
|
207 | 242 | command = commands[commandname]
|
|
0 commit comments