Created
September 18, 2009 01:30
-
-
Save jawspeak/188820 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env ruby | |
| require 'fileutils' | |
| require 'find' | |
| # FOR THE RECORD: I strongly dislike branch based development | |
| # FOR THE RECORD: I strongly dislike branch based development | |
| # FOR THE RECORD: I strongly dislike branch based development | |
| # FOR THE RECORD: I prefer trunk based development, and branch by abstraction | |
| # This assumes you are merging from trunk to your branch. I don't recommend branched based | |
| # development, but sometimes you may not have a choice. | |
| # I use this script in order to help me with merging, after already doing a svn merge. | |
| # Sometimes I want to double check what it is I merged for that file. So, I check out three | |
| # working copies of my project, and sync (1) to the previous merge revision, (2) to head on my branch | |
| # and (3) to trunk at the revision I merged to. | |
| merge_output_file=ARGV[0] # should be absolute path to the file you are merging, i.e. you are editing | |
| # it in intellij, but don't trust the merge you just did, so you want to re-check it against trunk and base. | |
| # Getting the path in IDEA is easy, right click on the file and: 'copy path'. | |
| # normalize the directories. we assume you checked out in the same directory the project 4 times: | |
| # "myCheckout" (where you merged into), | |
| # "myCheckoutPreviousMerge" | |
| # "trunk" | |
| # "myCheckoutPristine" (synced to same revision as myCheckout, but without any changes) | |
| # Also, inside each checkout is a directory "xyz-project", and in there is the base of the code | |
| # (or maven project parent in our case) | |
| # You could also simplify this to only open a diff between pristine, trunk, and the merging file. | |
| trunk_file=merge_output_file.gsub(/myCheckout\//, 'trunk/') | |
| # need to check out the previous merge revision, which is the base version for comparing our pristine branch's changes to trunk | |
| last_merge_file=merge_output_file.gsub(/myCheckout\//, 'myCheckoutPreviousMerge/') | |
| pristine_file=merge_output_file.gsub(/myCheckout\//, 'myCheckoutPristine/') | |
| puts "------------------------------------------" | |
| puts "pristine_file: #{pristine_file}\n\n" | |
| puts "\nyou will be merging to save to merge_output_file: #{merge_output_file}\n\n" | |
| def die(file) | |
| puts "Error: file does not exist: #{file} Goodbye." | |
| exit(1) | |
| end | |
| # This finds a file even if it has moved from one module to another. (We saw an refactoring | |
| # come into our branch where we needed to diff against their file, even if it moved). | |
| # This does not support file renames. | |
| def find_file(search_for_abs_path) | |
| base_dir = search_for_abs_path.gsub(/xyz-project.*/, 'xyz-project') | |
| search_for_file = File.basename(search_for_abs_path) | |
| # These are maven sub-modules (folders) inside the base of project, which might hold source code | |
| # Remember to add directories here if we need them later, so we search for files in there too. | |
| dir_stack = %w(common service integration-test service-account service-common service-foo web) | |
| dir_stack.each do |dir| | |
| cmd = "find #{base_dir}/#{dir} -name #{search_for_file}" | |
| found = `#{cmd}`.split("\n") | |
| if found.length > 1 | |
| puts "Found too many possibilities, choose one manually:\n#{found.join("\n")}\n\n" | |
| exit(1) | |
| end | |
| return found[0] if found.length == 1 | |
| end | |
| die(search_for_file) | |
| end | |
| def fix_if_file_missing(file) | |
| if (!File.exist?(file)) | |
| file = find_file(file) | |
| puts "Using different file, #{file}, okay? type [Y/N]" | |
| ok = STDIN.gets | |
| exit unless ok.upcase.index('Y') == 0 | |
| return file | |
| end | |
| file | |
| end | |
| last_merge_file = fix_if_file_missing(last_merge_file) | |
| trunk_file = fix_if_file_missing(trunk_file) | |
| pristine_file = fix_if_file_missing(pristine_file) | |
| puts "last_merge_file: #{last_merge_file}\n\n" | |
| puts "merge_output_file: #{merge_output_file}\n\n" | |
| puts "trunk_file: #{trunk_file}\n\n" | |
| # kdiff3 is what we use to merge, it's a very nice tool | |
| cmd="/usr/bin/kdiff3 \\\n #{last_merge_file} \\\n #{pristine_file} \\\n #{trunk_file} \\\n -o #{merge_output_file}" | |
| puts "Executing: \n #{cmd}\n\n\n" | |
| exec cmd | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env ruby | |
| require 'fileutils' | |
| require 'find' | |
| require 'rubygems' | |
| require 'ruby-debug' | |
| # FOR THE RECORD: I dislike branch based development. | |
| # We were in a svn branch, and frequently merging down changes from trunk. Trunk | |
| # did an unfortunate refactoring that was very complicated by moving files into | |
| # multiple different sub-projects (maven modules). The files weren't renamed, but | |
| # were moved. We were modifying them too on the branch. | |
| # This script helped to find, for every one of our files in service/ if the file | |
| # had been moved into service-*/ and if it had, then diff our version with their | |
| # version, to make sure we didn't loose any changes made by our team during the | |
| # several weeks it took for us to do the merge. (Without checking this, we could | |
| # have made changes to a file that no longer existed, and thus when we checked in | |
| # a version of that file from a week ago into service-*/, we'd loose the recent | |
| # changes. | |
| # the working directory we did the merge in: | |
| R3_MERGE_BASE_DIR='/developer/developer/myProject/xyz-project' | |
| # the working directory synced to same svn revision, but no local changes, just | |
| # up to date with the rest of the team's changes. (Which possibly include additions | |
| # to the service/ folder which we have moved to the service-* folders in the merge). | |
| R3_PRISTINE_BASE_DIR='/developer/developer/myProjectPristine/xyz-project' | |
| # really cool find options which exclude descending into .svn, target, and generated folders. | |
| # (I could have probably used -name target -prune instead of -iwholename...) | |
| FIND_OPTS = " -not \\( -name .svn -prune \\) -not \\( -iwholename '*/target/*' -prune \\) -not \\( -iwholename '*/generated/*' \\) -type f" | |
| def find_base_dir | |
| dir = `pwd` | |
| if !dir.match(/myProject\/xyz-project/) | |
| puts "Need to run from pwd as /myProject/xyz-project/"; exit(1); | |
| end | |
| dir | |
| end | |
| def find_all_java_files_in_service_star(base_dir) | |
| cmd = "/usr/bin/find #{base_dir}/service* -name '*.java' " + FIND_OPTS | |
| files = `#{cmd}`.split("\n") | |
| puts "Found #{files.length} files in #{base_dir}/service*, will now look in myProject's service/ folder for a matching (updated) file." | |
| files | |
| end | |
| def find_file_in_r3_service_dir(file, base_dir) | |
| search_for_file = File.basename(file) | |
| cmd = "/usr/bin/find #{base_dir}/service -name #{search_for_file}" + FIND_OPTS | |
| found = `#{cmd}`.split("\n") | |
| if found.length > 1 | |
| puts "!!!\nERROR: Found too many possibilities, manually resolve the conflict: :\n #{found.join(" \n")}\n\n!!!\n" | |
| return nil | |
| end | |
| return found[0] if found.length == 1 | |
| puts "WARNING: file does not exist: #{search_for_file}" | |
| return nil | |
| end | |
| def kdiff3_if_files_different(file, r3_file, command_stack) | |
| if `diff --ignore-all-space #{r3_file} #{file}`.length > 0 | |
| puts "Need to merge #{File.basename(file)}, because there are changes in myProjectPristine that are not dealt with in myProject merge yet" | |
| cmd="/usr/bin/kdiff3 \\\n #{r3_file} \\\n #{file} \\\n -o #{file}" | |
| command_stack.push(cmd) | |
| end | |
| end | |
| def run | |
| java_files = find_all_java_files_in_service_star(R3_MERGE_BASE_DIR) | |
| # record to stack so we can guage our progress and know the magnitude of the changes found. | |
| command_stack = [] | |
| java_files.each do |merge_file| | |
| r3_pristine_file = find_file_in_r3_service_dir(merge_file, R3_PRISTINE_BASE_DIR) | |
| next if !r3_pristine_file | |
| kdiff3_if_files_different(merge_file, r3_pristine_file, command_stack) | |
| end | |
| command_stack.each_with_index do |cmd, i| | |
| puts "Executing #{i}th of #{command_stack.length}: \n #{cmd}\n\n\n" | |
| system cmd | |
| end | |
| end | |
| if __FILE__ == $0 | |
| run | |
| end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment