Commit 3eba6652 authored by Shinya Maeda's avatar Shinya Maeda

Merge branch 'master-ce' into fix-environment-status-in-merge-request-widget

parents 14cdde72 1b788c66
...@@ -91,7 +91,14 @@ module EventsHelper ...@@ -91,7 +91,14 @@ module EventsHelper
words << "##{event.target_iid}" if event.target_iid words << "##{event.target_iid}" if event.target_iid
words << "in" words << "in"
elsif event.target elsif event.target
words << "##{event.target_iid}:" prefix =
if event.merge_request?
MergeRequest.reference_prefix
else
Issue.reference_prefix
end
words << "#{prefix}#{event.target_iid}:" if event.target_iid
words << event.target.title if event.target.respond_to?(:title) words << event.target.title if event.target.respond_to?(:title)
words << "at" words << "at"
end end
......
...@@ -39,7 +39,15 @@ module EachBatch ...@@ -39,7 +39,15 @@ module EachBatch
# #
# of - The number of rows to retrieve per batch. # of - The number of rows to retrieve per batch.
# column - The column to use for ordering the batches. # column - The column to use for ordering the batches.
def each_batch(of: 1000, column: primary_key) # order_hint - An optional column to append to the `ORDER BY id`
# clause to help the query planner. PostgreSQL might perform badly
# with a LIMIT 1 because the planner is guessing that scanning the
# index in ID order will come across the desired row in less time
# it will take the planner than using another index. The
# order_hint does not affect the search results. For example,
# `ORDER BY id ASC, updated_at ASC` means the same thing as `ORDER
# BY id ASC`.
def each_batch(of: 1000, column: primary_key, order_hint: nil)
unless column unless column
raise ArgumentError, raise ArgumentError,
'the column: argument must be set to a column name to use for ordering rows' 'the column: argument must be set to a column name to use for ordering rows'
...@@ -48,7 +56,9 @@ module EachBatch ...@@ -48,7 +56,9 @@ module EachBatch
start = except(:select) start = except(:select)
.select(column) .select(column)
.reorder(column => :asc) .reorder(column => :asc)
.take
start = start.order(order_hint) if order_hint
start = start.take
return unless start return unless start
...@@ -60,6 +70,9 @@ module EachBatch ...@@ -60,6 +70,9 @@ module EachBatch
.select(column) .select(column)
.where(arel_table[column].gteq(start_id)) .where(arel_table[column].gteq(start_id))
.reorder(column => :asc) .reorder(column => :asc)
stop = stop.order(order_hint) if order_hint
stop = stop
.offset(of) .offset(of)
.limit(1) .limit(1)
.take .take
......
---
title: Use merge request prefix symbol in event feed title
merge_request: 22449
author: George Tsiolis
type: changed
---
title: Fix statement timeouts in RemoveRestrictedTodos migration
merge_request: 22795
author:
type: other
# frozen_string_literal: true
# rescheduling of the revised RemoveRestrictedTodosWithCte background migration
class RemoveRestrictedTodosAgain < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
MIGRATION = 'RemoveRestrictedTodos'.freeze
BATCH_SIZE = 1000
DELAY_INTERVAL = 5.minutes.to_i
class Project < ActiveRecord::Base
include EachBatch
self.table_name = 'projects'
end
def up
Project.where('EXISTS (SELECT 1 FROM todos WHERE todos.project_id = projects.id)')
.each_batch(of: BATCH_SIZE) do |batch, index|
range = batch.pluck('MIN(id)', 'MAX(id)').first
BackgroundMigrationWorker.perform_in(index * DELAY_INTERVAL, MIGRATION, range)
end
end
def down
# nothing to do
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20181106135939) do ActiveRecord::Schema.define(version: 20181107054254) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
......
...@@ -774,7 +774,7 @@ These details <em>will</em> remain <strong>hidden</strong> until expanded. ...@@ -774,7 +774,7 @@ These details <em>will</em> remain <strong>hidden</strong> until expanded.
</details> </details>
</p> </p>
**Note:** Markdown inside these tags is supported, as long as you have a blank link after the `</summary>` tag and before the `</details>` tag, as shown in the example. _Redcarpet does not support Markdown inside these tags. You can work around this by using HTML, for example you can use `<pre><code>` tags instead of [code fences](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#code-and-syntax-highlighting)._ **Note:** Markdown inside these tags is supported, as long as you have a blank line after the `</summary>` tag and before the `</details>` tag, as shown in the example. _Redcarpet does not support Markdown inside these tags. You can work around this by using HTML, for example you can use `<pre><code>` tags instead of [code fences](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#code-and-syntax-highlighting)._
```html ```html
<details> <details>
......
...@@ -67,7 +67,7 @@ module Gitlab ...@@ -67,7 +67,7 @@ module Gitlab
.where('access_level >= ?', 20) .where('access_level >= ?', 20)
confidential_issues = Issue.select(:id, :author_id).where(confidential: true, project_id: project_id) confidential_issues = Issue.select(:id, :author_id).where(confidential: true, project_id: project_id)
confidential_issues.each_batch(of: 100) do |batch| confidential_issues.each_batch(of: 100, order_hint: :confidential) do |batch|
batch.each do |issue| batch.each do |issue|
assigned_users = IssueAssignee.select(:user_id).where(issue_id: issue.id) assigned_users = IssueAssignee.select(:user_id).where(issue_id: issue.id)
......
...@@ -16,6 +16,11 @@ module Gitlab ...@@ -16,6 +16,11 @@ module Gitlab
str.force_encoding(Encoding::UTF_8) str.force_encoding(Encoding::UTF_8)
end end
# Append path to host, making sure there's one single / in between
def append_path(host, path)
"#{host.to_s.sub(%r{\/+$}, '')}/#{path.to_s.sub(%r{^\/+}, '')}"
end
# A slugified version of the string, suitable for inclusion in URLs and # A slugified version of the string, suitable for inclusion in URLs and
# domain names. Rules: # domain names. Rules:
# #
......
...@@ -2,18 +2,18 @@ require 'spec_helper' ...@@ -2,18 +2,18 @@ require 'spec_helper'
describe EventsHelper do describe EventsHelper do
describe '#event_commit_title' do describe '#event_commit_title' do
let(:message) { "foo & bar " + "A" * 70 + "\n" + "B" * 80 } let(:message) { 'foo & bar ' + 'A' * 70 + '\n' + 'B' * 80 }
subject { helper.event_commit_title(message) } subject { helper.event_commit_title(message) }
it "returns the first line, truncated to 70 chars" do it 'returns the first line, truncated to 70 chars' do
is_expected.to eq(message[0..66] + "...") is_expected.to eq(message[0..66] + "...")
end end
it "is not html-safe" do it 'is not html-safe' do
is_expected.not_to be_a(ActiveSupport::SafeBuffer) is_expected.not_to be_a(ActiveSupport::SafeBuffer)
end end
it "handles empty strings" do it 'handles empty strings' do
expect(helper.event_commit_title("")).to eq("") expect(helper.event_commit_title("")).to eq("")
end end
...@@ -22,7 +22,7 @@ describe EventsHelper do ...@@ -22,7 +22,7 @@ describe EventsHelper do
end end
it 'does not escape HTML entities' do it 'does not escape HTML entities' do
expect(helper.event_commit_title("foo & bar")).to eq("foo & bar") expect(helper.event_commit_title('foo & bar')).to eq('foo & bar')
end end
end end
...@@ -30,38 +30,54 @@ describe EventsHelper do ...@@ -30,38 +30,54 @@ describe EventsHelper do
let(:event) { create(:event) } let(:event) { create(:event) }
let(:project) { create(:project, :public, :repository) } let(:project) { create(:project, :public, :repository) }
it "returns project issue url" do context 'issue' do
before do
event.target = create(:issue) event.target = create(:issue)
end
it 'returns the project issue url' do
expect(helper.event_feed_url(event)).to eq(project_issue_url(event.project, event.target))
end
expect(helper.event_feed_url(event)).to eq(project_issue_url(event.project, event.issue)) it 'contains the project issue IID link' do
expect(helper.event_feed_title(event)).to include("##{event.target.iid}")
end
end end
it "returns project merge_request url" do context 'merge request' do
before do
event.target = create(:merge_request) event.target = create(:merge_request)
end
it 'returns the project merge request url' do
expect(helper.event_feed_url(event)).to eq(project_merge_request_url(event.project, event.target))
end
expect(helper.event_feed_url(event)).to eq(project_merge_request_url(event.project, event.merge_request)) it 'contains the project merge request IID link' do
expect(helper.event_feed_title(event)).to include("!#{event.target.iid}")
end
end end
it "returns project commit url" do it 'returns project commit url' do
event.target = create(:note_on_commit, project: project) event.target = create(:note_on_commit, project: project)
expect(helper.event_feed_url(event)).to eq(project_commit_url(event.project, event.note_target)) expect(helper.event_feed_url(event)).to eq(project_commit_url(event.project, event.note_target))
end end
it "returns event note target url" do it 'returns event note target url' do
event.target = create(:note) event.target = create(:note)
expect(helper.event_feed_url(event)).to eq(event_note_target_url(event)) expect(helper.event_feed_url(event)).to eq(event_note_target_url(event))
end end
it "returns project url" do it 'returns project url' do
event.project = project event.project = project
event.action = 1 event.action = 1
expect(helper.event_feed_url(event)).to eq(project_url(event.project)) expect(helper.event_feed_url(event)).to eq(project_url(event.project))
end end
it "returns push event feed url" do it 'returns push event feed url' do
event = create(:push_event) event = create(:push_event)
create(:push_event_payload, event: event, action: :pushed) create(:push_event_payload, event: event, action: :pushed)
......
...@@ -2,7 +2,7 @@ require 'spec_helper' ...@@ -2,7 +2,7 @@ require 'spec_helper'
describe Gitlab::Utils do describe Gitlab::Utils do
delegate :to_boolean, :boolean_to_yes_no, :slugify, :random_string, :which, :ensure_array_from_string, delegate :to_boolean, :boolean_to_yes_no, :slugify, :random_string, :which, :ensure_array_from_string,
:bytes_to_megabytes, to: :described_class :bytes_to_megabytes, :append_path, to: :described_class
describe '.slugify' do describe '.slugify' do
{ {
...@@ -106,4 +106,25 @@ describe Gitlab::Utils do ...@@ -106,4 +106,25 @@ describe Gitlab::Utils do
expect(bytes_to_megabytes(bytes)).to eq(1) expect(bytes_to_megabytes(bytes)).to eq(1)
end end
end end
describe '.append_path' do
using RSpec::Parameterized::TableSyntax
where(:host, :path, :result) do
'http://test/' | '/foo/bar' | 'http://test/foo/bar'
'http://test/' | '//foo/bar' | 'http://test/foo/bar'
'http://test//' | '/foo/bar' | 'http://test/foo/bar'
'http://test' | 'foo/bar' | 'http://test/foo/bar'
'http://test//' | '' | 'http://test/'
'http://test//' | nil | 'http://test/'
'' | '/foo/bar' | '/foo/bar'
nil | '/foo/bar' | '/foo/bar'
end
with_them do
it 'makes sure there is only one slash as path separator' do
expect(append_path(host, path)).to eq(result)
end
end
end
end end
...@@ -14,14 +14,15 @@ describe EachBatch do ...@@ -14,14 +14,15 @@ describe EachBatch do
5.times { create(:user, updated_at: 1.day.ago) } 5.times { create(:user, updated_at: 1.day.ago) }
end end
shared_examples 'each_batch handling' do |kwargs|
it 'yields an ActiveRecord::Relation when a block is given' do it 'yields an ActiveRecord::Relation when a block is given' do
model.each_batch do |relation| model.each_batch(kwargs) do |relation|
expect(relation).to be_a_kind_of(ActiveRecord::Relation) expect(relation).to be_a_kind_of(ActiveRecord::Relation)
end end
end end
it 'yields a batch index as the second argument' do it 'yields a batch index as the second argument' do
model.each_batch do |_, index| model.each_batch(kwargs) do |_, index|
expect(index).to eq(1) expect(index).to eq(1)
end end
end end
...@@ -29,7 +30,7 @@ describe EachBatch do ...@@ -29,7 +30,7 @@ describe EachBatch do
it 'accepts a custom batch size' do it 'accepts a custom batch size' do
amount = 0 amount = 0
model.each_batch(of: 1) { amount += 1 } model.each_batch(kwargs.merge({ of: 1 })) { amount += 1 }
expect(amount).to eq(5) expect(amount).to eq(5)
end end
...@@ -50,4 +51,8 @@ describe EachBatch do ...@@ -50,4 +51,8 @@ describe EachBatch do
expect(model.where(updated_at: time).count).to eq(5) expect(model.where(updated_at: time).count).to eq(5)
end end
end end
it_behaves_like 'each_batch handling', {}
it_behaves_like 'each_batch handling', { order_hint: :updated_at }
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment