Commit 5d56da6bddcaa4d510fd97a8e38d80e750e3e20f

Authored by Izaak Alpert
1 parent 489fa5d7

MR on fork: Some cleanup, test updates

-The forked merge request test now tests it's componenets again, and seems to work every time (did this by reordering the branch updates so their is more time for update_branches to run) -- this could still technically fail, but after several runs it doesn't seem to.
-Removed todo in merge_request, pushed wrapping of grit down to the satellite
-updated action test to check flock status, made it nolonger pending
-moved all logging on failure to helper method in satellite
GITLAB-592

Change-Id: If0554ca35eedc3d3e8461f7d93d4b3939fa2cd75
app/assets/stylesheets/common.scss
... ... @@ -415,6 +415,7 @@ img.emoji {
415 415 @extend .light-well;
416 416 @extend .light;
417 417 margin-bottom: 10px;
  418 +}
418 419  
419 420 .label-project {
420 421 @include border-radius(4px);
... ...
app/models/merge_request.rb
... ... @@ -26,12 +26,10 @@ class MergeRequest < ActiveRecord::Base
26 26  
27 27 include Issuable
28 28  
29   - belongs_to :target_project,:foreign_key => :target_project_id, class_name: "Project"
30   - belongs_to :source_project, :foreign_key => :source_project_id,class_name: "Project"
  29 + belongs_to :target_project, :foreign_key => :target_project_id, class_name: "Project"
  30 + belongs_to :source_project, :foreign_key => :source_project_id, class_name: "Project"
31 31  
32   - BROKEN_DIFF = "--broken-diff"
33   -
34   - attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id,:author_id_of_changes, :state_event
  32 + attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :author_id_of_changes, :state_event
35 33  
36 34  
37 35 attr_accessor :should_remove_source_branch
... ... @@ -87,8 +85,8 @@ class MergeRequest < ActiveRecord::Base
87 85 validates :target_branch, presence: true
88 86 validate :validate_branches
89 87  
90   - scope :of_group, ->(group) { where("source_project_id in (:group_project_ids) OR target_project_id in (:group_project_ids)",group_project_ids:group.project_ids) }
91   - scope :of_user_team, ->(team) { where("(source_project_id in (:team_project_ids) OR target_project_id in (:team_project_ids) AND assignee_id in (:team_member_ids))",team_project_ids:team.project_ids,team_member_ids:team.member_ids) }
  88 + scope :of_group, ->(group) { where("source_project_id in (:group_project_ids) OR target_project_id in (:group_project_ids)", group_project_ids: group.project_ids) }
  89 + scope :of_user_team, ->(team) { where("(source_project_id in (:team_project_ids) OR target_project_id in (:team_project_ids) AND assignee_id in (:team_member_ids))", team_project_ids: team.project_ids, team_member_ids: team.member_ids) }
92 90 scope :opened, -> { with_state(:opened) }
93 91 scope :closed, -> { with_state(:closed) }
94 92 scope :merged, -> { with_state(:merged) }
... ... @@ -151,13 +149,8 @@ class MergeRequest < ActiveRecord::Base
151 149 end
152 150  
153 151 def unmerged_diffs
154   - #TODO:[IA-8] this needs to be handled better -- logged etc
155   - diffs = Gitlab::Satellite::MergeAction.new(author, self).diffs_between_satellite
156   - if diffs
157   - diffs = diffs.map { |diff| Gitlab::Git::Diff.new(diff) }
158   - else
159   - diffs = []
160   - end
  152 + diffs = Gitlab::Satellite::MergeAction.new(author, self).diffs_between_satellite
  153 + diffs ||= []
161 154 diffs
162 155 end
163 156  
... ... @@ -192,12 +185,11 @@ class MergeRequest < ActiveRecord::Base
192 185 end
193 186  
194 187 def unmerged_commits
195   - commits = Gitlab::Satellite::MergeAction.new(self.author,self).commits_between
196   - commits = commits.map{ |commit| Gitlab::Git::Commit.new(commit, nil) }
  188 + commits = Gitlab::Satellite::MergeAction.new(self.author, self).commits_between
197 189 if commits.present?
198 190 commits = Commit.decorate(commits).
199   - sort_by(&:created_at).
200   - reverse
  191 + sort_by(&:created_at).
  192 + reverse
201 193 end
202 194 commits
203 195 end
... ... @@ -222,6 +214,7 @@ class MergeRequest < ActiveRecord::Base
222 214 commit_ids = commits.map(&:id)
223 215 Note.where("(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))", mr_id: id, commit_ids: commit_ids)
224 216 end
  217 +
225 218 # Returns the raw diff for this merge request
226 219 #
227 220 # see "git diff"
... ...
features/steps/project/project_forked_merge_requests.rb
... ... @@ -5,6 +5,7 @@ class ProjectForkedMergeRequests < Spinach::FeatureSteps
5 5 include SharedPaths
6 6  
7 7  
  8 +
8 9 Given 'I am a member of project "Shop"' do
9 10 @project = Project.find_by_name "Shop"
10 11 @project ||= create(:project_with_code, name: "Shop")
... ... @@ -34,22 +35,42 @@ class ProjectForkedMergeRequests < Spinach::FeatureSteps
34 35 current_path.should == project_merge_request_path(@project, @merge_request)
35 36 @merge_request.title.should == "Merge Request On Forked Project"
36 37 @merge_request.source_project.should == @forked_project
  38 + @merge_request.source_branch.should == "master"
  39 + @merge_request.target_branch.should == "stable"
  40 + page.should have_content @forked_project.path_with_namespace
  41 + page.should have_content @project.path_with_namespace
  42 + page.should have_content @merge_request.source_branch
  43 + page.should have_content @merge_request.target_branch
37 44 end
38 45  
39 46 And 'I fill out a "Merge Request On Forked Project" merge request' do
  47 + #The ordering here is a bit whacky on purpose:
  48 + #Select the target right away, to give update_branches time to run and clean up the target_branches
  49 + find(:select, "merge_request_target_project_id", {}).value.should == @forked_project.id.to_s
  50 + select @project.path_with_namespace, from: "merge_request_target_project_id"
  51 +
  52 +
40 53 fill_in "merge_request_title", with: "Merge Request On Forked Project"
41 54 find(:select, "merge_request_source_project_id", {}).value.should == @forked_project.id.to_s
42   - find(:select, "merge_request_target_project_id", {}).value.should == @forked_project.id.to_s
43 55  
44   - select @project.path_with_namespace, from: "merge_request_target_project_id"
45 56 find(:select, "merge_request_target_project_id", {}).value.should == @project.id.to_s
  57 +
  58 + #Ensure the option exists in the select
  59 + find(:select, "merge_request_source_branch", {}).should have_content "master"
46 60 select "master", from: "merge_request_source_branch"
  61 + #Ensure the option is selected
47 62 find(:select, "merge_request_source_branch", {}).value.should have_content "master"
48   - #Force the page to wait until the javascript finishes, so the stable option shows up
49   - select "stable", from: "merge_request_target_branch"
  63 + verify_commit_link(".mr_source_commit",@forked_project)
  64 +
  65 +
  66 + #This could fail if the javascript hasn't run yet, there is a timing issue here -- this is why we do the select at the top
  67 + #Ensure the option exists in the select
50 68 find(:select, "merge_request_target_branch", {}).should have_content "stable"
  69 + #We must give apparently lots of time for update branches to finish
51 70  
52   - verify_commit_link(".mr_source_commit",@forked_project)
  71 + (find(:select, "merge_request_target_branch", {}).find(:option, "stable",{}).select_option).should be_true
  72 + #Ensure the option is selected
  73 + find(:select, "merge_request_target_branch", {}).value.should have_content "stable"
53 74 verify_commit_link(".mr_target_commit",@project)
54 75 end
55 76  
... ... @@ -126,14 +147,8 @@ class ProjectForkedMergeRequests < Spinach::FeatureSteps
126 147 find("#merge_request_target_project_id").value.should == @project.id.to_s
127 148 find("#merge_request_source_branch").value.should have_content "master"
128 149 verify_commit_link(".mr_source_commit",@forked_project)
129   - #TODO[IA-08] reienstate these -- not sure why they started repeatedly breaking
130   - #sleep 3
131   - #puts "Source text:#{find("#merge_request_source_branch").text}"
132   - #puts "Source value:#{find("#merge_request_source_branch").value}"
133   - #puts "Target text:#{find("#merge_request_target_branch").text}"
134   - #puts "Target value:#{find("#merge_request_target_branch").value}"
135   - #find("#merge_request_target_branch").value.should have_content "stable"
136   - #verify_commit_link(".mr_target_commit",@project)
  150 + find("#merge_request_target_branch").value.should have_content "stable"
  151 + verify_commit_link(".mr_target_commit",@project)
137 152 end
138 153  
139 154  
... ... @@ -144,16 +159,8 @@ class ProjectForkedMergeRequests < Spinach::FeatureSteps
144 159 #Verify a link is generated against the correct project
145 160 def verify_commit_link(container_div, container_project)
146 161 #This should force a wait for the javascript to execute
147   - #puts "text: #{find(:div,container_div).text}"
148 162 find(:div,container_div).should have_css ".browse_code_link_holder"
149 163 find(:div,container_div).find(".commit_short_id")['href'].should have_content "#{container_project.path_with_namespace}/commit"
150   - #commit_links = commit.all("a").map(&:text)
151   - #links = commit_links.collect {|e|commit.find(:link,e)['href']}
152   - #links.size.should == 4
153   - #links[0].should have_content "#{container_project.path_with_namespace}/tree"
154   - #links[1].should have_content "#{container_project.path_with_namespace}/commit"
155   - #links[3].should have_content "#{container_project.path_with_namespace}/commit"
156   -
157 164 end
158 165  
159 166 end
... ...
lib/gitlab/satellite/action.rb
1 1 module Gitlab
2 2 module Satellite
3 3 class Action
4   - DEFAULT_OPTIONS = { git_timeout: 30.seconds}
  4 + DEFAULT_OPTIONS = {git_timeout: 30.seconds}
5 5  
6 6 attr_accessor :options, :project, :user
7 7  
... ... @@ -25,11 +25,9 @@ module Gitlab
25 25 end
26 26 end
27 27 rescue Errno::ENOMEM => ex
28   - Gitlab::GitLogger.error(ex.message)
29   - return false
  28 + return handle_exception(ex)
30 29 rescue Grit::Git::GitTimeout => ex
31   - Gitlab::GitLogger.error(ex.message)
32   - return false
  30 + return handle_exception(ex)
33 31 ensure
34 32 Gitlab::ShellEnv.reset_env
35 33 end
... ... @@ -48,6 +46,11 @@ module Gitlab
48 46 def default_options(options = {})
49 47 {raise: true, timeout: true}.merge(options)
50 48 end
  49 +
  50 + def handle_exception(exception)
  51 + Gitlab::GitLogger.error(exception.message)
  52 + false
  53 + end
51 54 end
52 55 end
53 56 end
... ...
lib/gitlab/satellite/merge_action.rb
... ... @@ -41,8 +41,7 @@ module Gitlab
41 41 end
42 42 end
43 43 rescue Grit::Git::CommandFailed => ex
44   - Gitlab::GitLogger.error(ex.message)
45   - false
  44 + handle_exception(ex)
46 45 end
47 46  
48 47  
... ... @@ -61,8 +60,7 @@ module Gitlab
61 60 return diff
62 61 end
63 62 rescue Grit::Git::CommandFailed => ex
64   - Gitlab::GitLogger.error(ex.message)
65   - false
  63 + handle_exception(ex)
66 64 end
67 65  
68 66 # Only show what is new in the source branch compared to the target branch, not the other way around.
... ... @@ -81,11 +79,11 @@ module Gitlab
81 79 #this method doesn't take default options
82 80 diffs = merge_repo.diff(common_commit, "#{merge_request.source_branch}")
83 81 end
  82 + diffs = diffs.map { |diff| Gitlab::Git::Diff.new(diff) }
84 83 return diffs
85 84 end
86 85 rescue Grit::Git::CommandFailed => ex
87   - Gitlab::GitLogger.error(ex.message)
88   - false
  86 + handle_exception(ex)
89 87 end
90 88  
91 89 # Get commit as an email patch
... ... @@ -101,8 +99,7 @@ module Gitlab
101 99 return patch
102 100 end
103 101 rescue Grit::Git::CommandFailed => ex
104   - Gitlab::GitLogger.error(ex.message)
105   - false
  102 + handle_exception(ex)
106 103 end
107 104  
108 105 # Retrieve an array of commits between the source and the target
... ... @@ -115,12 +112,12 @@ module Gitlab
115 112 else
116 113 commits = merge_repo.commits_between("#{merge_request.target_branch}", "#{merge_request.source_branch}")
117 114 end
  115 + commits = commits.map { |commit| Gitlab::Git::Commit.new(commit, nil) }
118 116 return commits
119 117  
120 118 end
121 119 rescue Grit::Git::CommandFailed => ex
122   - Gitlab::GitLogger.error(ex.message)
123   - false
  120 + handle_exception(ex)
124 121 end
125 122  
126 123 private
... ... @@ -142,8 +139,7 @@ module Gitlab
142 139 repo.git.pull(default_options({no_ff: true}), 'origin', merge_request.source_branch)
143 140 end
144 141 rescue Grit::Git::CommandFailed => ex
145   - Gitlab::GitLogger.error(ex.message)
146   - false
  142 + handle_exception(ex)
147 143 end
148 144  
149 145 # Assumes a satellite exists that is a fresh clone of the projects repo, prepares satellite for merges, diffs etc
... ... @@ -159,11 +155,9 @@ module Gitlab
159 155 repo.git.checkout(default_options, "#{merge_request.target_branch}")
160 156 end
161 157 rescue Grit::Git::CommandFailed => ex
162   - Gitlab::GitLogger.error(ex.message)
163   - false
  158 + handle_exception(ex)
164 159 end
165 160  
166   -
167 161 end
168 162 end
169 163 end
... ...
spec/lib/gitlab/satellite/action_spec.rb
... ... @@ -78,52 +78,43 @@ describe 'Gitlab::Satellite::Action' do
78 78 end
79 79  
80 80 it 'should be able to use the satellite after locking' do
81   - pending "can't test this, doesn't seem to be a way to the the flock status on a file, throwing piles of processes at it seems lousy too"
82 81 repo = project.satellite.repo
83   - first_call = false
84   -
85   - (File.exists? project.satellite.lock_file).should be_false
86   -
87   - test_file = ->(called) {
88   - File.exists?(project.satellite.lock_file).should be_true
89   - called.should be_true
90   - File.readlines.should == "some test code"
91   - File.truncate(project.satellite.lock, 0)
92   - File.readlines.should == ""
93   - }
94   -
95   - write_file = ->(called, checker) {
96   - if (File.exists?(project.satellite.lock_file))
97   - file = File.open(project.satellite.lock, '+w')
98   - file.write("some test code")
99   - file.close
100   - checker.call(called)
101   - end
102   - }
  82 + called = false
103 83  
  84 + # Set base assumptions
  85 + if File.exists? project.satellite.lock_file
  86 + FileLockStatusChecker.new(project.satellite.lock_file).flocked?.should be_false
  87 + end
104 88  
105 89 satellite_action = Gitlab::Satellite::Action.new(user, project)
106 90 satellite_action.send(:in_locked_and_timed_satellite) do |sat_repo|
107   - write_file.call(first_call, test_file)
108   - first_call = true
  91 + called = true
109 92 repo.should == sat_repo
110 93 (File.exists? project.satellite.lock_file).should be_true
111   -
  94 + FileLockStatusChecker.new(project.satellite.lock_file).flocked?.should be_true
112 95 end
113 96  
114   - first_call.should be_true
115   - puts File.stat(project.satellite.lock_file).inspect
  97 + called.should be_true
  98 + FileLockStatusChecker.new(project.satellite.lock_file).flocked?.should be_false
116 99  
117   - second_call = false
118   - satellite_action.send(:in_locked_and_timed_satellite) do |sat_repo|
119   - write_file.call(second_call, test_file)
120   - second_call = true
121   - repo.should == sat_repo
122   - (File.exists? project.satellite.lock_file).should be_true
123   - end
  100 + end
124 101  
125   - second_call.should be_true
126   - (File.exists? project.satellite.lock_file).should be_true
  102 + class FileLockStatusChecker < File
  103 + def flocked? &block
  104 + status = flock LOCK_EX|LOCK_NB
  105 + case status
  106 + when false
  107 + return true
  108 + when 0
  109 + begin
  110 + block ? block.call : false
  111 + ensure
  112 + flock LOCK_UN
  113 + end
  114 + else
  115 + raise SystemCallError, status
  116 + end
  117 + end
127 118 end
128 119  
129 120 end
... ...
spec/lib/gitlab/satellite/merge_action_spec.rb
... ... @@ -8,7 +8,7 @@ describe &#39;Gitlab::Satellite::MergeAction&#39; do
8 8 @wiki_branch = ['wiki', '635d3e09b72232b6e92a38de6cc184147e5bcb41'] #this is the commit sha where the wiki branch goes off from master
9 9 @conflicting_metior = ['metior', '313d96e42b313a0af5ab50fa233bf43e27118b3f'] #this branch conflicts with the wiki branch
10 10  
11   - #these commits are quite close together, itended to make string diffs/format patches small
  11 + #these commits are quite close together, itended to make string diffs/format patches small
12 12 @close_commit1 = ['2_3_notes_fix', '8470d70da67355c9c009e4401746b1d5410af2e3']
13 13 @close_commit2 = ['scss_refactoring', 'f0f14c8eaba69ebddd766498a9d0b0e79becd633']
14 14  
... ... @@ -18,19 +18,23 @@ describe &#39;Gitlab::Satellite::MergeAction&#39; do
18 18 let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
19 19 let(:merge_request_fork) { create(:merge_request) }
20 20 describe '#commits_between' do
  21 + def verify_commits(commits, first_commit_sha, last_commit_sha)
  22 + commits.each { |commit| commit.class.should == Gitlab::Git::Commit }
  23 + commits.first.id.should == first_commit_sha
  24 + commits.last.id.should == last_commit_sha
  25 + end
  26 +
21 27 context 'on fork' do
22 28 it 'should get proper commits between' do
23 29 merge_request_fork.target_branch = @one_after_stable[0]
24 30 merge_request_fork.source_branch = @master[0]
25 31 commits = Gitlab::Satellite::MergeAction.new(merge_request_fork.author, merge_request_fork).commits_between
26   - commits.first.id.should == @one_after_stable[1]
27   - commits.last.id.should == @master[1]
  32 + verify_commits(commits, @one_after_stable[1], @master[1])
28 33  
29 34 merge_request_fork.target_branch = @wiki_branch[0]
30 35 merge_request_fork.source_branch = @master[0]
31 36 commits = Gitlab::Satellite::MergeAction.new(merge_request_fork.author, merge_request_fork).commits_between
32   - commits.first.id.should == @wiki_branch[1]
33   - commits.last.id.should == @master[1]
  37 + verify_commits(commits, @wiki_branch[1], @master[1])
34 38 end
35 39 end
36 40  
... ... @@ -39,14 +43,12 @@ describe &#39;Gitlab::Satellite::MergeAction&#39; do
39 43 merge_request.target_branch = @one_after_stable[0]
40 44 merge_request.source_branch = @master[0]
41 45 commits = Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).commits_between
42   - commits.first.id.should == @one_after_stable[1]
43   - commits.last.id.should == @master[1]
  46 + verify_commits(commits, @one_after_stable[1], @master[1])
44 47  
45 48 merge_request.target_branch = @wiki_branch[0]
46 49 merge_request.source_branch = @master[0]
47 50 commits = Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).commits_between
48   - commits.first.id.should == @wiki_branch[1]
49   - commits.last.id.should == @master[1]
  51 + verify_commits(commits, @wiki_branch[1], @master[1])
50 52 end
51 53 end
52 54 end
... ... @@ -81,8 +83,12 @@ describe &#39;Gitlab::Satellite::MergeAction&#39; do
81 83 diff_count = diff.scan('diff --git').size
82 84 diff_count.should >= 1
83 85 diffs.size.should == diff_count
84   - diffs.each {|a_diff| (diff.include? a_diff.diff).should be_true}
  86 + diffs.each do |a_diff|
  87 + a_diff.class.should == Gitlab::Git::Diff
  88 + (diff.include? a_diff.diff).should be_true
  89 + end
85 90 end
  91 +
86 92 context 'on fork' do
87 93 it 'should get proper diffs' do
88 94 merge_request_fork.target_branch = @close_commit1[0]
... ... @@ -93,7 +99,7 @@ describe &#39;Gitlab::Satellite::MergeAction&#39; do
93 99 merge_request_fork.source_branch = @master[0]
94 100 diff = Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request_fork).diff_in_satellite
95 101  
96   - is_a_matching_diff(diff,diffs)
  102 + is_a_matching_diff(diff, diffs)
97 103 end
98 104 end
99 105  
... ... @@ -108,7 +114,7 @@ describe &#39;Gitlab::Satellite::MergeAction&#39; do
108 114 merge_request.source_branch = @master[0]
109 115 diff = Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).diff_in_satellite
110 116  
111   - is_a_matching_diff(diff,diffs)
  117 + is_a_matching_diff(diff, diffs)
112 118 end
113 119 end
114 120 end
... ...