From 5a5dc4a8d1e6bd0db727edba9f43f1be8a9e519e Mon Sep 17 00:00:00 2001 From: Taufek Johar Date: Thu, 8 Feb 2018 05:04:02 +0800 Subject: [PATCH] Update PrePush Modified Files and Lines with Multiple Branches Push In `pre-push` hook, it receives multiple ref ranges when we pushed multiple branches to remote. Below is pushing multiple branches plus setting up the upstream branch on remote. ``` command: git push origin -u tj-test tj-test-2 stdin: refs/heads/tj-test 62738e20036f58060a8f94ff8cd73733acb6561b refs/heads/tj-test 0000000000000000000000000000000000000000 refs/heads/tj-test-2 feb40b515f598723fe043b7cb9510f28c287d642 refs/heads/tj-test-2 0000000000000000000000000000000000000000 ``` Below is pushing multiple branches which already has upstream branch on remote. ``` command: git push origin tj-test tj-test-2 stdin: refs/heads/tj-test 61bc13ab2e717633441855d534904c5036f342dd refs/heads/tj-test 62738e20036f58060a8f94ff8cd73733acb6561b refs/heads/tj-test-2 1e371d2c345e00c34410372dad2d7602aca99908 refs/heads/tj-test-2 feb40b515f598723fe043b7cb9510f28c287d642 ``` With these multiple ref ranges, we should read all of them during pre-push `modified_files` and `modified_lines_in_file`. --- lib/overcommit/hook_context/pre_push.rb | 23 ++-- spec/overcommit/hook_context/pre_push_spec.rb | 109 +++++++++++++++--- 2 files changed, 108 insertions(+), 24 deletions(-) diff --git a/lib/overcommit/hook_context/pre_push.rb b/lib/overcommit/hook_context/pre_push.rb index 4c0ca34d..66fa0c91 100644 --- a/lib/overcommit/hook_context/pre_push.rb +++ b/lib/overcommit/hook_context/pre_push.rb @@ -18,17 +18,14 @@ def pushed_refs end def modified_files - @modified_files ||= Overcommit::GitRepo.modified_files(refs: ref_range) + @modified_files ||= pushed_refs.map(&:modified_files).flatten.uniq end def modified_lines_in_file(file) @modified_lines ||= {} - @modified_lines[file] = - Overcommit::GitRepo.extract_modified_lines(file, refs: ref_range) - end - - def ref_range - "#{pushed_refs[0].remote_sha1}..#{pushed_refs[0].local_sha1}" + @modified_lines[file] = pushed_refs.each_with_object(Set.new) do |pushed_ref, set| + set.merge(pushed_ref.modified_lines_in_file(file)) + end end PushedRef = Struct.new(:local_ref, :local_sha1, :remote_ref, :remote_sha1) do @@ -48,12 +45,24 @@ def destructive? deleted? || forced? end + def modified_files + Overcommit::GitRepo.modified_files(refs: ref_range) + end + + def modified_lines_in_file(file) + Overcommit::GitRepo.extract_modified_lines(file, refs: ref_range) + end + def to_s "#{local_ref} #{local_sha1} #{remote_ref} #{remote_sha1}" end private + def ref_range + "#{remote_sha1}..#{local_sha1}" + end + def overwritten_commits return @overwritten_commits if defined? @overwritten_commits result = Overcommit::Subprocess.spawn(%W[git rev-list #{remote_sha1} ^#{local_sha1}]) diff --git a/spec/overcommit/hook_context/pre_push_spec.rb b/spec/overcommit/hook_context/pre_push_spec.rb index 007a70ca..e8306ad2 100644 --- a/spec/overcommit/hook_context/pre_push_spec.rb +++ b/spec/overcommit/hook_context/pre_push_spec.rb @@ -87,7 +87,55 @@ `git add . 2>&1 > #{File::NULL}` `git commit -m "Update Branch 2" 2>&1 > #{File::NULL}` - should include(*%w[added-1 update-me added-2].map { |file| File.expand_path(file) }) + should == %w[added-1 added-2 update-me].map { |file| File.expand_path(file) } + should_not include(*%w[delete-me].map { |file| File.expand_path(file) }) + end + end + end + + context 'when pushing multiple branches at once' do + let(:local_ref_1) { 'refs/heads/project-branch-1' } + let(:local_sha1_1) { get_sha1(local_ref_1) } + let(:local_ref_2) { 'refs/heads/project-branch-2' } + let(:local_sha1_2) { get_sha1(local_ref_2) } + let(:remote_ref) { 'refs/remotes/origin/master' } + let(:remote_sha1) { get_sha1(remote_ref) } + let(:input) do + double('input', read: ref_ranges) + end + let(:ref_ranges) do + [ + "#{local_ref_1} #{local_sha1_1} #{remote_ref} #{remote_sha1}\n", + "#{local_ref_2} #{local_sha1_2} #{remote_ref} #{remote_sha1}\n" + ].join + end + + it 'has modified files based on multiple tracking branches' do + repo do + `git remote add origin file://#{remote_repo}` + `git fetch origin 2>&1 > #{File::NULL} && git reset --hard origin/master` + + `git checkout -b project-branch-1 2>&1 > #{File::NULL}` + `git push -u origin project-branch-1 2>&1 > #{File::NULL}` + + touch 'added-1' + echo 'add', 'added-1' + echo 'append', 'update-me' + FileUtils.rm 'delete-me' + `git add . 2>&1 > #{File::NULL}` + `git commit -m "Update Branch 1" 2>&1 > #{File::NULL}` + + `git checkout master 2>&1 > #{File::NULL}` + `git checkout -b project-branch-2 2>&1 > #{File::NULL}` + `git push -u origin project-branch-2 2>&1 > #{File::NULL}` + + echo 'append', 'update-me' + touch 'added-2' + echo 'add', 'added-2' + `git add . 2>&1 > #{File::NULL}` + `git commit -m "Update Branch 2" 2>&1 > #{File::NULL}` + + should == %w[added-1 update-me added-2].map { |file| File.expand_path(file) } should_not include(*%w[delete-me].map { |file| File.expand_path(file) }) end end @@ -121,7 +169,7 @@ `git add . 2>&1 > #{File::NULL}` `git commit -m "Update Branch 2" 2>&1 > #{File::NULL}` - should include(*%w[added-1 update-me added-2].map { |file| File.expand_path(file) }) + should == %w[added-1 added-2 update-me].map { |file| File.expand_path(file) } should_not include(*%w[delete-me].map { |file| File.expand_path(file) }) end end @@ -130,12 +178,20 @@ describe '#modified_lines_in_file' do subject { context.modified_lines_in_file(file) } - let(:local_ref) { 'refs/heads/project-branch' } - let(:local_sha1) { get_sha1(local_ref) } + let(:local_ref_1) { 'refs/heads/project-branch-1' } + let(:local_sha1_1) { get_sha1(local_ref_1) } + let(:local_ref_2) { 'refs/heads/project-branch-2' } + let(:local_sha1_2) { get_sha1(local_ref_2) } let(:remote_ref) { 'refs/remotes/origin/master' } let(:remote_sha1) { get_sha1(remote_ref) } let(:input) do - double('input', read: "#{local_ref} #{local_sha1} #{remote_ref} #{remote_sha1}\n") + double('input', read: ref_ranges) + end + let(:ref_ranges) do + [ + "#{local_ref_1} #{local_sha1_1} #{remote_ref} #{remote_sha1}\n", + "#{local_ref_2} #{local_sha1_2} #{remote_ref} #{remote_sha1}\n" + ].join end let(:remote_repo) do repo do @@ -154,20 +210,28 @@ `git remote add origin file://#{remote_repo}` `git fetch origin 2>&1 > #{File::NULL} && git reset --hard origin/master` - `git checkout -b project-branch 2>&1 > #{File::NULL}` - `git push -u origin project-branch 2>&1 > #{File::NULL}` + `git checkout -b project-branch-1 2>&1 > #{File::NULL}` + `git push -u origin project-branch-1 2>&1 > #{File::NULL}` echo 'append-1', 'initial_file', append: true `git add . 2>&1 > #{File::NULL}` - `git commit -m "Update Branch 1" 2>&1 > #{File::NULL}` + `git commit -m "Update Branch 1 Commit 1" 2>&1 > #{File::NULL}` echo 'append-2', 'initial_file', append: true `git add . 2>&1 > #{File::NULL}` - `git commit -m "Update Branch 2" 2>&1 > #{File::NULL}` + `git commit -m "Update Branch 1 Commit 2" 2>&1 > #{File::NULL}` - should == [2, 3].to_set + `git checkout -b project-branch-2 2>&1 > #{File::NULL}` + `git push -u origin project-branch-2 2>&1 > #{File::NULL}` + + echo 'append-3', 'initial_file', append: true + + `git add . 2>&1 > #{File::NULL}` + `git commit -m "Update Branch 2 Commit 1" 2>&1 > #{File::NULL}` + + should == [2, 3, 4].to_set end end end @@ -180,36 +244,47 @@ `git remote add origin file://#{remote_repo}` `git fetch origin 2>&1 > #{File::NULL} && git reset --hard origin/master` - `git checkout -b project-branch 2>&1 > #{File::NULL}` - `git push -u origin project-branch 2>&1 > #{File::NULL}` + `git checkout -b project-branch-1 2>&1 > #{File::NULL}` + `git push -u origin project-branch-1 2>&1 > #{File::NULL}` touch 'new_file' echo 'append-1', 'new_file', append: true `git add . 2>&1 > #{File::NULL}` - `git commit -m "Update Branch 1" 2>&1 > #{File::NULL}` + `git commit -m "Update Branch 1 Commit 1" 2>&1 > #{File::NULL}` echo 'append-2', 'new_file', append: true `git add . 2>&1 > #{File::NULL}` - `git commit -m "Update Branch 2" 2>&1 > #{File::NULL}` + `git commit -m "Update Branch 1 Commit 2" 2>&1 > #{File::NULL}` + + `git checkout -b project-branch-2 2>&1 > #{File::NULL}` + `git push -u origin project-branch-2 2>&1 > #{File::NULL}` - should == [1, 2].to_set + echo 'append-3', 'new_file', append: true + + `git add . 2>&1 > #{File::NULL}` + `git commit -m "Update Branch 2 Commit 1" 2>&1 > #{File::NULL}` + + should == [1, 2, 3].to_set end end end context 'when deleting a file' do let(:file) { File.expand_path('initial_file') } + let(:ref_ranges) do + "#{local_ref_1} #{local_sha1_1} #{remote_ref} #{remote_sha1}\n" + end it 'has modified lines in file' do repo do `git remote add origin file://#{remote_repo}` `git fetch origin 2>&1 > #{File::NULL} && git reset --hard origin/master` - `git checkout -b project-branch 2>&1 > #{File::NULL}` - `git push -u origin project-branch 2>&1 > #{File::NULL}` + `git checkout -b project-branch-1 2>&1 > #{File::NULL}` + `git push -u origin project-branch-1 2>&1 > #{File::NULL}` FileUtils.rm 'initial_file'