Commit 28046b90 authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-04-24

# Conflicts:
#	doc/user/project/quick_actions.md
#	spec/factories/projects.rb
#	spec/models/project_spec.rb
#	spec/services/quick_actions/interpret_service_spec.rb

[ci skip]
parents 1a4b6568 878ad484
......@@ -31,7 +31,7 @@ module ProtectedRef
end
end
def protected_ref_accessible_to?(ref, user, action:, protected_refs: nil)
def protected_ref_accessible_to?(ref, user, project:, action:, protected_refs: nil)
access_levels_for_ref(ref, action: action, protected_refs: protected_refs).any? do |access_level|
access_level.check_access(user)
end
......
......@@ -1060,13 +1060,6 @@ class Project < ActiveRecord::Base
"#{web_url}.git"
end
def user_can_push_to_empty_repo?(user)
return false unless empty_repo?
return false unless Ability.allowed?(user, :push_code, self)
!ProtectedBranch.default_branch_protected? || team.max_member_access(user.id) > Gitlab::Access::DEVELOPER
end
def forked?
return true if fork_network && fork_network.root_project != self
......@@ -2024,10 +2017,11 @@ class Project < ActiveRecord::Base
def fetch_branch_allows_maintainer_push?(user, branch_name)
check_access = -> do
next false if empty_repo?
merge_request = source_of_merge_requests.opened
.where(allow_maintainer_to_push: true)
.find_by(source_branch: branch_name)
merge_request&.can_be_merged_by?(user)
end
......
......@@ -6,6 +6,15 @@ class ProtectedBranch < ActiveRecord::Base
protected_ref_access_levels :merge, :push
def self.protected_ref_accessible_to?(ref, user, project:, action:, protected_refs: nil)
# Masters, owners and admins are allowed to create the default branch
if default_branch_protected? && project.empty_repo?
return true if user.admin? || project.team.max_member_access(user.id) > Gitlab::Access::DEVELOPER
end
super
end
# Check if branch name is marked as protected in the system
def self.protected?(project, ref_name)
return true if project.empty_repo? && default_branch_protected?
......
......@@ -4,6 +4,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
include GitlabRoutingHelper
include StorageHelper
include TreeHelper
include ChecksCollaboration
include Gitlab::Utils::StrongMemoize
presents :project
......@@ -170,9 +171,11 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
end
def can_current_user_push_to_branch?(branch)
return false unless repository.branch_exists?(branch)
user_access(project).can_push_to_branch?(branch)
end
::Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(branch)
def can_current_user_push_to_default_branch?
can_current_user_push_to_branch?(default_branch)
end
def files_anchor_data
......@@ -200,7 +203,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
end
def new_file_anchor_data
if current_user && can_current_user_push_code?
if current_user && can_current_user_push_to_default_branch?
OpenStruct.new(enabled: false,
label: _('New file'),
link: project_new_blob_path(project, default_branch || 'master'),
......@@ -209,7 +212,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
end
def readme_anchor_data
if current_user && can_current_user_push_code? && repository.readme.blank?
if current_user && can_current_user_push_to_default_branch? && repository.readme.blank?
OpenStruct.new(enabled: false,
label: _('Add Readme'),
link: add_readme_path)
......@@ -221,7 +224,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
end
def changelog_anchor_data
if current_user && can_current_user_push_code? && repository.changelog.blank?
if current_user && can_current_user_push_to_default_branch? && repository.changelog.blank?
OpenStruct.new(enabled: false,
label: _('Add Changelog'),
link: add_changelog_path)
......@@ -233,7 +236,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
end
def license_anchor_data
if current_user && can_current_user_push_code? && repository.license_blob.blank?
if current_user && can_current_user_push_to_default_branch? && repository.license_blob.blank?
OpenStruct.new(enabled: false,
label: _('Add License'),
link: add_license_path)
......@@ -245,7 +248,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
end
def contribution_guide_anchor_data
if current_user && can_current_user_push_code? && repository.contribution_guide.blank?
if current_user && can_current_user_push_to_default_branch? && repository.contribution_guide.blank?
OpenStruct.new(enabled: false,
label: _('Add Contribution guide'),
link: add_contribution_guide_path)
......
......@@ -58,7 +58,9 @@
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master
- if @project.can_current_user_push_to_default_branch?
%span><
git push -u origin master
%fieldset
%h5 Existing folder
......@@ -69,7 +71,9 @@
git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'clone')}
git add .
git commit -m "Initial commit"
git push -u origin master
- if @project.can_current_user_push_to_default_branch?
%span><
git push -u origin master
%fieldset
%h5 Existing Git repository
......@@ -78,8 +82,10 @@
cd existing_repo
git remote rename origin old-origin
git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'clone')}
git push -u origin --all
git push -u origin --tags
- if @project.can_current_user_push_to_default_branch?
%span><
git push -u origin --all
git push -u origin --tags
- if can? current_user, :remove_project, @project
.prepend-top-20
......
---
title: Fix errors on pushing to an empty repository
merge_request: 18462
author:
type: fixed
......@@ -41,6 +41,7 @@ do.
| `/clear_weight` | Clears the issue weight |
| `/board_move ~column` | Move issue to column on the board |
| `/duplicate #issue` | Closes this issue and marks it as a duplicate of another issue |
<<<<<<< HEAD
| `/move path/to/project` | Moves issue to another project |
| `/tableflip` | Append the comment with `(╯°□°)╯︵ ┻━┻` |
| `/shrug` | Append the comment with `¯\_(ツ)_/¯` |
......@@ -48,3 +49,9 @@ do.
Note: In GitLab Starter every issue can have more than one assignee, so commands `/assign`, `/unassign` and `/reassign`
support multiple assignees.
=======
| `/move path/to/project` | Moves issue to another project |
| `/tableflip` | Append the comment with `(╯°□°)╯︵ ┻━┻` |
| `/shrug` | Append the comment with `¯\_(ツ)_/¯` |
| <code>/copy_metadata #issue &#124; !merge_request</code> | Copy labels and milestone from other issue or merge request |
>>>>>>> upstream/master
......@@ -244,3 +244,20 @@ GitLab checks files to detect LFS pointers on push. If LFS pointers are detected
Verify that LFS in installed locally and consider a manual push with `git lfs push --all`.
If you are storing LFS files outside of GitLab you can disable LFS on the project by settting `lfs_enabled: false` with the [projects api](../../api/projects.md#edit-project).
### Hosting LFS objects externally
It is possible to host LFS objects externally by setting a custom LFS url with `git config -f .lfsconfig lfs.url https://example.com/<project>.git/info/lfs`.
Because GitLab verifies the existence of objects referenced by LFS pointers, push will fail when LFS is enabled for the project.
LFS can be disabled for a project by Owners and Masters using the [Project API](../../api/projects.md#edit-project).
```bash
curl --request PUT \
--url https://example.com/api/v4/projects/<PROJECT_ID> \
--header 'Private-Token: <YOUR_PRIVATE_TOKEN>' \
--data 'lfs_enabled=false'
```
Note, `<PROJECT_ID>` can also be substituted with a [namespaced path](../../api/README.md#namespaced-path-encoding).
......@@ -63,10 +63,12 @@ module Gitlab
request_cache def can_push_to_branch?(ref)
return false unless can_access_git?
return false unless user.can?(:push_code, project) || project.branch_allows_maintainer_push?(user, ref)
return false unless project
return false if !user.can?(:push_code, project) && !project.branch_allows_maintainer_push?(user, ref)
if protected?(ProtectedBranch, project, ref)
project.user_can_push_to_empty_repo?(user) || protected_branch_accessible_to?(ref, action: :push)
protected_branch_accessible_to?(ref, action: :push)
else
true
end
......@@ -101,6 +103,7 @@ module Gitlab
def protected_branch_accessible_to?(ref, action:)
ProtectedBranch.protected_ref_accessible_to?(
ref, user,
project: project,
action: action,
protected_refs: project.protected_branches)
end
......@@ -108,6 +111,7 @@ module Gitlab
def protected_tag_accessible_to?(ref, action:)
ProtectedTag.protected_ref_accessible_to?(
ref, user,
project: project,
action: action,
protected_refs: project.protected_tags)
end
......
......@@ -183,6 +183,7 @@ FactoryBot.define do
end
end
<<<<<<< HEAD
trait :remote_mirror do
transient do
remote_name "remote_mirror_#{SecureRandom.hex}"
......@@ -192,6 +193,12 @@ FactoryBot.define do
after(:create) do |project, evaluator|
project.remote_mirrors.create!(url: evaluator.url, enabled: evaluator.enabled)
=======
trait :stubbed_repository do
after(:build) do |project|
allow(project).to receive(:empty_repo?).and_return(false)
allow(project.repository).to receive(:empty?).and_return(false)
>>>>>>> upstream/master
end
end
......
require 'spec_helper'
feature 'User creates blob in new project', :js do
let(:user) { create(:user) }
let(:project) { create(:project, :empty_repo) }
shared_examples 'creating a file' do
before do
sign_in(user)
visit project_path(project)
end
it 'allows the user to add a new file' do
click_link 'New file'
find('#editor')
execute_script('ace.edit("editor").setValue("Hello world")')
fill_in(:file_name, with: 'dummy-file')
click_button('Commit changes')
expect(page).to have_content('The file has been successfully created')
end
end
describe 'as a master' do
before do
project.add_master(user)
end
it_behaves_like 'creating a file'
end
describe 'as an admin' do
let(:user) { create(:user, :admin) }
it_behaves_like 'creating a file'
end
describe 'as a developer' do
before do
project.add_developer(user)
sign_in(user)
visit project_path(project)
end
it 'does not allow pushing to the default branch' do
expect(page).not_to have_content('New file')
end
end
end
require 'spec_helper'
describe 'User views an empty project' do
let(:project) { create(:project, :empty_repo) }
let(:user) { create(:user) }
shared_examples 'allowing push to default branch' do
before do
sign_in(user)
visit project_path(project)
end
it 'shows push-to-master instructions' do
expect(page).to have_content('git push -u origin master')
end
end
describe 'as a master' do
before do
project.add_master(user)
end
it_behaves_like 'allowing push to default branch'
end
describe 'as an admin' do
let(:user) { create(:user, :admin) }
it_behaves_like 'allowing push to default branch'
end
describe 'as a developer' do
before do
project.add_developer(user)
sign_in(user)
visit project_path(project)
end
it 'does not show push-to-master instructions' do
expect(page).not_to have_content('git push -u origin master')
end
end
end
......@@ -2,8 +2,8 @@ require 'spec_helper'
describe Gitlab::Ci::Status::Build::Play do
let(:user) { create(:user) }
let(:project) { build.project }
let(:build) { create(:ci_build, :manual) }
let(:project) { create(:project, :stubbed_repository) }
let(:build) { create(:ci_build, :manual, project: project) }
let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
subject { described_class.new(status) }
......@@ -46,6 +46,8 @@ describe Gitlab::Ci::Status::Build::Play do
context 'when user can not push to the branch' do
before do
build.project.add_developer(user)
create(:protected_branch, :masters_can_push,
name: build.ref, project: project)
end
it { is_expected.not_to have_action }
......
......@@ -32,6 +32,12 @@ describe Gitlab::UserAccess do
let(:empty_project) { create(:project_empty_repo) }
let(:project_access) { described_class.new(user, project: empty_project) }
it 'returns true for admins' do
user.update!(admin: true)
expect(access.can_push_to_branch?('master')).to be_truthy
end
it 'returns true if user is master' do
empty_project.add_master(user)
......@@ -71,6 +77,12 @@ describe Gitlab::UserAccess do
let(:branch) { create :protected_branch, project: project, name: "test" }
let(:not_existing_branch) { create :protected_branch, :developers_can_merge, project: project }
it 'returns true for admins' do
user.update!(admin: true)
expect(access.can_push_to_branch?(branch.name)).to be_truthy
end
it 'returns true if user is a master' do
project.add_master(user)
......
require 'spec_helper'
describe Environment do
let(:project) { create(:project) }
let(:project) { create(:project, :stubbed_repository) }
subject(:environment) { create(:environment, project: project) }
it { is_expected.to belong_to(:project) }
......@@ -201,7 +201,7 @@ describe Environment do
end
describe '#stop_with_action!' do
let(:user) { create(:admin) }
let(:user) { create(:user) }
subject { environment.stop_with_action!(user) }
......
......@@ -1625,6 +1625,7 @@ describe Project do
end
end
<<<<<<< HEAD
describe 'handling import URL' do
context 'when project is a mirror' do
it 'returns the full URL' do
......@@ -1693,6 +1694,8 @@ describe Project do
end
end
=======
>>>>>>> upstream/master
describe '#container_registry_url' do
let(:project) { create(:project) }
......
......@@ -208,6 +208,17 @@ describe ProjectPresenter do
it 'returns nil if user cannot push' do
expect(presenter.new_file_anchor_data).to be_nil
end
context 'when the project is empty' do
let(:project) { create(:project, :empty_repo) }
# Since we protect the default branch for empty repos
it 'is empty for a developer' do
project.add_developer(user)
expect(presenter.new_file_anchor_data).to be_nil
end
end
end
describe '#readme_anchor_data' do
......
......@@ -235,6 +235,8 @@ describe Ci::RetryPipelineService, '#execute' do
context 'when user is not allowed to trigger manual action' do
before do
project.add_developer(user)
create(:protected_branch, :masters_can_push,
name: pipeline.ref, project: project)
end
context 'when there is a failed manual action present' do
......
......@@ -817,6 +817,7 @@ describe QuickActions::InterpretService do
let(:issuable) { issue }
end
<<<<<<< HEAD
context 'issuable weights licensed' do
before do
stub_licensed_features(issue_weights: true)
......@@ -851,6 +852,8 @@ describe QuickActions::InterpretService do
end
end
=======
>>>>>>> upstream/master
context '/copy_metadata command' do
let(:todo_label) { create(:label, project: project, title: 'To Do') }
let(:inreview_label) { create(:label, project: project, title: 'In Review') }
......
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