Merge branch 'master' into remove-wip
This commit is contained in:
commit
d4b49587b9
|
@ -5,6 +5,12 @@ v 8.6.0 (unreleased)
|
||||||
- Fix avatar stretching by providing a cropping feature (Johann Pardanaud)
|
- Fix avatar stretching by providing a cropping feature (Johann Pardanaud)
|
||||||
- Easily (un)mark merge request as WIP using link
|
- Easily (un)mark merge request as WIP using link
|
||||||
- Use specialized system notes when MR is (un)marked as WIP
|
- Use specialized system notes when MR is (un)marked as WIP
|
||||||
|
- Strip leading and trailing spaces in URL validator (evuez)
|
||||||
|
- Update documentation to reflect Guest role not being enforced on internal projects
|
||||||
|
|
||||||
|
v 8.5.2
|
||||||
|
- Fix sidebar overlapping content when screen width was below 1200px
|
||||||
|
- Fix error 500 when commenting on a commit
|
||||||
|
|
||||||
v 8.5.1
|
v 8.5.1
|
||||||
- Fix group projects styles
|
- Fix group projects styles
|
||||||
|
@ -25,9 +31,6 @@ v 8.5.1
|
||||||
- Update sentry-raven gem to 0.15.6
|
- Update sentry-raven gem to 0.15.6
|
||||||
- Add build coverage in project's builds page (Steffen Köhler)
|
- Add build coverage in project's builds page (Steffen Köhler)
|
||||||
|
|
||||||
v 8.5.2
|
|
||||||
- Fix error 500 when commenting on a commit
|
|
||||||
|
|
||||||
v 8.5.0
|
v 8.5.0
|
||||||
- Fix duplicate "me" in tooltip of the "thumbsup" awards Emoji (Stan Hu)
|
- Fix duplicate "me" in tooltip of the "thumbsup" awards Emoji (Stan Hu)
|
||||||
- Cache various Repository methods to improve performance (Yorick Peterse)
|
- Cache various Repository methods to improve performance (Yorick Peterse)
|
||||||
|
|
|
@ -801,10 +801,7 @@ class Project < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def change_head(branch)
|
def change_head(branch)
|
||||||
# Cached divergent commit counts are based on repository head
|
repository.before_change_head
|
||||||
repository.expire_branch_cache
|
|
||||||
repository.expire_root_ref_cache
|
|
||||||
|
|
||||||
gitlab_shell.update_repository_head(self.path_with_namespace, branch)
|
gitlab_shell.update_repository_head(self.path_with_namespace, branch)
|
||||||
reload_default_branch
|
reload_default_branch
|
||||||
end
|
end
|
||||||
|
|
|
@ -245,15 +245,6 @@ class Repository
|
||||||
expire_emptiness_caches if empty?
|
expire_emptiness_caches if empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Expires _all_ caches, including those that would normally only be expired
|
|
||||||
# under specific conditions.
|
|
||||||
def expire_all_caches!
|
|
||||||
expire_cache
|
|
||||||
expire_root_ref_cache
|
|
||||||
expire_emptiness_caches
|
|
||||||
expire_has_visible_content_cache
|
|
||||||
end
|
|
||||||
|
|
||||||
def expire_branch_cache(branch_name = nil)
|
def expire_branch_cache(branch_name = nil)
|
||||||
# When we push to the root branch we have to flush the cache for all other
|
# When we push to the root branch we have to flush the cache for all other
|
||||||
# branches as their statistics are based on the commits relative to the
|
# branches as their statistics are based on the commits relative to the
|
||||||
|
@ -307,6 +298,46 @@ class Repository
|
||||||
cache.expire(:branch_names)
|
cache.expire(:branch_names)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Runs code just before a repository is deleted.
|
||||||
|
def before_delete
|
||||||
|
expire_cache if exists?
|
||||||
|
|
||||||
|
expire_root_ref_cache
|
||||||
|
expire_emptiness_caches
|
||||||
|
end
|
||||||
|
|
||||||
|
# Runs code just before the HEAD of a repository is changed.
|
||||||
|
def before_change_head
|
||||||
|
# Cached divergent commit counts are based on repository head
|
||||||
|
expire_branch_cache
|
||||||
|
expire_root_ref_cache
|
||||||
|
end
|
||||||
|
|
||||||
|
# Runs code before creating a new tag.
|
||||||
|
def before_create_tag
|
||||||
|
expire_cache
|
||||||
|
end
|
||||||
|
|
||||||
|
# Runs code after a repository has been forked/imported.
|
||||||
|
def after_import
|
||||||
|
expire_emptiness_caches
|
||||||
|
end
|
||||||
|
|
||||||
|
# Runs code after a new commit has been pushed.
|
||||||
|
def after_push_commit(branch_name)
|
||||||
|
expire_cache(branch_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Runs code after a new branch has been created.
|
||||||
|
def after_create_branch
|
||||||
|
expire_has_visible_content_cache
|
||||||
|
end
|
||||||
|
|
||||||
|
# Runs code after an existing branch has been removed.
|
||||||
|
def after_remove_branch
|
||||||
|
expire_has_visible_content_cache
|
||||||
|
end
|
||||||
|
|
||||||
def method_missing(m, *args, &block)
|
def method_missing(m, *args, &block)
|
||||||
if m == :lookup && !block_given?
|
if m == :lookup && !block_given?
|
||||||
lookup_cache[m] ||= {}
|
lookup_cache[m] ||= {}
|
||||||
|
|
|
@ -16,13 +16,13 @@ class GitPushService < BaseService
|
||||||
# 5. Executes the project's services
|
# 5. Executes the project's services
|
||||||
#
|
#
|
||||||
def execute
|
def execute
|
||||||
@project.repository.expire_cache(branch_name)
|
@project.repository.after_push_commit(branch_name)
|
||||||
|
|
||||||
if push_remove_branch?
|
if push_remove_branch?
|
||||||
@project.repository.expire_has_visible_content_cache
|
@project.repository.after_remove_branch
|
||||||
@push_commits = []
|
@push_commits = []
|
||||||
elsif push_to_new_branch?
|
elsif push_to_new_branch?
|
||||||
@project.repository.expire_has_visible_content_cache
|
@project.repository.after_create_branch
|
||||||
|
|
||||||
# Re-find the pushed commits.
|
# Re-find the pushed commits.
|
||||||
if is_default_branch?
|
if is_default_branch?
|
||||||
|
|
|
@ -2,7 +2,7 @@ class GitTagPushService
|
||||||
attr_accessor :project, :user, :push_data
|
attr_accessor :project, :user, :push_data
|
||||||
|
|
||||||
def execute(project, user, oldrev, newrev, ref)
|
def execute(project, user, oldrev, newrev, ref)
|
||||||
project.repository.expire_cache
|
project.repository.before_create_tag
|
||||||
|
|
||||||
@project, @user = project, user
|
@project, @user = project, user
|
||||||
@push_data = build_push_data(oldrev, newrev, ref)
|
@push_data = build_push_data(oldrev, newrev, ref)
|
||||||
|
|
|
@ -76,11 +76,9 @@ module Projects
|
||||||
end
|
end
|
||||||
|
|
||||||
def flush_caches(project, wiki_path)
|
def flush_caches(project, wiki_path)
|
||||||
project.repository.expire_all_caches! if project.repository.exists?
|
project.repository.before_delete
|
||||||
|
|
||||||
wiki_repo = Repository.new(wiki_path, project)
|
Repository.new(wiki_path, project).before_delete
|
||||||
|
|
||||||
wiki_repo.expire_all_caches! if wiki_repo.exists?
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -29,8 +29,11 @@ class UrlValidator < ActiveModel::EachValidator
|
||||||
end
|
end
|
||||||
|
|
||||||
def valid_url?(value)
|
def valid_url?(value)
|
||||||
|
return false if value.nil?
|
||||||
|
|
||||||
options = default_options.merge(self.options)
|
options = default_options.merge(self.options)
|
||||||
|
|
||||||
|
value.strip!
|
||||||
value =~ /\A#{URI.regexp(options[:protocols])}\z/
|
value =~ /\A#{URI.regexp(options[:protocols])}\z/
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,7 +27,7 @@ class RepositoryForkWorker
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
project.repository.expire_emptiness_caches
|
project.repository.after_import
|
||||||
project.import_finish
|
project.import_finish
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,7 +18,7 @@ class RepositoryImportWorker
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
project.repository.expire_emptiness_caches
|
project.repository.after_import
|
||||||
project.import_finish
|
project.import_finish
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,7 +6,7 @@ If a user is both in a project group and in the project itself, the highest perm
|
||||||
|
|
||||||
If a user is a GitLab administrator they receive all permissions.
|
If a user is a GitLab administrator they receive all permissions.
|
||||||
|
|
||||||
On public projects the Guest role is not enforced.
|
On public and internal projects the Guest role is not enforced.
|
||||||
All users will be able to create issues, leave comments, and pull or download the project code.
|
All users will be able to create issues, leave comments, and pull or download the project code.
|
||||||
|
|
||||||
To add or import a user, you can follow the [project users and members
|
To add or import a user, you can follow the [project users and members
|
||||||
|
|
|
@ -13,7 +13,7 @@ feature 'Issue filtering by Milestone', feature: true do
|
||||||
visit_issues(project)
|
visit_issues(project)
|
||||||
filter_by_milestone(Milestone::None.title)
|
filter_by_milestone(Milestone::None.title)
|
||||||
|
|
||||||
expect(page).to have_css('.title', count: 1)
|
expect(page).to have_css('.issue .title', count: 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario 'filters by a specific Milestone', js: true do
|
scenario 'filters by a specific Milestone', js: true do
|
||||||
|
@ -23,7 +23,7 @@ feature 'Issue filtering by Milestone', feature: true do
|
||||||
visit_issues(project)
|
visit_issues(project)
|
||||||
filter_by_milestone(milestone.title)
|
filter_by_milestone(milestone.title)
|
||||||
|
|
||||||
expect(page).to have_css('.title', count: 1)
|
expect(page).to have_css('.issue .title', count: 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
def visit_issues(project)
|
def visit_issues(project)
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe ProjectHook, models: true do
|
describe ProjectHook, models: true do
|
||||||
|
describe "Associations" do
|
||||||
|
it { is_expected.to belong_to :project }
|
||||||
|
end
|
||||||
|
|
||||||
describe '.push_hooks' do
|
describe '.push_hooks' do
|
||||||
it 'should return hooks for push events only' do
|
it 'should return hooks for push events only' do
|
||||||
hook = create(:project_hook, push_events: true)
|
hook = create(:project_hook, push_events: true)
|
||||||
|
|
|
@ -18,20 +18,14 @@
|
||||||
|
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe ProjectHook, models: true do
|
describe WebHook, models: true do
|
||||||
describe "Associations" do
|
|
||||||
it { is_expected.to belong_to :project }
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "Mass assignment" do
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "Validations" do
|
describe "Validations" do
|
||||||
it { is_expected.to validate_presence_of(:url) }
|
it { is_expected.to validate_presence_of(:url) }
|
||||||
|
|
||||||
context "url format" do
|
describe 'url' do
|
||||||
it { is_expected.to allow_value("http://example.com").for(:url) }
|
it { is_expected.to allow_value("http://example.com").for(:url) }
|
||||||
it { is_expected.to allow_value("https://excample.com").for(:url) }
|
it { is_expected.to allow_value("https://example.com").for(:url) }
|
||||||
|
it { is_expected.to allow_value(" https://example.com ").for(:url) }
|
||||||
it { is_expected.to allow_value("http://test.com/api").for(:url) }
|
it { is_expected.to allow_value("http://test.com/api").for(:url) }
|
||||||
it { is_expected.to allow_value("http://test.com/api?key=abc").for(:url) }
|
it { is_expected.to allow_value("http://test.com/api?key=abc").for(:url) }
|
||||||
it { is_expected.to allow_value("http://test.com/api?key=abc&type=def").for(:url) }
|
it { is_expected.to allow_value("http://test.com/api?key=abc&type=def").for(:url) }
|
||||||
|
@ -39,6 +33,12 @@ describe ProjectHook, models: true do
|
||||||
it { is_expected.not_to allow_value("example.com").for(:url) }
|
it { is_expected.not_to allow_value("example.com").for(:url) }
|
||||||
it { is_expected.not_to allow_value("ftp://example.com").for(:url) }
|
it { is_expected.not_to allow_value("ftp://example.com").for(:url) }
|
||||||
it { is_expected.not_to allow_value("herp-and-derp").for(:url) }
|
it { is_expected.not_to allow_value("herp-and-derp").for(:url) }
|
||||||
|
|
||||||
|
it 'strips :url before saving it' do
|
||||||
|
hook = create(:project_hook, url: ' https://example.com ')
|
||||||
|
|
||||||
|
expect(hook.url).to eq('https://example.com')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -362,14 +362,14 @@ describe Repository, models: true do
|
||||||
repository.expire_cache('master')
|
repository.expire_cache('master')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'expires the emptiness cache for an empty repository' do
|
it 'expires the emptiness caches for an empty repository' do
|
||||||
expect(repository).to receive(:empty?).and_return(true)
|
expect(repository).to receive(:empty?).and_return(true)
|
||||||
expect(repository).to receive(:expire_emptiness_caches)
|
expect(repository).to receive(:expire_emptiness_caches)
|
||||||
|
|
||||||
repository.expire_cache
|
repository.expire_cache
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not expire the emptiness cache for a non-empty repository' do
|
it 'does not expire the emptiness caches for a non-empty repository' do
|
||||||
expect(repository).to receive(:empty?).and_return(false)
|
expect(repository).to receive(:empty?).and_return(false)
|
||||||
expect(repository).to_not receive(:expire_emptiness_caches)
|
expect(repository).to_not receive(:expire_emptiness_caches)
|
||||||
|
|
||||||
|
@ -464,4 +464,108 @@ describe Repository, models: true do
|
||||||
expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).not_to be_present
|
expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).not_to be_present
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#before_delete' do
|
||||||
|
describe 'when a repository does not exist' do
|
||||||
|
before do
|
||||||
|
allow(repository).to receive(:exists?).and_return(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not flush caches that depend on repository data' do
|
||||||
|
expect(repository).to_not receive(:expire_cache)
|
||||||
|
|
||||||
|
repository.before_delete
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'flushes the root ref cache' do
|
||||||
|
expect(repository).to receive(:expire_root_ref_cache)
|
||||||
|
|
||||||
|
repository.before_delete
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'flushes the emptiness caches' do
|
||||||
|
expect(repository).to receive(:expire_emptiness_caches)
|
||||||
|
|
||||||
|
repository.before_delete
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when a repository exists' do
|
||||||
|
before do
|
||||||
|
allow(repository).to receive(:exists?).and_return(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'flushes the caches that depend on repository data' do
|
||||||
|
expect(repository).to receive(:expire_cache)
|
||||||
|
|
||||||
|
repository.before_delete
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'flushes the root ref cache' do
|
||||||
|
expect(repository).to receive(:expire_root_ref_cache)
|
||||||
|
|
||||||
|
repository.before_delete
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'flushes the emptiness caches' do
|
||||||
|
expect(repository).to receive(:expire_emptiness_caches)
|
||||||
|
|
||||||
|
repository.before_delete
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#before_change_head' do
|
||||||
|
it 'flushes the branch cache' do
|
||||||
|
expect(repository).to receive(:expire_branch_cache)
|
||||||
|
|
||||||
|
repository.before_change_head
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'flushes the root ref cache' do
|
||||||
|
expect(repository).to receive(:expire_root_ref_cache)
|
||||||
|
|
||||||
|
repository.before_change_head
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#before_create_tag' do
|
||||||
|
it 'flushes the cache' do
|
||||||
|
expect(repository).to receive(:expire_cache)
|
||||||
|
|
||||||
|
repository.before_create_tag
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#after_import' do
|
||||||
|
it 'flushes the emptiness cachess' do
|
||||||
|
expect(repository).to receive(:expire_emptiness_caches)
|
||||||
|
|
||||||
|
repository.after_import
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#after_push_commit' do
|
||||||
|
it 'flushes the cache' do
|
||||||
|
expect(repository).to receive(:expire_cache).with('master')
|
||||||
|
|
||||||
|
repository.after_push_commit('master')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#after_create_branch' do
|
||||||
|
it 'flushes the visible content cache' do
|
||||||
|
expect(repository).to receive(:expire_has_visible_content_cache)
|
||||||
|
|
||||||
|
repository.after_create_branch
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#after_remove_branch' do
|
||||||
|
it 'flushes the visible content cache' do
|
||||||
|
expect(repository).to receive(:expire_has_visible_content_cache)
|
||||||
|
|
||||||
|
repository.after_remove_branch
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue